|
|
(24 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.
| + | |
− | | + | |
− | <souce 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.
| + | |
− | | + | |
− | | + | |
− | | + | |
− | | + | |
− | In this case the transformation mapping concept in MOXy will make this use case much easier to map. Let's look at how this looks:
| + | |
− | | + | |
− | <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
| + | |
− | | + | |
− | An XML read transformer is responsible for constructing the object value from XML.
| + | |
− | | + | |
− | 1
| + | |
− | 2 | + | |
− | 3
| + | |
− | 4
| + | |
− | 5
| + | |
− | 6
| + | |
− | 7
| + | |
− | 8
| + | |
− | 9
| + | |
− | 10
| + | |
− | 11
| + | |
− | 12
| + | |
− | 13
| + | |
− | 14
| + | |
− | 15
| + | |
− | 16
| + | |
− | 17
| + | |
− | 18
| + | |
− | 19
| + | |
− | 20
| + | |
− | 21
| + | |
− | 22
| + | |
− | 23
| + | |
− | 24
| + | |
− | 25
| + | |
− | 26
| + | |
− | 27
| + | |
− | 28
| + | |
− | 29
| + | |
− | 30
| + | |
− | 31
| + | |
− | 32
| + | |
− | 33
| + | |
− | 34
| + | |
− | 35
| + | |
− | 36
| + | |
− | 37
| + | |
− |
| + | |
− | 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);
| + | |
− | }
| + | |
− | }
| + | |
− |
| + | |
− | }
| + | |
− | | + | |
− | XML Write Transformer(s)
| + | |
− | | + | |
− | An XML write transformer is responsible for constructing an XML value from the object. A transformation mapping may have multiple write transformers. For this example we will have two.
| + | |
− | | + | |
− | The first XML write transformer is responsible for writing out the year, month, and day information in the format yyMMdd.
| + | |
− | | + | |
− | 1
| + | |
− | 2
| + | |
− | 3
| + | |
− | 4 | + | |
− | 5
| + | |
− | 6
| + | |
− | 7
| + | |
− | 8
| + | |
− | 9
| + | |
− | 10
| + | |
− | 11
| + | |
− | 12
| + | |
− | 13
| + | |
− | 14
| + | |
− | 15
| + | |
− | 16
| + | |
− | 17
| + | |
− | 18
| + | |
− | 19
| + | |
− | 20
| + | |
− | 21
| + | |
− | 22
| + | |
− |
| + | |
− | 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);
| + | |
− | }
| + | |
− |
| + | |
− | }
| + | |
− | | + | |
− | The second XML write transformer is responsible for writing out the hour, minute, and second information in the format HHmmss.
| + | |
− | | + | |
− | | + | |
− | 1
| + | |
− | 2
| + | |
− | 3
| + | |
− | 4
| + | |
− | 5
| + | |
− | 6
| + | |
− | 7
| + | |
− | 8
| + | |
− | 9
| + | |
− | 10
| + | |
− | 11
| + | |
− | 12
| + | |
− | 13
| + | |
− | 14
| + | |
− | 15
| + | |
− | 16
| + | |
− | 17
| + | |
− | 18
| + | |
− | 19
| + | |
− | 20
| + | |
− | 21
| + | |
− | 22
| + | |
− |
| + | |
− | 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);
| + | |
− | }
| + | |
− |
| + | |
− | }
| + | |
− | | + | |
− | jaxb.properties
| + | |
− | | + | |
− | In order to use the MOXy JAXB implementation you need to add a jaxb.properties file in which your model classes with the following entry:
| + | |
− | | + | |
− | javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
| + | |
− | | + | |
− | Demo
| + | |
− | | + | |
− | The following class can be used to demonstrate the mapping:
| + | |
− | 1
| + | |
− | 2
| + | |
− | 3
| + | |
− | 4
| + | |
− | 5
| + | |
− | 6
| + | |
− | 7
| + | |
− | 8
| + | |
− | 9
| + | |
− | 10
| + | |
− | 11
| + | |
− | 12
| + | |
− | 13
| + | |
− | 14
| + | |
− | 15
| + | |
− | 16
| + | |
− | 17
| + | |
− | 18
| + | |
− | 19
| + | |
− | 20
| + | |
− | 21
| + | |
− |
| + | |
− | 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);
| + | |
− | }
| + | |
− |
| + | |
− | }
| + | |
− | Please Note
| + | |
− | | + | |
− | | + | |
− | | + | |
− | {{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}}
| + | |