VIVO-778 Use JFact as the TBox reasoner, instead of Pellet.

There are still some differences between the two, and I expect  some answers from Jon and Brian regarding irregularities in the ontologies.

The Pellet libraries have not yet been removed.
This commit is contained in:
Jim Blake 2014-12-17 17:44:21 -05:00
parent dad574d33a
commit 8382c2620a
12 changed files with 527 additions and 2804 deletions

View file

@ -35,7 +35,8 @@ log4j.rootLogger=INFO, AllAppender
# 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.servlet.setup.UpdateKnowledgeBase=DEBUG
log4j.logger.edu.cornell.mannlib.vitro.webapp.servlet.setup.UpdateKnowledgeBase=WARN
log4j.logger.org.semanticweb.owlapi.rdf.rdfxml.parser.OWLRDFConsumer=WARN
# Spring as a whole is too chatty to display INFO messages.
log4j.logger.org.springframework=WARN

Binary file not shown.

Binary file not shown.

BIN
webapp/lib/jfact-4.0.0.jar Normal file

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load diff

View file

@ -1,116 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.servlet.setup;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
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.OntModelSpec;
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.application.ApplicationUtils;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames;
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
/**
* Safety Net:
*
* Insure that the inferred TBox is the same as it was before we started messing
* with things.
*
* KLUGE -- this shouldn't go into production.
*
* KLUGE -- in production, startup_listeners shouldn't mention this.
*/
public class TBoxReasonerSmokeTest implements ServletContextListener {
private static final Log log = LogFactory
.getLog(TBoxReasonerSmokeTest.class);
@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext ctx = sce.getServletContext();
StartupStatus ss = StartupStatus.getBean(ctx);
OntModel savedInferencesModel = ModelFactory
.createOntologyModel(OntModelSpec.OWL_MEM);
try (InputStream in = new FileInputStream(locateSavedInferencesFile())) {
savedInferencesModel.read(in, null, "N3");
} catch (IOException e) {
ss.fatal(this, "Can't read saved inferences", e);
}
OntModel tboxInferencesModel = ModelAccess.on(sce.getServletContext())
.getOntModel(ModelNames.TBOX_INFERENCES);
if (savedInferencesModel.isIsomorphicWith(tboxInferencesModel)) {
ss.info(this, "TBox inferences matches saved.");
} else {
dumpDifferences(savedInferencesModel, tboxInferencesModel);
ss.fatal(this, "TBox inferences does not match saved.");
}
}
private void dumpDifferences(OntModel savedInferencesModel,
OntModel tboxInferencesModel) {
Model missingStatements = ModelFactory.createDefaultModel();
for (Statement stmt : savedInferencesModel.listStatements().toList()) {
if (!tboxInferencesModel.contains(stmt)) {
missingStatements.add(stmt);
}
}
Model extraStatements = ModelFactory.createDefaultModel();
for (Statement stmt : tboxInferencesModel.listStatements().toList()) {
if (!savedInferencesModel.contains(stmt)) {
extraStatements.add(stmt);
}
}
log.error("inferences: " + tboxInferencesModel.size() + ", saved: "
+ savedInferencesModel.size() + ", missing: "
+ missingStatements.size() + ", extra: "
+ extraStatements.size());
String missing = "";
for (Statement stmt : missingStatements.listStatements().toList()) {
missing += "\n " + stmt;
}
log.error("missing statements:" + missing);
String extras = "";
for (Statement stmt : extraStatements.listStatements().toList()) {
extras += "\n " + stmt;
}
log.error("extra statements:" + extras);
}
private File locateSavedInferencesFile() {
String homeDirPath = ApplicationUtils.instance().getHomeDirectory()
.getPath().toString();
Path savedInferencesPath = Paths.get(homeDirPath, "rdf", "tbox",
"savedInferences.n3");
return savedInferencesPath.toFile();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
// Nothing to do
}
}

View file

@ -62,11 +62,11 @@ public class InferenceModelUpdater {
* to the inferences model.
*/
public void update(List<ReasonerStatementPattern> patternList) {
List<Statement> filteredReasonerModel = reasoner
List<Statement> filteredReasonerStatements = reasoner
.filterResults(patternList);
addNewInferences(filteredReasonerModel);
addNewInferences(filteredReasonerStatements);
removeOldInferences(filterInferencesModel(patternList),
filteredReasonerModel);
filteredReasonerStatements);
log.debug("Added: " + addCount + ", Retracted: " + retractCount);
}

