Skip to main content

Notice: This Wiki is now read only and edits are no longer 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/XMLDirectMapping"

(Open Issues)
(Deployment XML)
 
(86 intermediate revisions by the same user not shown)
Line 3: Line 3:
  
 
== Requirements ==
 
== Requirements ==
Provide support for XML direct mappings.
+
Provide support for XML direct mapping configuration via XML metadata file.
  
 
The following structures are to be extended to support XML direct mapping configuration:
 
The following structures are to be extended to support XML direct mapping configuration:
 
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/277920/Phase3#xml-attribute <code>xml-attribute</code>]
 
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/277920/Phase3#xml-attribute <code>xml-attribute</code>]
 
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/277920/Phase3#xml-element <code>xml-element</code>]
 
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/277920/Phase3#xml-element <code>xml-element</code>]
 +
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/277920/Phase4#xml-value <code>xml-value</code>]
  
 
Path-based mappings must be supported.  Design notes are located [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/PathBasedMappings here].
 
  
 
The following should be configurable:
 
The following should be configurable:
* Converter
+
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/XMLDirectMapping#Path-based_mapping_support Path-based mappings]
* Get/set method names
+
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/XMLDirectMapping#Positional_Mappings Positional Mappings]
* Read only (boolean)
+
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/XMLDirectMapping#Read_Only Read only]
* Null policy
+
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/XMLDirectMapping#Write_Only Write only]
* Default null value
+
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/XMLDirectMapping#CDATA CDATA]
* CDATA (boolean)
+
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/XMLDirectMapping#Null_Poilcy Null policy]
 +
