The Types API will closely follow the method of type construction in XML Schema, where complex types are composed (built up from) other complex types and of simple types. Simple types are restrictions of built-in primitive types.
Built in types, also known as primitive types, have a special namespace, and do not have a base type. User defined types can use any other namespace, so that the user defined type could have the same name as a primitive type without creating a conflict. The definition of a type is somewhat complicated. There are a number of methods of defining a type. The tWSDL Type Component will support many, but not all of these methods. One API procedure will be needed for each method of defining a type. Here is a list of the most useful methods:
# call with typeNamespace, typeName, validation code, description ::wsdl::types::primitiveType::new tcl anySimpleType {return 1} \ {Base type, should return true for every case} # then the following should return 1 in every case: ::wsdb::types::tcl::anySimpleType::validate "My String Always Valid" # Assumes that newPrimitiveType places primitive types in a namespace called 'tcl'
proc ::wsdl::types::simpleType::new {typeNamespace typeName baseType} {...} # call with type namespace, type name, base type ::wsdl::types::simpleType::new "vs" numbers xsd::integer # Note that this simply aliases the type xsd::integer calling it 'numbers' # You call the validation code by reference: $::wsdb::types::vs::numbers::validate 8
Restriction by Enumeration:
proc ::wsdl::types::simpleType::restrictByEnumeration {typeNamespace typeName baseType enumerationList} {...} # call with typeNamespace, typeName, baseType and enumerated list of possible values: ::wsdl::types::simpleType::restrictByEnumeration "vs" someNumbers vs::numbers {5 6 7 8 9} # The following should return false (0): $::wsdb::types::vs::someNumbers::validate 10
Restriction by Pattern
::proc ::wsdl::types::simpleType::restrictionByPattern {typeNamespace typeName baseType pattern} {...} # Call with typeNamespace, typeName baseType and regular expression: ::wsdl::types::simpleType::restrictionByPattern vs guid xsd::string { [0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}} # use the type variable for validation: $::wsdb::types::vs::guid::validate 92ab783d-9303-571F-AC32-03bAcD9671F1
Notice that in order to validate a simple type, you use the value of the variable validate. When a new simpleType is created, a Tcl namespace is defines which at minimum contains the variable validate which references a procedure which handles the validation. This allows the developer to use any previously written Tcl procedure, the only restriction is that the procedure must return 1 if the data is valid and 0 otherwise. Complex type validation follows an similar pattern except that the validation procedure takes a reference to the complexType (Tcl namespace).
The following is an example of how to approach the construction of an API to build up a type based upon the XML fragment representing the type.
Restriction by Enumeration:
<s:simpleType name="CreditCardTypeCode"> <s:restriction base="xsd:string"> <s:enumeration value="Visa" /> <s:enumeration value="Mastercard" /> <s:enumeration value="AmericanExpress" /> <s:enumeration value="Discover" /> <s:enumeration value="DinersClub" /> </s:restriction> </s:simpleType>
This simpleType can be create via the following API call:
::wsdl::types::simpleType::restrictByEnumeration vs CreditCardTypeCode xsd::string { "Visa" "Mastercard" "AmericanExpress" "Discover" "DinersClub" }
Notice that the 'vs' type namespace (prefix/alias) is not shown in the WSDL file because vs is the targetNamespace, and uses the prefix 'tns' in the WSDL file.
Restriction by Pattern:
<s:simpleType name="guid"> <restriction base="xsd:string"> <pattern value="[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}" /> </s:restriction> </s:simpleType>
This simpleType can be create via the following API call:
::wsdl::types::simpleType::restrictByPattern vs guid xsd::string \ {[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}};
Model Group Sequence:
<xsd:complexType name="DonorDataResponse"> <xsd:sequence> <xsd:element minOccurs="0" maxOccurs="1" name="Result" type="tns:DonorData" /> <xsd:element minOccurs="0" maxOccurs="1" name="Source" type="xsd:string" /> <xsd:element minOccurs="0" maxOccurs="20" name="ErrorMessageList" type="tns:ErrorString" /> <xsd:element minOccurs="0" maxOccurs="1" name="StackTrace" type="xsd:string" /> </xsd:sequence> </xsd:complexType>
The DonorDataResponse would be defined in the following way:
::wsdl::elements::modelGroup::sequence::new vs DonorDataResponse { {Result:elements::vs::DonorData {minOccurs 0}} {Source {minOccurs 0}} {ErrorMessageList:vs::ErrorString {minOccurs 0 maxOccurs 20}} {StackTrace {minOccurs 0}} } # Note1: When the base type is xsd:string, # you do not need to include any type information. # # Note2: If the base type namespace is XML Schema (xsd prefix), # you do not need to include the prefix (xsd::dateTime = dateTime) # Note3: when the base type is a complexType, # you have to prefix the base type with 'elements::' # The referenced base complexType must exists prior to use.
Model Group Sequence (Extend complexType) [Note: Unimplimented]:
<xsd:complexType name="DirectBillDonationPaymentData"> <xsd:complexContent mixed="false"> <xsd:extension base="tns:DonationPaymentData"> <xsd:sequence> <xsd:element minOccurs="1" maxOccurs="1" name="StartDate" type="xsd:dateTime" /> <xsd:element minOccurs="0" maxOccurs="1" name="BillingAddress" type="tns:AddressData" /> </xsd:sequence> </xsd:extension> </xsd:complexContent> </xsd:complexType>
::wsdl::elements::modelGroup::sequence::extendSequence vs\ "DirectBillDonationPaymentData"\ "elements::vs::DonationPaymentData" \ { {StartDate:dateTime} {BillingAddress:vs::AddressData {minOccurs 0}} }
Note: Extending a sequence is not supported, but here are some ideas: