XMap
User Guide

Last Modi cation Project Code Document ID Copyright

0 9 /2 2 / 2 0 0 6 NXECM XMAP-GUIDE Copyright © 2006 Nuxeo. All Rights Reserved.


Versionning
Version 1.0 1.0.1 Date 2 2 /0 9 / 2 0 0 6 2 6 /0 9 / 2 0 0 6 Participant(s) · Bogdan Stefanescu · Stefane Fermigier Comments Created Light editting


Sommaire
1 Overview...........................................................................................................................................4 2 XMap Annotations..............................................................................................................................5 2.1 2.2 2.3 2.4 2.5 2.6 XObject.......................................................................................................................................5 XNode.........................................................................................................................................5 XNodeList....................................................................................................................................6 XNodeMap...................................................................................................................................7 XContent.....................................................................................................................................7 XParent.......................................................................................................................................7

3 Mapping complex field objects...........................................................................................................9 4 Value Factories.................................................................................................................................10 5 XMap Context..................................................................................................................................11 6 Example..........................................................................................................................................12


Project title I Document title

1 Overview
XMap is a library that maps XML elements to Java objects using annotations on the objects. The library is currently used by Nuxeo Runtime to ease the usage of extension contributions. The library was designed for usability, performance being a second goal. For instance the mapping is done in two steps: first a DOM representation of the XML is built, then the DOM tree is processed and DOM nodes are mapped to object fields as specified by annotations. The library is completely independent from Nuxeo Runtime and can be used by any type of Java application. For a complete example on using XMap annotations see the Junit tests from the XMap library sources.

Document type I All Rights Reserved. I Page 4/14


Project title I Document title

2 XMap Annotations
The mapping is completely described by annotations. Annotation can either be used on fields on methods. The XObject annotation can be used only on classes. This section describes the complete list of supported annotations.

2.1 XObject
This annotation is supported only on classes. It marks the class as being mappable to an XML element. This annotations supports 2 attributes:
1.

value - specify the element name to which this class is mapped. The default value is "" which means this class is not mappable to a top level element but can be used as the type of a mappable field. The value must be an element name not a path. This means values like "metadata/title" are invalid while values like "metadata" are valid values. order ­ specify the order to use when mapping the class fields. The default value is the empty array (i.e. no specific order).

2.

Example:
@XObject (value="author", order={"item1", "item2"}) public class Author { ... } @Xobject public class Name { ... }

2.2 XNode
This annotation is supported only on fields. It binds a field to a single XML node. This annotations supports 2 attributes:
1.

value ­ specify the path of the XML element to bind to. Only descending paths are supported (i.e. paths descending the XML tree). The empty path is supported and refers to the current element. XML Elements are separated by using '/' characters. if you want to specify an attribute node you should use an '@' character. Paths are always relative to the element corresponding to the current container object. The following paths are valid XMap paths:


"/metadata/author/name" "metadata/author/name" ""

Document type I All Rights Reserved. I Page 5/14


Project title I Document title



"metadata/author@id" "@name" while the following paths are invalid:

2.

"../metadata/author/name" "../../metadata" "../"

trim ­ specify whether or not the XML string value should be trimmed before being applied to the field. The default is "true".

Example:
@XNode("metadata/title") public String title;

@XNode("metadata/description") public String description;

@XNode("metadata/name") public Name name;

@XNode(value="content", trim=false) public String content;

@XNode("@id")

private String id;

2.3 XNodeList
This annotation is supported only on fields. It is binding a field to a list of XML nodes. The field should be either an array or a Java Collection. This annotations supports 4 attributes:
1. 2. 3. 4.

value ­ the same as for XNode value. trim - the same as XNode trim. type ­ the collection or the array type. comp on e ntType ­ the type of the collection (or array) elements. Example:

@XNodeList(value="list/item", type=ArrayList.class, componentType=String.class)
public List<String> items;

Document type I All Rights Reserved. I Page 6/14


Project title I Document title

@XnodeList(value="author@name", type=String[].class, componentType=String.class) public String[] names;

2.4 XNodeMap
This annotation is supported only on fields. It binds a field to a map of XML nodes. The field should be a Java Map. This annotation supports 5 attributes:
1. 2. 3.

value ­ the same as for XNode value. trim - the same as XNode trim. key ­ a path to the node used as the Map key. The path is the same as for the XNode value with an additional constraint ­ only attribute nodes can be used as keys. type ­ the Map type. comp on e ntType ­ the type of the Map values. Example:

4. 5.

@XNodeMap(value="properties/property", key="@name", type=HashMap.class, componentType=String.class) public Map<String, String> properties;

2.5 XContent
This annotation is supported only on fields. It binds a field to a the content of the given XML node. The content is either set as a String (by serializing the XML content) either set as a DocumentFragment depending on the field type. This annotations supports only 1 attribute:
1.

