Chapter 35. Using Complex Types

Abstract

Complex types can contain multiple elements and they can have attributes. They are mapped into Java classes that can hold the data represented by the type definition. Typically, the mapping is to a bean with a set of properties representing the elements and the attributes of the content model..

35.1. Basic Complex Type Mapping

Overview

XML Schema complex types define constructs containing more complex information than a simple type. The most simple complex types define an empty element with an attribute. More intricate complex types are made up of a collection of elements.

By default, an XML Schema complex type is mapped to a Java class, with a member variable to represent each element and attribute listed in the XML Schema definition. The class has setters and getters for each member variable.

Defining in XML Schema

XML Schema complex types are defined using the complexType element. The complexType element wraps the rest of elements used to define the structure of the data. It can appear either as the parent element of a named type definition, or as the child of an element element anonymously defining the structure of the information stored in the element. When the complexType element is used to define a named type, it requires the use of the name attribute. The name attribute specifies a unique identifier for referencing the type.

Complex type definitions that contain one or more elements have one of the child elements described in Table 35.1, “Elements for Defining How Elements Appear in a Complex Type”. These elements determine how the specified elements appear in an instance of the type.

Table 35.1. Elements for Defining How Elements Appear in a Complex Type

ElementDescription

all

All of the elements defined as part of the complex type must appear in an instance of the type. However, they can appear in any order.

choice

Only one of the elements defined as part of the complex type can appear in an instance of the type.

sequence

All of the elements defined as part of the complex type must appear in an instance of the type, and they must also appear in the order specified in the type definition.

Note

If a complex type definition only uses attributes, you do not need one of the elements described in Table 35.1, “Elements for Defining How Elements Appear in a Complex Type”.

After deciding how the elements will appear, you define the elements by adding one or more element element children to the definition.

Example 35.1, “XML Schema Complex Type” shows a complex type definition in XML Schema.

Example 35.1. XML Schema Complex Type

<complexType name="sequence">
  <sequence>
    <element name="name" type="xsd:string" />
    <element name="street" type="xsd:short" />
    <element name="city" type="xsd:string" />
    <element name="state" type="xsd:string" />
    <element name="zipCode" type="xsd:string" />
  </sequence>
</complexType>

Mapping to Java

XML Schema complex types are mapped to Java classes. Each element in the complex type definition is mapped to a member variable in the Java class. Getter and setter methods are also generated for each element in the complex type.

All generated Java classes are decorated with the @XmlType annotation. If the mapping is for a named complex type, the annotations name is set to the value of the complexType element’s name attribute. If the complex type is defined as part of an element definition, the value of the @XmlType annotation’s name property is the value of the element element’s name attribute.

Note

As described in the section called “Java mapping of elements with an in-line type”, the generated class is decorated with the @XmlRootElement annotation if it is generated for a complex type defined as part of an element definition.

To provide the runtime with guidelines indicating how the elements of the XML Schema complex type should be handled, the code generators alter the annotations used to decorate the class and its member variables.

All Complex Type

All complex types are defined using the all element. They are annotated as follows:

  • The @XmlType annotation’s propOrder property is empty.
  • Each element is decorated with the @XmlElement annotation.
  • The @XmlElement annotation’s required property is set to true.

    Example 35.2, “Mapping of an All Complex Type” shows the mapping for an all complex type with two elements.

    Example 35.2. Mapping of an All Complex Type

    @XmlType(name = "all", propOrder = {
    
    })
    public class All {
        @XmlElement(required = true)
        protected BigDecimal amount;
        @XmlElement(required = true)
        protected String type;
    
        public BigDecimal getAmount() {
            return amount;
        }
    
        public void setAmount(BigDecimal value) {
            this.amount = value;
        }
    
        public String getType() {
            return type;
        }
    
        public void setType(String value) {
            this.type = value;
        }
    }
Choice Complex Type

Choice complex types are defined using the choice element. They are annotated as follows:

  • The @XmlType annotation’s propOrder property lists the names of the elements in the order they appear in the XML Schema definition.
  • None of the member variables are annotated.

    Example 35.3, “Mapping of a Choice Complex Type” shows the mapping for a choice complex type with two elements.

    Example 35.3. Mapping of a Choice Complex Type

    @XmlType(name = "choice", propOrder = {
        "address",
        "floater"
    })
    public class Choice {
    
        protected Sequence address;
        protected Float floater;
    
        public Sequence getAddress() {
            return address;
        }
    
        public void setAddress(Sequence value) {
            this.address = value;
        }
    
        public Float getFloater() {
            return floater;
        }
    
        public void setFloater(Float value) {
            this.floater = value;
        }
    
    }
