merge recent revision from trunk

This commit is contained in:
brianjlowe 2012-06-08 19:41:48 +00:00
parent b480cb2eea
commit 101de4614b
6 changed files with 1632 additions and 259 deletions

View file

@ -0,0 +1,40 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.utils;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import net.sf.json.JSONObject;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.ResourceFactory;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelContext;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.utils.ProcessDataGetterN3;
import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetter;
/*
* This class determines what n3 should be returned for a particular data getter and can be overwritten or extended in VIVO.
*/
public class ProcessDataGetterN3Map {
private static final Log log = LogFactory.getLog(ProcessDataGetterN3Map.class);
public static HashMap<String, String> getDataGetterTypeToProcessorMap() {
HashMap<String, String> map = new HashMap<String, String>();
map.put("edu.cornell.mannlib.vitro.webapp.utils.dataGetter.SparqlQueryDataGetter", "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.utils.ProcessSparqlDataGetterN3");
map.put("edu.cornell.mannlib.vitro.webapp.utils.dataGetter.ClassGroupPageData", "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.utils.ProcessClassGroupDataGetterN3");
map.put("edu.cornell.mannlib.vitro.webapp.utils.dataGetter.IndividualsForClassesDataGetter", "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.utils.ProcessIndividualsForClassesDataGetterN3");
map.put("edu.cornell.mannlib.vitro.webapp.utils.dataGetter.FixedHTMLDataGetter", "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.utils.ProcessFixedHTMLN3");
return map;
}
}

View file

