NIHVIVO-1228 NIHVIVO-3202 improved selection of editable properties: support for simple union domains and domain inheritance

This commit is contained in:
brianjlowe 2011-10-11 21:00:20 +00:00
parent fc4a22d292
commit 1ec081dcf3
4 changed files with 397 additions and 400 deletions

View file

@ -45,6 +45,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.DataProperty;
import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.Ontology;
import edu.cornell.mannlib.vitro.webapp.beans.PropertyInstance;
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.InsertException;
@ -310,107 +311,37 @@ public class DataPropertyDaoJena extends PropertyDaoJena implements
}
public List<DataProperty> getDatapropsForClass(String vclassURI) {
// TODO make this more efficient once we figure out our reasoner strategy
List<DataProperty> datapropsForClass = new ArrayList();
OntModel ontModel = getOntModelSelector().getTBoxModel();
try {
VClassDao vcDao = getWebappDaoFactory().getVClassDao();
HashSet<String> superclassURIs = new HashSet<String>(vcDao.getAllSuperClassURIs(vclassURI));
superclassURIs.add(vclassURI);
for (String equivURI : vcDao.getEquivalentClassURIs(vclassURI)) {
superclassURIs.add(equivURI);
superclassURIs.addAll(vcDao.getAllSuperClassURIs(equivURI));
}
Iterator superclassURIsIt = superclassURIs.iterator();
ontModel.enterCriticalSection(Lock.READ);
try {
Iterator dataprops = ontModel.listDatatypeProperties();
while (dataprops.hasNext()) {
Object nextObj = dataprops.next();
try {
com.hp.hpl.jena.ontology.OntProperty jDataprop = (com.hp.hpl.jena.ontology.OntProperty) nextObj;
Resource domainRes = jDataprop.getDomain();
if (domainRes != null && !NONUSER_NAMESPACES.contains(jDataprop.getNameSpace()) && superclassURIs.contains(domainRes.getURI())) {
datapropsForClass.add(datapropFromOntProperty(jDataprop));
}
// also check restrictions
for (Iterator restStmtIt = ontModel.listStatements(null,OWL.onProperty,jDataprop); restStmtIt.hasNext();) {
Statement restStmt = (Statement) restStmtIt.next();
Resource restRes = restStmt.getSubject();
for (Iterator axStmtIt = ontModel.listStatements(null,null,restRes); axStmtIt.hasNext();) {
Statement axStmt = (Statement) axStmtIt.next();
OntResource subjOntRes = null;
if (axStmt.getSubject().canAs(OntResource.class)) {
subjOntRes = (OntResource) axStmt.getSubject().as(OntResource.class);
}
if (
( (subjOntRes!=null) && (superclassURIs.contains(getClassURIStr(subjOntRes))) ) &&
(axStmt.getPredicate().equals(RDFS.subClassOf) || (axStmt.getPredicate().equals(OWL.equivalentClass)))
) {
if (restRes.canAs(AllValuesFromRestriction.class) || restRes.canAs(SomeValuesFromRestriction.class)) {
datapropsForClass.add(datapropFromOntProperty(jDataprop));
}
}
}
}
} catch (ClassCastException e) {
e.printStackTrace();
}
}
} finally {
ontModel.leaveCriticalSection();
}
} catch (ProfileException pe) {
// TODO language profile doesn't support data properties.
// With RDFS, we might like to return properties with rdfs:range containing a datatype
}
Collections.sort(datapropsForClass, new DataPropertyRanker());
return datapropsForClass;
return filterAndConvertToDataProperties(getAllPropInstByVClass(vclassURI));
}
public Collection<DataProperty> getAllPossibleDatapropsForIndividual(String individualURI) {
Individual ind = getWebappDaoFactory().getIndividualDao().getIndividualByURI(individualURI);
Collection<DataProperty> dpColl = new ArrayList<DataProperty>();
List<String> vclassURIs = getVClassURIs(ind);
try {
for (VClass currClass : ind.getVClasses( DIRECT )) {
List<DataProperty> currList = getDatapropsForClass(currClass.getURI());
for (Iterator<DataProperty> dpIter = currList.iterator(); dpIter.hasNext();) {
DataProperty dp = (DataProperty) dpIter.next();
boolean addIt = true;
// some inefficient de-duping
for (Iterator<DataProperty> existingIter = dpColl.iterator(); existingIter.hasNext(); ) {
DataProperty existingDp = (DataProperty) existingIter.next();
try {
if (existingDp.getURI().equals(dp.getURI()) &&
existingDp.getDomainClassURI().equals(dp.getDomainClassURI()) &&
existingDp.getRangeDatatypeURI().equals(dp.getRangeDatatypeURI())) {
addIt = false;
}
} catch (Exception e) { }
}
if (addIt) {
dpColl.add(dp);
}
}
// 2010-01-25 addition by BJL
// now change range datatype based on individual
// TODO: rethink all these methods to reduce inefficiency
for (DataProperty dp : dpColl) {
dp.setRangeDatatypeURI(getRequiredDatatypeURI(ind, dp, vclassURIs));
}
}
} catch (ProfileException pe) {
// TODO language profile doesn't support data properties.
// With RDFS, we might like to return properties with rdfs:range containing a datatype
}
/*
for (DataProperty dp : dpColl) {
dp.setDomainClassURI(ind.getVClassURI()); // TODO: improve. This is so the DWR property editing passes the individual's VClass to get the right restrictions
}
Collections.sort(dpColl, new PropInstSorter()); */
return dpColl;
return filterAndConvertToDataProperties(getAllPossiblePropInstForIndividual(individualURI));
}
private List<DataProperty> filterAndConvertToDataProperties(
List<PropertyInstance> propInsts) {
List<DataProperty> dataprops = new ArrayList<DataProperty>();
for (PropertyInstance propInst : propInsts) {
OntModel tboxModel = getOntModel();
tboxModel.enterCriticalSection(Lock.READ);
boolean add = false;
try {
add = (propInst.getPropertyURI() != null
&& tboxModel.contains(
tboxModel.getResource(
propInst.getPropertyURI()),
RDF.type,
OWL.DatatypeProperty));
} finally {
tboxModel.leaveCriticalSection();
}
if (add) {
DataProperty dataprop = getDataPropertyByURI(propInst.getPropertyURI());
dataprop.setRangeDatatypeURI(propInst.getRangeClassURI());
dataprops.add(dataprop);
}
}
return dataprops;
}
protected boolean reasoningAvailable() {

View file

@ -3,12 +3,16 @@
package edu.cornell.mannlib.vitro.webapp.dao.jena;
import java.util.ArrayList;
import java.util.Collection;
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;
@ -16,11 +20,15 @@ import org.apache.commons.logging.LogFactory;
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.Dataset;
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.Syntax;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
@ -30,8 +38,10 @@ import com.hp.hpl.jena.sparql.resultset.ResultSetMem;
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.PropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.VClassDao;
@ -431,4 +441,318 @@ public class PropertyDaoJena extends JenaBaseDao implements PropertyDao {
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" +
"}";
log.info(queryStr);
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);
}
}
List<PropertyInstance> piList = getAllPropInstByVClasses(vclasses);
for (PropertyInstance pi : piList) {
pi.setDomainClassURI(ind.getVClassURI());
// TODO: improve. This is so the DWR property editing passes the
// individual's VClass to get the right restrictions
}
return piList;
}
/*
* sorts VClasses so that subclasses come before superclasses
*/
private class VClassHierarchyRanker implements Comparator<VClass> {
private VClassDao vcDao;
public VClassHierarchyRanker(VClassDao vcDao) {
this.vcDao = vcDao;
}
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) {
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 && existingRanges[1] == null) {
existingRanges[1] = ranges[1];
map.put(propURI, existingRanges);
}
}
public List<PropertyInstance> getAllPropInstByVClasses(List<VClass> vclasses) {
List<PropertyInstance> propInsts = new ArrayList<PropertyInstance>();
if(vclasses == null || vclasses.isEmpty()) {
return propInsts;
}
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) {
List<OntClass> relatedClasses = new ArrayList<OntClass>();
relatedClasses.addAll(ontClass.listEquivalentClasses().toList());
relatedClasses.addAll(ontClass.listSuperClasses().toList());
for (OntClass relatedClass : relatedClasses) {
// find properties in restrictions
if (relatedClass.isRestriction()) {
// TODO: check if restriction is something like
// maxCardinality 0 or allValuesFrom owl:Nothing,
// in which case the property is NOT applicable!
Restriction rest = (Restriction) relatedClass.as(Restriction.class);
OntProperty onProperty = rest.getOnProperty();
if (onProperty != null) {
Resource[] ranges = new Resource[2];
if (rest.isAllValuesFromRestriction()) {
ranges[0] = (rest.asAllValuesFromRestriction()).getAllValuesFrom();
} else if (rest.isSomeValuesFromRestriction()) {
ranges[1] = (rest.asSomeValuesFromRestriction()).getSomeValuesFrom();
}
updatePropertyRangeMap(applicableProperties, onProperty.getURI(), ranges);
}
}
}
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);
}
}
}
}
} 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;
}
String domainURIStr = getURIStr(op.getDomain());
Resource[] foundRanges = applicableProperties.get(propertyURI);
Resource rangeRes = (foundRanges[0] != null)
? foundRanges[0]
: (op.getRange() == null && foundRanges[1] != null)
? foundRanges[1]
: op.getRange();
PropertyInstance pi = new PropertyInstance();
if (rangeRes != null) {
String rangeClassURI;
if (rangeRes.isAnon()) {
rangeClassURI = PSEUDO_BNODE_NS + rangeRes.getId()
.toString();
} else {
rangeClassURI = (String) 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());
} else {
pi.setRangeClassURI(OWL.Thing.getURI()); // TODO see above
}
pi.setDomainClassURI(domainURIStr);
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));
propInsts.add(pi);
}
} finally {
ontModel.leaveCriticalSection();
}
return propInsts;
}
private String getURIStr(Resource res) {
String URIStr;
if (res == null) {
URIStr = OWL.Thing.getURI(); // TODO: rdf:Resource if using RDF model; or option to turn off entirely
} else {
if (res.isAnon()) {
URIStr = PSEUDO_BNODE_NS+res.getId().toString();
} else {
URIStr = res.getURI();
}
}
return URIStr;
}
}

