/*
* Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2007.
*
* Copyright FZI (http://fzi.de), (c) 2007-2008.
*
* Licensed under the Aduna/FZI BSD-style license.
*/
package org.semweb4j.sesame;
import java.util.Iterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.aduna.iteration.CloseableIteration;
import info.aduna.iteration.Iterations;
import info.aduna.text.ASCIIUtil;
import org.openrdf.model.Graph;
import org.openrdf.model.Resource;
import org.openrdf.model.Statement;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.model.impl.GraphImpl;
import org.openrdf.model.impl.URIImpl;
import org.openrdf.model.vocabulary.RDF;
import org.openrdf.model.vocabulary.RDFS;
import org.openrdf.sail.Sail;
import org.openrdf.sail.SailConnectionListener;
import org.openrdf.sail.SailException;
import org.openrdf.sail.inferencer.InferencerConnection;
import org.openrdf.sail.inferencer.InferencerConnectionWrapper;
/**
* Forward-chaining RDF Schema inferencer, using the rules from the <a
* href="http://www.w3.org/TR/2004/REC-rdf-mt-20040210/">RDF Semantics
* Recommendation (10 February 2004)</a>. This inferencer can be used to add
* RDF Schema semantics to any Sail that returns {@link InferencerConnection}s
* from their {@link Sail#getConnection()} method.
*
* Added: nrl:inverse
*
* @author voelkel
*/
class ForwardChainingRDFSPlusInverseInferencerConnection extends InferencerConnectionWrapper implements
SailConnectionListener
{
/*-----------*
* Constants *
*-----------*/
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
/*-----------*
* Variables *
*-----------*/
/**
* true if the base Sail reported removed statements.
*/
private boolean statementsRemoved;
/**
* Contains the statements that have been reported by the base Sail as
*/
private Graph newStatements;
private Graph newThisIteration;
/**
* Flags indicating which rules should be evaluated.
*/
private boolean[] checkRule = new boolean[RDFSPlusInversesRules.RULECOUNT];
/**
* Flags indicating which rules should be evaluated next iteration.
*/
private boolean[] checkRuleNextIter = new boolean[RDFSPlusInversesRules.RULECOUNT];
private int totalInferred = 0;
/**
* The number of inferred statements per rule.
*/
private int[] ruleCount = new int[RDFSPlusInversesRules.RULECOUNT];
/*--------------*
* Constructors *
*--------------*/
public ForwardChainingRDFSPlusInverseInferencerConnection(InferencerConnection con) {
super(con);
con.addConnectionListener(this);
}
/*---------*
* Methods *
*---------*/
// Called by base sail
public void statementAdded(Statement st) {
if (this.statementsRemoved) {
// No need to record, starting from scratch anyway
return;
}
if (this.newStatements == null) {
this.newStatements = new GraphImpl();
}
this.newStatements.add(st);
}
// Called by base sail
public void statementRemoved(@SuppressWarnings("unused")
Statement st) {
this.statementsRemoved = true;
this.newStatements = null;
}
@Override
public void flushUpdates()
throws SailException
{
super.flushUpdates();
if (this.statementsRemoved) {
this.logger.debug("statements removed, starting inferencing from scratch");
clearInferred();
addAxiomStatements();
this.newStatements = new GraphImpl();
Iterations.addAll(getWrappedConnection().getStatements(null, null, null, true), this.newStatements);
this.statementsRemoved = false;
}
doInferencing();
}
@Override
public void rollback()
throws SailException
{
this.statementsRemoved = false;
this.newStatements = null;
super.rollback();
}
public static final String NRL_NS = "http://www.semanticdesktop.org/ontologies/2007/08/15/nrl#";
public static final URI NRL_InverseProperty = new URIImpl(NRL_NS+"inverseProperty");
/**
* Adds all basic set of axiom statements from which the complete set can be
* inferred to the underlying Sail.
*/
protected void addAxiomStatements()
throws SailException
{
this.logger.debug("Inserting axiom statements");
// RDF axiomatic triples (from RDF Semantics, section 3.1):
addInferredStatement(RDF.TYPE, RDF.TYPE, RDF.PROPERTY);
addInferredStatement(RDF.SUBJECT, RDF.TYPE, RDF.PROPERTY);
addInferredStatement(RDF.PREDICATE, RDF.TYPE, RDF.PROPERTY);
addInferredStatement(RDF.OBJECT, RDF.TYPE, RDF.PROPERTY);
addInferredStatement(RDF.FIRST, RDF.TYPE, RDF.PROPERTY);
addInferredStatement(RDF.REST, RDF.TYPE, RDF.PROPERTY);
addInferredStatement(RDF.VALUE, RDF.TYPE, RDF.PROPERTY);
addInferredStatement(RDF.NIL, RDF.TYPE, RDF.LIST);
// RDFS axiomatic triples (from RDF Semantics, section 4.1):
addInferredStatement(RDF.TYPE, RDFS.DOMAIN, RDFS.RESOURCE);
addInferredStatement(RDFS.DOMAIN, RDFS.DOMAIN, RDF.PROPERTY);
addInferredStatement(RDFS.RANGE, RDFS.DOMAIN, RDF.PROPERTY);
addInferredStatement(RDFS.SUBPROPERTYOF, RDFS.DOMAIN, RDF.PROPERTY);
addInferredStatement(RDFS.SUBCLASSOF, RDFS.DOMAIN, RDFS.CLASS);
addInferredStatement(RDF.SUBJECT, RDFS.DOMAIN, RDF.STATEMENT);
addInferredStatement(RDF.PREDICATE, RDFS.DOMAIN, RDF.STATEMENT);
addInferredStatement(RDF.OBJECT, RDFS.DOMAIN, RDF.STATEMENT);
addInferredStatement(RDFS.MEMBER, RDFS.DOMAIN, RDFS.RESOURCE);
addInferredStatement(RDF.FIRST, RDFS.DOMAIN, RDF.LIST);
addInferredStatement(RDF.REST, RDFS.DOMAIN, RDF.LIST);
addInferredStatement(RDFS.SEEALSO, RDFS.DOMAIN, RDFS.RESOURCE);
addInferredStatement(RDFS.ISDEFINEDBY, RDFS.DOMAIN, RDFS.RESOURCE);
addInferredStatement(RDFS.COMMENT, RDFS.DOMAIN, RDFS.RESOURCE);
addInferredStatement(RDFS.LABEL, RDFS.DOMAIN, RDFS.RESOURCE);
addInferredStatement(RDF.VALUE, RDFS.DOMAIN, RDFS.RESOURCE);
addInferredStatement(RDF.TYPE, RDFS.RANGE, RDFS.CLASS);
addInferredStatement(RDFS.DOMAIN, RDFS.RANGE, RDFS.CLASS);
addInferredStatement(RDFS.RANGE, RDFS.RANGE, RDFS.CLASS);
addInferredStatement(RDFS.SUBPROPERTYOF, RDFS.RANGE, RDF.PROPERTY);
addInferredStatement(RDFS.SUBCLASSOF, RDFS.RANGE, RDFS.CLASS);
addInferredStatement(RDF.SUBJECT, RDFS.RANGE, RDFS.RESOURCE);
addInferredStatement(RDF.PREDICATE, RDFS.RANGE, RDFS.RESOURCE);
addInferredStatement(RDF.OBJECT, RDFS.RANGE, RDFS.RESOURCE);
addInferredStatement(RDFS.MEMBER, RDFS.RANGE, RDFS.RESOURCE);
addInferredStatement(RDF.FIRST, RDFS.RANGE, RDFS.RESOURCE);
addInferredStatement(RDF.REST, RDFS.RANGE, RDF.LIST);
addInferredStatement(RDFS.SEEALSO, RDFS.RANGE, RDFS.RESOURCE);
addInferredStatement(RDFS.ISDEFINEDBY, RDFS.RANGE, RDFS.RESOURCE);
addInferredStatement(RDFS.COMMENT, RDFS.RANGE, RDFS.LITERAL);
addInferredStatement(RDFS.LABEL, RDFS.RANGE, RDFS.LITERAL);
addInferredStatement(RDF.VALUE, RDFS.RANGE, RDFS.RESOURCE);
addInferredStatement(RDF.ALT, RDFS.SUBCLASSOF, RDFS.CONTAINER);
addInferredStatement(RDF.BAG, RDFS.SUBCLASSOF, RDFS.CONTAINER);
addInferredStatement(RDF.SEQ, RDFS.SUBCLASSOF, RDFS.CONTAINER);
addInferredStatement(RDFS.CONTAINERMEMBERSHIPPROPERTY, RDFS.SUBCLASSOF, RDF.PROPERTY);
addInferredStatement(RDFS.ISDEFINEDBY, RDFS.SUBPROPERTYOF, RDFS.SEEALSO);
addInferredStatement(RDF.XMLLITERAL, RDF.TYPE, RDFS.DATATYPE);
addInferredStatement(RDF.XMLLITERAL, RDFS.SUBCLASSOF, RDFS.LITERAL);
addInferredStatement(RDFS.DATATYPE, RDFS.SUBCLASSOF, RDFS.CLASS);
// // NRL inverse
// // FIXME made up a property for inverse-of rdf:type
// addInferredStatement(RDF.TYPE, NRL_InverseProperty, new URIImpl(NRL_NS+"hasInstance"));
}
protected void doInferencing()
throws SailException
{
if (!hasNewStatements()) {
// There's nothing to do
return;
}
// initialize some vars
this.totalInferred = 0;
int iteration = 0;
int nofInferred = 1;
// All rules need to be checked:
for (int i = 0; i < RDFSPlusInversesRules.RULECOUNT; i++) {
this.ruleCount[i] = 0;
this.checkRuleNextIter[i] = true;
}
while (hasNewStatements()) {
iteration++;
this.logger.debug("starting iteration " + iteration);
prepareIteration();
nofInferred = 0;
nofInferred += applyRule(RDFSPlusInversesRules.Rdf1);
nofInferred += applyRule(RDFSPlusInversesRules.Rdfs2_1);
nofInferred += applyRule(RDFSPlusInversesRules.Rdfs2_2);
nofInferred += applyRule(RDFSPlusInversesRules.Rdfs3_1);
nofInferred += applyRule(RDFSPlusInversesRules.Rdfs3_2);
nofInferred += applyRule(RDFSPlusInversesRules.Rdfs4a);
nofInferred += applyRule(RDFSPlusInversesRules.Rdfs4b);
nofInferred += applyRule(RDFSPlusInversesRules.Rdfs5_1);
nofInferred += applyRule(RDFSPlusInversesRules.Rdfs5_2);
nofInferred += applyRule(RDFSPlusInversesRules.Rdfs6);
nofInferred += applyRule(RDFSPlusInversesRules.Rdfs7_1);
nofInferred += applyRule(RDFSPlusInversesRules.Rdfs7_2);
nofInferred += applyRule(RDFSPlusInversesRules.Rdfs8);
nofInferred += applyRule(RDFSPlusInversesRules.Rdfs9_1);
nofInferred += applyRule(RDFSPlusInversesRules.Rdfs9_2);
nofInferred += applyRule(RDFSPlusInversesRules.Rdfs10);
nofInferred += applyRule(RDFSPlusInversesRules.Rdfs11_1);
nofInferred += applyRule(RDFSPlusInversesRules.Rdfs11_2);
nofInferred += applyRule(RDFSPlusInversesRules.Rdfs12);
nofInferred += applyRule(RDFSPlusInversesRules.Rdfs13);
nofInferred += applyRule(RDFSPlusInversesRules.RX1);
nofInferred += applyRule(RDFSPlusInversesRules.N1a);
nofInferred += applyRule(RDFSPlusInversesRules.N1b);
nofInferred += applyRule(RDFSPlusInversesRules.N2a);
nofInferred += applyRule(RDFSPlusInversesRules.N2b);
nofInferred += applyRule(RDFSPlusInversesRules.N3);
this.logger.debug("iteration " + iteration + " done; inferred " + nofInferred + " new statements");
this.totalInferred += nofInferred;
}
// Print some statistics
this.logger.debug("---RdfMTInferencer statistics:---");
this.logger.debug("total statements inferred = " + this.totalInferred);
for (int i = 0; i < RDFSPlusInversesRules.RULECOUNT; i++) {
this.logger.debug("rule " + RDFSPlusInversesRules.RULENAMES[i] + ":\t#inferred=" + this.ruleCount[i]);
}
this.logger.debug("---end of statistics:---");
}
protected void prepareIteration() {
for (int i = 0; i < RDFSPlusInversesRules.RULECOUNT; i++) {
this.checkRule[i] = this.checkRuleNextIter[i];
// reset for next iteration:
this.checkRuleNextIter[i] = false;
}
this.newThisIteration = this.newStatements;
this.newStatements = new GraphImpl();
}
protected boolean hasNewStatements() {
return this.newStatements != null && !this.newStatements.isEmpty();
}
protected void updateTriggers(int ruleNo, int nofInferred) {
if (nofInferred > 0) {
this.ruleCount[ruleNo] += nofInferred;
// Check which rules are triggered by this one.
boolean[] triggers = RDFSPlusInversesRules.TRIGGERS[ruleNo];
for (int i = 0; i < RDFSPlusInversesRules.RULECOUNT; i++) {
if (triggers[i] == true) {
this.checkRuleNextIter[i] = true;
}
}
}
}
protected int applyRule(int rule)
throws SailException
{
if (!this.checkRule[rule]) {
return 0;
}
int nofInferred = 0;
nofInferred = applyRuleInternal(rule);
updateTriggers(rule, nofInferred);
return nofInferred;
}
protected int applyRuleInternal(int rule)
throws SailException
{
int result = 0;
switch (rule) {
case RDFSPlusInversesRules.Rdf1:
result = applyRuleRdf1();
break;
case RDFSPlusInversesRules.Rdfs2_1:
result = applyRuleRdfs2_1();
break;
case RDFSPlusInversesRules.Rdfs2_2:
result = applyRuleRdfs2_2();
break;
case RDFSPlusInversesRules.Rdfs3_1:
result = applyRuleRdfs3_1();
break;
case RDFSPlusInversesRules.Rdfs3_2:
result = applyRuleRdfs3_2();
break;
case RDFSPlusInversesRules.Rdfs4a:
result = applyRuleRdfs4a();
break;
case RDFSPlusInversesRules.Rdfs4b:
result = applyRuleRdfs4b();
break;
case RDFSPlusInversesRules.Rdfs5_1:
result = applyRuleRdfs5_1();
break;
case RDFSPlusInversesRules.Rdfs5_2:
result = applyRuleRdfs5_2();
break;
case RDFSPlusInversesRules.Rdfs6:
result = applyRuleRdfs6();
break;
case RDFSPlusInversesRules.Rdfs7_1:
result = applyRuleRdfs7_1();
break;
case RDFSPlusInversesRules.Rdfs7_2:
result = applyRuleRdfs7_2();
break;
case RDFSPlusInversesRules.Rdfs8:
result = applyRuleRdfs8();
break;
case RDFSPlusInversesRules.Rdfs9_1:
result = applyRuleRdfs9_1();
break;
case RDFSPlusInversesRules.Rdfs9_2:
result = applyRuleRdfs9_2();
break;
case RDFSPlusInversesRules.Rdfs10:
result = applyRuleRdfs10();
break;
case RDFSPlusInversesRules.Rdfs11_1:
result = applyRuleRdfs11_1();
break;
case RDFSPlusInversesRules.Rdfs11_2:
result = applyRuleRdfs11_2();
break;
case RDFSPlusInversesRules.Rdfs12:
result = applyRuleRdfs12();
break;
case RDFSPlusInversesRules.Rdfs13:
result = applyRuleRdfs13();
break;
case RDFSPlusInversesRules.RX1:
result = applyRuleX1();
break;
case RDFSPlusInversesRules.N1a:
result = applyRuleN1a();
break;
case RDFSPlusInversesRules.N1b:
result = applyRuleN1b();
break;
case RDFSPlusInversesRules.N2a:
result = applyRuleN2a();
break;
case RDFSPlusInversesRules.N2b:
result = applyRuleN2b();
break;
case RDFSPlusInversesRules.N3:
result = applyRuleN3();
break;
default:
throw new AssertionError("Should be unreachable code");
}
// ThreadLog.trace("Rule " + RDFSRules.RULENAMES[rule] + " inferred " +
// result + " new triples.");
return result;
}
/*
* rdf1. xxx aaa yyy --> aaa rdf:type rdf:Property
*/
private int applyRuleRdf1()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> iter = this.newThisIteration.match(null, null, null);
while (iter.hasNext()) {
Statement st = iter.next();
boolean added = addInferredStatement(st.getPredicate(), RDF.TYPE, RDF.PROPERTY);
if (added) {
nofInferred++;
}
}
return nofInferred;
}
/*
* rdfs2. 2_1. xxx aaa yyy && (nt) aaa rdfs:domain zzz --> (t1) xxx rdf:type
* zzz (t2)
*/
private int applyRuleRdfs2_1()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> ntIter = this.newThisIteration.match(null, null, null);
while (ntIter.hasNext()) {
Statement nt = ntIter.next();
Resource xxx = nt.getSubject();
URI aaa = nt.getPredicate();
CloseableIteration<? extends Statement, SailException> t1Iter;
t1Iter = getWrappedConnection().getStatements(aaa, RDFS.DOMAIN, null, true);
while (t1Iter.hasNext()) {
Statement t1 = t1Iter.next();
Value zzz = t1.getObject();
if (zzz instanceof Resource) {
boolean added = addInferredStatement(xxx, RDF.TYPE, zzz);
if (added) {
nofInferred++;
}
}
}
t1Iter.close();
}
return nofInferred;
}
/*
* rdfs2. 2_2. aaa rdfs:domain zzz && (nt) xxx aaa yyy --> (t1) xxx rdf:type
* zzz (t2)
*/
private int applyRuleRdfs2_2()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> ntIter = this.newThisIteration.match(null, RDFS.DOMAIN, null);
while (ntIter.hasNext()) {
Statement nt = ntIter.next();
Resource aaa = nt.getSubject();
Value zzz = nt.getObject();
if (aaa instanceof URI && zzz instanceof Resource) {
CloseableIteration<? extends Statement, SailException> t1Iter;
t1Iter = getWrappedConnection().getStatements(null, (URI)aaa, null, true);
while (t1Iter.hasNext()) {
Statement t1 = t1Iter.next();
Resource xxx = t1.getSubject();
boolean added = addInferredStatement(xxx, RDF.TYPE, zzz);
if (added) {
nofInferred++;
}
}
t1Iter.close();
}
}
return nofInferred;
}
/*
* rdfs3. 3_1. xxx aaa uuu && (nt) aaa rdfs:range zzz --> (t1) uuu rdf:type
* zzz (t2)
*/
private int applyRuleRdfs3_1()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> ntIter = this.newThisIteration.match(null, null, null);
while (ntIter.hasNext()) {
Statement nt = ntIter.next();
URI aaa = nt.getPredicate();
Value uuu = nt.getObject();
if (uuu instanceof Resource) {
CloseableIteration<? extends Statement, SailException> t1Iter;
t1Iter = getWrappedConnection().getStatements(aaa, RDFS.RANGE, null, true);
while (t1Iter.hasNext()) {
Statement t1 = t1Iter.next();
Value zzz = t1.getObject();
if (zzz instanceof Resource) {
boolean added = addInferredStatement((Resource)uuu, RDF.TYPE, zzz);
if (added) {
nofInferred++;
}
}
}
t1Iter.close();
}
}
return nofInferred;
}
/*
* rdfs3. 3_2. aaa rdfs:range zzz && (nt) xxx aaa uuu --> (t1) uuu rdf:type
* zzz (t2)
*/
private int applyRuleRdfs3_2()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> ntIter = this.newThisIteration.match(null, RDFS.RANGE, null);
while (ntIter.hasNext()) {
Statement nt = ntIter.next();
Resource aaa = nt.getSubject();
Value zzz = nt.getObject();
if (aaa instanceof URI && zzz instanceof Resource) {
CloseableIteration<? extends Statement, SailException> t1Iter;
t1Iter = getWrappedConnection().getStatements(null, (URI)aaa, null, true);
while (t1Iter.hasNext()) {
Statement t1 = t1Iter.next();
Value uuu = t1.getObject();
if (uuu instanceof Resource) {
boolean added = addInferredStatement((Resource)uuu, RDF.TYPE, zzz);
if (added) {
nofInferred++;
}
}
}
t1Iter.close();
}
}
return nofInferred;
}
/*
* rdfs4a. xxx aaa yyy --> xxx rdf:type rdfs:Resource
*/
private int applyRuleRdfs4a()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> iter = this.newThisIteration.match(null, null, null);
while (iter.hasNext()) {
Statement st = iter.next();
boolean added = addInferredStatement(st.getSubject(), RDF.TYPE, RDFS.RESOURCE);
if (added) {
nofInferred++;
}
}
return nofInferred;
}
/*
* rdfs4b. xxx aaa uuu --> uuu rdf:type rdfs:Resource
*/
private int applyRuleRdfs4b()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> iter = this.newThisIteration.match(null, null, null);
while (iter.hasNext()) {
Statement st = iter.next();
Value uuu = st.getObject();
if (uuu instanceof Resource) {
boolean added = addInferredStatement((Resource)uuu, RDF.TYPE, RDFS.RESOURCE);
if (added) {
nofInferred++;
}
}
}
return nofInferred;
}
/*
* rdfs5. 5_1. aaa rdfs:subPropertyOf bbb && (nt) bbb rdfs:subPropertyOf ccc
* --> (t1) aaa rdfs:subPropertyOf ccc (t2)
*/
private int applyRuleRdfs5_1()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> ntIter = this.newThisIteration.match(null, RDFS.SUBPROPERTYOF, null);
while (ntIter.hasNext()) {
Statement nt = ntIter.next();
Resource aaa = nt.getSubject();
Value bbb = nt.getObject();
if (bbb instanceof Resource) {
CloseableIteration<? extends Statement, SailException> t1Iter;
t1Iter = getWrappedConnection().getStatements((Resource)bbb, RDFS.SUBPROPERTYOF, null, true);
while (t1Iter.hasNext()) {
Statement t1 = t1Iter.next();
Value ccc = t1.getObject();
if (ccc instanceof Resource) {
boolean added = addInferredStatement(aaa, RDFS.SUBPROPERTYOF, ccc);
if (added) {
nofInferred++;
}
}
}
t1Iter.close();
}
}
return nofInferred;
}
/*
* rdfs5. 5_2. bbb rdfs:subPropertyOf ccc && (nt) aaa rdfs:subPropertyOf bbb
* --> (t1) aaa rdfs:subPropertyOf ccc (t2)
*/
private int applyRuleRdfs5_2()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> ntIter = this.newThisIteration.match(null, RDFS.SUBPROPERTYOF, null);
while (ntIter.hasNext()) {
Statement nt = ntIter.next();
Resource bbb = nt.getSubject();
Value ccc = nt.getObject();
if (ccc instanceof Resource) {
CloseableIteration<? extends Statement, SailException> t1Iter;
t1Iter = getWrappedConnection().getStatements(null, RDFS.SUBPROPERTYOF, bbb, true);
while (t1Iter.hasNext()) {
Statement t1 = t1Iter.next();
Resource aaa = t1.getSubject();
boolean added = addInferredStatement(aaa, RDFS.SUBPROPERTYOF, ccc);
if (added) {
nofInferred++;
}
}
t1Iter.close();
}
}
return nofInferred;
}
/*
* rdfs6. xxx rdf:type rdf:Property --> xxx rdfs:subPropertyOf xxx
* reflexivity of rdfs:subPropertyOf
*/
private int applyRuleRdfs6()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> iter = this.newThisIteration.match(null, RDF.TYPE, RDF.PROPERTY);
while (iter.hasNext()) {
Statement st = iter.next();
Resource xxx = st.getSubject();
boolean added = addInferredStatement(xxx, RDFS.SUBPROPERTYOF, xxx);
if (added) {
nofInferred++;
}
}
return nofInferred;
}
/*
* rdfs7. 7_1. xxx aaa yyy && (nt) aaa rdfs:subPropertyOf bbb --> (t1) xxx
* bbb yyy (t2)
*/
private int applyRuleRdfs7_1()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> ntIter = this.newThisIteration.match(null, null, null);
while (ntIter.hasNext()) {
Statement nt = ntIter.next();
Resource xxx = nt.getSubject();
URI aaa = nt.getPredicate();
Value yyy = nt.getObject();
CloseableIteration<? extends Statement, SailException> t1Iter;
t1Iter = getWrappedConnection().getStatements(aaa, RDFS.SUBPROPERTYOF, null, true);
while (t1Iter.hasNext()) {
Statement t1 = t1Iter.next();
Value bbb = t1.getObject();
if (bbb instanceof URI) {
boolean added = addInferredStatement(xxx, (URI)bbb, yyy);
if (added) {
nofInferred++;
}
}
}
t1Iter.close();
}
return nofInferred;
}
/*
* rdfs7. 7_2. aaa rdfs:subPropertyOf bbb && (nt) xxx aaa yyy --> (t1) xxx
* bbb yyy (t2)
*/
private int applyRuleRdfs7_2()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> ntIter = this.newThisIteration.match(null, RDFS.SUBPROPERTYOF, null);
while (ntIter.hasNext()) {
Statement nt = ntIter.next();
Resource aaa = nt.getSubject();
Value bbb = nt.getObject();
if (aaa instanceof URI && bbb instanceof URI) {
CloseableIteration<? extends Statement, SailException> t1Iter;
t1Iter = getWrappedConnection().getStatements(null, (URI)aaa, null, true);
while (t1Iter.hasNext()) {
Statement t1 = t1Iter.next();
Resource xxx = t1.getSubject();
Value yyy = t1.getObject();
boolean added = addInferredStatement(xxx, (URI)bbb, yyy);
if (added) {
nofInferred++;
}
}
t1Iter.close();
}
}
return nofInferred;
}
/*
* rdfs8. xxx rdf:type rdfs:Class --> xxx rdfs:subClassOf rdfs:Resource
*/
private int applyRuleRdfs8()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> iter = this.newThisIteration.match(null, RDF.TYPE, RDFS.CLASS);
while (iter.hasNext()) {
Statement st = iter.next();
Resource xxx = st.getSubject();
boolean added = addInferredStatement(xxx, RDFS.SUBCLASSOF, RDFS.RESOURCE);
if (added) {
nofInferred++;
}
}
return nofInferred;
}
/*
* rdfs9. 9_1. xxx rdfs:subClassOf yyy && (nt) aaa rdf:type xxx --> (t1) aaa
* rdf:type yyy (t2)
*/
private int applyRuleRdfs9_1()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> ntIter = this.newThisIteration.match(null, RDFS.SUBCLASSOF, null);
while (ntIter.hasNext()) {
Statement nt = ntIter.next();
Resource xxx = nt.getSubject();
Value yyy = nt.getObject();
if (yyy instanceof Resource) {
CloseableIteration<? extends Statement, SailException> t1Iter;
t1Iter = getWrappedConnection().getStatements(null, RDF.TYPE, xxx, true);
while (t1Iter.hasNext()) {
Statement t1 = t1Iter.next();
Resource aaa = t1.getSubject();
boolean added = addInferredStatement(aaa, RDF.TYPE, yyy);
if (added) {
nofInferred++;
}
}
t1Iter.close();
}
}
return nofInferred;
}
/*
* rdfs9. 9_2. aaa rdf:type xxx && (nt) xxx rdfs:subClassOf yyy --> (t1) aaa
* rdf:type yyy (t2)
*/
private int applyRuleRdfs9_2()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> ntIter = this.newThisIteration.match(null, RDF.TYPE, null);
while (ntIter.hasNext()) {
Statement nt = ntIter.next();
Resource aaa = nt.getSubject();
Value xxx = nt.getObject();
if (xxx instanceof Resource) {
CloseableIteration<? extends Statement, SailException> t1Iter;
t1Iter = getWrappedConnection().getStatements((Resource)xxx, RDFS.SUBCLASSOF, null, true);
while (t1Iter.hasNext()) {
Statement t1 = t1Iter.next();
Value yyy = t1.getObject();
if (yyy instanceof Resource) {
boolean added = addInferredStatement(aaa, RDF.TYPE, yyy);
if (added) {
nofInferred++;
}
}
}
t1Iter.close();
}
}
return nofInferred;
}
/*
* rdfs10. xxx rdf:type rdfs:Class --> xxx rdfs:subClassOf xxx reflexivity of
* rdfs:subClassOf
*/
private int applyRuleRdfs10()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> iter = this.newThisIteration.match(null, RDF.TYPE, RDFS.CLASS);
while (iter.hasNext()) {
Statement st = iter.next();
Resource xxx = st.getSubject();
boolean added = addInferredStatement(xxx, RDFS.SUBCLASSOF, xxx);
if (added) {
nofInferred++;
}
}
return nofInferred;
}
/*
* rdfs11. 11_1. xxx rdfs:subClassOf yyy && (nt) yyy rdfs:subClassOf zzz -->
* (t1) xxx rdfs:subClassOf zzz (t2)
*/
private int applyRuleRdfs11_1()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> ntIter = this.newThisIteration.match(null, RDFS.SUBCLASSOF, null);
while (ntIter.hasNext()) {
Statement nt = ntIter.next();
Resource xxx = nt.getSubject();
Value yyy = nt.getObject();
if (yyy instanceof Resource) {
CloseableIteration<? extends Statement, SailException> t1Iter;
t1Iter = getWrappedConnection().getStatements((Resource)yyy, RDFS.SUBCLASSOF, null, true);
while (t1Iter.hasNext()) {
Statement t1 = t1Iter.next();
Value zzz = t1.getObject();
if (zzz instanceof Resource) {
boolean added = addInferredStatement(xxx, RDFS.SUBCLASSOF, zzz);
if (added) {
nofInferred++;
}
}
}
t1Iter.close();
}
}
return nofInferred;
}
/*
* rdfs11. 11_2. yyy rdfs:subClassOf zzz && (nt) xxx rdfs:subClassOf yyy -->
* (t1) xxx rdfs:subClassOf zzz (t2)
*/
private int applyRuleRdfs11_2()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> ntIter = this.newThisIteration.match(null, RDFS.SUBCLASSOF, null);
while (ntIter.hasNext()) {
Statement nt = ntIter.next();
Resource yyy = nt.getSubject();
Value zzz = nt.getObject();
if (zzz instanceof Resource) {
CloseableIteration<? extends Statement, SailException> t1Iter;
t1Iter = getWrappedConnection().getStatements(null, RDFS.SUBCLASSOF, yyy, true);
while (t1Iter.hasNext()) {
Statement t1 = t1Iter.next();
Resource xxx = t1.getSubject();
boolean added = addInferredStatement(xxx, RDFS.SUBCLASSOF, zzz);
if (added) {
nofInferred++;
}
}
t1Iter.close();
}
}
return nofInferred;
}
/*
* rdfs12. xxx rdf:type rdfs:ContainerMembershipProperty --> xxx
* rdfs:subPropertyOf rdfs:member
*/
private int applyRuleRdfs12()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> iter = this.newThisIteration.match(null, RDF.TYPE, RDFS.CONTAINERMEMBERSHIPPROPERTY);
while (iter.hasNext()) {
Statement st = iter.next();
Resource xxx = st.getSubject();
boolean added = addInferredStatement(xxx, RDFS.SUBPROPERTYOF, RDFS.MEMBER);
if (added) {
nofInferred++;
}
}
return nofInferred;
}
/*
* rdfs13. xxx rdf:type rdfs:Datatype --> xxx rdfs:subClassOf rdfs:Literal
*/
private int applyRuleRdfs13()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> iter = this.newThisIteration.match(null, RDF.TYPE, RDFS.DATATYPE);
while (iter.hasNext()) {
Statement st = iter.next();
Resource xxx = st.getSubject();
boolean added = addInferredStatement(xxx, RDFS.SUBCLASSOF, RDFS.LITERAL);
if (added) {
nofInferred++;
}
}
return nofInferred;
}
/*
* X1. xxx rdf:_* yyy --> rdf:_* rdf:type rdfs:ContainerMembershipProperty
* This is an extra rule for list membership properties (_1, _2, _3, ...).
* The RDF MT does not specificy a production for this.
*/
private int applyRuleX1()
throws SailException
{
int nofInferred = 0;
String prefix = RDF.NAMESPACE + "_";
Iterator<Statement> iter = this.newThisIteration.match(null, null, null);
while (iter.hasNext()) {
Statement st = iter.next();
URI predNode = st.getPredicate();
String predURI = predNode.toString();
if (predURI.startsWith(prefix) && isValidPredicateNumber(predURI.substring(prefix.length()))) {
boolean added = addInferredStatement(predNode, RDF.TYPE, RDFS.CONTAINERMEMBERSHIPPROPERTY);
if (added) {
nofInferred++;
}
}
}
return nofInferred;
}
/**
* xxx nrl:inverseProperty yyy
* aaa xxx bbb
* -->
* bbb yyy aaa
* @return
* @throws SailException
*/
private int applyRuleN1a()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> ntIter = this.newThisIteration.match(null, NRL_InverseProperty, null);
while (ntIter.hasNext()) {
Statement nt = ntIter.next();
Resource xxx = nt.getSubject();
Value yyy = nt.getObject();
if (xxx instanceof URI && yyy instanceof URI) {
// apply to triples using the property
CloseableIteration<? extends Statement, SailException> t1Iter;
t1Iter = getWrappedConnection().getStatements(null, (URI)xxx, null, true);
while (t1Iter.hasNext()) {
Statement t1 = t1Iter.next();
Value aaa = t1.getSubject();
Value bbb = t1.getObject();
if (bbb instanceof Resource) {
boolean added = addInferredStatement((Resource)bbb, (URI) yyy, aaa);
if (added) {
nofInferred++;
}
}
}
t1Iter.close();
}
}
return nofInferred;
}
/**
* aaa xxx bbb
* xxx nrl:inverseProperty yyy
* -->
* bbb yyy aaa
* @return
* @throws SailException
*/
private int applyRuleN1b()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> ntIter = this.newThisIteration.match(null, null, null);
while (ntIter.hasNext()) {
Statement nt = ntIter.next();
Resource xxx = nt.getPredicate();
CloseableIteration<? extends Statement, SailException> t1Iter;
t1Iter = getWrappedConnection().getStatements(xxx,NRL_InverseProperty, null, true);
while (t1Iter.hasNext()) {
Statement t1 = t1Iter.next();
Value yyy = t1.getObject();
if (yyy instanceof URI) {
Resource aaa = nt.getSubject();
Value bbb = nt.getObject();
boolean added = addInferredStatement((Resource)bbb, (URI) yyy, aaa);
if (added) {
nofInferred++;
}
}
}
t1Iter.close();
}
return nofInferred;
}
/**
* New: ppp nrl:inverseProperty qqq
*
* ... AND (case 1)
* rrr rdfs:subPropertyOf ppp /\ rrr nrl:inverseProperty sss
* -->
* sss rdfs:subPropertyOf qqq
*
*
* ... AND (case 2)
* ppp rdfs:subPropertyOf ttt (2)
* ttt nrl:inverseProperty uuu (1)
* -->
* qqq rdfs:subPropertyOf uuu
*
* @return
* @throws SailException
*/
private int applyRuleN2a()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> it1 = this.newThisIteration.match(null, NRL_InverseProperty, null);
while (it1.hasNext()) {
Statement stmt1 = it1.next();
Resource ppp = stmt1.getSubject();
Value qqq = stmt1.getObject();
if(qqq instanceof Resource) {
// case 1
CloseableIteration<? extends Statement, SailException> it2;
it2 = getWrappedConnection().getStatements(null,RDFS.SUBPROPERTYOF, ppp, true);
while (it2.hasNext()) {
Statement stmt2 = it2.next();
Resource rrr = stmt2.getSubject();
CloseableIteration<? extends Statement, SailException> it3;
it3 = getWrappedConnection().getStatements(rrr,NRL_InverseProperty, null, true);
while (it3.hasNext()) {
Statement stmt3 = it3.next();
Value sss = stmt3.getObject();
if( sss instanceof Resource) {
boolean added = addInferredStatement((Resource)sss, RDFS.SUBPROPERTYOF, qqq);
if (added) {
nofInferred++;
}
}
}
it3.close();
}
it2.close();
// case 2
it2 = getWrappedConnection().getStatements(ppp,RDFS.SUBPROPERTYOF, null, true);
while (it2.hasNext()) {
Statement stmt2 = it2.next();
Value ttt = stmt2.getObject();
if( ttt instanceof Resource) {
CloseableIteration<? extends Statement, SailException> it3;
it3 = getWrappedConnection().getStatements( (Resource) ttt,NRL_InverseProperty, null, true);
while (it3.hasNext()) {
Statement stmt3 = it3.next();
Value uuu = stmt3.getObject();
if( uuu instanceof Resource) {
boolean added = addInferredStatement((Resource)qqq, RDFS.SUBPROPERTYOF, uuu);
if (added) {
nofInferred++;
}
}
}
it3.close();
}
}
it2.close();
}
}
return nofInferred;
}
/**
* rrr rdfs:subPropertyOf ppp
* rrr nrl:inverseProperty sss
* ppp nrl:inverseProperty qqq
* -->
* sss rdfs:subPropertyOf qqq
* @return
* @throws SailException
*/
private int applyRuleN2b()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> it1 = this.newThisIteration.match(null, RDFS.SUBPROPERTYOF, null);
while (it1.hasNext()) {
Statement stmt1 = it1.next();
Resource rrr = stmt1.getSubject();
Value ppp = stmt1.getObject();
if(ppp instanceof Resource) {
CloseableIteration<? extends Statement, SailException> it2;
it2 = getWrappedConnection().getStatements(rrr,NRL_InverseProperty, null, true);
while (it2.hasNext()) {
Statement stmt2 = it2.next();
Value sss = stmt2.getObject();
if(sss instanceof Resource) {
CloseableIteration<? extends Statement, SailException> it3;
it3 = getWrappedConnection().getStatements( (Resource) ppp,NRL_InverseProperty, null, true);
while (it3.hasNext()) {
Statement stmt3 = it3.next();
Value qqq = stmt3.getObject();
if( qqq instanceof Resource) {
boolean added = addInferredStatement((Resource)sss, RDFS.SUBPROPERTYOF, qqq);
if (added) {
nofInferred++;
}
}
}
it3.close();
}
}
it2.close();
}
}
return nofInferred;
}
/**
* ppp nrl:inverseProperty qqq
* -->
* qqq nrl:inverseProperty ppp
* ppp a rdf:Property
* qqq a rdf:Property
*
* @return
* @throws SailException
*/
private int applyRuleN3()
throws SailException
{
int nofInferred = 0;
Iterator<Statement> it1 = this.newThisIteration.match(null, NRL_InverseProperty, null);
while (it1.hasNext()) {
Statement stmt1 = it1.next();
Resource ppp = stmt1.getSubject();
if(ppp instanceof URI) {
// infer: ppp is a property
boolean addedPPP = addInferredStatement(ppp, RDF.TYPE, RDF.PROPERTY);
if (addedPPP) {
nofInferred++;
}
}
Value qqq = stmt1.getObject();
if(qqq instanceof Resource) {
if(qqq instanceof URI) {
// infer: qqq is a property
boolean addedQQQ = addInferredStatement((URI)qqq, RDF.TYPE, RDF.PROPERTY);
if (addedQQQ) {
nofInferred++;
}
}
if(! qqq.equals(ppp)) {
// infer: qqq inverse ppp
boolean added = addInferredStatement((Resource)qqq, NRL_InverseProperty, ppp);
if (added) {
nofInferred++;
}
}
}
}
return nofInferred;
}
/**
* Util method for {@link #applyRuleX1}.
*/
private boolean isValidPredicateNumber(String str) {
int strLength = str.length();
if (strLength == 0) {
return false;
}
for (int i = 0; i < strLength; i++) {
if (!ASCIIUtil.isNumber(str.charAt(i))) {
return false;
}
}
// No leading zeros
if (str.charAt(0) == '0') {
return false;
}
return true;
}
}