35.4. 複合型からの複合型の導出

概要

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

スキーマ構文

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

複合型の拡張

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

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

例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「拡張による複合型の導出」 のスキーマにより、WidgetOrderInfo および WidgetBillOrderInfo の 2 つの Java クラスが生成されます。WidgetOrderBillInfowidgetOrderInfo の拡張で派生しているため、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;
    }
}