001 package nl.tudelft.tbm.eeni.owlstructure.processor;
002
003 import com.hp.hpl.jena.ontology.OntModel;
004 import com.hp.hpl.jena.ontology.OntProperty;
005 import com.hp.hpl.jena.query.*;
006 import com.hp.hpl.jena.shared.Lock;
007 import nl.tudelft.tbm.eeni.owlstructure.utils.OntologyUtils;
008 import org.apache.commons.logging.Log;
009 import org.apache.commons.logging.LogFactory;
010
011 /**
012 * Find functional properties by looking at instances in a given ontology
013 */
014 public class FunctionalPropertyInferer implements IOntologyProcessor {
015
016 static Log log = LogFactory.getLog(FunctionalPropertyInferer.class);
017
018 /**
019 * Creates a new functional property inferer, that tries to detect
020 * function properties by looking at instances in the ontology.
021 */
022 public FunctionalPropertyInferer() {
023 }
024
025 /**
026 * Run the functional propery inferer on all properties in the given ontology
027 *
028 * @param ontModel the ontology model to work on
029 */
030 @Override
031 public OntModel process(OntModel ontModel) {
032 // Look for properties that at least one instance uses once and no instances use more than once
033 String queryString = OntologyUtils.getSparqlPrefixes(ontModel)
034 + "select ?property (max(?count) as ?max) { "
035 + " select ?property (count(?o) as ?count) "
036 + " where { "
037 + " ?s ?property ?o . "
038 + " ?property rdf:type ?t "
039 + " } "
040 + " group by ?s ?property "
041 + "} "
042 + "group by ?property "
043 + "having (?max = 1) ";
044
045 ontModel.enterCriticalSection(Lock.READ);
046 try {
047 Query query = QueryFactory.create(queryString, Syntax.syntaxARQ);
048 QueryExecution qexec = QueryExecutionFactory.create(query, ontModel);
049
050 ResultSet results = qexec.execSelect();
051 while (results.hasNext()) {
052 // We've found a property that seems to be functional
053 OntProperty property = results.nextSolution().get("property").as(OntProperty.class);
054
055 // Convert the property to a functional property
056 property.convertToFunctionalProperty();
057
058 // Output a debug message
059 log.info("Functional property inference: " + property.getLocalName() + " is functional");
060 }
061 qexec.close();
062 } finally {
063 ontModel.leaveCriticalSection();
064 }
065
066 return ontModel;
067 }
068 }