001: package org.drools.reteoo;
002:
003: /*
004: * Copyright 2005 JBoss Inc
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
018:
019: import org.drools.RuleBaseConfiguration;
020: import org.drools.common.BaseNode;
021: import org.drools.common.InternalWorkingMemory;
022: import org.drools.common.NodeMemory;
023: import org.drools.common.PropagationContextImpl;
024: import org.drools.rule.EvalCondition;
025: import org.drools.spi.PropagationContext;
026: import org.drools.util.Iterator;
027: import org.drools.util.TupleHashTable;
028:
029: /**
030: * Node which filters <code>ReteTuple</code>s.
031: *
032: * <p>
033: * Using a semantic <code>Test</code>, this node may allow or disallow
034: * <code>Tuples</code> to proceed further through the Rete-OO network.
035: * </p>
036: *
037: * @see EvalConditionNode
038: * @see Eval
039: * @see ReteTuple
040: *
041: * @author <a href="mailto:mark.proctor@jboss.com">Mark Proctor</a>
042: * @author <a href="mailto:bob@werken.com">Bob McWhirter</a>
043: */
044: public class EvalConditionNode extends TupleSource implements
045: TupleSinkNode, NodeMemory {
046: // ------------------------------------------------------------
047: // Instance members
048: // ------------------------------------------------------------
049:
050: /**
051: *
052: */
053: private static final long serialVersionUID = 400L;
054:
055: /** The semantic <code>Test</code>. */
056: private final EvalCondition condition;
057:
058: /** The source of incoming <code>Tuples</code>. */
059: private final TupleSource tupleSource;
060:
061: private TupleSinkNode previousTupleSinkNode;
062: private TupleSinkNode nextTupleSinkNode;
063:
064: // ------------------------------------------------------------
065: // Constructors
066: // ------------------------------------------------------------
067:
068: /**
069: * Construct.
070: *
071: * @param rule
072: * The rule
073: * @param tupleSource
074: * The source of incoming <code>Tuples</code>.
075: * @param eval
076: */
077: public EvalConditionNode(final int id,
078: final TupleSource tupleSource, final EvalCondition eval) {
079: super (id);
080: this .condition = eval;
081: this .tupleSource = tupleSource;
082: this .hasMemory = true;
083: }
084:
085: /**
086: * Attaches this node into the network.
087: */
088: public void attach() {
089: this .tupleSource.addTupleSink(this );
090: }
091:
092: public void attach(final InternalWorkingMemory[] workingMemories) {
093: attach();
094:
095: for (int i = 0, length = workingMemories.length; i < length; i++) {
096: final InternalWorkingMemory workingMemory = workingMemories[i];
097: final PropagationContext propagationContext = new PropagationContextImpl(
098: workingMemory.getNextPropagationIdCounter(),
099: PropagationContext.RULE_ADDITION, null, null);
100: this .tupleSource.updateSink(this , propagationContext,
101: workingMemory);
102: }
103: }
104:
105: // ------------------------------------------------------------
106: // Instance methods
107: // ------------------------------------------------------------
108:
109: /**
110: * Retrieve the <code>Test</code> associated with this node.
111: *
112: * @return The <code>Test</code>.
113: */
114: public EvalCondition getCondition() {
115: return this .condition;
116: }
117:
118: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
119: // org.drools.reteoo.impl.TupleSink
120: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
121:
122: /**
123: * Assert a new <code>Tuple</code>.
124: *
125: * @param tuple
126: * The <code>Tuple</code> being asserted.
127: * @param workingMemory
128: * The working memory seesion.
129: * @throws AssertionException
130: * If an error occurs while asserting.
131: */
132: public void assertTuple(final ReteTuple tuple,
133: final PropagationContext context,
134: final InternalWorkingMemory workingMemory) {
135:
136: final boolean allowed = this .condition.isAllowed(tuple,
137: workingMemory);
138:
139: if (allowed) {
140: if (!workingMemory.isSequential()) {
141: final TupleHashTable memory = (TupleHashTable) workingMemory
142: .getNodeMemory(this );
143: memory.add(tuple);
144: }
145:
146: this .sink.propagateAssertTuple(tuple, context,
147: workingMemory);
148: }
149: }
150:
151: public void retractTuple(final ReteTuple tuple,
152: final PropagationContext context,
153: final InternalWorkingMemory workingMemory) {
154: final TupleHashTable memory = (TupleHashTable) workingMemory
155: .getNodeMemory(this );
156:
157: // can we improve that?
158: final ReteTuple memTuple = memory.remove(tuple);
159: if (memTuple != null) {
160: this .sink.propagateRetractTuple(memTuple, context,
161: workingMemory);
162: }
163: }
164:
165: /**
166: * Produce a debug string.
167: *
168: * @return The debug string.
169: */
170: public String toString() {
171: return "[EvalConditionNode: cond=" + this .condition + "]";
172: }
173:
174: public int hashCode() {
175: return this .tupleSource.hashCode() ^ this .condition.hashCode();
176: }
177:
178: public boolean equals(final Object object) {
179: if (this == object) {
180: return true;
181: }
182:
183: if (object == null
184: || object.getClass() != EvalConditionNode.class) {
185: return false;
186: }
187:
188: final EvalConditionNode other = (EvalConditionNode) object;
189:
190: return this .tupleSource.equals(other.tupleSource)
191: && this .condition.equals(other.condition);
192: }
193:
194: public Object createMemory(final RuleBaseConfiguration config) {
195: return new TupleHashTable();
196: }
197:
198: /* (non-Javadoc)
199: * @see org.drools.reteoo.BaseNode#updateNewNode(org.drools.reteoo.WorkingMemoryImpl, org.drools.spi.PropagationContext)
200: */
201: public void updateSink(final TupleSink sink,
202: final PropagationContext context,
203: final InternalWorkingMemory workingMemory) {
204:
205: final TupleHashTable memory = (TupleHashTable) workingMemory
206: .getNodeMemory(this );
207:
208: final Iterator it = memory.iterator();
209: for (ReteTuple tuple = (ReteTuple) it.next(); tuple != null; tuple = (ReteTuple) it
210: .next()) {
211: sink.assertTuple(tuple, context, workingMemory);
212: }
213: }
214:
215: public void remove(final BaseNode node,
216: final InternalWorkingMemory[] workingMemories) {
217: if (!node.isInUse()) {
218: removeTupleSink((TupleSink) node);
219: }
220: removeShare();
221: if (!this .isInUse()) {
222: for (int i = 0, length = workingMemories.length; i < length; i++) {
223: workingMemories[i].clearNodeMemory(this );
224: }
225: }
226: this .tupleSource.remove(this , workingMemories);
227:
228: }
229:
230: /**
231: * Returns the next node
232: * @return
233: * The next TupleSinkNode
234: */
235: public TupleSinkNode getNextTupleSinkNode() {
236: return this .nextTupleSinkNode;
237: }
238:
239: /**
240: * Sets the next node
241: * @param next
242: * The next TupleSinkNode
243: */
244: public void setNextTupleSinkNode(final TupleSinkNode next) {
245: this .nextTupleSinkNode = next;
246: }
247:
248: /**
249: * Returns the previous node
250: * @return
251: * The previous TupleSinkNode
252: */
253: public TupleSinkNode getPreviousTupleSinkNode() {
254: return this .previousTupleSinkNode;
255: }
256:
257: /**
258: * Sets the previous node
259: * @param previous
260: * The previous TupleSinkNode
261: */
262: public void setPreviousTupleSinkNode(final TupleSinkNode previous) {
263: this.previousTupleSinkNode = previous;
264: }
265:
266: }
|