Search code examples
javaxsdjaxbxjc

how do I persist 2 dimensional array of double in java


I am enhancing a desktop java app that uses an XSD and the java xjc.exe compiler to persist and restore object data. I need to persist a new type that contains double[][] feature data. I added:

<xs:schema
    ...
    xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">

<xs:import namespace="http://schemas.xmlsoap.org/soap/encoding/"
    schemaLocation="http://schemas.xmlsoap.org/soap/encoding/"/>

<xs:complexType name="patchFeature">
    <xs:all>
        <xs:element name="featureMatrix" type="doubleMatrix" />
    </xs:all>
    <xs:attribute name="type" type="patchType" use="required" />
</xs:complexType>

<xs:complexType name="doubleMatrix">
<xs:complexContent>
 <xs:restriction base="soapenc:Array">
      <xs:attribute ref="soapenc:arrayType" 
                 wsdl:arrayType="xs:double[][]"/>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
...
</xs:schema>

to the XSD file. The xjc.exe compiler compiles it ok, but the PatchFeature and DoubleMatrix classes it generates do not have methods to get/set a double[][] value. How do I persist a 2-dimensional array of primative double? I'd prefer not to use XSD sequences because they generate objects which take List<Double> which requires boxing, unboxing, and conversion to/from the primative double[][] matrix.


Solution

  • I finally gave up trying to persist/restore double[][] arrays. Instead, I persisted a 'stride' elements per row and a 1-dimensional ArrayList. I wrote converters between the double[][] array and the stride/ArrayList. It's not very elegant, but it works. The xsl looks like:

        <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
        targetNamespace="http://novodynamics.com/NovoHealth/features.xsd"
        xmlns="http://novodynamics.com/NovoHealth/features.xsd"
        elementFormDefault="qualified">
        <xs:complexType name="patchFeature">
            <xs:all>
                <xs:element name="featureVector" type="doubleVector" />
            </xs:all>
            <xs:attribute name="stride" type="xs:int" use="required" />
        </xs:complexType>
    
        <xs:complexType name="doubleVector">
            <xs:sequence minOccurs="0" maxOccurs="unbounded">
                <xs:element name="dbl" type="xs:double" />
            </xs:sequence>
        </xs:complexType>
        ...
    

    And the converters:

    private double[][] featureMatrix;
    
    public void setFeatureMatrix(int stride, List<Double> vector) {
      this.featureMatrix = new double[vector.size() / stride][stride];
      for (int i = 0; i < vector.size(); i++) {
        this.featureMatrix[i / stride][i % stride] = vector.get(i);
      }
    }
    
    public static void createPatchFeature(double[][] featureMatrix, Feature feature,
        ObjectFactory factory) {
      PatchFeature patchFeature = factory.createPatchFeature();
      int stride = featureMatrix[0].length;
      // int vectorSize = stride * featureMatrix.length;
      patchFeature.setStride(stride);
      DoubleVector vector = factory.createDoubleVector();
      for (int i = 0; i < featureMatrix.length; i++) {
        for (int j = 0; j < stride; j++) {
          vector.getDbl().add(featureMatrix[i][j]);
        }
      }
      patchFeature.setFeatureVector(vector);
      feature.setPatch(patchFeature);
    }