Nested Class Mapping
Hopefully, you can see the problem with nested Collections. In this example, you could keep the List of Map/HashMap objects, but that definitely complicates the code.
There is nothing to modify in the POJO, because it's got List already. But you'll need to modify the test application to store HashMap in the List. You cannot use java.util.HashMap, because it doesn't have appropriate getters and setters, which are required. You also will need to create your own wrapper class. The HMap.java is very simple. It has a public attribute of the Map type and the default constructor which instantiates it:
package us.prokhorenko.jx;
import java.util.*;
public class HMap {
public Map hm;
public HMap() {
this.hm = new HashMap();
}
}
Now, you need to modify the test application. First, modify where the application marshalls:
// Marshalling class to XML
List myList = new ArrayList();
// Prepare a HashMap and put it to the List
HMap hma = new HMap();
hma.hm.put("zzz", "value of zzz");
hma.hm.put("yyy", "value of yyy");
myList.add(hma);
l.add("List#1");
l.add("List#2");
// Create the Person class
Person person = new Person("Mr. White", "mr@white", "626-555-1234", myList);
// We have a mapping, apply it
Mapping mapping = new Mapping();
mapping.loadMapping("mapping.xml");
// Marshal and save to XML file
FileWriter file = new FileWriter("person.xml");
Marshaller m = new Marshaller(file);
m.setMapping(mapping);
m.marshal(person);
file.close();
You should also remove some old code, which adds String to the List. Next, modify where the app unmarshalls:
// Unmarshalling XML to class
// Read from XML and unmarshal
FileReader uFile = new FileReader("person.xml");
Unmarshaller u = new Unmarshaller(mapping);
Person uPerson = (Person)u.unmarshal(uFile);
// Show name and email
System.out.println("name: " + uPerson.getName());
System.out.println("email: " + uPerson.getEmail());
List myList = new ArrayList();
myList = uPerson.getMyList();
System.out.println("myList[0]: " + (String)myList.get(0));
HMap hma = new HMap();
hma = (HMap)myList.get(0);
System.out.println("myList[0][yyy]: " + hma.hm.get("yyy"));
Also, do not forget to place import us.prokhorenko.jx.HMap in the code. As you can see, the changes are very simple and don't go beyond regular Java code.
At this point, everything is ready except the new mapping for the XML. For this, you will use nested class mapping, which is useful when you need to specify more than one mapping for a particular class:
<?xml version="1.0" encoding="UTF-8"?>
<mapping>
<class name="us.prokhorenko.jx.Person">
<map-to xml="person"/>
<field name="email" type="string">
<bind-xml name="email" node="element"/>
</field>
<field name="phone" type="string">
<bind-xml name="phone" node="element"/>
</field>
<field name="name" type="string">
<bind-xml name="name" node="element"/>
</field>
<field name="myList" type="java.util.List" collection="arraylist">
<b> <bind-xml name="myList" node="element">
<class name="us.prokhorenko.jx.HMap">
<field name="hm" type="java.util.HashMap"
collection="map" direct="true">
<bind-xml name="hm" node="element"/>
</field>
</class>
</bind-xml></b>
</field>
</class>
</mapping>
Note the direct="true" option passed to field. This allows direct access to a public class variable (hm, in this example).
Now that the necessary changes have been made, it's time to build and run the code. After running the test application, you will see how the person.xml has changed:
<?xml version="1.0" encoding="UTF-8"?>
<person>
<myList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="java:us.prokhorenko.jx.HMap">
<hm xsi:type="java:org.exolab.castor.mapping.MapItem">
<key xsi:type="java:java.lang.String">yyy</key>
<value xsi:type="java:java.lang.String">value of yyy</value>
</hm>
<hm xsi:type="java:org.exolab.castor.mapping.MapItem">
<key xsi:type="java:java.lang.String">zzz</key>
<value xsi:type="java:java.lang.String">value of zzz</value>
</hm>
</myList>
<email>prokhorenko@gmail.com</email>
<name>Olexandr Prokhorenko</name>
<phone>123-555-1234</phone>
</person>
And output will also look like the following:
name: Olexandr Prokhorenko
email: prokhorenko@gmail.com
myList[0][yyy]: value of yyy
Running the Code
If you use the supplied build.xml, you will get the code built in the ./build directory. Make sure you've copied the mapping.xml there from ./src/us/prokhorenko/jx and you are running from it. You will also need the following libraries available either in your CLASSPATH or passed as java -cp ...:
castor-1.0M1.jar
castor-1.0M1-xml.jar
commons-logging.jar
xerces-J_1.4.0.jar
A Time-Saver
Hopefully, this will save you some time and will help to startup your code in the shortest terms.
Resources
New on the Java Boutique:
New Review:
Time Management Made Easy with the Quartz Enterprise Job Scheduler
Why not just use the Java timer API? This open source scheduling
API boasts simplicity, ease-of-integration, a well-rounded feature
set, and it's free!
New Applet:
Reverse Complement
Reverse Complement is a simple applet that converts DNA or RNA
sequences into three useful formats.
Elsewhere on internet.com:
WebDeveloper Java
Lots of Java information on webdeveloper.com
WDVL Java
Thorough Java resource at the Web Developer's Virtual Library.
ScriptSearch Java
Hundreds of free Java code files to download.
jGuru: Your View of the Java Universe
Customizable portal with online training, FAQs, regular news updates, and tutorials.
|