Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

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

m
(Replacing page with 'See http://www.eclipse.org/eclipselink/documentation/2.4/moxy/advanced_concepts007.htm')
 
(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}}
+

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