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/317962/Phase3"

(Purpose)
(Example)
 
(86 intermediate revisions by the same user not shown)
Line 50: Line 50:
 
| align="center" | X  
 
| align="center" | X  
 
|-
 
|-
| N/A
+
|  
| XmlAfterUnmarshal
+
| XmlKey
| xml-after-unmarshal
+
| xml-key
 
| align="center" |  
 
| align="center" |  
 
| align="center" |  
 
| align="center" |  
| align="center" |
+
| align="center" | X
| align="center" |
+
| align="center" | X
|-
+
| N/A
+
| XmlBeforeUnmarshal
+
| xml-before-unmarshal
+
| align="center" |
+
| align="center" |
+
| align="center" | 
+
| align="center" | 
+
|-
+
| N/A
+
| XmlAfterMarshal
+
| xml-after-marshal
+
| align="center" |
+
| align="center" |
+
| align="center" | 
+
| align="center" | 
+
|-
+
| N/A
+
| XmlBeforeMarshal
+
| xml-before-marshal
+
| align="center" |
+
| align="center" |
+
| align="center" | 
+
| align="center" | 
+
 
|}
 
|}
  
Line 92: Line 68:
 
package org.eclipse.persistence.oxm.annotations;
 
package org.eclipse.persistence.oxm.annotations;
  
 +
import java.lang.annotation.Retention;
 +
import java.lang.annotation.Target;
 +
import static java.lang.annotation.ElementType.TYPE;
 +
import static java.lang.annotation.RetentionPolicy.RUNTIME;
 +
 +
/**
 +
* The XmlDiscriminatorNode annotation is used to specify the class
 +
* indicator field name when using inheritance.
 +
*/
 
@Target({TYPE})  
 
@Target({TYPE})  
 
@Retention(RUNTIME)
 
@Retention(RUNTIME)
 
public @interface XmlDiscriminatorNode {
 
public @interface XmlDiscriminatorNode {
 +
   
 +
    /**
 +
    * (Required) Indicates the the class indicator field name.
 +
    */
 
     String value();
 
     String value();
 
}
 
}
 
</source>
 
</source>
 +
 
==== XML Metadata ====
 
==== XML Metadata ====
 
===== xml-discriminator-node =====
 
===== xml-discriminator-node =====
The <code>xml-discriminator-node</code> metadata tag will be used to set the class indicator field name when using inheritance.  The value will be in the form of an XPath to an attribute, i.e. <code>@xsi:type</code>.
+
The <code>xml-discriminator-node</code> metadata tag will be used to set the class indicator field name when using inheritance.  The value will be in the form of an XPath to an attribute, i.e. <code>@xsi:type</code>.  If this is present in XML, any value set via annotation will be overwritten.
  
 
eclipselink-oxm.xml snippet
 
eclipselink-oxm.xml snippet
Line 115: Line 105:
 
package org.eclipse.persistence.oxm.annotations;
 
package org.eclipse.persistence.oxm.annotations;
  
 +
import java.lang.annotation.Retention;
 +
import java.lang.annotation.Target;
 +
import static java.lang.annotation.ElementType.TYPE;
 +
import static java.lang.annotation.RetentionPolicy.RUNTIME;
 +
 +
/**
 +
* The XmlDiscriminatorValue annotation is used to specify the class indicator for a
 +
* given type when using inheritance.
 +
*/
 
@Target({TYPE})  
 
@Target({TYPE})  
 
@Retention(RUNTIME)
 
@Retention(RUNTIME)
 
public @interface XmlDiscriminatorValue {
 
public @interface XmlDiscriminatorValue {
 +
    /**
 +
    * (Required) Indicates the class indicator for a given Type.
 +
    */
 
     String value();
 
     String value();
 
}
 
}
 
</source>
 
</source>
 +
 
==== XML Metadata ====
 
==== XML Metadata ====
 
===== xml-discriminator-value =====
 
===== xml-discriminator-value =====
The <code>xml-discriminator-value</code> metadata tag will be used to set a class indicator when using inheritance.
+
The <code>xml-discriminator-value</code> metadata tag will be used to set a class indicator when using inheritance.  If this is present in XML, any value set via annotation will be overwritten.
  
 
eclipselink-oxm.xml snippet
 
eclipselink-oxm.xml snippet
Line 130: Line 133:
 
</source>
 
</source>
  
==== XML Schema  ====
+
=== XML Schema  ===
Following is the proposed XSD change necessary to provide support for inheritance:  
+
Following is the proposed XSD change necessary to provide support for inheritance.  The following attributes will be added to <code>java-type</code>:
 
<source lang="xml">
 
<source lang="xml">
<xs:element name="java-type">
+
<xs:attribute name="xml-discriminator-node" type="xs:string" />
    <xs:complexType>
+
<xs:attribute name="xml-discriminator-value" type="xs:string" />
        <xs:all>
+
            <xs:element ref="xml-type" minOccurs="0"/>
+
            <xs:element ref="xml-root-element" minOccurs="0"/>
+
            <xs:element ref="xml-see-also" minOccurs="0"/>
+
            <xs:element ref="xml-java-type-adapter" minOccurs="0"/>
+
            <xs:element ref="xml-class-extractor" minOccurs="0"/>
+
            <xs:element ref="xml-properties" minOccurs="0" />
+
            <xs:element name="java-attributes" minOccurs="0">
+
                <xs:complexType>
+
                    <xs:sequence>
+
                        <xs:element ref="java-attribute" minOccurs="0" maxOccurs="unbounded" />
+
                    </xs:sequence>
+
                </xs:complexType>
+
            </xs:element>
+
        </xs:all>
+
        <xs:attribute name="name" type="xs:string" />
+
        <xs:attribute name="xml-accessor-order" type="xml-access-order" default="UNDEFINED" />
+
        <xs:attribute name="xml-accessor-type" type="xml-access-type" default="PUBLIC_MEMBER" />
+
        <xs:attribute name="xml-customizer" type="xs:string" />
+
        <xs:attribute name="xml-discriminator-node" type="xs:string" />
+
        <xs:attribute name="xml-discriminator-value" type="xs:string" />
+
        <xs:attribute name="xml-inline-binary-data" type="xs:boolean" default="false" />
+
        <xs:attribute name="xml-transient" type="xs:boolean" default="false" />
+
    </xs:complexType>
+
</xs:element>
+
 
</source>
 
</source>
  
==== Example  ====
+
=== Example  ===
 
The following example will demonstrate how inheritance can be configured.
 
The following example will demonstrate how inheritance can be configured.
  
Line 194: Line 172:
 
import javax.xml.bind.annotation.XmlRootElement;
 
import javax.xml.bind.annotation.XmlRootElement;
  
@XmlRootElement("vehicle-data")
+
@XmlRootElement(name="vehicle-data")
 
@XmlDiscriminatorNode("@vtype")
 
@XmlDiscriminatorNode("@vtype")
 
@XmlDiscriminatorValue("vehicle")
 
@XmlDiscriminatorValue("vehicle")
Line 212: Line 190:
 
import javax.xml.bind.annotation.XmlRootElement;
 
import javax.xml.bind.annotation.XmlRootElement;
  
@XmlRootElement("car-data")
+
@XmlRootElement(name="car-data")
 
@XmlDiscriminatorValue("car")
 
@XmlDiscriminatorValue("car")
class Car {
+
class Car extends Vehicle {
 
     @XmlElement(name="number-of-doors")
 
     @XmlElement(name="number-of-doors")
 
     public int numberOfDoors;
 
     public int numberOfDoors;
Line 220: Line 198:
 
     public int milesPerGallon;
 
     public int milesPerGallon;
 
}
 
}
 +
</source>
 +
 +
Sample Generated Schema
 +
<source lang="xml">
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 +
  <xsd:complexType name="car">
 +
      <xsd:complexContent>
 +
        <xsd:extension base="vehicle">
 +
            <xsd:sequence>
 +
              <xsd:element name="number-of-doors" type="xsd:int"/>
 +
              <xsd:element name="miles-per-gallon" type="xsd:int"/>
 +
            </xsd:sequence>
 +
        </xsd:extension>
 +
      </xsd:complexContent>
 +
  </xsd:complexType>
 +
  <xsd:complexType name="vehicle">
 +
      <xsd:sequence>
 +
        <xsd:element name="model" type="xsd:string" minOccurs="0"/>
 +
        <xsd:element name="manufacturer" type="xsd:string" minOccurs="0"/>
 +
        <xsd:element name="top-speed" type="xsd:int"/>
 +
      </xsd:sequence>
 +
      <xsd:attribute name="vtype" type="xsd:string"/>
 +
  </xsd:complexType>
 +
  <xsd:element name="car-data" type="car"/>
 +
  <xsd:element name="vehicle-data" type="vehicle"/>
 +
</xsd:schema>
 
</source>
 
</source>
  
Line 249: Line 254:
 
@Target({METHOD, FIELD})  
 
@Target({METHOD, FIELD})  
 
@Retention(RUNTIME)
 
@Retention(RUNTIME)
public @interface XmlKey {
+
public @interface XmlKey {}
    String value();
+
</source>
}
+
 
 
==== XML Metadata ====
 
==== XML Metadata ====
 
===== xml-key =====
 
===== xml-key =====
<code>xml-key</code> will be used to identify one or more primary keys on a given type.  Any @XmlKey annotations will be combined with those set via xml metadata.  To unset a property annotated with </code>@XmlKey</code>, the property must be present in XML without xml-key="true".
+
<code>xml-key</code> will be used to identify one or more primary keys on a given type.  Any <code>XmlKey</code> annotations will be combined with those set via xml metadata.  To unset a property annotated with <code>XmlKey</code>, the property must be present in XML without <code>xml-key="true"</code>.
 +
 
 
eclipselink-oxm.xml snippet (<code>org.example.Address</code> type)
 
eclipselink-oxm.xml snippet (<code>org.example.Address</code> type)
 
<source lang="xml">
 
<source lang="xml">
<xml-element java-attribute="empId" xml-key="true" />
+
<xml-attribute java-attribute="id" xml-key="true" />
<xml-element java-attribute="type" xml-key="true" />
+
<xml-element java-attribute="cityName" xml-path="city/text()" xml-key="true" />
 +
</source>
 +
==== XML Schema  ====
 +
Following is the proposed XSD change necessary to provide additional relationship mapping support.  The following attribute will be added to <code>xml-attribute</code> and <code>xml-element</code>:
 +
<source lang="xml">
 +
<xs:attribute name="xml-key" type="xs:boolean" default="false" />
 
</source>
 
</source>
  
Line 274: Line 285:
 
}
 
}
 
</source>
 
</source>
 +
 
==== XML Metadata ====
 
==== XML Metadata ====
 
===== xml-join-nodes =====
 
===== xml-join-nodes =====
Line 280: Line 292:
 
=== XmlJoinNode ===
 
=== XmlJoinNode ===
 
==== Purpose ====
 
