[jboss-svn-commits] JBL Code SVN: r6472 - in labs/jbossrules/trunk/drools-core/src/main/java/org/drools: common reteoo util

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Fri Sep 29 13:35:34 EDT 2006


Author: mark.proctor at jboss.com
Date: 2006-09-29 13:35:20 -0400 (Fri, 29 Sep 2006)
New Revision: 6472

Added:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/BetaMemory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectHashTable.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FactHashTable.java
Removed:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeTupleMatch.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeTupleMatchFactory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/FactHandleList.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectMatches.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleTupleMatch.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleTupleMatchFactory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleKey.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleMatch.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleMatchFactory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FactHashSet.java
Modified:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/BetaNodeConstraints.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AccumulateNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AlphaNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/BetaNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CollectNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeTupleSinkAdapter.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/JoinNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/LeftInputAdapterNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/NotNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSink.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSource.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectTypeNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/Rete.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteTuple.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/RightInputAdapterNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSink.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSinkPropagator.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSource.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/AbstractHashTable.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FieldIndexHashTable.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/LinkedList.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/LinkedListEntry.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/TupleHashTable.java
Log:
JBRULES-498 Optimised HashMap implementations
-moved more of the nodes over to the new hashtable stuff
-added iterators

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/BetaNodeConstraints.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/BetaNodeConstraints.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/BetaNodeConstraints.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -21,9 +21,21 @@
 import java.util.Set;
 
 import org.drools.WorkingMemory;
+import org.drools.base.evaluators.Operator;
+import org.drools.reteoo.BetaMemory;
+import org.drools.reteoo.ObjectHashTable;
 import org.drools.rule.Declaration;
+import org.drools.rule.LiteralConstraint;
+import org.drools.rule.VariableConstraint;
+import org.drools.spi.Evaluator;
 import org.drools.spi.FieldConstraint;
+import org.drools.spi.FieldExtractor;
 import org.drools.spi.Tuple;
+import org.drools.util.FactHashTable;
+import org.drools.util.FieldIndexHashTable;
+import org.drools.util.LinkedList;
+import org.drools.util.LinkedListEntry;
+import org.drools.util.TupleHashTable;
 
 public class BetaNodeConstraints
     implements
@@ -36,20 +48,21 @@
 
     public final static BetaNodeConstraints emptyBetaNodeConstraints = new BetaNodeConstraints();
 
-    private final FieldConstraint[]         constraints;
+    private final LinkedList         constraints;
 
-    private static final FieldConstraint[]  EMPTY_CONSTRAINTS        = new FieldConstraint[0];
-
     public BetaNodeConstraints() {
-        this.constraints = BetaNodeConstraints.EMPTY_CONSTRAINTS;
+        this.constraints = null;
     }
 
     public BetaNodeConstraints(final FieldConstraint constraint) {
-        this.constraints = new FieldConstraint[]{constraint};
+        this( new FieldConstraint[]{constraint} );
     }
 
     public BetaNodeConstraints(final FieldConstraint[] constraints) {
-        this.constraints = constraints;
+        this.constraints =  new  LinkedList();
+        for ( int  i  = 0, length = constraints.length; i < length; i++ ) {
+            this.constraints.add( new LinkedListEntry( constraints[i] ) );
+        }        
     }
 
     public boolean isAllowed(final InternalFactHandle handle,
@@ -58,33 +71,34 @@
         if ( this.constraints == null ) {
             return true;
         }
-
-        for ( int i = 0; i < this.constraints.length; i++ ) {
-            if ( !this.constraints[i].isAllowed( handle.getObject(),
-                                                 tuple,
-                                                 workingMemory ) ) {
+                
+        for ( LinkedListEntry entry = ( LinkedListEntry ) this.constraints.getFirst(); entry != null; entry = ( LinkedListEntry ) entry.getNext() ) {
+            FieldConstraint constraint = (FieldConstraint) entry.getObject();
+            if ( constraint.isAllowed( handle.getObject(),
+                                       tuple,
+                                       workingMemory ) ) {
                 return false;
-            }
+            }            
         }
         return true;
-    }
+    }    
 
-    public Set getRequiredDeclarations() {
-        final Set declarations = new HashSet();
-        for ( int i = 0; i < this.constraints.length; i++ ) {
-            final Declaration[] array = this.constraints[i].getRequiredDeclarations();
-            for ( int j = 0; j < array.length; j++ ) {
-                declarations.add( array[j] );
-            }
-        }
-        return declarations;
-    }
+//    public Set getRequiredDeclarations() {
+//        final Set declarations = new HashSet();
+//        for ( int i = 0; i < this.constraints.length; i++ ) {
+//            final Declaration[] array = this.constraints[i].getRequiredDeclarations();
+//            for ( int j = 0; j < array.length; j++ ) {
+//                declarations.add( array[j] );
+//            }
+//        }
+//        return declarations;
+//    }
 
     public int hashCode() {
         return this.constraints.hashCode();
     }
 
-    public FieldConstraint[] getConstraints() {
+    public LinkedList getConstraints() {
         return this.constraints;
     }
 
@@ -112,17 +126,11 @@
             return true;
         }
 
-        if ( this.constraints.length != other.constraints.length ) {
+        if ( this.constraints.size() != other.constraints.size() ) {
             return false;
         }
-
-        for ( int i = 0; i < this.constraints.length; i++ ) {
-            if ( !this.constraints[i].equals( other.constraints[i] ) ) {
-                return false;
-            }
-        }
-
-        return true;
+        
+        return this.constraints.equals( other );
     }
 
 }
\ No newline at end of file

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AccumulateNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AccumulateNode.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AccumulateNode.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -236,7 +236,7 @@
         memory.add( workingMemory,
                     handle );
 
