Merge branch 'develop' into feature/fauxEditing
This commit is contained in:
commit
875ba66a46
36 changed files with 1709 additions and 1058 deletions
|
@ -35,7 +35,6 @@ log4j.rootLogger=INFO, AllAppender
|
||||||
|
|
||||||
# These classes are too chatty to display INFO messages.
|
# These classes are too chatty to display INFO messages.
|
||||||
log4j.logger.edu.cornell.mannlib.vitro.webapp.startup.StartupStatus=WARN
|
log4j.logger.edu.cornell.mannlib.vitro.webapp.startup.StartupStatus=WARN
|
||||||
log4j.logger.edu.cornell.mannlib.vitro.webapp.dao.jena.pellet.PelletListener=WARN
|
|
||||||
log4j.logger.edu.cornell.mannlib.vitro.webapp.servlet.setup.UpdateKnowledgeBase=DEBUG
|
log4j.logger.edu.cornell.mannlib.vitro.webapp.servlet.setup.UpdateKnowledgeBase=DEBUG
|
||||||
|
|
||||||
# Spring as a whole is too chatty to display INFO messages.
|
# Spring as a whole is too chatty to display INFO messages.
|
||||||
|
|
|
@ -16,6 +16,7 @@ import edu.cornell.mannlib.vitro.webapp.modules.ComponentStartupStatus;
|
||||||
import edu.cornell.mannlib.vitro.webapp.modules.fileStorage.FileStorage;
|
import edu.cornell.mannlib.vitro.webapp.modules.fileStorage.FileStorage;
|
||||||
import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor;
|
import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor;
|
||||||
import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngine;
|
import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngine;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner.TBoxReasonerModule;
|
||||||
import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.ConfigurationTripleSource;
|
import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.ConfigurationTripleSource;
|
||||||
import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.ContentTripleSource;
|
import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.ContentTripleSource;
|
||||||
import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.RDFServiceUtils;
|
import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.RDFServiceUtils;
|
||||||
|
@ -41,6 +42,7 @@ public class ApplicationImpl implements Application {
|
||||||
private FileStorage fileStorage;
|
private FileStorage fileStorage;
|
||||||
private ContentTripleSource contentTripleSource;
|
private ContentTripleSource contentTripleSource;
|
||||||
private ConfigurationTripleSource configurationTripleSource;
|
private ConfigurationTripleSource configurationTripleSource;
|
||||||
|
private TBoxReasonerModule tboxReasonerModule;
|
||||||
|
|
||||||
public void setServletContext(ServletContext ctx) {
|
public void setServletContext(ServletContext ctx) {
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
|
@ -140,6 +142,22 @@ public class ApplicationImpl implements Application {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TBoxReasonerModule getTBoxReasonerModule() {
|
||||||
|
return tboxReasonerModule;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Property(uri = "http://vitro.mannlib.cornell.edu/ns/vitro/ApplicationSetup#hasTBoxReasonerModule")
|
||||||
|
public void setTBoxReasonerModule(TBoxReasonerModule module) {
|
||||||
|
if (tboxReasonerModule == null) {
|
||||||
|
tboxReasonerModule = module;
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Configuration includes multiple intances of TBoxReasonerModule: "
|
||||||
|
+ tboxReasonerModule + ", and " + module);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Validation
|
@Validation
|
||||||
public void validate() throws Exception {
|
public void validate() throws Exception {
|
||||||
if (searchEngine == null) {
|
if (searchEngine == null) {
|
||||||
|
@ -162,6 +180,10 @@ public class ApplicationImpl implements Application {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"Configuration did not include a ConfigurationTripleSource.");
|
"Configuration did not include a ConfigurationTripleSource.");
|
||||||
}
|
}
|
||||||
|
if (tboxReasonerModule == null) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Configuration did not include a TBoxReasonerModule.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -244,4 +266,30 @@ public class ApplicationImpl implements Application {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Setup the reasoners.
|
||||||
|
//
|
||||||
|
// This must happen after the FileGraphSetup.
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
public static class ReasonersSetup implements ServletContextListener {
|
||||||
|
@Override
|
||||||
|
public void contextInitialized(ServletContextEvent sce) {
|
||||||
|
ServletContext ctx = sce.getServletContext();
|
||||||
|
Application app = ApplicationUtils.instance();
|
||||||
|
StartupStatus ss = StartupStatus.getBean(ctx);
|
||||||
|
ComponentStartupStatus css = new ComponentStartupStatusImpl(this,
|
||||||
|
ss);
|
||||||
|
|
||||||
|
TBoxReasonerModule tboxReasoner = app.getTBoxReasonerModule();
|
||||||
|
tboxReasoner.startup(app, css);
|
||||||
|
ss.info(this, "Started the TBoxReasonerModule: " + tboxReasoner);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contextDestroyed(ServletContextEvent sce) {
|
||||||
|
Application app = ApplicationUtils.instance();
|
||||||
|
app.getTBoxReasonerModule().shutdown(app);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vedit.beans.Option;
|
import edu.cornell.mannlib.vedit.beans.Option;
|
||||||
import edu.cornell.mannlib.vedit.util.FormUtils;
|
import edu.cornell.mannlib.vedit.util.FormUtils;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.application.ApplicationUtils;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
|
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper;
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.AuthorizationRequest;
|
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.AuthorizationRequest;
|
||||||
|
@ -24,7 +25,7 @@ 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.ResponseValues;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
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.WebappDaoFactory;
|
||||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.pellet.PelletListener;
|
import edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner.TBoxReasonerStatus;
|
||||||
import edu.cornell.mannlib.vitro.webapp.search.controller.IndexController;
|
import edu.cornell.mannlib.vitro.webapp.search.controller.IndexController;
|
||||||
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
|
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
|
||||||
|
|
||||||
|
@ -159,26 +160,23 @@ public class BaseSiteAdminController extends FreemarkerHttpServlet {
|
||||||
|
|
||||||
if (PolicyHelper.isAuthorizedForActions(vreq, SimplePermission.EDIT_ONTOLOGY.ACTION)) {
|
if (PolicyHelper.isAuthorizedForActions(vreq, SimplePermission.EDIT_ONTOLOGY.ACTION)) {
|
||||||
|
|
||||||
String pelletError = null;
|
String error = null;
|
||||||
String pelletExplanation = null;
|
String explanation = null;
|
||||||
Object plObj = getServletContext().getAttribute("pelletListener");
|
TBoxReasonerStatus status = ApplicationUtils.instance().getTBoxReasonerModule().getStatus();
|
||||||
if ( (plObj != null) && (plObj instanceof PelletListener) ) {
|
if (!status.isConsistent()) {
|
||||||
PelletListener pelletListener = (PelletListener) plObj;
|
error = "INCONSISTENT ONTOLOGY: reasoning halted.";
|
||||||
if (!pelletListener.isConsistent()) {
|
explanation = status.getExplanation();
|
||||||
pelletError = "INCONSISTENT ONTOLOGY: reasoning halted.";
|
} else if ( status.isInErrorState() ) {
|
||||||
pelletExplanation = pelletListener.getExplanation();
|
error = "An error occurred during reasoning. Reasoning has been halted. See error log for details.";
|
||||||
} else if ( pelletListener.isInErrorState() ) {
|
|
||||||
pelletError = "An error occurred during reasoning. Reasoning has been halted. See error log for details.";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pelletError != null) {
|
if (error != null) {
|
||||||
Map<String, String> pellet = new HashMap<String, String>();
|
Map<String, String> tboxReasonerStatus = new HashMap<String, String>();
|
||||||
pellet.put("error", pelletError);
|
tboxReasonerStatus.put("error", error);
|
||||||
if (pelletExplanation != null) {
|
if (explanation != null) {
|
||||||
pellet.put("explanation", pelletExplanation);
|
tboxReasonerStatus.put("explanation", explanation);
|
||||||
}
|
}
|
||||||
map.put("pellet", pellet);
|
map.put("tboxReasonerStatus", tboxReasonerStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> urls = new HashMap<String, String>();
|
Map<String, String> urls = new HashMap<String, String>();
|
||||||
|
|
|
@ -44,10 +44,12 @@ import com.hp.hpl.jena.vocabulary.RDF;
|
||||||
import com.hp.hpl.jena.vocabulary.RDFS;
|
import com.hp.hpl.jena.vocabulary.RDFS;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vedit.controller.BaseEditController;
|
import edu.cornell.mannlib.vedit.controller.BaseEditController;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.application.ApplicationUtils;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
|
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||||
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
|
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner.TBoxReasonerModule;
|
||||||
|
|
||||||
public class JenaAdminActions extends BaseEditController {
|
public class JenaAdminActions extends BaseEditController {
|
||||||
|
|
||||||
|
@ -190,9 +192,8 @@ public class JenaAdminActions extends BaseEditController {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void printRestrictions() {
|
private void printRestrictions() {
|
||||||
OntModel memoryModel = (OntModel) getServletContext().getAttribute("pelletOntModel");
|
TBoxReasonerModule reasoner = ApplicationUtils.instance().getTBoxReasonerModule();
|
||||||
for (Restriction rest : memoryModel.listRestrictions().toList() ) {
|
for (Restriction rest : reasoner.listRestrictions() ) {
|
||||||
//System.out.println();
|
|
||||||
if (rest.isAllValuesFromRestriction()) {
|
if (rest.isAllValuesFromRestriction()) {
|
||||||
log.trace("All values from: ");
|
log.trace("All values from: ");
|
||||||
AllValuesFromRestriction avfr = rest.asAllValuesFromRestriction();
|
AllValuesFromRestriction avfr = rest.asAllValuesFromRestriction();
|
||||||
|
|
|
@ -41,6 +41,7 @@ import com.hp.hpl.jena.vocabulary.OWL;
|
||||||
import com.hp.hpl.jena.vocabulary.RDF;
|
import com.hp.hpl.jena.vocabulary.RDF;
|
||||||
import com.hp.hpl.jena.vocabulary.RDFS;
|
import com.hp.hpl.jena.vocabulary.RDFS;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.application.ApplicationUtils;
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean;
|
import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean;
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.DataProperty;
|
import edu.cornell.mannlib.vitro.webapp.beans.DataProperty;
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement;
|
import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement;
|
||||||
|
@ -51,7 +52,7 @@ import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyDao;
|
||||||
import edu.cornell.mannlib.vitro.webapp.dao.InsertException;
|
import edu.cornell.mannlib.vitro.webapp.dao.InsertException;
|
||||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
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.event.EditEvent;
|
||||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.pellet.PelletListener;
|
import edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner.TBoxReasonerStatus;
|
||||||
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
|
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
|
||||||
|
|
||||||
public class DataPropertyDaoJena extends PropertyDaoJena implements
|
public class DataPropertyDaoJena extends PropertyDaoJena implements
|
||||||
|
@ -357,10 +358,8 @@ public class DataPropertyDaoJena extends PropertyDaoJena implements
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean reasoningAvailable() {
|
protected boolean reasoningAvailable() {
|
||||||
PelletListener pl = getWebappDaoFactory().getPelletListener();
|
TBoxReasonerStatus status = ApplicationUtils.instance().getTBoxReasonerModule().getStatus();
|
||||||
return !(
|
return status.isConsistent() && !status.isInErrorState();
|
||||||
( pl == null || !pl.isConsistent() || pl.isInErrorState() )
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getRequiredDatatypeURI(Individual individual, DataProperty dataprop, List<String> vclassURIs) {
|
private String getRequiredDatatypeURI(Individual individual, DataProperty dataprop, List<String> vclassURIs) {
|
||||||
|
|
|
@ -18,7 +18,6 @@ import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.apache.jena.iri.IRI;
|
import org.apache.jena.iri.IRI;
|
||||||
import org.apache.jena.iri.IRIFactory;
|
import org.apache.jena.iri.IRIFactory;
|
||||||
import org.mindswap.pellet.jena.vocabulary.SWRL;
|
|
||||||
|
|
||||||
import com.hp.hpl.jena.datatypes.xsd.XSDDatatype;
|
import com.hp.hpl.jena.datatypes.xsd.XSDDatatype;
|
||||||
import com.hp.hpl.jena.graph.Node;
|
import com.hp.hpl.jena.graph.Node;
|
||||||
|
@ -56,6 +55,8 @@ public class JenaBaseDao extends JenaBaseDaoCon {
|
||||||
public static final boolean KEEP_ONLY_IF_TRUE = true; //used for updatePropertyBooleanValue()
|
public static final boolean KEEP_ONLY_IF_TRUE = true; //used for updatePropertyBooleanValue()
|
||||||
public static final boolean KEEP_ONLY_IF_FALSE = false; //used for updatePropertyBooleanValue()
|
public static final boolean KEEP_ONLY_IF_FALSE = false; //used for updatePropertyBooleanValue()
|
||||||
|
|
||||||
|
private static final String SWRL_IMP = "http://www.w3.org/2003/11/swrl#Imp";
|
||||||
|
|
||||||
protected static final Log log = LogFactory.getLog(JenaBaseDao.class.getName());
|
protected static final Log log = LogFactory.getLog(JenaBaseDao.class.getName());
|
||||||
|
|
||||||
/* ******************* static constants ****************** */
|
/* ******************* static constants ****************** */
|
||||||
|
@ -1105,7 +1106,7 @@ public class JenaBaseDao extends JenaBaseDaoCon {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeRulesMentioningResource(Resource res, OntModel ontModel) {
|
public void removeRulesMentioningResource(Resource res, OntModel ontModel) {
|
||||||
Iterator<Resource> impIt = ontModel.listSubjectsWithProperty(RDF.type, SWRL.Imp);
|
Iterator<Resource> impIt = ontModel.listSubjectsWithProperty(RDF.type, SWRL_IMP);
|
||||||
while (impIt.hasNext()) {
|
while (impIt.hasNext()) {
|
||||||
Resource imp = impIt.next();
|
Resource imp = impIt.next();
|
||||||
boolean removeMe = false;
|
boolean removeMe = false;
|
||||||
|
|
|
@ -564,26 +564,36 @@ public class PropertyDaoJena extends JenaBaseDao implements PropertyDao {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Removed: see VIVO-766.
|
||||||
* sorts VClasses so that subclasses come before superclasses
|
* sorts VClasses so that subclasses come before superclasses
|
||||||
|
*
|
||||||
|
* Because subclass/superclass is only a partial ordering, this breaks the
|
||||||
|
* contract for Comparator, and throws an IllegalArgumentException under Java 8.
|
||||||
|
* In particular, for classes sub, super and other, we have sub=other, sub<super,
|
||||||
|
* which should imply other<super, but that is not true.
|
||||||
|
*
|
||||||
|
* As far as I can determine, this sort is never relied on anyway, so there
|
||||||
|
* should be no impact in removing it. Note that PropertyInstanceDaoJena re-sorts
|
||||||
|
* thes results before using them, so this sort was irrelevant for any calls
|
||||||
|
* through that path.
|
||||||
*/
|
*/
|
||||||
private class VClassHierarchyRanker implements Comparator<VClass> {
|
// private class VClassHierarchyRanker implements Comparator<VClass> {
|
||||||
private VClassDao vcDao;
|
// private VClassDao vcDao;
|
||||||
public VClassHierarchyRanker(VClassDao vcDao) {
|
// public VClassHierarchyRanker(VClassDao vcDao) {
|
||||||
this.vcDao = vcDao;
|
// this.vcDao = vcDao;
|
||||||
}
|
// }
|
||||||
@Override
|
// @Override
|
||||||
public int compare(VClass vc1, VClass vc2) {
|
// public int compare(VClass vc1, VClass vc2) {
|
||||||
if (vcDao.isSubClassOf(vc1, vc2)) {
|
// if (vcDao.isSubClassOf(vc1, vc2)) {
|
||||||
return -1;
|
// return -1;
|
||||||
} else if (vcDao.isSubClassOf(vc2, vc1)) {
|
// } else if (vcDao.isSubClassOf(vc2, vc1)) {
|
||||||
return 1;
|
// return 1;
|
||||||
} else {
|
// } else {
|
||||||
return 0;
|
// return 0;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
|
||||||
public List<PropertyInstance> getAllPropInstByVClass(String classURI) {
|
public List<PropertyInstance> getAllPropInstByVClass(String classURI) {
|
||||||
if (classURI==null || classURI.length()<1) {
|
if (classURI==null || classURI.length()<1) {
|
||||||
|
@ -708,7 +718,8 @@ public class PropertyDaoJena extends JenaBaseDao implements PropertyDao {
|
||||||
return propInsts;
|
return propInsts;
|
||||||
}
|
}
|
||||||
|
|
||||||
Collections.sort(vclasses, new VClassHierarchyRanker(this.getWebappDaoFactory().getVClassDao()));
|
// Removed: see VIVO-766.
|
||||||
|
// Collections.sort(vclasses, new VClassHierarchyRanker(this.getWebappDaoFactory().getVClassDao()));
|
||||||
|
|
||||||
OntModel ontModel = getOntModelSelector().getTBoxModel();
|
OntModel ontModel = getOntModelSelector().getTBoxModel();
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,6 @@ import edu.cornell.mannlib.vitro.webapp.dao.VClassGroupDao;
|
||||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
||||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactoryConfig;
|
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.modelaccess.ModelNames;
|
||||||
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
|
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.rdfservice.impl.jena.model.RDFServiceModel;
|
||||||
|
@ -71,8 +70,6 @@ public class WebappDaoFactoryJena implements WebappDaoFactory {
|
||||||
|
|
||||||
protected WebappDaoFactoryConfig config;
|
protected WebappDaoFactoryConfig config;
|
||||||
|
|
||||||
protected PelletListener pelletListener;
|
|
||||||
|
|
||||||
protected String userURI;
|
protected String userURI;
|
||||||
|
|
||||||
private Map<String,String> properties = new HashMap<String,String>();
|
private Map<String,String> properties = new HashMap<String,String>();
|
||||||
|
@ -239,18 +236,6 @@ public class WebappDaoFactoryJena implements WebappDaoFactory {
|
||||||
return config.getNonUserNamespaces();
|
return config.getNonUserNamespaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 PelletListener getPelletListener() {
|
|
||||||
return this.pelletListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getCommentsForResource(String resourceURI) {
|
public List<String> getCommentsForResource(String resourceURI) {
|
||||||
List<String> commentList = new LinkedList<String>();
|
List<String> commentList = new LinkedList<String>();
|
||||||
|
|
|
@ -1,52 +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 com.hp.hpl.jena.rdf.model.Property;
|
|
||||||
import com.hp.hpl.jena.rdf.model.Resource;
|
|
||||||
|
|
||||||
public class ObjectPropertyStatementPattern {
|
|
||||||
|
|
||||||
private Resource subject = null;
|
|
||||||
private Property predicate = null;
|
|
||||||
private Resource object = null;
|
|
||||||
|
|
||||||
public ObjectPropertyStatementPattern(Resource subject, Property predicate, Resource object) {
|
|
||||||
this.subject = subject;
|
|
||||||
this.predicate = predicate;
|
|
||||||
this.object = object;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Resource getSubject() {
|
|
||||||
return this.subject;
|
|
||||||
}
|
|
||||||
public Property getPredicate() {
|
|
||||||
return this.predicate;
|
|
||||||
}
|
|
||||||
public Resource getObject() {
|
|
||||||
return this.object;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean matches(ObjectPropertyStatementPattern p2) {
|
|
||||||
boolean sMatch = false;
|
|
||||||
boolean pMatch = false;
|
|
||||||
boolean oMatch = false;
|
|
||||||
if (this.getSubject() == null || p2.getSubject()==null) {
|
|
||||||
sMatch = true; // (this.getSubject() == null && p2.getSubject() == null);
|
|
||||||
} else {
|
|
||||||
sMatch = (this.getSubject().equals(p2.getSubject()));
|
|
||||||
}
|
|
||||||
if (this.getPredicate() == null || p2.getPredicate()==null) {
|
|
||||||
pMatch = true; // (this.getPredicate() == null && p2.getPredicate() == null);
|
|
||||||
} else {
|
|
||||||
pMatch = (this.getPredicate().equals(p2.getPredicate()));
|
|
||||||
}
|
|
||||||
if (this.getObject() == null || p2.getObject()==null) {
|
|
||||||
oMatch = true ; // (this.getObject() == null && p2.getObject() == null);
|
|
||||||
} else {
|
|
||||||
oMatch = (this.getObject().equals(p2.getObject()));
|
|
||||||
}
|
|
||||||
return (sMatch && pMatch && oMatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,26 +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 com.hp.hpl.jena.rdf.model.Property;
|
|
||||||
import com.hp.hpl.jena.rdf.model.Resource;
|
|
||||||
|
|
||||||
public class ObjectPropertyStatementPatternFactory {
|
|
||||||
|
|
||||||
//private static Set<ObjectPropertyStatementPattern> patternSet = new HashSet<ObjectPropertyStatementPattern>();
|
|
||||||
|
|
||||||
public static ObjectPropertyStatementPattern getPattern(Resource subject, Property predicate, Resource object) {
|
|
||||||
//for (Iterator<ObjectPropertyStatementPattern> i = patternSet.iterator(); i.hasNext(); ) {
|
|
||||||
// ObjectPropertyStatementPattern pat = i.next();
|
|
||||||
// if ( ( (pat.getSubject()==null && subject==null) || (pat.getSubject().equals(subject)) )
|
|
||||||
// && ( (pat.getPredicate()==null && predicate==null) || (pat.getPredicate().equals(predicate)) )
|
|
||||||
// && ( (pat.getObject()==null && object==null) || (pat.getObject().equals(object)) ) ) {
|
|
||||||
// return pat;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
ObjectPropertyStatementPattern newPat = new ObjectPropertyStatementPattern(subject,predicate,object);
|
|
||||||
//patternSet.add(newPat);
|
|
||||||
return newPat;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,732 +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.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Queue;
|
|
||||||
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 org.mindswap.pellet.jena.PelletReasonerFactory;
|
|
||||||
|
|
||||||
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.Literal;
|
|
||||||
import com.hp.hpl.jena.rdf.model.Model;
|
|
||||||
import com.hp.hpl.jena.rdf.model.ModelChangedListener;
|
|
||||||
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.shared.Lock;
|
|
||||||
import com.hp.hpl.jena.util.iterator.ClosableIterator;
|
|
||||||
import com.hp.hpl.jena.vocabulary.OWL;
|
|
||||||
import com.hp.hpl.jena.vocabulary.RDF;
|
|
||||||
import com.hp.hpl.jena.vocabulary.RDFS;
|
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent;
|
|
||||||
|
|
||||||
public class PelletListener implements ModelChangedListener {
|
|
||||||
|
|
||||||
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<ObjectPropertyStatementPattern> inferenceDrivingPatternAllowSet;
|
|
||||||
private Set<ObjectPropertyStatementPattern> inferenceDrivingPatternDenySet;
|
|
||||||
private Set<ObjectPropertyStatementPattern> inferenceReceivingPatternAllowSet;
|
|
||||||
|
|
||||||
private Map<Property,List<ObjectPropertyStatementPattern>> inferenceDrivingPatternMap;
|
|
||||||
|
|
||||||
private Model additionModel;
|
|
||||||
private Model removalModel;
|
|
||||||
|
|
||||||
private Model deletedObjectProperties;
|
|
||||||
private Model deletedDataProperties;
|
|
||||||
|
|
||||||
private boolean pipeOpen;
|
|
||||||
|
|
||||||
private boolean isConsistent = true;
|
|
||||||
private boolean inErrorState = false;
|
|
||||||
private String explanation = "";
|
|
||||||
|
|
||||||
public boolean isConsistent() {
|
|
||||||
return this.isConsistent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getExplanation() {
|
|
||||||
return this.explanation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isInErrorState() {
|
|
||||||
return this.inErrorState;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isReasoning() {
|
|
||||||
return this.isReasoning;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void closePipe() {
|
|
||||||
pipeOpen = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void openPipe() {
|
|
||||||
pipeOpen = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 int inferenceRounds = 0;
|
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
if (this.inferenceDrivingPatternAllowSet != null) {
|
|
||||||
this.inferenceDrivingPatternMap = new HashMap<Property,List<ObjectPropertyStatementPattern>>();
|
|
||||||
for (Iterator<ObjectPropertyStatementPattern> i = inferenceDrivingPatternAllowSet.iterator(); i.hasNext();) {
|
|
||||||
ObjectPropertyStatementPattern pat = i.next();
|
|
||||||
Property p = pat.getPredicate();
|
|
||||||
List<ObjectPropertyStatementPattern> patList = inferenceDrivingPatternMap.get(p);
|
|
||||||
if (patList == null) {
|
|
||||||
patList = new LinkedList<ObjectPropertyStatementPattern>();
|
|
||||||
patList.add(pat);
|
|
||||||
inferenceDrivingPatternMap.put(p, patList);
|
|
||||||
} else {
|
|
||||||
patList.add(pat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.pipeOpen = true;
|
|
||||||
this.additionModel = ModelFactory.createDefaultModel();
|
|
||||||
this.removalModel = ModelFactory.createDefaultModel();
|
|
||||||
this.deletedObjectProperties = ModelFactory.createDefaultModel();
|
|
||||||
this.deletedDataProperties = ModelFactory.createDefaultModel();
|
|
||||||
this.mainModel.enterCriticalSection(Lock.READ);
|
|
||||||
try {
|
|
||||||
for (ObjectPropertyStatementPattern pat : this.inferenceDrivingPatternAllowSet) {
|
|
||||||
addedStatements(mainModel.listStatements((Resource) null, pat.getPredicate(), (RDFNode) null));
|
|
||||||
}
|
|
||||||
if (!skipReasoningUponInitialization) {
|
|
||||||
this.foreground = foreground;
|
|
||||||
notifyEvent(null,new EditEvent(null,false));
|
|
||||||
} else if (inferenceModel.size() == 0){
|
|
||||||
foreground = true;
|
|
||||||
notifyEvent(null,new EditEvent(null,false));
|
|
||||||
this.foreground = foreground;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
this.mainModel.leaveCriticalSection();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.fullModel.getBaseModel().register(this);
|
|
||||||
this.mainModel.getBaseModel().register(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class InferenceGetter implements Runnable {
|
|
||||||
|
|
||||||
private PelletListener pelletListener;
|
|
||||||
|
|
||||||
public InferenceGetter(PelletListener pelletListener) {
|
|
||||||
this.pelletListener = pelletListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
while (pelletListener.isDirty()) {
|
|
||||||
//pipeOpen = false;
|
|
||||||
try {
|
|
||||||
pelletListener.setDirty(false);
|
|
||||||
inferenceRounds++;
|
|
||||||
log.info("Getting new inferences");
|
|
||||||
long startTime = System.currentTimeMillis();
|
|
||||||
LinkedList<ObjectPropertyStatementPattern> irpl = new LinkedList<ObjectPropertyStatementPattern>();
|
|
||||||
|
|
||||||
if (inferenceReceivingPatternAllowSet != null) {
|
|
||||||
irpl.addAll(inferenceReceivingPatternAllowSet);
|
|
||||||
} else {
|
|
||||||
irpl.add(ObjectPropertyStatementPatternFactory.getPattern(null,null,null));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reasonerConfiguration.getQueryForAllObjectProperties()) {
|
|
||||||
pelletModel.enterCriticalSection(Lock.READ);
|
|
||||||
try {
|
|
||||||
ClosableIterator closeIt = pelletModel.listObjectProperties();
|
|
||||||
try {
|
|
||||||
for (Iterator objPropIt = closeIt; objPropIt.hasNext();) {
|
|
||||||
ObjectProperty objProp = (ObjectProperty) objPropIt.next();
|
|
||||||
if ( !("http://www.w3.org/2002/07/owl#".equals(objProp.getNameSpace())) ) {
|
|
||||||
irpl.add(ObjectPropertyStatementPatternFactory.getPattern(null,objProp,null));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
closeIt.close();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
pelletModel.leaveCriticalSection();
|
|
||||||
}
|
|
||||||
deletedObjectProperties.enterCriticalSection(Lock.WRITE);
|
|
||||||
try {
|
|
||||||
ClosableIterator sit = deletedObjectProperties.listSubjects();
|
|
||||||
try {
|
|
||||||
while (sit.hasNext()) {
|
|
||||||
Resource subj = (Resource) sit.next();
|
|
||||||
irpl.add(ObjectPropertyStatementPatternFactory.getPattern(null,ResourceFactory.createProperty(subj.getURI()),null));
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
sit.close();
|
|
||||||
}
|
|
||||||
deletedObjectProperties.removeAll();
|
|
||||||
} finally {
|
|
||||||
deletedObjectProperties.leaveCriticalSection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reasonerConfiguration.getQueryForAllDatatypeProperties()) {
|
|
||||||
pelletModel.enterCriticalSection(Lock.READ);
|
|
||||||
try {
|
|
||||||
ClosableIterator closeIt = pelletModel.listDatatypeProperties();
|
|
||||||
try {
|
|
||||||
for (Iterator dataPropIt = closeIt; dataPropIt.hasNext();) {
|
|
||||||
DatatypeProperty dataProp = (DatatypeProperty) dataPropIt.next();
|
|
||||||
if ( !("http://www.w3.org/2002/07/owl#".equals(dataProp.getNameSpace())) ) {
|
|
||||||
// TODO: THIS WILL WORK, BUT NEED TO GENERALIZE THE PATTERN CLASSES
|
|
||||||
irpl.add(ObjectPropertyStatementPatternFactory.getPattern(null,dataProp,null));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
closeIt.close();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
pelletModel.leaveCriticalSection();
|
|
||||||
}
|
|
||||||
deletedDataProperties.enterCriticalSection(Lock.WRITE);
|
|
||||||
try {
|
|
||||||
ClosableIterator sit = deletedDataProperties.listSubjects();
|
|
||||||
try {
|
|
||||||
while (sit.hasNext()) {
|
|
||||||
Resource subj = (Resource) sit.next();
|
|
||||||
irpl.add(ObjectPropertyStatementPatternFactory.getPattern(null,ResourceFactory.createProperty(subj.getURI()),null));
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
sit.close();
|
|
||||||
}
|
|
||||||
deletedDataProperties.removeAll();
|
|
||||||
} finally {
|
|
||||||
deletedDataProperties.leaveCriticalSection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int addCount = 0;
|
|
||||||
int retractCount = 0;
|
|
||||||
|
|
||||||
// force new reasoner (disabled)
|
|
||||||
if (false && !reasonerConfiguration.isIncrementalReasoningEnabled()) {
|
|
||||||
Model baseModel = pelletModel.getBaseModel();
|
|
||||||
pelletModel = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC);
|
|
||||||
pelletModel.getDocumentManager().setProcessImports(false);
|
|
||||||
pelletModel.add(baseModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
pelletModel.enterCriticalSection(Lock.WRITE);
|
|
||||||
try {
|
|
||||||
pelletModel.rebind();
|
|
||||||
pelletModel.prepare();
|
|
||||||
} finally {
|
|
||||||
pelletModel.leaveCriticalSection();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Iterator<ObjectPropertyStatementPattern> patIt = irpl.iterator(); patIt.hasNext(); ) {
|
|
||||||
ObjectPropertyStatementPattern pat = patIt.next();
|
|
||||||
|
|
||||||
if (log.isDebugEnabled()) {
|
|
||||||
String subjStr = (pat.getSubject() != null) ? pat.getSubject().getURI() : "*";
|
|
||||||
String predStr = (pat.getPredicate() != null) ? pat.getPredicate().getURI() : "*";
|
|
||||||
String objStr = (pat.getObject() != null) ? pat.getObject().getURI() : "*";
|
|
||||||
log.debug("Querying for "+subjStr+" : "+predStr+" : "+objStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Model tempModel = ModelFactory.createDefaultModel();
|
|
||||||
|
|
||||||
pelletModel.enterCriticalSection(Lock.READ);
|
|
||||||
try {
|
|
||||||
|
|
||||||
ClosableIterator ci = pelletModel.listStatements(pat.getSubject(),pat.getPredicate(),pat.getObject());
|
|
||||||
try {
|
|
||||||
for (ClosableIterator i=ci; i.hasNext();) {
|
|
||||||
Statement stmt = (Statement) i.next();
|
|
||||||
|
|
||||||
boolean reject = false;
|
|
||||||
|
|
||||||
// this next part is only needed if we're using Jena's OWL reasoner instead of actually using Pellet
|
|
||||||
try {
|
|
||||||
if ( ( ((Resource)stmt.getObject()).equals(RDFS.Resource) ) ) {
|
|
||||||
reject = true;
|
|
||||||
} else if ( ( stmt.getSubject().equals(OWL.Nothing) ) ) {
|
|
||||||
reject = true;
|
|
||||||
} else if ( ( stmt.getObject().equals(OWL.Nothing) ) ) {
|
|
||||||
reject = true;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {}
|
|
||||||
|
|
||||||
if (!reject) {
|
|
||||||
tempModel.add(stmt);
|
|
||||||
|
|
||||||
boolean fullModelContainsStatement = false;
|
|
||||||
fullModel.enterCriticalSection(Lock.READ);
|
|
||||||
try {
|
|
||||||
fullModelContainsStatement = fullModel.contains(stmt);
|
|
||||||
} finally {
|
|
||||||
fullModel.leaveCriticalSection();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fullModelContainsStatement) {
|
|
||||||
// in theory we should be able to lock only the inference model, but I'm not sure yet if Jena propagates the locking upward
|
|
||||||
fullModel.enterCriticalSection(Lock.WRITE);
|
|
||||||
closePipe();
|
|
||||||
try {
|
|
||||||
inferenceModel.add(stmt);
|
|
||||||
addCount++;
|
|
||||||
} finally {
|
|
||||||
openPipe();
|
|
||||||
fullModel.leaveCriticalSection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
ci.close();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
pelletModel.leaveCriticalSection();
|
|
||||||
}
|
|
||||||
|
|
||||||
// now we see what's in the inference model that isn't in the temp model and remove it
|
|
||||||
|
|
||||||
try {
|
|
||||||
Queue<Statement> localRemovalQueue = new LinkedList<Statement>();
|
|
||||||
inferenceModel.enterCriticalSection(Lock.READ);
|
|
||||||
try {
|
|
||||||
ClosableIterator ci = inferenceModel.listStatements(pat.getSubject(),pat.getPredicate(),pat.getObject());
|
|
||||||
try {
|
|
||||||
for (ClosableIterator i=ci; i.hasNext();) {
|
|
||||||
Statement stmt = (Statement) i.next();
|
|
||||||
if (!tempModel.contains(stmt)) {
|
|
||||||
localRemovalQueue.add(stmt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
ci.close();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
inferenceModel.leaveCriticalSection();
|
|
||||||
}
|
|
||||||
for (Iterator<Statement> i = localRemovalQueue.iterator(); i.hasNext(); ) {
|
|
||||||
fullModel.enterCriticalSection(Lock.WRITE);
|
|
||||||
closePipe();
|
|
||||||
try {
|
|
||||||
retractCount++;
|
|
||||||
inferenceModel.remove(i.next());
|
|
||||||
} finally {
|
|
||||||
openPipe();
|
|
||||||
fullModel.leaveCriticalSection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
localRemovalQueue.clear();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Error getting inferences", e);
|
|
||||||
}
|
|
||||||
tempModel = null;
|
|
||||||
}
|
|
||||||
this.pelletListener.isConsistent = true;
|
|
||||||
this.pelletListener.inErrorState = false;
|
|
||||||
this.pelletListener.explanation = "";
|
|
||||||
if (log.isDebugEnabled()) {
|
|
||||||
log.info("Added "+addCount+" statements entailed by assertions");
|
|
||||||
log.info("Retracted "+retractCount+" statements no longer entailed by assertions");
|
|
||||||
log.info("Done getting new inferences: "+(System.currentTimeMillis()-startTime)/1000+" seconds");
|
|
||||||
}
|
|
||||||
} catch (InconsistentOntologyException ioe) {
|
|
||||||
this.pelletListener.isConsistent = false;
|
|
||||||
String explanation = ((PelletInfGraph)pelletModel.getGraph()).getKB().getExplanation();
|
|
||||||
this.pelletListener.explanation = explanation;
|
|
||||||
log.error(ioe);
|
|
||||||
log.error(explanation);
|
|
||||||
} catch (Exception e) {
|
|
||||||
this.pelletListener.inErrorState = true;
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: These next two methods are really ugly; I need to refactor them to remove redundancy.
|
|
||||||
|
|
||||||
private void tryAdd(Statement stmt) {
|
|
||||||
boolean sendToPellet = false;
|
|
||||||
if ( pipeOpen && reasonerConfiguration.getReasonOnAllDatatypePropertyStatements() && stmt.getObject().isLiteral() ) {
|
|
||||||
sendToPellet = true;
|
|
||||||
} else
|
|
||||||
if ( pipeOpen && hasCardinalityPredicate(stmt) ) { // see comment on this method
|
|
||||||
sendToPellet = true;
|
|
||||||
} else
|
|
||||||
if ( (stmt.getObject().isResource()) && !((stmt.getPredicate().getURI().indexOf(VitroVocabulary.vitroURI)==0)) ) {
|
|
||||||
if (pipeOpen) {
|
|
||||||
sendToPellet = false;
|
|
||||||
boolean denied = false;
|
|
||||||
ObjectPropertyStatementPattern stPat = ObjectPropertyStatementPatternFactory.getPattern(stmt.getSubject(), stmt.getPredicate(), (Resource) stmt.getObject());
|
|
||||||
if (inferenceDrivingPatternDenySet != null) {
|
|
||||||
for (Iterator<ObjectPropertyStatementPattern> i = inferenceDrivingPatternDenySet.iterator(); i.hasNext(); ){
|
|
||||||
ObjectPropertyStatementPattern pat = i.next();
|
|
||||||
if (pat.matches(stPat)) {
|
|
||||||
denied = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!denied) {
|
|
||||||
if (inferenceDrivingPatternAllowSet==null) {
|
|
||||||
sendToPellet = true;
|
|
||||||
} else {
|
|
||||||
// TODO: O(1) implementation of this
|
|
||||||
List<ObjectPropertyStatementPattern> patList = this.inferenceDrivingPatternMap.get(stmt.getPredicate());
|
|
||||||
if (patList != null) {
|
|
||||||
for (Iterator<ObjectPropertyStatementPattern> i = patList.iterator(); i.hasNext(); ){
|
|
||||||
ObjectPropertyStatementPattern pat = i.next();
|
|
||||||
if (pat.matches(stPat)) {
|
|
||||||
sendToPellet = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sendToPellet) {
|
|
||||||
//long startTime = System.currentTimeMillis();
|
|
||||||
String valueStr = (stmt.getObject().isResource()) ? ((Resource)stmt.getObject()).getLocalName() : ((Literal)stmt.getObject()).getLexicalForm();
|
|
||||||
if ( log.isDebugEnabled() ) {
|
|
||||||
log.debug( "Adding to Pellet: " + renderStatement( stmt ) );
|
|
||||||
}
|
|
||||||
additionModel.enterCriticalSection(Lock.WRITE);
|
|
||||||
try {
|
|
||||||
additionModel.add(stmt);
|
|
||||||
} finally {
|
|
||||||
additionModel.leaveCriticalSection();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ( log.isDebugEnabled() ) {
|
|
||||||
log.debug( "Not adding to Pellet: " + renderStatement( stmt ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void tryRemove(Statement stmt) {
|
|
||||||
boolean removeFromPellet = false;
|
|
||||||
if ( pipeOpen && reasonerConfiguration.getReasonOnAllDatatypePropertyStatements() && stmt.getObject().isLiteral() ) {
|
|
||||||
removeFromPellet = true;
|
|
||||||
} else
|
|
||||||
if ( pipeOpen && hasCardinalityPredicate(stmt) ) { // see comment on this method
|
|
||||||
removeFromPellet = true;
|
|
||||||
} else
|
|
||||||
if ( stmt.getObject().isResource() ) {
|
|
||||||
if (pipeOpen) {
|
|
||||||
if (reasonerConfiguration.getQueryForAllObjectProperties() && stmt.getPredicate().equals(RDF.type) && stmt.getObject().equals(OWL.ObjectProperty)) {
|
|
||||||
deletedObjectProperties.enterCriticalSection(Lock.WRITE);
|
|
||||||
try {
|
|
||||||
deletedObjectProperties.add(stmt);
|
|
||||||
} finally {
|
|
||||||
deletedObjectProperties.leaveCriticalSection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reasonerConfiguration.getQueryForAllDatatypeProperties() && stmt.getPredicate().equals(RDF.type) && stmt.getObject().equals(OWL.DatatypeProperty)) {
|
|
||||||
deletedDataProperties.enterCriticalSection(Lock.WRITE);
|
|
||||||
try{
|
|
||||||
deletedDataProperties.add(stmt);
|
|
||||||
} finally {
|
|
||||||
deletedDataProperties.leaveCriticalSection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
removeFromPellet = false;
|
|
||||||
boolean denied = false;
|
|
||||||
ObjectPropertyStatementPattern stPat = ObjectPropertyStatementPatternFactory.getPattern(stmt.getSubject(), stmt.getPredicate(), (Resource) stmt.getObject());
|
|
||||||
if (inferenceDrivingPatternDenySet != null) {
|
|
||||||
for (Iterator<ObjectPropertyStatementPattern> i = inferenceDrivingPatternDenySet.iterator(); i.hasNext(); ){
|
|
||||||
ObjectPropertyStatementPattern pat = i.next();
|
|
||||||
if (pat.matches(stPat)) {
|
|
||||||
denied = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!denied) {
|
|
||||||
if (inferenceDrivingPatternAllowSet==null) {
|
|
||||||
removeFromPellet = true;
|
|
||||||
} else {
|
|
||||||
// TODO: O(1) implementation of this
|
|
||||||
List<ObjectPropertyStatementPattern> patList = this.inferenceDrivingPatternMap.get(stmt.getPredicate());
|
|
||||||
if (patList != null) {
|
|
||||||
for (Iterator<ObjectPropertyStatementPattern> i = patList.iterator(); i.hasNext(); ){
|
|
||||||
ObjectPropertyStatementPattern pat = i.next();
|
|
||||||
if (pat.matches(stPat)) {
|
|
||||||
removeFromPellet = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (removeFromPellet) {
|
|
||||||
String valueStr = (stmt.getObject().isResource()) ? ((Resource)stmt.getObject()).getLocalName() : ((Literal)stmt.getObject()).getLexicalForm();
|
|
||||||
log.info("Removing from Pellet: "+stmt.getSubject().getLocalName()+" "+stmt.getPredicate().getLocalName()+" "+valueStr);
|
|
||||||
removalModel.enterCriticalSection(Lock.WRITE);
|
|
||||||
try {
|
|
||||||
removalModel.add(stmt);
|
|
||||||
} finally {
|
|
||||||
removalModel.leaveCriticalSection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The pattern matching stuff needs to get reworked.
|
|
||||||
// It originally assumed that only resources would be in object
|
|
||||||
// position, but cardinality axioms will have e.g. nonNegativeIntegers.
|
|
||||||
// This is a temporary workaround: all cardinality statements will
|
|
||||||
// be exposed to Pellet, regardless of configuration patterns.
|
|
||||||
private boolean hasCardinalityPredicate(Statement stmt) {
|
|
||||||
return (
|
|
||||||
stmt.getPredicate().equals(OWL.cardinality) ||
|
|
||||||
stmt.getPredicate().equals(OWL.minCardinality) ||
|
|
||||||
stmt.getPredicate().equals(OWL.maxCardinality)
|
|
||||||
) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void addedStatement(Statement arg0) {
|
|
||||||
tryAdd(arg0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void addedStatements(Statement[] arg0) {
|
|
||||||
for (int i=0; i<arg0.length; i++) {
|
|
||||||
tryAdd(arg0[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void addedStatements( List arg0 ) {
|
|
||||||
for ( Iterator i = arg0.iterator(); i.hasNext(); ) {
|
|
||||||
tryAdd( (Statement) i.next() );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void addedStatements(StmtIterator arg0) {
|
|
||||||
for (Iterator i = arg0; i.hasNext(); ) {
|
|
||||||
tryAdd( (Statement) i.next() );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void addedStatements(Model arg0) {
|
|
||||||
for (Iterator i = arg0.listStatements(); i.hasNext(); ) {
|
|
||||||
tryAdd( (Statement) i.next() );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void notifyEvent(Model arg0, Object arg1) {
|
|
||||||
if (arg1 instanceof EditEvent) {
|
|
||||||
EditEvent ee = (EditEvent) arg1;
|
|
||||||
if (!ee.getBegin()) {
|
|
||||||
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 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 void removedStatement(Statement arg0) {
|
|
||||||
tryRemove(arg0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void removedStatements(Statement[] arg0) {
|
|
||||||
for (int i=0; i<arg0.length; i++) {
|
|
||||||
tryRemove(arg0[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void removedStatements(List arg0) {
|
|
||||||
for (Iterator i = arg0.iterator(); i.hasNext(); ) {
|
|
||||||
tryRemove( (Statement) i.next());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void removedStatements(StmtIterator arg0) {
|
|
||||||
for (Iterator i = arg0; i.hasNext();) {
|
|
||||||
tryRemove( (Statement) i.next());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void removedStatements(Model arg0) {
|
|
||||||
for (Iterator i = arg0.listStatements(); i.hasNext();) {
|
|
||||||
tryRemove( (Statement) i.next());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public OntModel getPelletModel() {
|
|
||||||
return this.pelletModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String renderStatement(Statement stmt) {
|
|
||||||
String subjStr = (stmt.getSubject().getURI() != null) ? stmt.getSubject().getURI() : stmt.getSubject().getId().toString();
|
|
||||||
String predStr = stmt.getPredicate().getURI();
|
|
||||||
String objStr = "";
|
|
||||||
RDFNode obj = stmt.getObject();
|
|
||||||
if (obj.isLiteral()) {
|
|
||||||
objStr = "\""+(((Literal)obj).getLexicalForm());
|
|
||||||
} else {
|
|
||||||
objStr = (((Resource)stmt.getObject()).getURI() != null) ? ((Resource)stmt.getObject()).getURI() : ((Resource)stmt.getObject()).getId().toString();
|
|
||||||
}
|
|
||||||
return (subjStr+" : "+predStr+" : "+objStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -8,12 +8,12 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.application.ApplicationUtils;
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
|
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
|
||||||
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
|
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
|
||||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
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.edit.n3editing.VTwo.EditConfigurationVTwo;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner.TBoxReasonerStatus;
|
||||||
|
|
||||||
public class IndividualsViaVClassOptions implements FieldOptions {
|
public class IndividualsViaVClassOptions implements FieldOptions {
|
||||||
|
|
||||||
|
@ -101,20 +101,13 @@ public class IndividualsViaVClassOptions implements FieldOptions {
|
||||||
return individualMap;
|
return individualMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isReasoningAvailable( WebappDaoFactory wDaoFact){
|
protected boolean isReasoningAvailable(){
|
||||||
boolean inferenceAvailable = false;
|
TBoxReasonerStatus status = ApplicationUtils.instance().getTBoxReasonerModule().getStatus();
|
||||||
if (wDaoFact instanceof WebappDaoFactoryJena) {
|
return status.isConsistent() && !status.isInErrorState();
|
||||||
PelletListener pl = ((WebappDaoFactoryJena) wDaoFact).getPelletListener();
|
|
||||||
if (pl != null && pl.isConsistent() && !pl.isInErrorState()
|
|
||||||
&& !pl.isReasoning()) {
|
|
||||||
inferenceAvailable = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return inferenceAvailable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Map<String, Individual> addWhenMissingInference( String classUri , WebappDaoFactory wDaoFact ){
|
protected Map<String, Individual> addWhenMissingInference( String classUri , WebappDaoFactory wDaoFact ){
|
||||||
boolean inferenceAvailable = isReasoningAvailable(wDaoFact);
|
boolean inferenceAvailable = isReasoningAvailable();
|
||||||
Map<String,Individual> individualMap = new HashMap<String,Individual>();
|
Map<String,Individual> individualMap = new HashMap<String,Individual>();
|
||||||
if ( !inferenceAvailable ) {
|
if ( !inferenceAvailable ) {
|
||||||
for (String subclassURI : wDaoFact.getVClassDao().getAllSubClassURIs(classUri)) {
|
for (String subclassURI : wDaoFact.getVClassDao().getAllSubClassURIs(classUri)) {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import edu.cornell.mannlib.vitro.webapp.application.VitroHomeDirectory;
|
||||||
import edu.cornell.mannlib.vitro.webapp.modules.fileStorage.FileStorage;
|
import edu.cornell.mannlib.vitro.webapp.modules.fileStorage.FileStorage;
|
||||||
import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor;
|
import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor;
|
||||||
import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngine;
|
import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngine;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner.TBoxReasonerModule;
|
||||||
import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.ConfigurationTripleSource;
|
import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.ConfigurationTripleSource;
|
||||||
import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.ContentTripleSource;
|
import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.ContentTripleSource;
|
||||||
|
|
||||||
|
@ -29,6 +30,8 @@ public interface Application {
|
||||||
|
|
||||||
ConfigurationTripleSource getConfigurationTripleSource();
|
ConfigurationTripleSource getConfigurationTripleSource();
|
||||||
|
|
||||||
|
TBoxReasonerModule getTBoxReasonerModule();
|
||||||
|
|
||||||
void shutdown();
|
void shutdown();
|
||||||
|
|
||||||
public interface Component {
|
public interface Component {
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.hp.hpl.jena.ontology.Restriction;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.modules.Application;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A wrapper around the TBox reasoner
|
||||||
|
*/
|
||||||
|
public interface TBoxReasonerModule extends Application.Module {
|
||||||
|
/**
|
||||||
|
* What is the TBox reasoner doing now?
|
||||||
|
*/
|
||||||
|
TBoxReasonerStatus getStatus();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* What restrictions are currently in the reasoner's internal model?
|
||||||
|
*/
|
||||||
|
List<Restriction> listRestrictions();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait until the TBox reasoner becomes quiet.
|
||||||
|
*/
|
||||||
|
void waitForTBoxReasoning();
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* What is the current state of the TBox reasoner?
|
||||||
|
*/
|
||||||
|
public interface TBoxReasonerStatus {
|
||||||
|
/**
|
||||||
|
* Is reasoning in progress based on changes to the TBox?
|
||||||
|
*/
|
||||||
|
boolean isReasoning();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the TBox free of inconsistency?
|
||||||
|
*/
|
||||||
|
boolean isConsistent();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Did the reasoner fail in its most recent attempt?
|
||||||
|
*/
|
||||||
|
boolean isInErrorState();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A description of the error state, or an empty string (never null).
|
||||||
|
*/
|
||||||
|
String getExplanation();
|
||||||
|
|
||||||
|
}
|
|
@ -97,13 +97,6 @@ public class FileGraphSetup implements ServletContextListener {
|
||||||
OntDocumentManager.getInstance().setProcessImports(false);
|
OntDocumentManager.getInstance().setProcessImports(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
if (isUpdateRequired(ctx)) {
|
|
||||||
log.info("mostSpecificType will be computed because a knowledge base migration was performed." );
|
|
||||||
SimpleReasonerSetup.setMSTComputeRequired(ctx);
|
|
||||||
} else
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ( (aboxChanged || tboxChanged) && !isUpdateRequired(ctx)) {
|
if ( (aboxChanged || tboxChanged) && !isUpdateRequired(ctx)) {
|
||||||
log.info("a full recompute of the Abox will be performed because" +
|
log.info("a full recompute of the Abox will be performed because" +
|
||||||
" the filegraph abox(s) and/or tbox(s) have changed or are being read for the first time." );
|
" the filegraph abox(s) and/or tbox(s) have changed or are being read for the first time." );
|
||||||
|
|
|
@ -21,12 +21,7 @@ import org.apache.commons.logging.LogFactory;
|
||||||
import com.hp.hpl.jena.ontology.OntModel;
|
import com.hp.hpl.jena.ontology.OntModel;
|
||||||
import com.hp.hpl.jena.query.Dataset;
|
import com.hp.hpl.jena.query.Dataset;
|
||||||
import com.hp.hpl.jena.rdf.model.Model;
|
import com.hp.hpl.jena.rdf.model.Model;
|
||||||
import com.hp.hpl.jena.vocabulary.OWL;
|
|
||||||
|
|
||||||
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.dao.jena.pellet.ReasonerConfiguration;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
|
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
|
||||||
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames;
|
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames;
|
||||||
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
|
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
|
||||||
|
@ -51,40 +46,9 @@ public class SimpleReasonerSetup implements ServletContextListener {
|
||||||
ServletContext ctx = sce.getServletContext();
|
ServletContext ctx = sce.getServletContext();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// set up Pellet reasoning for the TBox
|
|
||||||
OntModel tboxAssertionsModel = ModelAccess.on(ctx).getOntModel(ModelNames.TBOX_ASSERTIONS);
|
OntModel tboxAssertionsModel = ModelAccess.on(ctx).getOntModel(ModelNames.TBOX_ASSERTIONS);
|
||||||
OntModel tboxInferencesModel = ModelAccess.on(ctx).getOntModel(ModelNames.TBOX_INFERENCES);
|
OntModel tboxInferencesModel = ModelAccess.on(ctx).getOntModel(ModelNames.TBOX_INFERENCES);
|
||||||
OntModel tboxUnionModel = ModelAccess.on(ctx).getOntModel(ModelNames.TBOX_UNION);
|
OntModel tboxUnionModel = ModelAccess.on(ctx).getOntModel(ModelNames.TBOX_UNION);
|
||||||
log.debug("tboxAssertionsModel=" + tboxAssertionsModel);
|
|
||||||
log.debug("tboxInferencesModel=" + tboxInferencesModel);
|
|
||||||
log.debug("tboxUnionModel=" + tboxUnionModel);
|
|
||||||
|
|
||||||
WebappDaoFactory wadf = ModelAccess.on(ctx).getWebappDaoFactory();
|
|
||||||
|
|
||||||
if (!tboxAssertionsModel.getProfile().NAMESPACE().equals(OWL.NAMESPACE.getNameSpace())) {
|
|
||||||
log.error("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,ReasonerConfiguration.DEFAULT);
|
|
||||||
sce.getServletContext().setAttribute("pelletListener",pelletListener);
|
|
||||||
sce.getServletContext().setAttribute("pelletOntModel", pelletListener.getPelletModel());
|
|
||||||
|
|
||||||
if (wadf instanceof WebappDaoFactoryJena) {
|
|
||||||
((WebappDaoFactoryJena) wadf).setPelletListener(pelletListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
log.info("Pellet reasoner connected for the TBox");
|
|
||||||
|
|
||||||
waitForTBoxReasoning(sce);
|
|
||||||
|
|
||||||
// set up simple reasoning for the ABox
|
// set up simple reasoning for the ABox
|
||||||
|
|
||||||
|
@ -139,23 +103,6 @@ public class SimpleReasonerSetup implements ServletContextListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void waitForTBoxReasoning(ServletContextEvent sce)
|
|
||||||
throws InterruptedException {
|
|
||||||
PelletListener pelletListener = (PelletListener) sce.getServletContext().getAttribute("pelletListener");
|
|
||||||
if (pelletListener == null) {
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
int sleeps = 0;
|
|
||||||
// sleep at least once to make sure the TBox reasoning gets started
|
|
||||||
while ((0 == sleeps) || ((sleeps < 1000) && pelletListener.isReasoning())) {
|
|
||||||
if (((sleeps - 1) % 10) == 0) { // print message at 10 second intervals
|
|
||||||
log.info("Waiting for initial TBox reasoning to complete");
|
|
||||||
}
|
|
||||||
Thread.sleep(1000);
|
|
||||||
sleeps++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void contextDestroyed(ServletContextEvent sce) {
|
public void contextDestroyed(ServletContextEvent sce) {
|
||||||
log.info("received contextDestroyed notification");
|
log.info("received contextDestroyed notification");
|
||||||
|
@ -209,17 +156,6 @@ public class SimpleReasonerSetup implements ServletContextListener {
|
||||||
return (RecomputeMode) ctx.getAttribute(RECOMPUTE_REQUIRED_ATTR);
|
return (RecomputeMode) ctx.getAttribute(RECOMPUTE_REQUIRED_ATTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String MSTCOMPUTE_REQUIRED_ATTR =
|
|
||||||
SimpleReasonerSetup.class.getName() + ".MSTComputeRequired";
|
|
||||||
|
|
||||||
public static void setMSTComputeRequired(ServletContext ctx) {
|
|
||||||
ctx.setAttribute(MSTCOMPUTE_REQUIRED_ATTR, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isMSTComputeRequired(ServletContext ctx) {
|
|
||||||
return (ctx.getAttribute(MSTCOMPUTE_REQUIRED_ATTR) != null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the names of the plugin classes classes.
|
* Read the names of the plugin classes classes.
|
||||||
*
|
*
|
||||||
|
@ -278,6 +214,7 @@ public class SimpleReasonerSetup implements ServletContextListener {
|
||||||
this.simpleReasoner = simpleReasoner;
|
this.simpleReasoner = simpleReasoner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
simpleReasoner.recompute();
|
simpleReasoner.recompute();
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,11 @@ public class UpdateKnowledgeBase implements ServletContextListener {
|
||||||
putReportingPathsIntoSettings(ctx, settings);
|
putReportingPathsIntoSettings(ctx, settings);
|
||||||
putNonReportingPathsIntoSettings(ctx, settings);
|
putNonReportingPathsIntoSettings(ctx, settings);
|
||||||
|
|
||||||
SimpleReasonerSetup.waitForTBoxReasoning(sce);
|
try {
|
||||||
|
ApplicationUtils.instance().getTBoxReasonerModule().waitForTBoxReasoning();
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Should mean that the reasoner is not even started yet.
|
||||||
|
}
|
||||||
|
|
||||||
WebappDaoFactory wadf = ModelAccess.on(ctx).getWebappDaoFactory();
|
WebappDaoFactory wadf = ModelAccess.on(ctx).getWebappDaoFactory();
|
||||||
settings.setDefaultNamespace(wadf.getDefaultNamespace());
|
settings.setDefaultNamespace(wadf.getDefaultNamespace());
|
||||||
|
|
|
@ -0,0 +1,349 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.tboxreasoner;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import com.hp.hpl.jena.rdf.model.Model;
|
||||||
|
import com.hp.hpl.jena.rdf.model.ModelChangedListener;
|
||||||
|
import com.hp.hpl.jena.rdf.model.Property;
|
||||||
|
import com.hp.hpl.jena.rdf.model.Statement;
|
||||||
|
import com.hp.hpl.jena.rdf.model.StmtIterator;
|
||||||
|
import com.hp.hpl.jena.vocabulary.OWL;
|
||||||
|
import com.hp.hpl.jena.vocabulary.RDF;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listens for changes on a model. When a change is announced, it is checked for
|
||||||
|
* worthiness. If worthy, it is added to a change set.
|
||||||
|
*
|
||||||
|
* When an ending EditEvent is received, the current change set is passed along
|
||||||
|
* to the reasoner driver, and a new change set is begun.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
public class ConfiguredReasonerListener implements ModelChangedListener {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(ConfiguredReasonerListener.class);
|
||||||
|
|
||||||
|
private final ReasonerConfiguration reasonerConfiguration;
|
||||||
|
private final TBoxReasonerDriver reasonerDriver;
|
||||||
|
|
||||||
|
private final DrivingPatternMap drivingPatternMap;
|
||||||
|
|
||||||
|
private final AtomicReference<TBoxChanges> changeSet;
|
||||||
|
private final AtomicBoolean suspended;
|
||||||
|
|
||||||
|
public ConfiguredReasonerListener(
|
||||||
|
ReasonerConfiguration reasonerConfiguration,
|
||||||
|
TBoxReasonerDriver reasonerDriver) {
|
||||||
|
this.reasonerConfiguration = reasonerConfiguration;
|
||||||
|
this.reasonerDriver = reasonerDriver;
|
||||||
|
|
||||||
|
this.drivingPatternMap = new DrivingPatternMap(
|
||||||
|
reasonerConfiguration.getInferenceDrivingPatternAllowSet());
|
||||||
|
|
||||||
|
this.changeSet = new AtomicReference<>(new TBoxChanges());
|
||||||
|
this.suspended = new AtomicBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Suspension suspend() {
|
||||||
|
if (!suspended.compareAndSet(false, true)) {
|
||||||
|
throw new IllegalStateException("Listener is already suspended.");
|
||||||
|
}
|
||||||
|
return new Suspension();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Suspension implements AutoCloseable {
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
boolean wasSuspended = suspended.compareAndSet(true, false);
|
||||||
|
if (!wasSuspended) {
|
||||||
|
log.warn("Listener was already not suspended.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists of patterns, mapped by their predicates.
|
||||||
|
*/
|
||||||
|
public class DrivingPatternMap extends
|
||||||
|
HashMap<Property, List<ReasonerStatementPattern>> {
|
||||||
|
|
||||||
|
public DrivingPatternMap(Set<ReasonerStatementPattern> patternSet) {
|
||||||
|
if (patternSet != null) {
|
||||||
|
for (ReasonerStatementPattern pat : patternSet) {
|
||||||
|
Property p = pat.getPredicate();
|
||||||
|
if (!containsKey(p)) {
|
||||||
|
put(p, new LinkedList<ReasonerStatementPattern>());
|
||||||
|
}
|
||||||
|
get(p).add(pat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Implement the ModelChangedListener methods. Delegate to the methods that
|
||||||
|
// check criteria.
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addedStatement(Statement s) {
|
||||||
|
tryAdd(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addedStatements(Statement[] statements) {
|
||||||
|
for (Statement stmt : statements) {
|
||||||
|
tryAdd(stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addedStatements(List<Statement> statements) {
|
||||||
|
for (Statement stmt : statements) {
|
||||||
|
tryAdd(stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addedStatements(StmtIterator statements) {
|
||||||
|
for (Statement stmt : statements.toList()) {
|
||||||
|
tryAdd(stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addedStatements(Model m) {
|
||||||
|
for (Statement stmt : m.listStatements().toList()) {
|
||||||
|
tryAdd(stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removedStatement(Statement s) {
|
||||||
|
tryRemove(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removedStatements(Statement[] statements) {
|
||||||
|
for (Statement stmt : statements) {
|
||||||
|
tryRemove(stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removedStatements(List<Statement> statements) {
|
||||||
|
for (Statement stmt : statements) {
|
||||||
|
tryRemove(stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removedStatements(StmtIterator statements) {
|
||||||
|
for (Statement stmt : statements.toList()) {
|
||||||
|
tryRemove(stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removedStatements(Model m) {
|
||||||
|
for (Statement stmt : m.listStatements().toList()) {
|
||||||
|
tryRemove(stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyEvent(Model m, Object event) {
|
||||||
|
if (event instanceof EditEvent) {
|
||||||
|
EditEvent ee = (EditEvent) event;
|
||||||
|
if (!ee.getBegin()) {
|
||||||
|
TBoxChanges changes = changeSet.getAndSet(new TBoxChanges());
|
||||||
|
this.reasonerDriver.runSynchronizer(changes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Check the criteria to determine whether each addition or removal should
|
||||||
|
// be passed to the reasoner.
|
||||||
|
//
|
||||||
|
// When the listener is suspended, nothing is passed on.
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
public void tryAdd(Statement stmt) {
|
||||||
|
if (suspended.get()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDataProperty(stmt)) {
|
||||||
|
if (reasonOnAllDataProperties() || hasCardinalityPredicate(stmt)) {
|
||||||
|
addIt(stmt);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (predicateIsInVitroNamespace(stmt)
|
||||||
|
|| statementMatchesDenyPattern(stmt)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thereAreNoDrivingPatterns() || statementMatchesDrivingPattern(stmt)) {
|
||||||
|
addIt(stmt);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tryRemove(Statement stmt) {
|
||||||
|
if (suspended.get()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDataProperty(stmt)) {
|
||||||
|
if (reasonOnAllDataProperties() || hasCardinalityPredicate(stmt)) {
|
||||||
|
removeIt(stmt);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actOnObjectPropertyDeclarations() && declaresObjectProperty(stmt)) {
|
||||||
|
deleteObjectProperty(stmt);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actOnDataPropertyDeclarations() && declaresDataProperty(stmt)) {
|
||||||
|
deleteDataProperty(stmt);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (statementMatchesDenyPattern(stmt)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thereAreNoDrivingPatterns() || statementMatchesDrivingPattern(stmt)) {
|
||||||
|
removeIt(stmt);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isDataProperty(Statement stmt) {
|
||||||
|
return stmt.getObject().isLiteral();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean reasonOnAllDataProperties() {
|
||||||
|
return reasonerConfiguration.getReasonOnAllDatatypePropertyStatements();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean predicateIsInVitroNamespace(Statement stmt) {
|
||||||
|
return stmt.getPredicate().getURI().indexOf(VitroVocabulary.vitroURI) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean statementMatchesDenyPattern(Statement stmt) {
|
||||||
|
Set<ReasonerStatementPattern> denyPatterns = reasonerConfiguration.inferenceDrivingPatternDenySet;
|
||||||
|
if (denyPatterns == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReasonerStatementPattern stPat = ReasonerStatementPattern
|
||||||
|
.objectPattern(stmt);
|
||||||
|
|
||||||
|
for (ReasonerStatementPattern pat : denyPatterns) {
|
||||||
|
if (pat.matches(stPat)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean thereAreNoDrivingPatterns() {
|
||||||
|
return reasonerConfiguration.inferenceDrivingPatternAllowSet == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean statementMatchesDrivingPattern(Statement stmt) {
|
||||||
|
List<ReasonerStatementPattern> drivePatterns = drivingPatternMap
|
||||||
|
.get(stmt.getPredicate());
|
||||||
|
if (drivePatterns == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReasonerStatementPattern stPat = ReasonerStatementPattern
|
||||||
|
.objectPattern(stmt);
|
||||||
|
|
||||||
|
for (ReasonerStatementPattern pat : drivePatterns) {
|
||||||
|
if (pat.matches(stPat)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean actOnObjectPropertyDeclarations() {
|
||||||
|
return reasonerConfiguration.getQueryForAllObjectProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean declaresObjectProperty(Statement stmt) {
|
||||||
|
return stmt.getPredicate().equals(RDF.type)
|
||||||
|
&& stmt.getObject().equals(OWL.ObjectProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean actOnDataPropertyDeclarations() {
|
||||||
|
return reasonerConfiguration.getQueryForAllDatatypeProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean declaresDataProperty(Statement stmt) {
|
||||||
|
return stmt.getPredicate().equals(RDF.type)
|
||||||
|
&& stmt.getObject().equals(OWL.DatatypeProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addIt(Statement stmt) {
|
||||||
|
changeSet.get().addStatement(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeIt(Statement stmt) {
|
||||||
|
changeSet.get().removeStatement(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteObjectProperty(Statement stmt) {
|
||||||
|
changeSet.get().deleteObjectProperty(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteDataProperty(Statement stmt) {
|
||||||
|
changeSet.get().deleteDataProperty(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The pattern matching stuff needs to get reworked.
|
||||||
|
// It originally assumed that only resources would be in object
|
||||||
|
// position, but cardinality axioms will have e.g. nonNegativeIntegers.
|
||||||
|
// This is a temporary workaround: all cardinality statements will
|
||||||
|
// be exposed to Pellet, regardless of configuration patterns.
|
||||||
|
private boolean hasCardinalityPredicate(Statement stmt) {
|
||||||
|
return (stmt.getPredicate().equals(OWL.cardinality)
|
||||||
|
|| stmt.getPredicate().equals(OWL.minCardinality) || stmt
|
||||||
|
.getPredicate().equals(OWL.maxCardinality));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
/* $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 org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
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 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.TBoxReasoner;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tool that will adjust the inferences model to match the reasoner model,
|
||||||
|
* after applying the proper filters to both.
|
||||||
|
*/
|
||||||
|
public class InferenceModelUpdater {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(InferenceModelUpdater.class);
|
||||||
|
|
||||||
|
private final TBoxReasoner reasoner;
|
||||||
|
private final LockableModel lockableInferencesModel;
|
||||||
|
private final LockableOntModel lockableFullModel;
|
||||||
|
private final ConfiguredReasonerListener listener;
|
||||||
|
|
||||||
|
private int addCount;
|
||||||
|
private int retractCount;
|
||||||
|
|
||||||
|
public int getAddCount() {
|
||||||
|
return addCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRetractCount() {
|
||||||
|
return retractCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InferenceModelUpdater(TBoxReasoner 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 this
|
||||||
|
* proviso:
|
||||||
|
*
|
||||||
|
* If a statement exists anywhere in the full TBox, don't bother adding it
|
||||||
|
* to the inferences model.
|
||||||
|
*/
|
||||||
|
public void update(List<ReasonerStatementPattern> patternList) {
|
||||||
|
List<Statement> filteredReasonerModel = reasoner
|
||||||
|
.filterResults(patternList);
|
||||||
|
addNewInferences(filteredReasonerModel);
|
||||||
|
removeOldInferences(filterInferencesModel(patternList),
|
||||||
|
filteredReasonerModel);
|
||||||
|
log.debug("Added: " + addCount + ", Retracted: " + retractCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addNewInferences(List<Statement> filteredReasonerModel) {
|
||||||
|
for (Statement stmt : filteredReasonerModel) {
|
||||||
|
if (!fullModelContainsStatement(stmt)) {
|
||||||
|
try (LockedModel inferenceModel = lockableInferencesModel
|
||||||
|
.write(); Suspension susp = listener.suspend()) {
|
||||||
|
inferenceModel.add(stmt);
|
||||||
|
addCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean fullModelContainsStatement(Statement stmt) {
|
||||||
|
try (LockedOntModel fullModel = lockableFullModel.read()) {
|
||||||
|
return fullModel.contains(stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Model filterInferencesModel(
|
||||||
|
List<ReasonerStatementPattern> patternList) {
|
||||||
|
Model filtered = ModelFactory.createDefaultModel();
|
||||||
|
try (LockedModel inferencesModel = lockableInferencesModel.read()) {
|
||||||
|
for (ReasonerStatementPattern pattern : patternList) {
|
||||||
|
filtered.add(pattern.matchStatementsFromModel(inferencesModel));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.debug("Filtered inferences model: " + filtered.size());
|
||||||
|
return filtered;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeOldInferences(Model filteredInferencesModel,
|
||||||
|
List<Statement> filteredReasonerStatements) {
|
||||||
|
Model filteredReasonerModel = ModelFactory.createDefaultModel();
|
||||||
|
filteredReasonerModel.add(filteredReasonerStatements);
|
||||||
|
|
||||||
|
for (Statement stmt : filteredInferencesModel.listStatements().toList()) {
|
||||||
|
if (!filteredReasonerModel.contains(stmt)) {
|
||||||
|
try (LockedModel inferenceModel = lockableInferencesModel
|
||||||
|
.write(); Suspension susp = listener.suspend()) {
|
||||||
|
retractCount++;
|
||||||
|
inferenceModel.remove(stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.tboxreasoner;
|
||||||
|
|
||||||
|
import static com.hp.hpl.jena.rdf.model.ResourceFactory.createProperty;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.hp.hpl.jena.ontology.DatatypeProperty;
|
||||||
|
import com.hp.hpl.jena.ontology.ObjectProperty;
|
||||||
|
|
||||||
|
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.TBoxReasoner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of patterns for filtering the models will include:
|
||||||
|
*
|
||||||
|
* All patterns specified by the ReasonerConfiguration,
|
||||||
|
*
|
||||||
|
* One pattern for each deleted property, to match the use of that property as a
|
||||||
|
* predicate.
|
||||||
|
*/
|
||||||
|
public class PatternListBuilder {
|
||||||
|
private static final String OWL_NS = "http://www.w3.org/2002/07/owl#";
|
||||||
|
|
||||||
|
private final ReasonerConfiguration reasonerConfiguration;
|
||||||
|
private final TBoxReasoner reasoner;
|
||||||
|
private final TBoxChanges changes;
|
||||||
|
|
||||||
|
public PatternListBuilder(ReasonerConfiguration reasonerConfiguration,
|
||||||
|
TBoxReasoner reasoner, TBoxChanges changes) {
|
||||||
|
this.reasonerConfiguration = reasonerConfiguration;
|
||||||
|
this.reasoner = reasoner;
|
||||||
|
this.changes = changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LinkedList<ReasonerStatementPattern> build() {
|
||||||
|
LinkedList<ReasonerStatementPattern> patterns = new LinkedList<>();
|
||||||
|
|
||||||
|
Set<ReasonerStatementPattern> allowSet = reasonerConfiguration
|
||||||
|
.getInferenceReceivingPatternAllowSet();
|
||||||
|
if (allowSet != null) {
|
||||||
|
patterns.addAll(allowSet);
|
||||||
|
} else {
|
||||||
|
patterns.add(ReasonerStatementPattern.ANY_OBJECT_PROPERTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reasonerConfiguration.getQueryForAllObjectProperties()) {
|
||||||
|
for (ObjectProperty objProp : reasoner.listObjectProperties()) {
|
||||||
|
if (!(OWL_NS.equals(objProp.getNameSpace()))) {
|
||||||
|
patterns.add(ReasonerStatementPattern
|
||||||
|
.objectPattern(objProp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String uri : changes.getDeletedObjectPropertyUris()) {
|
||||||
|
patterns.add(ReasonerStatementPattern
|
||||||
|
.objectPattern(createProperty(uri)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reasonerConfiguration.getQueryForAllDatatypeProperties()) {
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (String uri : changes.getDeletedDataPropertyUris()) {
|
||||||
|
patterns.add(ReasonerStatementPattern
|
||||||
|
.objectPattern(createProperty(uri)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return patterns;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,22 +1,22 @@
|
||||||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.dao.jena.pellet;
|
package edu.cornell.mannlib.vitro.webapp.tboxreasoner;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.mindswap.pellet.jena.PelletReasonerFactory;
|
||||||
|
|
||||||
import com.hp.hpl.jena.ontology.OntModelSpec;
|
import com.hp.hpl.jena.ontology.OntModelSpec;
|
||||||
import com.hp.hpl.jena.vocabulary.OWL;
|
import com.hp.hpl.jena.vocabulary.OWL;
|
||||||
import com.hp.hpl.jena.vocabulary.RDF;
|
import com.hp.hpl.jena.vocabulary.RDF;
|
||||||
import com.hp.hpl.jena.vocabulary.RDFS;
|
import com.hp.hpl.jena.vocabulary.RDFS;
|
||||||
|
|
||||||
import org.mindswap.pellet.jena.PelletReasonerFactory;
|
|
||||||
|
|
||||||
public class ReasonerConfiguration {
|
public class ReasonerConfiguration {
|
||||||
|
|
||||||
public Set<ObjectPropertyStatementPattern> inferenceDrivingPatternAllowSet;
|
public Set<ReasonerStatementPattern> inferenceDrivingPatternAllowSet;
|
||||||
public Set<ObjectPropertyStatementPattern> inferenceDrivingPatternDenySet;
|
public Set<ReasonerStatementPattern> inferenceDrivingPatternDenySet;
|
||||||
public Set<ObjectPropertyStatementPattern> inferenceReceivingPatternAllowSet;
|
public Set<ReasonerStatementPattern> inferenceReceivingPatternAllowSet;
|
||||||
|
|
||||||
private boolean queryForAllObjectProperties = false;
|
private boolean queryForAllObjectProperties = false;
|
||||||
private boolean incrementalReasoningEnabled = true;
|
private boolean incrementalReasoningEnabled = true;
|
||||||
|
@ -58,34 +58,34 @@ public class ReasonerConfiguration {
|
||||||
|
|
||||||
//ask the reasoner only to classify, realize, and infer disjointWith statements (based on a somewhat incomplete information)
|
//ask the reasoner only to classify, realize, and infer disjointWith statements (based on a somewhat incomplete information)
|
||||||
DEFAULT = new ReasonerConfiguration();
|
DEFAULT = new ReasonerConfiguration();
|
||||||
HashSet<ObjectPropertyStatementPattern> defaultInferenceDrivingPatternAllowSet = new HashSet<ObjectPropertyStatementPattern>();
|
HashSet<ReasonerStatementPattern> defaultInferenceDrivingPatternAllowSet = new HashSet<>();
|
||||||
defaultInferenceDrivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,RDF.type,null));
|
defaultInferenceDrivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(RDF.type));
|
||||||
defaultInferenceDrivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,RDFS.subClassOf,null));
|
defaultInferenceDrivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(RDFS.subClassOf));
|
||||||
defaultInferenceDrivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,RDFS.subPropertyOf,null));
|
defaultInferenceDrivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(RDFS.subPropertyOf));
|
||||||
defaultInferenceDrivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,OWL.equivalentClass,null));
|
defaultInferenceDrivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(OWL.equivalentClass));
|
||||||
defaultInferenceDrivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,OWL.unionOf,null));
|
defaultInferenceDrivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(OWL.unionOf));
|
||||||
defaultInferenceDrivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,OWL.intersectionOf,null));
|
defaultInferenceDrivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(OWL.intersectionOf));
|
||||||
defaultInferenceDrivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,OWL.complementOf,null));
|
defaultInferenceDrivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(OWL.complementOf));
|
||||||
defaultInferenceDrivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,OWL.oneOf,null));
|
defaultInferenceDrivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(OWL.oneOf));
|
||||||
defaultInferenceDrivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,OWL.onProperty,null));
|
defaultInferenceDrivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(OWL.onProperty));
|
||||||
defaultInferenceDrivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,OWL.someValuesFrom,null));
|
defaultInferenceDrivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(OWL.someValuesFrom));
|
||||||
defaultInferenceDrivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,OWL.allValuesFrom,null));
|
defaultInferenceDrivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(OWL.allValuesFrom));
|
||||||
defaultInferenceDrivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,OWL.hasValue,null));
|
defaultInferenceDrivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(OWL.hasValue));
|
||||||
defaultInferenceDrivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,OWL.minCardinality,null));
|
defaultInferenceDrivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(OWL.minCardinality));
|
||||||
defaultInferenceDrivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,OWL.maxCardinality,null));
|
defaultInferenceDrivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(OWL.maxCardinality));
|
||||||
defaultInferenceDrivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,OWL.cardinality,null));
|
defaultInferenceDrivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(OWL.cardinality));
|
||||||
defaultInferenceDrivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,RDF.first,null));
|
defaultInferenceDrivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(RDF.first));
|
||||||
defaultInferenceDrivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,RDF.rest,null));
|
defaultInferenceDrivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(RDF.rest));
|
||||||
defaultInferenceDrivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,OWL.disjointWith,null));
|
defaultInferenceDrivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(OWL.disjointWith));
|
||||||
defaultInferenceDrivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,OWL.inverseOf,null));
|
defaultInferenceDrivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(OWL.inverseOf));
|
||||||
DEFAULT.setInferenceDrivingPatternAllowSet(defaultInferenceDrivingPatternAllowSet);
|
DEFAULT.setInferenceDrivingPatternAllowSet(defaultInferenceDrivingPatternAllowSet);
|
||||||
Set<ObjectPropertyStatementPattern> defaultInferenceReceivingPatternAllowSet = new HashSet<ObjectPropertyStatementPattern>();
|
Set<ReasonerStatementPattern> defaultInferenceReceivingPatternAllowSet = new HashSet<>();
|
||||||
defaultInferenceReceivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,RDF.type,null));
|
defaultInferenceReceivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(RDF.type));
|
||||||
defaultInferenceReceivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,RDFS.subClassOf,null));
|
defaultInferenceReceivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(RDFS.subClassOf));
|
||||||
defaultInferenceReceivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,RDFS.subPropertyOf,null));
|
defaultInferenceReceivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(RDFS.subPropertyOf));
|
||||||
defaultInferenceReceivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,OWL.equivalentClass,null));
|
defaultInferenceReceivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(OWL.equivalentClass));
|
||||||
defaultInferenceReceivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,OWL.disjointWith,null));
|
defaultInferenceReceivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(OWL.disjointWith));
|
||||||
defaultInferenceReceivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null,OWL.inverseOf,null));
|
defaultInferenceReceivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(OWL.inverseOf));
|
||||||
DEFAULT.setInferenceReceivingPatternAllowSet(defaultInferenceReceivingPatternAllowSet);
|
DEFAULT.setInferenceReceivingPatternAllowSet(defaultInferenceReceivingPatternAllowSet);
|
||||||
DEFAULT.setQueryForAllObjectProperties(false);
|
DEFAULT.setQueryForAllObjectProperties(false);
|
||||||
|
|
||||||
|
@ -107,36 +107,36 @@ public class ReasonerConfiguration {
|
||||||
COMPLETE.setQueryForAllObjectProperties(true);
|
COMPLETE.setQueryForAllObjectProperties(true);
|
||||||
COMPLETE.setReasonOnAllDatatypePropertyStatements(true);
|
COMPLETE.setReasonOnAllDatatypePropertyStatements(true);
|
||||||
COMPLETE.setQueryForAllDatatypeProperties(true);
|
COMPLETE.setQueryForAllDatatypeProperties(true);
|
||||||
Set<ObjectPropertyStatementPattern> completeInferenceReceivingPatternAllowSet = new HashSet<ObjectPropertyStatementPattern>();
|
Set<ReasonerStatementPattern> completeInferenceReceivingPatternAllowSet = new HashSet<>();
|
||||||
completeInferenceReceivingPatternAllowSet.addAll(defaultInferenceReceivingPatternAllowSet);
|
completeInferenceReceivingPatternAllowSet.addAll(defaultInferenceReceivingPatternAllowSet);
|
||||||
completeInferenceReceivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null, OWL.sameAs, null));
|
completeInferenceReceivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern(OWL.sameAs));
|
||||||
// getting NPEs inside Pellet with differentFrom on 2.0.0-rc7
|
// getting NPEs inside Pellet with differentFrom on 2.0.0-rc7
|
||||||
//completeInferenceReceivingPatternAllowSet.add(ObjectPropertyStatementPatternFactory.getPattern(null, OWL.differentFrom, null));
|
//completeInferenceReceivingPatternAllowSet.add(ReasonerStatementPattern.objectPattern( OWL.differentFrom, null));
|
||||||
COMPLETE.setInferenceReceivingPatternAllowSet(completeInferenceReceivingPatternAllowSet);
|
COMPLETE.setInferenceReceivingPatternAllowSet(completeInferenceReceivingPatternAllowSet);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<ObjectPropertyStatementPattern> getInferenceDrivingPatternAllowSet() {
|
public Set<ReasonerStatementPattern> getInferenceDrivingPatternAllowSet() {
|
||||||
return this.inferenceDrivingPatternAllowSet;
|
return this.inferenceDrivingPatternAllowSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setInferenceDrivingPatternAllowSet(Set<ObjectPropertyStatementPattern> patternSet) {
|
public void setInferenceDrivingPatternAllowSet(Set<ReasonerStatementPattern> patternSet) {
|
||||||
this.inferenceDrivingPatternAllowSet = patternSet;
|
this.inferenceDrivingPatternAllowSet = patternSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<ObjectPropertyStatementPattern> getInferenceDrivingPatternDenySet() {
|
public Set<ReasonerStatementPattern> getInferenceDrivingPatternDenySet() {
|
||||||
return this.inferenceDrivingPatternDenySet;
|
return this.inferenceDrivingPatternDenySet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setInferenceDrivingPatternDenySet(Set<ObjectPropertyStatementPattern> patternSet) {
|
public void setInferenceDrivingPatternDenySet(Set<ReasonerStatementPattern> patternSet) {
|
||||||
this.inferenceDrivingPatternDenySet = patternSet;
|
this.inferenceDrivingPatternDenySet = patternSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<ObjectPropertyStatementPattern> getInferenceReceivingPatternAllowSet() {
|
public Set<ReasonerStatementPattern> getInferenceReceivingPatternAllowSet() {
|
||||||
return this.inferenceReceivingPatternAllowSet;
|
return this.inferenceReceivingPatternAllowSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setInferenceReceivingPatternAllowSet(Set<ObjectPropertyStatementPattern> patternSet) {
|
public void setInferenceReceivingPatternAllowSet(Set<ReasonerStatementPattern> patternSet) {
|
||||||
this.inferenceReceivingPatternAllowSet = patternSet;
|
this.inferenceReceivingPatternAllowSet = patternSet;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
/* $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.rdf.model.Model;
|
||||||
|
import com.hp.hpl.jena.rdf.model.Property;
|
||||||
|
import com.hp.hpl.jena.rdf.model.Resource;
|
||||||
|
import com.hp.hpl.jena.rdf.model.Statement;
|
||||||
|
import com.hp.hpl.jena.shared.Lock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For now, this only models Object Properties.
|
||||||
|
*
|
||||||
|
* It should be easy to add Data Property patterns by making this abstract and
|
||||||
|
* creating two concrete subclasses.
|
||||||
|
*/
|
||||||
|
public class ReasonerStatementPattern {
|
||||||
|
public static final ReasonerStatementPattern ANY_OBJECT_PROPERTY = new ReasonerStatementPattern(
|
||||||
|
null, null, null);
|
||||||
|
|
||||||
|
public static ReasonerStatementPattern objectPattern(Property predicate) {
|
||||||
|
return new ReasonerStatementPattern(null, predicate, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ReasonerStatementPattern objectPattern(Statement stmt) {
|
||||||
|
if (!stmt.getObject().isResource()) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Object of stmt must be a resource.");
|
||||||
|
}
|
||||||
|
return new ReasonerStatementPattern(stmt.getSubject(),
|
||||||
|
stmt.getPredicate(), stmt.getObject().asResource());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Any or all of these may be null, which acts as a wild card.
|
||||||
|
*/
|
||||||
|
private final Resource subject;
|
||||||
|
private final Property predicate;
|
||||||
|
private final Resource object;
|
||||||
|
private final String toString;
|
||||||
|
|
||||||
|
private ReasonerStatementPattern(Resource subject, Property predicate,
|
||||||
|
Resource object) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.predicate = predicate;
|
||||||
|
this.object = object;
|
||||||
|
this.toString = buildToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Property getPredicate() {
|
||||||
|
return predicate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All fields must match, either by being equal, or by being a wild card.
|
||||||
|
*/
|
||||||
|
public boolean matches(ReasonerStatementPattern that) {
|
||||||
|
boolean sMatch = this.subject == null || that.subject == null
|
||||||
|
|| this.subject.equals(that.subject);
|
||||||
|
boolean pMatch = this.predicate == null || that.predicate == null
|
||||||
|
|| this.predicate.equals(that.predicate);
|
||||||
|
boolean oMatch = this.object == null || that.object == null
|
||||||
|
|| this.object.equals(that.object);
|
||||||
|
return sMatch && pMatch && oMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of statements from this model that match this pattern.
|
||||||
|
*/
|
||||||
|
public List<Statement> matchStatementsFromModel(Model m) {
|
||||||
|
m.enterCriticalSection(Lock.READ);
|
||||||
|
try {
|
||||||
|
return m.listStatements(subject, predicate, object).toList();
|
||||||
|
} finally {
|
||||||
|
m.leaveCriticalSection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String buildToString() {
|
||||||
|
return "ReasonerStatementPattern[subject="
|
||||||
|
+ (subject == null ? "*" : subject.toString()) + ", predicate="
|
||||||
|
+ (predicate == null ? "*" : predicate.toString())
|
||||||
|
+ ", object=" + (object == null ? "*" : object.toString())
|
||||||
|
+ "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return toString;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
/* $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 that time, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
/* $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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The functionality of a TBox reasoner.
|
||||||
|
*
|
||||||
|
* The reasoner will maintain its own TBox model. It will receive updates to
|
||||||
|
* that model and perform reasoning on it. It will answer queries about the
|
||||||
|
* contents of the model, when reasoning is complete.
|
||||||
|
*/
|
||||||
|
public interface TBoxReasoner {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 restrictions in the reasoner model, after updating and
|
||||||
|
* reasoning.
|
||||||
|
*/
|
||||||
|
List<Restriction> listRestrictions();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List all of the statements that satisfy any of these patterns, after
|
||||||
|
* updating and reasoning.
|
||||||
|
*/
|
||||||
|
List<Statement> filterResults(List<ReasonerStatementPattern> patternList);
|
||||||
|
|
||||||
|
public static class Status {
|
||||||
|
public static final Status SUCCESS = new Status(true, false, "");
|
||||||
|
public static final Status ERROR = new Status(true, true, "");
|
||||||
|
|
||||||
|
public static final Status inconsistent(String explanation) {
|
||||||
|
return new Status(false, false, explanation);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final boolean consistent;
|
||||||
|
private final boolean inErrorState;
|
||||||
|
private final String explanation;
|
||||||
|
|
||||||
|
private Status(boolean consistent, boolean inErrorState,
|
||||||
|
String explanation) {
|
||||||
|
this.consistent = consistent;
|
||||||
|
this.inErrorState = inErrorState;
|
||||||
|
this.explanation = explanation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConsistent() {
|
||||||
|
return consistent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInErrorState() {
|
||||||
|
return inErrorState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExplanation() {
|
||||||
|
return explanation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.tboxreasoner;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner.TBoxReasonerStatus;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* What calls can the ConfiguredReasonerListener make to drive the TBox
|
||||||
|
* reasoner?
|
||||||
|
*/
|
||||||
|
public interface TBoxReasonerDriver {
|
||||||
|
|
||||||
|
void runSynchronizer(TBoxChanges changeSet);
|
||||||
|
|
||||||
|
TBoxReasonerStatus getStatus();
|
||||||
|
}
|
|
@ -0,0 +1,253 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.tboxreasoner.impl;
|
||||||
|
|
||||||
|
import static edu.cornell.mannlib.vitro.webapp.utils.threads.VitroBackgroundThread.WorkLevel.IDLE;
|
||||||
|
import static edu.cornell.mannlib.vitro.webapp.utils.threads.VitroBackgroundThread.WorkLevel.WORKING;
|
||||||
|
|
||||||
|
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.TimeUnit;
|
||||||
|
|
||||||
|
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 edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner.TBoxReasonerStatus;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.ConfiguredReasonerListener;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.InferenceModelUpdater;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.PatternListBuilder;
|
||||||
|
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.TBoxReasoner;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasoner.Status;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasonerDriver;
|
||||||
|
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;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.utils.threads.VitroBackgroundThread;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The basic implementation of the TBoxReasonerDriver. It gets help from a
|
||||||
|
* listener, an executor, and a reasoner.
|
||||||
|
*
|
||||||
|
* Create a listener that listens for changes to the TBox, but filters them
|
||||||
|
* according to a ReasonerConfiguration object. The listener accumulates the
|
||||||
|
* changes it likes, until it detects an ending EditEvent. Then it passes the
|
||||||
|
* change set back to the driver.
|
||||||
|
*
|
||||||
|
* Each time a change set is received, a task is created and given to the
|
||||||
|
* executor to run. The executor is single-threaded, so the change sets are
|
||||||
|
* processed in sequence.
|
||||||
|
*
|
||||||
|
* Processing involves the following steps:
|
||||||
|
*
|
||||||
|
* 1. Telling the reasoner about the changes, so it can update its own internal
|
||||||
|
* ontology model.
|
||||||
|
*
|
||||||
|
* 2. Telling the reasoner to re-inference its model. A status is returned.
|
||||||
|
*
|
||||||
|
* 3. Asking the reasoner for the inferences from its model. As with the initial
|
||||||
|
* changes, these inferences are filtered according to the
|
||||||
|
* ReasonerConfiguration.
|
||||||
|
*
|
||||||
|
* 4. Synchronizing the applications TBox inferences model with the inferences
|
||||||
|
* obtained from the reasoner.
|
||||||
|
*
|
||||||
|
* ----------------------
|
||||||
|
*
|
||||||
|
* Possible optimization: if change sets come in quickly enough that the third
|
||||||
|
* set is received while the first is still being processed, it would be
|
||||||
|
* reasonable to merge the second and third sets into one.
|
||||||
|
*/
|
||||||
|
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 Set<TBoxChanges> pendingChangeSets;
|
||||||
|
|
||||||
|
private final ExecutorService executorService;
|
||||||
|
|
||||||
|
private final TBoxReasoner reasoner;
|
||||||
|
|
||||||
|
private TBoxReasoner.Status innerStatus;
|
||||||
|
|
||||||
|
public BasicTBoxReasonerDriver(OntModel assertionsModel,
|
||||||
|
Model inferencesModel, OntModel fullModel, TBoxReasoner 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.pendingChangeSets = Collections
|
||||||
|
.synchronizedSet(new HashSet<TBoxChanges>());
|
||||||
|
|
||||||
|
this.executorService = Executors.newFixedThreadPool(1,
|
||||||
|
new VitroBackgroundThread.Factory("TBoxReasoner"));
|
||||||
|
|
||||||
|
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 TBoxReasonerStatus getStatus() {
|
||||||
|
return new FullStatus(innerStatus, !pendingChangeSets.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void runSynchronizer(TBoxChanges changeSet) {
|
||||||
|
if (!changeSet.isEmpty()) {
|
||||||
|
executorService.execute(new ReasoningTask(changeSet));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shut down the thread that runs the reasoning tasks. Don't wait longer
|
||||||
|
* than 1 minute.
|
||||||
|
*/
|
||||||
|
public void shutdown() {
|
||||||
|
executorService.shutdown();
|
||||||
|
int waited = 0;
|
||||||
|
while (waited < 60 && !executorService.isTerminated()) {
|
||||||
|
try {
|
||||||
|
log.info("Waiting for TBox reasoner to terminate.");
|
||||||
|
executorService.awaitTermination(5, TimeUnit.SECONDS);
|
||||||
|
waited += 5;
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// Should never happen.
|
||||||
|
e.printStackTrace();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!executorService.isTerminated()) {
|
||||||
|
log.warn("Forcing TBox reasoner to terminate.");
|
||||||
|
executorService.shutdownNow();
|
||||||
|
}
|
||||||
|
if (!executorService.isTerminated()) {
|
||||||
|
log.error("TBox reasoner did not terminate.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
setWorking();
|
||||||
|
|
||||||
|
reasoner.updateReasonerModel(changes);
|
||||||
|
innerStatus = reasoner.performReasoning();
|
||||||
|
|
||||||
|
buildPatternList();
|
||||||
|
updateInferencesModel();
|
||||||
|
|
||||||
|
setIdle();
|
||||||
|
} finally {
|
||||||
|
pendingChangeSets.remove(changes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setWorking() {
|
||||||
|
Thread current = Thread.currentThread();
|
||||||
|
if (current instanceof VitroBackgroundThread) {
|
||||||
|
((VitroBackgroundThread) current).setWorkLevel(WORKING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setIdle() {
|
||||||
|
Thread current = Thread.currentThread();
|
||||||
|
if (current instanceof VitroBackgroundThread) {
|
||||||
|
((VitroBackgroundThread) current).setWorkLevel(IDLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class FullStatus implements TBoxReasonerStatus {
|
||||||
|
private final TBoxReasoner.Status reasonerStatus;
|
||||||
|
private final boolean reasoning;
|
||||||
|
|
||||||
|
public FullStatus(Status reasonerStatus, boolean reasoning) {
|
||||||
|
this.reasonerStatus = reasonerStatus;
|
||||||
|
this.reasoning = reasoning;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReasoning() {
|
||||||
|
return reasoning;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isConsistent() {
|
||||||
|
return reasonerStatus.isConsistent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInErrorState() {
|
||||||
|
return reasonerStatus.isInErrorState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getExplanation() {
|
||||||
|
String explanation = reasonerStatus.getExplanation();
|
||||||
|
return explanation == null ? "" : explanation;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
/* $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.TBoxReasoner;
|
||||||
|
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 PelletTBoxReasoner implements TBoxReasoner {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(PelletTBoxReasoner.class);
|
||||||
|
|
||||||
|
private final LockableOntModel lockablePelletModel;
|
||||||
|
|
||||||
|
public PelletTBoxReasoner(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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.tboxreasoner.impl.pellet;
|
||||||
|
|
||||||
|
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.TBOX_ASSERTIONS;
|
||||||
|
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.TBOX_INFERENCES;
|
||||||
|
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.TBOX_UNION;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import com.hp.hpl.jena.ontology.OntModel;
|
||||||
|
import com.hp.hpl.jena.ontology.Restriction;
|
||||||
|
import com.hp.hpl.jena.rdf.model.Model;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.modelaccess.ContextModelAccess;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.modules.Application;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.modules.ComponentStartupStatus;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner.TBoxReasonerModule;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner.TBoxReasonerStatus;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.ReasonerConfiguration;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.impl.BasicTBoxReasonerDriver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure a Pellet reasoner on the TBox.
|
||||||
|
*/
|
||||||
|
public class PelletTBoxReasonerModule implements TBoxReasonerModule {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(PelletTBoxReasonerModule.class);
|
||||||
|
|
||||||
|
private PelletTBoxReasoner reasoner;
|
||||||
|
private BasicTBoxReasonerDriver driver;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startup(Application application, ComponentStartupStatus ss) {
|
||||||
|
ServletContext ctx = application.getServletContext();
|
||||||
|
|
||||||
|
ContextModelAccess contextModels = ModelAccess.on(ctx);
|
||||||
|
OntModel tboxAssertionsModel = contextModels
|
||||||
|
.getOntModel(TBOX_ASSERTIONS);
|
||||||
|
Model tboxInferencesModel = contextModels.getOntModel(TBOX_INFERENCES)
|
||||||
|
.getBaseModel();
|
||||||
|
OntModel tboxUnionModel = contextModels.getOntModel(TBOX_UNION);
|
||||||
|
|
||||||
|
reasoner = new PelletTBoxReasoner(ReasonerConfiguration.DEFAULT);
|
||||||
|
driver = new BasicTBoxReasonerDriver(tboxAssertionsModel,
|
||||||
|
tboxInferencesModel, tboxUnionModel, reasoner,
|
||||||
|
ReasonerConfiguration.DEFAULT);
|
||||||
|
|
||||||
|
ss.info("Pellet reasoner connected for the TBox");
|
||||||
|
|
||||||
|
waitForTBoxReasoning();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TBoxReasonerStatus getStatus() {
|
||||||
|
if (driver == null) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"PelletTBoxReasonerModule has not been started.");
|
||||||
|
}
|
||||||
|
return driver.getStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Restriction> listRestrictions() {
|
||||||
|
if (reasoner == null) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"PelletTBoxReasonerModule has not been started.");
|
||||||
|
}
|
||||||
|
return reasoner.listRestrictions();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutdown(Application application) {
|
||||||
|
driver.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void waitForTBoxReasoning() {
|
||||||
|
int sleeps = 0;
|
||||||
|
// sleep at least once to make sure the TBox reasoning gets started
|
||||||
|
while ((0 == sleeps)
|
||||||
|
|| ((sleeps < 1000) && getStatus().isReasoning())) {
|
||||||
|
if (((sleeps - 1) % 10) == 0) { // print message at 10 second
|
||||||
|
// intervals
|
||||||
|
log.info("Waiting for initial TBox reasoning to complete");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// This should never happen.
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
sleeps++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,8 @@ import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
@ -106,4 +108,25 @@ public class VitroBackgroundThread extends Thread {
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A factory class, for use in Executors, that creates threads with
|
||||||
|
* successive names.
|
||||||
|
*/
|
||||||
|
public static class Factory implements ThreadFactory{
|
||||||
|
private final String threadName;
|
||||||
|
private final AtomicInteger index;
|
||||||
|
|
||||||
|
public Factory(String threadName) {
|
||||||
|
this.threadName = threadName;
|
||||||
|
this.index = new AtomicInteger();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Thread newThread(Runnable r) {
|
||||||
|
return new VitroBackgroundThread(r, threadName + "_" + index.getAndIncrement());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,19 @@
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.controller.api.sparqlquery;
|
package edu.cornell.mannlib.vitro.webapp.controller.api.sparqlquery;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -25,6 +33,20 @@ import edu.cornell.mannlib.vitro.webapp.utils.http.NotAcceptableException;
|
||||||
* formats.
|
* formats.
|
||||||
*/
|
*/
|
||||||
public class SparqlQueryApiExecutorTest extends AbstractTestClass {
|
public class SparqlQueryApiExecutorTest extends AbstractTestClass {
|
||||||
|
|
||||||
|
/* SPARQL response types */
|
||||||
|
private static final String ACCEPT_TEXT = "text/plain";
|
||||||
|
private static final String ACCEPT_CSV = "text/csv";
|
||||||
|
private static final String ACCEPT_TSV = "text/tab-separated-values";
|
||||||
|
private static final String ACCEPT_SPARQL_XML = "application/sparql-results+xml";
|
||||||
|
private static final String ACCEPT_SPARQL_JSON = "application/sparql-results+json";
|
||||||
|
|
||||||
|
/* RDF result types */
|
||||||
|
private static final String ACCEPT_RDFXML = "application/rdf+xml";
|
||||||
|
private static final String ACCEPT_N3 = "text/n3";
|
||||||
|
private static final String ACCEPT_TURTLE = "text/turtle";
|
||||||
|
private static final String ACCEPT_JSON = "application/json";
|
||||||
|
|
||||||
private static final String MODEL_CONTENTS_N3 = "" //
|
private static final String MODEL_CONTENTS_N3 = "" //
|
||||||
+ "<http://here.edu/subject> \n"
|
+ "<http://here.edu/subject> \n"
|
||||||
+ " <http://here.edu/predicate> <http://here.edu/object> ."
|
+ " <http://here.edu/predicate> <http://here.edu/object> ."
|
||||||
|
@ -201,24 +223,24 @@ public class SparqlQueryApiExecutorTest extends AbstractTestClass {
|
||||||
|
|
||||||
@Test(expected = NullPointerException.class)
|
@Test(expected = NullPointerException.class)
|
||||||
public void nullRdfService() throws Exception {
|
public void nullRdfService() throws Exception {
|
||||||
SparqlQueryApiExecutor.instance(null, SELECT_ALL_QUERY, "text/plain");
|
SparqlQueryApiExecutor.instance(null, SELECT_ALL_QUERY, ACCEPT_TEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = NullPointerException.class)
|
@Test(expected = NullPointerException.class)
|
||||||
public void nullQuery() throws Exception {
|
public void nullQuery() throws Exception {
|
||||||
SparqlQueryApiExecutor.instance(rdfService, null, "text/plain");
|
SparqlQueryApiExecutor.instance(rdfService, null, ACCEPT_TEXT);
|
||||||
fail("nullQuery not implemented");
|
fail("nullQuery not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = QueryParseException.class)
|
@Test(expected = QueryParseException.class)
|
||||||
public void emptyQuery() throws Exception {
|
public void emptyQuery() throws Exception {
|
||||||
SparqlQueryApiExecutor.instance(rdfService, "", "text/plain");
|
SparqlQueryApiExecutor.instance(rdfService, "", ACCEPT_TEXT);
|
||||||
fail("emptyQuery not implemented");
|
fail("emptyQuery not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = QueryParseException.class)
|
@Test(expected = QueryParseException.class)
|
||||||
public void cantParseQuery() throws Exception {
|
public void cantParseQuery() throws Exception {
|
||||||
SparqlQueryApiExecutor.instance(rdfService, "BOGUS", "text/plain");
|
SparqlQueryApiExecutor.instance(rdfService, "BOGUS", ACCEPT_TEXT);
|
||||||
fail("cantParseQuery not implemented");
|
fail("cantParseQuery not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,179 +259,177 @@ public class SparqlQueryApiExecutorTest extends AbstractTestClass {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void selectToText() throws Exception {
|
public void selectToText() throws Exception {
|
||||||
executeQuery("select to text", SELECT_ALL_QUERY, "text/plain",
|
executeQuery("select to text", SELECT_ALL_QUERY, ACCEPT_TEXT,
|
||||||
SELECT_RESULT_TEXT);
|
SELECT_RESULT_TEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void selectToCsv() throws Exception {
|
public void selectToCsv() throws Exception {
|
||||||
executeQuery("select to csv", SELECT_ALL_QUERY, "text/csv",
|
executeQuery("select to csv", SELECT_ALL_QUERY, ACCEPT_CSV,
|
||||||
SELECT_RESULT_CSV);
|
SELECT_RESULT_CSV);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void selectToTsv() throws Exception {
|
public void selectToTsv() throws Exception {
|
||||||
executeQuery("select to tsv", SELECT_ALL_QUERY,
|
executeQuery("select to tsv", SELECT_ALL_QUERY, ACCEPT_TSV,
|
||||||
"text/tab-separated-values", SELECT_RESULT_TSV);
|
SELECT_RESULT_TSV);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void selectToXml() throws Exception {
|
public void selectToXml() throws Exception {
|
||||||
executeQuery("select to xml", SELECT_ALL_QUERY,
|
executeQuery("select to xml", SELECT_ALL_QUERY, ACCEPT_SPARQL_XML,
|
||||||
"application/sparql-results+xml", SELECT_RESULT_XML);
|
SELECT_RESULT_XML);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void selectToJson() throws Exception {
|
public void selectToJson() throws Exception {
|
||||||
executeQuery("select to json", SELECT_ALL_QUERY,
|
executeQuery("select to json", SELECT_ALL_QUERY, ACCEPT_SPARQL_JSON,
|
||||||
"application/sparql-results+json", SELECT_RESULT_JSON);
|
SELECT_RESULT_JSON);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void selectWithInvalidContentType() throws Exception {
|
public void selectWithInvalidContentType() throws Exception {
|
||||||
executeWithInvalidAcceptHeader("select with application/rdf+xml",
|
executeWithInvalidAcceptHeader("select with application/rdf+xml",
|
||||||
SELECT_ALL_QUERY, "application/rdf+xml");
|
SELECT_ALL_QUERY, ACCEPT_RDFXML);
|
||||||
executeWithInvalidAcceptHeader("select with text/n3", SELECT_ALL_QUERY,
|
executeWithInvalidAcceptHeader("select with text/n3", SELECT_ALL_QUERY,
|
||||||
"text/n3");
|
ACCEPT_N3);
|
||||||
executeWithInvalidAcceptHeader("select with text/turtle",
|
executeWithInvalidAcceptHeader("select with text/turtle",
|
||||||
SELECT_ALL_QUERY, "text/turtle");
|
SELECT_ALL_QUERY, ACCEPT_TURTLE);
|
||||||
executeWithInvalidAcceptHeader("select with application/json",
|
executeWithInvalidAcceptHeader("select with application/json",
|
||||||
SELECT_ALL_QUERY, "application/json");
|
SELECT_ALL_QUERY, ACCEPT_JSON);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void askToText() throws Exception {
|
public void askToText() throws Exception {
|
||||||
executeQuery("ask to text", ASK_ALL_QUERY, "text/plain",
|
executeQuery("ask to text", ASK_ALL_QUERY, ACCEPT_TEXT, ASK_RESULT_TEXT);
|
||||||
ASK_RESULT_TEXT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void askToCsv() throws Exception {
|
public void askToCsv() throws Exception {
|
||||||
executeQuery("ask to csv", ASK_ALL_QUERY, "text/csv", ASK_RESULT_CSV);
|
executeQuery("ask to csv", ASK_ALL_QUERY, ACCEPT_CSV, ASK_RESULT_CSV);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void askToTsv() throws Exception {
|
public void askToTsv() throws Exception {
|
||||||
executeQuery("ask to tsv", ASK_ALL_QUERY, "text/tab-separated-values",
|
executeQuery("ask to tsv", ASK_ALL_QUERY, ACCEPT_TSV, ASK_RESULT_TSV);
|
||||||
ASK_RESULT_TSV);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void askToXml() throws Exception {
|
public void askToXml() throws Exception {
|
||||||
executeQuery("ask to xml", ASK_ALL_QUERY,
|
executeQuery("ask to xml", ASK_ALL_QUERY, ACCEPT_SPARQL_XML,
|
||||||
"application/sparql-results+xml", ASK_RESULT_XML);
|
ASK_RESULT_XML);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void askToJson() throws Exception {
|
public void askToJson() throws Exception {
|
||||||
executeQuery("ask to json", ASK_ALL_QUERY,
|
executeQuery("ask to json", ASK_ALL_QUERY, ACCEPT_SPARQL_JSON,
|
||||||
"application/sparql-results+json", ASK_RESULT_JSON);
|
ASK_RESULT_JSON);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void askWithInvalidAcceptHeader() throws Exception {
|
public void askWithInvalidAcceptHeader() throws Exception {
|
||||||
executeWithInvalidAcceptHeader("ask with application/rdf+xml",
|
executeWithInvalidAcceptHeader("ask with application/rdf+xml",
|
||||||
ASK_ALL_QUERY, "application/rdf+xml");
|
ASK_ALL_QUERY, ACCEPT_RDFXML);
|
||||||
executeWithInvalidAcceptHeader("ask with text/n3", ASK_ALL_QUERY,
|
executeWithInvalidAcceptHeader("ask with text/n3", ASK_ALL_QUERY,
|
||||||
"text/n3");
|
ACCEPT_N3);
|
||||||
executeWithInvalidAcceptHeader("ask with text/turtle", ASK_ALL_QUERY,
|
executeWithInvalidAcceptHeader("ask with text/turtle", ASK_ALL_QUERY,
|
||||||
"text/turtle");
|
ACCEPT_TURTLE);
|
||||||
executeWithInvalidAcceptHeader("ask with application/json",
|
executeWithInvalidAcceptHeader("ask with application/json",
|
||||||
ASK_ALL_QUERY, "application/json");
|
ASK_ALL_QUERY, ACCEPT_JSON);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void constructToText() throws Exception {
|
public void constructToText() throws Exception {
|
||||||
executeQuery("construct to text", CONSTRUCT_ALL_QUERY, "text/plain",
|
executeQuery("construct to text", CONSTRUCT_ALL_QUERY, ACCEPT_TEXT,
|
||||||
CONSTRUCT_RESULT_TEXT);
|
CONSTRUCT_RESULT_TEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void constructToRdfXml() throws Exception {
|
public void constructToRdfXml() throws Exception {
|
||||||
executeQuery("construct to rdf/xml", CONSTRUCT_ALL_QUERY,
|
executeQuery("construct to rdf/xml", CONSTRUCT_ALL_QUERY,
|
||||||
"application/rdf+xml", CONSTRUCT_RESULT_RDFXML);
|
ACCEPT_RDFXML, CONSTRUCT_RESULT_RDFXML);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void constructToN3() throws Exception {
|
public void constructToN3() throws Exception {
|
||||||
executeQuery("construct to n3", CONSTRUCT_ALL_QUERY, "text/n3",
|
executeQuery("construct to n3", CONSTRUCT_ALL_QUERY, ACCEPT_N3,
|
||||||
CONSTRUCT_RESULT_N3);
|
CONSTRUCT_RESULT_N3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void constructToTurtle() throws Exception {
|
public void constructToTurtle() throws Exception {
|
||||||
executeQuery("construct to turtle", CONSTRUCT_ALL_QUERY, "text/turtle",
|
executeQuery("construct to turtle", CONSTRUCT_ALL_QUERY, ACCEPT_TURTLE,
|
||||||
CONSTRUCT_RESULT_TURTLE);
|
CONSTRUCT_RESULT_TURTLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void constructToJsonld() throws Exception {
|
public void constructToJsonld() throws Exception {
|
||||||
executeQuery("construct to JSON-LD", CONSTRUCT_ALL_QUERY,
|
executeQuery("construct to JSON-LD", CONSTRUCT_ALL_QUERY, ACCEPT_JSON,
|
||||||
"application/json", CONSTRUCT_RESULT_JSONLD);
|
CONSTRUCT_RESULT_JSONLD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void constructWithInvalidAcceptHeader() throws Exception {
|
public void constructWithInvalidAcceptHeader() throws Exception {
|
||||||
executeWithInvalidAcceptHeader("construct with text/csv",
|
executeWithInvalidAcceptHeader("construct with text/csv",
|
||||||
CONSTRUCT_ALL_QUERY, "text/csv");
|
CONSTRUCT_ALL_QUERY, ACCEPT_CSV);
|
||||||
executeWithInvalidAcceptHeader("construct with text/tsv",
|
executeWithInvalidAcceptHeader("construct with text/tsv",
|
||||||
CONSTRUCT_ALL_QUERY, "text/tsv");
|
CONSTRUCT_ALL_QUERY, "text/tsv");
|
||||||
executeWithInvalidAcceptHeader(
|
executeWithInvalidAcceptHeader(
|
||||||
"construct with application/sparql-results+xml",
|
"construct with application/sparql-results+xml",
|
||||||
CONSTRUCT_ALL_QUERY, "application/sparql-results+xml");
|
CONSTRUCT_ALL_QUERY, ACCEPT_SPARQL_XML);
|
||||||
executeWithInvalidAcceptHeader(
|
executeWithInvalidAcceptHeader(
|
||||||
"construct with application/sparql-results+json",
|
"construct with application/sparql-results+json",
|
||||||
CONSTRUCT_ALL_QUERY, "application/sparql-results+json");
|
CONSTRUCT_ALL_QUERY, ACCEPT_SPARQL_JSON);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void describeToText() throws Exception {
|
public void describeToText() throws Exception {
|
||||||
executeQuery("describe to text", DESCRIBE_ALL_QUERY, "text/plain",
|
executeQuery("describe to text", DESCRIBE_ALL_QUERY, ACCEPT_TEXT,
|
||||||
DESCRIBE_RESULT_TEXT);
|
DESCRIBE_RESULT_TEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void describeToRdfXml() throws Exception {
|
public void describeToRdfXml() throws Exception {
|
||||||
executeQuery("describe to rdf/xml", DESCRIBE_ALL_QUERY,
|
executeQuery("describe to rdf/xml", DESCRIBE_ALL_QUERY, ACCEPT_RDFXML,
|
||||||
"application/rdf+xml", DESCRIBE_RESULT_RDFXML);
|
DESCRIBE_RESULT_RDFXML);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void describeToN3() throws Exception {
|
public void describeToN3() throws Exception {
|
||||||
executeQuery("describe to n3", DESCRIBE_ALL_QUERY, "text/n3",
|
executeQuery("describe to n3", DESCRIBE_ALL_QUERY, ACCEPT_N3,
|
||||||
DESCRIBE_RESULT_N3);
|
DESCRIBE_RESULT_N3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void describeToTurtle() throws Exception {
|
public void describeToTurtle() throws Exception {
|
||||||
executeQuery("describe to turtle", DESCRIBE_ALL_QUERY, "text/turtle",
|
executeQuery("describe to turtle", DESCRIBE_ALL_QUERY, ACCEPT_TURTLE,
|
||||||
DESCRIBE_RESULT_TURTLE);
|
DESCRIBE_RESULT_TURTLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void describeToJsonld() throws Exception {
|
public void describeToJsonld() throws Exception {
|
||||||
executeQuery("describe to JSON-LD", DESCRIBE_ALL_QUERY,
|
executeQuery("describe to JSON-LD", DESCRIBE_ALL_QUERY, ACCEPT_JSON,
|
||||||
"application/json", DESCRIBE_RESULT_JSONLD);
|
DESCRIBE_RESULT_JSONLD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void describeWithInvalidAcceptHeader() throws Exception {
|
public void describeWithInvalidAcceptHeader() throws Exception {
|
||||||
executeWithInvalidAcceptHeader("describe with text/csv",
|
executeWithInvalidAcceptHeader("describe with text/csv",
|
||||||
DESCRIBE_ALL_QUERY, "text/csv");
|
DESCRIBE_ALL_QUERY, ACCEPT_CSV);
|
||||||
executeWithInvalidAcceptHeader("describe with text/tsv",
|
executeWithInvalidAcceptHeader("describe with text/tsv",
|
||||||
DESCRIBE_ALL_QUERY, "text/tsv");
|
DESCRIBE_ALL_QUERY, "text/tsv");
|
||||||
executeWithInvalidAcceptHeader(
|
executeWithInvalidAcceptHeader(
|
||||||
"describe with application/sparql-results+xml",
|
"describe with application/sparql-results+xml",
|
||||||
DESCRIBE_ALL_QUERY, "application/sparql-results+xml");
|
DESCRIBE_ALL_QUERY, ACCEPT_SPARQL_XML);
|
||||||
executeWithInvalidAcceptHeader(
|
executeWithInvalidAcceptHeader(
|
||||||
"describe with application/sparql-results+json",
|
"describe with application/sparql-results+json",
|
||||||
DESCRIBE_ALL_QUERY, "application/sparql-results+json");
|
DESCRIBE_ALL_QUERY, ACCEPT_SPARQL_JSON);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
@ -424,7 +444,87 @@ public class SparqlQueryApiExecutorTest extends AbstractTestClass {
|
||||||
rdfService, queryString, acceptHeader);
|
rdfService, queryString, acceptHeader);
|
||||||
executor.executeAndFormat(out);
|
executor.executeAndFormat(out);
|
||||||
|
|
||||||
assertEquals(message, expected.replaceAll("\\s+", " "), out.toString().replaceAll("\\s+", " "));
|
if (ACCEPT_RDFXML.equals(acceptHeader)) {
|
||||||
|
assertEquivalentRdfxml(message, expected, out.toString());
|
||||||
|
} else if (ACCEPT_TURTLE.equals(acceptHeader)) {
|
||||||
|
assertEquivalentTurtle(message, expected, out.toString());
|
||||||
|
} else if (ACCEPT_N3.equals(acceptHeader)) {
|
||||||
|
assertEquivalentN3(message, expected, out.toString());
|
||||||
|
} else {
|
||||||
|
assertEqualsIgnoreWhiteSpace(message, expected, out.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RDF/XML namespaces may come in any order, so separate them out and test
|
||||||
|
* accordingly.
|
||||||
|
*/
|
||||||
|
private void assertEquivalentRdfxml(String message, String expected,
|
||||||
|
String actual) {
|
||||||
|
assertEquals(message, getRdfxmlNamespaces(expected),
|
||||||
|
getRdfxmlNamespaces(actual));
|
||||||
|
assertEqualsIgnoreWhiteSpace(message, omitRdfxmlNamespaces(expected),
|
||||||
|
omitRdfxmlNamespaces(actual));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<String> getRdfxmlNamespaces(String rdfxml) {
|
||||||
|
Set<String> namespaces = new TreeSet<>();
|
||||||
|
Pattern p = Pattern.compile("xmlns:\\w+=\\\"[^\\\"]*\\\"");
|
||||||
|
Matcher m = p.matcher(rdfxml);
|
||||||
|
while (m.find()) {
|
||||||
|
namespaces.add(m.group());
|
||||||
|
}
|
||||||
|
return namespaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String omitRdfxmlNamespaces(String rdfxml) {
|
||||||
|
return rdfxml.replaceAll("xmlns:\\w+=\\\"[^\\\"]*\\\"", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TTL prefix lines may come in any order, so separate them out and test
|
||||||
|
* accordingly.
|
||||||
|
*/
|
||||||
|
private void assertEquivalentTurtle(String message, String expected,
|
||||||
|
String actual) {
|
||||||
|
assertEquals(message, getTurtlePrefixes(expected),
|
||||||
|
getTurtlePrefixes(actual));
|
||||||
|
assertEqualsIgnoreWhiteSpace(message, getTurtleRemainder(expected),
|
||||||
|
getTurtleRemainder(actual));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* N3 is like TTL, as far as prefix lines are concerned.
|
||||||
|
*/
|
||||||
|
private void assertEquivalentN3(String message, String expected,
|
||||||
|
String actual) {
|
||||||
|
assertEquivalentTurtle(message, expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<String> getTurtlePrefixes(String ttl) {
|
||||||
|
Set<String> prefixes = new TreeSet<>();
|
||||||
|
for (String line : ttl.split("[\\n\\r]+")) {
|
||||||
|
if (line.startsWith("@prefix")) {
|
||||||
|
prefixes.add(line.replaceAll("\\s+", " "));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return prefixes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getTurtleRemainder(String ttl) {
|
||||||
|
List<String> remainder = new ArrayList<>();
|
||||||
|
for (String line : ttl.split("[\\n\\r]+")) {
|
||||||
|
if (!line.startsWith("@prefix")) {
|
||||||
|
remainder.add(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return StringUtils.join(remainder, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertEqualsIgnoreWhiteSpace(String message, String expected,
|
||||||
|
String actual) {
|
||||||
|
assertEquals(message, expected.replaceAll("\\s+", " "),
|
||||||
|
actual.replaceAll("\\s+", " "));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void executeWithInvalidAcceptHeader(String message,
|
private void executeWithInvalidAcceptHeader(String message,
|
||||||
|
|
|
@ -970,7 +970,7 @@ public class ConfigurationBeanLoaderTest extends AbstractTestClass {
|
||||||
// Nothing.
|
// Nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AGoodApple implements OneBadAppleSpoilsTheBunch {
|
public static class AGoodApple implements OneBadAppleSpoilsTheBunch {
|
||||||
// Nothing
|
// Nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,10 @@ import java.io.StringReader;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
import org.hamcrest.CoreMatchers;
|
||||||
import org.hamcrest.Matcher;
|
import org.hamcrest.Matcher;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.matchers.JUnitMatchers;
|
|
||||||
import org.junit.rules.ExpectedException;
|
import org.junit.rules.ExpectedException;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
|
import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
|
||||||
|
@ -71,7 +71,7 @@ public class CustomListViewConfigFileTest extends AbstractTestClass {
|
||||||
@Test
|
@Test
|
||||||
public void invalidXml() throws InvalidConfigurationException {
|
public void invalidXml() throws InvalidConfigurationException {
|
||||||
suppressSyserr(); // catch the error report from the XML parser
|
suppressSyserr(); // catch the error report from the XML parser
|
||||||
expectException(JUnitMatchers
|
expectException(CoreMatchers
|
||||||
.containsString("Config file is not valid XML:"));
|
.containsString("Config file is not valid XML:"));
|
||||||
readConfigFile("<unbalancedTag>");
|
readConfigFile("<unbalancedTag>");
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import edu.cornell.mannlib.vitro.webapp.modules.Application;
|
||||||
import edu.cornell.mannlib.vitro.webapp.modules.fileStorage.FileStorage;
|
import edu.cornell.mannlib.vitro.webapp.modules.fileStorage.FileStorage;
|
||||||
import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor;
|
import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor;
|
||||||
import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngine;
|
import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngine;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner.TBoxReasonerModule;
|
||||||
import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.ConfigurationTripleSource;
|
import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.ConfigurationTripleSource;
|
||||||
import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.ContentTripleSource;
|
import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.ContentTripleSource;
|
||||||
|
|
||||||
|
@ -101,4 +102,11 @@ public class ApplicationStub implements Application {
|
||||||
"ApplicationStub.getConfigurationTripleSource() not implemented.");
|
"ApplicationStub.getConfigurationTripleSource() not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TBoxReasonerModule getTBoxReasonerModule() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
throw new RuntimeException("ApplicationStub.getTBoxReasonerModule() not implemented.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ edu.cornell.mannlib.vitro.webapp.servlet.setup.RemoveObsoletePermissions
|
||||||
|
|
||||||
edu.cornell.mannlib.vitro.webapp.servlet.setup.FileGraphSetup
|
edu.cornell.mannlib.vitro.webapp.servlet.setup.FileGraphSetup
|
||||||
|
|
||||||
|
edu.cornell.mannlib.vitro.webapp.application.ApplicationImpl$ReasonersSetup
|
||||||
edu.cornell.mannlib.vitro.webapp.servlet.setup.SimpleReasonerSetup
|
edu.cornell.mannlib.vitro.webapp.servlet.setup.SimpleReasonerSetup
|
||||||
|
|
||||||
#edu.cornell.mannlib.vitro.webapp.servlet.setup.UpdateKnowledgeBase
|
#edu.cornell.mannlib.vitro.webapp.servlet.setup.UpdateKnowledgeBase
|
||||||
|
|
|
@ -6,11 +6,11 @@
|
||||||
<section class="pageBodyGroup" role="region">
|
<section class="pageBodyGroup" role="region">
|
||||||
<h3>${i18n().ontology_editor}</h3>
|
<h3>${i18n().ontology_editor}</h3>
|
||||||
|
|
||||||
<#if ontologyEditor.pellet?has_content>
|
<#if ontologyEditor.tboxReasonerStatus?has_content>
|
||||||
<div class="notice">
|
<div class="notice">
|
||||||
<p>${ontologyEditor.pellet.error}</p>
|
<p>${ontologyEditor.tboxReasonerStatus.error}</p>
|
||||||
<#if ontologyEditor.pellet.explanation?has_content>
|
<#if ontologyEditor.tboxReasonerStatus.explanation?has_content>
|
||||||
<p>${i18n().cause} ${ontologyEditor.pellet.explanation}</p>
|
<p>${i18n().cause} ${ontologyEditor.tboxReasonerStatus.explanation}</p>
|
||||||
</#if>
|
</#if>
|
||||||
</div>
|
</div>
|
||||||
</#if>
|
</#if>
|
||||||
|
|
Loading…
Add table
Reference in a new issue