[Partly answering to myself, in case somebody else has the same problem, 
and going further with an extended question]

My use case was to build a 3D vector from the apache commons math 
library, using the constructor with 3 double parameters for the vector 
coordinates: Vector3D(double, double, double). 
<http://commons.apache.org/math/apidocs/org/apache/commons/math/geometry/Vector3D.html#Vector3D%28double,%20double,%20double%29>
 
This class is immutable (the coordinates are stored in final fields).

The only way I found was to implement complete marshaller/unmarshaller, 
has described in the Custom marshallers and unmarshallers 
<http://jibx.sourceforge.net/tutorial/binding-custom.html#marunmar> 
section of the documentation. Implementing only the unmarshller is 
impossible, if you use "unmarshaller=some.class.you.wrote", you must 
also provide the marshaller otherwise JiBX will complain.

The main unmarshal method from the IUnmarshaller interface is called 
with an object as its first parameter, but it seems to be always null (I 
found no hint about this in the documentation). This was pretty good for 
me as I wanted to build the vector myself after having unmarshalled the 
three coordinates. I ended up with something close to this (showing only 
the unmarshal part):

   public class Vector3DBinder implements IMarshaller, IUnmarshaller, 
IAliasable {

    private final String uri;
    private final int index;
    private final String name;

    public Vector3DBinder() {
        uri   = null;
        index = 0;
        name  = "vector";
    }

    public Vector3DBinder(final String uri, final int index, final 
String name) {
        this.uri   = uri;
        this.index = index;
        this.name  = name;
    }

    // skipping the isExtension, marshall and isPresent method

    public Object unmarshal(final Object object, final 
IUnmarshallingContext context)
        throws JiBXException {
        try {

            final UnmarshallingContext ctx = (UnmarshallingContext) context;

            // extract coordinates
            ctx.parseToStartTag(uri, name);
            final double x = Double.parseDouble(ctx.attributeText(uri, 
"x", null));
            final double y = Double.parseDouble(ctx.attributeText(uri, 
"y", null));
            final double z = Double.parseDouble(ctx.attributeText(uri, 
"z", null));
            ctx.parsePastStartTag(uri, name);
            ctx.parsePastEndTag(uri, name);

            // return a new vector
           return new Vector3D(x, y, z);

        } catch (ClassCastException cce) {
            throw new JiBXException(cce.getMessage(), cce);
        }
    }
}


This method is in a custom Vector3DBinder class. One interesting 
property of this approach is that JiBX does not attempt to modify the 
Vector3D class itself, which is simpler as it allows to simply put the 
commons-math jar as an already built dependency and not to change the 
build process.

I still have a problem, though. I want to extract data from an XML 
document containing several vectors instances, similar to this reduced 
exemple:

<root>
  <vector-1 x="1.0" y="0.0" z="0.0"/>
  <vector-2 x="0.0" y="1.0" z="0.0"/>
</root>

I was able to do this only with the following binding:

<mapping name="root" class="Root">
      <structure name="vector-1"
                 field="v1"
                 marshaller="some.package.path.Vector3DBinder"
                 unmarshaller="some.package.path.Vector3DBinder"/>
      <structure name="vector-2"
                 field="v2"
                 marshaller="some.package.path.Vector3DBinder"
                 unmarshaller="some.package.path.Vector3DBinder"/>
</mapping>

Since I have lots of vectors in the real file, I would have prefered to 
use something like:

<mapping name="root" class="Root">
      <structure name="vector-1" field="v1" />
      <structure name="vector-2" field="v2" />
</mapping>

<mapping class="org.apache.commons.math.geometry.Vector3D"
         abstract="true"
         marshaller="some.package.path.Vector3DBinder"
         unmarshaller="some.package.path.Vector3DBinder"/>
</mapping>

Despite the abstract="true" attribute, and the fact the class implements 
IAliasable, in the second case I get an error while unmarshalling 
because JiBX expects a "vector" element and not the "vector-1" and 
"vector-2" elements. The reason for this seems to be that the 
unmarshaller is built for the no-argument constructor instead of the 
constructor providing the current name.

If I use the first binding, repeating myself the marshaller="..." and 
unmarshaller="..." everywhere, all works as expected.

I don't understand what I do wrong. I guess I misunderstood the 
abstract="true" attribute and IAliasable interface, but need help to 
understand them correctly.

Thanks,
Luc

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
jibx-users mailing list
jibx-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jibx-users

Reply via email to