Sequence Complex Type

A sequence complex type is defined using the sequence element. It is annotated as follows:

  • The @XmlType annotation’s propOrder property lists the names of the elements in the order they appear in the XML Schema definition.
  • Each element is decorated with the @XmlElement annotation.
  • The @XmlElement annotation’s required property is set to true.

    Example 35.4, “Mapping of a Sequence Complex Type” shows the mapping for the complex type defined in Example 35.1, “XML Schema Complex Type”.

    Example 35.4. Mapping of a Sequence Complex Type

    @XmlType(name = "sequence", propOrder = {
        "name",
        "street",
        "city",
        "state",
        "zipCode"
    })
    public class Sequence {
    
        @XmlElement(required = true)
        protected String name;
        protected short street;
        @XmlElement(required = true)
        protected String city;
        @XmlElement(required = true)
        protected String state;
        @XmlElement(required = true)
        protected String zipCode;
    
        public String getName() {
            return name;
        }
    
        public void setName(String value) {
            this.name = value;
        }
    
        public short getStreet() {
            return street;
        }
    
        public void setStreet(short value) {
            this.street = value;
        }
    
        public String getCity() {
            return city;
        }
    
        public void setCity(String value) {
            this.city = value;
        }
    
        public String getState() {
            return state;
        }
    
        public void setState(String value) {
            this.state = value;
        }
    
        public String getZipCode() {
            return zipCode;
        }
    
        public void setZipCode(String value) {
            this.zipCode = value;
        }
    }

35.2. Attributes

Overview

Apache CXF supports the use of attribute elements and attributeGroup elements within the scope of a complexType element. When defining structures for an XML document attribute declarations provide a means of adding information that is specified within the tag, not the value that the tag contains. For example, when describing the XML element <value currency="euro">410<\value> in XML Schema the currency attribute is described using an attribute element as shown in Example 35.5, “XML Schema Defining and Attribute”.

The attributeGroup element allows you to define a group of reusable attributes that can be referenced by all complex types defined by the schema. For example, if you are defining a series of elements that all use the attributes category and pubDate, you could define an attribute group with these attributes and reference them in all the elements that use them. This is shown in Example 35.7, “Attribute Group Definition”.

When describing data types for use in developing application logic, attributes whose use attribute is set to either optional or required are treated as elements of a structure. For each attribute declaration contained within a complex type description, an element is generated in the class for the attribute, along with the appropriate getter and setter methods.

Defining an attribute in XML Schema

An XML Schema attribute element has one required attribute, name, that is used to identify the attribute. It also has four optional attributes that are described in Table 35.2, “Optional Attributes Used to Define Attributes in XML Schema”.

Table 35.2. Optional Attributes Used to Define Attributes in XML Schema

AttributeDescription

use

Specifies if the attribute is required. Valid values are required, optional, or prohibited. optional is the default value.

type

Specifies the type of value the attribute can take. If it is not used the schema type of the attribute must be defined in-line.

default

Specifies a default value to use for the attribute. It is only used when the attribute element’s use attribute is set to optional.

fixed

Specifies a fixed value to use for the attribute. It is only used when the attribute element’s use attribute is set to optional.

Example 35.5, “XML Schema Defining and Attribute” shows an attribute element defining an attribute, currency, whose value is a string.

Example 35.5. XML Schema Defining and Attribute

<element name="value">
  <complexType>
    <xsd:simpleContent>
      <xsd:extension base="xsd:integer">
        <xsd:attribute name="currency" type="xsd:string"
                       use="required"/>
      </xsd:extension>
    </xsd:simpleContent>
  </xsd:complexType>
</xsd:element>

If the type attribute is omitted from the attribute element, the format of the data must be described in-line. Example 35.6, “Attribute with an In-Line Data Description” shows an attribute element for an attribute, category, that can take the values autobiography, non-fiction, or fiction.

Example 35.6. Attribute with an In-Line Data Description

<attribute name="category" use="required">
  <simpleType>
    <restriction base="xsd:string">
      <enumeration value="autobiography"/>
      <enumeration value="non-fiction"/>
      <enumeration value="fiction"/>
    </restriction>
  </simpleType>
</attribute>

