[jboss-svn-commits] JBL Code SVN: r6143 - in labs/jbossrules/trunk/drools-core/src: main/java/org/drools/base main/java/org/drools/base/dataproviders main/java/org/drools/base/resolvers main/java/org/drools/common main/java/org/drools/reteoo main/java/org/drools/spi main/java/org/drools/util test/java/org/drools/base/dataproviders test/java/org/drools/base/resolvers test/java/org/drools/examples/manners test/java/org/drools/reteoo

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Mon Sep 11 11:48:26 EDT 2006


Author: mark.proctor at jboss.com
Date: 2006-09-11 11:47:48 -0400 (Mon, 11 Sep 2006)
New Revision: 6143

Added:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/BaseNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/NetworkNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeObjectSinkAdapter.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeTupleMatchChildren.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/ObjectSinkNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSinkNodeList.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSinkPropagator.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleObjectSinkAdapter.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleTupleMatchChildren.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleTupleSink.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleTupleSinkAdapter.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSinkNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSinkNodeList.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSinkPropagator.java
Removed:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AlphaNodeSwitch.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/BaseNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/DefaultObjectSinkList.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/HashedObjectSinkList.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSinkList.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSinkListFactory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/ReteooNode.java
Modified:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/FieldFactory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/dataproviders/MethodDataProvider.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/dataproviders/MethodInvoker.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/resolvers/LiteralValue.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InternalWorkingMemory.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/BetaMemory.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/EvalConditionNode.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/FromNode.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/ObjectMatches.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/QueryTerminalNode.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/ReteooBuilder.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooToJungVisitor.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/TerminalNode.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/TupleSink.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSource.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/FunctionResolver.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/LinkedList.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/dataproviders/MethodDataProviderTest.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/resolvers/ListValueTest.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/resolvers/LiteralValueTest.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/resolvers/MapValueTest.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/examples/manners/ReteooMannersTest.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/AccumulateNodeTest.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/BaseNodeTest.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockObjectSink.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockObjectSource.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockTupleSink.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockTupleSource.java
Log:
JBRULES-484 refactor the core reteoo code for sinle and composite propagations
-code now compiles and manners runs, just incorrectly
-also includes the alpha node hashing rewrite.

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/FieldFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/FieldFactory.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/FieldFactory.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -32,7 +32,7 @@
 
     }
 
