public final IBindingSet newBindingSet(final IRule rule) { final IBindingSet constants = rule.getConstants(); final int nconstants = constants.size(); final IBindingSet bindingSet = new ListBindingSet() // new ArrayBindingSet(rule.getVariableCount()+ nconstants) ; if (nconstants > 0) { /* * Bind constants declared by the rule before returning the binding * set to the caller. */ final Iterator<Map.Entry<IVariable, IConstant>> itr = constants.iterator(); while (itr.hasNext()) { final Map.Entry<IVariable, IConstant> entry = itr.next(); bindingSet.set(entry.getKey(), entry.getValue()); } } return bindingSet; }
/** * Constructs the element iff requested, saves the rule reference iff requested, and clones and * saves the bindingSet iff requested. The requested behavior depends on {@link * IJoinNexus#solutionFlags()}. When requested, the element is created using {@link * IRelation#newElement(IPredicate, IBindingSet)} for the {@link IRelation} that is named by the * head of the rule. * * @param e The element. * @param rule The rule. * @param bindingSet The binding set for this solution. If {@link IJoinNexus#BINDINGS} was * specified, then the binding set will be <em>cloned</em> by this ctor. * @throws IllegalArgumentException if any parameter is <code>null</code>. */ @SuppressWarnings("unchecked") public Solution(final IJoinNexus joinNexus, final IRule<E> rule, final IBindingSet bindingSet) { if (joinNexus == null) throw new IllegalArgumentException(); if (rule == null) throw new IllegalArgumentException(); if (bindingSet == null) throw new IllegalArgumentException(); final int flags = joinNexus.solutionFlags(); if ((flags & IJoinNexus.ELEMENT) != 0) { /* * The relation is responsible for how the elements are materialized * from the bindings. * * Note: Caching for this relation is very important! */ // the head of the rule. final IPredicate head = rule.getHead(); // the relation for the head of the rule. final IRelation relation = joinNexus.getHeadRelationView(head); // use the relation's element factory. this.e = (E) relation.newElement(head.args(), bindingSet); // TODO BOp.args() is not efficient! // // use the relation's element factory. // this.e = (E) relation.newElement(head, bindingSet); } else { this.e = null; } if ((flags & IJoinNexus.BINDINGS) != 0) { this.bindingSet = bindingSet.clone(); } else { this.bindingSet = null; } if ((flags & IJoinNexus.RULE) != 0) { this.rule = rule; } else { this.rule = null; } }
/** * Return the bound value for the variable. * * @param v The variable. * @param bset The source solution. * @param required <code>true</code> iff the variable must be bound. * @return The bound value and <code>null</code> if the variable is not bound. */ @SuppressWarnings("rawtypes") protected static IV getIV( final IVariable<?> var, final IBindingSet bset, final boolean required) { @SuppressWarnings("unchecked") final IConstant<IV> constant = bset.get(var); if (constant == null) { if (required) throw new RuntimeException("Variable is not bound: " + var); return null; } final IV _s = (IV) constant.get(); return _s; }
@SuppressWarnings("unchecked") private final void copyValues( final IElement e, final IPredicate<?> pred, final IBindingSet bindingSet) { for (int i = 0; i < pred.arity(); i++) { final IVariableOrConstant<?> t = pred.get(i); if (t.isVar()) { final IVariable<?> var = (IVariable<?>) t; final Constant<?> newval = new Constant(e.get(i)); bindingSet.set(var, newval); } } }
/** * Creates a {@link Justification}, writes it on the store using {@link * RDFJoinNexus#newInsertBuffer(IMutableRelation)}, verifies that we can read it back from the * store, and then retracts the justified statement and verifies that the justification was also * retracted. */ public void test_writeReadRetract() { 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 { if (!store.isJustify()) { log.warn("Test skipped - justifications not enabled"); } /* * the explicit statement that is the support for the rule. */ final IV U = store.addTerm(new URIImpl("http://www.bigdata.com/U")); final IV A = store.addTerm(new URIImpl("http://www.bigdata.com/A")); final IV Y = store.addTerm(new URIImpl("http://www.bigdata.com/Y")); store.addStatements( new SPO[] { // new SPO(U, A, Y, StatementEnum.Explicit) // }, // 1); assertTrue(store.hasStatement(U, A, Y)); assertEquals(1, store.getStatementCount()); final InferenceEngine inf = store.getInferenceEngine(); final Vocabulary vocab = store.getVocabulary(); // the rule. final Rule rule = new RuleRdf01(store.getSPORelation().getNamespace(), vocab); final IJoinNexus joinNexus = store .newJoinNexusFactory( RuleContextEnum.DatabaseAtOnceClosure, ActionEnum.Insert, IJoinNexus.ALL, null /* filter */) .newInstance(store.getIndexManager()); /* * The buffer that accepts solutions and causes them to be written * onto the statement indices and the justifications index. */ final IBuffer<ISolution[]> insertBuffer = joinNexus.newInsertBuffer(store.getSPORelation()); // the expected justification (setup and verified below). final Justification jst; // the expected entailment. final SPO expectedEntailment = new SPO( // A, vocab.get(RDF.TYPE), vocab.get(RDF.PROPERTY), StatementEnum.Inferred); { final IBindingSet bindingSet = joinNexus.newBindingSet(rule); /* * Note: rdfs1 is implemented using a distinct term scan. This * has the effect of leaving the variables that do not appear in * the head of the rule unbound. Therefore we DO NOT bind those * variables here in the test case and they will be represented * as ZERO (0L) in the justifications index and interpreted as * wildcards. */ // bindingSet.set(Var.var("u"), new Constant<IV>(U)); bindingSet.set(Var.var("a"), new Constant<IV>(A)); // bindingSet.set(Var.var("y"), new Constant<IV>(Y)); final ISolution solution = new Solution(joinNexus, rule, bindingSet); /* * Verify the justification that will be built from that * solution. */ { jst = new Justification(solution); /* * Verify the bindings on the head of the rule as * represented by the justification. */ assertEquals(expectedEntailment, jst.getHead()); /* * Verify the bindings on the tail of the rule as * represented by the justification. Again, note that the * variables that do not appear in the head of the rule are * left unbound for rdfs1 as a side-effect of evaluation * using a distinct term scan. */ final SPO[] expectedTail = new SPO[] { // new SPO(NULL, A, NULL, StatementEnum.Inferred) // }; if (!Arrays.equals(expectedTail, jst.getTail())) { fail("Expected: " + Arrays.toString(expectedTail) + ", but actual: " + jst); } } // insert solution into the buffer. insertBuffer.add(new ISolution[] {solution}); } // SPOAssertionBuffer buf = new SPOAssertionBuffer(store, store, // null/* filter */, 100/* capacity */, true/* justified */); // // assertTrue(buf.add(head, jst)); // no justifications before hand. assertEquals(0L, store.getSPORelation().getJustificationIndex().rangeCount()); // flush the buffer. assertEquals(1L, insertBuffer.flush()); // one justification afterwards. assertEquals(1L, store.getSPORelation().getJustificationIndex().rangeCount()); /* * verify read back from the index. */ { final ITupleIterator<Justification> itr = store.getSPORelation().getJustificationIndex().rangeIterator(); while (itr.hasNext()) { final ITuple<Justification> tuple = itr.next(); // de-serialize the justification from the key. final Justification tmp = tuple.getObject(); // verify the same. assertEquals(jst, tmp); // no more justifications in the index. assertFalse(itr.hasNext()); } } /* * test iterator with a single justification. */ { final FullyBufferedJustificationIterator itr = new FullyBufferedJustificationIterator(store, expectedEntailment); assertTrue(itr.hasNext()); final Justification tmp = itr.next(); assertEquals(jst, tmp); } // an empty focusStore. final TempTripleStore focusStore = new TempTripleStore(store.getIndexManager().getTempStore(), store.getProperties(), store); try { /* * The inference (A rdf:type rdf:property) is grounded by the * explicit statement (U A Y). */ assertTrue( Justification.isGrounded( inf, focusStore, store, expectedEntailment, false /* testHead */, true /* testFocusStore */, new VisitedSPOSet(focusStore.getIndexManager()))); // add the statement (U A Y) to the focusStore. focusStore.addStatements( new SPO[] { // new SPO(U, A, Y, StatementEnum.Explicit) // }, // 1); /* * The inference is no longer grounded since we have declared * that we are also retracting its grounds. */ assertFalse( Justification.isGrounded( inf, focusStore, store, expectedEntailment, false /* testHead */, true /* testFocusStore */, new VisitedSPOSet(focusStore.getIndexManager()))); } finally { /* * Destroy the temp kb, but not the backing TemporaryStore. That * will be destroyed when we destroy the IndexManager associated * with the main store (below). */ focusStore.destroy(); } /* * remove the justified statements. */ assertEquals( 1L, store .getAccessPath(expectedEntailment.s, expectedEntailment.p, expectedEntailment.o) .removeAll()); /* * verify that the justification for that statement is gone. */ { final ITupleIterator<?> itr = store.getSPORelation().getJustificationIndex().rangeIterator(); assertFalse(itr.hasNext()); } } finally { store.__tearDownUnitTest(); } }