Using an attribute group in XML Schema

Using an attribute group in a complex type definition is a two step process:

  1. Define the attribute group.

    An attribute group is defined using an attributeGroup element with a number of attribute child elements. The attributeGroup requires a name attribute that defines the string used to refer to the attribute group. The attribute elements define the members of the attribute group and are specified as shown in the section called “Defining an attribute in XML Schema”. Example 35.7, “Attribute Group Definition” shows the description of the attribute group catalogIndecies. The attribute group has two members: category, which is optional, and pubDate, which is required.

    Example 35.7. Attribute Group Definition

    <attributeGroup name="catalogIndices">
      <attribute name="category" type="catagoryType" />
      <attribute name="pubDate" type="dateTime"
                 use="required" />
    </attributeGroup>
  2. Use the attribute group in the definition of a complex type.

    You use attribute groups in complex type definitions by using the attributeGroup element with the ref attribute. The value of the ref attribute is the name given the attribute group that you want to use as part of the type definition. For example if you want to use the attribute group catalogIndecies in the complex type dvdType, you would use <attributeGroup ref="catalogIndecies" /> as shown in Example 35.8, “Complex Type with an Attribute Group”.

    Example 35.8. Complex Type with an Attribute Group

    <complexType name="dvdType">
      <sequence>
        <element name="title" type="xsd:string" />
        <element name="director" type="xsd:string" />
        <element name="numCopies" type="xsd:int" />
      </sequence>
      <attributeGroup ref="catalogIndices" />
    </complexType>

Mapping attributes to Java

Attributes are mapped to Java in much the same way that member elements are mapped to Java. Required attributes and optional attributes are mapped to member variables in the generated Java class. The member variables are decorated with the @XmlAttribute annotation. If the attribute is required, the @XmlAttribute annotation’s required property is set to true.

The complex type defined in Example 35.9, “techDoc Description” is mapped to the Java class shown in Example 35.10, “techDoc Java Class”.

Example 35.9. techDoc Description

<complexType name="techDoc">
  <all>
    <element name="product" type="xsd:string" />
    <element name="version" type="xsd:short" />
  </all>
  <attribute name="usefullness" type="xsd:float"
             use="optional" default="0.01" />
</complexType>

Example 35.10. techDoc Java Class

@XmlType(name = "techDoc", propOrder = {

})
public class TechDoc {

    @XmlElement(required = true)
    protected String product;
    protected short version;
    @XmlAttribute protected Float usefullness;

    public String getProduct() {
        return product;
    }

    public void setProduct(String value) {
        this.product = value;
    }

    public short getVersion() {
        return version;
    }

    public void setVersion(short value) {
        this.version = value;
    }

    public float getUsefullness() { if (usefullness == null) { return 0.01F; } else { return usefullness; } }

    public void setUsefullness(Float value) {
        this.usefullness = value;
    }
}

As shown in Example 35.10, “techDoc Java Class”, the default attribute and the fixed attribute instruct the code generators to add code to the getter method generated for the attribute. This additional code ensures that the specified value is returned if no value is set.

Important

The fixed attribute is treated the same as the default attribute. If you want the fixed attribute to be treated as a Java constant you can use the customization described in Section 38.5, “Customizing Fixed Value Attribute Mapping”.

Mapping attribute groups to Java

Attribute groups are mapped to Java as if the members of the group were explicitly used in the type definition. If the attribute group has three members, and it is used in a complex type, the generated class for that type will include a member variable, along with the getter and setter methods, for each member of the attribute group. For example, the complex type defined in Example 35.8, “Complex Type with an Attribute Group”, Apache CXF generates a class containing the member variables category and pubDate to support the members of the attribute group as shown in Example 35.11, “dvdType Java Class”.

Example 35.11. dvdType Java Class

@XmlType(name = "dvdType", propOrder = {
    "title",
    "director",
    "numCopies"
})
public class DvdType {

    @XmlElement(required = true)
    protected String title;
    @XmlElement(required = true)
    protected String director;
    protected int numCopies;
    @XmlAttribute protected CatagoryType category; @XmlAttribute(required = true) @XmlSchemaType(name = "dateTime") protected XMLGregorianCalendar pubDate;

    public String getTitle() {
        return title;
    }

    public void setTitle(String value) {
        this.title = value;
    }

    public String getDirector() {
        return director;
    }

    public void setDirector(String value) {
        this.director = value;
    }

    public int getNumCopies() {
        return numCopies;
    }

