Tutorial: Monomorphic Java - ecologylab/simpl GitHub Wiki
Introduction
Java Annotated Classes
Translation Scopes
Translating XML
In this tutorial we give a brief example of how S.IM.PL serialization can be used to translate between xml and java annotated classes. The particular xml scheme that this example focuses on is RSS.
To view this tutorial you will need to download the entire simplTutorials, simplTranslators and ecologylabFundamental projects. Access to the ecologylab fundamental project source is available through anonymous SVN access (user: anonymous, password: anonymous).
If you used the tutorial for setting up your dev environment (https://github.com/ecologylab/simpl/wiki/Check-out-code-and-set-up-development-environment) you should already have this tutorial. It is located under simplJava/SimplTutorial/src/ecologylab/tutorials/rss/MonomorphicJavaTutorial
The following are the set of classes defined to represent the Rss xml structure. Note that each of these classes extends ElementState, which is the root class of all classes that intend to use translation. In addition to being a subclass of ElementState, each class has an annotated set of fields. These fields can either be translated into attributes of the class's tag or into elements nested within the class element.
Rss is the definition for the root Rss element. It contains a single scalar version, which is annotated by @simpl_scalar, and composite element Channel, annotated by @simpl_composite. It is important to note that class names and field names are associated with tags and attributes in the xml based on a default translation. In the case of Rss, s.im.pl serialization uses the part of the name prior to "State" by default.
//Rss.java
package ecologylab.tutorials.rss;
import ecologylab.serialization.ElementState;
public class Rss extends ElementState
{
@simpl_scalar float version;
@simpl_composite Channel channel;
public Rss() {}
}
Now we'll take a look at Channel, the composite component of Rss. Channel has several sub-elements. These sub-elements are all of types that we refer to as scalar. So in this case to specify that they are sub-elements rather than attributes we use the @simple_hints(Hint.XML_LEAF) annotation.
In addition, channel contains a collection. This is a collection of "items". In Rss, this collection is not contained within a seperate element. For this reason, we specify the @simpl_nowrap annotation, which indicates that the collection should not be contained within a sub-element. The @simpl_collection("item") annotation specifies two things. First, it specifies that the collection items should be translated. Second, it associates a tag name of "item" with the collection. This ensures that the translated elements of items have the tag name "item".
//Channel.java
package ecologylab.tutorials.rss;
import java.util.ArrayList;
import ecologylab.net.ParsedURL;
import ecologylab.serialization.ElementState;
public class Channel extends ElementState
{
@simpl_scalar @simpl_hints(Hint.XML_LEAF) String title;
@simpl_scalar @simpl_hints(Hint.XML_LEAF) String description;
@simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL link;
@simpl_nowrap
@simpl_collection("item")
ArrayList<Item> items;
public Channel() { }
public ArrayList<Item> getItems()
{
return items;
}
}
Finally, we define the item class. An item has several sub elements, each of which is a leaf. An item may also have a collection of category elements. Here we use the same annotation as before with items.
//Item.java
package ecologylab.tutorials.rss;
import java.util.ArrayList;
import ecologylab.net.ParsedURL;
import ecologylab.serialization.ElementState;
public class Item extends ElementState
{
@simpl_scalar @simpl_hints(Hint.XML_LEAF) String title;
@simpl_scalar @simpl_hints(Hint.XML_LEAF) String description;
@simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL link;
@simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL guid;
@simpl_scalar @simpl_hints(Hint.XML_LEAF) String author;
@simpl_nowrap
@simpl_collection("category")
ArrayList<String> categorySet;
public Item() {}
}
Translation scopes are used to specify the set of classes available for translation when translating from xml. Here we define a class with a static method that returns a translation scope referencing all of the Rss classes: Rss, Channel, and Item.
//RssTranslations.java
package ecologylab.tutorials.rss;
import ecologylab.generic.Debug;
import ecologylab.serialization.TranslationScope;
public class RssTranslations extends Debug
{
public static TranslationScope get()
{
return TranslationScope.get("rss", Rss.class, Channel.class, Item.class);
}
}
In order to translate from XML we must acquire the proper translation scope.
public static void main(String[] args) throws IOException,
XMLTranslationException
{
TranslationScope rssTranslations = RssTranslations.get();
Next we'll read in the Rss feed for a comparison with the translated version.
URL url = new URL("http://www.xkcd.com/rss.xml");
String rssContent = readURL(url);
System.out.println("Raw RSS Feed:");
System.out.println(rssContent);
Now we'll translate the xml feed into an Rss object and then translate back to xml. Notice how if there are parts of the xml that are not annotated with the classes that they are simply ignored. In this case channel's language element and item's pubDate element.
Rss feed = (Rss) rssTranslations.deserialize(url);
System.out.println("\nFeed translated back to xml by s.im.pl serialization:");
System.out.println(feed.serialize());
In this last section we will create our own channel item and then put it in the Rss feed. Note we can just create an instance of item and set all of it's instance variables to the values that we wish. Then we just add the new item to the channel's list of items and translate back to xml.
Item ecologylabItem = new Item();
ecologylabItem.setTitle("The Interface Ecology Lab");
ecologylabItem
.setDescription("Highlights the cool research going on at the lab.");
ecologylabItem.setAuthor("Dr. Andruid Kerne");
ecologylabItem
.setLink(new ParsedURL(new URL("http://www.ecologylab.net")));
feed.getChannel().getItems().add(0, ecologylabItem);
System.out.println("\nFeed translated to xml with our added item:");
System.out.println(feed.serialize());
}