diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/reasoner/SimpleReasoner.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/reasoner/SimpleReasoner.java index 5fa989c4f..d32851ec5 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/reasoner/SimpleReasoner.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/reasoner/SimpleReasoner.java @@ -6,7 +6,6 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; -import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -60,16 +59,17 @@ public class SimpleReasoner extends StatementListener { private Model inferenceRebuildModel; // work area for re-computing all ABox inferences private Model scratchpadModel; // work area for re-computing all ABox inferences - private static final String mostSpecificTypePropertyURI = "http://vitro.mannlib.cornell.edu/ns/vitro/0.7#mostSpecificType"; - - private AnnotationProperty mostSpecificType = (ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM)).createAnnotationProperty(mostSpecificTypePropertyURI); + private static final String mostSpecificTypePropertyURI = "http://vitro.mannlib.cornell.edu/ns/vitro/0.7#mostSpecificType"; + private static final AnnotationProperty mostSpecificType = (ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM)).createAnnotationProperty(mostSpecificTypePropertyURI); + //TODO check this for thread safety private CumulativeDeltaModeler aBoxDeltaModeler1 = null; private CumulativeDeltaModeler aBoxDeltaModeler2 = null; private volatile boolean batchMode1 = false; private volatile boolean batchMode2 = false; private boolean stopRequested = false; + //TODO check this for thread safety private List pluginList = new ArrayList(); /** @@ -145,7 +145,7 @@ public class SimpleReasoner extends StatementListener { } catch (Exception e) { // don't stop the edit if there's an exception log.error("Exception while computing inferences: " + e.getMessage()); - e.printStackTrace(); + e.printStackTrace(); //TODO remove this for release } } @@ -205,7 +205,7 @@ public class SimpleReasoner extends StatementListener { return; } - log.debug("added TBox assertion = " + stmt.toString()); + //log.debug("added TBox assertion = " + stmt.toString()); if ( stmt.getObject().isResource() && (stmt.getObject().asResource()).getURI() == null ) { log.warn("The object of this assertion has a null URI: " + stmtString(stmt)); @@ -275,7 +275,7 @@ public class SimpleReasoner extends StatementListener { return; } - log.debug("removed TBox assertion = " + stmt.toString()); + //log.debug("removed TBox assertion = " + stmt.toString()); if ( stmt.getObject().isResource() && (stmt.getObject().asResource()).getURI() == null ) { log.warn("The object of this assertion has a null URI: " + stmtString(stmt)); @@ -365,7 +365,7 @@ public class SimpleReasoner extends StatementListener { */ protected void addedABoxTypeAssertion(Statement stmt, Model inferenceModel, HashSet unknownTypes) { - tboxModel.enterCriticalSection(Lock.READ); + tboxModel.enterCriticalSection(Lock.READ); try { OntClass cls = null; if ( (stmt.getObject().asResource()).getURI() != null ) { @@ -416,7 +416,62 @@ public class SimpleReasoner extends StatementListener { inferenceModel.leaveCriticalSection(); } } - + + /* + * If it is removed that B is of type A, then for each superclass of A remove + * the inferred statement that B is of that type UNLESS it is otherwise entailed + * that B is of that type. + * + */ + protected void removedABoxTypeAssertion(Statement stmt, Model inferenceModel) { + tboxModel.enterCriticalSection(Lock.READ); + try { + OntClass cls = null; + + if ( (stmt.getObject().asResource()).getURI() != null ) { + cls = tboxModel.getOntClass(stmt.getObject().asResource().getURI()); + + if (cls != null) { + if (entailedType(stmt.getSubject(),cls)) { + addInference(stmt,inferenceModel,true); + } + + List parents = null; + parents = (cls.listSuperClasses(false)).toList(); + parents.addAll((cls.listEquivalentClasses()).toList()); + + Iterator parentIt = parents.iterator(); + + while (parentIt.hasNext()) { + OntClass parentClass = parentIt.next(); + + // VIVO doesn't materialize statements that assert anonymous types + // for individuals. Also, sharing an identical anonymous node is + // not allowed in owl-dl. picklist population code looks at qualities + // of classes not individuals. + if (parentClass.isAnon()) continue; + + if (entailedType(stmt.getSubject(),parentClass)) continue; // if a type is still entailed without the + // removed statement, then don't remove it + // from the inferences + + Statement infStmt = ResourceFactory.createStatement(stmt.getSubject(), RDF.type, parentClass); + removeInference(infStmt,inferenceModel,true,false); + } + } else { + log.warn("Didn't find target class (the object of the removed rdf:type statement) in the TBox: " + + ((Resource)stmt.getObject()).getURI() + ". No class subsumption reasoning will be performed based on the removal of this assertion."); + } + } else { + log.warn("The object of this rdf:type assertion has a null URI: " + stmtString(stmt)); + } + } catch (Exception e) { + log.warn("exception while removing abox type assertions: " + e.getMessage()); + } finally { + tboxModel.leaveCriticalSection(); + } + } + /* * Materializes inferences based on the owl:sameAs relationship. * @@ -424,12 +479,10 @@ public class SimpleReasoner extends StatementListener { * statements about x will become inferred about y if they are not already * asserted about y, and vice versa. */ - public void addedABoxSameAsAssertion(Statement stmt, Model inferenceModel) { + protected void addedABoxSameAsAssertion(Statement stmt, Model inferenceModel) { Resource subject = null; Resource object = null; - //System.out.println("\n\naddedABoxSameAsAssertion called for this statement: " + stmtString(stmt)); - if (stmt.getSubject().isResource()) { subject = stmt.getSubject().asResource(); if (tboxModel.containsResource(subject) || subject.isAnon()) { @@ -475,7 +528,7 @@ public class SimpleReasoner extends StatementListener { * the inference graph and then recompute the inferences for x and * y based on their respective assertions. that x owl:sameAs y, then all asserted and inferred */ - public void removedABoxSameAsAssertion(Statement stmt, Model inferenceModel) { + protected void removedABoxSameAsAssertion(Statement stmt, Model inferenceModel) { Resource subject = null; Resource object = null; @@ -500,28 +553,9 @@ public class SimpleReasoner extends StatementListener { log.warn("the object of this removed sameAs statement is not a resource, no reasoning will be done: " + stmtString(stmt)); return; } - - Set sameIndividuals = new HashSet(); - - inferenceModel.enterCriticalSection(Lock.READ); - try { - Iterator iter1 = inferenceModel.listStatements(subject, OWL.sameAs, (RDFNode) null); - while (iter1.hasNext()) { - Statement sameStmt = iter1.next(); - if (sameStmt.getObject() == null || !sameStmt.getObject().isResource()) continue; - sameIndividuals.add(sameStmt.getObject().asResource()); - } - - Iterator iter2 = inferenceModel.listStatements(object, OWL.sameAs, (RDFNode) null); - while (iter2.hasNext()) { - Statement sameStmt = iter2.next(); - if (sameStmt.getObject() == null || !sameStmt.getObject().isResource()) continue; - sameIndividuals.add(sameStmt.getObject().asResource()); - } - } finally { - inferenceModel.leaveCriticalSection(); - } + List sameIndividuals = getSameIndividuals(subject,inferenceModel); + sameIndividuals.addAll(getSameIndividuals(object, inferenceModel)); Iterator sIter1 = sameIndividuals.iterator(); while (sIter1.hasNext()) { @@ -534,40 +568,231 @@ public class SimpleReasoner extends StatementListener { } } - public void generateSameAsInferences(Resource ind1, Resource ind2, Model inferenceModel) { + /* + * + * Materializes inferences based on the owl:inverseOf relationship. + * and owl:sameAs + * + * If it is added that x prop1 y, and prop2 is an inverseOf prop1 + * then add y prop2 x to the inference graph, if it is not already in + * the assertions graph. + * + */ + protected void addedABoxAssertion(Statement stmt, Model inferenceModel) { - //System.out.println("\n\tgenerateSameAsInferences. ind1= " + ind1.getLocalName() + " ind2= " + ind2.getLocalName()); + List inverseProperties = getInverseProperties(stmt); + Iterator inverseIter = inverseProperties.iterator(); + + while (inverseIter.hasNext()) { + Property inverseProp = inverseIter.next(); + Statement infStmt = ResourceFactory.createStatement(stmt.getObject().asResource(), inverseProp, stmt.getSubject()); + addInference(infStmt,inferenceModel,true); + } + + List sameIndividuals = getSameIndividuals(stmt.getSubject().asResource(), inferenceModel); + Iterator sameIter = sameIndividuals.iterator(); + while (sameIter.hasNext()) { + Resource subject = sameIter.next(); + Statement sameStmt = ResourceFactory.createStatement(subject,stmt.getPredicate(),stmt.getObject()); + addInference(sameStmt,inferenceModel,false); + } + + inferenceModel.enterCriticalSection(Lock.WRITE); + try { + if (inferenceModel.contains(stmt)) { + inferenceModel.remove(stmt); + } + } finally { + inferenceModel.leaveCriticalSection(); + } + } + + /* + * Performs incremental property-based reasoning. + * + * Retracts inferences based on the owl:inverseOf relationship. + * + * If it is removed that x prop1 y, and prop2 is an inverseOf prop1 + * then remove y prop2 x from the inference graph, unless it is + * otherwise entailed by the assertions graph independently of + * this removed statement. + */ + protected void removedABoxAssertion(Statement stmt, Model inferenceModel) { + List inverseProperties = getInverseProperties(stmt); + Iterator inverseIter = inverseProperties.iterator(); + + while (inverseIter.hasNext()) { + OntProperty inverseProp = inverseIter.next(); + Statement infStmt = ResourceFactory.createStatement(stmt.getObject().asResource(), inverseProp, stmt.getSubject()); + removeInference(infStmt,inferenceModel); + } + + List sameIndividuals = getSameIndividuals(stmt.getSubject().asResource(), inferenceModel); + Iterator sameIter = sameIndividuals.iterator(); + while (sameIter.hasNext()) { + Statement stmtSame = ResourceFactory.createStatement(sameIter.next(), stmt.getPredicate(), stmt.getObject()); + removeInference(stmtSame,inferenceModel,false,true); + } + + // if a statement has been removed that is otherwise entailed, + // add it to the inference graph. + inferenceModel.enterCriticalSection(Lock.WRITE); + try { + if (entailedStatement(stmt) && !inferenceModel.contains(stmt)) { + inferenceModel.add(stmt); + } + } finally { + inferenceModel.leaveCriticalSection(); + } + } + + /* + * If it is added that B is a subClass of A, then for each + * individual that is typed as B, either in the ABox or in the + * inferred model, infer that it is of type A. + */ + protected void addedSubClass(OntClass subClass, OntClass superClass, Model inferenceModel) { + //log.debug("subClass = " + subClass.getURI() + " superClass = " + superClass.getURI()); OntModel unionModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); unionModel.addSubModel(aboxModel); unionModel.addSubModel(inferenceModel); + List subjectList = new ArrayList(); + aboxModel.enterCriticalSection(Lock.READ); + try { + StmtIterator iter = unionModel.listStatements((Resource) null, RDF.type, subClass); + while (iter.hasNext()) { + Statement stmt = iter.next(); + subjectList.add(stmt.getSubject()); + } + } finally { + aboxModel.leaveCriticalSection(); + } - aboxModel.enterCriticalSection(Lock.READ); - try { - Iterator iter = unionModel.listStatements(ind1, (Property) null, (RDFNode) null); - while (iter.hasNext()) { - Statement stmt = iter.next(); - //System.out.println("\tIn loop. stmt = " + stmtString(stmt)); - if (stmt.getObject() == null) continue; - Statement infStmt = ResourceFactory.createStatement(ind2,stmt.getPredicate(),stmt.getObject()); - addInference(infStmt, inferenceModel,true); - } - } finally { - aboxModel.leaveCriticalSection(); + for (Resource subject : subjectList) { + Statement infStmt = ResourceFactory.createStatement(subject, RDF.type, superClass); + addInference(infStmt, inferenceModel, true); + setMostSpecificTypes(infStmt.getSubject(), inferenceModel, new HashSet()); + } + } + + /* + * If removed that B is a subclass of A, then for each individual + * that is of type B, either inferred or in the ABox, remove the + * assertion that it is of type A from the inferred model, + * UNLESS the individual is of some type C that is a subClass + * of A (including A itself) + */ + protected void removedSubClass(OntClass subClass, OntClass superClass, Model inferenceModel) { + OntModel unionModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); + unionModel.addSubModel(aboxModel); + unionModel.addSubModel(inferenceModel); + List subjectList = new ArrayList(); + aboxModel.enterCriticalSection(Lock.READ); + try { + StmtIterator iter = unionModel.listStatements((Resource) null, RDF.type, subClass); + while (iter.hasNext()) { + Statement stmt = iter.next(); + subjectList.add(stmt.getSubject()); + } + } finally { + aboxModel.leaveCriticalSection(); + } + + for (Resource ind : subjectList) { + if (entailedType(ind,superClass)) { + continue; } + Statement infStmt = ResourceFactory.createStatement(ind, RDF.type, superClass); + inferenceModel.enterCriticalSection(Lock.WRITE); + try { + if (inferenceModel.contains(infStmt)) { + inferenceModel.remove(infStmt); + } + + } finally { + inferenceModel.leaveCriticalSection(); + } + + setMostSpecificTypes(ind, inferenceModel, new HashSet()); + } + } + + /* + * If it is added that P is an inverse of Q, then: + * 1. For each statement involving predicate P in + * the assertions model add the inverse statement + * to the inference model if that inverse is + * in the assertions model. + * + * 2. Repeat the same for predicate Q. + * + */ + protected void addedInverseProperty(OntProperty prop1, OntProperty prop2, Model inferenceModel) { - return; + if ( !prop1.isObjectProperty() || !prop2.isObjectProperty() ) { + log.warn("The subject and object of the inverseOf statement are not both object properties. No inferencing will be performed. property 1: " + prop1.getURI() + " property 2:" + prop2.getURI()); + return; + } + + Model inferences = ModelFactory.createDefaultModel(); + inferences.add(generateInverseInferences(prop1, prop2)); + inferences.add(generateInverseInferences(prop2, prop1)); + + if (inferences.isEmpty()) return; + + StmtIterator iter = inferences.listStatements(); + + while (iter.hasNext()) { + Statement infStmt = iter.next(); + addInference(infStmt, inferenceModel, true); + } + } + + /* + * If it is removed that P is an inverse of Q, then: + * 1. For each statement involving predicate P in + * the abox assertions model remove the inverse + * statement from the inference model unless + * that statement is otherwise entailed. + * + * 2. Repeat the same for predicate Q. + */ + protected void removedInverseProperty(OntProperty prop1, OntProperty prop2, Model inferenceModel) { + + if ( !prop1.isObjectProperty() || !prop2.isObjectProperty() ) { + log.warn("The subject and object of the inverseOf statement are not both object properties. No inferencing will be performed. property 1: " + prop1.getURI() + " property 2:" + prop2.getURI()); + return; + } + + Model inferences = ModelFactory.createDefaultModel(); + inferences.add(generateInverseInferences(prop1, prop2)); + inferences.add(generateInverseInferences(prop2, prop1)); + + if (inferences.isEmpty()) return; + + StmtIterator iter = inferences.listStatements(); + + while (iter.hasNext()) { + Statement infStmt = iter.next(); + + if (entailedStatement(infStmt)) { + continue; + } + + removeInference(infStmt,inferenceModel); + } } /* * Get a list of individuals the same as the given individual */ - public List getSameIndividuals(Resource ind, Model inferenceModel) { + protected List getSameIndividuals(Resource ind, Model inferenceModel) { OntModel unionModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); unionModel.addSubModel(aboxModel); unionModel.addSubModel(inferenceModel); - + ArrayList sameIndividuals = new ArrayList(); aboxModel.enterCriticalSection(Lock.READ); try { @@ -590,10 +815,32 @@ public class SimpleReasoner extends StatementListener { return sameIndividuals; } + protected void generateSameAsInferences(Resource ind1, Resource ind2, Model inferenceModel) { + + OntModel unionModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); + unionModel.addSubModel(aboxModel); + unionModel.addSubModel(inferenceModel); + + aboxModel.enterCriticalSection(Lock.READ); + try { + Iterator iter = unionModel.listStatements(ind1, (Property) null, (RDFNode) null); + while (iter.hasNext()) { + Statement stmt = iter.next(); + if (stmt.getObject() == null) continue; + Statement infStmt = ResourceFactory.createStatement(ind2,stmt.getPredicate(),stmt.getObject()); + addInference(infStmt, inferenceModel,true); + } + } finally { + aboxModel.leaveCriticalSection(); + } + + return; + } + /* * Remove inferences for individual */ - public void removeInferencesForIndividual(Resource ind, Model inferenceModel) { + protected void removeInferencesForIndividual(Resource ind, Model inferenceModel) { Model individualInferences = ModelFactory.createDefaultModel(); @@ -621,7 +868,7 @@ public class SimpleReasoner extends StatementListener { /* * compute inferences for individual */ - public void computeInferencesForIndividual(Resource ind, Model inferenceModel) { + protected void computeInferencesForIndividual(Resource ind, Model inferenceModel) { Iterator iter = null; aboxModel.enterCriticalSection(Lock.WRITE); @@ -632,167 +879,13 @@ public class SimpleReasoner extends StatementListener { } while (iter.hasNext()) { - Statement stmt = iter.next(); - //System.out.println("calling addedStatement for: " + stmtString(stmt)); + Statement stmt = iter.next(); addedStatement(stmt); } return; } - /* - * Performs incremental property-based reasoning. - * - * Materializes inferences based on the owl:inverseOf relationship. - * and owl:sameAs - * - * If it is added that x prop1 y, and prop2 is an inverseOf prop1 - * then add y prop2 x to the inference graph, if it is not already in - * the assertions graph. - * - */ - public void addedABoxAssertion(Statement stmt, Model inferenceModel) { - - List inverseProperties = getInverseProperties(stmt); - Iterator inverseIter = inverseProperties.iterator(); - - while (inverseIter.hasNext()) { - Property inverseProp = inverseIter.next(); - Statement infStmt = ResourceFactory.createStatement(stmt.getObject().asResource(), inverseProp, stmt.getSubject()); - addInference(infStmt,inferenceModel,true); - } - - List sameIndividuals = getSameIndividuals(stmt.getSubject().asResource(), inferenceModel); - Iterator sameIter = sameIndividuals.iterator(); - while (sameIter.hasNext()) { - Resource subject = sameIter.next(); - Statement sameStmt = ResourceFactory.createStatement(subject,stmt.getPredicate(),stmt.getObject()); - addInference(sameStmt,inferenceModel,false); - } - - inferenceModel.enterCriticalSection(Lock.WRITE); - try { - if (inferenceModel.contains(stmt)) { - inferenceModel.remove(stmt); - } - } finally { - inferenceModel.leaveCriticalSection(); - } - } - - /* - * If it is removed that B is of type A, then for each superclass of A remove - * the inferred statement that B is of that type UNLESS it is otherwise entailed - * that B is of that type. - * - */ - protected void removedABoxTypeAssertion(Statement stmt, Model inferenceModel) { - tboxModel.enterCriticalSection(Lock.READ); - try { - OntClass cls = null; - - if ( (stmt.getObject().asResource()).getURI() != null ) { - cls = tboxModel.getOntClass(stmt.getObject().asResource().getURI()); - - if (cls != null) { - if (entailedType(stmt.getSubject(),cls)) { - inferenceModel.enterCriticalSection(Lock.WRITE); - try { - //don't have to check aboxmodel here because this is the - //statement being removed. - if (!inferenceModel.contains(stmt)) { - inferenceModel.add(stmt); - } - } finally { - inferenceModel.leaveCriticalSection(); - } - return; - } - - List parents = null; - parents = (cls.listSuperClasses(false)).toList(); - parents.addAll((cls.listEquivalentClasses()).toList()); - - Iterator parentIt = parents.iterator(); - - while (parentIt.hasNext()) { - OntClass parentClass = parentIt.next(); - - // VIVO doesn't materialize statements that assert anonymous types - // for individuals. Also, sharing an identical anonymous node is - // not allowed in owl-dl. picklist population code looks at qualities - // of classes not individuals. - if (parentClass.isAnon()) continue; - - if (entailedType(stmt.getSubject(),parentClass)) continue; // if a type is still entailed without the - // removed statement, then don't remove it - // from the inferences - - Statement infStmt = ResourceFactory.createStatement(stmt.getSubject(), RDF.type, parentClass); - - inferenceModel.enterCriticalSection(Lock.WRITE); - try { - if (inferenceModel.contains(infStmt)) { - inferenceModel.remove(infStmt); - } - } finally { - inferenceModel.leaveCriticalSection(); - } - } - } else { - log.warn("Didn't find target class (the object of the removed rdf:type statement) in the TBox: " - + ((Resource)stmt.getObject()).getURI() + ". No class subsumption reasoning will be performed based on the removal of this assertion."); - } - } else { - log.warn("The object of this rdf:type assertion has a null URI: " + stmtString(stmt)); - } - } catch (Exception e) { - log.warn("exception while removing abox type assertions: " + e.getMessage()); - } finally { - tboxModel.leaveCriticalSection(); - } - } - - /* - * Performs incremental property-based reasoning. - * - * Retracts inferences based on the owl:inverseOf relationship. - * - * If it is removed that x prop1 y, and prop2 is an inverseOf prop1 - * then remove y prop2 x from the inference graph, unless it is - * otherwise entailed by the assertions graph independently of - * this removed statement. - */ - public void removedABoxAssertion(Statement stmt, Model inferenceModel) { - - List inverseProperties = getInverseProperties(stmt); - Iterator inverseIter = inverseProperties.iterator(); - - while (inverseIter.hasNext()) { - OntProperty inverseProp = inverseIter.next(); - Statement infStmt = ResourceFactory.createStatement(stmt.getObject().asResource(), inverseProp, stmt.getSubject()); - removeInference(infStmt,inferenceModel,true); - } - - List sameIndividuals = getSameIndividuals(stmt.getSubject().asResource(), inferenceModel); - Iterator sameIter = sameIndividuals.iterator(); - while (sameIter.hasNext()) { - Statement stmtSame = ResourceFactory.createStatement(sameIter.next(), stmt.getPredicate(), stmt.getObject()); - removeInference(stmtSame,inferenceModel,false); - } - - // if a statement has been removed that is otherwise entailed, - // add it to the inference graph. - inferenceModel.enterCriticalSection(Lock.WRITE); - try { - if (entailedStatement(stmt) && !inferenceModel.contains(stmt)) { - inferenceModel.add(stmt); - } - } finally { - inferenceModel.leaveCriticalSection(); - } - } - // Returns true if it is entailed by class subsumption that // subject is of type cls; otherwise returns false. protected boolean entailedType(Resource subject, OntClass cls) { @@ -828,7 +921,7 @@ public class SimpleReasoner extends StatementListener { // reasoning or sameAs reasoning; otherwise returns false. protected boolean entailedStatement(Statement stmt) { - // class subsumption + //TODO think about checking class subsumption here // Inverse properties List inverses = getInverseProperties(stmt); @@ -870,6 +963,9 @@ public class SimpleReasoner extends StatementListener { return false; } + + + /* * Returns a list of properties that are inverses of the property * in the given statement. @@ -923,129 +1019,7 @@ public class SimpleReasoner extends StatementListener { return inverses; } - /* - * If it is added that B is a subClass of A, then for each - * individual that is typed as B, either in the ABox or in the - * inferred model, infer that it is of type A. - */ - protected void addedSubClass(OntClass subClass, OntClass superClass, Model inferenceModel) { - log.debug("subClass = " + subClass.getURI() + " superClass = " + superClass.getURI()); - OntModel unionModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); - unionModel.addSubModel(aboxModel); - unionModel.addSubModel(inferenceModel); - List subjectList = new ArrayList(); - aboxModel.enterCriticalSection(Lock.READ); - try { - StmtIterator iter = unionModel.listStatements((Resource) null, RDF.type, subClass); - while (iter.hasNext()) { - Statement stmt = iter.next(); - subjectList.add(stmt.getSubject()); - } - } finally { - aboxModel.leaveCriticalSection(); - } - - for (Resource subject : subjectList) { - Statement infStmt = ResourceFactory.createStatement(subject, RDF.type, superClass); - addInference(infStmt, inferenceModel, true); - setMostSpecificTypes(infStmt.getSubject(), inferenceModel, new HashSet()); - } - - /* - for (Resource subject : subjectList) { - Statement infStmt = ResourceFactory.createStatement(subject, RDF.type, superClass); - - inferenceModel.enterCriticalSection(Lock.WRITE); - aboxModel.enterCriticalSection(Lock.READ); - try { - if (!inferenceModel.contains(infStmt) ) { - if (!aboxModel.contains(infStmt)) { - inferenceModel.add(infStmt); - } - setMostSpecificTypes(infStmt.getSubject(), inferenceModel, new HashSet()); - } - } finally { - inferenceModel.leaveCriticalSection(); - aboxModel.leaveCriticalSection(); - } - } - */ - } - - /* - * If removed that B is a subclass of A, then for each individual - * that is of type B, either inferred or in the ABox, remove the - * assertion that it is of type A from the inferred model, - * UNLESS the individual is of some type C that is a subClass - * of A (including A itself) - */ - protected void removedSubClass(OntClass subClass, OntClass superClass, Model inferenceModel) { - OntModel unionModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); - unionModel.addSubModel(aboxModel); - unionModel.addSubModel(inferenceModel); - List subjectList = new ArrayList(); - aboxModel.enterCriticalSection(Lock.READ); - try { - StmtIterator iter = unionModel.listStatements((Resource) null, RDF.type, subClass); - while (iter.hasNext()) { - Statement stmt = iter.next(); - subjectList.add(stmt.getSubject()); - } - } finally { - aboxModel.leaveCriticalSection(); - } - - for (Resource ind : subjectList) { - if (entailedType(ind,superClass)) { - continue; - } - Statement infStmt = ResourceFactory.createStatement(ind, RDF.type, superClass); - inferenceModel.enterCriticalSection(Lock.WRITE); - try { - if (inferenceModel.contains(infStmt)) { - inferenceModel.remove(infStmt); - } - - } finally { - inferenceModel.leaveCriticalSection(); - } - - setMostSpecificTypes(ind, inferenceModel, new HashSet()); - } - } - - /* - * If it is added that P is an inverse of Q, then: - * 1. For each statement involving predicate P in - * the assertions model add the inverse statement - * to the inference model if that inverse is - * in the assertions model. - * - * 2. Repeat the same for predicate Q. - * - */ - public void addedInverseProperty(OntProperty prop1, OntProperty prop2, Model inferenceModel) { - - if ( !prop1.isObjectProperty() || !prop2.isObjectProperty() ) { - log.warn("The subject and object of the inverseOf statement are not both object properties. No inferencing will be performed. property 1: " + prop1.getURI() + " property 2:" + prop2.getURI()); - return; - } - - Model inferences = ModelFactory.createDefaultModel(); - inferences.add(generateInverseInferences(prop1, prop2)); - inferences.add(generateInverseInferences(prop2, prop1)); - - if (inferences.isEmpty()) return; - - StmtIterator iter = inferences.listStatements(); - - while (iter.hasNext()) { - Statement infStmt = iter.next(); - addInference(infStmt, inferenceModel, true); - } - } - - public Model generateInverseInferences(OntProperty prop, OntProperty inverseProp) { + protected Model generateInverseInferences(OntProperty prop, OntProperty inverseProp) { Model inferences = ModelFactory.createDefaultModel(); aboxModel.enterCriticalSection(Lock.READ); @@ -1066,38 +1040,43 @@ public class SimpleReasoner extends StatementListener { } /* - * If it is removed that P is an inverse of Q, then: - * 1. For each statement involving predicate P in - * the abox assertions model remove the inverse - * statement from the inference model unless - * that statement is otherwise entailed. - * - * 2. Repeat the same for predicate Q. + * Add an inference from the inference model + * + * Adds the inference to the inference model if it is not already in + * the inference model and not in the abox model. */ - public void removedInverseProperty(OntProperty prop1, OntProperty prop2, Model inferenceModel) { + protected void addInference(Statement infStmt, Model inferenceModel, boolean handleSameAs) { - if ( !prop1.isObjectProperty() || !prop2.isObjectProperty() ) { - log.warn("The subject and object of the inverseOf statement are not both object properties. No inferencing will be performed. property 1: " + prop1.getURI() + " property 2:" + prop2.getURI()); - return; - } - - Model inferences = ModelFactory.createDefaultModel(); - inferences.add(generateInverseInferences(prop1, prop2)); - inferences.add(generateInverseInferences(prop2, prop1)); - - if (inferences.isEmpty()) return; - - StmtIterator iter = inferences.listStatements(); - - while (iter.hasNext()) { - Statement infStmt = iter.next(); - - if (entailedStatement(infStmt)) { - continue; + aboxModel.enterCriticalSection(Lock.READ); + try { + inferenceModel.enterCriticalSection(Lock.WRITE); + try { + if (!inferenceModel.contains(infStmt) && !aboxModel.contains(infStmt)) { + inferenceModel.add(infStmt); + } + + if (handleSameAs) { + List sameIndividuals = getSameIndividuals(infStmt.getSubject().asResource(), inferenceModel); + Iterator sameIter = sameIndividuals.iterator(); + while (sameIter.hasNext()) { + Resource subject = sameIter.next(); + + Statement sameStmt = ResourceFactory.createStatement(subject,infStmt.getPredicate(),infStmt.getObject()); + if (subject.equals(infStmt.getObject()) && OWL.sameAs.equals(infStmt.getPredicate())) { + continue; + } + + if (!inferenceModel.contains(sameStmt) && !aboxModel.contains(sameStmt)) { + inferenceModel.add(sameStmt); + } + } + } + } finally { + inferenceModel.leaveCriticalSection(); } - - removeInference(infStmt,inferenceModel,true); - } + } finally { + aboxModel.leaveCriticalSection(); + } } /* @@ -1109,15 +1088,15 @@ public class SimpleReasoner extends StatementListener { * Removes the corresponding inference for each same individual * if that inference is not entailed by the abox model. */ - protected void removeInference(Statement infStmt, Model inferenceModel, boolean handleSameAs) { + protected void removeInference(Statement infStmt, Model inferenceModel) { + removeInference(infStmt,inferenceModel,true,true); + } - //TODO - add to Abox here if it's entailed? - - //System.out.println("\nremoveInference called for this statement: " + stmtString(infStmt)); + protected void removeInference(Statement infStmt, Model inferenceModel, boolean handleSameAs, boolean checkEntailment) { inferenceModel.enterCriticalSection(Lock.WRITE); - try { - if ( !entailedStatement(infStmt) && inferenceModel.contains(infStmt)) { + try { + if ( (!checkEntailment || !entailedStatement(infStmt)) && inferenceModel.contains(infStmt)) { inferenceModel.remove(infStmt); } } finally { @@ -1132,8 +1111,7 @@ public class SimpleReasoner extends StatementListener { Iterator sameIter = sameIndividuals.iterator(); while (sameIter.hasNext()) { Statement infStmtSame = ResourceFactory.createStatement(sameIter.next(), infStmt.getPredicate(), infStmt.getObject()); - if (!entailedStatement(infStmtSame) && inferenceModel.contains(infStmtSame)) { - //System.out.println("\tsameAs processing: removing this from the inference model: " + stmtString(infStmtSame)); + if ((!checkEntailment || !entailedStatement(infStmtSame)) && inferenceModel.contains(infStmtSame)) { inferenceModel.remove(infStmtSame); } } @@ -1143,75 +1121,9 @@ public class SimpleReasoner extends StatementListener { } } - /* - * Add an inference from the inference model - * - * Adds the inference to the inference model if it is not already in - * the inference model and not in the abox model. - */ - protected void addInference(Statement infStmt, Model inferenceModel, boolean handleSameAs) { - - //System.out.println("\taddInference called for this statement: " + stmtString(infStmt)); - - aboxModel.enterCriticalSection(Lock.READ); - try { - inferenceModel.enterCriticalSection(Lock.WRITE); - try { - if (!inferenceModel.contains(infStmt) && !aboxModel.contains(infStmt)) { - //System.out.println("\t\tadding this to the inference model: " + stmtString(infStmt)); - inferenceModel.add(infStmt); - } - - if (handleSameAs) { - List sameIndividuals = getSameIndividuals(infStmt.getSubject().asResource(), inferenceModel); - Iterator sameIter = sameIndividuals.iterator(); - while (sameIter.hasNext()) { - Resource subject = sameIter.next(); - - Statement sameStmt = ResourceFactory.createStatement(subject,infStmt.getPredicate(),infStmt.getObject()); - if (subject.equals(infStmt.getObject()) && OWL.sameAs.equals(infStmt.getPredicate())) { - //System.out.println("\t\tsameAS processing: skipping adding this statement to the inference model: " + stmtString(sameStmt)); - continue; - } - - if (!inferenceModel.contains(sameStmt) && !aboxModel.contains(sameStmt)) { - //System.out.println("\t\tsameAs processing: adding this to the inference model: " + stmtString(sameStmt)); - inferenceModel.add(sameStmt); - } - } - } - } finally { - inferenceModel.leaveCriticalSection(); - } - } finally { - aboxModel.leaveCriticalSection(); - } - - /* - //System.out.println("hello!!! ONE"); - if (handleSameAs) { - //System.out.println("hello!!! TWO"); - aboxModel.enterCriticalSection(Lock.READ); - //System.out.println("hello!!! TRES"); - try { - List sameIndividuals = getSameIndividuals(infStmt.getSubject().asResource(), inferenceModel); - Iterator sameIter = sameIndividuals.iterator(); - while (sameIter.hasNext()) { - Resource subject = sameIter.next(); - if (!inferenceModel.contains(subject,infStmt.getPredicate(),infStmt.getObject()) && !aboxModel.contains(subject,infStmt.getPredicate(),infStmt.getObject())) { - inferenceModel.add(subject,infStmt.getPredicate(),infStmt.getObject()); - } - } - } finally { - aboxModel.leaveCriticalSection(); - } - } - */ - } - /* * Find the most specific types (classes) of an individual and - * indicate them for the individual with the mostSpecificType + * infer them for the individual with the mostSpecificType * annotation. */ protected void setMostSpecificTypes(Resource individual, Model inferenceModel, HashSet unknownTypes) { @@ -1311,10 +1223,10 @@ public class SimpleReasoner extends StatementListener { protected void setMostSpecificTypes(Resource individual, HashSet typeURIs, Model inferenceModel) { - inferenceModel.enterCriticalSection(Lock.WRITE); - + Model retractions = ModelFactory.createDefaultModel(); + + inferenceModel.enterCriticalSection(Lock.READ); try { - Model retractions = ModelFactory.createDefaultModel(); // remove obsolete mostSpecificType assertions StmtIterator iter = inferenceModel.listStatements(individual, mostSpecificType, (RDFNode) null); @@ -1330,27 +1242,60 @@ public class SimpleReasoner extends StatementListener { retractions.add(stmt); } } - - inferenceModel.remove(retractions); - - // add new mostSpecificType assertions - Iterator typeIter = typeURIs.iterator(); - - while (typeIter.hasNext()) { - String typeURI = typeIter.next(); - Resource mstResource = ResourceFactory.createResource(typeURI); - - if (!inferenceModel.contains(individual, mostSpecificType, mstResource)) { - inferenceModel.add(individual, mostSpecificType, mstResource); - } - } } finally { inferenceModel.leaveCriticalSection(); - } - - return; + } + + Iterator rIter = retractions.listStatements(); + while (rIter.hasNext()) { + removeInference(rIter.next(), inferenceModel, true, false); + } + + Iterator typeIter = typeURIs.iterator(); + while (typeIter.hasNext()) { + String typeURI = typeIter.next(); + Statement mstStmt = ResourceFactory.createStatement(individual,mostSpecificType,ResourceFactory.createResource(typeURI)); + addInference(mstStmt,inferenceModel,true); + } + + return; } + // system-configured reasoning modules (plugins) + protected boolean isInterestedInRemovedStatement(Statement stmt) { + + if (stmt.getPredicate().equals(RDF.type)) return true; + + for (ReasonerPlugin plugin : getPluginList()) { + if (plugin.isInterestedInRemovedStatement(stmt)) return true; + } + + return false; + } + + protected void doPlugins(ModelUpdate.Operation op, Statement stmt) { + + for (ReasonerPlugin plugin : getPluginList()) { + try { + switch (op) { + case ADD: + if (plugin.isInterestedInAddedStatement(stmt)) { + plugin.addedABoxStatement(stmt, aboxModel, inferenceModel, tboxModel); + } + break; + case RETRACT: + if (plugin.isInterestedInRemovedStatement(stmt)) { + plugin.removedABoxStatement(stmt, aboxModel, inferenceModel, tboxModel); + } + break; + } + } catch (Exception e) { + log.error("Exception while processing " + (op == ModelUpdate.Operation.ADD ? "an added" : "a removed") + + " statement in SimpleReasoner plugin:" + plugin.getClass().getName() + " -- " + e.getMessage()); + } + } + } + /** * Returns true if the reasoner is in the process of recomputing all * inferences. @@ -1390,7 +1335,7 @@ public class SimpleReasoner extends StatementListener { HashSet unknownTypes = new HashSet(); inferenceRebuildModel.removeAll(); - log.info("Computing class subsumtion ABox inferences."); + log.info("Computing class subsumption ABox inferences."); int numStmts = 0; ArrayList individuals = this.getAllIndividualURIs(); @@ -1432,122 +1377,161 @@ public class SimpleReasoner extends StatementListener { } log.info("Finished computing class subsumption ABox inferences"); - log.info("Computing inverse property ABox inferences"); - Iterator invStatements = null; - tboxModel.enterCriticalSection(Lock.READ); + + Iterator invStatements = null; + tboxModel.enterCriticalSection(Lock.READ); + try { + invStatements = tboxModel.listStatements((Resource) null, OWL.inverseOf, (Resource) null); + } finally { + tboxModel.leaveCriticalSection(); + } + + numStmts = 0; + while (invStatements.hasNext()) { + Statement stmt = invStatements.next(); + try { - invStatements = tboxModel.listStatements((Resource) null, OWL.inverseOf, (Resource) null); - } finally { - tboxModel.leaveCriticalSection(); - } - - numStmts = 0; - while (invStatements.hasNext()) { - Statement stmt = invStatements.next(); - - try { - OntProperty prop1 = tboxModel.getOntProperty((stmt.getSubject()).getURI()); - if (prop1 == null) { - //TODO make sure not to print out a million of these for the same property - log.debug("didn't find subject property in the tbox: " + (stmt.getSubject()).getURI()); - continue; - } - - OntProperty prop2 = tboxModel.getOntProperty(((Resource)stmt.getObject()).getURI()); - if (prop2 == null) { - //TODO make sure not to print out a million of these for the same property - log.debug("didn't find object property in the tbox: " + ((Resource)stmt.getObject()).getURI()); - continue; - } - - addedInverseProperty(prop1, prop2, inferenceRebuildModel); - } catch (NullPointerException npe) { - log.error("a NullPointerException was received while recomputing the ABox inferences. Halting inference computation."); - return; - } catch (JenaException je) { - if (je.getMessage().equals("Statement models must no be null")) { - log.error("Exception while recomputing ABox inference model. Halting inference computation.", je); - return; - } - log.error("Exception while recomputing ABox inference model: ", je); - } catch (Exception e) { - log.error("Exception while recomputing ABox inference model: ", e); + OntProperty prop1 = tboxModel.getOntProperty((stmt.getSubject()).getURI()); + if (prop1 == null) { + //TODO make sure not to print out a million of these for the same property + log.debug("didn't find subject property in the tbox: " + (stmt.getSubject()).getURI()); + continue; } - numStmts++; - if ((numStmts % 10000) == 0) { - log.info("Still computing inverse property ABox inferences..."); - } - - if (stopRequested) { - log.info("a stopRequested signal was received during recomputeABox. Halting Processing."); - return; - } + OntProperty prop2 = tboxModel.getOntProperty(((Resource)stmt.getObject()).getURI()); + if (prop2 == null) { + //TODO make sure not to print out a million of these for the same property + log.debug("didn't find object property in the tbox: " + ((Resource)stmt.getObject()).getURI()); + continue; + } + + addedInverseProperty(prop1, prop2, inferenceRebuildModel); + } catch (NullPointerException npe) { + log.error("a NullPointerException was received while recomputing the ABox inferences. Halting inference computation."); + return; + } catch (JenaException je) { + if (je.getMessage().equals("Statement models must no be null")) { + log.error("Exception while recomputing ABox inference model. Halting inference computation.", je); + return; + } + log.error("Exception while recomputing ABox inference model: ", je); + } catch (Exception e) { + log.error("Exception while recomputing ABox inference model: ", e); } - log.info("Finished computing inverse property ABox inferences"); + numStmts++; + if ((numStmts % 10000) == 0) { + log.info("Still computing inverse property ABox inferences..."); + } + + if (stopRequested) { + log.info("a stopRequested signal was received during recomputeABox. Halting Processing."); + return; + } + } + log.info("Finished computing inverse property ABox inferences"); log.info("Computing sameAs ABox inferences"); - Iterator sameAsStatements = null; - aboxModel.enterCriticalSection(Lock.READ); + Iterator sameAsStatements = null; + aboxModel.enterCriticalSection(Lock.READ); + try { + sameAsStatements = aboxModel.listStatements((Resource) null, OWL.sameAs, (Resource) null); + } finally { + aboxModel.leaveCriticalSection(); + } + + numStmts = 0; + while (sameAsStatements.hasNext()) { + Statement stmt = sameAsStatements.next(); + try { - sameAsStatements = aboxModel.listStatements((Resource) null, OWL.sameAs, (Resource) null); - } finally { - aboxModel.leaveCriticalSection(); - } - - numStmts = 0; - while (sameAsStatements.hasNext()) { - Statement stmt = sameAsStatements.next(); - - try { - addedABoxSameAsAssertion(stmt, inferenceRebuildModel); - } catch (NullPointerException npe) { - log.error("a NullPointerException was received while recomputing the ABox inferences. Halting inference computation."); - return; - } catch (JenaException je) { - if (je.getMessage().equals("Statement models must no be null")) { - log.error("Exception while recomputing ABox inference model. Halting inference computation.", je); - return; - } - log.error("Exception while recomputing ABox inference model: ", je); - } catch (Exception e) { - log.error("Exception while recomputing ABox inference model: ", e); - } - - numStmts++; - if ((numStmts % 10000) == 0) { - log.info("Still computing sameAs ABox inferences..."); - } - - if (stopRequested) { - log.info("a stopRequested signal was received during recomputeABox. Halting Processing."); - return; - } - } - log.info("Finished computing sameAs ABox inferences"); - - try { - if (updateInferenceModel(inferenceRebuildModel)) { - log.info("a stopRequested signal was received during updateInferenceModel. Halting Processing."); - return; - } + addedABoxSameAsAssertion(stmt, inferenceRebuildModel); + } catch (NullPointerException npe) { + log.error("a NullPointerException was received while recomputing the ABox inferences. Halting inference computation."); + return; + } catch (JenaException je) { + if (je.getMessage().equals("Statement models must no be null")) { + log.error("Exception while recomputing ABox inference model. Halting inference computation.", je); + return; + } + log.error("Exception while recomputing ABox inference model: ", je); } catch (Exception e) { - log.error("Exception while reconciling the current and recomputed ABox inference model for class subsumption inferences. Halting processing." , e); - inferenceRebuildModel.removeAll(); - return; - } + log.error("Exception while recomputing ABox inference model: ", e); + } + + numStmts++; + if ((numStmts % 10000) == 0) { + log.info("Still computing sameAs ABox inferences..."); + } + + if (stopRequested) { + log.info("a stopRequested signal was received during recomputeABox. Halting Processing."); + return; + } + } + log.info("Finished computing sameAs ABox inferences"); + + try { + if (updateInferenceModel(inferenceRebuildModel)) { + log.info("a stopRequested signal was received during updateInferenceModel. Halting Processing."); + return; + } + } catch (Exception e) { + log.error("Exception while reconciling the current and recomputed ABox inference model for class subsumption inferences. Halting processing." , e); + inferenceRebuildModel.removeAll(); + return; + } } catch (Exception e) { - log.error("Exception while recomputing ABox inferences. Halting processing.", e); - inferenceRebuildModel.removeAll(); - return; + log.error("Exception while recomputing ABox inferences. Halting processing.", e); + inferenceRebuildModel.removeAll(); + return; } finally { - inferenceRebuildModel.leaveCriticalSection(); + inferenceRebuildModel.leaveCriticalSection(); } } + /* + * Get the URIs for all individuals in the system + */ + protected ArrayList getAllIndividualURIs() { + + String queryString = "select distinct ?subject where {?subject ?type}"; + return getIndividualURIs(queryString); + } + + protected ArrayList getIndividualURIs(String queryString) { + + ArrayList individuals = new ArrayList(); + aboxModel.enterCriticalSection(Lock.READ); + + try { + try { + Query query = QueryFactory.create(queryString, Syntax.syntaxARQ); + QueryExecution qe = QueryExecutionFactory.create(query, aboxModel); + + ResultSet results = qe.execSelect(); + + while (results.hasNext()) { + QuerySolution solution = results.next(); + Resource resource = solution.getResource("subject"); + + if ((resource != null) && !resource.isAnon()) { + individuals.add(resource.getURI()); + } + } + + } catch (Exception e) { + log.error("exception while retrieving list of individuals ",e); + } + } finally { + aboxModel.leaveCriticalSection(); + } + + return individuals; + } + /* * reconcile a set of inferences into the application inference model */ @@ -1653,82 +1637,7 @@ public class SimpleReasoner extends StatementListener { log.info("ABox inference model updated"); return false; } - /* - * Get the URIs for all individuals in the system - */ - protected ArrayList getAllIndividualURIs() { - - String queryString = "select distinct ?subject where {?subject ?type}"; - return getIndividualURIs(queryString); - } - - protected ArrayList getIndividualURIs(String queryString) { - - ArrayList individuals = new ArrayList(); - aboxModel.enterCriticalSection(Lock.READ); - - try { - try { - Query query = QueryFactory.create(queryString, Syntax.syntaxARQ); - QueryExecution qe = QueryExecutionFactory.create(query, aboxModel); - - ResultSet results = qe.execSelect(); - - while (results.hasNext()) { - QuerySolution solution = results.next(); - Resource resource = solution.getResource("subject"); - - if ((resource != null) && !resource.isAnon()) { - individuals.add(resource.getURI()); - } - } - - } catch (Exception e) { - log.error("exception while retrieving list of individuals ",e); - } - } finally { - aboxModel.leaveCriticalSection(); - } - - return individuals; - } - - // system-configured reasoning modules (plugins) - public boolean isInterestedInRemovedStatement(Statement stmt) { - - if (stmt.getPredicate().equals(RDF.type)) return true; - - for (ReasonerPlugin plugin : getPluginList()) { - if (plugin.isInterestedInRemovedStatement(stmt)) return true; - } - - return false; - } - - protected void doPlugins(ModelUpdate.Operation op, Statement stmt) { - - for (ReasonerPlugin plugin : getPluginList()) { - try { - switch (op) { - case ADD: - if (plugin.isInterestedInAddedStatement(stmt)) { - plugin.addedABoxStatement(stmt, aboxModel, inferenceModel, tboxModel); - } - break; - case RETRACT: - if (plugin.isInterestedInRemovedStatement(stmt)) { - plugin.removedABoxStatement(stmt, aboxModel, inferenceModel, tboxModel); - } - break; - } - } catch (Exception e) { - log.error("Exception while processing " + (op == ModelUpdate.Operation.ADD ? "an added" : "a removed") + - " statement in SimpleReasoner plugin:" + plugin.getClass().getName() + " -- " + e.getMessage()); - } - } - } - /** * This is called when the application shuts down. */ @@ -1745,10 +1654,8 @@ public class SimpleReasoner extends StatementListener { "] [object = " + (statement.getObject().isLiteral() ? ((Literal)statement.getObject()).getLexicalForm() + " (Literal)" : ((Resource)statement.getObject()).getURI() + " (Resource)") + "]"; } - - - // DeltaComputer - + + // DeltaComputer /* * Asynchronous reasoning mode (DeltaComputer) is used in the case of batch removals. */ diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/reasoner/SimpleReasonerTBoxListener.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/reasoner/SimpleReasonerTBoxListener.java index f3ab12423..840572d51 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/reasoner/SimpleReasonerTBoxListener.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/reasoner/SimpleReasonerTBoxListener.java @@ -49,12 +49,14 @@ public class SimpleReasonerTBoxListener extends StatementListener { @Override public void addedStatement(Statement statement) { + ModelUpdate mu = new ModelUpdate(statement, ModelUpdate.Operation.ADD, JenaDataSourceSetupBase.JENA_TBOX_ASSERTIONS_MODEL); processUpdate(mu); } @Override public void removedStatement(Statement statement) { + ModelUpdate mu = new ModelUpdate(statement, ModelUpdate.Operation.RETRACT, JenaDataSourceSetupBase.JENA_TBOX_ASSERTIONS_MODEL); processUpdate(mu); } diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/reasoner/SimpleReasonerInversePropertyTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/reasoner/SimpleReasonerInversePropertyTest.java index 2d23b3782..b96b33f64 100644 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/reasoner/SimpleReasonerInversePropertyTest.java +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/reasoner/SimpleReasonerInversePropertyTest.java @@ -24,7 +24,7 @@ public class SimpleReasonerInversePropertyTest extends AbstractTestClass { @Before public void suppressErrorOutput() { - //suppressSyserr(); + suppressSyserr(); //Turn off log messages to console setLoggerLevel(SimpleReasoner.class, Level.OFF); setLoggerLevel(SimpleReasonerTBoxListener.class, Level.OFF); @@ -42,44 +42,42 @@ public class SimpleReasonerInversePropertyTest extends AbstractTestClass { @Test public void addABoxAssertion1() { + // set up the tbox OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC); - OntProperty P = tBox.createOntProperty("http://test.vivo/P"); P.setLabel("property P", "en-US"); - OntProperty Q = tBox.createOntProperty("http://test.vivo/Q"); Q.setLabel("property Q", "en-US"); P.addInverseOf(Q); - // this is the model to receive inferences + // this is the model to receive abox inferences Model inf = ModelFactory.createDefaultModel(); - // create an ABox and register the SimpleReasoner listener with it + // create an abox and register the SimpleReasoner listener with it OntModel aBox = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); aBox.register(new SimpleReasoner(tBox, aBox, inf)); - // Individuals a, b, c and d + // add assertions to the abox and verify inferences Resource a = aBox.createResource("http://test.vivo/a"); Resource b = aBox.createResource("http://test.vivo/b"); Resource c = aBox.createResource("http://test.vivo/c"); Resource d = aBox.createResource("http://test.vivo/d"); - // b Q a is inferred from a P b aBox.add(a,P,b); - Assert.assertTrue(inf.contains(b,Q,a)); - - // d P c is inferred from c Q d. + Assert.assertTrue(inf.contains(b,Q,a)); aBox.add(c,Q,d); Assert.assertTrue(inf.contains(d,P,c)); } /* - * don't infer if it's already in the abox + * don't infer statements already in the abox + * (never infer because it's in the abox already) */ @Test public void addABoxAssertion2() { + // set up the tbox OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC); OntProperty P = tBox.createOntProperty("http://test.vivo/P"); @@ -88,10 +86,10 @@ public class SimpleReasonerInversePropertyTest extends AbstractTestClass { Q.setLabel("property Q", "en-US"); P.addInverseOf(Q); - // this is the model to receive inferences + // this is the model to receive abox inferences Model inf = ModelFactory.createDefaultModel(); - // create an ABox and add statement b Q a + // create an ABox and add data (no inferencing happening yet) OntModel aBox = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); // Individuals a, b, c and d Resource a = aBox.createResource("http://test.vivo/a"); @@ -101,38 +99,42 @@ public class SimpleReasonerInversePropertyTest extends AbstractTestClass { // register SimpleReasoner aBox.register(new SimpleReasoner(tBox, aBox, inf)); - // b Q a is inferred from a P b, but it is already in the abox + Assert.assertFalse(inf.contains(b,Q,a)); + + // add data and verify inferences aBox.add(a,P,b); Assert.assertFalse(inf.contains(b,Q,a)); } /* - * don't infer if it's already in the abox + * don't infer statements already in the abox + * (remove the inference when it is asserted) */ @Test public void addABoxAssertion3() { - OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC); + // set up the tbox + OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC); OntProperty P = tBox.createOntProperty("http://test.vivo/P"); P.setLabel("property P", "en-US"); OntProperty Q = tBox.createOntProperty("http://test.vivo/Q"); Q.setLabel("property Q", "en-US"); P.addInverseOf(Q); - // this is the model to receive inferences + // this is the model to receive abox inferences Model inf = ModelFactory.createDefaultModel(); - // create an ABox and register SimpleReasoner + // create abox and register SimpleReasoner OntModel aBox = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); aBox.register(new SimpleReasoner(tBox, aBox, inf)); - // Individuals a, b, c and d + // add statements to the abox and verify inferences Resource a = aBox.createResource("http://test.vivo/a"); Resource b = aBox.createResource("http://test.vivo/b"); - // b Q a is inferred from a P b, but it is already in the abox aBox.add(a,P,b); - aBox.add(b,Q,a); + Assert.assertTrue(inf.contains(b,Q,a)); + aBox.add(b,Q,a); // this should cause the inference to be removed Assert.assertFalse(inf.contains(b,Q,a)); } @@ -143,8 +145,8 @@ public class SimpleReasonerInversePropertyTest extends AbstractTestClass { @Test public void addABoxAssertion4() { + // set up the tbox OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC); - OntProperty P = tBox.createOntProperty("http://test.vivo/P"); P.setLabel("property P", "en-US"); OntProperty R = tBox.createOntProperty("http://test.vivo/R"); @@ -153,27 +155,24 @@ public class SimpleReasonerInversePropertyTest extends AbstractTestClass { Q.setLabel("property Q", "en-US"); R.addEquivalentProperty(P); - P.addEquivalentProperty(R); P.addInverseOf(Q); - // this is the model to receive inferences + // this is the model to receive abox inferences Model inf = ModelFactory.createDefaultModel(); - // create an ABox and register the SimpleReasoner listener with it + // create an ABox and register the SimpleReasoner with it OntModel aBox = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); aBox.register(new SimpleReasoner(tBox, aBox, inf)); - // a, b, c and d + // add abox statements and verify inferences Resource a = aBox.createResource("http://test.vivo/a"); Resource b = aBox.createResource("http://test.vivo/b"); Resource c = aBox.createResource("http://test.vivo/c"); Resource d = aBox.createResource("http://test.vivo/d"); - // b Q a is inferred from a R b. aBox.add(a,R,b); Assert.assertTrue(inf.contains(b,Q,a)); - - // d P c is inferred from c Q d. + aBox.add(c,Q,d); Assert.assertTrue(inf.contains(d,P,c)); Assert.assertTrue(inf.contains(d,R,c)); @@ -181,11 +180,14 @@ public class SimpleReasonerInversePropertyTest extends AbstractTestClass { /* * basic scenarios around removing abox data + * don't remove an inference if it's still + * entailed by something else in the abox. */ @Test public void removedABoxAssertion1() { - OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC); + // set up the tbox + OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC); OntProperty P = tBox.createOntProperty("http://test.vivo/P"); P.setLabel("property P", "en-US"); OntProperty Q = tBox.createOntProperty("http://test.vivo/Q"); @@ -195,24 +197,23 @@ public class SimpleReasonerInversePropertyTest extends AbstractTestClass { P.addInverseOf(Q); P.addInverseOf(T); - // this is the model to receive inferences + // this is the model to receive abox inferences Model inf = ModelFactory.createDefaultModel(); - // create an ABox and register the SimpleReasoner listener with it + // create an ABox and register the SimpleReasoner with it OntModel aBox = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); aBox.register(new SimpleReasoner(tBox, aBox, inf)); - // Individuals a, b, c and d + // add statements to the abox and verify inferences Resource a = aBox.createResource("http://test.vivo/a"); Resource b = aBox.createResource("http://test.vivo/b"); Resource c = aBox.createResource("http://test.vivo/c"); Resource d = aBox.createResource("http://test.vivo/d"); - // b Q a is inferred from a P b. aBox.add(a,P,b); Assert.assertTrue(inf.contains(b,Q,a)); - // d P c is inferred from c Q d and from c T d + // d P c is inferred from c Q d and also from c T d aBox.add(c,Q,d); aBox.add(c,T,d); Assert.assertTrue(inf.contains(d,P,c)); @@ -220,17 +221,19 @@ public class SimpleReasonerInversePropertyTest extends AbstractTestClass { aBox.remove(a,P,b); Assert.assertFalse(inf.contains(b,Q,a)); - aBox.remove(c,Q,d); - Assert.assertTrue(inf.contains(d,P,c)); + aBox.remove(c,Q,d); + Assert.assertTrue(inf.contains(d,P,c)); // still inferred from c T d } /* * removing abox data with equivalent and inverse properties + * don't remove inference if it's still inferred. */ @Test public void removedABoxAssertion2() { - OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC); + // set up the tbox + OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC); OntProperty P = tBox.createOntProperty("http://test.vivo/P"); P.setLabel("property P", "en-US"); OntProperty Q = tBox.createOntProperty("http://test.vivo/Q"); @@ -238,26 +241,29 @@ public class SimpleReasonerInversePropertyTest extends AbstractTestClass { OntProperty T = tBox.createOntProperty("http://test.vivo/T"); Q.setLabel("property T", "en-US"); P.addInverseOf(Q); - Q.addInverseOf(P); P.addEquivalentProperty(T); - T.addEquivalentProperty(P); + + // not clear what these will do + tBox.rebind(); + tBox.prepare(); - // this is the model to receive inferences + // this is the model to receive abox inferences Model inf = ModelFactory.createDefaultModel(); - // create an ABox and register the SimpleReasoner listener with it + // create an abox and register the SimpleReasoner listener with it OntModel aBox = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); aBox.register(new SimpleReasoner(tBox, aBox, inf)); - // Individuals a, b, c and d + // add abox data and verify inferences Resource a = aBox.createResource("http://test.vivo/a"); Resource b = aBox.createResource("http://test.vivo/b"); - // b Q a is inferred from a P b and a T b. + // b Q a is inferred from a P b and also from a T b. aBox.add(a,P,b); aBox.add(a,T,b); Assert.assertTrue(inf.contains(b,Q,a)); Assert.assertFalse(inf.contains(a,P,b)); + Assert.assertFalse(inf.contains(a,T,b)); aBox.remove(a,P,b); Assert.assertTrue(inf.contains(b,Q,a)); @@ -268,80 +274,81 @@ public class SimpleReasonerInversePropertyTest extends AbstractTestClass { */ @Test public void removedABoxAssertion3() { - OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC); + //set up the tbox + OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC); OntProperty P = tBox.createOntProperty("http://test.vivo/P"); P.setLabel("property P", "en-US"); OntProperty Q = tBox.createOntProperty("http://test.vivo/Q"); Q.setLabel("property Q", "en-US"); P.addInverseOf(Q); - // this is the model to receive inferences + tBox.rebind(); // not sure what effect this has + + // this is the model to receive abox inferences Model inf = ModelFactory.createDefaultModel(); - // create an ABox and register the SimpleReasoner listener with it - OntModel aBox = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); + // create the abox and add some data - no reasoning is happening yet + OntModel aBox = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); + Resource a = aBox.createResource("http://test.vivo/a"); Resource b = aBox.createResource("http://test.vivo/b"); aBox.add(a,P,b); + // register the SimpleReasoner aBox.register(new SimpleReasoner(tBox, aBox, inf)); + // add abox statements and verify inferences aBox.add(b,Q,a); - Assert.assertFalse(inf.contains(b,Q,a)); - Assert.assertFalse(inf.contains(a,P,b)); - + Assert.assertFalse(inf.contains(a,P,b)); // this could be inferred from b Q a, but + // it's already in the abox aBox.remove(a,P,b); - Assert.assertTrue(inf.contains(a,P,b)); + Assert.assertTrue(inf.contains(a,P,b)); // now it gets added to inference model + // when it's removed from the abox } /* - * Basic scenario around adding an inverseOf assertion to the - * TBox + * adding an inverseOf assertion to the tbox */ @Test public void addTBoxInverseAssertion1() throws InterruptedException { - - // Create TBox, ABox and Inference models and register - // the ABox reasoner listeners with the ABox and TBox - // Pellet will compute TBox inferences - + + // Set up the TBox. OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC); - OntProperty P = tBox.createOntProperty("http://test.vivo/P"); P.setLabel("property P", "en-US"); - OntProperty Q = tBox.createOntProperty("http://test.vivo/Q"); Q.setLabel("property Q", "en-US"); - OntModel aBox = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); + // this is the model to receive abox inferences Model inf = ModelFactory.createDefaultModel(); - - SimpleReasoner simpleReasoner = new SimpleReasoner(tBox, aBox, inf); + + // abox + OntModel aBox = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); + + // set up SimpleReasoner and register it with abox. register + // SimpleReasonerTBoxListener with the tbox. + SimpleReasoner simpleReasoner = new SimpleReasoner(tBox, aBox, inf); aBox.register(simpleReasoner); SimpleReasonerTBoxListener simpleReasonerTBoxListener = getTBoxListener(simpleReasoner); tBox.register(simpleReasonerTBoxListener); - // Individuals a, b, c and d + // add abox data Resource a = aBox.createResource("http://test.vivo/a"); Resource b = aBox.createResource("http://test.vivo/b"); Resource c = aBox.createResource("http://test.vivo/c"); Resource d = aBox.createResource("http://test.vivo/d"); - - // abox statements + aBox.add(a,P,b); aBox.add(c,P,d); aBox.add(b,Q,a); - // Assert P and Q as inverses and wait for SimpleReasoner TBox - // thread to end + // Assert P and Q as inverses and wait for + // SimpleReasonerTBoxListener thread to end Q.addInverseOf(P); - - tBox.rebind(); - tBox.prepare(); - + while (!VitroBackgroundThread.getLivingThreads().isEmpty()) { Thread.sleep(delay); } @@ -349,47 +356,43 @@ public class SimpleReasonerInversePropertyTest extends AbstractTestClass { // Verify inferences Assert.assertTrue(inf.contains(d,Q,c)); Assert.assertFalse(inf.contains(b,Q,a)); + Assert.assertFalse(inf.contains(a,P,b)); simpleReasonerTBoxListener.setStopRequested(); } /* - * Basic scenario around removing an inverseOf assertion to the - * TBox + * removing an inverseOf assertion from the tbox */ @Test public void removeTBoxInverseAssertion1() throws InterruptedException { - // Create TBox, ABox and Inference models and register - // the ABox reasoner listeners with the ABox and TBox - // Pellet will compute TBox inferences - + // set up the tbox. OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC); - // set up TBox and Abox - OntProperty P = tBox.createOntProperty("http://test.vivo/propP"); P.setLabel("property P", "en-US"); - OntProperty Q = tBox.createOntProperty("http://test.vivo/propQ"); Q.setLabel("property Q", "en-US"); - Q.addInverseOf(P); + // this is the model to receive abox inferences + Model inf = ModelFactory.createDefaultModel(); + + // abox OntModel aBox = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); - Model inf = ModelFactory.createDefaultModel(); - - SimpleReasoner simpleReasoner = new SimpleReasoner(tBox, aBox, inf); + + // set up SimpleReasoner and SimpleReasonerTBox listener, + // register them with abox and tbox + SimpleReasoner simpleReasoner = new SimpleReasoner(tBox, aBox, inf); aBox.register(simpleReasoner); SimpleReasonerTBoxListener simpleReasonerTBoxListener = getTBoxListener(simpleReasoner); tBox.register(simpleReasonerTBoxListener); - // Individuals a, b, c and d + + // add statements to the abox and verify inference Resource c = aBox.createResource("http://test.vivo/c"); Resource d = aBox.createResource("http://test.vivo/d"); - - // abox statements aBox.add(c,P,d); - Assert.assertTrue(inf.contains(d,Q,c)); // Remove P and Q inverse relationship and wait for @@ -397,14 +400,11 @@ public class SimpleReasonerInversePropertyTest extends AbstractTestClass { Q.removeInverseProperty(P); - tBox.rebind(); - tBox.prepare(); - while (!VitroBackgroundThread.getLivingThreads().isEmpty()) { Thread.sleep(delay); } - // Verify inferences + // Verify inference has been removed Assert.assertFalse(inf.contains(d,Q,c)); simpleReasonerTBoxListener.setStopRequested(); @@ -416,12 +416,9 @@ public class SimpleReasonerInversePropertyTest extends AbstractTestClass { @Test public void recomputeABox1() throws InterruptedException { - // Create TBox, ABox and Inference models and register - // the ABox reasoner listeners with the ABox and TBox - // Pellet will compute TBox inferences + // set up tbox OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC); - // set up TBox and Abox OntProperty P = tBox.createOntProperty("http://test.vivo/propP"); P.setLabel("property P", "en-US"); OntProperty Q = tBox.createOntProperty("http://test.vivo/propQ"); @@ -434,21 +431,23 @@ public class SimpleReasonerInversePropertyTest extends AbstractTestClass { Q.setLabel("property Y", "en-US"); X.addInverseOf(Y); + // create abox and abox inf model and register simplereasoner + // with abox. OntModel aBox = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); - Model inf = ModelFactory.createDefaultModel(); - + Model inf = ModelFactory.createDefaultModel(); SimpleReasoner simpleReasoner = new SimpleReasoner(tBox, aBox, inf); aBox.register(simpleReasoner); - // Individuals a, b, c and d + + // abox statements Resource a = aBox.createResource("http://test.vivo/a"); Resource b = aBox.createResource("http://test.vivo/b"); Resource c = aBox.createResource("http://test.vivo/c"); Resource d = aBox.createResource("http://test.vivo/d"); - // abox statements aBox.add(a,P,b); aBox.add(c,X,d); + //recompute whole abox simpleReasoner.recompute(); while (simpleReasoner.isRecomputing()) { diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/reasoner/SimpleReasonerSameAsTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/reasoner/SimpleReasonerSameAsTest.java index 3e589969e..b7b3574d4 100644 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/reasoner/SimpleReasonerSameAsTest.java +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/reasoner/SimpleReasonerSameAsTest.java @@ -8,6 +8,7 @@ import org.junit.Before; import org.junit.Test; import org.mindswap.pellet.jena.PelletReasonerFactory; +import com.hp.hpl.jena.ontology.AnnotationProperty; import com.hp.hpl.jena.ontology.OntClass; import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.ontology.OntModelSpec; @@ -16,6 +17,7 @@ import com.hp.hpl.jena.rdf.model.Literal; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.ModelFactory; import com.hp.hpl.jena.rdf.model.Resource; +import com.hp.hpl.jena.rdf.model.ResourceFactory; import com.hp.hpl.jena.vocabulary.OWL; import com.hp.hpl.jena.vocabulary.RDF; @@ -25,10 +27,11 @@ import edu.cornell.mannlib.vitro.webapp.utils.threads.VitroBackgroundThread; public class SimpleReasonerSameAsTest extends AbstractTestClass { long delay = 50; - + private static final String mostSpecificTypePropertyURI = "http://vitro.mannlib.cornell.edu/ns/vitro/0.7#mostSpecificType"; + @Before public void suppressErrorOutput() { - //suppressSyserr(); + suppressSyserr(); //Turn off log messages to console setLoggerLevel(SimpleReasoner.class, Level.OFF); setLoggerLevel(SimpleReasonerTBoxListener.class, Level.OFF); @@ -363,9 +366,6 @@ public class SimpleReasonerSameAsTest extends AbstractTestClass { Q.addInverseOf(P); - tBox.rebind(); - tBox.prepare(); - while (!VitroBackgroundThread.getLivingThreads().isEmpty()) { Thread.sleep(delay); } @@ -377,9 +377,6 @@ public class SimpleReasonerSameAsTest extends AbstractTestClass { Q.removeInverseProperty(P); - tBox.rebind(); - tBox.prepare(); - while (!VitroBackgroundThread.getLivingThreads().isEmpty()) { Thread.sleep(delay); } @@ -429,22 +426,127 @@ public class SimpleReasonerSameAsTest extends AbstractTestClass { Assert.assertTrue(inf.contains(y,RDF.type,classB)); Assert.assertTrue(inf.contains(y,RDF.type,classA)); -// Assert.assertTrue(inf.contains(z,RDF.type,classB)); -// Assert.assertTrue(inf.contains(z,RDF.type,classA)); + Assert.assertTrue(inf.contains(z,RDF.type,classB)); + Assert.assertTrue(inf.contains(z,RDF.type,classA)); aBox.remove(x,RDF.type,classB); Assert.assertFalse(inf.contains(y,RDF.type,classB)); - Assert.assertFalse(inf.contains(y,RDF.type,classA)); + Assert.assertFalse(inf.contains(y,RDF.type,classA)); + Assert.assertFalse(inf.contains(z,RDF.type,classB)); + Assert.assertFalse(inf.contains(z,RDF.type,classA)); } - /* * adding and removing subclass assertion when there is an * individual member who has a sameAs individual. */ - //@Test + @Test public void tBoxSubclassAssertion1() throws InterruptedException { + + //create aBox and tBox, and SimpleReasoner to listen to them + OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC); + OntModel aBox = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); + Model inf = ModelFactory.createDefaultModel(); + + SimpleReasoner simpleReasoner = new SimpleReasoner(tBox, aBox, inf); + aBox.register(simpleReasoner); + SimpleReasonerTBoxListener simpleReasonerTBoxListener = getTBoxListener(simpleReasoner); + tBox.register(simpleReasonerTBoxListener); + // set up TBox + OntClass classA = tBox.createClass("http://test.vivo/A"); + classA.setLabel("class A", "en-US"); + OntClass classB = tBox.createClass("http://test.vivo/B"); + classB.setLabel("class B", "en-US"); + OntClass classC = tBox.createClass("http://test.vivo/C"); + classC.setLabel("class C", "en-US"); + + // set up ABox + Resource a = aBox.createResource("http://test.vivo/a"); + Resource b = aBox.createResource("http://test.vivo/b"); + Resource c = aBox.createResource("http://test.vivo/c"); + + aBox.add(a, RDF.type, classC); + aBox.add(a, OWL.sameAs, b); + aBox.add(c, OWL.sameAs, a); + + // update TBox + classA.addSubClass(classB); + + // wait for SimpleReasonerTBoxListener thread to end + while (!VitroBackgroundThread.getLivingThreads().isEmpty()) { + Thread.sleep(delay); + } + + classB.addSubClass(classC); + classA.addSubClass(classC); // simulate what Pellet would infer, and + // thus what the SimpleReasonerTBoxListener + // would be notified of. + + // wait for SimpleReasonerTBoxListener thread to end + while (!VitroBackgroundThread.getLivingThreads().isEmpty()) { + Thread.sleep(delay); + } + + // Verify inferences + Assert.assertFalse(inf.contains(a, RDF.type, classC)); + Assert.assertTrue(inf.contains(a, RDF.type, classB)); + Assert.assertTrue(inf.contains(a, RDF.type, classA)); + + Assert.assertTrue(inf.contains(b, RDF.type, classC)); + Assert.assertTrue(inf.contains(b, RDF.type, classB)); + Assert.assertTrue(inf.contains(b, RDF.type, classA)); + + Assert.assertTrue(inf.contains(c, RDF.type, classC)); + Assert.assertTrue(inf.contains(c, RDF.type, classB)); + Assert.assertTrue(inf.contains(c, RDF.type, classA)); + + // update TBox + classA.removeSubClass(classB); + classA.removeSubClass(classC); // simulate what Pellet would infer, and + // thus what the SimpleReasonerTBoxListener + // would be notified of. + + // wait for SimpleReasonerTBoxListener thread to end + while (!VitroBackgroundThread.getLivingThreads().isEmpty()) { + Thread.sleep(delay); + } + + // Verify inferences + Assert.assertFalse(inf.contains(a, RDF.type, classC)); + Assert.assertTrue(inf.contains(a, RDF.type, classB)); + Assert.assertFalse(inf.contains(a, RDF.type, classA)); + + Assert.assertTrue(inf.contains(b, RDF.type, classC)); + Assert.assertTrue(inf.contains(b, RDF.type, classB)); + Assert.assertFalse(inf.contains(b, RDF.type, classA)); + + Assert.assertTrue(inf.contains(c, RDF.type, classC)); + Assert.assertTrue(inf.contains(c, RDF.type, classB)); + Assert.assertFalse(inf.contains(c, RDF.type, classA)); + + // update TBox + classB.removeSubClass(classC); + + // wait for SimpleReasonerTBoxListener thread to end + while (!VitroBackgroundThread.getLivingThreads().isEmpty()) { + Thread.sleep(delay); + } + + // Verify inferences + Assert.assertFalse(inf.contains(a, RDF.type, classC)); + Assert.assertFalse(inf.contains(a, RDF.type, classB)); + Assert.assertFalse(inf.contains(a, RDF.type, classA)); + + Assert.assertTrue(inf.contains(b, RDF.type, classC)); + Assert.assertFalse(inf.contains(b, RDF.type, classB)); + Assert.assertFalse(inf.contains(b, RDF.type, classA)); + + Assert.assertTrue(inf.contains(c, RDF.type, classC)); + Assert.assertFalse(inf.contains(c, RDF.type, classB)); + Assert.assertFalse(inf.contains(c, RDF.type, classA)); + + simpleReasonerTBoxListener.setStopRequested(); } /* @@ -453,19 +555,91 @@ public class SimpleReasonerSameAsTest extends AbstractTestClass { */ //@Test public void mostSpecificTypeTest1() throws InterruptedException { - - } - - /* - * there is a sameAs chain and one sameAs statement is removed. - * - */ - //@Test - public void sameAsChain1() throws InterruptedException { - - } - + // Create TBox, ABox and Inference models and register + // the ABox reasoner listeners with the ABox and TBox + // Pellet will compute TBox inferences + OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC); + OntModel aBox = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); + Model inf = ModelFactory.createDefaultModel(); + SimpleReasoner simpleReasoner = new SimpleReasoner(tBox, aBox, inf); + aBox.register(simpleReasoner); + SimpleReasonerTBoxListener simpleReasonerTBoxListener = getTBoxListener(simpleReasoner); + tBox.register(simpleReasonerTBoxListener); + + // Set up the Tbox with a class hierarchy. C is a + // subclass of A. D and E are subclasses C. + // Pellet will compute TBox inferences. + AnnotationProperty mostSpecificType = tBox.createAnnotationProperty(mostSpecificTypePropertyURI); + + OntClass classA = tBox.createClass("http://test.vivo/A"); + classA.setLabel("class A", "en-US"); + OntClass classC = tBox.createClass("http://test.vivo/C"); + classC.setLabel("class C", "en-US"); + OntClass classD = tBox.createClass("http://test.vivo/D"); + classD.setLabel("class D", "en-US"); + OntClass classE = tBox.createClass("http://test.vivo/E"); + classE.setLabel("class E", "en-US"); + + classA.addSubClass(classC); + classC.addSubClass(classD); + classC.addSubClass(classE); + + while (!VitroBackgroundThread.getLivingThreads().isEmpty()) { + Thread.sleep(delay); + } + + // add & remove ABox type statements and verify inferences + Resource a = aBox.createResource("http://test.vivo/a"); + Resource b = aBox.createResource("http://test.vivo/b"); + Resource c = aBox.createResource("http://test.vivo/c"); + Resource d = aBox.createResource("http://test.vivo/d"); + + aBox.add(a, OWL.sameAs, b); + aBox.add(c, OWL.sameAs, b); + aBox.add(d, OWL.sameAs, a); + + aBox.add(a, RDF.type, classD); + aBox.add(d, RDF.type, classC); + Assert.assertFalse(inf.contains(a,RDF.type,classD)); + Assert.assertTrue(inf.contains(a,RDF.type,classC)); + Assert.assertTrue(inf.contains(b,RDF.type, classD)); + Assert.assertTrue(inf.contains(b,RDF.type, classC)); + Assert.assertTrue(inf.contains(c,RDF.type, classD)); + Assert.assertTrue(inf.contains(c,RDF.type, classC)); + Assert.assertTrue(inf.contains(d,RDF.type, classD)); + Assert.assertFalse(inf.contains(d,RDF.type, classC)); + + Assert.assertTrue(inf.contains(a, mostSpecificType, ResourceFactory.createResource(classD.getURI()))); + Assert.assertTrue(inf.contains(b, mostSpecificType, ResourceFactory.createResource(classD.getURI()))); + Assert.assertTrue(inf.contains(c, mostSpecificType, ResourceFactory.createResource(classD.getURI()))); + Assert.assertTrue(inf.contains(d, mostSpecificType, ResourceFactory.createResource(classD.getURI()))); + Assert.assertFalse(inf.contains(a, mostSpecificType, ResourceFactory.createResource(classC.getURI()))); + Assert.assertFalse(inf.contains(b, mostSpecificType, ResourceFactory.createResource(classC.getURI()))); + Assert.assertFalse(inf.contains(c, mostSpecificType, ResourceFactory.createResource(classC.getURI()))); + Assert.assertFalse(inf.contains(d, mostSpecificType, ResourceFactory.createResource(classC.getURI()))); + + aBox.remove(a, RDF.type, classD); + Assert.assertFalse(inf.contains(a,RDF.type,classD)); + Assert.assertTrue(inf.contains(a,RDF.type,classC)); + Assert.assertFalse(inf.contains(b,RDF.type, classD)); + Assert.assertTrue(inf.contains(b,RDF.type, classC)); + Assert.assertFalse(inf.contains(c,RDF.type, classD)); + Assert.assertTrue(inf.contains(c,RDF.type, classC)); + Assert.assertFalse(inf.contains(d,RDF.type, classD)); + Assert.assertFalse(inf.contains(d,RDF.type, classC)); + Assert.assertTrue(inf.contains(a, mostSpecificType, ResourceFactory.createResource(classC.getURI()))); + Assert.assertTrue(inf.contains(b, mostSpecificType, ResourceFactory.createResource(classC.getURI()))); + Assert.assertTrue(inf.contains(c, mostSpecificType, ResourceFactory.createResource(classC.getURI()))); + Assert.assertTrue(inf.contains(d, mostSpecificType, ResourceFactory.createResource(classC.getURI()))); + Assert.assertFalse(inf.contains(a, mostSpecificType, ResourceFactory.createResource(classD.getURI()))); + Assert.assertFalse(inf.contains(b, mostSpecificType, ResourceFactory.createResource(classD.getURI()))); + Assert.assertFalse(inf.contains(c, mostSpecificType, ResourceFactory.createResource(classD.getURI()))); + Assert.assertFalse(inf.contains(d, mostSpecificType, ResourceFactory.createResource(classD.getURI()))); + + simpleReasonerTBoxListener.setStopRequested(); + } + /* * Basic scenario around recomputing the ABox inferences */ diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/reasoner/SimpleReasonerTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/reasoner/SimpleReasonerTest.java index c36dd37f9..0c6427377 100644 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/reasoner/SimpleReasonerTest.java +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/reasoner/SimpleReasonerTest.java @@ -13,7 +13,6 @@ import com.hp.hpl.jena.ontology.AnnotationProperty; import com.hp.hpl.jena.ontology.OntClass; import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.ontology.OntModelSpec; -import com.hp.hpl.jena.ontology.OntProperty; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.ModelFactory; import com.hp.hpl.jena.rdf.model.Resource; @@ -28,7 +27,6 @@ import edu.cornell.mannlib.vitro.webapp.utils.threads.VitroBackgroundThread; public class SimpleReasonerTest extends AbstractTestClass { - private Resource objectProperty = ResourceFactory.createResource("http://www.w3.org/2002/07/owl#ObjectProperty"); private static final String mostSpecificTypePropertyURI = "http://vitro.mannlib.cornell.edu/ns/vitro/0.7#mostSpecificType"; long delay = 50; @@ -591,8 +589,12 @@ public class SimpleReasonerTest extends AbstractTestClass { * inference graph. * */ - //@Test - enable this in 1.5 - will need to add in PelletListener infrastructure - public void removeTBoxSubClassAssertion2() throws InterruptedException { + //@Test - this test would need PelletListener infrastructure, which we're not + // testing in this suite. The reason it doesn't work as it is because + // the SimpleReasonerTBoxListener is not listening to the tBox inference + // model as Pellet is updating it. I could simulate it by adding to the + // tBox assertions what we can count on Pellet to infer. + public void bcdTest() throws InterruptedException { // Create TBox, ABox and Inference models and register // the ABox reasoner listeners with the ABox and TBox // Pellet will compute TBox inferences @@ -621,6 +623,9 @@ public class SimpleReasonerTest extends AbstractTestClass { LivingThing.addSubClass(Flora); Flora.addSubClass(Brassica); + tBox.rebind(); + tBox.prepare(); + while (!VitroBackgroundThread.getLivingThreads().isEmpty()) { Thread.sleep(delay); } @@ -631,7 +636,9 @@ public class SimpleReasonerTest extends AbstractTestClass { // Remove the statement that Brassica is a subclass of Flora from the TBox Flora.removeSubClass(Brassica); - + + tBox.rebind(); + tBox.prepare(); while (!VitroBackgroundThread.getLivingThreads().isEmpty()) { Thread.sleep(delay); } @@ -647,411 +654,6 @@ public class SimpleReasonerTest extends AbstractTestClass { simpleReasonerTBoxListener.setStopRequested(); } - /* - * tests rdfs:subPropertyOf materialization for object properties. - */ - // @Test uncomment when sub/equiv property inferencing is enabled. sjm222 5/13/2011 - public void addABoxAssertion1() throws InterruptedException { - - // Create TBox, ABox and Inference models and register - // the ABox reasoner listeners with the ABox and TBox - // Pellet will compute TBox inferences - - OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC); - OntModel aBox = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); - Model inf = ModelFactory.createDefaultModel(); - - SimpleReasoner simpleReasoner = new SimpleReasoner(tBox, aBox, inf); - aBox.register(simpleReasoner); - SimpleReasonerTBoxListener simpleReasonerTBoxListener = getTBoxListener(simpleReasoner); - tBox.register(simpleReasonerTBoxListener); - - // Add object properties propA and propB to the TBox. - // propB is a sub-property of propA. - - OntProperty propA = tBox.createOntProperty("http://test.vivo/propA"); - tBox.add(propA, RDF.type, objectProperty); - propA.setLabel("propA", "en-US"); - - OntProperty propB = tBox.createOntProperty("http://test.vivo/propB"); - tBox.add(propB, RDF.type, objectProperty); - propB.setLabel("propB", "en-US"); - - propA.addSubProperty(propB); - - // Add the assertion that x propB y to the ABox - Resource ind_x = aBox.createResource("http://test.vivo/x"); - Resource ind_y = aBox.createResource("http://test.vivo/y"); - aBox.add(ind_x, propB, ind_y); - - // Verify that x propA y was inferred - Statement xay = ResourceFactory.createStatement(ind_x, propA, ind_y); - Assert.assertTrue(inf.contains(xay)); - } - - /* - * Test that when a statement is asserted, that it not - * added to the inference graph. - */ - // @Test uncomment when sub/equiv property inferencing is enabled. sjm222 5/13/2011 - public void addABoxAssertion2(){ - - // Create TBox, ABox and Inference models and register - // the ABox reasoner listeners with the ABox and TBox - // Pellet will compute TBox inferences - - OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC); - OntModel aBox = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); - Model inf = ModelFactory.createDefaultModel(); - - SimpleReasoner simpleReasoner = new SimpleReasoner(tBox, aBox, inf); - aBox.register(simpleReasoner); - SimpleReasonerTBoxListener simpleReasonerTBoxListener = getTBoxListener(simpleReasoner); - tBox.register(simpleReasonerTBoxListener); - - // Add object properties propA and propB to the TBox. - // propB is a sub-property of propA. - - OntProperty propA = tBox.createOntProperty("http://test.vivo/propA"); - tBox.add(propA, RDF.type, objectProperty); - propA.setLabel("propA", "en-US"); - - OntProperty propB = tBox.createOntProperty("http://test.vivo/propB"); - tBox.add(propB, RDF.type, objectProperty); - propB.setLabel("propB", "en-US"); - - propA.addSubProperty(propB); - - // Add the assertion that x propB y to the ABox - Resource ind_x = aBox.createResource("http://test.vivo/x"); - Resource ind_y = aBox.createResource("http://test.vivo/y"); - aBox.add(ind_x, propB, ind_y); - - // Verify that x propA y was inferred - Statement xby = ResourceFactory.createStatement(ind_x, propB, ind_y); - Assert.assertFalse(inf.contains(xby)); - } - - /* - * Test inference based on property equivalence - */ - // @Test uncomment when sub/equiv property inferencing is enabled. sjm222 5/13/2011 - public void addABoxAssertion4(){ - - // Create TBox, ABox and Inference models and register - // the ABox reasoner listeners with the ABox and TBox - // Pellet will compute TBox inferences - - OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC); - OntModel aBox = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); - Model inf = ModelFactory.createDefaultModel(); - - SimpleReasoner simpleReasoner = new SimpleReasoner(tBox, aBox, inf); - aBox.register(simpleReasoner); - SimpleReasonerTBoxListener simpleReasonerTBoxListener = getTBoxListener(simpleReasoner); - tBox.register(simpleReasonerTBoxListener); - - // Add properties A, B and C to the TBox - // A is equivalent to B - // C is a subclass of A - - OntProperty propA = tBox.createOntProperty("http://test.vivo/A"); - tBox.add(propA, RDF.type, objectProperty); - propA.setLabel("property A", "en-US"); - - OntProperty propB = tBox.createOntProperty("http://test.vivo/B"); - tBox.add(propB, RDF.type, objectProperty); - propB.setLabel("property B", "en-US"); - - OntProperty propC = tBox.createOntProperty("http://test.vivo/C"); - tBox.add(propC, RDF.type, objectProperty); - propC.setLabel("property C", "en-US"); - - propA.addEquivalentProperty(propB); - propA.addSubProperty(propC); - - // Add a statement that individual x is of type C to the ABox - Resource ind_x = aBox.createResource("http://test.vivo/x"); - Resource ind_y = aBox.createResource("http://test.vivo/y"); - - aBox.add(ind_x, propC, ind_y); - - // Verify that "x A y" was inferred - Statement xAy = ResourceFactory.createStatement(ind_x, propA, ind_y); - Assert.assertTrue(inf.contains(xAy)); - - // Verify that "x B y" was inferred - Statement xBy = ResourceFactory.createStatement(ind_x, propB, ind_y); - Assert.assertTrue(inf.contains(xBy)); - } - - /* - * The sub-property is not of the same type as the super - * property so no inference should be materialized. - */ - - // @Test uncomment when sub/equiv property inferencing is enabled. sjm222 5/13/2011 - public void addABoxAssertion5(){ - - // Create TBox, ABox and Inference models and register - // the ABox reasoner listeners with the ABox and TBox - // Pellet will compute TBox inferences - - OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC); - OntModel aBox = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); - Model inf = ModelFactory.createDefaultModel(); - - SimpleReasoner simpleReasoner = new SimpleReasoner(tBox, aBox, inf); - aBox.register(simpleReasoner); - SimpleReasonerTBoxListener simpleReasonerTBoxListener = getTBoxListener(simpleReasoner); - tBox.register(simpleReasonerTBoxListener); - - // Add object properties propA and propB to the TBox. - // propB is a sub-property of propA. - - OntProperty propA = tBox.createOntProperty("http://test.vivo/propA"); - tBox.add(propA, RDF.type, objectProperty); - propA.setLabel("propA", "en-US"); - - OntProperty propB = tBox.createOntProperty("http://test.vivo/propB"); - Resource datatypeProperty = ResourceFactory.createResource("http://www.w3.org/2002/07/owl#DatatypeProperty"); - tBox.add(propB, RDF.type, datatypeProperty); - propB.setLabel("propB", "en-US"); - - propA.addSubProperty(propB); - - // Add the assertion that x propB y to the ABox - Resource ind_x = aBox.createResource("http://test.vivo/x"); - Resource ind_y = aBox.createResource("http://test.vivo/y"); - aBox.add(ind_x, propB, ind_y); - - // Verify that x propA y was not inferred - Statement xay = ResourceFactory.createStatement(ind_x, propA, ind_y); - Assert.assertFalse(inf.contains(xay)); - } - - /* - * Test inference based on property equivalence - */ - // @Test uncomment when sub/equiv property inferencing is enabled. sjm222 5/13/2011 - public void addABoxAssertion6() { - - // Create TBox, ABox and Inference models and register - // the ABox reasoner listeners with the ABox and TBox - // Pellet will compute TBox inferences - - OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC); - OntModel aBox = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); - Model inf = ModelFactory.createDefaultModel(); - - SimpleReasoner simpleReasoner = new SimpleReasoner(tBox, aBox, inf); - aBox.register(simpleReasoner); - SimpleReasonerTBoxListener simpleReasonerTBoxListener = getTBoxListener(simpleReasoner); - tBox.register(simpleReasonerTBoxListener); - - // Add properties A and B to the TBox - // A is equivalent to B - - OntProperty propA = tBox.createOntProperty("http://test.vivo/A"); - tBox.add(propA, RDF.type, objectProperty); - propA.setLabel("property A", "en-US"); - - OntProperty propB = tBox.createOntProperty("http://test.vivo/B"); - tBox.add(propB, RDF.type, objectProperty); - propB.setLabel("property B", "en-US"); - - propA.addEquivalentProperty(propB); - - // Add the statement x B y to the ABox - Resource ind_x = aBox.createResource("http://test.vivo/x"); - Resource ind_y = aBox.createResource("http://test.vivo/y"); - aBox.add(ind_x, propB, ind_y); - - // Verify that "x A y" was inferred - Statement xAy = ResourceFactory.createStatement(ind_x, propA, ind_y); - Assert.assertTrue(inf.contains(xAy)); - - // Remove the statement that x B y from the ABox - aBox.remove(ind_x, propB, ind_y); - - // Verify that "x is of type A" was removed from the inference graph - Assert.assertFalse(inf.contains(xAy)); - } - - - /* - * Test the addition of a subPropertyOf statement to - * the TBox. The instance data that is the basis - * for the inference is in the ABox. - * - * Since the addition of an owl:equivalentProperty - * statement is implemented as two calls to the - * method that handles the addition of an - * rdfs:subPropetyOf statement, this test serves - * as a test of equivalentProperty assertions also. - */ - // @Test uncomment when sub/equiv property inferencing is enabled. sjm222 5/13/2011 - public void addTBoxSubPropertyAssertion1(){ - - // Create TBox, ABox and Inference models and register - // the ABox reasoner listeners with the ABox and TBox - // Pellet will compute TBox inferences - - OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC); - OntModel aBox = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); - Model inf = ModelFactory.createDefaultModel(); - - SimpleReasoner simpleReasoner = new SimpleReasoner(tBox, aBox, inf); - aBox.register(simpleReasoner); - SimpleReasonerTBoxListener simpleReasonerTBoxListener = getTBoxListener(simpleReasoner); - tBox.register(simpleReasonerTBoxListener); - - // Add properties A, B, C and D to the TBox - OntProperty propA = tBox.createOntProperty("http://test.vivo/A"); - tBox.add(propA, RDF.type, objectProperty); - propA.setLabel("property A", "en-US"); - - OntProperty propB = tBox.createOntProperty("http://test.vivo/B"); - tBox.add(propB, RDF.type, objectProperty); - propB.setLabel("property B", "en-US"); - - OntProperty propC = tBox.createOntProperty("http://test.vivo/C"); - tBox.add(propC, RDF.type, objectProperty); - propB.setLabel("property C", "en-US"); - - OntProperty propD = tBox.createOntProperty("http://test.vivo/D"); - tBox.add(propD, RDF.type, objectProperty); - propB.setLabel("property D", "en-US"); - - // Add the statement "x C y" to the ABox - Resource ind_x = aBox.createResource("http://test.vivo/x"); - Resource ind_y = aBox.createResource("http://test.vivo/y"); - aBox.add(ind_x, propC, ind_y); - - // Add a statement that C is a sub-property of A to the TBox - - propA.addSubProperty(propC); - - // Verify that "x A y" was inferred - Statement xAy = ResourceFactory.createStatement(ind_x, propA, ind_y); - Assert.assertTrue(inf.contains(xAy)); - - // Verify that "x B y" was not inferred - Statement xBy = ResourceFactory.createStatement(ind_x, propB, ind_y); - Assert.assertFalse(inf.contains(xBy)); - - // Verify that "x D y" was not inferred - Statement xDy = ResourceFactory.createStatement(ind_x, propD, ind_y); - Assert.assertFalse(inf.contains(xDy)); - - } - - /* - * Test the removal of a subPropertyOf statement from - * the TBox. The instance data that is the basis - * for the inference is in the ABox graph and the - * inference graph. - * - * Since the addition of an owl:equivalentProperty - * statement is implemented as two calls to the - * method that handles the addition of an - * rdfs:subPropertyOf statement, this test serves - * as a test of equivalentProperty assertions also. - * - */ - // @Test uncomment when sub/equiv property inferencing is enabled. sjm222 5/13/2011 - public void removeTBoxSubPropertyAssertion1(){ - // Create TBox, ABox and Inference models and register - // the ABox reasoner listeners with the ABox and TBox - // Pellet will compute TBox inferences - - OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC); - OntModel aBox = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); - Model inf = ModelFactory.createDefaultModel(); - - SimpleReasoner simpleReasoner = new SimpleReasoner(tBox, aBox, inf); - aBox.register(simpleReasoner); - SimpleReasonerTBoxListener simpleReasonerTBoxListener = getTBoxListener(simpleReasoner); - tBox.register(simpleReasonerTBoxListener); - - // Add properties A, B, C, D, E, F, G and H to the TBox. - // B, C and D are subproperties of A. - // E is a subproperty of B. - // F and G are subproperties of C. - // H is a subproperty of D. - - OntProperty propA = tBox.createOntProperty("http://test.vivo/A"); - tBox.add(propA, RDF.type, objectProperty); - propA.setLabel("property A", "en-US"); - - OntProperty propB = tBox.createOntProperty("http://test.vivo/B"); - tBox.add(propB, RDF.type, objectProperty); - propB.setLabel("property B", "en-US"); - - OntProperty propC = tBox.createOntProperty("http://test.vivo/C"); - tBox.add(propC, RDF.type, objectProperty); - propB.setLabel("property C", "en-US"); - - OntProperty propD = tBox.createOntProperty("http://test.vivo/D"); - tBox.add(propD, RDF.type, objectProperty); - propB.setLabel("property D", "en-US"); - - OntProperty propE = tBox.createOntProperty("http://test.vivo/E"); - tBox.add(propE, RDF.type, objectProperty); - propB.setLabel("property E", "en-US"); - - OntProperty propF = tBox.createOntProperty("http://test.vivo/F"); - tBox.add(propF, RDF.type, objectProperty); - propB.setLabel("property F", "en-US"); - - OntProperty propG = tBox.createOntProperty("http://test.vivo/G"); - tBox.add(propG, RDF.type, objectProperty); - propB.setLabel("property G", "en-US"); - - OntProperty propH = tBox.createOntProperty("http://test.vivo/H"); - tBox.add(propH, RDF.type, objectProperty); - propB.setLabel("property H", "en-US"); - - propA.addSubProperty(propB); - propA.addSubProperty(propC); - propA.addSubProperty(propD); - propB.addSubProperty(propE); - propC.addSubProperty(propF); - propC.addSubProperty(propG); - propD.addSubProperty(propH); - - // Add the statement "x E y" to the ABox - Resource ind_x = aBox.createResource("http://test.vivo/x"); - Resource ind_y = aBox.createResource("http://test.vivo/y"); - aBox.add(ind_x, propE, ind_y); - - // Remove the statement that B is a subproperty of A from the TBox - propA.removeSubProperty(propB); - - // Verify that "x A y" is not in the inference graph - Statement xAy = ResourceFactory.createStatement(ind_x, propA, ind_y); - Assert.assertFalse(inf.contains(xAy)); - - // Verify that "x B y" is in the inference graph - Statement xBy = ResourceFactory.createStatement(ind_x, propB, ind_y); - Assert.assertTrue(inf.contains(xBy)); - - // Add statements "w F z" and "w H z" to the ABox - Resource ind_z = aBox.createResource("http://test.vivo/z"); - Resource ind_w = aBox.createResource("http://test.vivo/w"); - aBox.add(ind_w, propF, ind_z); - aBox.add(ind_w, propH, ind_z); - - // Remove the statement that C is a subproperty of A from the TBox - propA.removeSubProperty(propC); - - // Verify that "w A z" is in the inference graph - Statement wAz = ResourceFactory.createStatement(ind_w, propA, ind_z); - Assert.assertTrue(inf.contains(wAz)); - } - - - /* * Test computation of mostSpecificType annotations in response * to an added/removed ABox type assertion.