Creating a Simple Ontology to Query City Information from Geonames.org By Frank Wissinger 1 Table of Contents Introduction ......................................................................................................................... 3 City Ontology...................................................................................................................... 3 Creating City Ontology using Protégé ................................................................................ 4 Query City Information....................................................................................................... 6 Query Output .................................................................................................................. 7 CityInfo.java ................................................................................................................... 7 SemanticLibrary.java .................................................................................................... 10 2 Introduction This document provides an example on how to create a simple city ontology in protégé, how to map the city ontology with the geonames ontology, and how to query city information in jena. City Ontology The following figure illustrates a high level overview on the city ontology. 3 Creating City Ontology using Protégé 1. In protégé, I created ontology with filename city.owl and create a class called “city”. 2. I added Object Property called “nearbyCity”. 4 2. I added Data Property “hasName” and “hasPopulation”. 3. Save the file as “citySchema.owl” and open file city.owl. 4. In the individual tab, create Members “city1” and “city2”. Select “city1” and in the Property assertions tab, add Object assertion property mapping of nearbyCity to city2. 5 5. Select “city2” and in the Property assertions tab, add Object assertion property mapping of nearbyCity to city1. 6. Save the file as “city.owl”. Query City Information. I create a java project called SemanticLibrary and created the following packages: com.semanticlibrary.lib - implement common jena database loading and query com.semanticlibrary.test – test ontology files created from protégé and query geonames database. In the com.semanticlibrary.test package, I created a program called cityInfo.java and did the following: Loaded the citySchema.owl file Loaded the city file Loaded geonames RDF data for New York City and Washington D.C Performed data alignment between city1 and New York City geonames feature reference Performed data alignment between city2 and Washington D.C geonames feature reference Query city data (cityName and Population) Query for city, population, nearbyCity and nearbyCity population. 6 The following is the output from the cityInfo.java program: Query Output Loading Schema Database loaded Find 'City of New York' geonames reference reference=http://sws.geonames.org/7163824/ Find 'Washington' geonames reference reference=http://sws.geonames.org/4140963/ Perform schema alignment Query Data -----------------------------------------------------------------------------------------------| sub | cityName | population | ============================================================================ ==================== | <http://sws.geonames.org/5128638/> | "Nueva York" | "19274244" | | <http://sws.geonames.org/6955102/> | "New York-Northern New Jersey-Long Island" | "19006798" | | <http://sws.geonames.org/5128581/> | "Nueva York" | "8175133" | | <http://sws.geonames.org/7161774/> | "Village of New York Mills" | "3327" | | <http://sws.geonames.org/4140963/> | "Washington" | "601723" | | <http://sws.geonames.org/5125123/> | "Long Island" | "7559372" | | <http://sws.geonames.org/7163824/> | "City of New York" | "8175133" | -----------------------------------------------------------------------------------------------Search city and nearby city ----------------------------------------------------------------------------------| city | cityPopulation | nearbyCity | nearbyCityPopulation | ============================================================================ ======= | "Washington" | "601723" | "City of New York" | "8175133" | | "City of New York" | "8175133" | "Washington" | "601723" | ----------------------------------------------------------------------------------- The following are the files used in the semanticlibrary java project. CityInfo.java package com.semanticlibrary.test; import java.io.IOException; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.Property; import com.hp.hpl.jena.rdf.model.Resource; import com.semanticlibrary.lib.SemanticLibrary; public class cityInfo { static String defaultNameSpace = "http://frankwissinger.wordpress.com/2011/10/example/city#"; static String geonamesApiSearch = "http://api.geonames.org/search?q="; static String geonamesApiParams = "&type=rdf&maxRows=10&lang=es&username=frankWissinger&style=full"; 7 static String geonamesCityQuery =" select DISTINCT ?sub ?cityName ?population { ?sub rdf:type gn:Feature. ?sub gn:name ?cityName. ?sub gn:population ?population} "; static String CityOntologyQuery =" select DISTINCT ?city ?cityPopulation ?nearbyCity ?nearbyCityPopulation {?x city:hasName ?city. ?x city:hasPopulation ?cityPopulation. ?x city:nearbyCity ?near. ?near city:hasName ?nearbyCity. ?near city:hasPopulation ?nearbyCityPopulation } "; static String geonameNewYorkSource=""; static String geonameWashingtonSource=""; /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { SemanticLibrary lib= new SemanticLibrary(); lib.setDefaultNameSpace(defaultNameSpace); lib.loadDatabase(geonamesApiSearch+"New+York"+geonamesApiParams); lib.appendToDatabase(geonamesApiSearch+"Washington+DC"+geonamesApiParams); lib.appendToDatabase("Ontologies/city.owl"); System.out.println("Loading Schema"); lib.LoadSchema("Ontologies/ontology_v2.2.1.rdf"); lib.appendSchema("Ontologies/citySchema.owl"); System.out.println("Database loaded"); System.out.println("Find 'City of New York' geonames reference"); geonameNewYorkSource=executeQueryAndGetStringResults(lib ,geonamesCityQuery,lib.mod, "?cityName", "?sub","City of New York"); System.out.println("reference="+geonameNewYorkSource); System.out.println("Find 'Washington' geonames reference"); geonameWashingtonSource=executeQueryAndGetStringResults(lib ,geonamesCityQuery,lib.mod, "?cityName", "?sub","Washington"); //add the query string System.out.println("reference="+geonameWashingtonSource); System.out.println("Perform schema alignment"); addLocalAlignment(lib.schema); lib.bindReasoner(); System.out.println("Query Data"); executeQuery(lib ,geonamesCityQuery,lib.mod); //add the query string System.out.println("Search city and nearby city"); executeQuery(lib ,CityOntologyQuery,lib.inferred); //add the query string } static String setupQuery( String query) { StringBuffer queryStr = new StringBuffer(); // Establish Prefixes //Set default Name space first queryStr.append("PREFIX city" + ": <" + defaultNameSpace + "> "); queryStr.append("PREFIX rdfs" + ": <" + "http://www.w3.org/2000/01/rdf-schema#" + "> "); queryStr.append("PREFIX rdf" + ": <" + "http://www.w3.org/1999/02/22-rdf-syntaxns#" + "> "); queryStr.append("PREFIX foaf" + ": <" + "http://xmlns.com/foaf/0.1/" + "> "); queryStr.append("PREFIX pf: <http://jena.hpl.hp.com/ARQ/property#>"); 8 queryStr.append("PREFIX gn: //Now add query queryStr.append(query); <http://www.geonames.org/ontology#>"); return queryStr.toString(); } public static void addLocalAlignment(Model schema){ // State that :city is equivalentClass of gn:Feature Resource resource = schema.createResource(defaultNameSpace + "city"); Property prop = schema.createProperty("http://www.w3.org/2002/07/owl#equivalentClass"); Resource obj = schema.createResource("http://www.geonames.org/ontology#Feature"); schema.add(resource,prop,obj); //State that :hasName is a equivalentProperty of gn:name resource = schema.createResource(defaultNameSpace + "hasName"); prop = schema.createProperty("http://www.w3.org/2002/07/owl#equivalentProperty"); obj = schema.createResource("http://www.geonames.org/ontology#name"); schema.add(resource,prop,obj); //State that :hasPopulation is a equivalentProperty of gn:population resource = schema.createResource(defaultNameSpace + "hasPopulation"); prop = schema.createProperty("http://www.w3.org/2002/07/owl#equivalentProperty"); obj = schema.createResource("http://www.geonames.org/ontology#population"); schema.add(resource,prop,obj); //State that city2 is linked to geoname New York Source resource = schema.createResource(defaultNameSpace +"city2"); prop = schema.createProperty("http://www.w3.org/2002/07/owl#sameAs"); obj = schema.createResource(geonameNewYorkSource); schema.add(resource,prop,obj); //State that city2 is linked to geoname Washington Source resource = schema.createResource(defaultNameSpace +"city1"); prop = schema.createProperty("http://www.w3.org/2002/07/owl#sameAs"); obj = schema.createResource(geonameWashingtonSource); schema.add(resource,prop,obj); } static void executeQuery(SemanticLibrary lib , String query, Model model) { lib.runQuery(setupQuery(query), model); } static String executeQueryAndGetStringResults(SemanticLibrary lib , String query, Model model,String pName, String pId, String nameMatch) { return lib.runQueryAndGetObjects(setupQuery(query), model ,pName, pId,nameMatch); } } 9 SemanticLibrary.java package com.semanticlibrary.lib; import java.io.IOException; import java.io.InputStream; import com.hp.hpl.jena.query.Query; import com.hp.hpl.jena.query.QueryExecution; import com.hp.hpl.jena.query.QueryExecutionFactory; import com.hp.hpl.jena.query.QueryFactory; import com.hp.hpl.jena.query.QuerySolution; import com.hp.hpl.jena.query.ResultSet; import com.hp.hpl.jena.query.ResultSetFormatter; import com.hp.hpl.jena.query.larq.IndexBuilderString; import com.hp.hpl.jena.query.larq.IndexLARQ; import com.hp.hpl.jena.query.larq.LARQ; import com.hp.hpl.jena.rdf.model.*; import com.hp.hpl.jena.reasoner.Reasoner; import com.hp.hpl.jena.reasoner.ReasonerRegistry; import com.hp.hpl.jena.reasoner.rulesys.GenericRuleReasoner; import com.hp.hpl.jena.reasoner.rulesys.Rule; import com.hp.hpl.jena.util.FileManager; public class SemanticLibrary { String defaultNameSpace = ""; public Model mod=null; public Model schema=null; public Model inferred=null; IndexBuilderString larqBuilder=null; public void setDefaultNameSpace(String nameSpace) { defaultNameSpace = nameSpace; } public void setRestriction(Model model, String file) throws IOException { // Load restriction - if entered in model with reasoner, reasoner sets entailments InputStream inResInstance = FileManager.get().open(file); model.read(inResInstance,defaultNameSpace); inResInstance.close(); } public void loadDatabase(String file) { mod = ModelFactory.createOntologyModel(); InputStream inInstance = FileManager.get().open(file); mod.read(inInstance,defaultNameSpace); } 10 public void appendToDatabase( String file) throws IOException { InputStream inInstance = FileManager.get().open(file); mod.read(inInstance,defaultNameSpace); inInstance.close(); } public void LoadSchema(String file) throws IOException{ InputStream inMod = FileManager.get().open(file); InputStream inMod1 = FileManager.get().open(file); schema = ModelFactory.createOntologyModel(); // Use local copy for demos without network connection schema.read(inMod, defaultNameSpace); mod.read(inMod1, defaultNameSpace); inMod.close(); inMod1.close(); } public void appendSchema(String file) throws IOException { InputStream inInstance = FileManager.get().open(file); mod.read(inInstance,defaultNameSpace); inInstance.close(); } public void runQuery(String queryRequest, Model model){ // -- Read and index all literal strings. IndexBuilderString larqBuilder = new IndexBuilderString() ; // -- Create an index based on existing statements larqBuilder.indexStatements(model.listStatements()) ; // -- Finish indexing larqBuilder.closeWriter() ; // -- Create the access index IndexLARQ index = larqBuilder.getIndex() ; Query query = QueryFactory.create(queryRequest); QueryExecution qexec = QueryExecutionFactory.create(query, model); LARQ.setDefaultIndex(qexec.getContext(), index) ; ResultSetFormatter.out(System.out, qexec.execSelect(), query) ; qexec.close() ; } public String runQueryAndGetObjects(String queryRequest, Model model, String pName, String pId, String nameMatch){ String result=""; // -- Read and index all literal strings. IndexBuilderString larqBuilder = new IndexBuilderString() ; // -- Create an index based on existing statements larqBuilder.indexStatements(model.listStatements()) ; // -- Finish indexing 11 larqBuilder.closeWriter() ; // -- Create the access index IndexLARQ index = larqBuilder.getIndex() ; Query query = QueryFactory.create(queryRequest); QueryExecution qexec = QueryExecutionFactory.create(query, model); LARQ.setDefaultIndex(qexec.getContext(), index) ; ResultSet response = qexec.execSelect(); while( response.hasNext()){ QuerySolution soln = response.nextSolution(); RDFNode name = soln.get(pName); RDFNode id = soln.get(pId); if( name != null && id!=null) { if(nameMatch.equals(name.toString())) return ""+id.toString(); } } qexec.close(); return result; } public void bindReasoner(){ Reasoner reasoner = ReasonerRegistry.getOWLReasoner(); reasoner = reasoner.bindSchema(schema); inferred = ModelFactory.createInfModel(reasoner, mod); } public void runJenaRule(Model model, String rules){ Reasoner ruleReasoner = new GenericRuleReasoner(Rule.parseRules(rules)); ruleReasoner = ruleReasoner.bindSchema(schema); inferred = ModelFactory.createInfModel(ruleReasoner, model); } } 12