[jboss-svn-commits] JBL Code SVN: r17651 - in labs/jbossrules/branches/righttuple/drools-core/src: main/java/org/drools/reteoo and 2 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Wed Jan 9 07:41:15 EST 2008


Author: mark.proctor at jboss.com
Date: 2008-01-09 07:41:15 -0500 (Wed, 09 Jan 2008)
New Revision: 17651

Added:
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/CompositeLeftTupleSinkAdapter.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/RightTuple.java
Removed:
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/CompositeTupleSinkAdapter.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/FactList.java
Modified:
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/DefaultBetaConstraints.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/DefaultFactHandle.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/DoubleBetaConstraints.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/EmptyBetaConstraints.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/InternalFactHandle.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/QuadroupleBetaConstraints.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/TripleBetaConstraints.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/AlphaNode.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/CompositeRightTupleSinkAdapter.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/EmptyLeftTupleSinkAdapter.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/ExistsNode.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/JoinNode.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/LeftInputAdapterNode.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/LeftTuple.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/LeftTupleMemory.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/LeftTupleSinkPropagator.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/LeftTupleSource.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/NotNode.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/ObjectTypeNode.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/Rete.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/ReteooRuleBase.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/RightTupleMemory.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/RuleTerminalNode.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/SingleLeftTupleSinkAdapter.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/SingleRightTupletSinkAdapter.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/AbstractHashTable.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/FactHandleIndexHashTable.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/FactHashTable.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/Iterator.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/LinkedList.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/TupleHashTable.java
   labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/TupleIndexHashTable.java
   labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/AlphaNodeTest.java
   labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/CompositeObjectSinkAdapterTest.java
   labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/JoinNodeTest.java
   labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/LeftInputAdapterNodeTest.java
   labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/MockObjectSource.java
   labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/MockTupleSink.java
   labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/NotNodeTest.java
   labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/ObjectTypeNodeTest.java
   labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/ReteTest.java
   labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/TupleSourceTest.java
Log:
-more refactoring for a RightTuple so that we can retract via reference traversal.

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -1488,6 +1488,10 @@
 
         return memory;
     }
+    
+    public boolean nodeMemoryExists(final NodeMemory node) {
+        return this.nodeMemories.get( node.getId() ) != null;
+    }
 
     public void clearNodeMemory(final NodeMemory node) {
         this.nodeMemories.remove( node.getId() );

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/DefaultBetaConstraints.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/DefaultBetaConstraints.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/DefaultBetaConstraints.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -33,7 +33,6 @@
 import org.drools.spi.Constraint;
 import org.drools.util.FactHandleIndexHashTable;
 import org.drools.util.FactHashTable;
-import org.drools.util.FactList;
 import org.drools.util.LinkedList;
 import org.drools.util.LinkedListEntry;
 import org.drools.util.TupleHashTable;
@@ -230,13 +229,13 @@
             if ( config.isIndexRightBetaMemory() ) {
                 factHandleMemory = new FactHandleIndexHashTable( indexes );
             } else {
-                factHandleMemory = config.isSequential() ? (RightTupleMemory) new FactList() : (RightTupleMemory) new FactHashTable();
+                factHandleMemory = new FactHashTable();
             }
             memory = new BetaMemory( config.isSequential() ? null : tupleMemory,
                                      factHandleMemory );
         } else {
             memory = new BetaMemory( config.isSequential() ? null : new TupleHashTable(),
-                                     config.isSequential() ? (RightTupleMemory) new FactList() : (RightTupleMemory) new FactHashTable() );
+                                     new FactHashTable() );
         }
 
         return memory;

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/DefaultFactHandle.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/DefaultFactHandle.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/DefaultFactHandle.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -17,6 +17,7 @@
  */
 
 import org.drools.FactHandle;
+import org.drools.reteoo.RightTuple;
 
 /**
  * Implementation of <code>FactHandle</code>.
@@ -41,6 +42,7 @@
     private EqualityKey       key;
     private int               objectHashCode;
     private boolean           shadowFact;
+    private RightTuple        rightTuple;
 
     // ----------------------------------------------------------------------
     // Constructors
@@ -161,8 +163,16 @@
      */
     public void setEqualityKey(final EqualityKey key) {
         this.key = key;
+    }        
+
+    public RightTuple getRightTuple() {
+        return rightTuple;
     }
 
+    public void setRightTuple(RightTuple rightTuple) {
+        this.rightTuple = rightTuple;
+    }
+
     /**
      * Always returns false, since the DefaultFactHandle is
      * only used for regular Facts, and not for Events

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/DoubleBetaConstraints.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/DoubleBetaConstraints.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/DoubleBetaConstraints.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -32,7 +32,6 @@
 import org.drools.spi.BetaNodeFieldConstraint;
 import org.drools.util.FactHandleIndexHashTable;
 import org.drools.util.FactHashTable;
-import org.drools.util.FactList;
 import org.drools.util.LinkedList;
 import org.drools.util.LinkedListEntry;
 import org.drools.util.TupleHashTable;
@@ -212,13 +211,13 @@
             if ( config.isIndexRightBetaMemory() ) {
                 factHandleMemory = new FactHandleIndexHashTable( indexes );
             } else {
-                factHandleMemory = config.isSequential() ? (RightTupleMemory) new FactList() : (RightTupleMemory) new FactHashTable();
+                factHandleMemory =  new FactHashTable();
             }
             memory = new BetaMemory( config.isSequential() ? null : tupleMemory,
                                      factHandleMemory );
         } else {
             memory = new BetaMemory( config.isSequential() ? null : new TupleHashTable(),
-                                     config.isSequential() ? (RightTupleMemory) new FactList() : (RightTupleMemory) new FactHashTable() );
+                                     new FactHashTable());
         }
 
         return memory;

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/EmptyBetaConstraints.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/EmptyBetaConstraints.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/EmptyBetaConstraints.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -24,7 +24,6 @@
 import org.drools.reteoo.RightTupleMemory;
 import org.drools.reteoo.LeftTuple;
 import org.drools.util.FactHashTable;
-import org.drools.util.FactList;
 import org.drools.util.LinkedList;
 import org.drools.util.TupleHashTable;
 
@@ -89,7 +88,7 @@
 
     public BetaMemory createBetaMemory(final RuleBaseConfiguration config) {
         final BetaMemory memory = new BetaMemory( config.isSequential() ? null : new TupleHashTable(),
-                                                  config.isSequential() ? (RightTupleMemory) new FactList() : (RightTupleMemory) new FactHashTable() );
+                                                  new FactHashTable() );
 
         return memory;
     }

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/InternalFactHandle.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/InternalFactHandle.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/InternalFactHandle.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -17,6 +17,7 @@
  */
 
 import org.drools.FactHandle;
+import org.drools.reteoo.RightTuple;
 
 public interface InternalFactHandle
     extends
@@ -43,6 +44,10 @@
 
     public void setShadowFact(boolean shadowFact);
     
+    public RightTuple getRightTuple();
+
+    public void setRightTuple(RightTuple rightTuple);    
+    
     /**
      * Returns true if this FactHandle represents
      * and Event or false if this FactHandle represents

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/QuadroupleBetaConstraints.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/QuadroupleBetaConstraints.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/QuadroupleBetaConstraints.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -32,7 +32,6 @@
 import org.drools.spi.BetaNodeFieldConstraint;
 import org.drools.util.FactHandleIndexHashTable;
 import org.drools.util.FactHashTable;
-import org.drools.util.FactList;
 import org.drools.util.LinkedList;
 import org.drools.util.LinkedListEntry;
 import org.drools.util.TupleHashTable;
@@ -306,13 +305,13 @@
             if ( conf.isIndexRightBetaMemory() ) {
                 factHandleMemory = new FactHandleIndexHashTable( indexes );
             } else {
-                factHandleMemory = conf.isSequential() ? (RightTupleMemory) new FactList() : (RightTupleMemory) new FactHashTable();
+                factHandleMemory = new FactHashTable();
             }
             memory = new BetaMemory( conf.isSequential() ? null : tupleMemory,
                                      factHandleMemory );
         } else {
             memory = new BetaMemory( conf.isSequential() ? null : new TupleHashTable(),
-                                     conf.isSequential() ? (RightTupleMemory) new FactList() : (RightTupleMemory) new FactHashTable() );
+                                     new FactHashTable() );
         }
 
         return memory;

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/TripleBetaConstraints.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/TripleBetaConstraints.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/common/TripleBetaConstraints.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -32,7 +32,6 @@
 import org.drools.spi.BetaNodeFieldConstraint;
 import org.drools.util.FactHashTable;
 import org.drools.util.FactHandleIndexHashTable;
-import org.drools.util.FactList;
 import org.drools.util.LinkedList;
 import org.drools.util.LinkedListEntry;
 import org.drools.util.TupleHashTable;
@@ -257,13 +256,13 @@
             if ( conf.isIndexRightBetaMemory() ) {
                 factHandleMemory = new FactHandleIndexHashTable( indexes );
             } else {
-                factHandleMemory = conf.isSequential() ? (RightTupleMemory) new FactList() : (RightTupleMemory) new FactHashTable();
+                factHandleMemory = new FactHashTable();
             }
             memory = new BetaMemory( conf.isSequential() ? null : tupleMemory,
                                      factHandleMemory );
         } else {
             memory = new BetaMemory( conf.isSequential() ? null : new TupleHashTable(),
-                                     conf.isSequential() ? (RightTupleMemory) new FactList() : (RightTupleMemory) new FactHashTable() );
+                                     new FactHashTable() );
         }
 
         return memory;

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/AlphaNode.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/AlphaNode.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/AlphaNode.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -52,8 +52,8 @@
     /** The <code>FieldConstraint</code> */
     private final AlphaNodeFieldConstraint constraint;
 
-    private RightTupleSinkNode                 previousRightTupleSinkNode;
-    private RightTupleSinkNode                 nextRightTupleNode;
+    private RightTupleSinkNode             previousRightTupleSinkNode;
+    private RightTupleSinkNode             nextRightTupleNode;
 
     private boolean                        rightTupleMemoryEnabled;
 
@@ -126,38 +126,35 @@
     }
 
     public void assertRightTuple(final RightTuple rightTuple,
-                             final PropagationContext context,
-                             final InternalWorkingMemory workingMemory) throws FactException {
+                                 final PropagationContext context,
+                                 final InternalWorkingMemory workingMemory) throws FactException {
         if ( this.constraint.isAllowed( rightTuple.getHandle(),
                                         workingMemory ) ) {
             if ( isRightTupleMemoryEnabled() ) {
                 final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( this );
-                memory.add( rightTuple,
-                            false );
+                memory.add( rightTuple );
             }
 
             this.sink.propagateAssertRightTuple( rightTuple,
-                                             context,
-                                             workingMemory );
+                                                 context,
+                                                 workingMemory );
         }
     }
 
     public void retractRightTuple(final RightTuple rightTuple,
-                              final PropagationContext context,
-                              final InternalWorkingMemory workingMemory) {
-        boolean propagate = true;
+                                  final PropagationContext context,
+                                  final InternalWorkingMemory workingMemory) {        
         if ( isRightTupleMemoryEnabled() ) {
             final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( this );
-            propagate = memory.remove( rightTuple );
-        } else {
-            propagate = this.constraint.isAllowed( rightTuple.getHandle(),
-                                                   workingMemory );
+            memory.remove( rightTuple );
         }
-        if ( propagate ) {
+                
+        
+        if ( rightTuple.getAlphaChildren() != null ) {
             this.sink.propagateRetractRightTuple( rightTuple,
-                                              context,
-                                              workingMemory,
-                                              true );
+                                                  context,
+                                                  workingMemory,
+                                                  true );
         }
     }
 
@@ -168,18 +165,18 @@
 
         if ( !isRightTupleMemoryEnabled() ) {
             // get the objects from the parent
-            RightTupleSinkUpdateAdapter adapter = new RightTupleSinkUpdateAdapter( sink, this.constraint );
+            RightTupleSinkUpdateAdapter adapter = new RightTupleSinkUpdateAdapter( sink,
+                                                                                   this.constraint );
             this.objectSource.updateSink( adapter,
                                           context,
                                           workingMemory );
         } else {
             // if already has memory, just iterate and propagate
             memory = (FactHashTable) workingMemory.getNodeMemory( this );
-            final Iterator it = memory.iterator();
-            for ( RightTuple entry = (RightTuple) it.next(); entry != null; entry = (RightTuple) it.next() ) {
-                sink.assertRightTuple( entry,
-                                   context,
-                                   workingMemory );
+            for ( RightTuple rightTuple = (RightTuple)  memory.getFirst( null ); rightTuple != null; rightTuple = (RightTuple) rightTuple.getNext() ) {
+                sink.assertRightTuple( rightTuple,
+                                       context,
+                                       workingMemory );
             }
         }
     }
@@ -298,23 +295,23 @@
     private static class RightTupleSinkUpdateAdapter
         implements
         RightTupleSink {
-        private final RightTupleSink sink;
+        private final RightTupleSink           sink;
         private final AlphaNodeFieldConstraint constraint;
 
-        public RightTupleSinkUpdateAdapter(final RightTupleSink sink, 
-                                       final AlphaNodeFieldConstraint constraint ) {
+        public RightTupleSinkUpdateAdapter(final RightTupleSink sink,
+                                           final AlphaNodeFieldConstraint constraint) {
             this.sink = sink;
             this.constraint = constraint;
         }
 
         public void assertRightTuple(final RightTuple rightTuple,
-                                 final PropagationContext context,
-                                 final InternalWorkingMemory workingMemory) {
+                                     final PropagationContext context,
+                                     final InternalWorkingMemory workingMemory) {
             if ( this.constraint.isAllowed( rightTuple.getHandle(),
                                             workingMemory ) ) {
                 this.sink.assertRightTuple( rightTuple,
-                                        context,
-                                        workingMemory );
+                                            context,
+                                            workingMemory );
             }
         }
 
@@ -325,8 +322,8 @@
         }
 
         public void retractRightTuple(final RightTuple rightTuple,
-                                  final PropagationContext context,
-                                  final InternalWorkingMemory workingMemory) {
+                                      final PropagationContext context,
+                                      final InternalWorkingMemory workingMemory) {
             throw new UnsupportedOperationException( "ObjectSinkUpdateAdapter onlys supports assertObject method calls" );
         }
 

