3

My project contains a big XSD Schema, and schema instances are binded to the java code using JAXB. I would like to add strong types into the java code, using JScience, and bind them to XSD types.

My current problem is that JAXB handle very badly generics... They are not parsed at all.

For example, I want a power type in the XSD. I want JAXB to bind it the JScience type Measure<Power>:

<xs:simpleType name="PowerType">
    <xs:annotation>
        <xs:appinfo>
            <jxb:javaType name="org.jscience.physics.measures.Measure&lt;javax.measure.quantities.Power&gt;" 
                          parseMethod="org.f4g.adapter.UnitAdapter.unmarshalPower" />
        </xs:appinfo>
    </xs:annotation>
<xs:restriction base="xs:double"/>        
</xs:simpleType>



The parse method is:

public class UnitAdapter{

public static Measure<Power> unmarshalPower(String value) {
        return Measure.valueOf(Double.valueOf(value), SI.WATT);
    }
}

This compiles fine with JXC. My getters and setters have the nice type Measure<Power>.

But when I'm trying to read a schema instance with

// create an Unmarshaller
Unmarshaller u = JAXBContext.newInstance("org.f4g.schema.test").createUnmarshaller();


I get:

Exception in thread "main" java.lang.reflect.MalformedParameterizedTypeException
at sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl.validateConstructorArguments(ParameterizedTypeImpl.java:60)
at sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl.<init>(ParameterizedTypeImpl.java:53)
at sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl.make(ParameterizedTypeImpl.java:95)
at sun.reflect.generics.factory.CoreReflectionFactory.makeParameterizedType(CoreReflectionFactory.java:104)
at sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:140)
at sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49)
at sun.reflect.generics.repository.FieldRepository.getGenericType(FieldRepository.java:85)
etc...


Do you know how can I do? Is there are already work done in binding XSD to JScience's types through JAXB?

Thanks a lot, Corentin

cdupont
  • 1,138
  • 10
  • 17

2 Answers2

1

Your type should be org.jscience.physics.measures.Measure as generics information is not used to instanciate class (Class.forName(String) don't use generics information to instanciate objects).

Riduidel
  • 22,052
  • 14
  • 85
  • 185
  • Yes, that's true and it works if I just put org.jscience.physics.measures.Measure as the binding type. But I completely lose the information about the dimension in the XSD. I also lose it in the code, since my getters/setters will have only a "Measure" type and not a "Measure" type. – cdupont Jan 05 '11 at 12:11
  • I would like to have an expressive XSD, that include both the dimension (ex. Power) and the unit (ex. Watts). A little like in UnitsML http://unitsml.nist.gov/ – cdupont Jan 05 '11 at 12:16
  • I fear this level of information is unavaible in that case. Like I said before, that's due to limitations in behaviour of Class.forName. – Riduidel Jan 05 '11 at 13:37
  • Oh. So that's a limitation of java itself? – cdupont Jan 05 '11 at 14:14
0

I made the following class as an Adapter for Measure and it worked.

public class MeasureAdapter extends XmlAdapter<String, Measure<Double, Quantity>> {

public String marshal(Measure<Double, Quantity> value) throws Exception {
    if (null == value) {
        return null;
    }

    return value.toString();
}

@SuppressWarnings("unchecked")
@Override
public Measure<Double, Quantity> unmarshal(String str) throws Exception {
    if(str == null || str.length() == 0) {
        return null;
    }

    String[] d = str.split(" ");
    Measure<Double, Quantity> m = null;
    m = (Measure<Double, Quantity>) Measure.valueOf(Double.parseDouble(d[0]), Unit.valueOf(d[1]));

    return m;
}

}
Mo Kamyab
  • 27
  • 4