|
|
(19 intermediate revisions by the same user 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>
| + | |