-    public static FieldValue getFieldValue(final String value,
+    public static FieldValue getFieldValue(String value,
                                            ValueType valueType) {
         FieldValue field = null;
         if ( value == null ) {
@@ -48,13 +48,13 @@
         } else if ( valueType == ValueType.SHORT_TYPE ) {
             field = new FieldImpl( new Short( value ) );
         } else if ( valueType == ValueType.INTEGER_TYPE ) {
-            field = new FieldImpl( new Integer( value ) );
+            field = new FieldImpl( new Integer( stripNumericType( value ) ) );
         } else if ( valueType == ValueType.LONG_TYPE ) {
-            field = new FieldImpl( new Long( value ) );
+            field = new FieldImpl( new Long( stripNumericType( value ) ) );
         } else if ( valueType == ValueType.FLOAT_TYPE ) {
-            field = new FieldImpl( new Float( value ) );
+            field = new FieldImpl( new Float( stripNumericType( value ) ) );
         } else if ( valueType == ValueType.DOUBLE_TYPE ) {
-            field = new FieldImpl( new Double( value ) );
+            field = new FieldImpl( new Double( stripNumericType( value ) ) );
         } else if ( valueType == ValueType.BOOLEAN_TYPE ) {
             field = new FieldImpl( new Boolean( value ) );
         } else if ( valueType == ValueType.STRING_TYPE ) {
@@ -75,5 +75,14 @@
 
         return field;
     }
+    
+    private static String stripNumericType(String value) {
+        // incase a user adds a f or l, strip it as its not needed
+        if ( Character.getType( value.charAt( value.length() -1 ) ) != Character.DECIMAL_DIGIT_NUMBER ) {
+            value = value.substring( 0, value.length() -1 );
+        }
+        
+        return value;
+    }
 
 }
\ No newline at end of file

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/dataproviders/MethodDataProvider.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/dataproviders/MethodDataProvider.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/dataproviders/MethodDataProvider.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -13,21 +13,21 @@
 public class MethodDataProvider
     implements
     DataProvider {
-    private final MethodInvoker method;
+    private final Invoker invoker;
     
-    public MethodDataProvider(MethodInvoker method) {
-        this.method = method;
+    public MethodDataProvider(Invoker invoker) {
+        this.invoker = invoker;
     }
      
 
     public Declaration[] getRequiredDeclarations() {
-        return this.method.getRequiredDeclarations();
+        return this.invoker.getRequiredDeclarations();
     }
 
     public Iterator getResults(Tuple tuple,
                                WorkingMemory wm,
                                PropagationContext ctx) {
-        Object result = this.method.invoke( tuple, wm, ctx );
+        Object result = this.invoker.invoke( tuple, wm, ctx );
         if ( result instanceof Collection ) {
             return ((Collection) result).iterator();
         } else if ( result instanceof Iterator ) {

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/dataproviders/MethodInvoker.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/dataproviders/MethodInvoker.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/dataproviders/MethodInvoker.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -18,11 +18,15 @@
 import org.drools.spi.PropagationContext;
 import org.drools.spi.Tuple;
 
-public class MethodInvoker {
-    private final ValueHandler   instanceValueHandler;
-    private final Method         method;
-    private final ValueHandler[] valueHandlers;
-    private final Declaration[]  requiredDeclarations;
+public class MethodInvoker
+    implements
+    Invoker {
+    private final ValueHandler         instanceValueHandler;
+    private final Method               method;
+    private final Class[]              parameterTypes;
+    private final ValueHandler[]       valueHandlers;
+    private final Declaration[]        requiredDeclarations;
+    private static final Declaration[] EMPTY_DECLARATIONS = new Declaration[0];
 
     /**
      * Method invoker for static method
@@ -32,21 +36,31 @@
                          ValueHandler[] valueHandlers) {
         this.instanceValueHandler = null;
         this.valueHandlers = valueHandlers;
-        
+
         // determine required declarations
-        List list = new ArrayList(1);        
+        List list = new ArrayList( 1 );
+
         for ( int i = 0, length = valueHandlers.length; i < length; i++ ) {
             if ( valueHandlers[i].getClass() == DeclarationVariable.class ) {
-                list.add( ( (DeclarationVariable) valueHandlers[i] ).getDeclaration() );    
+                list.add( ((DeclarationVariable) valueHandlers[i]).getDeclaration() );
             }
         }
-        
-        this.requiredDeclarations = ( Declaration[] )list.toArray( new Declaration[ list.size() ] );
 
+        if ( list.isEmpty() ) {
+            this.requiredDeclarations = EMPTY_DECLARATIONS;
+        } else {
+            this.requiredDeclarations = (Declaration[]) list.toArray( new Declaration[list.size()] );
+        }
+
         this.method = configureMethod( clazz,
                                        methodName,
                                        valueHandlers.length );
+
+        //the types we have to convert the arguments to
+        this.parameterTypes = this.method.getParameterTypes();
+
     }
+
     /**
      * Method invoker for an instance
      */
@@ -55,31 +69,39 @@
                          ValueHandler[] valueHandlers) {
         this.instanceValueHandler = instanceValueHandler;
         this.valueHandlers = valueHandlers;
-        
+
         // determine required declarations
-        List list = new ArrayList(1);        
+        List list = new ArrayList( 1 );
         if ( instanceValueHandler != null && instanceValueHandler.getClass() == DeclarationVariable.class ) {
-            list.add( ( (DeclarationVariable) instanceValueHandler ).getDeclaration() ); 
+            list.add( ((DeclarationVariable) instanceValueHandler).getDeclaration() );
         }
+
         for ( int i = 0, length = valueHandlers.length; i < length; i++ ) {
             if ( valueHandlers[i].getClass() == DeclarationVariable.class ) {
-                list.add( ( (DeclarationVariable) valueHandlers[i] ).getDeclaration() );    
+                list.add( ((DeclarationVariable) valueHandlers[i]).getDeclaration() );
             }
         }
-        
-        this.requiredDeclarations = ( Declaration[] )list.toArray( new Declaration[ list.size() ] );
 
+        if ( list.isEmpty() ) {
+            this.requiredDeclarations = EMPTY_DECLARATIONS;
+        } else {
+            this.requiredDeclarations = (Declaration[]) list.toArray( new Declaration[list.size()] );
+        }
+
         this.method = configureMethod( this.instanceValueHandler.getExtractToClass(),
                                        methodName,
                                        valueHandlers.length );
+
+        //the types we have to convert the arguments to
+        this.parameterTypes = this.method.getParameterTypes();
     }
 
     /**
      * work out what method we will be calling at runtime, based on the name and number of parameters.
      */
-    private Method configureMethod(Class clazz,
-                                   String methodName,
-                                   int numOfArgs) {
+    private static Method configureMethod(Class clazz,
+                                          String methodName,
+                                          int numOfArgs) {
         Method[] methods = clazz.getMethods();
         for ( int i = 0; i < methods.length; i++ ) {
             if ( methods[i].getName().equals( methodName ) ) {
@@ -107,9 +129,6 @@
             throw new IllegalArgumentException( "Unable to resolve the variable: [" + this.instanceValueHandler + "]" );
         }
 
-        //the types we have to convert the arguments to
-        Class[] parameterTypes = this.method.getParameterTypes();
-
         //the args values that we will pass
         Object[] args = new Object[this.valueHandlers.length];
 
@@ -152,8 +171,8 @@
     /** 
      * Attempt to convert text to the target class type 
      */
-    private Object convert(String text,
-                           Class type) {
+    private static Object convert(String text,
+                                  Class type) {
         if ( type == Integer.class || type == int.class ) {
             return new Integer( text );
         } else if ( text == "null" ) {

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/resolvers/LiteralValue.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/resolvers/LiteralValue.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/resolvers/LiteralValue.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -14,13 +14,10 @@
     
     private static final long serialVersionUID = 320L;
 
-    private final String value;   
-    
-    private final Class clazz;
+    private final Object value;       
 
-    public LiteralValue(final String value, final Class clazz) {
+    public LiteralValue(final Object value) {
         this.value = value;
-        this.clazz = clazz;
     }
 
     public Object getValue(final Tuple tuple,
@@ -29,7 +26,7 @@
     }
     
     public Class getExtractToClass() {
-        return this.clazz;
+        return this.value.getClass();
     }     
     
     public void reset() {

Copied: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/BaseNode.java (from rev 6109, labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/BaseNode.java)
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/BaseNode.java	2006-09-07 16:54:21 UTC (rev 6109)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/BaseNode.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -0,0 +1,154 @@
+package org.drools.common;
+
+/*
+ * 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.spi.PropagationContext;
+
+/**
+ * The base class for all Rete nodes.
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ *
+ */
+public abstract class BaseNode
+    implements
+    NetworkNode {
+    protected final int id;
+
+    protected boolean   attachingNewNode = false;
+
+    protected boolean   hasMemory        = false;
+
+    protected int       sharedCount      = 0;
+
+    /**
+     * All nodes have a unique id, set in the constructor.
+     * 
+     * @param id
+     *      The unique id
+     */
+    public BaseNode(final int id) {
+        super();
+        this.id = id;
+    }
+
+    /* (non-Javadoc)
+     * @see org.drools.spi.ReteooNode#getId()
+     */
+    public int getId() {
+        return this.id;
+    }
+
+    /**
+     * Specifies with the node has any memory.
+     * 
+     * @param hasMemory
+     */
+    protected void setHasMemory(final boolean hasMemory) {
+        this.hasMemory = hasMemory;
+    }
+
+    /**
+     * 
+     * Indicates whether the node has any memory.
+     * @return
+     */
+    public boolean hasMemory() {
+        return this.hasMemory;
+    }
+
+    /**
+     * Attaches the node into the network. Usually to the parent <code>ObjectSource</code> or <code>TupleSource</code>
+     */
+    public abstract void attach();
+
+    public abstract void attach(InternalWorkingMemory[] workingMemories);
+
+    /**
+     * Removes the node from teh network. Usually from the parent <code>ObjectSource</code> or <code>TupleSource</code>
+     *
+     */
+    public abstract void remove(BaseNode node,
+                                InternalWorkingMemory[] workingMemories);
+
+    /**
+     * When nodes are added to the network that already has data. that existing data must be repropagated to the new node.
+     * This new propagation may result in one or more assertions, so a PropagationContext and the workingMemory for the facts
+     * must be provided.
+     * 
+     * @param workingMemory
+     *      The WorkingMemory
+     * @param context
+     *      The PropagationContext
+     *      
+     */
+    public abstract void updateNewNode(InternalWorkingMemory workingMemory,
+                                       PropagationContext context);
+
+    /**
+     * Each time a node is shared a counter is increased.
+     *
+     */
+    public void addShare() {
+        ++this.sharedCount;
+    }
+
+    /**
+     * Each time a node is unshared a counter is decreased.
+     *
+     */
+    public void removeShare() {
+        --this.sharedCount;
+    }
+
+    /**
+     * Indicates whether the node is shared.
+     * @return
+     */
+    public boolean isShared() {
+        return this.sharedCount > 0;
+    }
+
+    /**
+     * Returns true in case the current node is in use (is referenced by any other node)
+     * @return
+     */
+    public boolean isInUse() {
+        return this.sharedCount >= 0;
+    }
+
+    /**
+     * Returns the number of times the node is shared
+     * @return
+     *      int value indicating the share count.
+     */
+    public int getSharedCount() {
+        return this.sharedCount;
+    }
+
+    /** 
+     * The hashCode return is simply the unique id of the node. It is expected that base classes will also implement equals(Object object). 
+     */
+    public int hashCode() {
+        return this.id;
+    }
+
+    public String toString() {
+        return "[" + this.getClass().getName() + "(" + this.id + ")]";
+    }  
+}

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InternalWorkingMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InternalWorkingMemory.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InternalWorkingMemory.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -1,7 +1,25 @@
 package org.drools.common;
 
+import java.util.Map;
+
 import org.drools.WorkingMemory;
+import org.drools.event.AgendaEventSupport;
 
 public interface InternalWorkingMemory extends WorkingMemory {
     public long getId();
+    
+    public Object getNodeMemory(NodeMemory node);
+    
+    public void clearNodeMemory(NodeMemory node);
+    
+    public long getNextPropagationIdCounter();
+    
+    public Map getFactHandleMap();
+    
+    public AgendaEventSupport getAgendaEventSupport();
+    
+    public TruthMaintenanceSystem getTruthMaintenanceSystem();
+    
+    public void propagateQueuedActions();    
 }
+

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/NetworkNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/NetworkNode.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/NetworkNode.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -0,0 +1,39 @@
+package org.drools.common;
+
+/*
+ * 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;
+
+/**
+ * Interface used to expose generic information on Rete nodes outside of he package. It is used
+ * for exposing information events.
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ *
+ */
+public interface NetworkNode
+    extends
+    Serializable {
+
+    /**
+     * Returns the unique id that represents the node in the Rete network
+     * @return
+     *      unique int value
+     */
+    public int getId();
+}
\ 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-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AccumulateNode.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -24,6 +24,7 @@
 import org.drools.common.BetaNodeBinder;
 import org.drools.common.DefaultFactHandle;
 import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
 import org.drools.rule.Accumulate;
 import org.drools.spi.FieldConstraint;
 import org.drools.spi.PropagationContext;
@@ -222,9 +223,9 @@
      *  2. For each matching tuple, call a modify tuple
      *  
      */
-    public void assertObject(DefaultFactHandle handle,
+    public void assertObject(InternalFactHandle handle,
                              PropagationContext context,
-                             ReteooWorkingMemory workingMemory) {
+                             InternalWorkingMemory workingMemory) {
 
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
         ObjectMatches objectMatches = memory.add( workingMemory,
@@ -257,9 +258,9 @@
      * So, a modify object is in fact a retract+assert object.
      * 
      */
-    public void modifyObject(DefaultFactHandle handle,
+    public void modifyObject(InternalFactHandle handle,
                              PropagationContext context,
-                             ReteooWorkingMemory workingMemory) {
+                             InternalWorkingMemory workingMemory) {
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
 
         // Remove the FactHandle from memory
@@ -284,9 +285,9 @@
      *  If an object is retract, call modify tuple for each
      *  tuple match.
      */
-    public void retractObject(DefaultFactHandle handle,
+    public void retractObject(InternalFactHandle handle,
                               PropagationContext context,
-                              ReteooWorkingMemory workingMemory) {
+                              InternalWorkingMemory workingMemory) {
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
 
         // Remove the FactHandle from memory
@@ -328,7 +329,7 @@
     /**
      * @inheritDoc
      */
-    public void updateNewNode(ReteooWorkingMemory workingMemory,
+    public void updateNewNode(InternalWorkingMemory workingMemory,
                               PropagationContext context) {
         this.attachingNewNode = true;
 

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-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AlphaNode.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -22,7 +22,10 @@
 
 import org.drools.FactException;
 import org.drools.RuleBaseConfiguration;
+import org.drools.common.BaseNode;
 import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
 import org.drools.common.NodeMemory;
 import org.drools.common.PropagationContextImpl;
 import org.drools.spi.FieldConstraint;
@@ -41,7 +44,7 @@
  */
 class AlphaNode extends ObjectSource
     implements
-    ObjectSink,
+    ObjectSinkNode,
     NodeMemory {
 
     /**
@@ -54,6 +57,9 @@
 
     /** The <code>ObjectSource</code> */
     private final ObjectSource    objectSource;
+    
+    private ObjectSinkNode previousObjectSinkNode;
+    private ObjectSinkNode nextObjectSinkNode; 
 
     /**
      * Construct an <code>AlphaNode</code> with a unique id using the provided
@@ -69,27 +75,7 @@
     AlphaNode(final int id,
               final FieldConstraint constraint,
               final ObjectSource objectSource) {
-        this( id,
-              null,
-              constraint,
-              objectSource );
-    }
-
-    /**
-     * Construct an <code>AlphaNode</code> with a unique id using the provided
-     * <code>ObjectSinkList</code> and <code>FieldConstraint</code>. 
-     * 
-     * @param id Node unique id
-     * @param sinklist An object sink list. If null, a default will be used.
-     * @param constraint Node's constraints
-     * @param objectSource Node's object source
-     */
-    AlphaNode(final int id,
-              final ObjectSinkList sinklist,
-              final FieldConstraint constraint,
-              final ObjectSource objectSource) {
-        super( id,
-               sinklist );
+        super( id );
         this.constraint = constraint;
         this.objectSource = objectSource;
         setHasMemory( true );
@@ -113,11 +99,11 @@
         this.objectSource.addObjectSink( this );
     }
 
-    public void attach(final ReteooWorkingMemory[] workingMemories) {
+    public void attach(final InternalWorkingMemory[] workingMemories) {
         attach();
 
         for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
-            final ReteooWorkingMemory workingMemory = workingMemories[i];
+            final InternalWorkingMemory workingMemory = workingMemories[i];
             final PropagationContext propagationContext = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(),
                                                                                       PropagationContext.RULE_ADDITION,
                                                                                       null,
@@ -127,83 +113,82 @@
         }
     }
 
-    public void assertObject(final DefaultFactHandle handle,
+    public void assertObject(final InternalFactHandle handle,
                              final PropagationContext context,
-                             final ReteooWorkingMemory workingMemory) throws FactException {
+                             final InternalWorkingMemory workingMemory) throws FactException {
         final Set memory = (Set) workingMemory.getNodeMemory( this );
         if ( this.constraint.isAllowed( handle.getObject(),
                                         null,
                                         workingMemory ) ) {
             memory.add( handle );
-            propagateAssertObject( handle,
-                                   context,
-                                   workingMemory );
+            sink.propagateAssertObject( handle,
+                                        context,
+                                        workingMemory );
         }
     }
 
-    public void retractObject(final DefaultFactHandle handle,
+    public void retractObject(final InternalFactHandle handle,
                               final PropagationContext context,
-                              final ReteooWorkingMemory workingMemory) {
+                              final InternalWorkingMemory workingMemory) {
         final Set memory = (Set) workingMemory.getNodeMemory( this );
         if ( memory.remove( handle ) ) {
-            propagateRetractObject( handle,
-                                    context,
-                                    workingMemory );
+
+            this.sink.propagateRetractObject( handle,
+                                              context,
+                                              workingMemory,
+                                              true );
         }
     }
 
-    public void modifyObject(final DefaultFactHandle handle,
+    public void modifyObject(final InternalFactHandle handle,
                              final PropagationContext context,
-                             final ReteooWorkingMemory workingMemory) {
+                             final InternalWorkingMemory workingMemory) {
         final Set memory = (Set) workingMemory.getNodeMemory( this );
 
         if ( this.constraint.isAllowed( handle.getObject(),
                                         null,
                                         workingMemory ) ) {
             if ( memory.add( handle ) ) {
-                propagateAssertObject( handle,
-                                       context,
-                                       workingMemory );
+                this.sink.propagateAssertObject( handle,
+                                                 context,
+                                                 workingMemory );
             } else {
                 // handle already existed so propagate as modify
-                propagateModifyObject( handle,
-                                       context,
-                                       workingMemory );
+                this.sink.propagateModifyObject( handle,
+                                                 context,
+                                                 workingMemory );
             }
         } else {
             if ( memory.remove( handle ) ) {
-                propagateRetractObject( handle,
-                                        context,
-                                        workingMemory );
+                this.sink.propagateRetractObject( handle,
+                                                  context,
+                                                  workingMemory,
+                                                  false );
             }
         }
     }
 
-    public void updateNewNode(final ReteooWorkingMemory workingMemory,
+    public void updateNewNode(final InternalWorkingMemory workingMemory,
                               final PropagationContext context) {
         this.attachingNewNode = true;
 
         final Set memory = (Set) workingMemory.getNodeMemory( this );
 
         for ( final Iterator it = memory.iterator(); it.hasNext(); ) {
-            final DefaultFactHandle handle = (DefaultFactHandle) it.next();
-            final ObjectSink sink = this.objectSinks.getLastObjectSink();
-            if ( sink != null ) {
-                sink.assertObject( handle,
-                                   context,
-                                   workingMemory );
-            } else {
-                throw new RuntimeException( "Possible BUG: trying to propagate an assert to a node that was the last added node" );
-            }
+            final InternalFactHandle handle = (InternalFactHandle) it.next();
+            this.sink.propagateNewObjectSink( handle,
+                                              context,
+                                              workingMemory );
         }
 
         this.attachingNewNode = false;
     }
 
     public void remove(final BaseNode node,
-                       final ReteooWorkingMemory[] workingMemories) {
-        if( !node.isInUse()) {
-            this.objectSinks.remove( (ObjectSink) node );
+                       final InternalWorkingMemory[] workingMemories) {
+
+        if ( !node.isInUse() ) {
+            removeObjectSink( (ObjectSink) node );
         }
         removeShare();
         if ( !this.isInUse() ) {
@@ -223,7 +208,7 @@
     }
 
     public String toString() {
-        return "[AlphaNode("+this.id+") constraint=" + this.constraint + "]";
+        return "[AlphaNode(" + this.id + ") constraint=" + this.constraint + "]";
     }
 
     public int hashCode() {
@@ -248,4 +233,40 @@
 
         return this.objectSource.equals( other.objectSource ) && this.constraint.equals( other.constraint );
     }
+    
+    /**
+     * Returns the next node
+     * @return
+     *      The next ObjectSinkNode
+     */
+    public ObjectSinkNode getNextObjectSinkNode() {
+        return this.nextObjectSinkNode;
+    }
+
+    /**
+     * Sets the next node 
+     * @param next
+     *      The next ObjectSinkNode
+     */
+    public void setNextObjectSinkNode(ObjectSinkNode next) {
+        this.nextObjectSinkNode = next;
+    }
+
+    /**
+     * Returns the previous node
+     * @return
+     *      The previous ObjectSinkNode
+     */
+    public ObjectSinkNode getPreviousObjectSinkNode() {
+       return this.previousObjectSinkNode;
+    }
+
+    /**
+     * Sets the previous node 
+     * @param previous
+     *      The previous ObjectSinkNode
+     */
+    public void setPreviousObjectSinkNode(ObjectSinkNode previous) {
+        this.previousObjectSinkNode = previous;
+    }    
 }

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AlphaNodeSwitch.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AlphaNodeSwitch.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AlphaNodeSwitch.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -1,99 +0,0 @@
-/*
- * 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.
- */
-
-package org.drools.reteoo;
-
-import java.io.Serializable;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.drools.WorkingMemory;
-import org.drools.common.InternalFactHandle;
-import org.drools.rule.LiteralConstraint;
-
-/**
- * AlphaNodeSwitch
- * A LiteralConstraint wrapper to be used on alpha node hashing algorithm
- *
- * @author <a href="mailto:tirelli at post.com">Edson Tirelli</a>
- *
- * Created: 04/03/2006
- */
-public class AlphaNodeSwitch
-    implements
-    Serializable {
-    /**
-     * 
-     */
-    private static final long       serialVersionUID = 3574628117634649074L;
-    private final LiteralConstraint constraint;
-    private final Map               alphaSwitch;
-
-    public AlphaNodeSwitch(final LiteralConstraint constraint) {
-        this.constraint = constraint;
-        this.alphaSwitch = new HashMap();
-    }
-
-    public void addAlphaNode(final AlphaNode node) {
-        final LiteralConstraint constraint = (LiteralConstraint) node.getConstraint();
-        this.alphaSwitch.put( constraint.getField().getValue(),
-                              node );
-    }
-
-    public boolean removeAlphaNode(final AlphaNode node) {
-        final LiteralConstraint constraint = (LiteralConstraint) node.getConstraint();
-        return this.alphaSwitch.remove( constraint.getField().getValue() ) != null;
-    }
-
-    public AlphaNode getNode(final WorkingMemory workingMemory,
-                             final InternalFactHandle handle) {
-        final Object value = this.constraint.getFieldExtractor().getValue( handle.getObject() );
-        return (AlphaNode) this.alphaSwitch.get( value );
-    }
-
-    public int getSwitchCount() {
-        return this.alphaSwitch.size();
-    }
-
-    public Collection getAllNodes() {
-        return this.alphaSwitch.values();
-    }
-
-    public int hashCode() {
-        final int PRIME = 31;
-        int result = 1;
-        result = PRIME * result +  this.constraint.getEvaluator().getOperator().hashCode();
-        result = PRIME * result + this.constraint.getFieldExtractor().getIndex();
-        return result;
-    }
-
-    public boolean equals(final Object otherConstraint) {
-        if ( this == otherConstraint ) {
-            return true;
-        }
-
-        if ( (otherConstraint != null) && (otherConstraint instanceof AlphaNodeSwitch) ) {
-            final AlphaNodeSwitch other = (AlphaNodeSwitch) otherConstraint;
-            if ( (this.constraint.getEvaluator().getOperator() == other.constraint.getEvaluator().getOperator()) && (this.constraint.getFieldExtractor().getIndex() == other.constraint.getFieldExtractor().getIndex()) ) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-
-}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/BaseNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/BaseNode.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/BaseNode.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -1,155 +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.spi.PropagationContext;
-import org.drools.spi.ReteooNode;
-
-/**
- * The base class for all Rete nodes.
- * 
- * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
- * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
- *
- */
-abstract class BaseNode
-    implements
-    ReteooNode {
-    protected final int id;
-
-    protected boolean   attachingNewNode = false;
-
-    protected boolean   hasMemory        = false;
-
-    protected int       sharedCount      = 0;
-
-    /**
-     * All nodes have a unique id, set in the constructor.
-     * 
-     * @param id
-     *      The unique id
-     */
-    public BaseNode(final int id) {
-        super();
-        this.id = id;
-    }
-
-    /* (non-Javadoc)
-     * @see org.drools.spi.ReteooNode#getId()
-     */
-    public int getId() {
-        return this.id;
-    }
-
-    /**
-     * Specifies with the node has any memory.
-     * 
-     * @param hasMemory
-     */
-    protected void setHasMemory(final boolean hasMemory) {
-        this.hasMemory = hasMemory;
-    }
-
-    /**
-     * 
-     * Indicates whether the node has any memory.
-     * @return
-     */
-    public boolean hasMemory() {
-        return this.hasMemory;
-    }
-
-    /**
-     * Attaches the node into the network. Usually to the parent <code>ObjectSource</code> or <code>TupleSource</code>
-     */
-    public abstract void attach();
-
-    public abstract void attach(ReteooWorkingMemory[] workingMemories);
-
-    /**
-     * Removes the node from teh network. Usually from the parent <code>ObjectSource</code> or <code>TupleSource</code>
-     *
-     */
-    public abstract void remove(BaseNode node,
-                                ReteooWorkingMemory[] workingMemories);
-
-    /**
-     * When nodes are added to the network that already has data. that existing data must be repropagated to the new node.
-     * This new propagation may result in one or more assertions, so a PropagationContext and the workingMemory for the facts
-     * must be provided.
-     * 
-     * @param workingMemory
-     *      The WorkingMemory
-     * @param context
-     *      The PropagationContext
-     *      
-     */
-    public abstract void updateNewNode(ReteooWorkingMemory workingMemory,
-                                       PropagationContext context);
-
-    /**
-     * Each time a node is shared a counter is increased.
-     *
-     */
-    public void addShare() {
-        ++this.sharedCount;
-    }
-
-    /**
-     * Each time a node is unshared a counter is decreased.
-     *
-     */
-    public void removeShare() {
-        --this.sharedCount;
-    }
-
-    /**
-     * Indicates whether the node is shared.
-     * @return
-     */
-    public boolean isShared() {
-        return this.sharedCount > 0;
-    }
-
-    /**
-     * Returns true in case the current node is in use (is referenced by any other node)
-     * @return
-     */
-    public boolean isInUse() {
-        return this.sharedCount >= 0;
-    }
-
-    /**
-     * Returns the number of times the node is shared
-     * @return
-     *      int value indicating the share count.
-     */
-    public int getSharedCount() {
-        return this.sharedCount;
-    }
-
-    /** 
-     * The hashCode return is simply the unique id of the node. It is expected that base classes will also implement equals(Object object). 
-     */
-    public int hashCode() {
-        return this.id;
-    }
-
-    public String toString() {
-        return "[" + this.getClass().getName() + "(" + this.id + ")]";
-    }
-}

Modified: 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-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/BetaMemory.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -24,7 +24,7 @@
 import org.drools.RuleBaseConfiguration;
 import org.drools.WorkingMemory;
 import org.drools.common.BetaNodeBinder;
-import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalFactHandle;
 import org.drools.reteoo.beta.BetaLeftMemory;
 import org.drools.reteoo.beta.BetaMemoryFactory;
 import org.drools.reteoo.beta.BetaRightMemory;
@@ -94,7 +94,7 @@
      * @return A tuple iterator with possible matches for the handle
      */
     public Iterator leftTupleIterator(final WorkingMemory wm,
-                                      final DefaultFactHandle handle) {
+                                      final InternalFactHandle handle) {
         return this.leftMemory.iterator( wm,
                                          handle );
     }
@@ -140,7 +140,7 @@
      *      The ObjectMatches to hold the tuples that match with the <code>FactHandleImpl</code>
      */
     ObjectMatches add(final WorkingMemory wm,
-                      final DefaultFactHandle handle) {
+                      final InternalFactHandle handle) {
         final ObjectMatches objectMatches = new ObjectMatches( handle );
         this.rightObjectMap.put( handle,
                                  objectMatches );
@@ -167,7 +167,7 @@
      *      The ObjectMatches that held the tuples that match with the <code>FactHandleImpl</code>
      */
     ObjectMatches remove(final WorkingMemory wm,
-                         final DefaultFactHandle handle) {
+                         final InternalFactHandle handle) {
         final ObjectMatches matches = (ObjectMatches) this.rightObjectMap.remove( handle );
         this.rightMemory.remove( wm,
                                  matches );

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-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/BetaNode.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -17,7 +17,10 @@
  */
 
 import org.drools.RuleBaseConfiguration;
+import org.drools.common.BaseNode;
 import org.drools.common.BetaNodeBinder;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
 import org.drools.common.NodeMemory;
 import org.drools.common.PropagationContextImpl;
 import org.drools.spi.FieldConstraint;
@@ -35,10 +38,9 @@
  * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
  * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
  */
-abstract class BetaNode extends TupleSource
-    implements
-    TupleSink,
-    ObjectSink,
+abstract class BetaNode extends TupleSource implements
+    TupleSinkNode,
+    ObjectSinkNode,
     NodeMemory {
     // ------------------------------------------------------------
     // Instance members
@@ -51,6 +53,12 @@
     private final ObjectSource   rightInput;
 
     private final BetaNodeBinder joinNodeBinder;
+    
+    private TupleSinkNode previousTupleSinkNode;
+    private TupleSinkNode nextTupleSinkNode;
+    
+    private ObjectSinkNode previousObjectSinkNode;
+    private ObjectSinkNode nextObjectSinkNode;   
 
     // ------------------------------------------------------------
     // Constructors
@@ -104,11 +112,11 @@
         this.rightInput.addObjectSink( this );
     }
 
-    public void attach(final ReteooWorkingMemory[] workingMemories) {
+    public void attach(final InternalWorkingMemory[] workingMemories) {
         attach();
 
         for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
-            final ReteooWorkingMemory workingMemory = workingMemories[i];
+            final InternalWorkingMemory workingMemory = workingMemories[i];
             final PropagationContext propagationContext = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(),
                                                                                       PropagationContext.RULE_ADDITION,
                                                                                       null,
@@ -122,22 +130,22 @@
     }
 
     public void remove(final BaseNode node,
-                       final ReteooWorkingMemory[] workingMemories) {
-        if( !node.isInUse()) {
-            getTupleSinks().remove( node );
-        }
-        removeShare();
+                       final InternalWorkingMemory[] workingMemories) {
+//        if( !node.isInUse()) {
+//            getTupleSinks().remove( node );
+//        }
+//        removeShare();
+//
+//        if ( ! this.isInUse() ) {
+//            for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
+//                workingMemories[i].clearNodeMemory( this );
+//            }
+//        }
+//        this.rightInput.remove( this,
+//                                workingMemories );
+//        this.leftInput.remove( this,
+//                               workingMemories );
 
-        if ( ! this.isInUse() ) {
-            for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
-                workingMemories[i].clearNodeMemory( this );
-            }
-        }
-        this.rightInput.remove( this,
-                                workingMemories );
-        this.leftInput.remove( this,
-                               workingMemories );
-
     }
 
     /**
@@ -145,7 +153,28 @@
      */
     BetaNodeBinder getJoinNodeBinder() {
         return this.joinNodeBinder;
+    }    
+    
+    protected TupleMatch attemptJoin(final ReteTuple leftTuple,
+                                     final InternalFactHandle handle,
+                                     final ObjectMatches objectMatches,
+                                     final BetaNodeBinder binder,
+                                     final InternalWorkingMemory workingMemory) {
+        if ( binder.isAllowed( handle,
+                               leftTuple,
+                               workingMemory ) ) {
+            TupleMatch tupleMatch = objectMatches.add( leftTuple );          
+
+            leftTuple.addTupleMatch( handle,
+                                     tupleMatch );
+            return tupleMatch;
+
+        } else {
+            return null;
+        }
     }
+    
+    //public abstract TupleSink getTupleSink();
 
     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -186,5 +215,78 @@
         return new BetaMemory( config,
                                this.getJoinNodeBinder() );
     }
+    
+    
+    /**
+     * Returns the next node
+     * @return
+     *      The next TupleSinkNode
+     */
+    public TupleSinkNode getNextTupleSinkNode() {
+        return this.nextTupleSinkNode;
+    }
 
+    /**
+     * Sets the next node 
+     * @param next
+     *      The next TupleSinkNode
+     */
+    public void setNextTupleSinkNode(TupleSinkNode next) {
+        this.nextTupleSinkNode = next;
+    }
+
+    /**
+     * Returns the previous node
+     * @return
+     *      The previous TupleSinkNode
+     */
+    public TupleSinkNode getPreviousTupleSinkNode() {
+       return this.previousTupleSinkNode;
+    }
+
+    /**
+     * Sets the previous node 
+     * @param previous
+     *      The previous TupleSinkNode
+     */
+    public void setPreviousTupleSinkNode(TupleSinkNode previous) {
+        this.previousTupleSinkNode = previous;
+    }
+
+    /**
+     * Returns the next node
+     * @return
+     *      The next ObjectSinkNode
+     */
+    public ObjectSinkNode getNextObjectSinkNode() {
+        return this.nextObjectSinkNode;
+    }
+
+    /**
+     * Sets the next node 
+     * @param next
+     *      The next ObjectSinkNode
+     */
+    public void setNextObjectSinkNode(ObjectSinkNode next) {
+        this.nextObjectSinkNode = next;
+    }
+
+    /**
+     * Returns the previous node
+     * @return
+     *      The previous ObjectSinkNode
+     */
+    public ObjectSinkNode getPreviousObjectSinkNode() {
+       return this.previousObjectSinkNode;
+    }
+
+    /**
+     * Sets the previous node 
+     * @param previous
+     *      The previous ObjectSinkNode
+     */
+    public void setPreviousObjectSinkNode(ObjectSinkNode previous) {
+        this.previousObjectSinkNode = previous;
+    }
+    
 }

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeObjectSinkAdapter.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeObjectSinkAdapter.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeObjectSinkAdapter.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -0,0 +1,460 @@
+package org.drools.reteoo;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.drools.base.evaluators.Operator;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.rule.LiteralConstraint;
+import org.drools.spi.Evaluator;
+import org.drools.spi.FieldConstraint;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.PropagationContext;
+import org.drools.util.LinkedList;
+import org.drools.util.LinkedListNode;
+
+public class CompositeObjectSinkAdapter
+    implements
+    ObjectSinkPropagator {
+
+    private ObjectSinkNodeList otherSinks;
+
+    private LinkedList         hashedFieldIndexes;
+
+    private Map                hashedSinks;
+
+    private HashKey            hashKey;
+
+    public CompositeObjectSinkAdapter() {
+        this.otherSinks = new ObjectSinkNodeList();
+        this.hashKey = new HashKey();
+    }
+
+    public void addObjectSink(ObjectSink sink) {
+        if ( sink.getClass() == AlphaNode.class ) {
+            AlphaNode alphaNode = (AlphaNode) sink;
+            FieldConstraint fieldConstraint = alphaNode.getConstraint();
+
+            if ( fieldConstraint.getClass() == LiteralConstraint.class ) {
+                LiteralConstraint literalConstraint = (LiteralConstraint) fieldConstraint;
+                Evaluator evaluator = literalConstraint.getEvaluator();
+                Object value = literalConstraint.getField().getValue();
+
+                if ( evaluator.getOperator() == Operator.EQUAL ) {
+                    int index = literalConstraint.getFieldExtractor().getIndex();
+                    FieldIndex fieldIndex = registerFieldIndex( index,
+                                                                literalConstraint.getFieldExtractor() );
+                    if ( fieldIndex.count > 2 ) {
+                        if ( this.hashedSinks == null ) {
+                            this.hashedSinks = new HashMap();
+                        }
+                        // this is our third equal constraint for this field, so hash this index
+                        hashSinks( index );
+                        hashedSinks.put( new HashKey( index,
+                                                      value ),
+                                         sink );
+                        fieldIndex.setHashed( true );
+                        return;
+                    }
+                }
+
+            }
+        }
+
+        this.otherSinks.add( (ObjectSinkNode) sink );
+    }
+
+    public void removeObjectSink(ObjectSink sink) {
+        if ( sink.getClass() == AlphaNode.class ) {
+            AlphaNode alphaNode = (AlphaNode) sink;
+            FieldConstraint fieldConstraint = alphaNode.getConstraint();
+
+            if ( fieldConstraint.getClass() == LiteralConstraint.class ) {
+                LiteralConstraint literalConstraint = (LiteralConstraint) fieldConstraint;
+                Evaluator evaluator = literalConstraint.getEvaluator();
+                Object value = literalConstraint.getField().getValue();
+
+                if ( evaluator.getOperator() == Operator.EQUAL ) {
+                    int index = literalConstraint.getFieldExtractor().getIndex();
+                    this.hashKey.setIndex( index );
+                    this.hashKey.setValue( value );
+                    hashedSinks.remove( this.hashKey );
+                    FieldIndex fieldIndex = unregisterFieldIndex( index );
+                    if ( fieldIndex.count < 3 ) {
+                        // we have less than three so unhash
+                        unHashSinks( index );
+                        fieldIndex.setHashed( false );
+                        return;
+                    }
+                    if ( this.hashedSinks.isEmpty() ) {
+                        this.hashedSinks = null;
+                    }
+                    return;
+                }
+            }
+        }
+
+        this.otherSinks.remove( (ObjectSinkNode) sink );
+    }
+
+    public void hashSinks(int index) {
+        List list = new ArrayList();
+
+        for ( ObjectSinkNode sink = this.otherSinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode() ) {
+            if ( sink.getClass() == AlphaNode.class ) {
+                AlphaNode alphaNode = (AlphaNode) sink;
+                FieldConstraint fieldConstraint = alphaNode.getConstraint();
+
+                if ( fieldConstraint.getClass() == LiteralConstraint.class ) {
+                    LiteralConstraint literalConstraint = (LiteralConstraint) fieldConstraint;
+                    Evaluator evaluator = literalConstraint.getEvaluator();
+                    Object value = literalConstraint.getField().getValue();
+
+                    if ( evaluator.getOperator() == Operator.EQUAL && index == literalConstraint.getFieldExtractor().getIndex() ) {
+                        hashedSinks.put( new HashKey( index,
+                                                      value ),
+                                         sink );
+                        //Add to a list as our linkedlists cannot handle removal during iteration
+                        list.add( sink );
+                    }
+                }
+            }
+        }
+
+        // now remove all the sinks
+        for ( Iterator it = list.iterator(); it.hasNext(); ) {
+            ObjectSink sink = (ObjectSink) it.next();
+            this.otherSinks.remove( (ObjectSinkNode) sink );
+        }
+    }
+
+    public void unHashSinks(int index) {
+        for ( Iterator it = this.hashedSinks.entrySet().iterator(); it.hasNext(); ) {
+            Entry entry = (Entry) it.next();
+            ObjectSink sink = (ObjectSink) entry.getValue();
+
+            if ( sink.getClass() == AlphaNode.class ) {
+                AlphaNode alphaNode = (AlphaNode) sink;
+                FieldConstraint fieldConstraint = alphaNode.getConstraint();
+
+                if ( fieldConstraint.getClass() == LiteralConstraint.class ) {
+                    LiteralConstraint literalConstraint = (LiteralConstraint) fieldConstraint;
+                    Evaluator evaluator = literalConstraint.getEvaluator();
+                    Object value = literalConstraint.getField().getValue();
+
+                    if ( evaluator.getOperator() == Operator.EQUAL && index == literalConstraint.getFieldExtractor().getIndex() ) {
+                        this.hashedSinks.remove( entry.getKey() );
+                        this.otherSinks.add( (ObjectSinkNode) sink );
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns a FieldIndex which Keeps a count on how many times a particular field is used with an equality check in the sinks.
+     * @param index
+     * @param fieldExtractor
+     * @return
+     */
+    private FieldIndex registerFieldIndex(int index,
+                                          FieldExtractor fieldExtractor) {
+        FieldIndex fieldIndex = null;
+
+        // is linkedlist null, if so create and add
+        if ( hashedFieldIndexes == null ) {
+            this.hashedFieldIndexes = new LinkedList();
+            fieldIndex = new FieldIndex( index,
+                                         fieldExtractor );
+            this.hashedFieldIndexes.add( fieldIndex );
+        }
+
+        // still null, so see if it already exists
+        if ( fieldIndex == null ) {
+            fieldIndex = findFieldIndex( index );
+        }
+
+        // doesn't exist so create it
+        if ( fieldIndex == null ) {
+            fieldIndex = new FieldIndex( index,
+                                         fieldExtractor );
+            this.hashedFieldIndexes.add( fieldIndex );
+        }
+
+        fieldIndex.increaseCounter();
+
+        return fieldIndex;
+    }
+
+    private FieldIndex unregisterFieldIndex(int index) {
+        FieldIndex fieldIndex = findFieldIndex( index );
+        fieldIndex.decreaseCounter();
+
+        // if the fieldcount is 0 then remove it from the linkedlist
+        if ( fieldIndex.getCount() == 0 ) {
+            this.hashedFieldIndexes.remove( fieldIndex );
+
+            // if the linkedlist is empty then null it
+            if ( this.hashedFieldIndexes.isEmpty() ) {
+                this.hashedFieldIndexes = null;
+            }
+        }
+
+        return fieldIndex;
+    }
+
+    private FieldIndex findFieldIndex(int index) {
+        for ( FieldIndex node = (FieldIndex) this.hashedFieldIndexes.getFirst(); node != null; node = (FieldIndex) node.getNext() ) {
+            if ( node.getIndex() == index ) {
+                return node;
+            }
+        }
+
+        return null;
+    }
+
+    public void propagateAssertObject(InternalFactHandle handle,
+                                      PropagationContext context,
+                                      InternalWorkingMemory workingMemory) {
+        Object object = handle.getObject();
+        if ( this.hashedFieldIndexes != null ) {
+            // Iterate the FieldIndexes to see if any are hashed        
+            for ( FieldIndex fieldIndex = (FieldIndex) this.hashedFieldIndexes.getFirst(); fieldIndex != null; fieldIndex = (FieldIndex) fieldIndex.getNext() ) {
+                if ( fieldIndex.isHashed() ) {
+                    // this field is hashed so set the existing hashKey and see if there is a sink for it
+                    int index = fieldIndex.getIndex();
+                    FieldExtractor extractor = fieldIndex.getFieldExtactor();
+                    this.hashKey.setIndex( index );
+                    this.hashKey.setValue( extractor.getValue( object ) );
+                    ObjectSink sink = (ObjectSink) this.hashedSinks.get( this.hashKey );
+                    if ( sink != null ) {
+                        // The sink exists so propagate
+                        sink.assertObject( handle,
+                                           context,
+                                           workingMemory );
+                    }
+                }
+            }
+        }
+
+        // propagate others
+        for ( ObjectSinkNode sink = this.otherSinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode() ) {
+            sink.assertObject( handle,
+                               context,
+                               workingMemory );
+        }
+
+    }
+
+    public void propagateModifyObject(InternalFactHandle handle,
+                                      PropagationContext context,
+                                      InternalWorkingMemory workingMemory) {
+        if ( this.hashedSinks != null ) {
+            // we can't retrieve hashed sinks, as the field value might have changed, so we have to iterate and propagate to all hashed sinks
+            for ( Iterator it = this.hashedSinks.values().iterator(); it.hasNext(); ) {
+                ObjectSink sink = (ObjectSink) it.next();
+                sink.modifyObject( handle,
+                                   context,
+                                   workingMemory );
+            }
+        }
+
+        // propagate others
+        for ( ObjectSinkNode sink = this.otherSinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode() ) {
+            sink.modifyObject( handle,
+                               context,
+                               workingMemory );
+        }
+
+    }
+
+    public void propagateRetractObject(InternalFactHandle handle,
+                                       PropagationContext context,
+                                       InternalWorkingMemory workingMemory,
+                                       boolean useHash) {
+        if ( this.hashedFieldIndexes != null ) {
+            if ( useHash ) {
+                Object object = handle.getObject();
+                // Iterate the FieldIndexes to see if any are hashed        
+                for ( FieldIndex fieldIndex = (FieldIndex) this.hashedFieldIndexes.getFirst(); fieldIndex != null; fieldIndex = (FieldIndex) fieldIndex.getNext() ) {
+                    if ( fieldIndex.isHashed() ) {
+                        // this field is hashed so set the existing hashKey and see if there is a sink for it
+                        int index = fieldIndex.getIndex();
+                        FieldExtractor extractor = fieldIndex.getFieldExtactor();
+                        this.hashKey.setIndex( index );
+                        this.hashKey.setValue( extractor.getValue( object ) ); 
+                        ObjectSink sink = (ObjectSink) this.hashedSinks.get( this.hashKey );
+                        if ( sink != null ) {
+                            // The sink exists so propagate
+                            sink.retractObject( handle,
+                                                context,
+                                                workingMemory );
+                        }
+                    }
+                }
+            }
+        } else {
+            // we can't retrieve hashed sinks, as the field value might have changed, so we have to iterate and propagate to all hashed sinks
+            for ( Iterator it = this.hashedSinks.values().iterator(); it.hasNext(); ) {
+                ObjectSink sink = (ObjectSink) it.next();
+                sink.retractObject( handle,
+                                    context,
+                                    workingMemory );
+            }
+        }
+
+        // propagate others
+        for ( ObjectSinkNode sink = this.otherSinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode() ) {
+            sink.retractObject( handle,
+                                context,
+                                workingMemory );
+        }
+    }
+
+    public void propagateNewObjectSink(InternalFactHandle handle,
+                                       PropagationContext context,
+                                       InternalWorkingMemory workingMemory) {
+        final ObjectSink sink = this.otherSinks.getLast();
+        sink.assertObject( handle,
+                           context,
+                           workingMemory );
+
+    }
+
+    public ObjectSink[] getSinks() {
+        ObjectSink[] sinkArray = new ObjectSink[this.otherSinks.size()];
+
+        int i = 0;
+
+        for ( ObjectSinkNode sink = this.otherSinks.getFirst(); sink != null; sink = sink.getNextObjectSinkNode() ) {
+            sinkArray[i++] = sink;
+        }
+
+        return sinkArray;
+    }
+
+    public int size() {
+        return this.otherSinks.size();
+    }
+
+    public static class HashKey {
+        private int    index;
+        private Object value;
+
+        public HashKey() {
+
+        }
+
+        public HashKey(int index,
+                       Object value) {
+            super();
+            this.index = index;
+            this.value = value;
+        }
+
+        public int getIndex() {
+            return this.index;
+        }
+
+        public void setIndex(int index) {
+            this.index = index;
+        }
+
+        public Object getValue() {
+            return this.value;
+        }
+
+        public void setValue(Object value) {
+            this.value = value;
+        }
+
+        public int hashCode() {
+            final int PRIME = 31;
+            int result = 1;
+            result = PRIME * result + this.index;
+            result = PRIME * result + ((this.value == null) ? 0 : this.value.hashCode());
+            return result;
+        }
+
+        public boolean equals(Object object) {
+            final HashKey other = (HashKey) object;
+
+            return this.index == other.index && this.value.equals( other.value);
+        }
+
+    }
+
+    public static class FieldIndex
+        implements
+        LinkedListNode {
+        private final int      index;
+        private FieldExtractor fieldExtactor;
+
+        private int            count;
+
+        private boolean        hashed;
+
+        private LinkedListNode previous;
+        private LinkedListNode next;
+
+        public FieldIndex(int index,
+                          FieldExtractor fieldExtractor) {
+            this.index = index;
+            this.fieldExtactor = fieldExtractor;
+        }
+
+        public FieldExtractor getFieldExtractor() {
+            return this.fieldExtactor;
+        }
+
+        public int getIndex() {
+            return this.index;
+        }
+
+        public int getCount() {
+            return this.count;
+        }
+
+        public FieldExtractor getFieldExtactor() {
+            return this.fieldExtactor;
+        }
+
+        public boolean isHashed() {
+            return this.hashed;
+        }
+
+        public void setHashed(boolean hashed) {
+            this.hashed = hashed;
+        }
+
+        public void increaseCounter() {
+            this.count++;
+        }
+
+        public void decreaseCounter() {
+            this.count--;
+        }
+
+        public LinkedListNode getNext() {
+            return this.next;
+        }
+
+        public LinkedListNode getPrevious() {
+            return this.previous;
+        }
+
+        public void setNext(LinkedListNode next) {
+            this.next = next;
+
+        }
+
+        public void setPrevious(LinkedListNode previous) {
+            this.previous = previous;
+        }
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeTupleMatchChildren.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeTupleMatchChildren.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeTupleMatchChildren.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -0,0 +1,52 @@
+package org.drools.reteoo;
+
+import java.util.LinkedList;
+import java.util.Iterator;
+
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+
+public class CompositeTupleMatchChildren
+    implements
+    TupleMatchChildren {
+    private LinkedList list;
+
+    public CompositeTupleMatchChildren() {
+        this.list = new LinkedList();
+    }
+
+    public void add(ReteTuple tuple) {
+        list.add( tuple );
+    }
+
+    public void propagateRetractTuple(final PropagationContext context,
+                                      final InternalWorkingMemory workingMemory) {
+        for ( Iterator it = this.list.iterator(); it.hasNext(); ) {
+            ReteTuple joined = (ReteTuple) it.next();
+            joined.retractTuple( context,
+                                 workingMemory );
+        }
+    }
+
+    public void propagateModifyTuple(final PropagationContext context,
+                                     final InternalWorkingMemory workingMemory) {
+        for ( Iterator it = this.list.iterator(); it.hasNext(); ) {
+            ReteTuple joined = (ReteTuple) it.next();
+            joined.modifyTuple( context,
+                                workingMemory );
+        }
+    }
+
+    public ReteTuple getTupleForSink(TupleSink sink) {
+        for ( Iterator it = this.list.iterator(); it.hasNext(); ) {
+            ReteTuple joined = (ReteTuple) it.next();
+            if ( sink.equals(  joined.getTupleSink() ) ) {
+                return joined;
+            }
+        }    
+        return null;
+    }
+    
+    
+
+}

Added: 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-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeTupleSinkAdapter.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -0,0 +1,133 @@
+package org.drools.reteoo;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+import org.drools.util.LinkedList;
+import org.drools.util.LinkedListNode;
+import org.drools.util.LinkedListObjectWrapper;
+
+public class CompositeTupleSinkAdapter implements TupleSinkPropagator {
+    private TupleSinkNodeList sinks;
+    
+    public CompositeTupleSinkAdapter() {
+        this.sinks = new TupleSinkNodeList();
+    }
+    
+    public void addTupleSink(TupleSink sink) {
+        this.sinks.add( (TupleSinkNode) sink );
+    }
+
+    public void removeTupleSink(TupleSink sink) {
+        this.sinks.remove( (TupleSinkNode) sink );
+    }        
+    
+    public void propagateAssertTuple(ReteTuple tuple,
+                                     InternalFactHandle handle,
+                                     TupleMatch tupleMatch,
+                                     PropagationContext context,
+                                     InternalWorkingMemory workingMemory) {
+        ReteTuple joined = new ReteTuple(tuple, handle, (TupleSink) sinks.getFirst() );
+        tupleMatch.addJoinedTuple( joined );
+        joined.assertTuple( context, workingMemory );           
+        
+        for ( TupleSinkNode sink = this.sinks.getFirst(); sink != null; sink = sink.getNextTupleSinkNode() ) {
+            ReteTuple cloned = new ReteTuple(tuple, sink);
+            tupleMatch.addJoinedTuple( cloned );
+            joined.assertTuple( context, workingMemory );                
+        }
+    }
+    
+    public void propagateAssertTuple(ReteTuple tuple,
+                                     PropagationContext context,
+                                     InternalWorkingMemory workingMemory) {        
+        for ( TupleSinkNode sink = this.sinks.getFirst(); sink != null; sink = sink.getNextTupleSinkNode() ) {
+            final ReteTuple child = new ReteTuple( tuple, sink );
+            // no TupleMatch so instead add as a linked tuple
+            tuple.addLinkedTuple( new LinkedListObjectWrapper( child ) );
+            child.assertTuple( context, workingMemory );            
+        }
+    }    
+    
+    public void createAndAssertTuple(InternalFactHandle handle,
+                                     PropagationContext context,
+                                     InternalWorkingMemory workingMemory,
+                                     Map memory) {
+        final LinkedList list = new LinkedList();
+        for ( TupleSinkNode sink = this.sinks.getFirst(); sink != null; sink = sink.getNextTupleSinkNode() ) {    
+            ReteTuple tuple = new ReteTuple( handle, sink );
+            list.add( new LinkedListObjectWrapper( tuple ) );
+            tuple.assertTuple( context, workingMemory );
+        }     
+    }    
+
+    public TupleSink[] getSinks() {
+        TupleSink[] sinkArray = new TupleSink[ this.sinks.size() ];
+        
+        int i =0;        
+        for ( TupleSinkNode sink = this.sinks.getFirst(); sink != null; sink = sink.getNextTupleSinkNode() ) {
+            sinkArray[i++] = sink;
+        }
+        
+        return sinkArray;
+    }
+
+    public void propagateNewTupleSink(TupleMatch tupleMatch,
+                                      PropagationContext context,
+                                      InternalWorkingMemory workingMemory) {
+
+            final TupleSink sink = sinks.getLast();
+            final ReteTuple tuple = new ReteTuple( tupleMatch.getTuple(),
+                                                   tupleMatch.getObjectMatches().getFactHandle(), 
+                                                   sink  );
+            tupleMatch.addJoinedTuple( tuple );
+            tuple.assertTuple( context, workingMemory );                          
+    }
+    
+    public void propagateNewTupleSink(InternalFactHandle handle,
+                                      LinkedList list,
+                                      PropagationContext context,
+                                      InternalWorkingMemory workingMemory) {
+        TupleSink sink = this.sinks.getLast();
+        ReteTuple tuple = new ReteTuple( handle, sink );
+        list.add( new LinkedListObjectWrapper( tuple ) );
+        tuple.assertTuple( context, workingMemory );                       
+    }    
+    
+    /**
+     * @inheritDoc
+     */
+    public List getPropagatedTuples(final Map memory,
+                                    final InternalWorkingMemory workingMemory,
+                                    final TupleSink sink) {
+        int index =  0;
+        for ( TupleSinkNode node = this.sinks.getFirst(); node != null; node = node.getNextTupleSinkNode() ) {
+            if ( node.equals( sink ) ) {
+                break;
+            }
+            index++;
+        }
+        
+        final List propagatedTuples = new ArrayList( memory.size() );
+
+        for ( final Iterator it = memory.values().iterator(); it.hasNext(); ) {
+            final LinkedList tuples = (LinkedList) it.next();
+            LinkedListObjectWrapper wrapper = (LinkedListObjectWrapper) tuples.getFirst();
+            for ( int i = 0; i < index; i++ ) {
+                wrapper = (LinkedListObjectWrapper) wrapper.getNext();
+            }
+            propagatedTuples.add( wrapper.getObject() );
+        }
+
+        return propagatedTuples;
+    }
+    
+    public int size() {
+        return this.sinks.size();
+    }
+}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/DefaultObjectSinkList.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/DefaultObjectSinkList.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/DefaultObjectSinkList.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -1,76 +0,0 @@
-/*
- * 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.
- */
-
-package org.drools.reteoo;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.drools.WorkingMemory;
-import org.drools.common.DefaultFactHandle;
-
-/**
- * DefaultObjectSinkList
- * A default implementation for DefaultObjectSinkList
- *
- * @author <a href="mailto:tirelli at post.com">Edson Tirelli</a>
- *
- * Created: 06/march/2006
- */
-public class DefaultObjectSinkList extends ArrayList
-    implements
-    ObjectSinkList {
-
-    /**
-     * 
-     */
-    private static final long serialVersionUID = -414815245412273791L;
-
-    public DefaultObjectSinkList() {
-        super();
-    }
-
-    public DefaultObjectSinkList(final int size) {
-        super( size );
-    }
-
-    public ObjectSink getLastObjectSink() {
-        return (ObjectSink) super.get( this.size() - 1 );
-    }
-
-    public List getObjectsAsList() {
-        return this;
-    }
-
-    public boolean add(final ObjectSink objectSink) {
-        return super.add( objectSink );
-    }
-
-    public boolean contains(final ObjectSink objectSink) {
-        return super.contains( objectSink );
-    }
-
-    public boolean remove(final ObjectSink objectSink) {
-        return super.remove( objectSink );
-    }
-
-    public Iterator iterator(final WorkingMemory workingMemory,
-                             final DefaultFactHandle handle) {
-        return super.iterator();
-    }
-
-}

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/EvalConditionNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/EvalConditionNode.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/EvalConditionNode.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -21,6 +21,8 @@
 import java.util.List;
 
 import org.drools.RuleBaseConfiguration;
+import org.drools.common.BaseNode;
+import org.drools.common.InternalWorkingMemory;
 import org.drools.common.NodeMemory;
 import org.drools.common.PropagationContextImpl;
 import org.drools.rule.EvalCondition;
@@ -91,7 +93,7 @@
         this.tupleSource.addTupleSink( this );
     }
 
-    public void attach(final ReteooWorkingMemory[] workingMemories) {
+    public void attach(final InternalWorkingMemory[] workingMemories) {
         attach();
 
         for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
@@ -196,7 +198,7 @@
         }
     }
 
-    public void updateNewNode(final ReteooWorkingMemory workingMemory,
+    public void updateNewNode(final InternalWorkingMemory workingMemory,
                               final PropagationContext context) {
         this.attachingNewNode = true;
 
@@ -243,7 +245,7 @@
     }
 
     public void remove(final BaseNode node,
-                       final ReteooWorkingMemory[] workingMemories) {
+                       final InternalWorkingMemory[] workingMemories) {
         if( !node.isInUse() ) {
             getTupleSinks().remove( node );
         }

Modified: 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-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/FactHandleList.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -46,7 +46,7 @@
     /**
      * 
      */
-    private static final long          serialVersionUID = -6767210501355521967L;
+    private static final long          serialVersionUID = 320L;
 
     /** Empty list for testing purposes only. */
     static final FactHandleList        EMPTY_LIST       = new FactHandleList();
@@ -96,8 +96,8 @@
      * @param handle
      *            The handle to use.
      */
-    public FactHandleList(final DefaultFactHandle handle) {
-        this.handles = new DefaultFactHandle[]{handle};
+    public FactHandleList(final InternalFactHandle handle) {
+        this.handles = new DefaultFactHandle[]{(DefaultFactHandle) handle};
         this.hashCode = handle.hashCode();
     }
 

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/FromNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/FromNode.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/FromNode.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -5,9 +5,11 @@
 import java.util.Map;
 
 import org.drools.RuleBaseConfiguration;
+import org.drools.common.BaseNode;
 import org.drools.common.BetaNodeBinder;
 import org.drools.common.DefaultFactHandle;
 import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
 import org.drools.common.NodeMemory;
 import org.drools.common.PropagationContextImpl;
 import org.drools.spi.DataProvider;
@@ -168,7 +170,7 @@
         this.tupleSource.addTupleSink( this );
     }
 
-    public void attach(ReteooWorkingMemory[] workingMemories) {
+    public void attach(InternalWorkingMemory[] workingMemories) {
         attach();
 
         for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
@@ -183,7 +185,7 @@
     }
 
     public void remove(BaseNode node,
-                       ReteooWorkingMemory[] workingMemories) {
+                       InternalWorkingMemory[] workingMemories) {
         if( !node.isInUse() ) {
             getTupleSinks().remove( node );
         }
@@ -198,7 +200,7 @@
                                  workingMemories );
     }
 
-    public void updateNewNode(ReteooWorkingMemory workingMemory,
+    public void updateNewNode(InternalWorkingMemory workingMemory,
                               PropagationContext context) {
         this.attachingNewNode = true;
 

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/HashedObjectSinkList.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/HashedObjectSinkList.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/HashedObjectSinkList.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -1,287 +0,0 @@
-/*
- * 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.
- */
-
-package org.drools.reteoo;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-
-import org.drools.WorkingMemory;
-import org.drools.base.evaluators.Operator;
-import org.drools.common.DefaultFactHandle;
-import org.drools.rule.LiteralConstraint;
-import org.drools.spi.FieldConstraint;
-
-/**
- * HashedObjectSinkList
- * A hashed implementation for ObjectSinkList to use in nodes
- * that do alpha node hashing
- *
- * @author <a href="mailto:tirelli at post.com">Edson Tirelli</a>
- *
- * Created: 06/march/2006
- */
-public class HashedObjectSinkList
-    implements
-    ObjectSinkList,
-    Serializable {
-
-    /**
-     * 
-     */
-    private static final long serialVersionUID = -3031367588747727946L;
-    /** A switch map for hashed alpha nodes */
-    private final Map         alphaSwitch      = new HashMap();
-    /** The hashed sinks list, for simple and quick retrieval */
-    private final List        hashedSinks      = new ArrayList( 1 );
-    /** A list for not hashed sinks */
-    private final List        otherSinks       = new ArrayList( 1 );
-    /** The last added objectSink */
-    private ObjectSink        lastObjectSink;
-
-    /**
-     * @inheritDoc
-     */
-    public boolean contains(final ObjectSink objectSink) {
-        return this.otherSinks.contains( objectSink ) || this.alphaSwitch.containsValue( objectSink );
-    }
-
-    /**
-     * @inheritDoc
-     */
-    public boolean add(final ObjectSink objectSink) {
-        if ( (objectSink instanceof AlphaNode) && (((AlphaNode) objectSink).getConstraint() instanceof LiteralConstraint) && (((LiteralConstraint) ((AlphaNode) objectSink).getConstraint()).getEvaluator().getOperator() == Operator.EQUAL) ) {
-
-            final FieldConstraint constraint = ((AlphaNode) objectSink).getConstraint();
-            final AlphaNodeSwitch wrapper = new AlphaNodeSwitch( (LiteralConstraint) constraint );
-
-            AlphaNodeSwitch aux = (AlphaNodeSwitch) this.alphaSwitch.get( wrapper );
-            if ( aux == null ) {
-                this.alphaSwitch.put( wrapper,
-                                      wrapper );
-                aux = wrapper;
-            }
-            aux.addAlphaNode( (AlphaNode) objectSink );
-            this.hashedSinks.add( objectSink );
-        } else {
-            this.otherSinks.add( objectSink );
-        }
-        this.lastObjectSink = objectSink;
-        return true;
-    }
-
-    /**
-     * @inheritDoc
-     */
-    public boolean remove(final ObjectSink objectSink) {
-        if ( (objectSink instanceof AlphaNode) && (((AlphaNode) objectSink).getConstraint() instanceof LiteralConstraint) && (((LiteralConstraint) ((AlphaNode) objectSink).getConstraint()).getEvaluator().getOperator() == Operator.EQUAL) ) {
-
-            final FieldConstraint constraint = ((AlphaNode) objectSink).getConstraint();
-            AlphaNodeSwitch wrapper = new AlphaNodeSwitch( (LiteralConstraint) constraint );
-
-            wrapper = (AlphaNodeSwitch) this.alphaSwitch.get( wrapper );
-            wrapper.removeAlphaNode( (AlphaNode) objectSink );
-            this.hashedSinks.remove( objectSink );
-            if ( wrapper.getSwitchCount() == 0 ) {
-                this.alphaSwitch.remove( wrapper );
-            }
-        } else {
-            this.otherSinks.remove( objectSink );
-        }
-        if ( this.lastObjectSink == objectSink ) {
-            this.lastObjectSink = null;
-        }
-        return true;
-    }
-
-    /**
-     * @inheritDoc
-     */
-    public ObjectSink getLastObjectSink() {
-        return this.lastObjectSink;
-    }
-
-    /**
-     * @inheritDoc
-     */
-    public Iterator iterator(final WorkingMemory workingMemory,
-                             final DefaultFactHandle handle) {
-        return new Iterator() {
-            private static final int FLAG_ITER_HASH = 0;
-            private static final int FLAG_ITER_LIST = 1;
-
-            private Iterator         it             = HashedObjectSinkList.this.alphaSwitch.values().iterator();
-            private ObjectSink       current        = null;
-            private ObjectSink       next           = null;
-            private int              flag           = FLAG_ITER_HASH;
-
-            public boolean hasNext() {
-                boolean hasnext = false;
-                if ( this.next == null ) {
-                    switch ( this.flag ) {
-                        // iterating over hashed list
-                        case FLAG_ITER_HASH :
-                            while ( this.it.hasNext() ) {
-                                final AlphaNodeSwitch wrapper = (AlphaNodeSwitch) this.it.next();
-                                this.next = wrapper.getNode( workingMemory,
-                                                             handle );
-                                if ( this.next != null ) {
-                                    hasnext = true;
-                                    break;
-                                }
-                            }
-                            if ( hasnext == false ) {
-                                this.it = HashedObjectSinkList.this.otherSinks.iterator();
-                                hasnext = this.it.hasNext();
-                                if ( hasnext ) {
-                                    this.next = (ObjectSink) this.it.next();
-                                }
-                                this.flag = FLAG_ITER_LIST;
-                            }
-                            break;
-                        // interating over other not hashed sinks
-                        case FLAG_ITER_LIST :
-                            hasnext = this.it.hasNext();
-                            if ( hasnext ) {
-                                this.next = (ObjectSink) this.it.next();
-                            }
-                            break;
-                    }
-                } else {
-                    hasnext = true;
-                }
-                return hasnext;
-            }
-
-            public Object next() {
-                if ( this.next == null ) {
-                    this.hasNext();
-                }
-                this.current = this.next;
-                this.next = null;
-                if ( this.current == null ) {
-                    throw new NoSuchElementException( "No more elements to return" );
-                }
-                return this.current;
-            }
-
-            public void remove() {
-                if ( this.current != null ) {
-                    HashedObjectSinkList.this.remove( this.current );
-                    this.current = null;
-                } else {
-                    throw new IllegalStateException( "No item to remove. Call next() before calling remove()." );
-                }
-            }
-        };
-    }
-
-    /**
-     * @inheritDoc
-     */
-    public Iterator iterator() {
-        return new Iterator() {
-            private static final int FLAG_ITER_HASH = 0;
-            private static final int FLAG_ITER_LIST = 1;
-
-            private Iterator         it             = HashedObjectSinkList.this.hashedSinks.iterator();
-            private ObjectSink       current        = null;
-            private ObjectSink       next           = null;
-            private int              flag           = FLAG_ITER_HASH;
-
-            public boolean hasNext() {
-                boolean hasnext = false;
-                if ( this.next == null ) {
-                    switch ( this.flag ) {
-                        // iterating over hashed list
-                        case FLAG_ITER_HASH :
-                            hasnext = this.it.hasNext();
-                            if ( hasnext ) {
-                                this.next = (ObjectSink) this.it.next();
-                            } else {
-                                this.it = HashedObjectSinkList.this.otherSinks.iterator();
-                                hasnext = this.it.hasNext();
-                                if ( hasnext ) {
-                                    this.next = (ObjectSink) this.it.next();
-                                }
-                                this.flag = FLAG_ITER_LIST;
-                            }
-                            break;
-                        // interating over other not hashed sinks
-                        case FLAG_ITER_LIST :
-                            hasnext = this.it.hasNext();
-                            if ( hasnext ) {
-                                this.next = (ObjectSink) this.it.next();
-                            }
-                            break;
-                    }
-                } else {
-                    hasnext = true;
-                }
-                return hasnext;
-            }
-
-            public Object next() {
-                if ( this.next == null ) {
-                    this.hasNext();
-                }
-                this.current = this.next;
-                this.next = null;
-                if ( this.current == null ) {
-                    throw new NoSuchElementException( "No more elements to return" );
-                }
-                return this.current;
-            }
-
-            public void remove() {
-                if ( this.current != null ) {
-                    HashedObjectSinkList.this.remove( this.current );
-                    this.current = null;
-                } else {
-                    throw new IllegalStateException( "No item to remove. Call next() before calling remove()." );
-                }
-            }
-        };
-    }
-
-    /**
-     * @inheritDoc
-     * 
-     * This method is not efficient and shall be used only for debugging and
-     * test purposes.
-     * Also, the list returned is an unmodifiable list to prevent misusage of it.
-     */
-    public List getObjectsAsList() {
-        final List list = new ArrayList();
-        for ( final Iterator i = this.alphaSwitch.values().iterator(); i.hasNext(); ) {
-            final AlphaNodeSwitch wrapper = (AlphaNodeSwitch) i.next();
-            list.addAll( wrapper.getAllNodes() );
-        }
-        list.addAll( this.otherSinks );
-        return Collections.unmodifiableList( list );
-    }
-
-    public int size() {
-        return this.hashedSinks.size() + this.otherSinks.size();
-    }
-
-}

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-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/JoinNode.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -23,7 +23,8 @@
 import java.util.Map;
 
 import org.drools.common.BetaNodeBinder;
-import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
 import org.drools.spi.PropagationContext;
 
 /**
@@ -107,9 +108,9 @@
      */
     public void assertTuple(final ReteTuple leftTuple,
                             final PropagationContext context,
-                            final ReteooWorkingMemory workingMemory) {
+                            final InternalWorkingMemory workingMemory) {
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
-        
+
         memory.add( workingMemory,
                     leftTuple );
 
@@ -118,18 +119,18 @@
         for ( final Iterator it = memory.rightObjectIterator( workingMemory,
                                                               leftTuple ); it.hasNext(); ) {
             final ObjectMatches objectMatches = (ObjectMatches) it.next();
-            final DefaultFactHandle handle = objectMatches.getFactHandle();
+            final InternalFactHandle handle = objectMatches.getFactHandle();
             final TupleMatch tupleMatch = attemptJoin( leftTuple,
                                                        handle,
                                                        objectMatches,
                                                        binder,
                                                        workingMemory );
             if ( tupleMatch != null ) {
-                propagateAssertTuple( new ReteTuple( leftTuple,
-                                                     handle ),
-                                      tupleMatch,
-                                      context,
-                                      workingMemory );
+                sink.propagateAssertTuple( leftTuple,
+                                           handle,
+                                           tupleMatch,
+                                           context,
+                                           workingMemory );
             }
         }
     }
@@ -152,9 +153,9 @@
      * @param workingMemory
      *            The working memory seesion.
      */
-    public void assertObject(final DefaultFactHandle handle,
+    public void assertObject(final InternalFactHandle handle,
                              final PropagationContext context,
-                             final ReteooWorkingMemory workingMemory) {
+                             final InternalWorkingMemory workingMemory) {
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
         final ObjectMatches objectMatches = memory.add( workingMemory,
                                                         handle );
@@ -168,12 +169,13 @@
                                                        objectMatches,
                                                        binder,
                                                        workingMemory );
+
             if ( tupleMatch != null ) {
-                propagateAssertTuple( new ReteTuple( leftTuple,
-                                                     handle ),
-                                      tupleMatch,
-                                      context,
-                                      workingMemory );
+                this.sink.propagateAssertTuple( leftTuple,
+                                                handle,
+                                                tupleMatch,
+                                                context,
+                                                workingMemory );
             }
         }
     }
@@ -189,11 +191,11 @@
      * @param workingMemory
      *            The working memory seesion.
      */
-    public void retractObject(final DefaultFactHandle handle,
+    public void retractObject(final InternalFactHandle handle,
                               final PropagationContext context,
-                              final ReteooWorkingMemory workingMemory) {
+                              final InternalWorkingMemory workingMemory) {
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
-        
+
         // Remove the FactHandle from memory
         final ObjectMatches objectMatches = memory.remove( workingMemory,
                                                            handle );
@@ -201,9 +203,8 @@
         for ( TupleMatch tupleMatch = objectMatches.getFirstTupleMatch(); tupleMatch != null; tupleMatch = (TupleMatch) tupleMatch.getNext() ) {
             final ReteTuple leftTuple = tupleMatch.getTuple();
             leftTuple.removeMatch( handle );
-            propagateRetractTuple( tupleMatch,
-                                   context,
-                                   workingMemory );
+            tupleMatch.propagateRetractTuple( context,
+                                              workingMemory );
         }
     }
 
@@ -221,7 +222,7 @@
      */
     public void retractTuple(final ReteTuple leftTuple,
                              final PropagationContext context,
-                             final ReteooWorkingMemory workingMemory) {
+                             final InternalWorkingMemory workingMemory) {
 
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
         memory.remove( workingMemory,
@@ -233,16 +234,15 @@
             for ( final Iterator it = matches.values().iterator(); it.hasNext(); ) {
                 final TupleMatch tupleMatch = (TupleMatch) it.next();
                 tupleMatch.getObjectMatches().remove( tupleMatch );
-                propagateRetractTuple( tupleMatch,
-                                       context,
-                                       workingMemory );
+                tupleMatch.propagateRetractTuple( context,
+                                                  workingMemory );
             }
         }
     }
 
     public void modifyTuple(final ReteTuple leftTuple,
                             final PropagationContext context,
-                            final ReteooWorkingMemory workingMemory) {
+                            final 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
@@ -262,9 +262,9 @@
             // 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);
+            final Map oldMatches = new HashMap( matches );
             leftTuple.getTupleMatches().clear();
-            
+
             // ensure the tuple is at the top of the memory
             memory.add( workingMemory,
                         leftTuple );
@@ -273,7 +273,7 @@
             for ( final Iterator rightIterator = memory.rightObjectIterator( workingMemory,
                                                                              leftTuple ); rightIterator.hasNext(); ) {
                 final ObjectMatches objectMatches = (ObjectMatches) rightIterator.next();
-                final DefaultFactHandle handle = objectMatches.getFactHandle();
+                final InternalFactHandle handle = objectMatches.getFactHandle();
 
                 if ( binder.isAllowed( handle,
                                        leftTuple,
@@ -283,20 +283,19 @@
                         // ensures tupleMatch will be in the appropriate order
                         objectMatches.remove( tupleMatch );
                         objectMatches.add( tupleMatch );
-                        leftTuple.addTupleMatch( handle, tupleMatch );
-                        
-                        propagateModifyTuple( tupleMatch,
-                                              context,
-                                              workingMemory );
+                        leftTuple.addTupleMatch( handle,
+                                                 tupleMatch );
+                        tupleMatch.propagateModifyTuple( context,
+                                                         workingMemory );
                     } else {
                         tupleMatch = objectMatches.add( leftTuple );
                         leftTuple.addTupleMatch( handle,
                                                  tupleMatch );
-                        propagateAssertTuple( new ReteTuple( leftTuple,
-                                                             handle ),
-                                              tupleMatch,
-                                              context,
-                                              workingMemory );
+                        this.sink.propagateAssertTuple( leftTuple,
+                                                        handle,
+                                                        tupleMatch,
+                                                        context,
+                                                        workingMemory );
                     }
 
                 } else {
@@ -304,33 +303,30 @@
                     if ( tupleMatch != null ) {
                         oldMatches.remove( handle );
                         objectMatches.remove( tupleMatch );
-                        propagateRetractTuple( tupleMatch,
-                                               context,
-                                               workingMemory );
+                        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(); ) {
+            if ( !oldMatches.isEmpty() ) {
+                for ( Iterator it = oldMatches.values().iterator(); it.hasNext(); ) {
                     final TupleMatch tupleMatch = (TupleMatch) it.next();
                     tupleMatch.getObjectMatches().remove( tupleMatch );
-                    propagateRetractTuple( tupleMatch,
-                                           context,
-                                           workingMemory );
+                    tupleMatch.propagateRetractTuple( context, workingMemory );
                 }
             }
         }
     }
 
-    public void modifyObject(final DefaultFactHandle handle,
+    public void modifyObject(final InternalFactHandle handle,
                              final PropagationContext context,
-                             final ReteooWorkingMemory workingMemory) {
+                             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 );
@@ -353,15 +349,11 @@
                 if ( binder.isAllowed( handle,
                                        leftTuple,
                                        workingMemory ) ) {
-                    propagateModifyTuple( tupleMatch,
-                                          context,
-                                          workingMemory );
+                    tupleMatch.propagateModifyTuple( context, workingMemory );
                 } else {
                     leftTuple.removeMatch( handle );
                     objectMatches.remove( tupleMatch );
-                    propagateRetractTuple( tupleMatch,
-                                           context,
-                                           workingMemory );
+                    tupleMatch.propagateRetractTuple( context, workingMemory );
                 }
                 tupleMatch = nextTupleMatch;
             } else {
@@ -372,11 +364,7 @@
                                                               binder,
                                                               workingMemory );
                 if ( newTupleMatch != null ) {
-                    propagateAssertTuple( new ReteTuple( leftTuple,
-                                                         handle ),
-                                          newTupleMatch,
-                                          context,
-                                          workingMemory );
+                    this.sink.propagateAssertTuple( leftTuple, handle, newTupleMatch, context, workingMemory );
                 }
             }
         }
@@ -385,7 +373,7 @@
     /* (non-Javadoc)
      * @see org.drools.reteoo.BaseNode#updateNewNode(org.drools.reteoo.WorkingMemoryImpl, org.drools.spi.PropagationContext)
      */
-    public void updateNewNode(final ReteooWorkingMemory workingMemory,
+    public void updateNewNode(final InternalWorkingMemory workingMemory,
                               final PropagationContext context) {
         this.attachingNewNode = true;
 
@@ -393,19 +381,8 @@
 
         for ( final Iterator it = memory.getRightObjectMemory().iterator(); it.hasNext(); ) {
             final ObjectMatches objectMatches = (ObjectMatches) it.next();
-            final DefaultFactHandle handle = objectMatches.getFactHandle();
-            for ( TupleMatch tupleMatch = objectMatches.getFirstTupleMatch(); tupleMatch != null; tupleMatch = (TupleMatch) tupleMatch.getNext() ) {
-                final ReteTuple tuple = new ReteTuple( tupleMatch.getTuple(),
-                                                       handle );
-                final TupleSink sink = (TupleSink) this.tupleSinks.get( this.tupleSinks.size() - 1 );
-                if ( sink != null ) {
-                    tupleMatch.addJoinedTuple( tuple );
-                    sink.assertTuple( tuple,
-                                      context,
-                                      workingMemory );
-                } else {
-                    throw new RuntimeException( "Possible BUG: trying to propagate an assert to a node that was the last added node" );
-                }
+            for ( TupleMatch tupleMatch = objectMatches.getFirstTupleMatch(); tupleMatch != null; tupleMatch = (TupleMatch) tupleMatch.getNext() ) {                
+                this.sink.propagateNewTupleSink( tupleMatch, context, workingMemory );
             }
         }
 
@@ -415,16 +392,16 @@
     /**
      * @inheritDoc
      */
-    public List getPropagatedTuples(final ReteooWorkingMemory workingMemory,
+    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.getRightObjectMemory().iterator(); it.hasNext(); ) {
             final ObjectMatches objectMatches = (ObjectMatches) it.next();
-            for ( TupleMatch tupleMatch = objectMatches.getFirstTupleMatch(); tupleMatch != null; tupleMatch = (TupleMatch) tupleMatch.getNext() ) {
-                propagatedTuples.add( tupleMatch.getJoinedTuples().get( index ) );
+            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-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/LeftInputAdapterNode.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -21,10 +21,14 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 
 import org.drools.RuleBaseConfiguration;
+import org.drools.common.BaseNode;
 import org.drools.common.BetaNodeBinder;
 import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
 import org.drools.common.NodeMemory;
 import org.drools.common.PropagationContextImpl;
 import org.drools.spi.FieldConstraint;
@@ -51,7 +55,7 @@
     /**
      * 
      */
-    private static final long    serialVersionUID = 7377381894771069492L;
+    private static final long    serialVersionUID = 320L;
     private final ObjectSource   objectSource;
     private final BetaNodeBinder binder;
 
@@ -103,11 +107,11 @@
         this.objectSource.addObjectSink( this );
     }
 
-    public void attach(final ReteooWorkingMemory[] workingMemories) {
+    public void attach(final InternalWorkingMemory[] workingMemories) {
         attach();
 
         for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
-            final ReteooWorkingMemory workingMemory = workingMemories[i];
+            final InternalWorkingMemory workingMemory = workingMemories[i];
             final PropagationContext propagationContext = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(),
                                                                                       PropagationContext.RULE_ADDITION,
                                                                                       null,
@@ -128,62 +132,22 @@
      * @param workingMemory
      *            the <code>WorkingMemory</code> session.
      */
-    public void assertObject(final DefaultFactHandle handle,
+    public void assertObject(final InternalFactHandle handle,
                              final PropagationContext context,
-                             final ReteooWorkingMemory workingMemory) {
+                             final InternalWorkingMemory workingMemory) {
         final Map memory = (Map) workingMemory.getNodeMemory( this );
 
         if ( (this.binder == null) || (this.binder.isAllowed( handle,
                                                               null,
                                                               workingMemory )) ) {
-            createAndAssertTuple( handle,
-                                  context,
-                                  workingMemory,
-                                  memory );
+            this.sink.createAndAssertTuple( handle,
+                                            context,
+                                            workingMemory,
+                                            memory );
         }
     }
 
     /**
-     * A private helper method to avoid code duplication between assert and 
-     * modify object methods
-     * 
-     * @param handle
-     * @param context
-     * @param workingMemory
-     * @param memory
-     */
-    private void createAndAssertTuple(final DefaultFactHandle handle,
-                                      final PropagationContext context,
-                                      final ReteooWorkingMemory workingMemory,
-                                      final Map memory) {
-        final int size = getTupleSinks().size();
-
-        final LinkedList list = new LinkedList();
-
-        ReteTuple tuple = new ReteTuple( handle );
-
-        list.add( new LinkedListObjectWrapper( tuple ) );
-
-        if ( !getTupleSinks().isEmpty() ) {
-            // We do this one seperately so we avoid another tuple replication
-            ((TupleSink) getTupleSinks().get( 0 )).assertTuple( tuple,
-                                                                context,
-                                                                workingMemory );
-
-            for ( int i = 1; i < size; i++ ) {
-                tuple = new ReteTuple( tuple );
-                list.add( new LinkedListObjectWrapper( tuple ) );
-                ((TupleSink) getTupleSinks().get( i )).assertTuple( tuple,
-                                                                    context,
-                                                                    workingMemory );
-            }
-        }
-
-        memory.put( handle,
-                    list );
-    }
-
-    /**
      * Retract an existing <code>FactHandleImpl</code> by placing it in a new <code>ReteTuple</code> before 
      * proagating to the <code>TupleSinks</code>
      * 
@@ -194,26 +158,24 @@
      * @param workingMemory
      *            the <code>WorkingMemory</code> session.
      */
-    public void retractObject(final DefaultFactHandle handle,
+    public void retractObject(final InternalFactHandle handle,
                               final PropagationContext context,
-                              final ReteooWorkingMemory workingMemory) {
+                              final InternalWorkingMemory workingMemory) {
         final Map memory = (Map) workingMemory.getNodeMemory( this );
         final LinkedList list = (LinkedList) memory.remove( handle );
 
         // the handle might have been filtered out by the binder
         if ( list != null ) {
-            int i = 0;
-            for ( LinkedListNode node = list.removeFirst(); node != null; node = list.removeFirst() ) {
-                ((TupleSink) getTupleSinks().get( i++ )).retractTuple( (ReteTuple) ((LinkedListObjectWrapper) node).getObject(),
-                                                                       context,
-                                                                       workingMemory );
+            for ( LinkedListNode node = list.removeFirst(); node != null; node = list.removeFirst() ) {                
+                ReteTuple reteTuple = ( ReteTuple )  ((LinkedListObjectWrapper) node).getObject();
+                reteTuple.retractTuple( context, workingMemory );
             }
         }
     }
 
-    public void modifyObject(final DefaultFactHandle handle,
+    public void modifyObject(final InternalFactHandle handle,
                              final PropagationContext context,
-                             final ReteooWorkingMemory workingMemory) {
+                             final InternalWorkingMemory workingMemory) {
         final Map memory = (Map) workingMemory.getNodeMemory( this );
 
         if ( (this.binder == null) || (this.binder.isAllowed( handle,
@@ -223,15 +185,13 @@
 
             if ( list != null ) {
                 // already existed, so propagate as a modify
-                int i = 0;
                 for ( LinkedListNode node = list.getFirst(); node != null; node = node.getNext() ) {
-                    ((TupleSink) getTupleSinks().get( i++ )).modifyTuple( (ReteTuple) ((LinkedListObjectWrapper) node).getObject(),
-                                                                          context,
-                                                                          workingMemory );
+                    ReteTuple reteTuple = ( ReteTuple )  ((LinkedListObjectWrapper) node).getObject();
+                    reteTuple.modifyTuple( context, workingMemory );
                 }
             } else {
                 // didn't existed, so propagate as an assert
-                this.createAndAssertTuple( handle,
+                this.sink.createAndAssertTuple( handle,
                                            context,
                                            workingMemory,
                                            memory );
@@ -240,11 +200,9 @@
             final LinkedList list = (LinkedList) memory.remove( handle );
 
             if ( list != null ) {
-                int i = 0;
                 for ( LinkedListNode node = list.getFirst(); node != null; node = node.getNext() ) {
-                    ((TupleSink) getTupleSinks().get( i++ )).retractTuple( (ReteTuple) ((LinkedListObjectWrapper) node).getObject(),
-                                                                           context,
-                                                                           workingMemory );
+                    ReteTuple reteTuple = ( ReteTuple )  ((LinkedListObjectWrapper) node).getObject();
+                    reteTuple.retractTuple( context, workingMemory );
                 }
             }
         }
@@ -253,31 +211,31 @@
     /* (non-Javadoc)
      * @see org.drools.reteoo.BaseNode#updateNewNode(org.drools.reteoo.WorkingMemoryImpl, org.drools.spi.PropagationContext)
      */
-    public void updateNewNode(final ReteooWorkingMemory workingMemory,
+    public void updateNewNode(final InternalWorkingMemory workingMemory,
                               final PropagationContext context) {
         this.attachingNewNode = true;
 
         // Get the newly attached TupleSink
-        final TupleSink sink = (TupleSink) getTupleSinks().get( getTupleSinks().size() - 1 );
+//        final TupleSink sink = (TupleSink) getTupleSinks().get( getTupleSinks().size() - 1 );
 
         // Iterate the memory and assert all tuples into the newly attached TupleSink
         final Map memory = (Map) workingMemory.getNodeMemory( this );
-        for ( final Iterator it = memory.values().iterator(); it.hasNext(); ) {
-            final LinkedList list = (LinkedList) it.next();
-            for ( LinkedListNode node = list.getFirst(); node != null; node = node.getNext() ) {
-                sink.assertTuple( (ReteTuple) ((LinkedListObjectWrapper) node).getObject(),
-                                  context,
-                                  workingMemory );
-            }
+        
+        for ( final Iterator it = memory.entrySet().iterator(); it.hasNext(); ) {
+            Entry entry = ( Entry ) it.next();
+            
+            final InternalFactHandle handle = ( InternalFactHandle ) entry.getKey();
+            final LinkedList list = (LinkedList) entry.getValue();
+            this.sink.propagateNewTupleSink( handle, list, context, workingMemory );
         }
 
         this.attachingNewNode = false;
     }
 
     public void remove(final BaseNode node,
-                       final ReteooWorkingMemory[] workingMemories) {
-        if( !node.isInUse() ) {
-            getTupleSinks().remove( node );
+                       final InternalWorkingMemory[] workingMemories) {
+        if ( !node.isInUse() ) {
+            removeTupleSink( (TupleSink ) node );
         }
         removeShare();
         if ( !this.isInUse() ) {
@@ -321,21 +279,9 @@
     /**
      * @inheritDoc
      */
-    public List getPropagatedTuples(final ReteooWorkingMemory workingMemory,
+    public List getPropagatedTuples(final InternalWorkingMemory workingMemory,
                                     final TupleSink sink) {
         final Map memory = (Map) workingMemory.getNodeMemory( this );
-        final int index = this.getTupleSinks().indexOf( sink );
-        final List propagatedTuples = new ArrayList();
-
-        for ( final Iterator it = memory.values().iterator(); it.hasNext(); ) {
-            final LinkedList tuples = (LinkedList) it.next();
-            LinkedListObjectWrapper wrapper = (LinkedListObjectWrapper) tuples.getFirst();
-            for ( int i = 0; i < index; i++ ) {
-                wrapper = (LinkedListObjectWrapper) wrapper.getNext();
-            }
-            propagatedTuples.add( wrapper.getObject() );
-        }
-
-        return propagatedTuples;
+        return this.sink.getPropagatedTuples( memory, workingMemory, sink );
     }
 }

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-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/NotNode.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -24,8 +24,11 @@
 
 import org.drools.common.BetaNodeBinder;
 import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
 import org.drools.spi.PropagationContext;
 import org.drools.util.LinkedList;
+import org.drools.util.LinkedListNode;
 import org.drools.util.LinkedListObjectWrapper;
 
 /**
@@ -106,7 +109,7 @@
      */
     public void assertTuple(final ReteTuple leftTuple,
                             final PropagationContext context,
-                            final ReteooWorkingMemory workingMemory) {
+                            final InternalWorkingMemory workingMemory) {
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
 
         memory.add( workingMemory,
@@ -117,7 +120,7 @@
         for ( final Iterator it = memory.rightObjectIterator( workingMemory,
                                                               leftTuple ); it.hasNext(); ) {
             final ObjectMatches objectMatches = (ObjectMatches) it.next();
-            final DefaultFactHandle handle = objectMatches.getFactHandle();
+            final InternalFactHandle handle = objectMatches.getFactHandle();
             attemptJoin( leftTuple,
                          handle,
                          objectMatches,
@@ -126,9 +129,9 @@
         }
 
         if ( leftTuple.matchesSize() == 0 ) {
-            propagateAssertTuple( leftTuple,
-                                  context,
-                                  workingMemory );
+            this.sink.propagateAssertTuple( leftTuple,
+                                            context,
+                                            workingMemory );
         }
 
     }
@@ -145,9 +148,9 @@
      * @param workingMemory
      *            The working memory seesion.
      */
-    public void assertObject(final DefaultFactHandle handle,
+    public void assertObject(final InternalFactHandle handle,
                              final PropagationContext context,
-                             final ReteooWorkingMemory workingMemory) {
+                             final InternalWorkingMemory workingMemory) {
 
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
         final ObjectMatches objectMatches = memory.add( workingMemory,
@@ -165,9 +168,12 @@
                          binder,
                          workingMemory );
             if ( previousSize == 0 && leftTuple.matchesSize() != 0 ) {
-                propagateRetractTuple( leftTuple,
-                                       context,
-                                       workingMemory );
+                LinkedList list = leftTuple.getLinkedTuples();
+                for ( LinkedListNode node = list.getFirst(); node != null; node = node.getNext() ) {
+                    ReteTuple tuple = (ReteTuple) ((LinkedListObjectWrapper) node).getObject();
+                    tuple.retractTuple( context,
+                                        workingMemory );
+                }
             }
         }
     }
@@ -185,9 +191,9 @@
      *            The working memory seesion.
      * @throws AssertionException
      */
-    public void retractObject(final DefaultFactHandle handle,
+    public void retractObject(final InternalFactHandle handle,
                               final PropagationContext context,
-                              final ReteooWorkingMemory workingMemory) {
+                              final InternalWorkingMemory workingMemory) {
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
         final ObjectMatches objectMatches = memory.remove( workingMemory,
                                                            handle );
@@ -198,9 +204,12 @@
             leftTuple.removeMatch( handle );
 
             if ( previousSize != 0 && leftTuple.matchesSize() == 0 ) {
-                propagateAssertTuple( leftTuple,
-                                      context,
-                                      workingMemory );
+                LinkedList list = leftTuple.getLinkedTuples();
+                for ( LinkedListNode node = list.getFirst(); node != null; node = node.getNext() ) {
+                    ReteTuple tuple = (ReteTuple) ((LinkedListObjectWrapper) node).getObject();
+                    tuple.assertTuple( context,
+                                       workingMemory );
+                }
             }
         }
     }
@@ -218,7 +227,7 @@
      */
     public void retractTuple(final ReteTuple leftTuple,
                              final PropagationContext context,
-                             final ReteooWorkingMemory workingMemory) {
+                             final InternalWorkingMemory workingMemory) {
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
         memory.remove( workingMemory,
                        leftTuple );
@@ -232,14 +241,17 @@
             }
         }
 
-        propagateRetractTuple( leftTuple,
-                               context,
-                               workingMemory );
+        LinkedList list = leftTuple.getLinkedTuples();
+        for ( LinkedListNode node = list.getFirst(); node != null; node = node.getNext() ) {
+            ReteTuple tuple = (ReteTuple) ((LinkedListObjectWrapper) node).getObject();
+            tuple.retractTuple( context,
+                                workingMemory );
+        }
     }
 
     public void modifyTuple(final ReteTuple leftTuple,
                             final PropagationContext context,
-                            final ReteooWorkingMemory workingMemory) {
+                            final 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
@@ -253,7 +265,7 @@
         // 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());
+        final Map oldMatches = new HashMap( leftTuple.getTupleMatches() );
         leftTuple.getTupleMatches().clear();
 
         final int previous = oldMatches.size();
@@ -262,7 +274,7 @@
         for ( final Iterator rightIterator = memory.rightObjectIterator( workingMemory,
                                                                          leftTuple ); rightIterator.hasNext(); ) {
             final ObjectMatches objectMatches = (ObjectMatches) rightIterator.next();
-            final DefaultFactHandle handle = objectMatches.getFactHandle();
+            final InternalFactHandle handle = objectMatches.getFactHandle();
 
             if ( binder.isAllowed( handle,
                                    leftTuple,
@@ -291,25 +303,31 @@
             final TupleMatch tupleMatch = (TupleMatch) oldMatchesIt.next();
             tupleMatch.getObjectMatches().remove( tupleMatch );
         }
-        
+
         if ( previous == 0 && leftTuple.matchesSize() == 0 ) {
-            propagateModifyTuple( leftTuple,
-                                  context,
-                                  workingMemory );
+            LinkedList list = leftTuple.getLinkedTuples();
+            for ( LinkedListNode node = list.getFirst(); node != null; node = node.getNext() ) {
+                ReteTuple tuple = (ReteTuple) ((LinkedListObjectWrapper) node).getObject();
+                tuple.modifyTuple( context,
+                                   workingMemory );
+            }
         } else if ( previous != 0 && leftTuple.matchesSize() == 0 ) {
-            propagateAssertTuple( leftTuple,
-                                  context,
-                                  workingMemory );
+            this.sink.propagateAssertTuple( leftTuple,
+                                            context,
+                                            workingMemory );
         } else if ( previous == 0 && leftTuple.matchesSize() != 0 ) {
-            propagateRetractTuple( leftTuple,
-                                   context,
-                                   workingMemory );
+            LinkedList list = leftTuple.getLinkedTuples();
+            for ( LinkedListNode node = list.getFirst(); node != null; node = node.getNext() ) {
+                ReteTuple tuple = (ReteTuple) ((LinkedListObjectWrapper) node).getObject();
+                tuple.retractTuple( context,
+                                    workingMemory );
+            }
         }
     }
 
-    public void modifyObject(final DefaultFactHandle handle,
+    public void modifyObject(final InternalFactHandle handle,
                              final PropagationContext context,
-                             final ReteooWorkingMemory workingMemory) {
+                             final InternalWorkingMemory workingMemory) {
         final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
 
         // Remove the FactHandle from memory
@@ -320,11 +338,11 @@
 
         TupleMatch tupleMatch = objectMatches.getFirstTupleMatch();
         final BetaNodeBinder 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
@@ -335,19 +353,25 @@
                                         workingMemory ) ) {
                     leftTuple.removeMatch( handle );
                     objectMatches.remove( tupleMatch );
-                } 
+                }
                 if ( previous == 0 && leftTuple.matchesSize() == 0 ) {
-                    propagateModifyTuple( leftTuple,
-                                          context,
-                                          workingMemory );
+                    LinkedList list = leftTuple.getLinkedTuples();
+                    for ( LinkedListNode node = list.getFirst(); node != null; node = node.getNext() ) {
+                        ReteTuple tuple = (ReteTuple) ((LinkedListObjectWrapper) node).getObject();
+                        tuple.modifyTuple( context,
+                                           workingMemory );
+                    }
                 } else if ( previous != 0 && leftTuple.matchesSize() == 0 ) {
-                    propagateAssertTuple( leftTuple,
-                                          context,
-                                          workingMemory );
+                    this.sink.propagateAssertTuple( leftTuple,
+                                                    context,
+                                                    workingMemory );
                 } else if ( previous == 0 && leftTuple.matchesSize() != 0 ) {
-                    propagateRetractTuple( leftTuple,
-                                           context,
-                                           workingMemory );
+                    LinkedList list = leftTuple.getLinkedTuples();
+                    for ( LinkedListNode node = list.getFirst(); node != null; node = node.getNext() ) {
+                        ReteTuple tuple = (ReteTuple) ((LinkedListObjectWrapper) node).getObject();
+                        tuple.retractTuple( context,
+                                            workingMemory );
+                    }
                 }
 
                 tupleMatch = (TupleMatch) nextTupleMatch;
@@ -360,9 +384,12 @@
                              binder,
                              workingMemory );
                 if ( previousSize == 0 && leftTuple.matchesSize() != 0 ) {
-                    propagateRetractTuple( leftTuple,
-                                           context,
-                                           workingMemory );
+                    LinkedList list = leftTuple.getLinkedTuples();
+                    for ( LinkedListNode node = list.getFirst(); node != null; node = node.getNext() ) {
+                        ReteTuple tuple = (ReteTuple) ((LinkedListObjectWrapper) node).getObject();
+                        tuple.retractTuple( context,
+                                            workingMemory );
+                    }
                 }
             }
         }
@@ -371,46 +398,47 @@
     /* (non-Javadoc)
      * @see org.drools.reteoo.BaseNode#updateNewNode(org.drools.reteoo.WorkingMemoryImpl, org.drools.spi.PropagationContext)
      */
-    public void updateNewNode(final ReteooWorkingMemory workingMemory,
+    public void updateNewNode(final InternalWorkingMemory workingMemory,
                               final PropagationContext context) {
-        this.attachingNewNode = true;
-
-        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
-        for ( final Iterator it = memory.getLeftTupleMemory().iterator(); it.hasNext(); ) {
-            final ReteTuple leftTuple = (ReteTuple) it.next();
-            if ( leftTuple.matchesSize() == 0 ) {
-                final ReteTuple child = new ReteTuple( leftTuple );
-                // no TupleMatch so instead add as a linked tuple
-                leftTuple.addLinkedTuple( new LinkedListObjectWrapper( child ) );
-                ((TupleSink) getTupleSinks().get( getTupleSinks().size() - 1 )).assertTuple( child,
-                                                                                             context,
-                                                                                             workingMemory );
-            }
-        }
-
-        this.attachingNewNode = true;
+        //        this.attachingNewNode = true;
+        //
+        //        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+        //        for ( final Iterator it = memory.getLeftTupleMemory().iterator(); it.hasNext(); ) {
+        //            final ReteTuple leftTuple = (ReteTuple) it.next();
+        //            if ( leftTuple.matchesSize() == 0 ) {
+        //                final ReteTuple child = new ReteTuple( leftTuple );
+        //                // no TupleMatch so instead add as a linked tuple
+        //                leftTuple.addLinkedTuple( new LinkedListObjectWrapper( child ) );
+        //                ((TupleSink) getTupleSinks().get( getTupleSinks().size() - 1 )).assertTuple( child,
+        //                                                                                             context,
+        //                                                                                             workingMemory );
+        //            }
+        //        }
+        //
+        //        this.attachingNewNode = true;
     }
 
-    /**
-     * @inheritDoc
-     */
-    public List getPropagatedTuples(final ReteooWorkingMemory 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() );
+        /**
+         * @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;
         }
-        return propagatedTuples;
-    }
 
 }

Modified: 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-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectMatches.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -17,6 +17,7 @@
  */
 
 import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalFactHandle;
 import org.drools.util.BaseMultiLinkedListNode;
 import org.drools.util.LinkedList;
 
@@ -34,14 +35,14 @@
 public class ObjectMatches extends BaseMultiLinkedListNode {
     private LinkedList              list;
 
-    private final DefaultFactHandle handle;
+    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 DefaultFactHandle handle) {
+    public ObjectMatches(final InternalFactHandle handle) {
         this.list = new LinkedList();
         this.handle = handle;
     }
@@ -79,7 +80,7 @@
      * Return <code>FactHandleImpl</code> that this provides the <code>TupleMatch</code>es for.
      * @return
      */
-    public DefaultFactHandle getFactHandle() {
+    public InternalFactHandle getFactHandle() {
         return this.handle;
     }
 

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-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSink.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -16,7 +16,8 @@
  * limitations under the License.
  */
 
-import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
 import org.drools.spi.PropagationContext;
 
 /**
@@ -41,9 +42,9 @@
      * @param workingMemory
      *            the <code>WorkingMemory</code> session.
      */
-    void assertObject(DefaultFactHandle handle,
+    void assertObject(InternalFactHandle handle,
                       PropagationContext context,
-                      ReteooWorkingMemory workingMemory);
+                      InternalWorkingMemory workingMemory);
 
     /**
      * Retract an existing <code>FactHandleImpl</code>.
@@ -55,11 +56,11 @@
      * @param workingMemory
      *            the <code>WorkingMemory</code> session.
      */
-    void retractObject(DefaultFactHandle handle,
+    void retractObject(InternalFactHandle handle,
                        PropagationContext context,
-                       ReteooWorkingMemory workingMemory);
+                       InternalWorkingMemory workingMemory);
 
-    void modifyObject(DefaultFactHandle handle,
+    void modifyObject(InternalFactHandle handle,
                       PropagationContext context,
-                      ReteooWorkingMemory workingMemory);
+                      InternalWorkingMemory workingMemory);
 }

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSinkList.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSinkList.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSinkList.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -1,96 +0,0 @@
-/*
- * 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.
- */
-
-package org.drools.reteoo;
-
-import java.util.Iterator;
-import java.util.List;
-
-import org.drools.WorkingMemory;
-import org.drools.common.DefaultFactHandle;
-
-/**
- * ObjectSinkList
- * An interface for object sink lists
- *
- * @author <a href="mailto:tirelli at post.com">Edson Tirelli</a>
- *
- * Created: 06/march/2006
- */
-public interface ObjectSinkList {
-
-    /**
-     * Returns true if the ObjectSinkList already contains the given object sink
-     * @param element
-     * @return
-     */
-    public boolean contains(ObjectSink objectSink);
-
-    /**
-     * Adds the given objectSink to the list
-     * @param objectSink
-     * @return
-     */
-    public boolean add(ObjectSink objectSink);
-
-    /**
-     * Removes the given objectSink from the list
-     * @param objectSink
-     * @return
-     */
-    public boolean remove(ObjectSink objectSink);
-
-    /**
-     * Returns the number of ObjectSinks in this list
-     * @return
-     */
-    public int size();
-
-    /**
-     * Returns the last added object sink.
-     * 
-     * @return
-     */
-    public ObjectSink getLastObjectSink();
-
-    /**
-     * Iterates over all matching (in case of hashed list) object Sinks
-     * 
-     * @param workingMemory
-     * @param handle
-     * @return
-     */
-    public Iterator iterator(WorkingMemory workingMemory,
-                             DefaultFactHandle handle);
-
-    /**
-     * Iterates over all  object Sinks
-     * 
-     * @return
-     */
-    public Iterator iterator();
-
-    /**
-     * Returns a list with all object sinks
-     * This may be an inneficient method to call, so we recomend using it only for
-     * tests and debug purposes
-     * Also, it returns an unmodifiable list to prevent misuse
-     * 
-     * @return
-     */
-    public List getObjectsAsList();
-
-}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSinkListFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSinkListFactory.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSinkListFactory.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -1,49 +0,0 @@
-/*
- * 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.
- */
-
-package org.drools.reteoo;
-
-import org.drools.RuleBaseConfiguration;
-
-/**
- * ObjectSinkListFactory
- * A factory for ObjectSinkLists
- *
- * @author <a href="mailto:tirelli at post.com">Edson Tirelli</a>
- *
- * Created: 06/march/2006
- */
-public class ObjectSinkListFactory {
-    private final RuleBaseConfiguration config;
-
-    public ObjectSinkListFactory(final RuleBaseConfiguration config) {
-        this.config = config;
-    }
-
-    public final ObjectSinkList newObjectSinkList(final Class owner) {
-        if ( this.config.getBooleanProperty( RuleBaseConfiguration.PROPERTY_HASH_OBJECT_TYPE_NODES ) && (ObjectTypeNode.class.isAssignableFrom( owner )) ) {
-            return new HashedObjectSinkList();
-        } else if ( this.config.getBooleanProperty( RuleBaseConfiguration.PROPERTY_HASH_ALPHA_NODES ) && (AlphaNode.class.isAssignableFrom( owner )) ) {
-            return new HashedObjectSinkList();
-        }
-        return new DefaultObjectSinkList( 1 );
-    }
-
-    public static final ObjectSinkList newDefaultObjectSinkList() {
-        return new DefaultObjectSinkList( 1 );
-    }
-
-}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSinkNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSinkNode.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSinkNode.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -0,0 +1,59 @@
+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;
+
+/**
+ * Items placed in a <code>LinkedList<code> must implement this interface .
+ * 
+ * @see TupleSinkNodeList
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ */
+public interface ObjectSinkNode extends ObjectSink {
+
+    /**
+     * Returns the next node
+     * @return
+     *      The next LinkedListNode
+     */
+    public ObjectSinkNode getNextObjectSinkNode();
+
+    /**
+     * Sets the next node 
+     * @param next
+     *      The next LinkedListNode
+     */
+    public void setNextObjectSinkNode(ObjectSinkNode next);
+
+    /**
+     * Returns the previous node
+     * @return
+     *      The previous LinkedListNode
+     */
+    public ObjectSinkNode getPreviousObjectSinkNode();
+
+    /**
+     * Sets the previous node 
+     * @param previous
+     *      The previous LinkedListNode
+     */
+    public void setPreviousObjectSinkNode(ObjectSinkNode previous);
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSinkNodeList.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSinkNodeList.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSinkNodeList.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -0,0 +1,229 @@
+package org.drools.reteoo;
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import org.drools.util.LinkedListNode;
+
+/*
+ * 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.
+ */
+
+/**
+ * This is a simple linked linked implementation. Each node must implement </code>LinkedListNode<code> so that it references
+ * the node before and after it. This way a node can be removed without having to scan the list to find it. This class
+ * does not provide an Iterator implementation as its designed for efficiency and not genericity. There are a number of 
+ * ways to iterate the list.
+ * <p>
+ * Simple iterator:
+ * <pre>
+ * for ( LinkedListNode node = list.getFirst(); node != null; node =  node.getNext() ) {
+ * }
+ * </pre>
+ * 
+ * Iterator that pops the first entry:
+ * <pre>
+ * for ( LinkedListNode node = list.removeFirst(); node != null; node = list.removeFirst() ) {
+ * }
+ * </pre>
+ *
+ *
+ * @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 ObjectSinkNodeList implements Serializable {
+    private static final long serialVersionUID = 320;
+    
+    private ObjectSinkNode firstNode;
+    private ObjectSinkNode lastNode;
+
+    private int            size;
+
+    /**
+     * Construct an empty <code>LinkedList</code>
+     */
+    public ObjectSinkNodeList() {
+
+    }
+
+    /**
+     * Add a <code>ObjectSinkNode</code> to the list. If the <code>LinkedList</code> is empty then the first and 
+     * last nodes are set to the added node.
+     * 
+     * @param node
+     *      The <code>ObjectSinkNode</code> to be added
+     */
+    public void add(final ObjectSinkNode node) {
+        if ( this.firstNode == null ) {
+            this.firstNode = node;
+            this.lastNode = node;;
+        } else {
+            this.lastNode.setNextObjectSinkNode( node );
+            node.setPreviousObjectSinkNode( this.lastNode );
+            this.lastNode = node;
+        }
+        this.size++;
+    }
+
+    /**
+     * Removes a <code>ObjectSinkNode</code> from the list. This works by attach the previous reference to the child reference.
+     * When the node to be removed is the first node it calls <code>removeFirst()</code>. When the node to be removed is the last node
+     * it calls <code>removeLast()</code>.
+     * 
+     * @param node
+     *      The <code>ObjectSinkNode</code> to be removed.
+     */
+    public void remove(final ObjectSinkNode node) {
+        if ( (this.firstNode != node) && (this.lastNode != node) ) {
+            node.getPreviousObjectSinkNode().setNextObjectSinkNode( node.getNextObjectSinkNode() );
+            node.getNextObjectSinkNode().setPreviousObjectSinkNode( node.getPreviousObjectSinkNode() );
+            this.size--;
+            node.setPreviousObjectSinkNode( null );
+            node.setNextObjectSinkNode( null );
+
+        } else {
+            if ( this.firstNode == node ) {
+                removeFirst();
+            } else if ( this.lastNode == node ) {
+                removeLast();
+            }
+        }
+    }
+
+    /**
+     * Return the first node in the list
+     * @return
+     *      The first <code>ObjectSinkNode</code>.
+     */
+    public final ObjectSinkNode getFirst() {
+        return this.firstNode;
+    }
+
+    /**
+     * Return the last node in the list
+     * @return
+     *      The last <code>ObjectSinkNode</code>.
+     */
+    public final ObjectSinkNode getLast() {
+        return this.lastNode;
+    }
+
+    /**
+     * Remove the first node from the list. The next node then becomes the first node. If this is the last 
+     * node then both first and last node references are set to null.
+     * 
+     * @return
+     *      The first <code>ObjectSinkNode</code>.
+     */
+    public ObjectSinkNode removeFirst() {
+        if ( this.firstNode == null ) {
+            return null;
+        }
+        final ObjectSinkNode node = this.firstNode;
+        this.firstNode = node.getNextObjectSinkNode();
+        node.setNextObjectSinkNode( null );
+        if ( this.firstNode != null ) {
+            this.firstNode.setPreviousObjectSinkNode( null );
+        } else {
+            this.lastNode = null;
+        }
+        this.size--;
+        return node;
+    }
+
+    /**
+     * Remove the last node from the list. The previous node then becomes the last node. If this is the last 
+     * node then both first and last node references are set to null.
+     * 
+     * @return
+     *      The first <code>ObjectSinkNode</code>.
+     */
+    public ObjectSinkNode removeLast() {
+        if ( this.lastNode == null ) {
+            return null;
+        }
+        final ObjectSinkNode node = this.lastNode;
+        this.lastNode = node.getPreviousObjectSinkNode();
+        node.setPreviousObjectSinkNode( null );
+        if ( this.lastNode != null ) {
+            this.lastNode.setNextObjectSinkNode( null );
+        } else {
+            this.firstNode = this.lastNode;
+        }
+        this.size--;
+        return node;
+    }
+
+    /**
+     * @return
+     *      boolean value indicating the empty status of the list
+     */
+    public final boolean isEmpty() {
+        return (this.firstNode == null);
+    }
+
+    /**
+     * Iterates the list removing all the nodes until there are no more nodes to remove. 
+     */
+    public void clear() {
+        while ( removeFirst() != null ) {
+        }
+    }
+
+    /**
+     * @return
+     *     return size of the list as an int
+     */
+    public final int size() {
+        return this.size;
+    }
+
+    /**
+     * Returns a list iterator
+     * @return
+     */
+    public Iterator iterator() {
+        return new Iterator() {
+            private ObjectSinkNode currentNode = null;
+            private ObjectSinkNode nextNode    = getFirst();
+
+            public boolean hasNext() {
+                return (this.nextNode != null);
+            }
+
+            public Object next() {
+                this.currentNode = this.nextNode;
+                if ( this.currentNode != null ) {
+                    this.nextNode = this.currentNode.getNextObjectSinkNode();
+                } else {
+                    throw new NoSuchElementException( "No more elements to return" );
+                }
+                return this.currentNode;
+            }
+
+            public void remove() {
+                if ( this.currentNode != null ) {
+                    ObjectSinkNodeList.this.remove( this.currentNode );
+                    this.currentNode = null;
+                } else {
+                    throw new IllegalStateException( "No item to remove. Call next() before calling remove()." );
+                }
+            }
+        };
+    }
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSinkPropagator.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSinkPropagator.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSinkPropagator.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -0,0 +1,28 @@
+package org.drools.reteoo;
+
+import java.util.Map;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+
+public interface ObjectSinkPropagator {
+    public void propagateAssertObject(InternalFactHandle handle,
+                                      PropagationContext context,
+                                      InternalWorkingMemory workingMemory);
+
+    public void propagateRetractObject(InternalFactHandle handle,
+                                       PropagationContext context,
+                                       InternalWorkingMemory workingMemory,
+                                       boolean useHash);
+
+    public void propagateModifyObject(InternalFactHandle handle,
+                                      PropagationContext context,
+                                      InternalWorkingMemory workingMemory);
+
+    public ObjectSink[] getSinks();
+
+    public void propagateNewObjectSink(InternalFactHandle handle,
+                                       PropagationContext context,
+                                       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-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectSource.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -20,6 +20,7 @@
 import java.util.Iterator;
 import java.util.List;
 
+import org.drools.common.BaseNode;
 import org.drools.common.DefaultFactHandle;
 import org.drools.spi.PropagationContext;
 
@@ -44,7 +45,9 @@
     // ------------------------------------------------------------
 
     /** The destination for <code>FactHandleImpl</code>. */
-    protected ObjectSinkList objectSinks;
+    protected ObjectSinkPropagator sink;
+    
+    protected ObjectSource objectSource;   
 
     // ------------------------------------------------------------
     // Constructors
@@ -66,9 +69,9 @@
      * @param id
      */
     ObjectSource(final int id,
-                 final ObjectSinkList objectSinks) {
+                 final ObjectSource objectSource) {
         super( id );
-        this.objectSinks = (objectSinks != null) ? objectSinks : ObjectSinkListFactory.newDefaultObjectSinkList();
+        this.objectSource = objectSource;
     }
 
     // ------------------------------------------------------------
@@ -85,8 +88,15 @@
      *            <code>FactHandleImpl</code>.
      */
     protected void addObjectSink(final ObjectSink objectSink) {
-        if ( !this.objectSinks.contains( objectSink ) ) {
-            this.objectSinks.add( objectSink );
+        if ( this.sink == null ) {
+            this.sink = new SingleObjectSinkAdapter( objectSink );
+        } else if ( this.sink.getClass() == SingleObjectSinkAdapter.class ) {
+            CompositeObjectSinkAdapter sinkAdapter = ( CompositeObjectSinkAdapter ) new CompositeObjectSinkAdapter();
+            sinkAdapter.addObjectSink( this.sink.getSinks()[0] );
+            sinkAdapter.addObjectSink( objectSink );
+            this.sink = sinkAdapter;
+        } else {
+            ( (CompositeObjectSinkAdapter) sink ).addObjectSink( objectSink );
         }
     }
 
@@ -97,80 +107,14 @@
      *            The <code>ObjectSink</code> to remove
      */
     protected void removeObjectSink(final ObjectSink objectSink) {
-        this.objectSinks.remove( objectSink );
+        if ( this.sink.getClass() == SingleObjectSinkAdapter.class ) {
+            this.sink = null;
+        } else { 
+            CompositeObjectSinkAdapter sinkAdapter = ( CompositeObjectSinkAdapter ) objectSink;
+            sinkAdapter.removeObjectSink( objectSink );
+            if ( sinkAdapter.size() == 1 ) {
+                this.sink = new SingleObjectSinkAdapter( sinkAdapter.getSinks()[0] );
+            }
+        }         
     }
-
-    /**
-     * Propagate the assertion of a <code>FactHandleImpl/code> to this node's
-     * <code>ObjectSink</code>s.
-     * 
-     * @param handle
-     *           the FactHandleImpl to be asserted
-     * @param context
-     *             The <code>PropagationContext</code> of the <code>WorkingMemory<code> action            
-     * @param workingMemory
-     *            the <code>WorkingMemory</code> session.
-     */
-    protected void propagateAssertObject(final DefaultFactHandle handle,
-                                         final PropagationContext context,
-                                         final ReteooWorkingMemory workingMemory) {
-        for ( final Iterator i = this.objectSinks.iterator( workingMemory,
-                                                            handle ); i.hasNext(); ) {
-            ((ObjectSink) i.next()).assertObject( handle,
-                                                  context,
-                                                  workingMemory );
-        }
-    }
-
-    /**
-     * Propagate the retration of a <code>FactHandleImpl/code> to this node's
-     * <code>ObjectSink</code>.
-     * 
-     * @param handle
-     *           the FactHandleImpl to be retractred
-     * @param context
-     *             The <code>PropagationContext</code> of the <code>WorkingMemory<code> action            
-     * @param workingMemory
-     *            the <code>WorkingMemory</code> session.
-     *
-     */
-    protected void propagateRetractObject(final DefaultFactHandle handle,
-                                          final PropagationContext context,
-                                          final ReteooWorkingMemory workingMemory) {
-        for ( final Iterator i = this.objectSinks.iterator(); i.hasNext(); ) {
-            ((ObjectSink) i.next()).retractObject( handle,
-                                                   context,
-                                                   workingMemory );
-        }
-    }
-
-    protected void propagateModifyObject(final DefaultFactHandle handle,
-                                         final PropagationContext context,
-                                         final ReteooWorkingMemory workingMemory) {
-        for ( final Iterator i = this.objectSinks.iterator(); i.hasNext(); ) {
-            ((ObjectSink) i.next()).modifyObject( handle,
-                                                  context,
-                                                  workingMemory );
-        }
-    }
-
-    /**
-     * Retrieve the <code>ObectsSinks</code> that receive propagated
-     * <code>FactHandleImpl</code>s.
-     * 
-     * @return The <code>ObjectsSinks</code> that receive propagated
-     *         <code>FactHandles</code>.
-     */
-    public ObjectSinkList getObjectSinks() {
-        return this.objectSinks;
-    }
-
-    /**
-     * Returns the object sinks as an unmodifiable list
-     * @return
-     */
-    public List getObjectSinksAsList() {
-        return this.objectSinks.getObjectsAsList();
-    }
-
 }

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-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectTypeNode.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -20,7 +20,10 @@
 import java.util.Iterator;
 
 import org.drools.RuleBaseConfiguration;
+import org.drools.common.BaseNode;
 import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
 import org.drools.common.NodeMemory;
 import org.drools.common.PropagationContextImpl;
 import org.drools.spi.ObjectType;
@@ -84,27 +87,7 @@
     public ObjectTypeNode(final int id,
                           final ObjectType objectType,
                           final Rete rete) {
-        this( id,
-              null,
-              objectType,
-              rete );
-    }
-
-    /**
-     * Construct given a semantic <code>ObjectType</code> and the provided
-     * unique id. All <code>ObjectTypdeNode</code> have node memory.
-     * 
-     * @param id The unique id for the node
-     * @param sinklist An object sink list for the node. If null, a default will be created.
-     * @param objectType The semantic object-type differentiator
-     * @param rete The rete network reference
-     */
-    public ObjectTypeNode(final int id,
-                          final ObjectSinkList sinklist,
-                          final ObjectType objectType,
-                          final Rete rete) {
-        super( id,
-               sinklist );
+        super( id );
         this.rete = rete;
         this.objectType = objectType;
         setHasMemory( true );
@@ -148,16 +131,14 @@
      * @param workingMemory
      *            The working memory session.
      */
-    public void assertObject(final DefaultFactHandle handle,
+    public void assertObject(final InternalFactHandle handle,
                              final PropagationContext context,
-                             final ReteooWorkingMemory workingMemory) {
+                             final InternalWorkingMemory workingMemory) {
         final PrimitiveLongMap memory = (PrimitiveLongMap) workingMemory.getNodeMemory( this );
         memory.put( handle.getId(),
                     handle );
-
-        propagateAssertObject( handle,
-                               context,
-                               workingMemory );
+        
+        this.sink.propagateAssertObject( handle, context, workingMemory );
     }
 
     /**
@@ -171,46 +152,33 @@
      * @param workingMemory
      *            The working memory session.
      */
-    public void retractObject(final DefaultFactHandle handle,
+    public void retractObject(final InternalFactHandle handle,
                               final PropagationContext context,
-                              final ReteooWorkingMemory workingMemory) {
+                              final InternalWorkingMemory workingMemory) {
         final PrimitiveLongMap memory = (PrimitiveLongMap) workingMemory.getNodeMemory( this );
         memory.remove( handle.getId() );
 
-        propagateRetractObject( handle,
-                                context,
-                                workingMemory );
+        this.sink.propagateRetractObject( handle, context, workingMemory, true );
     }
 
-    public void modifyObject(final DefaultFactHandle handle,
+    public void modifyObject(final InternalFactHandle handle,
                              final PropagationContext context,
-                             final ReteooWorkingMemory workingMemory) {
-        final PrimitiveLongMap memory = (PrimitiveLongMap) workingMemory.getNodeMemory( this );
-
-        propagateModifyObject( handle,
-                               context,
-                               workingMemory );
+                             final InternalWorkingMemory workingMemory) {        
+        this.sink.propagateModifyObject( handle, context, workingMemory );       
     }
 
     /* (non-Javadoc)
      * @see org.drools.reteoo.BaseNode#updateNewNode(org.drools.reteoo.WorkingMemoryImpl, org.drools.spi.PropagationContext)
      */
-    public void updateNewNode(final ReteooWorkingMemory workingMemory,
+    public void updateNewNode(final InternalWorkingMemory workingMemory,
                               final PropagationContext context) {
         this.attachingNewNode = true;
 
-        final PrimitiveLongMap memory = (PrimitiveLongMap) workingMemory.getNodeMemory( this );
+        final PrimitiveLongMap memory = (PrimitiveLongMap) workingMemory.getNodeMemory( this );        
 
-        for ( final Iterator it = memory.values().iterator(); it.hasNext(); ) {
+        for ( final Iterator it = memory.values().iterator(); it.hasNext(); ) {            
             final DefaultFactHandle handle = (DefaultFactHandle) it.next();
-            final ObjectSink sink = this.objectSinks.getLastObjectSink();
-            if ( sink != null ) {
-                sink.assertObject( handle,
-                                   context,
-                                   workingMemory );
-            } else {
-                throw new RuntimeException( "Possible BUG: trying to propagate an assert to a node that was the last added node" );
-            }
+            this.sink.propagateNewObjectSink( handle, context, workingMemory );
         }
 
         this.attachingNewNode = false;
@@ -223,14 +191,14 @@
         this.rete.addObjectSink( this );
     }
 
-    public void attach(final ReteooWorkingMemory[] workingMemories) {
+    public void attach(final InternalWorkingMemory[] workingMemories) {
         attach();
 
         // we need to call updateNewNode on Rete, because someone 
         // might have already added facts matching this ObjectTypeNode 
         // to working memories
         for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
-            final ReteooWorkingMemory workingMemory = workingMemories[i];
+            final InternalWorkingMemory workingMemory = workingMemories[i];
             final PropagationContext propagationContext = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(),
                                                                                       PropagationContext.RULE_ADDITION,
                                                                                       null,
@@ -241,9 +209,9 @@
     }
 
     public void remove(final BaseNode node,
-                       final ReteooWorkingMemory[] workingMemories) {
+                       final InternalWorkingMemory[] workingMemories) {
         if( !node.isInUse()) {
-            this.objectSinks.remove( (ObjectSink) node );
+            removeObjectSink( ( ObjectSink ) node );
         }
         removeShare();
         if ( !this.isInUse() ) {

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/QueryTerminalNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/QueryTerminalNode.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/QueryTerminalNode.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -19,6 +19,8 @@
 import java.util.LinkedList;
 
 import org.drools.RuleBaseConfiguration;
+import org.drools.common.BaseNode;
+import org.drools.common.InternalWorkingMemory;
 import org.drools.common.NodeMemory;
 import org.drools.common.PropagationContextImpl;
 import org.drools.rule.Rule;
@@ -97,23 +99,23 @@
      */
     public void assertTuple(final ReteTuple tuple,
                             final PropagationContext context,
-                            final ReteooWorkingMemory workingMemory) {
+                            final InternalWorkingMemory workingMemory) {
         final LinkedList list = (LinkedList) workingMemory.getNodeMemory( this );
         if ( list.isEmpty() ) {
-            workingMemory.setQueryResults( this.rule.getName(),
-                                           this );
+            ((ReteooWorkingMemory) workingMemory).setQueryResults( this.rule.getName(),
+                                                                   this );
         }
         list.add( tuple );
     }
 
     public void retractTuple(final ReteTuple tuple,
                              final PropagationContext context,
-                             final ReteooWorkingMemory workingMemory) {
+                             final InternalWorkingMemory workingMemory) {
     }
 
     public void modifyTuple(final ReteTuple tuple,
                             final PropagationContext context,
-                            final ReteooWorkingMemory workingMemory) {
+                            final InternalWorkingMemory workingMemory) {
 
     }
 
@@ -129,11 +131,11 @@
         this.tupleSource.addTupleSink( this );
     }
 
-    public void attach(final ReteooWorkingMemory[] workingMemories) {
+    public void attach(final InternalWorkingMemory[] workingMemories) {
         attach();
 
         for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
-            final ReteooWorkingMemory workingMemory = workingMemories[i];
+            final InternalWorkingMemory workingMemory = workingMemories[i];
             final PropagationContext propagationContext = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(),
                                                                                       PropagationContext.RULE_ADDITION,
                                                                                       null,
@@ -144,7 +146,7 @@
     }
 
     public void remove(final BaseNode node,
-                       final ReteooWorkingMemory[] workingMemories) {
+                       final InternalWorkingMemory[] workingMemories) {
         for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
             workingMemories[i].clearNodeMemory( this );
         }
@@ -152,7 +154,7 @@
                                  workingMemories );
     }
 
-    public void updateNewNode(final ReteooWorkingMemory workingMemory,
+    public void updateNewNode(final InternalWorkingMemory workingMemory,
                               final PropagationContext context) {
         // There are no child nodes to update, do nothing.
     }

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-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/Rete.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -26,7 +26,10 @@
 
 import org.drools.FactException;
 import org.drools.RuleBaseConfiguration;
+import org.drools.common.BaseNode;
 import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
 import org.drools.common.NodeMemory;
 import org.drools.facttemplates.Fact;
 import org.drools.facttemplates.FactImpl;
@@ -104,13 +107,12 @@
      * @param workingMemory
      *            The working memory session.
      */
-    public void assertObject(final DefaultFactHandle handle,
+    public void assertObject(final InternalFactHandle handle,
                              final PropagationContext context,
-                             final ReteooWorkingMemory workingMemory) {
+                             final InternalWorkingMemory workingMemory) {
         final HashMap memory = (HashMap) workingMemory.getNodeMemory( this );
 
         final Object object = handle.getObject();
-
         
         Object key = null;
             
@@ -143,9 +145,9 @@
      * @param workingMemory
      *            The working memory session.
      */
-    public void retractObject(final DefaultFactHandle handle,
+    public void retractObject(final InternalFactHandle handle,
                               final PropagationContext context,
-                              final ReteooWorkingMemory workingMemory) {
+                              final InternalWorkingMemory workingMemory) {
         final HashMap memory = (HashMap) workingMemory.getNodeMemory( this );
 
         final Object object = handle.getObject();
@@ -164,9 +166,9 @@
         }
     }
 
-    public void modifyObject(final DefaultFactHandle handle,
+    public void modifyObject(final InternalFactHandle handle,
                              final PropagationContext context,
-                             final ReteooWorkingMemory workingMemory) {
+                             final InternalWorkingMemory workingMemory) {
         final HashMap memory = (HashMap) workingMemory.getNodeMemory( this );
 
         final Object object = handle.getObject();
@@ -262,13 +264,13 @@
         // do nothing this is the root node
     }
 
-    public void attach(final ReteooWorkingMemory[] workingMemories) {
+    public void attach(final InternalWorkingMemory[] workingMemories) {
         // do nothing this is the root node        
     }
 
     // when a new ObjectTypeNode is added, check for possible 
     // propagations into the new node
-    public void updateNewNode(final ReteooWorkingMemory workingMemory,
+    public void updateNewNode(final InternalWorkingMemory workingMemory,
                               final PropagationContext context) {
         if ( this.lastAddedNode != null ) {
             final ObjectType objType = this.lastAddedNode.getObjectType();
@@ -286,7 +288,7 @@
     }
 
     public void remove(final BaseNode node,
-                       final ReteooWorkingMemory[] workingMemories) {
+                       final InternalWorkingMemory[] workingMemories) {
         final ObjectTypeNode objectTypeNode = (ObjectTypeNode) node;
         removeObjectSink( objectTypeNode );
         //@todo: we really should attempt to clear the memory cache for this ObjectTypeNode        

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-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteTuple.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -24,8 +24,10 @@
 import org.drools.FactHandle;
 import org.drools.common.DefaultFactHandle;
 import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
 import org.drools.rule.Declaration;
 import org.drools.spi.Activation;
+import org.drools.spi.PropagationContext;
 import org.drools.spi.Tuple;
 import org.drools.util.BaseMultiLinkedListNode;
 import org.drools.util.LinkedList;
@@ -61,10 +63,12 @@
     /**
      * 
      */
-    private static final long serialVersionUID = -4430322768472253111L;
+    private static final long serialVersionUID = 320;
 
     /** The </code>TupleKey</code> */
     private final TupleKey    key;
+    
+    private final TupleSink   sink;
 
     /** The <code>Map</code> of <code>FactHandleImpl</code> matches */
     private Map               matches          = Collections.EMPTY_MAP;
@@ -72,7 +76,7 @@
     /** The resuling propagation when used in a <code>NotNode</code> */
     private LinkedList        linkedTuples;
 
-    private Activation        activation;
+    private Activation        activation;    
 
     // ------------------------------------------------------------
     // Constructors
@@ -87,8 +91,9 @@
      * @param workingMemory
      *      The <code>WorkingMemory</code> session.
      */
-    public ReteTuple(final DefaultFactHandle handle) {
+    public ReteTuple(final InternalFactHandle handle, final TupleSink sink) {
         this.key = new TupleKey( handle );
+        this.sink = sink;
     }
 
     /**
@@ -96,8 +101,9 @@
      * 
      * @param tuple
      */
-    public ReteTuple(final ReteTuple tuple) {
+    public ReteTuple(final ReteTuple tuple, final TupleSink sink) {
         this.key = new TupleKey( tuple.key );
+        this.sink = sink;
     }
 
     /**
@@ -109,9 +115,10 @@
      *      the <code>FactHandleImpl</code> to be joined.
      */
     public ReteTuple(final ReteTuple left,
-              final DefaultFactHandle handle) {
+              final InternalFactHandle handle, final TupleSink sink) {
         this.key = new TupleKey( left.key,
                                  handle );
+        this.sink = sink;
     }
 
     // ------------------------------------------------------------
@@ -207,7 +214,7 @@
         this.matches.clear();
     }    
     
-    public void addTupleMatch(final DefaultFactHandle handle,
+    public void addTupleMatch(final InternalFactHandle handle,
                               final TupleMatch node) {
         if ( this.matches == Collections.EMPTY_MAP ) {
             this.matches = new HashMap(2);
@@ -228,7 +235,7 @@
         return (TupleMatch) this.matches.get( handle );
     }
 
-    public TupleMatch removeMatch(final DefaultFactHandle handle) {
+    public TupleMatch removeMatch(final InternalFactHandle handle) {
         return (TupleMatch) this.matches.remove( handle );
     }
 
@@ -287,4 +294,26 @@
         }
         return buffer.toString();
     }
+
+    public void assertTuple(PropagationContext context,
+                            InternalWorkingMemory workingMemory) {
+        this.sink.assertTuple( this, context, workingMemory );
+        
+    }
+
+    public void modifyTuple(PropagationContext context,
+                            InternalWorkingMemory workingMemory) {
+        this.sink.modifyTuple( this, context, workingMemory );
+        
+    }
+
+    public void retractTuple(PropagationContext context,
+                             InternalWorkingMemory workingMemory) {
+        this.sink.retractTuple( this, context, workingMemory );        
+    }
+    
+    public TupleSink getTupleSink() {
+        return this.sink;
+    }
+    
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooBuilder.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooBuilder.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -32,6 +32,7 @@
 import org.drools.base.FieldFactory;
 import org.drools.base.ValueType;
 import org.drools.base.evaluators.Operator;
+import org.drools.common.BaseNode;
 import org.drools.common.BetaNodeBinder;
 import org.drools.common.InstanceEqualsConstraint;
 import org.drools.common.InstanceNotEqualsConstraint;
@@ -101,9 +102,6 @@
 
     private int                             currentOffsetAdjustment;
 
-    /** A factory for object sink lists */
-    private transient ObjectSinkListFactory sinklistFactory;
-
     // ------------------------------------------------------------
     // Constructors
     // ------------------------------------------------------------
@@ -122,9 +120,6 @@
 
         //Set to 1 as Rete node is set to 0
         this.id = 1;
-
-        // creating factory
-        this.sinklistFactory = new ObjectSinkListFactory( this.ruleBase.getConfiguration() );
     }
 
     /**
@@ -296,7 +291,6 @@
                     this.currentOffsetAdjustment = 1;
 
                     final ObjectSource objectSource = attachNode( new ObjectTypeNode( this.id++,
-                                                                                      this.sinklistFactory.newObjectSinkList( ObjectTypeNode.class ),
                                                                                       new ClassObjectType( InitialFact.class ),
                                                                                       this.rete ) );
 
@@ -347,7 +341,6 @@
         this.currentOffsetAdjustment += 1;
 
         final ObjectSource objectTypeSource = attachNode( new ObjectTypeNode( this.id++,
-                                                                              this.sinklistFactory.newObjectSinkList( ObjectTypeNode.class ),
                                                                               new ClassObjectType( DroolsQuery.class ),
                                                                               this.rete ) );
 
@@ -362,7 +355,6 @@
                                                                     field );
 
         final ObjectSource alphaNodeSource = attachNode( new AlphaNode( this.id++,
-                                                                        this.sinklistFactory.newObjectSinkList( AlphaNode.class ),
                                                                         constraint,
                                                                         objectTypeSource ) );
 
@@ -403,7 +395,6 @@
         final List constraints = column.getConstraints();
 
         this.objectSource = attachNode( new ObjectTypeNode( this.id++,
-                                                            this.sinklistFactory.newObjectSinkList( ObjectTypeNode.class ),
                                                             column.getObjectType(),
                                                             this.rete ) );
 
@@ -440,7 +431,6 @@
             final FieldConstraint fieldConstraint = (FieldConstraint) object;
             if ( fieldConstraint.getRequiredDeclarations().length == 0 ) {
                 this.objectSource = attachNode( new AlphaNode( this.id++,
-                                                               this.sinklistFactory.newObjectSinkList( AlphaNode.class ),
                                                                fieldConstraint,
                                                                this.objectSource ) );
             } else {
@@ -576,7 +566,6 @@
             this.currentOffsetAdjustment = 1;
 
             final ObjectSource objectSource = attachNode( new ObjectTypeNode( this.id++,
-                                                                              this.sinklistFactory.newObjectSinkList( ObjectTypeNode.class ),
                                                                               new ClassObjectType( InitialFact.class ),
                                                                               this.rete ) );
 
@@ -646,7 +635,6 @@
             this.currentOffsetAdjustment = 1;
 
             final ObjectSource auxObjectSource = attachNode( new ObjectTypeNode( this.id++,
-                                                                                 this.sinklistFactory.newObjectSinkList( ObjectTypeNode.class ),
                                                                                  new ClassObjectType( InitialFact.class ),
                                                                                  this.rete ) );
 

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooToJungVisitor.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooToJungVisitor.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooToJungVisitor.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -24,6 +24,7 @@
 import java.util.Map;
 
 import org.drools.base.ClassFieldExtractor;
+import org.drools.common.BaseNode;
 import org.drools.rule.LiteralConstraint;
 import org.drools.spi.FieldConstraint;
 import org.drools.util.ReflectiveVisitor;

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-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/RightInputAdapterNode.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -16,7 +16,10 @@
  * limitations under the License.
  */
 
+import org.drools.common.BaseNode;
 import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
 import org.drools.spi.PropagationContext;
 
 /**
@@ -72,10 +75,8 @@
      */
     public void assertTuple(final ReteTuple tuple,
                             final PropagationContext context,
-                            final ReteooWorkingMemory workingMemory) {
-        propagateAssertObject( (DefaultFactHandle) tuple.get( this.column ),
-                               context,
-                               workingMemory );
+                            final InternalWorkingMemory workingMemory) {
+        this.sink.propagateAssertObject( (InternalFactHandle) tuple.get( this.column ), context, workingMemory );
     }
 
     /* (non-Javadoc)
@@ -83,18 +84,14 @@
      */
     public void retractTuple(final ReteTuple tuple,
                              final PropagationContext context,
-                             final ReteooWorkingMemory workingMemory) {
-        propagateRetractObject( (DefaultFactHandle) tuple.get( this.column ),
-                                context,
-                                workingMemory );
+                             final InternalWorkingMemory workingMemory) {
+        this.sink.propagateRetractObject( (InternalFactHandle) tuple.get( this.column ), context, workingMemory, true );
     }
 
     public void modifyTuple(final ReteTuple tuple,
                             final PropagationContext context,
-                            final ReteooWorkingMemory workingMemory) {
-        propagateModifyObject( (DefaultFactHandle) tuple.get( this.column ),
-                               context,
-                               workingMemory );
+                            final InternalWorkingMemory workingMemory) {
+        this.sink.propagateModifyObject( (InternalFactHandle) tuple.get( this.column ), context, workingMemory );
     }
 
     /* (non-Javadoc)
@@ -104,7 +101,7 @@
         this.tupleSource.addTupleSink( this );
     }
 
-    public void attach(final ReteooWorkingMemory[] workingMemories) {
+    public void attach(final InternalWorkingMemory[] workingMemories) {
         attach();
         // this node has no memory, no point requesting repropagation     
     }
@@ -112,7 +109,7 @@
     /* (non-Javadoc)
      * @see org.drools.reteoo.BaseNode#updateNewNode(org.drools.reteoo.WorkingMemoryImpl, org.drools.spi.PropagationContext)
      */
-    public void updateNewNode(final ReteooWorkingMemory workingMemory,
+    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;
@@ -126,9 +123,9 @@
     }
 
     public void remove(final BaseNode node,
-                       final ReteooWorkingMemory[] workingMemories) {
+                       final InternalWorkingMemory[] workingMemories) {
         if( !node.isInUse() ) {
-            getObjectSinks().remove( (ObjectSink) node );
+            removeObjectSink( (ObjectSink ) node );
         }
         removeShare();
         this.tupleSource.remove( this,

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleObjectSinkAdapter.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleObjectSinkAdapter.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleObjectSinkAdapter.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -0,0 +1,53 @@
+package org.drools.reteoo;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+
+public class SingleObjectSinkAdapter
+    implements
+    ObjectSinkPropagator {
+    
+    private ObjectSink sink;
+    
+    public SingleObjectSinkAdapter(ObjectSink sink) {
+        this.sink = sink;
+    }
+
+    public void propagateAssertObject(InternalFactHandle handle,
+                                      PropagationContext context,
+                                      InternalWorkingMemory workingMemory) {
+        this.sink.assertObject( handle, context, workingMemory );
+
+    }
+
+    public void propagateModifyObject(InternalFactHandle handle,
+                                      PropagationContext context,
+                                      InternalWorkingMemory workingMemory) {
+        this.sink.modifyObject( handle, context, workingMemory );
+
+    }
+    
+    public void propagateRetractObject(InternalFactHandle handle,
+                                       PropagationContext context,
+                                       InternalWorkingMemory workingMemory,
+                                       boolean useHash) {
+        this.sink.retractObject( handle, context, workingMemory );
+
+    }    
+
+    public void propagateNewObjectSink(InternalFactHandle handle,
+                                       PropagationContext context,
+                                       InternalWorkingMemory workingMemory) {
+        // do nothing as this cannot have new sinks
+        throw new RuntimeException( "This is a bug you cannot update new data through this single sink adapter" );
+
+    }
+
+    public ObjectSink[] getSinks() {
+        return new ObjectSink[] { this.sink };
+    }
+
+
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleTupleMatchChildren.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleTupleMatchChildren.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleTupleMatchChildren.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -0,0 +1,5 @@
+package org.drools.reteoo;
+
+public class SingleTupleMatchChildren {
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleTupleSink.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleTupleSink.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleTupleSink.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -0,0 +1,34 @@
+package org.drools.reteoo;
+
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+
+public class SingleTupleSink implements TupleSink {
+    private TupleSink sink;
+    public SingleTupleSink(TupleSink sink) {
+        this.sink = sink;
+    }
+    
+    public void assertTuple(ReteTuple tuple,
+                            PropagationContext context,
+                            InternalWorkingMemory workingMemory) {
+        sink.assertTuple( tuple, context, workingMemory );
+        
+    }
+
+    public void modifyTuple(ReteTuple tuple,
+                            PropagationContext context,
+                            InternalWorkingMemory workingMemory) {
+        sink.modifyTuple( tuple, context, workingMemory );
+        
+    }
+
+    public void retractTuple(ReteTuple tuple,
+                             PropagationContext context,
+                             InternalWorkingMemory workingMemory) {
+        this.retractTuple( tuple, context, workingMemory );
+        
+    }
+
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleTupleSinkAdapter.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleTupleSinkAdapter.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleTupleSinkAdapter.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -0,0 +1,92 @@
+package org.drools.reteoo;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+import org.drools.util.LinkedList;
+import org.drools.util.LinkedListObjectWrapper;
+
+public class SingleTupleSinkAdapter
+    implements
+    TupleSinkPropagator {
+    private TupleSink sink;
+
+    public SingleTupleSinkAdapter(TupleSink sink) {
+        this.sink = sink;
+    }
+
+    public void propagateAssertTuple(ReteTuple tuple,
+                                     InternalFactHandle handle,
+                                     TupleMatch tupleMatch,
+                                     PropagationContext context,
+                                     InternalWorkingMemory workingMemory) {
+        ReteTuple joined = new ReteTuple( tuple,
+                                          handle,
+                                          sink );
+        tupleMatch.addJoinedTuple( joined );
+        joined.assertTuple( context,
+                            workingMemory );
+    }
+
+    public void createAndAssertTuple(InternalFactHandle handle,
+                                     PropagationContext context,
+                                     InternalWorkingMemory workingMemory,
+                                     Map memory) {
+        final LinkedList list = new LinkedList();
+        ReteTuple tuple = new ReteTuple( handle,
+                                         sink );
+        tuple.assertTuple( context,
+                           workingMemory );
+        list.add( tuple );
+    }
+
+    public void propagateAssertTuple(ReteTuple tuple,
+                                     PropagationContext context,
+                                     InternalWorkingMemory workingMemory) {
+        final ReteTuple child = new ReteTuple( tuple,
+                                               sink );
+        // no TupleMatch so instead add as a linked tuple
+        tuple.addLinkedTuple( new LinkedListObjectWrapper( child ) );
+        child.assertTuple( context,
+                           workingMemory );
+    }
+
+    public TupleSink[] getSinks() {
+        return new TupleSink[]{this.sink};
+    }
+
+    public void propagateNewTupleSink(TupleMatch tupleMatch,
+                                      PropagationContext context,
+                                      InternalWorkingMemory workingMemory) {
+        // do nothing, as we have no new tuple sinks
+        throw new RuntimeException( "This is a bug you cannot update new data through this single sink adapter" );
+    }
+
+    public void propagateNewTupleSink(InternalFactHandle handle,
+                                      LinkedList list,
+                                      PropagationContext context,
+                                      InternalWorkingMemory workingMemory) {
+        // do nothing, as we have no new tuple sinks
+        throw new RuntimeException( "This is a bug you cannot update new data through this single sink adapter" );
+
+    }
+
+    public List getPropagatedTuples(final Map memory,
+                                    final InternalWorkingMemory workingMemory,
+                                    final TupleSink sink) {
+        final List propagatedTuples = new ArrayList( memory.size() );
+
+        for ( final Iterator it = memory.values().iterator(); it.hasNext(); ) {
+            final LinkedList tuples = (LinkedList) it.next();
+            propagatedTuples.add( ((LinkedListObjectWrapper) tuples.getFirst()).getObject() );
+        }
+
+        return propagatedTuples;
+    }
+
+}

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TerminalNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TerminalNode.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TerminalNode.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -22,7 +22,9 @@
 import org.drools.RuleBaseConfiguration;
 import org.drools.common.AgendaGroupImpl;
 import org.drools.common.AgendaItem;
+import org.drools.common.BaseNode;
 import org.drools.common.InternalAgenda;
+import org.drools.common.InternalWorkingMemory;
 import org.drools.common.NodeMemory;
 import org.drools.common.PropagationContextImpl;
 import org.drools.common.ScheduledAgendaItem;
@@ -43,7 +45,7 @@
  */
 final class TerminalNode extends BaseNode
     implements
-    TupleSink,
+    TupleSinkNode,
     NodeMemory {
     // ------------------------------------------------------------
     // Instance members
@@ -56,6 +58,9 @@
     /** The rule to invoke upon match. */
     private final Rule        rule;
     private final TupleSource tupleSource;
+    
+    private TupleSinkNode previousTupleSinkNode;
+    private TupleSinkNode nextTupleSinkNode;
 
     // ------------------------------------------------------------
     // Constructors
@@ -96,7 +101,7 @@
 
     public void assertTuple(final ReteTuple tuple,
                             final PropagationContext context,
-                            final ReteooWorkingMemory workingMemory) {
+                            final InternalWorkingMemory workingMemory) {
         assertTuple( tuple,
                      context,
                      workingMemory,
@@ -116,7 +121,7 @@
      */
     public void assertTuple(final ReteTuple tuple,
                             final PropagationContext context,
-                            final ReteooWorkingMemory workingMemory,
+                            final InternalWorkingMemory workingMemory,
                             final boolean fireActivationCreated) {
         // if the current Rule is no-loop and the origin rule is the same then
         // return
@@ -209,7 +214,7 @@
 
     public void retractTuple(final ReteTuple tuple,
                              final PropagationContext context,
-                             final ReteooWorkingMemory workingMemory) {
+                             final InternalWorkingMemory workingMemory) {
         final Activation activation = tuple.getActivation();
         if ( activation.isActivated() ) {
             activation.remove();
@@ -223,7 +228,7 @@
 
     public void modifyTuple(final ReteTuple tuple,
                             final PropagationContext context,
-                            final ReteooWorkingMemory workingMemory) {
+                            final InternalWorkingMemory workingMemory) {
         // We have to remove and assert the new tuple as it has modified facts and thus its tuple is newer
         boolean fireActivation = true;
         Activation activation = tuple.getActivation();
@@ -252,11 +257,11 @@
         this.tupleSource.addTupleSink( this );
     }
 
-    public void attach(final ReteooWorkingMemory[] workingMemories) {
+    public void attach(final InternalWorkingMemory[] workingMemories) {
         attach();
 
         for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
-            final ReteooWorkingMemory workingMemory = workingMemories[i];
+            final InternalWorkingMemory workingMemory = workingMemories[i];
             final PropagationContext propagationContext = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(),
                                                                                       PropagationContext.RULE_ADDITION,
                                                                                       null,
@@ -267,9 +272,9 @@
     }
 
     public void remove(final BaseNode node,
-                       final ReteooWorkingMemory[] workingMemories) {
+                       final InternalWorkingMemory[] workingMemories) {
         for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
-            final ReteooWorkingMemory workingMemory = workingMemories[i];
+            final InternalWorkingMemory workingMemory = workingMemories[i];
 
             for ( final Iterator it = this.tupleSource.getPropagatedTuples( workingMemory,
                                                                             this ).iterator(); it.hasNext(); ) {
@@ -296,7 +301,7 @@
                                  workingMemories );
     }
 
-    public void updateNewNode(final ReteooWorkingMemory workingMemory,
+    public void updateNewNode(final InternalWorkingMemory workingMemory,
                               final PropagationContext context) {
         // There are no child nodes to update, do nothing.
     }
@@ -304,7 +309,43 @@
     public Object createMemory(final RuleBaseConfiguration config) {
         return new TerminalNodeMemory();
     }
+    
+    /**
+     * Returns the next node
+     * @return
+     *      The next TupleSinkNode
+     */
+    public TupleSinkNode getNextTupleSinkNode() {
+        return this.nextTupleSinkNode;
+    }
 
+    /**
+     * Sets the next node 
+     * @param next
+     *      The next TupleSinkNode
+     */
+    public void setNextTupleSinkNode(TupleSinkNode next) {
+        this.nextTupleSinkNode = next;
+    }
+
+    /**
+     * Returns the previous node
+     * @return
+     *      The previous TupleSinkNode
+     */
+    public TupleSinkNode getPreviousTupleSinkNode() {
+       return this.previousTupleSinkNode;
+    }
+
+    /**
+     * Sets the previous node 
+     * @param previous
+     *      The previous TupleSinkNode
+     */
+    public void setPreviousTupleSinkNode(TupleSinkNode previous) {
+        this.previousTupleSinkNode = previous;
+    }    
+
     public int hashCode() {
         return this.rule.hashCode();
     }

Modified: 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-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleKey.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -36,7 +36,7 @@
     /**
      * 
      */
-    private static final long    serialVersionUID = -880184112928387666L;
+    private static final long    serialVersionUID = 320L;
 
     public static final TupleKey EMPTY_KEY        = new TupleKey();
 
@@ -66,13 +66,13 @@
         this.recency = key.recency;
     }
 
-    public TupleKey(final DefaultFactHandle handle) {
+    public TupleKey(final InternalFactHandle handle) {
         this.handles = new FactHandleList( handle );
         this.recency = handle.getRecency();
     }
 
     public TupleKey(final TupleKey left,
-                    final DefaultFactHandle handle) {
+                    final InternalFactHandle handle) {
         this.handles = new FactHandleList( left.handles,
                                            handle );
         this.recency = left.recency + handle.getRecency();

Modified: 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-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleMatch.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -16,10 +16,8 @@
  * limitations under the License.
  */
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
 import org.drools.util.AbstractBaseLinkedListNode;
 
 /**
@@ -37,11 +35,11 @@
  *
  */
 public class TupleMatch extends AbstractBaseLinkedListNode {
-    private ReteTuple     tuple;
+    private ReteTuple          tuple;
 
-    private List          joined = Collections.EMPTY_LIST;
+    private TupleMatchChildren children;
 
-    private ObjectMatches objectMatches;
+    private ObjectMatches      objectMatches;
 
     /**
      * Construct a <code>TupleMatch</code> with references to the parent <code>ReteTuple</code> and 
@@ -54,6 +52,7 @@
                       final ObjectMatches objectMatches) {
         this.tuple = tuple;
         this.objectMatches = objectMatches;
+        this.children = new CompositeTupleMatchChildren();
     }
 
     /**
@@ -81,19 +80,23 @@
      * @param tuple
      */
     public void addJoinedTuple(final ReteTuple tuple) {
-        if ( this.joined == Collections.EMPTY_LIST ) {
-            this.joined = new ArrayList( 1 );
-        }
-        this.joined.add( tuple );
+        this.children.add( tuple );
     }
 
-    /**
-     * Return the <code>List</code> of joined <code>ReteTuple</code>s.
-     * 
-     * @return the <code>List<code>.
-     */
-    public List getJoinedTuples() {
-        return this.joined;
+    public void propagateRetractTuple(final PropagationContext context,
+                                      final InternalWorkingMemory workingMemory) {
+        this.children.propagateRetractTuple( context,
+                                        workingMemory );
     }
 
+    public void propagateModifyTuple(final PropagationContext context,
+                                     final InternalWorkingMemory workingMemory) {
+        this.children.propagateModifyTuple( context,
+                                       workingMemory );
+    }
+    
+    public ReteTuple getTupleForSink(TupleSink sink) {
+        return this.children.getTupleForSink( sink );
+    }
+
 }
\ No newline at end of file

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-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSink.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -18,7 +18,9 @@
 
 import java.io.Serializable;
 
+import org.drools.common.InternalWorkingMemory;
 import org.drools.spi.PropagationContext;
+import org.drools.util.LinkedListNode;
 
 /**
  * Receiver of propagated <code>ReteTuple</code>s from a
@@ -45,14 +47,16 @@
      */
     void assertTuple(ReteTuple tuple,
                      PropagationContext context,
-                     ReteooWorkingMemory workingMemory);
+                     InternalWorkingMemory workingMemory);
 
     void retractTuple(ReteTuple tuple,
                       PropagationContext context,
-                      ReteooWorkingMemory workingMemory);
+                      InternalWorkingMemory workingMemory);
 
     void modifyTuple(ReteTuple tuple,
                      PropagationContext context,
-                     ReteooWorkingMemory workingMemory);
+                     InternalWorkingMemory workingMemory);
+    
+    
 
 }

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSinkNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSinkNode.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSinkNode.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -0,0 +1,59 @@
+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;
+
+/**
+ * Items placed in a <code>LinkedList<code> must implement this interface .
+ * 
+ * @see TupleSinkNodeList
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ */
+public interface TupleSinkNode extends TupleSink {
+
+    /**
+     * Returns the next node
+     * @return
+     *      The next LinkedListNode
+     */
+    public TupleSinkNode getNextTupleSinkNode();
+
+    /**
+     * Sets the next node 
+     * @param next
+     *      The next LinkedListNode
+     */
+    public void setNextTupleSinkNode(TupleSinkNode next);
+
+    /**
+     * Returns the previous node
+     * @return
+     *      The previous LinkedListNode
+     */
+    public TupleSinkNode getPreviousTupleSinkNode();
+
+    /**
+     * Sets the previous node 
+     * @param previous
+     *      The previous LinkedListNode
+     */
+    public void setPreviousTupleSinkNode(TupleSinkNode previous);
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSinkNodeList.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSinkNodeList.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSinkNodeList.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -0,0 +1,229 @@
+package org.drools.reteoo;
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import org.drools.util.LinkedListNode;
+
+/*
+ * 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.
+ */
+
+/**
+ * This is a simple linked linked implementation. Each node must implement </code>LinkedListNode<code> so that it references
+ * the node before and after it. This way a node can be removed without having to scan the list to find it. This class
+ * does not provide an Iterator implementation as its designed for efficiency and not genericity. There are a number of 
+ * ways to iterate the list.
+ * <p>
+ * Simple iterator:
+ * <pre>
+ * for ( LinkedListNode node = list.getFirst(); node != null; node =  node.getNext() ) {
+ * }
+ * </pre>
+ * 
+ * Iterator that pops the first entry:
+ * <pre>
+ * for ( LinkedListNode node = list.removeFirst(); node != null; node = list.removeFirst() ) {
+ * }
+ * </pre>
+ *
+ *
+ * @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 TupleSinkNodeList implements Serializable {
+    private static final long serialVersionUID = 320;
+    
+    private TupleSinkNode firstNode;
+    private TupleSinkNode lastNode;
+
+    private int            size;
+
+    /**
+     * Construct an empty <code>LinkedList</code>
+     */
+    public TupleSinkNodeList() {
+
+    }
+
+    /**
+     * Add a <code>TupleSinkNode</code> to the list. If the <code>LinkedList</code> is empty then the first and 
+     * last nodes are set to the added node.
+     * 
+     * @param node
+     *      The <code>TupleSinkNode</code> to be added
+     */
+    public void add(final TupleSinkNode node) {
+        if ( this.firstNode == null ) {
+            this.firstNode = node;
+            this.lastNode = node;;
+        } else {
+            this.lastNode.setNextTupleSinkNode( node );
+            node.setPreviousTupleSinkNode( this.lastNode );
+            this.lastNode = node;
+        }
+        this.size++;
+    }
+
+    /**
+     * Removes a <code>TupleSinkNode</code> from the list. This works by attach the previous reference to the child reference.
+     * When the node to be removed is the first node it calls <code>removeFirst()</code>. When the node to be removed is the last node
+     * it calls <code>removeLast()</code>.
+     * 
+     * @param node
+     *      The <code>TupleSinkNode</code> to be removed.
+     */
+    public void remove(final TupleSinkNode node) {
+        if ( (this.firstNode != node) && (this.lastNode != node) ) {
+            node.getPreviousTupleSinkNode().setNextTupleSinkNode( node.getNextTupleSinkNode() );
+            node.getNextTupleSinkNode().setPreviousTupleSinkNode( node.getPreviousTupleSinkNode() );
+            this.size--;
+            node.setPreviousTupleSinkNode( null );
+            node.setNextTupleSinkNode( null );
+
+        } else {
+            if ( this.firstNode == node ) {
+                removeFirst();
+            } else if ( this.lastNode == node ) {
+                removeLast();
+            }
+        }
+    }
+
+    /**
+     * Return the first node in the list
+     * @return
+     *      The first <code>TupleSinkNode</code>.
+     */
+    public final TupleSinkNode getFirst() {
+        return this.firstNode;
+    }
+
+    /**
+     * Return the last node in the list
+     * @return
+     *      The last <code>TupleSinkNode</code>.
+     */
+    public final TupleSinkNode getLast() {
+        return this.lastNode;
+    }
+
+    /**
+     * Remove the first node from the list. The next node then becomes the first node. If this is the last 
+     * node then both first and last node references are set to null.
+     * 
+     * @return
+     *      The first <code>TupleSinkNode</code>.
+     */
+    public TupleSinkNode removeFirst() {
+        if ( this.firstNode == null ) {
+            return null;
+        }
+        final TupleSinkNode node = this.firstNode;
+        this.firstNode = node.getNextTupleSinkNode();
+        node.setNextTupleSinkNode( null );
+        if ( this.firstNode != null ) {
+            this.firstNode.setPreviousTupleSinkNode( null );
+        } else {
+            this.lastNode = null;
+        }
+        this.size--;
+        return node;
+    }
+
+    /**
+     * Remove the last node from the list. The previous node then becomes the last node. If this is the last 
+     * node then both first and last node references are set to null.
+     * 
+     * @return
+     *      The first <code>TupleSinkNode</code>.
+     */
+    public TupleSinkNode removeLast() {
+        if ( this.lastNode == null ) {
+            return null;
+        }
+        final TupleSinkNode node = this.lastNode;
+        this.lastNode = node.getPreviousTupleSinkNode();
+        node.setPreviousTupleSinkNode( null );
+        if ( this.lastNode != null ) {
+            this.lastNode.setNextTupleSinkNode( null );
+        } else {
+            this.firstNode = this.lastNode;
+        }
+        this.size--;
+        return node;
+    }
+
+    /**
+     * @return
+     *      boolean value indicating the empty status of the list
+     */
+    public final boolean isEmpty() {
+        return (this.firstNode == null);
+    }
+
+    /**
+     * Iterates the list removing all the nodes until there are no more nodes to remove. 
+     */
+    public void clear() {
+        while ( removeFirst() != null ) {
+        }
+    }
+
+    /**
+     * @return
+     *     return size of the list as an int
+     */
+    public final int size() {
+        return this.size;
+    }
+
+    /**
+     * Returns a list iterator
+     * @return
+     */
+    public Iterator iterator() {
+        return new Iterator() {
+            private TupleSinkNode currentNode = null;
+            private TupleSinkNode nextNode    = getFirst();
+
+            public boolean hasNext() {
+                return (this.nextNode != null);
+            }
+
+            public Object next() {
+                this.currentNode = this.nextNode;
+                if ( this.currentNode != null ) {
+                    this.nextNode = this.currentNode.getNextTupleSinkNode();
+                } else {
+                    throw new NoSuchElementException( "No more elements to return" );
+                }
+                return this.currentNode;
+            }
+
+            public void remove() {
+                if ( this.currentNode != null ) {
+                    TupleSinkNodeList.this.remove( this.currentNode );
+                    this.currentNode = null;
+                } else {
+                    throw new IllegalStateException( "No item to remove. Call next() before calling remove()." );
+                }
+            }
+        };
+    }
+
+}

Added: 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-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSinkPropagator.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -0,0 +1,43 @@
+package org.drools.reteoo;
+
+import java.util.List;
+import java.util.Map;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.spi.PropagationContext;
+import org.drools.util.LinkedList;
+
+public interface TupleSinkPropagator {
+    public void propagateAssertTuple(ReteTuple tuple,
+                                     InternalFactHandle handle,
+                                     TupleMatch tupleMatch,
+                                     PropagationContext context,
+                                     InternalWorkingMemory workingMemory);
+    
+    public void propagateAssertTuple(ReteTuple tuple,
+                                     PropagationContext context,
+                                     InternalWorkingMemory workingMemory);    
+    
+    public void createAndAssertTuple(InternalFactHandle handle,
+                                     PropagationContext context,
+                                     InternalWorkingMemory workingMemory,
+                                     Map memory);    
+    
+
+    public TupleSink[] getSinks();
+
+    public void propagateNewTupleSink(TupleMatch tupleMatch,
+                                      PropagationContext context,
+                                      InternalWorkingMemory workingMemory);
+    
+    public void propagateNewTupleSink(InternalFactHandle handle,
+                                      LinkedList list,
+                                      PropagationContext context,
+                                      InternalWorkingMemory workingMemory);    
+    
+    public List getPropagatedTuples(final Map memory,
+                                    final InternalWorkingMemory workingMemory,
+                                    final TupleSink sink);
+
+}

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-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TupleSource.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -20,8 +20,10 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.drools.common.BaseNode;
 import org.drools.common.BetaNodeBinder;
 import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalWorkingMemory;
 import org.drools.spi.PropagationContext;
 import org.drools.util.LinkedList;
 import org.drools.util.LinkedListNode;
@@ -48,7 +50,7 @@
     // ------------------------------------------------------------
 
     /** The destination for <code>Tuples</code>. */
-    protected List tupleSinks = new ArrayList( 1 );
+    protected TupleSinkPropagator sink;
 
     // ------------------------------------------------------------
     // Constructors
@@ -75,9 +77,16 @@
      *            The <code>TupleSink</code> to receive propagated
      *            <code>Tuples</code>.
      */
-    protected void addTupleSink(final TupleSink tupleSink) {
-        if ( !this.tupleSinks.contains( tupleSink ) ) {
-            this.tupleSinks.add( tupleSink );
+    protected void addTupleSink(final TupleSink tupleSink) {        
+        if ( this.sink == null ) {
+            this.sink = new SingleTupleSinkAdapter( tupleSink );
+        } else if ( this.sink.getClass() == SingleTupleSinkAdapter.class ) {
+            CompositeTupleSinkAdapter sinkAdapter = ( CompositeTupleSinkAdapter ) new CompositeTupleSinkAdapter();
+            sinkAdapter.addTupleSink( this.sink.getSinks()[0] );
+            sinkAdapter.addTupleSink( tupleSink );
+            this.sink = sinkAdapter;
+        } else {
+            ( (CompositeTupleSinkAdapter) sink ).addTupleSink( tupleSink );
         }
     }
 
@@ -88,168 +97,23 @@
      *            The <code>TupleSink</code> to remove
      */
     protected void removeTupleSink(final TupleSink tupleSink) {
-        this.tupleSinks.remove( tupleSink );
-    }
-
-    protected TupleMatch attemptJoin(final ReteTuple leftTuple,
-                                     final DefaultFactHandle handle,
-                                     final ObjectMatches objectMatches,
-                                     final BetaNodeBinder binder,
-                                     final ReteooWorkingMemory workingMemory) {
-        if ( binder.isAllowed( handle,
-                               leftTuple,
-                               workingMemory ) ) {
-            final TupleMatch tupleMatch = objectMatches.add( leftTuple );
-
-            leftTuple.addTupleMatch( handle,
-                                     tupleMatch );
-            return tupleMatch;
-
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Propagate the assertion of a <code>ReteTuple</code> to this node's
-     * <code>TupleSink</code>.
-     * 
-     * @param tuple
-     *            The <code>ReteTuple</code> to propagate.
-     * @param context
-     *            The <code>PropagationContext</code> of the
-     *            <code>WorkingMemory<code> action            
-     * @param workingMemory
-     *            the <code>WorkingMemory</code> session.
-     */
-
-    protected void propagateAssertTuple(final ReteTuple tuple,
-                                        final TupleMatch tupleMatch,
-                                        final PropagationContext context,
-                                        final ReteooWorkingMemory workingMemory) {
-
-        // we do this one first to avoid an extra clone
-        if ( !getTupleSinks().isEmpty() ) {
-            ((TupleSink) getTupleSinks().get( 0 )).assertTuple( tuple,
-                                                                context,
-                                                                workingMemory );
-
-            tupleMatch.addJoinedTuple( tuple );
-
-            for ( int i = 1, size = getTupleSinks().size(); i < size; i++ ) {
-                final ReteTuple clone = new ReteTuple( tuple );
-                tupleMatch.addJoinedTuple( clone );
-                ((TupleSink) getTupleSinks().get( i )).assertTuple( clone,
-                                                                    context,
-                                                                    workingMemory );
+        if ( this.sink.getClass() == SingleTupleSinkAdapter.class ) {
+            this.sink = null;
+        } else { 
+            CompositeTupleSinkAdapter sinkAdapter = ( CompositeTupleSinkAdapter ) tupleSink;
+            sinkAdapter.removeTupleSink( tupleSink );
+            if ( sinkAdapter.size() == 1 ) {
+                this.sink = new SingleTupleSinkAdapter( sinkAdapter.getSinks()[0] );
             }
-        }
+        } 
     }
 
-    protected void propagateAssertTuple(final ReteTuple tuple,
-                                        final PropagationContext context,
-                                        final ReteooWorkingMemory workingMemory) {
-        for ( int i = 0, size = getTupleSinks().size(); i < size; i++ ) {
-            final ReteTuple child = new ReteTuple( tuple );
-            // no TupleMatch so instead add as a linked tuple
-            tuple.addLinkedTuple( new LinkedListObjectWrapper( child ) );
-            ((TupleSink) getTupleSinks().get( i )).assertTuple( child,
-                                                                context,
-                                                                workingMemory );
-        }
-    }
 
     /**
-     * Propagates a new tuple adding the given fact handle to the tuple 
-     * before propagating.
-     * 
-     * @param tuple The base tuple for propagation
-     * @param handle The handle to add to the tuple when propagating
-     * @param context
-     * @param workingMemory
-     */
-    protected void propagateAssertTuple(final ReteTuple tuple,
-                                        final DefaultFactHandle handle,
-                                        final PropagationContext context,
-                                        final ReteooWorkingMemory workingMemory) {
-        for ( int i = 0, size = getTupleSinks().size(); i < size; i++ ) {
-            final ReteTuple child = new ReteTuple( tuple, handle );
-            // no TupleMatch so instead add as a linked tuple
-            tuple.addLinkedTuple( new LinkedListObjectWrapper( child ) );
-            ((TupleSink) getTupleSinks().get( i )).assertTuple( child,
-                                                                context,
-                                                                workingMemory );
-        }
-    }
-
-    protected void propagateRetractTuple(final TupleMatch tupleMatch,
-                                         final PropagationContext context,
-                                         final ReteooWorkingMemory workingMemory) {
-
-        final List joined = tupleMatch.getJoinedTuples();
-        for ( int i = 0, size = joined.size(); i < size; i++ ) {
-            ((TupleSink) getTupleSinks().get( i )).retractTuple( (ReteTuple) joined.get( i ),
-                                                                 context,
-                                                                 workingMemory );
-        }
-    }
-
-    protected void propagateRetractTuple(final ReteTuple tuple,
-                                         final PropagationContext context,
-                                         final ReteooWorkingMemory workingMemory) {
-        final LinkedList list = tuple.getLinkedTuples();
-        if ( list != null && !list.isEmpty() ) {
-            int i = 0;
-            for ( LinkedListNode node = list.removeFirst(); node != null; node = list.removeFirst() ) {
-                ((TupleSink) getTupleSinks().get( i++ )).retractTuple( (ReteTuple) ((LinkedListObjectWrapper) node).getObject(),
-                                                                       context,
-                                                                       workingMemory );
-            }
-        }
-    }
-
-    protected void propagateModifyTuple(final TupleMatch tupleMatch,
-                                        final PropagationContext context,
-                                        final ReteooWorkingMemory workingMemory) {
-
-        final List joined = tupleMatch.getJoinedTuples();
-        for ( int i = 0, size = joined.size(); i < size; i++ ) {
-            ((TupleSink) getTupleSinks().get( i )).modifyTuple( (ReteTuple) joined.get( i ),
-                                                                context,
-                                                                workingMemory );
-        }
-    }
-
-    protected void propagateModifyTuple(final ReteTuple tuple,
-                                        final PropagationContext context,
-                                        final ReteooWorkingMemory workingMemory) {
-        final LinkedList list = tuple.getLinkedTuples();
-        if ( list != null && !list.isEmpty() ) {
-            int i = 0;
-            for ( LinkedListNode node = list.getFirst(); node != null; node = node.getNext() ) {
-                ((TupleSink) getTupleSinks().get( i++ )).modifyTuple( (ReteTuple) ((LinkedListObjectWrapper) node).getObject(),
-                                                                      context,
-                                                                      workingMemory );
-            }
-        }
-    }
-
-    /**
-     * Retrieve the <code>TupleSinks</code> that receive propagated
-     * <code>Tuples</code>s.
-     * 
-     * @return The <code>TupleSinks</code> that receive propagated
-     *         <code>Tuples</code>.
-     */
-    public List getTupleSinks() {
-        return this.tupleSinks;
-    }
-
-    /**
      * Returns the list of propagated tuples
      * @return
      */
-    public abstract List getPropagatedTuples(ReteooWorkingMemory workingMemory,
+    public abstract List getPropagatedTuples(InternalWorkingMemory workingMemory,
                                              TupleSink sink);
 
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/FunctionResolver.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/FunctionResolver.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/FunctionResolver.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -2,10 +2,17 @@
 
 import java.util.List;
 
+
 public interface FunctionResolver {
     public List getFunctionImports();
 
     public void addFunctionImport(String functionImport);
+    
+    public String resolveFunction(String functionName,
+                                  String params);    
 
-    public String resolveFunction(String functionName, int numberOfArgs);
+    public String resolveFunction(String functionName,
+                                  String params,
+                                  AvailableVariables variables);
+
 }

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/ReteooNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/ReteooNode.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/ReteooNode.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -1,39 +0,0 @@
-package org.drools.spi;
-
-/*
- * 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;
-
-/**
- * Interface used to expose generic information on Rete nodes outside of he package. It is used
- * for exposing information events.
- * 
- * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
- * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
- *
- */
-public interface ReteooNode
-    extends
-    Serializable {
-
-    /**
-     * Returns the unique id that represents the node in the Rete network
-     * @return
-     *      unique int value
-     */
-    public int getId();
-}
\ No newline at end of file

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-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/LinkedList.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -4,6 +4,8 @@
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 
+import org.drools.reteoo.CompositeObjectSinkAdapter.FieldIndex;
+
 /*
  * Copyright 2005 JBoss Inc
  * 
@@ -44,6 +46,8 @@
  *
  */
 public class LinkedList implements Serializable {
+    private static final long serialVersionUID = 320;
+    
     private LinkedListNode firstNode;
     private LinkedListNode lastNode;
 
@@ -162,7 +166,7 @@
         }
         this.size--;
         return node;
-    }
+    }    
 
     /**
      * @return

Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/dataproviders/MethodDataProviderTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/dataproviders/MethodDataProviderTest.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/dataproviders/MethodDataProviderTest.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -71,8 +71,8 @@
                           var2Dec );
 
         List args = new ArrayList();
-        args.add( new LiteralValue( "boo", String.class ) );
-        args.add( new LiteralValue( "42", Integer.class ) );
+        args.add( new LiteralValue( "boo" ) );
+        args.add( new LiteralValue( new Integer( 42 ) ) );
         args.add( new DeclarationVariable( var2Dec ) );
 
         MethodInvoker invoker = new MethodInvoker( "helloWorld",

Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/resolvers/ListValueTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/resolvers/ListValueTest.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/resolvers/ListValueTest.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -31,7 +31,7 @@
         wm.setGlobal( "list",
                       list );        
         
-        LiteralValue literal = new LiteralValue( "literal", String.class );
+        LiteralValue literal = new LiteralValue( "literal" );
         
         Column column = new Column( 0,
                                     new ClassObjectType( Cheese.class ),
@@ -40,8 +40,8 @@
         
         GlobalVariable global = new GlobalVariable( "list", List.class );
         
-        LiteralValue literalKey = new LiteralValue( "literalKey", String.class );
-        LiteralValue literalValue = new LiteralValue( "literalValue", String.class );
+        LiteralValue literalKey = new LiteralValue( "literalKey" );
+        LiteralValue literalValue = new LiteralValue( "literalValue" );
         MapValue.KeyValuePair literalPair = new MapValue.KeyValuePair( literalKey,
                                                                        literalValue );
         MapValue mapValue = new MapValue( new MapValue.KeyValuePair[]{literalPair} );
@@ -74,7 +74,7 @@
         RuleBase rb = RuleBaseFactory.newRuleBase();
         WorkingMemory wm = rb.newWorkingMemory();
         
-        LiteralValue literal = new LiteralValue( "literal", String.class );
+        LiteralValue literal = new LiteralValue( "literal" );
         List nestedListValueHandlers = new ArrayList();
         nestedListValueHandlers.add(  literal );
         ListValue nestedListValue = new ListValue( nestedListValueHandlers );

Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/resolvers/LiteralValueTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/resolvers/LiteralValueTest.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/resolvers/LiteralValueTest.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -18,7 +18,7 @@
         rb.addPackage( pkg );
         WorkingMemory wm = rb.newWorkingMemory();
 
-        LiteralValue literal = new LiteralValue( "literal", String.class );
+        LiteralValue literal = new LiteralValue( "literal" );
 
         Cheese stilton = new Cheese( "stilton",
                                      20 );

Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/resolvers/MapValueTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/resolvers/MapValueTest.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/resolvers/MapValueTest.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -27,8 +27,8 @@
         WorkingMemory wm = rb.newWorkingMemory();
 
         // Make a literal key/value pair
-        LiteralValue literalKey = new LiteralValue( "literalKey1", String.class );
-        LiteralValue literalValue = new LiteralValue( "literalValue", String.class );
+        LiteralValue literalKey = new LiteralValue( "literalKey1" );
+        LiteralValue literalValue = new LiteralValue( "literalValue" );
         MapValue.KeyValuePair literalPair = new MapValue.KeyValuePair( literalKey,
                                                                        literalValue );
 
@@ -41,7 +41,7 @@
                                                                                   literalValue );
 
         // Make a literal/declaration key/value pair
-        LiteralValue literalKey2 = new LiteralValue( "literalKey2", String.class );
+        LiteralValue literalKey2 = new LiteralValue( "literalKey2" );
         MapValue.KeyValuePair literalDeclarationPair = new MapValue.KeyValuePair( literalKey2,
                                                                                   declaration );
 
@@ -51,7 +51,7 @@
                                                                                  declaration );
 
         // Make a literal/global key/value pair
-        LiteralValue literalKey3 = new LiteralValue( "literalKey3", String.class );
+        LiteralValue literalKey3 = new LiteralValue( "literalKey3" );
         MapValue.KeyValuePair LiteralGlobalPair = new MapValue.KeyValuePair( literalKey3,
                                                                              global );
 
@@ -88,13 +88,13 @@
         WorkingMemory wm = rb.newWorkingMemory();
 
         // Make a literal key/value pair
-        LiteralValue literalKey1 = new LiteralValue( "literalKey1", String.class );
-        LiteralValue literalValue1 = new LiteralValue( "literalValue1", String.class );
+        LiteralValue literalKey1 = new LiteralValue( "literalKey1" );
+        LiteralValue literalValue1 = new LiteralValue( "literalValue1" );
         MapValue.KeyValuePair literalPair = new MapValue.KeyValuePair( literalKey1,
                                                                        literalValue1 );
         MapValue nestedMapValue = new MapValue( new MapValue.KeyValuePair[]{literalPair} );
 
-        LiteralValue literalKey2 = new LiteralValue( "literalKey2", String.class );
+        LiteralValue literalKey2 = new LiteralValue( "literalKey2" );
         MapValue.KeyValuePair nestedMapPair = new MapValue.KeyValuePair( literalKey2,
                                                                          nestedMapValue );
 

Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/examples/manners/ReteooMannersTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/examples/manners/ReteooMannersTest.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/examples/manners/ReteooMannersTest.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -55,7 +55,7 @@
         //           
         //        });
 
-        final InputStream is = getClass().getResourceAsStream( "/manners64.dat" );
+        final InputStream is = getClass().getResourceAsStream( "/manners5.dat" );
         final List list = getInputObjects( is );
         for ( final Iterator it = list.iterator(); it.hasNext(); ) {
             final Object object = it.next();

Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/AccumulateNodeTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/AccumulateNodeTest.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/AccumulateNodeTest.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -23,6 +23,8 @@
 import org.drools.RuleBaseFactory;
 import org.drools.base.ClassObjectType;
 import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
 import org.drools.common.PropagationContextImpl;
 import org.drools.rule.Accumulate;
 import org.drools.rule.Column;
@@ -106,7 +108,7 @@
     }
 
     /**
-     * Test method for {@link org.drools.reteoo.AccumulateNode#updateNewNode(org.drools.reteoo.ReteooWorkingMemory, org.drools.spi.PropagationContext)}.
+     * Test method for {@link org.drools.reteoo.AccumulateNode#updateNewNode(InternalWorkingMemory, org.drools.spi.PropagationContext)}.
      */
     public void testUpdateNewNode() {
         this.node.updateNewNode( workingMemory,
@@ -327,7 +329,7 @@
     }
 
     /**
-     * Test method for {@link org.drools.reteoo.AccumulateNode#assertObject(org.drools.common.DefaultFactHandle, org.drools.spi.PropagationContext, org.drools.reteoo.ReteooWorkingMemory)}.
+     * Test method for {@link org.drools.reteoo.AccumulateNode#assertObject(InternalFactHandle, org.drools.spi.PropagationContext, InternalWorkingMemory)}.
      */
     public void testAssertObject() {
         final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory.getFactHandleFactory().newFactHandle( "cheese" );
@@ -372,7 +374,7 @@
     }
 
     /**
-     * Test method for {@link org.drools.reteoo.AccumulateNode#modifyObject(org.drools.common.DefaultFactHandle, org.drools.spi.PropagationContext, org.drools.reteoo.ReteooWorkingMemory)}.
+     * Test method for {@link org.drools.reteoo.AccumulateNode#modifyObject(InternalFactHandle, org.drools.spi.PropagationContext, InternalWorkingMemory)}.
      */
     public void testModifyObject() {
         final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory.getFactHandleFactory().newFactHandle( "cheese" );
@@ -426,7 +428,7 @@
     }
 
     /**
-     * Test method for {@link org.drools.reteoo.AccumulateNode#retractObject(org.drools.common.DefaultFactHandle, org.drools.spi.PropagationContext, org.drools.reteoo.ReteooWorkingMemory)}.
+     * Test method for {@link org.drools.reteoo.AccumulateNode#retractObject(InternalFactHandle, org.drools.spi.PropagationContext, InternalWorkingMemory)}.
      */
     public void testRetractObject() {
         final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory.getFactHandleFactory().newFactHandle( "cheese" );

Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/BaseNodeTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/BaseNodeTest.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/BaseNodeTest.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -18,6 +18,8 @@
 
 import junit.framework.TestCase;
 
+import org.drools.common.BaseNode;
+import org.drools.common.InternalWorkingMemory;
 import org.drools.spi.PropagationContext;
 
 public class BaseNodeTest extends TestCase {
@@ -52,19 +54,19 @@
 
         }
 
-        public void updateNewNode(final ReteooWorkingMemory workingMemory,
+        public void updateNewNode(final InternalWorkingMemory workingMemory,
                                   final PropagationContext context) {
             // TODO Auto-generated method stub
 
         }
 
         public void remove(final BaseNode node,
-                           final ReteooWorkingMemory[] workingMemories) {
+                           final InternalWorkingMemory[] workingMemories) {
             // TODO Auto-generated method stub
 
         }
 
-        public void attach(final ReteooWorkingMemory[] workingMemories) {
+        public void attach(final InternalWorkingMemory[] workingMemories) {
             // TODO Auto-generated method stub
 
         }

Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockObjectSink.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockObjectSink.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockObjectSink.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -19,7 +19,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
 import org.drools.spi.PropagationContext;
 
 public class MockObjectSink
@@ -29,21 +30,21 @@
     private final List retracted = new ArrayList();
     private final List modified  = new ArrayList();
 
-    public void assertObject(final DefaultFactHandle handle,
+    public void assertObject(final InternalFactHandle handle,
                              final PropagationContext context,
-                             final ReteooWorkingMemory workingMemory) {
+                             final InternalWorkingMemory workingMemory) {
         this.asserted.add( new Object[]{handle, context, workingMemory} );
     }
 
-    public void retractObject(final DefaultFactHandle handle,
+    public void retractObject(final InternalFactHandle handle,
                               final PropagationContext context,
-                              final ReteooWorkingMemory workingMemory) {
+                              final InternalWorkingMemory workingMemory) {
         this.retracted.add( new Object[]{handle, context, workingMemory} );
     }
 
-    public void modifyObject(final DefaultFactHandle handle,
+    public void modifyObject(final InternalFactHandle handle,
                              final PropagationContext context,
-                             final ReteooWorkingMemory workingMemory) {
+                             final InternalWorkingMemory workingMemory) {
         this.modified.add( new Object[]{handle, context, workingMemory} );
 
     }

Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockObjectSource.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockObjectSource.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockObjectSource.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -16,6 +16,8 @@
  * limitations under the License.
  */
 
+import org.drools.common.BaseNode;
+import org.drools.common.InternalWorkingMemory;
 import org.drools.spi.PropagationContext;
 
 public class MockObjectSource extends ObjectSource {
@@ -45,18 +47,18 @@
         return this.updated;
     }
 
-    public void updateNewNode(final ReteooWorkingMemory workingMemory,
+    public void updateNewNode(final InternalWorkingMemory workingMemory,
                               final PropagationContext context) {
         this.updated++;
     }
 
     public void remove(final BaseNode node,
-                       final ReteooWorkingMemory[] workingMemories) {
+                       final InternalWorkingMemory[] workingMemories) {
         // TODO Auto-generated method stub
 
     }
 
-    public void attach(final ReteooWorkingMemory[] workingMemories) {
+    public void attach(final InternalWorkingMemory[] workingMemories) {
         // TODO Auto-generated method stub
 
     }

Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockTupleSink.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockTupleSink.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockTupleSink.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -23,6 +23,8 @@
 
 import org.drools.FactException;
 import org.drools.RuleBaseConfiguration;
+import org.drools.common.BaseNode;
+import org.drools.common.InternalWorkingMemory;
 import org.drools.common.NodeMemory;
 import org.drools.spi.PropagationContext;
 
@@ -99,19 +101,19 @@
 
     }
 
-    public void updateNewNode(final ReteooWorkingMemory workingMemory,
+    public void updateNewNode(final InternalWorkingMemory workingMemory,
                               final PropagationContext context) throws FactException {
         // TODO Auto-generated method stub
 
     }
 
     public void remove(final BaseNode node,
-                       final ReteooWorkingMemory[] workingMemories) {
+                       final InternalWorkingMemory[] workingMemories) {
         // TODO Auto-generated method stub
 
     }
 
-    public void attach(final ReteooWorkingMemory[] workingMemories) {
+    public void attach(final InternalWorkingMemory[] workingMemories) {
         // TODO Auto-generated method stub
 
     }

Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockTupleSource.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockTupleSource.java	2006-09-11 15:43:26 UTC (rev 6142)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockTupleSource.java	2006-09-11 15:47:48 UTC (rev 6143)
@@ -19,6 +19,8 @@
 import java.util.Collections;
 import java.util.List;
 
+import org.drools.common.BaseNode;
+import org.drools.common.InternalWorkingMemory;
 import org.drools.spi.PropagationContext;
 
 public class MockTupleSource extends TupleSource {
@@ -48,18 +50,18 @@
         return this.updated;
     }
 
-    public void updateNewNode(final ReteooWorkingMemory workingMemory,
+    public void updateNewNode(final InternalWorkingMemory workingMemory,
                               final PropagationContext context) {
         this.updated++;
     }
 
     public void remove(final BaseNode node,
-                       final ReteooWorkingMemory[] workingMemories) {
+                       final InternalWorkingMemory[] workingMemories) {
         // TODO Auto-generated method stub
 
     }
 
-    public void attach(final ReteooWorkingMemory[] workingMemories) {
+    public void attach(final InternalWorkingMemory[] workingMemories) {
         // TODO Auto-generated method stub
 
     }




More information about the jboss-svn-commits mailing list