J2XB Allows to control structurally how a set of classes is mapped to XML. The control allows to group different Bean properties into XML Elements (grouping elements) and to flatten Java class hierarchies into flat XML structures (Java delegates). Obviously, any combination of the two is also allowed.
In the example below, we take two Java classes (Location and Location.Address ) and flatten them - Location.Address is a delegate of Location . The attributes of Location.Address are considered attributes of the Location class.
After flattening the attributes, we group the attributes in different ways (the groups beeing properties , properties/subgroup and theAddress .
The following figure shows an example mapping of two classes to XML (in this case one of the classes is an inner class of the other, but this is not required for delegates). The classes source code is here at Location.java .
An example of the XML written for the Location class in this example is
<ex2:location xmlns:ex2="http://example.abra.com/nonTrivialTransformation"> <ex2:name>joe</ex2:name> <ex2:properties> <ex2:type>abbbg</ex2:type> <ex2:subgroup> <ex2:someProperty>56465</ex2:someProperty> <ex2:state>IL</ex2:state> <ex2:street>Shenkar</ex2:street> </ex2:subgroup> <ex2:city>hifa</ex2:city> </ex2:properties> <ex2:description>hotel</ex2:description> <ex2:address2> <ex2:description>hotel - TLV</ex2:description> <ex2:properties> <ex2:city>Tel Aviv</ex2:city> <ex2:subgroup> <ex2:state>IL</ex2:state> <ex2:street>Ben Gurion</ex2:street> </ex2:subgroup> </ex2:properties> </ex2:address2> </ex2:location>
The MOProperty allows to specify a name for the XML element and to specify if the attribute is mapped as an XML attribute or XML element. By default, properties are mapped as XML Elements with the same name as the java Bean property name.
To specify an alternate name, use the xmlName member of MOProperty .
@MOProperty(xmlName = "town") public String getCity() {...}
To specify that the property is mapped as an XML attribute, set the isXmlAttribute member.
@MOProperty(xmlName = "town", isXmlAttribute = true) public String getCity() {...}
By default, J2XB orders the properties of a Bean by the alpha-nomeric ordering of the property names. However, if specifing the xmlOrder member of the MOProperty annotation, the ordering is done using the xmlOrder values. If two attributes have the same value, the ordering between them will be alpha-nomeric.
When considering the ordering of groups, a group position in the XML document is that of the first property it contain (where first is by the properties ordering). A property will allways appear inside the group element, even if its position implies that is should appear after another property not in the group.
For example, if we have the following properties -
We will see a group element called abc containing both the firstName and lastName XML elemenets. After the abc element will appear the caption element.
e.g.
<abc> <firstName>xxx</firstName> <lastName>xxx</lastName> </abc> <caption>xxx</caption>
Grouping attributes is done using the MOPropertyGroup annotation, which takes one parameter - the group name. Nesting unlimited nested groups is supported by using a path like structure (e.g. to specify the group subgroup nested in the group properties use properties/subgroup ). For each group, an XML element is created (e.g. in the example above, an XML element called properties is created, nested inside it is the subgroup XML element).
When more then one property define the same groups (or subbset of the groups), the corresponsing XML elements are joined.
The annotation syntax is (for example)
@MOPropertyGroup("properties") @MOProperty(xmlOrder = 5, xmlName = "city", xmlOptional = false) public String getCity() {...}
which will render the XML as
<properties> <city>xxx</city> </properties>
a Delegate is a Bean member of another Bean that is considered a compositor of the parent Bean. The delegate bean can only be a simple property (non collection or array). From the point of view of modeling, the delegate is considered part of the parent class and should be rendered in XML as if the delegate properties are the properties of the parent class.
In the example above, we have the Location class which has two properties of type Location.Address . The first is mapped as a delegate, the second as a delegate with grouping.
The delegate bean is defined by
@MODelegateProperty(xmlOrder = 4) public Address getAddress() {...}
Where the delegate with grouping is defined by
@MOPropertyGroup("address2") @MODelegateProperty(xmlOrder = 5) public Address getAddress2() {...}
Note the xmlOrder member of the delegate - it is used to define how to order the delegate members when combining them in the parent bean properties. The delegate properties will appear in the position specified in the xmlOrder member of the MODelegateProperty annotation, where the internal ordering between the delegate properties is done using the alpha-nomeric ordering or xmlOrder member of the delegate properties MOProperty annotations.
When the delegate property is mapped with MOPropertyGroup , all the properties of the delegate will be flattened in the scope of the group. When the delegate class itself also defines properties with grouping, those groups are merged with the groups of the parent class.