Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
EclipseLink/DesignDocs/277920/Phase3
Phase 3 - Containment Mappings
Provide support for nested data.
Annotations
The following annotations will be targetted in this phase:
Annotation | XML Metadata Tag | Package | Type | Field | Method |
---|---|---|---|---|---|
XmlAttribute | xml-attribute | X | X | ||
XmlElement | xml-element | X | X | ||
XmlAdapter | xml-java-type-adapter | X | X | X | X |
XmlCustomizer | xml-customizer | X | |||
N/A | xml-map | X | X |
Example: XmlAttribute, XmlElement and XmlCustomizer annotations
Java Metadata
The following example will demonstrate how the XmlAttribute, XmlElement, and XmlCustomizer annotations can be applied to a Java class:
org.example.Employee.java
package org.example; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import org.eclipse.persistence.oxm.annotations.XmlCustomizer; @XmlCustomizer(value=MyEmployeeCustomizer.class) public class Employee { public String firstName; public String lastName; @XmlAttribute(name="employee-id", namespace="urn:employeedata", required=true) public int id; @XmlElement(name="hire-date", namespace="urn:utildata", nillable=false, required=true, type=java.util.Date.class) public Object myUtilDate; }
org.example.MyEmployeeCustomizer.java
package org.example; import org.eclipse.persistence.config.DescriptorCustomizer; import org.eclipse.persistence.descriptors.ClassDescriptor; import org.eclipse.persistence.oxm.XMLField; import org.eclipse.persistence.oxm.mappings.XMLDirectMapping; /** * This simple customizer will change 'firstName' to 'first-name' * and 'lastName' to 'last-name'. */ public class MyEmployeeCustomizer implements DescriptorCustomizer { public void customize(ClassDescriptor descriptor) throws Exception { XMLDirectMapping firstNameMapping = (XMLDirectMapping) descriptor.getMappingForAttributeName("firstName"); XMLField fnxField = (XMLField) firstNameMapping.getField(); fnxField.setXPath("first-name/text()"); XMLDirectMapping lastNameMapping = (XMLDirectMapping) descriptor.getMappingForAttributeName("lastName" ); XMLField lnxField = (XMLField) lastNameMapping.getField(); lnxField.setXPath("last-name/text()"); } }
XML Metadata
xml-attribute
If this is present in the XML then it completely replaces the corresponding annotation.
xml-element
If this is present in the XML then it completely replaces the corresponding annotation.
xml-customizer
If this is present in the XML then it completely replaces the corresponding annotation.
org/example/eclipselink-oxm.xml
This XML file represents metadata overrides for the "org.example.Employee" class.
<?xml version="1.0" encoding="US-ASCII"?> <xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"> <java-types> <java-type name="org.example.Employee" xml-customizer="org.example.MyXmlEmployeeCustomizer"> <java-attributes> <xml-attribute java-attribute="id" name="employee-id", namespace="urn:employeedata", required="true"/> <xml-element java-attribute="myUtilDate" name="hire-date", namespace="urn:utildata", nillable="false", required="true", type="java.util.Date"/> </java-attributes> </java-type> </java-types> </xml-bindings>
Example: Package-level XmlAdapter
Java Metadata
The following example will demonstrate how a package level XmlAdapter annotation can be applied:
org.example.package-info.java
@javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter(value=org.example.DateAdapter.class, type=java.util.Calendar.class) package org.example;
org.example.DateAdapter.java
package org.example; import java.util.Calendar; import java.util.GregorianCalendar; import javax.xml.bind.annotation.adapters.XmlAdapter; public final class DateAdapter extends XmlAdapter<CustomDateType, Calendar> { public DateAdapter() {} public CustomDateType marshal(Calendar arg0) throws Exception { CustomDateType cType = new CustomDateType(); cType.day = arg0.get(Calendar.DATE); cType.month = arg0.get(Calendar.MONTH); cType.year = arg0.get(Calendar.YEAR); return cType; } public Calendar unmarshal(CustomDateType arg0) throws Exception { return new GregorianCalendar(arg0.year, arg0.month, arg0.day); } }
org.example.CustomDateType.java
package org.example; public class CustomDateType { public int year; public int month; public int day; }
XML Metadata
xml-java-type-adapter
If this is present in the XML then it completely replaces the corresponding annotation.
org/example/eclipselink-oxm.xml
This XML file represents metadata overrides for the "org.example" package.
<?xml version="1.0" encoding="US-ASCII"?> <xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"> <xml-java-type-adapters> <xml-java-type-adapter value="org.example.DateAdapter" type="java.util.Calendar"/> </xml-java-type-adapters> </xml-bindings>
Example: Class-level XmlAdapter
Java Metadata
The following example will demonstrate how a class level XmlAdapter annotation can be applied:
org.example.MyCalendar.java
package org.example; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlJavaTypeAdapter(value=org.example.MyCalendarAdapter.class) public class MyCalendar { @XmlAttribute public int year; @XmlAttribute public int month; @XmlAttribute public int day; }
org.example.MyCalendarAdapter.java
package org.example; import java.util.Calendar; import java.util.GregorianCalendar; import javax.xml.bind.annotation.adapters.XmlAdapter; public final class MyCalendarAdapter extends XmlAdapter<Calendar, MyCalendar> { public MyCalendarAdapter() {} public MyCalendar unmarshal(Calendar arg0) throws Exception { MyCalendar cType = new MyCalendar(); cType.day = arg0.get(Calendar.DATE); cType.month = arg0.get(Calendar.MONTH); cType.year = arg0.get(Calendar.YEAR); return cType; } public Calendar marshal(MyCalendar arg0) throws Exception { return new GregorianCalendar(arg0.year, arg0.month, arg0.day); } }
XML Metadata
xml-java-type-adapter
If this is present in the XML then it completely replaces the corresponding annotation.
org/example/eclipselink-oxm.xml
This XML file represents metadata overrides for the "org.example.MyCalendar" class.
<?xml version="1.0" encoding="US-ASCII"?> <xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"> <java-types> <java-type name="org.example.MyCalendar"> <xml-java-type-adapter value="org.example.MyCalendarAdapter"/> </java-type> </java-types> </xml-bindings>
Example: Property-level XmlAdapter
Java Metadata
The following example will demonstrate how a property level XmlAdapter annotation can be applied:
org.example.MyClass.java
package org.example; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; public class MyClass { @XmlAttribute @XmlJavaTypeAdapter(value=org.example.IdAdapter.class) public int id; @XmlJavaTypeAdapter(value=org.example.DateAdapter.class) public Calendar cal; }
org.example.DateAdapter.java
package org.example; import java.util.Calendar; import java.util.GregorianCalendar; import javax.xml.bind.annotation.adapters.XmlAdapter; public final class DateAdapter extends XmlAdapter<CustomDateType, Calendar> { public DateAdapter() {} public CustomDateType marshal(Calendar arg0) throws Exception { CustomDateType cType = new CustomDateType(); cType.day = arg0.get(Calendar.DATE); cType.month = arg0.get(Calendar.MONTH); cType.year = arg0.get(Calendar.YEAR); return cType; } public Calendar unmarshal(CustomDateType arg0) throws Exception { return new GregorianCalendar(arg0.year, arg0.month, arg0.day); } }
org.example.CustomDateType.java
package org.example; public class CustomDateType { public int year; public int month; public int day; }
org.example.IdAdapter.java
package org.example; import javax.xml.bind.annotation.adapters.XmlAdapter; public final class IdAdapter extends XmlAdapter<String, Integer> { public IdAdapter() {} public String marshal(Integer arg0) throws Exception { return String.valueOf(arg0.intValue()); } public Integer unmarshal(String arg0) throws Exception { return Integer.valueOf(arg0); } }
XML Metadata
xml-java-type-adapter
If this is present in the XML then it completely replaces the corresponding annotation.
org/example/eclipselink-oxm.xml
This XML file represents metadata overrides for the "org.example.MyClass" class.
<?xml version="1.0" encoding="US-ASCII"?> <xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"> <java-types> <java-type name="org.example.MyClass"> <java-attributes> <xml-attribute java-attribute="id"> <xml-java-type-adapter value="org.example.IdAdapter" /> </xml-attribute> <xml-element java-attribute="cal"> <xml-java-type-adapter value="org.example.DateAdapter"/> </xml-element> </java-attributes> </java-type> </java-types> </xml-bindings>
Example: xml-map
The following example will demonstrate xml-map usage.
org.example.Company.java
public class Company { public List departments; public Map departmentIdToName; public Map intObjectMap; public Map objectStringMap; public Map objectIntMap; ...
XML Metadata
xml-map
If this is present in the XML then the key and value type of the map can be overridden.
org/example/eclipselink-oxm.xml
<?xml version="1.0" encoding="US-ASCII"?> <xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"> <java-types> <java-type name='org.example.Company'> <java-attributes> <xml-element java-attribute='departments' name='departments' type='java.lang.Integer'/> //example setting the key-type and value-type* <xml-element java-attribute='departmentIdToName' name='departmentIdToName'> <xml-map> <key type='java.lang.Integer'/> <value type='java.lang.String'/> </xml-map> </xml-element> //example setting the key-type only (value-type will then be Object) <xml-element java-attribute='intObjectMap' name='int-to-object'> <xml-map> <key type='java.lang.Integer'/> </xml-map> </xml-element> //example setting the value-type only (key-type will then be Object) <xml-element java-attribute='objectStringMap' name='object-to-string'> <xml-map> <value type='java.lang.String'/> </xml-map> </xml-element> //example setting the key-type and value-type along with the type attribute on xml-element //in this case we will ignore the type on xml-element and log a warning that it's being ignored <xml-element java-attribute='objectStringMap' name='object-to-string' type='java.lang.Integer'> <xml-map> <value type='java.lang.String'/> </xml-map> </xml-element> </java-attributes> </java-type> </java-types> </xml-bindings>