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)
(Phase 7 - Additional mapping support)
 
(95 intermediate revisions by the same user not shown)
Line 9: Line 9:
  
 
The following MOXy mappings will be supported via XML metadata:
 
The following MOXy mappings will be supported via XML metadata:
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/XMLDirectMapping XML Direct]
+
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/MOXyExtensions/XmlAnyAttributeMapping XML Any Attribute]
* XML Composite Direct Collection
+
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/MOXyExtensions/XmlAnyCollectionMapping XML Any Collection]
* XML Composite Object
+
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/MOXyExtensions/XmlAnyObjectMapping XML Any Object]
* XML Composite Collection
+
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/MOXyExtensions/XmlBinaryDataMapping XML Binary Data]
* XML Object Reference
+
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/MOXyExtensions/XmlBinaryDataCollectionMapping XML Binary Data Collection]
* XML Collection Reference
+
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/MOXyExtensions/XmlChoiceObjectMapping XML Choice Object]
* XML Binary Data
+
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/MOXyExtensions/XmlChoiceCollectionMapping XML Choice Collection]
* XML Binary Data Collection
+
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/MOXyExtensions/XmlCollectionReferenceMapping XML Collection Reference]
* XML Any Object
+
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/MOXyExtensions/XMLCompositeMapping XML Composite Object]
* XML Any Collection
+
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/MOXyExtensions/XMLCompositeCollectionMapping XML Composite Collection]
* XML Fragment
+
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/MOXyExtensions/XMLDirectMapping XML Direct]
* XML Fragment Collection
+
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/MOXyExtensions/XMLDirectCollectionMapping XML Direct Collection]
* XML Choice Object
+
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/MOXyExtensions/XmlInverseReferenceMapping XML Inverse Reference]
* XML Choice Collection
+
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/MOXyExtensions/XmlObjectReferenceMapping XML Object Reference]
* XML Transformation
+
* XML Any Attribute
+
  
Path-based mappings must be supported.  Design notes are located [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/PathBasedMappings here].
+
The following should be configurable (note that some items are not applicable to all mappings):
 
+
* Path-based mappings
The following should be configurable:
+
* Positional mappings
* Positional Mappings
+
 
* Read only (boolean)
 
* Read only (boolean)
 
* Write only (boolean)
 
* Write only (boolean)
 
* CDATA (boolean)
 
* CDATA (boolean)
* Converters
 
* Default null value
 
 
* Null policy
 
* Null policy
 
* Get/set method names
 
* Get/set method names
 +
