RDF/OWL tempts us to compare it’s type system with Java, however, the two are different in substantial ways. OWL allows RDF resources to inherit from more that one class. Furthermore, there is no such thing as an RDF “interface”. Perhaps the most striking difference are properties. RDF properties aren’t owned by any particular class. They can be in the domain of many classes, and can inherit from other properties. Furthermore, classification (typing) can be inferred from the properties given to a RDF resource. If something has a foaf:mbox, it’s a foaf:Agent. Note how that’s the complete opposite of how we nomaly think in OOP…”If the object is an instance of Agent, by definition it must have an mbox property.”. This is the motivation for “jenathing”, my moniker for what is essentialy a very simple utility class…thewebsemantic.Thing.
Introduction
Let’s say we have a jena model, m, created as…
Model m = ModelFactory.createDefaultModel();
To create a new resource (a new Thing) we’ll need a URI and the model, combined via constuctor:
Thing t = new Thing(“http://example.com/1″,m);
At this point the model hasn’t changed. Thing loosely wraps the Jena resource type, and we haven’t said anything about “http://example.com/1″ as of yet. So let’s assert a DublinCore property:
t.as(DublinCore.class).subject(“owl”);
<http://example.com/1>
dc:subject “owl”^^xsd:string
Now we’ve said something. The magic comes to us via a simple interface definition, DublinCore:
@Namespace(“http://purl.org/dc/elements/1.1/”)
public interface DublinCore extends As {
public DublinCore subject(String s);
“subject()” tells the Thing to create a dynamic proxy. The method name is placed within the context of the interface’s namespace, allowing Thing to declare the appropriate RDF property within our model. Notice that the setters return back the same DublinCore interface, allowing for a builder api:
Thing me = new Thing(“http://tcowan.myopenid.com”, m);
t.as(DublinCore.class).
creator(“me”).
subject(“binding”).
subject(“owl”).
subject(me).
title(“The web semantic”)
And last but not least, you can “polymorph” your Thing into another interface using “as”. In this case “t” is being used to assert Foaf properties:
title(“The web semantic”).
as(FoafThing.class).
made(new Thing(“http://thewebsemantic.com”,m)).
made(new Thing(“http://tripblox.com,”,m)).
mbox(new Thing(“mailto:gorby.kremvax@example.com”,m))
;
Creating Jena Thing Interfaces
Jena Thing is convention based. It looks for methods prefixed with either “set”, “add”, or “get”.
Declaring your Interface
All Jena Thing interfaces need a namespace. This will be used as the namespace for all properties declared in your interface. Use the @Namespace annotation along with desired namespace like this:
@Namespace(“http://purl.org/dc/elements/1.1/”)
public interface DublinCore extends As { …
Although it’s not a requirement, it’s friendly to extend the “As” interface. This makes it easy to morph your Thing to a different interface all in one long line of builder code.
Declaring Setters
Jena Things are not beans. They are always connected to your model, and they don’t use java bean property conventions. Your thing setter methods designate the property name and the type being assigned. You are limited to primitive types (including java.lang.String and java.util.Date) or other “Things”. That’s it…however, it’s pretty much all you’ll need to work with many populare RDF vocabulares. The Dublin Core has a description property that while not necessary “functional” (there can only be one), we’ll assume that’s our intent. To declare that in an interface you’d do the following:
public DublinCore description(String s);
That will allow us to assert a dc:description relationship to a string literal. The pattern is simple, the method name becomes the RDF property after being appended to the name space. Notice the return type. That’s for convenience, and allows you to assert many properties against one subject in a single line of java code. Most dublin core properties will allow for multiple assertions, like subject. To do this, tell Jena Thing that you want to “add” the property:
public DublinCore subject(String s);
You can assert int, long, float, Date, and other primitive types. When you want to associate two resources together just use “Thing” as the setter type. FOAF has it’s mbox property which should point to a resource, not a literal:
public FoafThing mbox(Thing mbox);
Declaring Getters
Getters follow a similar pattern. The getter for our Dublin Core description looks like this:
public String description();
If your property needs to be plural, the return type should be a parameterized Collection<?>. The foaf mbox property would be a Collection of Things:
public Collection<Thing> mbox();
Usage
Visit jenabean.googlecode.com and download the jenabean library. Import thewebsemantic.Thing class in your own code, define your own “Thing” interfaces, and assert away. The examples discussed here can be found at:
http://code.google.com/p/jenabean/source/browse/trunk/?r=433#trunk/src/test/java/test/thing