NIHVIVO-3205 reasoner plugin infrastructure for inter-ontology mapping; NIHVIVO-3221 derive dc:title for documents; and NIHVIVO-3239 bugfix to prevent anonymous type creation in IndividualDaoJena.updateIndividual()

This commit is contained in:
brianjlowe 2011-10-25 19:20:02 +00:00
parent b0db754533
commit 91a483a788
4 changed files with 185 additions and 23 deletions

View file

@ -23,6 +23,8 @@ import com.hp.hpl.jena.ontology.OntResource;
import com.hp.hpl.jena.ontology.UnionClass;
import com.hp.hpl.jena.rdf.model.AnonId;
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.Property;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.ResIterator;
@ -285,6 +287,13 @@ public class IndividualDaoJena extends JenaBaseDao implements IndividualDao {
com.hp.hpl.jena.ontology.Individual ind = ontModel.getIndividual(ent.getURI());
if (ind != null) {
if (ent.getName() != null && ( (ind.getLabel(getDefaultLanguage())==null) || (ind.getLabel(getDefaultLanguage())!=null && ent.getName()!=null && !ent.getName().equals(ind.getLabel(getDefaultLanguage())) ) ) ) {
// removal of existing values done this odd way to trigger
// the change listeners
Model temp = ModelFactory.createDefaultModel();
temp.add(ontModel.listStatements(ind, RDFS.label, (RDFNode) null));
ontModel.remove(temp);
ind.setLabel(ent.getName(), getDefaultLanguage());
}
Set<String> oldTypeURIsSet = new HashSet<String>();
@ -295,7 +304,9 @@ public class IndividualDaoJena extends JenaBaseDao implements IndividualDao {
}
}
Set<String> newTypeURIsSet = new HashSet<String>();
newTypeURIsSet.add(ent.getVClassURI());
if (ent.getVClassURI() != null) {
newTypeURIsSet.add(ent.getVClassURI());
}
boolean conservativeTypeDeletion = false;
try {
List<VClass> vcl = ent.getVClasses(false);

View file

@ -0,0 +1,23 @@
package edu.cornell.mannlib.vitro.webapp.reasoner;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.Statement;
public interface ReasonerPlugin {
public boolean isInterestedInAddedStatement(Statement stmt);
public boolean isInterestedInRemovedStatement(Statement stmt);
public void addedABoxStatement(Statement stmt,
Model aboxAssertionsModel,
Model aboxInferencesModel,
OntModel TBoxInferencesModel);
public void removedABoxStatement(Statement stmt,
Model aboxAssertionsModel,
Model aboxInferencesModel,
OntModel TBoxInferencesModel);
}

View file

@ -70,6 +70,8 @@ public class SimpleReasoner extends StatementListener {
private CumulativeDeltaModeler aBoxDeltaModeler2 = null;
private boolean batchMode1 = false, batchMode2 = false;
private boolean stopRequested = false;
private List<ReasonerPlugin> pluginList = new ArrayList<ReasonerPlugin>();
/**
* @param tboxModel - input. This model contains both asserted and inferred TBox axioms
@ -114,6 +116,14 @@ public class SimpleReasoner extends StatementListener {
stopRequested = false;
}
public void setPluginList(List<ReasonerPlugin> pluginList) {
this.pluginList = pluginList;
}
public List<ReasonerPlugin> getPluginList() {
return this.pluginList;
}
/*
* Performs selected incremental ABox reasoning based
* on the addition of a new statement (aka assertion)
@ -127,11 +137,19 @@ public class SimpleReasoner extends StatementListener {
addedABoxTypeAssertion(stmt, inferenceModel, new HashSet<String>());
setMostSpecificTypes(stmt.getSubject(), inferenceModel, new HashSet<String>());
}
/* uncomment this to enable subproperty/equivalent property inferencing. sjm222 5/13/2011
else {
addedABoxAssertion(stmt,inferenceModel);
// uncomment this to enable subproperty/equivalent property inferencing. sjm222 5/13/2011
// addedABoxAssertion(stmt,inferenceModel);
for (ReasonerPlugin plugin : getPluginList()) {
try {
if (plugin.isInterestedInAddedStatement(stmt)) {
plugin.addedABoxStatement(
stmt, aboxModel, inferenceModel, tboxModel);
}
} catch (Throwable t) {
log.error(t, t);
}
}
*/
} catch (Exception e) {
// don't stop the edit if there's an exception
log.error("Exception while computing inferences: " + e.getMessage());
@ -141,30 +159,46 @@ public class SimpleReasoner extends StatementListener {
/*
* Performs selected incremental ABox reasoning based
* on the retraction of a statement (aka assertion)
* from the ABox.
* from the ABox.
*/
@Override
public void removedStatement(Statement stmt) {
try {
if (stmt.getPredicate().equals(RDF.type)) {
if (batchMode1) {
aBoxDeltaModeler1.removedStatement(stmt);
} else if (batchMode2) {
aBoxDeltaModeler2.removedStatement(stmt);
} else {
removedABoxTypeAssertion(stmt, inferenceModel);
setMostSpecificTypes(stmt.getSubject(), inferenceModel, new HashSet<String>());
// The delta modeler could optionally record only statements relevant
// to reasoning by checking the .isInterestedInRemovedStatement()
// methods on the plugins in addition to recording rdf:type
// statements. If property reasoning were uncommented, however,
// almost all statements would be relevant.
if (batchMode1) {
aBoxDeltaModeler1.removedStatement(stmt);
} else if (batchMode2) {
aBoxDeltaModeler2.removedStatement(stmt);
} else {
if (stmt.getPredicate().equals(RDF.type)) {
removedABoxTypeAssertion(stmt, inferenceModel);
setMostSpecificTypes(stmt.getSubject(), inferenceModel, new HashSet<String>());
}
// uncomment this to enable subproperty/equivalent property inferencing. sjm222 5/13/2011
// removedABoxAssertion(stmt, inferenceModel);
for (ReasonerPlugin plugin : getPluginList()) {
try {
if (plugin.isInterestedInRemovedStatement(stmt)) {
plugin.removedABoxStatement(
stmt, aboxModel, inferenceModel, tboxModel);
}
} catch (Throwable t) {
log.error(t, t);
}
}
}
/* uncomment this to enable subproperty/equivalent property inferencing. sjm222 5/13/2011
else {
removedABoxAssertion(stmt, inferenceModel);
}
*/
} catch (Exception e) {
// don't stop the edit if there's an exception
log.error("Exception while retracting inferences: " + e.getMessage());
log.error("Exception while retracting inferences: ", e);
}
}
@ -1013,17 +1047,24 @@ public class SimpleReasoner extends StatementListener {
try {
addedABoxTypeAssertion(individual, inferenceRebuildModel, unknownTypes);
setMostSpecificTypes(individual, inferenceRebuildModel, unknownTypes);
StmtIterator sit = aboxModel.listStatements(individual, null, (RDFNode) null);
while (sit.hasNext()) {
Statement s = sit.nextStatement();
for (ReasonerPlugin plugin : getPluginList()) {
plugin.addedABoxStatement(s, aboxModel, inferenceRebuildModel, tboxModel);
}
}
} 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: " + je.getMessage() + ". Halting inference computation.");
log.error("Exception while recomputing ABox inference model. Halting inference computation.", je);
return;
}
log.error("Exception while recomputing ABox inference model: " + je.getMessage());
log.error("Exception while recomputing ABox inference model: ", je);
} catch (Exception e) {
log.error("Exception while recomputing ABox inference model: " + e.getMessage());
log.error("Exception while recomputing ABox inference model: ", e);
}
numStmts++;
@ -1391,6 +1432,16 @@ public class SimpleReasoner extends StatementListener {
try {
removedABoxTypeAssertion(stmt, inferenceModel);
for (ReasonerPlugin plugin : getPluginList()) {
try {
if (plugin.isInterestedInRemovedStatement(stmt)) {
plugin.removedABoxStatement(
stmt, aboxModel, inferenceModel, tboxModel);
}
} catch (Throwable t) {
log.error(t, t);
}
}
setMostSpecificTypes(stmt.getSubject(), inferenceModel, new HashSet<String>());
//TODO update this part when subproperty inferencing is added.
} catch (NullPointerException npe) {

View file

@ -2,6 +2,13 @@
package edu.cornell.mannlib.vitro.webapp.servlet.setup;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
@ -20,14 +27,18 @@ import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelector;
import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactoryJena;
import edu.cornell.mannlib.vitro.webapp.dao.jena.pellet.PelletListener;
import edu.cornell.mannlib.vitro.webapp.dao.jena.pellet.ReasonerConfiguration;
import edu.cornell.mannlib.vitro.webapp.reasoner.ReasonerPlugin;
import edu.cornell.mannlib.vitro.webapp.reasoner.SimpleReasoner;
import edu.cornell.mannlib.vitro.webapp.reasoner.support.SimpleReasonerTBoxListener;
import edu.cornell.mannlib.vitro.webapp.servlet.setup.JenaDataSourceSetupBase.TripleStoreType;
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
public class SimpleReasonerSetup implements ServletContextListener {
private static final Log log = LogFactory.getLog(SimpleReasonerSetup.class.getName());
public static final String FILE_OF_PLUGINS = "/WEB-INF/resources/reasoner_plugins.txt";
// Models used during a full recompute of the ABox
static final String JENA_INF_MODEL_REBUILD = "http://vitro.mannlib.cornell.edu/default/vitro-kb-inf-rebuild";
static final String JENA_INF_MODEL_SCRATCHPAD = "http://vitro.mannlib.cornell.edu/default/vitro-kb-inf-scratchpad";
@ -93,6 +104,21 @@ public class SimpleReasonerSetup implements ServletContextListener {
SimpleReasoner simpleReasoner = new SimpleReasoner(unionOms.getTBoxModel(), assertionsOms.getABoxModel(), inferencesOms.getABoxModel(), rebuildModel, scratchModel);
sce.getServletContext().setAttribute(SimpleReasoner.class.getName(),simpleReasoner);
StartupStatus ss = StartupStatus.getBean(ctx);
List<ReasonerPlugin> pluginList = new ArrayList<ReasonerPlugin>();
List<String> pluginClassnameList = this.readFileOfListeners(ctx);
for (String classname : pluginClassnameList) {
try {
ReasonerPlugin plugin = (ReasonerPlugin) Class.forName(
classname).getConstructors()[0].newInstance();
pluginList.add(plugin);
} catch(Throwable t) {
ss.info(this, "Could not instantiate reasoner plugin " + classname);
}
}
simpleReasoner.setPluginList(pluginList);
if (isRecomputeRequired(sce.getServletContext())) {
log.info("ABox inference recompute required.");
@ -204,4 +230,55 @@ public class SimpleReasonerSetup implements ServletContextListener {
simpleReasoner.computeMostSpecificType();
}
}
/**
* Read the names of the plugin classes classes.
*
* If there is a problem, set a fatal error, and return an empty list.
*/
private List<String> readFileOfListeners(ServletContext ctx) {
List<String> list = new ArrayList<String>();
StartupStatus ss = StartupStatus.getBean(ctx);
InputStream is = null;
BufferedReader br = null;
try {
is = ctx.getResourceAsStream(FILE_OF_PLUGINS);
br = new BufferedReader(new InputStreamReader(is));
String line;
while (null != (line = br.readLine())) {
String trimmed = line.trim();
if (!trimmed.isEmpty() && !trimmed.startsWith("#")) {
list.add(trimmed);
}
}
} catch (NullPointerException e) {
// ignore the lack of file
} catch (IOException e) {
ss.fatal(this,
"Failed while processing the list of startup listeners: "
+ FILE_OF_PLUGINS, e);
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
log.error(e);
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
log.error(e);
}
}
}
log.debug("Classnames of reasoner plugins = " + list);
return list;
}
}