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:
parent
b0db754533
commit
91a483a788
4 changed files with 185 additions and 23 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue