Skip to main content
Jump to: navigation, search

Difference between revisions of "EclipseLink/UserGuide/MOXy/Mapping the Unmappable/XML Transformations"

m (XML Write Transformer(s))
(Replacing page with 'See http://www.eclipse.org/eclipselink/documentation/2.4/moxy/advanced_concepts007.htm')
 
(20 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{EclipseLink_UserGuide
+
See http://www.eclipse.org/eclipselink/documentation/2.4/moxy/advanced_concepts007.htm
|info=y
+
|eclipselink=y
+
|eclipselinktype=MOXy
+
}}
+
=Transformation Mapping=
+
In many cases, you can use MOXy's transformation mapping ('''@XmlTransformation''') to map an unmapple object in JAXB.
+
 
+
For example, if you wanted to map the following XML to objects and combine the values of '''DATE''' and '''TIME''' into a single '''java.util.Date''' object, you can use a transformation mapping.
+
 
+
<source lang="xml">
+
 
+
<ELEM_B>
+
    <B_DATE>20100825</B_DATE>
+
    <B_TIME>153000</B_TIME>
+
    <NUM>123</NUM>
+
    <C_DATE>20100825</C_DATE>
+
    <C_TIME>154500</C_TIME>
+
</ELEM_B>
+
</source>
+
 
+
'''Note:''' Ordinarily, you would use '''@XmlAdapter'''. However:
+
* Although the '''DATE/TIME''' pairings are repeated throughout the document, the element name changes ''each time'' (such as '''B_DATE/B_TIME''', '''C_DATE/C_TIME''', and so on).
+
* Because each pairing is missing a grouping element, you would need to adapt ''the entire'' '''ElemB''' class.
+
Because of these issues, MOXy's transformation mapping is much easier to implement:
+
 
+
<source lang="Java">
+
+
import java.util.Date;
+
+
import javax.xml.bind.annotation.XmlAccessType;
+
import javax.xml.bind.annotation.XmlAccessorType;
+
import javax.xml.bind.annotation.XmlElement;
+
import javax.xml.bind.annotation.XmlRootElement;
+
+
import org.eclipse.persistence.oxm.annotations.XmlReadTransformer;
+
import org.eclipse.persistence.oxm.annotations.XmlTransformation;
+
import org.eclipse.persistence.oxm.annotations.XmlWriteTransformer;
+
import org.eclipse.persistence.oxm.annotations.XmlWriteTransformers;
+
+
@XmlAccessorType(XmlAccessType.FIELD)
+
@XmlRootElement(name="ELEM_B")
+
public class ElemB {
+
+
    @XmlReadTransformer(transformerClass=DateAttributeTransformer.class)
+
    @XmlWriteTransformers({
+
        @XmlWriteTransformer(xmlPath="B_DATE/text()", transformerClass=DateFieldTransformer.class),
+
        @XmlWriteTransformer(xmlPath="B_TIME/text()", transformerClass=TimeFieldTransformer.class),
+
    })
+
    private Date bDate;
+
+
    @XmlElement(name="NUM")
+
    private int num;
+
+
    @XmlReadTransformer(transformerClass=DateAttributeTransformer.class)
+
    @XmlWriteTransformers({
+
        @XmlWriteTransformer(xmlPath="C_DATE/text()", transformerClass=DateFieldTransformer.class),
+
        @XmlWriteTransformer(xmlPath="C_TIME/text()", transformerClass=TimeFieldTransformer.class),
+
    })
+
    private Date cDate;
+
+
}
+
 
+
</source>
+
 
+
 
+
 
+
==XML Read Transformer==
+
Use an XML ''read transformer'' to constructing the object value from XML, as shown here:
+
 
+
<source lang="java">
+
+
import java.text.ParseException;
+
import java.text.SimpleDateFormat;
+
+
import org.eclipse.persistence.internal.helper.DatabaseField;
+
import org.eclipse.persistence.mappings.foundation.AbstractTransformationMapping;
+
import org.eclipse.persistence.mappings.transformers.AttributeTransformer;
+
import org.eclipse.persistence.sessions.Record;
+
import org.eclipse.persistence.sessions.Session;
+
+
public class DateAttributeTransformer implements AttributeTransformer {
+
+
    private AbstractTransformationMapping mapping;
+
    private SimpleDateFormat yyyyMMddHHmmss = new SimpleDateFormat("yyyyMMddHHmmss");
+
+
    public void initialize(AbstractTransformationMapping mapping) {
+
        this.mapping = mapping;
+
    }
+
+
    public Object buildAttributeValue(Record record, Object instance, Session session) {
+
        try {
+
            String dateString = null;
+
            String timeString = null;
+
           
+
            for(DatabaseField field : mapping.getFields()) {
+
                if(field.getName().contains("DATE")) {
+
                    dateString = (String) record.get(field);
+
                } else {
+
                    timeString = (String) record.get(field);
+
                }
+
            }
+
            return yyyyMMddHHmmss.parseObject(dateString + timeString);
+
        } catch(ParseException e) {
+
            throw new RuntimeException(e);
+
        }
+
    }
+
+
}
+
 
+
</source>
+
 
+
==XML Write Transformer(s)==
+
Use an XML ''write transformer'' to constructing an XML value from the object.
+
 
+
Each transformation mapping may have multiple write transformers. In this example, you will need two:For this example we will *The first XML write transformer writes the year, month, and day in '''yyMMdd''' format.
+
 
+
<source lang="java">
+
import java.text.SimpleDateFormat;
+
import java.util.Date;
+
+
import org.eclipse.persistence.mappings.foundation.AbstractTransformationMapping;
+
import org.eclipse.persistence.mappings.transformers.FieldTransformer;
+
import org.eclipse.persistence.sessions.Session;
+
+
public class DateFieldTransformer implements FieldTransformer {
+
+
    private AbstractTransformationMapping mapping;
+
    private SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyyMMdd");
+
+
    public void initialize(AbstractTransformationMapping mapping) {
+
        this.mapping = mapping;
+
    }
+
+
    public Object buildFieldValue(Object instance, String xPath, Session session) {
+
        Date date = (Date) mapping.getAttributeValueFromObject(instance);
+
        return yyyyMMdd.format(date);
+
    }
+
+
}
+
</source>
+
 
+
 
+
*The second XML write transformer writes out the hour, minutes, and seconds in '''HHmmss''' format.
+
 
+
<source lang="java">
+
import java.text.SimpleDateFormat;
+
import java.util.Date;
+
+
import org.eclipse.persistence.mappings.foundation.AbstractTransformationMapping;
+
import org.eclipse.persistence.mappings.transformers.FieldTransformer;
+
import org.eclipse.persistence.sessions.Session;
+
+
public class TimeFieldTransformer implements FieldTransformer {
+
+
    private AbstractTransformationMapping mapping;
+
    private SimpleDateFormat HHmmss = new SimpleDateFormat("HHmmss");
+
+
    public void initialize(AbstractTransformationMapping mapping) {
+
        this.mapping = mapping;
+
    }
+
+
    public Object buildFieldValue(Object instance, String xPath, Session session) {
+
        Date date = (Date) mapping.getAttributeValueFromObject(instance);
+
        return HHmmss.format(date);
+
    }
+
+
}
+
</source>
+
 
+
==jaxb.properties==
+
To use the MOXy JAXB implementation, add a '''jaxb.properties''' file in which your model classes with the following entry:
+
 
+
<tt>
+
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
+
</tt>
+
 
+
==Example==
+
Demo
+
 
+
The following class can be used to demonstrate the mapping:
+
<source lang="java">
+
import java.io.File;
+
+
import javax.xml.bind.JAXBContext;
+
import javax.xml.bind.Marshaller;
+
import javax.xml.bind.Unmarshaller;
+
+
public class Demo {
+
+
    public static void main(String[] args) throws Exception {
+
        JAXBContext jc = JAXBContext.newInstance(ElemB.class);
+
+
        Unmarshaller unmarshaller = jc.createUnmarshaller();
+
        File xml = new File("input.xml");
+
        ElemB elemB = (ElemB) unmarshaller.unmarshal(xml);
+
+
        Marshaller marshaller = jc.createMarshaller();
+
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+
        marshaller.marshal(elemB, System.out);
+
    }
+
+
}
+
</source>
+
 
+
 
+
 
+
{{EclipseLink_MOXy
+
|next=    [[EclipseLink/UserGuide/MOXy/Mapping_the_Unmappable/XMLFragmentMapping|XML Fragment mapping]]
+
|previous= [[EclipseLink/UserGuide/MOXy/Mapping_the_Unmappable/Converters|Converters]]
+
|up =      [[EclipseLink/UserGuide/MOXy/Mapping_the_Unmappable|Mapping the Unmappable]]
+
|version=2.2.0 - DRAFT}}
+

Latest revision as of 10:33, 8 November 2012

See http://www.eclipse.org/eclipselink/documentation/2.4/moxy/advanced_concepts007.htm

Back to the top