Hi -
I have a question regarding the form of the generated Java bindings for
a list defined by the following schema fragment:
<complexType name="RegistryObjectType">
<sequence>
<element name="Name" type="string" minOccurs="0" maxOccurs="1"/>
<element name="Description" type="string" minOccurs="0"
maxOccurs="1"/>
</sequence>
</complexType>
<element name="RegistryObject" type="tns:RegistryObjectType"/>
<complexType name="RegistryObjectListType">
<annotation>
<documentation xml:lang="en">
Represents a list of RegistryObjectType instances.
</documentation>
</annotation>
<sequence>
<element ref="tns:RegistryObject" minOccurs="0" maxOccurs="unbounded"
/>
</sequence>
</complexType>
<element name="RegistryObjectList" type="tns:RegistryObjectListType"/>
<complexType name="AssociationType">
<complexContent>
<extension base="tns:RegistryObjectType">
<attribute name="type" type="string" use="required"/>
<attribute name="sourceObject" type="string" use="required"/>
<attribute name="targetObject" type="string" use="required"/>
</extension>
</complexContent>
</complexType>
In XML documents that conform to this schema, I can put different
types on the list using the xsi:type syntax, i.e.:
<?xml version = "1.0" encoding = "UTF-8"?>
<RegistryObjectList
xmlns="
http://oasis.org/ebxml/regrep/rim/4.0"
xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://oasis.org/ebxml/regrep/rim/4.0../xsd/rim.xsd">
<!-- Heterogeneous items on list specified using RegistryObject element
and xsi:type -->
<RegistryObject xsi:type="AssociationType" type="parentOf"
sourceObject="obj1" targetObject="obj2" >
<Name>Test Association</Name>
</RegistryObject>
</RegistryObjectList>
If I do not define any elements that are substitutable for <RegistryObject>,
then when I run the JAXB schema compiler I get a nice straightforward Java
class, like:
public class RegistryObjectListType {
@XmlElement(name = "RegistryObject")
protected List<RegistryObjectType> registryObject;
....
}
This interface is nice and easy to use.
Now lets say that users of the schema want to support element-based
substitution
for list members in addition to (or instead of) the xsi:type mechanism,
i.e.:
<?xml version = "1.0" encoding = "UTF-8"?>
<RegistryObjectList
xmlns="
http://oasis.org/ebxml/regrep/rim/4.0"
xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://oasis.org/ebxml/regrep/rim/4.0../xsd/rim.xsd">
<Association type="parentOf" sourceObject="obj1" targetObject="obj2">
<Name>Test Association</Name>
</Association>
</RegistryObjectList>
To support this usage in the XML Schema, an Association element is added to
the original schema, and it is added to the substitution group for
RegistryObject.
The modified schema looks like:
<complexType name="RegistryObjectType">
<sequence>
<element name="Name" type="string" minOccurs="0" maxOccurs="1"/>
<element name="Description" type="string" minOccurs="0"
maxOccurs="1"/>
</sequence>
</complexType>
<element name="RegistryObject" type="tns:RegistryObjectType"/>
<complexType name="RegistryObjectListType">
<annotation>
<documentation xml:lang="en">
Represents a list of RegistryObjectType instances.
</documentation>
</annotation>
<sequence>
<element ref="tns:RegistryObject" minOccurs="0" maxOccurs="unbounded"
/>
</sequence>
</complexType>
<element name="RegistryObjectList" type="tns:RegistryObjectListType"/>
<complexType name="AssociationType">
<complexContent>
<extension base="tns:RegistryObjectType">
<attribute name="type" type="string" use="required"/>
<attribute name="sourceObject" type="string" use="required"/>
<attribute name="targetObject" type="string" use="required"/>
</extension>
</complexContent>
</complexType>
<!-- ### New element that is substitutable for RegistryObject ### -->
<element name="Association" type="tns:AssociationType"
substitutionGroup="RegistryObject" />
After this schema change, the generated Java class for the
RegistryObjectListType now looks like:
public class RegistryObjectListType {
@XmlElementRef(name = "RegistryObject",
namespace = "
http://oasis.org/ebxml/regrep/rim-alt/4.0",
type = JAXBElement.class)
protected List<JAXBElement<? extends RegistryObjectType>>
registryObject;
....
}
I find this interface with the JAXBElement wrapper around list elements
much clunkier to use than the simple list. It seems like the information
content
of the XML is the same in either case - the extra element (in this case
<Association> is in some sense
just 'syntatic sugar' that for my use cases is equivalent to <RegistryObject
xsi:type="AssociationType">.
I am in search of a binding model that treats the two forms in an identical
(simple) fashion.
I see that by enabling the 'simple' JAXB extension, JAXBElement wrappers are
removed in favor of more bare-bones
Java classes. But that configuration setting doesn't seem to impact my
particular case (substitutionGroup-based containers).
Does anyone know of a way to configure JAXB to generate the simpler binding
for
RegistryObjectListType when element definitions that are substitutable
RegistryObject
as above are included in the schema? If not something that is currently
'tweakable',
is there a way to do this with a plugin? Or a relatively simple patch to
the JAXB
implementation? (I would be willing if the concept wasn't fundamentally a
non-starter and somebody could give me a hint)
Thanks in advance for any advice,
-Oliver
P.S. A simple Maven-based project used to test the two variants is
attached, in case there is any interest in it!