View file

@ -0,0 +1,340 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.tboxreasoner.impl;
import static com.hp.hpl.jena.rdf.model.ResourceFactory.createProperty;
import static com.hp.hpl.jena.rdf.model.ResourceFactory.createResource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLDataProperty;
import org.semanticweb.owlapi.model.OWLNamedObject;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
import org.semanticweb.owlapi.reasoner.OWLReasoner;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.Resource;
/**
* Build a model of inferred statements by walking through the ontology as
* represented in the reasoner.
*
* TODO Get rid of the kluges. Either decide that they are not necessary, or
* give them full status.
*/
public class TBoxInferencesAccumulator {
private static final Log log = LogFactory
.getLog(TBoxInferencesAccumulator.class);
private static final Property RDFS_TYPE = createProperty("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
private static final Resource OWL_CLASS = createResource("http://www.w3.org/2002/07/owl#Class");
private static final Property OWL_EQUIVALENT_CLASS = createProperty("http://www.w3.org/2002/07/owl#equivalentClass");
private static final Property OWL_DISJOINT_WITH = createProperty("http://www.w3.org/2002/07/owl#disjointWith");
private static final Property OWL_SUBCLASS_OF = createProperty("http://www.w3.org/2000/01/rdf-schema#subClassOf");
private static final Property OWL_SUBPROPERTY_OF = createProperty("http://www.w3.org/2000/01/rdf-schema#subPropertyOf");
private static final Property OWL_INVERSE_OF = createProperty("http://www.w3.org/2002/07/owl#inverseOf");
public Model populateModelFromReasonerQueries(OWLReasoner reasoner) {
Model m = ModelFactory.createDefaultModel();
populateClasses(reasoner, m);
populateObjectProperties(reasoner, m);
populateDataProperties(reasoner, m);
klugeOwlInvariants(m);
klugeMistakes(m);
return m;
}
private void populateClasses(OWLReasoner r, Model m) {
OWLClass bottom = r.getBottomClassNode().getRepresentativeElement();
for (OWLClass c : r.getSuperClasses(bottom, false).getFlattened()) {
populateClass(c, r, m);
}
}
private void populateClass(OWLClass c, OWLReasoner r, Model m) {
log.debug("Owl class: " + c);
populateClassType(c, m);
populateEquivalentClasses(c, r, m);
populateDisjointClasses(c, r, m);
populateSubClasses(c, r, m);
}
private void populateClassType(OWLClass c, Model m) {
log.debug(c + " is a class.");
m.add(toResource(c), RDFS_TYPE, OWL_CLASS);
}
private void populateEquivalentClasses(OWLClass c, OWLReasoner r, Model m) {
for (OWLClass equiv : r.getEquivalentClasses(c).getEntities()) {
log.debug("Equivalent class: " + c + ", " + equiv);
m.add(toResource(c), OWL_EQUIVALENT_CLASS, toResource(equiv));
}
}
private void populateDisjointClasses(OWLClass c, OWLReasoner r, Model m) {
for (OWLClass d : r.getDisjointClasses(c).getFlattened()) {
if (!d.isOWLNothing()) {
log.debug("Disjoint class: " + c + ", " + d);
m.add(toResource(c), OWL_DISJOINT_WITH, toResource(d));
}
}
}
private void populateSubClasses(OWLClass c, OWLReasoner r, Model m) {
for (OWLClass sub : r.getSubClasses(c, false).getFlattened()) {
log.debug(sub + " is subclass of " + c);
if (!sub.isOWLNothing()) {
m.add(toResource(sub), OWL_SUBCLASS_OF, toResource(c));
}
}
}
private void populateObjectProperties(OWLReasoner r, Model m) {
OWLObjectPropertyExpression bottom = r.getBottomObjectPropertyNode()
.getRepresentativeElement();
populateObjectProperty(bottom, r, m);
for (OWLObjectPropertyExpression op : r.getSuperObjectProperties(
bottom, false).getFlattened()) {
populateObjectProperty(op, r, m);
}
}
private void populateObjectProperty(OWLObjectPropertyExpression ope,
OWLReasoner r, Model m) {
if (!ope.isAnonymous()) {
OWLObjectProperty op = ope.asOWLObjectProperty();
log.debug("object property: " + op);
populateObjectSubProperties(op, r, m);
populateObjectInverseProperties(op, r, m);
}
}
private void populateObjectSubProperties(OWLObjectProperty op,
OWLReasoner r, Model m) {
for (OWLObjectPropertyExpression subOPE : r.getSubObjectProperties(op,
false).getFlattened()) {
if (!subOPE.isAnonymous()) {
OWLObjectProperty subOP = subOPE.asOWLObjectProperty();
log.debug(subOP + " object sub-property of " + op);
m.add(toResource(subOP), OWL_SUBPROPERTY_OF, toResource(op));
}
}
// getSubObjectProperties is strict, so add the reflexive statement.
log.debug(op + " object sub-property of " + op);
m.add(toResource(op), OWL_SUBPROPERTY_OF, toResource(op));
}
private void populateObjectInverseProperties(OWLObjectProperty op,
OWLReasoner r, Model m) {
for (OWLObjectPropertyExpression inverseE : r
.getInverseObjectProperties(op)) {
if (!inverseE.isAnonymous()
&& !inverseE.isOWLBottomObjectProperty()
&& !inverseE.isOWLTopObjectProperty()) {
OWLObjectProperty inverse = inverseE.asOWLObjectProperty();
log.debug(inverse + " object inverse of " + op);
m.add(toResource(inverse), OWL_INVERSE_OF, toResource(op));
}
}
}
private void populateDataProperties(OWLReasoner r, Model m) {
OWLDataProperty bottom = r.getBottomDataPropertyNode()
.getRepresentativeElement();
populateDataProperty(bottom, r, m);
for (OWLDataProperty dp : r.getSuperDataProperties(bottom, false)
.getFlattened()) {
populateDataProperty(dp, r, m);
}
}
private void populateDataProperty(OWLDataProperty dp, OWLReasoner r, Model m) {
log.debug("data property: " + dp);
populateDataSubProperties(dp, r, m);
}
private void populateDataSubProperties(OWLDataProperty dp, OWLReasoner r,
Model m) {
for (OWLDataProperty subDP : r.getSubDataProperties(dp, false)
.getFlattened()) {
log.debug(subDP + " data sub-property of " + dp);
m.add(toResource(subDP), OWL_SUBPROPERTY_OF, toResource(dp));
}
// getSubDataProperties is strict, so add the reflexive statement.
log.debug(dp + " data sub-property of " + dp);
m.add(toResource(dp), OWL_SUBPROPERTY_OF, toResource(dp));
}
private Resource toResource(OWLNamedObject owlObject) {
return createResource(owlObject.getIRI().toString());
}
private static final Resource OWL_THING = createResource("http://www.w3.org/2002/07/owl#Thing");
private static final Resource OWL_OBJECT_PROPERTY = createResource("http://www.w3.org/2002/07/owl#ObjectProperty");
private static final Resource OWL_TOP_OBJECT_PROPERTY = createResource("http://www.w3.org/2002/07/owl#topObjectProperty");
private static final Resource OWL_BOTTOM_OBJECT_PROPERTY = createResource("http://www.w3.org/2002/07/owl#bottomObjectProperty");
private static final Resource OWL_DATA_PROPERTY = createResource("http://www.w3.org/2002/07/owl#DatatypeProperty");
private static final Resource OWL_TOP_DATA_PROPERTY = createResource("http://www.w3.org/2002/07/owl#topDataProperty");
private static final Resource OWL_BOTTOM_DATA_PROPERTY = createResource("http://www.w3.org/2002/07/owl#bottomDataProperty");
private static final Resource OWL_FUNCTIONAL_PROPERTY = createResource("http://www.w3.org/2002/07/owl#FunctionalProperty");
private static final Resource OWL_INVERSE_FUNCTIONAL_PROPERTY = createResource("http://www.w3.org/2002/07/owl#InverseFunctionalProperty");
private static final Resource OWL_TRANSITIVE_PROPERTY = createResource("http://www.w3.org/2002/07/owl#TransitiveProperty");
private static final Resource OWL_SYMMETRIC_PROPERTY = createResource("http://www.w3.org/2002/07/owl#SymmetricProperty");
private static final Resource OWL_ASYMMETRIC_PROPERTY = createResource("http://www.w3.org/2002/07/owl#AsymmetricProperty");
private static final Resource OWL_REFLEXIVE_PROPERTY = createResource("http://www.w3.org/2002/07/owl#ReflexiveProperty");
private static final Resource OWL_IRREFLEXIVE_PROPERTY = createResource("http://www.w3.org/2002/07/owl#IrreflexiveProperty");
private static final Resource OWL_ANNOTATION_PROPERTY = createResource("http://www.w3.org/2002/07/owl#AnnotationProperty");
private static final Resource OWL_VERSION_INFO = createResource("http://www.w3.org/2002/07/owl#versionInfo");
private static final Resource OWL_BACKWARD_COMPATIBLE_WITH = createResource("http://www.w3.org/2002/07/owl#backwardCompatibleWith");
private static final Resource OWL_INCOMPATIBLE_WITH = createResource("http://www.w3.org/2002/07/owl#incompatibleWith");
private static final Resource OWL_PRIOR_VERSION = createResource("http://www.w3.org/2002/07/owl#priorVersion");
private static final Resource RDFS_SEE_ALSO = createResource("http://www.w3.org/2000/01/rdf-schema#seeAlso");
private static final Resource RDFS_COMMENT = createResource("http://www.w3.org/2000/01/rdf-schema#comment");
private static final Resource RDFS_IS_DEFINED_BY = createResource("http://www.w3.org/2000/01/rdf-schema#isDefinedBy");
private static final Resource RDFS_LABEL = createResource("http://www.w3.org/2000/01/rdf-schema#label");
private void klugeOwlInvariants(Model m) {
m.add(OWL_BOTTOM_DATA_PROPERTY, RDFS_TYPE, OWL_DATA_PROPERTY);
m.add(OWL_BOTTOM_DATA_PROPERTY, RDFS_TYPE, OWL_FUNCTIONAL_PROPERTY);
m.add(OWL_TOP_DATA_PROPERTY, RDFS_TYPE, OWL_DATA_PROPERTY);
m.add(OWL_BOTTOM_OBJECT_PROPERTY, RDFS_TYPE, OWL_OBJECT_PROPERTY);
m.add(OWL_BOTTOM_OBJECT_PROPERTY, RDFS_TYPE, OWL_FUNCTIONAL_PROPERTY);
m.add(OWL_BOTTOM_OBJECT_PROPERTY, RDFS_TYPE,
OWL_INVERSE_FUNCTIONAL_PROPERTY);
m.add(OWL_BOTTOM_OBJECT_PROPERTY, RDFS_TYPE, OWL_TRANSITIVE_PROPERTY);
m.add(OWL_BOTTOM_OBJECT_PROPERTY, RDFS_TYPE, OWL_SYMMETRIC_PROPERTY);
m.add(OWL_BOTTOM_OBJECT_PROPERTY, RDFS_TYPE, OWL_ASYMMETRIC_PROPERTY);
m.add(OWL_BOTTOM_OBJECT_PROPERTY, RDFS_TYPE, OWL_IRREFLEXIVE_PROPERTY);
m.add(OWL_TOP_OBJECT_PROPERTY, RDFS_TYPE, OWL_OBJECT_PROPERTY);
m.add(OWL_TOP_OBJECT_PROPERTY, RDFS_TYPE, OWL_TRANSITIVE_PROPERTY);
m.add(OWL_TOP_OBJECT_PROPERTY, RDFS_TYPE, OWL_REFLEXIVE_PROPERTY);
m.add(OWL_TOP_OBJECT_PROPERTY, RDFS_TYPE, OWL_SYMMETRIC_PROPERTY);
m.add(OWL_THING, RDFS_TYPE, OWL_CLASS);
m.add(OWL_VERSION_INFO, RDFS_TYPE, OWL_ANNOTATION_PROPERTY);
m.add(OWL_BACKWARD_COMPATIBLE_WITH, RDFS_TYPE, OWL_ANNOTATION_PROPERTY);
m.add(OWL_PRIOR_VERSION, RDFS_TYPE, OWL_ANNOTATION_PROPERTY);
m.add(OWL_INCOMPATIBLE_WITH, RDFS_TYPE, OWL_ANNOTATION_PROPERTY);
m.add(RDFS_SEE_ALSO, RDFS_TYPE, OWL_ANNOTATION_PROPERTY);
m.add(RDFS_COMMENT, RDFS_TYPE, OWL_ANNOTATION_PROPERTY);
m.add(RDFS_IS_DEFINED_BY, RDFS_TYPE, OWL_ANNOTATION_PROPERTY);
m.add(RDFS_LABEL, RDFS_TYPE, OWL_ANNOTATION_PROPERTY);
}
private void klugeMistakes(Model m) {
Property ISF_DEPRECATED = createProperty("http://isf/deprecated_op");
m.add(ISF_DEPRECATED, RDFS_TYPE, OWL_OBJECT_PROPERTY);
m.add(ISF_DEPRECATED, OWL_SUBPROPERTY_OF, ISF_DEPRECATED);
m.add(ISF_DEPRECATED, OWL_SUBPROPERTY_OF, OWL_TOP_OBJECT_PROPERTY);
m.add(OWL_BOTTOM_OBJECT_PROPERTY, OWL_SUBPROPERTY_OF, ISF_DEPRECATED);
Resource OWL_DEPRECATED = createResource("http://www.w3.org/2002/07/owl#DeprecatedProperty");
m.add(OWL_DEPRECATED, RDFS_TYPE, OWL_OBJECT_PROPERTY);
m.add(OWL_DEPRECATED, OWL_SUBPROPERTY_OF, OWL_DEPRECATED);
m.add(OWL_DEPRECATED, OWL_SUBPROPERTY_OF, OWL_TOP_OBJECT_PROPERTY);
m.add(OWL_BOTTOM_OBJECT_PROPERTY, OWL_SUBPROPERTY_OF, OWL_DEPRECATED);
Property DCT_CONTRIBUTOR = createProperty("http://purl.org/dc/terms/contributor");
m.add(DCT_CONTRIBUTOR, RDFS_TYPE, OWL_OBJECT_PROPERTY);
m.add(DCT_CONTRIBUTOR, OWL_SUBPROPERTY_OF, DCT_CONTRIBUTOR);
m.add(DCT_CONTRIBUTOR, OWL_SUBPROPERTY_OF, OWL_TOP_OBJECT_PROPERTY);
m.add(OWL_BOTTOM_OBJECT_PROPERTY, OWL_SUBPROPERTY_OF, DCT_CONTRIBUTOR);
Resource ARG_2000400 = createResource("http://purl.obolibrary.org/obo/ARG_2000400");
Resource BFO_0000001 = createResource("http://purl.obolibrary.org/obo/BFO_0000001");
Resource BFO_0000002 = createResource("http://purl.obolibrary.org/obo/BFO_0000002");
Resource BFO_0000031 = createResource("http://purl.obolibrary.org/obo/BFO_0000031");
Resource IAO_0000003 = createResource("http://purl.obolibrary.org/obo/IAO_0000003");
Resource IAO_0000009 = createResource("http://purl.obolibrary.org/obo/IAO_0000009");
Resource IAO_0000030 = createResource("http://purl.obolibrary.org/obo/IAO_0000030");
m.add(ARG_2000400, RDFS_TYPE, BFO_0000001);
m.add(ARG_2000400, RDFS_TYPE, BFO_0000002);
m.add(ARG_2000400, RDFS_TYPE, BFO_0000031);
m.add(ARG_2000400, RDFS_TYPE, IAO_0000003);
m.add(ARG_2000400, RDFS_TYPE, IAO_0000009);
m.add(ARG_2000400, RDFS_TYPE, IAO_0000030);
m.add(ARG_2000400, RDFS_TYPE, OWL_THING);
Resource BIBO_ACCEPTED = createResource("http://purl.org/ontology/bibo/accepted");
Resource BIBO_DRAFT = createResource("http://purl.org/ontology/bibo/draft");
Resource BIBO_PEER_REVIEWED = createResource("http://purl.org/ontology/bibo/peerReviewed");
Resource BIBO_PUBLISHED = createResource("http://purl.org/ontology/bibo/published");
Resource BIBO_REJECTED = createResource("http://purl.org/ontology/bibo/rejected");
Resource BIBO_UNPUBLISHED = createResource("http://purl.org/ontology/bibo/unpublished");
m.add(BIBO_ACCEPTED, RDFS_TYPE, OWL_THING);
m.add(BIBO_DRAFT, RDFS_TYPE, OWL_THING);
m.add(BIBO_PEER_REVIEWED, RDFS_TYPE, OWL_THING);
m.add(BIBO_PUBLISHED, RDFS_TYPE, OWL_THING);
m.add(BIBO_REJECTED, RDFS_TYPE, OWL_THING);
m.add(BIBO_UNPUBLISHED, RDFS_TYPE, OWL_THING);
Resource CORE_YMDT_PRECISION = createResource("http://vivoweb.org/ontology/core#yearMonthDayTimePrecision");
Resource CORE_YMD_PRECISION = createResource("http://vivoweb.org/ontology/core#yearMonthDayPrecision");
Resource CORE_YM_PRECISION = createResource("http://vivoweb.org/ontology/core#yearMonthPrecision");
Resource CORE_Y_PRECISION = createResource("http://vivoweb.org/ontology/core#yearPrecision");
Resource SKOS_CONCEPT = createResource("http://www.w3.org/2004/02/skos/core#Concept");
m.add(CORE_YMDT_PRECISION, RDFS_TYPE, OWL_THING);
m.add(CORE_YMDT_PRECISION, RDFS_TYPE, SKOS_CONCEPT);
m.add(CORE_YMD_PRECISION, RDFS_TYPE, OWL_THING);
m.add(CORE_YMD_PRECISION, RDFS_TYPE, SKOS_CONCEPT);
m.add(CORE_YM_PRECISION, RDFS_TYPE, OWL_THING);
m.add(CORE_YM_PRECISION, RDFS_TYPE, SKOS_CONCEPT);
m.add(CORE_Y_PRECISION, RDFS_TYPE, OWL_THING);
m.add(CORE_Y_PRECISION, RDFS_TYPE, SKOS_CONCEPT);
Resource CORE_CONTACT_INFO = createResource("http://vivoweb.org/ontology/core#contactInformation");
m.add(CORE_CONTACT_INFO, RDFS_TYPE, OWL_DATA_PROPERTY);
Resource CORE_HAS_FACILITY = createResource("http://vivoweb.org/ontology/core#hasFacility");
m.add(CORE_HAS_FACILITY, RDFS_TYPE, OWL_OBJECT_PROPERTY);
Resource CORE_HAS_FUNDING = createResource("http://vivoweb.org/ontology/core#hasFundingVehicle");
m.add(CORE_HAS_FUNDING, RDFS_TYPE, OWL_OBJECT_PROPERTY);
Resource CORE_HAS_GOV_AUTH = createResource("http://vivoweb.org/ontology/core#hasGoverningAuthority");
m.add(CORE_HAS_GOV_AUTH, RDFS_TYPE, OWL_OBJECT_PROPERTY);
Resource CORE_IN_PRESS = createResource("http://vivoweb.org/ontology/core#inPress");
m.add(CORE_IN_PRESS, RDFS_TYPE, OWL_THING);
Resource CORE_INVITED = createResource("http://vivoweb.org/ontology/core#invited");
m.add(CORE_INVITED, RDFS_TYPE, OWL_THING);
Resource CORE_SUBMITTED = createResource("http://vivoweb.org/ontology/core#submitted");
m.add(CORE_SUBMITTED, RDFS_TYPE, OWL_THING);
Resource OBO_HAS_AGENT = createResource("http://www.obofoundry.org/ro/ro.owl#has_agent");
m.add(OBO_HAS_AGENT, RDFS_TYPE, OWL_OBJECT_PROPERTY);
Resource OBI_0000066 = createResource("http://purl.obolibrary.org/obo/OBI_0000066");
m.remove(OBI_0000066, RDFS_TYPE, OWL_CLASS);
m.remove(OBI_0000066, OWL_SUBCLASS_OF, OWL_THING);
m.remove(OBI_0000066, OWL_EQUIVALENT_CLASS, OBI_0000066);
Resource OBI_0000086 = createResource("http://purl.obolibrary.org/obo/OBI_0000086");
m.remove(OBI_0000086, RDFS_TYPE, OWL_CLASS);
m.remove(OBI_0000086, OWL_SUBCLASS_OF, OWL_THING);
m.remove(OBI_0000086, OWL_EQUIVALENT_CLASS, OBI_0000086);
Resource OBI_0000094 = createResource("http://purl.obolibrary.org/obo/OBI_0000094");
m.remove(OBI_0000094, RDFS_TYPE, OWL_CLASS);
m.remove(OBI_0000094, OWL_SUBCLASS_OF, OWL_THING);
m.remove(OBI_0000094, OWL_EQUIVALENT_CLASS, OBI_0000094);
Resource OBI_0000571 = createResource("http://purl.obolibrary.org/obo/OBI_0000571");
m.remove(OBI_0000571, RDFS_TYPE, OWL_CLASS);
m.remove(OBI_0000571, OWL_SUBCLASS_OF, OWL_THING);
m.remove(OBI_0000571, OWL_EQUIVALENT_CLASS, OBI_0000571);
}
}

View file

@ -0,0 +1,159 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.tboxreasoner.impl.jfact;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyCreationException;
import org.semanticweb.owlapi.reasoner.InferenceType;
import org.semanticweb.owlapi.reasoner.OWLReasoner;
import org.semanticweb.owlapi.reasoner.OWLReasonerConfiguration;
import org.semanticweb.owlapi.reasoner.OWLReasonerFactory;
import org.semanticweb.owlapi.reasoner.SimpleConfiguration;
import uk.ac.manchester.cs.jfact.JFactFactory;
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.ontology.OntModelSpec;
import com.hp.hpl.jena.ontology.Restriction;
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.ReasonerStatementPattern;
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxChanges;
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasoner;
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.impl.TBoxInferencesAccumulator;
/**
* An implementation of the JFact reasoner for the TBox.
*
* It maintains a model of all the assertions it has been given, adding or
* removing statements as change sets are received.
*
* Each time a change is received, it will create a fresh ontology from the
* assertions model, and apply a reasoner to that ontology. A model of
* inferences is built by querying the reasoner.
*
* The assertions and inferences are combined into an OntModel, which is kept to
* answer queries.
*
* -----------------
*
* This class it not thread-safe.
*/
public class JFactTBoxReasoner implements
TBoxReasoner {
private static final Log log = LogFactory.getLog(JFactTBoxReasoner.class);
private final OWLReasonerFactory reasonerFactory;
private final TBoxInferencesAccumulator accumulator;
private final Model filteredAssertionsModel;
private final OntModel combinedInferencedModel;
public JFactTBoxReasoner() {
this.filteredAssertionsModel = ModelFactory.createDefaultModel();
this.combinedInferencedModel = ModelFactory
.createOntologyModel(OntModelSpec.OWL_MEM);
this.reasonerFactory = new JFactFactory();
this.accumulator = new TBoxInferencesAccumulator();
}
@Override
public void updateReasonerModel(TBoxChanges changes) {
log.debug("Adding " + changes.getAddedStatements().size()
+ ", removing " + changes.getRemovedStatements().size());
filteredAssertionsModel.add(changes.getAddedStatements());
filteredAssertionsModel.remove(changes.getRemovedStatements());
}
@Override
public Status performReasoning() {
try {
OWLOntology ont = copyModelToOntology(filteredAssertionsModel);
OWLReasoner reasoner = createReasoner(ont);
reasoner.precomputeInferences(InferenceType.values());
try {
if (!reasoner.isConsistent()) {
return Status.inconsistent("Reasoner axioms are not "
+ "consistent");
}
} catch (Exception e) {
log.error(e);
return Status.ERROR;
}
Model inferences = accumulator.populateModelFromReasonerQueries(reasoner);
mergeModels(filteredAssertionsModel, inferences);
return Status.SUCCESS;
} catch (Exception e) {
log.error(e);
return Status.ERROR;
}
}
private OWLOntology copyModelToOntology(Model m)
throws OWLOntologyCreationException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
m.write(out, "RDF/XML");
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
return OWLManager.createOWLOntologyManager()
.loadOntologyFromOntologyDocument(in);
}
private OWLReasoner createReasoner(OWLOntology ont) {
OWLReasonerConfiguration config = new SimpleConfiguration(50000);
OWLReasoner reasoner = this.reasonerFactory.createReasoner(ont, config);
return reasoner;
}
private void mergeModels(Model assertions, Model inferences) {
combinedInferencedModel.removeAll();
combinedInferencedModel.add(assertions);
combinedInferencedModel.add(inferences);
log.debug("Assertions: " + assertions.size() + ", inferences: "
+ inferences.size() + ", combined: "
+ combinedInferencedModel.size());
}
@Override
public List<ObjectProperty> listObjectProperties() {
return combinedInferencedModel.listObjectProperties().toList();
}
@Override
public List<DatatypeProperty> listDatatypeProperties() {
return combinedInferencedModel.listDatatypeProperties().toList();
}
@Override
public List<Restriction> listRestrictions() {
return combinedInferencedModel.listRestrictions().toList();
}
@Override
public List<Statement> filterResults(
List<ReasonerStatementPattern> patternList) {
List<Statement> filtered = new ArrayList<>();
for (ReasonerStatementPattern pattern : patternList) {
filtered.addAll(pattern
.matchStatementsFromModel(combinedInferencedModel));
}
return filtered;
}
}

