Skip to main content
Jump to: navigation, search

EclipseLink/DesignDocs/293925/MOXyExtensions

< EclipseLink‎ | DesignDocs‎ | 293925
Revision as of 05:09, 4 March 2010 by David.mccann.oracle.com (Talk | contribs) (Open Issues)

MOXy Mapping Extensions

Purpose

The purpose of this work is to provide an extension of our JAXB metadata support that will allow MOXy mappings to be configured through the external mapping file.

Requirements

Provide support for MOXy mappings via XML metadata.

The following MOXy mappings will be supported via XML metadata:

  • XML Direct
  • XML Composite Direct Collection
  • XML Composite Object
  • XML Composite Collection
  • XML Object Reference
  • XML Collection Reference
  • XML Binary Data
  • XML Binary Data Collection
  • XML Any Object
  • XML Any Collection
  • XML Fragment
  • XML Fragment Collection
  • XML Choice Object
  • XML Choice Collection
  • XML Transformation
  • XML Any Attribute
  • XML Inverse Reference

The following should be configurable (note that some items are not applicable to all mappings):

  • Path-based mappings
  • Positional mappings
  • Read only (boolean)
  • Write only (boolean)
  • CDATA (boolean)
  • Converters
  • Default null value
  • Null policy
  • Get/set method names
  • Container policy

Design

Path-based mapping support (design notes are located here)

Basic configuration

We will support path-based mappings by creating a new xml-path structure. This new structure will be created as a global type/element, and referenced where appropriate, such as xml-attribute, xml-element, etc. If xml-path is present, it is assumed to contain the entire XPath as well as namespace information, hence the name and namespace - if set - on the enclosing structure will be ignored, as well as any xml-element-wrapper declarations.

The xml-path schema structure will look like the following:

<xs:element name="xml-path" type="xml-path" />
<xs:complexType name="xml-path">
    <xs:attribute name="name" type="xs:string" use="required" />
    <xs:attribute name="namespace" type="xs:string" />
</xs:complexType>

Follwing is an example of mapping a firstName field to personal-info/name/first-name:

<xml-element java-attribute="firstName">
    <xml-path name="personal-info/name/first-name" />
</xml-element>

Equivalent annotations:

package org.example;
 
public class Employee {
    @javax.xml.bind.annotation.XmlElement
    @org.eclipse.persistence.oxm.annotations.XmlPath(name="personal-info/name/first-name")*
    public String firstName;
}
  • Note that the XmlPath annotation does not exist and is intended for example purposes only.

Positional Paths

Positional paths will be supported via xml-path. For example, the following would be used to create a direct mapping to street in the second occurrence of address:

<xml-element java-attribute="street">
    <xml-path name="addresses/address[2]/street" />
</xml-element>

Equivalent annotation:

package org.example;
 
public class Employee {
    @javax.xml.bind.annotation.XmlElement
    @org.eclipse.persistence.oxm.annotations.XmlPath(name="addresses/address[2]/street")*
    public String street;
}
  • Note that the XmlPath annotation does not exist and is intended for example purposes only.

Optional Elements

The following optional elements are applicable to xml-path:

  • namespace
Namespace

If namespace is set, it will be applied to any path element that is not prefixed. For example, the following:

<?xml version="1.0" encoding="US-ASCII"?>
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm">
    <xml-schema namespace="http://www.example.com/default">
        <xml-ns namespace-uri="http://www.example.com/employees" prefix="emp"/>
        <xml-ns namespace-uri="http://www.example.com/projects" prefix="prj"/>
    </xml-schema>
    <java-types>
        <java-type name="org.example.Employee">
            <java-attributes>
                <xml-element java-attribute="firstName">
                    <xml-path name="prj:info/personal-info/name/first-name" namespace="http://www.example.com/employees" />
                </xml-element>
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

Would be equivalent to:

<?xml version="1.0" encoding="US-ASCII"?>
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm">
    <xml-schema namespace="http://www.example.com/default">
        <xml-ns namespace-uri="http://www.example.com/employees" prefix="emp"/>
        <xml-ns namespace-uri="http://www.example.com/projects" prefix="prj"/>
    </xml-schema>
    <java-types>
        <java-type name="org.example.Employee">
            <java-attributes>
                <xml-element java-attribute="firstName">
                    <xml-path name="prj:info/emp:personal-info/emp:name/emp:first-name" />
                </xml-element>
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

Positional Mappings

Positional mappings will be supported via xml-path. For example, the following would be used to map to the first and second occurrence of street to address/street[x]:

<xml-element java-attribute="streetOne">
    <xml-path name="address/street[1]" />
</xml-element>
<xml-element java-attribute="streetTwo">
    <xml-path name="address/street[2]" />
</xml-element>

Equivalent annotations:

package org.example;
 
public class Employee {
    @javax.xml.bind.annotation.XmlElement
    @org.eclipse.persistence.oxm.annotations.XmlPath(name="address/street[1]")*
    public String streetOne;
 
    @javax.xml.bind.annotation.XmlElement
    @org.eclipse.persistence.oxm.annotations.XmlPath(name="address/street[2]")*
    public String streetTwo;
}
  • Note that the XmlPath annotation does not exist and is intended for example purposes only.

Read only

Read only will be supported via boolean attribute, i.e.:

<xml-attribute java-attribute="salary" read-only="true" />

The equivalent configured via annotations would look like:

package org.example;
 
public class Employee {
    @javax.xml.bind.annotation.XmlAttribute
    @org.eclipse.persistence.oxm.annotations.XmlReadOnly*
    public String salary;
}
  • Note that the XmlReadOnly annotation does not exist and is intended for example purposes only.

Write only

