NIHVIVO-3967 retraction of inferences by SimpleBridgingRule in batch mode and NIHVIVO-3955 batch mode retraction performance improvments for SimpleReasoner
This commit is contained in:
parent
fb483663bf
commit
61ede29fa7
6 changed files with 470 additions and 192 deletions
|
@ -7,6 +7,7 @@ import java.io.UnsupportedEncodingException;
|
|||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.openjena.riot.RiotException;
|
||||
|
||||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
import com.hp.hpl.jena.rdf.model.ModelChangedListener;
|
||||
|
@ -64,6 +65,9 @@ public class JenaChangeListener implements ChangeListener {
|
|||
}
|
||||
return s;
|
||||
}
|
||||
} catch (RuntimeException riot) {
|
||||
log.error("Unable to parse triple " + serializedTriple, riot);
|
||||
throw riot;
|
||||
} catch (UnsupportedEncodingException uee) {
|
||||
throw new RuntimeException(uee);
|
||||
}
|
||||
|
|
|
@ -201,7 +201,7 @@ public abstract class RDFServiceImpl implements RDFService {
|
|||
literalBuff.append("\"");
|
||||
if (node.getLiteralDatatypeURI() != null) {
|
||||
literalBuff.append("^^<").append(node.getLiteralDatatypeURI()).append(">");
|
||||
} else if (node.getLiteralLanguage() != null && node.getLiteralLanguage() != "") {
|
||||
} else if (node.getLiteralLanguage() != null && node.getLiteralLanguage().length() > 0) {
|
||||
literalBuff.append("@").append(node.getLiteralLanguage());
|
||||
}
|
||||
return literalBuff.toString();
|
||||
|
|
|
@ -6,13 +6,13 @@ import java.util.ArrayList;
|
|||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.hp.hpl.jena.ontology.AnnotationProperty;
|
||||
import com.hp.hpl.jena.ontology.ConversionException;
|
||||
import com.hp.hpl.jena.ontology.OntClass;
|
||||
import com.hp.hpl.jena.ontology.OntModel;
|
||||
import com.hp.hpl.jena.ontology.OntModelSpec;
|
||||
|
@ -23,6 +23,7 @@ import com.hp.hpl.jena.rdf.model.Model;
|
|||
import com.hp.hpl.jena.rdf.model.ModelFactory;
|
||||
import com.hp.hpl.jena.rdf.model.Property;
|
||||
import com.hp.hpl.jena.rdf.model.RDFNode;
|
||||
import com.hp.hpl.jena.rdf.model.ResIterator;
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
import com.hp.hpl.jena.rdf.model.ResourceFactory;
|
||||
import com.hp.hpl.jena.rdf.model.Statement;
|
||||
|
@ -424,6 +425,20 @@ public class SimpleReasoner extends StatementListener {
|
|||
*
|
||||
*/
|
||||
protected void removedABoxTypeAssertion(Statement stmt, Model inferenceModel) {
|
||||
removedABoxTypeAssertion(stmt, inferenceModel, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* remainingTypeURIs is an optional list of asserted type URIs for the subject of
|
||||
* stmt, and may be null. Supplying a precompiled list can yield performance
|
||||
* improvement when this method is called repeatedly for the same subject.
|
||||
*
|
||||
*/
|
||||
protected void removedABoxTypeAssertion(Statement stmt, Model inferenceModel, List<String> remainingTypeURIs) {
|
||||
tboxModel.enterCriticalSection(Lock.READ);
|
||||
try {
|
||||
Resource cls = null;
|
||||
|
@ -450,7 +465,8 @@ public class SimpleReasoner extends StatementListener {
|
|||
// of classes not individuals.
|
||||
if (parentClass.isAnon()) continue;
|
||||
|
||||
if (entailedType(stmt.getSubject(),parentClass)) {
|
||||
List<String> typeURIs = (remainingTypeURIs == null) ? getRemainingAssertedTypeURIs(stmt.getSubject()) : remainingTypeURIs;
|
||||
if (entailedType(stmt.getSubject(),parentClass, typeURIs)) {
|
||||
continue; // if a type is still entailed without the
|
||||
}
|
||||
// removed statement, then don't remove it
|
||||
|
@ -884,29 +900,62 @@ public class SimpleReasoner extends StatementListener {
|
|||
// Returns true if it is entailed by class subsumption that
|
||||
// subject is of type cls; otherwise returns false.
|
||||
protected boolean entailedType(Resource subject, Resource cls) {
|
||||
return entailedType(subject, cls, null);
|
||||
}
|
||||
|
||||
List<Resource> sameIndividuals = getSameIndividuals(subject,inferenceModel);
|
||||
sameIndividuals.add(subject);
|
||||
// Returns true if it is entailed by class subsumption that
|
||||
// subject is of type cls; otherwise returns false.
|
||||
// remainingTypeURIs is an optional list of asserted type URIs for the subject
|
||||
// resource, and may be null. Supplying a precompiled list can yield performance
|
||||
// improvement when this method is called repeatedly for the same subject.
|
||||
protected boolean entailedType(Resource subject, Resource cls, List<String> remainingTypeURIs) {
|
||||
|
||||
List<Resource> subClasses = getSubClasses(cls);
|
||||
aboxModel.enterCriticalSection(Lock.READ);
|
||||
try {
|
||||
Iterator<Resource> iter = subClasses.iterator();
|
||||
while (iter.hasNext()) {
|
||||
Resource childClass = iter.next();
|
||||
if (childClass.equals(cls)) continue;
|
||||
Iterator<Resource> sameIter = sameIndividuals.iterator();
|
||||
while (sameIter.hasNext()) {
|
||||
Statement stmt = ResourceFactory.createStatement(sameIter.next(), RDF.type, childClass);
|
||||
if (aboxModel.contains(stmt)) {
|
||||
Set<String> subClassURIs = new HashSet<String>();
|
||||
for (Resource subClass : subClasses) {
|
||||
if (!subClass.isAnon()) {
|
||||
subClassURIs.add(subClass.getURI());
|
||||
}
|
||||
}
|
||||
|
||||
List<String> typeURIs = (remainingTypeURIs == null) ? getRemainingAssertedTypeURIs(subject) : remainingTypeURIs;
|
||||
|
||||
for (String typeURI : typeURIs) {
|
||||
if (!typeURI.equals(cls.getURI()) && subClassURIs.contains(typeURI)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
protected List<String> getRemainingAssertedTypeURIs(Resource resource) {
|
||||
|
||||
List<String> typeURIs = new ArrayList<String>();
|
||||
|
||||
List<Resource> sameIndividuals = getSameIndividuals(resource,inferenceModel);
|
||||
sameIndividuals.add(resource);
|
||||
|
||||
aboxModel.enterCriticalSection(Lock.READ);
|
||||
try {
|
||||
Iterator<Resource> sameIter = sameIndividuals.iterator();
|
||||
while (sameIter.hasNext()) {
|
||||
Resource res = sameIter.next();
|
||||
StmtIterator typeIt = aboxModel.listStatements(res, RDF.type, (RDFNode) null);
|
||||
while (typeIt.hasNext()) {
|
||||
Statement stmt = typeIt.nextStatement();
|
||||
if (stmt.getObject().isURIResource()) {
|
||||
String typeURI = stmt.getObject().asResource().getURI();
|
||||
typeURIs.add(typeURI);
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
aboxModel.leaveCriticalSection();
|
||||
}
|
||||
|
||||
return typeURIs;
|
||||
}
|
||||
|
||||
protected List<Resource> getSubClasses(Resource cls) {
|
||||
|
@ -1555,22 +1604,31 @@ public class SimpleReasoner extends StatementListener {
|
|||
}
|
||||
|
||||
retractions.enterCriticalSection(Lock.READ);
|
||||
StmtIterator iter = null;
|
||||
int num = 0;
|
||||
|
||||
try {
|
||||
log.info("started computing inferences for batch " + qualifier + " updates");
|
||||
iter = retractions.listStatements();
|
||||
|
||||
|
||||
ResIterator subIt = retractions.listSubjects();
|
||||
while (subIt.hasNext()) {
|
||||
Resource subj = subIt.nextResource();
|
||||
StmtIterator iter = retractions.listStatements(
|
||||
subj, null, (RDFNode) null);
|
||||
boolean typesModified = false;
|
||||
try {
|
||||
List<String> typeURIs = null;
|
||||
while (iter.hasNext() && !stopRequested) {
|
||||
Statement stmt = iter.next();
|
||||
num++;
|
||||
|
||||
try {
|
||||
if (stmt.getPredicate().equals(RDF.type)) {
|
||||
removedABoxTypeAssertion(stmt, inferenceModel);
|
||||
typesModified = true;
|
||||
if (typeURIs == null) {
|
||||
typeURIs = getRemainingAssertedTypeURIs(stmt.getSubject());
|
||||
}
|
||||
removedABoxTypeAssertion(stmt, inferenceModel, typeURIs);
|
||||
}
|
||||
setMostSpecificTypes(stmt.getSubject(), inferenceModel, new HashSet<String>());
|
||||
doPlugins(ModelUpdate.Operation.RETRACT,stmt);
|
||||
} catch (NullPointerException npe) {
|
||||
abort = true;
|
||||
|
@ -1590,6 +1648,12 @@ public class SimpleReasoner extends StatementListener {
|
|||
}
|
||||
} finally {
|
||||
iter.close();
|
||||
if (typesModified) {
|
||||
setMostSpecificTypes(subj, inferenceModel, new HashSet<String>());
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
retractions.removeAll();
|
||||
retractions.leaveCriticalSection();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,209 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.reasoner.plugin;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.hp.hpl.jena.graph.Graph;
|
||||
import com.hp.hpl.jena.ontology.OntModel;
|
||||
import com.hp.hpl.jena.query.Query;
|
||||
import com.hp.hpl.jena.query.QueryExecution;
|
||||
import com.hp.hpl.jena.query.QueryExecutionFactory;
|
||||
import com.hp.hpl.jena.query.QueryFactory;
|
||||
import com.hp.hpl.jena.query.QueryParseException;
|
||||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
import com.hp.hpl.jena.rdf.model.ModelFactory;
|
||||
import com.hp.hpl.jena.rdf.model.Property;
|
||||
import com.hp.hpl.jena.rdf.model.RDFNode;
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
import com.hp.hpl.jena.rdf.model.ResourceFactory;
|
||||
import com.hp.hpl.jena.rdf.model.Statement;
|
||||
import com.hp.hpl.jena.rdf.model.StmtIterator;
|
||||
import com.hp.hpl.jena.sparql.util.graph.GraphFactory;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.DifferenceGraph;
|
||||
import edu.cornell.mannlib.vitro.webapp.reasoner.ReasonerPlugin;
|
||||
import edu.cornell.mannlib.vitro.webapp.reasoner.SimpleReasoner;
|
||||
|
||||
/**
|
||||
* handles rules of the form
|
||||
* assertedProp1(?x, ?y) ^ assertedProp2(?y, ?z) -> inferredProp(?x, ?z)
|
||||
*
|
||||
*/
|
||||
public abstract class SimpleBridgingRule implements ReasonerPlugin {
|
||||
|
||||
private static final Log log = LogFactory.getLog(SimpleBridgingRule.class);
|
||||
|
||||
private Property assertedProp1;
|
||||
private Property assertedProp2;
|
||||
private Property inferredProp;
|
||||
|
||||
private String queryStr;
|
||||
private String retractionTestString;
|
||||
|
||||
private SimpleReasoner simpleReasoner;
|
||||
|
||||
protected SimpleBridgingRule(String assertedProp1, String assertedProp2, String inferredProp) {
|
||||
this.assertedProp1 = ResourceFactory.createProperty(assertedProp1);
|
||||
this.assertedProp2 = ResourceFactory.createProperty(assertedProp2);
|
||||
this.inferredProp = ResourceFactory.createProperty(inferredProp);
|
||||
|
||||
this.queryStr = "CONSTRUCT { \n" +
|
||||
" ?x <" + inferredProp + "> ?z \n" +
|
||||
"} WHERE { \n" +
|
||||
" ?x <" + assertedProp1 + "> ?y . \n" +
|
||||
" ?y <" + assertedProp2 + "> ?z \n" +
|
||||
"}";
|
||||
|
||||
this.retractionTestString =
|
||||
" ASK { \n" +
|
||||
" ?x <" + assertedProp1 + "> ?y . \n" +
|
||||
" ?y <" + assertedProp2 + "> ?z \n" +
|
||||
" } ";
|
||||
|
||||
}
|
||||
|
||||
public boolean isInterestedInAddedStatement(Statement stmt) {
|
||||
return isRelevantPredicate(stmt);
|
||||
}
|
||||
|
||||
public boolean isInterestedInRemovedStatement(Statement stmt) {
|
||||
return isRelevantPredicate(stmt);
|
||||
}
|
||||
|
||||
public void addedABoxStatement(Statement stmt,
|
||||
Model aboxAssertionsModel,
|
||||
Model aboxInferencesModel,
|
||||
OntModel TBoxInferencesModel) {
|
||||
if (ignore(stmt)) {
|
||||
return;
|
||||
}
|
||||
Model inf = constructInferences(this.queryStr, stmt, aboxAssertionsModel);
|
||||
StmtIterator sit = inf.listStatements();
|
||||
while(sit.hasNext()) {
|
||||
Statement s = sit.nextStatement();
|
||||
if (simpleReasoner != null) simpleReasoner.addInference(s,aboxInferencesModel);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean ignore(Statement stmt) {
|
||||
return (
|
||||
(stmt.getSubject().isAnon() || stmt.getObject().isAnon())
|
||||
// can't deal with blank nodes
|
||||
||
|
||||
(!stmt.getObject().isResource())
|
||||
// don't deal with literal values
|
||||
);
|
||||
}
|
||||
|
||||
private Query createQuery(String queryString, Statement stmt, Statement statement2) {
|
||||
String queryStr = new String(queryString);
|
||||
if (stmt.getPredicate().equals(assertedProp1)) {
|
||||
queryStr = queryStr.replace(
|
||||
"?x", "<" + stmt.getSubject().getURI() + ">");
|
||||
queryStr = queryStr.replace(
|
||||
"?y", "<" + ((Resource) stmt.getObject()).getURI() + ">");
|
||||
} else if (stmt.getPredicate().equals(assertedProp2)) {
|
||||
queryStr = queryStr.replace(
|
||||
"?y", "<" + stmt.getSubject().getURI() + ">");
|
||||
queryStr = queryStr.replace(
|
||||
"?z", "<" + ((Resource) stmt.getObject()).getURI() + ">");
|
||||
} else {
|
||||
// should never be here
|
||||
return null;
|
||||
}
|
||||
if (statement2 != null) {
|
||||
queryStr = queryStr.replace(
|
||||
"?x", "<" + stmt.getSubject().getURI() + ">");
|
||||
queryStr = queryStr.replace(
|
||||
"?z", "<" + ((Resource) stmt.getObject()).getURI() + ">");
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(queryStr);
|
||||
}
|
||||
Query query = null;
|
||||
try {
|
||||
query = QueryFactory.create(queryStr);
|
||||
} catch (QueryParseException e) {
|
||||
log.error("Unable to parse query for SimpleBridgingRule. \n" +
|
||||
"This may mean that one of the following URIs is malformed: \n" +
|
||||
stmt.getSubject() + "\n" + stmt.getObject() + "\n"
|
||||
);
|
||||
log.error(e, e);
|
||||
throw(e);
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
private Model constructInferences(String queryString, Statement stmt, Model aboxAssertionsModel) {
|
||||
Query query = createQuery(queryString, stmt, null);
|
||||
QueryExecution qe = QueryExecutionFactory.create(query, aboxAssertionsModel);
|
||||
try {
|
||||
return qe.execConstruct();
|
||||
} finally {
|
||||
qe.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void removedABoxStatement(Statement stmt,
|
||||
Model aboxAssertionsModel,
|
||||
Model aboxInferencesModel,
|
||||
OntModel TBoxInferencesModel) {
|
||||
|
||||
if (ignore(stmt)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// I initially tried constructing the statements to remove with a single
|
||||
// SPARQL CONSTRUCT statement, but that didn't seem to perform very well.
|
||||
// So this first retrieves a list of candidate ?x <inferredProp> ?z
|
||||
// statements, and then runs an ASK query to determine if there are still
|
||||
// statements ?x <assertedProp1> ?y and ?y <assertedProp2> ?z that entail
|
||||
// the statement in question. If not, the statement is removed.
|
||||
|
||||
// find-based candidate identification
|
||||
Resource x = null;
|
||||
RDFNode z = null;
|
||||
if (stmt.getPredicate().equals(assertedProp1)) {
|
||||
x = stmt.getSubject();
|
||||
} else if (stmt.getPredicate().equals(assertedProp2)) {
|
||||
z = stmt.getObject();
|
||||
}
|
||||
StmtIterator sit = aboxInferencesModel.listStatements(x, this.inferredProp, z);
|
||||
|
||||
while(sit.hasNext()) {
|
||||
Statement s = sit.nextStatement();
|
||||
Query ask = createQuery(this.retractionTestString, stmt, s);
|
||||
QueryExecution qe = QueryExecutionFactory.create(ask, aboxAssertionsModel);
|
||||
try {
|
||||
if (!qe.execAsk()) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("==> removing " + s);
|
||||
}
|
||||
if (simpleReasoner != null) simpleReasoner.removeInference(s,aboxInferencesModel);
|
||||
}
|
||||
} finally {
|
||||
qe.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isRelevantPredicate(Statement stmt) {
|
||||
return (assertedProp1.equals(stmt.getPredicate())
|
||||
|| assertedProp2.equals(stmt.getPredicate()));
|
||||
}
|
||||
|
||||
public void setSimpleReasoner(SimpleReasoner simpleReasoner) {
|
||||
this.simpleReasoner = simpleReasoner;
|
||||
}
|
||||
|
||||
public SimpleReasoner getSimpleReasoner() {
|
||||
return this.simpleReasoner;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.reasoner.plugin;
|
||||
|
||||
import com.hp.hpl.jena.ontology.OntModel;
|
||||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
import com.hp.hpl.jena.rdf.model.Property;
|
||||
import com.hp.hpl.jena.rdf.model.RDFNode;
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
import com.hp.hpl.jena.rdf.model.ResourceFactory;
|
||||
import com.hp.hpl.jena.rdf.model.Statement;
|
||||
import com.hp.hpl.jena.rdf.model.StmtIterator;
|
||||
import com.hp.hpl.jena.vocabulary.RDF;
|
||||
import com.hp.hpl.jena.vocabulary.RDFS;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.reasoner.ReasonerPlugin;
|
||||
import edu.cornell.mannlib.vitro.webapp.reasoner.SimpleReasoner;
|
||||
|
||||
/**
|
||||
* handles rules of the form
|
||||
* assertedProp(?x, ?y) ^ type(?x) -> inferredProp(?x, ?y)
|
||||
*
|
||||
* @author bjl23
|
||||
*
|
||||
*/
|
||||
public abstract class SimplePropertyAndTypeRule implements ReasonerPlugin {
|
||||
|
||||
private Property ASSERTED_PROP;
|
||||
private Resource TYPE;
|
||||
private Property INFERRED_PROP;
|
||||
private SimpleReasoner simpleReasoner;
|
||||
|
||||
protected SimplePropertyAndTypeRule(String assertedProp, String type, String inferredProp) {
|
||||
TYPE = ResourceFactory.createResource(type);
|
||||
ASSERTED_PROP = ResourceFactory.createProperty(assertedProp);
|
||||
INFERRED_PROP = ResourceFactory.createProperty(inferredProp);
|
||||
}
|
||||
|
||||
public boolean isInterestedInAddedStatement(Statement stmt) {
|
||||
return (RDF.type.equals(stmt.getPredicate()) || isRelevantPredicate(stmt));
|
||||
}
|
||||
|
||||
public boolean isInterestedInRemovedStatement(Statement stmt) {
|
||||
return (RDF.type.equals(stmt.getPredicate()) || isRelevantPredicate(stmt));
|
||||
}
|
||||
|
||||
public void addedABoxStatement(Statement stmt,
|
||||
Model aboxAssertionsModel,
|
||||
Model aboxInferencesModel,
|
||||
OntModel TBoxInferencesModel) {
|
||||
boolean relevantType = isRelevantType(stmt, TBoxInferencesModel);
|
||||
boolean relevantPredicate = isRelevantPredicate(stmt);
|
||||
|
||||
if (relevantType) {
|
||||
StmtIterator stmtIt = aboxAssertionsModel.listStatements(
|
||||
stmt.getSubject(), ASSERTED_PROP, (RDFNode)null);
|
||||
while (stmtIt.hasNext()) {
|
||||
Statement s = stmtIt.nextStatement();
|
||||
tryToInfer(stmt.getSubject(),
|
||||
INFERRED_PROP,
|
||||
s.getObject(),
|
||||
aboxAssertionsModel,
|
||||
aboxInferencesModel);
|
||||
}
|
||||
} else if (relevantPredicate) {
|
||||
if(aboxAssertionsModel.contains(
|
||||
stmt.getSubject(), RDF.type, TYPE)
|
||||
|| aboxInferencesModel.contains(
|
||||
stmt.getSubject(), RDF.type, TYPE)) {
|
||||
tryToInfer(stmt.getSubject(),
|
||||
INFERRED_PROP,
|
||||
stmt.getObject(),
|
||||
aboxAssertionsModel,
|
||||
aboxInferencesModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void tryToInfer(Resource subject,
|
||||
Property predicate,
|
||||
RDFNode object,
|
||||
Model aboxAssertionsModel,
|
||||
Model aboxInferencesModel) {
|
||||
// this should be part of a superclass or some class that provides
|
||||
// reasoning framework functions
|
||||
Statement s = ResourceFactory.createStatement(subject, predicate, object);
|
||||
if (simpleReasoner != null) {
|
||||
simpleReasoner.addInference(s,aboxInferencesModel);
|
||||
}
|
||||
}
|
||||
|
||||
public void removedABoxStatement(Statement stmt,
|
||||
Model aboxAssertionsModel,
|
||||
Model aboxInferencesModel,
|
||||
OntModel TBoxInferencesModel) {
|
||||
|
||||
if (isRelevantPredicate(stmt)) {
|
||||
// if (aboxAssertionsModel.contains(
|
||||
// stmt.getSubject(), RDF.type, BIBO_DOCUMENT)
|
||||
// || aboxInferencesModel.contains(
|
||||
// stmt.getSubject(), RDF.type, BIBO_DOCUMENT)) {
|
||||
if (simpleReasoner != null) {
|
||||
simpleReasoner.removeInference(ResourceFactory.createStatement(stmt.getSubject(), INFERRED_PROP, stmt.getObject()), aboxInferencesModel);
|
||||
}
|
||||
// }
|
||||
} else if (isRelevantType(stmt, TBoxInferencesModel)) {
|
||||
if(!aboxInferencesModel.contains(
|
||||
stmt.getSubject(), RDF.type, TYPE)) {
|
||||
StmtIterator groundIt = aboxAssertionsModel.listStatements(
|
||||
stmt.getSubject(), ASSERTED_PROP, (RDFNode) null);
|
||||
while (groundIt.hasNext()) {
|
||||
Statement groundStmt = groundIt.nextStatement();
|
||||
simpleReasoner.removeInference(ResourceFactory.createStatement(groundStmt.getSubject(), INFERRED_PROP, groundStmt.getObject()), aboxInferencesModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isRelevantType(Statement stmt, Model TBoxInferencesModel) {
|
||||
return (RDF.type.equals(stmt.getPredicate())
|
||||
&& (TYPE.equals(stmt.getObject())
|
||||
|| TBoxInferencesModel.contains(
|
||||
(Resource) stmt.getObject(), RDFS.subClassOf, TYPE)));
|
||||
}
|
||||
|
||||
private boolean isRelevantPredicate(Statement stmt) {
|
||||
return (ASSERTED_PROP.equals(stmt.getPredicate()));
|
||||
}
|
||||
|
||||
public void setSimpleReasoner(SimpleReasoner simpleReasoner) {
|
||||
this.simpleReasoner = simpleReasoner;
|
||||
}
|
||||
|
||||
public SimpleReasoner getSimpleReasoner() {
|
||||
return this.simpleReasoner;
|
||||
}
|
||||
}
|
|
@ -1,136 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.reasoner.plugin;
|
||||
|
||||
import com.hp.hpl.jena.ontology.OntModel;
|
||||
import com.hp.hpl.jena.query.Query;
|
||||
import com.hp.hpl.jena.query.QueryExecution;
|
||||
import com.hp.hpl.jena.query.QueryExecutionFactory;
|
||||
import com.hp.hpl.jena.query.QueryFactory;
|
||||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
import com.hp.hpl.jena.rdf.model.ModelFactory;
|
||||
import com.hp.hpl.jena.rdf.model.Property;
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
import com.hp.hpl.jena.rdf.model.ResourceFactory;
|
||||
import com.hp.hpl.jena.rdf.model.Statement;
|
||||
import com.hp.hpl.jena.rdf.model.StmtIterator;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.reasoner.ReasonerPlugin;
|
||||
import edu.cornell.mannlib.vitro.webapp.reasoner.SimpleReasoner;
|
||||
|
||||
/**
|
||||
* handles rules of the form
|
||||
* assertedProp1(?x, ?y) ^ assertedProp2(?y, ?z) -> inferredProp(?x, ?z)
|
||||
*
|
||||
*/
|
||||
public abstract class SimpleBridgingRule implements ReasonerPlugin {
|
||||
|
||||
private Property assertedProp1;
|
||||
private Property assertedProp2;
|
||||
private String queryStr;
|
||||
private SimpleReasoner simpleReasoner;
|
||||
|
||||
protected SimpleBridgingRule(String assertedProp1, String assertedProp2, String inferredProp) {
|
||||
this.assertedProp1 = ResourceFactory.createProperty(assertedProp1);
|
||||
this.assertedProp2 = ResourceFactory.createProperty(assertedProp2);
|
||||
|
||||
this.queryStr = "CONSTRUCT { \n" +
|
||||
" ?x <" + inferredProp + "> ?z \n" +
|
||||
"} WHERE { \n" +
|
||||
" ?x <" + assertedProp1 + "> ?y . \n" +
|
||||
" ?y <" + assertedProp2 + "> ?z \n" +
|
||||
"}";
|
||||
}
|
||||
|
||||
public boolean isInterestedInAddedStatement(Statement stmt) {
|
||||
return isRelevantPredicate(stmt);
|
||||
}
|
||||
|
||||
public boolean isInterestedInRemovedStatement(Statement stmt) {
|
||||
return isRelevantPredicate(stmt);
|
||||
}
|
||||
|
||||
public void addedABoxStatement(Statement stmt,
|
||||
Model aboxAssertionsModel,
|
||||
Model aboxInferencesModel,
|
||||
OntModel TBoxInferencesModel) {
|
||||
if (ignore(stmt)) {
|
||||
return;
|
||||
}
|
||||
Model inf = constructInferences(stmt, aboxAssertionsModel);
|
||||
StmtIterator sit = inf.listStatements();
|
||||
while(sit.hasNext()) {
|
||||
Statement s = sit.nextStatement();
|
||||
if (simpleReasoner != null) simpleReasoner.addInference(s,aboxInferencesModel);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean ignore(Statement stmt) {
|
||||
return (
|
||||
(stmt.getSubject().isAnon() || stmt.getObject().isAnon())
|
||||
// can't deal with blank nodes
|
||||
||
|
||||
(!stmt.getObject().isResource())
|
||||
// don't deal with literal values
|
||||
);
|
||||
}
|
||||
|
||||
private Model constructInferences(Statement stmt, Model aboxAssertionsModel) {
|
||||
String queryStr = new String(this.queryStr);
|
||||
if (stmt.getPredicate().equals(assertedProp1)) {
|
||||
queryStr = queryStr.replace(
|
||||
"?x", "<" + stmt.getSubject().getURI() + ">");
|
||||
queryStr = queryStr.replace(
|
||||
"?y", "<" + ((Resource) stmt.getObject()).getURI() + ">");
|
||||
} else if (stmt.getPredicate().equals(assertedProp2)) {
|
||||
queryStr = queryStr.replace(
|
||||
"?y", "<" + stmt.getSubject().getURI() + ">");
|
||||
queryStr = queryStr.replace(
|
||||
"?z", "<" + ((Resource) stmt.getObject()).getURI() + ">");
|
||||
} else {
|
||||
// should never be here
|
||||
return ModelFactory.createDefaultModel();
|
||||
}
|
||||
Query query = QueryFactory.create(queryStr);
|
||||
QueryExecution qe = QueryExecutionFactory.create(query, aboxAssertionsModel);
|
||||
try {
|
||||
return qe.execConstruct();
|
||||
} finally {
|
||||
qe.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void removedABoxStatement(Statement stmt,
|
||||
Model aboxAssertionsModel,
|
||||
Model aboxInferencesModel,
|
||||
OntModel TBoxInferencesModel) {
|
||||
if (ignore(stmt)) {
|
||||
return;
|
||||
}
|
||||
Model m = ModelFactory.createDefaultModel();
|
||||
m.add(stmt);
|
||||
Model union = ModelFactory.createUnion(m, aboxAssertionsModel);
|
||||
|
||||
Model inf = constructInferences(stmt, union);
|
||||
StmtIterator sit = inf.listStatements();
|
||||
while(sit.hasNext()) {
|
||||
Statement s = sit.nextStatement();
|
||||
if (simpleReasoner != null) simpleReasoner.removeInference(s,aboxInferencesModel);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isRelevantPredicate(Statement stmt) {
|
||||
return (assertedProp1.equals(stmt.getPredicate())
|
||||
|| assertedProp2.equals(stmt.getPredicate()));
|
||||
}
|
||||
|
||||
public void setSimpleReasoner(SimpleReasoner simpleReasoner) {
|
||||
this.simpleReasoner = simpleReasoner;
|
||||
}
|
||||
|
||||
public SimpleReasoner getSimpleReasoner() {
|
||||
return this.simpleReasoner;
|
||||
}
|
||||
}
|
||||
|
Loading…
Add table
Reference in a new issue