-        final BetaNodeConstraints binder = getJoinNodeBinder();
+        final BetaNodeConstraints binder = constraints();
         for ( final Iterator it = memory.leftTupleIterator( workingMemory,
                                                             handle ); it.hasNext(); ) {
             final ReteTuple leftTuple = (ReteTuple) it.next();

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AlphaNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AlphaNode.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AlphaNode.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -30,7 +30,7 @@
 import org.drools.spi.FieldConstraint;
 import org.drools.spi.PropagationContext;
 import org.drools.util.AbstractHashTable;
-import org.drools.util.FactHashSet;
+import org.drools.util.FactHashTable;
 
 /**
  * <code>AlphaNodes</code> are nodes in the <code>Rete</code> network used
@@ -58,10 +58,10 @@
 
     /** The <code>ObjectSource</code> */
     private final ObjectSource    objectSource;
-    
-    private ObjectSinkNode previousObjectSinkNode;
-    private ObjectSinkNode nextObjectSinkNode; 
 
+    private ObjectSinkNode        previousObjectSinkNode;
+    private ObjectSinkNode        nextObjectSinkNode;
+
     /**
      * Construct an <code>AlphaNode</code> with a unique id using the provided
      * <code>FieldConstraint</code>. <code>NodeMemory</code> is optional in
@@ -102,7 +102,7 @@
 
     public void attach(final InternalWorkingMemory[] workingMemories) {
         attach();
-        
+
         // we are attaching this node with existing working memories
         // so this  node must also have memory
         this.hasMemory = true;
@@ -124,9 +124,10 @@
         if ( this.constraint.isAllowed( handle.getObject(),
                                         null,
                                         workingMemory ) ) {
-            if( hasMemory() ) {
-                final FactHashSet memory = (FactHashSet) workingMemory.getNodeMemory( this );
-                memory.add( handle, false );
+            if ( hasMemory() ) {
+                final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( this );
+                memory.add( handle,
+                            false );
             }
             sink.propagateAssertObject( handle,
                                         context,
@@ -138,9 +139,9 @@
                               final PropagationContext context,
                               final InternalWorkingMemory workingMemory) {
         boolean propagate = true;
-        if( hasMemory() ) {
-            final FactHashSet memory = (FactHashSet) workingMemory.getNodeMemory( this );
-            propagate = memory.remove( handle ); 
+        if ( hasMemory() ) {
+            final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( this );
+            propagate = memory.remove( handle );
         }
         if ( propagate ) {
             this.sink.propagateRetractObject( handle,
@@ -149,34 +150,36 @@
                                               true );
         }
     }
-
+    
     public void modifyObject(final InternalFactHandle handle,
                              final PropagationContext context,
-                             final InternalWorkingMemory workingMemory) {
-        boolean propagate = true;        
+                             final InternalWorkingMemory workingMemory) {      
         if ( this.constraint.isAllowed( handle.getObject(),
                                         null,
                                         workingMemory ) ) {
+            boolean exists = false;  
             if( hasMemory() ) {
-                final FactHashSet memory = (FactHashSet) workingMemory.getNodeMemory( this );
-                propagate = memory.add( handle, true );
+                final ObjectHashTable memory = (ObjectHashTable) workingMemory.getNodeMemory( this );
+                // true if the handle exists and it cannot be added
+                exists = !memory.add( handle, true );
             }
-            if ( propagate ) {
-                this.sink.propagateAssertObject( handle,
-                                                 context,
-                                                 workingMemory );
-            } else {
+            if ( exists ) {
                 // handle already existed so propagate as modify
                 this.sink.propagateModifyObject( handle,
                                                  context,
+                                                 workingMemory );                
+            } else {
+                this.sink.propagateAssertObject( handle,
+                                                 context,
                                                  workingMemory );
             }
         } else {
+            boolean exists = true;  
             if( hasMemory ) {
-                final FactHashSet memory = (FactHashSet) workingMemory.getNodeMemory( this );
-                propagate = memory.remove( handle ); 
+                final ObjectHashTable memory = (ObjectHashTable) workingMemory.getNodeMemory( this );
+                exists = memory.remove( handle ); 
             }
-            if ( propagate ) {
+            if ( exists ) {
                 this.sink.propagateRetractObject( handle,
                                                   context,
                                                   workingMemory,
@@ -184,32 +187,40 @@
             }
         }
     }
+    
 
-    public void updateSink(ObjectSink sink, PropagationContext context, InternalWorkingMemory workingMemory) {
-        FactHashSet memory = null;
+    public void updateSink(ObjectSink sink,
+                           PropagationContext context,
+                           InternalWorkingMemory workingMemory) {
+        FactHashTable memory = null;
 
         // if it was not storing facts in memory previously, create memory and
         // start storing facts in the local memory
-        if( ! hasMemory() ) {
+        if ( !hasMemory() ) {
             setHasMemory( true );
-            memory = (FactHashSet) workingMemory.getNodeMemory( this );
-            for(Iterator it = this.objectSource.getPropagatedFacts( workingMemory ).iterator(); it.hasNext(); ) {
+            memory = (FactHashTable) workingMemory.getNodeMemory( this );
+            for ( Iterator it = this.objectSource.getPropagatedFacts( workingMemory ).iterator(); it.hasNext(); ) {
                 InternalFactHandle handle = (InternalFactHandle) it.next();
-                memory.add( handle, false );
-                sink.assertObject( handle, context, workingMemory );
+                memory.add( handle,
+                            false );
+                sink.assertObject( handle,
+                                   context,
+                                   workingMemory );
             }
         } else {
             // if already has memory, just iterate and propagate
-            memory = (FactHashSet) workingMemory.getNodeMemory( this );
-            AbstractHashTable.FactEntry[] entries  = (AbstractHashTable.FactEntry[]) memory.getTable();
-            for ( int i = 0, length  = entries.length; i < length; i++ ) {
+            memory = (FactHashTable) workingMemory.getNodeMemory( this );
+            AbstractHashTable.FactEntry[] entries = (AbstractHashTable.FactEntry[]) memory.getTable();
+            for ( int i = 0, length = entries.length; i < length; i++ ) {
                 AbstractHashTable.FactEntry current = entries[i];
-                while  ( current != null ) {
-                    sink.assertObject( current.getFactHandle(), context, workingMemory );
-                    current = ( AbstractHashTable.FactEntry ) current.getNext();
+                while ( current != null ) {
+                    sink.assertObject( current.getFactHandle(),
+                                       context,
+                                       workingMemory );
+                    current = (AbstractHashTable.FactEntry) current.getNext();
                 }
-            }        
-        }        
+            }
+        }
     }
 
     public void remove(final BaseNode node,
@@ -232,7 +243,7 @@
      * Creates a HashSet for the AlphaNode's memory.
      */
     public Object createMemory(final RuleBaseConfiguration config) {
-        return new FactHashSet();
+        return new FactHashTable();
     }
 
     public String toString() {
@@ -261,7 +272,7 @@
 
         return this.objectSource.equals( other.objectSource ) && this.constraint.equals( other.constraint );
     }
-    
+
     /**
      * Returns the next node
      * @return
@@ -286,7 +297,7 @@
      *      The previous ObjectSinkNode
      */
     public ObjectSinkNode getPreviousObjectSinkNode() {
-       return this.previousObjectSinkNode;
+        return this.previousObjectSinkNode;
     }
 
     /**
@@ -296,23 +307,23 @@
      */
     public void setPreviousObjectSinkNode(ObjectSinkNode previous) {
         this.previousObjectSinkNode = previous;
-    }   
-    
+    }
+
     public List getPropagatedFacts(InternalWorkingMemory workingMemory) {
         List facts = null;
-        if( hasMemory() ) {
-            final FactHashSet memory = (FactHashSet) workingMemory.getNodeMemory( this );
-            AbstractHashTable.FactEntry[] entries  = (AbstractHashTable.FactEntry[]) memory.getTable();
-            facts = new ArrayList(entries.length);
-            for ( int i = 0, length  = entries.length; i < length; i++ ) {
+        if ( hasMemory() ) {
+            final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( this );
+            AbstractHashTable.FactEntry[] entries = (AbstractHashTable.FactEntry[]) memory.getTable();
+            facts = new ArrayList( entries.length );
+            for ( int i = 0, length = entries.length; i < length; i++ ) {
                 AbstractHashTable.FactEntry current = entries[i];
-                while  ( current != null ) {
+                while ( current != null ) {
                     facts.add( current.getFactHandle() );
-                    current = ( AbstractHashTable.FactEntry ) current.getNext();
+                    current = (AbstractHashTable.FactEntry) current.getNext();
                 }
             }
         } else {
-            facts = this.objectSource.getPropagatedFacts(workingMemory);
+            facts = this.objectSource.getPropagatedFacts( workingMemory );
         }
         return facts;
     }

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/BetaMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/BetaMemory.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/BetaMemory.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -0,0 +1,21 @@
+package org.drools.reteoo;
+
+import org.drools.util.TupleHashTable;
+
+public class BetaMemory {
+    private TupleHashTable tupleMemory;
+    private ObjectHashTable objectMemory;
+    
+    public BetaMemory(TupleHashTable tupleMemory, ObjectHashTable objectMemory) {
+        this.tupleMemory = tupleMemory;   
+        this.objectMemory = objectMemory;
+    }
+
+    public ObjectHashTable getObjectMemory() {
+        return objectMemory;
+    }
+
+    public TupleHashTable getTupleMemory() {
+        return tupleMemory;
+    }           
+}

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/BetaNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/BetaNode.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/BetaNode.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -17,14 +17,23 @@
  */
 
 import org.drools.RuleBaseConfiguration;
+import org.drools.base.evaluators.Operator;
 import org.drools.common.BaseNode;
 import org.drools.common.BetaNodeConstraints;
 import org.drools.common.InternalFactHandle;
 import org.drools.common.InternalWorkingMemory;
 import org.drools.common.NodeMemory;
 import org.drools.common.PropagationContextImpl;
+import org.drools.rule.VariableConstraint;
+import org.drools.spi.Evaluator;
 import org.drools.spi.FieldConstraint;
+import org.drools.spi.FieldExtractor;
 import org.drools.spi.PropagationContext;
+import org.drools.util.FactHashTable;
+import org.drools.util.FieldIndexHashTable;
+import org.drools.util.LinkedList;
+import org.drools.util.LinkedListEntry;
+import org.drools.util.TupleHashTable;
 
 /**
  * <code>BetaNode</code> provides the base abstract class for <code>JoinNode</code> and <code>NotNode</code>. It implements
@@ -52,7 +61,7 @@
     /** The right input <code>TupleSource</code>. */
     private final ObjectSource   rightInput;
 
-    private final BetaNodeConstraints joinNodeBinder;
+    protected final BetaNodeConstraints constraints;
     
     private TupleSinkNode previousTupleSinkNode;
     private TupleSinkNode nextTupleSinkNode;
@@ -94,11 +103,11 @@
     BetaNode(final int id,
              final TupleSource leftInput,
              final ObjectSource rightInput,
-             final BetaNodeConstraints joinNodeBinder) {
+             final BetaNodeConstraints constraints) {
         super( id );
         this.leftInput = leftInput;
         this.rightInput = rightInput;
-        this.joinNodeBinder = joinNodeBinder;
+        this.constraints = constraints;
         
         this.tupleMatchFactory = SingleTupleMatchFactory.getInstance();     
     }
@@ -127,7 +136,14 @@
     
 
     public FieldConstraint[] getConstraints() {
-        return this.joinNodeBinder.getConstraints();
+        LinkedList constraints = this.constraints.getConstraints();
+        
+        FieldConstraint[] array = new FieldConstraint[ constraints.size() ];
+        int i = 0;
+        for ( LinkedListEntry entry = ( LinkedListEntry ) constraints.getFirst(); entry != null; entry = ( LinkedListEntry ) entry.getNext() ) {
+            array[i++] = ( FieldConstraint ) entry.getObject();
+        }
+        return array;        
     }
 
     /* (non-Javadoc)
@@ -147,10 +163,12 @@
                                                                                       PropagationContext.RULE_ADDITION,
                                                                                       null,
                                                                                       null );
-            this.leftInput.updateNewNode( workingMemory,
-                                          propagationContext );
-            this.rightInput.updateNewNode( workingMemory,
-                                           propagationContext );
+            this.leftInput.updateSink( this,
+                                      propagationContext,
+                                      workingMemory );
+            this.rightInput.updateSink( this,
+                                        propagationContext,
+                                        workingMemory );
         }
 
     }
@@ -172,34 +190,8 @@
 //        this.leftInput.remove( this,
 //                               workingMemories );
 
-    }
-
-    /**
-     * @return the <code>joinNodeBinder</code>
-     */
-    BetaNodeConstraints getJoinNodeBinder() {
-        return this.joinNodeBinder;
-    }    
+    }     
     
-    protected TupleMatch attemptJoin(final ReteTuple leftTuple,
-                                     final InternalFactHandle handle,
-                                     final ObjectMatches objectMatches,
-                                     final BetaNodeConstraints binder,
-                                     final InternalWorkingMemory workingMemory) {
-        if ( binder.isAllowed( handle,
-                               leftTuple,
-                               workingMemory ) ) {
-            TupleMatch tupleMatch = this.tupleMatchFactory.newTupleMatch( leftTuple, objectMatches );          
-			objectMatches.add( tupleMatch );
-            leftTuple.addTupleMatch( handle,
-                                     tupleMatch );
-            return tupleMatch;
-
-        } else {
-            return null;
-        }
-    }
-    
     //public abstract TupleSink getTupleSink();
 
     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -231,18 +223,40 @@
 
         final BetaNode other = (BetaNode) object;
 
-        return this.leftInput.equals( other.leftInput ) && this.rightInput.equals( other.rightInput ) && this.joinNodeBinder.equals( other.joinNodeBinder );
+        return this.leftInput.equals( other.leftInput ) && this.rightInput.equals( other.rightInput ) && this.constraints.equals( other.constraints );
     }
 
     /**
      * Creates a BetaMemory for the BetaNode's memory.
      */
     public Object createMemory(final RuleBaseConfiguration config) {
-        return new BetaMemory( config,
-                               this.getJoinNodeBinder() );
+        // iterate over all the constraints untill we find one that is indexeable. When we find it we remove it from the list and create the 
+        // BetaMemory for it. If we don't find one, we create a normal beta memory. We don't need the constraint as we can assume that 
+        // anything  returned by the memory already passes that test.
+        LinkedList constraints = this.constraints.getConstraints();
+        for ( LinkedListEntry entry = ( LinkedListEntry ) constraints.getFirst(); entry != null; entry = ( LinkedListEntry ) entry.getNext() ) {
+            FieldConstraint constraint = ( FieldConstraint ) entry.getObject();            
+            if ( constraint.getClass() == VariableConstraint.class ) {
+                VariableConstraint variableConstraint = ( VariableConstraint ) constraint;
+                FieldExtractor extractor = variableConstraint.getFieldExtractor();
+                Evaluator evaluator = variableConstraint.getEvaluator();
+                if ( evaluator.getOperator() == Operator.EQUAL ) {
+                    // remove this entry                    
+                    constraints.remove( entry );                    
+                    BetaMemory memory = new BetaMemory( new TupleHashTable(),
+                                                        new FieldIndexHashTable(extractor, variableConstraint.getRequiredDeclarations()[0]) );
+                    return memory;
+                    
+                }
+            }
+        }
+        
+        BetaMemory memory = new BetaMemory( new TupleHashTable(),
+                                            new FactHashTable() );                
+        return memory;
     }
+         
     
-    
     /**
      * Returns the next node
      * @return

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CollectNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CollectNode.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CollectNode.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -239,7 +239,7 @@
         memory.add( workingMemory,
                     handle );
 
-        final BetaNodeConstraints binder = getJoinNodeBinder();
+        final BetaNodeConstraints binder = constraints();
         for ( final Iterator it = memory.leftTupleIterator( workingMemory,
                                                             handle ); it.hasNext(); ) {
             final ReteTuple leftTuple = (ReteTuple) it.next();

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeTupleMatch.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeTupleMatch.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeTupleMatch.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -1,108 +0,0 @@
-package org.drools.reteoo;
-
-/*
- * Copyright 2005 JBoss Inc
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import org.drools.common.InternalWorkingMemory;
-import org.drools.spi.PropagationContext;
-import org.drools.util.AbstractBaseLinkedListNode;
-import org.drools.util.LinkedList;
-import org.drools.util.LinkedListNode;
-import org.drools.util.LinkedListEntry;
-
-/**
- * <code>TupleMatch</code> maintains a reference to the parent <code>ReteTuple</code> and a <code>List</code> of all resulting joins. 
- * This is a List rather than a single instance reference because we need to create a join for each TupleSink branches.
- * A reference is also maintained to the <code>ObjectMatches</code> instance; this is so the <code>FactHandleImpl</code> that 
- * is used in the join can be referenced, and also any other <code>TupleMatch</code>es the <code>FactHandleImpl</code> is joined with.
- * 
- * @see CompositeTupleMatch
- * @see ObjectMatches
- * @see ReteTuple
- * 
- * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
- * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
- *
- */
-public class CompositeTupleMatch extends AbstractBaseLinkedListNode
-    implements
-    TupleMatch {
-    private ReteTuple     tuple;
-
-    private LinkedList    list;
-
-    private ObjectMatches objectMatches;
-
-    /**
-     * Construct a <code>TupleMatch</code> with references to the parent <code>ReteTuple</code> and 
-     * <code>FactHandleImpl</code>, via ObjecMatches.
-     * 
-     * @param tuple
-     * @param objectMatches
-     */
-    public CompositeTupleMatch(final ReteTuple tuple,
-                               final ObjectMatches objectMatches) {
-        this.tuple = tuple;
-        this.objectMatches = objectMatches;
-        this.list = new LinkedList();
-    }
-
-    /* (non-Javadoc)
-     * @see org.drools.reteoo.ITupleMatch#getTuple()
-     */
-    public ReteTuple getTuple() {
-        return this.tuple;
-    }
-
-    /* (non-Javadoc)
-     * @see org.drools.reteoo.ITupleMatch#getObjectMatches()
-     */
-    public ObjectMatches getObjectMatches() {
-        return this.objectMatches;
-    }
-
-    public void addJoinedTuple(ReteTuple joined) {
-        this.list.add( new LinkedListEntry( joined ) );
-    }
-
-    public void propagateRetractTuple(final PropagationContext context,
-                                      final InternalWorkingMemory workingMemory) {
-        for ( LinkedListNode node = this.list.getFirst(); node != null; node = node.getNext() ) {
-            ReteTuple joined = (ReteTuple) ((LinkedListEntry) node).getObject();
-            joined.retractTuple( context,
-                                 workingMemory );
-        }
-    }
-
-    public void propagateModifyTuple(final PropagationContext context,
-                                     final InternalWorkingMemory workingMemory) {
-        for ( LinkedListNode node = this.list.getFirst(); node != null; node = node.getNext() ) {
-            ReteTuple joined = (ReteTuple) ((LinkedListEntry) node).getObject();
-            joined.modifyTuple( context,
-                                workingMemory );
-        }
-    }
-
-    public ReteTuple getTupleForSink(TupleSink sink) {
-        for ( LinkedListNode node = this.list.getFirst(); node != null; node = node.getNext() ) {
-            ReteTuple joined = (ReteTuple) ((LinkedListEntry) node).getObject();
-            if ( sink.equals( joined.getTupleSink() ) ) {
-                return joined;
-            }
-        }
-        return null;
-    }
-
-}
\ No newline at end of file

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeTupleMatchFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeTupleMatchFactory.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeTupleMatchFactory.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -1,25 +0,0 @@
-package org.drools.reteoo;
-
-public class CompositeTupleMatchFactory
-    implements
-    TupleMatchFactory {
-    
-    private static TupleMatchFactory INSTANCE;
-    
-    public static TupleMatchFactory getInstance() {
-        if ( INSTANCE == null ) {
-            INSTANCE = new CompositeTupleMatchFactory();
-        }
-        return INSTANCE;
-    }
-    
-    private CompositeTupleMatchFactory() {
-        
-    }
-
-    public TupleMatch newTupleMatch(ReteTuple tuple,
-                                    ObjectMatches objectMatches) {
-        return new CompositeTupleMatch(tuple, objectMatches);
-    }
-
-}

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeTupleSinkAdapter.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeTupleSinkAdapter.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeTupleSinkAdapter.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -51,6 +51,31 @@
         }
     }
 
+    public void propagateRetractTuple(ReteTuple tuple,
+                                      InternalFactHandle handle,
+                                      PropagationContext context,
+                                      InternalWorkingMemory workingMemory) {
+        for ( TupleSinkNode sink = this.sinks.getFirst(); sink != null; sink = sink.getNextTupleSinkNode() ) {
+            sink.retractTuple( new ReteTuple( tuple,
+                                              handle ),
+                               context,
+                               workingMemory );
+        }
+    }
+
+    public void propagateModifyTuple(ReteTuple tuple,
+                                     InternalFactHandle handle,
+                                     PropagationContext context,
+                                     InternalWorkingMemory workingMemory) {
+
+        for ( TupleSinkNode sink = this.sinks.getFirst(); sink != null; sink = sink.getNextTupleSinkNode() ) {
+            sink.modifyTuple( new ReteTuple( tuple,
+                                             handle ),
+                              context,
+                              workingMemory );
+        }
+    }
+
     public LinkedList createAndPropagateAssertTupleWithMemory(InternalFactHandle handle,
                                                               PropagationContext context,
                                                               InternalWorkingMemory workingMemory) {

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/FactHandleList.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/FactHandleList.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/FactHandleList.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -1,187 +0,0 @@
-package org.drools.reteoo;
-
-/*
- * Copyright 2005 JBoss Inc
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import java.io.Serializable;
-import java.util.Arrays;
-
-import org.drools.FactHandle;
-import org.drools.common.DefaultFactHandle;
-import org.drools.common.InternalFactHandle;
-import org.drools.rule.Declaration;
-
-/**
- * Specialised array of {@link FactHandle}s intended to be keyed by a
- * {@link Declaration}s index. The list only ever contains as many elements as
- * necessary to hold a handle at the position specified by the largest
- * Declaration index. As a result, the list will neccessarily contain
- * <code>NULL</code> values.
- * 
- * This class exists purely for performance reasons and as such, many
- * assumptions have been made regarding behaviour based on know usage.
- * Therefore, this class should in no way be considered a general purpose data
- * structure. Hence it resides in this package and not a more generic "util"
- * package.
- * 
- * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris</a>
- */
-final class FactHandleList
-    implements
-    Serializable {
-
-    /**
-     * 
-     */
-    private static final long          serialVersionUID = 320L;
-
-    /** Empty list for testing purposes only. */
-    static final FactHandleList        EMPTY_LIST       = new FactHandleList();
-
-    /** The list of handles. */
-    private final InternalFactHandle[] handles;
-
-    /** The cached hash code value. */
-    private final int                  hashCode;
-
-    /**
-     * Private constructor for creating the {@link #EMPTY_LIST}.
-     */
-    private FactHandleList() {
-        this.handles = new DefaultFactHandle[0];
-        this.hashCode = 0;
-    }
-
-    /**
-     * Join two lists.
-     * 
-     * @param left
-     *            The left list.
-     * @param right
-     *            The right list.
-     */
-    public FactHandleList(final FactHandleList left,
-                          final InternalFactHandle handle) {
-        this.handles = new DefaultFactHandle[left.handles.length + 1];
-
-        System.arraycopy( left.handles,
-                          0,
-                          this.handles,
-                          0,
-                          left.handles.length );
-
-        this.handles[left.handles.length] = handle;
-
-        this.hashCode = left.hashCode + handle.hashCode();
-    }
-
-    /**
-     * Single value constructor.
-     * 
-     * @param index
-     *            The index at which the handle will be placed.
-     * @param handle
-     *            The handle to use.
-     */
-    public FactHandleList(final InternalFactHandle handle) {
-        this.handles = new DefaultFactHandle[]{(DefaultFactHandle) handle};
-        this.hashCode = handle.hashCode();
-    }
-
-    /**
-     * Obtains the handle at a specified index.
-     * 
-     * @param index
-     *            The position from which the handle should be obtained.
-     * @return The handle; or <code>null</code> if no handle exists.
-     * @throws ArrayIndexOutOfBoundsException
-     *             if <code>index</code> &gt; {@link #size()}.
-     */
-    public InternalFactHandle get(final int index) {
-        return this.handles[index];
-    }
-
-    /**
-     * Determines if the list contains a specified handle.
-     * 
-     * @param handle
-     *            The handle to search for.
-     * @return <code>true</code> if the handle is found; otherwise
-     *         <code>false</code>
-     */
-    public boolean contains(final FactHandle handle) {
-        for ( int i = this.handles.length - 1; i >= 0; i-- ) {
-            if ( handle.equals( this.handles[i] ) ) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    /**
-     * Determines if the list is a super-set of another list.
-     * 
-     * @param other
-     *            The list to be checked.
-     * @return <code>true</code> if this list contains all values from the
-     *         other list; <code>false</code> otherwise.
-     */
-    public boolean containsAll(final FactHandleList other) {
-        if ( other.handles.length > this.handles.length ) {
-            return false;
-        }
-
-        FactHandle handle;
-        for ( int i = other.handles.length - 1; i >= 0; i-- ) {
-            handle = other.handles[i];
-            if ( handle != null && !handle.equals( this.handles[i] ) ) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    InternalFactHandle[] getHandles() {
-        return this.handles;
-    }
-
-    /**
-     * Obtains the length of the list.
-     * 
-     * @return The length of the list, including all <code>null</code> values.
-     */
-    public int size() {
-        return this.handles.length;
-    }
-
-    public int hashCode() {
-        return this.hashCode;
-    }
-
-    public boolean equals(final Object object) {
-        if ( this == object ) {
-            return true;
-        }
-
-        if ( object == null || getClass() != object.getClass() ) {
-            return false;
-        }
-
-        return Arrays.equals( this.handles,
-                              ((FactHandleList) object).handles );
-    }
-}

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/JoinNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/JoinNode.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/JoinNode.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -18,7 +18,6 @@
 
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
@@ -26,6 +25,11 @@
 import org.drools.common.InternalFactHandle;
 import org.drools.common.InternalWorkingMemory;
 import org.drools.spi.PropagationContext;
+import org.drools.util.FactHashTable;
+import org.drools.util.FieldIndexHashTable;
+import org.drools.util.Iterator;
+import org.drools.util.AbstractHashTable.FactEntry;
+import org.drools.util.FieldIndexHashTable.FieldIndexEntry;
 
 /**
  * <code>JoinNode</code> extends <code>BetaNode</code> to perform
@@ -110,29 +114,15 @@
                             final PropagationContext context,
                             final InternalWorkingMemory workingMemory) {
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
-
-        memory.add( workingMemory,
-                    leftTuple );
-
-        final BetaNodeConstraints binder = getJoinNodeBinder();
-
-        for ( final Iterator it = memory.rightObjectIterator( workingMemory,
-                                                              leftTuple ); it.hasNext(); ) {
-            final ObjectMatches objectMatches = (ObjectMatches) it.next();
-            final InternalFactHandle handle = objectMatches.getFactHandle();
-            final TupleMatch tupleMatch = attemptJoin( leftTuple,
-                                                       handle,
-                                                       objectMatches,
-                                                       binder,
-                                                       workingMemory );
-            if ( tupleMatch != null ) {
-                sink.propagateAssertTuple( leftTuple,
-                                           handle,
-                                           tupleMatch,
-                                           context,
-                                           workingMemory );
+        memory.getTupleMemory().add( leftTuple );
+                
+        Iterator it = memory.getObjectMemory().iterator( leftTuple );
+        for ( FactEntry entry = ( FactEntry ) it.next(); entry != null; entry = ( FactEntry ) it.next() ) {
+            InternalFactHandle handle = entry.getFactHandle();
+            if ( this.constraints.isAllowed( handle, leftTuple, workingMemory ) ) {
+                sink.propagateAssertTuple( leftTuple, handle, context, workingMemory );
             }
-        }
+        }        
     }
 
     /**
@@ -157,25 +147,12 @@
                              final PropagationContext context,
                              final InternalWorkingMemory workingMemory) {
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
-        final ObjectMatches objectMatches = memory.add( workingMemory,
-                                                        handle );
-
-        final BetaNodeConstraints binder = getJoinNodeBinder();
-        for ( final Iterator it = memory.leftTupleIterator( workingMemory,
-                                                            handle ); it.hasNext(); ) {
-            final ReteTuple leftTuple = (ReteTuple) it.next();
-            final TupleMatch tupleMatch = attemptJoin( leftTuple,
-                                                       handle,
-                                                       objectMatches,
-                                                       binder,
-                                                       workingMemory );
-
-            if ( tupleMatch != null ) {
-                this.sink.propagateAssertTuple( leftTuple,
-                                                handle,
-                                                tupleMatch,
-                                                context,
-                                                workingMemory );
+        memory.getObjectMemory().add( handle );
+        
+        Iterator it = memory.getTupleMemory().iterator();
+        for ( ReteTuple tuple = ( ReteTuple ) it.next(); tuple != null; tuple = ( ReteTuple ) it.next() ) {
+            if ( this.constraints.isAllowed( handle, tuple, workingMemory ) ) {
+                sink.propagateAssertTuple( tuple, handle, context, workingMemory );
             }
         }
     }
@@ -195,17 +172,14 @@
                               final PropagationContext context,
                               final InternalWorkingMemory workingMemory) {
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
-
-        // Remove the FactHandle from memory
-        final ObjectMatches objectMatches = memory.remove( workingMemory,
-                                                           handle );
-
-        for ( TupleMatch tupleMatch = objectMatches.getFirstTupleMatch(); tupleMatch != null; tupleMatch = (TupleMatch) tupleMatch.getNext() ) {
-            final ReteTuple leftTuple = tupleMatch.getTuple();
-            leftTuple.removeMatch( handle );
-            tupleMatch.propagateRetractTuple( context,
-                                              workingMemory );
+        if (! memory.getObjectMemory().remove( handle ) ) {
+            return;
         }
+        
+        Iterator it = memory.getTupleMemory().iterator();
+        for ( ReteTuple tuple = ( ReteTuple ) it.next(); tuple != null; tuple = ( ReteTuple ) it.next() ) {
+            sink.propagateRetractTuple( tuple, handle, context, workingMemory );
+        }
     }
 
     /**
@@ -223,187 +197,81 @@
     public void retractTuple(final ReteTuple leftTuple,
                              final PropagationContext context,
                              final InternalWorkingMemory workingMemory) {
-
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
-        memory.remove( workingMemory,
-                       leftTuple );
-
-        final Map matches = leftTuple.getTupleMatches();
-
-        if ( !matches.isEmpty() ) {
-            for ( final Iterator it = matches.values().iterator(); it.hasNext(); ) {
-                final TupleMatch tupleMatch = (TupleMatch) it.next();
-                tupleMatch.getObjectMatches().remove( tupleMatch );
-                tupleMatch.propagateRetractTuple( context,
-                                                  workingMemory );
-            }
+        
+        if ( memory.getTupleMemory().remove( leftTuple ) ==  null )  {
+            return;
         }
+        
+        Iterator it = memory.getObjectMemory().iterator( leftTuple );
+        for ( FactEntry entry = ( FactEntry ) it.next(); entry != null; entry = ( FactEntry ) it.next() ) {
+            sink.propagateRetractTuple( leftTuple, entry.getFactHandle(), context, workingMemory );
+        }        
     }
-
+    
     public void modifyTuple(final ReteTuple leftTuple,
                             final PropagationContext context,
                             final InternalWorkingMemory workingMemory) {
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+        
+        if ( ! memory.getTupleMemory().contains( leftTuple ) ) {
+            assertTuple( leftTuple, context, workingMemory );
+        }
 
-        // We remove the tuple as now its modified it needs to go to the top of
-        // the stack, which is added back in else where
-        memory.remove( workingMemory,
-                       leftTuple );
-
-        final Map matches = leftTuple.getTupleMatches();
-
-        if ( matches.isEmpty() ) {
-            // No child propagations, so try as a new assert, will ensure the
-            // tuple is added to the top of the memory
-            assertTuple( leftTuple,
-                         context,
-                         workingMemory );
+        Iterator iterator;
+        if ( leftTuple.isFieldIndexed() ) {
+            iterator = memory.getObjectMemory().iterator(leftTuple.getFieldIndexHashCode());
         } else {
-            // TIRELLI's NOTE: the following is necessary because in case memory  
-            // indexing is enabled, the loop over right objects may skip some of the
-            // previously matched objects
-            final Map oldMatches = new HashMap( matches );
-            leftTuple.getTupleMatches().clear();
-
-            // ensure the tuple is at the top of the memory
-            memory.add( workingMemory,
-                        leftTuple );
-            final BetaNodeConstraints binder = getJoinNodeBinder();
-
-            for ( final Iterator rightIterator = memory.rightObjectIterator( workingMemory,
-                                                                             leftTuple ); rightIterator.hasNext(); ) {
-                final ObjectMatches objectMatches = (ObjectMatches) rightIterator.next();
-                final InternalFactHandle handle = objectMatches.getFactHandle();
-
-                if ( binder.isAllowed( handle,
-                                       leftTuple,
-                                       workingMemory ) ) {
-                    TupleMatch tupleMatch = (TupleMatch) oldMatches.remove( handle );
-                    if ( tupleMatch != null ) {
-                        // ensures tupleMatch will be in the appropriate order
-                        objectMatches.remove( tupleMatch );
-                        objectMatches.add( tupleMatch );
-                        leftTuple.addTupleMatch( handle,
-                                                 tupleMatch );
-                        tupleMatch.propagateModifyTuple( context,
-                                                         workingMemory );
-                    } else {
-                        tupleMatch = this.tupleMatchFactory.newTupleMatch( leftTuple, objectMatches );
-                        objectMatches.add( tupleMatch );
-                        leftTuple.addTupleMatch( handle,
-                                                 tupleMatch );
-                        this.sink.propagateAssertTuple( leftTuple,
-                                                        handle,
-                                                        tupleMatch,
-                                                        context,
-                                                        workingMemory );
-                    }
-
-                } else {
-                    final TupleMatch tupleMatch = leftTuple.removeMatch( handle );
-                    if ( tupleMatch != null ) {
-                        oldMatches.remove( handle );
-                        objectMatches.remove( tupleMatch );
-                        tupleMatch.propagateRetractTuple( context,
-                                                          workingMemory );
-                    }
-                }
-            }
-
-            // TIRELLI's NOTE: the following is necessary because in case memory  
-            // indexing is enabled, the loop over right objects may skip some of the
-            // previously matched objects
-            if ( !oldMatches.isEmpty() ) {
-                for ( Iterator it = oldMatches.values().iterator(); it.hasNext(); ) {
-                    final TupleMatch tupleMatch = (TupleMatch) it.next();
-                    tupleMatch.getObjectMatches().remove( tupleMatch );
-                    tupleMatch.propagateRetractTuple( context, workingMemory );
-                }
-            }
+            iterator = memory.getObjectMemory().iterator();
         }
-    }
-
+        
+        for ( FactEntry entry = (FactEntry) iterator.next(); entry != null; entry = ( FactEntry )entry.getNext() ) {
+            InternalFactHandle handle = entry.getFactHandle();
+            if ( this.constraints.isAllowed( handle, leftTuple, workingMemory ) ) {
+                this.sink.propagateModifyTuple( leftTuple, handle, context, workingMemory );
+            } else {   
+                this.sink.propagateRetractTuple( leftTuple, handle, context, workingMemory );
+            }
+        }        
+    }    
+    
     public void modifyObject(final InternalFactHandle handle,
-                             final PropagationContext context,
-                             final InternalWorkingMemory workingMemory) {
+                            final PropagationContext context,
+                            final InternalWorkingMemory workingMemory) {
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
-
-        // Remove and re-add the FactHandle from memory, ensures that its the latest on the list
-        final ObjectMatches objectMatches = memory.remove( workingMemory,
-                                                           handle );
-        memory.add( workingMemory,
-                    objectMatches );
-
-        TupleMatch tupleMatch = objectMatches.getFirstTupleMatch();
-        final BetaNodeConstraints binder = getJoinNodeBinder();
-
-        for ( final Iterator it = memory.leftTupleIterator( workingMemory,
-                                                            handle ); it.hasNext(); ) {
-            final ReteTuple leftTuple = (ReteTuple) it.next();
-            if ( tupleMatch != null && tupleMatch.getTuple() == leftTuple ) {
-                // has previous match so need to decide whether to continue
-                // modify or retract    
-
-                // Need to get the "next" tuple match before messing with references 
-                // using objectMatches.remove( tupleMatch ); for instance.
-                TupleMatch nextTupleMatch = (TupleMatch) tupleMatch.getNext();
-                if ( binder.isAllowed( handle,
-                                       leftTuple,
-                                       workingMemory ) ) {
-                    tupleMatch.propagateModifyTuple( context, workingMemory );
-                } else {
-                    leftTuple.removeMatch( handle );
-                    objectMatches.remove( tupleMatch );
-                    tupleMatch.propagateRetractTuple( context, workingMemory );
-                }
-                tupleMatch = nextTupleMatch;
+        
+        if ( ! memory.getObjectMemory().contains( handle ) ) {
+            assertObject( handle, context, workingMemory );
+        }
+                
+        Iterator it = memory.getTupleMemory().iterator();
+        for ( ReteTuple tuple = ( ReteTuple ) it.next(); tuple != null; tuple = ( ReteTuple ) it.next() ) {
+            if ( this.constraints.isAllowed( handle, tuple, workingMemory ) ) {
+                this.sink.propagateModifyTuple( tuple, handle, context, workingMemory );
             } else {
-                // no previous join, so attempt join now
-                final TupleMatch newTupleMatch = attemptJoin( leftTuple,
-                                                              handle,
-                                                              objectMatches,
-                                                              binder,
-                                                              workingMemory );
-                if ( newTupleMatch != null ) {
-                    this.sink.propagateAssertTuple( leftTuple, handle, newTupleMatch, context, workingMemory );
-                }
+                this.sink.propagateRetractTuple( tuple, handle, context, workingMemory );
             }
-        }
-    }
+        }           
+    }       
 
     /* (non-Javadoc)
      * @see org.drools.reteoo.BaseNode#updateNewNode(org.drools.reteoo.WorkingMemoryImpl, org.drools.spi.PropagationContext)
      */
     public void updateSink(final TupleSink sink,
-                           final InternalWorkingMemory workingMemory,
-                           final PropagationContext context) {
+                           final PropagationContext context,
+                           final InternalWorkingMemory workingMemory) {
 
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
 
-        for ( final Iterator it = memory.getRightObjectMemory().iterator(); it.hasNext(); ) {
-            final ObjectMatches objectMatches = (ObjectMatches) it.next();
-            for ( TupleMatch tupleMatch = objectMatches.getFirstTupleMatch(); tupleMatch != null; tupleMatch = (TupleMatch) tupleMatch.getNext() ) {
-                this.sink.propagateAssertTuple( tupleMatch.getTuple(), context, workingMemory );
-            }
+        Iterator tupleIter = memory.getTupleMemory().iterator();
+        for ( ReteTuple tuple = ( ReteTuple ) tupleIter.next(); tuple != null; tuple = ( ReteTuple ) tupleIter.next() ) {
+            Iterator objectIter = memory.getObjectMemory().iterator( tuple );
+            for ( FactEntry entry = ( FactEntry ) objectIter.next(); entry != null; entry = ( FactEntry ) objectIter.next() ) {
+                InternalFactHandle handle = entry.getFactHandle();
+                if ( this.constraints.isAllowed( handle, tuple, workingMemory ) ) {
+                    sink.assertTuple( new ReteTuple( tuple, handle),  context, workingMemory );
+                }
+            }               
         }
     }
-
-    /**
-     * @inheritDoc
-     */
-    public List getPropagatedTuples(final InternalWorkingMemory workingMemory,
-                                    final TupleSink sink) {
-        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
-        
-        final List propagatedTuples = new ArrayList();
-
-        for ( final Iterator it = memory.getRightObjectMemory().iterator(); it.hasNext(); ) {
-            final ObjectMatches objectMatches = (ObjectMatches) it.next();
-            for ( TupleMatch tupleMatch = objectMatches.getFirstTupleMatch(); tupleMatch != null; tupleMatch = (TupleMatch) tupleMatch.getNext() ) {                
-                propagatedTuples.add( tupleMatch.getTupleForSink( sink ) );
-            }
-        }
-        return propagatedTuples;
-    }
-
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/LeftInputAdapterNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/LeftInputAdapterNode.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/LeftInputAdapterNode.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -58,7 +58,7 @@
      */
     private static final long         serialVersionUID = 320L;
     private final ObjectSource        objectSource;
-    private final BetaNodeConstraints binder;
+    private final BetaNodeConstraints constraints;
 
     /**
      * Constructus a LeftInputAdapterNode with a unique id that receives <code>FactHandle</code> from a 
@@ -70,12 +70,10 @@
      *      The parent node, where Facts are propagated from
      */
     public LeftInputAdapterNode(final int id,
-                                final ObjectSource source,
-                                final boolean hashMemory) {
+                                final ObjectSource source) {
         this( id,
               source,
-              null,
-              hashMemory );
+              null );
     }
 
     /**
@@ -92,16 +90,22 @@
      */
     public LeftInputAdapterNode(final int id,
                                 final ObjectSource source,
-                                final BetaNodeConstraints binder,
-                                final boolean hashMemory) {
+                                final BetaNodeConstraints constraints) {
         super( id );
         this.objectSource = source;
-        this.binder = binder;
-        setHasMemory( hashMemory );
+        this.constraints = constraints;
+        setHasMemory( false );
     }
 
     public FieldConstraint[] getConstraints() {
-        return this.binder.getConstraints();
+        LinkedList constraints = this.constraints.getConstraints();
+        
+        FieldConstraint[] array = new FieldConstraint[ constraints.size() ];
+        int i = 0;
+        for ( LinkedListEntry entry = ( LinkedListEntry ) constraints.getFirst(); entry != null; entry = ( LinkedListEntry ) entry.getNext() ) {
+            array[i++] = ( FieldConstraint ) entry.getObject();
+        }
+        return array;        
     }
 
     /* (non-Javadoc)
@@ -140,7 +144,7 @@
     public void assertObject(final InternalFactHandle handle,
                              final PropagationContext context,
                              final InternalWorkingMemory workingMemory) {
-        if ( (this.binder == null) || (this.binder.isAllowed( handle,
+        if ( (this.constraints == null) || (this.constraints.isAllowed( handle,
                                                               null,
                                                               workingMemory )) ) {
             if ( this.hasMemory ) {
@@ -263,38 +267,13 @@
         }
 
         final LeftInputAdapterNode other = (LeftInputAdapterNode) object;
-        if ( this.binder == null ) {
-            return this.objectSource.equals( other.objectSource ) && other.binder == null;
+        if ( this.constraints == null ) {
+            return this.objectSource.equals( other.objectSource ) && other.constraints == null;
         } else {
-            return this.objectSource.equals( other.objectSource ) && this.binder.equals( other.binder );
+            return this.objectSource.equals( other.objectSource ) && this.constraints.equals( other.constraints );
         }
     }
 
-    /**
-     * @inheritDoc
-     */
-    public List getPropagatedTuples(final InternalWorkingMemory workingMemory,
-                                    final TupleSink sink) {
-        List tupeList = new ArrayList();
-        if (  this.hasMemory ) {  
-            ObjectHashMap map = (ObjectHashMap) workingMemory.getNodeMemory( this );
-            ObjectEntry[] entries = (ObjectEntry[]) map.getTable();
-            for ( int i = 0, length = entries.length; i < length; i++ ) {
-                ObjectEntry current = entries[i];
-                while ( current != null ) {
-                    LinkedList list = (LinkedList) current.getValue();
-                    for ( LinkedListEntry entry = ( LinkedListEntry ) list.getFirst(); entry != null; entry = ( LinkedListEntry ) entry.getNext() ) {
-                        tupeList.add( entry.getObject() );
-                    }                    
-                    current = (ObjectEntry) current.getNext();
-                }
-            }                    
-        } else{
-            ObjectSinkAdapter adapter = new ObjectSinkAdapter( tupeList );
-        }
-        return tupeList;
-    }
-
     public Object createMemory(RuleBaseConfiguration config) {
         return new ObjectHashMap();
     }
@@ -309,12 +288,6 @@
         implements
         ObjectSink {
         private TupleSink sink;
-        private List list;
-        
-        public ObjectSinkAdapter(List list) {
-            this.list = list;
-        }
-
         public ObjectSinkAdapter(TupleSink sink) {
             this.sink = sink;
         }        
@@ -323,13 +296,9 @@
                                  PropagationContext context,
                                  InternalWorkingMemory workingMemory) {
             ReteTuple tuple = new ReteTuple( handle );
-            if ( this.sink != null  ) {
-                this.sink.assertTuple( tuple,
-                                       context,
-                                       workingMemory );
-            } else {
-                this.list.add( tuple );
-            }
+            this.sink.assertTuple( tuple,
+                                   context,
+                                   workingMemory );
         }
 
         public void modifyObject(InternalFactHandle handle,

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/NotNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/NotNode.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/NotNode.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -18,7 +18,6 @@
 
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
@@ -27,9 +26,11 @@
 import org.drools.common.InternalFactHandle;
 import org.drools.common.InternalWorkingMemory;
 import org.drools.spi.PropagationContext;
+import org.drools.util.Iterator;
 import org.drools.util.LinkedList;
 import org.drools.util.LinkedListNode;
 import org.drools.util.LinkedListEntry;
+import org.drools.util.AbstractHashTable.FactEntry;
 
 /**
  * <code>NotNode</code> extends <code>BetaNode</code> to perform tests for
@@ -111,29 +112,24 @@
                             final PropagationContext context,
                             final InternalWorkingMemory workingMemory) {
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
-
-        memory.add( workingMemory,
-                    leftTuple );
-
-        final BetaNodeConstraints binder = getJoinNodeBinder();
-
-        for ( final Iterator it = memory.rightObjectIterator( workingMemory,
-                                                              leftTuple ); it.hasNext(); ) {
-            final ObjectMatches objectMatches = (ObjectMatches) it.next();
-            final InternalFactHandle handle = objectMatches.getFactHandle();
-            attemptJoin( leftTuple,
-                         handle,
-                         objectMatches,
-                         binder,
-                         workingMemory );
+        memory.getTupleMemory().add( leftTuple );
+                
+        Iterator it = memory.getObjectMemory().iterator( leftTuple );
+        int matches = 0;
+        for ( FactEntry entry = ( FactEntry ) it.next(); entry != null; entry = ( FactEntry ) it.next() ) {
+            InternalFactHandle handle = entry.getFactHandle();            
+            if ( this.constraints.isAllowed( handle, leftTuple, workingMemory ) ) {
+                matches++;
+            }
         }
-
-        if ( leftTuple.matchesSize() == 0 ) {
+        
+        leftTuple.setMatches( matches );
+        
+        if ( matches == 0 ) {
             this.sink.propagateAssertTuple( leftTuple,
                                             context,
                                             workingMemory );
         }
-
     }
 
     /**
@@ -151,27 +147,16 @@
     public void assertObject(final InternalFactHandle handle,
                              final PropagationContext context,
                              final InternalWorkingMemory workingMemory) {
-
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
-        final ObjectMatches objectMatches = memory.add( workingMemory,
-                                                        handle );
-
-        final BetaNodeConstraints binder = getJoinNodeBinder();
-
-        for ( final Iterator it = memory.leftTupleIterator( workingMemory,
-                                                            handle ); it.hasNext(); ) {
-            final ReteTuple leftTuple = (ReteTuple) it.next();
-            final int previousSize = leftTuple.matchesSize();
-            attemptJoin( leftTuple,
-                         handle,
-                         objectMatches,
-                         binder,
-                         workingMemory );
-            if ( previousSize == 0 && leftTuple.matchesSize() != 0 ) {
-                for ( LinkedListNode node = leftTuple.getChildEntries().getFirst(); node != null; node = node.getNext() ) {
-                    ReteTuple tuple = (ReteTuple) ((LinkedListEntry) node).getObject();
-                    tuple.retractTuple( context,
-                                        workingMemory );
+        memory.getObjectMemory().add( handle );
+        
+        Iterator it = memory.getTupleMemory().iterator();
+        for ( ReteTuple tuple = ( ReteTuple ) it.next(); tuple != null; tuple = ( ReteTuple ) it.next() ) {
+            if ( this.constraints.isAllowed( handle, tuple, workingMemory ) ) {
+                int matches = tuple.getMatches();
+                tuple.setMatches( matches + 1 );
+                if ( matches == 0 ) {
+                    this.sink.propagateRetractTuple( tuple, context, workingMemory );
                 }
             }
         }
@@ -194,18 +179,19 @@
                               final PropagationContext context,
                               final InternalWorkingMemory workingMemory) {
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
-        final ObjectMatches objectMatches = memory.remove( workingMemory,
-                                                           handle );
-
-        for ( TupleMatch tupleMatch = objectMatches.getFirstTupleMatch(); tupleMatch != null; tupleMatch = (TupleMatch) tupleMatch.getNext() ) {
-            final ReteTuple leftTuple = tupleMatch.getTuple();
-            final int previousSize = leftTuple.matchesSize();
-            leftTuple.removeMatch( handle );
-
-            if ( previousSize != 0 && leftTuple.matchesSize() == 0 ) {
-                this.sink.propagateAssertTuple( leftTuple, context, workingMemory );
-            }
+        if ( memory.getObjectMemory().remove( handle ) ) {
+            return;
         }
+        
+        Iterator it = memory.getTupleMemory().iterator();
+        for ( ReteTuple tuple = ( ReteTuple ) it.next(); tuple != null; tuple = ( ReteTuple ) it.next() ) {
+            if ( this.constraints.isAllowed( handle, tuple, workingMemory ) ) {
+                tuple.setMatches( tuple.getMatches() - 1 );
+                if ( tuple.getMatches() == 0 ) {
+                    this.sink.propagateAssertTuple( tuple, context, workingMemory );
+                }
+            }
+        }        
     }
 
     /**
@@ -223,172 +209,98 @@
                              final PropagationContext context,
                              final InternalWorkingMemory workingMemory) {
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
-        memory.remove( workingMemory,
-                       leftTuple );
-
-        final Map matches = leftTuple.getTupleMatches();
-
-        if ( !matches.isEmpty() ) {
-            for ( final Iterator it = matches.values().iterator(); it.hasNext(); ) {
-                final TupleMatch tupleMatch = (TupleMatch) it.next();
-                tupleMatch.getObjectMatches().remove( tupleMatch );
-            }
-        } else {
-            for ( LinkedListNode node = leftTuple.getChildEntries().getFirst(); node != null; node = node.getNext() ) {
-                ReteTuple tuple = (ReteTuple) ((LinkedListEntry) node).getObject();
-                tuple.retractTuple( context,
-                                    workingMemory );
-            }
+        
+        // Must use the tuple in memory as it has the tuple matches count
+        ReteTuple tuple = ( ReteTuple ) memory.getTupleMemory().remove( leftTuple );
+        if ( tuple == null ) {
+            return;
         }
+        
+        int matches =  tuple.getMatches();
+        int previousMatches = matches;
+        
+        Iterator it = memory.getObjectMemory().iterator( tuple );        
+        for ( FactEntry entry = ( FactEntry ) it.next(); entry != null; entry = ( FactEntry ) it.next() ) {
+            InternalFactHandle handle = entry.getFactHandle();            
+            if ( this.constraints.isAllowed( handle, tuple, workingMemory ) ) {
+                matches--;
+            }
+        }        
+        
+        tuple.setMatches( matches );
+        
+        if (previousMatches != 0 && matches == 0 ) {
+            this.sink.propagateRetractTuple( tuple,
+                                             context,
+                                             workingMemory );            
+        }    
     }
 
-    public void modifyTuple(final ReteTuple leftTuple,
-                            final PropagationContext context,
-                            final InternalWorkingMemory workingMemory) {
+    public void modifyTuple(ReteTuple leftTuple,
+                            PropagationContext context,
+                            InternalWorkingMemory workingMemory) {
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
-
-        // We remove the tuple as now its modified it needs to go to the top of
-        // the stack, which is added back in else where
-        memory.remove( workingMemory,
-                       leftTuple );
-        // ensure the tuple is at the top of the memory
-        memory.add( workingMemory,
-                    leftTuple );
-
-        // TIRELLI's NOTE: the following is necessary because in case memory  
-        // indexing is enabled, the loop over right objects may skip some of the
-        // previously matched objects
-        final Map oldMatches = new HashMap( leftTuple.getTupleMatches() );
-        leftTuple.getTupleMatches().clear();
-
-        final int previous = oldMatches.size();
-        final BetaNodeConstraints binder = getJoinNodeBinder();
-
-        for ( final Iterator rightIterator = memory.rightObjectIterator( workingMemory,
-                                                                         leftTuple ); rightIterator.hasNext(); ) {
-            final ObjectMatches objectMatches = (ObjectMatches) rightIterator.next();
-            final InternalFactHandle handle = objectMatches.getFactHandle();
-
-            if ( binder.isAllowed( handle,
-                                   leftTuple,
-                                   workingMemory ) ) {
-                // test passes
-                TupleMatch tupleMatch = (TupleMatch) oldMatches.remove( handle );
-                if ( tupleMatch == null ) {
-                    // no previous matches so add a match now
-                    tupleMatch = this.tupleMatchFactory.newTupleMatch( leftTuple, objectMatches );
-                    objectMatches.add( tupleMatch );
-                }
-                leftTuple.addTupleMatch( handle,
-                                         tupleMatch );
-            } else {
-                final TupleMatch tupleMatch = (TupleMatch) oldMatches.remove( handle );
-                if ( tupleMatch != null ) {
-                    // use to match and doesn't any more, so remove match
-                    objectMatches.remove( tupleMatch );
-                }
-            }
+        
+        // Must use the tuple in memory as it has the tuple matches count
+        // If it doesn't exist then propagate as an assert
+        ReteTuple tuple = ( ReteTuple ) memory.getTupleMemory().remove( leftTuple );
+        if ( tuple == null ) {
+            assertTuple( leftTuple, context, workingMemory );
         }
-
-        // TIRELLI's NOTE: the following is necessary because in case memory  
-        // indexing is enabled, the loop over right objects may skip some of the
-        // previously matched objects
-        for ( final Iterator oldMatchesIt = oldMatches.values().iterator(); oldMatchesIt.hasNext(); ) {
-            final TupleMatch tupleMatch = (TupleMatch) oldMatchesIt.next();
-            tupleMatch.getObjectMatches().remove( tupleMatch );
+        
+        Iterator iterator;
+        if ( leftTuple.isFieldIndexed() ) {
+            iterator = memory.getObjectMemory().iterator(leftTuple.getFieldIndexHashCode());
+        } else {
+            iterator = memory.getObjectMemory().iterator();
         }
-
-        if ( previous == 0 && leftTuple.matchesSize() == 0 ) {
-            for ( LinkedListNode node = leftTuple.getChildEntries().getFirst(); node != null; node = node.getNext() ) {
-                ReteTuple tuple = (ReteTuple) ((LinkedListEntry) node).getObject();
-                tuple.modifyTuple( context,
-                                   workingMemory );
+        
+        int matches = tuple.getMatches();
+        
+        for ( FactEntry entry = (FactEntry) iterator.next(); entry != null; entry = ( FactEntry )entry.getNext() ) {
+            InternalFactHandle handle = entry.getFactHandle();
+            if ( !this.constraints.isAllowed( handle, leftTuple, workingMemory ) ) {                                   
+                matches--;
             }
-        } else if ( previous != 0 && leftTuple.matchesSize() == 0 ) {
+        } 
+        
+        if  ( tuple.getMatches() != 0 && matches  == 0 ) {
             this.sink.propagateAssertTuple( leftTuple,
                                             context,
-                                            workingMemory );
-        } else if ( previous == 0 && leftTuple.matchesSize() != 0 ) {
-            for ( LinkedListNode node = leftTuple.getChildEntries().getFirst(); node != null; node = node.getNext() ) {
-                ReteTuple tuple = (ReteTuple) ((LinkedListEntry) node).getObject();
-                tuple.retractTuple( context,
-                                    workingMemory );
-            }
+                                            workingMemory );            
+        } else if ( tuple.getMatches() == 0 && matches != 0 )  {
+            this.sink.propagateRetractTuple( leftTuple,
+                                             context,
+                                             workingMemory );            
         }
     }
 
-    public void modifyObject(final InternalFactHandle handle,
-                             final PropagationContext context,
-                             final InternalWorkingMemory workingMemory) {
+    public void modifyObject(InternalFactHandle handle,
+                             PropagationContext context,
+                             InternalWorkingMemory workingMemory) {
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
-
-        // Remove the FactHandle from memory
-        final ObjectMatches objectMatches = memory.remove( workingMemory,
-                                                           handle );
-        memory.add( workingMemory,
-                    objectMatches );
-
-        TupleMatch tupleMatch = objectMatches.getFirstTupleMatch();
-        final BetaNodeConstraints binder = getJoinNodeBinder();
-
-        for ( final Iterator it = memory.leftTupleIterator( workingMemory,
-                                                            handle ); it.hasNext(); ) {
-            final ReteTuple leftTuple = (ReteTuple) it.next();
-
-            if ( tupleMatch != null && tupleMatch.getTuple() == leftTuple ) {
-                // has previous match so need to decide whether to continue
-                // modify or retract
-                final int previous = leftTuple.getTupleMatches().size();
-                TupleMatch nextTupleMatch = (TupleMatch) tupleMatch.getNext();
-                if ( !binder.isAllowed( handle,
-                                        leftTuple,
-                                        workingMemory ) ) {
-                    leftTuple.removeMatch( handle );
-                    objectMatches.remove( tupleMatch );
+        if ( !memory.getObjectMemory().contains( handle ) ) {
+            assertObject( handle, context, workingMemory );
+        }
+        
+        Iterator it = memory.getTupleMemory().iterator();
+        for ( ReteTuple tuple = ( ReteTuple ) it.next(); tuple != null; tuple = ( ReteTuple ) it.next() ) {
+            if ( this.constraints.isAllowed( handle, tuple, workingMemory ) ) {
+                int matches = tuple.getMatches();
+                tuple.setMatches( matches + 1 );
+                if ( matches == 0 ) {
+                    this.sink.propagateRetractTuple( tuple, context, workingMemory );
                 }
-                if ( previous == 0 && leftTuple.matchesSize() == 0 ) {
-                    for ( LinkedListNode node = leftTuple.getChildEntries().getFirst(); node != null; node = node.getNext() ) {
-                        ReteTuple tuple = (ReteTuple) ((LinkedListEntry) node).getObject();
-                        tuple.modifyTuple( context,
-                                           workingMemory );
-                    }
-                } else if ( previous != 0 && leftTuple.matchesSize() == 0 ) {
-                    this.sink.propagateAssertTuple( leftTuple,
-                                                    context,
-                                                    workingMemory );
-                } else if ( previous == 0 && leftTuple.matchesSize() != 0 ) {
-                    for ( LinkedListNode node = leftTuple.getChildEntries().getFirst(); node != null; node = node.getNext() ) {
-                        ReteTuple tuple = (ReteTuple) ((LinkedListEntry) node).getObject();
-                        tuple.retractTuple( context,
-                                            workingMemory );
-                    }
-                }
-
-                tupleMatch = (TupleMatch) nextTupleMatch;
-            } else {
-                // no previous join, so attempt join now
-                final int previousSize = leftTuple.matchesSize();
-                attemptJoin( leftTuple,
-                             handle,
-                             objectMatches,
-                             binder,
-                             workingMemory );
-                if ( previousSize == 0 && leftTuple.matchesSize() != 0 ) {
-                    for ( LinkedListNode node = leftTuple.getChildEntries().getFirst(); node != null; node = node.getNext() ) {
-                        ReteTuple tuple = (ReteTuple) ((LinkedListEntry) node).getObject();
-                        tuple.retractTuple( context,
-                                            workingMemory );
-                    }
-                }
             }
-        }
-    }
-
+        }        
+    }            
+    
     /* (non-Javadoc)
      * @see org.drools.reteoo.BaseNode#updateNewNode(org.drools.reteoo.WorkingMemoryImpl, org.drools.spi.PropagationContext)
      */
-    public void updateNewNode(final InternalWorkingMemory workingMemory,
-                              final PropagationContext context) {
+    public void updateSink(final TupleSink sink,
+                           final PropagationContext context,
+                           final InternalWorkingMemory workingMemory) {
         //        this.attachingNewNode = true;
         //
         //        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
@@ -406,28 +318,4 @@
         //
         //        this.attachingNewNode = true;
     }
-
-        /**
-         * @inheritDoc
-         */
-        public List getPropagatedTuples(final InternalWorkingMemory workingMemory,
-                                        final TupleSink sink) {
-    //        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
-    //        final int index = this.getTupleSinks().indexOf( sink );
-    //        final List propagatedTuples = new ArrayList();
-    //
-    //        for ( final Iterator it = memory.getLeftTupleMemory().iterator(); it.hasNext(); ) {
-    //            final ReteTuple leftTuple = (ReteTuple) it.next();
-    //            final LinkedList linkedTuples = leftTuple.getLinkedTuples();
-    //
-    //            LinkedListObjectWrapper wrapper = (LinkedListObjectWrapper) linkedTuples.getFirst();
-    //            for ( int i = 0; i < index; i++ ) {
-    //                wrapper = (LinkedListObjectWrapper) wrapper.getNext();
-    //            }
-    //            propagatedTuples.add( wrapper.getObject() );
-    //        }
-    //        return propagatedTuples;
-            return null;
-        }
-
 }

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectHashTable.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectHashTable.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectHashTable.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -0,0 +1,17 @@
+package org.drools.reteoo;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.spi.Tuple;
+import org.drools.util.Iterator;
+
+public interface ObjectHashTable {
+    public Iterator iterator();
+    public Iterator iterator(int hashCode);
+    public Iterator iterator(ReteTuple tuple);
+    
+    public boolean add(InternalFactHandle handle, boolean checkExists);
+    public boolean add(InternalFactHandle handle);
+    public boolean remove(InternalFactHandle handle);
+    public boolean contains(InternalFactHandle handle);
+    
+}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectMatches.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectMatches.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectMatches.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -1,96 +0,0 @@
-package org.drools.reteoo;
-
-/*
- * Copyright 2005 JBoss Inc
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import org.drools.common.DefaultFactHandle;
-import org.drools.common.InternalFactHandle;
-import org.drools.util.BaseMultiLinkedListNode;
-import org.drools.util.LinkedList;
-
-/**
- * 
- * <code>ObjectMatches</code> maintains a reference to its <code>FactHandleImpl</code> and a <code>LinkedList</code> of <code>TupleMatch</code>es.
- * 
- * @see CompositeTupleMatch
- * @see LinkedList
- * 
- * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
- * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
- *
- */
-public class ObjectMatches extends BaseMultiLinkedListNode {
-    private LinkedList              list;
-
-    private final InternalFactHandle handle;
-
-    /**
-     * Constructs an ObjectMatches which maintain a reference to its <code>FactHandleImpl</code> with an empty <code>LinkedList</code>.
-     *  
-     * @param handle
-     */
-    public ObjectMatches(final InternalFactHandle handle) {
-        this.list = new LinkedList();
-        this.handle = handle;
-    }
-   
-    void add(final TupleMatch tupleMatch) {
-        this.list.add( tupleMatch );
-    }
-
-    /**
-     * Removes the <code>TupleMatch</code> as the underlying <code>ReteTuple</code> has been retracted and no longer matches.
-     * 
-     * @param compositeTupleMatch
-     */
-    void remove(final TupleMatch tupleMatch) {
-        this.list.remove( tupleMatch );
-    }
-
-    /**
-     * Return <code>FactHandleImpl</code> that this provides the <code>TupleMatch</code>es for.
-     * @return
-     */
-    public InternalFactHandle getFactHandle() {
-        return this.handle;
-    }
-
-    /**
-     * Return the first <code>TupleMatch</code> that this <code>FactHandleImpl</code> matches.
-     * 
-     * @return the <code>TupleMatch</code>
-     */
-    public CompositeTupleMatch getFirstTupleMatch() {
-        return (CompositeTupleMatch) this.list.getFirst();
-    }
-
-    /**
-     * Return the last <code>TupleMatch</code> that this <code>FactHandleImpl</code> matches.
-     * 
-     * @return the <code>TupleMatch</code>
-     */
-    public TupleMatch getLastTupleMatch() {
-        return (TupleMatch) this.list.getLast();
-    }
-
-    public int size() {
-        return this.list.size();
-    }
-
-    public boolean hasMatches() {
-        return !this.list.isEmpty();
-    }
-}

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSink.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSink.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSink.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -59,8 +59,8 @@
     void retractObject(InternalFactHandle handle,
                        PropagationContext context,
                        InternalWorkingMemory workingMemory);
-
+    
     void modifyObject(InternalFactHandle handle,
                       PropagationContext context,
-                      InternalWorkingMemory workingMemory);
+                      InternalWorkingMemory workingMemory);    
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSource.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSource.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSource.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -118,7 +118,5 @@
         }         
     }
     
-    public abstract void updateSink(ObjectSink sink, PropagationContext context, InternalWorkingMemory workingMemory);
-    
-    public abstract List getPropagatedFacts(InternalWorkingMemory workingMemory);
+    public abstract void updateSink(ObjectSink sink, PropagationContext context, InternalWorkingMemory workingMemory);    
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectTypeNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectTypeNode.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectTypeNode.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -162,12 +162,14 @@
 
         this.sink.propagateRetractObject( handle, context, workingMemory, true );
     }
+    
 
     public void modifyObject(final InternalFactHandle handle,
                              final PropagationContext context,
                              final InternalWorkingMemory workingMemory) {        
         this.sink.propagateModifyObject( handle, context, workingMemory );       
     }
+
     
     public void updateSink(ObjectSink sink, PropagationContext context, InternalWorkingMemory workingMemory) {
         final PrimitiveLongMap memory = (PrimitiveLongMap) workingMemory.getNodeMemory( this );        

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/Rete.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/Rete.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/Rete.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -315,14 +315,14 @@
         return this.objectTypeNodes.equals( other.objectTypeNodes );
     }
 
-    public List getPropagatedFacts(InternalWorkingMemory workingMemory) {
-        List facts = new ArrayList();
+    public void updateSink(ObjectSink sink,
+                           PropagationContext context,
+                           InternalWorkingMemory workingMemory) {
         for ( final Iterator i = workingMemory.getFactHandleMap().entrySet().iterator(); i.hasNext(); ) {
             final Map.Entry entry = (Map.Entry) i.next();
             final DefaultFactHandle handle = (DefaultFactHandle) entry.getValue();
-            facts.add(handle);
+            sink.assertObject( handle, context, workingMemory );
         }
-        return facts;
     }
 
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteTuple.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteTuple.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteTuple.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -8,6 +8,7 @@
 import org.drools.spi.Activation;
 import org.drools.spi.Tuple;
 import org.drools.util.BaseEntry;
+import org.drools.util.LinkedList;
 
 public class ReteTuple extends BaseEntry
     implements
@@ -25,6 +26,12 @@
     private long                     recency;    
     
     private int                      hashCode;
+    
+    private int                      fieldIndexHashCode;
+    
+    private boolean                  fieldIndexed;
+    
+    private int                      matches;    
 
     // ------------------------------------------------------------
     // Constructors
@@ -60,8 +67,32 @@
             entry = entry.parent;
         }
         return entry.handle;
+    }        
+    
+    public int getFieldIndexHashCode() {
+        return fieldIndexHashCode;
     }
-    
+
+    public void setFieldIndexHashCode(int fieldIndexHashCode) {
+        this.fieldIndexHashCode = fieldIndexHashCode;
+    }
+
+    public boolean isFieldIndexed() {
+        return fieldIndexed;
+    }
+
+    public void setIsFieldIndexHashCode(boolean fieldIndexed) {
+        this.fieldIndexed = fieldIndexed;
+    }        
+
+    public int getMatches() {
+        return matches;
+    }
+
+    public void setMatches(int matches) {
+        this.matches = matches;
+    }
+
     public InternalFactHandle getLastHandle() {
         return this.handle;
     }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/RightInputAdapterNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/RightInputAdapterNode.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/RightInputAdapterNode.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -40,7 +40,7 @@
     /**
      * 
      */
-    private static final long serialVersionUID = 5777695177854269219L;
+    private static final long serialVersionUID = 320L;
 
     private final TupleSource tupleSource;
 
@@ -113,17 +113,10 @@
     /* (non-Javadoc)
      * @see org.drools.reteoo.BaseNode#updateNewNode(org.drools.reteoo.WorkingMemoryImpl, org.drools.spi.PropagationContext)
      */
-    public void updateNewNode(final InternalWorkingMemory workingMemory,
-                              final PropagationContext context) {
-        // this node has no memory, so we need to get the parent node to repropagate. We simulate this be re-attaching
-        this.attachingNewNode = true;
-        // We need to detach and re-attach to make sure the node is at the top
-        // for the propagation
-        this.tupleSource.removeTupleSink( this );
-        this.tupleSource.addTupleSink( this );
-        this.tupleSource.updateNewNode( workingMemory,
-                                        context );
-        this.attachingNewNode = false;
+    public void updateSink(final ObjectSink sink,
+                           final PropagationContext context,
+                           final InternalWorkingMemory workingMemory) {
+        this.tupleSource.updateSink( new TupleSinkAdapter( sink, this.column), context, workingMemory );
     }
 
     public void remove(final BaseNode node,
@@ -135,16 +128,40 @@
         this.tupleSource.remove( this,
                                  workingMemories );
     }
+    
+    /**
+     * Used with the updateSink method, so that the parent ObjectSource
+     * can  update the  TupleSink
+     * @author mproctor
+     *
+     */
+    private static class TupleSinkAdapter
+        implements
+        TupleSink {
+        private ObjectSink sink;
+        private int column;
 
-    public List getPropagatedFacts(InternalWorkingMemory workingMemory) {
-        List tuples = this.tupleSource.getPropagatedTuples( workingMemory, this );
-        List facts = new ArrayList();
-        
-        for(Iterator it = tuples.iterator(); it.hasNext(); ) {
-            ReteTuple tuple = (ReteTuple) it.next();
-            facts.add( (InternalFactHandle) tuple.get( this.column ) );
+        public TupleSinkAdapter(ObjectSink sink, int column) {
+            this.sink = sink;
+            this.column =  column;
         }
-        return facts;
+
+        public void assertTuple(ReteTuple tuple,
+                                PropagationContext context,
+                                InternalWorkingMemory workingMemory) {
+            this.sink.assertObject( (InternalFactHandle) tuple.get( this.column ), context, workingMemory );
+        }
+
+        public void modifyTuple(ReteTuple tuple,
+                                PropagationContext context,
+                                InternalWorkingMemory workingMemory) {
+            throw new UnsupportedOperationException( "TupleSinkAdapter onlys supports assertObject method calls" );
+        }
+
+        public void retractTuple(ReteTuple tuple,
+                                 PropagationContext context,
+                                 InternalWorkingMemory workingMemory) {
+            throw new UnsupportedOperationException( "TupleSinkAdapter onlys supports assertObject method calls" );
+        }  
     }
-
 }

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleTupleMatch.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleTupleMatch.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleTupleMatch.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -1,103 +0,0 @@
-package org.drools.reteoo;
-
-/*
- * Copyright 2005 JBoss Inc
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import org.drools.common.InternalWorkingMemory;
-import org.drools.spi.PropagationContext;
-import org.drools.spi.Tuple;
-import org.drools.util.AbstractBaseLinkedListNode;
-import org.drools.util.LinkedListEntry;
-
-/**
- * <code>TupleMatch</code> maintains a reference to the parent <code>ReteTuple</code> and a <code>List</code> of all resulting joins. 
- * This is a List rather than a single instance reference because we need to create a join for each TupleSink branches.
- * A reference is also maintained to the <code>ObjectMatches</code> instance; this is so the <code>FactHandleImpl</code> that 
- * is used in the join can be referenced, and also any other <code>TupleMatch</code>es the <code>FactHandleImpl</code> is joined with.
- * 
- * @see SingleTupleMatch
- * @see ObjectMatches
- * @see ReteTuple
- * 
- * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
- * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
- *
- */
-public class SingleTupleMatch extends AbstractBaseLinkedListNode implements TupleMatch {
-    private ReteTuple          tuple;
-    
-    private ReteTuple           joined;
-
-    private ObjectMatches      objectMatches;
-
-    /**
-     * Construct a <code>TupleMatch</code> with references to the parent <code>ReteTuple</code> and 
-     * <code>FactHandleImpl</code>, via ObjecMatches.
-     * 
-     * @param tuple
-     * @param objectMatches
-     */
-    public SingleTupleMatch(final ReteTuple tuple,
-                      final ObjectMatches objectMatches) {
-        this.tuple = tuple;
-        this.objectMatches = objectMatches;    
-    }
-
-    /* (non-Javadoc)
-     * @see org.drools.reteoo.ITupleMatch#getTuple()
-     */
-    public ReteTuple getTuple() {
-        return this.tuple;
-    }
-
-    /* (non-Javadoc)
-     * @see org.drools.reteoo.ITupleMatch#getObjectMatches()
-     */
-    public ObjectMatches getObjectMatches() {
-        return this.objectMatches;
-    }
-
-    /* (non-Javadoc)
-     * @see org.drools.reteoo.ITupleMatch#addJoinedTuple(org.drools.reteoo.ReteTuple)
-     */
-    public void addJoinedTuple(final ReteTuple tuple) {
-        this.joined = tuple;
-    }
-
-    /* (non-Javadoc)
-     * @see org.drools.reteoo.ITupleMatch#propagateRetractTuple(org.drools.spi.PropagationContext, org.drools.common.InternalWorkingMemory)
-     */
-    public void propagateRetractTuple(final PropagationContext context,
-                                      final InternalWorkingMemory workingMemory) {
-        this.joined.retractTuple( context, workingMemory );
-    }
-
-    /* (non-Javadoc)
-     * @see org.drools.reteoo.ITupleMatch#propagateModifyTuple(org.drools.spi.PropagationContext, org.drools.common.InternalWorkingMemory)
-     */
-    public void propagateModifyTuple(final PropagationContext context,
-                                     final InternalWorkingMemory workingMemory) {
-        this.joined.modifyTuple( context, workingMemory );
-    }
-
-    /* (non-Javadoc)
-     * @see org.drools.reteoo.ITupleMatch#getTupleForSink(org.drools.reteoo.TupleSink)
-     */
-    public ReteTuple getTupleForSink(TupleSink sink) {
-        return this.joined;
-    }
-
-}
\ No newline at end of file

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleTupleMatchFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleTupleMatchFactory.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleTupleMatchFactory.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -1,26 +0,0 @@
-package org.drools.reteoo;
-
-public class SingleTupleMatchFactory
-    implements
-    TupleMatchFactory {
-
-    private static TupleMatchFactory INSTANCE;
-    
-    public static TupleMatchFactory getInstance() {
-        if ( INSTANCE == null ) {
-            INSTANCE = new SingleTupleMatchFactory();
-        }
-        return INSTANCE;
-    }
-    
-    private SingleTupleMatchFactory() {
-        
-    }
-    
-    
-    public TupleMatch newTupleMatch(ReteTuple tuple,
-                                    ObjectMatches objectMatches) {
-        return new CompositeTupleMatch(tuple, objectMatches);
-    }
-
-}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleKey.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleKey.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleKey.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -1,162 +0,0 @@
-package org.drools.reteoo;
-
-/*
- * Copyright 2005 JBoss Inc
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import java.io.Serializable;
-
-import org.drools.FactHandle;
-import org.drools.common.DefaultFactHandle;
-import org.drools.common.InternalFactHandle;
-import org.drools.spi.Tuple;
-
-/**
- * A composite key to match tuples.
- * 
- * @see Tuple
- * 
- * @author <a href="mailto:bob at eng.werken.com">bob mcwhirter </a>
- */
-class TupleKey
-    implements
-    Serializable {
-    /**
-     * 
-     */
-    private static final long    serialVersionUID = 320L;
-
-    public static final TupleKey EMPTY_KEY        = new TupleKey();
-
-    // ------------------------------------------------------------
-    // Instance members
-    // ------------------------------------------------------------
-
-    /** Columns. */
-    private final FactHandleList handles;
-
-    /**
-     * The recency of this tuple is given by the 
-     * highest recency of all added fact handles
-     */
-    private long                 recency          = 0;
-
-    // ------------------------------------------------------------
-    // Constructors
-    // ------------------------------------------------------------
-
-    private TupleKey() {
-        this.handles = FactHandleList.EMPTY_LIST;// FactHandleList.EMPTY_LIST;
-    }
-
-    public TupleKey(final TupleKey key) {
-        this.handles = key.handles;
-        this.recency = key.recency;
-    }
-
-    public TupleKey(final InternalFactHandle handle) {
-        this.handles = new FactHandleList( handle );
-        this.recency = handle.getRecency();
-    }
-
-    public TupleKey(final TupleKey left,
-                    final InternalFactHandle handle) {
-        this.handles = new FactHandleList( left.handles,
-                                           handle );
-        this.recency = left.recency + handle.getRecency();
-    }
-
-    public String toString() {
-        return "[TupleKey: recency=" + this.recency + " handles=" + this.handles + "]";
-    }
-
-    // ------------------------------------------------------------
-    //
-    // ------------------------------------------------------------
-
-    /**
-     * Retrieve a <code>FactHandle</code> by declaration.
-     * 
-     * @param declaration
-     *            The declaration.
-     * 
-     * @return The fact handle.
-     */
-    public InternalFactHandle get(final int index) {
-        return this.handles.get( index );
-    }
-
-    /**
-     * Determine if this key contains the specified root fact object.
-     * 
-     * @param handle
-     *            The fact-handle to test.
-     * 
-     * @return <code>true</code> if this key contains the specified root
-     *         fact-handle, otherwise <code>false</code>.
-     */
-    public boolean containsFactHandle(final FactHandle handle) {
-        return this.handles.contains( handle );
-    }
-
-    /**
-     * Determine if the specified key is a subset of this key.
-     * 
-     * @param that
-     *            The key to compare.
-     * 
-     * @return <code>true</code> if the specified key is a subset of this key.
-     */
-    public boolean containsAll(final TupleKey that) {
-        return this.handles.containsAll( that.handles );
-    }
-
-    InternalFactHandle[] getFactHandles() {
-        return this.handles.getHandles();
-    }
-
-    public int size() {
-        return this.handles.size();
-    }
-
-    public long getRecency() {
-        return this.recency;
-    }
-
-    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-    /**
-     * @see Object
-     */
-    public boolean equals(final Object object) {
-        if ( this == object ) {
-            return true;
-        }
-
-        if ( object == null || getClass() != object.getClass() ) {
-            return false;
-        }
-
-        return this.handles.equals( ((TupleKey) object).handles );
-    }
-
-    /**
-     * @see Object
-     */
-    public int hashCode() {
-        return this.handles.hashCode();
-    }
-
-}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleMatch.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleMatch.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleMatch.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -1,42 +0,0 @@
-package org.drools.reteoo;
-
-import org.drools.common.InternalWorkingMemory;
-import org.drools.spi.PropagationContext;
-import org.drools.spi.Tuple;
-import org.drools.util.LinkedListNode;
-
-public interface TupleMatch
-    extends
-    LinkedListNode {
-
-    /**
-     * Return the parent <code>ReteTuple</code>
-     * 
-     * @return the <code>ReteTuple</code>
-     */
-    public ReteTuple getTuple();
-
-    /**
-     * Returns the referenced <code>ObjectMatches</code> which provides the 
-     * <code>FactHandleImpl</code> the <code>ReteTuple</code> is joined with.
-     * 
-     * @return the <code>ObjectMatches</code>
-     */
-    public ObjectMatches getObjectMatches();
-
-    /**
-     * Adds a resulting join to the <code>List</code>. A join is made for each <code>TupleSink</code>.
-     * 
-     * @param tuple
-     */
-    public void addJoinedTuple(final ReteTuple tuple);
-
-    public void propagateRetractTuple(final PropagationContext context,
-                                      final InternalWorkingMemory workingMemory);
-
-    public void propagateModifyTuple(final PropagationContext context,
-                                     final InternalWorkingMemory workingMemory);
-
-    public ReteTuple getTupleForSink(TupleSink sink);
-
-}
\ No newline at end of file

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleMatchFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleMatchFactory.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleMatchFactory.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -1,5 +0,0 @@
-package org.drools.reteoo;
-
-public interface TupleMatchFactory {
-    public TupleMatch newTupleMatch(ReteTuple tuple, ObjectMatches objectMatches);
-}

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSink.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSink.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSink.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -54,8 +54,8 @@
     void retractTuple(ReteTuple tuple,
                       PropagationContext context,
                       InternalWorkingMemory workingMemory);
-
+    
     void modifyTuple(ReteTuple tuple,
                      PropagationContext context,
-                     InternalWorkingMemory workingMemory);
+                     InternalWorkingMemory workingMemory);    
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSinkPropagator.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSinkPropagator.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSinkPropagator.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -14,6 +14,24 @@
     public void propagateAssertTuple(ReteTuple tuple,
                                      PropagationContext context,
                                      InternalWorkingMemory workingMemory);
+    
+    public void propagateRetractTuple(ReteTuple tuple,
+                                      InternalFactHandle handle,
+                                      PropagationContext context,
+                                      InternalWorkingMemory workingMemory);  
+    
+    public void propagateRetractTuple(ReteTuple tuple,
+                                      PropagationContext context,
+                                      InternalWorkingMemory workingMemory);      
+    
+    public void propagateModifyTuple(ReteTuple tuple,
+                                     InternalFactHandle handle,
+                                     PropagationContext context,
+                                     InternalWorkingMemory workingMemory);    
+    
+    public void propagateModifyTuple(ReteTuple tuple,
+                                     PropagationContext context,
+                                     InternalWorkingMemory workingMemory);       
 
     public LinkedList createAndPropagateAssertTupleWithMemory(InternalFactHandle handle,
                                                               PropagationContext context,

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSource.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSource.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSource.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -107,14 +107,6 @@
             }
         } 
     }