* Default null value (see [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/MOXyExtensions#Decisions Decision# 3] below)
 +
* Converters (see [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/MOXyExtensions#Decisions Decision# 4] below)
 +
* Container policy (see [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/MOXyExtensions#Decisions 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 ==
 
== Design ==
 
=== Path-based mapping support ===
 
=== Path-based mapping support ===
 +
We will support the following paths:
 +
* <code>personal-info/first-name/text()</code> - Direct Mapping
 +
* <code>ns:personal-info/ns:first-name/text()</code> - Direct Mapping with Namespace
 +
* <code>street[2]/text()</code> - Direct Mapping positional XPath
 +
* <code>@id</code> - Direct Mapping to Attribute
 +
* <code>contact-info/address</code> - Composite Mapping
 +
* <code>contact-info/address[2]</code> - Composite Mapping positional XPath
 +
* <code>.</code> - Self Composite Object Mapping
 +
 
==== Basic configuration ====
 
==== Basic configuration ====
We will support path-based mappings by making use of the <code>xml-element-wrapper</code> structureThe current constraints on <code>xml-element-wrapper</code> that it is only applicable to multi-valued properties and not for use with <code><xml-attribute></code> and <code>xml-value</code> will be removedThe path will be set by overloading the <code>name</code> attribute. For example, the following XML metadata snippet would be used to setup a direct mapping that maps <code>firstName</code> to <code>personal-info/name/first-name</code>:
+
We will support path-based mappings via <code>xml-path</code> attributeIf <code>xml-path</code> is present, it is assumed to contain the entire XPath, hence the <code>name</code> and <code>namespace</code> attributes - if set - will be ignored, as well as any <code>xml-element-wrapper</code> declarations. Since the <code>namespace</code> is ignored when an <code>xml-path</code> is set, prefixes are to be used to configure the namespace for a given path elementAn example demonstrating how to set the prefix/uri pairs and an <code>xml-path</code> that makes use of prefixes can be found [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/XMLDirectMapping#org.2Fexample.2Feclipselink-oxm.xml here]. Design notes for the path-based mapping support are located [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/PathBasedMappings here].
 +
 
 +
Following is an example of a direct mapping - <code>firstName</code> field mapped to a <code>personal-info/name/first-name</code> element:
 
<source lang="xml">
 
<source lang="xml">
<xml-element java-attribute="firstName" name="first-name">
+
<xml-element java-attribute="firstName" xml-path="personal-info/name/first-name/text()" />
    <xml-element-wrapper name="personal-info/name" />
+
</xml-element>
+
 
</source>
 
</source>
  
Line 53: Line 109:
  
 
public class Employee {
 
public class Employee {
     @javax.xml.bind.annotation.XmlElement(name="first-name")
+
     @javax.xml.bind.annotation.XmlElement
     @javax.xml.bind.annotation.XmlElementWrapper(name="personal-info/name")
+
     @org.eclipse.persistence.oxm.annotations.XmlPath("personal-info/name/first-name/text()")*
 
     public String firstName;
 
     public String firstName;
 
}
 
}
 
</source>
 
</source>
 +
*Note that the <code>XmlPath</code> annotation does not exist and is intended for example purposes only.
  
==== Positional Paths ====
+
Following is an example of a direct mapping - <code>employeeId</code> field mapped to an <code>id</code> attribute:
Positional paths will be supported.  For example, the following would be used to create a direct mapping to <code>street</code> in the second occurrence of <code>address</code>:
+
 
<source lang="xml">
 
<source lang="xml">
<xml-element java-attribute="street">
+
<xml-attribute java-attribute="employeeId" xml-path="employee/@id" />
    <xml-element-wrapper name="addresses/address[2]" />
+
</xml-element>
+
 
</source>
 
</source>
  
Equivalent annotation:
+
Equivalent annotations:
 
<source lang="java">
 
<source lang="java">
 
package org.example;
 
package org.example;
+
 
 
public class Employee {
 
public class Employee {
     @javax.xml.bind.annotation.XmlElementWrapper(name="addresses/address[2]")
+
     @javax.xml.bind.annotation.XmlAttribute
     public String street;
+
    @org.eclipse.persistence.oxm.annotations.XmlPath("employee/@id")*
 +
     public String employeeId;
 
}
 
}
 
</source>
 
</source>
 +
*Note that the <code>XmlPath</code> annotation does not exist and is intended for example purposes only.
  
==== Optional Elements ====
+
Following is an example of a composite mapping:
The following optional elements are applicable to <code>xml-element-wrapper</code>:
+
*<code>namespace</code>
+
*<code>nillable</code>
+
*<code>required</code>
+
===== Namespace =====
+
If <code>namespace</code> is set, it will be applied to any path element that is not prefixed.  For example, the following:
+
 
<source lang="xml">
 
<source lang="xml">
<?xml version="1.0" encoding="US-ASCII"?>
+
<xml-element java-attribute="address" xml-path="contact-info/address" />
<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>
+
 
</source>
 
</source>
Would be equivalent to:
+
 
<source lang="xml">
+
Equivalent annotations:
<?xml version="1.0" encoding="US-ASCII"?>
+
<source lang="java">
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm">
+
package org.example;
     <xml-schema namespace="http://www.example.com/default">
+
 
        <xml-ns namespace-uri="http://www.example.com/employees" prefix="emp"/>
+
public class Employee {
        <xml-ns namespace-uri="http://www.example.com/projects" prefix="prj"/>
+
     @javax.xml.bind.annotation.XmlElement
     </xml-schema>
+
     @org.eclipse.persistence.oxm.annotations.XmlPath("contact-info/address")*
    <java-types>
+
     public String address;
        <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>
+
 
</source>
 
</source>
 +
*Note that the <code>XmlPath</code> annotation does not exist and is intended for example purposes only.
  
===== Nillable & Required =====
+
Following is an example of a composite mapping to self:
If <code>nillable</code> or <code>required</code> are set, they will be applied to the last element in the path.  For example, given the following XML metadata file:
+
 
<source lang="xml">
 
<source lang="xml">
<?xml version="1.0" encoding="US-ASCII"?>
+
<xml-element java-attribute="address" xml-path="." />
<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>
+
 
</source>
 
</source>
Would result in the following schema:
+
 
 +
Equivalent annotations:
 +
<source lang="java">
 +
package org.example;
 +
 
 +
public class Employee {
 +
    @javax.xml.bind.annotation.XmlElement
 +
    @org.eclipse.persistence.oxm.annotations.XmlPath(".")*
 +
    public String address;
 +
}
 +
</source>
 +
*Note that the <code>XmlPath</code> annotation does not exist and is intended for example purposes only.
 +
 
 +
==== Positional Paths ====
 +
Positional paths will be supported via <code>xml-path</code>.  For example, the following would be used to create a direct mapping to <code>street</code> in the second occurrence of <code>address</code>:
 
<source lang="xml">
 
<source lang="xml">
<?xml version="1.0" encoding="UTF-8"?>
+
<xml-element java-attribute="street" xml-path="addresses/address[2]/street/text()" />
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
</source>
  <xsd:complexType name="employee">
+
 
      <xsd:sequence>
+
Equivalent annotation:
        <xsd:element name="info">
+
<source lang="java">
            <xsd:complexType>
+
package org.example;
              <xsd:sequence>
+
                  <xsd:element name="personal-info" minOccurs="1" nillable="true">
+
public class Employee {
                    <xsd:complexType>
+
    @javax.xml.bind.annotation.XmlElement
                        <xsd:sequence>
+
    @org.eclipse.persistence.oxm.annotations.XmlPath("addresses/address[2]/street/text()")*
                          <xsd:element name="first-name" type="xsd:string" />
+
    public String street;
                        </xsd:sequence>
+
}
                    </xsd:complexType>
+
                  </xsd:element>
+
              </xsd:sequence>
+
            </xsd:complexType>
+
        </xsd:element>
+
      </xsd:sequence>
+
  </xsd:complexType>
+
  <xsd:element name="employee" type="employee" />
+
</xsd:schema>
+
 
</source>
 
</source>
 +
*Note that the <code>XmlPath</code> annotation does not exist and is intended for example purposes only.
  
 
=== Positional Mappings ===
 
=== Positional Mappings ===
Positional mappings will be supported on <code>xml-element</code>.  This can be done by overloading the <code>name</code> attribute.  For example, the following would be used to map to the first and second occurrence of <code>street</code>:
+
Positional mappings will be supported via <code>xml-path</code>.  For example, the following would be used to map to the first and second occurrence of <code>street</code> to <code>address/street[x]</code>:
 
<source lang="xml">
 
<source lang="xml">
<xml-element java-attribute="streetOne" name="street[1]" />
+
<xml-element java-attribute="streetOne" xml-path="address/street[1]/text()" />
<xml-element java-attribute="streetTwo" name="street[2]" />
+
<xml-element java-attribute="streetTwo" xml-path="address/street[2]/text()" />
 
</source>
 
</source>
  
Line 175: Line 197:
  
 
public class Employee {
 
public class Employee {
     @javax.xml.bind.annotation.XmlElement(name="street[1]")
+
     @javax.xml.bind.annotation.XmlElement
 +
    @org.eclipse.persistence.oxm.annotations.XmlPath("address/street[1]/text()")*
 
     public String streetOne;
 
     public String streetOne;
  
     @javax.xml.bind.annotation.XmlElement(name="street[2]")
+
     @javax.xml.bind.annotation.XmlElement
 +
    @org.eclipse.persistence.oxm.annotations.XmlPath("address/street[2]/text()")*
 
     public String streetTwo;
 
     public String streetTwo;
 
}
 
}
 
</source>
 
</source>
Note that positional mappings cannot be applied to <code>xml-attribute</code> or <code>xml-value</code>.
+
*Note that the <code>XmlPath</code> annotation does not exist and is intended for example purposes only.
  
 
=== Read only ===
 
=== Read only ===
Read only will be supported via boolean attribute on <code>xml-attribute</code>, <code>xml-element</code> and <code>xml-value</code>, i.e.:
+
Read only will be supported via boolean attribute, i.e.:
 
<source lang="xml">
 
<source lang="xml">
 
<xml-attribute java-attribute="salary" read-only="true" />
 
<xml-attribute java-attribute="salary" read-only="true" />
 
</source>
 
</source>
 
+
The equivalent configured via annotations would look like:
An example of a MOXy annotation for read only would look something like the following:
+
<source lang="java">
+
package org.eclipse.persistence.oxm.annotations;
+
 
+
import java.lang.annotation.ElementType;
+
import java.lang.annotation.Retention;
+
import java.lang.annotation.RetentionPolicy;
+
import java.lang.annotation.Target;
+
 
+
@Target({ElementType.FIELD, ElementType.METHOD})
+
@Retention(RetentionPolicy.RUNTIME)
+
public @interface XmlReadOnly {}
+
</source>
+
 
+
The equivalent configured via annotations:
+
 
<source lang="java">
 
<source lang="java">
 
package org.example;
 
package org.example;
Line 210: Line 219:
 
public class Employee {
 
public class Employee {
 
     @javax.xml.bind.annotation.XmlAttribute
 
     @javax.xml.bind.annotation.XmlAttribute
     @org.eclipse.persistence.oxm.annotations.XmlReadOnly
+
     @org.eclipse.persistence.oxm.annotations.XmlReadOnly*
     public string salary;
+
     public String salary;
 
}
 
}
 
</source>
 
</source>
 +
*Note that the <code>XmlReadOnly</code> annotation does not exist and is intended for example purposes only.
  
 
=== Write only ===
 
=== Write only ===
Write only will be supported via boolean attribute on <code>xml-attribute</code>, <code>xml-element</code> and <code>xml-value</code>, i.e.:
+
Write only will be supported via boolean attribute, i.e.:
 
<source lang="xml">
 
<source lang="xml">
 
<xml-attribute java-attribute="privateData" write-only="true" />
 
<xml-attribute java-attribute="privateData" write-only="true" />
 
</source>
 
</source>
 +
The equivalent configured via annotations would look like:
 +
<source lang="java">
 +
package org.example;
 +
 +
public class Employee {
 +
    @javax.xml.bind.annotation.XmlAttribute
 +
    @org.eclipse.persistence.oxm.annotations.XmlWriteOnly*
 +
    public String privateData;
 +
}
 +
</source>
 +
*Note that the <code>XmlWriteOnly</code> annotation does not exist and is intended for example purposes only.
  
 
=== CDATA ===
 
=== CDATA ===
CDATA will be supported via boolean attribute on <code>xml-element</code> and <code>xml-value</code>, i.e.:
+
CDATA will be supported via boolean attribute, i.e.:
 
<source lang="xml">
 
<source lang="xml">
 
<xml-element java-attribute="characterData" cdata="true" />
 
<xml-element java-attribute="characterData" cdata="true" />
 
</source>
 
</source>
 
+
The equivalent configured via annotations would look like:
Note that CDATA is not supported on attributes.
+
<source lang="java">
 +
package org.example;
 +
 +
public class Employee {
 +
    @javax.xml.bind.annotation.XmlElement
 +
    @org.eclipse.persistence.oxm.annotations.XmlCDATA*
 +
    public String characterData;
 +
}
 +
</source>
 +
*Note that the <code>XmlCDATA</code> annotation does not exist and is intended for example purposes only.
  
 
=== Converters ===
 
=== Converters ===
 
Converters will be supported by extending our existing <code>xml-java-type-adapter</code> functionality.
 
Converters will be supported by extending our existing <code>xml-java-type-adapter</code> functionality.
  
=== Default null value ===
+
=== Default Null Value ===
To support default null value configuration, a sub-element will be added to <code>xml-attribute</code>, <code>xml-element</code> and <code>xml-value</code>.  The schema structure of this element will be as follows:
+
Default null value will be supported via <code>default-value</code> on <code>xml-element</code>.  In addition, our [http://wiki.eclipse.org/EclipseLink/DesignDocs/277920/Phase3#xml-customizer XmlCustomizer] support could be utilized to set a default value on the mapping.
<source lang="xml">
+
<xsd:element name="null-value" type="xsd:anySimpleType" minOccurs="0" />
+
</source>
+
An example of setting the null value in XML metadata would be:
+
<source lang="xml">
+
<xml-element java-attribute="empId" name="id">
+
    <null-value xsi:type="xs:int">-1</null-value>
+
</xml-element>
+
</source>
+
  
 
=== Null Policy ===
 
=== Null Policy ===
Line 248: Line 269:
 
<source lang="xml">
 
<source lang="xml">
 
<xs:element name="xml-abstract-null-policy" type="xml-abstract-null-policy" />
 
<xs:element name="xml-abstract-null-policy" type="xml-abstract-null-policy" />
<xs:complexType name="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="xsi-nil-represents-null" type="xs:boolean" default="false" />
 
     <xs:attribute name="empty-node-represents-null" type="xs:boolean" default="false" />
 
     <xs:attribute name="empty-node-represents-null" type="xs:boolean" default="false" />
Line 289: Line 310:
 
</source>
 
</source>
  
=== Get/Set method names ===
+
=== Get/Set Method Names ===
The get/set method names on <code>xml-attribute</code>, <code>xml-element</code> and <code>xml-value</code> 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):
+
The get/set method names will be configurable via sub-element.  The following structures will be added to the schema:
  
 
<source lang="xml">
 
<source lang="xml">
<xml-element name="access-methods" type="access-methods" />
+
<xs:element name="xml-access-methods" type="xml-access-methods" />
<xs:complexType name="access-methods">
+
<xs:complexType name="xml-access-methods">
 
   <xs:attribute name="get-method" type="xs:string" use="required"/>
 
   <xs:attribute name="get-method" type="xs:string" use="required"/>
 
   <xs:attribute name="set-method" type="xs:string" use="required"/>
 
   <xs:attribute name="set-method" type="xs:string" use="required"/>
Line 302: Line 323:
 
<source lang="xml">
 
<source lang="xml">
 
<xml-element java-attribute="firstName">
 
<xml-element java-attribute="firstName">
   <access-methods get-method="getFirstName" set-method="setFirstName" />
+
   <xml-access-methods get-method="getFirstName" set-method="setFirstName" />
 
</xml-element>
 
</xml-element>
 
</source>
 
</source>
 +
The equivalent configured via annotations would look like:
 +
<source lang="java">
 +
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;
 +
}
 +
</source>
 +
*Note that the <code>XmlAccessMethods</code> annotation does not exist and is intended for example purposes only.
  
 
== Open Issues  ==
 
== Open Issues  ==
Line 317: Line 349:
 
| 1
 
| 1
 
| D.McCann
 
| D.McCann
| Two possible ways to allow a path-based mapping to be configured are being considered:  <code>xml-attribute/xml-element/xml-value</code> or <code>xml-element-wrapper</code>.  Which is preferred?  Design note are located [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/PathBasedMappings#Decision_Point_1:__xml-attribute.2Fxml-element_vs._xml-element-wrapper here].
+
| Default null value is supported via <code>defaultValue</code> on <code>xml-element</code>; is there a need to support default null value on <code>xml-attribute</code>?
|-
+
| 2
+
| D.McCann
+
| Three possible ways to set the path for a mapping are being considered:  <code>name</code> overload vs. <code>xpath</code> vs. <code>name</code> + <code>grouping-element</code>.  Which is preferred?  Design notes are located [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/PathBasedMappings#Decision_Point_2:__name_overload_vs._xpath_vs._name_.2B_grouping-element here].
+
|-
+
| 3
+
| D.McCann
+
| What is the expected behavior when <code>namespace</code> is set on an <code>xml-element-wrapper</code> that has a path set?
+
|-
+
| 4
+
| D.McCann
+
| What is the expected behavior when <code>required</code> is set on an <code>xml-element-wrapper</code> that has a path set?
+
|-
+
| 5
+
| D.McCann
+
| What is the expected behavior when <code>nillable</code> is set on an <code>xml-element-wrapper</code> 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?
+
 
|}
 
|}
  
Line 355: Line 363:
 
|-
 
|-
 
| 1
 
| 1
| Two possible ways to allow a path-based mapping to be configured are being considered: <code>xml-attribute/xml-element/xml-value</code> or <code>xml-element-wrapper</code>
+
| 'name' attribute override
| <code>xml-element-wrapper</code> will be extended to handle multi-level paths, and enabled for use with <code>xml-attribute/xml-value</code> and single-valued properties.
+
| 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
 
| 2
| Three possible ways to set the path for a mapping are being considered: <code>name</code> overload vs. <code>xpath</code> vs. <code>name</code> + <code>grouping-element</code>
+
| Path-based and positional mapping support
| <code>name</code> will be overloaded.
+
| We will use an <code>xml-path</code> attribute where appropriate to support path-based mappings
 
|-
 
|-
 
| 3
 
| 3
| What is the expected behavior when <code>namespace</code> is set on an <code>xml-element-wrapper</code> that has a path set?
+
| Default null value
| If <code>namespace</code> is set, it will be applied to any path element that is not prefixed.
+
| 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
 
| 4
| What is the expected behavior when <code>required</code> is set on an <code>xml-element-wrapper</code> that has a path set?
+
| Converters
| If <code>required</code> is set, it will be applied to the last element in the path.
+
| Since we already support converter functionality through XmlAdapter we will not add any additional support at this time
 
|-
 
|-
 
| 5
 
| 5
| What is the expected behavior when <code>nillable</code> is set on an <code>xml-element-wrapper</code> that has a path set?
+
| Container Policy
| If <code>nillable</code> is set, it will be applied to the last element in the path.
+
| Container policy will be determined under the covers based on the field type. We will not provide support for user-set container policy.
|-
+
| 6
+
| How can we support positional mappings?
+
| Positional mappings will be supported by overloading the <code>name</code> attribute on <code>xml-element</code>.
+
 
|}
 
|}
  
Line 382: Line 386:
  
 
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.
 
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 <code>name</code> attribute in a non-standard way are able to set a multi-level path.
+
* 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

Latest revision as of 15:29, 28 May 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:

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

Back to the top