    public void setNumCopies(int value) {
        this.numCopies = value;
    }

    public CatagoryType getCatagory() {
        return catagory;
    }

    public void setCatagory(CatagoryType value) {
        this.catagory = value;
    }

    public XMLGregorianCalendar getPubDate() {
        return pubDate;
    }

    public void setPubDate(XMLGregorianCalendar value) {
        this.pubDate = value;
    }

}

35.3. Deriving Complex Types from Simple Types

Overview

Apache CXF supports derivation of a complex type from a simple type. A simple type has, by definition, neither sub-elements nor attributes. Hence, one of the main reasons for deriving a complex type from a simple type is to add attributes to the simple type.

There are two ways of deriving a complex type from a simple type:

Derivation by extension

Example 35.12, “Deriving a Complex Type from a Simple Type by Extension” shows an example of a complex type, internationalPrice, derived by extension from the xsd:decimal primitive type to include a currency attribute.

Example 35.12. Deriving a Complex Type from a Simple Type by Extension

<complexType name="internationalPrice">
    <simpleContent>
        <extension base="xsd:decimal">
            <attribute name="currency" type="xsd:string"/>
        </extension>
    </simpleContent>
    </complexType>

The simpleContent element indicates that the new type does not contain any sub-elements. The extension element specifies that the new type extends xsd:decimal.

Derivation by restriction

Example 35.13, “Deriving a Complex Type from a Simple Type by Restriction” shows an example of a complex type, idType, that is derived by restriction from xsd:string. The defined type restricts the possible values of xsd:stringto values that are ten characters in length. It also adds an attribute to the type.

Example 35.13. Deriving a Complex Type from a Simple Type by Restriction

<complexType name="idType">
  <simpleContent>
    <restriction base="xsd:string">
     <length value="10" />
     <attribute name="expires" type="xsd:dateTime" />
    </restriction>
  </simpleContent>
</complexType>

As in Example 35.12, “Deriving a Complex Type from a Simple Type by Extension” the simpleContent element signals that the new type does not contain any children. This example uses a restriction element to constrain the possible values used in the new type. The attribute element adds the element to the new type.

Mapping to Java

A complex type derived from a simple type is mapped to a Java class that is decorated with the @XmlType annotation. The generated class contains a member variable, value, of the simple type from which the complex type is derived. The member variable is decorated with the @XmlValue annotation. The class also has a getValue() method and a setValue() method. In addition, the generated class has a member variable, and the associated getter and setter methods, for each attribute that extends the simple type.

Example 35.14, “idType Java Class” shows the Java class generated for the idType type defined in Example 35.13, “Deriving a Complex Type from a Simple Type by Restriction”.

Example 35.14. idType Java Class

@XmlType(name = "idType", propOrder = {
    "value"
})
public class IdType {

    @XmlValue
    protected String value;
    @XmlAttribute
    @XmlSchemaType(name = "dateTime")
    protected XMLGregorianCalendar expires;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public XMLGregorianCalendar getExpires() {
        return expires;
    }

    public void setExpires(XMLGregorianCalendar value) {
        this.expires = value;
    }

}

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;
    }
}

35.5. Occurrence Constraints

35.5.1. Schema Elements Supporting Occurrence Constraints

XML Schema allows you to specify the occurrence constraints on four of the XML Schema elements that make up a complex type definition:

35.5.2. Occurrence Constraints on the All Element

XML Schema

Complex types defined with the all element do not allow for multiple occurrences of the structure defined by the all element. You can, however, make the structure defined by the all element optional by setting its minOccurs attribute to 0.

Mapping to Java

Setting the all element’s minOccurs attribute to 0 has no effect on the generated Java class.

35.5.3. Occurrence Constraints on the Choice Element

Overview

By default, the results of a choice element can only appear once in an instance of a complex type. You can change the number of times the element chosen to represent the structure defined by a choice element is allowed to appear using its minOccurs attribute and its mxOccurs attribute. Using these attributes you can specify that the choice type can occur zero to an unlimited number of times in an instance of a complex type. The element chosen for the choice type does not need to be the same for each occurrence of the type.

Using in XML Schema

The minOccurs attribute specifies the minimum number of times the choice type must appear. Its value can be any positive integer. Setting the minOccurs attribute to 0 specifies that the choice type does not need to appear inside an instance of the complex type.

