Difference between revisions of "EclipseLink/UserGuide/MOXy/Advanced XML Schema Concepts/Substitution Groups and Choices"

From Eclipsepedia

Jump to: navigation, search
m (New page: {{EclipseLink_UserGuide |info=y |api=y |apis=* [http://www.eclipse.org/eclipselink/api/latest/org/eclipse/persistence/mappings/XMLTransient.html XMLTransient] * [http://www.eclipse.org/ecl...)
 
m (Replacing page with ''''Warning This page is obsolete. Please see ''[http://www.eclipse.org/eclipselink/documentation/2.4/ Developing JAXB Applications Using EclipseLi...')
 
(8 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{EclipseLink_UserGuide
+
'''[[Image:Elug_draft_icon.png|Warning]] This page is obsolete. Please see ''[http://www.eclipse.org/eclipselink/documentation/2.4/ Developing JAXB Applications Using EclipseLink MOXy]'' for current information.'''
|info=y
+
|api=y
+
|apis=* [http://www.eclipse.org/eclipselink/api/latest/org/eclipse/persistence/mappings/XMLTransient.html XMLTransient]
+
* [http://www.eclipse.org/eclipselink/api/latest/org/eclipse/persistence/mappings/XMLInverseReferenceMapping.html XMLInverseReferenceMapping]
+
}}
+
 
+
==Substitution Groups ==
+
 
+
JAXB and Inheritance - Using Substitution Groups
+
In a previous blog post I described how to leverage the xsi:type attribute to represent inheritance.  In this post I'll demonstrate how to use the element name instead by leveraging the XML Schema concept of substitution groups.
+
 
+
Java Model
+
 
+
The model will contain an abstract super class for all types of contact information.
+
 
+
1
+
2
+
3
+
4
+
5
+
+
package blog.inheritance;
+
+
public abstract class ContactInfo {
+
+
}
+
 
+
Address and PhoneNumber will be the concrete implementations of ContactInfo.  Since we will be using the element name as the inheritance indicator we will annotate each of the sub-classes with @XmlRootElement.
+
 
+
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
+
package blog.inheritance;
+
+
import javax.xml.bind.annotation.XmlRootElement;
+
+
@XmlRootElement
+
public class Address extends ContactInfo {
+
+
    private String street;
+
+
    public String getStreet() {
+
        return street;
+
    }
+
+
    public void setStreet(String street) {
+
        this.street = street;
+
    }
+
+
}
+
 
+
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
+
package blog.inheritance;
+
+
import javax.xml.bind.annotation.XmlRootElement;
+
+
@XmlRootElement
+
public class PhoneNumber extends ContactInfo {
+
+
}
+
 
+
The Customer object can have different types of contact info set on it, so the property will refer to the super class.  We will annotate the contactInfo property with @XmlElementRef to indicate the value type will be derived from the element name (and namespace URI).
+
 
+
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
+
package blog.inheritance;
+
+
import javax.xml.bind.annotation.XmlElementRef;
+
import javax.xml.bind.annotation.XmlRootElement;
+
+
@XmlRootElement
+
public class Customer {
+
+
    private ContactInfo contactInfo;
+
+
    @XmlElementRef
+
    public ContactInfo getContactInfo() {
+
        return contactInfo;
+
    }
+
+
    public void setContactInfo(ContactInfo contactInfo) {
+
        this.contactInfo = contactInfo;
+
    }
+
+
}
+
 
+
Demo Code
+
 
+
We will use the following demo code to demonstrate the use of the xsi:type attribute to represent inheritance.
+
 
+
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
+
package blog.inheritance;
+
+
import javax.xml.bind.JAXBContext;
+
import javax.xml.bind.Marshaller;
+
+
public class Demo {
+
+
    public static void main(String[] args) throws Exception {
+
        Customer customer = new Customer();
+
        Address address = new Address();
+
        address.setStreet("1 A Street");
+
        customer.setContactInfo(address);
+
+
        JAXBContext jc = JAXBContext.newInstance(Customer.class, Address.class, PhoneNumber.class);
+
+
        Marshaller marshaller = jc.createMarshaller();
+
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+
        marshaller.marshal(customer, System.out);
+
    }
+
+
}
+
 
+
XML
+
 
+
The following is the resulting XML document.  Note that the Address object is marshalled to the address element.
+
 
+
 
+
1
+
2
+
3
+
4
+
5
+
+
<customer>
+
    <address>
+
        <street>1 A Street</street>
+
    </address>
+
</customer>
+
 
+
How does this All Work?
+
 
+
First we will take a look at the schema that represents JAXB's view on this object model.  There is an inheritance among the schema types that matches the inheritance among the Java classes.  Each type has a corresponding global element.  The address and phoneNumber elements specify that they may be substituted for the contactInfo element.
+
 
+
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
+
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+
    <xs:element name="customer" type="customer"/>
+
+
    <xs:element name="contactInfo" type="contactInfo"/>
+
+
    <xs:element name="address" type="address"
+
        substitutionGroup="contactInfo"/>
+
+
    <xs:element name="phoneNumber" type="phoneNumber"
+
        substitutionGroup="contactInfo"/>
+
+
    <xs:complexType name="customer">
+
        <xs:sequence>
+
            <xs:element ref="contactInfo"/>
+
        </xs:sequence>
+
    </xs:complexType>
+
+
    <xs:complexType name="contactInfo" abstract="true">
+
        <xs:sequence/>
+
    </xs:complexType>
+
+
    <xs:complexType name="address">
+
        <xs:complexContent>
+
            <xs:extension base="contactInfo">
+
                <xs:sequence>
+
                    <xs:element name="street" type="xs:string" minOccurs="0"/>
+
                </xs:sequence>
+
            </xs:extension>
+
        </xs:complexContent>
+
    </xs:complexType>
+
+
    <xs:complexType name="phoneNumber">
+
        <xs:complexContent>
+
            <xs:extension base="contactInfo">
+
                <xs:sequence/>
+
            </xs:extension>
+
        </xs:complexContent>
+
    </xs:complexType>
+
+
</xs:schema>
+
 
+
Summary
+
 
+
Not all XML binding tools support inheritance.  The ones that do often use different strategies.  Some include the class name of the subclass as the qualifier, this strategy makes it difficult to send the resulting XML document to another tool.  JAXB on the other hand leverages existing XML schema concepts to produce very portable XML documents.  In a future post I'll discuss a MOXy extension for an alternate means of representing inheritance (check out the following for a sneak peak).
+
 
+
 
+
 
+
{{EclipseLink_MOXy
+
|previous=[[EclipseLink/UserGuide/MOXy/Advanced_XML_Schema_Concepts/Handling_Null_Values|Handling Null Values]]
+
|next    =[[EclipseLink/UserGuide/MOXy/Advanced_XML_Schema_Concepts/Wildcard_Content|Wildcard Content]]
+
|up      =[[EclipseLink/UserGuide/MOXy/Advanced XML Schema Concepts|Advanced XML Schema Concepts]]
+
|version=2.2.0 DRAFT
+
}}
+

Latest revision as of 13:12, 30 January 2013

Warning This page is obsolete. Please see Developing JAXB Applications Using EclipseLink MOXy for current information.