==== Purpose ====
<code>XmlJoinNode</code> is used to identify a source to target primary key field association.  For composite keys, [http://wiki.eclipse.org/index.php?title=EclipseLink/DesignDocs/317962/Phase3#XmlJoinNodes <code>XmlJoinNodes</code>] can be used.  To unset a property annotated with <code>@XmlJoinNodes</code>, the property must be present in XML without an <code>xml-join-nodes</code> element.
+
<code>XmlJoinNode</code> is used to identify a source to target primary key field association.  For composite keys, [http://wiki.eclipse.org/index.php?title=EclipseLink/DesignDocs/317962/Phase3#XmlJoinNodes <code>XmlJoinNodes</code>] can be used.  To unset a property annotated with <code>XmlJoinNodes</code>, the property must be present in XML without an <code>xml-join-nodes</code> element.
  
 
==== Java Metadata ====
 
==== Java Metadata ====
Line 295: Line 307:
  
 
==== XML Metadata ====
 
==== XML Metadata ====
<code>xml-join-node</code> is used to identify a source to target primary key field association.  For composite keys, [http://wiki.eclipse.org/index.php?title=EclipseLink/DesignDocs/317962/Phase3#xml-join-nodes <code>xml-join-nodes</code>] can be used.  To unset a property annotated with <code>@XmlJoinNode</code>, the property must be present in XML without any <code>xml-join-node</code> elements.
+
===== xml-join-node =====
 +
<code>xml-join-node</code> is used to identify a source to target primary key field association.  For composite keys, [http://wiki.eclipse.org/index.php?title=EclipseLink/DesignDocs/317962/Phase3#xml-join-nodes <code>xml-join-nodes</code>] can be used.  To unset a property annotated with <code>XmlJoinNode</code>, the property must be present in XML without any <code>xml-join-node</code> elements.
  
 
eclipselink-oxm.xml snippet (<code>org.example.Employee</code> type)
 
eclipselink-oxm.xml snippet (<code>org.example.Employee</code> type)
 
<source lang="xml">
 
<source lang="xml">
<xml-element java-attribute="address">
+
<xml-join-nodes java-attribute="address">
     <xml-join-nodes>
+
     <xml-join-node xml-path="work-address/@id" referenced-xml-path="@id" />
        <xml-join-node xml-path="address/@emp-id" referenced-xml-path="empId" />
+
    <xml-join-node xml-path="work-address/city/text()" referenced-xml-path="city/text()" />
        <xml-join-node xml-path="address/@type" referenced-xml-path="type" />
+
</xml-join-nodes>
    </xml-join-nodes>
+
</xml-element>
+
 
</source>
 
</source>
  
==== XML Schema  ====
+
=== XML Schema  ===
 
Following is the proposed XSD change necessary to provide additional relationship mapping support:  
 
Following is the proposed XSD change necessary to provide additional relationship mapping support:  
 
<source lang="xml">
 
<source lang="xml">
<xs:element name="xml-join-nodes" type="xml-join-nodes" />
+
<xs:element name="xml-join-nodes" substitutionGroup="java-attribute" >
<xs:complexType name="xml-join-nodes">
+
    <xs:complexType>
    <xs:sequence>
+
        <xs:complexContent>
        <xs:element name="xml-join-node" minOccurs="0" maxOccurs="unbounded" >
+
            <xs:extension base="java-attribute">
            <xs:complexType>
+
                <xs:sequence>
                <xs:attribute name="xml-path" type="xs:string" use="required" />
+
                    <xs:element name="xml-join-node" minOccurs="1" maxOccurs="unbounded" >
                <xs:attribute name="referenced-xml-path" type="xs:string" use="required" />
+
                        <xs:complexType>
            </xs:complexType>
+
                            <xs:attribute name="xml-path" type="xs:string" use="required" />
        </xs:element>
+
                            <xs:attribute name="referenced-xml-path" type="xs:string" use="required" />
    </xs:sequence>
+
                        </xs:complexType>
</xs:complexType>
+
                    </xs:element>
 +
                </xs:sequence>
 +
            </xs:extension>
 +
        </xs:complexContent>
 +
    </xs:complexType>
 +
</xs:element>
 
</source>
 
</source>
  
Line 329: Line 345:
 
<source lang="xml">
 
<source lang="xml">
 
<java-types>
 
<java-types>
 +
    <java-type name="org.example.Company">
 +
        <xml-root-element/>
 +
        <java-attributes>
 +
            <xml-element java-attribute="employees" xml-path="employee-data" />
 +
            <xml-element java-attribute="buildingAddresses" xml-path="business-address" />
 +
        </java-attributes>
 +
    </java-type>
 
     <java-type name="org.example.Employee">
 
     <java-type name="org.example.Employee">
 
         <xml-root-element name="employee-data" />
 
         <xml-root-element name="employee-data" />
 
         <java-attributes>
 
         <java-attributes>
 
             <xml-attribute java-attribute="id" />
 
             <xml-attribute java-attribute="id" />
             <xml-element java-attribute="address">
+
             <xml-join-nodes java-attribute="workAddress">
                 <xml-join-nodes>
+
                 <xml-join-node xml-path="work-address/@id" referenced-xml-path="@id" />
                    <xml-join-node xml-path="address/@emp-id" referenced-xml-path="empId" />
+
                <xml-join-node xml-path="work-address/@city" referenced-xml-path="city/text()" />
                    <xml-join-node xml-path="address/@type" referenced-xml-path="type" />
+
            </xml-join-nodes>
                </xml-join-nodes>
+
            </xml-element>
+
 
         </java-attributes>
 
         </java-attributes>
 
     </java-type>
 
     </java-type>
 
     <java-type name="org.example.Address">
 
     <java-type name="org.example.Address">
         <xml-root-element name="address-data" />  
+
         <xml-root-element name="business-address" />
 +
        <java-attributes>
 +
            <xml-attribute java-attribute="id" xml-id="true" />
 +
            <xml-element java-attribute="cityName" xml-path="city/text()" xml-key="true" />
 +
        </java-attributes>
 
     </java-type>
 
     </java-type>
 
</java-types>
 
</java-types>
 
</source>
 
</source>
 
Setting up a relationship mapping via Annotations would be accomplished  as follows:<br>
 
Setting up a relationship mapping via Annotations would be accomplished  as follows:<br>
 +
org.example.Company.java
 +
<source lang="java">
 +
package org.example;
 +
 +
import java.util.List;
 +
import javax.xml.bind.annotation.XmlElement;
 +
import javax.xml.bind.annotation.XmlRootElement;
 +
 +
@XmlRootElement
 +
public class Company {
 +
    @XmlElement(name="employee-data")
 +
    public List<Employee> employees;
 +
    @XmlElement(name="business-address")
 +
    public List<Address> buildingAddresses;
 +
}
 +
</source>
  
 
org.example.Employee.java
 
org.example.Employee.java
 
<source lang="java">
 
<source lang="java">
 
package org.example;
 
package org.example;
 +
 +
import org.eclipse.persistence.oxm.annotations.XmlJoinNode;
 +
import org.eclipse.persistence.oxm.annotations.XmlJoinNodes;
  
 
import javax.xml.bind.annotation.XmlElement;
 
import javax.xml.bind.annotation.XmlElement;
 
import javax.xml.bind.annotation.XmlRootElement;
 
import javax.xml.bind.annotation.XmlRootElement;
  
@XmlRootElement("employee-data")
+
@XmlRootElement(name="employee-data")
 
class Employee {
 
class Employee {
 
     @XmlAttribute
 
     @XmlAttribute
Line 361: Line 405:
  
 
     @XmlJoinNodes({
 
     @XmlJoinNodes({
         @XmlJoinNode(xmlPath="address/@emp-id" referencedXmlPath="empId"),
+
         @XmlJoinNode(xmlPath="work-address/@id", referencedXmlPath="@id"),
         @XmlJoinNode(xmlPath="address/@type" referencedXmlPath="type")
+
         @XmlJoinNode(xmlPath="work-address/@city", referencedXmlPath="city/text()")
 
     })
 
     })
 
     public Address address;
 
     public Address address;
Line 371: Line 415:
 
package org.example;
 
package org.example;
  
 +
import org.eclipse.persistence.oxm.annotations.XmlKey;
 +
import org.eclipse.persistence.oxm.annotations.XmlPath;
 +
 +
import javax.xml.bind.annotation.XmlElement;
 
import javax.xml.bind.annotation.XmlRootElement;
 
import javax.xml.bind.annotation.XmlRootElement;
  
@XmlRootElement("address-data")
+
@XmlRootElement(name="business-address")
 
class Address {
 
class Address {
     public String empId;
+
     @XmlID
     public String type;
+
    @XmlPath("@id")
 +
     public String id;
 +
 
 
     public String street;
 
     public String street;
     public String city;
+
     public String suite;
 +
 
 +
    @XmlKey
 +
    @XmlPath("city/text()")
 +
    public String cityName;
 +
 
 
     public String postal;
 
     public String postal;
 
}
 
}
 +
</source>
 +
 +
Sample Generated Schema
 +
<source lang="xml">
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 +
  <xsd:complexType name="address">
 +
      <xsd:sequence>
 +
        <xsd:element name="street" type="xsd:string" minOccurs="0"/>
 +
        <xsd:element name="suite" type="xsd:string" minOccurs="0"/>
 +
        <xsd:element name="city" type="xsd:string" minOccurs="0"/>
 +
        <xsd:element name="postal" type="xsd:string" minOccurs="0"/>
 +
      </xsd:sequence>
 +
      <xsd:attribute name="id" type="xsd:ID"/>
 +
  </xsd:complexType>
 +
  <xsd:complexType name="company">
 +
      <xsd:sequence>
 +
        <xsd:element name="employees" type="employee" minOccurs="0" maxOccurs="unbounded"/>
 +
        <xsd:element name="buildingAddresses" type="address" minOccurs="0" maxOccurs="unbounded"/>
 +
      </xsd:sequence>
 +
  </xsd:complexType>
 +
  <xsd:complexType name="employee">
 +
      <xsd:sequence>
 +
        <xsd:element name="work-address" minOccurs="0">
 +
            <xsd:complexType>
 +
              <xsd:attribute name="id" type="xsd:anySimpleType"/>
 +
              <xsd:attribute name="city" type="xsd:anySimpleType"/>
 +
            </xsd:complexType>
 +
        </xsd:element>
 +
      </xsd:sequence>
 +
      <xsd:attribute name="id" type="xsd:string"/>
 +
  </xsd:complexType>
 +
  <xsd:element name="business-address" type="address"/>
 +
  <xsd:element name="company" type="company"/>
 +
  <xsd:element name="employee-data" type="employee"/>
 +
</xsd:schema>
 
</source>
 
</source>
  
 
Sample XML Instance Document
 
Sample XML Instance Document
 
<source lang="xml">
 
<source lang="xml">
<root>
+
<company>
     <employee-data id="100">
+
     <employee-data id="101">
         <address emp-id="100" type="HOME" />
+
         <work-address id="ba100" city="Ottawa" />
 +
    </employee-data>
 +
    <employee-data id="102">
 +
        <work-address id="ba100" city="Kanata" />
 
     </employee-data>
 
     </employee-data>
     <address-data>
+
     <business-address id="ba100">
        <empId>100</empId>
+
        <type>HOME</type>
+
 
         <street>99 Some St.</street>
 
         <street>99 Some St.</street>
 +
        <suite>1001</suite>
 
         <city>Kanata</city>
 
         <city>Kanata</city>
 
         <postal>K0A3m0</postal>
 
         <postal>K0A3m0</postal>
     </address-data>
+
     </business-address>
     <address-data>
+
     <business-address id="ba100">
         <empId>100</empId>
+
         <street>45 O'Connor St.</street>
         <type>WORK</type>
+
         <suite>400</suite>
        <street>45 O'Connor St., Suite 400</street>
+
 
         <city>Ottawa</city>
 
         <city>Ottawa</city>
 
         <postal>K1P1A4</postal>
 
         <postal>K1P1A4</postal>
     </address-data>
+
     </business-address>
     <address-data>
+
     <business-address id="ba200">
        <empId>200</empId>
+
        <type>HOME</type>
+
 
         <street>1 Anystreet Rd.</street>
 
         <street>1 Anystreet Rd.</street>
 +
        <suite>9</suite>
 
         <city>Ottawa</city>
 
         <city>Ottawa</city>
 
         <postal>K4P1A2</postal>
 
         <postal>K4P1A2</postal>
     </address-data>
+
     </business-address>
</root>
+
</company>
 
</source>
 
</source>
  
Line 422: Line 513:
 
|-  
 
|-  
 
| xml-discriminator-node
 
| xml-discriminator-node
| <code>org.eclipse.persistence.testing.jaxb.externalizedmetadata.inheritance</code>  
+
| <code>org.eclipse.persistence.testing.jaxb.externalizedmetadata.xmldiscriminator</code>  
 
|-  
 
|-  
 
| xml-discriminator-value
 
| xml-discriminator-value
| <code>org.eclipse.persistence.testing.jaxb.externalizedmetadata.inheritance</code>  
+
| <code>org.eclipse.persistence.testing.jaxb.externalizedmetadata.xmldiscriminator</code>
 +
|-
 +
| xml-key
 +
| <code>org.eclipse.persistence.testing.jaxb.externalizedmetadata.xmljoinnode</code>
 +
|-
 +
| xml-join-nodes
 +
| <code>org.eclipse.persistence.testing.jaxb.externalizedmetadata.xmljoinnode</code>  
 
|}
 
|}
  
Line 434: Line 531:
 
! Package
 
! Package
 
|-
 
|-
|  
+
| XmlDiscriminatorNode
| <code></code>  
+
| <code>org.eclipse.persistence.testing.jaxb.annotations.xmldiscriminator</code>
|}  
+
|-
 +
| XmlDiscriminatorValue
 +
| <code>org.eclipse.persistence.testing.jaxb.annotations.xmldiscriminator</code>
 +
|-
 +
| XmlKey
 +
| <code>org.eclipse.persistence.testing.jaxb.annotations.xmljoinnode</code>
 +
|-
 +
| XmlJoinNodes
 +
| <code>org.eclipse.persistence.testing.jaxb.annotations.xmljoinnode</code>  
 +
|}
  
== Open Issues ==
+
== Planning  ==
  
 +
This section lists feature delivery estimates.
 +
 +
{|{{BMTableStyle}}
 +
|-{{BMTHStyle}}
 +
! Name
 +
! Estimate (days)
 +
! Estimate Complete
 +
! Actual Complete
 +
|-
 +
| xml-discriminator-node
 +
| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2
 +
| &nbsp;&nbsp;&nbsp;Aug.25, 2010
 +
| &nbsp;&nbsp;&nbsp;Aug.25, 2010
 +
|-
 +
| xml-discriminator-value
 +
| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1
 +
| &nbsp;&nbsp;&nbsp;Aug.26, 2010
 +
| &nbsp;&nbsp;&nbsp;Aug.25, 2010
 +
|-
 +
| XmlDiscriminatorNode
 +
| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1
 +
| &nbsp;&nbsp;&nbsp;Aug.27, 2010
 +
| &nbsp;&nbsp;&nbsp;Aug.25, 2010
 +
|-
 +
| XmlDiscriminatorValue
 +
| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1
 +
| &nbsp;&nbsp;&nbsp;Aug.30, 2010
 +
| &nbsp;&nbsp;&nbsp;Aug.25, 2010
 +
|-
 +
| xml-key
 +
| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2
 +
| &nbsp;&nbsp;&nbsp;Sept.02, 2010
 +
| &nbsp;&nbsp;&nbsp;Sept.15, 2010
 +
|-
 +
| xml-join-node(s)
 +
| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3
 +
| &nbsp;&nbsp;&nbsp;Sept.08, 2010
 +
| &nbsp;&nbsp;&nbsp;Sept.15, 2010
 +
|-
 +
| XmlKey
 +
| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2
 +
| &nbsp;&nbsp;&nbsp;Sept.10, 2010
 +
| &nbsp;&nbsp;&nbsp;Sept.15, 2010
 +
|-
 +
| XmlJoinNode
 +
| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2
 +
| &nbsp;&nbsp;&nbsp;Sept.14, 2010
 +
| &nbsp;&nbsp;&nbsp;Sept.15, 2010
 +
|-
 +
| XmlJoinNodes
 +
| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1
 +
| &nbsp;&nbsp;&nbsp;Sept.15, 2010
 +
| &nbsp;&nbsp;&nbsp;Sept.15, 2010
 +
|}
 +
 +
== Open Issues ==
 
This section lists open issues.  
 
This section lists open issues.  
  
Line 448: Line 610:
 
|-
 
|-
 
| 1
 
| 1
| Since (according to the JAXB spec.) there can only be one @XmlID per class, we need a way to handle multpile @XmlIDs for composite keys.  How should we handle this? One suggestion is to introduce a new annotation called @XmlKey that can be used to define one or more keys in a class.  This could also be used with a single @XmlID. Is there another way to support composite keys w/o violating the JAXB spec?
+
| Support for XmlJoinNodes on XmlElements cannot be added until EclipseLink bug# 323756 is resolved.
 
|}
 
|}
  