* [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/XMLDirectMapping#Get.2FSet_Method_Names Get/set method names]
  
 
== Design ==
 
== Design ==
 
=== Basic XML direct mapping support ===
 
=== Basic XML direct mapping support ===
We will use the <code>xml-attribute</code> and <code>xml-element</code> structures to support direct mappings.  For example, the following XML metadata snippet would be used to setup a direct mapping for an <code>empId</code> attribute:
+
We will use the <code>xml-attribute</code>, <code>xml-element</code> and <code>xml-value</code> structures to support direct mappings.  For example, the following XML metadata snippet would be used to setup a direct mapping for an <code>empId</code> attribute:
 
<source lang="xml">
 
<source lang="xml">
 
<xml-attribute java-attribute="empId" />
 
<xml-attribute java-attribute="empId" />
Line 34: Line 34:
 
<xml-element java-attribute="empId" name="id" />
 
<xml-element java-attribute="empId" name="id" />
 
</source>
 
</source>
 
+
The same example mapped to a simple type:
=== Path-based mapping support ===
+
==== Basic configuration ====
+
We will support path-based mappings by making use of the <code>xml-element-wrapper</code> structure.  The 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> will be removed.  The 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>:
+
 
<source lang="xml">
 
<source lang="xml">
<xml-element java-attribute="firstName" name="first-name">
+
<xml-value java-attribute="empId" />
    <xml-element-wrapper name="personal-info/name" />
+
</xml-element>
+
 
</source>
 
</source>
  
==== Positional Paths ====
+
=== Path-based mapping support ===
Positional paths will be supported.  For example, the following would be used to create a mapping to <code>street</code> in the second occurrence of <code>address</code>:
+
We will support path-based mappings on <code>xml-attribute</code> and <code>xml-element</code> 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. Path-based mappings will not apply to <code>xml-value</code>.  An example of configuring a path-based XML direct mapping can be found [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/XMLDirectMapping#org.2Fexample.2Feclipselink-oxm.xml below], and additional information/examples [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/MOXyExtensions#Basic_configuration here].
<source lang="xml">
+
<xml-element java-attribute="street">
+
    <xml-element-wrapper name="addresses/address[2]" />
+
</xml-element>
+
</source>
+
Or:
+
<source lang="xml">
+
<xml-element java-attribute="street">
+
    <xml-element-wrapper name="addresses/address.2" />
+
</xml-element>
+
</source>
+
  
==== Optional Elements ====
+
=== Positional Mappings ===
The following optional elements are applicable to <code>xml-element-wrapper</code>:
+
Positional mappings will be supported on <code>xml-element</code>.  An example of configuring a positional XML direct mapping can be found [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/XMLDirectMapping#org.2Fexample.2Feclipselink-oxm.xml below] and additional information/examples [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/MOXyExtensions#Positional_Mappings here]. Note that positional mappings cannot be applied to <code>xml-attribute</code> or <code>xml-value</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 prefixedFor example, the following:
+
<source lang="xml">
+
<?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>
+
</source>
+
Would be equivalent to:
+
<source lang="xml">
+
<?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>
+
</source>
+
  
===== Nillable & Required =====
+
=== Read Only ===
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:
+
Read only will be supported via boolean attribute on <code>xml-attribute</code>, <code>xml-element</code> and <code>xml-value</code>.  An example of configuring a read only XML direct mapping can be found [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/XMLDirectMapping#org.2Fexample.2Feclipselink-oxm.xml below] and [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/MOXyExtensions#Read_only here].
<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>
+
  
=== Read only ===
+
=== Write Only ===
Read only will be supported via boolean attribute on <code>xml-attribute</code> and <code>xml-element</code>, i.e.:
+
Write only will be supported via boolean attribute on <code>xml-attribute</code>, <code>xml-element</code> and <code>xml-value</code>.  An example of configuring a write only XML direct mapping can be found [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/XMLDirectMapping#org.2Fexample.2Feclipselink-oxm.xml below] and [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/MOXyExtensions#Write_only here].
<source lang="xml">
+
<xml-attribute java-attribute="salary" read-only="true" />
+
</source>
+
  
 
=== CDATA ===
 
=== CDATA ===
CDATA will be supported via boolean attribute on <code>xml-attribute</code> and <code>xml-element</code>, i.e.:
+
CDATA will be supported via boolean attribute on <code>xml-element</code> and <code>xml-value</code>. An example of configuring a XML direct mapping as CDATA can be found [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/XMLDirectMapping#org.2Fexample.2Feclipselink-oxm.xml below] and [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/MOXyExtensions#CDATA here].  Note that CDATA cannot be applied to <code>xml-attribute</code>.
<source lang="xml">
+
<xml-element java-attribute="characterData" cdata="true" />
+
</source>
+
  
== Example ==
+
=== Null Poilcy ===
The following example will demonstrate how to configure XML direct mappings via XML metadata.
+
Null policy will be supported via sub-element on <code>xml-attribute</code>, <code>xml-element</code> and <code>xml-value</code>.  The proposed schema modifications for the global null policy elements/complex types can be found [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/MOXyExtensions#Null_Policy here].  An example of configuring a null policy on an XML direct mapping can be found [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/XMLDirectMapping#org.2Fexample.2Feclipselink-oxm.xml below].
 +
 
 +
=== 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.  An example of configuring the accessor methods on a XML direct mapping can be found [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/XMLDirectMapping#org.2Fexample.2Feclipselink-oxm.xml below], and additional examples and proposed schema changes can be found [http://wiki.eclipse.org/EclipseLink/DesignDocs/293925/MOXyExtensions#Get.2FSet_Method_Names here].
 +
 
 +
== Example:  <code>xml-attribute</code> & <code>xml-element</code> ==
 +
The following example will demonstrate how to configure XML direct mappings via XML metadata by using <code>xml-attribute</code> & <code>xml-element</code>.
  
 
=== org.example.Employee.java  ===
 
=== org.example.Employee.java  ===
Line 165: Line 69:
 
public class Employee {
 
public class Employee {
 
     public int empId;
 
     public int empId;
 +
    public int projectId;
 
     public String firstName;
 
     public String firstName;
 
     public String lastName;
 
     public String lastName;
 
     public String projectName;
 
     public String projectName;
 +
    public String data1;
 +
    public String data2;
 +
    public double salary;
 +
    public String privateData;
 +
    public String characterData;
 +
    public String someString;
 +
    public String aString;
 +
 +
    @javax.xml.bind.annotation.XmlTransient
 +
    public boolean isSomeStringSet;
 +
 +
    String getProject() {
 +
        return projectName;
 +
    }
 +
   
 +
    void setProject(String name) {
 +
        projectName = name;
 +
    }
 +
 +
    String getSomeString() {
 +
        return someString;
 +
    }
 +
   
 +
    void setSomeString(String str) {
 +
        someString = str;
 +
    }
 +
   
 +
    public boolean isSetSomeString(Boolean ignoredParam) {
 +
        return isSomeStringSet;
 +
    }
 +
   
 +
    String getAString() {
 +
        return aString;
 +
    }
 +
   
 +
    void setAString(String str) {
 +
        aString = str;
 +
    }
 
}
 
}
</source>  
+
</source>
  
 
=== Deployment XML  ===
 
=== Deployment XML  ===
Line 182: Line 125:
 
         <attribute-mapping xsi:type="xml-direct-mapping">
 
         <attribute-mapping xsi:type="xml-direct-mapping">
 
           <attribute-name>firstName</attribute-name>
 
           <attribute-name>firstName</attribute-name>
           <field name="personal-info/first-name/text()" xsi:type="node"/>
+
           <field name="info/personal-info/first-name/text()" xsi:type="node"/>
 
         </attribute-mapping>
 
         </attribute-mapping>
 
         <attribute-mapping xsi:type="xml-direct-mapping">
 
         <attribute-mapping xsi:type="xml-direct-mapping">
 
           <attribute-name>lastName</attribute-name>
 
           <attribute-name>lastName</attribute-name>
           <field name="personal-info/last-name/text()" xsi:type="node"/>
+
           <field name="info/personal-info/last-name/text()" xsi:type="node"/>
 
         </attribute-mapping>
 
         </attribute-mapping>
 
         <attribute-mapping xsi:type="xml-direct-mapping">
 
         <attribute-mapping xsi:type="xml-direct-mapping">
 
             <attribute-name>mgrId</attribute-name>
 
             <attribute-name>mgrId</attribute-name>
             <field name="projects/prj:project/@managerId" xsi:type="node"/>
+
             <field name="projects/prj:project/@prj:managerId" xsi:type="node"/>
 
         </attribute-mapping>
 
         </attribute-mapping>
 
         <attribute-mapping xsi:type="xml-direct-mapping">
 
         <attribute-mapping xsi:type="xml-direct-mapping">
 
           <attribute-name>projectName</attribute-name>
 
           <attribute-name>projectName</attribute-name>
 +
          <get-method>getProject</get-method>
 +
          <set-method>setProject</set-method>
 
           <field name="projects/prj:project/text()" xsi:type="node"/>
 
           <field name="projects/prj:project/text()" xsi:type="node"/>
 +
        </attribute-mapping>
 +
        <attribute-mapping xsi:type="xml-direct-mapping">
 +
            <attribute-name>data1</attribute-name>
 +
            <field name="pieces-of-data/data[1]/text()" xsi:type="node"/>
 +
        </attribute-mapping>
 +
        <attribute-mapping xsi:type="xml-direct-mapping">
 +
            <attribute-name>data2</attribute-name>
 +
            <field name="pieces-of-data/data[2]/text()" xsi:type="node"/>
 +
        </attribute-mapping>
 +
        <attribute-mapping xsi:type="xml-direct-mapping">
 +
            <attribute-name>salary</attribute-name>
 +
            <read-only>true</read-only>
 +
            <field name="@salary" xsi:type="node"/>
 +
        </attribute-mapping>
 +
        <attribute-mapping xsi:type="xml-direct-mapping">
 +
            <attribute-name>privateData</attribute-name>
 +
            <field name="private-data/text()" xsi:type="node"/>
 +
        </attribute-mapping>
 +
        <attribute-mapping xsi:type="xml-direct-mapping">
 +
            <attribute-name>characterData</attribute-name>
 +
            <field name="character-data/text()" xsi:type="node"/>
 +
            <is-cdata>true</is-cdata>
 +
        </attribute-mapping>
 +
        <attribute-mapping xsi:type="xml-direct-mapping">
 +
            <attribute-name>projectId</attribute-name>
 +
            <field name="project-id/text()" xsi:type="node"/>
 +
            <null-value xsi:type="xsd:int">-1</null-value>
 +
        </attribute-mapping>
 +
        <attribute-mapping xsi:type="xml-direct-mapping">
 +
            <attribute-name>someString</attribute-name>
 +
            <get-method>getSomeString</get-method>
 +
            <set-method>setSomeString</set-method>
 +
            <field name="some-string/text()" xsi:type="node"/>
 +
            <null-policy xsi:type="null-policy">
 +
                <null-representation-for-xml>EMPTY_NODE</null-representation-for-xml>
 +
            </null-policy>
 +
        </attribute-mapping>
 +
        <attribute-mapping xsi:type="xml-direct-mapping">
 +
            <attribute-name>aString</attribute-name>
 +
            <get-method>getAString</get-method>
 +
            <set-method>setAString</set-method>
 +
            <field name="a-string/text()" xsi:type="node"/>
 +
            <null-policy xsi:type="null-policy">
 +
                <empty-node-represents-null>true</empty-node-represents-null>
 +
                <null-representation-for-xml>ABSENT_NODE</null-representation-for-xml>
 +
            </null-policy>
 
         </attribute-mapping>
 
         </attribute-mapping>
 
     <attribute-mappings>
 
     <attribute-mappings>
Line 207: Line 198:
 
             </namespace>
 
             </namespace>
 
         </namespaces>
 
         </namespaces>
        <default-namespace-uri>http://www.example.com/employees</default-namespace-uri>
 
 
     </namespace-resolver>
 
     </namespace-resolver>
 
</class-mapping-descriptor>
 
</class-mapping-descriptor>
 
</source>
 
</source>
  
=== XML Instance Document ===
+
=== XML Instance Document (read) ===
 
<source lang="xml">
 
<source lang="xml">
 
<?xml version="1.0" encoding="UTF-8"?>
 
<?xml version="1.0" encoding="UTF-8"?>
<employee id="66" xmlns="http://www.example.com/employees" xmlns:prj="http://www.example.com/projects">
+
<ns0:employee id="66" salary="123456.78" xmlns:ns0="http://www.example.com/employees" xmlns:prj="http://www.example.com/projects" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <personal-info>
+
        <first-name>Joe</first-name>
+
        <last-name>Black</last-name>
+
    </personal-info>
+
 
     <projects>
 
     <projects>
         <prj:project managerId="99">XML External Metadata Support</prj:project>
+
         <prj:project prj:managerId="99">XML External Metadata Support</prj:project>
 
     </projects>
 
     </projects>
</employee>
+
    <info>
 +
        <personal-info>
 +
            <first-name>Joe</first-name>
 +
            <last-name>Oracle</last-name>
 +
        </personal-info>
 +
    </info>
 +
    <project-id/>
 +
    <pieces-of-data>
 +
        <data>data one</data>
 +
        <data>data two</data>
 +
        <data>data three</data>
 +
    </pieces-of-data>
 +
    <private-data>This is some private data</private-data>
 +
    <character-data><![CDATA[<characters>a b c d e f g</characters>]]></character-data>
 +
    <some-string />
 +
</ns0:employee>
 +
</source>
 +
 
 +
=== XML Instance Document (write) ===
 +
<source lang="xml">
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<ns0:employee id="66" xmlns:ns0="http://www.example.com/employees" xmlns:prj="http://www.example.com/projects" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 +
    <projects>
 +
        <prj:project prj:managerId="99">XML External Metadata Support</prj:project>
 +
    </projects>
 +
    <project-id>999</project-id>
 +
    <info>
 +
        <personal-info>
 +
            <first-name>Joe</first-name>
 +
            <last-name>Oracle</last-name>
 +
        </personal-info>
 +
    </info>
 +
    <pieces-of-data>
 +
        <data>data one</data>
 +
        <data>data two</data>
 +
    </pieces-of-data>
 +
    <private-data>This is some private data</private-data>
 +
    <character-data><![CDATA[<characters>a b c d e f g</characters>]]></character-data>
 +
    <some-string xsi:nil="true" />
 +
    <a-string/>
 +
</ns0:employee>
 
</source>
 
</source>
  
Line 230: Line 256:
 
<source lang="xml">
 
<source lang="xml">
 
<?xml version="1.0" encoding="US-ASCII"?>
 
<?xml version="1.0" encoding="US-ASCII"?>
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm">
+
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
 +
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 +
  xmlns:xs="http://www.w3.org/2001/XMLSchema">
 
     <xml-schema namespace="http://www.example.com/employees">
 
     <xml-schema namespace="http://www.example.com/employees">
 
         <xml-ns namespace-uri="http://www.example.com/projects" prefix="prj"/>
 
         <xml-ns namespace-uri="http://www.example.com/projects" prefix="prj"/>
 
     </xml-schema>
 
     </xml-schema>
 
     <java-types>
 
     <java-types>
         <java-type name="org.example.Employee">
+
         <java-type name="org.example.Employee" xml-accessor-type="FIELD">
 
             <xml-root-element name="employee" />
 
             <xml-root-element name="employee" />
 
             <java-attributes>
 
             <java-attributes>
                 <xml-attribute java-attribute="empId" name="id" />
+
                 <xml-attribute java-attribute="empId" xml-path="@id" />
                 <xml-element java-attribute="firstName" name="first-name">
+
                <xml-attribute java-attribute="salary" read-only="true" />
                    <xml-element-wrapper name="personal-info" />
+
                <xml-attribute java-attribute="mgrId" xml-path="projects/prj:project/@prj:managerId" />
 +
                 <xml-element java-attribute="firstName" xml-path="info/personal-info/first-name/text()" />
 +
                <xml-element java-attribute="lastName" xml-path="info/personal-info/last-name/text()" />
 +
                <xml-element java-attribute="data2" xml-path="pieces-of-data/data[2]/text()" />
 +
                <xml-element java-attribute="data1" xml-path="pieces-of-data/data[1]/text()" />
 +
                <xml-element java-attribute="privateData" name="private-data" write-only="true" />
 +
                <xml-element java-attribute="characterData" name="character-data" cdata="true" />
 +
                <xml-element java-attribute="projectId" name="project-id" default-value="-1" />
 +
                <xml-element java-attribute="projectName" xml-path="projects/prj:project/text()">
 +
                    <xml-access-methods get-method="getProject" set-method="setProject" />
 
                 </xml-element>
 
                 </xml-element>
                 <xml-element java-attribute="lastName" name="last-name" >
+
                 <xml-element java-attribute="someString" name="some-string">
                     <xml-element-wrapper name="personal-info" />
+
                     <xml-access-methods get-method="getSomeString" set-method="setSomeString" />
 +
                    <xml-is-set-null-policy xsi-nil-represents-null="true" null-representation-for-xml="XSI_NIL" is-set-method-name="isSetSomeString">
 +
                        <is-set-parameter value="false" type="java.lang.Boolean" />
 +
                    </xml-is-set-null-policy>
 
                 </xml-element>
 
                 </xml-element>
                 <xml-attribute java-attribute="mgrId" name="managerId" >
+
                 <xml-element java-attribute="aString" name="a-string">
                     <xml-element-wrapper name="projects/prj:project" />
+
                     <xml-access-methods get-method="getAString" set-method="setAString" />
                </xml-attribute>
+
                     <xml-null-policy null-representation-for-xml="EMPTY_NODE" />
                <xml-element java-attribute="projectName" name="project" namespace="http://www.example.com/projects" >
+
                     <xml-element-wrapper name="projects" />
+
 
                 </xml-element>
 
                 </xml-element>
 +
            </java-attributes>
 +
        </java-type>
 +
    </java-types>
 +
</xml-bindings>
 +
</source>
 +
 +
== Example:  <code>xml-value</code> ==
 +
The following example will demonstrate how to configure XML direct mappings via XML metadata by using <code>xml-value</code>.
 +
 +
=== org.example.Price.java  ===
 +
<source lang="java">
 +
package org.example;
 +
 +
public class Price {
 +
    public java.math.BigDecimal price;
 +
    public String currency;
 +
 +
    java.math.BigDecimal getPrice() {
 +
        return price;
 +
    }
 +
   
 +
    void setPrice(java.math.BigDecimal price) {
 +
        this.price = price;
 +
    }
 +
}
 +
</source>
 +
 +
=== Deployment XML  ===
 +
<source lang="xml">
 +
<class-mapping-descriptor xsi:type="xml-class-mapping-descriptor">
 +
    <class>org.example.Price</class>
 +
    <alias>Price</alias>
 +
    <attribute-mappings>
 +
        <attribute-mapping xsi:type="xml-direct-mapping">
 +
            <attribute-name>price</attribute-name>
 +
            <read-only>true</read-only>
 +
            <set-method>setPrice</set-method>
 +
            <field name="price-data/text()" xsi:type="node"/>
 +
        </attribute-mapping>
 +
        <attribute-mapping xsi:type="xml-direct-mapping">
 +
            <attribute-name>currency</attribute-name>
 +
            <field name="@currency" xsi:type="node"/>
 +
        </attribute-mapping>
 +
    </attribute-mappings>
 +
    <descriptor-type>aggregate</descriptor-type>
 +
    <default-root-element>price-data</default-root-element>
 +
    <default-root-element-field name="price-data"/>
 +
</class-mapping-descriptor>
 +
</source>
 +
 +
=== XML Instance Document (read) ===
 +
<source lang="xml">
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<price-data currency="CAD">123.4560000000000030695446184836328029632568359375</price-data>
 +
</source>
 +
 +
=== XML Instance Document (write) ===
 +
<source lang="xml">
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<price-data currency="CAD"/>
 +
</source>
 +
 +
=== org/example/eclipselink-oxm.xml ===
 +
This XML file demonstrates configuring XML direct mappings on the "org.example.Price" class.
 +
<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.Price" xml-accessor-type="FIELD">
 +
            <xml-root-element name="price-data" />
 +
            <java-attributes>
 +
                <xml-value java-attribute="price" read-only="true">
 +
                    <xml-access-methods get-method="getPrice" set-method="setPrice" />
 +
                </xml-value>
 +
                <xml-attribute java-attribute="currency" />
 
             </java-attributes>
 
             </java-attributes>
 
         </java-type>
 
         </java-type>
Line 267: Line 380:
 
! Description/Notes
 
! Description/Notes
 
|-
 
|-
| 1
+
|  
| D.McCann
+
|  
| Two possible ways to allow a path-based mapping to be configured are being considered:  <code>xml-attribute/xml-element</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].
+
|  
|-
+
| 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?
+
 
|}
 
|}
  
Line 302: Line 395:
 
! Decision
 
! Decision
 
|-
 
|-
| 1
+
|  
| Two possible ways to allow a path-based mapping to be configured are being considered: <code>xml-attribute/xml-element</code> or <code>xml-element-wrapper</code>
+
|  
| <code>xml-element-wrapper</code> will be extended to handle multi-level paths, and enabled for use with <code>xml-attribute</code> and single-valued properties.
+
|  
|-
+
| 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>
+
| <code>name</code> will be overloaded.
+
|-
+
| 3
+
| What is the expected behavior when <code>namespace</code> is set on an <code>xml-element-wrapper</code> that has a path set?
+
| If <code>namespace</code> is set, it will be applied to any path element that is not prefixed.
+
|-
+
| 4
+
| What is the expected behavior when <code>required</code> is set on an <code>xml-element-wrapper</code> that has a path set?
+
| If <code>required</code> is set, it will be applied to the last element in the path.
+
|-
+
| 5
+
| What is the expected behavior when <code>nillable</code> is set on an <code>xml-element-wrapper</code> that has a path set?
+
| If <code>nillable</code> is set, it will be applied to the last element in the path.
+
 
|}
 
|}
  
Line 326: Line 403:
  
 
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.
 

Latest revision as of 14:39, 2 June 2010

XMLDirectMapping

Requirements

Provide support for XML direct mapping configuration via XML metadata file.

The following structures are to be extended to support XML direct mapping configuration:


The following should be configurable:

Design

Basic XML direct mapping support

We will use the xml-attribute, xml-element and xml-value structures to support direct mappings. For example, the following XML metadata snippet would be used to setup a direct mapping for an empId attribute:

<xml-attribute java-attribute="empId" />

If empId was to be mapped to id, then the following would be used:

<xml-attribute java-attribute="empId" name="id" />

The same example mapped to an id element:

<xml-element java-attribute="empId" name="id" />

The same example mapped to a simple type:

<xml-value java-attribute="empId" />

Path-based mapping support

We will support path-based mappings on xml-attribute and xml-element 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. Path-based mappings will not apply to xml-value. An example of configuring a path-based XML direct mapping can be found below, and additional information/examples here.

Positional Mappings

Positional mappings will be supported on xml-element. An example of configuring a positional XML direct mapping can be found below and additional information/examples here. 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. An example of configuring a read only XML direct mapping can be found below and here.

Write Only

Write only will be supported via boolean attribute on xml-attribute, xml-element and xml-value. An example of configuring a write only XML direct mapping can be found below and here.

CDATA

CDATA will be supported via boolean attribute on xml-element and xml-value. An example of configuring a XML direct mapping as CDATA can be found below and here. Note that CDATA cannot be applied to xml-attribute.

Null Poilcy

Null policy will be supported via sub-element on xml-attribute, xml-element and xml-value. The proposed schema modifications for the global null policy elements/complex types can be found here. An example of configuring a null policy on an XML direct mapping can be found below.

Get/Set Method Names

The get/set method names on xml-attribute, xml-element and xml-value will be configurable via sub-element. An example of configuring the accessor methods on a XML direct mapping can be found below, and additional examples and proposed schema changes can be found here.

Example: xml-attribute & xml-element

The following example will demonstrate how to configure XML direct mappings via XML metadata by using xml-attribute & xml-element.

org.example.Employee.java

package org.example;
 
public class Employee {
    public int empId;
    public int projectId;
    public String firstName;
    public String lastName;
    public String projectName;
    public String data1;
    public String data2;
    public double salary;
    public String privateData;
    public String characterData; 
    public String someString;
    public String aString;
 
    @javax.xml.bind.annotation.XmlTransient
    public boolean isSomeStringSet;
 
    String getProject() {
        return projectName; 
    }
 
    void setProject(String name) {
        projectName = name;
    }
 
    String getSomeString() { 
        return someString; 
    }
 
    void setSomeString(String str) {
        someString = str; 
    }
 
    public boolean isSetSomeString(Boolean ignoredParam) {
        return isSomeStringSet;
    }
 
    String getAString() { 
        return aString; 
    }
 
    void setAString(String str) {
        aString = str; 
    }
}

Deployment XML

<class-mapping-descriptor xsi:type="xml-class-mapping-descriptor">
    <alias>Employee</alias>
    <attribute-mappings>
        <attribute-mapping xsi:type="xml-direct-mapping">
           <attribute-name>empId</attribute-name>
           <field name="@id" xsi:type="node"/>
        </attribute-mapping>
        <attribute-mapping xsi:type="xml-direct-mapping">
           <attribute-name>firstName</attribute-name>
           <field name="info/personal-info/first-name/text()" xsi:type="node"/>
        </attribute-mapping>
        <attribute-mapping xsi:type="xml-direct-mapping">
           <attribute-name>lastName</attribute-name>
           <field name="info/personal-info/last-name/text()" xsi:type="node"/>
        </attribute-mapping>
        <attribute-mapping xsi:type="xml-direct-mapping">
            <attribute-name>mgrId</attribute-name>
            <field name="projects/prj:project/@prj:managerId" xsi:type="node"/>
        </attribute-mapping>
        <attribute-mapping xsi:type="xml-direct-mapping">
           <attribute-name>projectName</attribute-name>
           <get-method>getProject</get-method>
           <set-method>setProject</set-method>
           <field name="projects/prj:project/text()" xsi:type="node"/>
        </attribute-mapping>
        <attribute-mapping xsi:type="xml-direct-mapping">
            <attribute-name>data1</attribute-name>
            <field name="pieces-of-data/data[1]/text()" xsi:type="node"/>
        </attribute-mapping>
        <attribute-mapping xsi:type="xml-direct-mapping">
            <attribute-name>data2</attribute-name>
            <field name="pieces-of-data/data[2]/text()" xsi:type="node"/>
        </attribute-mapping>
        <attribute-mapping xsi:type="xml-direct-mapping">
            <attribute-name>salary</attribute-name>
            <read-only>true</read-only>
            <field name="@salary" xsi:type="node"/>
        </attribute-mapping>
        <attribute-mapping xsi:type="xml-direct-mapping">
            <attribute-name>privateData</attribute-name>
            <field name="private-data/text()" xsi:type="node"/>
        </attribute-mapping>
        <attribute-mapping xsi:type="xml-direct-mapping">
            <attribute-name>characterData</attribute-name>
            <field name="character-data/text()" xsi:type="node"/>
            <is-cdata>true</is-cdata>
        </attribute-mapping>
        <attribute-mapping xsi:type="xml-direct-mapping">
            <attribute-name>projectId</attribute-name>
            <field name="project-id/text()" xsi:type="node"/>
            <null-value xsi:type="xsd:int">-1</null-value>
        </attribute-mapping>
        <attribute-mapping xsi:type="xml-direct-mapping">
            <attribute-name>someString</attribute-name>
            <get-method>getSomeString</get-method>
            <set-method>setSomeString</set-method>
            <field name="some-string/text()" xsi:type="node"/>
            <null-policy xsi:type="null-policy">
                <null-representation-for-xml>EMPTY_NODE</null-representation-for-xml>
            </null-policy>
        </attribute-mapping>
        <attribute-mapping xsi:type="xml-direct-mapping">
            <attribute-name>aString</attribute-name>
            <get-method>getAString</get-method>
            <set-method>setAString</set-method>
            <field name="a-string/text()" xsi:type="node"/>
            <null-policy xsi:type="null-policy">
                <empty-node-represents-null>true</empty-node-represents-null>
                <null-representation-for-xml>ABSENT_NODE</null-representation-for-xml>
            </null-policy>
        </attribute-mapping>
    <attribute-mappings>
    <descriptor-type>aggregate</descriptor-type>
    <default-root-element>employee</default-root-element>
    <default-root-element-field name="employee" xsi:type="node"/>
    <namespace-resolver>
        <namespaces>
            <namespace>
                <prefix>prj</prefix>
                <namespace-uri>http://www.example.com/projects</namespace-uri>
            </namespace>
        </namespaces>
    </namespace-resolver>
</class-mapping-descriptor>

XML Instance Document (read)

<?xml version="1.0" encoding="UTF-8"?>
<ns0:employee id="66" salary="123456.78" xmlns:ns0="http://www.example.com/employees" xmlns:prj="http://www.example.com/projects" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <projects>
        <prj:project prj:managerId="99">XML External Metadata Support</prj:project>
    </projects>
    <info>
        <personal-info>
            <first-name>Joe</first-name>
            <last-name>Oracle</last-name>
        </personal-info>
    </info>
    <project-id/>
    <pieces-of-data>
        <data>data one</data>
        <data>data two</data>
        <data>data three</data>
    </pieces-of-data>
    <private-data>This is some private data</private-data>
    <character-data><![CDATA[<characters>a b c d e f g</characters>]]></character-data>
    <some-string />
</ns0:employee>

XML Instance Document (write)

<?xml version="1.0" encoding="UTF-8"?>
<ns0:employee id="66" xmlns:ns0="http://www.example.com/employees" xmlns:prj="http://www.example.com/projects" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <projects>
        <prj:project prj:managerId="99">XML External Metadata Support</prj:project>
    </projects>
    <project-id>999</project-id>
    <info>
        <personal-info>
            <first-name>Joe</first-name>
            <last-name>Oracle</last-name>
        </personal-info>
    </info>
    <pieces-of-data>
        <data>data one</data>
        <data>data two</data>
    </pieces-of-data>
    <private-data>This is some private data</private-data>
    <character-data><![CDATA[<characters>a b c d e f g</characters>]]></character-data>
    <some-string xsi:nil="true" />
    <a-string/>
</ns0:employee>

org/example/eclipselink-oxm.xml

This XML file demonstrates configuring XML direct mappings on the "org.example.Employee" class.

<?xml version="1.0" encoding="US-ASCII"?>
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xml-schema namespace="http://www.example.com/employees">
        <xml-ns namespace-uri="http://www.example.com/projects" prefix="prj"/>
    </xml-schema>
    <java-types>
        <java-type name="org.example.Employee" xml-accessor-type="FIELD">
            <xml-root-element name="employee" />
            <java-attributes>
                <xml-attribute java-attribute="empId" xml-path="@id" />
                <xml-attribute java-attribute="salary" read-only="true" />
                <xml-attribute java-attribute="mgrId" xml-path="projects/prj:project/@prj:managerId" />
                <xml-element java-attribute="firstName" xml-path="info/personal-info/first-name/text()" />
                <xml-element java-attribute="lastName" xml-path="info/personal-info/last-name/text()" />
                <xml-element java-attribute="data2" xml-path="pieces-of-data/data[2]/text()" />
                <xml-element java-attribute="data1" xml-path="pieces-of-data/data[1]/text()" />
                <xml-element java-attribute="privateData" name="private-data" write-only="true" />
                <xml-element java-attribute="characterData" name="character-data" cdata="true" />
                <xml-element java-attribute="projectId" name="project-id" default-value="-1" />
                <xml-element java-attribute="projectName" xml-path="projects/prj:project/text()">
                    <xml-access-methods get-method="getProject" set-method="setProject" />
                </xml-element>
                <xml-element java-attribute="someString" name="some-string">
                    <xml-access-methods get-method="getSomeString" set-method="setSomeString" />
                    <xml-is-set-null-policy xsi-nil-represents-null="true" null-representation-for-xml="XSI_NIL" is-set-method-name="isSetSomeString">
                        <is-set-parameter value="false" type="java.lang.Boolean" />
                    </xml-is-set-null-policy>
                </xml-element>
                <xml-element java-attribute="aString" name="a-string">
                    <xml-access-methods get-method="getAString" set-method="setAString" />
                    <xml-null-policy null-representation-for-xml="EMPTY_NODE" />
                </xml-element>
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

Example: xml-value

The following example will demonstrate how to configure XML direct mappings via XML metadata by using xml-value.

org.example.Price.java

package org.example;
 
public class Price {
    public java.math.BigDecimal price;
    public String currency;
 
    java.math.BigDecimal getPrice() { 
        return price; 
    }
 
    void setPrice(java.math.BigDecimal price) {
        this.price = price; 
    }
}

Deployment XML

<class-mapping-descriptor xsi:type="xml-class-mapping-descriptor">
    <class>org.example.Price</class>
    <alias>Price</alias>
    <attribute-mappings>
        <attribute-mapping xsi:type="xml-direct-mapping">
            <attribute-name>price</attribute-name>
            <read-only>true</read-only>
            <set-method>setPrice</set-method>
            <field name="price-data/text()" xsi:type="node"/>
        </attribute-mapping>
        <attribute-mapping xsi:type="xml-direct-mapping">
            <attribute-name>currency</attribute-name>
            <field name="@currency" xsi:type="node"/>
        </attribute-mapping>
    </attribute-mappings>
    <descriptor-type>aggregate</descriptor-type>
    <default-root-element>price-data</default-root-element>
    <default-root-element-field name="price-data"/>
</class-mapping-descriptor>

XML Instance Document (read)

<?xml version="1.0" encoding="UTF-8"?>
<price-data currency="CAD">123.4560000000000030695446184836328029632568359375</price-data>

XML Instance Document (write)

<?xml version="1.0" encoding="UTF-8"?>
<price-data currency="CAD"/>

org/example/eclipselink-oxm.xml

This XML file demonstrates configuring XML direct mappings on the "org.example.Price" class.

<?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.Price" xml-accessor-type="FIELD">
            <xml-root-element name="price-data" />
            <java-attributes>
                <xml-value java-attribute="price" read-only="true">
                    <xml-access-methods get-method="getPrice" set-method="setPrice" />
                </xml-value>
                <xml-attribute java-attribute="currency" />
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

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

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

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.

Back to the top