online - Polimorfismo en esquema XSD y clases JAXB
xsd java xjc (4)
Use xs: extensión en su esquema y sus clases JAXB se heredarán (se extenderán) según lo defina en su esquema.
Tengo un xml como este:
<todo>
<doLaundry cost="1"/>
<washCar cost="10"/>
<tidyBedroom cost="0" experiencePoints="5000"/>
</todo>
Y el esquema XSD para esto es:
<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>
Y cuando proceso este esquema a través de JAXB obtengo una clase con un método como este:
public class Todo {
public List<Object> getDoLaundryOrWashCarOrTidyBedroom() {
...
}
}
Idealmente, lo que me gustaría es una forma de definir un tipo de base genérico que extiendan todos los demás tipos de XSD. Las clases Jaxb generadas a partir del esquema XSD deben tener un método para devolver una lista de tareas genéricas. Esto haría que sea muy fácil agregar nuevas tareas a la lista de tareas pendientes:
public class Todo {
public List<Task> getTasks() {
...
}
}
public abstract class Task {
public int getCost() {
...
}
}
public class TidyBedroom extends Task {
public int getExperiencePoints() {
...
}
}
¿Cómo debería ser el esquema XSD para generar las clases Java anteriores?
xsd: la opción corresponde a la anotación @XmlElements. Puede aplicar esta anotación directamente a su modelo de objeto deseado.
Para más información, ver:
Encontré la respuesta con la ayuda del artículo de Blaise Doughan aquí: http://bdoughan.blogspot.com/2010/11/jaxb-and-inheritance-using-xsitype.html
Este esquema:
<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>
combinado con un archivo de enlace:
<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>
Darán clases abstractas y heredadas como describí en la pregunta. El archivo de enlace cambiará el nombre del método predeterminado de Jaxb de getDoLaundryOrWashCarOrTidyBedroom () a getTasks ().
Tal vez no estoy ''entendiendo'' la pregunta, pero ¿qué está mal con ...
<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="task" />
<xs:element name="washCar" type="task" />
<xs:element name="tidyBedroom" type="task" />
</xs:choice>
</xs:sequence>
</xs:complexType>
<xs:complexType name="task">
<xs:attribute name="cost" type="xs:int" />
<xs:attribute name="experiencePoints" type="xs:int" />
</xs:complexType>
</xs:schema>