users@jaxb.java.net

Re: schemagen and using _at_XmlElementRef on a non-collection property

From: Kohsuke Kawaguchi <Kohsuke.Kawaguchi_at_Sun.COM>
Date: Mon, 30 Jul 2007 12:32:30 -0700

James.Strachan wrote:
> In the Apache Camel project I want to create an XSD something like the
> following, so that a <filter> can contain a choice of <groovy> <ognl> or
> <ruby> expressions etc.
>
> <xs:complexType name="filterType">
> <xs:complexContent>
> <xs:extension base="tns:processorType">
> <xs:sequence>
> <xs:choice minOccurs="1" maxOccurs="1">
> <xs:element ref="tns:groovy"/>
> <xs:element ref="tns:ognl"/>
> <xs:element ref="tns:ruby"/>
> <xs:element ref="tns:xpath"/>
> </xs:choice>
> <xs:choice maxOccurs="unbounded">
> <xs:element ref="tns:choice"/>
> <xs:element ref="tns:filter"/>
> <xs:element ref="tns:process"/>
> <xs:element ref="tns:recipientList"/>
> <xs:element ref="tns:splitter"/>
> <xs:element ref="tns:to"/>
> </xs:choice>
> </xs:sequence>
> </xs:extension>
> </xs:complexContent>
> </xs:complexType>
>
> So I've a FilterType class like this...
>
> @XmlRootElement(name = "filter")
> @XmlAccessorType(XmlAccessType.FIELD)
> public class FilterType extends ProcessorType {
> @XmlElementRef
> private ExpressionType expression;
>
> @XmlElementRef
> private List<ProcessorType> outputs = new ArrayList<ProcessorType>();
> ..
>
> However that doesn't work as it doesn't generate a choice on the
> 'expression' property, instead it generates a sequence of all possible
> @XmlElementRef types, which seems a bit bizarre as the setter can only
> contain one value; is this a bug?

Yeah, this is a bug. I'm honestly surprised that such a bug still exists
and didn't get caught. The use of annotations look all correct to me.

Thank you for filing a bug.

> <xs:complexType name="filterType">
> <xs:complexContent>
> <xs:extension base="tns:processorType">
> <xs:sequence>
> <xs:element ref="tns:groovy"/>
> <xs:element ref="tns:ognl"/>
> <xs:element ref="tns:ruby"/>
> <xs:element ref="tns:xpath"/>
> <xs:choice maxOccurs="unbounded">
> <xs:element ref="tns:route"/>
> <xs:element ref="tns:choice"/>
> <xs:element ref="tns:otherwise"/>
> <xs:element ref="tns:when"/>
> <xs:element ref="tns:filter"/>
> <xs:element ref="tns:process"/>
> <xs:element ref="tns:recipientList"/>
> <xs:element ref="tns:splitter"/>
> <xs:element ref="tns:to"/>
> </xs:choice>
> </xs:sequence>
> </xs:extension>
> </xs:complexContent>
> </xs:complexType>
>
>
> Though @XmlElementRef works great on collections. So as a dirty hack I've
> done this...
>
> @XmlRootElement(name = "filter")
> @XmlAccessorType(XmlAccessType.FIELD)
> public class FilterType extends ProcessorType {
>
> // a dirty hack to fix schemagen...
> @XmlElementRef
> private List<ExpressionType> expressions;
> @XmlTransient
> private ExpressionType expression;
>
> @XmlElementRef
> private List<ProcessorType> outputs = new ArrayList<ProcessorType>();
>
>
> i.e. I added an extra collection-of-one field.
>
> I just wondered; is there a proper way to specify that an @XmlElementRef
> really is a choice; in addition is there any way to set the min/max occurs?
>
> BTW the reason I like the @XmlElementRef is it nicely does the extension
> mechanism, without having to cut and paste a chunk of
> @XmlElements({_at_XmlElement(), ...}) declarations whenever a common base class
> is used in my POJO model.
>
> James


-- 
Kohsuke Kawaguchi
Sun Microsystems                   kohsuke.kawaguchi_at_sun.com