Jump to: navigation, search

EclipseLink/DesignDocs/293925/MOXyExtensions

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:

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)
  • Null policy
  • Get/set method names
  • Default null value (see Decision# 3 below)
  • Converters (see Decision# 4 below)
  • Container policy (see Decision# 5 below)

Development Phases

Support for MOXy mapping configuration via external metadata file will be delivered in the following phases:

Phase 1 - Initial support (complete mappings)

  • Direct
  • Composite Object

Phase 2 - xml-path support

  • Direct Collection
  • Composite Collection
  • Any Object
  • Any Collection
  • Any Attribute
  • Object Reference
  • Collection Reference

Phase 2.1 - additional xml-path support

  • Binary Data
  • Binary Data Collection

Phase 3 - Method access support

  • Direct Collection
  • Composite Collection
  • Any Object
  • Any Collection
  • Any Attribute
  • Object Reference
  • Collection Reference
  • Choice Object
  • Choice Collection
  • Binary Data
  • Binary Data Collection

Phase 4 - Null policy support

  • Direct Collection
  • Composite Collection

Phase 5 - Read/Write only support w/CDATA support for direct colleciton

  • Direct Collection
  • Composite Collection
  • Any Object
  • Any Collection
  • Any Attribute
  • Object Reference
  • Collection Reference
  • Choice Object
  • Choice Collection
  • Binary Data
  • Binary Data Collection

Phase 6 - Additional xml-path support

  • Choice Object
  • Choice Collection

Phase 7 - Additional mapping support

  • Inverse Reference

Design

Path-based mapping support

We will support the following paths:

  • personal-info/first-name/text() - Direct Mapping
  • ns:personal-info/ns:first-name/text() - Direct Mapping with Namespace
  • street[2]/text() - Direct Mapping positional XPath
  • @id - Direct Mapping to Attribute
  • contact-info/address - Composite Mapping
  • contact-info/address[2] - Composite Mapping positional XPath
  • . - Self Composite Object Mapping

Basic configuration

We will support path-based mappings via xml-path attribute. If xml-path is present, it is assumed to contain the entire XPath, hence the name and namespace attributes - if set - will be ignored, as well as any xml-element-wrapper declarations. Since the namespace is ignored when an xml-path is set, prefixes are to be used to configure the namespace for a given path element. An example demonstrating how to set the prefix/uri pairs and an xml-path that makes use of prefixes can be found here. Design notes for the path-based mapping support are located here.

Following is an example of a direct mapping - firstName field mapped to a personal-info/name/first-name element:

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

Equivalent annotations:

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

Following is an example of a direct mapping - employeeId field mapped to an id attribute:

<xml-attribute java-attribute="employeeId" xml-path="employee/@id" />

Equivalent annotations:

package org.example;
 
public class Employee {
    @javax.xml.bind.annotation.XmlAttribute
    @org.eclipse.persistence.oxm.annotations.XmlPath("employee/@id")*
    public String employeeId;
}
  • Note that the XmlPath annotation does not exist and is intended for example purposes only.

Following is an example of a composite mapping:

<xml-element java-attribute="address" xml-path="contact-info/address" />

Equivalent annotations:

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

Following is an example of a composite mapping to self:

<xml-element java-attribute="address" xml-path="." />

Equivalent annotations:

package org.example;
 
public class Employee {
    @javax.xml.bind.annotation.XmlElement
    @org.eclipse.persistence.oxm.annotations.XmlPath(".")*
    public String address;
}
  • 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="addresses/address[2]/street/text()" />

Equivalent annotation:

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

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="address/street[1]/text()" />
<xml-element java-attribute="streetTwo" xml-path="address/street[2]/text()" />

Equivalent annotations:

package org.example;
 
public class Employee {
    @javax.xml.bind.annotation.XmlElement
    @org.eclipse.persistence.oxm.annotations.XmlPath("address/street[1]/text()")*
    public String streetOne;
 
    @javax.xml.bind.annotation.XmlElement
    @org.eclipse.persistence.oxm.annotations.XmlPath("address/street[2]/text()")*
    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" abstract="true">
    <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?

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 We will use an xml-path attribute where appropriate to support path-based mappings
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. The handling of default value should be consistent with current MOXy default value handling.
4 Converters Since we already support converter functionality through XmlAdapter we will not add any additional support at this time
5 Container Policy Container policy will be determined under the covers based on the field type. We will not provide support for user-set container policy.

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