The maxOccurs attribute specifies the maximum number of times the choice type can appear. Its value can be any non-zero, positive integer or unbounded. Setting the maxOccurs attribute to unbounded specifies that the choice type can appear an infinite number of times.

Example 35.18, “Choice Occurrence Constraints” shows the definition of a choice type, ClubEvent, with choice occurrence constraints. The choice type overall can be repeated 0 to unbounded times.

Example 35.18. Choice Occurrence Constraints

<complexType name="ClubEvent">
  <choice minOccurs="0" maxOccurs="unbounded">
    <element name="MemberName" type="xsd:string"/>
    <element name="GuestName" type="xsd:string"/>
  </choice>
</complexType>

Mapping to Java

Unlike single instance choice structures, XML Schema choice structures that can occur multiple times are mapped to a Java class with a single member variable. This single member variable is a List<T> object that holds all of the data for the multiple occurrences of the sequence. For example, if the sequence defined in Example 35.18, “Choice Occurrence Constraints” occurred two times, then the list would have two items.

The name of the Java class' member variable is derived by concatenating the names of the member elements. The element names are separated by Or and the first letter of the variable name is converted to lower case. For example, the member variable generated from Example 35.18, “Choice Occurrence Constraints” would be named memberNameOrGuestName.

The type of object stored in the list depends on the relationship between the types of the member elements. For example:

  • If the member elements are of the same type the generated list will contain JAXBElement<T> objects. The base type of the JAXBElement<T> objects is determined by the normal mapping of the member elements' type.
  • If the member elements are of different types and their Java representations implement a common interface, the list will contains objects of the common interface.
  • If the member elements are of different types and their Java representations extend a common base class, the list will contains objects of the common base class.
  • If none of the other conditions are met, the list will contain Object objects.

The generated Java class will only have a getter method for the member variable. The getter method returns a reference to the live list. Any modifications made to the returned list will effect the actual object.

The Java class is decorated with the @XmlType annotation. The annotation’s name property is set to the value of the name attribute from the parent element of the XML Schema definition. The annotation’s propOrder property contains the single member variable representing the elements in the sequence.

The member variable representing the elements in the choice structure are decorated with the @XmlElements annotation. The @XmlElements annotation contains a comma separated list of @XmlElement annotations. The list has one @XmlElement annotation for each member element defined in the XML Schema definition of the type. The @XmlElement annotations in the list have their name property set to the value of the XML Schema element element’s name attribute and their type property set to the Java class resulting from the mapping of the XML Schema element element’s type.

Example 35.19, “Java Representation of Choice Structure with an Occurrence Constraint” shows the Java mapping for the XML Schema choice structure defined in Example 35.18, “Choice Occurrence Constraints”.

Example 35.19. Java Representation of Choice Structure with an Occurrence Constraint

@XmlType(name = "ClubEvent", propOrder = {
    "memberNameOrGuestName"
})
public class ClubEvent {

    @XmlElementRefs({
        @XmlElementRef(name = "GuestName", type = JAXBElement.class),
        @XmlElementRef(name = "MemberName", type = JAXBElement.class)
    })
    protected List<JAXBElement<String>> memberNameOrGuestName;

    public List<JAXBElement<String>> getMemberNameOrGuestName() {
        if (memberNameOrGuestName == null) {
            memberNameOrGuestName = new ArrayList<JAXBElement<String>>();
        }
        return this.memberNameOrGuestName;
    }

}

minOccurs set to 0

If only the minOccurs element is specified and its value is 0, the code generators generate the Java class as if the minOccurs attribute were not set.

35.5.4. Occurrence Constraints on Elements

Overview

You can specify how many times a specific element in a complex type appears using the element element’s minOccurs attribute and maxOccurs attribute. The default value for both attributes is 1.

minOccurs set to 0

When you set one of the complex type’s member element’s minOccurs attribute to 0, the @XmlElement annotation decorating the corresponding Java member variable is changed. Instead of having its required property set to true, the @XmlElement annotation’s required property is set to false.

minOccurs set to a value greater than 1

In XML Schema you can specify that an element must occur more than once in an instance of the type by setting the element element’s minOccurs attribute to a value greater than one. However, the generated Java class will not support the XML Schema constraint. Apache CXF generates the supporting Java member variable as if the minOccurs attribute were not set.

Elements with maxOccurs set

When you want a member element to appear multiple times in an instance of a complex type, you set the element’s maxOccurs attribute to a value greater than 1. You can set the maxOccurs attribute’s value to unbounded to specify that the member element can appear an unlimited number of times.

