0001: /*
0002: * Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2007.
0003: *
0004: * Licensed under the Aduna BSD-style license.
0005: */
0006: package org.openrdf.sail.inferencer.fc;
0007:
0008: import java.util.Iterator;
0009:
0010: import org.slf4j.Logger;
0011: import org.slf4j.LoggerFactory;
0012:
0013: import info.aduna.iteration.CloseableIteration;
0014: import info.aduna.iteration.Iterations;
0015: import info.aduna.text.ASCIIUtil;
0016:
0017: import org.openrdf.model.Graph;
0018: import org.openrdf.model.Resource;
0019: import org.openrdf.model.Statement;
0020: import org.openrdf.model.URI;
0021: import org.openrdf.model.Value;
0022: import org.openrdf.model.impl.GraphImpl;
0023: import org.openrdf.model.vocabulary.RDF;
0024: import org.openrdf.model.vocabulary.RDFS;
0025: import org.openrdf.sail.Sail;
0026: import org.openrdf.sail.SailConnectionListener;
0027: import org.openrdf.sail.SailException;
0028: import org.openrdf.sail.inferencer.InferencerConnection;
0029: import org.openrdf.sail.inferencer.InferencerConnectionWrapper;
0030:
0031: /**
0032: * Forward-chaining RDF Schema inferencer, using the rules from the <a
0033: * href="http://www.w3.org/TR/2004/REC-rdf-mt-20040210/">RDF Semantics
0034: * Recommendation (10 February 2004)</a>. This inferencer can be used to add
0035: * RDF Schema semantics to any Sail that returns {@link InferencerConnection}s
0036: * from their {@link Sail#getConnection()} method.
0037: */
0038: class ForwardChainingRDFSInferencerConnection extends
0039: InferencerConnectionWrapper implements SailConnectionListener {
0040:
0041: /*-----------*
0042: * Constants *
0043: *-----------*/
0044:
0045: protected final Logger logger = LoggerFactory.getLogger(this
0046: .getClass());
0047:
0048: /*-----------*
0049: * Variables *
0050: *-----------*/
0051:
0052: /**
0053: * true if the base Sail reported removed statements.
0054: */
0055: private boolean statementsRemoved;
0056:
0057: /**
0058: * Contains the statements that have been reported by the base Sail as
0059: */
0060: private Graph newStatements;
0061:
0062: private Graph newThisIteration;
0063:
0064: /**
0065: * Flags indicating which rules should be evaluated.
0066: */
0067: private boolean[] checkRule = new boolean[RDFSRules.RULECOUNT];
0068:
0069: /**
0070: * Flags indicating which rules should be evaluated next iteration.
0071: */
0072: private boolean[] checkRuleNextIter = new boolean[RDFSRules.RULECOUNT];
0073:
0074: private int totalInferred = 0;
0075:
0076: /**
0077: * The number of inferred statements per rule.
0078: */
0079: private int[] ruleCount = new int[RDFSRules.RULECOUNT];
0080:
0081: /*--------------*
0082: * Constructors *
0083: *--------------*/
0084:
0085: public ForwardChainingRDFSInferencerConnection(
0086: InferencerConnection con) {
0087: super (con);
0088: con.addConnectionListener(this );
0089: }
0090:
0091: /*---------*
0092: * Methods *
0093: *---------*/
0094:
0095: // Called by base sail
0096: public void statementAdded(Statement st) {
0097: if (statementsRemoved) {
0098: // No need to record, starting from scratch anyway
0099: return;
0100: }
0101:
0102: if (newStatements == null) {
0103: newStatements = new GraphImpl();
0104: }
0105: newStatements.add(st);
0106: }
0107:
0108: // Called by base sail
0109: public void statementRemoved(Statement st) {
0110: statementsRemoved = true;
0111: newStatements = null;
0112: }
0113:
0114: @Override
0115: public void flushUpdates() throws SailException {
0116: super .flushUpdates();
0117:
0118: if (statementsRemoved) {
0119: logger
0120: .debug("statements removed, starting inferencing from scratch");
0121: clearInferred();
0122: addAxiomStatements();
0123:
0124: newStatements = new GraphImpl();
0125: Iterations.addAll(getWrappedConnection().getStatements(
0126: null, null, null, true), newStatements);
0127:
0128: statementsRemoved = false;
0129: }
0130:
0131: doInferencing();
0132: }
0133:
0134: @Override
0135: public void rollback() throws SailException {
0136: statementsRemoved = false;
0137: newStatements = null;
0138:
0139: super .rollback();
0140: }
0141:
0142: /**
0143: * Adds all basic set of axiom statements from which the complete set can be
0144: * inferred to the underlying Sail.
0145: */
0146: protected void addAxiomStatements() throws SailException {
0147: logger.debug("Inserting axiom statements");
0148:
0149: // RDF axiomatic triples (from RDF Semantics, section 3.1):
0150:
0151: addInferredStatement(RDF.TYPE, RDF.TYPE, RDF.PROPERTY);
0152: addInferredStatement(RDF.SUBJECT, RDF.TYPE, RDF.PROPERTY);
0153: addInferredStatement(RDF.PREDICATE, RDF.TYPE, RDF.PROPERTY);
0154: addInferredStatement(RDF.OBJECT, RDF.TYPE, RDF.PROPERTY);
0155:
0156: addInferredStatement(RDF.FIRST, RDF.TYPE, RDF.PROPERTY);
0157: addInferredStatement(RDF.REST, RDF.TYPE, RDF.PROPERTY);
0158: addInferredStatement(RDF.VALUE, RDF.TYPE, RDF.PROPERTY);
0159:
0160: addInferredStatement(RDF.NIL, RDF.TYPE, RDF.LIST);
0161:
0162: // RDFS axiomatic triples (from RDF Semantics, section 4.1):
0163:
0164: addInferredStatement(RDF.TYPE, RDFS.DOMAIN, RDFS.RESOURCE);
0165: addInferredStatement(RDFS.DOMAIN, RDFS.DOMAIN, RDF.PROPERTY);
0166: addInferredStatement(RDFS.RANGE, RDFS.DOMAIN, RDF.PROPERTY);
0167: addInferredStatement(RDFS.SUBPROPERTYOF, RDFS.DOMAIN,
0168: RDF.PROPERTY);
0169: addInferredStatement(RDFS.SUBCLASSOF, RDFS.DOMAIN, RDFS.CLASS);
0170: addInferredStatement(RDF.SUBJECT, RDFS.DOMAIN, RDF.STATEMENT);
0171: addInferredStatement(RDF.PREDICATE, RDFS.DOMAIN, RDF.STATEMENT);
0172: addInferredStatement(RDF.OBJECT, RDFS.DOMAIN, RDF.STATEMENT);
0173: addInferredStatement(RDFS.MEMBER, RDFS.DOMAIN, RDFS.RESOURCE);
0174: addInferredStatement(RDF.FIRST, RDFS.DOMAIN, RDF.LIST);
0175: addInferredStatement(RDF.REST, RDFS.DOMAIN, RDF.LIST);
0176: addInferredStatement(RDFS.SEEALSO, RDFS.DOMAIN, RDFS.RESOURCE);
0177: addInferredStatement(RDFS.ISDEFINEDBY, RDFS.DOMAIN,
0178: RDFS.RESOURCE);
0179: addInferredStatement(RDFS.COMMENT, RDFS.DOMAIN, RDFS.RESOURCE);
0180: addInferredStatement(RDFS.LABEL, RDFS.DOMAIN, RDFS.RESOURCE);
0181: addInferredStatement(RDF.VALUE, RDFS.DOMAIN, RDFS.RESOURCE);
0182:
0183: addInferredStatement(RDF.TYPE, RDFS.RANGE, RDFS.CLASS);
0184: addInferredStatement(RDFS.DOMAIN, RDFS.RANGE, RDFS.CLASS);
0185: addInferredStatement(RDFS.RANGE, RDFS.RANGE, RDFS.CLASS);
0186: addInferredStatement(RDFS.SUBPROPERTYOF, RDFS.RANGE,
0187: RDF.PROPERTY);
0188: addInferredStatement(RDFS.SUBCLASSOF, RDFS.RANGE, RDFS.CLASS);
0189: addInferredStatement(RDF.SUBJECT, RDFS.RANGE, RDFS.RESOURCE);
0190: addInferredStatement(RDF.PREDICATE, RDFS.RANGE, RDFS.RESOURCE);
0191: addInferredStatement(RDF.OBJECT, RDFS.RANGE, RDFS.RESOURCE);
0192: addInferredStatement(RDFS.MEMBER, RDFS.RANGE, RDFS.RESOURCE);
0193: addInferredStatement(RDF.FIRST, RDFS.RANGE, RDFS.RESOURCE);
0194: addInferredStatement(RDF.REST, RDFS.RANGE, RDF.LIST);
0195: addInferredStatement(RDFS.SEEALSO, RDFS.RANGE, RDFS.RESOURCE);
0196: addInferredStatement(RDFS.ISDEFINEDBY, RDFS.RANGE,
0197: RDFS.RESOURCE);
0198: addInferredStatement(RDFS.COMMENT, RDFS.RANGE, RDFS.LITERAL);
0199: addInferredStatement(RDFS.LABEL, RDFS.RANGE, RDFS.LITERAL);
0200: addInferredStatement(RDF.VALUE, RDFS.RANGE, RDFS.RESOURCE);
0201:
0202: addInferredStatement(RDF.ALT, RDFS.SUBCLASSOF, RDFS.CONTAINER);
0203: addInferredStatement(RDF.BAG, RDFS.SUBCLASSOF, RDFS.CONTAINER);
0204: addInferredStatement(RDF.SEQ, RDFS.SUBCLASSOF, RDFS.CONTAINER);
0205: addInferredStatement(RDFS.CONTAINERMEMBERSHIPPROPERTY,
0206: RDFS.SUBCLASSOF, RDF.PROPERTY);
0207:
0208: addInferredStatement(RDFS.ISDEFINEDBY, RDFS.SUBPROPERTYOF,
0209: RDFS.SEEALSO);
0210:
0211: addInferredStatement(RDF.XMLLITERAL, RDF.TYPE, RDFS.DATATYPE);
0212: addInferredStatement(RDF.XMLLITERAL, RDFS.SUBCLASSOF,
0213: RDFS.LITERAL);
0214: addInferredStatement(RDFS.DATATYPE, RDFS.SUBCLASSOF, RDFS.CLASS);
0215: }
0216:
0217: protected void doInferencing() throws SailException {
0218: if (!hasNewStatements()) {
0219: // There's nothing to do
0220: return;
0221: }
0222:
0223: // initialize some vars
0224: totalInferred = 0;
0225: int iteration = 0;
0226: int nofInferred = 1;
0227:
0228: // All rules need to be checked:
0229: for (int i = 0; i < RDFSRules.RULECOUNT; i++) {
0230: ruleCount[i] = 0;
0231: checkRuleNextIter[i] = true;
0232: }
0233:
0234: while (hasNewStatements()) {
0235: iteration++;
0236: logger.debug("starting iteration " + iteration);
0237: prepareIteration();
0238:
0239: nofInferred = 0;
0240: nofInferred += applyRule(RDFSRules.Rdf1);
0241: nofInferred += applyRule(RDFSRules.Rdfs2_1);
0242: nofInferred += applyRule(RDFSRules.Rdfs2_2);
0243: nofInferred += applyRule(RDFSRules.Rdfs3_1);
0244: nofInferred += applyRule(RDFSRules.Rdfs3_2);
0245: nofInferred += applyRule(RDFSRules.Rdfs4a);
0246: nofInferred += applyRule(RDFSRules.Rdfs4b);
0247: nofInferred += applyRule(RDFSRules.Rdfs5_1);
0248: nofInferred += applyRule(RDFSRules.Rdfs5_2);
0249: nofInferred += applyRule(RDFSRules.Rdfs6);
0250: nofInferred += applyRule(RDFSRules.Rdfs7_1);
0251: nofInferred += applyRule(RDFSRules.Rdfs7_2);
0252: nofInferred += applyRule(RDFSRules.Rdfs8);
0253: nofInferred += applyRule(RDFSRules.Rdfs9_1);
0254: nofInferred += applyRule(RDFSRules.Rdfs9_2);
0255: nofInferred += applyRule(RDFSRules.Rdfs10);
0256: nofInferred += applyRule(RDFSRules.Rdfs11_1);
0257: nofInferred += applyRule(RDFSRules.Rdfs11_2);
0258: nofInferred += applyRule(RDFSRules.Rdfs12);
0259: nofInferred += applyRule(RDFSRules.Rdfs13);
0260: nofInferred += applyRule(RDFSRules.RX1);
0261:
0262: logger.debug("iteration " + iteration + " done; inferred "
0263: + nofInferred + " new statements");
0264: totalInferred += nofInferred;
0265: }
0266:
0267: // Print some statistics
0268: logger.debug("---RdfMTInferencer statistics:---");
0269: logger.debug("total statements inferred = " + totalInferred);
0270: for (int i = 0; i < RDFSRules.RULECOUNT; i++) {
0271: logger.debug("rule " + RDFSRules.RULENAMES[i]
0272: + ":\t#inferred=" + ruleCount[i]);
0273: }
0274: logger.debug("---end of statistics:---");
0275: }
0276:
0277: protected void prepareIteration() {
0278: for (int i = 0; i < RDFSRules.RULECOUNT; i++) {
0279: checkRule[i] = checkRuleNextIter[i];
0280:
0281: // reset for next iteration:
0282: checkRuleNextIter[i] = false;
0283: }
0284:
0285: newThisIteration = newStatements;
0286: newStatements = new GraphImpl();
0287: }
0288:
0289: protected boolean hasNewStatements() {
0290: return newStatements != null && !newStatements.isEmpty();
0291: }
0292:
0293: protected void updateTriggers(int ruleNo, int nofInferred) {
0294: if (nofInferred > 0) {
0295: ruleCount[ruleNo] += nofInferred;
0296:
0297: // Check which rules are triggered by this one.
0298: boolean[] triggers = RDFSRules.TRIGGERS[ruleNo];
0299:
0300: for (int i = 0; i < RDFSRules.RULECOUNT; i++) {
0301: if (triggers[i] == true) {
0302: checkRuleNextIter[i] = true;
0303: }
0304: }
0305: }
0306: }
0307:
0308: protected int applyRule(int rule) throws SailException {
0309: if (!checkRule[rule]) {
0310: return 0;
0311: }
0312: int nofInferred = 0;
0313:
0314: nofInferred = applyRuleInternal(rule);
0315:
0316: updateTriggers(rule, nofInferred);
0317:
0318: return nofInferred;
0319: }
0320:
0321: protected int applyRuleInternal(int rule) throws SailException {
0322: int result = 0;
0323:
0324: switch (rule) {
0325: case RDFSRules.Rdf1:
0326: result = applyRuleRdf1();
0327: break;
0328: case RDFSRules.Rdfs2_1:
0329: result = applyRuleRdfs2_1();
0330: break;
0331: case RDFSRules.Rdfs2_2:
0332: result = applyRuleRdfs2_2();
0333: break;
0334: case RDFSRules.Rdfs3_1:
0335: result = applyRuleRdfs3_1();
0336: break;
0337: case RDFSRules.Rdfs3_2:
0338: result = applyRuleRdfs3_2();
0339: break;
0340: case RDFSRules.Rdfs4a:
0341: result = applyRuleRdfs4a();
0342: break;
0343: case RDFSRules.Rdfs4b:
0344: result = applyRuleRdfs4b();
0345: break;
0346: case RDFSRules.Rdfs5_1:
0347: result = applyRuleRdfs5_1();
0348: break;
0349: case RDFSRules.Rdfs5_2:
0350: result = applyRuleRdfs5_2();
0351: break;
0352: case RDFSRules.Rdfs6:
0353: result = applyRuleRdfs6();
0354: break;
0355: case RDFSRules.Rdfs7_1:
0356: result = applyRuleRdfs7_1();
0357: break;
0358: case RDFSRules.Rdfs7_2:
0359: result = applyRuleRdfs7_2();
0360: break;
0361: case RDFSRules.Rdfs8:
0362: result = applyRuleRdfs8();
0363: break;
0364: case RDFSRules.Rdfs9_1:
0365: result = applyRuleRdfs9_1();
0366: break;
0367: case RDFSRules.Rdfs9_2:
0368: result = applyRuleRdfs9_2();
0369: break;
0370: case RDFSRules.Rdfs10:
0371: result = applyRuleRdfs10();
0372: break;
0373: case RDFSRules.Rdfs11_1:
0374: result = applyRuleRdfs11_1();
0375: break;
0376: case RDFSRules.Rdfs11_2:
0377: result = applyRuleRdfs11_2();
0378: break;
0379: case RDFSRules.Rdfs12:
0380: result = applyRuleRdfs12();
0381: break;
0382: case RDFSRules.Rdfs13:
0383: result = applyRuleRdfs13();
0384: break;
0385: case RDFSRules.RX1:
0386: result = applyRuleX1();
0387: break;
0388: default:
0389: // FIXME throw exception here?
0390: break;
0391: }
0392: // ThreadLog.trace("Rule " + RDFSRules.RULENAMES[rule] + " inferred " +
0393: // result + " new triples.");
0394: return result;
0395: }
0396:
0397: // xxx aaa yyy --> aaa rdf:type rdf:Property
0398: private int applyRuleRdf1() throws SailException {
0399: int nofInferred = 0;
0400:
0401: Iterator<Statement> iter = newThisIteration.match(null, null,
0402: null);
0403:
0404: while (iter.hasNext()) {
0405: Statement st = iter.next();
0406:
0407: boolean added = addInferredStatement(st.getPredicate(),
0408: RDF.TYPE, RDF.PROPERTY);
0409:
0410: if (added) {
0411: nofInferred++;
0412: }
0413: }
0414:
0415: return nofInferred;
0416: }
0417:
0418: // xxx aaa yyy (nt) && aaa rdfs:domain zzz (t1) --> xxx rdf:type zzz
0419: private int applyRuleRdfs2_1() throws SailException {
0420: int nofInferred = 0;
0421:
0422: Iterator<Statement> ntIter = newThisIteration.match(null, null,
0423: null);
0424:
0425: while (ntIter.hasNext()) {
0426: Statement nt = ntIter.next();
0427:
0428: Resource xxx = nt.getSubject();
0429: URI aaa = nt.getPredicate();
0430:
0431: CloseableIteration<? extends Statement, SailException> t1Iter;
0432: t1Iter = getWrappedConnection().getStatements(aaa,
0433: RDFS.DOMAIN, null, true);
0434:
0435: while (t1Iter.hasNext()) {
0436: Statement t1 = t1Iter.next();
0437:
0438: Value zzz = t1.getObject();
0439: if (zzz instanceof Resource) {
0440: boolean added = addInferredStatement(xxx, RDF.TYPE,
0441: zzz);
0442: if (added) {
0443: nofInferred++;
0444: }
0445: }
0446: }
0447: t1Iter.close();
0448: }
0449:
0450: return nofInferred;
0451: }
0452:
0453: // aaa rdfs:domain zzz (nt) && xxx aaa yyy (t1) --> xxx rdf:type zzz
0454: private int applyRuleRdfs2_2() throws SailException {
0455: int nofInferred = 0;
0456:
0457: Iterator<Statement> ntIter = newThisIteration.match(null,
0458: RDFS.DOMAIN, null);
0459:
0460: while (ntIter.hasNext()) {
0461: Statement nt = ntIter.next();
0462:
0463: Resource aaa = nt.getSubject();
0464: Value zzz = nt.getObject();
0465:
0466: if (aaa instanceof URI && zzz instanceof Resource) {
0467: CloseableIteration<? extends Statement, SailException> t1Iter;
0468: t1Iter = getWrappedConnection().getStatements(null,
0469: (URI) aaa, null, true);
0470:
0471: while (t1Iter.hasNext()) {
0472: Statement t1 = t1Iter.next();
0473:
0474: Resource xxx = t1.getSubject();
0475: boolean added = addInferredStatement(xxx, RDF.TYPE,
0476: zzz);
0477: if (added) {
0478: nofInferred++;
0479: }
0480: }
0481: t1Iter.close();
0482: }
0483: }
0484:
0485: return nofInferred;
0486: }
0487:
0488: // xxx aaa uuu (nt) && aaa rdfs:range zzz (t1) --> uuu rdf:type zzz
0489: private int applyRuleRdfs3_1() throws SailException {
0490: int nofInferred = 0;
0491:
0492: Iterator<Statement> ntIter = newThisIteration.match(null, null,
0493: null);
0494:
0495: while (ntIter.hasNext()) {
0496: Statement nt = ntIter.next();
0497:
0498: URI aaa = nt.getPredicate();
0499: Value uuu = nt.getObject();
0500:
0501: if (uuu instanceof Resource) {
0502: CloseableIteration<? extends Statement, SailException> t1Iter;
0503: t1Iter = getWrappedConnection().getStatements(aaa,
0504: RDFS.RANGE, null, true);
0505:
0506: while (t1Iter.hasNext()) {
0507: Statement t1 = t1Iter.next();
0508:
0509: Value zzz = t1.getObject();
0510: if (zzz instanceof Resource) {
0511: boolean added = addInferredStatement(
0512: (Resource) uuu, RDF.TYPE, zzz);
0513: if (added) {
0514: nofInferred++;
0515: }
0516: }
0517: }
0518: t1Iter.close();
0519: }
0520: }
0521: return nofInferred;
0522: }
0523:
0524: // aaa rdfs:range zzz (nt) && xxx aaa uuu (t1) --> uuu rdf:type zzz
0525: private int applyRuleRdfs3_2() throws SailException {
0526: int nofInferred = 0;
0527:
0528: Iterator<Statement> ntIter = newThisIteration.match(null,
0529: RDFS.RANGE, null);
0530:
0531: while (ntIter.hasNext()) {
0532: Statement nt = ntIter.next();
0533:
0534: Resource aaa = nt.getSubject();
0535: Value zzz = nt.getObject();
0536:
0537: if (aaa instanceof URI && zzz instanceof Resource) {
0538: CloseableIteration<? extends Statement, SailException> t1Iter;
0539: t1Iter = getWrappedConnection().getStatements(null,
0540: (URI) aaa, null, true);
0541:
0542: while (t1Iter.hasNext()) {
0543: Statement t1 = t1Iter.next();
0544:
0545: Value uuu = t1.getObject();
0546: if (uuu instanceof Resource) {
0547: boolean added = addInferredStatement(
0548: (Resource) uuu, RDF.TYPE, zzz);
0549: if (added) {
0550: nofInferred++;
0551: }
0552: }
0553: }
0554: t1Iter.close();
0555: }
0556: }
0557:
0558: return nofInferred;
0559:
0560: }
0561:
0562: // xxx aaa yyy --> xxx rdf:type rdfs:Resource
0563: private int applyRuleRdfs4a() throws SailException {
0564: int nofInferred = 0;
0565:
0566: Iterator<Statement> iter = newThisIteration.match(null, null,
0567: null);
0568:
0569: while (iter.hasNext()) {
0570: Statement st = iter.next();
0571:
0572: boolean added = addInferredStatement(st.getSubject(),
0573: RDF.TYPE, RDFS.RESOURCE);
0574: if (added) {
0575: nofInferred++;
0576: }
0577: }
0578:
0579: return nofInferred;
0580: }
0581:
0582: // xxx aaa uuu --> uuu rdf:type rdfs:Resource
0583: private int applyRuleRdfs4b() throws SailException {
0584: int nofInferred = 0;
0585:
0586: Iterator<Statement> iter = newThisIteration.match(null, null,
0587: null);
0588:
0589: while (iter.hasNext()) {
0590: Statement st = iter.next();
0591:
0592: Value uuu = st.getObject();
0593: if (uuu instanceof Resource) {
0594: boolean added = addInferredStatement((Resource) uuu,
0595: RDF.TYPE, RDFS.RESOURCE);
0596: if (added) {
0597: nofInferred++;
0598: }
0599: }
0600: }
0601:
0602: return nofInferred;
0603: }
0604:
0605: // aaa rdfs:subPropertyOf bbb (nt) && bbb rdfs:subPropertyOf ccc (t1)
0606: // --> aaa rdfs:subPropertyOf ccc
0607: private int applyRuleRdfs5_1() throws SailException {
0608: int nofInferred = 0;
0609:
0610: Iterator<Statement> ntIter = newThisIteration.match(null,
0611: RDFS.SUBPROPERTYOF, null);
0612:
0613: while (ntIter.hasNext()) {
0614: Statement nt = ntIter.next();
0615:
0616: Resource aaa = nt.getSubject();
0617: Value bbb = nt.getObject();
0618:
0619: if (bbb instanceof Resource) {
0620: CloseableIteration<? extends Statement, SailException> t1Iter;
0621: t1Iter = getWrappedConnection().getStatements(
0622: (Resource) bbb, RDFS.SUBPROPERTYOF, null, true);
0623:
0624: while (t1Iter.hasNext()) {
0625: Statement t1 = t1Iter.next();
0626:
0627: Value ccc = t1.getObject();
0628: if (ccc instanceof Resource) {
0629: boolean added = addInferredStatement(aaa,
0630: RDFS.SUBPROPERTYOF, ccc);
0631: if (added) {
0632: nofInferred++;
0633: }
0634: }
0635: }
0636: t1Iter.close();
0637:
0638: }
0639: }
0640:
0641: return nofInferred;
0642: }
0643:
0644: // bbb rdfs:subPropertyOf ccc (nt) && aaa rdfs:subPropertyOf bbb (t1)
0645: // --> aaa rdfs:subPropertyOf ccc
0646: private int applyRuleRdfs5_2() throws SailException {
0647: int nofInferred = 0;
0648:
0649: Iterator<Statement> ntIter = newThisIteration.match(null,
0650: RDFS.SUBPROPERTYOF, null);
0651:
0652: while (ntIter.hasNext()) {
0653: Statement nt = ntIter.next();
0654:
0655: Resource bbb = nt.getSubject();
0656: Value ccc = nt.getObject();
0657:
0658: if (ccc instanceof Resource) {
0659: CloseableIteration<? extends Statement, SailException> t1Iter;
0660: t1Iter = getWrappedConnection().getStatements(null,
0661: RDFS.SUBPROPERTYOF, bbb, true);
0662:
0663: while (t1Iter.hasNext()) {
0664: Statement t1 = t1Iter.next();
0665:
0666: Resource aaa = t1.getSubject();
0667: boolean added = addInferredStatement(aaa,
0668: RDFS.SUBPROPERTYOF, ccc);
0669: if (added) {
0670: nofInferred++;
0671: }
0672: }
0673: t1Iter.close();
0674: }
0675: }
0676:
0677: return nofInferred;
0678: }
0679:
0680: // xxx rdf:type rdf:Property --> xxx rdfs:subPropertyOf xxx
0681: private int applyRuleRdfs6() throws SailException {
0682: int nofInferred = 0;
0683:
0684: Iterator<Statement> iter = newThisIteration.match(null,
0685: RDF.TYPE, RDF.PROPERTY);
0686:
0687: while (iter.hasNext()) {
0688: Statement st = iter.next();
0689:
0690: Resource xxx = st.getSubject();
0691: boolean added = addInferredStatement(xxx,
0692: RDFS.SUBPROPERTYOF, xxx);
0693: if (added) {
0694: nofInferred++;
0695: }
0696: }
0697:
0698: return nofInferred;
0699: }
0700:
0701: // xxx aaa yyy (nt) && aaa rdfs:subPropertyOf bbb (t1) --> xxx bbb yyy
0702: private int applyRuleRdfs7_1() throws SailException {
0703: int nofInferred = 0;
0704:
0705: Iterator<Statement> ntIter = newThisIteration.match(null, null,
0706: null);
0707:
0708: while (ntIter.hasNext()) {
0709: Statement nt = ntIter.next();
0710:
0711: Resource xxx = nt.getSubject();
0712: URI aaa = nt.getPredicate();
0713: Value yyy = nt.getObject();
0714:
0715: CloseableIteration<? extends Statement, SailException> t1Iter;
0716: t1Iter = getWrappedConnection().getStatements(aaa,
0717: RDFS.SUBPROPERTYOF, null, true);
0718:
0719: while (t1Iter.hasNext()) {
0720: Statement t1 = t1Iter.next();
0721:
0722: Value bbb = t1.getObject();
0723: if (bbb instanceof URI) {
0724: boolean added = addInferredStatement(xxx,
0725: (URI) bbb, yyy);
0726: if (added) {
0727: nofInferred++;
0728: }
0729: }
0730: }
0731: t1Iter.close();
0732: }
0733:
0734: return nofInferred;
0735: }
0736:
0737: // aaa rdfs:subPropertyOf bbb (nt) && xxx aaa yyy (t1) --> xxx bbb yyy
0738: private int applyRuleRdfs7_2() throws SailException {
0739: int nofInferred = 0;
0740:
0741: Iterator<Statement> ntIter = newThisIteration.match(null,
0742: RDFS.SUBPROPERTYOF, null);
0743:
0744: while (ntIter.hasNext()) {
0745: Statement nt = ntIter.next();
0746:
0747: Resource aaa = nt.getSubject();
0748: Value bbb = nt.getObject();
0749:
0750: if (aaa instanceof URI && bbb instanceof URI) {
0751: CloseableIteration<? extends Statement, SailException> t1Iter;
0752: t1Iter = getWrappedConnection().getStatements(null,
0753: (URI) aaa, null, true);
0754:
0755: while (t1Iter.hasNext()) {
0756: Statement t1 = t1Iter.next();
0757:
0758: Resource xxx = t1.getSubject();
0759: Value yyy = t1.getObject();
0760:
0761: boolean added = addInferredStatement(xxx,
0762: (URI) bbb, yyy);
0763: if (added) {
0764: nofInferred++;
0765: }
0766: }
0767: t1Iter.close();
0768: }
0769: }
0770:
0771: return nofInferred;
0772: }
0773:
0774: // xxx rdf:type rdfs:Class --> xxx rdfs:subClassOf rdfs:Resource
0775: private int applyRuleRdfs8() throws SailException {
0776: int nofInferred = 0;
0777:
0778: Iterator<Statement> iter = newThisIteration.match(null,
0779: RDF.TYPE, RDFS.CLASS);
0780:
0781: while (iter.hasNext()) {
0782: Statement st = iter.next();
0783:
0784: Resource xxx = st.getSubject();
0785:
0786: boolean added = addInferredStatement(xxx, RDFS.SUBCLASSOF,
0787: RDFS.RESOURCE);
0788: if (added) {
0789: nofInferred++;
0790: }
0791: }
0792:
0793: return nofInferred;
0794: }
0795:
0796: // xxx rdfs:subClassOf yyy (nt) && aaa rdf:type xxx (t1) --> aaa rdf:type yyy
0797: private int applyRuleRdfs9_1() throws SailException {
0798: int nofInferred = 0;
0799:
0800: Iterator<Statement> ntIter = newThisIteration.match(null,
0801: RDFS.SUBCLASSOF, null);
0802:
0803: while (ntIter.hasNext()) {
0804: Statement nt = ntIter.next();
0805:
0806: Resource xxx = nt.getSubject();
0807: Value yyy = nt.getObject();
0808:
0809: if (yyy instanceof Resource) {
0810: CloseableIteration<? extends Statement, SailException> t1Iter;
0811: t1Iter = getWrappedConnection().getStatements(null,
0812: RDF.TYPE, xxx, true);
0813:
0814: while (t1Iter.hasNext()) {
0815: Statement t1 = t1Iter.next();
0816:
0817: Resource aaa = t1.getSubject();
0818:
0819: boolean added = addInferredStatement(aaa, RDF.TYPE,
0820: yyy);
0821: if (added) {
0822: nofInferred++;
0823: }
0824: }
0825: t1Iter.close();
0826: }
0827: }
0828:
0829: return nofInferred;
0830: }
0831:
0832: // aaa rdf:type xxx (nt) && xxx rdfs:subClassOf yyy (t1) --> aaa rdf:type yyy
0833: private int applyRuleRdfs9_2() throws SailException {
0834: int nofInferred = 0;
0835:
0836: Iterator<Statement> ntIter = newThisIteration.match(null,
0837: RDF.TYPE, null);
0838:
0839: while (ntIter.hasNext()) {
0840: Statement nt = ntIter.next();
0841:
0842: Resource aaa = nt.getSubject();
0843: Value xxx = nt.getObject();
0844:
0845: if (xxx instanceof Resource) {
0846: CloseableIteration<? extends Statement, SailException> t1Iter;
0847: t1Iter = getWrappedConnection().getStatements(
0848: (Resource) xxx, RDFS.SUBCLASSOF, null, true);
0849:
0850: while (t1Iter.hasNext()) {
0851: Statement t1 = t1Iter.next();
0852:
0853: Value yyy = t1.getObject();
0854:
0855: if (yyy instanceof Resource) {
0856: boolean added = addInferredStatement(aaa,
0857: RDF.TYPE, yyy);
0858: if (added) {
0859: nofInferred++;
0860: }
0861: }
0862: }
0863: t1Iter.close();
0864: }
0865: }
0866:
0867: return nofInferred;
0868: }
0869:
0870: // xxx rdf:type rdfs:Class --> xxx rdfs:subClassOf xxx
0871: private int applyRuleRdfs10() throws SailException {
0872: int nofInferred = 0;
0873:
0874: Iterator<Statement> iter = newThisIteration.match(null,
0875: RDF.TYPE, RDFS.CLASS);
0876:
0877: while (iter.hasNext()) {
0878: Statement st = iter.next();
0879:
0880: Resource xxx = st.getSubject();
0881:
0882: boolean added = addInferredStatement(xxx, RDFS.SUBCLASSOF,
0883: xxx);
0884: if (added) {
0885: nofInferred++;
0886: }
0887: }
0888:
0889: return nofInferred;
0890: }
0891:
0892: // xxx rdfs:subClassOf yyy (nt) && yyy rdfs:subClassOf zzz (t1)
0893: // --> xxx rdfs:subClassOf zzz
0894: private int applyRuleRdfs11_1() throws SailException {
0895: int nofInferred = 0;
0896:
0897: Iterator<Statement> ntIter = newThisIteration.match(null,
0898: RDFS.SUBCLASSOF, null);
0899:
0900: while (ntIter.hasNext()) {
0901: Statement nt = ntIter.next();
0902:
0903: Resource xxx = nt.getSubject();
0904: Value yyy = nt.getObject();
0905:
0906: if (yyy instanceof Resource) {
0907: CloseableIteration<? extends Statement, SailException> t1Iter;
0908: t1Iter = getWrappedConnection().getStatements(
0909: (Resource) yyy, RDFS.SUBCLASSOF, null, true);
0910:
0911: while (t1Iter.hasNext()) {
0912: Statement t1 = t1Iter.next();
0913:
0914: Value zzz = t1.getObject();
0915:
0916: if (zzz instanceof Resource) {
0917: boolean added = addInferredStatement(xxx,
0918: RDFS.SUBCLASSOF, zzz);
0919: if (added) {
0920: nofInferred++;
0921: }
0922: }
0923: }
0924: t1Iter.close();
0925: }
0926: }
0927:
0928: return nofInferred;
0929: }
0930:
0931: // yyy rdfs:subClassOf zzz (nt) && xxx rdfs:subClassOf yyy (t1)
0932: // --> xxx rdfs:subClassOf zzz
0933: private int applyRuleRdfs11_2() throws SailException {
0934: int nofInferred = 0;
0935:
0936: Iterator<Statement> ntIter = newThisIteration.match(null,
0937: RDFS.SUBCLASSOF, null);
0938:
0939: while (ntIter.hasNext()) {
0940: Statement nt = ntIter.next();
0941:
0942: Resource yyy = nt.getSubject();
0943: Value zzz = nt.getObject();
0944:
0945: if (zzz instanceof Resource) {
0946: CloseableIteration<? extends Statement, SailException> t1Iter;
0947: t1Iter = getWrappedConnection().getStatements(null,
0948: RDFS.SUBCLASSOF, yyy, true);
0949:
0950: while (t1Iter.hasNext()) {
0951: Statement t1 = t1Iter.next();
0952:
0953: Resource xxx = t1.getSubject();
0954:
0955: boolean added = addInferredStatement(xxx,
0956: RDFS.SUBCLASSOF, zzz);
0957: if (added) {
0958: nofInferred++;
0959: }
0960: }
0961: t1Iter.close();
0962: }
0963: }
0964:
0965: return nofInferred;
0966: }
0967:
0968: // xxx rdf:type rdfs:ContainerMembershipProperty
0969: // --> xxx rdfs:subPropertyOf rdfs:member
0970: private int applyRuleRdfs12() throws SailException {
0971: int nofInferred = 0;
0972:
0973: Iterator<Statement> iter = newThisIteration.match(null,
0974: RDF.TYPE, RDFS.CONTAINERMEMBERSHIPPROPERTY);
0975:
0976: while (iter.hasNext()) {
0977: Statement st = iter.next();
0978:
0979: Resource xxx = st.getSubject();
0980:
0981: boolean added = addInferredStatement(xxx,
0982: RDFS.SUBPROPERTYOF, RDFS.MEMBER);
0983: if (added) {
0984: nofInferred++;
0985: }
0986: }
0987:
0988: return nofInferred;
0989: }
0990:
0991: // xxx rdf:type rdfs:Datatype --> xxx rdfs:subClassOf rdfs:Literal
0992: private int applyRuleRdfs13() throws SailException {
0993: int nofInferred = 0;
0994:
0995: Iterator<Statement> iter = newThisIteration.match(null,
0996: RDF.TYPE, RDFS.DATATYPE);
0997:
0998: while (iter.hasNext()) {
0999: Statement st = iter.next();
1000:
1001: Resource xxx = st.getSubject();
1002:
1003: boolean added = addInferredStatement(xxx, RDFS.SUBCLASSOF,
1004: RDFS.LITERAL);
1005: if (added) {
1006: nofInferred++;
1007: }
1008: }
1009:
1010: return nofInferred;
1011: }
1012:
1013: // xxx rdf:_* yyy --> rdf:_* rdf:type rdfs:ContainerMembershipProperty
1014: // This is an extra rule for list membership properties (_1, _2, _3, ...).
1015: // The RDF MT does not specificy a production for this.
1016: private int applyRuleX1() throws SailException {
1017: int nofInferred = 0;
1018:
1019: String prefix = RDF.NAMESPACE + "_";
1020: Iterator<Statement> iter = newThisIteration.match(null, null,
1021: null);
1022:
1023: while (iter.hasNext()) {
1024: Statement st = iter.next();
1025:
1026: URI predNode = st.getPredicate();
1027: String predURI = predNode.toString();
1028:
1029: if (predURI.startsWith(prefix)
1030: && isValidPredicateNumber(predURI.substring(prefix
1031: .length()))) {
1032: boolean added = addInferredStatement(predNode,
1033: RDF.TYPE, RDFS.CONTAINERMEMBERSHIPPROPERTY);
1034: if (added) {
1035: nofInferred++;
1036: }
1037: }
1038: }
1039:
1040: return nofInferred;
1041: }
1042:
1043: /**
1044: * Util method for {@link #applyRuleX1}.
1045: */
1046: private boolean isValidPredicateNumber(String str) {
1047: int strLength = str.length();
1048:
1049: if (strLength == 0) {
1050: return false;
1051: }
1052:
1053: for (int i = 0; i < strLength; i++) {
1054: if (!ASCIIUtil.isNumber(str.charAt(i))) {
1055: return false;
1056: }
1057: }
1058:
1059: // No leading zeros
1060: if (str.charAt(0) == '0') {
1061: return false;
1062: }
1063:
1064: return true;
1065: }
1066: }
|