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

EclipseLink/DesignDocs/293925/MOXyExtensions

< EclipseLink‎ | DesignDocs‎ | 293925
Revision as of 16:22, 19 March 2010 by David.mccann.oracle.com (Talk | contribs) (Requirements)

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

Design

Path-based mapping support

We will support the following paths:

  • 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
  • . - 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

Back to the top