/** Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved. Contact: SYSTAP, LLC DBA Blazegraph 2501 Calvert ST NW #106 Washington, DC 20008 licenses@blazegraph.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Created on Oct 30, 2007 */ package com.bigdata.rdf.rules; import java.util.Properties; import org.openrdf.model.vocabulary.RDF; import org.openrdf.model.vocabulary.RDFS; import com.bigdata.rdf.axioms.NoAxioms; import com.bigdata.rdf.inf.BackchainTypeResourceIterator; import com.bigdata.rdf.internal.IV; import com.bigdata.rdf.model.BigdataURI; import com.bigdata.rdf.model.BigdataValueFactory; import com.bigdata.rdf.model.StatementEnum; import com.bigdata.rdf.rio.IStatementBuffer; import com.bigdata.rdf.rio.StatementBuffer; import com.bigdata.rdf.spo.ISPO; import com.bigdata.rdf.spo.SPO; import com.bigdata.rdf.store.AbstractTestCase; import com.bigdata.rdf.store.AbstractTripleStore; import com.bigdata.rdf.vocab.Vocabulary; import com.bigdata.relation.accesspath.IAccessPath; import com.bigdata.striterator.IChunkedOrderedIterator; /** * Test suite for {@link BackchainTypeResourceIterator}. * * @todo write a test where we compute the forward closure of a data set with (x * type Resource) entailments included in the rule set and then compare it * to the forward closure of the same data set computed without those * entailments and using backward chaining to supply the entailments. The * result graphs should be equals. * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> * @version $Id$ */ public class TestBackchainTypeResourceIterator extends AbstractRuleTestCase { /** * */ public TestBackchainTypeResourceIterator() { super(); } /** * @param name */ public TestBackchainTypeResourceIterator(String name) { super(name); } /** * Test when only the subject of the triple pattern is bound. In this case * the iterator MUST add a single entailment (s rdf:Type rdfs:Resource) * unless it is explicitly present in the database. */ public void test_subjectBound() { final Properties properties = super.getProperties(); // override the default axiom model. properties.setProperty(com.bigdata.rdf.store.AbstractTripleStore.Options.AXIOMS_CLASS, NoAxioms.class.getName()); final AbstractTripleStore store = getStore(properties); try { final Vocabulary vocab = store.getVocabulary(); final BigdataValueFactory f = store.getValueFactory(); final BigdataURI A = f.createURI("http://www.foo.org/A"); final BigdataURI B = f.createURI("http://www.foo.org/B"); final BigdataURI C = f.createURI("http://www.foo.org/C"); /* * add statements to the store. * * Note: this gives us TWO (2) distinct subjects (A and B), but we * will only visit statements for (A). */ { final IStatementBuffer buffer = new StatementBuffer(store, 10/* capacity */); buffer.add(A, RDF.TYPE, B); buffer.add(B, RDF.TYPE, C); buffer.flush(); } final IChunkedOrderedIterator<ISPO> itr; { final IAccessPath<ISPO> accessPath = store.getAccessPath(store .getIV(A), NULL, NULL); itr = BackchainTypeResourceIterator.newInstance(// accessPath.iterator(),// accessPath,// store, // vocab.get(RDF.TYPE), // vocab.get(RDFS.RESOURCE)// ); } assertSameSPOsAnyOrder(store, new SPO[]{ new SPO(// store.getIV(A),// store.getIV(RDF.TYPE),// store.getIV(B),// StatementEnum.Explicit), new SPO(// store.getIV(A), // store.getIV(RDF.TYPE), // store.getIV(RDFS.RESOURCE), // StatementEnum.Inferred) }, itr ); } finally { store.__tearDownUnitTest(); } } /** * Variant test where there is an explicit ( s rdf:type rdfs:Resource ) in * the database for the given subject. For this test we verify that the * iterator visits an "explicit" statement rather than adding its own * inference. */ public void test_subjectBound2() { final Properties properties = super.getProperties(); // override the default axiom model. properties.setProperty(com.bigdata.rdf.store.AbstractTripleStore.Options.AXIOMS_CLASS, NoAxioms.class.getName()); final AbstractTripleStore store = getStore(properties); try { final Vocabulary vocab = store.getVocabulary(); final BigdataValueFactory f = store.getValueFactory(); final BigdataURI A = f.createURI("http://www.foo.org/A"); final BigdataURI B = f.createURI("http://www.foo.org/B"); final BigdataURI C = f.createURI("http://www.foo.org/C"); /* * add statements to the store. * * Note: this gives us TWO (2) distinct subjects (A and B), but we * will only visit statements for (A). */ { IStatementBuffer buffer = new StatementBuffer(store, 10/* capacity */); buffer.add(A, RDF.TYPE, B); buffer.add(A, RDF.TYPE, RDFS.RESOURCE); buffer.add(B, RDF.TYPE, C); buffer.flush(); } if(log.isInfoEnabled()) log.info("\n"+store.dumpStore()); final IChunkedOrderedIterator<ISPO> itr; { final IAccessPath<ISPO> accessPath = store.getAccessPath(store .getIV(A), NULL, NULL); itr = BackchainTypeResourceIterator.newInstance(// accessPath.iterator(),// accessPath,// store, // vocab.get(RDF.TYPE), // vocab.get(RDFS.RESOURCE)// ); } assertSameSPOsAnyOrder(store, new SPO[]{ new SPO(// store.getIV(A),// store.getIV(RDF.TYPE),// store.getIV(B),// StatementEnum.Explicit), new SPO(// store.getIV(A), // store.getIV(RDF.TYPE), // store.getIV(RDFS.RESOURCE), // StatementEnum.Explicit) }, itr ); } finally { store.__tearDownUnitTest(); } } /** * Test when the triple pattern has no bound variables. In this case the * iterator MUST add an entailment for each distinct resource in the store * unless there is also an explicit (s rdf:type rdfs:Resource) assertion in * the database. */ public void test_noneBound() { final Properties properties = super.getProperties(); // override the default axiom model. properties.setProperty(com.bigdata.rdf.store.AbstractTripleStore.Options.AXIOMS_CLASS, NoAxioms.class.getName()); final AbstractTripleStore store = getStore(properties); try { final Vocabulary vocab = store.getVocabulary(); final BigdataValueFactory f = store.getValueFactory(); final BigdataURI A = f.createURI("http://www.foo.org/A"); final BigdataURI B = f.createURI("http://www.foo.org/B"); final BigdataURI C = f.createURI("http://www.foo.org/C"); /* * add statements to the store. * * Note: this gives us TWO (2) distinct subjects (A and B). Since * nothing is bound in the query we will visit both explicit * statements and also the (s type resource) entailments for both * distinct subjects. */ { final IStatementBuffer buffer = new StatementBuffer(store, 10/* capacity */); buffer.add(A, RDF.TYPE, B); buffer.add(A, RDF.TYPE, RDFS.RESOURCE); buffer.add(B, RDF.TYPE, C); buffer.flush(); } final IChunkedOrderedIterator<ISPO> itr; { final IAccessPath<ISPO> accessPath = store.getAccessPath(NULL, NULL, NULL); itr = BackchainTypeResourceIterator.newInstance(// accessPath.iterator(),// accessPath,// store, // vocab.get(RDF.TYPE), // vocab.get(RDFS.RESOURCE)// ); } assertSameSPOsAnyOrder(store, new SPO[]{ new SPO(// store.getIV(A),// store.getIV(RDF.TYPE),// store.getIV(B),// StatementEnum.Explicit), new SPO(// store.getIV(B),// store.getIV(RDF.TYPE),// store.getIV(C),// StatementEnum.Explicit), new SPO(// store.getIV(A), // store.getIV(RDF.TYPE), // store.getIV(RDFS.RESOURCE), // StatementEnum.Explicit), new SPO(// store.getIV(B), // store.getIV(RDF.TYPE), // store.getIV(RDFS.RESOURCE), // StatementEnum.Inferred), new SPO(// store.getIV(C), // store.getIV(RDF.TYPE), // store.getIV(RDFS.RESOURCE), // StatementEnum.Inferred), new SPO(// store.getIV(RDFS.RESOURCE), // store.getIV(RDF.TYPE), // store.getIV(RDFS.RESOURCE), // StatementEnum.Inferred) }, itr); } finally { store.__tearDownUnitTest(); } } /** * Test for other triple patterns (all bound, predicate bound, object bound, * etc). In all cases the iterator MUST NOT add any entailments. * * @todo this is only testing a single access path. */ public void test_otherBound_01() { final Properties properties = super.getProperties(); // override the default axiom model. properties.setProperty(com.bigdata.rdf.store.AbstractTripleStore.Options.AXIOMS_CLASS, NoAxioms.class.getName()); final AbstractTripleStore store = getStore(properties); try { final Vocabulary vocab = store.getVocabulary(); final BigdataValueFactory f = store.getValueFactory(); final BigdataURI A = f.createURI("http://www.foo.org/A"); final BigdataURI B = f.createURI("http://www.foo.org/B"); final BigdataURI C = f.createURI("http://www.foo.org/C"); /* * add statements to the store. * * Note: this gives us TWO (2) distinct subjects (A and B). */ { IStatementBuffer buffer = new StatementBuffer(store, 10/* capacity */); buffer.add(A, RDF.TYPE, B); buffer.add(B, RDF.TYPE, C); buffer.flush(); } final IChunkedOrderedIterator<ISPO> itr; { final IAccessPath<ISPO> accessPath = store.getAccessPath(NULL, NULL, store.getIV(B)); itr = BackchainTypeResourceIterator.newInstance(// accessPath.iterator(),// accessPath,// store, // vocab.get(RDF.TYPE), // vocab.get(RDFS.RESOURCE)// ); } /* * Note: Since we are reading with the object bound, only the * explicit statements for that object should make it into the * iterator. */ assertSameSPOsAnyOrder(store, new SPO[]{ new SPO(// store.getIV(A),// store.getIV(RDF.TYPE),// store.getIV(B),// StatementEnum.Explicit) }, itr); } finally { store.__tearDownUnitTest(); } } /** * Backchain test when the subject is both bound and unbound and where the * predicate is bound to <code>rdf:type</code> and the object is bound to * <code>rdfs:Resource</code>. * * FIXME test all access paths, including where the predicate is NULL and * where it is rdf:type and where the object is NULL and where it is * rdfs:Resource. */ public void test_backchain_foo_type_resource() { final Properties properties = super.getProperties(); // override the default axiom model. properties.setProperty(com.bigdata.rdf.store.AbstractTripleStore.Options.AXIOMS_CLASS, NoAxioms.class.getName()); final AbstractTripleStore store = getStore(properties); try { final Vocabulary vocab = store.getVocabulary(); final BigdataValueFactory f = store.getValueFactory(); final BigdataURI S = f.createURI("http://www.bigdata.com/s"); final BigdataURI P = f.createURI("http://www.bigdata.com/p"); final BigdataURI O = f.createURI("http://www.bigdata.com/o"); final IV s = store.addTerm(S); final IV p = store.addTerm(P); final IV o = store.addTerm(O); final IV rdfType = vocab.get(RDF.TYPE); final IV rdfsResource = vocab.get(RDFS.RESOURCE); store.addStatements(new SPO[] {// new SPO(s, p, o, StatementEnum.Explicit) // }, 1); if(log.isInfoEnabled()) { log.info("\n:"+store.dumpStore()); } AbstractTestCase.assertSameSPOs(new SPO[] { new SPO(s, p, o, StatementEnum.Explicit), }, store.getAccessPath(NULL, NULL, NULL).iterator() ); { // where s is bound. final IAccessPath<ISPO> accessPath = store.getAccessPath(s, rdfType, // rdfsResource// ); final IChunkedOrderedIterator<ISPO> itr = BackchainTypeResourceIterator .newInstance(// accessPath.iterator(),// accessPath,// store, // rdfType, // rdfsResource// ); AbstractTestCase.assertSameSPOs(new SPO[] { new SPO(s, rdfType, // rdfsResource,// StatementEnum.Inferred), }, itr); } { // where s is unbound. final IAccessPath<ISPO> accessPath = store.getAccessPath(NULL, rdfType, // rdfsResource// ); final IChunkedOrderedIterator<ISPO> itr = BackchainTypeResourceIterator.newInstance(// accessPath.iterator(),// accessPath,// store, // rdfType, // rdfsResource// ); AbstractTestCase.assertSameSPOs(new SPO[] { // new SPO(s, rdfType, rdfsResource, StatementEnum.Inferred), new SPO(o, rdfType, rdfsResource, StatementEnum.Inferred), }, itr); } } finally { store.__tearDownUnitTest(); } } }