/* * 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 java.util.*; import org.apache.jena.graph.* ; /** * Represents one input left of a join node. The queue points to a sibling queue * representing the other leg which should be joined against. */ public class RETEQueue implements RETESinkNode, RETESourceNode { /** * A multi-set of partially bound envionments indices for matching are * specified by matchIndices */ protected BindingVectorMultiSet queue; /** A set of variable indices which should match between the two inputs */ protected byte[] matchIndices; /** The sibling queue which forms the other half of the join node */ protected RETEQueue sibling; /** The node that results should be passed on to */ protected RETESinkNode continuation; /** * Constructor. The queue is not usable until it has been bound to a sibling * and a continuation node. * * @param matchIndices * set of variable indices which should match between the two * inputs */ public RETEQueue(byte[] matchIndices) { this.matchIndices = matchIndices; this.queue = new BindingVectorMultiSet(matchIndices); } /** * Constructor. The queue is not usable until it has been bound to a sibling * and a continuation node. * * @param matchIndexList * List of variable indices which should match between the two * inputs */ public RETEQueue(List<? extends Byte> matchIndexList) { int len = matchIndexList.size(); matchIndices = new byte[len]; for (int i = 0; i < len; i++) { matchIndices[i] = matchIndexList.get( i ); } this.queue = new BindingVectorMultiSet(matchIndices); } /** * Set the sibling for this node. */ public void setSibling(RETEQueue sibling) { this.sibling = sibling; } /** * Set the continuation node for this node (and any sibling) */ @Override public void setContinuation(RETESinkNode continuation) { this.continuation = continuation; if (sibling != null) sibling.continuation = continuation; } /** * Propagate a token to this node. * * @param env * a set of variable bindings for the rule being processed. * @param isAdd * distinguishes between add and remove operations. */ @Override public void fire(BindingVector env, boolean isAdd) { // Store the new token in this store if (isAdd) { queue.add(env); } else { queue.remove(env); } // Cross match new token against the entries in the sibling queue Node[] envNodes = env.getEnvironment(); for (Iterator<BindingVector> i = sibling.queue.getSubSet(env); i .hasNext();) { Node[] candidate = i.next().getEnvironment(); // matching is no longer required since queue.getSubSet(env) returns // a HashMap with matching BindingVector's // Instantiate a new extended environment Node[] newNodes = new Node[candidate.length]; for (int j = 0; j < candidate.length; j++) { Node n = candidate[j]; newNodes[j] = (n == null) ? envNodes[j] : n; } BindingVector newEnv = new BindingVector(newNodes); // Fire the successor processing continuation.fire(newEnv, isAdd); } } /** * Clone this node in the network. * * @param context * the new context to which the network is being ported */ @Override public RETENode clone(Map<RETENode, RETENode> netCopy, RETERuleContext context) { RETEQueue clone = (RETEQueue) netCopy.get(this); if (clone == null) { clone = new RETEQueue(matchIndices); netCopy.put(this, clone); clone.setSibling((RETEQueue) sibling.clone(netCopy, context)); clone.setContinuation((RETESinkNode) continuation.clone(netCopy, context)); clone.queue.putAll(queue); } return clone; } }