@ -133,6 +133,8 @@ public class SimpleReasoner extends StatementListener {
if (stmt.getPredicate().equals(RDF.type)) {
addedABoxTypeAssertion(stmt, inferenceModel, new HashSet<String>());
setMostSpecificTypes(stmt.getSubject(), inferenceModel, new HashSet<String>());
} else if (stmt.getPredicate().equals(OWL.sameAs)) {
addedABoxSameAsAssertion(stmt, inferenceModel);
} else {
addedABoxAssertion(stmt, inferenceModel);
}
@ -179,6 +181,8 @@ public class SimpleReasoner extends StatementListener {
if (stmt.getPredicate().equals(RDF.type)) {
removedABoxTypeAssertion(stmt, inferenceModel);
setMostSpecificTypes(stmt.getSubject(), inferenceModel, new HashSet<String>());
} else if (stmt.getPredicate().equals(OWL.sameAs)) {
removedABoxSameAsAssertion(stmt, inferenceModel);
} else {
removedABoxAssertion(stmt, inferenceModel);
}
@ -360,11 +364,8 @@ public class SimpleReasoner extends StatementListener {
protected void addedABoxTypeAssertion(Statement stmt, Model inferenceModel, HashSet<String> unknownTypes) {
tboxModel.enterCriticalSection(Lock.READ);
try {
OntClass cls = null;
if ( (stmt.getObject().asResource()).getURI() != null ) {
cls = tboxModel.getOntClass(stmt.getObject().asResource().getURI());
@ -374,6 +375,8 @@ public class SimpleReasoner extends StatementListener {
parents.addAll((cls.listEquivalentClasses()).toList());
Iterator<OntClass> parentIt = parents.iterator();
if (parentIt.hasNext()) {
List<Resource> sameIndividuals = getSameIndividuals(stmt.getSubject().asResource(), inferenceModel);
while (parentIt.hasNext()) {
OntClass parentClass = parentIt.next();
@ -389,9 +392,17 @@ public class SimpleReasoner extends StatementListener {
inferenceModel.enterCriticalSection(Lock.WRITE);
try {
if (!inferenceModel.contains(infStmt) && !aboxModel.contains(infStmt)) {
//log.debug("Adding this inferred statement: " + infStmt.toString() );
inferenceModel.add(infStmt);
}
Iterator<Resource> 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 {
inferenceModel.leaveCriticalSection();
}
@ -399,6 +410,7 @@ public class SimpleReasoner extends StatementListener {
aboxModel.leaveCriticalSection();
}
}
}
} else {
if ( !(stmt.getObject().asResource().getNameSpace()).equals(OWL.NS)) {
if (!unknownTypes.contains(stmt.getObject().asResource().getURI())) {
@ -418,24 +430,47 @@ public class SimpleReasoner extends StatementListener {
}
/*
* Performs incremental property-based reasoning.
* Materializes inferences based on the owl:sameAs relationship.
*
* Materializes inferences based on the owl:inverseOf relationship.
*
* 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.
* If it is added that x owl:sameAs y, then all asserted and inferred
* statements about x will become inferred about y if they are not already
* asserted about y, and vice versa.
*/
public void addedABoxAssertion(Statement stmt, Model inferenceModel) {
public void addedABoxSameAsAssertion(Statement stmt, Model inferenceModel) {
Resource subject = null;
Resource object = null;
List<OntProperty> inverseProperties = getInverseProperties(stmt);
Iterator<OntProperty> inverseIter = inverseProperties.iterator();
if (stmt.getSubject().isResource()) {
subject = stmt.getSubject().asResource();
if (tboxModel.containsResource(subject) || subject.isAnon()) {
log.debug("the subject of this sameAs statement is either in the tbox or an anonymous node, no reasoning will be done: " + stmtString(stmt));
return;
}
} else {
log.warn("the subject of this sameAs statement is not a resource, no reasoning will be done: " + stmtString(stmt));
return;
}
while (inverseIter.hasNext()) {
Property inverseProp = inverseIter.next();
if (stmt.getObject().isResource()) {
object = stmt.getObject().asResource();
if (tboxModel.containsResource(object) || object.isAnon()) {
log.debug("the object of this sameAs statement is either in the tbox or an anonymous node, no reasoning will be done: " + stmtString(stmt));
return;
}
} else {
log.warn("the object of this sameAs statement is not a resource, no reasoning will be done: " + stmtString(stmt));
return;
}
Statement infStmt = ResourceFactory.createStatement(stmt.getObject().asResource(), inverseProp, stmt.getSubject());
Model inferences = ModelFactory.createDefaultModel();
inferences.add(generateSameAsInferences(subject, object, inferenceModel));
inferences.add(generateSameAsInferences(object, subject, inferenceModel));
inferences.add(object, OWL.sameAs, subject);
Iterator<Statement> infIter = inferences.listStatements();
while (infIter.hasNext()) {
Statement infStmt = infIter.next();
aboxModel.enterCriticalSection(Lock.READ);
try {
inferenceModel.enterCriticalSection(Lock.WRITE);
@ -456,6 +491,214 @@ public class SimpleReasoner extends StatementListener {
}
}
/*
* Create a model that contains every assertion about indB as exists for
* indA in the Abox assertions or inference model
*/
public Model generateSameAsInferences(Resource indA, Resource indB, Model inferenceModel) {
Model inferences = ModelFactory.createDefaultModel();
OntModel unionModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM);
unionModel.addSubModel(aboxModel);
unionModel.addSubModel(inferenceModel);
aboxModel.enterCriticalSection(Lock.READ);
try {
Iterator<Statement> iter = unionModel.listStatements(indA, (Property) null, (RDFNode) null);
while (iter.hasNext()) {
Statement stmt = iter.next();
if (stmt.getObject() == null) continue;
if (OWL.sameAs.equals(stmt.getPredicate()) && indB.equals(stmt.getObject())) continue;
inferences.add(indB, stmt.getPredicate(), stmt.getObject());
}
} finally {
aboxModel.leaveCriticalSection();
}
return inferences;
}
/*
* Get a list of individuals the same as the given individual
*/
public List<Resource> getSameIndividuals(Resource ind, Model inferenceModel) {
OntModel unionModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM);
unionModel.addSubModel(aboxModel);
unionModel.addSubModel(inferenceModel);
ArrayList<Resource> sameIndividuals = new ArrayList<Resource>();
aboxModel.enterCriticalSection(Lock.READ);
inferenceModel.enterCriticalSection(Lock.READ);
try {
Iterator<Statement> iter = unionModel.listStatements(ind, OWL.sameAs, (RDFNode) null);
while (iter.hasNext()) {
Statement stmt = iter.next();
if (stmt.getObject() == null || !stmt.getObject().isResource() || stmt.getObject().asResource().getURI() == null) continue;
sameIndividuals.add(stmt.getObject().asResource());
}
} finally {
inferenceModel.leaveCriticalSection();
aboxModel.leaveCriticalSection();
}
return sameIndividuals;
}
/*
* Materializes inferences based on the owl:sameAs relationship.
*
* If it is removed that x is sameAs y, then remove y sameAs x from
* 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) {
Resource subject = null;
Resource object = null;
if (stmt.getSubject().isResource()) {
subject = stmt.getSubject().asResource();
if (tboxModel.containsResource(subject) || subject.isAnon()) {
log.debug("the subject of this removed sameAs statement is either in the tbox or an anonymous node, no reasoning will be done: " + stmtString(stmt));
return;
}
} else {
log.warn("the subject of this removed sameAs statement is not a resource, no reasoning will be done: " + stmtString(stmt));
return;
}
if (stmt.getObject().isResource()) {
object = stmt.getObject().asResource();
if (tboxModel.containsResource(object) || object.isAnon()) {
log.debug("the object of this removed sameAs statement is either in the tbox or an anonymous node, no reasoning will be done: " + stmtString(stmt));
return;
}
} else {
log.warn("the object of this removed sameAs statement is not a resource, no reasoning will be done: " + stmtString(stmt));
return;
}
inferenceModel.enterCriticalSection(Lock.WRITE);
try {
if (inferenceModel.contains(stmt)) {
inferenceModel.remove(stmt);
}
if (!inferenceModel.contains(object, OWL.sameAs, subject) && !aboxModel.contains(object, OWL.sameAs, subject) ) {
inferenceModel.add(object, OWL.sameAs, subject);
}
} finally {
inferenceModel.leaveCriticalSection();
}
recomputeInferencesForIndividual(subject, inferenceModel);
recomputeInferencesForIndividual(object, inferenceModel);
}
/*
* Recompute inferences for individual
*/
public void recomputeInferencesForIndividual(Resource ind, Model inferenceModel) {
Model inferencesToRemove = ModelFactory.createDefaultModel();
inferenceModel.enterCriticalSection(Lock.READ);
try {
Iterator<Statement> iter = inferenceModel.listStatements(ind, (Property) null, (RDFNode) null);
while (iter.hasNext()) {
inferencesToRemove.add(iter.next());
}
} finally {
inferenceModel.leaveCriticalSection();
}
inferenceModel.enterCriticalSection(Lock.WRITE);
try {
inferenceModel.remove(inferencesToRemove);
} finally {
inferenceModel.leaveCriticalSection();
}
Iterator<Statement> iter = null;
aboxModel.enterCriticalSection(Lock.WRITE);
try {
iter = aboxModel.listStatements(ind, (Property) null, (RDFNode) null);
} finally {
aboxModel.leaveCriticalSection();
}
while (iter.hasNext()) {
addedStatement(iter.next());
}
return;
}
/*
* Performs incremental property-based reasoning.
*
* Materializes inferences based on the owl:inverseOf relationship.
*
* 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<Resource> sameIndividuals = getSameIndividuals(stmt.getSubject().asResource(), inferenceModel);
List<OntProperty> inverseProperties = getInverseProperties(stmt);
Iterator<OntProperty> inverseIter = inverseProperties.iterator();
while (inverseIter.hasNext()) {
Property inverseProp = inverseIter.next();
Statement infStmt = ResourceFactory.createStatement(stmt.getObject().asResource(), inverseProp, stmt.getSubject());
aboxModel.enterCriticalSection(Lock.READ);
try {
inferenceModel.enterCriticalSection(Lock.WRITE);
try {
if (!inferenceModel.contains(infStmt) && !aboxModel.contains(infStmt) ) {
inferenceModel.add(infStmt);
}
Iterator<Resource> 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 {
inferenceModel.leaveCriticalSection();
}
} finally {
aboxModel.leaveCriticalSection();
}
}
inferenceModel.enterCriticalSection(Lock.WRITE);
try {
if (inferenceModel.contains(stmt)) {
inferenceModel.remove(stmt);
}
Iterator<Resource> sameIter = sameIndividuals.iterator();
while (sameIter.hasNext()) {
Resource subject = sameIter.next();
if (!inferenceModel.contains(subject,stmt.getPredicate(),stmt.getObject()) && !aboxModel.contains(subject,stmt.getPredicate(),stmt.getObject())) {
inferenceModel.add(subject,stmt.getPredicate(),stmt.getObject());
}
}
} 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
@ -484,7 +727,6 @@ public class SimpleReasoner extends StatementListener {
} finally {
inferenceModel.leaveCriticalSection();
}
return;
}
@ -543,6 +785,8 @@ public class SimpleReasoner extends StatementListener {
* this removed statement.
*/
public void removedABoxAssertion(Statement stmt, Model inferenceModel) {
List<Resource> sameIndividuals = getSameIndividuals(stmt.getSubject().asResource(), inferenceModel);
List<OntProperty> inverseProperties = getInverseProperties(stmt);
Iterator<OntProperty> inverseIter = inverseProperties.iterator();
@ -553,19 +797,40 @@ public class SimpleReasoner extends StatementListener {
inferenceModel.enterCriticalSection(Lock.WRITE);
try {
if (!entailedInverseStmt(infStmt) && inferenceModel.contains(infStmt)) {
if (!entailedStatement(infStmt) && inferenceModel.contains(infStmt)) {
inferenceModel.remove(infStmt);
}
// if a statement has been removed that is otherwise entailed,
// add it to the inference graph.
if (entailedInverseStmt(stmt) && !inferenceModel.contains(stmt)) {
inferenceModel.add(stmt);
Iterator<Resource> sameIter = sameIndividuals.iterator();
while (sameIter.hasNext()) {
Statement infStmtSame = ResourceFactory.createStatement(sameIter.next(), infStmt.getPredicate(), infStmt.getObject());
if (!entailedStatement(infStmtSame) && inferenceModel.contains(infStmtSame)) {
inferenceModel.remove(infStmtSame);
}
}
} finally {
inferenceModel.leaveCriticalSection();
}
}
inferenceModel.enterCriticalSection(Lock.WRITE);
try {
// if a statement has been removed that is otherwise entailed,
// add it to the inference graph.
if (entailedStatement(stmt) && !inferenceModel.contains(stmt)) {
inferenceModel.add(stmt);
}
Iterator<Resource> sameIter = sameIndividuals.iterator();
while (sameIter.hasNext()) {
Statement stmtSame = ResourceFactory.createStatement(sameIter.next(), stmt.getPredicate(), stmt.getObject());
if (!entailedStatement(stmtSame) && inferenceModel.contains(stmtSame)) {
inferenceModel.remove(stmtSame);
}
}
} finally {
inferenceModel.leaveCriticalSection();
}
}
// Returns true if it is entailed by class subsumption that
@ -600,22 +865,25 @@ public class SimpleReasoner extends StatementListener {
}
// Returns true if the triple is entailed by inverse property
// reasoning; otherwise returns false.
protected boolean entailedInverseStmt(Statement stmt) {
ExtendedIterator <? extends OntProperty> iter = null;
// reasoning or sameAs reasoning; otherwise returns false.
protected boolean entailedStatement(Statement stmt) {
List<OntProperty> inverses = new ArrayList<OntProperty>();
tboxModel.enterCriticalSection(Lock.READ);
try {
OntProperty prop = tboxModel.getOntProperty(stmt.getPredicate().asResource().getURI());
iter = prop.listInverse();
inverses.addAll(prop.listInverse().toList());
} finally {
tboxModel.leaveCriticalSection();
}
Iterator<OntProperty> oIter = inverses.iterator();
if (oIter.hasNext()) {
aboxModel.enterCriticalSection(Lock.READ);
try {
while (iter.hasNext()) {
Property invProp = iter.next();
while (oIter.hasNext()) {
Property invProp = oIter.next();
// not reasoning on properties in the OWL, RDF or RDFS namespace
if ((invProp.getNameSpace()).equals(OWL.NS) ||
@ -629,12 +897,31 @@ public class SimpleReasoner extends StatementListener {
return true;
}
}
return false;
} finally {
aboxModel.leaveCriticalSection();
}
}
List<Resource> sameIndividuals = getSameIndividuals(stmt.getSubject().asResource(),inferenceModel);
Iterator<Resource> rIter = sameIndividuals.iterator();
if (rIter.hasNext()) {
aboxModel.enterCriticalSection(Lock.READ);
try {
while (rIter.hasNext()) {
Resource subject = rIter.next();
if (aboxModel.contains(subject, stmt.getPredicate(), stmt.getObject())) {
return true;
}
}
} finally {
aboxModel.leaveCriticalSection();
}
}
return false;
}
/*
* Returns a list of properties that are inverses of the property
* in the given statement.
@ -800,12 +1087,21 @@ public class SimpleReasoner extends StatementListener {
while (iter.hasNext()) {
Statement infStmt = iter.next();
List<Resource> sameIndividuals = getSameIndividuals(infStmt.getSubject().asResource(), inferenceModel);
inferenceModel.enterCriticalSection(Lock.WRITE);
try {
if (!inferenceModel.contains(infStmt) && !aboxModel.contains(infStmt)) {
inferenceModel.add(infStmt);
}
Iterator<Resource> 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 {
inferenceModel.leaveCriticalSection();
}
@ -862,7 +1158,7 @@ public class SimpleReasoner extends StatementListener {
while (iter.hasNext()) {
Statement infStmt = iter.next();
if (entailedInverseStmt(infStmt)) {
if (entailedStatement(infStmt)) {
continue;
}
@ -1051,19 +1347,18 @@ public class SimpleReasoner extends StatementListener {
* inference models.
*/
protected synchronized void recomputeABox() {
HashSet<String> unknownTypes = new HashSet<String>();
// recompute the inferences
// recompute class subsumption inferences
inferenceRebuildModel.enterCriticalSection(Lock.WRITE);
try {
log.info("Computing ABox inferences.");
HashSet<String> unknownTypes = new HashSet<String>();
inferenceRebuildModel.removeAll();
log.info("Computing class subsumtion ABox inferences.");
int numStmts = 0;
ArrayList<String> individuals = this.getAllIndividualURIs();
for (String individualURI : individuals) {
Resource individual = ResourceFactory.createResource(individualURI);
try {
@ -1091,7 +1386,7 @@ public class SimpleReasoner extends StatementListener {
numStmts++;
if ((numStmts % 10000) == 0) {
log.info("Still computing class-based ABox inferences...");
log.info("Still computing class subsumption ABox inferences...");
}
if (stopRequested) {
@ -1100,8 +1395,9 @@ public class SimpleReasoner extends StatementListener {
}
}
log.info("Finished computing class-based ABox inferences");
log.info("Finished computing class subsumption ABox inferences");
log.info("Computing inverse property ABox inferences");
Iterator<Statement> invStatements = null;
tboxModel.enterCriticalSection(Lock.READ);
try {
@ -1110,18 +1406,21 @@ public class SimpleReasoner extends StatementListener {
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;
}
@ -1142,7 +1441,7 @@ public class SimpleReasoner extends StatementListener {
numStmts++;
if ((numStmts % 10000) == 0) {
log.info("Still computing property-based ABox inferences...");
log.info("Still computing inverse property ABox inferences...");
}
if (stopRequested) {
@ -1150,26 +1449,80 @@ public class SimpleReasoner extends StatementListener {
return;
}
}
log.info("Finished computing inverse property ABox inferences");
log.info("Computing sameAs ABox inferences");
Iterator<Statement> 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 {
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);
inferenceRebuildModel.removeAll(); // don't do this in the finally, it's needed in the case
// where there isn't an exception
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;
} finally {
inferenceRebuildModel.leaveCriticalSection();
}
}
log.info("Finished computing property-based ABox inferences");
/*
* reconcile a set of inferences into the application inference model
*/
protected synchronized boolean updateInferenceModel(Model inferenceRebuildModel) {
// reflect the recomputed inferences into the application
// inference model.
log.info("Updating ABox inference model");
StmtIterator iter = null;
// Remove everything from the current inference model that is not
// in the recomputed inference model
int num = 0;
inferenceRebuildModel.enterCriticalSection(Lock.WRITE);
scratchpadModel.enterCriticalSection(Lock.WRITE);
try {
inferenceModel.enterCriticalSection(Lock.READ);
@ -1189,18 +1542,15 @@ public class SimpleReasoner extends StatementListener {
}
if (stopRequested) {
log.info("a stopRequested signal was received during recomputeABox. Halting Processing.");
return;
return true;
}
}
} catch (Exception e) {
log.error("Exception while reconciling the current and recomputed ABox inference models", e);
return;
} finally {
iter.close();
inferenceModel.leaveCriticalSection();
}
try {
iter = scratchpadModel.listStatements();
while (iter.hasNext()) {
Statement stmt = iter.next();
@ -1208,12 +1558,13 @@ public class SimpleReasoner extends StatementListener {
inferenceModel.enterCriticalSection(Lock.WRITE);
try {
inferenceModel.remove(stmt);
} catch (Exception e) {
log.error("Exception while reconciling the current and recomputed ABox inference models", e);
} finally {
inferenceModel.leaveCriticalSection();
}
}
} finally {
iter.close();
}
// Add everything from the recomputed inference model that is not already
// in the current inference model to the current inference model.
@ -1239,13 +1590,9 @@ public class SimpleReasoner extends StatementListener {
}
if (stopRequested) {
log.info("a stopRequested signal was received during recomputeABox. Halting Processing.");
return;
return true;
}
}
} catch (Exception e) {
log.error("Exception while reconciling the current and recomputed ABox inference models", e);
return;
} finally {
iter.close();
}
@ -1257,24 +1604,19 @@ public class SimpleReasoner extends StatementListener {
inferenceModel.enterCriticalSection(Lock.WRITE);
try {
inferenceModel.add(stmt);
} catch (Exception e) {
log.error("Exception while reconciling the current and recomputed ABox inference models", e);
return;
} finally {
inferenceModel.leaveCriticalSection();
}
}
} finally {
iter.close();
inferenceRebuildModel.removeAll();
scratchpadModel.removeAll();
inferenceRebuildModel.leaveCriticalSection();
scratchpadModel.leaveCriticalSection();
}
log.info("ABox inference model updated");
return false;
}
/*
* Get the URIs for all individuals in the system
*/
@ -1492,7 +1834,6 @@ public class SimpleReasoner extends StatementListener {
log.info("started computing inferences for batch " + qualifier + " updates");
iter = retractions.listStatements();
while (iter.hasNext() && !stopRequested) {
Statement stmt = iter.next();
num++;

View file

@ -0,0 +1,564 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.ucsf.vitro.opensocial;
import java.io.File;
import java.io.InputStream;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
import edu.cornell.mannlib.vitro.webapp.utils.threads.VitroBackgroundThread;
/**
* Do some quick checks to see whether the OpenSocial stuff is configured and
* working.
*/
public class OpenSocialSmokeTests implements ServletContextListener {
private static final String PROPERTY_SHINDIG_URL = "OpenSocial.shindigURL";
private static final String PROPERTY_SHINDIG_TOKEN_KEY_FILE = "OpenSocial.tokenKeyFile";
private static final String PROPERTY_SHINDIG_TOKEN_SERVICE = "OpenSocial.tokenService";
private static final String PROPERTY_DB_DRIVER = "VitroConnection.DataSource.driver";
private static final String PROPERTY_DB_JDBC_URL = "VitroConnection.DataSource.url";
private static final String PROPERTY_DB_USERNAME = "VitroConnection.DataSource.username";
private static final String PROPERTY_DB_PASSWORD = "VitroConnection.DataSource.password";
private static final String FILENAME_SHINDIG_PROPERTIES = "shindig.orng.properties";
/*
* If a connection fails in the tester thread, how long do we wait before
* trying again?
*/
private static final long SLEEP_INTERVAL = 10000; // 10 seconds
private ServletContext ctx;
private ConfigurationProperties configProps;
private List<Warning> warnings = new ArrayList<Warning>();
private String shindigBaseUrl;
private String tokenServiceHost;
private int tokenServicePort;
/**
* When the system starts up, run the tests.
*/
@Override
public void contextInitialized(ServletContextEvent sce) {
ctx = sce.getServletContext();
StartupStatus ss = StartupStatus.getBean(ctx);
configProps = ConfigurationProperties.getBean(ctx);
/*
* If OpenSocial is not configured in deploy.properties, skip the tests.
*/
if (!configurationPresent()) {
ss.info(this, "The OpenSocial connection is not configured.");
return;
}
/*
* Run all of the non-threaded tests. If any fail, skip the threaded
* tests.
*/
checkDatabaseTables();
checkShindigConfigFile();
checkTokenKeyFile();
checkTokenServiceInfo();
if (!warnings.isEmpty()) {
for (Warning w : warnings) {
w.warn(ss);
}
return;
}
/*
* Run the threaded tests.
*/
ss.info(this, "Starting threads for OpenSocial smoke tests");
new ShindigTestThread(this, ss, shindigBaseUrl).start();
new TokenServiceTestThread(this, ss, tokenServiceHost, tokenServicePort)
.start();
}
/**
* Get the base URL for the Shindig server. If none, then the whole thing is
* disabled.
*/
private boolean configurationPresent() {
String shindigUrl = configProps.getProperty(PROPERTY_SHINDIG_URL);
if (StringUtils.isNotEmpty(shindigUrl)) {
this.shindigBaseUrl = shindigUrl;
return true;
} else {
return false;
}
}
/**
* Check that we can connect to the database, and query one of the Shindig
* tables.
*/
private void checkDatabaseTables() {
BasicDataSource dataSource = null;
Connection conn = null;
Statement stmt = null;
ResultSet rset = null;
try {
dataSource = new BasicDataSource();
dataSource.setDriverClassName(getProperty(PROPERTY_DB_DRIVER));
dataSource.setUrl(getProperty(PROPERTY_DB_JDBC_URL));
dataSource.setUsername(getProperty(PROPERTY_DB_USERNAME));
dataSource.setPassword(getProperty(PROPERTY_DB_PASSWORD));
conn = dataSource.getConnection();
stmt = conn.createStatement();
rset = stmt.executeQuery("select * from shindig_apps");
} catch (NoSuchPropertyException e) {
warnings.add(new Warning(e.getMessage()));
} catch (SQLException e) {
if (e.getMessage().contains("doesn't exist")) {
warnings.add(new Warning("The Shindig tables don't exist "
+ "in the database. Was shindig_orng_tables.sql "
+ "run to set them up?", e));
} else {
warnings.add(new Warning(
"Can't access the Shindig database tables", e));
}
} finally {
try {
if (rset != null) {
rset.close();
}
} catch (Exception e) {
e.printStackTrace();
}
try {
if (stmt != null) {
stmt.close();
}
} catch (Exception e) {
e.printStackTrace();
}
try {
if (conn != null) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Check that the Shindig configuration file is present in the classpath.
*/
private void checkShindigConfigFile() {
URL url = this.getClass()
.getResource("/" + FILENAME_SHINDIG_PROPERTIES);
if (url == null) {
String message = "Can't find the '" + FILENAME_SHINDIG_PROPERTIES
+ "' file in the classpath. ";
message += "Has the Tomcat classpath been set to include the "
+ "Shindig config directory? "
+ "(inside the Vitro home directory) ";
message += "Was the openSocial build script run? "
+ "('ant -file openSocialBuild.xml')";
warnings.add(new Warning(message));
}
}
/**
* Check that the Token Key file has been specified in deploy.properties,
* and that it actually does exist.
*/
private void checkTokenKeyFile() {
try {
String tokenFilename = getProperty(PROPERTY_SHINDIG_TOKEN_KEY_FILE);
File tokenFile = new File(tokenFilename);
if (!tokenFile.exists()) {
warnings.add(new Warning(
"Token key file for Shindig does not exist: '"
+ tokenFilename + "'"));
} else if (!tokenFile.isFile()) {
warnings.add(new Warning(
"Token key file for Shindig is not a file: '"
+ tokenFilename + "'"));
}
} catch (NoSuchPropertyException e) {
warnings.add(new Warning(e.getMessage()));
}
}
/**
* Get the Token Service info from deploy.properties. It must be in the form
* of host:port, and may not refer to localhost.
*/
private void checkTokenServiceInfo() {
String tsInfo = configProps.getProperty(PROPERTY_SHINDIG_TOKEN_SERVICE);
if (StringUtils.isEmpty(tsInfo)) {
warnings.add(new Warning("There is no value for '"
+ PROPERTY_SHINDIG_TOKEN_SERVICE + "' in deploy.properties"));
return;
}
/*
* If the parameter is invalid, use this message.
*/
String warningText = "The '" + PROPERTY_SHINDIG_TOKEN_SERVICE
+ "' parameter is set to \"" + tsInfo
+ "\". It must be in the form [hostname]:[port]. "
+ "For example, \"myhost.mydomain.edu:8777\". "
+ "The hostname may be an IP address, "
+ "but it may not be \"localhost\" or \"127.0.0.1\"";
int firstColon = tsInfo.indexOf(':');
if (firstColon <= 0) {
warnings.add(new Warning(warningText));
return;
}
int lastColon = tsInfo.lastIndexOf(':');
if (firstColon != lastColon) {
warnings.add(new Warning(warningText));
return;
}
tokenServiceHost = tsInfo.substring(0, firstColon);
if (("localhost".equals(tokenServiceHost))
|| ("127.0.0.1".equals(tokenServiceHost))) {
warnings.add(new Warning(warningText));
return;
}
try {
tokenServicePort = Integer.parseInt(tsInfo
.substring(firstColon + 1));
} catch (Exception e) { // probably a NumberFormatException
warnings.add(new Warning(warningText, e));
}
}
private String getProperty(String key) throws NoSuchPropertyException {
String value = configProps.getProperty(key);
if (StringUtils.isEmpty(value)) {
throw new NoSuchPropertyException(key);
} else {
return value;
}
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
// nothing to destroy
}
// ----------------------------------------------------------------------
// Helper classes
// ----------------------------------------------------------------------
private static class NoSuchPropertyException extends Exception {
NoSuchPropertyException(String key) {
super("There is no value for '" + key + "' in deploy.properties");
}
}
private class Warning {
private final String message;
private final Throwable cause;
Warning(String message) {
this.message = message;
this.cause = null;
}
Warning(String message, Throwable cause) {
this.message = message;
this.cause = cause;
}
void warn(StartupStatus ss) {
if (cause == null) {
ss.warning(OpenSocialSmokeTests.this, message);
} else {
ss.warning(OpenSocialSmokeTests.this, message, cause);
}
}
}
private static class ShindigTestThread extends VitroBackgroundThread {
private final OpenSocialSmokeTests listener;
private final StartupStatus ss;
private final String shindigBaseUrl;
public ShindigTestThread(OpenSocialSmokeTests listener,
StartupStatus ss, String shindigBaseUrl) {
super("OpenSocialSmokeTest.ShindigTestThread");
this.listener = listener;
this.ss = ss;
this.shindigBaseUrl = shindigBaseUrl;
}
@Override
public void run() {
try {
new ShindigTester(shindigBaseUrl).connect();
ss.info(listener, "Shindig service responds to a REST query.");
} catch (ShindigTesterException e) {
String message = e.getMessage();
Throwable cause = e.getCause();
if (cause == null) {
ss.warning(listener, message);
} else {
ss.warning(listener, message, cause);
}
return;
}
}
}
private static class ShindigTester {
// Use the parent's log
private static final Log log = LogFactory
.getLog(OpenSocialSmokeTests.class);
/** Pretend that there is an HTTP status code for this. */
private static final int SOCKET_TIMEOUT_STATUS = -500;
private final String shindigBaseUrl;
private final HttpClient httpClient = new HttpClient();
private int statusCode = Integer.MIN_VALUE;
public ShindigTester(String shindigBaseUrl) {
this.shindigBaseUrl = shindigBaseUrl;
}
public void connect() throws ShindigTesterException {
testConnection();
if (!isDone()) {
sleep();
testConnection();
}
if (!isDone()) {
sleep();
testConnection();
}
if (statusCode != HttpStatus.SC_OK) {
throw new ShindigTesterException(statusCode);
}
}
private void testConnection() throws ShindigTesterException {
String shindigTestUrl = shindigBaseUrl + "/rest/activities";
GetMethod method = new GetMethod(shindigTestUrl);
try {
log.debug("Trying to connect to Shindig");
statusCode = httpClient.executeMethod(method);
log.debug("HTTP status was " + statusCode);
// clear the buffer.
InputStream stream = method.getResponseBodyAsStream();
stream.close();
} catch (SocketTimeoutException e) {
// Catch the exception so we can retry this.
// Save the status so we know why we failed.
statusCode = SOCKET_TIMEOUT_STATUS;
} catch (Exception e) {
throw new ShindigTesterException(e);
} finally {
method.releaseConnection();
}
}
/**
* Stop trying to connect if we succeed, or if we receive an error that
* won't change on retry.
*/
private boolean isDone() {
return (statusCode == HttpStatus.SC_OK)
|| (statusCode == HttpStatus.SC_FORBIDDEN);
}
private void sleep() {
try {
Thread.sleep(SLEEP_INTERVAL);
} catch (InterruptedException e) {
e.printStackTrace(); // Should never happen
}
}
}
protected static class ShindigTesterException extends Exception {
private final int httpStatusCode;
protected ShindigTesterException(Integer httpStatusCode) {
super("Failed to connect to the Shindig service. "
+ "status code was " + httpStatusCode);
this.httpStatusCode = httpStatusCode;
}
protected ShindigTesterException(Throwable cause) {
super("Failed to connect to the Shindig service.", cause);
this.httpStatusCode = Integer.MIN_VALUE;
}
protected int getHttpStatusCode() {
return httpStatusCode;
}
}
private static class TokenServiceTestThread extends VitroBackgroundThread {
private final OpenSocialSmokeTests listener;
private final StartupStatus ss;
private final String tokenServiceHost;
private final int tokenServicePort;
public TokenServiceTestThread(OpenSocialSmokeTests listener,
StartupStatus ss, String tokenServiceHost, int tokenServicePort) {
super("OpenSocialSmokeTest.TokenServiceTestThread");
this.listener = listener;
this.ss = ss;
this.tokenServiceHost = tokenServiceHost;
this.tokenServicePort = tokenServicePort;
}
@Override
public void run() {
try {
new TokenServiceTester(tokenServiceHost, tokenServicePort)
.connect();
ss.info(listener,
"Shindig security token service responds to a request.");
} catch (TokenServiceTesterException e) {
String message = e.getMessage();
Throwable cause = e.getCause();
if (cause == null) {
ss.warning(listener, message);
} else {
ss.warning(listener, message, cause);
}
return;
}
}
}
protected static class TokenServiceTester {
// Use the parent's log
private static final Log log = LogFactory
.getLog(OpenSocialSmokeTests.class);
private final String host;
private final int port;
private Object problem;
public TokenServiceTester(String host, int port) {
this.host = host;
this.port = port;
}
public void connect() throws TokenServiceTesterException {
testConnection();
if (!isDone()) {
sleep();
testConnection();
}
if (!isDone()) {
sleep();
testConnection();
}
if (problem instanceof Throwable) {
throw new TokenServiceTesterException(
"Test of the Shindig token service failed.",
(Throwable) problem);
} else if (problem instanceof String) {
throw new TokenServiceTesterException((String) problem);
}
}
private void testConnection() {
try {
log.debug("Connecting to the token service");
Socket s = new Socket(host, port);
s.getOutputStream().write("c=default\n".getBytes());
int byteCount = 0;
int totalBytecount = 0;
byte[] buffer = new byte[8192];
// The following will block until the page is transmitted.
InputStream inputStream = s.getInputStream();
while ((byteCount = inputStream.read(buffer)) > 0) {
totalBytecount += byteCount;
}
if (totalBytecount == 0) {
log.debug("Received an empty response.");
problem = "The Shindig security token service responded to a test, but the response was empty.";
} else {
log.debug("Recieved the token.");
problem = null;
}
} catch (Exception e) {
log.debug("Problem with the token service", e);
problem = e;
}
}
/**
* Stop trying to connect if we succeed, or if we receive an error that
* won't change on retry.
*/
private boolean isDone() {
return ((problem == null) || (problem instanceof String));
}
private void sleep() {
try {
Thread.sleep(SLEEP_INTERVAL);
} catch (InterruptedException e) {
e.printStackTrace(); // Should never happen
}
}
}
protected static class TokenServiceTesterException extends Exception {
protected TokenServiceTesterException(String message) {
super(message);
}
protected TokenServiceTesterException(String message, Throwable cause) {
super(message, cause);
}
}
}

View file

@ -18,7 +18,7 @@ import com.hp.hpl.jena.rdf.model.Resource;
import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
import edu.cornell.mannlib.vitro.webapp.utils.threads.VitroBackgroundThread;
public class SimpleReasonerPropertyTest extends AbstractTestClass {
public class SimpleReasonerInversePropertyTest extends AbstractTestClass {
long delay = 50;
@ -439,8 +439,6 @@ public class SimpleReasonerPropertyTest extends AbstractTestClass {
SimpleReasoner simpleReasoner = new SimpleReasoner(tBox, aBox, inf);
aBox.register(simpleReasoner);
SimpleReasonerTBoxListener simpleReasonerTBoxListener = getTBoxListener(simpleReasoner);
tBox.register(simpleReasonerTBoxListener);
// Individuals a, b, c and d
Resource a = aBox.createResource("http://test.vivo/a");
Resource b = aBox.createResource("http://test.vivo/b");
@ -460,8 +458,6 @@ public class SimpleReasonerPropertyTest extends AbstractTestClass {
// Verify inferences
Assert.assertTrue(inf.contains(b,Q,a));
Assert.assertTrue(inf.contains(d,Y,c));
simpleReasonerTBoxListener.setStopRequested();
}
//==================================== Utility methods ====================

View file

@ -0,0 +1,430 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.reasoner;
import org.apache.log4j.Level;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mindswap.pellet.jena.PelletReasonerFactory;
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.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.vocabulary.OWL;
import com.hp.hpl.jena.vocabulary.RDF;
import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
import edu.cornell.mannlib.vitro.webapp.utils.threads.VitroBackgroundThread;
public class SimpleReasonerSameAsTest extends AbstractTestClass {
long delay = 50;
@Before
public void suppressErrorOutput() {
suppressSyserr();
//Turn off log messages to console
setLoggerLevel(SimpleReasoner.class, Level.OFF);
setLoggerLevel(SimpleReasonerTBoxListener.class, Level.OFF);
}
/*
* basic scenario of adding an abox sameAs assertion
//*/
@Test
public void addSameAsABoxAssertion1() {
OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC);
OntProperty P = tBox.createObjectProperty("http://test.vivo/P");
P.setLabel("property P", "en-US");
OntProperty Q = tBox.createObjectProperty("http://test.vivo/Q");
Q.setLabel("property Q", "en-US");
OntProperty S = tBox.createDatatypeProperty("http://test.vivo/");
S.setLabel("property S", "en-US");
OntProperty T = tBox.createDatatypeProperty("http://test.vivo/");
T.setLabel("property T", "en-US");
Literal literal1 = tBox.createLiteral("Literal value 1");
Literal literal2 = tBox.createLiteral("Literal value 2");
// this is the model to receive inferences
Model inf = ModelFactory.createDefaultModel();
// 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
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,P,c);
aBox.add(a,S,literal1);
aBox.add(b,Q,d);
aBox.add(b,T,literal2);
aBox.add(a,OWL.sameAs,b);
Assert.assertTrue(inf.contains(b,OWL.sameAs,a));
Assert.assertTrue(inf.contains(b,P,c));
Assert.assertTrue(inf.contains(b,S,literal1));
Assert.assertTrue(inf.contains(a,Q,d));
Assert.assertTrue(inf.contains(a,T,literal2));
Assert.assertFalse(aBox.contains(b,OWL.sameAs,a));
Assert.assertFalse(aBox.contains(b,P,c));
Assert.assertFalse(aBox.contains(b,S,literal1));
Assert.assertFalse(aBox.contains(a,Q,d));
Assert.assertFalse(aBox.contains(a,T,literal2));
}
/*
* basic scenario of removing an abox sameAs assertion
*/
@Test
public void removeSameAsABoxAssertion1() {
OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC);
OntProperty P = tBox.createObjectProperty("http://test.vivo/P");
P.setLabel("property P", "en-US");
OntProperty Q = tBox.createObjectProperty("http://test.vivo/Q");
Q.setLabel("property Q", "en-US");
OntProperty S = tBox.createDatatypeProperty("http://test.vivo/");
S.setLabel("property S", "en-US");
OntProperty T = tBox.createDatatypeProperty("http://test.vivo/");
T.setLabel("property T", "en-US");
Literal literal1 = tBox.createLiteral("Literal value 1");
Literal literal2 = tBox.createLiteral("Literal value 2");
// this is the model to receive inferences
Model inf = ModelFactory.createDefaultModel();
// 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
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,P,c);
aBox.add(a,S,literal1);
aBox.add(b,Q,d);
aBox.add(b,T,literal2);
aBox.add(a,OWL.sameAs,b);
Assert.assertTrue(inf.contains(b,OWL.sameAs,a));
Assert.assertTrue(inf.contains(b,P,c));
Assert.assertTrue(inf.contains(b,S,literal1));
Assert.assertTrue(inf.contains(a,Q,d));
Assert.assertTrue(inf.contains(a,T,literal2));
aBox.remove(a,OWL.sameAs,b);
Assert.assertFalse(inf.contains(b,OWL.sameAs,a));
Assert.assertFalse(inf.contains(b,P,c));
Assert.assertFalse(inf.contains(b,S,literal1));
Assert.assertFalse(inf.contains(a,Q,d));
Assert.assertFalse(inf.contains(a,T,literal2));
}
/*
* basic scenario of adding an abox assertion for
* an individual is sameAs another.
*/
@Test
public void addABoxAssertion1() {
OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC);
OntProperty P = tBox.createObjectProperty("http://test.vivo/P");
P.setLabel("property P", "en-US");
OntProperty Q = tBox.createObjectProperty("http://test.vivo/Q");
Q.setLabel("property Q", "en-US");
OntProperty S = tBox.createDatatypeProperty("http://test.vivo/");
S.setLabel("property S", "en-US");
OntProperty T = tBox.createDatatypeProperty("http://test.vivo/");
T.setLabel("property T", "en-US");
Literal literal1 = tBox.createLiteral("Literal value 1");
Literal literal2 = tBox.createLiteral("Literal value 2");
// this is the model to receive inferences
Model inf = ModelFactory.createDefaultModel();
// 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
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);
Assert.assertTrue(inf.contains(b,OWL.sameAs,a));
aBox.add(a,P,c);
aBox.add(a,S,literal1);
aBox.add(b,Q,d);
aBox.add(b,T,literal2);
Assert.assertTrue(inf.contains(b,P,c));
Assert.assertTrue(inf.contains(b,S,literal1));
Assert.assertTrue(inf.contains(a,Q,d));
Assert.assertTrue(inf.contains(a,T,literal2));
}
/*
* adding abox assertion for individuals that are sameAs
* each other.
*/
@Test
public void addABoxAssertion2() {
OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC);
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");
classA.addSubClass(classB);
OntProperty desc = tBox.createDatatypeProperty("http://test.vivo/desc");
desc.setLabel("property desc", "en-US");
Literal desc1 = tBox.createLiteral("individual 1");
Literal desc2 = tBox.createLiteral("individual 2");
// this is the model to receive inferences
Model inf = ModelFactory.createDefaultModel();
// 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 and b
Resource a = aBox.createResource("http://test.vivo/a");
Resource b = aBox.createResource("http://test.vivo/b");
aBox.add(a,desc,desc1);
aBox.add(b,desc,desc2);
aBox.add(a,OWL.sameAs,b);
aBox.add(a, RDF.type, classB);
Assert.assertTrue(inf.contains(a,desc,desc2));
Assert.assertTrue(inf.contains(a,RDF.type,classA));
Assert.assertTrue(inf.contains(b,desc,desc1));
Assert.assertTrue(inf.contains(b,OWL.sameAs,a));
Assert.assertTrue(inf.contains(b,RDF.type,classB));
Assert.assertTrue(inf.contains(b,RDF.type,classA));
}
/*
* basic scenario of removing an abox assertion for
* an individual is sameAs another.
*/
@Test
public void removeABoxAssertion1() {
OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC);
OntProperty P = tBox.createObjectProperty("http://test.vivo/P");
P.setLabel("property P", "en-US");
OntProperty Q = tBox.createObjectProperty("http://test.vivo/Q");
Q.setLabel("property Q", "en-US");
OntProperty S = tBox.createDatatypeProperty("http://test.vivo/");
S.setLabel("property S", "en-US");
OntProperty T = tBox.createDatatypeProperty("http://test.vivo/");
T.setLabel("property T", "en-US");
Literal literal1 = tBox.createLiteral("Literal value 1");
Literal literal2 = tBox.createLiteral("Literal value 2");
// this is the model to receive inferences
Model inf = ModelFactory.createDefaultModel();
// 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
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,P,c);
aBox.add(a,S,literal1);
aBox.add(b,Q,d);
aBox.add(b,T,literal2);
aBox.add(a,OWL.sameAs,b);
aBox.remove(a,P,c);
aBox.remove(a,S,literal1);
Assert.assertFalse(inf.contains(b,P,c));
Assert.assertFalse(inf.contains(b,S,literal1));
}
/*
* adding an inverseOf assertion for individuals who are sameAs
* each other.
*/
@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
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);
Model inf = ModelFactory.createDefaultModel();
SimpleReasoner simpleReasoner = new SimpleReasoner(tBox, aBox, inf);
aBox.register(simpleReasoner);
SimpleReasonerTBoxListener simpleReasonerTBoxListener = getTBoxListener(simpleReasoner);
tBox.register(simpleReasonerTBoxListener);
// Individuals a and b
Resource a = aBox.createResource("http://test.vivo/a");
Resource b = aBox.createResource("http://test.vivo/b");
// abox statements
aBox.add(a,P,b);
aBox.add(a, OWL.sameAs,b);
// Assert P and Q as inverses and wait for SimpleReasoner TBox
// thread to end
Q.addInverseOf(P);
tBox.rebind();
tBox.prepare();
while (!VitroBackgroundThread.getLivingThreads().isEmpty()) {
Thread.sleep(delay);
}
// Verify inferences
Assert.assertTrue(inf.contains(b,Q,a));
Assert.assertTrue(inf.contains(b,OWL.sameAs,a));
Assert.assertTrue(inf.contains(b,P,b));
Assert.assertTrue(inf.contains(a,Q,a));
simpleReasonerTBoxListener.setStopRequested();
}
/*
* Basic scenario around recomputing the ABox inferences
*/
@Test
public void recomputeABox1() throws InterruptedException {
OntModel tBox = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC);
OntProperty P = tBox.createObjectProperty("http://test.vivo/P");
P.setLabel("property P", "en-US");
OntProperty Q = tBox.createObjectProperty("http://test.vivo/Q");
Q.setLabel("property Q", "en-US");
OntProperty S = tBox.createDatatypeProperty("http://test.vivo/");
S.setLabel("property S", "en-US");
OntProperty T = tBox.createDatatypeProperty("http://test.vivo/");
T.setLabel("property T", "en-US");
Literal literal1 = tBox.createLiteral("Literal value 1");
Literal literal2 = tBox.createLiteral("Literal value 2");
// this is the model to receive inferences
Model inf = ModelFactory.createDefaultModel();
// create an ABox and register the SimpleReasoner listener with it
OntModel aBox = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM);
SimpleReasoner simpleReasoner = new SimpleReasoner(tBox, aBox, inf);
aBox.register(simpleReasoner);
// Individuals a, b, c and d
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,P,c);
aBox.add(a,S,literal1);
aBox.add(b,Q,d);
aBox.add(b,T,literal2);
aBox.add(a,OWL.sameAs,b);
simpleReasoner.recompute();
while (simpleReasoner.isRecomputing()) {
Thread.sleep(delay);
}
// Verify inferences
Assert.assertTrue(inf.contains(b,OWL.sameAs,a));
Assert.assertTrue(inf.contains(b,P,c));
Assert.assertTrue(inf.contains(b,S,literal1));
Assert.assertTrue(inf.contains(a,Q,d));
Assert.assertTrue(inf.contains(a,T,literal2));
}
//==================================== Utility methods ====================
SimpleReasonerTBoxListener getTBoxListener(SimpleReasoner simpleReasoner) {
return new SimpleReasonerTBoxListener(simpleReasoner, new Exception().getStackTrace()[1].getMethodName());
}
// To help in debugging the unit test
void printModel(Model model, String modelName) {
System.out.println("\nThe " + modelName + " model has " + model.size() + " statements:");
System.out.println("---------------------------------------------------------------------");
model.write(System.out);
}
// To help in debugging the unit test
void printModel(OntModel ontModel, String modelName) {
System.out.println("\nThe " + modelName + " model has " + ontModel.size() + " statements:");
System.out.println("---------------------------------------------------------------------");
ontModel.writeAll(System.out,"N3",null);
}
}

View file

@ -54,6 +54,8 @@ edu.cornell.mannlib.vitro.webapp.auth.policy.RestrictHomeMenuItemEditingPolicy$S
edu.cornell.mannlib.vitro.webapp.services.shortview.ShortViewServiceSetup
edu.ucsf.vitro.opensocial.OpenSocialSmokeTests
# The Solr index uses a "public" permission, so the PropertyRestrictionPolicyHelper
# and the PermissionRegistry must already be set up.
edu.cornell.mannlib.vitro.webapp.search.solr.SolrSetup