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

Difference between revisions of "EclipseLink/DesignDocs/293925/MOXyExtensions"

(Read only)
(Get/Set method names)
Line 333: Line 333:
 
}
 
}
 
</source>
 
</source>
 +
*Note that the <code>XmlAccessMethods</code> annotation is not real and is intended for example purposes only.
  
 
== Open Issues  ==
 
== Open Issues  ==

Revision as of 16:57, 17 February 2010

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

Path-based mappings must be supported. Design notes are located here.

The following should be configurable:

  • Positional Mappings
  • Read only (boolean)
  • Write only (boolean)
  • CDATA (boolean)
  • Converters
  • Default null value
  • Null policy
  • Get/set method names

Design

Path-based mapping support

Basic configuration

We will support path-based mappings by making use of the xml-element-wrapper structure. The current constraints on xml-element-wrapper that it is only applicable to multi-valued properties and not for use with <xml-attribute> and xml-value will be removed. The path will be set by overloading the name attribute. For example, the following XML metadata snippet would be used to setup a direct mapping that maps firstName to personal-info/name/first-name:

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

Equivalent annotations:

package org.example;
 
public class Employee {
    @javax.xml.bind.annotation.XmlElement(name="first-name")
    @javax.xml.bind.annotation.XmlElementWrapper(name="personal-info/name")
    public String firstName;
}

Positional Paths

Positional paths will be supported. 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-element-wrapper name="addresses/address[2]" />
</xml-element>

Equivalent annotation:

package org.example;
 
public class Employee {
    @javax.xml.bind.annotation.XmlElementWrapper(name="addresses/address[2]")
    public String street;
}

Optional Elements

The following optional elements are applicable to xml-element-wrapper:

  • namespace
  • nillable
  • required
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-element-wrapper name="prj:info/personal-info/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-element-wrapper name="prj:info/emp:personal-info/emp:name" />
                </xml-element>
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>
Nillable & Required

If nillable or required are set, they will be applied to the last element in the path. For example, given the following XML metadata file:

<?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">
            <java-attributes>
                <xml-element java-attribute="firstName" name="first-name">
                    <xml-element-wrapper name="info/personal-info" nillable="true" required="true" />
                </xml-element>
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

Would result in the following schema:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <xsd:complexType name="employee">
      <xsd:sequence>
         <xsd:element name="info">
            <xsd:complexType>
               <xsd:sequence>
                  <xsd:element name="personal-info" minOccurs="1" nillable="true">
                     <xsd:complexType>
                        <xsd:sequence>
                           <xsd:element name="first-name" type="xsd:string" />
                        </xsd:sequence>
                     </xsd:complexType>
                  </xsd:element>
               </xsd:sequence>
            </xsd:complexType>
         </xsd:element>
      </xsd:sequence>
   </xsd:complexType>
   <xsd:element name="employee" type="employee" />
</xsd:schema>

Positional Mappings

Positional mappings will be supported on xml-element. This can be done by overloading the name attribute. For example, the following would be used to map to the first and second occurrence of street:

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

Equivalent annotations:

package org.example;
 
public class Employee {
    @javax.xml.bind.annotation.XmlElement(name="street[1]")
    public String streetOne;
 
    @javax.xml.bind.annotation.XmlElement(name="street[2]")
    public String streetTwo;
}

Note that positional mappings cannot be applied to xml-attribute or xml-value.

Read only

Read only will be supported via boolean attribute on xml-attribute, xml-element and xml-value, 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 is not real and is intended for example purposes only.

Write only

Write only will be supported via boolean attribute on xml-attribute, xml-element and xml-value, 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 is not real and is intended for example purposes only.

CDATA

CDATA will be supported via boolean attribute on xml-element and xml-value, 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 is not real and is intended for example purposes only.

CDATA is not supported on attributes.

Converters

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

Default null value

To support default null value configuration, a sub-element will be added to xml-attribute, xml-element and xml-value. The schema structure of this element will be as follows:

<xsd:element name="null-value" type="xsd:anySimpleType" minOccurs="0" />

An example of setting the null value in XML metadata would be:

<xml-element java-attribute="empId" name="id">
    <null-value xsi:type="xs:int">-1</null-value>
</xml-element>

The equivalent configured via annotations would look like:

package org.example;
 
public class Employee {
    @javax.xml.bind.annotation.XmlElement(name="id")
    @org.eclipse.persistence.oxm.annotations.XmlNullValue(type="int", value=-1)*
    public int empId;
}
  • Note that the XmlNullValue annotation is not real and is intended for example purposes only.

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 on xml-attribute, xml-element and xml-value will be configurable via sub-element. The following structures will be added to the schema (an element ref with minOccurs=0, maxOccurs=1 will be added to each of the above-mentioned elements):

<xml-element name="access-methods" type="access-methods" />
<xs:complexType name="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">
  <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 is not real 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 Two possible ways to allow a path-based mapping to be configured are being considered: xml-attribute/xml-element/xml-value or xml-element-wrapper. Which is preferred? Design note are located here.
2 D.McCann Three possible ways to set the path for a mapping are being considered: name overload vs. xpath vs. name + grouping-element. Which is preferred? Design notes are located here.
3 D.McCann What is the expected behavior when namespace is set on an xml-element-wrapper that has a path set?
4 D.McCann What is the expected behavior when required is set on an xml-element-wrapper that has a path set?
5 D.McCann What is the expected behavior when nillable is set on an xml-element-wrapper that has a path set?
6 D.McCann How can we support positional mappings?
7 D.McCann What will the schema look like WRT converters?

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 Two possible ways to allow a path-based mapping to be configured are being considered: xml-attribute/xml-element/xml-value or xml-element-wrapper xml-element-wrapper will be extended to handle multi-level paths, and enabled for use with xml-attribute/xml-value and single-valued properties.
2 Three possible ways to set the path for a mapping are being considered: name overload vs. xpath vs. name + grouping-element name will be overloaded.
3 What is the expected behavior when namespace is set on an xml-element-wrapper that has a path set? If namespace is set, it will be applied to any path element that is not prefixed.
4 What is the expected behavior when required is set on an xml-element-wrapper that has a path set? If required is set, it will be applied to the last element in the path.
5 What is the expected behavior when nillable is set on an xml-element-wrapper that has a path set? If nillable is set, it will be applied to the last element in the path.
6 How can we support positional mappings? Positional mappings will be supported by overloading the name attribute on xml-element.

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.

  • For issue #2 above, it may be useful to add an additional attribute such that users who do not wish use the name attribute in a non-standard way are able to set a multi-level path.

Back to the top