-
-
-    /**
-     * Returns the list of propagated tuples
-     * @return
-     */
-    public abstract List getPropagatedTuples(InternalWorkingMemory workingMemory,
-                                             TupleSink sink);
     
     public abstract void updateSink(TupleSink sink, PropagationContext context, InternalWorkingMemory workingMemory);
 

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/AbstractHashTable.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/AbstractHashTable.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/AbstractHashTable.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -20,6 +20,9 @@
 
     protected Entry[]          table;
 
+    
+    private HashTableIterator iterator;
+    
     public AbstractHashTable() {
         this( 16,
               0.75f );
@@ -32,6 +35,14 @@
         this.table = new Entry[capacity];
         this.comparator = EqualityEquals.getInstance();
     }
+    
+    public Iterator iterator() {
+        if ( this.iterator == null ) {
+            this.iterator = new HashTableIterator( this );            
+        }
+        this.iterator.reset();
+        return this.iterator;
+    }    
 
     public void setComparator(ObjectComparator comparator) {
         this.comparator = comparator;
@@ -158,6 +169,52 @@
         public boolean equal(Object object1,
                              Object object2);
     }
+    
+    /**
+     * Fast re-usable iterator
+     *
+     */
+    public static class HashTableIterator implements Iterator {
+        private AbstractHashTable hashTable;
+        private Entry[] table;
+        private int row;
+        private int length;
+        private Entry entry;
+        
+        public HashTableIterator(AbstractHashTable hashTable) {
+            this.hashTable = hashTable;
+        }
+        
+        /* (non-Javadoc)
+         * @see org.drools.util.Iterator#next()
+         */
+        public Entry next() {            
+            if (  this.entry == null ) {
+                row++;
+                if ( row == length ) {
+                    return null;
+                }
+                this.entry = this.table[row];
+            } else {
+                this.entry = this.entry.getNext();
+                if ( this.entry == null ) {
+                    this.entry = next();
+                }
+            }
+            
+            return this.entry;
+        }
+        
+        /* (non-Javadoc)
+         * @see org.drools.util.Iterator#reset()
+         */
+        public void reset() {
+            this.table = this.hashTable.getTable();
+            this.length = this.table.length;
+            this.row = -1;
+            this.entry = null;
+        }
+    }    
 
     public static class InstanceEquals
         implements

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FactHashSet.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FactHashSet.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FactHashSet.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -1,108 +0,0 @@
-/**
- * 
- */
-package org.drools.util;
-
-import org.drools.common.InternalFactHandle;
-
-public class FactHashSet extends AbstractHashTable {
-    private static final long serialVersionUID = -45167109828358945L;
-
-    public FactHashSet() {
-        this( 16,
-              0.75f );
-    }
-
-    public FactHashSet(int capacity,
-                         float loadFactor) {
-        super( capacity,
-               loadFactor );
-    }    
-
-    public boolean add(InternalFactHandle handle, boolean checkExists) {
-        int hashCode =  handle.hashCode();
-        int index = indexOf( hashCode,
-                             table.length );
-
-        // scan the linked entries to see if it exists
-        if ( checkExists ) {
-            FactEntry current = (FactEntry) this.table[index];
-            while ( current != null ) {
-                if ( hashCode == current.hashCode && handle.getId() == current.handle.getId() )  {
-                    return false;
-                }
-                current = (FactHashSet.FactEntry) current.getNext();
-            }
-        }
-
-        // We aren't checking the key exists, or it didn't find the key
-        FactEntry entry = new FactEntry( handle,
-                                             hashCode );
-        entry.next = (FactEntry) this.table[index];
-        this.table[index] = entry;
-
-        if ( this.size++ >= this.threshold ) {
-            resize( 2 * this.table.length );
-        }
-        return true;
-    }
-
-    public boolean contains(InternalFactHandle handle) {
-        int hashCode = handle.hashCode();
-        int index = indexOf( hashCode,
-                             table.length );
-
-        FactEntry current = (FactEntry) this.table[index];
-        while ( current != null ) {
-            if ( hashCode == current.hashCode && handle.getId() == current.handle.getId() ) {
-                return false;
-            }
-            current = (FactEntry) current.getNext();
-        }
-        return true;
-    }
-
-    public boolean remove(InternalFactHandle handle) {
-        int hashCode = handle.hashCode();
-        int index = indexOf( hashCode,
-                             table.length );
-
-        FactEntry previous = (FactEntry) this.table[index];
-        FactEntry current = previous;
-        while ( current != null ) {
-            FactEntry next = (FactEntry) current.getNext();
-            if ( hashCode == current.hashCode && handle.getId() == current.handle.getId() ) {
-                if ( previous == current ) {
-                    this.table[index] = next;
-                } else {
-                    previous.setNext( next );
-                }
-                current.setNext( null );
-                this.size--;
-                return true;
-            }
-            previous = current;
-            current = next;
-        }
-        return false;
-    }
-    
-    public Entry getBucket(int hashCode) {
-        int h = hashCode;
-        h += ~(h << 9);
-        h ^= (h >>> 14);
-        h += (h << 4);
-        h ^= (h >>> 10);
-        
-        return this.table[ indexOf( h, table.length ) ];
-    }       
-
-    public int hash(Object key) {
-        return key.hashCode();
-    }
-
-    protected int indexOf(int hashCode,
-                          int dataSize) {
-        return hashCode & (dataSize - 1);
-    }    
-}
\ No newline at end of file

