2012-07-12 20 views
8

La situaciónCómo evitar la duplicación de código usando JAXB con elementos contenedores similares con una estructura similar

estoy usando la aplicación JAXB de moxy trabajar con un documento XML grande cuyo esquema tiene muchos tipos complejos parecidos. En concreto, hay unas dos docenas de tipos que actúan como elementos de la lista de envoltura con la siguiente estructura:

<ITEMS attr1="X" attr2="Y"> 
    <ITEM>...</ITEM> 
    ... 
    <EXTENSION/> 
<ITEMS> 

Para cada uno de estos elementos lista-envoltura similar, los cambios de nombre y el elemento de lista que se está contenían cambios. Sin embargo, los atributos (que son todos opcionales) y el único elemento de EXTENSIÓN (también opcional) siempre están presentes. Aquí está un ejemplo de usos de dos de los tipos:

<ROLES visible="false"> 
    <ROLE type="X"/> 
    <ROLE type="Y"/> 
</ROLES> 

<PAYMENTS visible="true"> 
    <PAYMENT> 
    <PAYEENAME>Joe</PAYEENAME> 
    </PAYMENT> 
    <EXTENSION> 
    <SOMETHING>Here</SOMETHING> 
    </EXTENSION> 
</PAYMENTS> 

La pregunta

me gustaría evitar la duplicación de código ya que el único cambio entre estos elementos es el nombre y el de-o- más elementos que contiene. ¿Cuál es la mejor manera de hacer esto?

Solo puedo ver dos soluciones posibles.

Creación de una clase concreta utilizando los genéricos para indicar el tipo de objeto que se utiliza en la colección que cambia. Luego, use las asignaciones de OX externas de MOXy para indicar cómo debe serializarse cualquier uso individual de la clase. Algo así como:

public class GenericContainer<T> { 
@XmlAttribute 
protected Boolean visibile; 
@XmlElement(name = "Extension") 
protected Extension extension; 

// OX Mappings done in external meta file 
protected List<T> items; 
... 
} 

Aunque me gusta esta opción, no parece ser posible redefinir las asignaciones de buey de una clase sobre una base por uso.

Creación de una clase base sin la propiedad lista, y luego la creación de una clase concreta para cada elemento de envoltorio personalizado. Esta solución definitivamente funciona, pero terminaré con cerca de dos docenas de clases casi identitarias.

¿Es posible el número 1 o hay una forma mejor de manejar esto en la que no he pensado?

¡Gracias de antemano!

Respuesta

0
public class GenericContainer { 

private Boolean visible; 
private Object extension; 
private List<Object> nodes; 

@XmlAttribute 
public Boolean isVisible() { 
    return visible; 
} 

public void setVisible(Boolean visible) { 
    this.visible = visible; 
} 

@XmlElement(name="EXTENSION") 
public Object getExtension() { 
    return extension; 
} 

public void setExtension(Object extension) { 
    this.extension = extension; 
} 

@XmlAnyElement 
public List<Object> getNodes() { 
    return nodes; 
} 

public void setNodes(List<Object> nodes) { 
    this.nodes = nodes; 
} 

} 

Y para leer la instancia XML

JAXBContext jaxbContext = JAXBContext.newInstance("jaxbtest1"); 
    Unmarshaller um = jaxbContext.createUnmarshaller(); 

    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
    DocumentBuilder db = dbf.newDocumentBuilder(); 
    Document doc = db.parse(new File("src/test1.xml")); 
    Node node = doc.getFirstChild(); 

    JAXBElement<GenericContainer> jaxbE = um.unmarshal(node, GenericContainer.class); 

    GenericContainer gc = jaxbE.getValue(); 
    Boolean vis = gc.isVisible(); 
    Element ext = (Element)gc.getExtension(); 
    for(Object o : gc.getNodes()) { 
     Element listItem = (Element)o; 
    } 

Pero es realmente importante la duplicación de código? Si su esquema tiene una base de extensión común para los tipos de contenedor de lista y está utilizando xjc, ¿por qué evitar clases distintas? Después de todo, la idea detrás de JAXB es tener una clase de valor para cada tipo complejo único.

Si puede crear una lógica de propósito general que maneje tipos XML similares pero distintos y no desee una gran cantidad de clases de Java, podría cambiar a StAX.

+0

El ejemplo no se ajusta realmente a lo que estoy buscando, a menos que me falta algo. En realidad, no me permitiría unir elementos de la lista a las clases comentadas JAXB, ya que el unmarshaller convertiría todo en objetos org.w3c.dom.Element. Ir por el otro lado sería un poco menos incómodo, pero no tiene ningún tipo de seguridad. – Terence

+0

Para su pregunta sobre la duplicación de código, tiene razón, no es terriblemente importante. Realmente odio hacerlo. Terminé yendo por la ruta de tener más de 30 clases casi idénticas, aunque no estaba muy entusiasmado con eso. La situación ideal habría sido crear mi propia clase java.util.Collection personalizada con soporte genérico, pero eso parece ser imposible en este momento. – Terence

Cuestiones relacionadas