Line 462: Line 624:
 
|-
 
|-
 
| 1  
 
| 1  
|  
+
| Event handling
|  
+
| It was originally thought that providing support for event handling (loosely based on JPA pre/post events) in the form of before/after marshal/unmarshal events would be useful.  However, we already support these events in JAXB by looking for specific methods (i.e. beforeMarshal) and hooking up the listeners under the covers.  At this point there would be no benefit in providing support for this configuration in annotations or xml metadata.
 
|}
 
|}

Latest revision as of 16:18, 23 September 2010

Phase 3 - MOXy Equivalents of Relevant JPA Annotations

This phase of development involves providing additional MOXy annotations and XML metadata support equivalent to that of any relevant JPA annotations.

Annotations/XML Metadata

The following MOXy annotations/XML metadata will be targeted in this phase:

JPA Annotation MOXy Annotation XML Metadata Tag Package Type Field Method
DiscriminatorColumn XmlDiscriminatorNode xml-discriminator-node X
DiscriminatorValue XmlDiscriminatorValue xml-discriminator-value X
JoinColumn XmlJoinNode xml-join-node X X
JoinColumns XmlJoinNodes xml-join-nodes X X
XmlKey xml-key X X

Inheritance Support

XmlDiscriminatorNode

Purpose

Provide a means to set the class indicator field name when using inheritance.

