From f93b0259637686895f0763eef0b5f1aee6d20cff Mon Sep 17 00:00:00 2001 From: brianjlowe Date: Wed, 26 Oct 2011 21:08:54 +0000 Subject: [PATCH] NIHVIVO-3223 derive dc:creator for documents --- .../WEB-INF/resources/reasoner_plugins.txt | 1 + .../plugin/DCCreatorForDocuments.java | 16 ++ .../reasoner/plugin/DCTitleForDocuments.java | 102 +------------ .../reasoner/plugin/SimpleBridgingRule.java | 141 ++++++++++++++++++ .../plugin/SimplePropertyAndTypeRule.java | 126 ++++++++++++++++ 5 files changed, 290 insertions(+), 96 deletions(-) create mode 100644 src/org/vivoweb/reasoner/plugin/DCCreatorForDocuments.java create mode 100644 src/org/vivoweb/reasoner/plugin/SimpleBridgingRule.java create mode 100644 src/org/vivoweb/reasoner/plugin/SimplePropertyAndTypeRule.java diff --git a/productMods/WEB-INF/resources/reasoner_plugins.txt b/productMods/WEB-INF/resources/reasoner_plugins.txt index 25372641..7a96851c 100644 --- a/productMods/WEB-INF/resources/reasoner_plugins.txt +++ b/productMods/WEB-INF/resources/reasoner_plugins.txt @@ -1 +1,2 @@ org.vivoweb.reasoner.plugin.DCTitleForDocuments +org.vivoweb.reasoner.plugin.DCCreatorForDocuments diff --git a/src/org/vivoweb/reasoner/plugin/DCCreatorForDocuments.java b/src/org/vivoweb/reasoner/plugin/DCCreatorForDocuments.java new file mode 100644 index 00000000..51d1974b --- /dev/null +++ b/src/org/vivoweb/reasoner/plugin/DCCreatorForDocuments.java @@ -0,0 +1,16 @@ +package org.vivoweb.reasoner.plugin; + +import edu.cornell.mannlib.vitro.webapp.reasoner.ReasonerPlugin; + +public class DCCreatorForDocuments extends SimpleBridgingRule implements ReasonerPlugin { + + private final static String DCTERMS = "http://purl.org/dc/terms/"; + private final static String VIVOCORE = "http://vivoweb.org/ontology/core#"; + + public DCCreatorForDocuments() { + super(VIVOCORE + "informationResourceInAuthorship", + VIVOCORE + "linkedAuthor", + DCTERMS + "creator"); + } + +} diff --git a/src/org/vivoweb/reasoner/plugin/DCTitleForDocuments.java b/src/org/vivoweb/reasoner/plugin/DCTitleForDocuments.java index aeabcd66..9295e7de 100644 --- a/src/org/vivoweb/reasoner/plugin/DCTitleForDocuments.java +++ b/src/org/vivoweb/reasoner/plugin/DCTitleForDocuments.java @@ -16,102 +16,12 @@ import com.hp.hpl.jena.vocabulary.RDFS; import edu.cornell.mannlib.vitro.webapp.reasoner.ReasonerPlugin; -public class DCTitleForDocuments implements ReasonerPlugin { +public class DCTitleForDocuments extends SimplePropertyAndTypeRule implements ReasonerPlugin { - private final static Log log = LogFactory.getLog(DCTitleForDocuments.class); - - private final Resource BIBO_DOCUMENT = ResourceFactory.createResource( - "http://purl.org/ontology/bibo/Document"); - private final Property DCTERMS_TITLE = ResourceFactory.createProperty( - "http://purl.org/dc/terms/title"); - - public boolean isInterestedInAddedStatement(Statement stmt) { - return (isRelevantType(stmt) || isRelevantPredicate(stmt)); + public DCTitleForDocuments() { + super(RDFS.label.getURI(), + "http://purl.org/ontology/bibo/Document", + "http://purl.org/dc/terms/title"); } - - public boolean isInterestedInRemovedStatement(Statement stmt) { - return (isRelevantType(stmt) || isRelevantPredicate(stmt)); - } - - public void addedABoxStatement(Statement stmt, - Model aboxAssertionsModel, - Model aboxInferencesModel, - OntModel TBoxInferencesModel) { - boolean relevantType = isRelevantType(stmt); - boolean relevantPredicate = isRelevantPredicate(stmt); - - if (relevantType) { - StmtIterator stmtIt = aboxAssertionsModel.listStatements( - stmt.getSubject(), RDFS.label, (RDFNode)null); - while (stmtIt.hasNext()) { - Statement s = stmtIt.nextStatement(); - tryToInfer(stmt.getSubject(), - DCTERMS_TITLE, - s.getObject(), - aboxAssertionsModel, - aboxInferencesModel); - } - } else if (relevantPredicate) { - if(aboxAssertionsModel.contains( - stmt.getSubject(), RDF.type, BIBO_DOCUMENT) - || aboxInferencesModel.contains( - stmt.getSubject(), RDF.type, BIBO_DOCUMENT)) { - tryToInfer(stmt.getSubject(), - DCTERMS_TITLE, - 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 (!aboxAssertionsModel.contains(s) && !aboxInferencesModel.contains(s)) { - aboxInferencesModel.add(s); - } - } - - 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)) { - aboxInferencesModel.remove( - stmt.getSubject(), DCTERMS_TITLE, stmt.getObject()); -// } - } else if (isRelevantType(stmt)) { - if(!aboxInferencesModel.contains( - stmt.getSubject(), RDF.type, BIBO_DOCUMENT)) { - StmtIterator labelIt = aboxAssertionsModel.listStatements( - stmt.getSubject(), RDFS.label, (RDFNode) null); - while (labelIt.hasNext()) { - Statement labelStmt = labelIt.nextStatement(); - aboxInferencesModel.remove( - labelStmt.getSubject(), DCTERMS_TITLE, labelStmt.getObject()); - } - } - } - } - - private boolean isRelevantType(Statement stmt) { - return (RDF.type.equals(stmt.getPredicate()) - && BIBO_DOCUMENT.equals(stmt.getObject())); - } - - private boolean isRelevantPredicate(Statement stmt) { - return (RDFS.label.equals(stmt.getPredicate())); - } - + } diff --git a/src/org/vivoweb/reasoner/plugin/SimpleBridgingRule.java b/src/org/vivoweb/reasoner/plugin/SimpleBridgingRule.java new file mode 100644 index 00000000..9b376519 --- /dev/null +++ b/src/org/vivoweb/reasoner/plugin/SimpleBridgingRule.java @@ -0,0 +1,141 @@ +package org.vivoweb.reasoner.plugin; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +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; + +/** + * handles rules of the form + * assertedProp1(?x, ?y) ^ assertedProp2(?y, ?z) -> inferredProp(?x, ?z) + * + * @author bjl23 + * + */ +public abstract class SimpleBridgingRule implements ReasonerPlugin { + + private static final Log log = LogFactory.getLog(SimpleBridgingRule.class); + + private Property assertedProp1; + private Property assertedProp2; + private String queryStr; + + 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(); + tryToInfer(s, aboxAssertionsModel, 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(); + } + + } + + private void tryToInfer(Statement s, + Model aboxAssertionsModel, + Model aboxInferencesModel) { + // this should be part of a superclass or some class that provides + // reasoning framework functions + if (!aboxAssertionsModel.contains(s) && !aboxInferencesModel.contains(s)) { + aboxInferencesModel.add(s); + } + } + + public void removedABoxStatement(Statement stmt, + Model aboxAssertionsModel, + Model aboxInferencesModel, + OntModel TBoxInferencesModel) { + if (ignore(stmt)) { + return; + } + // The following should probably be improved, as it is likely to be + // inefficient. + // The SPARQL query will currently depend on the existence of the triple + // that has just been removed, so we'll union it in temporarily. + // TODO: make the SPARQL query construction smarter. + Model m = ModelFactory.createDefaultModel(); + m.add(stmt); + Model union = ModelFactory.createUnion(m, aboxAssertionsModel); + aboxInferencesModel.remove(constructInferences(stmt, union)); + } + + private boolean isRelevantPredicate(Statement stmt) { + return (assertedProp1.equals(stmt.getPredicate()) + || assertedProp2.equals(stmt.getPredicate())); + } + +} + diff --git a/src/org/vivoweb/reasoner/plugin/SimplePropertyAndTypeRule.java b/src/org/vivoweb/reasoner/plugin/SimplePropertyAndTypeRule.java new file mode 100644 index 00000000..d6e14024 --- /dev/null +++ b/src/org/vivoweb/reasoner/plugin/SimplePropertyAndTypeRule.java @@ -0,0 +1,126 @@ +package org.vivoweb.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; + +/** + * 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; + + 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 (!aboxAssertionsModel.contains(s) && !aboxInferencesModel.contains(s)) { + aboxInferencesModel.add(s); + } + } + + 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)) { + aboxInferencesModel.remove( + stmt.getSubject(), INFERRED_PROP, stmt.getObject()); +// } + } 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(); + aboxInferencesModel.remove( + groundStmt.getSubject(), INFERRED_PROP, groundStmt.getObject()); + } + } + } + } + + 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())); + } + +}