Copied: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FactHashTable.java (from rev 6390, labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FactHashSet.java)
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FactHashSet.java	2006-09-23 21:31:37 UTC (rev 6390)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FactHashTable.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -0,0 +1,123 @@
+/**
+ * 
+ */
+package org.drools.util;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.reteoo.ObjectHashTable;
+import org.drools.reteoo.ReteTuple;
+import org.drools.spi.Tuple;
+
+public class FactHashTable extends AbstractHashTable implements ObjectHashTable {
+    private static final long serialVersionUID = 320L;    
+
+    public FactHashTable() {
+        this( 16,
+              0.75f );
+    }
+
+    public FactHashTable(int capacity,
+                         float loadFactor) {
+        super( capacity,
+               loadFactor );
+    }        
+    
+    public Iterator iterator(int hashCode) {
+        throw new UnsupportedOperationException("FactHashTable does not support the method iterator(int hashCode");
+    }      
+    
+    public Iterator iterator(ReteTuple tuple) {
+        return iterator();
+    }    
+
+    public boolean add(InternalFactHandle handle) {
+        return add( handle, true);
+    }
+    
+    public boolean add(InternalFactHandle handle, boolean checkExists) {
+        int hashCode =  handle.hashCode();
+        int index = indexOf( hashCode,
+                             table.length );
+
+        // scan the linked entries to see if it exists
+        if ( checkExists ) {
+            FactEntry current = (FactEntry) this.table[index];
+            while ( current != null ) {
+                if ( hashCode == current.hashCode && handle.getId() == current.handle.getId() )  {
+                    return false;
+                }
+                current = (FactHashTable.FactEntry) current.getNext();
+            }
+        }
+
+        // We aren't checking the key exists, or it didn't find the key
+        FactEntry entry = new FactEntry( handle,
+                                             hashCode );
+        entry.next = (FactEntry) this.table[index];
+        this.table[index] = entry;
+
+        if ( this.size++ >= this.threshold ) {
+            resize( 2 * this.table.length );
+        }
+        return true;
+    }
+
+    public boolean contains(InternalFactHandle handle) {
+        int hashCode = handle.hashCode();
+        int index = indexOf( hashCode,
+                             table.length );
+
+        FactEntry current = (FactEntry) this.table[index];
+        while ( current != null ) {
+            if ( hashCode == current.hashCode && handle.getId() == current.handle.getId() ) {
+                return false;
+            }
+            current = (FactEntry) current.getNext();
+        }
+        return true;
+    }
+
+    public boolean remove(InternalFactHandle handle) {
+        int hashCode = handle.hashCode();
+        int index = indexOf( hashCode,
+                             table.length );
+
+        FactEntry previous = (FactEntry) this.table[index];
+        FactEntry current = previous;
+        while ( current != null ) {
+            FactEntry next = (FactEntry) current.getNext();
+            if ( hashCode == current.hashCode && handle.getId() == current.handle.getId() ) {
+                if ( previous == current ) {
+                    this.table[index] = next;
+                } else {
+                    previous.setNext( next );
+                }
+                current.setNext( null );
+                this.size--;
+                return true;
+            }
+            previous = current;
+            current = next;
+        }
+        return false;
+    }        
+    
+    public Entry getBucket(int hashCode) {
+        int h = hashCode;
+        h += ~(h << 9);
+        h ^= (h >>> 14);
+        h += (h << 4);
+        h ^= (h >>> 10);
+        
+        return this.table[ indexOf( h, table.length ) ];
+    }       
+
+    public int hash(Object key) {
+        return key.hashCode();
+    }
+
+    protected int indexOf(int hashCode,
+                          int dataSize) {
+        return hashCode & (dataSize - 1);
+    }    
+}
\ No newline at end of file

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FieldIndexHashTable.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FieldIndexHashTable.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FieldIndexHashTable.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -4,42 +4,164 @@
 package org.drools.util;
 
 import org.drools.common.InternalFactHandle;