Java Metadata

package org.eclipse.persistence.oxm.annotations;
 
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
/**
 * The XmlDiscriminatorNode annotation is used to specify the class 
 * indicator field name when using inheritance.
 */
@Target({TYPE}) 
@Retention(RUNTIME)
public @interface XmlDiscriminatorNode {
 
    /**
     * (Required) Indicates the the class indicator field name.
     */
    String value();
}

XML Metadata

xml-discriminator-node

The xml-discriminator-node metadata tag will be used to set the class indicator field name when using inheritance. The value will be in the form of an XPath to an attribute, i.e. @xsi:type. If this is present in XML, any value set via annotation will be overwritten.

eclipselink-oxm.xml snippet

<java-type name="org.example.Vehicle" xml-discriminator-node="@vtype">

XmlDiscriminatorValue

Purpose

Provide a means to set a class indicator when using inheritance.

Java Metadata

package org.eclipse.persistence.oxm.annotations;
 
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
/**
 * The XmlDiscriminatorValue annotation is used to specify the class indicator for a 
 * given type when using inheritance.
 */
@Target({TYPE}) 
@Retention(RUNTIME)
public @interface XmlDiscriminatorValue {
    /**
     * (Required) Indicates the class indicator for a given Type.
     */
    String value();
}

XML Metadata

