37.2. Java에서 그룹 대체

37.2.1. 개요

JAXB 사양에 지정된 대로 Apache CXF는 와일드카드 정의에 대한 JAXBElement 클래스 지원 기능과 함께 Java의 네이티브 클래스 계층 구조를 사용하는 대체 그룹을 지원합니다. 대체 그룹의 멤버가 모두 공통 기본 형식을 공유해야 하므로 요소의 유형을 지원하기 위해 생성된 클래스도 공통 기본 유형을 공유합니다. 또한 Apache CXF는 헤드 요소의 인스턴스를 JAXBElement<? 확장 T > 속성에 매핑합니다.

37.2.2. 생성된 개체 팩토리 방법

대체 그룹을 포함하는 패키지를 지원하기 위해 생성된 개체 팩토리에는 대체 그룹의 각 요소에 대한 메서드가 있습니다. head 요소를 제외하고 대체 그룹의 각 멤버마다 표 37.1. “JAXB 요소 선언을 위한 속성은 Substitution 그룹의 멤버입니다.” 에 설명된 대로 오브젝트 팩토리 메서드를 장식하는 @XmlElementDecl 주석에는 두 가지 추가 속성이 포함됩니다.

표 37.1. JAXB 요소 선언을 위한 속성은 Substitution 그룹의 멤버입니다.

속성설명

substitutionHeadNamespace

head 요소가 정의된 네임스페이스를 지정합니다.

substitutionHeadName

head 요소의 name 특성의 값을 지정합니다.

대체 그룹의 @XmlElementDecl 대체 요소의 헤드 요소에 대한 개체 팩토리 메서드에는 기본 네임스페이스 속성 및 기본 이름 속성만 포함됩니다.

요소 인스턴스화 방법 외에도 개체 팩토리에는 head 요소를 나타내는 개체를 인스턴스화하는 메서드가 포함됩니다.In addition to the element instantiation methods, the object factory contains a method for instantiating an object representing the head element. 대체 그룹의 멤버가 모두 복잡한 형식인 경우 개체 팩토리에는 사용되는 각 복잡한 유형의 인스턴스를 인스턴스화하는 방법도 포함됩니다.

예 37.5. “Substitution 그룹에 대한 Object Factory Method” 예 37.2. “Complex Types을 사용하는 대체 그룹” 에 정의된 대체 그룹의 오브젝트 팩토리 메서드를 보여줍니다.

예 37.5. Substitution 그룹에 대한 Object Factory Method

public class ObjectFactory {

    private final static QName _Widget_QNAME = new QName(...);
    private final static QName _PlasticWidget_QNAME = new QName(...);
    private final static QName _WoodWidget_QNAME = new QName(...);

    public ObjectFactory() {
    }

    public WidgetType createWidgetType() {
        return new WidgetType();
    }

    public PlasticWidgetType createPlasticWidgetType() {
        return new PlasticWidgetType();
    }

    public WoodWidgetType createWoodWidgetType() {
        return new WoodWidgetType();
    }

    @XmlElementDecl(namespace="...", name = "widget")
    public JAXBElement<WidgetType> createWidget(WidgetType value) {
        return new JAXBElement<WidgetType>(_Widget_QNAME, WidgetType.class, null, value);
    }

    @XmlElementDecl(namespace = "...", name = "plasticWidget", substitutionHeadNamespace = "...", substitutionHeadName = "widget")
    public JAXBElement<PlasticWidgetType> createPlasticWidget(PlasticWidgetType value) {
        return new JAXBElement<PlasticWidgetType>(_PlasticWidget_QNAME, PlasticWidgetType.class, null, value);
    }

    @XmlElementDecl(namespace = "...", name = "woodWidget", substitutionHeadNamespace = "...", substitutionHeadName = "widget")
    public JAXBElement<WoodWidgetType> createWoodWidget(WoodWidgetType value) {
        return new JAXBElement<WoodWidgetType>(_WoodWidget_QNAME, WoodWidgetType.class, null, value);
    }

}

37.2.3. 인터페이스의 대체 그룹

대체 그룹의 헤드 요소가 작업 메시지 중 하나에서 메시지 파트로 사용되는 경우 결과 메서드 매개 변수는 해당 요소를 지원하기 위해 생성된 클래스의 객체가 됩니다. JAXBElement<? extends T> 클래스의 인스턴스일 필요는 없습니다. 런타임은 Java의 네이티브 유형 계층 구조를 사용하여 유형 대체를 지원하고 Java는 지원되지 않는 유형을 사용하려고 합니다.

