Mobile RDF |
|
A Java implementation of Resource Description Framework |
Author: | Michael Hedenus |
Date: | 09-2008 |
Version: | 0.3 |
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:
rdfs:Class
to Java classes. The basic RDF/RDF-Schema classes
like rdf:List
or rdfs:Container
are implemented.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.
Instead of bothering you with long text I present some code examples to show how Mobile RDF works.
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> .
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 .
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:
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.
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(); }
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.
RDFGraph.removeStatement
, and Resource.setProperty
.The RDF-XML parser lacks implementation of following features:
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.
Get the complete bundle including sources, binaries and API docs.