001: /******************************************************************
002: * File: RETEQueue.java
003: * Created by: Dave Reynolds
004: * Created on: 09-Jun-2003
005: *
006: * (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
007: * [See end of file]
008: * $Id: RETEQueue.java,v 1.11 2008/01/02 12:06:16 andy_seaborne Exp $
009: *****************************************************************/package com.hp.hpl.jena.reasoner.rulesys.impl;
010:
011: import com.hp.hpl.jena.graph.*;
012:
013: import java.util.*;
014:
015: /**
016: * Represents one input left of a join node. The queue points to
017: * a sibling queue representing the other leg which should be joined
018: * against.
019: *
020: * @author <a href="mailto:der@hplb.hpl.hp.com">Dave Reynolds</a>
021: * @version $Revision: 1.11 $ on $Date: 2008/01/02 12:06:16 $
022: */
023: public class RETEQueue implements RETESinkNode, RETESourceNode {
024:
025: /** A multi-set of partially bound envionments */
026: protected HashMap queue = new HashMap();
027:
028: /** A set of variable indices which should match between the two inputs */
029: protected byte[] matchIndices;
030:
031: /** The sibling queue which forms the other half of the join node */
032: protected RETEQueue sibling;
033:
034: /** The node that results should be passed on to */
035: protected RETESinkNode continuation;
036:
037: /**
038: * Constructor. The queue is not usable until it has been bound
039: * to a sibling and a continuation node.
040: * @param A set of variable indices which should match between the two inputs
041: */
042: public RETEQueue(byte[] matchIndices) {
043: this .matchIndices = matchIndices;
044: }
045:
046: /**
047: * Constructor. The queue is not usable until it has been bound
048: * to a sibling and a continuation node.
049: * @param A List of variable indices which should match between the two inputs
050: */
051: public RETEQueue(List matchIndexList) {
052: int len = matchIndexList.size();
053: matchIndices = new byte[len];
054: for (int i = 0; i < len; i++) {
055: matchIndices[i] = (byte) ((Number) matchIndexList.get(i))
056: .intValue();
057: }
058: }
059:
060: /**
061: * Set the sibling for this node.
062: */
063: public void setSibling(RETEQueue sibling) {
064: this .sibling = sibling;
065: }
066:
067: /**
068: * Set the continuation node for this node (and any sibling)
069: */
070: public void setContinuation(RETESinkNode continuation) {
071: this .continuation = continuation;
072: if (sibling != null)
073: sibling.continuation = continuation;
074: }
075:
076: /**
077: * Propagate a token to this node.
078: * @param env a set of variable bindings for the rule being processed.
079: * @param isAdd distinguishes between add and remove operations.
080: */
081: public void fire(BindingVector env, boolean isAdd) {
082: // Store the new token in this store
083: Count count = (Count) queue.get(env);
084: if (count == null) {
085: // no entry yet
086: if (!isAdd)
087: return;
088: queue.put(env, new Count(1));
089: } else {
090: if (isAdd) {
091: count.inc();
092: } else {
093: count.dec();
094: if (count.getCount() == 0) {
095: queue.remove(env);
096: }
097: }
098: }
099:
100: // Cross match new token against the entries in the sibling queue
101: for (Iterator i = sibling.queue.keySet().iterator(); i
102: .hasNext();) {
103: Node[] candidate = ((BindingVector) i.next())
104: .getEnvironment();
105: Node[] envNodes = env.getEnvironment();
106: boolean matchOK = true;
107: for (int j = 0; j < matchIndices.length; j++) {
108: int index = matchIndices[j];
109: if (!candidate[index].sameValueAs(envNodes[index])) {
110: matchOK = false;
111: break;
112: }
113: }
114: if (matchOK) {
115: // Instantiate a new extended environment
116: Node[] newNodes = new Node[candidate.length];
117: for (int j = 0; j < candidate.length; j++) {
118: Node n = candidate[j];
119: newNodes[j] = (n == null) ? envNodes[j] : n;
120: }
121: BindingVector newEnv = new BindingVector(newNodes);
122: // Fire the successor processing
123: continuation.fire(newEnv, isAdd);
124: }
125: }
126: }
127:
128: /**
129: * Inner class used to represent an updatable count.
130: */
131: protected static class Count {
132: /** the count */
133: int count;
134:
135: /** Constructor */
136: public Count(int count) {
137: this .count = count;
138: }
139:
140: /** Access count value */
141: public int getCount() {
142: return count;
143: }
144:
145: /** Increment the count value */
146: public void inc() {
147: count++;
148: }
149:
150: /** Decrement the count value */
151: public void dec() {
152: count--;
153: }
154:
155: /** Set the count value */
156: public void setCount(int count) {
157: this .count = count;
158: }
159: }
160:
161: /**
162: * Clone this node in the network.
163: * @param context the new context to which the network is being ported
164: */
165: public RETENode clone(Map netCopy, RETERuleContext context) {
166: RETEQueue clone = (RETEQueue) netCopy.get(this );
167: if (clone == null) {
168: clone = new RETEQueue(matchIndices);
169: netCopy.put(this , clone);
170: clone.setSibling((RETEQueue) sibling
171: .clone(netCopy, context));
172: clone.setContinuation((RETESinkNode) continuation.clone(
173: netCopy, context));
174: clone.queue.putAll(queue);
175: }
176: return clone;
177: }
178: }
179:
180: /*
181: (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
182: All rights reserved.
183:
184: Redistribution and use in source and binary forms, with or without
185: modification, are permitted provided that the following conditions
186: are met:
187:
188: 1. Redistributions of source code must retain the above copyright
189: notice, this list of conditions and the following disclaimer.
190:
191: 2. Redistributions in binary form must reproduce the above copyright
192: notice, this list of conditions and the following disclaimer in the
193: documentation and/or other materials provided with the distribution.
194:
195: 3. The name of the author may not be used to endorse or promote products
196: derived from this software without specific prior written permission.
197:
198: THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
199: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
200: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
201: IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
202: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
203: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
204: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
205: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
206: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
207: THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
208: */
|