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"

Line 28: Line 28:
  
 
The following should be configurable (note that some items are not applicable to all mappings):
 
The following should be configurable (note that some items are not applicable to all mappings):
* Path-based mappings (design notes are located [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/PathBasedMappings here])
+
* Path-based mappings
 
* Positional mappings
 
* Positional mappings
 
* Read only (boolean)
 
* Read only (boolean)
Line 42: Line 42:
 
=== Path-based mapping support (design notes are located [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/PathBasedMappings here]) ===
 
=== Path-based mapping support (design notes are located [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/PathBasedMappings here]) ===
 
==== Basic configuration ====
 
==== Basic configuration ====
We will support path-based mappings by creating a new <code>xml-path</code> structure.  This new structure will be created as a global type/element, and referenced where appropriate, such as <code>xml-attribute</code>, <code>xml-element</code>, etc.  The <code>name</code> and <code>namespace</code> - if set - on the enclosing structure will be ignored.  The <code>xml-path</code> schema structure will look like the following:
+
We will support path-based mappings by creating a new <code>xml-path</code> structure.  This new structure will be created as a global type/element, and referenced where appropriate, such as <code>xml-attribute</code>, <code>xml-element</code>, etc.  If <code>xml-path</code> is present, it is assumed to contain the entire XPath as well as namespace information, hence the <code>name</code> and <code>namespace</code> - if set - on the enclosing structure will be ignored, as well as any <code>xml-element-wrapper</code> declarations. 
<source lang="xml">
+
  
 +
The <code>xml-path</code> schema structure will look like the following:
 +
<source lang="xml">
 +
<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>
 
</source>
 
</source>
<code>firstName</code> to <code>personal-info/name/first-name</code>:
+
 
 +
Follwing is an example of mapping a <code>firstName</code> field to <code>personal-info/name/first-name</code>:
 
<source lang="xml">
 
<source lang="xml">
 
<xml-element java-attribute="firstName">
 
<xml-element java-attribute="firstName">
     <xml-path name="personal-info/name" />
+
     <xml-path name="personal-info/name/first-name" />
 
</xml-element>
 
</xml-element>
 
</source>
 
</source>
Line 58: Line 65:
  
 
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(name="personal-info/name/first-name")*
 
     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 ====
 
==== Positional Paths ====
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>:
+
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-element java-attribute="street">
 
<xml-element java-attribute="street">
     <xml-element-wrapper name="addresses/address[2]" />
+
     <xml-path name="addresses/address[2]/street" />
 
</xml-element>
 
</xml-element>
 
</source>
 
</source>
Line 77: Line 85:
 
   
 
   
 
public class Employee {
 
public class Employee {
     @javax.xml.bind.annotation.XmlElementWrapper(name="addresses/address[2]")
+
     @javax.xml.bind.annotation.XmlElement
 +
    @org.eclipse.persistence.oxm.annotations.XmlPath(name="addresses/address[2]/street")*
 
     public String street;
 
     public String street;
 
}
 
}
 
</source>
 
</source>
 +
*Note that the <code>XmlPath</code> annotation does not exist and is intended for example purposes only.
  
 
==== Optional Elements ====
 
==== Optional Elements ====
The following optional elements are applicable to <code>xml-element-wrapper</code>:
+
The following optional elements are applicable to <code>xml-path</code>:
 
*<code>namespace</code>
 
*<code>namespace</code>
*<code>nillable</code>
 
*<code>required</code>
 
 
===== Namespace =====
 
===== Namespace =====
 
If <code>namespace</code> is set, it will be applied to any path element that is not prefixed.  For example, the following:
 
If <code>namespace</code> is set, it will be applied to any path element that is not prefixed.  For example, the following:
Line 100: Line 108:
 
             <java-attributes>
 
             <java-attributes>
 
                 <xml-element java-attribute="firstName">
 
                 <xml-element java-attribute="firstName">
                     <xml-element-wrapper name="prj:info/personal-info/name" namespace="http://www.example.com/employees" />
+
                     <xml-path name="prj:info/personal-info/name/first-name" namespace="http://www.example.com/employees" />
 
                 </xml-element>
 
                 </xml-element>
 
             </java-attributes>
 
             </java-attributes>
Line 119: Line 127:
 
             <java-attributes>
 
             <java-attributes>
 
                 <xml-element java-attribute="firstName">
 
                 <xml-element java-attribute="firstName">
                     <xml-element-wrapper name="prj:info/emp:personal-info/emp:name" />
+
                     <xml-path name="prj:info/emp:personal-info/emp:name/emp:first-name" />
 
                 </xml-element>
 
                 </xml-element>
 
             </java-attributes>
 
             </java-attributes>
Line 125: Line 133:
 
     </java-types>
 
     </java-types>
 
</xml-bindings>
 
</xml-bindings>
</source>
 
 
===== Nillable & Required =====
 
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">
 
<?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>
 
</source>
 
Would result in the following schema:
 
<source lang="xml">
 
<?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>
 
 
</source>
 
</source>
  
 
=== Positional Mappings ===
 
=== Positional Mappings ===
Positional mappings will be supported 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-element java-attribute="streetTwo" name="street[2]" />
+
    <xml-path name="address/street[1]" />
 +
</xml-element>
 +
<xml-element java-attribute="streetTwo">
 +
    <xml-path name="address/street[2]" />
 +
</xml-element>
 
</source>
 
</source>
  
Line 180: Line 151:
  
 
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(name="address/street[1]")*
 
     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(name="address/street[2]")*
 
     public String streetTwo;
 
     public String streetTwo;
 
}
 
}
 
</source>
 
</source>
 +
*Note that the <code>XmlPath</code> annotation does not exist and is intended for example purposes only.
  
 
=== Read only ===
 
=== Read only ===
Line 243: Line 217:
  
 
=== Default Null Value ===
 
=== Default Null Value ===
To support default null value configuration, the following global element will be added:
+
Default null value will be supported via <code>defaultValue</code> on <code>xml-element</code>.  In addition, our XmlCustomizer support could be utilized to set a default value on the mapping.
<source lang="xml">
+
<xs:element name="xml-null-value" type="xs:anySimpleType" />
+
</source>
+
An example of setting the null value in XML metadata would be:
+
<source lang="xml">
+
<xml-element java-attribute="projectId" name="project-id">
+
    <xml-null-value xsi:type="xs:int">-1</xml-null-value>
+
</xml-element>
+
</source>
+
The equivalent configured via annotations would look like:
+
<source lang="java">
+
package org.example;
+
   
+
public class Employee {
+
    @javax.xml.bind.annotation.XmlElement(name="project-id")
+
    @org.eclipse.persistence.oxm.annotations.XmlNullValue(type="int", value=-1)*
+
    public int projectId;
+
}
+
</source>
+
*Note that the <code>XmlNullValue</code> annotation does not exist and is intended for example purposes only.
+
  
 
=== Null Policy ===
 
=== Null Policy ===
Line 349: Line 303:
 
| 1
 
| 1
 
| D.McCann
 
| D.McCann
| How do we support path-based mappings, positional mappings, and other mapping settings that cannot be configured w/o improper use of the standard JAXB annotations?
+
| 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>?
 
|}
 
|}
  
Line 368: Line 322:
 
| 2
 
| 2
 
| Path-based and positional mapping support
 
| 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 was 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
+
| 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
 
| 3
 
| Default null value
 
| Default null value
| No need to support this now as xml-element already has the concept of default-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
 
| 4

Revision as of 06:25, 3 March 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


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 defaultValue 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?

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