2010-12-29 5 views
6

necesita ayuda con la siguiente situación: Los usuarios pueden generar sus propias estructuras de datos que se almacenan como JAXB listo fuentes XSD, como a continuación:cómo forzar clases de esquema compilado para extender clase específica de esquema fuera

<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 

    <xs:element name="Group" type="Group"/> 
    <xs:element name="Parameter" type="Parameter"/> 

    <xs:complexType name="Group"> 
    <xs:sequence> 
     <xs:element name="caption" type="xs:string" minOccurs="0"/> 
     <xs:element name="parameters" type="Parameter" nillable="true" minOccurs="0" maxOccurs="unbounded"/> 
    </xs:sequence> 
    </xs:complexType> 

    <xs:complexType name="Parameter"> 
    <xs:sequence> 
     <xs:element name="key" type="xs:string" minOccurs="0"/> 
     <xs:element name="group" type="Group" minOccurs="0"/> 
     <xs:element name="value" type="xs:string" minOccurs="0"/> 
    </xs:sequence> 
    </xs:complexType> 
</xs:schema> 

Después nueva o esquema modificado parece que se analiza automáticamente por el compilador de esquema, las fuentes de Java que se genera, compilado y empaquetado en frascos de usuario:

SchemaCompiler sc = XJC.createSchemaCompiler(); 
    // Input source for schema 
    InputSource is = new InputSource(new StringInputStream(objectPackage.getObjectSchema())); 
    // Parse 
    sc.parseSchema(is); 
    S2JJAXBModel model = sc.bind(); 
    // Generate source 
    JCodeModel jCodeModel = model.generateCode(null, null); 
    jCodeModel.build(packageSourceDirectory); 
    // Compile and package 
    // ...... 

y todo estaba bien hasta que se decidió que todas las clases generadas por los usuarios deben extenderse una clase específica conocida, por ejemplo UserRootObject:

package user.abc; 
public class Group extends com.mycompany.xml.UserRootObject { 
    // 
} 

y

package user.abc; 
public class Parameter extends com.mycompany.xml.UserRootObject { 
    // 
} 

Todo está sobre la marcha, no puedo obligar a los usuarios a modificar sus archivos de esquema pero puedo transformarlos antes de la generación de código. Parece que tengo dos opciones para introducir ese UserRootObject: de alguna manera a través de JCodeModel o de alguna manera transformar los archivos de esquema antes de compilar las fuentes de Java.

Respuesta

1

No creo que hay una manera fácil de hacer esto utilizando JAXB sí. Hay una serie de opciones de personalización disponibles que no se conocen comúnmente: lea section 7 of JSR222 para obtener más información.

Si tiene algún control sobre los esquemas de entrada, entonces es posible que desee considerar el uso de XSLT para transformar el esquema. Creo que esto se puede hacer mediante el uso de una instancia de javax.xml.transform.dom.DOMResult como el objetivo de la transformación y el uso de la salida como un árbol DOM (por ejemplo, llamando getNode() en el resultado) como la entrada a parseSchema. Una transformación básica sería la de sustituir:

<xs:complexType name="foo"> 
    <!-- CONTENTS --> 
</xs:complexType> 

con algo como:

<xs:complexType name="foo"> 
    <xs:complexContent> 
    <xs:extension base="UserRootObject"> 
     <!-- CONTENTS --> 
    </xs:extension> 
    </xs:complexContent> 
</xs:complexType> 

Por supuesto, esto sólo funciona para los casos simples. Si ya tiene herencia en sus archivos de esquema, tendrá que hacer algunos filtros en el XSLT que solo aplica esta transformación a tipos que aún no se extienden.

+0

Gracias! Sí, podría transformar el esquema de esa manera, pero ¿cómo le digo al compilador de esquemas que no genere UserRootObject sino que 'haga referencia' a una clase existente? ¿Es posible? Eso sería genial y resolver el problema. – Osw

+1

Está en lo correcto en ese estándar. JAXB no cubre este caso de uso, pero XJC ofrece esto como una extensión. Para obtener más información, consulte: http://stackoverflow.com/questions/4556179/how-to-force-schema-compiled-classes-to-extend-specific-class-outside-schema/4607476#4607476 –

5

Muchas gracias a D.Shawley para señalar la sección de la derecha en JSR 222. Aquí está la solución final que podría ser útil y ahorrar para algún otro momento. esquema original debe ser transformada de la siguiente manera:

<xs:schema version="1.0" 
       xmlns:xs="http://www.w3.org/2001/XMLSchema" 
       xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" 
       jaxb:version="2.0" > 

     <xs:element name="Group" type="Group"/> 
     <xs:element name="Parameter" type="Parameter"/> 


     <xs:complexType name="Group"> 
     <xs:complexContent> 
      <xs:extension base="UserRootObject"> 
      <xs:sequence> 
      <!-- params --> 
      </xs:sequence> 
      </xs:extension> 
     </xs:complexContent> 
     </xs:complexType> 

     <xs:complexType name="Parameter"> 
     <xs:complexContent> 
      <xs:extension base="UserRootObject"> 
      <xs:sequence> 
      <!-- params --> 
      </xs:sequence> 
      </xs:extension> 
     </xs:complexContent> 
     </xs:complexType> 

     <xs:complexType name="UserRootObject"> 
     <xs:annotation> 
      <xs:appinfo> 
      <jaxb:class name="UserRootObject" implClass="com.mycompany.xml.UserRootObject"/> 
      </xs:appinfo> 
     </xs:annotation> 
     </xs:complexType> 
    </xs:schema> 

La transformación puede realizarse fácilmente a través de org.w3c.dom.Document inteface.

7

XJC tiene una extensión para este fin

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" 
      xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" 
      jaxb:extensionBindingPrefixes="xjc" 
      jaxb:version="2.0"> 

    <xs:annotation> 
     <xs:appinfo> 
      <jaxb:globalBindings> 
      <xjc:superClass name="com.mycompany.xml.UserRootObject"/> 
      </jaxb:globalBindings> 
     </xs:appinfo> 
    </xs:annotation> 
. 
. 
. 
</xs:schema> 

Para obtener más información, véase:

Las anotaciones de esquema también se pueden suministrar a través de un archivo de enlaces externos.Para ver un ejemplo:

+0

Buena solución. Desearía que estuvieras aquí en 2010 :) Personalmente, prefiero seguir con las especificaciones de JAXB y no confiar en la implementación de XJC, pero la solución puede ser muy útil y ahorrar tiempo para otros. Por cierto, el modo "-extensión" mencionado es un poco confuso, uno tendrá que verificar si este modo está habilitado para la compilación de esquemas sobre la marcha como en mi caso. – Osw

Cuestiones relacionadas