The code generators map a member element with the maxOccurs attribute set to a value greater than 1 to a Java member variable that is a List<T> object. The base class of the list is determined by mapping the element’s type to Java. For XML Schema primitive types, the wrapper classes are used as described in the section called “Wrapper classes”. For example, if the member element is of type xsd:int the generated member variable is a List<Integer> object.

35.5.5. Occurrence Constraints on Sequences

Overview

By default, the contents of a sequence element can only appear once in an instance of a complex type. You can change the number of times the sequence of elements defined by a sequence element is allowed to appear using its minOccurs attribute and its maxOccurs attribute. Using these attributes you can specify that the sequence type can occur zero to an unlimited number of times in an instance of a complex type.

Using XML Schema

The minOccurs attribute specifies the minimum number of times the sequence must occur in an instance of the defined complex type. Its value can be any positive integer. Setting the minOccurs attribute to 0 specifies that the sequence does not need to appear inside an instance of the complex type.

The maxOccurs attribute specifies the upper limit for how many times the sequence can occur in an instance of the defined complex type. Its value can be any non-zero, positive integer or unbounded. Setting the maxOccurs attribute to unbounded specifies that the sequence can appear an infinite number of times.

Example 35.20, “Sequence with Occurrence Constraints” shows the definition of a sequence type, CultureInfo, with sequence occurrence constraints. The sequence can be repeated 0 to 2 times.

Example 35.20. Sequence with Occurrence Constraints

<complexType name="CultureInfo">
  <sequence minOccurs="0" maxOccurs="2">
    <element name="Name" type="string"/>
    <element name="Lcid" type="int"/>
  </sequence>
</complexType>

Mapping to Java

Unlike single instance sequences, XML Schema sequences that can occur multiple times are mapped to a Java class with a single member variable. This single member variable is a List<T> object that holds all of the data for the multiple occurrences of the sequence. For example, if the sequence defined in Example 35.20, “Sequence with Occurrence Constraints” occurred two times, then the list would have four items.

The name of the Java class' member variable is derived by concatenating the names of the member elements. The element names are separated by And and the first letter of the variable name is converted to lower case. For example, the member variable generated from Example 35.20, “Sequence with Occurrence Constraints” is named nameAndLcid.

The type of object stored in the list depends on the relationship between the types of the member elements. For example:

  • If the member elements are of the same type the generated list will contain JAXBElement<T> objects. The base type of the JAXBElement<T> objects is determined by the normal mapping of the member elements' type.
  • If the member elements are of different types and their Java representations implement a common interface, the list will contains objects of the common interface.
  • If the member elements are of different types and their Java representations extend a common base class, the list will contain objects of the common base class.
  • If none of the other conditions are met, the list will contain Object objects.

The generated Java class only has a getter method for the member variable. The getter method returns a reference to the live list. Any modifications made to the returned list effects the actual object.

The Java class is decorated with the @XmlType annotation. The annotation’s name property is set to the value of the name attribute from the parent element of the XML Schema definition. The annotation’s propOrder property contains the single member variable representing the elements in the sequence.

The member variable representing the elements in the sequence are decorated with the @XmlElements annotation. The @XmlElements annotation contains a comma separated list of @XmlElement annotations. The list has one @XmlElement annotation for each member element defined in the XML Schema definition of the type. The @XmlElement annotations in the list have their name property set to the value of the XML Schema element element’s name attribute and their type property set to the Java class resulting from the mapping of the XML Schema element element’s type.

Example 35.21, “Java Representation of Sequence with an Occurrence Constraint” shows the Java mapping for the XML Schema sequence defined in Example 35.20, “Sequence with Occurrence Constraints”.

Example 35.21. Java Representation of Sequence with an Occurrence Constraint

@XmlType(name = "CultureInfo", propOrder = {
    "nameAndLcid"
})
public class CultureInfo {

    @XmlElements({
        @XmlElement(name = "Name", type = String.class),
        @XmlElement(name = "Lcid", type = Integer.class)
    })
    protected List<Serializable> nameAndLcid;

    public List<Serializable> getNameAndLcid() {
        if (nameAndLcid == null) {
            nameAndLcid = new ArrayList<Serializable>();
        }
        return this.nameAndLcid;
    }

}

minOccurs set to 0

If only the minOccurs element is specified and its value is 0, the code generators generate the Java class as if the minOccurs attribute is not set.