런타임에서 요소 대체를 지원하는 데 필요한 모든 클래스를 알고 있도록 SEI는 @XmlSee also 주석으로 장식됩니다. 이 주석은 마샬링에 런타임에 필요한 클래스 목록을 지정합니다. @XmlSeeAlso 주석을 사용하는 방법에 대한 자세한 내용은 32.4절. “런타임 Marshaller에 클래스 추가” 을 참조하십시오.

예 37.7. “Substitution 그룹을 사용하여 생성된 인터페이스”예 37.6. “Substitution 그룹을 사용하는 WSDL 인터페이스” 에 표시된 인터페이스에 대해 생성된 SEI를 표시합니다. 이 인터페이스에서는 예 37.2. “Complex Types을 사용하는 대체 그룹” 에 정의된 대체 그룹을 사용합니다.

예 37.6. Substitution 그룹을 사용하는 WSDL 인터페이스

<message name="widgetMessage">
    <part name="widgetPart" element="xsd1:widget" />
  </message>
  <message name="numWidgets">
    <part name="numInventory" type="xsd:int" />
  </message>
  <message name="badSize">
    <part name="numInventory" type="xsd:int" />
  </message>
  <portType name="orderWidgets">
    <operation name="placeWidgetOrder">
      <input message="tns:widgetOrder" name="order" />
      <output message="tns:widgetOrderBill" name="bill" />
      <fault message="tns:badSize" name="sizeFault" />
    </operation>
    <operation name="checkWidgets">
      <input message="tns:widgetMessage" name="request" />
      <output message="tns:numWidgets" name="response" />
    </operation>
  </portType>

예 37.7. Substitution 그룹을 사용하여 생성된 인터페이스

@WebService(targetNamespace = "...", name = "orderWidgets")
@XmlSeeAlso({com.widgetvendor.types.widgettypes.ObjectFactory.class})
public interface OrderWidgets {

    @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
    @WebResult(name = "numInventory", targetNamespace = "", partName = "numInventory")
    @WebMethod
    public int checkWidgets(
        @WebParam(partName = "widgetPart", name = "widget", targetNamespace = "...")
        com.widgetvendor.types.widgettypes.WidgetType widgetPart
    );
}

예 37.7. “Substitution 그룹을 사용하여 생성된 인터페이스” 에 표시된 SEI는 @XmlSeeAlso 주석의 오브젝트 팩토리를 나열합니다. 네임스페이스의 개체 팩토리를 나열하면 해당 네임스페이스에 대해 생성된 모든 클래스에 액세스할 수 있습니다.

37.2.4. 복잡한 유형의 대체 그룹

대체 그룹의 헤드 요소가 복잡한 형식의 요소로 사용될 때 코드 생성기는 요소를 JAXBElement<? extends T> 속성에 매핑합니다.When the head element of a substitution group is used as an element in a complex type, the code generator maps the element to a JAXBElement<? extends T > property. 대체 그룹을 지원하기 위해 생성된 생성된 클래스의 인스턴스가 포함된 속성에 매핑되지 않습니다.It does not map it to a property containing an instance of the generated class generated to support the substitution group.

예를 들어 예 37.8. “대체 그룹을 사용하는 복잡한 유형” 에 정의된 복잡한 유형은 예 37.9. “대체 그룹을 사용하여 복잡한 유형의 Java 클래스” 로 표시되는 Java 클래스가 생성됩니다. 복잡한 유형에서는 예 37.2. “Complex Types을 사용하는 대체 그룹” 에 정의된 대체 그룹을 사용합니다.

예 37.8. 대체 그룹을 사용하는 복잡한 유형

<complexType name="widgetOrderInfo">
  <sequence>
    <element name="amount" type="xsd:int"/>
    <element ref="xsd1:widget"/>
  </sequence>
</complexType>

예 37.9. 대체 그룹을 사용하여 복잡한 유형의 Java 클래스

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "widgetOrderInfo", propOrder = {"amount","widget",})
public class WidgetOrderInfo {

    protected int amount;
    @XmlElementRef(name = "widget", namespace = "...", type = JAXBElement.class) protected JAXBElement<? extends WidgetType> widget;
    public int getAmount() {
        return amount;
    }

    public void setAmount(int value) {
        this.amount = value;
    }

    public JAXBElement<? extends WidgetType> getWidget() { return widget; }

    public void setWidget(JAXBElement<? extends WidgetType> value) { this.widget = ((JAXBElement<? extends WidgetType> ) value); }

}

37.2.5. 대체 그룹 속성 설정

