/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.jena.reasoner.rulesys.impl; import org.apache.jena.graph.* ; import org.apache.jena.reasoner.* ; import org.apache.jena.reasoner.rulesys.* ; import org.apache.jena.util.iterator.ClosableIterator ; /** * An implementation of the generic RuleContext for use in the RETE implementation. * The RuleContext is used to supply context information to the builtin operations. */ public class RETERuleContext implements RuleContext { /** The binding environment which represents the state of the current rule execution. */ protected BindingEnvironment env; /** The rule current being executed. */ protected Rule rule; /** The enclosing inference graph. */ protected ForwardRuleInfGraphI graph; /** The RETE engine associated with the inference graph */ protected RETEEngine engine; /** * Constructor. * @param graph the inference graph which owns this context. */ public RETERuleContext(ForwardRuleInfGraphI graph, RETEEngine engine) { this.graph = graph; this.engine = engine; } /** * Returns the current variable binding environment for the current rule. * @return BindingEnvironment */ @Override public BindingEnvironment getEnv() { return env; } /** * Returns the graph. * @return InfGraph */ @Override public InfGraph getGraph() { return graph; } /** * Returns the RETE engine associated with this context. */ public RETEEngine getEngine() { return engine; } /** * Returns the rule. * @return Rule */ @Override public Rule getRule() { return rule; } /** * Sets the rule. * @param rule The rule to set */ @Override public void setRule(Rule rule) { this.rule = rule; } /** * Sets the current binding environment for this context. * @param env the binding environment so far */ public void setEnv(BindingEnvironment env) { this.env = env; } /** * Return true if the triple is already in either the graph or the stack. * I.e. it has already been deduced. */ @Override public boolean contains(Triple t) { // Can't use stackCache.contains because that does not do semantic equality return contains(t.getSubject(), t.getPredicate(), t.getObject()); } /** * Return true if the triple pattern is already in either the graph or the stack. * I.e. it has already been deduced. */ @Override public boolean contains(Node s, Node p, Node o) { ClosableIterator<Triple> it = find(s, p, o); boolean result = it.hasNext(); it.close(); return result; } /** * In some formulations the context includes deductions that are not yet * visible to the underlying graph but need to be checked for. * However, currently this calls the graph find directly. */ @Override public ClosableIterator<Triple> find(Node s, Node p, Node o) { //return graph.find(s, p, o).andThen(pendingCache.find(s, p, o)); return graph.findDataMatches(s, p, o); } /** * Assert a new triple in the deduction graph, bypassing any processing machinery. */ @Override public void silentAdd(Triple t) { ((SilentAddI)graph).silentAdd(t); } /** * Remove a triple from the deduction graph (and the original graph if relevant). */ @Override public void remove(Triple t) { graph.getRawGraph().delete(t); engine.deleteTriple(t, true); } /** * Assert a new triple in the deduction graph, triggering any consequent processing as appropriate. */ @Override public void add(Triple t) { engine.addTriple(t, true); } /** * Check whether the rule should fire in this context. */ public boolean shouldFire(boolean allowUnsafe) { // Check any non-pattern clauses for (int i = 0; i < rule.bodyLength(); i++) { Object clause = rule.getBodyElement(i); if (clause instanceof Functor) { // Fire a built in if (allowUnsafe) { if (!((Functor)clause).evalAsBodyClause(this)) { // Failed guard so just discard and return return false; } } else { // Don't re-run side-effectful clause on a re-run if (!((Functor)clause).safeEvalAsBodyClause(this)) { // Failed guard so just discard and return return false; } } } } return true; } /** * Check if a rule from the conflict set is still OK to fire. * Just checks the non-monotonic guards such as noValue. */ public boolean shouldStillFire() { // Check any non-pattern clauses for (int i = 0; i < rule.bodyLength(); i++) { Object clause = rule.getBodyElement(i); if (clause instanceof Functor) { Builtin builtin = ((Functor)clause).getImplementor(); if (builtin != null && !builtin.isMonotonic()) { if (!((Functor)clause).evalAsBodyClause(this)) { return false; } } } } return true; } }