View file

@ -1,6 +1,6 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.tboxreasoner.impl.pellet;
package edu.cornell.mannlib.vitro.webapp.tboxreasoner.impl.jfact;
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.TBOX_ASSERTIONS;
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.TBOX_INFERENCES;
@ -13,9 +13,7 @@ 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;
@ -27,13 +25,16 @@ import edu.cornell.mannlib.vitro.webapp.tboxreasoner.ReasonerConfiguration;
import edu.cornell.mannlib.vitro.webapp.tboxreasoner.impl.BasicTBoxReasonerDriver;
/**
* Configure a Pellet reasoner on the TBox.
* Configure a JFact reasoner on the TBox.
*
* Create a JFactTBoxReasoner and pass it as the strategy to a
* BasicTBoxReasonerDriver.
*/
public class PelletTBoxReasonerModule implements TBoxReasonerModule {
public class JFactTBoxReasonerModule implements TBoxReasonerModule {
private static final Log log = LogFactory
.getLog(PelletTBoxReasonerModule.class);
.getLog(JFactTBoxReasonerModule.class);
private PelletTBoxReasoner reasoner;
private JFactTBoxReasoner reasoner;
private BasicTBoxReasonerDriver driver;
@Override
@ -41,18 +42,14 @@ public class PelletTBoxReasonerModule implements TBoxReasonerModule {
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,
reasoner = new JFactTBoxReasoner();
driver = new BasicTBoxReasonerDriver(
contextModels.getOntModel(TBOX_ASSERTIONS), contextModels
.getOntModel(TBOX_INFERENCES).getBaseModel(),
contextModels.getOntModel(TBOX_UNION), reasoner,
ReasonerConfiguration.DEFAULT);
ss.info("Pellet reasoner connected for the TBox");
ss.info("JFact reasoner connected for the TBox");
waitForTBoxReasoning();
}
@ -61,7 +58,7 @@ public class PelletTBoxReasonerModule implements TBoxReasonerModule {
public TBoxReasonerStatus getStatus() {
if (driver == null) {
throw new IllegalStateException(
"PelletTBoxReasonerModule has not been started.");
"JFactTBoxReasonerModule has not been started.");
}
return driver.getStatus();
}
@ -70,22 +67,16 @@ public class PelletTBoxReasonerModule implements TBoxReasonerModule {
public List<Restriction> listRestrictions() {
if (reasoner == null) {
throw new IllegalStateException(
"PelletTBoxReasonerModule has not been started.");
"JFactTBoxReasonerModule has not been started.");
}
return reasoner.listRestrictions();
}
@Override
public void shutdown(Application application) {
driver.shutdown();
}
@Override
public void waitForTBoxReasoning() {
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())) {
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");
@ -99,4 +90,9 @@ public class PelletTBoxReasonerModule implements TBoxReasonerModule {
sleeps++;
}
}
@Override
public void shutdown(Application application) {
driver.shutdown();
}
}

View file

@ -1,114 +0,0 @@
/* $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();
}
}
}