Write only will be supported via boolean attribute, i.e.:

<xml-attribute java-attribute="privateData" write-only="true" />

The equivalent configured via annotations would look like:

package org.example;
 
public class Employee {
    @javax.xml.bind.annotation.XmlAttribute
    @org.eclipse.persistence.oxm.annotations.XmlWriteOnly*
    public String privateData;
}
  • Note that the XmlWriteOnly annotation does not exist and is intended for example purposes only.

CDATA

CDATA will be supported via boolean attribute, i.e.:

<xml-element java-attribute="characterData" cdata="true" />

The equivalent configured via annotations would look like:

package org.example;
 
public class Employee {
    @javax.xml.bind.annotation.XmlElement
    @org.eclipse.persistence.oxm.annotations.XmlCDATA*
    public String characterData;
}
  • Note that the XmlCDATA annotation does not exist and is intended for example purposes only.

Converters

Converters will be supported by extending our existing xml-java-type-adapter functionality.

Default Null Value

Default null value will be supported via default-value on xml-element. In addition, our XmlCustomizer support could be utilized to set a default value on the mapping.

Null Policy

The schema structures for null policy will look like:

<xs:element name="xml-abstract-null-policy" type="xml-abstract-null-policy" />
<xs:complexType name="xml-abstract-null-policy">
    <xs:attribute name="xsi-nil-represents-null" type="xs:boolean" default="false" />
    <xs:attribute name="empty-node-represents-null" type="xs:boolean" default="false" />
    <xs:attribute name="null-representation-for-xml" type="xml-marshal-null-representation" />
</xs:complexType>
 
<xs:element name="xml-null-policy" substitutionGroup="xml-abstract-null-policy" type="xml-null-policy"/>
<xs:complexType name="xml-null-policy">
    <xs:complexContent>
        <xs:extension base="xml-abstract-null-policy">
            <xs:attribute name="is-set-performed-for-absent-node" type="xs:boolean" default="true" />
        </xs:extension>
    </xs:complexContent>
</xs:complexType>
 
<xs:element name="xml-is-set-null-policy" substitutionGroup="xml-abstract-null-policy" type="xml-is-set-null-policy"/>
<xs:complexType name="xml-is-set-null-policy">
    <xs:complexContent>
        <xs:extension base="xml-abstract-null-policy">
            <xs:sequence>
                <xs:element name="is-set-parameter" minOccurs="0" maxOccurs="unbounded">
                    <xs:complexType>
                        <xs:attribute name="name" type="xs:string"/>
                        <xs:attribute name="type" type="xs:string"/>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
            <xs:attribute name="is-set-method-name" type="xs:string" />
        </xs:extension>
    </xs:complexContent>
</xs:complexType>
 
<xs:simpleType name="xml-marshal-null-representation">
    <xs:restriction base="xs:string">
        <xs:enumeration value="XSI_NIL" />
        <xs:enumeration value="ABSENT_NODE" />
        <xs:enumeration value="EMPTY_NODE" />
    </xs:restriction>
</xs:simpleType>

Get/Set Method Names

The get/set method names will be configurable via sub-element. The following structures will be added to the schema:

<xs:element name="xml-access-methods" type="xml-access-methods" />
<xs:complexType name="xml-access-methods">
  <xs:attribute name="get-method" type="xs:string" use="required"/>
  <xs:attribute name="set-method" type="xs:string" use="required"/>
</xs:complexType>

The following example demonstrates setting the accessor method names for a direct mapping:

<xml-element java-attribute="firstName">
  <xml-access-methods get-method="getFirstName" set-method="setFirstName" />
</xml-element>

The equivalent configured via annotations would look like:

package org.example;
 
public class Employee {
    @javax.xml.bind.annotation.XmlElement
    @org.eclipse.persistence.oxm.annotations.XmlAccessMethods(get-method="getFirstName", set-method="setFirstName")*
    public String firstName;
}
  • Note that the XmlAccessMethods annotation does not exist and is intended for example purposes only.

Open Issues

This section lists the open issues that are still pending that must be decided prior to fully implementing this project's requirements.

Issue# Owner Description/Notes
1 D.McCann Default null value is supported via defaultValue on xml-element; is there a need to support default null value on xml-attribute?
2 D.McCann Regarding default null value, if we unmarshal a null we will set the default in the object; the question is, what is the expected behavior when we write out the default? I.e. the default-value for projectId is set to "999", and we marshal out the object which has "999" set for the projectId.
3 D.McCann Container policy can be determined under the covers based on the field type. JPA currently does not support user-set container policy - should we provide this support now, or add it as a future consideration?

Decisions

This section lists decisions made. These are intended to document the resolution of open issues or constraints added to the project that are important.

Issue# Description/Notes Decision
1 'name' attribute override Overloading 'name' to add extended support is not acceptable; we do not want to recommend/support invalid attribute/element content like '[' which would be invalid WRT the RI
2 Path-based and positional mapping support Extending element wrapper would involve improper usage (as with XmlAttribute and single-valued properties), hence we will need a different way to support path-based mappings. One suggestion would be to introduce the concept of an "xml-path" that would be used to create a mapping with an xpath and possibly other settings
3 Default null value No need to support this now as xml-element already has the concept of default-value. Also, XmlCustomizer can be used to set a default null value on the mapping.
4 Converters Since we already support converter functionality through XmlAdapter we will not add any additional support at this time

Future Considerations

During the research for this project the following items were identified as out of scope but are captured here as potential future enhancements. If agreed upon during the review process these should be logged in the bug system.

  • We may need to add support for default null value if customers require it
  • We may need to add support for converters if use of xml-adapter isn't sufficient

Back to the top