+import org.drools.reteoo.ObjectHashTable;
+import org.drools.reteoo.ReteTuple;
+import org.drools.rule.Declaration;
 import org.drools.spi.FieldExtractor;
+import org.drools.spi.Tuple;
 
-public class FieldIndexHashTable extends AbstractHashTable {
-    private int            fieldIndex;
-    private FieldExtractor extractor;
+public class FieldIndexHashTable extends AbstractHashTable
+    implements
+    ObjectHashTable {
+    private int                         fieldIndex;
 
-    private final int      PRIME = 31;
+    private FieldExtractor              extractor;
 
-    private final int      startResult;
+    private Declaration                 declaration;
 
-    public FieldIndexHashTable(int fieldIndex,
-                               FieldExtractor extractor) {
+    private final int                   PRIME = 31;
+
+    private final int                   startResult;
+
+    private FieldIndexHashTableIterator tupleValueIterator;
+
+    private HashCodeHashTableIterator   hashCodeValueIterator;
+
+    public FieldIndexHashTable(FieldExtractor extractor,
+                               Declaration declaration) {
         this( 16,
               0.75f,
-              fieldIndex,
-              extractor );
+              extractor,
+              declaration );
     }
 
     public FieldIndexHashTable(int capacity,
                                float loadFactor,
-                               int fieldIndex,
-                               FieldExtractor extractor) {
+                               FieldExtractor extractor,
+                               Declaration declaration) {
         super( capacity,
                loadFactor );
-        this.fieldIndex = fieldIndex;
+        this.fieldIndex = extractor.getIndex();
+
         this.extractor = extractor;
 
+        this.declaration = declaration;
+
         this.startResult = PRIME + this.fieldIndex;
     }
 
-    public void add(InternalFactHandle handle) {
+    public Iterator iterator() {
+        throw new UnsupportedOperationException( "FieldIndexHashTable does not support  iterator()" );
+    }
+
+    public Iterator iterator(ReteTuple tuple) {
+        if ( this.tupleValueIterator == null ) {
+            this.tupleValueIterator = new FieldIndexHashTableIterator();
+        }
+        this.tupleValueIterator.reset( get( tuple ) );
+        return this.iterator();
+    }
+
+    public Iterator iterator(int hashCode) {
+        if ( this.hashCodeValueIterator == null ) {
+            this.hashCodeValueIterator = new HashCodeHashTableIterator( this );
+        }
+
+        this.hashCodeValueIterator.reset( hashCode );
+        return this.iterator();
+    }
+
+    /**
+     * Fast re-usable iterator
+     *
+     */
+    public static class FieldIndexHashTableIterator
+        implements
+        Iterator {
+        private Entry entry;
+
+        public FieldIndexHashTableIterator() {
+
+        }
+
+        /* (non-Javadoc)
+         * @see org.drools.util.Iterator#next()
+         */
+        public Entry next() {
+            this.entry = this.entry.getNext();
+            return this.entry;
+        }
+
+        /* (non-Javadoc)
+         * @see org.drools.util.Iterator#reset()
+         */
+        public void reset(Entry entry) {
+            this.entry = entry;
+        }
+
+        public void reset(int hashCode) {
+            throw new UnsupportedOperationException( "FieldIndexHashTableIterator does not support reset(int hashCode)" );
+        }
+    }
+
+    /**
+     * Fast re-usable iterator
+     *
+     */
+    public static class HashCodeHashTableIterator
+        implements
+        Iterator {
+        private AbstractHashTable hashTable;
+        private FactEntry         current;
+        private FactEntry         next;
+        private FieldIndexEntry   index;
+
+        public HashCodeHashTableIterator(AbstractHashTable hashTable) {
+            this.hashTable = hashTable;
+        }
+
+        /* (non-Javadoc)
+         * @see org.drools.util.Iterator#next()
+         */
+        public Entry next() {
+            this.current = (FactEntry) this.next;
+            if ( current == null ) {
+                this.index = (FieldIndexEntry) this.index.getNext();
+                if ( this.index == null ) {
+                    return null;
+                }
+                this.current = this.index.first;
+            }
+            this.next = (FactEntry) current.getNext();
+            return current;
+        }
+
+        /* (non-Javadoc)
+         * @see org.drools.util.Iterator#reset()
+         */
+        public void reset(int hashCode) {
+            this.index = (FieldIndexEntry) this.hashTable.getBucket( hashCode );
+            this.current = null;
+            this.next = (FactEntry) index.getFirst();
+        }
+
+        public void reset(Entry entry) {
+            throw new UnsupportedOperationException( "FieldIndexHashTableIterator does not support reset(Entry entry)" );
+        }
+    }
+
+    public boolean add(InternalFactHandle handle) {
         FieldIndexEntry entry = getOrCreate( this.extractor.getValue( handle.getObject() ) );
         entry.add( handle );
+        return true;
     }
 
-    public void remove(InternalFactHandle handle) {
+    public boolean add(InternalFactHandle handle,
+                       boolean checkExists) {
+        throw new UnsupportedOperationException( "FieldIndexHashTable does not support add(InternalFactHandle handle, boolean checkExists)" );
+    }
+
+    public boolean remove(InternalFactHandle handle) {
         Object value = this.extractor.getValue( handle.getObject() );
         int hashCode = PRIME * startResult + ((value == null) ? 0 : value.hashCode());
 
@@ -63,16 +185,22 @@
                     current.next = null;
                     this.size--;
                 }
-                return;
+                return true;
             }
             previous = current;
             current = next;
         }
+        return false;
     }
 
-    public FieldIndexEntry get(Object value) {
+    public FieldIndexEntry get(ReteTuple tuple) {
+        Object value = this.declaration.getValue( tuple.get( this.declaration ).getObject() );
         int hashCode = PRIME * startResult + ((value == null) ? 0 : value.hashCode());
 
+        if ( !tuple.isFieldIndexed() ) {
+            tuple.setFieldIndexHashCode( hashCode );
+        }
+
         int index = indexOf( hashCode,
                              table.length );
         FieldIndexEntry entry = (FieldIndexEntry) this.table[index];
@@ -125,7 +253,7 @@
         implements
         Entry {
         private Entry                next;
-        FactEntry                    first;
+        private FactEntry            first;
         private final int            hashCode;
         private final int            fieldIndex;
         private final FieldExtractor extractor;
@@ -152,7 +280,7 @@
 
         public void add(InternalFactHandle handle) {
             FactEntry entry = new FactEntry( handle );
-            entry.next =  this.first;
+            entry.next = this.first;
             this.first = entry;
         }
 
@@ -179,7 +307,7 @@
                     if ( this.first == current ) {
                         this.first = next;
                     } else {
-                        previous.next =   next;
+                        previous.next = next;
                     }
                     current.next = null;
                     return current;

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/LinkedList.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/LinkedList.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/LinkedList.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -191,6 +191,38 @@
     public final int size() {
         return this.size;
     }
+    
+    public int hashCode()  {
+        final int PRIME = 31;
+        int result = 1;
+        for ( LinkedListNode node = this.firstNode; node  != null; node =  node.getNext()  ) {
+            result = PRIME * result + node.hashCode();    
+        }
+        return result;        
+    }
+    
+    public boolean equals(Object object) {
+        if ( object == this ) {
+            return  true;
+        }
+        
+        if ( object == null || object.getClass() != LinkedList.class ) {
+            return false;
+        }
+        
+        LinkedList other = ( LinkedList ) object;
+        
+        if ( this.size() != other.size() ) {
+            return false;
+        }
+        
+        for ( LinkedListNode thisNode = this.firstNode, otherNode = other.firstNode; thisNode  != null && otherNode != null; thisNode =  thisNode.getNext(), otherNode = otherNode.getNext()  ) {
+            if ( !thisNode.equals( otherNode ) ) {
+                return false;
+            }
+        }
+        return true;
+    }
 
     /**
      * Returns a list iterator
@@ -224,6 +256,6 @@
                 }
             }
         };
-    }
+    }        
 
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/LinkedListEntry.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/LinkedListEntry.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/LinkedListEntry.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -30,5 +30,13 @@
 
     public Object getObject() {
         return this.object;
+    }    
+    
+    public int hashCode() {
+        return object.hashCode();
     }
+    
+    public boolean equals(Object other)  {
+        return this.object.equals( other );
+    }
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/TupleHashTable.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/TupleHashTable.java	2006-09-29 16:53:05 UTC (rev 6471)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/TupleHashTable.java	2006-09-29 17:35:20 UTC (rev 6472)
@@ -28,7 +28,7 @@
             resize( 2 * this.table.length );
         }
         return null;
-    }
+    }    
 
     public Object get(ReteTuple tuple) {
         int hashCode = tuple.hashCode();
@@ -44,6 +44,10 @@
         }
         return null;
     }
+    
+    public boolean contains(ReteTuple tuple) {
+        return (get(tuple) != null);
+    }
 
     public Object remove(ReteTuple tuple) {
         int hashCode = tuple.hashCode();




More information about the jboss-svn-commits mailing list