Menu Close

35.4. 複合型からの複合型の派生

概要

XML スキーマを使用すると、complexContent 要素を使用して、他の複合型を拡張または制限することで、新しい複合型を派生することができます。派生した複合型を表す Java クラスを生成すると、Apache CXF はベース型のクラスを拡張します。このようにして、生成された Java コードは XML スキーマで意図される継承階層を保持します。

スキーマ構文

complexContent 要素および extension 要素または restriction 要素のいずれかを使用して、他の複合型から複合型を派生します。complexContent 要素は、含まれるデータの説明に複数のフィールドが含まれることを指定します。complexContent 要素の子である extension 要素および restriction 要素は、新しい型を作成するために変更するベース型を指定します。ベース型は base 属性で指定します。

複合型の拡張

複合型を拡張するには、extension 要素を使用して、新しい型を構成する追加の要素と属性を定義します。複合型の説明で使用できるすべての要素は、新しい型の定義の一部として許可されます。たとえば、新しい型に匿名の列挙を追加することや、choice 要素を使用して新しいフィールドの 1 つだけを一度に有効にできることを指定することが可能です。

例35.15「拡張による複合型の派生」に、widgetOrderInfowidgetOrderBillInfo の 2 つの複合型を定義する XML スキーマフラグメントを示します。orderNumberamtDue の 2 つの新しい要素が含まれるように widgetOrderInfo を拡張して、widgetOrderBillInfo を派生します。

例35.15 拡張による複合型の派生

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

複合型の制限

複合型を制限するには、restriction 要素を使用してベース型の要素または属性で使用可能な値を制限します。複合型を制限する場合は、ベース型のすべての要素および属性を一覧表示する必要があります。要素ごとに、定義に制限のある属性を追加できます。たとえば、maxOccurs 属性を要素に追加して、発生回数を制限できます。fixed 属性を使用して、1 つまたは複数の要素が事前に決定された値を持つように強制することもできます。

例35.16「制限による複合型の定義」に、複合型を制限して別の複合型を定義する例を示します。city 要素、state 要素、および zipCode 要素の値は固定なので、制限された型 wallawallaAddress は、Washington 州 Walla Walla のアドレスにのみ使用できます。

例35.16 制限による複合型の定義

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

Java へのマッピング

すべての複合型と同様に、Apache CXF は別の複合型から派生した複合型を表すクラスを生成します。派生した複合型用に生成された Java クラスは、ベースの複合型をサポートするために生成された Java クラスを拡張します。ベース Java クラスは @XmlSeeAlso アノテーションを付けるためにも変更されます。ベースクラスの @XmlSeeAlso アノテーションは、ベースクラスを拡張するすべてのクラスを一覧表示します。

新しい複合型が拡張によって派生されると、生成されたクラスには、追加されたすべての要素および属性のメンバー変数が含まれます。新規メンバー変数は、他のすべての要素と同じマッピングに従って生成されます。

新しい複合型が制限によって派生されると、生成されたクラスに新しいメンバー変数は含まれません。生成されたクラスは、追加機能を提供しないただのシェルになります。XML スキーマで定義された制限が強制されるようにするのは、完全にユーザー次第です。

たとえば、例35.15「拡張による複合型の派生」のスキーマの場合は、WidgetOrderInfoWidgetBillOrderInfo の 2 つの Java クラスが生成されます。widgetOrderBillInfo はエクステンションにより widgetOrderInfo から派生するため、WidgetOrderBillInfoWidgetOrderInfo を拡張します。例35.17「WidgetOrderBillInfo」に、widgetOrderBillInfo の生成されたクラスを示します。

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