Java tutorial
/* $This file is distributed under the terms of the license in /doc/license.txt$ */ package edu.cornell.mannlib.vitro.webapp.dao.jena; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.hp.hpl.jena.ontology.IntersectionClass; import com.hp.hpl.jena.ontology.OntClass; import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.ontology.OntProperty; import com.hp.hpl.jena.ontology.Restriction; 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.ResultSetFactory; import com.hp.hpl.jena.query.Syntax; import com.hp.hpl.jena.rdf.model.RDFNode; import com.hp.hpl.jena.rdf.model.Resource; import com.hp.hpl.jena.rdf.model.ResourceFactory; import com.hp.hpl.jena.rdf.model.Statement; import com.hp.hpl.jena.rdf.model.StmtIterator; import com.hp.hpl.jena.shared.Lock; import com.hp.hpl.jena.vocabulary.OWL; import com.hp.hpl.jena.vocabulary.RDFS; import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; import edu.cornell.mannlib.vitro.webapp.beans.Property; import edu.cornell.mannlib.vitro.webapp.beans.PropertyInstance; import edu.cornell.mannlib.vitro.webapp.beans.VClass; import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyDao; import edu.cornell.mannlib.vitro.webapp.dao.PropertyDao; import edu.cornell.mannlib.vitro.webapp.dao.VClassDao; import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent; import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException; public class PropertyDaoJena extends JenaBaseDao implements PropertyDao { protected static final Log log = LogFactory.getLog(PropertyDaoJena.class.getName()); protected static final String FAUX_PROPERTY_FLAG = "FAUX"; private static final Map<String, String> NAMESPACES = new HashMap<String, String>() { { put("afn", VitroVocabulary.AFN); put("owl", VitroVocabulary.OWL); put("rdf", VitroVocabulary.RDF); put("rdfs", VitroVocabulary.RDFS); put("vitro", VitroVocabulary.vitroURI); put("vitroPublic", VitroVocabulary.VITRO_PUBLIC); } }; protected static final String PREFIXES; static { String prefixes = ""; for (String key : NAMESPACES.keySet()) { prefixes += "PREFIX " + key + ": <" + NAMESPACES.get(key) + ">\n"; } PREFIXES = prefixes; log.debug("Query prefixes: " + PREFIXES); } protected RDFService rdfService; protected DatasetWrapperFactory dwf; public PropertyDaoJena(RDFService rdfService, DatasetWrapperFactory dwf, WebappDaoFactoryJena wadf) { super(wadf); this.rdfService = rdfService; this.dwf = dwf; } @Override protected OntModel getOntModel() { return getOntModelSelector().getTBoxModel(); } protected RDFService getRDFService() { return this.rdfService; } public void addSuperproperty(ObjectProperty property, ObjectProperty superproperty) { addSuperproperty(property.getURI(), superproperty.getURI()); } @Override public void addSuperproperty(String propertyURI, String superpropertyURI) { getOntModel().enterCriticalSection(Lock.WRITE); try { getOntModel().add(getOntModel().getResource(propertyURI), RDFS.subPropertyOf, getOntModel().getResource(superpropertyURI)); } finally { getOntModel().leaveCriticalSection(); } } public void removeSuperproperty(ObjectProperty property, ObjectProperty superproperty) { removeSuperproperty(property.getURI(), superproperty.getURI()); } @Override public void removeSuperproperty(String propertyURI, String superpropertyURI) { getOntModel().enterCriticalSection(Lock.WRITE); try { if (getOntModel().contains(getOntModel().getResource(propertyURI), RDFS.subPropertyOf, getOntModel().getResource(superpropertyURI))) { getOntModel().remove(getOntModel().getResource(propertyURI), RDFS.subPropertyOf, getOntModel().getResource(superpropertyURI)); } } finally { getOntModel().leaveCriticalSection(); } } public void addSubproperty(ObjectProperty property, ObjectProperty subproperty) { addSuperproperty(subproperty, property); } @Override public void addSubproperty(String propertyURI, String subpropertyURI) { addSuperproperty(subpropertyURI, propertyURI); } public void removeSubproperty(ObjectProperty property, ObjectProperty subproperty) { removeSuperproperty(subproperty, property); } @Override public void removeSubproperty(String propertyURI, String subpropertyURI) { removeSuperproperty(subpropertyURI, propertyURI); } @Override public List<String> getSubPropertyURIs(String propertyURI) { List<String> subURIs = new LinkedList<String>(); getOntModel().enterCriticalSection(Lock.READ); try { Iterator subIt = getOntModel().getOntProperty(propertyURI).listSubProperties(true); while (subIt.hasNext()) { try { OntProperty prop = (OntProperty) subIt.next(); subURIs.add(prop.getURI()); } catch (Exception cce) { } } } catch (Exception e) { log.error(e, e); } finally { getOntModel().leaveCriticalSection(); } return subURIs; } private void getAllSubPropertyURIs(String propertyURI, HashSet<String> subtree) { List<String> directSubproperties = getSubPropertyURIs(propertyURI); Iterator<String> it = directSubproperties.iterator(); while (it.hasNext()) { String uri = it.next(); if (!subtree.contains(uri)) { subtree.add(uri); getAllSubPropertyURIs(uri, subtree); } } } @Override public List<String> getAllSubPropertyURIs(String propertyURI) { HashSet<String> nodeSet = new HashSet<String>(); nodeSet.add(propertyURI); getAllSubPropertyURIs(propertyURI, nodeSet); nodeSet.remove(propertyURI); List<String> outputList = new LinkedList<String>(); outputList.addAll(nodeSet); return outputList; } @Override public List<String> getSuperPropertyURIs(String propertyURI, boolean direct) { List<String> supURIs = new LinkedList<String>(); getOntModel().enterCriticalSection(Lock.READ); try { Iterator supIt = getOntModel().getOntProperty(propertyURI).listSuperProperties(direct); while (supIt.hasNext()) { try { OntProperty prop = (OntProperty) supIt.next(); supURIs.add(prop.getURI()); } catch (Exception cce) { } } } catch (Exception e) { log.error("Failed to get super-properties for " + propertyURI, e); } finally { getOntModel().leaveCriticalSection(); } return supURIs; } private void getAllSuperPropertyURIs(String propertyURI, HashSet<String> subtree) { List<String> directSuperproperties = getSuperPropertyURIs(propertyURI, true); Iterator<String> it = directSuperproperties.iterator(); while (it.hasNext()) { String uri = it.next(); if (!subtree.contains(uri)) { subtree.add(uri); getAllSuperPropertyURIs(uri, subtree); } } } @Override public List<String> getAllSuperPropertyURIs(String propertyURI) { HashSet<String> nodeSet = new HashSet<String>(); nodeSet.add(propertyURI); getAllSuperPropertyURIs(propertyURI, nodeSet); nodeSet.remove(propertyURI); List<String> outputList = new LinkedList<String>(); outputList.addAll(nodeSet); return outputList; } @Override public void addSubproperty(Property property, Property subproperty) { addSubproperty(property.getURI(), subproperty.getURI()); } @Override public void addSuperproperty(Property property, Property superproperty) { addSuperproperty(property.getURI(), superproperty.getURI()); } @Override public void removeSubproperty(Property property, Property subproperty) { removeSubproperty(property.getURI(), subproperty.getURI()); } @Override public void removeSuperproperty(Property property, Property superproperty) { removeSuperproperty(property.getURI(), superproperty.getURI()); } @Override public void addEquivalentProperty(String propertyURI, String equivalentPropertyURI) { if (propertyURI == null || equivalentPropertyURI == null) { throw new RuntimeException("cannot assert equivalence of anonymous properties"); } OntModel ontModel = getOntModel(); ontModel.enterCriticalSection(Lock.WRITE); try { Resource property = ontModel.getResource(propertyURI); Resource equivalentProperty = ontModel.getResource(equivalentPropertyURI); ontModel.add(property, OWL.equivalentProperty, equivalentProperty); ontModel.add(equivalentProperty, OWL.equivalentProperty, property); } finally { ontModel.leaveCriticalSection(); } } @Override public void addEquivalentProperty(Property property, Property equivalentProperty) { addEquivalentProperty(property.getURI(), equivalentProperty.getURI()); } @Override public List<String> getEquivalentPropertyURIs(String propertyURI) { List<String> equivURIs = new LinkedList<String>(); getOntModel().enterCriticalSection(Lock.READ); try { StmtIterator eqStmtIt = getOntModel().listStatements(getOntModel().getResource(propertyURI), OWL.equivalentProperty, (RDFNode) null); while (eqStmtIt.hasNext()) { Statement eqStmt = eqStmtIt.nextStatement(); RDFNode prop = eqStmt.getObject(); if (prop.isResource() && ((Resource) prop).getURI() != null) { equivURIs.add(((Resource) prop).getURI()); } } } catch (Exception e) { log.error(e, e); } finally { getOntModel().leaveCriticalSection(); } return equivURIs; } @Override public void removeEquivalentProperty(String propertyURI, String equivalentPropertyURI) { if (propertyURI == null || equivalentPropertyURI == null) { throw new RuntimeException("cannot remove equivalence axiom about anonymous properties"); } OntModel ontModel = getOntModel(); ontModel.enterCriticalSection(Lock.WRITE); try { Resource property = ontModel.getResource(propertyURI); Resource equivalentProperty = ontModel.getResource(equivalentPropertyURI); ontModel.remove(property, OWL.equivalentProperty, equivalentProperty); ontModel.remove(equivalentProperty, OWL.equivalentProperty, property); } finally { ontModel.leaveCriticalSection(); } } @Override public void removeEquivalentProperty(Property property, Property equivalentProperty) { removeEquivalentProperty(property, equivalentProperty); } protected void removeABoxStatementsWithPredicate(Property predicate) { // DO NOT issue a removeAll() with a null (wildcard) in predicate position! if (predicate == null) { log.debug("Cannot remove ABox statements with a null predicate."); return; } else { removeABoxStatementsWithPredicate(predicate.getURI()); } } protected void removeABoxStatementsWithPredicate(String predicateURI) { if (predicateURI == null) { log.debug("Cannot remove ABox statements with null predicate URI."); return; } OntModel aboxModel = getOntModelSelector().getABoxModel(); aboxModel.enterCriticalSection(Lock.WRITE); try { aboxModel.getBaseModel().notifyEvent(new EditEvent(getWebappDaoFactory().getUserURI(), true)); aboxModel.removeAll((Resource) null, aboxModel.getProperty(predicateURI), (RDFNode) null); } finally { aboxModel.getBaseModel().notifyEvent(new EditEvent(getWebappDaoFactory().getUserURI(), false)); aboxModel.leaveCriticalSection(); } } /** * Finds the classes that have a definition involving a restriction * on the given property. * * @param propertyURI identifier of a property * @return a list of VClass objects representing the classes that have * definitions involving a restriction on the given property. */ @Override public List<VClass> getClassesWithRestrictionOnProperty(String propertyURI) { if (propertyURI == null) { log.warn("getClassesWithRestrictionOnProperty: called with null propertyURI"); return null; } OntModel ontModel = getOntModel(); ontModel.enterCriticalSection(Lock.READ); HashSet<String> classURISet = new HashSet<String>(); try { Resource targetProp = ontModel.getResource(propertyURI); if (targetProp != null) { StmtIterator stmtIter = ontModel.listStatements((Resource) null, OWL.onProperty, targetProp); while (stmtIter.hasNext()) { Statement statement = stmtIter.next(); if (statement.getSubject().canAs(OntClass.class)) { classURISet.addAll(getRestrictedClasses(statement.getSubject().as(OntClass.class))); } else { log.warn( "getClassesWithRestrictionOnProperty: Unexpected use of onProperty: it is not applied to a class"); } } } else { log.error( "getClassesWithRestrictionOnProperty: Error: didn't find a Property in the ontology model for the URI: " + propertyURI); } } finally { ontModel.leaveCriticalSection(); } List<VClass> classes = new ArrayList<VClass>(); Iterator<String> iter = classURISet.iterator(); VClassDao vcd = getWebappDaoFactory().getVClassDao(); while (iter.hasNext()) { String curi = iter.next(); VClass vc = vcd.getVClassByURI(curi); if (vc != null) { classes.add(vc); } else { log.error("getClassesWithRestrictionOnProperty: Error: no VClass found for URI: " + curi); } } return (classes.size() > 0) ? classes : null; } /** * Find named classes to which a restriction "applies" * @param resourceURI identifier of a class * @return set of class URIs * * Note: this method assumes that the caller holds a read lock on * the ontology model. */ public HashSet<String> getRestrictedClasses(OntClass ontClass) { HashSet<String> classSet = new HashSet<String>(); List<OntClass> classList = ontClass.listEquivalentClasses().toList(); classList.addAll(ontClass.listSubClasses().toList()); Iterator<OntClass> it = classList.iterator(); while (it.hasNext()) { OntClass oc = it.next(); if (!oc.isAnon()) { classSet.add(oc.getURI()); } else { classSet.addAll(getRestrictedClasses(oc)); } } return classSet; } protected ResultSet getPropertyQueryResults(String queryString) { log.debug("SPARQL query:\n" + queryString); // RY Removing prebinding due to Jena bug: when isLiteral(?object) or // isURI(?object) is added to the query as a filter, the query fails with prebinding // but succeeds when the subject uri is concatenated into the query string. //QuerySolutionMap subjectBinding = new QuerySolutionMap(); //subjectBinding.add("subject", ResourceFactory.createResource(subjectUri)); // Run the SPARQL query to get the properties try { return ResultSetFactory .fromJSON(getRDFService().sparqlSelectQuery(queryString, RDFService.ResultFormat.JSON)); } catch (RDFServiceException e) { throw new RuntimeException(e); } // DatasetWrapper w = dwf.getDatasetWrapper(); // Dataset dataset = w.getDataset(); // dataset.getLock().enterCriticalSection(Lock.READ); // ResultSet rs = null; // try { // QueryExecution qexec = QueryExecutionFactory.create( // query, dataset); //, subjectBinding); // try { // rs = new ResultSetMem(qexec.execSelect()); // } finally { // qexec.close(); // } // } finally { // dataset.getLock().leaveCriticalSection(); // w.close(); // } // return rs; } /** * requires SPARQL 1.1 (or ARQ) property path support * @param vclassURI * @return list of property resources with union domains that include the vclass */ protected List<Resource> getPropertiesWithAppropriateDomainFor(String vclassURI) { List<Resource> propertyResList = new ArrayList<Resource>(); String queryStr = "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n" + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "PREFIX owl: <http://www.w3.org/2002/07/owl#> \n\n " + "SELECT ?p WHERE { \n" + " { \n" + " ?p rdfs:domain <" + vclassURI + "> . \n" + " } UNION { \n" + " ?parent rdfs:domain <" + vclassURI + "> . \n" + " ?p rdfs:subPropertyOf* ?parent. \n" + " OPTIONAL { \n" + " ?p rdfs:domain ?childDomain \n" + " } \n" + " FILTER (!bound(?childDomain)) \n" + " } UNION { \n" + " ?f rdf:first <" + vclassURI + "> . \n" + " ?u rdf:rest* ?f . \n" + " ?d owl:unionOf ?u . \n" + " ?p rdfs:domain ?d . \n" + " } UNION { \n" + " ?f rdf:first <" + vclassURI + "> . \n" + " ?u rdf:rest* ?f . \n" + " ?d owl:unionOf ?u . \n" + " ?parent rdfs:domain ?d . \n" + " ?p rdfs:subPropertyOf* ?parent. \n" + " OPTIONAL { \n" + " ?p rdfs:domain ?childDomain \n" + " } \n" + " FILTER (!bound(?childDomain)) \n" + " } \n" + " FILTER(?p != owl:bottomDataProperty \n" + " && ?p != owl:bottomObjectProperty) \n" + "}"; Query q = QueryFactory.create(queryStr, Syntax.syntaxSPARQL_11); QueryExecution qe = QueryExecutionFactory.create(q, getOntModelSelector().getTBoxModel()); try { ResultSet rs = qe.execSelect(); while (rs.hasNext()) { QuerySolution qs = rs.nextSolution(); propertyResList.add(qs.getResource("p")); } } finally { qe.close(); } return propertyResList; } public List<PropertyInstance> getAllPossiblePropInstForIndividual(String individualURI) { Individual ind = getWebappDaoFactory().getIndividualDao().getIndividualByURI(individualURI); VClassDao vcDao = getWebappDaoFactory().getVClassDao(); List<VClass> allTypes = ind.getVClasses(false); // include indirect types Set<String> allSuperclassURIs = new HashSet<String>(); for (VClass type : allTypes) { String classURI = type.getURI(); if (classURI != null) { allSuperclassURIs.add(type.getURI()); } for (String equivURI : vcDao.getEquivalentClassURIs(classURI)) { allSuperclassURIs.add(equivURI); allSuperclassURIs.addAll(vcDao.getAllSuperClassURIs(equivURI)); } allSuperclassURIs.addAll(vcDao.getAllSuperClassURIs(classURI)); } List<VClass> vclasses = new ArrayList<VClass>(); for (String vclassURI : allSuperclassURIs) { VClass vclass = vcDao.getVClassByURI(vclassURI); if (vclass != null) { vclasses.add(vclass); } } return getAllPropInstByVClasses(vclasses); } /* Removed: see VIVO-766. * sorts VClasses so that subclasses come before superclasses * * Because subclass/superclass is only a partial ordering, this breaks the * contract for Comparator, and throws an IllegalArgumentException under Java 8. * In particular, for classes sub, super and other, we have sub=other, sub<super, * which should imply other<super, but that is not true. * * As far as I can determine, this sort is never relied on anyway, so there * should be no impact in removing it. Note that PropertyInstanceDaoJena re-sorts * thes results before using them, so this sort was irrelevant for any calls * through that path. */ // private class VClassHierarchyRanker implements Comparator<VClass> { // private VClassDao vcDao; // public VClassHierarchyRanker(VClassDao vcDao) { // this.vcDao = vcDao; // } // @Override // public int compare(VClass vc1, VClass vc2) { // if (vcDao.isSubClassOf(vc1, vc2)) { // return -1; // } else if (vcDao.isSubClassOf(vc2, vc1)) { // return 1; // } else { // return 0; // } // } // } // public List<PropertyInstance> getAllPropInstByVClass(String classURI) { if (classURI == null || classURI.length() < 1) { return null; } VClassDao vcDao = getWebappDaoFactory().getVClassDao(); Set<String> allSuperclassURIs = new HashSet<String>(); allSuperclassURIs.add(classURI); for (String equivURI : vcDao.getEquivalentClassURIs(classURI)) { allSuperclassURIs.add(equivURI); allSuperclassURIs.addAll(vcDao.getAllSuperClassURIs(equivURI)); } allSuperclassURIs.addAll(vcDao.getAllSuperClassURIs(classURI)); List<VClass> vclasses = new ArrayList<VClass>(); for (String vclassURI : allSuperclassURIs) { VClass vclass = vcDao.getVClassByURI(vclassURI); if (vclass != null) { vclasses.add(vclass); } } return getAllPropInstByVClasses(vclasses); } private void updatePropertyRangeMap(Map<String, Resource[]> map, String propURI, Resource[] ranges, boolean replaceIfMoreSpecific) { Resource[] existingRanges = map.get(propURI); if (existingRanges == null) { map.put(propURI, ranges); } else if (existingRanges[0] == null && existingRanges[1] != null) { existingRanges[0] = ranges[0]; map.put(propURI, existingRanges); } else if (existingRanges[0] != null) { if (existingRanges[1] == null) { existingRanges[1] = ranges[1]; } if (ranges[0] != null && moreSpecificThan(ranges[0], existingRanges[0])) { existingRanges[0] = ranges[0]; } map.put(propURI, existingRanges); } } private boolean moreSpecificThan(Resource r1, Resource r2) { if (r1.getURI() == null) { return false; } else if (r2.getURI() == null) { return true; } return getWebappDaoFactory().getVClassDao().isSubClassOf(r1.getURI(), r2.getURI()); } private List<OntClass> listSuperClasses(OntClass ontClass) { return relatedClasses(ontClass, RDFS.subClassOf); } private List<OntClass> listEquivalentClasses(OntClass ontClass) { return relatedClasses(ontClass, OWL.equivalentClass); } private List<OntClass> relatedClasses(OntClass ontClass, com.hp.hpl.jena.rdf.model.Property property) { List<OntClass> classes = new ArrayList<OntClass>(); StmtIterator closeIt = ontClass.listProperties(property); try { while (closeIt.hasNext()) { Statement stmt = closeIt.nextStatement(); if (stmt.getObject().canAs(OntClass.class)) { classes.add(stmt.getObject().as(OntClass.class)); } } } finally { closeIt.close(); } return classes; } private static final int DEPTH_LIMIT = 20; private List<Restriction> getRelatedRestrictions(OntClass ontClass) { List<Restriction> restList = new ArrayList<Restriction>(); addRelatedRestrictions(ontClass, restList, DEPTH_LIMIT); return restList; } private void addRelatedRestrictions(OntClass ontClass, List<Restriction> relatedRestrictions, int limit) { limit--; if (ontClass.isRestriction()) { relatedRestrictions.add(ontClass.as(Restriction.class)); } else if (ontClass.isIntersectionClass()) { IntersectionClass inter = ontClass.as(IntersectionClass.class); Iterator<? extends OntClass> operIt = inter.listOperands(); while (operIt.hasNext()) { OntClass operand = operIt.next(); if (!relatedRestrictions.contains(operand) && limit > 0) { addRelatedRestrictions(operand, relatedRestrictions, limit); } } } else { List<OntClass> superClasses = listSuperClasses(ontClass); superClasses.addAll(listEquivalentClasses(ontClass)); for (OntClass sup : superClasses) { if (sup.isAnon() && !sup.equals(ontClass) && !relatedRestrictions.contains(ontClass) && limit > 0) { addRelatedRestrictions(sup, relatedRestrictions, limit); } } } } public List<PropertyInstance> getAllPropInstByVClasses(List<VClass> vclasses) { List<PropertyInstance> propInsts = new ArrayList<PropertyInstance>(); if (vclasses == null || vclasses.isEmpty()) { return propInsts; } // Removed: see VIVO-766. // Collections.sort(vclasses, new VClassHierarchyRanker(this.getWebappDaoFactory().getVClassDao())); OntModel ontModel = getOntModelSelector().getTBoxModel(); try { ontModel.enterCriticalSection(Lock.READ); // map object property URI to an array of two resources: // the first is the "allValuesFrom" resource and the second is // "someValuesFrom" Map<String, Resource[]> applicableProperties = new HashMap<String, Resource[]>(); try { for (VClass vclass : vclasses) { if (vclass.isAnonymous()) { continue; } String VClassURI = vclass.getURI(); OntClass ontClass = getOntClass(ontModel, VClassURI); if (ontClass == null) { continue; } List<Restriction> relatedRestrictions = getRelatedRestrictions(ontClass); for (Restriction rest : relatedRestrictions) { // find properties in restrictions // TODO: check if restriction is something like // maxCardinality 0 or allValuesFrom owl:Nothing, // in which case the property is NOT applicable! OntProperty onProperty = rest.getOnProperty(); if (onProperty != null) { Resource[] ranges = new Resource[2]; if (rest.isAllValuesFromRestriction()) { ranges[0] = (rest.asAllValuesFromRestriction()).getAllValuesFrom(); updatePropertyRangeMap(applicableProperties, onProperty.getURI(), ranges, true); } else if (rest.isSomeValuesFromRestriction()) { ranges[1] = (rest.asSomeValuesFromRestriction()).getSomeValuesFrom(); updatePropertyRangeMap(applicableProperties, onProperty.getURI(), ranges, false); } } } List<Resource> propertyList = getPropertiesWithAppropriateDomainFor(VClassURI); for (Resource prop : propertyList) { if (prop.getNameSpace() != null && !NONUSER_NAMESPACES.contains(prop.getNameSpace())) { StmtIterator rangeSit = prop.listProperties(RDFS.range); Resource rangeRes = null; while (rangeSit.hasNext()) { Statement s = rangeSit.nextStatement(); if (s.getObject().isURIResource()) { rangeRes = (Resource) s.getObject(); } } Resource[] ranges = new Resource[2]; ranges[0] = rangeRes; updatePropertyRangeMap(applicableProperties, prop.getURI(), ranges, false); } } } } catch (Exception e) { log.error("Unable to get applicable properties " + "by examining property restrictions and domains", e); } // make the PropertyInstance objects for (String propertyURI : applicableProperties.keySet()) { OntProperty op = ontModel.getOntProperty(propertyURI); if (op == null) { continue; } Resource[] foundRanges = applicableProperties.get(propertyURI); Resource rangeRes = (foundRanges[0] != null) ? foundRanges[0] : (op.getRange() == null && foundRanges[1] != null) ? foundRanges[1] : op.getRange(); Resource domainRes = op.getDomain(); propInsts.add(getPropInst(op, domainRes, rangeRes)); List<FullPropertyKey> additionalFauxSubpropertyKeys = getAdditionalFauxSubpropertyKeysForPropertyURI( propertyURI); for (FullPropertyKey fauxSubpropertyKey : additionalFauxSubpropertyKeys) { boolean applicablePropInst = false; if (rangeRes == null || !getWebappDaoFactory().getVClassDao().isSubClassOf(rangeRes.getURI(), fauxSubpropertyKey.getRangeUri())) { if (fauxSubpropertyKey.getDomainUri() == null) { applicablePropInst = true; } else { for (VClass vclass : vclasses) { if (vclass.getURI() != null && vclass.getURI().equals(fauxSubpropertyKey.getDomainUri())) { applicablePropInst = true; break; } } } if (applicablePropInst) { propInsts.add(getPropInst(op, ResourceFactory.createResource(fauxSubpropertyKey.getDomainUri()), ResourceFactory.createResource(fauxSubpropertyKey.getRangeUri()))); } } } } } finally { ontModel.leaveCriticalSection(); } // add any faux properties with applicable domain where the predicate URI // is not already on the list List<ObjectProperty> stragglers = getAdditionalFauxSubpropertiesForVClasses(vclasses, propInsts); for (ObjectProperty op : stragglers) { propInsts.add(makePropInst(op)); } return propInsts; } private PropertyInstance makePropInst(ObjectProperty op) { PropertyInstance pi = new PropertyInstance(); pi.setDomainClassURI(op.getDomainVClassURI()); pi.setRangeClassURI(op.getRangeVClassURI()); pi.setSubjectSide(true); pi.setPropertyURI(op.getURI()); pi.setPropertyName(op.getLabel()); pi.setDomainPublic(op.getDomainPublic()); return pi; } private PropertyInstance getPropInst(OntProperty op, Resource domainRes, Resource rangeRes) { if (log.isDebugEnabled() && domainRes != null && rangeRes != null) { log.debug("getPropInst() op: " + op.getURI() + " domain: " + domainRes.getURI() + " range: " + rangeRes.getURI()); } PropertyInstance pi = new PropertyInstance(); String domainURIStr = (domainRes != null && !domainRes.isAnon()) ? domainURIStr = domainRes.getURI() : null; // if (rangeRes == null) { // pi.setRangeClassURI(OWL.Thing.getURI()); // TODO see above if (rangeRes != null) { String rangeClassURI; if (rangeRes.isAnon()) { rangeClassURI = PSEUDO_BNODE_NS + rangeRes.getId().toString(); } else { rangeClassURI = rangeRes.getURI(); } pi.setRangeClassURI(rangeClassURI); VClass range = getWebappDaoFactory().getVClassDao().getVClassByURI(rangeClassURI); if (range == null) { range = new VClass(); range.setURI(rangeClassURI); range.setName(range.getLocalName()); } pi.setRangeClassName(range.getName()); } pi.setDomainClassURI(domainURIStr); if (domainURIStr != null) { VClass domain = getWebappDaoFactory().getVClassDao().getVClassByURI(domainURIStr); if (domain == null) { domain = new VClass(); domain.setURI(domainURIStr); domain.setName(domain.getLocalName()); } pi.setDomainClassName(domain.getName()); } pi.setSubjectSide(true); pi.setPropertyURI(op.getURI()); pi.setPropertyName(getLabelOrId(op)); // TODO pi.setRangePublic(getLabelOrId(op)); pi.setDomainPublic(getLabelOrId(op)); return pi; } private List<ObjectProperty> getAdditionalFauxSubpropertiesForVClasses(List<VClass> vclasses, List<PropertyInstance> propInsts) { List<ObjectProperty> opList = new ArrayList<ObjectProperty>(); if (vclasses.size() == 0) { return opList; } ObjectPropertyDao opDao = getWebappDaoFactory().getObjectPropertyDao(); String propQuery = "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "PREFIX config: <http://vitro.mannlib.cornell.edu/ns/vitro/ApplicationConfiguration#> \n" + "PREFIX vitro: <http://vitro.mannlib.cornell.edu/ns/vitro/0.7#> \n" + "SELECT ?property ?domain ?range WHERE { \n" + " ?context config:configContextFor ?property . \n" + " ?context config:qualifiedByDomain ?domain . \n" + " ?context config:qualifiedBy ?range . \n"; for (PropertyInstance propInst : propInsts) { propQuery += " FILTER (?property != <" + propInst.getPropertyURI() + "> ) \n"; } Iterator<VClass> classIt = vclasses.iterator(); if (classIt.hasNext()) { propQuery += " FILTER ( \n"; propQuery += " (?domain = <" + OWL.Thing.getURI() + "> )\n"; while (classIt.hasNext()) { VClass vclass = classIt.next(); if (vclass.isAnonymous()) { continue; } propQuery += " || (?domain = <" + vclass.getURI() + "> ) \n"; } propQuery += ") \n"; } propQuery += "} \n"; log.debug(propQuery); Query q = QueryFactory.create(propQuery); QueryExecution qe = QueryExecutionFactory.create(q, getOntModelSelector().getDisplayModel()); try { ResultSet rs = qe.execSelect(); while (rs.hasNext()) { QuerySolution qsoln = rs.nextSolution(); String propertyURI = qsoln.getResource("property").getURI(); String domainURI = qsoln.getResource("domain").getURI(); String rangeURI = qsoln.getResource("range").getURI(); opList.add(opDao.getObjectPropertyByURIs(propertyURI, domainURI, rangeURI, null)); } } finally { qe.close(); } return opList; } private List<FullPropertyKey> getAdditionalFauxSubpropertyKeysForPropertyURI(String propertyURI) { List<FullPropertyKey> keys = new ArrayList<>(); String propQuery = "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "PREFIX config: <http://vitro.mannlib.cornell.edu/ns/vitro/ApplicationConfiguration#> \n" + "PREFIX vitro: <http://vitro.mannlib.cornell.edu/ns/vitro/0.7#> \n" + "SELECT ?domain ?range WHERE { \n" + " ?context config:configContextFor <" + propertyURI + "> . \n" + " ?context config:qualifiedBy ?range . \n" + " OPTIONAL { ?context config:qualifiedByDomain ?domain } \n" + "}"; Query q = QueryFactory.create(propQuery); QueryExecution qe = QueryExecutionFactory.create(q, getOntModelSelector().getDisplayModel()); try { ResultSet rs = qe.execSelect(); while (rs.hasNext()) { QuerySolution qsoln = rs.nextSolution(); Resource rangeRes = qsoln.getResource("range"); String rangeURI = rangeRes.getURI(); Resource domainRes = qsoln.getResource("domain"); String domainURI = null; if (domainRes != null && !domainRes.isAnon()) { domainURI = domainRes.getURI(); } keys.add(new FullPropertyKey(domainURI, propertyURI, rangeURI)); } } finally { qe.close(); } return keys; } }