views:

24

answers:

2

So I've been reading up on using IDs and IDREFs in JAXB here, and in the example presented they make use of 1 IDREF element, which appears as an Object in the generated Java code. I include both the XML Schema...

<xsd:complexType name="CustomerType">
  <xsd:sequence>
    <xsd:element name="id"   type="xsd:ID"/>
    <xsd:element name="name" type="xsd:string"/>
  </xsd:sequence>
</xsd:complexType>

<xsd:complexType name="OrderType">
  <xsd:sequence>
    <xsd:choice>
      <xsd:element name="customer" type="CustomerType"/>
      <xsd:element name="custref"  type="xsd:IDREF"/>
    </xsd:choice>
    <xsd:element name="items" type="ItemType" maxOccurs="unbounded"/>
  </xsd:sequence>
</xsd:complexType>

and the Java code for posterity.

public class OrderType {

    protected CustomerType customer;
    protected Object custref;
    protected List items;

    public CustomerType getCustomer() {
        return customer;
    }

    public void setCustomer(CustomerType value) {
        this.customer = value;
    }

    public Object getCustref() {
        return custref;
    }

    public void setCustref(Object value) {
        this.custref = value;
    }

    public List getItems() {
        if (items == null) {
            items = new ArrayList();
        }
        return this.items;
    }
}

Now, in my code, I tried something a tad different, exemplified by the following schema:

<xsd:complexType name="SimViewType">
    <xsd:sequence>
        <xsd:element name="NAME" type="xsd:string"></xsd:element>
        <xsd:element name="ITEM" type="am:SimItemIDREF" minOccurs="0" maxOccurs="unbounded"></xsd:element>
    </xsd:sequence>
    <xsd:attribute name="id" type="xsd:ID" use="required"></xsd:attribute>
</xsd:complexType>

<xsd:simpleType name="SimItemIDREF">
    <xsd:restriction base="xsd:IDREF"></xsd:restriction>
</xsd:simpleType>

Though I've enclosed a general IDREF with a SimItemIDREF, it's just for readability. However, even if I use a normal xsd:IDREF instead, the simple fact I use a value other than 1 means that my Java code ends up with the following...

public class SimViewType {
    ...
    protected List<JAXBElement<Object>> item;
    ...
}

Instead of a List<Object>, I get a List<JAXElement<Object>>. Now, if I want to make a JAXElement, I can do that fine, but I cannot add it to my SimViewType as there is no conversion between JAXElement<SimItemType> and JAXElement<Object>. The idea that SimViews don't actually maintain control of SimItems is crucial in my design, so simply removing references is just not a good idea as it can create dangerous discrepancies at runtime.

How can I create a SimItemType or JAXBElement such that I can use it with my SimViewType?

A: 

XJC generates ObjectFactory with createSimViewTypeITEM method to create ITEM elements.

/**
 * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
 * 
 */
@XmlElementDecl(namespace = "", name = "ITEM", scope = SimViewType.class)
@XmlIDREF
public JAXBElement<Object> createSimViewTypeITEM(Object value) {
    return new JAXBElement<Object>(_SimViewTypeITEM_QNAME, Object.class, SimViewType.class, value);
}

Does it help?

syntetic
A: 

You could annotated your schema as follows to get the desired class:

<xsd:schema 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns="http://www.mycompany.org/exchange" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    targetNamespace="http://www.mycompany.org/exchange" 
    elementFormDefault="qualified" attributeFormDefault="unqualified"
    jaxb:version="2.1"> 

    <xsd:complexType name="CustomerType"> 
        <xsd:sequence> 
            <xsd:element name="id"   type="xsd:ID"/> 
            <xsd:element name="name" type="xsd:string"/> 
        </xsd:sequence> 
    </xsd:complexType> 

    <xsd:complexType name="OrderType"> 
        <xsd:sequence> 
            <xsd:choice> 
                <xsd:element name="customer" type="CustomerType"/> 
                <xsd:element name="custref"  type="xsd:IDREF"> 
                    <xsd:annotation>
                        <xsd:appinfo>
                            <jaxb:property>
                                <jaxb:baseType name="org.mycompany.exchange.CustomerType"/>
                            </jaxb:property>
                        </xsd:appinfo>
                    </xsd:annotation>
                </xsd:element>
            </xsd:choice> 
            <!--xsd:element name="items" type="ItemType" maxOccurs="unbounded"/--> 
        </xsd:sequence> 
    </xsd:complexType> 

</xsd:schema>

The following is the resulting class:

package org.mycompany.exchange;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlIDREF;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;


@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "OrderType", propOrder = {
    "customer",
    "custref"
})
public class OrderType {

    protected org.mycompany.exchange.CustomerType customer;
    @XmlElement(type = Object.class)
    @XmlIDREF
    @XmlSchemaType(name = "IDREF")
    protected org.mycompany.exchange.CustomerType custref;

    public org.mycompany.exchange.CustomerType getCustomer() {
        return customer;
    }

    public void setCustomer(org.mycompany.exchange.CustomerType value) {
        this.customer = value;
    }

    public org.mycompany.exchange.CustomerType getCustref() {
        return custref;
    }

    public void setCustref(org.mycompany.exchange.CustomerType value) {
        this.custref = value;
    }

}
Blaise Doughan