35.6. Using Model Groups

Overview

XML Schema model groups are convenient shortcuts that allows you to reference a group of elements from a user-defined complex type.For example, you can define a group of elements that are common to several types in your application and then reference the group repeatedly. Model groups are defined using the group element, and are similar to complex type definitions. The mapping of model groups to Java is also similar to the mapping for complex types.

Defining a model group in XML Schema

You define a model group in XML Schema using the group element with the name attribute. The value of the name attribute is a string that is used to refer to the group throughout the schema. The group element, like the complexType element, can have the sequence element, the all element, or the choice element as its immediate child.

Inside the child element, you define the members of the group using element elements. For each member of the group, specify one element element. Group members can use any of the standard attributes for the element element including minOccurs and maxOccurs. So, if your group has three elements and one of them can occur up to three times, you define a group with three element elements, one of which uses maxOccurs="3". Example 35.22, “XML Schema Model Group” shows a model group with three elements.

Example 35.22. XML Schema Model Group

<group name="passenger">
  <sequence>
    <element name="name" type="xsd:string" />
    <element name="clubNum" type="xsd:long" />
    <element name="seatPref" type="xsd:string"
             maxOccurs="3" />
  </sequence>
</group>

Using a model group in a type definition

Once a model group has been defined, it can be used as part of a complex type definition. To use a model group in a complex type definition, use the group element with the ref attribute. The value of the ref attribute is the name given to the group when it was defined. For example, to use the group defined in Example 35.22, “XML Schema Model Group” you use <group ref="tns:passenger" /> as shown in Example 35.23, “Complex Type with a Model Group”.

Example 35.23. Complex Type with a Model Group

<complexType name="reservation">
  <sequence>
    <group ref="tns:passenger" />
    <element name="origin" type="xsd:string" />
    <element name="destination" type="xsd:string" />
    <element name="fltNum" type="xsd:long" />
  </sequence>
</complexType>

When a model group is used in a type definition, the group becomes a member of the type. So an instance of reservation has four member elements. The first element is the passenger element and it contains the member elements defined by the group shown in Example 35.22, “XML Schema Model Group”. An example of an instance of reservation is shown in Example 35.24, “Instance of a Type with a Model Group”.

Example 35.24. Instance of a Type with a Model Group

<reservation>
  <passenger> <name>A. Smart</name> <clubNum>99</clubNum> <seatPref>isle1</seatPref> </passenger>
  <origin>LAX</origin>
  <destination>FRA</destination>
  <fltNum>34567</fltNum>
</reservation>

Mapping to Java

By default, a model group is only mapped to Java artifacts when it is included in a complex type definition. When generating code for a complex type that includes a model group, Apache CXF simply includes the member variables for the model group into the Java class generated for the type. The member variables representing the model group are annotated based on the definitions of the model group.

Example 35.25, “Type with a Group” shows the Java class generated for the complex type defined in Example 35.23, “Complex Type with a Model Group”.

Example 35.25. Type with a Group

@XmlType(name = "reservation", propOrder = {
    "name",
    "clubNum",
    "seatPref",
    "origin",
    "destination",
    "fltNum"
})
public class Reservation {

    @XmlElement(required = true)
    protected String name;
    protected long clubNum;
    @XmlElement(required = true)
    protected List<String> seatPref;
    @XmlElement(required = true)
    protected String origin;
    @XmlElement(required = true)
    protected String destination;
    protected long fltNum;

    public String getName() {
        return name;
    }

    public void setName(String value) {
        this.name = value;
    }

    public long getClubNum() {
        return clubNum;
    }

    public void setClubNum(long value) {
        this.clubNum = value;
    }

    public List<String> getSeatPref() {
        if (seatPref == null) {
            seatPref = new ArrayList<String>();
        }
        return this.seatPref;
    }

    public String getOrigin() {
        return origin;
    }

    public void setOrigin(String value) {
        this.origin = value;
    }

    public String getDestination() {
        return destination;
    }

    public void setDestination(String value) {
        this.destination = value;
    }

    public long getFltNum() {
        return fltNum;
    }

    public void setFltNum(long value) {
        this.fltNum = value;
    }

Multiple occurrences

You can specify that the model group appears more than once by setting the group element’s maxOccurs attribute to a value greater than one. To allow for multiple occurrences of the model group Apache CXF maps the model group to a List<T> object. The List<T> object is generated following the rules for the group’s first child: