Mobile RDF

RDF Resource Description Framework Icon
A Java implementation of Resource Description Framework


Author:Michael Hedenus
Date:09-2008
Version:0.3

Table of Contents

Synopsis

This is a free and open source Java implementation of Resource Description Framework. The design goals are:

Actually I stick to Java ME Personal Profile because I want to use the collection framework of java.util and have at least some UI (AWT).

The current implementation provides following features:

The XML parser has support for character encoding detection, UTF-8, UTF-16 (big and little endian), xml:base, xml:lang, xml:id, xml:space, general internal parsed entities.

This is an early release but I hope you find it useful. I am looking forward to any kind of feedback - criticism is welcome, too.

The download contains all source including the code examples, binaries, Java-docs and a ready-to-install jar.

Examples

Instead of bothering you with long text I present some code examples to show how Mobile RDF works.

Example 1: Parsing a RDF-XML file

Let's start with parsing. A simple example a RDF-XML file is loaded into a graph and the new statements are printed out.

	// an new RDF graph
	RDFGraph graph = new RDFGraph();
	
	// an RDF event listener which translates RDF events
	// to add new statements to the graph
	GraphBuilder graphBuilder = new GraphBuilder(graph);
	
	// an RDF XML parser
	RDFXMLParser rdfXmlParser = new RDFXMLParser();
	rdfXmlParser.parse(graphBuilder, new URL("http://www.hedenus.de/rdf/example1.rdf")); 
	
	// print the statements to System.out
	graph.dump();

The output is in form of N-Triples:

<http://www.hedenus.de/rdf/example1.rdf> <http://purl.org/dc/elements/1.1/description> "An example file."@en .
<http://www.hedenus.de/rdf/example1.rdf> <http://purl.org/dc/elements/1.1/creator> <http://www.hedenus.de/foaf.rdf#Michael> .
<http://www.hedenus.de/rdf/example1.rdf> <http://purl.org/dc/elements/1.1/date> "2008-07-13"^^<http://www.w3.org/2001/XMLSchema#date> .

Example 2: Manipulating the RDF model

Of course the graph can also be manipulated directly:

	// new graph
	RDFGraph graph = new RDFGraph();
	
	// the subject resource
	URIRefNode subject = graph.createURIRefNode("http://www.hedenus.de/rdf/Example2");
	
	// the property URI
	String predicate = Namespaces.DUBLINCORE11+"description";
	
	// the object literal
	// the second argument is the datatype
	Literal object = graph.createLiteral("Hello World.", null, "en");
	
	// create statement
	Statement statement = graph.createStatement(subject, predicate, object);
	System.out.println(statement);

The output is then:

<http://www.hedenus.de/rdf/Example2> <http://purl.org/dc/elements/1.1/description> "Hello World."@en .

Example 3: Serialization

Currently the graph can be serialized as RDF-XML or in form of Graph Modelling Language. Append following lines to the code of Example 1:

	new RDFXMLSerializer().serialize(graph, new File("example3_output.rdf"));
	new GMLSerializer().serialize(graph, new File("example3_output.gml"));

The resulting RDF-XML output is like:

<?xml version="1.0" encoding="US-ASCII"?>
<!-- created Sun Jul 13 22:28:47 CEST 2008-->
<!DOCTYPE rdf:RDF [
	<!ENTITY dc "http://purl.org/dc/elements/1.1/">
	<!ENTITY rdfs "http://www.w3.org/2000/01/rdf-schema#">
	<!ENTITY geo "http://www.w3.org/2003/01/geo/wgs84_pos#">
	<!ENTITY xsd "http://www.w3.org/2001/XMLSchema#">
	<!ENTITY owl "http://www.w3.org/2002/07/owl#">
	<!ENTITY rss "http://purl.org/rss/1.0/">
	<!ENTITY mh "http://www.hedenus.de/Ontologie/">
	<!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#">
]>
<rdf:RDF
	xmlns:dc="&dc;"
	xmlns:rdfs="&rdfs;"
	xmlns:geo="&geo;"
	xmlns:xsd="&xsd;"
	xmlns:owl="&owl;"
	xmlns:rss="&rss;"
	xmlns:mh="&mh;"
	xmlns:rdf="&rdf;"
	>

	<rdf:Description rdf:about="http://www.hedenus.de/rdf/example1.rdf">
		<dc:creator rdf:resource="http://www.hedenus.de/foaf.rdf#Michael"/>
		<dc:date rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2008-07-13</dc:date>
		<dc:description xml:lang="en">An example file.</dc:description>
	</rdf:Description>
</rdf:RDF>

The GML output can be loaded and rendered by a suitable application, e.g. yEd. yEd really makes beautiful graph renderings:

Example 4: RDF-Schema

So far so good, these examples were the basics. If you want to work with RDF, the next step is RDF-Schema. RDF-Schema provides the notation of classes, so a databinding framework which maps rdfs:Class resources to Java objects suggests itself.

The central interface is de.hedenus.rdfschema.Resource which represents a rdfs:Resource. Other classes which are defined by RDF/RDF-Schema are represented by sub-interfaces. They provide convenience methods like de.hedenus.rdfschema.Container.li(int) or de.hedenus.rdfschema.List.iterator().

The following example code creates a databinding instance which is backed by a RDF graph. You can access resources and list their properties.

	// a new databinding (includes the graph)
	RDFDatabinding dataBinding = new RDFDatabinding();
	
	// parse the RDF file
	dataBinding.parse(new URL("http://www.hedenus.de/rdf/example4.rdf"));
	
	// get a resource
	Resource example4 = dataBinding.getResource("http://www.hedenus.de/rdf/example4.rdf");
	
	// list all dc:description properties
	Resource[] hellos = example4.getProperties(Namespaces.DUBLINCORE11 + "description");
	for (int i = 0; i < hellos.length; i++)
	{
		System.out.println(hellos[i]);
	}
	
	// list only (first) french dc:description
	System.out.println(example4.getProperty(Namespaces.DUBLINCORE11 + "description", (Locale)null));

Typed literals are also supported. For example, a xsd:dateTime property can be accessed as follows:

	DateTime dateTime = (DateTime)example4.getProperty(Namespaces.DUBLINCORE11 + "date", Namespaces.XMLSCHEMA + "dateTime");
	System.out.println(dateTime.toDate());

The datatypes are internally created and mapped by de.hedenus.xmltypes.TypeFactory. Currently the most important XML Schema types are implemented. Here is a list of the mapped types.

Example 5: RDF-Schema Databinding Framework

To add more convenience, you can specifiy special Java-RDF type bindings. This is done in a subclass-from-basetype-way. I am experimenting with a POJO-annotations-approach, but this is for Java 5 and will also include a special marshaller/unmarshaller.

You can subclass from de.hedenus.rdfschema.ResourceImpl and add methods you like. As an example I create a class for RSS 1.0 channels. The new method items() gets the rdf:Seq of items (which is a rdfs:Container) and returns it as java.util.List:

	public class Channel extends ResourceImpl
	{
		public static final String URI = Namespaces.RSS10 + "channel";
	
		public List items()
		{
			Container seq = (Container)getProperty(Namespaces.RSS10 + "items");
			return seq.toList();
		}
	}

Now you must register your new implementing class. This done by creating a mapping text file (encoded US-ASCII) which contains URI-class pairs, separated by whitespace, one pair per row. You must put the file in the classpath as 'rdfschema/typemapping'.

; Java type mapping of RSS channel
http://purl.org/rss/1.0/channel de.hedenus.mobilerss.Channel

Well, this is the most simple way. I started to write a RDF-to-Java code generator (generating getter/setter methods from rdf:Property/rdfs:range/rdfs:domain), but I think it is not worth the trouble.

A class for a RSS item can look like this:

	public class Item extends ResourceImpl
	{
		public static final String URI = Namespaces.RSS10 + "item";
		
		public String getTitle()
		{
			return String.valueOf(getProperty(Namespaces.RSS10 + "title", (String)null));
		}
	
		public String getDescription()
		{
			return String.valueOf(getProperty(Namespaces.RSS10 + "description", (String)null));
		}
	}

Finally, reading a RSS feed becomes quite easy:

	// a new databinding (includes the graph)
	// type mappings will be loaded from 'rdfschema/typemapping'
	RDFDatabinding dataBinding = new RDFDatabinding();

	// parse a RSS resource
	String home = "http://www.w3.org/2000/08/w3c-synd/home.rss";
	dataBinding.parse(new URL(home));

	// get the channel instance
	// (it is assumed that the channel URI is the same as the resource URL)
	Channel channel = (Channel)dataBinding.getResource(home);

	// the items are listed in form of rdf:Seq
	for (Iterator i = channel.items().iterator(); i.hasNext();)
	{
		// print next item
		Item item = (Item)i.next();
		String title = item.getTitle();
		System.out.print(title);
		
		// lookup an optional date information
		Date date = (Date)item.getProperty(Namespaces.DUBLINCORE11 + "date", Namespaces.XMLSCHEMA + "date");
		if (date != null)
		{
			System.out.print(" (" + date.toString() + ")");
		}
		
		System.out.println();
	}

Example Application

As an example application I have written a simple RSS 1.0 client. The client will load and display the items of a specified RSS source file.

The application is suitable for Java Personal Profile and has been tested for Nokia 9500. Simply install the JAR file which is bundled in the download on your device. The following screenshots show what will happen:

(1) Start of RSS Client with a preselected URL. Now just click enter or click the button.

(2) The client loads the data - please be patient.

(3) When accessing the channel was successful the UI switches to a list of items. Use the up-down keys to scroll to an item and hit enter to select it.

(4) The item is displayed in a text panel. Use the TAB key to switch to the tab list on the right and to go back to the item list.

Implementation Status

The RDF-XML parser lacks implementation of following features:

License

This software is released under the Apache License 2.0. I appreciate if you send me an email about your application and give me some feedback.

Download

Get the complete bundle including sources, binaries and API docs.


Impressum