Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Meet Jena, a Semantic Web Platform for Java : Page 3

Tools for developing semantically aware applications are rapidly growing more Java friendly. Take a closer look at Jena, an open source toolkit for processing and working with semantic web data.

Jena's Model Abstraction
Jena represents an RDF graph as an instance of the class Model. Abstractly, a Model holds a set of Statement objects, each of which is one RDF triple. Of course, the storage schemes vary for different types of Model, and these schemes try to be both compact and efficient to process under a range of usages.

Model itself is a Java interface, not a class, which allows different types of triple store to present the same interface to user code, as you'll see in upcoming examples. The consequence, though, is that client code can't construct a Model directly. Instead, application code invokes the ModelFactory. The simplest kind of model, which uses an in-memory storage model and has no inference or any other cleverness, is created by ModelFactory.createDefaultModel(). Looking at the Javadoc, it's quickly clear that Model has a daunting number of methods. However, they group into a small number of operation types:

  • I/O operations for reading and writing RDF documents in a variety of syntaxes
  • Query operations for listing the resources and statements contained in a model
  • Update operations for creating and removing statements
  • Support for RDF's reification capability (making statements about statements)
  • Utilities, such as transaction support, critical section locking, and so on
One class of operations that's not in the Model API is in-place updating of resources, statements, and literals. There's no setURI() in the Resource API. All of Jena's key abstractions are immutable, and update can be achieved only by removing the old and adding the new.

This next example shows a few of the Model API methods in action. The objective this time is to list every resource of rdf:type FOAF Person and then for each of those show the person's name, if it is known:

protected void run() { // use the file manager to create a plain model holding the sample FOAF file Model m = FileManager.get().loadModel( HelloWorld.FOAF_FILE ); listPeople( m ); } /** Print out all named resources of type foaf:Person */ protected void listPeople( Model m ) { // get all resources of type foaf:Person Resource personClass = m.getResource( FOAF_NS + "Person" ); ResIterator i = m.listSubjectsWithProperty( RDF.type, personClass ); // for each person, show their foaf:name if known Property name = m.getProperty( FOAF_NS + "name" ); Property firstName = m.getProperty( FOAF_NS + "firstName" ); while (i.hasNext()) { Resource person = i.nextResource(); Statement nm = person.getProperty( name ); nm = (nm == null) ? person.getProperty( firstName ) : nm; if (nm != null) { System.out.println( "Person named: " + nm.getString() ); } } }

Arguably, accessing the Model API this way provides a fairly low-level view of the RDF graph. Other query techniques, such as the SPARQL query language, provide a more compact and powerful query notation, but that's material for a future article.

In principle, there's no difference in accessing a simple memory model or any of the more sophisticated model variants. Some of these variants will be explored shortly, but it's worth remembering that whether the model is an unadorned, in-memory data structure; an inference engine; or a view of a relational database, the core API remains the same. This consistency underpins some useful modularity in Jena. The SPARQL query engine, for example, runs queries against any model; to perform SPARQL queries over the logical entailments of an ontology, simply pass the SPARQL engine an inference-backed Model.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.