대체 그룹으로 작업하는 방법은 코드 생성기가 그룹을 직각 Java 클래스 또는 JAXBElement<? extends T > 클래스에 매핑했는지에 따라 달라집니다. 요소가 생성된 값 클래스의 개체에 간단히 매핑되면 형식 계층 구조의 일부인 다른 Java 객체와 동일한 방식으로 오브젝트로 작업합니다. 부모 클래스에 대한 하위 클래스 중 하나를 대체할 수 있습니다. 개체를 검사하여 정확한 클래스를 확인하고 적절하게 캐스팅할 수 있습니다.

JAXB 사양은 생성된 클래스의 오브젝트를 인스턴스화하는 데 오브젝트 팩토리 메서드를 사용하는 것이 좋습니다.

코드 생성기에서 JAXBElement<? 확장 T> 개체를 확장하여 대체 그룹의 인스턴스를 보관하도록 확장하는 경우 요소의 값을 JAXBElement<? extends T > 개체에 래핑해야 합니다.When the code generators create a JAXBElement<? extends T> object to hold instances of a substitution group, you must wrap the element's value in a JAXBElement<? extends T > object. 이를 수행하는 가장 좋은 방법은 개체 팩토리에서 제공하는 요소 생성 방법을 사용하는 것입니다. 해당 값을 기반으로 요소를 만들기 위한 쉬운 방법을 제공합니다.

예 37.10. “하위 그룹의 멤버 설정” 대체 그룹의 인스턴스를 설정하기 위한 코드를 보여줍니다.

예 37.10. 하위 그룹의 멤버 설정

ObjectFactory of = new ObjectFactory();
PlasticWidgetType pWidget = of.createPlasticWidgetType();
pWidget.setShape = "round';
pWidget.setColor = "green";
pWidget.setMoldProcess = "injection";

JAXBElement<PlasticWidgetType> widget = of.createPlasticWidget(pWidget);

WidgetOrderInfo order = of.createWidgetOrderInfo();
order.setWidget(widget);

예 37.10. “하위 그룹의 멤버 설정” 의 코드는 다음을 수행합니다.

개체 팩토리를 인스턴스화합니다.

plastic WidgetType 개체를 인스턴스화 합니다.

JAXBElement<PlasticWidgetType > 개체를 인스턴스화하여 플라스틱 위젯 요소를 보유합니다.

위젯 OrderInfo 오브젝트를 인스턴스화 합니다.

위젯 OrderInfo 개체의 위젯을 plastic widget 요소를 포함하는 JAXBElement 개체로 설정합니다.

37.2.6. 대체 그룹 속성의 값 가져오기

개체 팩토리 메서드는 요소의 값을 JAXBElement<? 확장 T > 개체에서 추출할 때 도움이 되지 않습니다. JAXBElement<? 확장 T >의 getValue() 메서드를 사용해야 합니다. 다음 옵션은 getValue() 메서드에서 반환된 오브젝트 유형을 결정합니다.

  • 모든 가능한 클래스의 isInstance() 메서드를 사용하여 요소의 value 개체의 클래스를 결정합니다.
  • JAXBElement<? extends T > 개체의 getName() 메서드를 사용하여 요소의 이름을 결정합니다.

    getName() 메서드는 QName을 반환합니다. 요소의 로컬 이름을 사용하여 값 개체에 대한 적절한 클래스를 확인할 수 있습니다.

  • JAXBElement<? extends T > 개체의 getDeclaredType() 메서드를 사용하여 value 개체의 클래스를 확인합니다.

    getDeclaredType() 메서드는 요소의 value 개체의 Class 오브젝트를 반환합니다.

    주의

    getDeclaredType() 메서드가 value 개체의 실제 클래스에 관계없이 head 요소의 기본 클래스를 반환할 가능성이 있습니다.

예 37.11. “Substitution 그룹의 멤버 값 가져오기Get the value of a Member of the Substitution Group” 대체 그룹에서 값을 검색하는 코드를 표시합니다. 요소 값 개체의 적절한 클래스를 결정하려면 예제에서는 요소의 getName() 메서드를 사용합니다.

예 37.11. Substitution 그룹의 멤버 값 가져오기Get the value of a Member of the Substitution Group

String elementName = order.getWidget().getName().getLocalPart();
if (elementName.equals("woodWidget")
{
  WoodWidgetType widget=order.getWidget().getValue();
}
else if (elementName.equals("plasticWidget")
{
  PlasticWidgetType widget=order.getWidget().getValue();
}
else
{
  WidgetType widget=order.getWidget().getValue();
}