users@jaxb.java.net

Re: XML element polymorphism??

From: Filip Rindler <filip.rindler_at_gmx.de>
Date: Tue, 03 Jun 2003 17:27:34 +0200

> Filip Rindler <filip.rindler_at_gmx.de> wrote:
> > Thanks, that doesn't help my problem, though because setMatrix() then is
> > overloaded and I also have to declare the choice list, which removes the
> > possibility to extend the SCHEME at run time, at least in my app..
>
> But no matter what schema feature you use you have to have your schema
> at compile-time. You can't just have a schema at run-time. I mean, how
> do you compile it?
>
> regards,
> --
> Kohsuke KAWAGUCHI 408-276-7063 (x17063)
> Sun Microsystems kohsuke.kawaguchi_at_sun.com
>

I more thought about a user providing some sort of additional matrix class
together with an XML schema describing this matrix' XML format. The
JAXB-generated (compiled from schema) classes would be shipped as well and
would be used by the matrix to store itself. As every matrix would have to
be stored in an XML complex type extending 'Matrix', the corresponding
JAXB-generated class (for my case XMLBMatrixXXX) would extend the XMLBMatrix
class as well and the general saving routine would use polymorphism to
archive that. At least that's what I think. I mean, you can combine more
than one schema under certain circumstances (e.g. using <any>) already.

Here's some code:

every subclass of Matrix provides a method
    public MatrixXMLEncoder getXMLEncoder();
which returns a MatrixXMLEncoder object approriate for encoding the matrix
type the above method was called for.
The MatrixXMLEncoder interface contains a method with the following
signature:
    public XMLBMatrix encode( Matrix matrix ).

If this method is called with the matrix, the MatrixXMLEncoder was acquired
for, it returns an appropriate subclass of XMLBMatrix with all matrix
information to be stored. This works, because if in the schema e.g. the
Matrix2DGrid complex type extends the Matrix complex type then
XMLBMatrix2DGrid extends XMLBMatrix as well (XMLB = Prefix for
JAXB-generated classes for XML types from schema). So my saving routine can
save an arbitrary matrix object as this matrix object basically knows how to
save its state into some XMLBMatrix subclass.
Then, if this worked, i could just use something like setMatrix( XMLBMatrix
matrix ) for the XML root element and marshall the object tree with a
marshaller. At least that's what I imagine. While all of the above works
fine, validation fails.

This is my whole store method that takes a matrix as argument and marshalls
it to an outputStream:

public void store( Matrix matrix, OutputStream outputStream )
        throws MTXException {

        if ( matrix == null ) {
            throw new MTXException( "No matrix to store!" );
        }

        if ( outputStream == null ) {
            throw new MTXException( "No output stream to write into!" );
        }

        try {

            JAXBContext jaxbContext = JAXBContext.newInstance(
                "de.filiprindler.cytorit.xml" );
            Marshaller marshaller = jaxbContext.createMarshaller();
            Validator validator = jaxbContext.createValidator();
            ObjectFactory factory = new ObjectFactory();

            XMLBmtxfileElement xmlRoot = factory.createXMLBmtxfileElement();

            // Get encoder
            MatrixXMLEncoder matrixEncoder = (
MatrixXMLEncoder )matrix.getClass()
                .getDeclaredMethod( "getXMLEncoder", new Class[]
{} ).invoke( null,
                new Object[] {} );
            xmlRoot.setMatrix( matrixEncoder.encode( matrix ) );

            // Validate & marshall
            validator.validateRoot( xmlRoot );
            marshaller.marshal( xmlRoot, outputStream );

        } catch ( Exception exception ) {
            throw new MTXException( "Storing of MTX file did not succeed!",
exception );
        }

    }


Here's an excerpt from the schema (directly from the <xsd:schema> tag):

<xsd:element name="mtxfile" type="MTXFile">
</xsd:element>

<xsd:complexType name="MTXFile">
 <xsd:all>
  <xsd:element name="minVersion" type="xsd:int" />

  <xsd:element name="matrix" type="Matrix" />
 </xsd:all>
</xsd:complexType>

<xsd:complexType name="Matrix">
 <xsd:attribute name="className" type="xsd:string" />
</xsd:complexType>

<xsd:complexType name="Matrix2DGrid">
 <xsd:complexContent>
  <xsd:extension base="Matrix">
   <xsd:all>
    <xsd:element name="size" type="Matrix2DGridDimension" /> <--- type
definitions for these have been omitted in this excerpt
    <xsd:element name="neighborhoodRelation" type="xsd:int" />
    <xsd:element name="cells" type="CellsList" />
   </xsd:all>
  </xsd:extension>
 </xsd:complexContent>
</xsd:complexType>


Hope, this clears up things... ;-)

Best regards,

Filip Rindler