35.4. Deriving Complex Types from Complex Types
Overview
Using XML Schema, you can derive new complex types by either extending or restricting other complex types using the
complexContent
element. When generating the Java class to represent the derived complex type, Apache CXF extends the base type’s class. In this way, the generated Java code preserves the inheritance hierarchy intended in the XML Schema.
Schema syntax
You derive complex types from other complex types by using the
complexContent
element, and either the extension
element or the restriction
element. The complexContent
element specifies that the included data description includes more than one field. The extension
element and the restriction
element, which are children of the complexContent
element, specify the base type being modified to create the new type. The base type is specified by the base
attribute.
Extending a complex type
To extend a complex type use the
extension
element to define the additional elements and attributes that make up the new type. All elements that are allowed in a complex type description are allowable as part of the new type’s definition. For example, you can add an anonymous enumeration to the new type, or you can use the choice
element to specify that only one of the new fields can be valid at a time.
Example 35.15, “Deriving a Complex Type by Extension” shows an XML Schema fragment that defines two complex types, widgetOrderInfo and widgetOrderBillInfo. widgetOrderBillInfo is derived by extending widgetOrderInfo to include two new elements:
orderNumber
and amtDue
.
Example 35.15. Deriving a Complex Type by Extension
<complexType name="widgetOrderInfo"> <sequence> <element name="amount" type="xsd:int"/> <element name="order_date" type="xsd:dateTime"/> <element name="type" type="xsd1:widgetSize"/> <element name="shippingAddress" type="xsd1:Address"/> </sequence> <attribute name="rush" type="xsd:boolean" use="optional" /> </complexType> <complexType name="widgetOrderBillInfo"> <complexContent> <extension base="xsd1:widgetOrderInfo"> <sequence> <element name="amtDue" type="xsd:decimal"/> <element name="orderNumber" type="xsd:string"/> </sequence> <attribute name="paid" type="xsd:boolean" default="false" /> </extension> </complexContent> </complexType>
Restricting a complex type
To restrict a complex type use the
restriction
element to limit the possible values of the base type's elements or attributes. When restricting a complex type you must list all of the elements and attributes of the base type. For each element you can add restrictive attributes to the definition. For example, you can add a maxOccurs
attribute to an element to limit the number of times it can occur. You can also use the fixed
attribute to force one or more of the elements to have predetermined values.
Example 35.16, “Defining a Complex Type by Restriction” shows an example of defining a complex type by restricting another complex type. The restricted type, wallawallaAddress, can only be used for addresses in Walla Walla, Washington because the values for the
city
element, the state
element, and the zipCode
element are fixed.
Example 35.16. Defining a Complex Type by Restriction
<complexType name="Address"> <sequence> <element name="name" type="xsd:string"/> <element name="street" type="xsd:short" maxOccurs="3"/> <element name="city" type="xsd:string"/> <element name="state" type="xsd:string"/> <element name="zipCode" type="xsd:string"/> </sequence> </complexType> <complexType name="wallawallaAddress"> <complexContent> <restriction base="xsd1:Address"> <sequence> <element name="name" type="xsd:string"/> <element name="street" type="xsd:short" maxOccurs="3"/> <element name="city" type="xsd:string" fixed="WallaWalla"/> <element name="state" type="xsd:string" fixed="WA" /> <element name="zipCode" type="xsd:string" fixed="99362" /> </sequence> </restriction> </complexContent> </complexType>
Mapping to Java
As it does with all complex types, Apache CXF generates a class to represent complex types derived from another complex type. The Java class generated for the derived complex type extends the Java class generated to support the base complex type. The base Java class is also modified to include the
@XmlSeeAlso
annotation. The base class' @XmlSeeAlso
annotation lists all of the classes that extend the base class.
When the new complex type is derived by extension, the generated class will include member variables for all of the added elements and attributes. The new member variables will be generated according to the same mappings as all other elements.
When the new complex type is derived by restriction, the generated class will have no new member variables. The generated class will simply be a shell that does not provide any additional functionality. It is entirely up to you to ensure that the restrictions defined in the XML Schema are enforced.
For example, the schema in Example 35.15, “Deriving a Complex Type by Extension” results in the generation of two Java classes:
WidgetOrderInfo
and WidgetBillOrderInfo
. WidgetOrderBillInfo
extends WidgetOrderInfo
because widgetOrderBillInfo is derived by extension from widgetOrderInfo. Example 35.17, “WidgetOrderBillInfo” shows the generated class for widgetOrderBillInfo.
Example 35.17. WidgetOrderBillInfo
@XmlType(name = "widgetOrderBillInfo", propOrder = { "amtDue", "orderNumber" }) public class WidgetOrderBillInfo extends WidgetOrderInfo { @XmlElement(required = true) protected BigDecimal amtDue; @XmlElement(required = true) protected String orderNumber; @XmlAttribute protected Boolean paid; public BigDecimal getAmtDue() { return amtDue; } public void setAmtDue(BigDecimal value) { this.amtDue = value; } public String getOrderNumber() { return orderNumber; } public void setOrderNumber(String value) { this.orderNumber = value; } public boolean isPaid() { if (paid == null) { return false; } else { return paid; } } public void setPaid(Boolean value) { this.paid = value; } }