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


Let Semantics Bring Sophistication to Your Applications : Page 5

Leverage semantic technology and the W3C's Web Ontology Language standard to spice up a query-based application.

Putting It All Together
Enough talk; it's time to build your sommelier! You might be surprised at how easy it really is. I would feel like a failure as a guide if I didn't show one test for your sommelier first:

src/test/java/com/devx/semantics/sommelier/SommelierTest.java ... public void testRecommendWine_FullBody() { WineDescriptor descriptor = new WineDescriptor(); descriptor.setBody(BODY.Full); List<Wine> recommendedWines = sommelier.recommendWine(descriptor); for (Wine wine : recommendedWines) { assertEquals("Full", wine.getBody()); } assertEquals(16, recommendedWines.size()); } ...

This test first constructs a WineDescriptor object to contain the factors I would like to use in wine selection. In this case, I chose to verify the number of full-bodied wines returned. Although there are 11 wines in your wine ontology that are asserted (explicitly defined) as full-bodied wines, I chose to verify that 16 wines are recommended. Why? Because I wanted to test that the sommelier can properly infer wines that are full-bodied implicitly because of their classification.

Now turn your attention to the sommelier. The first job of the sommelier is to read in the wine ontology. I have chosen to do this in the default constructor:

src/main/java/com/devx/semantics/sommelier/Sommelier.java ... private static final String uri = "http://www.w3.org/TR/2003/CR-owl-guide-20030818/wine#"; private Model model; public Sommelier() { OntModel ontModel = ModelFactory.createOntologyModel(); ontModel.read(Sommelier.class.getResourceAsStream("/wine.owl"), "http://www.w3.org/TR/2003/CR-owl-guide-20030818/wine"); model = ModelFactory.createInfModel( PelletReasonerFactory.theInstance().create(), ontModel); } ...

For this application, I have chosen to use Jena (a Java-based semantics framework) because it is lightweight, easy to use, and supports OWL and SPARQL. In the constructor, read in the wine ontology (wine.owl) from the class path and declare that the base URI for resources local to this ontology is http://www.w3.org/TR/2003/CR-owl-guide-20030818/wine. Next, create an instance of a PelletReasoner, and instruct the reasoner to create a new ontology that includes the asserted and inferred relationships. Pellet is a separate tool from Jena; it implements Jena's Reasoner interface.

Next, implement the wine recommendation logic:

src/main/java/com/devx/semantics/sommelier/Sommelier.java ... public List<Wine> recommendWine(WineDescriptor descriptor) { String query = "SELECT DISTINCT ?s WHERE { "; query = query + createBodyPattern(descriptor); query = query + createFlavorPattern(descriptor); query = query + createColorPattern(descriptor); query = query + "}"; QueryExecution qexec = QueryExecutionFactory.create(query, model); ResultSet results = qexec.execSelect(); List<Wine> wines = new ArrayList<Wine>(); while (results.hasNext()) { ... } return wines; } private String createBodyPattern(WineDescriptor descriptor) { if (descriptor.getBody() != null) { return "?s <" + uri + "hasBody> <" + uri + descriptor.getBody() + "> ."; } else { return ""; } } ...

This section of code creates the SPARQL query and executes it against the inferred model. The results are traversed and a list of wines is packaged and returned to the caller. Inside the while loop, I use the Jena API directly to navigate to the subject returned from the query and construct a wine object that contains the relevant properties (color, body, and flavor) to describe the subject.

src/main/java/com/devx/semantics/sommelier/Sommelier.java ... public List<Wine> recommendWine(WineDescriptor descriptor) { ... ResultBinding result = (ResultBinding) results.next(); RDFNode node = result.get("s"); String name = getNameOfNode(node); String body = getPropertyForNode("hasBody", node); String flavor = getPropertyForNode("hasFlavor", node); String color = getPropertyForNode("hasColor", node); wines.add(new Wine(name, body, flavor, color)); ... } private String getNameOfNode(RDFNode node) { Resource resource = (Resource) node.as(Resource.class); return resource.getLocalName(); } private String getPropertyForNode(String property, RDFNode node) { Resource resource = (Resource) node.as(Resource.class); Statement statement = resource.getProperty( model.getProperty(uri + property)); return getNameOfNode(statement.getObject()); } ...

In this code retrieve the subject in the form of a RDFNode from the result, and then determine its name and properties. To determine the properties of the resource, navigate the statement formed between the subject and the property (hasBody, for example) and then programmatically read the name of the corresponding object. This process is used to find the values for body, flavor, and color for each result of the SPARQL query executed earlier.

You also can download the full source code for this article, if you are so inclined.

Here's to You
You have covered quite a bit of ground during this article. You have taken a high-level look at semantics, ontologies, and some of the technologies and tools behind them. Hopefully this fairly high-level overview has helped you to formulate an understanding of how semantic technologies fit together, and how you might begin to integrate some of these technologies into your own applications. For a more detailed treatment of this subject area, consult these related resources, and keep your eye out for future articles from DevX that will cover this topic.

Related Resources:

Rod Coffin is an agile technologist at Semantra, helping to develop an innovative natural language ad hoc reporting platform. He has many years of experience mentoring teams on enterprise Java development and agile practices and has written several articles on a range of topics from Aspect-Oriented Programming to EJB 3.0. Rod is a frequent speaker at user groups and technology conferences and can be contacted via his home page.
Comment and Contribute






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



Thanks for your registration, follow us on our social networks to keep up-to-date