001: package org.drools.reteoo;
002:
003: import org.drools.RuleBaseConfiguration;
004: import org.drools.common.BaseNode;
005: import org.drools.common.BetaConstraints;
006: import org.drools.common.EmptyBetaConstraints;
007: import org.drools.common.InternalFactHandle;
008: import org.drools.common.InternalWorkingMemory;
009: import org.drools.common.NodeMemory;
010: import org.drools.common.PropagationContextImpl;
011: import org.drools.spi.AlphaNodeFieldConstraint;
012: import org.drools.spi.DataProvider;
013: import org.drools.spi.PropagationContext;
014: import org.drools.util.Iterator;
015: import org.drools.util.LinkedList;
016: import org.drools.util.LinkedListEntry;
017: import org.drools.util.TupleHashTable;
018:
019: public class FromNode extends TupleSource implements TupleSinkNode,
020: NodeMemory {
021: /**
022: *
023: */
024: private static final long serialVersionUID = 400L;
025:
026: private DataProvider dataProvider;
027: private TupleSource tupleSource;
028: private AlphaNodeFieldConstraint[] alphaConstraints;
029: private BetaConstraints betaConstraints;
030:
031: private TupleSinkNode previousTupleSinkNode;
032: private TupleSinkNode nextTupleSinkNode;
033:
034: public FromNode(final int id, final DataProvider dataProvider,
035: final TupleSource tupleSource,
036: final AlphaNodeFieldConstraint[] constraints,
037: final BetaConstraints binder) {
038: super (id);
039: this .dataProvider = dataProvider;
040: this .tupleSource = tupleSource;
041: this .alphaConstraints = constraints;
042: this .betaConstraints = (binder == null) ? EmptyBetaConstraints
043: .getInstance() : binder;
044: }
045:
046: /**
047: * @inheritDoc
048: */
049: public void assertTuple(final ReteTuple leftTuple,
050: final PropagationContext context,
051: final InternalWorkingMemory workingMemory) {
052: final BetaMemory memory = (BetaMemory) workingMemory
053: .getNodeMemory(this );
054:
055: memory.getTupleMemory().add(leftTuple);
056: final LinkedList list = new LinkedList();
057: this .betaConstraints.updateFromTuple(workingMemory, leftTuple);
058:
059: for (final java.util.Iterator it = this .dataProvider
060: .getResults(leftTuple, workingMemory, context); it
061: .hasNext();) {
062: final Object object = it.next();
063:
064: if (this .alphaConstraints != null) {
065: // First alpha node filters
066: boolean isAllowed = true;
067: for (int i = 0, length = this .alphaConstraints.length; i < length; i++) {
068: if (!this .alphaConstraints[i].isAllowed(object,
069: workingMemory)) {
070: // next iteration
071: isAllowed = false;
072: break;
073: }
074: }
075: if (!isAllowed) {
076: continue;
077: }
078: }
079:
080: if (this .betaConstraints.isAllowedCachedLeft(object)) {
081: final InternalFactHandle handle = workingMemory
082: .getFactHandleFactory().newFactHandle(object);
083:
084: list.add(new LinkedListEntry(handle));
085:
086: this .sink.propagateAssertTuple(leftTuple, handle,
087: context, workingMemory);
088: }
089: }
090: if (!list.isEmpty()) {
091: memory.getCreatedHandles().put(leftTuple, list);
092: }
093:
094: }
095:
096: public void retractTuple(final ReteTuple leftTuple,
097: final PropagationContext context,
098: final InternalWorkingMemory workingMemory) {
099:
100: final BetaMemory memory = (BetaMemory) workingMemory
101: .getNodeMemory(this );
102: final ReteTuple tuple = memory.getTupleMemory().remove(
103: leftTuple);
104:
105: final LinkedList list = (LinkedList) memory.getCreatedHandles()
106: .remove(tuple);
107: // if tuple was propagated
108: if (list != null) {
109: for (LinkedListEntry entry = (LinkedListEntry) list
110: .getFirst(); entry != null; entry = (LinkedListEntry) entry
111: .getNext()) {
112: final InternalFactHandle handle = (InternalFactHandle) entry
113: .getObject();
114: this .sink.propagateRetractTuple(leftTuple, handle,
115: context, workingMemory);
116: workingMemory.getFactHandleFactory().destroyFactHandle(
117: handle);
118: }
119: }
120: }
121:
122: public void attach() {
123: this .tupleSource.addTupleSink(this );
124: }
125:
126: public void attach(final InternalWorkingMemory[] workingMemories) {
127: attach();
128:
129: for (int i = 0, length = workingMemories.length; i < length; i++) {
130: final InternalWorkingMemory workingMemory = workingMemories[i];
131: final PropagationContext propagationContext = new PropagationContextImpl(
132: workingMemory.getNextPropagationIdCounter(),
133: PropagationContext.RULE_ADDITION, null, null);
134: this .tupleSource.updateSink(this , propagationContext,
135: workingMemory);
136: }
137: }
138:
139: public void remove(final BaseNode node,
140: final InternalWorkingMemory[] workingMemories) {
141:
142: if (!node.isInUse()) {
143: removeTupleSink((TupleSink) node);
144: }
145: removeShare();
146:
147: if (!this .isInUse()) {
148: for (int i = 0, length = workingMemories.length; i < length; i++) {
149: workingMemories[i].clearNodeMemory(this );
150: }
151: }
152: this .tupleSource.remove(this , workingMemories);
153: }
154:
155: public void updateSink(final TupleSink sink,
156: final PropagationContext context,
157: final InternalWorkingMemory workingMemory) {
158:
159: final BetaMemory memory = (BetaMemory) workingMemory
160: .getNodeMemory(this );
161:
162: final Iterator tupleIter = memory.getTupleMemory().iterator();
163: for (ReteTuple tuple = (ReteTuple) tupleIter.next(); tuple != null; tuple = (ReteTuple) tupleIter
164: .next()) {
165: final LinkedList list = (LinkedList) memory
166: .getCreatedHandles().remove(tuple);
167: if (list == null) {
168: continue;
169: }
170: for (LinkedListEntry entry = (LinkedListEntry) list
171: .getFirst(); entry != null; entry = (LinkedListEntry) entry
172: .getNext()) {
173: final InternalFactHandle handle = (InternalFactHandle) entry
174: .getObject();
175: this .sink.propagateRetractTuple(tuple, handle, context,
176: workingMemory);
177: workingMemory.getFactHandleFactory().destroyFactHandle(
178: handle);
179: }
180: }
181: }
182:
183: public Object createMemory(final RuleBaseConfiguration config) {
184: return new BetaMemory(new TupleHashTable(), null);
185: }
186:
187: /**
188: * Returns the next node
189: * @return
190: * The next TupleSinkNode
191: */
192: public TupleSinkNode getNextTupleSinkNode() {
193: return this .nextTupleSinkNode;
194: }
195:
196: /**
197: * Sets the next node
198: * @param next
199: * The next TupleSinkNode
200: */
201: public void setNextTupleSinkNode(final TupleSinkNode next) {
202: this .nextTupleSinkNode = next;
203: }
204:
205: /**
206: * Returns the previous node
207: * @return
208: * The previous TupleSinkNode
209: */
210: public TupleSinkNode getPreviousTupleSinkNode() {
211: return this .previousTupleSinkNode;
212: }
213:
214: /**
215: * Sets the previous node
216: * @param previous
217: * The previous TupleSinkNode
218: */
219: public void setPreviousTupleSinkNode(final TupleSinkNode previous) {
220: this.previousTupleSinkNode = previous;
221: }
222:
223: }
|