EclipseLink/DesignDocs/277920/Phase3

From Eclipsepedia

Jump to: navigation, search

Contents

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>