View file

@ -19,21 +19,14 @@ 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.Syntax;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.ResIterator;
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.RDF;
import com.hp.hpl.jena.vocabulary.RDFS;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
@ -45,11 +38,11 @@ import edu.cornell.mannlib.vitro.webapp.dao.PropertyInstanceDao;
import edu.cornell.mannlib.vitro.webapp.dao.VClassDao;
import edu.cornell.mannlib.vitro.webapp.dao.jena.event.IndividualDeletionEvent;
import edu.cornell.mannlib.vitro.webapp.dao.jena.event.IndividualUpdateEvent;
public class PropertyInstanceDaoJena extends JenaBaseDao implements
public class PropertyInstanceDaoJena extends PropertyDaoJena implements
PropertyInstanceDao {
public PropertyInstanceDaoJena(WebappDaoFactoryJena wadf) {
super(wadf);
public PropertyInstanceDaoJena(DatasetWrapperFactory dwf, WebappDaoFactoryJena wadf) {
super(dwf, wadf);
}
public void deleteObjectPropertyStatement(String subjectURI, String propertyURI, String objectURI) {
@ -98,299 +91,48 @@ public class PropertyInstanceDaoJena extends JenaBaseDao implements
ontModel.leaveCriticalSection();
}
}
public Collection<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);
}
}
Collection<PropertyInstance> piList = getAllPropInstByVClasses(vclasses);
for (PropertyInstance pi : piList) {
pi.setDomainClassURI(ind.getVClassURI());
// TODO: improve. This is so the DWR property editing passes the
// individual's VClass to get the right restrictions
@Override
public List<PropertyInstance> getAllPossiblePropInstForIndividual(String individualURI) {
return filterAndSort(super.getAllPossiblePropInstForIndividual(individualURI));
}
@Override
public List<PropertyInstance> getAllPropInstByVClass(String vclassURI) {
return filterAndSort(super.getAllPropInstByVClass(vclassURI));
}
@Override
public List<PropertyInstance> getAllPropInstByVClasses(List<VClass> vclasses) {
return filterAndSort(super.getAllPropInstByVClasses(vclasses));
}
private List<PropertyInstance>filterAndSort(List<PropertyInstance> propList) {
ArrayList<PropertyInstance> propInsts = new ArrayList<PropertyInstance>();
for (PropertyInstance propInst : propList) {
OntModel tboxModel = getOntModel();
tboxModel.enterCriticalSection(Lock.READ);
boolean add = false;
try {
add = (propInst.getPropertyURI() != null
&& tboxModel.contains(
tboxModel.getResource(
propInst.getPropertyURI()),
RDF.type,
OWL.ObjectProperty));
} finally {
tboxModel.leaveCriticalSection();
}
if (add) {
propInsts.add(propInst);
}
}
return piList;
}
/*
* sorts VClasses so that subclasses come before superclasses
*/
private class VClassHierarchyRanker implements Comparator<VClass> {
private VClassDao vcDao;
public VClassHierarchyRanker(VClassDao vcDao) {
this.vcDao = vcDao;
}
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 Collection<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) {
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 && existingRanges[1] == null) {
existingRanges[1] = ranges[1];
map.put(propURI, existingRanges);
}
}
public Collection<PropertyInstance> getAllPropInstByVClasses(List<VClass> vclasses) {
List<PropertyInstance> propInsts = new ArrayList<PropertyInstance>();
if(vclasses == null || vclasses.isEmpty()) {
return propInsts;
}
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) {
List<OntClass> relatedClasses = new ArrayList<OntClass>();
relatedClasses.addAll(ontClass.listEquivalentClasses().toList());
relatedClasses.addAll(ontClass.listSuperClasses().toList());
for (OntClass relatedClass : relatedClasses) {
// find properties in restrictions
if (relatedClass.isRestriction()) {
// TODO: check if restriction is something like
// maxCardinality 0 or allValuesFrom owl:Nothing,
// in which case the property is NOT applicable!
Restriction rest = (Restriction) relatedClass.as(Restriction.class);
OntProperty onProperty = rest.getOnProperty();
if (onProperty != null && onProperty.canAs(ObjectProperty.class)) {
Resource[] ranges = new Resource[2];
if (rest.isAllValuesFromRestriction()) {
ranges[0] = (rest.asAllValuesFromRestriction()).getAllValuesFrom();
} else if (rest.isSomeValuesFromRestriction()) {
ranges[1] = (rest.asSomeValuesFromRestriction()).getSomeValuesFrom();
}
updatePropertyRangeMap(applicableProperties, onProperty.getURI(), ranges);
}
}
}
List<Resource> propertyList = new ArrayList<Resource>();
// find properties with class in domain
ResIterator pit = ontModel.listSubjectsWithProperty(
RDFS.domain, ontClass);
while (pit.hasNext()) {
Resource prop = pit.nextResource();
propertyList.add(prop);
}
propertyList.addAll(
getPropertiesWithUnionDomainIncluding(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);
}
}
}
}
} 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()) {
ObjectProperty op = ontModel.getObjectProperty(propertyURI);
if (op == null) {
continue;
}
String domainURIStr = getURIStr(op.getDomain());
Resource[] foundRanges = applicableProperties.get(propertyURI);
Resource rangeRes = (foundRanges[0] != null)
? foundRanges[0]
: (op.getRange() == null && foundRanges[1] != null)
? foundRanges[1]
: op.getRange();
PropertyInstance pi = new PropertyInstance();
if (rangeRes != null) {
String rangeClassURI;
if (rangeRes.isAnon()) {
rangeClassURI = PSEUDO_BNODE_NS+rangeRes.getId().toString();
} else {
rangeClassURI = (String) rangeRes.getURI();
}
pi.setRangeClassURI(rangeClassURI);
try {
pi.setRangeClassName(getWebappDaoFactory().getVClassDao().getVClassByURI(rangeClassURI).getName());
//pi.setRangeClassName(getLabel(getOntModel().getOntResource(rangeClassURI)));
} catch (NullPointerException e) {/* probably a union or intersection - need to handle this somehow */}
} else {
pi.setRangeClassURI(OWL.Thing.getURI()); // TODO see above
}
pi.setDomainClassURI(domainURIStr);
try {
pi.setDomainClassName(getWebappDaoFactory().getVClassDao().getVClassByURI(domainURIStr).getName());
//pi.setDomainClassName(getLabel(getOntModel().getOntResource(op.getDomain().getURI())));
} catch (NullPointerException e) {/* probably a union or intersection - need to handle this somehow */}
pi.setSubjectSide(true);
pi.setPropertyURI(op.getURI());
pi.setPropertyName(getLabelOrId(op)); // TODO
pi.setRangePublic(getLabelOrId(op));
pi.setDomainPublic(getLabelOrId(op));
propInsts.add(pi);
}
} finally {
ontModel.leaveCriticalSection();
}
Collections.sort(propInsts, new PropInstSorter());
return propInsts;
Collections.sort(propInsts, new PropInstSorter());
return propInsts;
}
/**
* requires SPARQL 1.1 (or ARQ) property path support
* @param vclassURI
* @return list of property resources with union domains that include the vclass
*/
private List<Resource> getPropertiesWithUnionDomainIncluding(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" +
" ?f rdf:first <" + vclassURI + "> . \n" +
" ?u rdf:rest* ?f . \n" +
" ?d owl:unionOf ?u . \n" +
" ?p rdfs:domain ?d . \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;
}
private String getURIStr(Resource res) {
String URIStr;
if (res == null) {
URIStr = OWL.Thing.getURI(); // TODO: rdf:Resource if using RDF model; or option to turn off entirely
} else {
if (res.isAnon()) {
URIStr = PSEUDO_BNODE_NS+res.getId().toString();
} else {
URIStr = res.getURI();
}
}
return URIStr;
}
private class PropInstSorter implements Comparator {
public int compare (Object o1, Object o2) {
PropertyInstance pi1 = (PropertyInstance) o1;
PropertyInstance pi2 = (PropertyInstance) o2;
private class PropInstSorter implements Comparator<PropertyInstance> {
public int compare (PropertyInstance pi1, PropertyInstance pi2) {
try {
if (pi1.getDomainPublic().equals(pi2.getDomainPublic())) {
return pi1.getRangeClassName().compareTo(pi2.getRangeClassName());

View file

@ -536,7 +536,7 @@ public class WebappDaoFactoryJena implements WebappDaoFactory {
private PropertyInstanceDao propertyInstanceDao = null;
public PropertyInstanceDao getPropertyInstanceDao() {
if( propertyInstanceDao == null )
propertyInstanceDao = new PropertyInstanceDaoJena(this);
propertyInstanceDao = new PropertyInstanceDaoJena(dwf, this);
return propertyInstanceDao;
}