I am generating Java objects from an XML schema using xjc. I would like to reference the same element multiple times within the document using IDREF. I would also like to constrain the objects referenced by IDREF to a specific type. I'd like to do this for the purposes of schema validation, but also so that in the Java code, the referenced object is returned as a specific type instead of type Object. For example, say I want a schema to describe the following:
<teams>
<team id="team1">
<coach>coachz</coach>
<player>homestar</player>
<player>marzipan</player>
<player>strongsad</player>
<player>strongbad</player>
</team>
<team id="team2">
<coach>bubs</coach>
<player>homesar</player>
<player>thecheat</player>
<player>poopsmith</player>
<player>bubs</player>
</team>
<team id="allstars">
<coach>poopsmith</coach>
<player>coachz</player>
<player>bubs</player>
<player>kingoftown</player>
<player>strongbad</player>
</team>
</teams>
<people>
<person id="coachz">Coach Z</person>
<person id="homesar">Homesar</person>
<person id="homestar">Homestar</person>
<person id="strongbad">Strong Bad</person>
<person id="strongsad">Strong Sad</person>
<person id="marzipan">Marzipan</person>
<person id="bubs">Bubs</person>
<person id="kingoftown">King of Town</person>
<person id="poopsmith">The Poopsmith</person>
<person id="thecheat">The Cheat</person>
</people>
I can define player
like this:
<xs:element name="player" type="xs:IDREF" maxOccurs="unbounded"/>
but then in the Java code, when I try to retrieve a player it will come back as type object, and I have to cast it to a person. At that point, if someone has mistakenly referenced a Team object, I have errors to deal with that could have been caught at validation. I want to specify something like this:
<xs:element name="player" type="xs:IDREF"
reftype="person"
maxOccurs="unbounded" />
But as far as I can tell, there is no way to specify a type as I have done here with the contrived attribute 'reftype'. Can this be done, using IDREF? If not, is there another method?
You can simply apply baseType
binding to your player
element. Something like:
<jaxb:bindings node="xsd:element[@name='player']">
<jaxb:property>
<jaxb:baseType name="....Person"/>
</jaxb:property>
</jaxb:bindings>
You may need to figure out the correct binding location for your schema.
Example from my code:
Schema:
<xsd:complexType name="HJIII-53-A">
<xsd:sequence>
<xsd:element name="b" type="xsd:IDREF"/>
<xsd:element name="b1" type="test:HJIII-53-B"/>
<xsd:element name="c" type="xsd:IDREFS"/>
<xsd:element name="c1" type="test:HJIII-53-C" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
Bindings:
<jaxb:bindings schemaLocation="schema.xsd" node="/xsd:schema">
<jaxb:globalBindings localScoping="toplevel">
<jaxb:serializable/>
</jaxb:globalBindings>
<jaxb:bindings node="xsd:complexType[@name='HJIII-53-A']//xsd:element[@name='b']">
<jaxb:property>
<jaxb:baseType name="org.jvnet.hyperjaxb3.ejb.tests.issuesjpa2.HJIII53B"/>
</jaxb:property>
</jaxb:bindings>
<jaxb:bindings node="xsd:complexType[@name='HJIII-53-A']//xsd:element[@name='c']">
<jaxb:property>
<jaxb:baseType name="org.jvnet.hyperjaxb3.ejb.tests.issuesjpa2.HJIII53C"/>
</jaxb:property>
</jaxb:bindings>
</jaxb:bindings>
Generated code:
@XmlElement(required = true, type = Object.class)
@XmlIDREF
@XmlSchemaType(name = "IDREF")
protected org.jvnet.hyperjaxb3.ejb.tests.issuesjpa2.HJIII53B b;
@XmlElement(required = true)
protected org.jvnet.hyperjaxb3.ejb.tests.issuesjpa2.HJIII53B b1;
@XmlList
@XmlElement(required = true, type = Object.class)
@XmlIDREF
protected List<org.jvnet.hyperjaxb3.ejb.tests.issuesjpa2.HJIII53C> c;
protected List<org.jvnet.hyperjaxb3.ejb.tests.issuesjpa2.HJIII53C> c1;
See: https://svn.java.net/svn/hj3~svn/trunk/ejb/tests/issues-jpa2/src/main/resources/