value ­ the same as for XNode value.

Example:
@XContent("testContent") public String testContent; @XContent("testContent") public DocumentFragment testContent2;

2.6 XParent
This annotation is supported only on fields. It binds a field to a the content of the parent object. The parent object is the object that contains the current object as a field. This annotations has no attributes. Example:

Document type I All Rights Reserved. I Page 7/14


Project title I Document title

@XParent public Author owner;

Document type I All Rights Reserved. I Page 8/14


Project title I Document title

3 Mapping complex eld objects
What happens when a mappable object contains a field that is another mappable object? As you may expect the field is detected as being mappable (the XObject annotation is found) and the mapping context is set to the element corresponding to this field. When mapping a complex field the XParent annotation can be used to refer to the parent object. In the following example you can see how the Author object is containing a mappable member of type Name:
@XObject (value="author", order={"item1", "item2"}) public class Author { ... @Xnode("metadata/name") public Name name; ... } @Xobject public class Name { @Xparent public Author owner; @Xnode("firstName") public String firstName; @Xnode("lastName") public String lastName; @XNode("") public Element myself; }

Document type I All Rights Reserved. I Page 9/14


Project title I Document title

4 Value Factories
How are values applied from XML nodes to object fields? When binding DOM nodes to object fields string values are converted to objects of the same type as the field. This is done by using a registry of value factories - see org.nuxeo.xmap.XValueFactory. There is a built-in set of value factories that covers common primitive types and some common Java types. Here is the list of built-in value factories:
1. 2. 3. 4. 5. 6. 7. 8. 9. 10.

Integer Long Double Float Boolean String Date File URL Class

This means string values are correctly set to fields having these types. When mapping fields with types not listed here you should register a value factory that is able to convert a string value to your desired type. Example of how to set up a custom value factory that constructs a ComponentName object given a String value:
XMap xmap = new XMap(); xmap.setValueFactory(ComponentName.class, new XValueFactory() { @Override public Object getValue(Context context, String value) { return new ComponentName(value); } });

Document type I All Rights Reserved. I Page 10/14


Project title I Document title

5 XMap Context
The Class value factory uses the XMap Context class loader to load the class from the class name string. The default XMap Context uses the current thread context class loader to load classes. The context can be customized by extending the default context to be able to change the class loading rules. This allows for example to integrate XMap with OSGi bundles by changing the class loader used by XMap by the class loader of the bundle that contains the classes to load. Without this feature the class loading would failed in an OSGi environment. On Eclipse this sort of problems are resolved by using the Eclipse-BundlePolicy header.

Document type I All Rights Reserved. I Page 11/14


Project title I Document title

6 Example
Here is a complete example on how XMap can be used to map an XML file to Java objects. Let's say we have an XML containing a set of book elements and we have a Java Book object that we want to map to a book field. Each book contains a complex element author that contains two fields: rstName and lastName. We want to map these elements into a Java object of type Name. Here is the XML file we have as input:
<?xml version="1.0"?> <library> <book id="book1"> <title>Book 1</title> <subject>Software</subject> <subject>Computers</subject> <author> <firstName>JohnFirstName</firstName> <lastName>JohnLastName</lastName> </author> </book> <book id="book2"> <title>Book 2</title> <subject>Sport</subject> <author> <firstName>BillFirstName</firstName> <lastName>BillLastName</lastName> </author> </book> </library>

And here we have the 2 Java objects we want to map:
1.

The Book class:

public class Book { @XNode() private String tile; @XNodeList(value="subject", type=String[].class, componentType=String.class) private String[] subjects; @Xnode("name") private Name name;

Document type I All Rights Reserved. I Page 12/14


Project title I Document title

public String getTile() { return tile; } public void setTile(String tile) { this.tile = tile; } public String[] getSubjects() { return subjects; } public void setSubjects(String[] subjects) { this.subjects = subjects; } public Name getName() { return name; } public void setName(Name name) { this.name = name; } }

2.

The Name class

@Xobject public class Name { @Xnode("firstName") private String firstName; @Xnode("firstName") private String lastName; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; }

Document type I All Rights Reserved. I Page 13/14


Project title I Document title

}

To load the XML document we need to create an instance of XMap, to explicitly register the top level classes (in other case the Book class) and then to start processing the input document:
try { XMap xmap = new XMap(); xmap.register(Book.class);
URL url = new File("books.xml").toURL();

Object[] result = (Object[]) xmap.loadAll(url); for (Object element : result) { Book book = (Book)element; // do something with that book // ... } } catch (Exception e) { e.printStackTrace(); }

That's all!

Document type I All Rights Reserved. I Page 14/14