Copied: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/CompositeLeftTupleSinkAdapter.java (from rev 17533, labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/CompositeTupleSinkAdapter.java)
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/CompositeLeftTupleSinkAdapter.java	                        (rev 0)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/CompositeLeftTupleSinkAdapter.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -0,0 +1,186 @@
+package org.drools.reteoo;
+
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+
+public class CompositeLeftTupleSinkAdapter
+    implements
+    LeftTupleSinkPropagator {
+    private LeftTupleSinkNodeList sinks;
+
+    public CompositeLeftTupleSinkAdapter() {
+        this.sinks = new LeftTupleSinkNodeList();
+    }
+
+    public void addTupleSink(final LeftTupleSink sink) {
+        this.sinks.add( (LeftTupleSinkNode) sink );
+    }
+
+    public void removeTupleSink(final LeftTupleSink sink) {
+        this.sinks.remove( (LeftTupleSinkNode) sink );
+    }
+
+    public void propagateAssertTuple(final LeftTuple leftTuple,
+                                     final RightTuple rightTuple,
+                                     final PropagationContext context,
+                                     final InternalWorkingMemory workingMemory) {
+
+        for ( LeftTupleSinkNode sink = this.sinks.getFirst(); sink != null; sink = sink.getNextLeftTupleSinkNode() ) {
+            sink.assertTuple( new LeftTuple( leftTuple,
+                                             rightTuple,
+                                             sink ),
+                              context,
+                              workingMemory );
+        }
+    }
+
+    public void propagateAssertTuple(final LeftTuple tuple,
+                                     final PropagationContext context,
+                                     final InternalWorkingMemory workingMemory) {
+        for ( LeftTupleSinkNode sink = this.sinks.getFirst(); sink != null; sink = sink.getNextLeftTupleSinkNode() ) {
+            sink.assertTuple( new LeftTuple( tuple,
+                                             sink ),
+                              context,
+                              workingMemory );
+        }
+    }
+
+    public void propagateRetractLeftTuple(final LeftTuple leftTuple,
+                                          final PropagationContext context,
+                                          final InternalWorkingMemory workingMemory) {
+        LeftTuple child = leftTuple.getBetaChildren();
+        while ( child != null ) {
+            //LeftTuple temp = leftTuple.getRightParentNext();
+            //child.unlinkFromParents();
+            child.unlinkFromRightParent();
+            child.getSink().retractTuple( child,
+                                          context,
+                                          workingMemory );
+            child = child.getRightParentNext();
+            //child = temp;
+        }
+        leftTuple.setBetaChildren( null );
+    }
+
+    public void propagateRetractRightTuple(final RightTuple rightTuple,
+                                           final PropagationContext context,
+                                           final InternalWorkingMemory workingMemory) {
+        LeftTuple child = rightTuple.getBetaChildren();
+        while ( child != null ) {
+            //LeftTuple temp = child.getRightParentNext();
+            //child.unlinkFromParents();
+            child.unlinkFromLeftParent();
+            child.getSink().retractTuple( child,
+                                          context,
+                                          workingMemory );
+            child = child.getRightParentNext();
+            //child = temp;
+        }
+        rightTuple.setBetaChildren( null );
+    }
+
+    public void createAndPropagateAssertTuple(final RightTuple rightTuple,
+                                              final PropagationContext context,
+                                              final InternalWorkingMemory workingMemory) {
+        for ( LeftTupleSinkNode sink = this.sinks.getFirst(); sink != null; sink = sink.getNextLeftTupleSinkNode() ) {
+            sink.assertTuple( new LeftTuple( rightTuple,
+                                             sink ),
+                              context,
+                              workingMemory );
+        }
+    }
+
+    public void createAndPropagateRetractTuple(final RightTuple rightTuple,
+                                               final PropagationContext context,
+                                               final InternalWorkingMemory workingMemory) {
+        LeftTuple child = rightTuple.getBetaChildren();
+        while ( child != null ) {
+            //LeftTuple temp = child.getRightParentNext();
+            //child.unlinkFromParents();
+            child.getSink().retractTuple( child, context, workingMemory );
+            child = child.getRightParentNext();
+            //child = temp;
+        }
+        rightTuple.setBetaChildren( null );
+    }
+
+    public LeftTupleSink[] getSinks() {
+        final LeftTupleSink[] sinkArray = new LeftTupleSink[this.sinks.size()];
+
+        int i = 0;
+        for ( LeftTupleSinkNode sink = this.sinks.getFirst(); sink != null; sink = sink.getNextLeftTupleSinkNode() ) {
+            sinkArray[i++] = sink;
+        }
+
+        return sinkArray;
+    }
+
+    //    public void propagateNewTupleSink(TupleMatch tupleMatch,
+    //                                      PropagationContext context,
+    //                                      InternalWorkingMemory workingMemory) {
+    //
+    //        final TupleSink sink = sinks.getLast();
+    //        final ReteTuple tuple = new ReteTuple( tupleMatch.getTuple(),
+    //                                               tupleMatch.getObjectMatches().getFactHandle(),
+    //                                               sink );
+    //        tupleMatch.addJoinedTuple( tuple );
+    //        tuple.assertTuple( context,
+    //                           workingMemory );
+    //    }
+    //
+    //    public void propagateNewTupleSink(ReteTuple tuple,
+    //                                      PropagationContext context,
+    //                                      InternalWorkingMemory workingMemory) {
+    //
+    //        final TupleSink sink = sinks.getLast();
+    //        ReteTuple child = new ReteTuple( tuple,
+    //                                         sink );
+    //        tuple.addChildEntry( child );
+    //        child.assertTuple( context,
+    //                           workingMemory );
+    //    }
+    //
+    //    public void propagateNewTupleSink(InternalFactHandle handle,
+    //                                      LinkedList list,
+    //                                      PropagationContext context,
+    //                                      InternalWorkingMemory workingMemory) {
+    //        TupleSink sink = this.sinks.getLast();
+    //        ReteTuple tuple = new ReteTuple( handle,
+    //                                         sink );
+    //        list.add( new LinkedListEntry( tuple ) );
+    //        tuple.assertTuple( context,
+    //                           workingMemory );
+    //    }
+    //
+    //    /**
+    //     * @inheritDoc
+    //     */
+    //    public List getPropagatedTuples(final Map memory,
+    //                                    final InternalWorkingMemory workingMemory,
+    //                                    final TupleSink sink) {
+    //        int index = 0;
+    //        for ( TupleSinkNode node = this.sinks.getFirst(); node != null; node = node.getNextTupleSinkNode() ) {
+    //            if ( node.equals( sink ) ) {
+    //                break;
+    //            }
+    //            index++;
+    //        }
+    //
+    //        final List propagatedTuples = new ArrayList( memory.size() );
+    //
+    //        for ( final Iterator it = memory.values().iterator(); it.hasNext(); ) {
+    //            final LinkedList tuples = (LinkedList) it.next();
+    //            LinkedListEntry wrapper = (LinkedListEntry) tuples.getFirst();
+    //            for ( int i = 0; i < index; i++ ) {
+    //                wrapper = (LinkedListEntry) wrapper.getNext();
+    //            }
+    //            propagatedTuples.add( wrapper.getObject() );
+    //        }
+    //
+    //        return propagatedTuples;
+    //    }
+
+    public int size() {
+        return this.sinks.size();
+    }
+}

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/CompositeRightTupleSinkAdapter.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/CompositeRightTupleSinkAdapter.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/CompositeRightTupleSinkAdapter.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -298,7 +298,8 @@
                 final RightTupleSink sink = (RightTupleSink) this.hashedSinkMap.get( this.hashKey );
                 if ( sink != null ) {
                     // The sink exists so propagate
-                    sink.assertRightTuple( new RightTuple( rightTuple ),
+                    sink.assertRightTuple( new RightTuple( rightTuple, 
+                                                           sink ),
                                            context,
                                            workingMemory );
                 }
@@ -308,7 +309,8 @@
         // propagate unhashed
         if ( this.hashableSinks != null ) {
             for ( RightTupleSinkNode sink = this.hashableSinks.getFirst(); sink != null; sink = sink.getNextRightTupleSinkNode() ) {
-                sink.assertRightTuple( new RightTuple( rightTuple ),
+                sink.assertRightTuple( new RightTuple( rightTuple, 
+                                                       sink ),
                                        context,
                                        workingMemory );
             }
@@ -317,7 +319,8 @@
         if ( this.otherSinks != null ) {
             // propagate others
             for ( RightTupleSinkNode sink = this.otherSinks.getFirst(); sink != null; sink = sink.getNextRightTupleSinkNode() ) {
-                sink.assertRightTuple( new RightTuple( rightTuple ),
+                sink.assertRightTuple( new RightTuple( rightTuple, 
+                                                       sink ),
                                        context,
                                        workingMemory );
             }
@@ -329,57 +332,10 @@
                                            final PropagationContext context,
                                            final InternalWorkingMemory workingMemory,
                                            final boolean useHash) {
-        if ( this.hashedFieldIndexes != null ) {
-            if ( useHash && this.hashedSinkMap != null ) {
-                final Object object = rightTuple.getHandle().getObject();
-                // Iterate the FieldIndexes to see if any are hashed        
-                for ( FieldIndex fieldIndex = (FieldIndex) this.hashedFieldIndexes.getFirst(); fieldIndex != null; fieldIndex = (FieldIndex) fieldIndex.getNext() ) {
-                    // this field is hashed so set the existing hashKey and see if there is a sink for it
-                    if ( !fieldIndex.isHashed() ) {
-                        continue;
-                    }
-
-                    final int index = fieldIndex.getIndex();
-                    final FieldExtractor extractor = fieldIndex.getFieldExtactor();
-                    this.hashKey.setValue( index,
-                                           object,
-                                           extractor );
-                    final RightTupleSink sink = (RightTupleSink) this.hashedSinkMap.get( this.hashKey );
-                    if ( sink != null ) {
-                        // The sink exists so propagate
-                        sink.retractRightTuple( new RightTuple( rightTuple ),
-                                                context,
-                                                workingMemory );
-                    }
-                }
-            } else if ( this.hashedSinkMap != null ) {
-                final Iterator it = this.hashedSinkMap.newIterator();
-                for ( ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next() ) {
-                    final RightTupleSink sink = (RightTupleSink) entry.getValue();
-                    sink.retractRightTuple( new RightTuple( rightTuple ),
-                                            context,
-                                            workingMemory );
-                }
-            }
+        for( RightTuple childRightTuple = rightTuple.getAlphaChildren(); childRightTuple != null; childRightTuple = childRightTuple.getParentNext() ) {
+            childRightTuple.getRightTupleSink().retractRightTuple( childRightTuple, context, workingMemory );
         }
-
-        if ( this.hashableSinks != null ) {
-            // we can't retrieve hashed sinks, as the field value might have changed, so we have to iterate and propagate to all hashed sinks
-            for ( RightTupleSinkNode sink = this.hashableSinks.getFirst(); sink != null; sink = sink.getNextRightTupleSinkNode() ) {
-                sink.retractRightTuple( new RightTuple( rightTuple ),
-                                        context,
-                                        workingMemory );
-            }
-        }
-
-        if ( this.otherSinks != null ) {
-            // propagate others
-            for ( RightTupleSinkNode sink = this.otherSinks.getFirst(); sink != null; sink = sink.getNextRightTupleSinkNode() ) {
-                sink.retractRightTuple( new RightTuple( rightTuple ),
-                                        context,
-                                        workingMemory );
-            }
-        }
+        rightTuple.setAlphaChildren( null );
     }
 
     public RightTupleSink[] getSinks() {

Deleted: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/CompositeTupleSinkAdapter.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/CompositeTupleSinkAdapter.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/CompositeTupleSinkAdapter.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -1,167 +0,0 @@
-package org.drools.reteoo;
-
-import org.drools.common.InternalWorkingMemory;
-import org.drools.spi.PropagationContext;
-
-public class CompositeTupleSinkAdapter
-    implements
-    LeftTupleSinkPropagator {
-    private LeftTupleSinkNodeList sinks;
-
-    public CompositeTupleSinkAdapter() {
-        this.sinks = new LeftTupleSinkNodeList();
-    }
-
-    public void addTupleSink(final LeftTupleSink sink) {
-        this.sinks.add( (LeftTupleSinkNode) sink );
-    }
-
-    public void removeTupleSink(final LeftTupleSink sink) {
-        this.sinks.remove( (LeftTupleSinkNode) sink );
-    }
-
-    public void propagateAssertTuple(final LeftTuple leftTuple,
-                                     final RightTuple rightTuple,
-                                     final PropagationContext context,
-                                     final InternalWorkingMemory workingMemory) {
-
-        for ( LeftTupleSinkNode sink = this.sinks.getFirst(); sink != null; sink = sink.getNextLeftTupleSinkNode() ) {
-            sink.assertTuple( new LeftTuple( leftTuple,
-                                             rightTuple ),
-                              context,
-                              workingMemory );
-        }
-    }
-
-    public void propagateAssertTuple(final LeftTuple tuple,
-                                     final PropagationContext context,
-                                     final InternalWorkingMemory workingMemory) {
-        for ( LeftTupleSinkNode sink = this.sinks.getFirst(); sink != null; sink = sink.getNextLeftTupleSinkNode() ) {
-            sink.assertTuple( new LeftTuple( tuple ),
-                              context,
-                              workingMemory );
-        }
-    }
-
-    public void propagateRetractTuple(final LeftTuple leftTuple,
-                                      final RightTuple rightTuple,
-                                      final PropagationContext context,
-                                      final InternalWorkingMemory workingMemory) {
-        for ( LeftTupleSinkNode sink = this.sinks.getFirst(); sink != null; sink = sink.getNextLeftTupleSinkNode() ) {
-            sink.retractTuple( new LeftTuple( leftTuple,
-                                              rightTuple ),
-                               context,
-                               workingMemory );
-        }
-    }
-
-    public void propagateRetractTuple(final LeftTuple tuple,
-                                      final PropagationContext context,
-                                      final InternalWorkingMemory workingMemory) {
-        for ( LeftTupleSinkNode sink = this.sinks.getFirst(); sink != null; sink = sink.getNextLeftTupleSinkNode() ) {
-            sink.retractTuple( new LeftTuple( tuple ),
-                               context,
-                               workingMemory );
-        }
-    }
-
-    public void createAndPropagateAssertTuple(final RightTuple rightTuple,
-                                              final PropagationContext context,
-                                              final InternalWorkingMemory workingMemory) {
-        for ( LeftTupleSinkNode sink = this.sinks.getFirst(); sink != null; sink = sink.getNextLeftTupleSinkNode() ) {
-            sink.assertTuple( new LeftTuple( rightTuple ),
-                              context,
-                              workingMemory );
-        }
-    }
-
-    public void createAndPropagateRetractTuple(final RightTuple rightTuple,
-                                               final PropagationContext context,
-                                               final InternalWorkingMemory workingMemory) {
-        for ( LeftTupleSinkNode sink = this.sinks.getFirst(); sink != null; sink = sink.getNextLeftTupleSinkNode() ) {
-            sink.retractTuple( new LeftTuple( rightTuple ),
-                               context,
-                               workingMemory );
-        }
-    }
-
-    public LeftTupleSink[] getSinks() {
-        final LeftTupleSink[] sinkArray = new LeftTupleSink[this.sinks.size()];
-
-        int i = 0;
-        for ( LeftTupleSinkNode sink = this.sinks.getFirst(); sink != null; sink = sink.getNextLeftTupleSinkNode() ) {
-            sinkArray[i++] = sink;
-        }
-
-        return sinkArray;
-    }
-
-    //    public void propagateNewTupleSink(TupleMatch tupleMatch,
-    //                                      PropagationContext context,
-    //                                      InternalWorkingMemory workingMemory) {
-    //
-    //        final TupleSink sink = sinks.getLast();
-    //        final ReteTuple tuple = new ReteTuple( tupleMatch.getTuple(),
-    //                                               tupleMatch.getObjectMatches().getFactHandle(),
-    //                                               sink );
-    //        tupleMatch.addJoinedTuple( tuple );
-    //        tuple.assertTuple( context,
-    //                           workingMemory );
-    //    }
-    //
-    //    public void propagateNewTupleSink(ReteTuple tuple,
-    //                                      PropagationContext context,
-    //                                      InternalWorkingMemory workingMemory) {
-    //
-    //        final TupleSink sink = sinks.getLast();
-    //        ReteTuple child = new ReteTuple( tuple,
-    //                                         sink );
-    //        tuple.addChildEntry( child );
-    //        child.assertTuple( context,
-    //                           workingMemory );
-    //    }
-    //
-    //    public void propagateNewTupleSink(InternalFactHandle handle,
-    //                                      LinkedList list,
-    //                                      PropagationContext context,
-    //                                      InternalWorkingMemory workingMemory) {
-    //        TupleSink sink = this.sinks.getLast();
-    //        ReteTuple tuple = new ReteTuple( handle,
-    //                                         sink );
-    //        list.add( new LinkedListEntry( tuple ) );
-    //        tuple.assertTuple( context,
-    //                           workingMemory );
-    //    }
-    //
-    //    /**
-    //     * @inheritDoc
-    //     */
-    //    public List getPropagatedTuples(final Map memory,
-    //                                    final InternalWorkingMemory workingMemory,
-    //                                    final TupleSink sink) {
-    //        int index = 0;
-    //        for ( TupleSinkNode node = this.sinks.getFirst(); node != null; node = node.getNextTupleSinkNode() ) {
-    //            if ( node.equals( sink ) ) {
-    //                break;
-    //            }
-    //            index++;
-    //        }
-    //
-    //        final List propagatedTuples = new ArrayList( memory.size() );
-    //
-    //        for ( final Iterator it = memory.values().iterator(); it.hasNext(); ) {
-    //            final LinkedList tuples = (LinkedList) it.next();
-    //            LinkedListEntry wrapper = (LinkedListEntry) tuples.getFirst();
-    //            for ( int i = 0; i < index; i++ ) {
-    //                wrapper = (LinkedListEntry) wrapper.getNext();
-    //            }
-    //            propagatedTuples.add( wrapper.getObject() );
-    //        }
-    //
-    //        return propagatedTuples;
-    //    }
-
-    public int size() {
-        return this.sinks.size();
-    }
-}

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/EmptyLeftTupleSinkAdapter.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/EmptyLeftTupleSinkAdapter.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/EmptyLeftTupleSinkAdapter.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -27,12 +27,6 @@
                                      final InternalWorkingMemory workingMemory) {
     }
 
-    public void propagateRetractTuple(final LeftTuple leftTuple,
-                                      final RightTuple rightTuple,
-                                      final PropagationContext context,
-                                      final InternalWorkingMemory workingMemory) {
-    }
-
     public void propagateRetractTuple(final LeftTuple tuple,
                                       final PropagationContext context,
                                       final InternalWorkingMemory workingMemory) {
@@ -55,4 +49,18 @@
     public int size() {
         return 0;
     }
+
+    public void propagateRetractLeftTuple(LeftTuple tuple,
+                                          PropagationContext context,
+                                          InternalWorkingMemory workingMemory) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    public void propagateRetractRightTuple(RightTuple tuple,
+                                           PropagationContext context,
+                                           InternalWorkingMemory workingMemory) {
+        // TODO Auto-generated method stub
+        
+    }
 }

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/ExistsNode.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/ExistsNode.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/ExistsNode.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -101,12 +101,12 @@
         for ( FactEntry entry = (FactEntry) it.next(); entry != null; entry = (FactEntry) it.next() ) {            
             final InternalFactHandle handle = entry.getFactHandle();
             if ( this.constraints.isAllowedCachedLeft( handle ) ) {
-                leftTuple.setMatch( handle );
+                leftTuple.setBlocked( handle );
                 break;
             }            
         }
 
-        if ( leftTuple.getMatch() != null ) {
+        if ( leftTuple.getBlocked() != null ) {
             this.sink.propagateAssertTuple( leftTuple,
                                             context,
                                             workingMemory );
@@ -140,8 +140,8 @@
         this.constraints.updateFromRightTuple( workingMemory,
                                                rightTuple );
         for ( LeftTuple tuple = (LeftTuple) it.next(); tuple != null; tuple = (LeftTuple) it.next() ) {
-            if ( this.constraints.isAllowedCachedRight( tuple ) && tuple.getMatch() == null) {
-                    tuple.setMatch( rightTuple );
+            if ( this.constraints.isAllowedCachedRight( tuple ) && tuple.getBlocked() == null) {
+                    tuple.setBlocked( rightTuple );
                     this.sink.propagateAssertTuple( tuple,
                                                      context,
                                                      workingMemory );                                 
@@ -174,9 +174,9 @@
                                                rightTuple );
         for ( LeftTuple tuple = (LeftTuple) it.next(); tuple != null; tuple = (LeftTuple) it.next() ) {
             if ( this.constraints.isAllowedCachedRight( tuple ) ) {
-                if ( tuple.getMatch() == rightTuple ) {
+                if ( tuple.getBlocked() == rightTuple ) {
                     // reset the match                    
-                    tuple.setMatch( null );
+                    tuple.setBlocked( null );
                     
                     // find next match, remember it and break.
                     final Iterator tupleIt = memory.getRightTupleMemory().iterator( tuple );
@@ -185,13 +185,13 @@
                     for ( FactEntry entry = (FactEntry) tupleIt.next(); entry != null; entry = (FactEntry) tupleIt.next() ) {
                         final InternalFactHandle rightHandle = entry.getFactHandle();
                         if ( this.constraints.isAllowedCachedLeft( rightHandle ) ) {
-                            tuple.setMatch( rightHandle );
+                            tuple.setBlocked( rightHandle );
                             break;
                         }
                     }
                     
                     // if there is now no new tuple match then propagate assert.
-                    if ( tuple.getMatch() == null ) {
+                    if ( tuple.getBlocked() == null ) {
                         this.sink.propagateRetractTuple( tuple,
                                                         context,
                                                         workingMemory );
@@ -224,7 +224,7 @@
             return;
         }
 
-        if ( tuple.getMatch() !=  null) {
+        if ( tuple.getBlocked() !=  null) {
             this.sink.propagateRetractTuple( tuple,
                                              context,
                                              workingMemory );
@@ -242,7 +242,7 @@
 
         final Iterator tupleIter = memory.getLeftTupleMemory().iterator();
         for ( LeftTuple tuple = (LeftTuple) tupleIter.next(); tuple != null; tuple = (LeftTuple) tupleIter.next() ) {
-            if ( tuple.getMatch() != null ) {
+            if ( tuple.getBlocked() != null ) {
                 sink.assertTuple( new LeftTuple( tuple ),
                                   context,
                                   workingMemory );

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/JoinNode.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/JoinNode.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/JoinNode.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -97,14 +97,13 @@
             memory.getLeftTupleMemory().add( leftTuple );
         }
 
-        final Iterator it = memory.getRightTupleMemory().iterator( leftTuple );
         this.constraints.updateFromTuple( workingMemory,
                                           leftTuple );
         
-        for ( RightTuple entry = (RightTuple) it.next(); entry != null; entry = (RightTuple) it.next() ) {
-            if ( this.constraints.isAllowedCachedLeft( entry.getHandle() ) ) {
+        for ( RightTuple rightTuple = memory.getRightTupleMemory().getFirst( leftTuple ); rightTuple != null; rightTuple = (RightTuple) rightTuple.getNext() ) {
+            if ( this.constraints.isAllowedCachedLeft( rightTuple.getHandle() ) ) {
                 this.sink.propagateAssertTuple( leftTuple,
-                                                entry,
+                                                rightTuple,
                                                 context,
                                                 workingMemory );
             }
@@ -142,10 +141,9 @@
             return;
         }
 
-        final Iterator it = memory.getLeftTupleMemory().iterator( rightTuple );
         this.constraints.updateFromRightTuple( workingMemory,
                                                rightTuple );
-        for ( LeftTuple leftTuple = (LeftTuple) it.next(); leftTuple != null; leftTuple = (LeftTuple) it.next() ) {
+        for ( LeftTuple leftTuple = memory.getLeftTupleMemory().getFirst( rightTuple ); leftTuple != null; leftTuple = (LeftTuple) leftTuple.getNext() ) {
             if ( this.constraints.isAllowedCachedRight( leftTuple ) ) {
                 this.sink.propagateAssertTuple( leftTuple,
                                                 rightTuple,
@@ -168,23 +166,12 @@
      */
     public void retractRightTuple(final RightTuple rightTuple,
                               final PropagationContext context,
-                              final InternalWorkingMemory workingMemory) {
+                              final InternalWorkingMemory workingMemory) {        
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
-        if ( !memory.getRightTupleMemory().remove( rightTuple ) ) {
-            return;
+        memory.getRightTupleMemory().remove( rightTuple );
+        if ( rightTuple.getBetaChildren() != null ) {
+            this.sink.propagateRetractRightTuple( rightTuple, context, workingMemory );
         }
-
-        final Iterator it = memory.getLeftTupleMemory().iterator( rightTuple );
-        this.constraints.updateFromRightTuple( workingMemory,
-                                               rightTuple );
-        for ( LeftTuple tuple = (LeftTuple) it.next(); tuple != null; tuple = (LeftTuple) it.next() ) {
-            if ( this.constraints.isAllowedCachedRight( tuple ) ) {
-                this.sink.propagateRetractTuple( tuple,
-                                                 rightTuple,
-                                                 context,
-                                                 workingMemory );
-            }
-        }
     }
 
     /**
@@ -203,22 +190,22 @@
                              final PropagationContext context,
                              final InternalWorkingMemory workingMemory) {
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
-        final LeftTuple tuple = memory.getLeftTupleMemory().remove( leftTuple );
-        if ( tuple == null ) {
-            return;
+        memory.getLeftTupleMemory().remove( leftTuple );
+        if ( leftTuple.getBetaChildren() != null ) {
+            this.sink.propagateRetractLeftTuple( leftTuple, context, workingMemory );
         }
-
-        final Iterator it = memory.getRightTupleMemory().iterator( leftTuple );
-        this.constraints.updateFromTuple( workingMemory,
-                                          leftTuple );
-        for ( RightTuple rightTuple = (RightTuple) it.next(); rightTuple != null; rightTuple = (RightTuple) it.next() ) {
-            if ( this.constraints.isAllowedCachedLeft( rightTuple.getHandle() ) ) {
-                this.sink.propagateRetractTuple( leftTuple,
-                                                 rightTuple,
-                                                 context,
-                                                 workingMemory );
-            }
-        }
+        
+//        final Iterator it = memory.getRightTupleMemory().iterator( leftTuple );
+//        this.constraints.updateFromTuple( workingMemory,
+//                                          leftTuple );
+//        for ( RightTuple rightTuple = (RightTuple) it.next(); rightTuple != null; rightTuple = (RightTuple) it.next() ) {
+//            if ( this.constraints.isAllowedCachedLeft( rightTuple.getHandle() ) ) {
+//                this.sink.propagateRetractTuple( leftTuple,
+//                                                 rightTuple,
+//                                                 context,
+//                                                 workingMemory );
+//            }
+//        }
     }
 
     /* (non-Javadoc)
@@ -232,13 +219,13 @@
 
         final Iterator tupleIter = memory.getLeftTupleMemory().iterator();
         for ( LeftTuple tuple = (LeftTuple) tupleIter.next(); tuple != null; tuple = (LeftTuple) tupleIter.next() ) {
-            final Iterator objectIter = memory.getRightTupleMemory().iterator( tuple );
             this.constraints.updateFromTuple( workingMemory,
                                               tuple );
-            for ( RightTuple rightTuple = (RightTuple) objectIter.next(); rightTuple != null; rightTuple = (RightTuple) objectIter.next() ) {
+            for ( RightTuple rightTuple = memory.getRightTupleMemory().getFirst( tuple ); rightTuple != null; rightTuple = (RightTuple) rightTuple.getNext() ) {
                 if ( this.constraints.isAllowedCachedLeft( rightTuple.getHandle() ) ) {
                     sink.assertTuple( new LeftTuple( tuple,
-                                                     rightTuple ),
+                                                     rightTuple,
+                                                     this ),
                                       context,
                                       workingMemory );
                 }

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/LeftInputAdapterNode.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/LeftInputAdapterNode.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/LeftInputAdapterNode.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -45,14 +45,14 @@
     /**
      * 
      */
-    private static final long  serialVersionUID = 400L;
+    private static final long      serialVersionUID = 400L;
     private final RightTupleSource objectSource;
 
     private RightTupleSinkNode     previousRightTupleSinkNode;
     private RightTupleSinkNode     nextRightTupleSinkNode;
-    
-    private boolean           rightTupleMemoryEnabled;    
 
+    private boolean                rightTupleMemoryEnabled;
+
     /**
      * Constructus a LeftInputAdapterNode with a unique id that receives <code>FactHandle</code> from a 
      * parent <code>ObjectSource</code> and adds it to a given pattern in the resulting Tuples.
@@ -108,8 +108,8 @@
      *            the <code>WorkingMemory</code> session.
      */
     public void assertRightTuple(final RightTuple rightTuple,
-                             final PropagationContext context,
-                             final InternalWorkingMemory workingMemory) {
+                                 final PropagationContext context,
+                                 final InternalWorkingMemory workingMemory) {
 
         if ( !workingMemory.isSequential() ) {
             this.sink.createAndPropagateAssertTuple( rightTuple,
@@ -118,8 +118,7 @@
 
             if ( this.rightTupleMemoryEnabled ) {
                 final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( this );
-                memory.add( rightTuple,
-                            false );
+                memory.add( rightTuple );
             }
         } else {
             //workingMemory.addLIANodePropagation( new LIANodePropagation(this, rightTuple, context) );
@@ -138,19 +137,16 @@
      *            the <code>WorkingMemory</code> session.
      */
     public void retractRightTuple(final RightTuple rightTuple,
-                              final PropagationContext context,
-                              final InternalWorkingMemory workingMemory) {
-        boolean propagate = true;
+                                  final PropagationContext context,
+                                  final InternalWorkingMemory workingMemory) {
         if ( this.rightTupleMemoryEnabled ) {
             final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( this );
-            propagate = memory.remove( rightTuple );
+            memory.remove( rightTuple );
         }
 
-        if ( propagate ) {
-            this.sink.createAndPropagateRetractTuple( rightTuple,
-                                                      context,
-                                                      workingMemory );
-        }
+        this.sink.createAndPropagateRetractTuple( rightTuple,
+                                                  context,
+                                                  workingMemory );
     }
 
     public void updateSink(final LeftTupleSink sink,
@@ -159,9 +155,8 @@
         if ( this.rightTupleMemoryEnabled ) {
             // We have memory so iterate over all entries
             final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( this );
-            final Iterator it = memory.iterator();
-            for ( RightTuple rightTuple = (RightTuple) it.next(); rightTuple != null; rightTuple = (RightTuple) it.next() ) {
-                sink.assertTuple( new LeftTuple( rightTuple ),
+            for ( RightTuple rightTuple = (RightTuple) memory.getFirst( null ); rightTuple != null; rightTuple = (RightTuple) rightTuple.getNext() ) {
+                sink.assertTuple( new LeftTuple( rightTuple, sink ),
                                   context,
                                   workingMemory );
             }
@@ -186,15 +181,15 @@
         }
         this.objectSource.remove( this,
                                   workingMemories );
-    }    
-    
+    }
+
     public boolean isRightTupleMemoryEnabled() {
         return this.rightTupleMemoryEnabled;
     }
 
     public void setRightTupleMemoryEnabled(boolean objectMemoryEnabled) {
         this.rightTupleMemoryEnabled = objectMemoryEnabled;
-    }    
+    }
 
     /**
      * Returns the next node
@@ -270,9 +265,9 @@
         }
 
         public void assertRightTuple(final RightTuple rightTuple,
-                                 final PropagationContext context,
-                                 final InternalWorkingMemory workingMemory) {
-            final LeftTuple tuple = new LeftTuple( rightTuple );
+                                     final PropagationContext context,
+                                     final InternalWorkingMemory workingMemory) {
+            final LeftTuple tuple = new LeftTuple( rightTuple, this.sink );
             this.sink.assertTuple( tuple,
                                    context,
                                    workingMemory );
@@ -285,18 +280,18 @@
         }
 
         public void retractRightTuple(final RightTuple rightTuple,
-                                  final PropagationContext context,
-                                  final InternalWorkingMemory workingMemory) {
+                                      final PropagationContext context,
+                                      final InternalWorkingMemory workingMemory) {
             throw new UnsupportedOperationException( "ObjectSinkAdapter onlys supports assertObject method calls" );
         }
-        
+
         public boolean isRightTupleMemoryEnabled() {
-            throw new UnsupportedOperationException("ObjectSinkAdapters have no Object memory");
+            throw new UnsupportedOperationException( "ObjectSinkAdapters have no Object memory" );
         }
 
         public void setRightTupleMemoryEnabled(boolean objectMemoryEnabled) {
-            throw new UnsupportedOperationException("ObjectSinkAdapters have no Object memory");
-        }        
+            throw new UnsupportedOperationException( "ObjectSinkAdapters have no Object memory" );
+        }
     }
 
 }

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/LeftTuple.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/LeftTuple.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/LeftTuple.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -20,129 +20,249 @@
 
     private final InternalFactHandle handle;
 
-    private LeftTuple                parent;       
+    private LeftTuple                parent;
 
     private Activation               activation;
 
     private long                     recency;
 
     private int                      hashCode;
-    
-    private RightTuple               match;
 
-    
+    private RightTuple               blocker;
+
+    private LeftTuple                blockedPrevious;
+
+    private LeftTuple                blockedNext;
+
     // left and right tuples in parent
-    private LeftTuple               leftParent;  
-    private LeftTuple               leftParentLeft;
-    private LeftTuple               leftParentright;
-    
-    private RightTuple              rightParent;    
-    private RightTuple              rightParentLeft;
-    private RightTuple              rightParentright;
-    
+    private LeftTuple                leftParent;
+    private LeftTuple                leftParentPrevious;
+    private LeftTuple                leftParentNext;
+
+    private RightTuple               rightParent;
+    private LeftTuple                rightParentPrevious;
+    private LeftTuple                rightParentNext;
+
     // node memory
-    private Entry                    next;    
+    private Entry                    next;
     private Entry                    previous;
-    
+
     // children
-    private LeftTuple                children;    
+    private LeftTuple                children;
 
+    private final LeftTupleSink      sink;
+
     // ------------------------------------------------------------
     // Constructors
     // ------------------------------------------------------------
-    public LeftTuple(final RightTuple rightTuple) {
+    public LeftTuple(final RightTuple rightTuple,
+                     LeftTupleSink sink) {
         this.handle = rightTuple.getHandle();
         this.recency = this.handle.getRecency();
+
         int h = handle.hashCode();
         h += ~(h << 9);
         h ^= (h >>> 14);
         h += (h << 4);
         h ^= (h >>> 10);
         this.hashCode = h;
+
+        this.rightParent = rightTuple;
+        this.rightParentNext = this.rightParent.getBetaChildren();
+        if ( this.rightParentNext != null ) {
+            this.rightParentNext.rightParentPrevious = this;
+        }
+        this.rightParent.setBetaChildren( this );
+        this.sink = sink;
     }
 
-    public LeftTuple(final LeftTuple tuple) {
-        this.index = tuple.index;
-        this.parent = tuple.parent;
-        this.recency = tuple.recency;
-        this.handle = tuple.handle;
-        this.hashCode = tuple.hashCode();
+    public LeftTuple(final LeftTuple leftTuple,
+                     LeftTupleSink sink) {
+        this.index = leftTuple.index;
+        this.parent = leftTuple.parent;
+        this.recency = leftTuple.recency;
+        this.handle = leftTuple.handle;
+        this.hashCode = leftTuple.hashCode();
+
+        this.leftParent = leftTuple;
+        this.leftParentNext = leftTuple.children;
+        if ( this.leftParentNext != null ) {
+            this.leftParentNext.leftParentPrevious = this;
+        }
+        this.leftParent.children = this;
+        this.sink = sink;
     }
 
-    public LeftTuple(final LeftTuple parentTuple,
-                     final RightTuple rightTuple) {
+    public LeftTuple(final LeftTuple leftTuple,
+                     final RightTuple rightTuple,
+                     LeftTupleSink sink) {
         this.handle = rightTuple.getHandle();
-        this.index = parentTuple.index + 1;
-        this.parent = parentTuple;
-        this.recency = parentTuple.recency + this.handle.getRecency();
-        this.hashCode = parentTuple.hashCode ^ (handle.hashCode() * 31);
-    }        
+        this.index = leftTuple.index + 1;
+        this.parent = leftTuple;
+        this.recency = leftTuple.recency + this.handle.getRecency();
+        this.hashCode = leftTuple.hashCode ^ (handle.hashCode() * 31);
 
+        this.rightParent = rightTuple;
+        this.rightParentNext = this.rightParent.getBetaChildren();
+        if ( this.rightParentNext != null ) {
+            this.rightParentNext.rightParentPrevious = this;
+        }
+        this.rightParent.setBetaChildren( this );
+
+        this.leftParent = leftTuple;
+        this.leftParentNext = leftTuple.children;
+        if ( this.leftParentNext != null ) {
+            this.leftParentNext.leftParentPrevious = this;
+        }
+        this.leftParent.children = this;
+        this.sink = sink;
+    }
+
+    public void unlinkFromParents() {
+        if ( this.rightParent != null ) {
+            if ( this.rightParentPrevious != null ) {
+                this.rightParentPrevious.rightParentNext = this.rightParentNext;
+            } else {
+                // first one in the chain, so treat differently
+                this.rightParent.setBetaChildren( this.rightParentNext );
+            }
+
+            if ( rightParentNext != null ) {
+                rightParentNext.rightParentPrevious = this.rightParentPrevious;
+            }
+        }
+
+        if ( this.leftParent != null ) {
+            if ( this.leftParentPrevious != null ) {
+                this.leftParentPrevious.leftParentNext = this.leftParentNext;
+            } else {
+                // first one in the chain, so treat differently                
+                this.leftParent.setBetaChildren( this.leftParentNext );
+            }
+
+            if ( leftParentNext != null ) {
+                leftParentNext.leftParentPrevious = this.leftParentPrevious;
+            }
+        }
+    }
+    
+    public void unlinkFromLeftParent() {
+        LeftTuple previous = (LeftTuple) this.leftParentPrevious;
+        LeftTuple next = (LeftTuple) this.leftParentNext;
+
+        if ( previous != null && next != null ) {
+            //remove  from middle
+            this.leftParentPrevious.leftParentNext = this.leftParentNext;
+            this.leftParentNext.leftParentPrevious = this.leftParentPrevious;
+        } else if ( next != null ) {
+            //remove from first
+            this.leftParent.children = this.leftParentNext;
+            this.leftParentNext.leftParentPrevious = null;
+        } else if ( previous != null ) {
+            //remove from end
+            this.leftParentPrevious.leftParentNext = null;
+        } else {
+            this.leftParent.children = null;
+        }        
+    }
+    
+    public void unlinkFromRightParent() {
+        LeftTuple previous = (LeftTuple) this.rightParentPrevious;
+        LeftTuple next = (LeftTuple) this.rightParentNext;
+
+        if ( previous != null && next != null ) {
+            //remove  from middle
+            this.rightParentPrevious.rightParentNext = this.rightParentNext;
+            this.rightParentNext.rightParentPrevious = this.rightParentPrevious;
+        } else if ( next != null ) {
+            //remove from first
+            this.rightParent.setBetaChildren( this.rightParentNext );
+            this.rightParentNext.rightParentPrevious = null;
+        } else if ( previous != null ) {
+            //remove from end
+            this.rightParentPrevious.rightParentNext = null;
+        } else if ( this.rightParent != null ){
+            this.rightParent.setBetaChildren( null );
+        }          
+    }
+
+    public LeftTupleSink getSink() {
+        return sink;
+    }
+
     public LeftTuple getLeftParent() {
-		return leftParent;
-	}
+        return leftParent;
+    }
 
-	public void setLeftParent(LeftTuple leftParent) {
-		this.leftParent = leftParent;
-	}
+    public void setLeftParent(LeftTuple leftParent) {
+        this.leftParent = leftParent;
+    }
 
-	public LeftTuple getLeftParentLeft() {
-		return leftParentLeft;
-	}
+    public LeftTuple getLeftParentPrevious() {
+        return leftParentPrevious;
+    }
 
-	public void setLeftParentLeft(LeftTuple leftParentLeft) {
-		this.leftParentLeft = leftParentLeft;
-	}
+    public void setLeftParentPrevious(LeftTuple leftParentLeft) {
+        this.leftParentPrevious = leftParentLeft;
+    }
 
-	public LeftTuple getLeftParentright() {
-		return leftParentright;
-	}
+    public LeftTuple getLeftParentNext() {
+        return leftParentNext;
+    }
 
-	public void setLeftParentright(LeftTuple leftParentright) {
-		this.leftParentright = leftParentright;
-	}
+    public void setLeftParentNext(LeftTuple leftParentright) {
+        this.leftParentNext = leftParentright;
+    }
 
-	public RightTuple getRightParent() {
-		return rightParent;
-	}
+    public RightTuple getRightParent() {
+        return rightParent;
+    }
 
-	public void setRightParent(RightTuple rightParent) {
-		this.rightParent = rightParent;
-	}
+    public void setRightParent(RightTuple rightParent) {
+        this.rightParent = rightParent;
+    }
 
-	public RightTuple getRightParentLeft() {
-		return rightParentLeft;
-	}
+    public LeftTuple getRightParentPrevious() {
+        return rightParentPrevious;
+    }
 
-	public void setRightParentLeft(RightTuple rightParentLeft) {
-		this.rightParentLeft = rightParentLeft;
-	}
+    public void setRightParentPrevious(LeftTuple rightParentLeft) {
+        this.rightParentPrevious = rightParentLeft;
+    }
 
-	public RightTuple getRightParentright() {
-		return rightParentright;
-	}
+    public LeftTuple getRightParentNext() {
+        return rightParentNext;
+    }
 
-	public void setRightParentright(RightTuple rightParentright) {
-		this.rightParentright = rightParentright;
-	}
+    public void setRightParentNext(LeftTuple rightParentRight) {
+        this.rightParentNext = rightParentRight;
+    }
 
-	public InternalFactHandle get(final int index) {
+    public void setBetaChildren(LeftTuple leftTuple) {
+        this.children = leftTuple;
+    }
+
+    public LeftTuple getBetaChildren() {
+        return this.children;
+    }
+
+    public InternalFactHandle get(final int index) {
         LeftTuple entry = this;
         while ( entry.index != index ) {
             entry = entry.parent;
         }
         return entry.handle;
-    }        
+    }
 
     public Entry getPrevious() {
-		return previous;
-	}
+        return previous;
+    }
 
-	public void setPrevious(Entry previous) {
-		this.previous = previous;
-	}
+    public void setPrevious(Entry previous) {
+        this.previous = previous;
+    }
 
-	public void setNext(final Entry next) {
+    public void setNext(final Entry next) {
         this.next = next;
     }
 
@@ -179,16 +299,31 @@
     public long getRecency() {
         return this.recency;
     }
-        
 
-    public RightTuple getMatch() {
-        return match;
+    public void setBlocker(RightTuple blocker) {
+        this.blocker = blocker;
     }
 
-    public void setMatch(RightTuple match) {
-        this.match = match;
+    public RightTuple getBlocker() {
+        return this.blocker;
     }
 
+    public LeftTuple getBlockedPrevious() {
+        return this.blockedPrevious;
+    }
+
+    public void setBlockedPrevious(LeftTuple blockerPrevious) {
+        this.blockedPrevious = blockerPrevious;
+    }
+
+    public LeftTuple getBlockedNext() {
+        return this.blockedNext;
+    }
+
+    public void setBlockedNext(LeftTuple blockerNext) {
+        this.blockedNext = blockerNext;
+    }
+
     public void setActivation(final Activation activation) {
         this.activation = activation;
     }
@@ -271,18 +406,18 @@
         }
         return entry;
     }
-    
-    public Object[] toObjectArray() {        
-        Object[] objects = new Object[ this.index + 1 ];
-        LeftTuple entry = this;       
+
+    public Object[] toObjectArray() {
+        Object[] objects = new Object[this.index + 1];
+        LeftTuple entry = this;
         while ( entry != null ) {
             Object object = entry.getLastHandle().getObject();
             if ( object instanceof ShadowProxy ) {
-                object = ((ShadowProxy)object).getShadowedObject();
+                object = ((ShadowProxy) object).getShadowedObject();
             }
             objects[entry.index] = object;
             entry = entry.parent;
-        }   
+        }
         return objects;
     }
 }

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/LeftTupleMemory.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/LeftTupleMemory.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/LeftTupleMemory.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -6,12 +6,12 @@
 
 public interface LeftTupleMemory {
     public Iterator iterator();
+    
+    public LeftTuple getFirst(RightTuple rightTuple);
 
-    public Iterator iterator(RightTuple rightTuple);
-
     public void add(LeftTuple tuple);
 
-    public LeftTuple remove(LeftTuple tuple);
+    public void remove(LeftTuple tuple);
 
     public boolean contains(LeftTuple tuple);
 
@@ -19,8 +19,8 @@
 
     public int size();
 
-    public Entry[] getTable();
-    
-    public Entry[] toArray();
+//    public Entry[] getTable();
+//    
+    public LeftTuple[] toArray();
 
 }

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/LeftTupleSinkPropagator.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/LeftTupleSinkPropagator.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/LeftTupleSinkPropagator.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -17,14 +17,13 @@
                                      PropagationContext context,
                                      InternalWorkingMemory workingMemory);
 
-    public void propagateRetractTuple(LeftTuple leftTuple,
-                                      RightTuple rightTuple,
-                                      PropagationContext context,
-                                      InternalWorkingMemory workingMemory);
+    public void propagateRetractLeftTuple(LeftTuple tuple,
+                                          PropagationContext context,
+                                          InternalWorkingMemory workingMemory);
 
-    public void propagateRetractTuple(LeftTuple tuple,
-                                      PropagationContext context,
-                                      InternalWorkingMemory workingMemory);
+    public void propagateRetractRightTuple(RightTuple tuple,
+                                           PropagationContext context,
+                                           InternalWorkingMemory workingMemory);
 
     public void createAndPropagateAssertTuple(RightTuple rightTuple,
                                               PropagationContext context,

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/LeftTupleSource.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/LeftTupleSource.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/LeftTupleSource.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -75,12 +75,12 @@
         if ( this.sink == EmptyLeftTupleSinkAdapter.getInstance() ) {
             this.sink = new SingleLeftTupleSinkAdapter( tupleSink );
         } else if ( this.sink instanceof SingleLeftTupleSinkAdapter ) {
-            final CompositeTupleSinkAdapter sinkAdapter = new CompositeTupleSinkAdapter();
+            final CompositeLeftTupleSinkAdapter sinkAdapter = new CompositeLeftTupleSinkAdapter();
             sinkAdapter.addTupleSink( this.sink.getSinks()[0] );
             sinkAdapter.addTupleSink( tupleSink );
             this.sink = sinkAdapter;
         } else {
-            ((CompositeTupleSinkAdapter) this.sink).addTupleSink( tupleSink );
+            ((CompositeLeftTupleSinkAdapter) this.sink).addTupleSink( tupleSink );
         }
     }
 
@@ -98,7 +98,7 @@
         if ( this.sink instanceof SingleLeftTupleSinkAdapter ) {
             this.sink = EmptyLeftTupleSinkAdapter.getInstance();
         } else {
-            final CompositeTupleSinkAdapter sinkAdapter = (CompositeTupleSinkAdapter) this.sink;
+            final CompositeLeftTupleSinkAdapter sinkAdapter = (CompositeLeftTupleSinkAdapter) this.sink;
             sinkAdapter.removeTupleSink( tupleSink );
             if ( sinkAdapter.size() == 1 ) {
                 this.sink = new SingleLeftTupleSinkAdapter( sinkAdapter.getSinks()[0] );

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/NotNode.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/NotNode.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/NotNode.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -68,7 +68,7 @@
                leftInput,
                rightInput,
                joinNodeBinder );
-        this.tupleMemoryEnabled = context.isTupleMemoryEnabled();        
+        this.tupleMemoryEnabled = context.isTupleMemoryEnabled();
     }
 
     /**
@@ -87,23 +87,32 @@
                             final PropagationContext context,
                             final InternalWorkingMemory workingMemory) {
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
-        
-        if ( this.tupleMemoryEnabled ) {
-            memory.getLeftTupleMemory().add( leftTuple );
-        }
 
-        final Iterator it = memory.getRightTupleMemory().iterator( leftTuple );
         this.constraints.updateFromTuple( workingMemory,
                                           leftTuple );
-        
-        for ( RightTuple rightTuple = (RightTuple) it.next(); rightTuple != null; rightTuple = (RightTuple) it.next() ) {
+
+        for ( RightTuple rightTuple = memory.getRightTupleMemory().getLast( leftTuple ); rightTuple != null; rightTuple = (RightTuple) rightTuple.getPrevious() ) {
             if ( this.constraints.isAllowedCachedLeft( rightTuple.getHandle() ) ) {
-                leftTuple.setMatch( rightTuple );
+
+                leftTuple.setBlocker( rightTuple );
+
+                LeftTuple blockedPrevious = rightTuple.getBlocked();
+                if ( blockedPrevious != null ) {
+                    leftTuple.setBlockedNext( blockedPrevious );
+                    blockedPrevious.setBlockedPrevious( leftTuple );
+                }
+                rightTuple.setBlocked( leftTuple );
+
                 break;
             }
         }
 
-        if ( leftTuple.getMatch() == null ) {
+        if ( leftTuple.getBlocker() == null ) {
+            // only add it to node memory if still need Objects to attempt to match
+            if ( this.tupleMemoryEnabled ) {
+                memory.getLeftTupleMemory().add( leftTuple );
+            }
+
             this.sink.propagateAssertTuple( leftTuple,
                                             context,
                                             workingMemory );
@@ -123,25 +132,41 @@
      *            The working memory seesion.
      */
     public void assertRightTuple(final RightTuple rightTuple,
-                             final PropagationContext context,
-                             final InternalWorkingMemory workingMemory) {
+                                 final PropagationContext context,
+                                 final InternalWorkingMemory workingMemory) {
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
         memory.getRightTupleMemory().add( rightTuple );
-        
+
         if ( !this.tupleMemoryEnabled ) {
             // do nothing here, as we know there are no left tuples at this stage in sequential mode.
             return;
-        }        
+        }
 
-        final Iterator it = memory.getLeftTupleMemory().iterator( rightTuple );
         this.constraints.updateFromRightTuple( workingMemory,
                                                rightTuple );
-        for ( LeftTuple tuple = (LeftTuple) it.next(); tuple != null; tuple = (LeftTuple) it.next() ) {
-            if ( this.constraints.isAllowedCachedRight( tuple ) &&  tuple.getMatch() == null) {
-                    tuple.setMatch( rightTuple );
-                    this.sink.propagateRetractTuple( tuple,
-                                                     context,
-                                                     workingMemory );                    
+
+        for ( LeftTuple leftTuple = memory.getLeftTupleMemory().getFirst( rightTuple ); leftTuple != null; leftTuple = (LeftTuple) leftTuple.getNext() ) {
+            // we know that only unblocked LeftTuples are  still in the memory
+            if ( this.constraints.isAllowedCachedRight( leftTuple ) ) {
+                leftTuple.setBlocker( rightTuple );
+                leftTuple.setBlocker( rightTuple );
+
+                LeftTuple blockedPrevious = rightTuple.getBlocked();
+                if ( blockedPrevious != null ) {
+                    leftTuple.setBlockedNext( blockedPrevious );
+                    blockedPrevious.setBlockedPrevious( leftTuple );
+                }
+                rightTuple.setBlocked( leftTuple );
+
+                LeftTuple temp = (LeftTuple) leftTuple.getPrevious();
+                // this is now blocked so remove from memory
+                memory.getLeftTupleMemory().remove( leftTuple );
+
+                if ( leftTuple.getBetaChildren() != null ) {
+                    this.sink.propagateRetractLeftTuple( leftTuple,
+                                                         context,
+                                                         workingMemory );
+                }
             }
         }
     }
@@ -160,42 +185,54 @@
      * @throws AssertionException
      */
     public void retractRightTuple(final RightTuple rightTuple,
-                              final PropagationContext context,
-                              final InternalWorkingMemory workingMemory) {
+                                  final PropagationContext context,
+                                  final InternalWorkingMemory workingMemory) {
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
-        if ( !memory.getRightTupleMemory().remove( rightTuple ) ) {
+
+               
+        if ( rightTuple.getBlocked() == null ) {
+            memory.getRightTupleMemory().remove( rightTuple );
             return;
         }
+        
+        // assign now, so we can remove from memory before doing any possible propagations
+        final RightTuple rootBlocker = (RightTuple) rightTuple.getPrevious();        
 
-        final Iterator it = memory.getLeftTupleMemory().iterator( rightTuple );
-        this.constraints.updateFromRightTuple( workingMemory,
-                                               rightTuple );
-        for ( LeftTuple tuple = (LeftTuple) it.next(); tuple != null; tuple = (LeftTuple) it.next() ) {
-            if ( this.constraints.isAllowedCachedRight( tuple ) ) {
-                
-                if ( tuple.getMatch() == rightTuple ) {
-                    // reset the match                    
-                    tuple.setMatch( null );
-                    
-                    // find next match, remember it and break.
-                    final Iterator tupleIt = memory.getRightTupleMemory().iterator( tuple );
-                    this.constraints.updateFromTuple( workingMemory, tuple );
-                    
-                    for ( RightTuple nextRightTuple = (RightTuple) tupleIt.next(); nextRightTuple != null; nextRightTuple = (RightTuple) tupleIt.next() ) {
-                        if ( this.constraints.isAllowedCachedLeft( nextRightTuple.getHandle() ) ) {
-                            tuple.setMatch( nextRightTuple );
-                            break;
-                        }
+        for ( LeftTuple leftTuple = (LeftTuple) rightTuple.getBlocked(); leftTuple != null; leftTuple = (LeftTuple) leftTuple.getBlockedNext() ) {
+            leftTuple.setBlocker( null );
+            LeftTuple previousBlocked = leftTuple.getBlockedPrevious();
+            if ( previousBlocked != null ) {
+                previousBlocked.setBlockedNext( null );
+            }
+            leftTuple.setBlockedPrevious ( null );
+            
+            this.constraints.updateFromTuple( workingMemory,
+                                              leftTuple );
+
+            // we know that older tuples have been checked so continue previously
+            for ( RightTuple newBlocker = rootBlocker; newBlocker != null; newBlocker = (RightTuple) newBlocker.getPrevious() ) {
+                if ( this.constraints.isAllowedCachedLeft( newBlocker.getHandle() ) ) {
+                    leftTuple.setBlocker( newBlocker );
+
+                    LeftTuple blockedPrevious = newBlocker.getBlocked();
+                    if ( blockedPrevious != null ) {
+                        leftTuple.setBlockedNext( blockedPrevious );
+                        blockedPrevious.setBlockedPrevious( leftTuple );
                     }
-                    
-                    // if there is now no new tuple match then propagate assert.
-                    if ( tuple.getMatch() == null ) {
-                        this.sink.propagateAssertTuple( tuple,
-                                                        context,
-                                                        workingMemory );
-                    }                    
+                    newBlocker.setBlocked( leftTuple );
+
+                    break;
                 }
             }
+            
+            if ( leftTuple.getBlocker() == null ) {
+                // was previous blocked and not in memory, so add
+                memory.getLeftTupleMemory().add( leftTuple );
+
+                this.sink.propagateAssertTuple( leftTuple,
+                                                context,
+                                                workingMemory );
+            }            
         }
     }
 
@@ -213,19 +250,32 @@
     public void retractTuple(final LeftTuple leftTuple,
                              final PropagationContext context,
                              final InternalWorkingMemory workingMemory) {
-        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
-
-        // Must use the tuple in memory as it has the tuple matches count
-        final LeftTuple tuple = memory.getLeftTupleMemory().remove( leftTuple );
-        if ( tuple == null ) {
-            return;
+        RightTuple blocker = leftTuple.getBlocker();
+        if ( blocker == null ) {
+            final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+            memory.getLeftTupleMemory().remove( leftTuple );            
+            
+            this.sink.propagateRetractLeftTuple( leftTuple,
+                                                 context,
+                                                 workingMemory );
+        } else {
+            LeftTuple previous = (LeftTuple) leftTuple.getBlockedPrevious();
+            LeftTuple next = (LeftTuple) leftTuple.getBlockedNext();
+            if ( previous != null && next != null ) {
+                //remove  from middle
+                previous.setNext( next );
+                next.setPrevious( previous );
+            } else if ( next != null ) {
+                //remove from first
+                leftTuple.getBlocker().setBlocked( next );
+                next.setPrevious( null );
+            } else if ( previous != null ) {
+                //remove from end
+                previous.setNext( null );
+            } else {
+                leftTuple.getBlocker().setBlocked( null );
+            }
         }
-
-        if ( tuple.getMatch() ==  null) {
-            this.sink.propagateRetractTuple( tuple,
-                                             context,
-                                             workingMemory );
-        }
     }
 
     /* (non-Javadoc)
@@ -237,13 +287,13 @@
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
 
         final Iterator tupleIter = memory.getLeftTupleMemory().iterator();
-        for ( LeftTuple tuple = (LeftTuple) tupleIter.next(); tuple != null; tuple = (LeftTuple) tupleIter.next() ) {
-            if ( tuple.getMatch() == null ) {
-                sink.assertTuple( new LeftTuple( tuple ),
-                                  context,
-                                  workingMemory );
-            }
-        }
+        //        for ( LeftTuple tuple = (LeftTuple) tupleIter.next(); tuple != null; tuple = (LeftTuple) tupleIter.next() ) {
+        //            if ( tuple.getBlockers() == null ) {
+        //                sink.assertTuple( new LeftTuple( tuple ),
+        //                                  context,
+        //                                  workingMemory );
+        //            }
+        //        }
     }
 
     public String toString() {

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/ObjectTypeNode.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/ObjectTypeNode.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/ObjectTypeNode.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -148,8 +148,7 @@
 
         if ( this.objectMemoryEnabled ) {
             final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( this );
-            memory.add( rightTuple,
-                        false );
+            memory.add( rightTuple );
         }
 
         this.sink.propagateAssertRightTuple( rightTuple,
@@ -176,22 +175,27 @@
             return;
         }
 
-        final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( this );
-        memory.remove( rightTuple );
+        if ( this.objectMemoryEnabled ) {
+            final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( this );
+            memory.remove( rightTuple );
+        }
+         
+        
+        if ( rightTuple.getAlphaChildren() != null ) {
+            this.sink.propagateRetractRightTuple( rightTuple,
+                                                  context,
+                                                  workingMemory,
+                                                  true );
+        }
 
-        this.sink.propagateRetractRightTuple( rightTuple,
-                                              context,
-                                              workingMemory,
-                                              true );
     }
 
     public void updateSink(final RightTupleSink sink,
                            final PropagationContext context,
                            final InternalWorkingMemory workingMemory) {
         final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( this );
-        final Iterator it = memory.iterator();
-        for ( RightTuple entry = (RightTuple) it.next(); entry != null; entry = (RightTuple) it.next() ) {
-            sink.assertRightTuple( entry,
+        for ( RightTuple rightTuple = (RightTuple) memory.getFirst( null ); rightTuple != null; rightTuple = (RightTuple) rightTuple.getNext() ) {
+            sink.assertRightTuple( rightTuple,
                                    context,
                                    workingMemory );
         }

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/Rete.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/Rete.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/Rete.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -25,6 +25,7 @@
 import org.drools.base.ShadowProxy;
 import org.drools.common.BaseNode;
 import org.drools.common.DroolsObjectInputStream;
+import org.drools.common.InternalFactHandle;
 import org.drools.common.InternalRuleBase;
 import org.drools.common.InternalWorkingMemory;
 import org.drools.common.NodeMemory;
@@ -94,6 +95,12 @@
     // Instance methods
     // ------------------------------------------------------------
 
+    
+    public void assertRightTuple(final RightTuple rightTuple,
+                                 final PropagationContext context,
+                                 final InternalWorkingMemory workingMemory) {
+        // do nothing
+    }
     /**
      * This is the entry point into the network for all asserted Facts. Iterates a cache
      * of matching <code>ObjectTypdeNode</code>s asserting the Fact. If the cache does not
@@ -106,10 +113,10 @@
      * @param workingMemory
      *            The working memory session.
      */
-    public void assertRightTuple(final RightTuple rightTuple,
+    public void assertRightTuple(final InternalFactHandle factHandle,
                                  final PropagationContext context,
                                  final InternalWorkingMemory workingMemory) {
-        Object object = rightTuple.getHandle().getObject();
+        Object object = factHandle.getObject();
 
         ObjectTypeConf objectTypeConf = workingMemory.getObjectTypeConf( context.getEntryPoint(),
                                                                          object );
@@ -117,10 +124,10 @@
         // checks if shadow is enabled
         if ( objectTypeConf.isShadowEnabled() ) {
             // need to improve this
-            if ( !(rightTuple.getHandle().getObject() instanceof ShadowProxy) ) {
+            if ( !(factHandle.getObject() instanceof ShadowProxy) ) {
                 // replaces the actual object by its shadow before propagating
-                rightTuple.getHandle().setObject( objectTypeConf.getShadow( object ) );
-                rightTuple.getHandle().setShadowFact( true );
+                factHandle.setObject( objectTypeConf.getShadow( object ) );
+                factHandle.setShadowFact( true );
             } else {
                 ((ShadowProxy) object).updateProxy();
             }
@@ -128,11 +135,22 @@
 
         ObjectTypeNode[] cachedNodes = objectTypeConf.getObjectTypeNodes();
 
+        RightTuple rightTuple = null;
         for ( int i = 0, length = cachedNodes.length; i < length; i++ ) {
+            rightTuple =  new RightTuple( factHandle,
+                                          cachedNodes[i] );
             cachedNodes[i].assertRightTuple( rightTuple,
                                              context,
                                              workingMemory );
+            if ( i < length-1 ) {
+                RightTuple temp = new RightTuple( factHandle );
+                temp.setParentNext( rightTuple );
+                rightTuple.setParentPrevious( temp );
+                                
+                rightTuple = temp;
+            }
         }
+        factHandle.setRightTuple( rightTuple );
     }
 
     /**
@@ -144,25 +162,12 @@
      * @param workingMemory
      *            The working memory session.
      */
-    public void retractRightTuple(final RightTuple rightTuple,
+    public void retractRightTuple(RightTuple rightTuple,
                                   final PropagationContext context,
                                   final InternalWorkingMemory workingMemory) {
-        final Object object = rightTuple.getHandle().getObject();
-
-        ObjectTypeConf objectTypeConf = workingMemory.getObjectTypeConf( context.getEntryPoint(),
-                                                                         object );
-        ObjectTypeNode[] cachedNodes = objectTypeConf.getObjectTypeNodes();
-
-        if ( cachedNodes == null ) {
-            // it is  possible that there are no ObjectTypeNodes for an  object being retracted
-            return;
+        for ( ; rightTuple != null; rightTuple = ( RightTuple ) rightTuple.getParentNext() ) {
+            rightTuple.getRightTupleSink().retractRightTuple( rightTuple, context, workingMemory );
         }
-
-        for ( int i = 0; i < cachedNodes.length; i++ ) {
-            cachedNodes[i].retractRightTuple( rightTuple,
-                                              context,
-                                              workingMemory );
-        }
     }
 
     /**
@@ -259,9 +264,8 @@
                 objectTypeConf.resetCache();
                 ObjectTypeNode sourceNode = objectTypeConf.getConcreteObjectTypeNode();
                 FactHashTable table = (FactHashTable) workingMemory.getNodeMemory( sourceNode );
-                Iterator factIter = table.iterator();
-                for ( RightTuple factEntry = (RightTuple) factIter.next(); factEntry != null; factEntry = (RightTuple) factIter.next() ) {
-                    sink.assertRightTuple( factEntry,
+                for ( RightTuple rightTuple = (RightTuple) table.getFirst( null ); rightTuple != null; rightTuple = (RightTuple) rightTuple.getNext() ) {
+                    sink.assertRightTuple( new RightTuple( rightTuple, sink ),
                                            context,
                                            workingMemory );
                 }

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/ReteooRuleBase.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/ReteooRuleBase.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/ReteooRuleBase.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -196,7 +196,7 @@
                              final Object object,
                              final PropagationContext context,
                              final InternalWorkingMemory workingMemory) throws FactException {
-        getRete().assertRightTuple( new RightTuple( (InternalFactHandle) handle ),
+        getRete().assertRightTuple( (InternalFactHandle) handle,
                                     context,
                                     workingMemory );
     }
@@ -215,9 +215,11 @@
     public void retractObject(final FactHandle handle,
                               final PropagationContext context,
                               final ReteooWorkingMemory workingMemory) throws FactException {
-        getRete().retractRightTuple( new RightTuple( (InternalFactHandle) handle ),
+        getRete().retractRightTuple( ((InternalFactHandle)handle).getRightTuple(),
                                      context,
                                      workingMemory );
+        
+        ((InternalFactHandle)handle).setRightTuple( null );
     }
 
     public synchronized StatefulSession newStatefulSession(final boolean keepReference) {

Added: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/RightTuple.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/RightTuple.java	                        (rev 0)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/RightTuple.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -0,0 +1,187 @@
+package org.drools.reteoo;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.util.Entry;
+
+public class RightTuple
+    implements
+    Entry {
+    private final InternalFactHandle handle;
+
+    private final RightTuple         parent;
+    private RightTuple               parentPrevious;
+    private RightTuple               parentNext;
+
+    private Entry                    previous;
+    private Entry                    next;
+
+    private RightTuple               alphaChildren;
+    private LeftTuple                betaChildren;
+
+    private LeftTuple                blocked;
+
+    private RightTupleSink           sink;
+
+    private int                      hashCode;
+
+    public RightTuple(InternalFactHandle handle) {
+        this.handle = handle;
+        this.hashCode = this.handle.hashCode();
+        this.parent = null;
+    }
+    
+    public RightTuple(InternalFactHandle handle,
+                      RightTupleSink sink) {
+        this.handle = handle;
+        this.hashCode = this.handle.hashCode();
+        this.parent = null;
+        this.sink = sink;
+    }    
+
+    public RightTuple(RightTuple parent) {
+        this.handle = parent.getHandle();
+        this.hashCode = this.handle.hashCode();
+        this.parent = parent;
+
+        this.parentNext = parent.getAlphaChildren();
+        if  (parentNext != null ) {
+            this.parentNext.parentPrevious = this;
+        }
+        parent.setAlphaChildren( this );
+    }
+
+    public RightTuple(RightTuple parent,
+                      RightTupleSink sink) {
+        this.handle = parent.getHandle();
+        this.hashCode = this.handle.hashCode();
+        this.parent = parent;
+
+        this.parentNext = parent.getAlphaChildren();
+        if  (parentNext != null ) {
+            this.parentNext.parentPrevious = this;
+        }
+        parent.setAlphaChildren( this );
+        
+        this.sink = sink;
+
+
+    }
+
+    public RightTupleSink getRightTupleSink() {
+        return this.sink;
+    }
+
+    public void unlinkFromRightParent() {
+        if ( this.parent != null ) {            
+            if ( this.parentPrevious != null ) {
+                this.parentPrevious.parentNext = this.parentNext;                
+            } else {
+                // first one in the chain, so treat differently                
+                this.parent.setAlphaChildren( this.parentNext );                
+            }
+            
+            if (  this.parentNext != null ) {
+                this.parentNext.parentPrevious = this.parentPrevious;
+            }
+        }
+    }
+
+    public InternalFactHandle getHandle() {
+        return this.handle;
+    }
+
+    public RightTuple getParent() {
+        return parent;
+    }
+
+    public RightTuple getParentPrevious() {
+        return parentPrevious;
+    }
+
+    public void setParentPrevious(RightTuple parentPrevious) {
+        this.parentPrevious = parentPrevious;
+    }       
+
+    public RightTuple getParentNext() {
+        return parentNext;
+    }
+    
+    public void setParentNext(RightTuple parentNext) {
+        this.parentNext = parentNext;
+    }    
+
+    public LeftTuple getBlocked() {
+        return blocked;
+    }
+
+    public void setBlocked(LeftTuple blocked) {
+        this.blocked = blocked;
+    }
+
+    public Entry getPrevious() {
+        return previous;
+    }
+
+    public void setPrevious(Entry previous) {
+        this.previous = previous;
+    }
+
+    public Entry getNext() {
+        return next;
+    }
+
+    public void setNext(Entry next) {
+        this.next = next;
+    }
+
+    public RightTuple getAlphaChildren() {
+        return alphaChildren;
+    }
+
+    public void setAlphaChildren(RightTuple alphaChildren) {
+        this.alphaChildren = alphaChildren;
+    }
+
+    public LeftTuple getBetaChildren() {
+        return betaChildren;
+    }
+
+    public void setBetaChildren(LeftTuple betachildren) {
+        this.betaChildren = betachildren;
+    }
+
+    public int getHashCode() {
+        return hashCode;
+    }
+
+    public void setHashCode(int hashCode) {
+        this.hashCode = hashCode;
+    }
+
+    public int hashCode() {
+        return this.hashCode;
+    }
+    
+    public String toString() {
+        return this.handle.toString() + "\n";
+    }    
+
+    public boolean equals(RightTuple other) {
+        // we know the object is never null and always of the  type ReteTuple
+        if ( other == this ) {
+            return true;
+        }
+
+        // A ReteTuple is  only the same if it has the same hashCode, factId and parent
+        if ( (other == null) || (this.hashCode != other.hashCode) ) {
+            return false;
+        }
+
+        return this.handle == other.handle;
+    }
+
+    public boolean equals(Object object) {
+        return equals( (RightTuple) object );
+    }
+
+}

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/RightTupleMemory.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/RightTupleMemory.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/RightTupleMemory.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -5,17 +5,18 @@
 import org.drools.util.Iterator;
 
 public interface RightTupleMemory {
-    public Iterator iterator();
+//    public Iterator iterator();
+//
+//    public Iterator iterator(LeftTuple leftTuple);
+    
+    public RightTuple getFirst(LeftTuple leftTuple);
+    
+    public RightTuple getLast(LeftTuple leftTuple);
 
-    public Iterator iterator(LeftTuple leftTuple);
+    public void add(RightTuple rightTuple);
 
-    public boolean add(RightTuple rightTuple,
-                       boolean checkExists);
+    public void remove(RightTuple rightTuple);
 
-    public boolean add(RightTuple rightTuple);
-
-    public boolean remove(RightTuple rightTuple);
-
     public boolean contains(RightTuple rightTuple);
 
     public boolean isIndexed();

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/RuleTerminalNode.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/RuleTerminalNode.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/RuleTerminalNode.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -171,7 +171,7 @@
         }
 
         //we only have to clone the head fact to make sure the graph is not affected during consequence reads after a modify
-        final LeftTuple cloned = new LeftTuple( tuple );
+        final LeftTuple cloned = tuple;///new LeftTuple( tuple, this );
 
         final InternalAgenda agenda = (InternalAgenda) workingMemory.getAgenda();
 
@@ -358,14 +358,9 @@
                              final PropagationContext context,
                              final InternalWorkingMemory workingMemory) {
         final TerminalNodeMemory memory = (TerminalNodeMemory) workingMemory.getNodeMemory( this );
-        final LeftTuple tuple = memory.getTupleMemory().remove( leftTuple );
-        if ( tuple == null ) {
-            // tuple should only be null if it was asserted and reached a no-loop causing it to exit early
-            // before being added to the node memory and an activation created and attached
-            return;
-        }
+        memory.getTupleMemory().remove( leftTuple );
 
-        final Activation activation = tuple.getActivation();
+        final Activation activation = leftTuple.getActivation();
         if ( activation.getLogicalDependencies() != null && !activation.getLogicalDependencies().isEmpty() ) {
             context.addRetractedTuple( this.rule,
                                        activation );

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/SingleLeftTupleSinkAdapter.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/SingleLeftTupleSinkAdapter.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/SingleLeftTupleSinkAdapter.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -17,7 +17,8 @@
                                      final PropagationContext context,
                                      final InternalWorkingMemory workingMemory) {
         this.sink.assertTuple( new LeftTuple( leftTuple,
-                                              rightTuple ),
+                                              rightTuple,
+                                              this.sink ),
                                context,
                                workingMemory );
     }
@@ -25,33 +26,51 @@
     public void propagateAssertTuple(final LeftTuple tuple,
                                      final PropagationContext context,
                                      final InternalWorkingMemory workingMemory) {
-        this.sink.assertTuple( new LeftTuple( tuple ),
+        this.sink.assertTuple( new LeftTuple( tuple,
+                                              this.sink ),
                                context,
                                workingMemory );
     }
 
-    public void propagateRetractTuple(final LeftTuple leftTuple,
-                                      final RightTuple rightTuple,
+    public void propagateRetractLeftTuple(final LeftTuple leftTuple,
                                       final PropagationContext context,
                                       final InternalWorkingMemory workingMemory) {
-        this.sink.retractTuple( new LeftTuple( leftTuple,
-                                               rightTuple ),
-                                context,
-                                workingMemory );
+        LeftTuple child = leftTuple.getBetaChildren();
+        while ( child != null ) {
+            //LeftTuple temp = leftTuple.getRightParentNext();
+            //child.unlinkFromParents();
+            child.unlinkFromRightParent();
+            child.getSink().retractTuple( child,
+                                          context,
+                                          workingMemory );
+            child = child.getRightParentNext();
+            //child = temp;
+        }
+        leftTuple.setBetaChildren( null );
     }
-
-    public void propagateRetractTuple(final LeftTuple tuple,
+    
+    public void propagateRetractRightTuple(final RightTuple rightTuple,
                                       final PropagationContext context,
                                       final InternalWorkingMemory workingMemory) {
-        this.sink.retractTuple( new LeftTuple( tuple ),
-                                context,
-                                workingMemory );
-    }
+        LeftTuple child = rightTuple.getBetaChildren();
+        while ( child != null ) {
+            //LeftTuple temp = child.getRightParentNext();
+            //child.unlinkFromParents();
+            child.unlinkFromLeftParent();
+            child.getSink().retractTuple( child,
+                                          context,
+                                          workingMemory );
+            child = child.getRightParentNext();
+            //child = temp;
+        }
+        rightTuple.setBetaChildren( null );
+    }    
 
     public void createAndPropagateAssertTuple(final RightTuple rightTuple,
                                               final PropagationContext context,
                                               final InternalWorkingMemory workingMemory) {
-        this.sink.assertTuple( new LeftTuple( rightTuple ),
+        this.sink.assertTuple( new LeftTuple( rightTuple,
+                                              this.sink ),
                                context,
                                workingMemory );
     }
@@ -59,9 +78,15 @@
     public void createAndPropagateRetractTuple(final RightTuple rightTuple,
                                                final PropagationContext context,
                                                final InternalWorkingMemory workingMemory) {
-        this.sink.retractTuple( new LeftTuple( rightTuple ),
-                                context,
-                                workingMemory );
+        LeftTuple child = rightTuple.getBetaChildren();
+        while ( child != null ) {
+            //LeftTuple temp = child.getRightParentNext();
+            //child.unlinkFromParents();
+            child.getSink().retractTuple( child, context, workingMemory );
+            child = child.getRightParentNext();
+            //child = temp;
+        }
+        rightTuple.setBetaChildren( null );
     }
 
     public LeftTupleSink[] getSinks() {

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/SingleRightTupletSinkAdapter.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/SingleRightTupletSinkAdapter.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/reteoo/SingleRightTupletSinkAdapter.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -28,10 +28,11 @@
                                            final PropagationContext context,
                                            final InternalWorkingMemory workingMemory,
                                            final boolean useHash) {
-        this.sink.retractRightTuple( new RightTuple( rightTuple ),
+        //rightTuple.unlinkFromRightParent();
+        this.sink.retractRightTuple( rightTuple.getAlphaChildren(),
                                      context,
-                                     workingMemory );
-
+                                     workingMemory );              
+        rightTuple.setAlphaChildren( null );        
     }
 
     public RightTupleSink[] getSinks() {

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/AbstractHashTable.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/AbstractHashTable.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/AbstractHashTable.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -246,24 +246,41 @@
         /* (non-Javadoc)
          * @see org.drools.util.Iterator#next()
          */
-        public Object next() {
-            if ( this.entry == null ) {
-                // keep skipping rows until we come to the end, or find one that is populated
-                while ( this.entry == null ) {
-                    this.row++;
-                    if ( this.row == this.length ) {
-                        return null;
-                    }
-                    this.entry = this.table[this.row];
+        public Object next() {            
+            if ( this.entry != null  ) {
+                this.entry = this.entry.getNext();
+            }
+            
+            // if no entry keep skipping rows until we come to the end, or find one that is populated
+            while ( this.entry == null ) {
+                this.row++;
+                if ( this.row == this.length ) {
+                    return null;
                 }
+                this.entry = this.table[this.row];
+            }            
+            
+            return this.entry;
+        }  
+        
+        /**
+         * Removes the current node
+         */
+        public void remove() {
+            Entry previous = this.entry.getPrevious();
+            Entry next = this.entry.getNext();
+            
+            if ( previous != null ) {
+                previous.setNext( next );
             } else {
-                this.entry = this.entry.getNext();
-                if ( this.entry == null ) {
-                    this.entry = (Entry) next();
-                }
+                this.table[this.row] = next;
             }
-
-            return this.entry;
+                        
+            if ( next != null ) {                    
+                next.setPrevious( previous );
+            }             
+            
+            this.entry = previous;
         }
 
         /* (non-Javadoc)

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/FactHandleIndexHashTable.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/FactHandleIndexHashTable.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/FactHandleIndexHashTable.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -7,7 +7,6 @@
 import org.drools.reteoo.RightTuple;
 import org.drools.reteoo.RightTupleMemory;
 import org.drools.reteoo.LeftTuple;
-import org.drools.util.TupleIndexHashTable.FieldIndexEntry;
 
 public class FactHandleIndexHashTable extends AbstractHashTable
     implements
@@ -61,24 +60,29 @@
                 throw new IllegalArgumentException( "FieldIndexHashTable cannot use an index[] of length  great than 3" );
         }
     }
-
-    public Iterator iterator() {
-        throw new UnsupportedOperationException( "FieldIndexHashTable does not support  iterator()" );
-    }
-
-    public Iterator iterator(final LeftTuple tuple) {
-        if ( this.tupleValueIterator == null ) {
-            this.tupleValueIterator = new FieldIndexHashTableIterator();
+    
+    public RightTuple getFirst(LeftTuple leftTuple) {
+        FactHashTable bucket = get( leftTuple );
+        if ( bucket != null ) {
+            return bucket.first;
+        } else {
+            return null;
         }
-        final FieldIndexEntry entry = get( tuple );
-        this.tupleValueIterator.reset( (entry != null) ? entry.first : null );
-        return this.tupleValueIterator;
     }
+    
+    public RightTuple getLast(LeftTuple leftTuple) {
+        FactHashTable bucket = get( leftTuple );
+        if ( bucket != null ) {
+            return bucket.last;
+        } else {
+            return null;
+        }        
+    }
 
     public boolean isIndexed() {
         return true;
     }
-    
+
     public Index getIndex() {
         return this.index;
     }
@@ -112,6 +116,10 @@
             this.entry = (this.entry != null) ? this.entry.getNext() : null;
             return current;
         }
+        
+        public void remove()  {
+            
+        }
 
         /* (non-Javadoc)
          * @see org.drools.util.Iterator#reset()
@@ -120,37 +128,43 @@
             this.entry = entry;
         }
     }
-    
+
     public Entry[] toArray() {
         Entry[] result = new Entry[this.factSize];
         int index = 0;
         for ( int i = 0; i < this.table.length; i++ ) {
-            FieldIndexEntry fieldIndexEntry = (FieldIndexEntry)this.table[i];
-            while ( fieldIndexEntry != null ) {
-                Entry entry = fieldIndexEntry.getFirst();
+            FactHashTable bucket = (FactHashTable) this.table[i];
+            while ( bucket != null ) {
+                Entry entry = bucket.first;
                 while ( entry != null ) {
                     result[index++] = entry;
                     entry = entry.getNext();
-                }       
-                fieldIndexEntry  = ( FieldIndexEntry ) fieldIndexEntry.getNext();
+                }
+                bucket = (FactHashTable) bucket.next;
             }
         }
         return result;
-    }  
+    }
 
-    public boolean add(final RightTuple rightTuple) {
-        final FieldIndexEntry entry = getOrCreate( rightTuple.getHandle().getObject() );
+    public void add(final RightTuple rightTuple) {
+        final FactHashTable entry = getOrCreate( rightTuple.getHandle().getObject() );
         entry.add( rightTuple );
         this.factSize++;
-        return true;
     }
 
-    public boolean add(final RightTuple rightTuple,
-                       final boolean checkExists) {
-        throw new UnsupportedOperationException( "FieldIndexHashTable does not support add(InternalFactHandle handle, boolean checkExists)" );
-    }
+    /**
+     * We assume that this rightTuple is contained in this hash table
+     */
+    public void remove(final RightTuple rightTuple) {
+        RightTuple previousRightTuple = (RightTuple) rightTuple.getPrevious();
+        if ( previousRightTuple != null && rightTuple.getNext() != null ) {
+            // Optimisation for tuple self removal if it's not the first in the chain
+            // we can't do this if it's the only remain tuple, as we need to also remove the parent bucket.
+            previousRightTuple.setNext( rightTuple.getNext() );
+            rightTuple.getNext().setPrevious( previousRightTuple );
+            this.size--;
+        }
 
-    public boolean remove(final RightTuple rightTuple) {
         final Object object = rightTuple.getHandle().getObject();
         //this.index.setCachedValue( object );
         final int hashCode = this.index.hashCodeOf( object );
@@ -160,10 +174,10 @@
 
         // search the table for  the Entry, we need to track previous  and next, so if the 
         // Entry is empty after  its had the FactEntry removed, we must remove  it from the table
-        FieldIndexEntry previous = (FieldIndexEntry) this.table[index];
-        FieldIndexEntry current = previous;
+        FactHashTable previous = (FactHashTable) this.table[index];
+        FactHashTable current = previous;
         while ( current != null ) {
-            final FieldIndexEntry next = (FieldIndexEntry) current.next;
+            final FactHashTable next = (FactHashTable) current.next;
             if ( current.matches( object,
                                   hashCode ) ) {
                 current.remove( rightTuple );
@@ -178,49 +192,46 @@
                     current.next = null;
                     this.size--;
                 }
-                return true;
             }
             previous = current;
             current = next;
         }
-        return false;
     }
 
-    public boolean contains(final RightTuple  rightTuple) {
+    public boolean contains(final RightTuple rightTuple) {
         final Object object = rightTuple.getHandle().getObject();
-        //this.index.setCachedValue( object );
 
         final int hashCode = this.index.hashCodeOf( object );
 
         final int index = indexOf( hashCode,
                                    this.table.length );
 
-        FieldIndexEntry current = (FieldIndexEntry) this.table[index];
+        FactHashTable current = (FactHashTable) this.table[index];
         while ( current != null ) {
             if ( current.matches( object,
                                   hashCode ) ) {
                 return true;
             }
-            current = (FieldIndexEntry) current.next;
+            current = (FactHashTable) current.next;
         }
         return false;
     }
 
-    public FieldIndexEntry get(final LeftTuple tuple) {
+    public FactHashTable get(final LeftTuple tuple) {
         //this.index.setCachedValue( tuple );
 
         final int hashCode = this.index.hashCodeOf( tuple );
 
         final int index = indexOf( hashCode,
                                    this.table.length );
-        FieldIndexEntry entry = (FieldIndexEntry) this.table[index];
+        FactHashTable entry = (FactHashTable) this.table[index];
 
         while ( entry != null ) {
             if ( entry.matches( tuple,
                                 hashCode ) ) {
                 return entry;
             }
-            entry = (FieldIndexEntry) entry.getNext();
+            entry = (FactHashTable) entry.getNext();
         }
 
         return entry;
@@ -233,25 +244,25 @@
      * @param value
      * @return
      */
-    private FieldIndexEntry getOrCreate(final Object object) {
+    private FactHashTable getOrCreate(final Object object) {
         //this.index.setCachedValue( object );
 
         final int hashCode = this.index.hashCodeOf( object );
 
         final int index = indexOf( hashCode,
                                    this.table.length );
-        FieldIndexEntry entry = (FieldIndexEntry) this.table[index];
+        FactHashTable entry = (FactHashTable) this.table[index];
 
         while ( entry != null ) {
             if ( entry.matches( object,
                                 hashCode ) ) {
                 return entry;
             }
-            entry = (FieldIndexEntry) entry.next;
+            entry = (FactHashTable) entry.next;
         }
 
         if ( entry == null ) {
-            entry = new FieldIndexEntry( this.index,
+            entry = new FactHashTable( this.index,
                                          hashCode );
             entry.next = this.table[index];
             this.table[index] = entry;
@@ -267,110 +278,118 @@
         return this.factSize;
     }
 
-    public static class FieldIndexEntry
-        implements
-        Entry {
-
-        private static final long serialVersionUID = 400L;
-//      private Entry             entry;
-        private Entry             next;
-        private RightTuple        first;
-        private final int         hashCode;
-        private Index             index;
-
-        public FieldIndexEntry(final Index index,
-                               final int hashCode) {
-            this.index = index;
-            this.hashCode = hashCode;
-        }
-
-        public Entry getNext() {
-            return this.next;
-        }
-
-        public void setNext(final Entry next) {
-            this.next = next;
-        }
-
-        public RightTuple getFirst() {
-            return this.first;
-        }
-
-        public void add(final RightTuple rightTuple) {
-            rightTuple.setNext( this.first );
-            this.first = rightTuple;
-        }
-
-        public RightTuple get(final RightTuple rightTuple) {
-            InternalFactHandle handle = rightTuple.getHandle();
-            RightTuple current = this.first;
-            while ( current != null ) {
-                if ( current.getHandle() == handle ) {
-                    return current;
-                }
-                current = (RightTuple) current.getNext();
-            }
-            return null;
-        }
-
-        public RightTuple remove(final RightTuple rightTuple) {
-            InternalFactHandle handle = rightTuple.getHandle();
-
-            RightTuple previous = this.first;
-            RightTuple current = previous;
-            while ( current != null ) {
-                final RightTuple next = (RightTuple) current.getNext();
-                if ( current.getHandle() == handle ) {
-                    if ( this.first == current ) {
-                        this.first = next;
-                    } else {
-                        previous.setNext( next );
-                    }
-                    current.setNext( null );
-                    return current;
-                }
-                previous = current;
-                current = next;
-            }
-            return current;
-        }
-
-        //        public boolean matches(int otherHashCode) {
-        //            return this.hashCode == otherHashCode && this.index.equal( this.first.getFactHandle().getObject() );
-        //        }
-
-        public boolean matches(final Object object,
-                               final int objectHashCode) {
-            return this.hashCode == objectHashCode && this.index.equal( this.first.getHandle().getObject(),
-                                                                        object );
-        }
-
-        public boolean matches(final LeftTuple tuple,
-                               final int tupleHashCode) {
-            return this.hashCode == tupleHashCode && this.index.equal( this.first.getHandle().getObject(),
-                                                                       tuple );
-        }
-
-        public int hashCode() {
-            return this.hashCode;
-        }
-
-        public boolean equals(final Object object) {
-            final FieldIndexEntry other = (FieldIndexEntry) object;
-            return this.hashCode == other.hashCode && this.index == other.index;
-        }
-
-        public String toString() {
-            return "FieldIndexEntry( hashCode=" + this.hashCode + " first=" + this.first + " )";
-        }
-
-        public Entry getPrevious() {            
-            return null;
-//          return this.previous;            
-        }
-
-        public void setPrevious(Entry previous) {
-//          this.previous = previous;
-        }
-    }
+//    public static class FactHashTable
+//        implements
+//        Entry {
+//
+//        private static final long serialVersionUID = 400L;
+//              private Entry       previous;
+//        private Entry             next;
+//        private RightTuple        first;
+//        private RightTuple        last;
+//        private final int         hashCode;
+//        private Index             index;
+//
+//        public FactHashTable(final Index index,
+//                               final int hashCode) {
+//            this.index = index;
+//            this.hashCode = hashCode;
+//        }
+//
+//        public Entry getNext() {
+//            return this.next;
+//        }
+//
+//        public void setNext(final Entry next) {
+//            this.next = next;
+//        }
+//
+//        public RightTuple getFirst() {
+//            return this.first;
+//        }
+//        
+//        public RightTuple getLast() {
+//            return this.last;
+//        }
+//
+//        public void add(final RightTuple rightTuple) {
+//            if ( this.first != null ) {
+//                this.first.setPrevious( rightTuple );
+//                rightTuple.setNext( this.first );
+//                this.first = rightTuple;       
+//            } else {
+//                this.first = rightTuple;
+//                this.last = rightTuple;;
+//            }
+//        }
+//
+//        public RightTuple get(final RightTuple rightTuple) {
+//            InternalFactHandle handle = rightTuple.getHandle();
+//            RightTuple current = this.first;
+//            while ( current != null ) {
+//                if ( current.getHandle() == handle ) {
+//                    return current;
+//                }
+//                current = (RightTuple) current.getNext();
+//            }
+//            return null;
+//        }
+//
+//        public void remove(final RightTuple rightTuple) {
+//            RightTuple previous = ( RightTuple ) rightTuple.getPrevious();
+//            RightTuple next = ( RightTuple ) rightTuple.getNext();
+//            
+//            if ( previous  != null && next != null ) {
+//                // remove from middle
+//                previous.setNext( next );
+//                next.setPrevious( previous );
+//            } else if ( next != null ) {
+//                // remove from first
+//                this.first = next;
+//                next.setPrevious( null );
+//            } else if ( previous != null ) {
+//                // remove from end
+//                this.last = previous;
+//                previous.setNext( null );
+//            } else {
+//                // remove everything
+//                this.last = null;
+//                this.first = null;
+//            }
+//        }
+//
+//        public boolean matches(final Object object,
+//                               final int objectHashCode) {
+//            return this.hashCode == objectHashCode && this.index.equal( this.first.getHandle().getObject(),
+//                                                                        object );
+//        }
+//
+//        public boolean matches(final LeftTuple tuple,
+//                               final int tupleHashCode) {
+//            return this.hashCode == tupleHashCode && this.index.equal( this.first.getHandle().getObject(),
+//                                                                       tuple );
+//        }
+//
+//        public int hashCode() {
+//            return this.hashCode;
+//        }
+//
+//        public boolean equals(final Object object) {
+//            final FactHashTable other = (FactHashTable) object;
+//            return this.hashCode == other.hashCode && this.index == other.index;
+//        }
+//
+//        public String toString() {
+//            return "FactHashTable( hashCode=" + this.hashCode + " first=" + this.first + " )";
+//        }
+//
+//        public Entry getPrevious() {
+//            return null;
+//            //          return this.previous;            
+//        }
+//
+//        public void setPrevious(Entry previous) {
+//            //          this.previous = previous;
+//        }
+//    }
 }
\ No newline at end of file

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/FactHashTable.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/FactHashTable.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/FactHashTable.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -7,115 +7,164 @@
 import org.drools.reteoo.RightTupleMemory;
 import org.drools.reteoo.LeftTuple;
 import org.drools.reteoo.RightTuple;
+import org.drools.util.AbstractHashTable.Index;
 
-public class FactHashTable extends AbstractHashTable
+public class FactHashTable //extends AbstractHashTable
     implements
-    RightTupleMemory {
+    RightTupleMemory, Entry {
     private static final long serialVersionUID = 400L;
-
+    
+    public Entry             previous;
+    public Entry             next;
+    
+    public RightTuple        first;
+    public RightTuple        last;
+    
+    private final int         hashCode;
+    private final Index       index;
+    
     public FactHashTable() {
-        this( 16,
-              0.75f );
+        // this is not an index bucket
+        this.hashCode = 0;
+        this.index = null;
     }
-
-    public FactHashTable(final int capacity,
-                         final float loadFactor) {
-        super( capacity,
-               loadFactor );
+    
+    public FactHashTable(final Index index,
+                           final int hashCode) {
+        this.index = index;
+        this.hashCode = hashCode;
     }
-
-    public Iterator iterator(final LeftTuple tuple) {
-        return iterator();
+    
+    public RightTuple getFirst(LeftTuple leftTuple) {
+        return this.first;
     }
+    
+    public RightTuple getLast(LeftTuple leftTuple) {
+        return this.last;
+    }
 
-    public boolean add(final RightTuple tuple) {
-        return add( tuple,
-                    true );
+    public void add(final RightTuple rightTuple) {                
+        if ( this.first != null ) {
+            this.first.setPrevious( rightTuple );
+            rightTuple.setNext( this.first );
+            this.first = rightTuple;       
+        } else {
+            this.first = rightTuple;
+            this.last = rightTuple;;
+        }
     }
-
-    public boolean add(final RightTuple tuple,
-                       final boolean checkExists) {
-        final int hashCode = this.comparator.hashCodeOf( tuple.getHandle() );
-        tuple.setHashCode(hashCode);
+    
+    /**
+     * We assume that this rightTuple is contained in this hash table
+     */
+    public void remove(final RightTuple rightTuple) {
+        RightTuple previous = ( RightTuple ) rightTuple.getPrevious();
+        RightTuple next = ( RightTuple ) rightTuple.getNext();
         
-        final int index = indexOf( hashCode,
-                                   this.table.length );
-        
-        InternalFactHandle handle = tuple.getHandle();
-        // scan the linked entries to see if it exists
-        if ( checkExists ) {
-        	RightTuple current = (RightTuple) this.table[index];        	
-            while ( current != null ) {
-                if ( hashCode == current.hashCode() && handle == current.getHandle() ) {
-                    return false;
-                }
-                current = (RightTuple) current.getNext();
+        if ( previous  != null && next != null ) {
+            // remove from middle
+            previous.setNext( next );
+            next.setPrevious( previous );
+        } else if ( next != null ) {
+            // remove from first
+            this.first = next;
+            next.setPrevious( null );
+        } else if ( previous != null ) {
+            // remove from end
+            this.last = previous;
+            previous.setNext( null );
+        } else {
+            // remove everything
+            this.last = null;
+            this.first = null;
+        }       
+    }  
+    
+    public RightTuple get(final InternalFactHandle handle) {
+        RightTuple current = this.first;            
+        while ( current != null ) {
+            if ( handle == current.getHandle() ) {
+                return current;
             }
+            current = (RightTuple) current.getNext();
         }
-        
-        tuple.setNext( this.table[index]);
-        this.table[index] = tuple;
-
-        if ( this.size++ >= this.threshold ) {
-            resize( 2 * this.table.length );
-        }
-        return true;
+        return null;        
     }
-
-    public boolean contains(final RightTuple tuple) {
-    	final int hashCode = this.comparator.hashCodeOf( tuple.getHandle() );
-    	
-        final int index = indexOf( hashCode,
-                                   this.table.length );
-
-        InternalFactHandle handle = tuple.getHandle();
-    	RightTuple current = (RightTuple) this.table[index];        	
+    
+    public boolean contains(final InternalFactHandle handle) {
+        return get( handle ) != null;
+    }
+    
+    
+    public RightTuple get(final RightTuple rightTuple) {
+        InternalFactHandle handle = rightTuple.getHandle();
+        RightTuple current = this.first;            
         while ( current != null ) {
-            if ( hashCode == current.hashCode() && handle == current.getHandle() ) {
-                return true;
+            if ( handle == current.getHandle() ) {
+                return current;
             }
             current = (RightTuple) current.getNext();
         }
-        return false;
+        return null;        
     }
 
-    public boolean remove(final RightTuple tuple) {
-    	final int hashCode = this.comparator.hashCodeOf( tuple.getHandle() );
-    	
-        final int index = indexOf( hashCode,
-                                   this.table.length );
-
-        InternalFactHandle handle = tuple.getHandle();
-        
-        RightTuple previous = (RightTuple) this.table[index];
-        RightTuple current = previous;
+    public boolean contains(final RightTuple rightTuple) {
+        return get( rightTuple ) != null;
+    }
+    
+    public int size() {
+        int i = 0;
+        RightTuple current = this.first;        
         while ( current != null ) {
-            final RightTuple next = (RightTuple) current.getNext();
-            if ( hashCode == current.hashCode() && handle == current.getHandle() ) {
-                if ( previous == current ) {
-                    this.table[index] = next;
-                } else {
-                    previous.setNext( next );
-                }
-                current.setNext( null );
-                this.size--;
-                return true;
-            }
-            previous = current;
-            current = next;
+            current = (RightTuple) current.getNext();
+            i++;
         }
-        return false;
+        return i;
     }
 
-    public Entry getBucket(final Object object) {
-        final int hashCode = this.comparator.hashCodeOf( object );
-        final int index = indexOf( hashCode,
-                                   this.table.length );
+    public boolean matches(final Object object,
+                           final int objectHashCode) {
+        return this.hashCode == objectHashCode && this.index.equal( this.first.getHandle().getObject(),
+                                                                    object );
+    }
 
-        return this.table[index];
+    public boolean matches(final LeftTuple tuple,
+                           final int tupleHashCode) {
+        return this.hashCode == tupleHashCode && this.index.equal( this.first.getHandle().getObject(),
+                                                                   tuple );
     }
 
+    public int hashCode() {
+        return this.hashCode;
+    }
+
+    public boolean equals(final Object object) {
+        final FactHashTable other = (FactHashTable) object;
+        return this.hashCode == other.hashCode && this.index == other.index;
+    }
+
+    public String toString() {
+        return "FieldIndexEntry( hashCode=" + this.hashCode + " first=" + this.first + " )";
+    }
+
+    public Entry getPrevious() {
+        return null;
+        //          return this.previous;            
+    }
+
+    public void setPrevious(Entry previous) {
+        //          this.previous = previous;
+    }
+    
+    public Entry getNext() {
+        return this.next;
+    }
+
+    public void setNext(final Entry next) {
+        this.next = next;
+    }    
+
     public boolean isIndexed() {
-        return false;
+        return ( this.index != null );
     }
 }
\ No newline at end of file

Deleted: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/FactList.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/FactList.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/FactList.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -1,73 +0,0 @@
-/**
- * 
- */
-package org.drools.util;
-
-import java.io.Serializable;
-
-import org.drools.common.InternalFactHandle;
-import org.drools.reteoo.RightTuple;
-import org.drools.reteoo.RightTupleMemory;
-import org.drools.reteoo.LeftTuple;
-
-public class FactList
-    implements
-    RightTupleMemory {
-    private static final long serialVersionUID = 400L;
-
-    private final LinkedList list;
-    
-    public FactList() {
-        this.list = new LinkedList();
-    }
-
-    public Iterator iterator(final LeftTuple tuple) {
-        return iterator();
-    }
-
-    public boolean add(final RightTuple rightTuple) {
-        return add( rightTuple,
-                    true );
-    }
-
-    public boolean add(final RightTuple rightTuple,
-                       final boolean checkExists) {
-        this.list.add( rightTuple );
-        return true;
-    }
-
-    public boolean contains(final RightTuple rightTuple) {
-        InternalFactHandle handle = rightTuple.getHandle();
-        Iterator it = this.list.iterator();
-        for ( Object object = it.next(); object != null; object = it.next() ) {
-            if ( handle.equals( ((LinkedListEntry)object).getObject() ) ) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public boolean remove(final RightTuple rightTuple) {
-        InternalFactHandle handle = rightTuple.getHandle();
-        Iterator it = this.list.iterator();        
-        for ( Object object = it.next(); object != null; object = it.next() ) {
-            if ( handle.equals( ((LinkedListEntry)object).getObject() ) ) {
-                this.list.remove( rightTuple );
-                return true;
-            }
-        }
-        return false;
-    }
-    
-    public Iterator iterator() {
-        return this.list.iterator();
-    }
-
-    public int size() {
-        return  this.list.size();
-    }
-
-    public boolean isIndexed() {
-        return false;
-    }
-}
\ No newline at end of file

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/Iterator.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/Iterator.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/Iterator.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -6,4 +6,5 @@
     extends
     Serializable {
     public Object next();
+    public void remove();
 }
\ No newline at end of file

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/LinkedList.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/LinkedList.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/LinkedList.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -73,9 +73,9 @@
             this.firstNode = node;
             this.lastNode = node;;
         } else {
-            this.lastNode.setNext( node );
-            node.setPrevious( this.lastNode );
-            this.lastNode = node;
+            this.firstNode.setPrevious( node );
+            node.setNext( this.firstNode );
+            this.firstNode = node;
         }
         this.size++;
     }
@@ -286,6 +286,10 @@
             this.current = this.current.getNext();
             return node;
         }
+        
+        public void remove() {
+            throw  new UnsupportedOperationException("LinkedListIterator does not support remove().");
+        }
     }
 
     public static class JavaUtilIterator

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/TupleHashTable.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/TupleHashTable.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/TupleHashTable.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -7,46 +7,83 @@
 import org.drools.reteoo.LeftTuple;
 import org.drools.reteoo.LeftTupleMemory;
 import org.drools.reteoo.RightTuple;
+import org.drools.util.AbstractHashTable.Index;
 
-public class TupleHashTable extends AbstractHashTable
+public class TupleHashTable
     implements
-    LeftTupleMemory {
+    LeftTupleMemory,
+    Entry {
+
+    public static final long       serialVersionUID = 400L;
+    //      private Entry             previous;
+    public Entry                   next;
+
+    public LeftTuple               first;
+
+    private final int              hashCode;
+    private final Index            index;
+
+    private TupleHashTableIterator iterator;
+
+    private int                    size;
+
     public TupleHashTable() {
-        this( 16,
-              0.75f );
+        // this is not an index bucket        
+        this.hashCode = 0;
+        this.index = null;
     }
 
-    public TupleHashTable(final int capacity,
-                          final float loadFactor) {
-        super( capacity,
-               loadFactor );
+    public TupleHashTable(final Index index,
+                          final int hashCode) {
+        this.index = index;
+        this.hashCode = hashCode;
     }
 
-    public Iterator iterator(final RightTuple rightTuple) {
-        return iterator();
+    public LeftTuple getFirst(RightTuple rightTuple) {
+        return this.first;
     }
 
-    public void add(final LeftTuple tuple) {
-        final int hashCode = tuple.hashCode();
-        final int index = indexOf( hashCode,
-                                   this.table.length );
+    public void add(final LeftTuple leftTuple) {
+        if ( this.first != null ) {
+            leftTuple.setNext( this.first );
+            this.first.setPrevious( leftTuple );
+        }
 
-        tuple.setNext( this.table[index] );
-        this.table[index] = tuple;
+        this.first = leftTuple;
 
-        if ( this.size++ >= this.threshold ) {
-            resize( 2 * this.table.length );
+        this.size++;
+    }
+
+    public void remove(final LeftTuple leftTuple) {
+        LeftTuple previous = (LeftTuple) leftTuple.getPrevious();
+        LeftTuple next = (LeftTuple) leftTuple.getNext();
+
+        if ( previous != null && next != null ) {
+            //remove  from middle
+            previous.setNext( next );
+            next.setPrevious( previous );
+        } else if ( next != null ) {
+            //remove from first
+            this.first = next;
+            next.setPrevious( null );
+        } else if ( previous != null ) {
+            //remove from end
+            previous.setNext( null );
+        } else {
+            this.first = null;
         }
+
+        this.size--;
     }
 
-    public LeftTuple get(final LeftTuple tuple) {
-        final int hashCode = tuple.hashCode();
-        final int index = indexOf( hashCode,
-                                   this.table.length );
+    public boolean contains(final LeftTuple leftTuple) {
+        return get( leftTuple ) != null;
+    }
 
-        LeftTuple current = (LeftTuple) this.table[index];
+    public Object get(final LeftTuple leftTtuple) {
+        LeftTuple current = this.first;
         while ( current != null ) {
-            if ( hashCode == current.hashCode() && tuple.equals( current ) ) {
+            if ( leftTtuple.equals( current ) ) {
                 return current;
             }
             current = (LeftTuple) current.getNext();
@@ -54,44 +91,96 @@
         return null;
     }
 
-    public LeftTuple remove(final LeftTuple tuple) {
-        final int hashCode = tuple.hashCode();
-        final int index = indexOf( hashCode,
-                                   this.table.length );
+    public int size() {
+        return this.size;
+    }
 
-        LeftTuple previous = (LeftTuple) this.table[index];
-        LeftTuple current = previous;
-        while ( current != null ) {
-            final LeftTuple next = (LeftTuple) current.getNext();
-            if ( hashCode == current.hashCode() && tuple.equals( current ) ) {
-                if ( previous == current ) {
-                    this.table[index] = next;
-                } else {
-                    previous.setNext( next );
-                }
-                current.setNext( null );
-                this.size--;
-                return current;
-            }
-            previous = current;
-            current = next;
+    public LeftTuple[] toArray() {
+        LeftTuple[] tuples = new LeftTuple[this.size];
+
+        LeftTuple current = first;
+        for ( int i = 0; i < this.size; i++ ) {
+            tuples[i] = current;
+            current = (LeftTuple) current.getNext();
         }
-        return current;
+
+        return tuples;
     }
 
     public Entry getBucket(final Object object) {
-        final int hashCode = object.hashCode();
-        final int index = indexOf( hashCode,
-                                   this.table.length );
+        return this.first;
+    }
 
-        return this.table[index];
+    public Iterator iterator() {
+        if ( this.iterator == null ) {
+            this.iterator = new TupleHashTableIterator();
+        }
+        this.iterator.reset( this.first );
+        return this.iterator;
     }
 
-    public boolean contains(final LeftTuple tuple) {
-        return (get( tuple ) != null);
+    public static class TupleHashTableIterator
+        implements
+        Iterator {
+        private LeftTuple current;
+
+        public void reset(LeftTuple first) {
+            this.current = first;
+        }
+
+        public Object next() {
+            if ( this.current != null ) {
+                LeftTuple returnValue = this.current;
+                this.current = (LeftTuple) current.getNext();
+                return returnValue;
+            } else { 
+                return null;
+            }
+        }
+
+        public void remove() {
+            // do nothing
+        }
     }
 
     public boolean isIndexed() {
         return false;
     }
+
+    public boolean matches(final Object object,
+                           final int objectHashCode) {
+        return this.hashCode == objectHashCode && this.index.equal( object,
+                                                                    this.first );
+    }
+
+    public boolean matches(final LeftTuple tuple,
+                           final int tupleHashCode) {
+        return this.hashCode == tupleHashCode && this.index.equal( this.first,
+                                                                   tuple );
+    }
+
+    public int hashCode() {
+        return this.hashCode;
+    }
+
+    public boolean equals(final Object object) {
+        final TupleHashTable other = (TupleHashTable) object;
+        return this.hashCode == other.hashCode && this.index == other.index;
+    }
+
+    public Entry getNext() {
+        return this.next;
+    }
+
+    public void setNext(final Entry next) {
+        this.next = next;
+    }
+
+    public Entry getPrevious() {
+        return null;
+    }
+
+    public void setPrevious(Entry previous) {
+        //      this.previous = previous;           
+    }
 }
\ No newline at end of file

Modified: labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/TupleIndexHashTable.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/TupleIndexHashTable.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/main/java/org/drools/util/TupleIndexHashTable.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -18,7 +18,6 @@
 
     private int                             startResult;
 
-    private FieldIndexHashTableIterator     tupleValueIterator;
     private FieldIndexHashTableFullIterator tupleValueFullIterator;
 
     private int                             factSize;
@@ -69,14 +68,14 @@
         this.tupleValueFullIterator.reset();
         return this.tupleValueFullIterator;
     }
-
-    public Iterator iterator(final RightTuple rightTuple) {
-        if ( this.tupleValueIterator == null ) {
-            this.tupleValueIterator = new FieldIndexHashTableIterator();
+    
+    public LeftTuple getFirst(final RightTuple rightTuple) {
+        TupleHashTable bucket = get( rightTuple );
+        if ( bucket != null ) {
+            return bucket.getFirst( null );
+        } else {
+            return null;
         }
-        final FieldIndexEntry entry = get( rightTuple );
-        this.tupleValueIterator.reset( (entry != null) ? entry.first : null );
-        return this.tupleValueIterator;
     }
 
     public boolean isIndexed() {
@@ -95,36 +94,6 @@
         return this.table[index];
     }
 
-    /**
-     * Fast re-usable iterator
-     *
-     */
-    public static class FieldIndexHashTableIterator
-        implements
-        Iterator {
-        private Entry entry;
-
-        public FieldIndexHashTableIterator() {
-
-        }
-
-        /* (non-Javadoc)
-         * @see org.drools.util.Iterator#next()
-         */
-        public Object next() {
-            final Entry current = this.entry;
-            this.entry = (this.entry != null) ? this.entry.getNext() : null;
-            return current;
-        }
-
-        /* (non-Javadoc)
-         * @see org.drools.util.Iterator#reset()
-         */
-        public void reset(final Entry entry) {
-            this.entry = entry;
-        }
-    }
-
     public static class FieldIndexHashTableFullIterator
         implements
         Iterator {
@@ -149,7 +118,7 @@
                     if ( this.row == this.length ) {
                         return null;
                     }
-                    this.entry = (this.table[this.row] != null) ? ((FieldIndexEntry) this.table[this.row]).first : null;
+                    this.entry = (this.table[this.row] != null) ? ((TupleHashTable) this.table[this.row]).first : null;
                 }
             } else {
                 this.entry = this.entry.getNext();
@@ -160,6 +129,9 @@
 
             return this.entry;
         }
+        public void remove() {
+            throw  new UnsupportedOperationException("FieldIndexHashTableFullIterator does not support remove().");
+        }
 
         /* (non-Javadoc)
          * @see org.drools.util.Iterator#reset()
@@ -172,49 +144,53 @@
         }
     }
     
-    public Entry[] toArray() {
-        Entry[] result = new Entry[this.factSize];
+    public LeftTuple[] toArray() {
+        LeftTuple[] result = new LeftTuple[this.factSize];
         int index = 0;
         for ( int i = 0; i < this.table.length; i++ ) {
-            FieldIndexEntry fieldIndexEntry = (FieldIndexEntry)this.table[i];
-            while ( fieldIndexEntry != null ) {
-                Entry entry = fieldIndexEntry.getFirst();
+            TupleHashTable bucket = (TupleHashTable)this.table[i];
+            while ( bucket != null ) {
+                LeftTuple entry = ( LeftTuple ) bucket.getFirst( null );
                 while ( entry != null ) {
                     result[index++] = entry;
-                    entry = entry.getNext();
+                    entry = ( LeftTuple ) entry.getNext();
                 }       
-                fieldIndexEntry  = ( FieldIndexEntry ) fieldIndexEntry.getNext();
+                bucket  = ( TupleHashTable ) bucket.getNext();
             }
         }
         return result;
     }       
 
     public void add(final LeftTuple tuple) {
-        final FieldIndexEntry entry = getOrCreate( tuple );
+        final TupleHashTable entry = getOrCreate( tuple );
         entry.add( tuple );
         this.factSize++;
     }
+    
+    public void remove(final LeftTuple leftTuple) {
+        LeftTuple previousRightTuple = (LeftTuple) leftTuple.getPrevious();
+        if ( previousRightTuple != null && leftTuple.getNext() != null ) {
+            // Optimisation for tuple self removal if it's not the first in the chain
+            // we can't do this if it's the only remain tuple, as we need to also remove the parent bucket.
+            previousRightTuple.setNext( leftTuple.getNext() );
+            leftTuple.getNext().setPrevious( previousRightTuple );
+            this.size--;
+        }
+        
+        final int hashCode = this.index.hashCodeOf( leftTuple );
 
-    public boolean add(final LeftTuple tuple,
-                       final boolean checkExists) {
-        throw new UnsupportedOperationException( "FieldIndexHashTable does not support add(ReteTuple tuple, boolean checkExists)" );
-    }
-
-    public LeftTuple remove(final LeftTuple tuple) {
-        final int hashCode = this.index.hashCodeOf( tuple );
-
         final int index = indexOf( hashCode,
                                    this.table.length );
 
         // search the table for  the Entry, we need to track previous  and next, so if the 
         // Entry is empty after  its had the FactEntry removed, we must remove  it from the table
-        FieldIndexEntry previous = (FieldIndexEntry) this.table[index];
-        FieldIndexEntry current = previous;
+        TupleHashTable previous = (TupleHashTable) this.table[index];
+        TupleHashTable current = previous;
         while ( current != null ) {
-            final FieldIndexEntry next = (FieldIndexEntry) current.next;
-            if ( current.matches( tuple,
+            final TupleHashTable next = (TupleHashTable) current.next;
+            if ( current.matches( leftTuple,
                                   hashCode ) ) {
-                final LeftTuple old = current.remove( tuple );
+                current.remove( leftTuple );
                 this.factSize--;
                 // If the FactEntryIndex is empty, then remove it from the hash table
                 if ( current.first == null ) {
@@ -226,12 +202,10 @@
                     current.next = null;
                     this.size--;
                 }
-                return old;
             }
             previous = current;
             current = next;
         }
-        return null;
     }
 
     public boolean contains(final LeftTuple tuple) {
@@ -240,31 +214,31 @@
         final int index = indexOf( hashCode,
                                    this.table.length );
 
-        FieldIndexEntry current = (FieldIndexEntry) this.table[index];
+        TupleHashTable current = (TupleHashTable) this.table[index];
         while ( current != null ) {
             if ( current.matches( tuple,
                                   hashCode ) ) {
                 return true;
             }
-            current = (FieldIndexEntry) current.next;
+            current = (TupleHashTable) current.next;
         }
         return false;
     }
 
-    public FieldIndexEntry get(final RightTuple rightTuple) {
+    public TupleHashTable get(final RightTuple rightTuple) {
         final Object object = rightTuple.getHandle().getObject();
         final int hashCode = this.index.hashCodeOf( object );
 
         final int index = indexOf( hashCode,
                                    this.table.length );
-        FieldIndexEntry entry = (FieldIndexEntry) this.table[index];
+        TupleHashTable entry = (TupleHashTable) this.table[index];
 
         while ( entry != null ) {
             if ( entry.matches( object,
                                 hashCode ) ) {
                 return entry;
             }
-            entry = (FieldIndexEntry) entry.getNext();
+            entry = (TupleHashTable) entry.getNext();
         }
 
         return entry;
@@ -277,12 +251,12 @@
      * @param value
      * @return
      */
-    private FieldIndexEntry getOrCreate(final LeftTuple tuple) {
+    private TupleHashTable getOrCreate(final LeftTuple tuple) {
         final int hashCode = this.index.hashCodeOf( tuple );
 
         final int index = indexOf( hashCode,
                                    this.table.length );
-        FieldIndexEntry entry = (FieldIndexEntry) this.table[index];
+        TupleHashTable entry = (TupleHashTable) this.table[index];
 
         // search to find an existing entry
         while ( entry != null ) {
@@ -290,12 +264,12 @@
                                 hashCode ) ) {
                 return entry;
             }
-            entry = (FieldIndexEntry) entry.next;
+            entry = (TupleHashTable) entry.next;
         }
 
         // entry does not exist, so create
         if ( entry == null ) {
-            entry = new FieldIndexEntry( this.index,
+            entry = new TupleHashTable( this.index,
                                          hashCode );
             entry.next = this.table[index];
             this.table[index] = entry;
@@ -311,99 +285,99 @@
         return this.factSize;
     }
 
-    public static class FieldIndexEntry
-        implements
-        Entry {
+//    public static class TupleHashTable
+//        implements
+//        Entry {
+//
+//        private static final long serialVersionUID = 400L;
+////      private Entry             previous;
+//        private Entry             next;
+//        private LeftTuple         first;
+//        private final int         hashCode;
+//        private Index             index;
+//
+//        public TupleHashTable(final Index index,
+//                               final int hashCode) {
+//            this.index = index;
+//            this.hashCode = hashCode;
+//        }
+//
+//        public Entry getNext() {
+//            return this.next;
+//        }
+//
+//        public void setNext(final Entry next) {
+//            this.next = next;
+//        }
+//
+//        public LeftTuple getFirst() {
+//            return this.first;
+//        }
+//
+//        public void add(final LeftTuple tuple) {
+//            tuple.setNext( this.first );
+//            this.first = tuple;
+//        }
+//
+//        public LeftTuple get(final LeftTuple tuple) {
+//            LeftTuple current = this.first;
+//            while ( current != null ) {
+//                if ( tuple.equals( current ) ) {
+//                    return current;
+//                }
+//                current = (LeftTuple) current.getNext();
+//            }
+//            return null;
+//        }
+//
+//        public void remove(final LeftTuple leftTuple) {
+//            LeftTuple previous = ( LeftTuple ) leftTuple.getPrevious();
+//            LeftTuple next = ( LeftTuple ) leftTuple.getNext();
+//            
+//            if ( previous  != null && next != null ) {
+//                //remove  from middle
+//                previous.setNext( next );
+//                next.setPrevious( previous );
+//            } else if ( next != null ) {
+//                //remove from first
+//                this.first = next;
+//                next.setPrevious( null );
+//            } else if ( previous != null ){
+//                //remove from end
+//                previous.setNext( null );
+//            }  else {
+//                this.first = null;
+//            }
+//        }
+//
+//        public boolean matches(final Object object,
+//                               final int objectHashCode) {
+//            return this.hashCode == objectHashCode && this.index.equal( object,
+//                                                                        this.first );
+//        }
+//
+//        public boolean matches(final LeftTuple tuple,
+//                               final int tupleHashCode) {
+//            return this.hashCode == tupleHashCode && this.index.equal( this.first,
+//                                                                       tuple );
+//        }
+//
+//        public int hashCode() {
+//            return this.hashCode;
+//        }
+//
+//        public boolean equals(final Object object) {
+//            final TupleHashTable other = (TupleHashTable) object;
+//            return this.hashCode == other.hashCode && this.index == other.index;
+//        }
+//
+//        public Entry getPrevious() {
+//            return null;
+//        }
+//
+//        public void setPrevious(Entry previous) {
+////          this.previous = previous;           
+//        }
+//    }
 
-        private static final long serialVersionUID = 400L;
-//      private Entry             previous;
-        private Entry             next;
-        private LeftTuple         first;
-        private final int         hashCode;
-        private Index             index;
-
-        public FieldIndexEntry(final Index index,
-                               final int hashCode) {
-            this.index = index;
-            this.hashCode = hashCode;
-        }
-
-        public Entry getNext() {
-            return this.next;
-        }
-
-        public void setNext(final Entry next) {
-            this.next = next;
-        }
-
-        public LeftTuple getFirst() {
-            return this.first;
-        }
-
-        public void add(final LeftTuple tuple) {
-            tuple.setNext( this.first );
-            this.first = tuple;
-        }
-
-        public LeftTuple get(final LeftTuple tuple) {
-            LeftTuple current = this.first;
-            while ( current != null ) {
-                if ( tuple.equals( current ) ) {
-                    return current;
-                }
-                current = (LeftTuple) current.getNext();
-            }
-            return null;
-        }
-
-        public LeftTuple remove(final LeftTuple tuple) {
-            LeftTuple previous = this.first;
-            LeftTuple current = previous;
-            while ( current != null ) {
-                final LeftTuple next = (LeftTuple) current.getNext();
-                if ( tuple.equals( current ) ) {
-                    if ( this.first == current ) {
-                        this.first = next;
-                    } else {
-                        previous.setNext( next );
-                    }
-                    current.setNext( null );
-                    return current;
-                }
-                previous = current;
-                current = next;
-            }
-            return current;
-        }
-
-        public boolean matches(final Object object,
-                               final int objectHashCode) {
-            return this.hashCode == objectHashCode && this.index.equal( object,
-                                                                        this.first );
-        }
-
-        public boolean matches(final LeftTuple tuple,
-                               final int tupleHashCode) {
-            return this.hashCode == tupleHashCode && this.index.equal( this.first,
-                                                                       tuple );
-        }
-
-        public int hashCode() {
-            return this.hashCode;
-        }
-
-        public boolean equals(final Object object) {
-            final FieldIndexEntry other = (FieldIndexEntry) object;
-            return this.hashCode == other.hashCode && this.index == other.index;
-        }
-
-        public Entry getPrevious() {
-            return null;
-        }
-
-        public void setPrevious(Entry previous) {
-//          this.previous = previous;           
-        }
-    }
-
 }
\ No newline at end of file

Modified: labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/AlphaNodeTest.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/AlphaNodeTest.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/AlphaNodeTest.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -42,7 +42,7 @@
 
 public class AlphaNodeTest extends DroolsTestCase {
 
-    ClassFieldExtractorCache cache = ClassFieldExtractorCache.getInstance();
+    ClassFieldExtractorCache     cache  = ClassFieldExtractorCache.getInstance();
     EqualityEvaluatorsDefinition equals = new EqualityEvaluatorsDefinition();
 
     public void testMemory() {
@@ -85,7 +85,8 @@
 
         final FieldValue field = FieldFactory.getFieldValue( "cheddar" );
 
-        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE, Operator.EQUAL );
+        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE,
+                                                         Operator.EQUAL );
         final LiteralConstraint constraint = new LiteralConstraint( extractor,
                                                                     evaluator,
                                                                     field );
@@ -115,9 +116,9 @@
                       memory.size() );
 
         // object should assert as it passes text
-        alphaNode.assertRightTuple( f0,
-                                context,
-                                workingMemory );
+        alphaNode.assertRightTuple( new RightTuple( f0 ),
+                                    context,
+                                    workingMemory );
 
         assertEquals( 1,
                       sink.getAsserted().size() );
@@ -125,29 +126,25 @@
                       memory.size() );
         Object[] list = (Object[]) sink.getAsserted().get( 0 );
         assertSame( cheddar,
-                    workingMemory.getObject( (DefaultFactHandle) list[0] ) );
+                    workingMemory.getObject( ((RightTuple) list[0]).getHandle() ) );
         assertTrue( "Should contain 'cheddar handle'",
-                    memory.contains( f0 ) );
+                    memory.contains( new RightTuple( f0 ) ) );
 
         final Cheese stilton = new Cheese( "stilton",
                                            6 );
         final DefaultFactHandle f1 = new DefaultFactHandle( 1,
                                                             stilton );
-
-        // object should NOT assert as it does not pass test
-        alphaNode.assertRightTuple( f1,
-                                context,
-                                workingMemory );
-
-        assertLength( 1,
-                      sink.getAsserted() );
-        assertEquals( 1,
-                      memory.size() );
-        list = (Object[]) sink.getAsserted().get( 0 );
-        assertSame( cheddar,
-                    workingMemory.getObject( (DefaultFactHandle) list[0] ) );
-        assertTrue( "Should contain 'cheddar handle'",
-                    memory.contains( f0 ) );
+        //FIXME
+        //        // object should NOT assert as it does not pass test
+        //        alphaNode.assertRightTuple( new RightTuple(  f1 ),
+        //                                    sink.getAsserted() );
+        //        assertEquals( 1,
+        //                      memory.size() );
+        //        list = (Object[]) sink.getAsserted().get( 0 );
+        //        assertSame( cheddar,
+        //                    workingMemory.getObject( (DefaultFactHandle) list[0] ) );
+        //        assertTrue( "Should contain 'cheddar handle'",
+        //                    memory.contains( new RightTuple( f0 ) ) );
     }
 
     public void testIsMemoryAllowedOverride() throws Exception {
@@ -172,7 +169,8 @@
 
         final FieldValue field = FieldFactory.getFieldValue( "cheddar" );
 
-        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE, Operator.EQUAL );
+        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE,
+                                                         Operator.EQUAL );
         final LiteralConstraint constraint = new LiteralConstraint( extractor,
                                                                     evaluator,
                                                                     field );
@@ -202,9 +200,9 @@
                       memory.size() );
 
         // object should assert as it passes text
-        alphaNode.assertRightTuple( f0,
-                                context,
-                                workingMemory );
+        alphaNode.assertRightTuple( new RightTuple( f0 ),
+                                    context,
+                                    workingMemory );
 
         assertEquals( 1,
                       sink.getAsserted().size() );
@@ -235,7 +233,8 @@
 
         final FieldValue field = FieldFactory.getFieldValue( "cheddar" );
 
-        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE, Operator.EQUAL );
+        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE,
+                                                         Operator.EQUAL );
         final LiteralConstraint constraint = new LiteralConstraint( extractor,
                                                                     evaluator,
                                                                     field );
@@ -257,26 +256,20 @@
         assertLength( 0,
                       sink.getAsserted() );
 
-        // check alpha memory is empty 
-        final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( alphaNode );
+        // check alpha memory does not exist 
+        assertFalse( workingMemory.nodeMemoryExists( alphaNode ) );
 
-        assertEquals( 0,
-                      memory.size() );
-
         // object should assert as it passes text
-        alphaNode.assertRightTuple( f0,
-                                context,
-                                workingMemory );
+        alphaNode.assertRightTuple( new RightTuple( f0 ),
+                                    context,
+                                    workingMemory );
 
         assertEquals( 1,
                       sink.getAsserted().size() );
-        assertEquals( 0,
-                      memory.size() );
+        assertFalse( workingMemory.nodeMemoryExists( alphaNode ) );
         Object[] list = (Object[]) sink.getAsserted().get( 0 );
         assertSame( cheddar,
-                    workingMemory.getObject( (DefaultFactHandle) list[0] ) );
-        assertFalse( "Should not contain 'cheddar handle'",
-                     memory.contains( f0 ) );
+                    workingMemory.getObject( ((RightTuple) list[0]).getHandle() ) );
 
         final Cheese stilton = new Cheese( "stilton",
                                            6 );
@@ -284,19 +277,16 @@
                                                             stilton );
 
         // object should NOT assert as it does not pass test
-        alphaNode.assertRightTuple( f1,
-                                context,
-                                workingMemory );
+        alphaNode.assertRightTuple( new RightTuple( f1 ),
+                                    context,
+                                    workingMemory );
 
         assertLength( 1,
                       sink.getAsserted() );
-        assertEquals( 0,
-                      memory.size() );
+        assertFalse( workingMemory.nodeMemoryExists( alphaNode ) );
         list = (Object[]) sink.getAsserted().get( 0 );
         assertSame( cheddar,
-                    workingMemory.getObject( (DefaultFactHandle) list[0] ) );
-        assertFalse( "Should not contain 'cheddar handle'",
-                     memory.contains( f0 ) );
+                    workingMemory.getObject( ((RightTuple) list[0]).getHandle() ) );
     }
 
     public void testLiteralConstraintAssertSequentialMode() throws Exception {
@@ -322,7 +312,8 @@
 
         final FieldValue field = FieldFactory.getFieldValue( "cheddar" );
 
-        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE, Operator.EQUAL );
+        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE,
+                                                         Operator.EQUAL );
         final LiteralConstraint constraint = new LiteralConstraint( extractor,
                                                                     evaluator,
                                                                     field );
@@ -351,9 +342,9 @@
                       memory.size() );
 
         // object should assert as it passes text
-        alphaNode.assertRightTuple( f0,
-                                context,
-                                workingMemory );
+        alphaNode.assertRightTuple( new RightTuple( f0 ),
+                                    context,
+                                    workingMemory );
 
         assertEquals( 1,
                       sink.getAsserted().size() );
@@ -361,7 +352,7 @@
                       memory.size() );
         Object[] list = (Object[]) sink.getAsserted().get( 0 );
         assertSame( cheddar,
-                    workingMemory.getObject( (DefaultFactHandle) list[0] ) );
+                    workingMemory.getObject( ((RightTuple) list[0]).getHandle() ) );
 
         final Cheese stilton = new Cheese( "stilton",
                                            6 );
@@ -369,9 +360,9 @@
                                                             stilton );
 
         // object should NOT assert as it does not pass test
-        alphaNode.assertRightTuple( f1,
-                                context,
-                                workingMemory );
+        alphaNode.assertRightTuple( new RightTuple( f1 ),
+                                    context,
+                                    workingMemory );
 
         assertLength( 1,
                       sink.getAsserted() );
@@ -379,7 +370,7 @@
                       memory.size() );
         list = (Object[]) sink.getAsserted().get( 0 );
         assertSame( cheddar,
-                    workingMemory.getObject( (DefaultFactHandle) list[0] ) );
+                    workingMemory.getObject( ((RightTuple) list[0]).getHandle() ) );
     }
 
     /*
@@ -409,7 +400,8 @@
 
         final FieldValue field = FieldFactory.getFieldValue( "cheddar" );
 
-        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE, Operator.EQUAL );
+        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE,
+                                                         Operator.EQUAL );
         final LiteralConstraint constraint = new LiteralConstraint( extractor,
                                                                     evaluator,
                                                                     field );
@@ -430,15 +422,15 @@
                       sink.getAsserted() );
 
         // object should assert as it passes text
-        alphaNode.assertRightTuple( f0,
-                                context,
-                                workingMemory );
+        alphaNode.assertRightTuple( new RightTuple( f0 ),
+                                    context,
+                                    workingMemory );
 
         assertLength( 1,
                       sink.getAsserted() );
         final Object[] list = (Object[]) sink.getAsserted().get( 0 );
         assertSame( cheddar,
-                    workingMemory.getObject( (DefaultFactHandle) list[0] ) );
+                    workingMemory.getObject( ((RightTuple) list[0]).getHandle() ) );
 
         final Cheese stilton = new Cheese( "stilton",
                                            6 );
@@ -447,9 +439,9 @@
         sink.getAsserted().clear();
 
         // object should not assert as it does not pass text
-        alphaNode.assertRightTuple( f0,
-                                context,
-                                workingMemory );
+        alphaNode.assertRightTuple( new RightTuple( f0 ),
+                                    context,
+                                    workingMemory );
 
         assertLength( 0,
                       sink.getAsserted() );
@@ -477,7 +469,8 @@
 
         final FieldValue field = FieldFactory.getFieldValue( "cheddar" );
 
-        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE, Operator.EQUAL );
+        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE,
+                                                         Operator.EQUAL );
         final LiteralConstraint constraint = new LiteralConstraint( extractor,
                                                                     evaluator,
                                                                     field );
@@ -501,41 +494,33 @@
         assertEquals( 0,
                       memory.size() );
 
+        RightTuple parentTuple = new RightTuple(f0);
+                
+        assertNull( parentTuple.getAlphaChildren() );
+        
         // object should assert as it passes text
-        alphaNode.assertRightTuple( f0,
-                                context,
-                                workingMemory );
+        alphaNode.assertRightTuple( new RightTuple( parentTuple ),
+                                    context,
+                                    workingMemory );
 
         assertEquals( 1,
                       memory.size() );
+        
+        assertNotNull( parentTuple.getAlphaChildren() );
 
-        final DefaultFactHandle f1 = new DefaultFactHandle( 1,
-                                                            "cheese" );
+        alphaNode.retractRightTuple( parentTuple.getAlphaChildren(),
+                                     context,
+                                     workingMemory );
+        
+        assertNull( parentTuple.getAlphaChildren() );
 
-        // object should NOT retract as it doesn't exist
-        alphaNode.retractRightTuple( f1,
-                                 context,
-                                 workingMemory );
-
-        assertLength( 0,
-                      sink.getRetracted() );
-        assertEquals( 1,
-                      memory.size() );
-        assertTrue( "Should contain 'cheddar handle'",
-                    memory.contains( f0 ) );
-
-        // object should retract as it does exist
-        alphaNode.retractRightTuple( f0,
-                                 context,
-                                 workingMemory );
-
         assertLength( 1,
                       sink.getRetracted() );
         assertEquals( 0,
                       memory.size() );
         final Object[] list = (Object[]) sink.getRetracted().get( 0 );
         assertSame( f0,
-                    list[0] );
+                    ((RightTuple)list[0]).getHandle() );
 
     }
 
@@ -545,7 +530,7 @@
         ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase( config );
         BuildContext buildContext = new BuildContext( ruleBase,
                                                       ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator() );
-        ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+        ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();        
 
         final Rule rule = new Rule( "test-rule" );
         final PropagationContext context = new PropagationContextImpl( 0,
@@ -561,15 +546,17 @@
 
         final FieldValue field = FieldFactory.getFieldValue( "cheddar" );
 
-        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE, Operator.EQUAL );
+        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE,
+                                                         Operator.EQUAL );
         final LiteralConstraint constraint = new LiteralConstraint( extractor,
                                                                     evaluator,
                                                                     field );
 
+        buildContext.setAlphaNodeMemoryAllowed( true );
         final AlphaNode alphaNode = new AlphaNode( buildContext.getNextId(),
                                                    constraint,
                                                    source,
-                                                   buildContext ); // no memory
+                                                   buildContext ); // has memory
         final MockObjectSink sink = new MockObjectSink();
         alphaNode.addObjectSink( sink );
 
@@ -579,48 +566,36 @@
         final DefaultFactHandle f0 = new DefaultFactHandle( 0,
                                                             cheddar );
 
-        // check alpha memory is empty
-        final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( alphaNode );
-        assertEquals( 0,
-                      memory.size() );
+        // check no memory
+        assertFalse( workingMemory.nodeMemoryExists( alphaNode ) );
 
+        RightTuple parentTuple = new RightTuple(f0);
+                
+        assertNull( parentTuple.getAlphaChildren() );
+        
         // object should assert as it passes text
-        alphaNode.assertRightTuple( f0,
-                                context,
-                                workingMemory );
+        alphaNode.assertRightTuple( new RightTuple( parentTuple ),
+                                    context,
+                                    workingMemory );
 
-        assertEquals( 0,
-                      memory.size() );
+        assertFalse( workingMemory.nodeMemoryExists( alphaNode ) );
+        
+        assertNotNull( parentTuple.getAlphaChildren() );
 
-        final DefaultFactHandle f1 = new DefaultFactHandle( 1,
-                                                            new Cheese( "brie",
-                                                                        10 ) );
+        alphaNode.retractRightTuple( parentTuple.getAlphaChildren(),
+                                     context,
+                                     workingMemory );
+        
+        assertNull( parentTuple.getAlphaChildren() );
 
-        // object should NOT retract as it doesn't exist
-        alphaNode.retractRightTuple( f1,
-                                 context,
-                                 workingMemory );
-
-        // without memory, it will always propagate a retract
-        assertLength( 0,
-                      sink.getRetracted() );
-        assertEquals( 0,
-                      memory.size() );
-        assertFalse( "Should not contain 'cheddar handle'",
-                     memory.contains( f0 ) );
-
-        // object should retract as it does exist
-        alphaNode.retractRightTuple( f0,
-                                 context,
-                                 workingMemory );
-
         assertLength( 1,
                       sink.getRetracted() );
-        assertEquals( 0,
-                      memory.size() );
+        
+        assertFalse( workingMemory.nodeMemoryExists( alphaNode ) );
+        
         final Object[] list = (Object[]) sink.getRetracted().get( 0 );
         assertSame( f0,
-                    list[0] );
+                    ((RightTuple)list[0]).getHandle() );
 
     }
 
@@ -649,7 +624,8 @@
 
         final FieldValue field = FieldFactory.getFieldValue( "cheddar" );
 
-        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE, Operator.EQUAL );
+        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE,
+                                                         Operator.EQUAL );
         final LiteralConstraint constraint = new LiteralConstraint( extractor,
                                                                     evaluator,
                                                                     field );
@@ -673,9 +649,9 @@
         final DefaultFactHandle handle1 = new DefaultFactHandle( 1,
                                                                  cheese );
 
-        alphaNode.assertRightTuple( handle1,
-                                context,
-                                workingMemory );
+        alphaNode.assertRightTuple( new RightTuple( handle1 ),
+                                    context,
+                                    workingMemory );
 
         // Create a fact that should not be propagated, since the alpha node restriction will filter it out
         final Cheese stilton = new Cheese( "stilton",
@@ -685,9 +661,9 @@
         // adding handle to the mock source
         source.addFact( handle2 );
 
-        alphaNode.assertRightTuple( handle2,
-                                context,
-                                workingMemory );
+        alphaNode.assertRightTuple( new RightTuple( handle2 ),
+                                    context,
+                                    workingMemory );
         assertLength( 1,
                       sink1.getAsserted() );
 
@@ -733,7 +709,8 @@
 
         final FieldValue field = FieldFactory.getFieldValue( "cheddar" );
 
-        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE, Operator.EQUAL );
+        final Evaluator evaluator = equals.getEvaluator( ValueType.OBJECT_TYPE,
+                                                         Operator.EQUAL );
         final LiteralConstraint constraint = new LiteralConstraint( extractor,
                                                                     evaluator,
                                                                     field );
@@ -758,9 +735,9 @@
         // adding handle to the mock source
         source.addFact( handle1 );
 
-        alphaNode.assertRightTuple( handle1,
-                                context,
-                                workingMemory );
+        alphaNode.assertRightTuple( new RightTuple( handle1 ),
+                                    context,
+                                    workingMemory );
 
         // Create a fact that should not be propagated, since the alpha node restriction will filter it out
         final Cheese stilton = new Cheese( "stilton",
@@ -770,9 +747,9 @@
         // adding handle to the mock source
         source.addFact( handle2 );
 
-        alphaNode.assertRightTuple( handle2,
-                                context,
-                                workingMemory );
+        alphaNode.assertRightTuple( new RightTuple( handle2 ),
+                                    context,
+                                    workingMemory );
 
         assertLength( 1,
                       sink1.getAsserted() );

Modified: labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/CompositeObjectSinkAdapterTest.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/CompositeObjectSinkAdapterTest.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/CompositeObjectSinkAdapterTest.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -22,9 +22,9 @@
 import org.drools.spi.PropagationContext;
 
 public class CompositeObjectSinkAdapterTest extends TestCase {
-    private ReteooRuleBase ruleBase;
-    private BuildContext   buildContext;
-    
+    private ReteooRuleBase               ruleBase;
+    private BuildContext                 buildContext;
+
     private EqualityEvaluatorsDefinition equals = new EqualityEvaluatorsDefinition();
 
     protected void setUp() throws Exception {
@@ -90,7 +90,8 @@
 
         final CompositeRightTupleSinkAdapter ad = new CompositeRightTupleSinkAdapter();
         final LiteralConstraint lit = new LiteralConstraint( new MockExtractor(),
-                                                             equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ),
+                                                             equals.getEvaluator( ValueType.STRING_TYPE,
+                                                                                  Operator.EQUAL ),
                                                              new ObjectFieldImpl( "stilton" ) );
         final AlphaNode al = new AlphaNode( buildContext.getNextId(),
                                             lit,
@@ -116,7 +117,8 @@
 
         final CompositeRightTupleSinkAdapter ad = new CompositeRightTupleSinkAdapter();
         final LiteralConstraint lit = new LiteralConstraint( new MockExtractor(),
-                                                             equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ),
+                                                             equals.getEvaluator( ValueType.STRING_TYPE,
+                                                                                  Operator.EQUAL ),
                                                              new ObjectFieldImpl( "stilton" ) );
         final AlphaNode al = new AlphaNode( buildContext.getNextId(),
                                             lit,
@@ -133,7 +135,8 @@
                       ad.getSinks()[0] );
 
         final LiteralConstraint lit2 = new LiteralConstraint( new MockExtractor(),
-                                                              equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ),
+                                                              equals.getEvaluator( ValueType.STRING_TYPE,
+                                                                                   Operator.EQUAL ),
                                                               new ObjectFieldImpl( "cheddar" ) );
         final AlphaNode al2 = new AlphaNode( buildContext.getNextId(),
                                              lit2,
@@ -176,9 +179,10 @@
         FieldExtractor extractor = ClassFieldExtractorCache.getInstance().getExtractor( Cheese.class,
                                                                                         "type",
                                                                                         this.getClass().getClassLoader() );
-        
+
         final LiteralConstraint lit = new LiteralConstraint( extractor,
-                                                             equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ),
+                                                             equals.getEvaluator( ValueType.STRING_TYPE,
+                                                                                  Operator.EQUAL ),
                                                              new ObjectFieldImpl( "stilton" ) );
         final AlphaNode al = new AlphaNode( buildContext.getNextId(),
                                             lit,
@@ -195,7 +199,8 @@
                       ad.getSinks()[0] );
 
         final LiteralConstraint lit2 = new LiteralConstraint( extractor,
-                                                              equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ),
+                                                              equals.getEvaluator( ValueType.STRING_TYPE,
+                                                                                   Operator.EQUAL ),
                                                               new ObjectFieldImpl( "cheddar" ) );
         final AlphaNode al2 = new AlphaNode( buildContext.getNextId(),
                                              lit2,
@@ -209,7 +214,8 @@
                       ad.hashableSinks.size() );
 
         final LiteralConstraint lit3 = new LiteralConstraint( extractor,
-                                                              equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ),
+                                                              equals.getEvaluator( ValueType.STRING_TYPE,
+                                                                                   Operator.EQUAL ),
                                                               new ObjectFieldImpl( "stinky" ) );
         final AlphaNode al3 = new AlphaNode( buildContext.getNextId(),
                                              lit3,
@@ -235,9 +241,10 @@
         FieldExtractor extractor = ClassFieldExtractorCache.getInstance().getExtractor( Cheese.class,
                                                                                         "charType",
                                                                                         this.getClass().getClassLoader() );
-        
+
         final LiteralConstraint lit = new LiteralConstraint( extractor,
-                                                             equals.getEvaluator( extractor.getValueType(), Operator.EQUAL ),
+                                                             equals.getEvaluator( extractor.getValueType(),
+                                                                                  Operator.EQUAL ),
                                                              new LongFieldImpl( 65 ) ); // chars are handled as integers
         final AlphaNode al = new AlphaNode( buildContext.getNextId(),
                                             lit,
@@ -254,7 +261,8 @@
                       ad.getSinks()[0] );
 
         final LiteralConstraint lit2 = new LiteralConstraint( extractor,
-                                                              equals.getEvaluator( extractor.getValueType(), Operator.EQUAL ),
+                                                              equals.getEvaluator( extractor.getValueType(),
+                                                                                   Operator.EQUAL ),
                                                               new LongFieldImpl( 66 ) );
         final AlphaNode al2 = new AlphaNode( buildContext.getNextId(),
                                              lit2,
@@ -268,7 +276,8 @@
                       ad.hashableSinks.size() );
 
         final LiteralConstraint lit3 = new LiteralConstraint( extractor,
-                                                              equals.getEvaluator( extractor.getValueType(), Operator.EQUAL ),
+                                                              equals.getEvaluator( extractor.getValueType(),
+                                                                                   Operator.EQUAL ),
                                                               new LongFieldImpl( 67 ) );
         final AlphaNode al3 = new AlphaNode( buildContext.getNextId(),
                                              lit3,
@@ -279,18 +288,19 @@
         //this should now be nicely hashed.
         assertNotNull( ad.hashedSinkMap );
         assertNull( ad.hashableSinks );
-        
+
         // test propagation
         Cheese cheese = new Cheese();
         cheese.setCharType( 'B' );
         CompositeRightTupleSinkAdapter.HashKey hashKey = new CompositeRightTupleSinkAdapter.HashKey();
-        
+
         // should find this
         hashKey.setValue( extractor.getIndex(),
                           cheese,
                           extractor );
         RightTupleSink sink = (RightTupleSink) ad.hashedSinkMap.get( hashKey );
-        assertSame( al2, sink );
+        assertSame( al2,
+                    sink );
 
         // should not find this one
         cheese.setCharType( 'X' );
@@ -316,7 +326,8 @@
                                                                                         "type",
                                                                                         this.getClass().getClassLoader() );
         final LiteralConstraint lit1 = new LiteralConstraint( extractor,
-                                                              equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ),
+                                                              equals.getEvaluator( ValueType.STRING_TYPE,
+                                                                                   Operator.EQUAL ),
                                                               new ObjectFieldImpl( "stilton" ) );
         final AlphaNode al1 = new AlphaNode( buildContext.getNextId(),
                                              lit1,
@@ -324,7 +335,8 @@
                                              buildContext );
 
         final LiteralConstraint lit2 = new LiteralConstraint( extractor,
-                                                              equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ),
+                                                              equals.getEvaluator( ValueType.STRING_TYPE,
+                                                                                   Operator.EQUAL ),
                                                               new ObjectFieldImpl( "brie" ) );
         final AlphaNode al2 = new AlphaNode( buildContext.getNextId(),
                                              lit2,
@@ -332,7 +344,8 @@
                                              buildContext );
 
         final LiteralConstraint lit3 = new LiteralConstraint( extractor,
-                                                              equals.getEvaluator( ValueType.STRING_TYPE, Operator.EQUAL ),
+                                                              equals.getEvaluator( ValueType.STRING_TYPE,
+                                                                                   Operator.EQUAL ),
                                                               new ObjectFieldImpl( "muzzarela" ) );
         final AlphaNode al3 = new AlphaNode( buildContext.getNextId(),
                                              lit3,
@@ -343,11 +356,14 @@
         ad.addObjectSink( al2 );
         ad.addObjectSink( al3 );
 
-        InternalFactHandle handle = new ReteooFactHandleFactory().newFactHandle( new Cheese(), false, null );
+        InternalFactHandle handle = new ReteooFactHandleFactory().newFactHandle( new Cheese(),
+                                                                                 false,
+                                                                                 null );
         try {
-            ad.propagateAssertRightTuple( handle,
-                                      null,
-                                      null );
+            ad.propagateAssertRightTuple( new RightTuple( handle,
+                                                          null ),
+                                          null,
+                                          null );
         } catch ( RuntimeException e ) {
             fail( "Not supposed to throw any exception: " + e.getMessage() );
         }
@@ -494,15 +510,15 @@
         }
 
         public void assertRightTuple(final RightTuple rightTuple,
-                                 final PropagationContext context,
-                                 final InternalWorkingMemory workingMemory) {
+                                     final PropagationContext context,
+                                     final InternalWorkingMemory workingMemory) {
             //  Auto-generated method stub
 
         }
 
         public void retractRightTuple(final RightTuple rightTuple,
-                                  final PropagationContext context,
-                                  final InternalWorkingMemory workingMemory) {
+                                      final PropagationContext context,
+                                      final InternalWorkingMemory workingMemory) {
             //  Auto-generated method stub
 
         }

Modified: labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/JoinNodeTest.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/JoinNodeTest.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/JoinNodeTest.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -34,7 +34,6 @@
 import org.drools.spi.BetaNodeFieldConstraint;
 import org.drools.spi.MockConstraint;
 import org.drools.spi.PropagationContext;
-import org.drools.util.FactEntry;
 import org.drools.util.Iterator;
 
 public class JoinNodeTest extends DroolsTestCase {
@@ -65,10 +64,11 @@
         this.sink = new MockTupleSink();
 
         final RuleBaseConfiguration configuration = new RuleBaseConfiguration();
-        
-        ReteooRuleBase ruleBase = ( ReteooRuleBase ) RuleBaseFactory.newRuleBase();
-        BuildContext buildContext = new BuildContext( ruleBase, ruleBase.getReteooBuilder().getIdGenerator() );
 
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        BuildContext buildContext = new BuildContext( ruleBase,
+                                                      ruleBase.getReteooBuilder().getIdGenerator() );
+
         this.node = new JoinNode( 15,
                                   this.tupleSource,
                                   this.objectSource,
@@ -128,8 +128,9 @@
         final MockObjectSource objectSource = new MockObjectSource( 1 );
         final MockTupleSource tupleSource = new MockTupleSource( 1 );
 
-        ReteooRuleBase ruleBase = ( ReteooRuleBase ) RuleBaseFactory.newRuleBase();
-        BuildContext buildContext = new BuildContext( ruleBase, ruleBase.getReteooBuilder().getIdGenerator() );        
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        BuildContext buildContext = new BuildContext( ruleBase,
+                                                      ruleBase.getReteooBuilder().getIdGenerator() );
         final JoinNode joinNode = new JoinNode( 2,
                                                 tupleSource,
                                                 objectSource,
@@ -149,8 +150,11 @@
     public void testAssertTuple() throws Exception {
         final DefaultFactHandle f0 = new DefaultFactHandle( 0,
                                                             "cheese" );
-        final LeftTuple tuple0 = new LeftTuple( f0 );
+        RightTuple rightTuplef0 = new RightTuple( f0,
+                                                  null );
 
+        final LeftTuple tuple0 = new LeftTuple( rightTuplef0, this.node );
+
         // assert tuple, should add one to left memory
         this.node.assertTuple( tuple0,
                                this.context,
@@ -164,7 +168,10 @@
         // assert tuple, should add left memory should be 2
         final DefaultFactHandle f1 = new DefaultFactHandle( 1,
                                                             "cheese" );
-        final LeftTuple tuple1 = new LeftTuple( f1 );
+        RightTuple rightTuplef1 = new RightTuple( f1,
+                                                  null );
+
+        final LeftTuple tuple1 = new LeftTuple( rightTuplef1, this.node );
         this.node.assertTuple( tuple1,
                                this.context,
                                this.workingMemory );
@@ -172,10 +179,11 @@
                       this.memory.getLeftTupleMemory().size() );
 
         final Iterator it = this.memory.getLeftTupleMemory().iterator();
+        assertEquals( tuple1,
+                      it.next() );
         assertEquals( tuple0,
                       it.next() );
-        assertEquals( tuple1,
-                      it.next() );
+        assertNull( it.next() );
     }
 
     /**
@@ -190,18 +198,19 @@
         this.workingMemory = new ReteooWorkingMemory( 1,
                                                       (ReteooRuleBase) RuleBaseFactory.newRuleBase( conf ) );
 
-        ReteooRuleBase ruleBase = ( ReteooRuleBase ) RuleBaseFactory.newRuleBase();
-        BuildContext buildContext = new BuildContext( ruleBase, ruleBase.getReteooBuilder().getIdGenerator() );
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        BuildContext buildContext = new BuildContext( ruleBase,
+                                                      ruleBase.getReteooBuilder().getIdGenerator() );
         buildContext.setTupleMemoryEnabled( false );
         buildContext.setObjectTypeNodeMemoryEnabled( false );
-        
+
         // override setup, so its working in sequential mode
         this.node = new JoinNode( 15,
                                   this.tupleSource,
                                   this.objectSource,
                                   new DefaultBetaConstraints( new BetaNodeFieldConstraint[]{this.constraint},
                                                               conf ),
-                                  buildContext);
+                                  buildContext );
 
         this.node.addTupleSink( this.sink );
 
@@ -209,12 +218,20 @@
 
         final DefaultFactHandle f0 = new DefaultFactHandle( 0,
                                                             "cheese" );
-        final LeftTuple tuple0 = new LeftTuple( f0 );
+        RightTuple rightTuplef0 = new RightTuple( f0,
+                                                  null );
 
-        this.node.assertRightTuple( f0,
-                                this.context,
-                                this.workingMemory );
+        final DefaultFactHandle f1 = new DefaultFactHandle( 0,
+                                                            "beans" );
+        RightTuple rightTuplef1 = new RightTuple( f0,
+                                                  null );
 
+        final LeftTuple tuple0 = new LeftTuple( rightTuplef1, this.node );
+
+        this.node.assertRightTuple( rightTuplef0,
+                                    this.context,
+                                    this.workingMemory );
+
         // assert tuple
         this.node.assertTuple( tuple0,
                                this.context,
@@ -229,7 +246,7 @@
                       this.memory.getRightTupleMemory().size() );
 
         assertEquals( new LeftTuple( tuple0,
-                                     f0 ),
+                                     rightTuplef0, this.node ),
                       ((Object[]) this.sink.getAsserted().get( 0 ))[0] );
     }
 
@@ -240,11 +257,13 @@
      */
     public void testAssertObject() throws Exception {
         final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.insert( "test0" );
+        RightTuple rightTuplef0 = new RightTuple( f0,
+                                                  null );
 
         // assert object, should add one to right memory
-        this.node.assertRightTuple( f0,
-                                this.context,
-                                this.workingMemory );
+        this.node.assertRightTuple( rightTuplef0,
+                                    this.context,
+                                    this.workingMemory );
         assertEquals( 0,
                       this.memory.getLeftTupleMemory().size() );
         assertEquals( 1,
@@ -252,20 +271,26 @@
 
         // check new objects/handles still assert
         final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory.insert( "test1" );
-        this.node.assertRightTuple( f1,
-                                this.context,
-                                this.workingMemory );
+        RightTuple rightTuplef1 = new RightTuple( f1,
+                                                  null );
+
+        this.node.assertRightTuple( rightTuplef1,
+                                    this.context,
+                                    this.workingMemory );
         assertEquals( 2,
                       this.memory.getRightTupleMemory().size() );
 
-        final Iterator it = this.memory.getRightTupleMemory().iterator( new LeftTuple( f0 ) );
+        RightTuple rightTuple = this.memory.getRightTupleMemory().getFirst( new LeftTuple( rightTuplef0, this.node ) );
 
-        final InternalFactHandle rf0 = ((FactEntry) it.next()).getFactHandle();
-        final InternalFactHandle rf1 = ((FactEntry) it.next()).getFactHandle();
+        final InternalFactHandle rf0 = rightTuple.getHandle();
+        rightTuple = (RightTuple) rightTuple.getNext();
+        final InternalFactHandle rf1 = rightTuple.getHandle();
 
+        assertNull( rightTuple.getNext() );
+
+        assertEquals( f1,
+                      rf0 );
         assertEquals( f0,
-                      rf0 );
-        assertEquals( f1,
                       rf1 );
     }
 
@@ -277,14 +302,20 @@
     public void testAssertPropagations() throws Exception {
         // assert first right object
         final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.insert( "test0" );
-        this.node.assertRightTuple( f0,
-                                this.context,
-                                this.workingMemory );
+        RightTuple rightTuplef0 = new RightTuple( f0,
+                                                  null );
 
+        this.node.assertRightTuple( rightTuplef0,
+                                    this.context,
+                                    this.workingMemory );
+
         // assert tuple, should add left memory should be 2
         final DefaultFactHandle f1 = new DefaultFactHandle( 1,
                                                             "cheese" );
-        final LeftTuple tuple1 = new LeftTuple( f1 );
+        RightTuple rightTuplef1 = new RightTuple( f1,
+                                                  null );
+
+        final LeftTuple tuple1 = new LeftTuple( rightTuplef1, this.node );
         this.node.assertTuple( tuple1,
                                this.context,
                                this.workingMemory );
@@ -293,12 +324,14 @@
                       this.sink.getAsserted().size() );
 
         assertEquals( new LeftTuple( tuple1,
-                                     f0 ),
+                                     rightTuplef0, this.node ),
                       ((Object[]) this.sink.getAsserted().get( 0 ))[0] );
 
         final DefaultFactHandle f2 = new DefaultFactHandle( 2,
                                                             "cheese" );
-        final LeftTuple tuple2 = new LeftTuple( f2 );
+        RightTuple rightTuplef2 = new RightTuple( f2,
+                                                  null );
+        final LeftTuple tuple2 = new LeftTuple( rightTuplef2, this.node );
         this.node.assertTuple( tuple2,
                                this.context,
                                this.workingMemory );
@@ -306,13 +339,15 @@
         assertEquals( 2,
                       this.sink.getAsserted().size() );
         assertEquals( new LeftTuple( tuple2,
-                                     f0 ),
+                                     rightTuplef0, this.node ),
                       ((Object[]) this.sink.getAsserted().get( 1 ))[0] );
 
         final DefaultFactHandle f3 = (DefaultFactHandle) this.workingMemory.insert( "test2" );
-        this.node.assertRightTuple( f3,
-                                this.context,
-                                this.workingMemory );
+        RightTuple rightTuplef3 = new RightTuple( f3,
+                                                  null );
+        this.node.assertRightTuple( rightTuplef3,
+                                    this.context,
+                                    this.workingMemory );
 
         assertEquals( 4,
                       this.sink.getAsserted().size() );
@@ -322,9 +357,9 @@
         tuples.add( ((Object[]) this.sink.getAsserted().get( 3 ))[0] );
 
         assertTrue( tuples.contains( new LeftTuple( tuple1,
-                                                    f3 ) ) );
+                                                    rightTuplef3, this.node ) ) );
         assertTrue( tuples.contains( new LeftTuple( tuple2,
-                                                    f3 ) ) );
+                                                    rightTuplef3, this.node ) ) );
     }
 
     /**
@@ -336,43 +371,55 @@
     public void testRetractTuple() throws Exception {
         // setup 2 tuples 3 fact handles
         final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.insert( "test0" );
-        this.node.assertRightTuple( f0,
-                                this.context,
-                                this.workingMemory );
+        RightTuple rightTuplef0 = new RightTuple( f0,
+                                                  null );
 
+        this.node.assertRightTuple( rightTuplef0,
+                                    this.context,
+                                    this.workingMemory );
+
         final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory.insert( "test1" );
-        final LeftTuple tuple1 = new LeftTuple( f1 );
+        RightTuple rightTuplef1 = new RightTuple( f0,
+                                                  null );
+
+        final LeftTuple tuple1 = new LeftTuple( rightTuplef1, this.node );
         this.node.assertTuple( tuple1,
                                this.context,
                                this.workingMemory );
 
         final DefaultFactHandle f2 = (DefaultFactHandle) this.workingMemory.insert( "test2" );
-        final LeftTuple tuple2 = new LeftTuple( f2 );
+        RightTuple rightTuplef2 = new RightTuple( f2,
+                                                  null );
+        final LeftTuple tuple2 = new LeftTuple( rightTuplef2, this.node );
         this.node.assertTuple( tuple2,
                                this.context,
                                this.workingMemory );
 
         final DefaultFactHandle f3 = (DefaultFactHandle) this.workingMemory.insert( "test3" );
-        this.node.assertRightTuple( f3,
-                                this.context,
-                                this.workingMemory );
+        RightTuple rightTuplef3 = new RightTuple( f3,
+                                                  null );
+        this.node.assertRightTuple( rightTuplef3,
+                                    this.context,
+                                    this.workingMemory );
 
         final DefaultFactHandle f4 = (DefaultFactHandle) this.workingMemory.insert( "test4" );
-        this.node.assertRightTuple( f4,
-                                this.context,
-                                this.workingMemory );
+        RightTuple rightTuplef4 = new RightTuple( f4,
+                                                  null );
+        this.node.assertRightTuple( rightTuplef4,
+                                    this.context,
+                                    this.workingMemory );
 
         assertLength( 6,
                       this.sink.getAsserted() );
 
         // Double check the item is in memory
         final BetaMemory memory = (BetaMemory) this.workingMemory.getNodeMemory( this.node );
-        assertTrue( memory.getRightTupleMemory().contains( f0 ) );
+        assertTrue( memory.getRightTupleMemory().contains( rightTuplef0 ) );
 
         // Retract an object, check propagations  and memory
-        this.node.retractRightTuple( f0,
-                                 this.context,
-                                 this.workingMemory );
+        this.node.retractRightTuple( rightTuplef0,
+                                     this.context,
+                                     this.workingMemory );
         assertLength( 2,
                       this.sink.getRetracted() );
 
@@ -381,12 +428,12 @@
         tuples.add( ((Object[]) this.sink.getRetracted().get( 1 ))[0] );
 
         assertTrue( tuples.contains( new LeftTuple( tuple1,
-                                                    f0 ) ) );
+                                                    rightTuplef0, this.node ) ) );
         assertTrue( tuples.contains( new LeftTuple( tuple1,
-                                                    f0 ) ) );
+                                                    rightTuplef1, this.node ) ) );
 
         // Now check the item  is no longer in memory
-        assertFalse( memory.getRightTupleMemory().contains( f0 ) );
+        assertFalse( memory.getRightTupleMemory().contains( rightTuplef0 ) );
 
         this.node.retractTuple( tuple2,
                                 this.context,
@@ -399,23 +446,27 @@
         tuples.add( ((Object[]) this.sink.getRetracted().get( 3 ))[0] );
 
         assertTrue( tuples.contains( new LeftTuple( tuple2,
-                                                    f3 ) ) );
+                                                    rightTuplef3, this.node ) ) );
         assertTrue( tuples.contains( new LeftTuple( tuple2,
-                                                    f4 ) ) );
+                                                    rightTuplef4, this.node ) ) );
     }
 
     public void testConstraintPropagations() throws Exception {
         this.constraint.isAllowed = false;
         // assert first right object
         final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.insert( "test0" );
-        this.node.assertRightTuple( f0,
-                                this.context,
-                                this.workingMemory );
+        RightTuple rightTuplef0 = new RightTuple( f0,
+                                                  null );        
+        this.node.assertRightTuple( rightTuplef0,
+                                    this.context,
+                                    this.workingMemory );
 
         // assert tuple, should add left memory should be 2
         final DefaultFactHandle f1 = new DefaultFactHandle( 1,
                                                             "cheese" );
-        final LeftTuple tuple1 = new LeftTuple( f1 );
+        RightTuple rightTuplef1 = new RightTuple( f1,
+                                                  null );          
+        final LeftTuple tuple1 = new LeftTuple( rightTuplef1, this.node );
         this.node.assertTuple( tuple1,
                                this.context,
                                this.workingMemory );
@@ -424,9 +475,9 @@
         assertLength( 0,
                       this.sink.getAsserted() );
 
-        this.node.retractRightTuple( f0,
-                                 this.context,
-                                 this.workingMemory );
+        this.node.retractRightTuple( rightTuplef0,
+                                     this.context,
+                                     this.workingMemory );
         assertLength( 0,
                       this.sink.getRetracted() );
     }
@@ -435,9 +486,10 @@
         final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory( 1,
                                                                            (ReteooRuleBase) RuleBaseFactory.newRuleBase() );
 
-        ReteooRuleBase ruleBase = ( ReteooRuleBase ) RuleBaseFactory.newRuleBase();
-        BuildContext buildContext = new BuildContext( ruleBase, ruleBase.getReteooBuilder().getIdGenerator() );
-        
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        BuildContext buildContext = new BuildContext( ruleBase,
+                                                      ruleBase.getReteooBuilder().getIdGenerator() );
+
         final JoinNode joinNode = new JoinNode( 1,
                                                 this.tupleSource,
                                                 this.objectSource,
@@ -451,8 +503,10 @@
 
         final DefaultFactHandle f0 = new DefaultFactHandle( 0,
                                                             "string0" );
+        RightTuple rightTuplef0 = new RightTuple( f0,
+                                                  null );          
 
-        final LeftTuple tuple1 = new LeftTuple( f0 );
+        final LeftTuple tuple1 = new LeftTuple( rightTuplef0, joinNode );
 
         joinNode.assertTuple( tuple1,
                               this.context,
@@ -461,10 +515,12 @@
         final String string1 = "string1";
         final DefaultFactHandle string1Handle = new DefaultFactHandle( 1,
                                                                        string1 );
+        RightTuple string1HandleTuple = new RightTuple( string1Handle,
+                                                  null );         
 
-        joinNode.assertRightTuple( string1Handle,
-                               this.context,
-                               workingMemory );
+        joinNode.assertRightTuple( string1HandleTuple,
+                                   this.context,
+                                   workingMemory );
 
         assertLength( 1,
                       sink1.getAsserted() );

Modified: labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/LeftInputAdapterNodeTest.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/LeftInputAdapterNodeTest.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/LeftInputAdapterNodeTest.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -33,13 +33,14 @@
 
 public class LeftInputAdapterNodeTest extends DroolsTestCase {
     private ReteooRuleBase ruleBase;
-    private BuildContext buildContext;
-    
+    private BuildContext   buildContext;
+
     protected void setUp() throws Exception {
-        this.ruleBase = ( ReteooRuleBase ) RuleBaseFactory.newRuleBase();
-        this.buildContext = new BuildContext( ruleBase, ((ReteooRuleBase)ruleBase).getReteooBuilder().getIdGenerator() );
+        this.ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        this.buildContext = new BuildContext( ruleBase,
+                                              ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator() );
     }
-    
+
     public void testLeftInputAdapterNode() {
         final MockObjectSource source = new MockObjectSource( 15 );
         final LeftInputAdapterNode liaNode = new LeftInputAdapterNode( 23,
@@ -108,10 +109,13 @@
 
         // assert object
         final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory.insert( string1 );
-        liaNode.assertRightTuple( f0,
-                              context,
-                              workingMemory );
+        RightTuple rightTuplef0 = new RightTuple( f0,
+                                                  liaNode );
 
+        liaNode.assertRightTuple( rightTuplef0,
+                                  context,
+                                  workingMemory );
+
         final List asserted = sink.getAsserted();
         assertLength( 1,
                       asserted );
@@ -126,7 +130,7 @@
      * 
      * @throws Exception
      */
-    public void testAssertObjectWithMemory() throws Exception {        
+    public void testAssertObjectWithMemory() throws Exception {
         final PropagationContext context = new PropagationContextImpl( 0,
                                                                        PropagationContext.ASSERTION,
                                                                        null,
@@ -134,7 +138,7 @@
 
         ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
         IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
-        final InternalWorkingMemory workingMemory = ( InternalWorkingMemory ) ruleBase.newStatefulSession();                
+        final InternalWorkingMemory workingMemory = (InternalWorkingMemory) ruleBase.newStatefulSession();
 
         final LeftInputAdapterNode liaNode = new LeftInputAdapterNode( idGenerator.getNextId(),
                                                                        new MockObjectSource( idGenerator.getNextId() ),
@@ -149,9 +153,12 @@
 
         // assert object
         final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory.insert( string1 );
-        liaNode.assertRightTuple( f0,
-                              context,
-                              workingMemory );
+        RightTuple rightTuplef0 = new RightTuple( f0,
+                                                  liaNode );
+        
+        liaNode.assertRightTuple( rightTuplef0,
+                                  context,
+                                  workingMemory );
 
         final List asserted = sink.getAsserted();
         assertLength( 1,
@@ -168,9 +175,12 @@
 
         // check memory works with multiple handles
         final DefaultFactHandle f1 = (DefaultFactHandle) workingMemory.insert( "test1" );
-        liaNode.assertRightTuple( f1,
-                              context,
-                              workingMemory );
+        RightTuple rightTuplef1 = new RightTuple( f1,
+                                                  liaNode );
+        
+        liaNode.assertRightTuple( rightTuplef1,
+                                  context,
+                                  workingMemory );
 
         assertLength( 2,
                       asserted );
@@ -209,17 +219,18 @@
         liaNode.addTupleSink( sink );
 
         final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory.insert( "f1" );
-
+        RightTuple rightTuplef0 = new RightTuple( f0,
+                                                  liaNode );
         // assert object 
-        liaNode.assertRightTuple( f0,
-                              context,
-                              workingMemory );
+        liaNode.assertRightTuple( rightTuplef0,
+                                  context,
+                                  workingMemory );
 
         final Tuple tuple = (Tuple) ((Object[]) sink.getAsserted().get( 0 ))[0];
 
-        liaNode.retractRightTuple( f0,
-                               context,
-                               workingMemory );
+        liaNode.retractRightTuple( rightTuplef0,
+                                   context,
+                                   workingMemory );
 
         assertEquals( tuple,
                       ((Object[]) sink.getRetracted().get( 0 ))[0] );
@@ -236,7 +247,7 @@
 
         ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
         IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
-        final InternalWorkingMemory workingMemory = ( InternalWorkingMemory ) ruleBase.newStatefulSession();                
+        final InternalWorkingMemory workingMemory = (InternalWorkingMemory) ruleBase.newStatefulSession();
 
         final LeftInputAdapterNode liaNode = new LeftInputAdapterNode( idGenerator.getNextId(),
                                                                        new MockObjectSource( idGenerator.getNextId() ),
@@ -248,20 +259,21 @@
         liaNode.addTupleSink( sink );
 
         final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory.insert( "f1" );
-
+        RightTuple rightTuplef0 = new RightTuple( f0,
+                                                  liaNode );
         // assert object
-        liaNode.assertRightTuple( f0,
-                              context,
-                              workingMemory );
+        liaNode.assertRightTuple( rightTuplef0,
+                                  context,
+                                  workingMemory );
 
         final Tuple tuple = (Tuple) ((Object[]) sink.getAsserted().get( 0 ))[0];
 
         final FactHashTable map = (FactHashTable) workingMemory.getNodeMemory( liaNode );
         assertTrue( map.contains( f0 ) );
 
-        liaNode.retractRightTuple( f0,
-                               context,
-                               workingMemory );
+        liaNode.retractRightTuple( rightTuplef0,
+                                   context,
+                                   workingMemory );
 
         assertFalse( map.contains( f0 ) );
 

Modified: labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/MockObjectSource.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/MockObjectSource.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/MockObjectSource.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -65,7 +65,7 @@
         this.updated++;
         for ( final Iterator it = this.facts.iterator(); it.hasNext(); ) {
             final InternalFactHandle handle = (InternalFactHandle) it.next();
-            sink.assertRightTuple( handle,
+            sink.assertRightTuple( new RightTuple( handle ),
                                context,
                                workingMemory );
         }

Modified: labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/MockTupleSink.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/MockTupleSink.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/MockTupleSink.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -159,4 +159,9 @@
         
     }
 
+    public LeftTupleSinkNode getPreviousLeftTupleSinkNode() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
 }
\ No newline at end of file

Modified: labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/NotNodeTest.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/NotNodeTest.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/NotNodeTest.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -99,8 +99,11 @@
         final Cheese cheddar = new Cheese( "cheddar",
                                            10 );
         final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.insert( cheddar );
+        RightTuple rightTuplef0 = new RightTuple( f0,
+                                                  null );
 
-        final LeftTuple tuple1 = new LeftTuple( f0 );
+        final LeftTuple tuple1 = new LeftTuple( rightTuplef0,
+                                                this.node );
 
         this.node.assertTuple( tuple1,
                                this.context,
@@ -113,17 +116,24 @@
         assertLength( 0,
                       this.sink.getRetracted() );
 
-        assertEquals( new LeftTuple( f0 ),
+        // as propagated should 1be in the memory
+        assertEquals( 1,
+                      this.memory.getLeftTupleMemory().size() );
+
+        assertEquals( new LeftTuple( rightTuplef0,
+                                     this.node ),
                       ((Object[]) this.sink.getAsserted().get( 0 ))[0] );
 
         // assert will match, so propagated tuple should be retracted
         final Cheese brie = new Cheese( "brie",
                                         10 );
         final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory.insert( brie );
+        RightTuple rightTuplef1 = new RightTuple( f1,
+                                                  null );
 
-        this.node.assertRightTuple( f1,
-                                this.context,
-                                this.workingMemory );
+        this.node.assertRightTuple( rightTuplef1,
+                                    this.context,
+                                    this.workingMemory );
 
         // check no as assertions, but should be one retraction
         assertLength( 1,
@@ -132,13 +142,23 @@
         assertLength( 1,
                       this.sink.getRetracted() );
 
-        assertEquals( new LeftTuple( f0 ),
+        assertEquals( new LeftTuple( rightTuplef0,
+                                     this.node ),
                       ((Object[]) this.sink.getRetracted().get( 0 ))[0] );
 
+        // is blocked, so should not be in left memory
+        assertEquals( 0,
+                      this.memory.getLeftTupleMemory().size() );
+        assertEquals( 1,
+                      this.memory.getRightTupleMemory().size() );
+
         // assert tuple, will have matches, so no propagation
         final DefaultFactHandle f2 = (DefaultFactHandle) this.workingMemory.insert( new Cheese( "gouda",
                                                                                                 10 ) );
-        final LeftTuple tuple2 = new LeftTuple( f2 );
+        RightTuple rightTuplef2 = new RightTuple( f2,
+                                                  null );
+        final LeftTuple tuple2 = new LeftTuple( rightTuplef2,
+                                                this.node );
         this.node.assertTuple( tuple2,
                                this.context,
                                this.workingMemory );
@@ -150,16 +170,16 @@
         assertLength( 1,
                       this.sink.getRetracted() );
 
-        // check memory sizes
-        assertEquals( 2,
+        // is blocked, so should still  be zero in memory
+        assertEquals( 0,
                       this.memory.getLeftTupleMemory().size() );
         assertEquals( 1,
                       this.memory.getRightTupleMemory().size() );
 
         // When this is retracter both tuples should assert
-        this.node.retractRightTuple( f1,
-                                 this.context,
-                                 this.workingMemory );
+        this.node.retractRightTuple( rightTuplef1,
+                                     this.context,
+                                     this.workingMemory );
 
         // check propagations 
         assertLength( 3,
@@ -167,6 +187,12 @@
 
         assertLength( 1,
                       this.sink.getRetracted() );
+
+        // unblocked blocked, so should now be 2 in left memory and as right was retracted should be 0
+        assertEquals( 2,
+                      this.memory.getLeftTupleMemory().size() );
+        assertEquals( 0,
+                      this.memory.getRightTupleMemory().size() );
     }
 
     /**
@@ -181,8 +207,11 @@
         final Cheese cheddar = new Cheese( "cheddar",
                                            10 );
         final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.insert( cheddar );
+        RightTuple rightTuplef0 = new RightTuple( f0,
+                                                  null );
 
-        final LeftTuple tuple1 = new LeftTuple( f0 );
+        final LeftTuple tuple1 = new LeftTuple( rightTuplef0,
+                                                this.node );
 
         this.node.assertTuple( tuple1,
                                this.context,
@@ -195,17 +224,20 @@
         assertLength( 0,
                       this.sink.getRetracted() );
 
-        assertEquals( new LeftTuple( f0 ),
+        assertEquals( new LeftTuple( rightTuplef0,
+                                     this.node ),
                       ((Object[]) this.sink.getAsserted().get( 0 ))[0] );
 
         // assert will not match, so activation should stay propagated
         final Cheese brie = new Cheese( "brie",
                                         10 );
         final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory.insert( brie );
+        RightTuple rightTuplef1 = new RightTuple( f0,
+                                                  null );
 
-        this.node.assertRightTuple( f1,
-                                this.context,
-                                this.workingMemory );
+        this.node.assertRightTuple( rightTuplef1,
+                                    this.context,
+                                    this.workingMemory );
 
         // check no as assertions, but should be one retraction
         assertLength( 1,
@@ -217,7 +249,10 @@
         // assert tuple, will have no matches, so do assert propagation
         final DefaultFactHandle f2 = (DefaultFactHandle) this.workingMemory.insert( new Cheese( "gouda",
                                                                                                 10 ) );
-        final LeftTuple tuple2 = new LeftTuple( f2 );
+        RightTuple rightTuplef2 = new RightTuple( f2,
+                                                  null );
+        final LeftTuple tuple2 = new LeftTuple( rightTuplef2,
+                                                this.node );
         this.node.assertTuple( tuple2,
                                this.context,
                                this.workingMemory );
@@ -236,80 +271,103 @@
      * @throws AssertionException
      */
     public void testNotMemoryManagement() throws FactException {
-        try {
-            // assert tuple
-            final Cheese cheddar = new Cheese( "cheddar",
-                                               10 );
-            final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.insert( cheddar );
-            final LeftTuple tuple1 = new LeftTuple( f0 );
+        // assert tuple
+        final Cheese cheddar = new Cheese( "cheddar",
+                                           10 );
+        final DefaultFactHandle f0 = (DefaultFactHandle) this.workingMemory.insert( cheddar );
+        RightTuple rightTuplef0 = new RightTuple( f0,
+                                                  null );
+        final LeftTuple tuple1 = new LeftTuple( rightTuplef0,
+                                                this.node );
 
-            this.node.assertTuple( tuple1,
-                                   this.context,
-                                   this.workingMemory );
+        this.node.assertTuple( tuple1,
+                               this.context,
+                               this.workingMemory );
 
-            // assert will match, so propagated tuple should be retracted
-            final Cheese brie = new Cheese( "brie",
-                                            10 );
-            final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory.insert( brie );
+        assertLength( 1,
+                      this.sink.getAsserted() );
 
-            // Initially, no objects in right memory
-            assertEquals( 0,
-                          this.memory.getRightTupleMemory().size() );
-            this.node.assertRightTuple( f1,
+        // LeftTuple is propagated so keep it in memory for potential RightTuple blockage
+        assertEquals( 1,
+                      this.memory.getLeftTupleMemory().size() );
+
+        // assert will match, so propagated tuple should be retracted
+        final Cheese brie = new Cheese( "brie",
+                                        10 );
+        final DefaultFactHandle f1 = (DefaultFactHandle) this.workingMemory.insert( brie );
+        RightTuple rightTuplef1 = new RightTuple( f1,
+                                                  null );
+
+        // Initially, no objects in right memory
+        assertEquals( 0,
+                      this.memory.getRightTupleMemory().size() );
+        this.node.assertRightTuple( rightTuplef1,
                                     this.context,
                                     this.workingMemory );
 
-            // Now, needs to have 1 object in right memory
-            assertEquals( 1,
-                          this.memory.getRightTupleMemory().size() );
+        // Left Tuple is matched and removed from memory
+        assertLength( 1,
+                      this.sink.getRetracted() );
 
-            // simulate modify
-            this.node.retractRightTuple( f1,
+        // Left tuple is now matched, so removed from memory
+        assertEquals( 0,
+                      this.memory.getLeftTupleMemory().size() );
+
+        // Now, needs to have 1 object in right memory
+        assertEquals( 1,
+                      this.memory.getRightTupleMemory().size() );
+
+        // simulate modify
+        this.node.retractRightTuple( rightTuplef1,
                                      this.context,
                                      this.workingMemory );
-            this.node.assertRightTuple( f1,
+        this.node.assertRightTuple( rightTuplef1,
                                     this.context,
                                     this.workingMemory );
-            // Memory should not change
-            assertEquals( 1,
-                          this.memory.getRightTupleMemory().size() );
+        // Memory should not change
+        assertEquals( 1,
+                      this.memory.getRightTupleMemory().size() );
+        assertEquals( 0,
+                      this.memory.getLeftTupleMemory().size() );
+        assertLength( 2,
+                      this.sink.getAsserted() );
+        assertLength( 2,
+                      this.sink.getRetracted() );
 
-            // When this is retracter both tuples should assert
-            this.node.retractRightTuple( f1,
+        // When this is retracted  both tuples should assert
+        this.node.retractRightTuple( rightTuplef1,
                                      this.context,
                                      this.workingMemory );
-            assertEquals( 0,
-                          this.memory.getRightTupleMemory().size() );
+        assertEquals( 0,
+                      this.memory.getRightTupleMemory().size() );
 
-            // check memory sizes
-            assertEquals( 1,
-                          this.memory.getLeftTupleMemory().size() );
+        // check memory sizes
+        assertEquals( 1,
+                      this.memory.getLeftTupleMemory().size() );
 
-            // simulate modify
-            this.node.retractTuple( tuple1,
-                                    this.context,
-                                    this.workingMemory );
-            this.node.assertTuple( tuple1,
-                                   this.context,
-                                   this.workingMemory );
-            assertEquals( 1,
-                          this.memory.getLeftTupleMemory().size() );
-            this.node.retractTuple( tuple1,
-                                    this.context,
-                                    this.workingMemory );
-            assertEquals( 0,
-                          this.memory.getLeftTupleMemory().size() );
-        } catch ( final Exception e ) {
-            Assert.fail( "No exception should be raised in this procedure, but got: " + e.toString() );
-        }
+        // simulate modify
+        this.node.retractTuple( tuple1,
+                                this.context,
+                                this.workingMemory );
+        this.node.assertTuple( tuple1,
+                               this.context,
+                               this.workingMemory );
+        assertEquals( 1,
+                      this.memory.getLeftTupleMemory().size() );
+        this.node.retractTuple( tuple1,
+                                this.context,
+                                this.workingMemory );
+        assertEquals( 0,
+                      this.memory.getLeftTupleMemory().size() );
     }
 
     public void testGetConstraints_ReturnsNullEvenWithEmptyBinder() {
         final BetaConstraints nullConstraints = EmptyBetaConstraints.getInstance();
-        
-        ReteooRuleBase ruleBase = ( ReteooRuleBase ) RuleBaseFactory.newRuleBase();
-        BuildContext buildContext = new BuildContext( ruleBase, ruleBase.getReteooBuilder().getIdGenerator() );
-        
+
+        ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        BuildContext buildContext = new BuildContext( ruleBase,
+                                                      ruleBase.getReteooBuilder().getIdGenerator() );
+
         final NotNode notNode = new NotNode( 1,
                                              this.tupleSource,
                                              this.objectSource,
@@ -330,13 +388,13 @@
         conf.setSequential( true );
 
         ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase( conf );
-        
+
         this.workingMemory = new ReteooWorkingMemory( 1,
                                                       ruleBase );
 
         BuildContext buildContext = new BuildContext( ruleBase,
                                                       ruleBase.getReteooBuilder().getIdGenerator() );
-        
+
         buildContext.setTupleMemoryEnabled( false );
         buildContext.setObjectTypeNodeMemoryEnabled( false );
         buildContext.setTerminalNodeMemoryEnabled( false );
@@ -355,11 +413,14 @@
 
         final DefaultFactHandle f0 = new DefaultFactHandle( 0,
                                                             "cheese" );
-        final LeftTuple tuple0 = new LeftTuple( f0 );
+        RightTuple rightTuplef0 = new RightTuple( f0,
+                                                  null );
+        final LeftTuple tuple0 = new LeftTuple( rightTuplef0,
+                                                this.node );
 
-        this.node.assertRightTuple( f0,
-                                this.context,
-                                this.workingMemory );
+        this.node.assertRightTuple( rightTuplef0,
+                                    this.context,
+                                    this.workingMemory );
 
         // assert tuple
         this.node.assertTuple( tuple0,

Modified: labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/ObjectTypeNodeTest.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/ObjectTypeNodeTest.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/ObjectTypeNodeTest.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -44,17 +44,18 @@
 
 public class ObjectTypeNodeTest extends DroolsTestCase {
     private ReteooRuleBase ruleBase;
-    private BuildContext buildContext;
-    
+    private BuildContext   buildContext;
+
     protected void setUp() throws Exception {
-        this.ruleBase = ( ReteooRuleBase ) RuleBaseFactory.newRuleBase();
-        this.buildContext = new BuildContext( ruleBase, ((ReteooRuleBase)ruleBase).getReteooBuilder().getIdGenerator() );
+        this.ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
+        this.buildContext = new BuildContext( ruleBase,
+                                              ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator() );
     }
-    
+
     public void testAttach() throws Exception {
         IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
 
-        final Rete source = this.ruleBase.getRete();    
+        final Rete source = this.ruleBase.getRete();
 
         final ObjectType objectType = new ClassObjectType( String.class );
 
@@ -89,7 +90,7 @@
         ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
         IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
 
-        final ReteooWorkingMemory workingMemory = ( ReteooWorkingMemory ) ruleBase.newStatefulSession();
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
 
         final Rete source = ruleBase.getRete();
 
@@ -105,24 +106,24 @@
         final InternalFactHandle handle1 = (InternalFactHandle) workingMemory.insert( string1 );
 
         // should assert as ObjectType matches
-        objectTypeNode.assertRightTuple( handle1,
-                                     context,
-                                     workingMemory );
+        objectTypeNode.assertRightTuple( new RightTuple( handle1 ),
+                                         context,
+                                         workingMemory );
 
         // make sure just string1 was asserted 
         final List asserted = sink.getAsserted();
         assertLength( 1,
                       asserted );
         assertSame( string1,
-                    workingMemory.getObject( (DefaultFactHandle) ((Object[]) asserted.get( 0 ))[0] ) );
+                    workingMemory.getObject( ((RightTuple) ((Object[]) asserted.get( 0 ))[0]).getHandle() ) );
 
         // check asserted object was added to memory
         final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( objectTypeNode );
         assertEquals( 1,
                       memory.size() );
-        assertTrue( memory.contains( handle1 ) );
+        assertTrue( memory.contains( new RightTuple( handle1 ) ) );
     }
-    
+
     public void testAssertObjectSequentialMode() {
         final PropagationContext context = new PropagationContextImpl( 0,
                                                                        PropagationContext.ASSERTION,
@@ -132,9 +133,10 @@
         RuleBaseConfiguration conf = new RuleBaseConfiguration();
         conf.setSequential( true );
         final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase( conf );
-        buildContext = new BuildContext( ruleBase, ((ReteooRuleBase)ruleBase).getReteooBuilder().getIdGenerator() );
+        buildContext = new BuildContext( ruleBase,
+                                         ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator() );
         buildContext.setObjectTypeNodeMemoryEnabled( false );
-        
+
         final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory( 1,
                                                                            ruleBase );
 
@@ -152,29 +154,27 @@
         final InternalFactHandle handle1 = (InternalFactHandle) workingMemory.insert( string1 );
 
         // should assert as ObjectType matches
-        objectTypeNode.assertRightTuple( handle1,
-                                     context,
-                                     workingMemory );
+        objectTypeNode.assertRightTuple( new RightTuple( handle1 ),
+                                         context,
+                                         workingMemory );
 
         // make sure just string1 was asserted 
         final List asserted = sink.getAsserted();
         assertLength( 1,
                       asserted );
         assertSame( string1,
-                    workingMemory.getObject( (DefaultFactHandle) ((Object[]) asserted.get( 0 ))[0] ) );
+                    workingMemory.getObject( ((RightTuple) ((Object[]) asserted.get( 0 ))[0]).getHandle() ) );
 
         // it's sequential, so check the asserted object was not added to the node memory
-        final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( objectTypeNode );
-        assertEquals( 0,
-                      memory.size() );
+        assertFalse( workingMemory.nodeMemoryExists( objectTypeNode ) );
     }
 
     public void testMemory() {
         ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
-        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();   
-        
-        final ReteooWorkingMemory workingMemory = ( ReteooWorkingMemory ) ruleBase.newStatefulSession();
+        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
 
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
         final ObjectTypeNode objectTypeNode = new ObjectTypeNode( idGenerator.getNextId(),
                                                                   new ClassObjectType( String.class ),
                                                                   buildContext );
@@ -186,8 +186,8 @@
 
     public void testMatches() {
         ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
-        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator(); 
-        final Rete source = new Rete((InternalRuleBase) ruleBase);
+        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
+        final Rete source = new Rete( (InternalRuleBase) ruleBase );
 
         ObjectTypeNode objectTypeNode = new ObjectTypeNode( idGenerator.getNextId(),
                                                             new ClassObjectType( String.class ),
@@ -209,15 +209,15 @@
 
     public void testRetractObject() throws Exception {
         ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
-        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();      
+        IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
         final PropagationContext context = new PropagationContextImpl( 0,
                                                                        PropagationContext.ASSERTION,
                                                                        null,
                                                                        null );
 
-        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory)ruleBase.newStatefulSession();
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
 
-        final Rete source = new Rete((InternalRuleBase) ruleBase);
+        final Rete source = new Rete( (InternalRuleBase) ruleBase );
 
         final ObjectTypeNode objectTypeNode = new ObjectTypeNode( idGenerator.getNextId(),
                                                                   new ClassObjectType( String.class ),
@@ -231,29 +231,30 @@
         final DefaultFactHandle handle1 = new DefaultFactHandle( 1,
                                                                  string1 );
 
-        /* should assert as ObjectType matches */
-        objectTypeNode.assertRightTuple( handle1,
-                                     context,
-                                     workingMemory );
-        /* check asserted object was added to memory */
+        RightTuple rightTuple = new RightTuple( handle1, objectTypeNode);
+        // should assert as ObjectType matches
+        objectTypeNode.assertRightTuple( rightTuple,
+                                         context,
+                                         workingMemory );
+        // check asserted object was added to memory 
         final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( objectTypeNode );
         assertEquals( 1,
                       memory.size() );
 
-        /* should retract as ObjectType matches */
-        objectTypeNode.retractRightTuple( handle1,
-                                      context,
-                                      workingMemory );
-        /* check asserted object was removed from memory */
+        // should retract as ObjectType matches 
+        objectTypeNode.retractRightTuple( rightTuple,
+                                          context,
+                                          workingMemory );
+        // check asserted object was removed from memory 
         assertEquals( 0,
                       memory.size() );
 
-        /* make sure its just the handle1 for string1 that was propagated */
+        // make sure its just the handle1 for string1 that was propagated 
         final List retracted = sink.getRetracted();
         assertLength( 1,
                       retracted );
         assertSame( handle1,
-                    ((Object[]) retracted.get( 0 ))[0] );
+                    ( ((RightTuple) ((Object[]) retracted.get( 0 ))[0]).getHandle() ) );
     }
 
     public void testUpdateSink() throws FactException {
@@ -264,11 +265,11 @@
                                                                        PropagationContext.ASSERTION,
                                                                        null,
                                                                        null );
-        final RuleBase ruleBase = RuleBaseFactory.newRuleBase();     
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
         final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory( 1,
                                                                            (ReteooRuleBase) ruleBase );
 
-        final Rete source = new Rete( (InternalRuleBase)ruleBase);
+        final Rete source = new Rete( (InternalRuleBase) ruleBase );
 
         final ObjectTypeNode objectTypeNode = new ObjectTypeNode( 1,
                                                                   new ClassObjectType( String.class ),
@@ -285,14 +286,17 @@
                                                                  string1 );
         final DefaultFactHandle handle2 = new DefaultFactHandle( 2,
                                                                  string2 );
+        
+        RightTuple rightTuple1 = new RightTuple( handle1, objectTypeNode);
+        RightTuple rightTuple2 = new RightTuple( handle2, objectTypeNode);
 
-        objectTypeNode.assertRightTuple( handle1,
-                                     context,
-                                     workingMemory );
+        objectTypeNode.assertRightTuple( rightTuple1,
+                                         context,
+                                         workingMemory );
 
-        objectTypeNode.assertRightTuple( handle2,
-                                     context,
-                                     workingMemory );
+        objectTypeNode.assertRightTuple( rightTuple2,
+                                         context,
+                                         workingMemory );
 
         assertEquals( 2,
                       sink1.getAsserted().size() );
@@ -314,10 +318,12 @@
 
         final DefaultFactHandle handle3 = new DefaultFactHandle( 3,
                                                                  string3 );
+        
+        RightTuple rightTuple3 = new RightTuple( handle3, objectTypeNode);
 
-        objectTypeNode.assertRightTuple( handle3,
-                                     context,
-                                     workingMemory );
+        objectTypeNode.assertRightTuple( rightTuple3,
+                                         context,
+                                         workingMemory );
 
         assertEquals( 3,
                       sink1.getAsserted().size() );
@@ -336,7 +342,7 @@
         final Rete source = ruleBase.getRete();
 
         final ObjectTypeNode objectTypeNode = new ObjectTypeNode( 1,
-                                                                  new ClassObjectType( Cheese.class  ),
+                                                                  new ClassObjectType( Cheese.class ),
                                                                   buildContext );
 
         final MockObjectSink sink = new MockObjectSink();
@@ -352,9 +358,9 @@
         final List asserted = sink.getAsserted();
         assertLength( 1,
                       asserted );
-        assertTrue( ((InternalFactHandle) ((Object[]) asserted.get( 0 ))[0]).getObject() instanceof ShadowProxy );
+        assertTrue( ((RightTuple) ((Object[]) asserted.get( 0 ))[0]).getHandle().getObject() instanceof ShadowProxy );
         assertEquals( cheese,
-                      ((InternalFactHandle) ((Object[]) asserted.get( 0 ))[0]).getObject() );
+                      ((RightTuple) ((Object[]) asserted.get( 0 ))[0]).getHandle().getObject() );
 
         // check asserted object was added to memory
         final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( objectTypeNode );
@@ -371,7 +377,7 @@
 
         ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
         IdGenerator idGenerator = ruleBase.getReteooBuilder().getIdGenerator();
-        final ReteooWorkingMemory workingMemory = ( ReteooWorkingMemory ) ruleBase.newStatefulSession();
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
 
         final Rete source = ruleBase.getRete();
 
@@ -387,18 +393,19 @@
                                           25 );
 
         final InternalFactHandle handle1 = (InternalFactHandle) workingMemory.insert( person );
+        RightTuple rightTuple1 = new RightTuple( handle1, objectTypeNode);
 
         // should assert as ObjectType matches
-        objectTypeNode.assertRightTuple( handle1,
-                                     context,
-                                     workingMemory );
+        objectTypeNode.assertRightTuple( rightTuple1,
+                                         context,
+                                         workingMemory );
 
         // make sure just string1 was asserted 
         final List asserted = sink.getAsserted();
         assertLength( 1,
                       asserted );
-        assertTrue( ((InternalFactHandle) ((Object[]) asserted.get( 0 ))[0]).getObject() instanceof ShadowProxy );
-        assertEquals( ((InternalFactHandle) ((Object[]) asserted.get( 0 ))[0]).getObject(),
+        assertTrue( ((RightTuple) ((Object[]) asserted.get( 0 ))[0]).getHandle().getObject() instanceof ShadowProxy );
+        assertEquals( ((RightTuple) ((Object[]) asserted.get( 0 ))[0]).getHandle().getObject(),
                       person );
 
         // check asserted object was added to memory

Modified: labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/ReteTest.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/ReteTest.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/ReteTest.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -195,7 +195,7 @@
 
         final Object[] results = (Object[]) asserted.get( 0 );
         assertSame( list,
-                    unwrapShadow( ((DefaultFactHandle) results[0]).getObject() ) );
+                    unwrapShadow( ((RightTuple) results[0]).getHandle().getObject() ) );
     }
 
     public void testAssertObjectWithNoMatchingObjectTypeNode() {
@@ -264,7 +264,7 @@
                       listSink.getAsserted().size() );
         assertEquals( 1,
                       arraySink.getAsserted().size() );
-
+        
         // Add a Collection ObjectTypeNode, so that we can check that the data from ArrayList is sent to it
         final ObjectTypeNode collectionOtn = new ObjectTypeNode( idGenerator.getNextId(),
                                                                  new ClassObjectType( Collection.class ),
@@ -319,7 +319,7 @@
         // There is a List ObjectTypeNode, make sure it was propagated
         final List list = new ArrayList();
         final DefaultFactHandle h2 = new DefaultFactHandle( 1,
-                                                            list );
+                                                            list );        
 
         // need  to assert first, to force it to build  up the cache
         rete.assertRightTuple( h2,
@@ -329,7 +329,7 @@
                                                        null ),
                            workingMemory );
 
-        rete.retractRightTuple( h2,
+        rete.retractRightTuple( h2.getRightTuple(),
                             new PropagationContextImpl( 0,
                                                         PropagationContext.ASSERTION,
                                                         null,
@@ -342,7 +342,7 @@
 
         final Object[] results = (Object[]) retracted.get( 0 );
         assertSame( list,
-                    unwrapShadow( ((DefaultFactHandle) results[0]).getObject() ) );
+                    unwrapShadow( ((RightTuple) results[0]).getHandle().getObject() ) );
     }
 
     public void testIsShadowed() {
@@ -374,7 +374,7 @@
         assertTrue( h1.isShadowFact() );
 
         final Object[] results = (Object[]) sink1.getAsserted().get( 0 );
-        assertTrue( ((DefaultFactHandle) results[0]).getObject() instanceof ShadowProxy );
+        assertTrue( ((RightTuple) results[0]).getHandle().getObject() instanceof ShadowProxy );
     }
 
     public void testNotShadowed() {
@@ -413,7 +413,7 @@
 
         assertFalse( h1.isShadowFact() );
         final Object[] results = (Object[]) sink1.getAsserted().get( 0 );
-        assertFalse( ((DefaultFactHandle) results[0]).getObject() instanceof ShadowProxy );
+        assertFalse( ((RightTuple) results[0]).getHandle().getObject() instanceof ShadowProxy );
     }
 
     private Object unwrapShadow(Object object) {

Modified: labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/TupleSourceTest.java
===================================================================
--- labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/TupleSourceTest.java	2008-01-09 11:04:06 UTC (rev 17650)
+++ labs/jbossrules/branches/righttuple/drools-core/src/test/java/org/drools/reteoo/TupleSourceTest.java	2008-01-09 12:41:15 UTC (rev 17651)
@@ -50,20 +50,20 @@
         final MockTupleSink sink2 = new MockTupleSink();
         source.addTupleSink( sink2 );
         sink = (LeftTupleSinkPropagator) field.get( source );
-        assertSame( CompositeTupleSinkAdapter.class,
+        assertSame( CompositeLeftTupleSinkAdapter.class,
                     sink.getClass() );
         assertEquals( 2,
                       sink.getSinks().length );
 
         final MockTupleSink sink3 = new MockTupleSink();
         source.addTupleSink( sink3 );
-        assertSame( CompositeTupleSinkAdapter.class,
+        assertSame( CompositeLeftTupleSinkAdapter.class,
                     sink.getClass() );
         assertEquals( 3,
                       sink.getSinks().length );
 
         source.removeTupleSink( sink2 );
-        assertSame( CompositeTupleSinkAdapter.class,
+        assertSame( CompositeLeftTupleSinkAdapter.class,
                     sink.getClass() );
         assertEquals( 2,
                       sink.getSinks().length );




More information about the jboss-svn-commits mailing list