xml-discriminator-value

The xml-discriminator-value metadata tag will be used to set a class indicator when using inheritance. If this is present in XML, any value set via annotation will be overwritten.

eclipselink-oxm.xml snippet

<java-type name="org.example.Car" xml-discriminator-value="car">

XML Schema

Following is the proposed XSD change necessary to provide support for inheritance. The following attributes will be added to java-type:

<xs:attribute name="xml-discriminator-node" type="xs:string" />
<xs:attribute name="xml-discriminator-value" type="xs:string" />

Example

The following example will demonstrate how inheritance can be configured.

Using the xml-discriminator-node and xml-discriminator-value EclipseLink XML metadata tags to set the class indicator field name and class indicator(s) can be accomplished as follows:

<java-types>
    <java-type name="org.example.Vehicle" xml-discriminator-node="@vtype" xml-discriminator-value="vehicle">
        <xml-root-element name="vehicle-data" />
        <java-attributes>
            <xml-element java-attribute="topSpeed" name="top-speed" />
        </java-attributes>
    </java-type>
    <java-type name="org.example.Car" xml-discriminator-value="car">
        <xml-root-element name="car-data" /> 
        <java-attributes>
            <xml-element java-attribute="numberOfDoors" name="number-of-doors" />
            <xml-element java-attribute="milesPerGallon" name="miles-per-gallon" />
        </java-attributes>
    </java-type>
</java-types>

Setting the class indicator field name and class indicator(s) via Annotations would be accomplished as follows:

org.example.Vehicle.java

package org.example;
 
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorNode;
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorValue;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
 
@XmlRootElement(name="vehicle-data")
@XmlDiscriminatorNode("@vtype")
@XmlDiscriminatorValue("vehicle")
class Vehicle {
    public String model;
    public String manufacturer;
    @XmlElement(name="top-speed")
    public int topSpeed;
}

org.example.Car.java

package org.example;
 
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorValue;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
 
@XmlRootElement(name="car-data")
@XmlDiscriminatorValue("car")
class Car extends Vehicle {
    @XmlElement(name="number-of-doors")
    public int numberOfDoors;
    @XmlElement(name="miles-per-gallon")
    public int milesPerGallon;
}

Sample Generated Schema

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <xsd:complexType name="car">
      <xsd:complexContent>
         <xsd:extension base="vehicle">
            <xsd:sequence>
               <xsd:element name="number-of-doors" type="xsd:int"/>
               <xsd:element name="miles-per-gallon" type="xsd:int"/>
            </xsd:sequence>
         </xsd:extension>
      </xsd:complexContent>
   </xsd:complexType>
   <xsd:complexType name="vehicle">
      <xsd:sequence>
         <xsd:element name="model" type="xsd:string" minOccurs="0"/>
         <xsd:element name="manufacturer" type="xsd:string" minOccurs="0"/>
         <xsd:element name="top-speed" type="xsd:int"/>
      </xsd:sequence>
      <xsd:attribute name="vtype" type="xsd:string"/>
   </xsd:complexType>
   <xsd:element name="car-data" type="car"/>
   <xsd:element name="vehicle-data" type="vehicle"/>
