VIVO-778 Wild restructuring
Create TBoxChanges, createTBoxReasonerDriver, delete PelletListener, deal with repercussions all over.
This commit is contained in:
parent
4e15695281
commit
24bce9ff67
15 changed files with 517 additions and 466 deletions
|
@ -24,9 +24,10 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMa
|
|||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.pellet.PelletListener;
|
||||
import edu.cornell.mannlib.vitro.webapp.search.controller.IndexController;
|
||||
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasonerDriver;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasonerDriver.Status;
|
||||
|
||||
public class BaseSiteAdminController extends FreemarkerHttpServlet {
|
||||
|
||||
|
@ -161,13 +162,13 @@ public class BaseSiteAdminController extends FreemarkerHttpServlet {
|
|||
|
||||
String pelletError = null;
|
||||
String pelletExplanation = null;
|
||||
Object plObj = getServletContext().getAttribute("pelletListener");
|
||||
if ( (plObj != null) && (plObj instanceof PelletListener) ) {
|
||||
PelletListener pelletListener = (PelletListener) plObj;
|
||||
if (!pelletListener.isConsistent()) {
|
||||
Object tbrObj = getServletContext().getAttribute("tboxReasoner");
|
||||
if ( tbrObj instanceof TBoxReasonerDriver) {
|
||||
Status status = ((TBoxReasonerDriver) tbrObj).getStatus();
|
||||
if (!status.isConsistent()) {
|
||||
pelletError = "INCONSISTENT ONTOLOGY: reasoning halted.";
|
||||
pelletExplanation = pelletListener.getExplanation();
|
||||
} else if ( pelletListener.isInErrorState() ) {
|
||||
pelletExplanation = status.getExplanation();
|
||||
} else if ( status.isInErrorState() ) {
|
||||
pelletError = "An error occurred during reasoning. Reasoning has been halted. See error log for details.";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
|
|||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasonerWrapper;
|
||||
|
||||
public class JenaAdminActions extends BaseEditController {
|
||||
|
||||
|
@ -190,8 +191,8 @@ public class JenaAdminActions extends BaseEditController {
|
|||
}
|
||||
|
||||
private void printRestrictions() {
|
||||
OntModel memoryModel = (OntModel) getServletContext().getAttribute("pelletOntModel");
|
||||
for (Restriction rest : memoryModel.listRestrictions().toList() ) {
|
||||
TBoxReasonerWrapper reasoner = (TBoxReasonerWrapper) getServletContext().getAttribute("tboxReasonerWrapper");
|
||||
for (Restriction rest : reasoner.listRestrictions() ) {
|
||||
//System.out.println();
|
||||
if (rest.isAllValuesFromRestriction()) {
|
||||
log.trace("All values from: ");
|
||||
|
|
|
@ -51,8 +51,8 @@ import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyDao;
|
|||
import edu.cornell.mannlib.vitro.webapp.dao.InsertException;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.pellet.PelletListener;
|
||||
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasonerDriver;
|
||||
|
||||
public class DataPropertyDaoJena extends PropertyDaoJena implements
|
||||
DataPropertyDao {
|
||||
|
@ -357,9 +357,9 @@ public class DataPropertyDaoJena extends PropertyDaoJena implements
|
|||
}
|
||||
|
||||
protected boolean reasoningAvailable() {
|
||||
PelletListener pl = getWebappDaoFactory().getPelletListener();
|
||||
TBoxReasonerDriver pl = getWebappDaoFactory().getTBoxReasonerDriver();
|
||||
return !(
|
||||
( pl == null || !pl.isConsistent() || pl.isInErrorState() )
|
||||
( pl == null || !pl.getStatus().isConsistent() || pl.getStatus().isInErrorState() )
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -47,10 +47,10 @@ import edu.cornell.mannlib.vitro.webapp.dao.VClassGroupDao;
|
|||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactoryConfig;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.pellet.PelletListener;
|
||||
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames;
|
||||
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
|
||||
import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.jena.model.RDFServiceModel;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasonerDriver;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.jena.URIUtils;
|
||||
|
||||
public class WebappDaoFactoryJena implements WebappDaoFactory {
|
||||
|
@ -70,7 +70,7 @@ public class WebappDaoFactoryJena implements WebappDaoFactory {
|
|||
|
||||
protected WebappDaoFactoryConfig config;
|
||||
|
||||
protected PelletListener pelletListener;
|
||||
protected TBoxReasonerDriver tbrd;
|
||||
|
||||
protected String userURI;
|
||||
|
||||
|
@ -242,12 +242,12 @@ public class WebappDaoFactoryJena implements WebappDaoFactory {
|
|||
* This enables the WebappDaoFactory to check the status of a reasoner.
|
||||
* This will likely be refactored in future releases.
|
||||
*/
|
||||
public void setPelletListener(PelletListener pl) {
|
||||
this.pelletListener = pl;
|
||||
public void setTBoxReasonerDriver(TBoxReasonerDriver tbrd) {
|
||||
this.tbrd = tbrd;
|
||||
}
|
||||
|
||||
public PelletListener getPelletListener() {
|
||||
return this.pelletListener;
|
||||
public TBoxReasonerDriver getTBoxReasonerDriver() {
|
||||
return this.tbrd;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -2,21 +2,19 @@
|
|||
|
||||
package edu.cornell.mannlib.vitro.webapp.dao.jena.pellet;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
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.Model;
|
||||
import com.hp.hpl.jena.rdf.model.ModelFactory;
|
||||
import com.hp.hpl.jena.rdf.model.Statement;
|
||||
import com.hp.hpl.jena.vocabulary.OWL;
|
||||
import com.hp.hpl.jena.vocabulary.RDFS;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.ConfiguredReasonerListener;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.ConfiguredReasonerListener.Suspension;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.ReasonerStatementPattern;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasonerWrapper;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockableModel;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockableOntModel;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockedModel;
|
||||
|
@ -30,8 +28,8 @@ public class InferenceModelUpdater {
|
|||
private static final Log log = LogFactory
|
||||
.getLog(InferenceModelUpdater.class);
|
||||
|
||||
private final LockableOntModel lockableReasonerModel;
|
||||
private final LockableModel lockableInferenceModel;
|
||||
private final TBoxReasonerWrapper reasoner;
|
||||
private final LockableModel lockableInferencesModel;
|
||||
private final LockableOntModel lockableFullModel;
|
||||
private final ConfiguredReasonerListener listener;
|
||||
|
||||
|
@ -46,57 +44,36 @@ public class InferenceModelUpdater {
|
|||
return retractCount;
|
||||
}
|
||||
|
||||
public InferenceModelUpdater(OntModel reasonerModel, Model inferenceModel,
|
||||
OntModel fullModel, ConfiguredReasonerListener listener) {
|
||||
this.lockableReasonerModel = new LockableOntModel(reasonerModel);
|
||||
this.lockableInferenceModel = new LockableModel(inferenceModel);
|
||||
this.lockableFullModel = new LockableOntModel(fullModel);
|
||||
public InferenceModelUpdater(TBoxReasonerWrapper reasoner,
|
||||
LockableModel lockableInferencesModel,
|
||||
LockableOntModel lockableFullModel,
|
||||
ConfiguredReasonerListener listener) {
|
||||
this.reasoner = reasoner;
|
||||
this.lockableInferencesModel = lockableInferencesModel;
|
||||
this.lockableFullModel = lockableFullModel;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronize the inferences model with the reasoner model, with these
|
||||
* provisos:
|
||||
*
|
||||
* Statements in the reasoner model about RDFS.Resource or OWL.Nothing are
|
||||
* ignored.
|
||||
* Synchronize the inferences model with the reasoner model, with this
|
||||
* proviso:
|
||||
*
|
||||
* If a statement exists anywhere in the full TBox, don't bother adding it
|
||||
* to the inferences model.
|
||||
*/
|
||||
public void update(LinkedList<ReasonerStatementPattern> patternList) {
|
||||
Model filteredReasonerModel = filterReasonerModel(patternList);
|
||||
public void update(List<ReasonerStatementPattern> patternList) {
|
||||
List<Statement> filteredReasonerModel = reasoner
|
||||
.filterResults(patternList);
|
||||
addNewInferences(filteredReasonerModel);
|
||||
removeOldInferences(filterInferencesModel(patternList),
|
||||
filteredReasonerModel);
|
||||
log.warn("Added: " + addCount + ", Retracted: " + retractCount);
|
||||
}
|
||||
|
||||
private Model filterReasonerModel(
|
||||
LinkedList<ReasonerStatementPattern> patternList) {
|
||||
Model filtered = ModelFactory.createDefaultModel();
|
||||
try (LockedOntModel reasonerModel = lockableReasonerModel.read()) {
|
||||
for (ReasonerStatementPattern pattern : patternList) {
|
||||
filtered.add(pattern.matchStatementsFromModel(reasonerModel));
|
||||
}
|
||||
}
|
||||
for (Statement stmt : filtered.listStatements().toList()) {
|
||||
if (stmt.getObject().equals(RDFS.Resource)) {
|
||||
filtered.remove(stmt);
|
||||
} else if (stmt.getSubject().equals(OWL.Nothing)) {
|
||||
filtered.remove(stmt);
|
||||
} else if (stmt.getObject().equals(OWL.Nothing)) {
|
||||
filtered.remove(stmt);
|
||||
}
|
||||
}
|
||||
log.warn("Filtered reasoner model: " + filtered.size());
|
||||
return filtered;
|
||||
}
|
||||
|
||||
private void addNewInferences(Model filteredReasonerModel) {
|
||||
for (Statement stmt : filteredReasonerModel.listStatements().toList()) {
|
||||
private void addNewInferences(List<Statement> filteredReasonerModel) {
|
||||
for (Statement stmt : filteredReasonerModel) {
|
||||
if (!fullModelContainsStatement(stmt)) {
|
||||
try (LockedModel inferenceModel = lockableInferenceModel
|
||||
try (LockedModel inferenceModel = lockableInferencesModel
|
||||
.write(); Suspension susp = listener.suspend()) {
|
||||
inferenceModel.add(stmt);
|
||||
addCount++;
|
||||
|
@ -112,11 +89,11 @@ public class InferenceModelUpdater {
|
|||
}
|
||||
|
||||
private Model filterInferencesModel(
|
||||
LinkedList<ReasonerStatementPattern> patternList) {
|
||||
List<ReasonerStatementPattern> patternList) {
|
||||
Model filtered = ModelFactory.createDefaultModel();
|
||||
try (LockedOntModel reasonerModel = lockableReasonerModel.read()) {
|
||||
try (LockedModel inferencesModel = lockableInferencesModel.read()) {
|
||||
for (ReasonerStatementPattern pattern : patternList) {
|
||||
filtered.add(pattern.matchStatementsFromModel(reasonerModel));
|
||||
filtered.add(pattern.matchStatementsFromModel(inferencesModel));
|
||||
}
|
||||
}
|
||||
log.warn("Filtered inferences model: " + filtered.size());
|
||||
|
@ -124,10 +101,13 @@ public class InferenceModelUpdater {
|
|||
}
|
||||
|
||||
private void removeOldInferences(Model filteredInferencesModel,
|
||||
Model filteredReasonerModel) {
|
||||
List<Statement> filteredReasonerStatements) {
|
||||
Model filteredReasonerModel = ModelFactory.createDefaultModel();
|
||||
filteredReasonerModel.add(filteredReasonerStatements);
|
||||
|
||||
for (Statement stmt : filteredInferencesModel.listStatements().toList()) {
|
||||
if (!filteredReasonerModel.contains(stmt)) {
|
||||
try (LockedModel inferenceModel = lockableInferenceModel
|
||||
try (LockedModel inferenceModel = lockableInferencesModel
|
||||
.write(); Suspension susp = listener.suspend()) {
|
||||
retractCount++;
|
||||
inferenceModel.remove(stmt);
|
||||
|
|
|
@ -9,16 +9,11 @@ import java.util.Set;
|
|||
|
||||
import com.hp.hpl.jena.ontology.DatatypeProperty;
|
||||
import com.hp.hpl.jena.ontology.ObjectProperty;
|
||||
import com.hp.hpl.jena.ontology.OntModel;
|
||||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.ReasonerConfiguration;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.ReasonerStatementPattern;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockableModel;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockableOntModel;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockedModel;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockedOntModel;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxChanges;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasonerWrapper;
|
||||
|
||||
/**
|
||||
* The list of patterns for filtering the models will include:
|
||||
|
@ -32,79 +27,55 @@ public class PatternListBuilder {
|
|||
private static final String OWL_NS = "http://www.w3.org/2002/07/owl#";
|
||||
|
||||
private final ReasonerConfiguration reasonerConfiguration;
|
||||
private final LockableOntModel lockableReasonerModel;
|
||||
private final LockableModel lockableDeletedObjectProperties;
|
||||
private final LockableModel lockableDeletedDataProperties;
|
||||
private final TBoxReasonerWrapper reasoner;
|
||||
private final TBoxChanges changes;
|
||||
|
||||
public PatternListBuilder(ReasonerConfiguration reasonerConfiguration,
|
||||
OntModel reasonerModel, Model deletedObjectProperties,
|
||||
Model deletedDataProperties) {
|
||||
TBoxReasonerWrapper reasoner, TBoxChanges changes) {
|
||||
this.reasonerConfiguration = reasonerConfiguration;
|
||||
this.lockableReasonerModel = new LockableOntModel(reasonerModel);
|
||||
this.lockableDeletedObjectProperties = new LockableModel(
|
||||
deletedObjectProperties);
|
||||
this.lockableDeletedDataProperties = new LockableModel(
|
||||
deletedDataProperties);
|
||||
this.reasoner = reasoner;
|
||||
this.changes = changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public LinkedList<ReasonerStatementPattern> build() {
|
||||
LinkedList<ReasonerStatementPattern> irpl = new LinkedList<>();
|
||||
LinkedList<ReasonerStatementPattern> patterns = new LinkedList<>();
|
||||
|
||||
Set<ReasonerStatementPattern> allowSet = reasonerConfiguration
|
||||
.getInferenceReceivingPatternAllowSet();
|
||||
if (allowSet != null) {
|
||||
irpl.addAll(allowSet);
|
||||
patterns.addAll(allowSet);
|
||||
} else {
|
||||
irpl.add(ReasonerStatementPattern.ANY_OBJECT_PROPERTY);
|
||||
patterns.add(ReasonerStatementPattern.ANY_OBJECT_PROPERTY);
|
||||
}
|
||||
|
||||
if (reasonerConfiguration.getQueryForAllObjectProperties()) {
|
||||
try (LockedOntModel reasonerModel = lockableReasonerModel.read()) {
|
||||
for (ObjectProperty objProp : reasonerModel
|
||||
.listObjectProperties().toList()) {
|
||||
if (!(OWL_NS.equals(objProp.getNameSpace()))) {
|
||||
irpl.add(ReasonerStatementPattern
|
||||
.objectPattern(objProp));
|
||||
}
|
||||
for (ObjectProperty objProp : reasoner.listObjectProperties()) {
|
||||
if (!(OWL_NS.equals(objProp.getNameSpace()))) {
|
||||
patterns.add(ReasonerStatementPattern
|
||||
.objectPattern(objProp));
|
||||
}
|
||||
}
|
||||
|
||||
try (LockedModel deletedObjectProperties = lockableDeletedObjectProperties
|
||||
.write()) {
|
||||
for (Resource subj : deletedObjectProperties.listSubjects()
|
||||
.toList()) {
|
||||
irpl.add(ReasonerStatementPattern
|
||||
.objectPattern(createProperty(subj.getURI())));
|
||||
}
|
||||
deletedObjectProperties.removeAll();
|
||||
for (String uri : changes.getDeletedObjectPropertyUris()) {
|
||||
patterns.add(ReasonerStatementPattern
|
||||
.objectPattern(createProperty(uri)));
|
||||
}
|
||||
}
|
||||
|
||||
if (reasonerConfiguration.getQueryForAllDatatypeProperties()) {
|
||||
try (LockedOntModel reasonerModel = lockableReasonerModel.read()) {
|
||||
for (DatatypeProperty dataProp : reasonerModel
|
||||
.listDatatypeProperties().toList()) {
|
||||
if (!(OWL_NS.equals(dataProp.getNameSpace()))) {
|
||||
// TODO: THIS WILL WORK, BUT NEED TO GENERALIZE THE
|
||||
// PATTERN CLASSES
|
||||
irpl.add(ReasonerStatementPattern
|
||||
.objectPattern(dataProp));
|
||||
}
|
||||
for (DatatypeProperty dataProp : reasoner.listDatatypeProperties()) {
|
||||
if (!(OWL_NS.equals(dataProp.getNameSpace()))) {
|
||||
// TODO: THIS WILL WORK, BUT NEED TO GENERALIZE THE
|
||||
// PATTERN CLASSES
|
||||
patterns.add(ReasonerStatementPattern
|
||||
.objectPattern(dataProp));
|
||||
}
|
||||
}
|
||||
try (LockedModel deletedDataProperties = lockableDeletedDataProperties
|
||||
.write()) {
|
||||
for (Resource subj : deletedDataProperties.listSubjects()
|
||||
.toList()) {
|
||||
irpl.add(ReasonerStatementPattern
|
||||
.objectPattern(createProperty(subj.getURI())));
|
||||
}
|
||||
deletedDataProperties.removeAll();
|
||||
for (String uri : changes.getDeletedDataPropertyUris()) {
|
||||
patterns.add(ReasonerStatementPattern
|
||||
.objectPattern(createProperty(uri)));
|
||||
}
|
||||
}
|
||||
return irpl;
|
||||
return patterns;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,313 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.dao.jena.pellet;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.mindswap.pellet.exceptions.InconsistentOntologyException;
|
||||
import org.mindswap.pellet.jena.PelletInfGraph;
|
||||
|
||||
import com.hp.hpl.jena.ontology.OntModel;
|
||||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
import com.hp.hpl.jena.rdf.model.ModelFactory;
|
||||
import com.hp.hpl.jena.rdf.model.RDFNode;
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
import com.hp.hpl.jena.rdf.model.Statement;
|
||||
import com.hp.hpl.jena.shared.Lock;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.ConfiguredReasonerListener;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.ReasonerConfiguration;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.ReasonerStatementPattern;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasonerDriver;
|
||||
|
||||
public class PelletListener implements TBoxReasonerDriver {
|
||||
|
||||
private static final Log log = LogFactory.getLog(PelletListener.class.getName());
|
||||
private boolean isReasoning = false;
|
||||
private boolean isSynchronizing = false;
|
||||
private boolean dirty = false;
|
||||
|
||||
private OntModel pelletModel;
|
||||
private OntModel fullModel;
|
||||
private OntModel mainModel;
|
||||
private Model inferenceModel;
|
||||
private ReasonerConfiguration reasonerConfiguration;
|
||||
private Set<ReasonerStatementPattern> inferenceDrivingPatternAllowSet;
|
||||
private Set<ReasonerStatementPattern> inferenceDrivingPatternDenySet;
|
||||
private Set<ReasonerStatementPattern> inferenceReceivingPatternAllowSet;
|
||||
|
||||
private final ConfiguredReasonerListener listener;
|
||||
|
||||
private Model additionModel;
|
||||
private Model removalModel;
|
||||
|
||||
private Model deletedObjectProperties;
|
||||
private Model deletedDataProperties;
|
||||
|
||||
private Status status = Status.SUCCESS;
|
||||
|
||||
public boolean isConsistent() {
|
||||
return this.status.isConsistent();
|
||||
}
|
||||
|
||||
public String getExplanation() {
|
||||
return this.status.getExplanation();
|
||||
}
|
||||
|
||||
public boolean isInErrorState() {
|
||||
return this.status.isInErrorState();
|
||||
}
|
||||
|
||||
public boolean isReasoning() {
|
||||
return this.isReasoning;
|
||||
}
|
||||
|
||||
public synchronized boolean checkAndStartReasoning(){
|
||||
if( this.isReasoning )
|
||||
return false;
|
||||
else{
|
||||
this.isReasoning = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void endReasoning() {
|
||||
this.isReasoning = false;
|
||||
}
|
||||
|
||||
public boolean isDirty() {
|
||||
return this.dirty;
|
||||
}
|
||||
|
||||
public void setDirty(boolean dirt) {
|
||||
this.dirty = dirt;
|
||||
}
|
||||
|
||||
private boolean foreground = false;
|
||||
private static final boolean FOREGROUND = true;
|
||||
private static final boolean BACKGROUND = false;
|
||||
private static final boolean DONT_SKIP_INITIAL_REASONING = false;
|
||||
|
||||
public PelletListener(OntModel fullModel, OntModel model, Model inferenceModel, ReasonerConfiguration reasonerConfiguration) {
|
||||
this(fullModel, model, inferenceModel, reasonerConfiguration, BACKGROUND);
|
||||
}
|
||||
|
||||
public PelletListener(OntModel fullModel, OntModel model, Model inferenceModel, ReasonerConfiguration reasonerConfiguration, boolean foreground) {
|
||||
this(fullModel, model, inferenceModel, reasonerConfiguration, foreground, DONT_SKIP_INITIAL_REASONING);
|
||||
}
|
||||
|
||||
public PelletListener(OntModel fullModel, OntModel model, Model inferenceModel, ReasonerConfiguration reasonerConfiguration, boolean foreground, boolean skipReasoningUponInitialization) {
|
||||
this.pelletModel = ModelFactory.createOntologyModel(reasonerConfiguration.getOntModelSpec());
|
||||
this.fullModel = fullModel;
|
||||
this.mainModel = model;
|
||||
this.inferenceModel = inferenceModel;
|
||||
if (this.inferenceModel == null) {
|
||||
log.trace("Inference model is null");
|
||||
}
|
||||
this.reasonerConfiguration = reasonerConfiguration;
|
||||
this.inferenceDrivingPatternAllowSet = reasonerConfiguration.getInferenceDrivingPatternAllowSet();
|
||||
this.inferenceDrivingPatternDenySet = reasonerConfiguration.getInferenceDrivingPatternDenySet();
|
||||
this.inferenceReceivingPatternAllowSet = reasonerConfiguration.getInferenceReceivingPatternAllowSet();
|
||||
|
||||
this.additionModel = ModelFactory.createDefaultModel();
|
||||
this.removalModel = ModelFactory.createDefaultModel();
|
||||
this.deletedObjectProperties = ModelFactory.createDefaultModel();
|
||||
this.deletedDataProperties = ModelFactory.createDefaultModel();
|
||||
|
||||
listener = new ConfiguredReasonerListener(reasonerConfiguration, this);
|
||||
|
||||
this.mainModel.enterCriticalSection(Lock.READ);
|
||||
try {
|
||||
for (ReasonerStatementPattern pat : this.inferenceDrivingPatternAllowSet) {
|
||||
listener.addedStatements(mainModel.listStatements((Resource) null, pat.getPredicate(), (RDFNode) null));
|
||||
}
|
||||
if (!skipReasoningUponInitialization) {
|
||||
this.foreground = foreground;
|
||||
listener.notifyEvent(null,new EditEvent(null,false));
|
||||
} else if (inferenceModel.size() == 0){
|
||||
foreground = true;
|
||||
listener.notifyEvent(null,new EditEvent(null,false));
|
||||
this.foreground = foreground;
|
||||
}
|
||||
} finally {
|
||||
this.mainModel.leaveCriticalSection();
|
||||
}
|
||||
|
||||
this.fullModel.getBaseModel().register(listener);
|
||||
this.mainModel.getBaseModel().register(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addStatement(Statement stmt) {
|
||||
additionModel.enterCriticalSection(Lock.WRITE);
|
||||
try {
|
||||
additionModel.add(stmt);
|
||||
} finally {
|
||||
additionModel.leaveCriticalSection();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeStatement(Statement stmt) {
|
||||
removalModel.enterCriticalSection(Lock.WRITE);
|
||||
try {
|
||||
removalModel.add(stmt);
|
||||
} finally {
|
||||
removalModel.leaveCriticalSection();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteDataProperty(Statement stmt) {
|
||||
deletedDataProperties.enterCriticalSection(Lock.WRITE);
|
||||
try {
|
||||
deletedDataProperties.add(stmt);
|
||||
} finally {
|
||||
deletedDataProperties.leaveCriticalSection();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteObjectProperty(Statement stmt) {
|
||||
deletedObjectProperties.enterCriticalSection(Lock.WRITE);
|
||||
try {
|
||||
deletedObjectProperties.add(stmt);
|
||||
} finally {
|
||||
deletedObjectProperties.leaveCriticalSection();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runSynchronizer() {
|
||||
if ((additionModel.size() > 0) || (removalModel.size() > 0)) {
|
||||
if (!isSynchronizing) {
|
||||
if (foreground) {
|
||||
log.debug("Running Pellet in foreground.");
|
||||
(new PelletSynchronizer()).run();
|
||||
} else {
|
||||
log.debug("Running Pellet in background.");
|
||||
new Thread(new PelletSynchronizer(),
|
||||
"PelletListener.PelletSynchronizer").start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class InferenceGetter implements Runnable {
|
||||
|
||||
private PelletListener pelletListener;
|
||||
|
||||
public InferenceGetter(PelletListener pelletListener) {
|
||||
this.pelletListener = pelletListener;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (pelletListener.isDirty()) {
|
||||
try {
|
||||
pelletListener.setDirty(false);
|
||||
log.info("Getting new inferences");
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
PatternListBuilder patternListBuilder = new PatternListBuilder(
|
||||
reasonerConfiguration, pelletModel,
|
||||
deletedObjectProperties, deletedDataProperties);
|
||||
LinkedList<ReasonerStatementPattern> irpl = patternListBuilder
|
||||
.build();
|
||||
|
||||
pelletModel.enterCriticalSection(Lock.WRITE);
|
||||
try {
|
||||
pelletModel.rebind();
|
||||
pelletModel.prepare();
|
||||
} finally {
|
||||
pelletModel.leaveCriticalSection();
|
||||
}
|
||||
|
||||
InferenceModelUpdater inferenceModelUpdater = new InferenceModelUpdater(
|
||||
pelletModel, inferenceModel, fullModel, listener);
|
||||
inferenceModelUpdater.update(irpl);
|
||||
|
||||
this.pelletListener.status = Status.SUCCESS;
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("Added "+inferenceModelUpdater.getAddCount()+" statements entailed by assertions");
|
||||
log.info("Retracted "+inferenceModelUpdater.getRetractCount()+" statements no longer entailed by assertions");
|
||||
log.info("Done getting new inferences: "+(System.currentTimeMillis()-startTime)/1000+" seconds");
|
||||
}
|
||||
} catch (InconsistentOntologyException ioe) {
|
||||
String explanation = ((PelletInfGraph)pelletModel.getGraph()).getKB().getExplanation();
|
||||
this.pelletListener.status = Status.inconsistent(explanation);
|
||||
log.error(ioe);
|
||||
log.error(explanation);
|
||||
} catch (Exception e) {
|
||||
this.pelletListener.status = Status.ERROR;
|
||||
log.error("Exception during inference", e);
|
||||
} finally {
|
||||
pelletListener.endReasoning();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void getInferences() {
|
||||
this.setDirty(true);
|
||||
if ( this.checkAndStartReasoning() ){
|
||||
if (foreground) {
|
||||
(new InferenceGetter(this)).run();
|
||||
} else {
|
||||
new Thread(new InferenceGetter(this), "PelletListener.InferenceGetter").start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class PelletSynchronizer implements Runnable {
|
||||
public void run() {
|
||||
try {
|
||||
isSynchronizing = true;
|
||||
while (removalModel.size()>0 || additionModel.size()>0) {
|
||||
Model tempModel = ModelFactory.createDefaultModel();
|
||||
removalModel.enterCriticalSection(Lock.WRITE);
|
||||
try {
|
||||
tempModel.add(removalModel);
|
||||
removalModel.removeAll();
|
||||
} finally {
|
||||
removalModel.leaveCriticalSection();
|
||||
}
|
||||
pelletModel.enterCriticalSection(Lock.WRITE);
|
||||
try {
|
||||
pelletModel.remove(tempModel);
|
||||
} finally {
|
||||
pelletModel.leaveCriticalSection();
|
||||
}
|
||||
tempModel.removeAll();
|
||||
additionModel.enterCriticalSection(Lock.WRITE);
|
||||
try {
|
||||
tempModel.add(additionModel);
|
||||
additionModel.removeAll();
|
||||
} finally {
|
||||
additionModel.leaveCriticalSection();
|
||||
}
|
||||
pelletModel.enterCriticalSection(Lock.WRITE);
|
||||
try {
|
||||
pelletModel.add(tempModel);
|
||||
} finally {
|
||||
pelletModel.leaveCriticalSection();
|
||||
}
|
||||
tempModel = null;
|
||||
|
||||
getInferences();
|
||||
|
||||
}
|
||||
} finally {
|
||||
isSynchronizing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public OntModel getPelletModel() {
|
||||
return this.pelletModel;
|
||||
}
|
||||
|
||||
}
|
|
@ -12,8 +12,8 @@ import edu.cornell.mannlib.vitro.webapp.beans.Individual;
|
|||
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
||||
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.edit.n3editing.VTwo.EditConfigurationVTwo;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasonerDriver;
|
||||
|
||||
public class IndividualsViaVClassOptions implements FieldOptions {
|
||||
|
||||
|
@ -104,8 +104,8 @@ public class IndividualsViaVClassOptions implements FieldOptions {
|
|||
protected boolean isReasoningAvailable( WebappDaoFactory wDaoFact){
|
||||
boolean inferenceAvailable = false;
|
||||
if (wDaoFact instanceof WebappDaoFactoryJena) {
|
||||
PelletListener pl = ((WebappDaoFactoryJena) wDaoFact).getPelletListener();
|
||||
if (pl != null && pl.isConsistent() && !pl.isInErrorState()
|
||||
TBoxReasonerDriver pl = ((WebappDaoFactoryJena) wDaoFact).getTBoxReasonerDriver();
|
||||
if (pl != null && pl.getStatus().isConsistent() && !pl.getStatus().isInErrorState()
|
||||
&& !pl.isReasoning()) {
|
||||
inferenceAvailable = true;
|
||||
}
|
||||
|
|
|
@ -14,15 +14,18 @@ import org.apache.commons.logging.Log;
|
|||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.hp.hpl.jena.ontology.OntModel;
|
||||
import com.hp.hpl.jena.vocabulary.OWL;
|
||||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
||||
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.modelaccess.ContextModelAccess;
|
||||
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
|
||||
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.BasicTBoxReasonerDriver;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.ReasonerConfiguration;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasonerDriver;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasonerWrapper;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.impl.pellet.PelletTBoxReasonerDriver;
|
||||
|
||||
/**
|
||||
* Start the Pellet reasoner on the TBox.
|
||||
|
@ -38,35 +41,22 @@ public class PelletReasonerSetup implements ServletContextListener {
|
|||
ContextModelAccess contextModels = ModelAccess.on(ctx);
|
||||
OntModel tboxAssertionsModel = contextModels
|
||||
.getOntModel(TBOX_ASSERTIONS);
|
||||
OntModel tboxInferencesModel = contextModels
|
||||
.getOntModel(TBOX_INFERENCES);
|
||||
Model tboxInferencesModel = contextModels
|
||||
.getOntModel(TBOX_INFERENCES).getBaseModel();
|
||||
OntModel tboxUnionModel = contextModels.getOntModel(TBOX_UNION);
|
||||
WebappDaoFactory wadf = contextModels.getWebappDaoFactory();
|
||||
|
||||
if (!tboxAssertionsModel.getProfile().NAMESPACE()
|
||||
.equals(OWL.NAMESPACE.getNameSpace())) {
|
||||
ss.fatal(this, "Not connecting Pellet reasoner "
|
||||
+ "- the TBox assertions model is not an OWL model");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set various Pellet options for incremental consistency checking, etc.
|
||||
// PelletOptions.DL_SAFE_RULES = true;
|
||||
// PelletOptions.USE_COMPLETION_QUEUE = true;
|
||||
// PelletOptions.USE_TRACING = true;
|
||||
// PelletOptions.TRACK_BRANCH_EFFECTS = true;
|
||||
// PelletOptions.USE_INCREMENTAL_CONSISTENCY = true;
|
||||
// PelletOptions.USE_INCREMENTAL_DELETION = true;
|
||||
|
||||
PelletListener pelletListener = new PelletListener(tboxUnionModel,
|
||||
tboxAssertionsModel, tboxInferencesModel,
|
||||
TBoxReasonerWrapper reasoner = new PelletTBoxReasonerDriver(
|
||||
ReasonerConfiguration.DEFAULT);
|
||||
sce.getServletContext().setAttribute("pelletListener", pelletListener);
|
||||
sce.getServletContext().setAttribute("pelletOntModel",
|
||||
pelletListener.getPelletModel());
|
||||
TBoxReasonerDriver driver = new BasicTBoxReasonerDriver(
|
||||
tboxAssertionsModel, tboxInferencesModel, tboxUnionModel,
|
||||
reasoner, ReasonerConfiguration.DEFAULT);
|
||||
|
||||
sce.getServletContext().setAttribute("tboxReasoner", driver);
|
||||
sce.getServletContext().setAttribute("tboxReasonerWrapper", reasoner);
|
||||
|
||||
if (wadf instanceof WebappDaoFactoryJena) {
|
||||
((WebappDaoFactoryJena) wadf).setPelletListener(pelletListener);
|
||||
((WebappDaoFactoryJena) wadf).setTBoxReasonerDriver(driver);
|
||||
}
|
||||
|
||||
ss.info(this, "Pellet reasoner connected for the TBox");
|
||||
|
@ -75,15 +65,14 @@ public class PelletReasonerSetup implements ServletContextListener {
|
|||
}
|
||||
|
||||
public static void waitForTBoxReasoning(ServletContextEvent sce) {
|
||||
PelletListener pelletListener = (PelletListener) sce
|
||||
.getServletContext().getAttribute("pelletListener");
|
||||
if (pelletListener == null) {
|
||||
TBoxReasonerDriver driver = (TBoxReasonerDriver) sce.getServletContext().getAttribute("tboxReasoner");
|
||||
if (driver == null) {
|
||||
return;
|
||||
}
|
||||
int sleeps = 0;
|
||||
// sleep at least once to make sure the TBox reasoning gets started
|
||||
while ((0 == sleeps)
|
||||
|| ((sleeps < 1000) && pelletListener.isReasoning())) {
|
||||
|| ((sleeps < 1000) && driver.isReasoning())) {
|
||||
if (((sleeps - 1) % 10) == 0) { // print message at 10 second
|
||||
// intervals
|
||||
log.info("Waiting for initial TBox reasoning to complete");
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.tboxreasoner;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
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.Model;
|
||||
import com.hp.hpl.jena.rdf.model.RDFNode;
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
import com.hp.hpl.jena.rdf.model.Statement;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.pellet.InferenceModelUpdater;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.pellet.PatternListBuilder;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockableModel;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockableOntModel;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockedOntModel;
|
||||
|
||||
/**
|
||||
* The basic implementation of the TBoxReasonerDriver.
|
||||
*/
|
||||
public class BasicTBoxReasonerDriver implements TBoxReasonerDriver {
|
||||
private static final Log log = LogFactory
|
||||
.getLog(BasicTBoxReasonerDriver.class);
|
||||
|
||||
private final LockableOntModel lockableAssertionsModel;
|
||||
private final LockableModel lockableInferencesModel;
|
||||
private final LockableOntModel lockableFullModel;
|
||||
|
||||
private final ReasonerConfiguration reasonerConfiguration;
|
||||
|
||||
private final ConfiguredReasonerListener listener;
|
||||
|
||||
private final AtomicReference<TBoxChanges> currentChangeSet;
|
||||
private final Set<TBoxChanges> pendingChangeSets;
|
||||
|
||||
private final ExecutorService executorService;
|
||||
|
||||
private final TBoxReasonerWrapper reasoner;
|
||||
|
||||
private TBoxReasonerDriver.Status status;
|
||||
|
||||
public BasicTBoxReasonerDriver(OntModel assertionsModel,
|
||||
Model inferencesModel, OntModel fullModel, TBoxReasonerWrapper reasoner,
|
||||
ReasonerConfiguration reasonerConfiguration) {
|
||||
this.lockableAssertionsModel = new LockableOntModel(assertionsModel);
|
||||
this.lockableInferencesModel = new LockableModel(inferencesModel);
|
||||
this.lockableFullModel = new LockableOntModel(fullModel);
|
||||
this.reasoner = reasoner;
|
||||
this.reasonerConfiguration = reasonerConfiguration;
|
||||
|
||||
this.listener = new ConfiguredReasonerListener(reasonerConfiguration,
|
||||
this);
|
||||
|
||||
this.currentChangeSet = new AtomicReference<>(new TBoxChanges());
|
||||
this.pendingChangeSets = Collections.synchronizedSet(new HashSet<TBoxChanges>());
|
||||
|
||||
this.executorService = Executors.newFixedThreadPool(1);
|
||||
|
||||
assertionsModel.getBaseModel().register(listener);
|
||||
fullModel.getBaseModel().register(listener);
|
||||
|
||||
doInitialReasoning();
|
||||
}
|
||||
|
||||
private void doInitialReasoning() {
|
||||
try (LockedOntModel assertionsModel = lockableAssertionsModel.read()) {
|
||||
for (ReasonerStatementPattern pat : reasonerConfiguration
|
||||
.getInferenceDrivingPatternAllowSet()) {
|
||||
listener.addedStatements(assertionsModel.listStatements(
|
||||
(Resource) null, pat.getPredicate(), (RDFNode) null));
|
||||
}
|
||||
}
|
||||
listener.notifyEvent(null, new EditEvent(null, false));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReasoning() {
|
||||
return !pendingChangeSets.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addStatement(Statement stmt) {
|
||||
currentChangeSet.get().addStatement(stmt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeStatement(Statement stmt) {
|
||||
currentChangeSet.get().removeStatement(stmt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteDataProperty(Statement stmt) {
|
||||
currentChangeSet.get().deleteDataProperty(stmt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteObjectProperty(Statement stmt) {
|
||||
currentChangeSet.get().deleteObjectProperty(stmt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runSynchronizer() {
|
||||
TBoxChanges changes = currentChangeSet.getAndSet(new TBoxChanges());
|
||||
if (changes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
executorService.execute(new ReasoningTask(changes));
|
||||
}
|
||||
|
||||
private class ReasoningTask implements Runnable {
|
||||
private final TBoxChanges changes;
|
||||
private List<ReasonerStatementPattern> patternList;
|
||||
|
||||
public ReasoningTask(TBoxChanges changes) {
|
||||
this.changes = changes;
|
||||
pendingChangeSets.add(changes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
reasoner.updateReasonerModel(changes);
|
||||
status = reasoner.performReasoning();
|
||||
buildPatternList();
|
||||
updateInferencesModel();
|
||||
} finally {
|
||||
pendingChangeSets.remove(changes);
|
||||
}
|
||||
}
|
||||
|
||||
private void buildPatternList() {
|
||||
PatternListBuilder patternListBuilder = new PatternListBuilder(
|
||||
reasonerConfiguration, reasoner, changes);
|
||||
this.patternList = patternListBuilder.build();
|
||||
}
|
||||
|
||||
private void updateInferencesModel() {
|
||||
InferenceModelUpdater inferenceModelUpdater = new InferenceModelUpdater(
|
||||
reasoner, lockableInferencesModel, lockableFullModel, listener);
|
||||
inferenceModelUpdater.update(patternList);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -26,6 +26,11 @@ import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent;
|
|||
* Listens for changes on a model. When a change is announced, it is passed
|
||||
* along to the reasoner driver, if the configuration says that it is worthy.
|
||||
*
|
||||
* Among the criteria for deciding on worthiness is the driving pattern set. In
|
||||
* the constructor, a map is made from this set, to reduce the number of tests
|
||||
* made against each statement. I don't know whether this optimization is
|
||||
* justified.
|
||||
*
|
||||
* It is possible to "suspend" the listener, so it will ignore any changes. This
|
||||
* is useful when the reasoner itself makes changes to the models, so those
|
||||
* changes do not trigger additional reasoning.
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.tboxreasoner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.hp.hpl.jena.rdf.model.Resource;
|
||||
import com.hp.hpl.jena.rdf.model.Statement;
|
||||
|
||||
/**
|
||||
* Accumulate changes to the TBox as they arrive. Then make them available to
|
||||
* the TBox reasoner.
|
||||
*/
|
||||
public class TBoxChanges {
|
||||
private final List<Statement> addedStatements = Collections
|
||||
.synchronizedList(new ArrayList<Statement>());
|
||||
|
||||
private final List<Statement> removedStatements = Collections
|
||||
.synchronizedList(new ArrayList<Statement>());
|
||||
|
||||
private final List<String> deletedDataPropertyUris = Collections
|
||||
.synchronizedList(new ArrayList<String>());
|
||||
private final List<String> deletedObjectPropertyUris = Collections
|
||||
.synchronizedList(new ArrayList<String>());
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// These methods are called when populating the changeSet. They must be
|
||||
// thread-safe.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
public void addStatement(Statement stmt) {
|
||||
addedStatements.add(stmt);
|
||||
}
|
||||
|
||||
public void removeStatement(Statement stmt) {
|
||||
removedStatements.remove(stmt);
|
||||
}
|
||||
|
||||
public void deleteDataProperty(Statement stmt) {
|
||||
Resource subject = stmt.getSubject();
|
||||
if (subject.isURIResource()) {
|
||||
deletedDataPropertyUris.add(subject.getURI());
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteObjectProperty(Statement stmt) {
|
||||
Resource subject = stmt.getSubject();
|
||||
if (subject.isURIResource()) {
|
||||
deletedObjectPropertyUris.add(subject.getURI());
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// These methods are called when processing the changeSet. By then, it is
|
||||
// owned and accessed by a single thread.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
public boolean isEmpty() {
|
||||
return addedStatements.isEmpty() && removedStatements.isEmpty()
|
||||
&& deletedDataPropertyUris.isEmpty()
|
||||
&& deletedObjectPropertyUris.isEmpty();
|
||||
}
|
||||
|
||||
public List<Statement> getAddedStatements() {
|
||||
return addedStatements;
|
||||
}
|
||||
|
||||
public List<Statement> getRemovedStatements() {
|
||||
return removedStatements;
|
||||
}
|
||||
|
||||
public List<String> getDeletedDataPropertyUris() {
|
||||
return deletedDataPropertyUris;
|
||||
}
|
||||
|
||||
public List<String> getDeletedObjectPropertyUris() {
|
||||
return deletedObjectPropertyUris;
|
||||
}
|
||||
|
||||
}
|
|
@ -19,6 +19,10 @@ public interface TBoxReasonerDriver {
|
|||
|
||||
void deleteObjectProperty(Statement stmt);
|
||||
|
||||
boolean isReasoning();
|
||||
|
||||
Status getStatus();
|
||||
|
||||
public static class Status {
|
||||
public static final Status SUCCESS = new Status(true, false, "");
|
||||
public static final Status ERROR = new Status(true, true, "");
|
||||
|
@ -51,4 +55,5 @@ public interface TBoxReasonerDriver {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.tboxreasoner;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.hp.hpl.jena.ontology.DatatypeProperty;
|
||||
import com.hp.hpl.jena.ontology.ObjectProperty;
|
||||
import com.hp.hpl.jena.ontology.Restriction;
|
||||
import com.hp.hpl.jena.rdf.model.Statement;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasonerDriver.Status;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
public interface TBoxReasonerWrapper {
|
||||
|
||||
/**
|
||||
* Add the additions and remove the removals.
|
||||
*/
|
||||
void updateReasonerModel(TBoxChanges changes);
|
||||
|
||||
/**
|
||||
* Chew on it and create the inferences. Report status.
|
||||
*/
|
||||
Status performReasoning();
|
||||
|
||||
/**
|
||||
* List all of the ObjectProperties from the reasoner model, after updating
|
||||
* and reasoning.
|
||||
*/
|
||||
List<ObjectProperty> listObjectProperties();
|
||||
|
||||
/**
|
||||
* List all of the DatatypeProperties from the reasoner model, after
|
||||
* updating and reasoning.
|
||||
*/
|
||||
List<DatatypeProperty> listDatatypeProperties();
|
||||
|
||||
/**
|
||||
* List all of the statements that satisfy any of these patterns, after
|
||||
* updating and reasoning.
|
||||
*/
|
||||
List<Statement> filterResults(List<ReasonerStatementPattern> patternList);
|
||||
|
||||
/**
|
||||
* List all of the restrictions in the reasoner model, after updating and
|
||||
* reasoning.
|
||||
*/
|
||||
List<Restriction> listRestrictions();
|
||||
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.tboxreasoner.impl.pellet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.mindswap.pellet.exceptions.InconsistentOntologyException;
|
||||
import org.mindswap.pellet.jena.PelletInfGraph;
|
||||
|
||||
import com.hp.hpl.jena.ontology.DatatypeProperty;
|
||||
import com.hp.hpl.jena.ontology.ObjectProperty;
|
||||
import com.hp.hpl.jena.ontology.Restriction;
|
||||
import com.hp.hpl.jena.rdf.model.ModelFactory;
|
||||
import com.hp.hpl.jena.rdf.model.Statement;
|
||||
import com.hp.hpl.jena.vocabulary.OWL;
|
||||
import com.hp.hpl.jena.vocabulary.RDFS;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.ReasonerConfiguration;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.ReasonerStatementPattern;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxChanges;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasonerDriver.Status;
|
||||
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasonerWrapper;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockableOntModel;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockedOntModel;
|
||||
|
||||
/**
|
||||
* An implementation the TBoxReasonerWrapper for Pellet.
|
||||
*/
|
||||
public class PelletTBoxReasonerDriver implements TBoxReasonerWrapper {
|
||||
private static final Log log = LogFactory
|
||||
.getLog(PelletTBoxReasonerDriver.class);
|
||||
|
||||
private final LockableOntModel lockablePelletModel;
|
||||
|
||||
public PelletTBoxReasonerDriver(ReasonerConfiguration reasonerConfiguration) {
|
||||
this.lockablePelletModel = new LockableOntModel(
|
||||
ModelFactory.createOntologyModel(reasonerConfiguration
|
||||
.getOntModelSpec()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateReasonerModel(TBoxChanges changes) {
|
||||
try (LockedOntModel pelletModel = lockablePelletModel.write()) {
|
||||
pelletModel.remove(changes.getRemovedStatements());
|
||||
pelletModel.add(changes.getAddedStatements());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Status performReasoning() {
|
||||
try (LockedOntModel pelletModel = lockablePelletModel.write()) {
|
||||
try {
|
||||
pelletModel.rebind();
|
||||
pelletModel.prepare();
|
||||
return Status.SUCCESS;
|
||||
} catch (InconsistentOntologyException ioe) {
|
||||
String explanation = ((PelletInfGraph) pelletModel.getGraph())
|
||||
.getKB().getExplanation();
|
||||
log.error(ioe);
|
||||
log.error(explanation);
|
||||
return Status.inconsistent(explanation);
|
||||
} catch (Exception e) {
|
||||
log.error("Exception during inference", e);
|
||||
return Status.ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ObjectProperty> listObjectProperties() {
|
||||
try (LockedOntModel pelletModel = lockablePelletModel.read()) {
|
||||
return pelletModel.listObjectProperties().toList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DatatypeProperty> listDatatypeProperties() {
|
||||
try (LockedOntModel pelletModel = lockablePelletModel.read()) {
|
||||
return pelletModel.listDatatypeProperties().toList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Statement> filterResults(
|
||||
List<ReasonerStatementPattern> patternList) {
|
||||
List<Statement> filtered = new ArrayList<>();
|
||||
try (LockedOntModel pelletModel = lockablePelletModel.read()) {
|
||||
for (ReasonerStatementPattern pattern : patternList) {
|
||||
filtered.addAll(pattern.matchStatementsFromModel(pelletModel));
|
||||
}
|
||||
}
|
||||
for (Iterator<Statement> fit = filtered.iterator(); fit.hasNext(); ) {
|
||||
Statement stmt = fit.next();
|
||||
if (stmt.getObject().equals(RDFS.Resource)) {
|
||||
fit.remove();
|
||||
} else if (stmt.getSubject().equals(OWL.Nothing)) {
|
||||
fit.remove();
|
||||
} else if (stmt.getObject().equals(OWL.Nothing)) {
|
||||
fit.remove();
|
||||
}
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Restriction> listRestrictions() {
|
||||
try (LockedOntModel pelletModel = lockablePelletModel.read()) {
|
||||
return pelletModel.listRestrictions().toList();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue