Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Polymorphism in XSD schema and JAXB classes

Tags:

jaxb

xsd

I have an xml like this:

<todo>
    <doLaundry cost="1"/>
    <washCar cost="10"/>
    <tidyBedroom cost="0" experiencePoints="5000"/>
</todo>

And the XSD schema for it is:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:complexType name="todo">
        <xs:sequence>
            <xs:choice maxOccurs="unbounded">
                <xs:element name="doLaundry" type="doLaundry" />
                <xs:element name="washCar" type="washCar" />
                <xs:element name="tidyBedroom" type="tidyBedroom" />
            </xs:choice>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="doLaundry">
        <xs:attribute name="cost" type="xs:int" />
    </xs:complexType>

    <xs:complexType name="washCar">
        <xs:attribute name="cost" type="xs:int" />
    </xs:complexType>

    <xs:complexType name="tidyBedroom">
        <xs:attribute name="cost" type="xs:int" />
        <xs:attribute name="experiencePoints" type="xs:int" />
    </xs:complexType>
</xs:schema>

And when I process this schema through JAXB I get a class with a method like this:

public class Todo {

    public List<Object> getDoLaundryOrWashCarOrTidyBedroom() {
        ...
    }

}

Ideally, what I would like is a way to define a generic base type that all the other XSD types extend. The Jaxb classes generated from the XSD schema should have a method to return a list of generic tasks. This would make it very easy to add new tasks to the todo list:

public class Todo {

    public List<Task> getTasks() {
        ...
    }

}

public abstract class Task {
    public int getCost() {
        ...
    }
}

public class TidyBedroom extends Task {
    public int getExperiencePoints() {
        ...
    }
}

What should the XSD schema look like in order to generate the above Java classes?

like image 290
Alex Spurling Avatar asked Feb 16 '11 18:02

Alex Spurling


2 Answers

I found the answer with the help of Blaise Doughan's article here: http://bdoughan.blogspot.com/2010/11/jaxb-and-inheritance-using-xsitype.html

This schema:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">     <xs:complexType name="todo">         <xs:sequence>             <xs:choice maxOccurs="unbounded">                 <xs:element name="doLaundry" type="doLaundry" />                 <xs:element name="washCar" type="washCar" />                 <xs:element name="tidyBedroom" type="tidyBedroom" />             </xs:choice>         </xs:sequence>     </xs:complexType>      <xs:complexType abstract="true" name="Task">         <xs:attribute name="cost" type="xs:int" use="required" />     </xs:complexType>      <xs:complexType name="doLaundry">         <xs:complexContent>             <xs:extension base="Task">             </xs:extension>         </xs:complexContent>     </xs:complexType>      <xs:complexType name="washCar">         <xs:complexContent>             <xs:extension base="Task">             </xs:extension>         </xs:complexContent>     </xs:complexType>      <xs:complexType name="tidyBedroom">         <xs:complexContent>             <xs:extension base="Task">                 <xs:attribute name="experiencePoints" type="xs:int" />             </xs:extension>         </xs:complexContent>     </xs:complexType>  </xs:schema> 

combined with a binding file:

<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema">     <jxb:bindings>       <jxb:bindings schemaLocation="todo.xsd" node="/xs:schema/xs:complexType[@name='todo']/xs:sequence/xs:choice">             <jxb:property name="Tasks"/>         </jxb:bindings>     </jxb:bindings> </jxb:bindings> 

Will give abstract and inherited classes as I described in the question. The binding file will change Jaxb's default method name from getDoLaundryOrWashCarOrTidyBedroom() to getTasks().

like image 91
Alex Spurling Avatar answered Sep 28 '22 09:09

Alex Spurling


xsd:choice corresponds to the @XmlElements annotation. You could apply this annotation directly to your desired object model.

For more information see:

  • http://bdoughan.blogspot.com/2010/10/jaxb-and-xsd-choice-xmlelements.html
like image 32
bdoughan Avatar answered Sep 28 '22 08:09

bdoughan