</xsd:schema>

Sample XML Instance Document

<vehicle-data vtype="car">
    <model>Mustang GT</model>
    <manufacturer>Ford</manufacturer>
    <top-speed>354</top-speed>
    <number-of-doors>2</number-of-doors>
    <miles-per-gallon>26</miles-per-gallon>
</vehicle-data>

Relationship Mapping Support

We currently support relationship mappings through @ID/@IDREF annotations, and xml-id/xml-idref metadata tags. There are a number of limitations when using these:

  • ID property must be of type String
  • Target class of an IDREF must have an ID property
  • JAXB expects that a given class can have at most one ID property, so composite keys cannot be configured w/o violating the JAXB spec.

Use of XmlJoinNode(s) will allow one or more properties in the target class to be used as the key for a relationship mapping.

XmlKey

Purpose

One or more XmlKey annotations can be used to declare the primary keys in a given class. For a single key, either XmlID or XmlKey can be used. For composite primary keys, multiple XmlKey annotations can be used, or a single XmlID can be combined with one or more XmlKey annotations.

Java Metadata

package org.eclipse.persistence.oxm.annotations;
 
@Target({METHOD, FIELD}) 
@Retention(RUNTIME)
public @interface XmlKey {}

XML Metadata

xml-key

xml-key will be used to identify one or more primary keys on a given type. Any XmlKey annotations will be combined with those set via xml metadata. To unset a property annotated with XmlKey, the property must be present in XML without xml-key="true".

eclipselink-oxm.xml snippet (org.example.Address type)

<xml-attribute java-attribute="id" xml-key="true" />
<xml-element java-attribute="cityName" xml-path="city/text()" xml-key="true" />

XML Schema

Following is the proposed XSD change necessary to provide additional relationship mapping support. The following attribute will be added to xml-attribute and xml-element:

<xs:attribute name="xml-key" type="xs:boolean" default="false" />

XmlJoinNodes

Purpose

XmlJoinNodes is used to group one or more XmlJoinNode entries. Please see XmlJoinNode below for examples of use.

Java Metadata

package org.eclipse.persistence.oxm.annotations;
 
@Target({METHOD, FIELD}) 
@Retention(RUNTIME)
public @interface XmlJoinNodes {
    XmlJoinNode[] value();
}

XML Metadata

xml-join-nodes

xml-join-nodes will be used to group one or more xml-join-node entries. Please see xml-join-node below for additional information and examples of use.

XmlJoinNode

Purpose

XmlJoinNode is used to identify a source to target primary key field association. For composite keys, XmlJoinNodes can be used. To unset a property annotated with XmlJoinNodes, the property must be present in XML without an xml-join-nodes element.

Java Metadata

package org.eclipse.persistence.oxm.annotations;
 
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface XmlJoinNode {
    String xmlPath();
    String referencedXmlPath();
}

XML Metadata

xml-join-node

xml-join-node is used to identify a source to target primary key field association. For composite keys, xml-join-nodes can be used. To unset a property annotated with XmlJoinNode, the property must be present in XML without any xml-join-node elements.

eclipselink-oxm.xml snippet (org.example.Employee type)

<xml-join-nodes java-attribute="address">
    <xml-join-node xml-path="work-address/@id" referenced-xml-path="@id" />
    <xml-join-node xml-path="work-address/city/text()" referenced-xml-path="city/text()" />
</xml-join-nodes>

XML Schema

Following is the proposed XSD change necessary to provide additional relationship mapping support:

<xs:element name="xml-join-nodes" substitutionGroup="java-attribute" >
    <xs:complexType>
        <xs:complexContent>
            <xs:extension base="java-attribute">
                <xs:sequence>
                    <xs:element name="xml-join-node" minOccurs="1" maxOccurs="unbounded" >
                        <xs:complexType>
                            <xs:attribute name="xml-path" type="xs:string" use="required" />
                            <xs:attribute name="referenced-xml-path" type="xs:string" use="required" />
                        </xs:complexType>
                    </xs:element>
                </xs:sequence>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
</xs:element>

Example

The following example will demonstrate how a relationship mapping with composite keys can be configured.

Using the xml-join-nodes and xml-join-node EclipseLink XML metadata tags to configure a relationship mapping can be accomplished as follows:

<java-types>
    <java-type name="org.example.Company">
        <xml-root-element/>
        <java-attributes>
            <xml-element java-attribute="employees" xml-path="employee-data" />
            <xml-element java-attribute="buildingAddresses" xml-path="business-address" />
        </java-attributes>
    </java-type>
    <java-type name="org.example.Employee">
        <xml-root-element name="employee-data" />
        <java-attributes>
            <xml-attribute java-attribute="id" />
            <xml-join-nodes java-attribute="workAddress">
                <xml-join-node xml-path="work-address/@id" referenced-xml-path="@id" />
                <xml-join-node xml-path="work-address/@city" referenced-xml-path="city/text()" />
            </xml-join-nodes>
        </java-attributes>
    </java-type>
    <java-type name="org.example.Address">
        <xml-root-element name="business-address" />
        <java-attributes>
            <xml-attribute java-attribute="id" xml-id="true" />
            <xml-element java-attribute="cityName" xml-path="city/text()" xml-key="true" />
        </java-attributes>
    </java-type>
</java-types>

Setting up a relationship mapping via Annotations would be accomplished as follows:
org.example.Company.java

package org.example;
 
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
 
@XmlRootElement
public class Company {
    @XmlElement(name="employee-data")
    public List<Employee> employees;
    @XmlElement(name="business-address")
    public List<Address> buildingAddresses;
}

