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    }