org.example.Employee.java

package org.example;
 
import org.eclipse.persistence.oxm.annotations.XmlJoinNode;
import org.eclipse.persistence.oxm.annotations.XmlJoinNodes;
 
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
 
@XmlRootElement(name="employee-data")
class Employee {
    @XmlAttribute
    public String id;
 
    @XmlJoinNodes({
        @XmlJoinNode(xmlPath="work-address/@id", referencedXmlPath="@id"),
        @XmlJoinNode(xmlPath="work-address/@city", referencedXmlPath="city/text()")
    })
    public Address address;
}

org.example.Address.java

package org.example;
 
import org.eclipse.persistence.oxm.annotations.XmlKey;
import org.eclipse.persistence.oxm.annotations.XmlPath;
 
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
 
@XmlRootElement(name="business-address")
class Address {
    @XmlID
    @XmlPath("@id")
    public String id;
 
    public String street;
    public String suite;
 
    @XmlKey
    @XmlPath("city/text()")
    public String cityName;
 
    public String postal;
}

Sample Generated Schema

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <xsd:complexType name="address">
      <xsd:sequence>
         <xsd:element name="street" type="xsd:string" minOccurs="0"/>
         <xsd:element name="suite" type="xsd:string" minOccurs="0"/>
         <xsd:element name="city" type="xsd:string" minOccurs="0"/>
         <xsd:element name="postal" type="xsd:string" minOccurs="0"/>
      </xsd:sequence>
      <xsd:attribute name="id" type="xsd:ID"/>
   </xsd:complexType>
   <xsd:complexType name="company">
      <xsd:sequence>
         <xsd:element name="employees" type="employee" minOccurs="0" maxOccurs="unbounded"/>
         <xsd:element name="buildingAddresses" type="address" minOccurs="0" maxOccurs="unbounded"/>
      </xsd:sequence>
   </xsd:complexType>
   <xsd:complexType name="employee">
      <xsd:sequence>
         <xsd:element name="work-address" minOccurs="0">
            <xsd:complexType>
               <xsd:attribute name="id" type="xsd:anySimpleType"/>
               <xsd:attribute name="city" type="xsd:anySimpleType"/>
            </xsd:complexType>
         </xsd:element>
      </xsd:sequence>
      <xsd:attribute name="id" type="xsd:string"/>
   </xsd:complexType>
   <xsd:element name="business-address" type="address"/>
   <xsd:element name="company" type="company"/>
   <xsd:element name="employee-data" type="employee"/>
</xsd:schema>

Sample XML Instance Document

<company>
    <employee-data id="101">
        <work-address id="ba100" city="Ottawa" />
    </employee-data>
    <employee-data id="102">
        <work-address id="ba100" city="Kanata" />
    </employee-data>
    <business-address id="ba100">
        <street>99 Some St.</street>
        <suite>1001</suite>
        <city>Kanata</city>
        <postal>K0A3m0</postal>
    </business-address>
    <business-address id="ba100">
        <street>45 O'Connor St.</street>
        <suite>400</suite>
        <city>Ottawa</city>
        <postal>K1P1A4</postal>
    </business-address>
    <business-address id="ba200">
        <street>1 Anystreet Rd.</street>
        <suite>9</suite>
        <city>Ottawa</city>
        <postal>K4P1A2</postal>
    </business-address>
</company>

Testing

This section identifies the test package(s) for each feature outlined on this page.

XML Metadata

XML Metadata Package
xml-discriminator-node org.eclipse.persistence.testing.jaxb.externalizedmetadata.xmldiscriminator
xml-discriminator-value org.eclipse.persistence.testing.jaxb.externalizedmetadata.xmldiscriminator
xml-key org.eclipse.persistence.testing.jaxb.externalizedmetadata.xmljoinnode
xml-join-nodes org.eclipse.persistence.testing.jaxb.externalizedmetadata.xmljoinnode

Annotations

Annotation Package
XmlDiscriminatorNode org.eclipse.persistence.testing.jaxb.annotations.xmldiscriminator
XmlDiscriminatorValue org.eclipse.persistence.testing.jaxb.annotations.xmldiscriminator
XmlKey org.eclipse.persistence.testing.jaxb.annotations.xmljoinnode
XmlJoinNodes org.eclipse.persistence.testing.jaxb.annotations.xmljoinnode

Planning

This section lists feature delivery estimates.

Name Estimate (days) Estimate Complete Actual Complete
xml-discriminator-node            2    Aug.25, 2010    Aug.25, 2010
xml-discriminator-value            1    Aug.26, 2010    Aug.25, 2010
XmlDiscriminatorNode            1    Aug.27, 2010    Aug.25, 2010
XmlDiscriminatorValue            1    Aug.30, 2010    Aug.25, 2010
xml-key            2    Sept.02, 2010    Sept.15, 2010
xml-join-node(s)            3    Sept.08, 2010    Sept.15, 2010
XmlKey            2    Sept.10, 2010    Sept.15, 2010
XmlJoinNode            2    Sept.14, 2010    Sept.15, 2010
XmlJoinNodes            1    Sept.15, 2010    Sept.15, 2010

Open Issues

This section lists open issues.

Issue# Description/Notes
1 Support for XmlJoinNodes on XmlElements cannot be added until EclipseLink bug# 323756 is resolved.

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.

Decision# Description/Notes Decision
1 Event handling It was originally thought that providing support for event handling (loosely based on JPA pre/post events) in the form of before/after marshal/unmarshal events would be useful. However, we already support these events in JAXB by looking for specific methods (i.e. beforeMarshal) and hooking up the listeners under the covers. At this point there would be no benefit in providing support for this configuration in annotations or xml metadata.

Back to the top