[jboss-svn-commits] JBL Code SVN: r5713 - in labs/jbossrules/trunk/drools-core/src: main/java/org/drools/common main/java/org/drools/leaps main/java/org/drools/reteoo main/java/org/drools/rule main/java/org/drools/spi test/java/org/drools/reteoo test/java/org/drools/rule test/java/org/drools/spi

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Thu Aug 10 12:59:25 EDT 2006


Author: mark.proctor at jboss.com
Date: 2006-08-10 12:59:10 -0400 (Thu, 10 Aug 2006)
New Revision: 5713

Added:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/FromNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/From.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/DataProvider.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/FromNodeTest.java
Modified:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/BetaNodeBinder.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InstanceEqualsConstraint.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InstanceNotEqualsConstraint.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/AlphaMemory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/ColumnConstraints.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsWorkingMemory.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/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/ReteooWorkingMemory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TerminalNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/AndCompositeRestriction.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Column.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/LiteralConstraint.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/LiteralRestriction.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/MultiRestrictionFieldConstraint.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/OrCompositeRestriction.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/PredicateConstraint.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/ReturnValueConstraint.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/ReturnValueRestriction.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/VariableConstraint.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/VariableRestriction.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/FieldConstraint.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/PredicateExpression.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/Restriction.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockTupleSource.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/rule/FieldConstraintTest.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/spi/MockConstraint.java
Log:
JBRULES-340 core implementation for 'from'
-The from node is now added
-ReteooBuilder is added, but not unit tested.

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -95,7 +95,7 @@
     protected final AgendaEventSupport        agendaEventSupport                            = new AgendaEventSupport( this );
 
     /** The <code>RuleBase</code> with which this memory is associated. */
-    protected transient InternalRuleBase          ruleBase;
+    protected transient InternalRuleBase      ruleBase;
 
     protected final FactHandleFactory         handleFactory;
 
@@ -156,40 +156,75 @@
     void setRuleBase(InternalRuleBase ruleBase) {
         this.ruleBase = ruleBase;
     }
-    
+
     public void addEventListener(final WorkingMemoryEventListener listener) {
-        this.workingMemoryEventSupport.addEventListener( listener );
+        try {
+            lock.lock();
+            this.workingMemoryEventSupport.addEventListener( listener );
+        } finally {
+            lock.unlock();
+        }
     }
 
     public void removeEventListener(final WorkingMemoryEventListener listener) {
-        this.workingMemoryEventSupport.removeEventListener( listener );
+        try {
+            lock.lock();
+            this.workingMemoryEventSupport.removeEventListener( listener );
+        } finally {
+            lock.unlock();
+        }
     }
 
     public List getWorkingMemoryEventListeners() {
-        return this.workingMemoryEventSupport.getEventListeners();
+        try {
+            lock.lock();
+            return this.workingMemoryEventSupport.getEventListeners();
+        } finally {
+            lock.unlock();
+        }
     }
 
     public void addEventListener(final AgendaEventListener listener) {
-        this.agendaEventSupport.addEventListener( listener );
+        try {
+            lock.lock();
+            this.agendaEventSupport.addEventListener( listener );
+        } finally {
+            lock.unlock();
+        }
     }
 
     public void removeEventListener(final AgendaEventListener listener) {
-        this.agendaEventSupport.removeEventListener( listener );
+        try {
+            lock.lock();
+            this.agendaEventSupport.removeEventListener( listener );
+        } finally {
+            lock.unlock();
+        }
     }
 
+    public List getAgendaEventListeners() {
+        try {
+            lock.lock();
+            return this.agendaEventSupport.getEventListeners();
+        } finally {
+            lock.unlock();
+        }
+    }
+
     public FactHandleFactory getFactHandleFactory() {
         return this.handleFactory;
     }
 
-    public List getAgendaEventListeners() {
-        return this.agendaEventSupport.getEventListeners();
-    }
-
     /**
      * @see WorkingMemory
      */
     public Map getGlobals() {
-        return this.globals;
+        try {
+            lock.lock();
+            return this.globals;
+        } finally {
+            lock.unlock();
+        }
     }
 
     /**
@@ -197,20 +232,25 @@
      */
     public void setGlobal(final String name,
                           final Object value) {
-        // Make sure the global has been declared in the RuleBase
-        final Map globalDefintions = this.ruleBase.getGlobals();
-        final Class type = (Class) globalDefintions.get( name );
-        if ( (type == null) ) {
-            throw new RuntimeException( "Unexpected global [" + name + "]" );
-        } else if ( !type.isInstance( value ) ) {
-            throw new RuntimeException( "Illegal class for global. " + "Expected [" + type.getName() + "], " + "found [" + value.getClass().getName() + "]." );
+        try {
+            lock.lock();
+            // Make sure the global has been declared in the RuleBase
+            final Map globalDefintions = this.ruleBase.getGlobals();
+            final Class type = (Class) globalDefintions.get( name );
+            if ( (type == null) ) {
+                throw new RuntimeException( "Unexpected global [" + name + "]" );
+            } else if ( !type.isInstance( value ) ) {
+                throw new RuntimeException( "Illegal class for global. " + "Expected [" + type.getName() + "], " + "found [" + value.getClass().getName() + "]." );
 
-        } else {
-            this.globals.put( name,
-                              value );
+            } else {
+                this.globals.put( name,
+                                  value );
+            }
+        } finally {
+            lock.unlock();
         }
     }
-    
+
     public long getId() {
         return this.id;
     }
@@ -219,8 +259,13 @@
      * @see WorkingMemory
      */
     public Object getGlobal(final String name) {
-        final Object object = this.globals.get( name );
-        return object;
+        try {
+            lock.lock();
+            final Object object = this.globals.get( name );
+            return object;
+        } finally {
+            lock.unlock();
+        }
     }
 
     /**
@@ -293,28 +338,43 @@
      * 
      */
     public Object getObject(final FactHandle handle) {
-        // you must always take the value from the assertMap, incase the handle
-        // is not from this WorkingMemory
-        InternalFactHandle factHandle = (InternalFactHandle) this.assertMap.get( handle );
-        if ( factHandle != null ) {
-            return factHandle.getObject();
+        try {
+            lock.lock();
+            // you must always take the value from the assertMap, incase the handle
+            // is not from this WorkingMemory
+            InternalFactHandle factHandle = (InternalFactHandle) this.assertMap.get( handle );
+            if ( factHandle != null ) {
+                return factHandle.getObject();
+            }
+
+            return null;
+        } finally {
+            lock.unlock();
         }
 
-        return null;
-
     }
 
     /**
      * @see WorkingMemory
      */
     public FactHandle getFactHandle(final Object object) {
-        final FactHandle factHandle = (FactHandle) this.assertMap.get( object );
+        try {
+            lock.lock();
+            final FactHandle factHandle = (FactHandle) this.assertMap.get( object );
 
-        return factHandle;
+            return factHandle;
+        } finally {
+            lock.unlock();
+        }
     }
 
     public List getFactHandles() {
-        return new ArrayList( this.assertMap.values() );
+        try {
+            lock.lock();
+            return new ArrayList( this.assertMap.values() );
+        } finally {
+            lock.unlock();
+        }
     }
 
     /**
@@ -422,8 +482,8 @@
             return null;
         }
         InternalFactHandle handle = null;
-        this.lock.lock();
         try {
+            this.lock.lock();
             // check if the object already exists in the WM
             handle = (InternalFactHandle) this.assertMap.get( object );
 
@@ -656,8 +716,8 @@
                               final boolean updateEqualsMap,
                               final Rule rule,
                               final Activation activation) throws FactException {
-        this.lock.lock();
         try {
+            this.lock.lock();
             final InternalFactHandle handle = (InternalFactHandle) factHandle;
             if ( handle.getId() == -1 ) {
                 // can't retract an already retracted handle

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/BetaNodeBinder.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/BetaNodeBinder.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/BetaNodeBinder.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -60,7 +60,7 @@
         }
 
         for ( int i = 0; i < this.constraints.length; i++ ) {
-            if ( !this.constraints[i].isAllowed( handle,
+            if ( !this.constraints[i].isAllowed( handle.getObject(),
                                                  tuple,
                                                  workingMemory ) ) {
                 return false;

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InstanceEqualsConstraint.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InstanceEqualsConstraint.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InstanceEqualsConstraint.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -48,10 +48,10 @@
         return this.declarations;
     }
 
-    public boolean isAllowed(final InternalFactHandle handle,
+    public boolean isAllowed(final Object object,
                              final Tuple tuple,
                              final WorkingMemory workingMemory) {
-        return (tuple.get( this.otherColumn ).getObject() == handle.getObject());
+        return (tuple.get( this.otherColumn ).getObject() == object);
     }
 
     public String toString() {

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InstanceNotEqualsConstraint.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InstanceNotEqualsConstraint.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InstanceNotEqualsConstraint.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -41,10 +41,10 @@
         return this.declarations;
     }
 
-    public boolean isAllowed(final InternalFactHandle handle,
+    public boolean isAllowed(final Object object,
                              final Tuple tuple,
                              final WorkingMemory workingMemory) {
-        return !(tuple.get( this.otherColumn ).getObject() == handle.getObject());
+        return !(tuple.get( this.otherColumn ).getObject() == object);
     }
 
     public String toString() {

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/AlphaMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/AlphaMemory.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/AlphaMemory.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -19,7 +19,7 @@
                         final WorkingMemory workingMemory ) {
         Boolean ret = (Boolean) this.alphaChecks.get( factHandle );
         if (ret == null) {
-            ret = new Boolean( alpha.isAllowed( factHandle, tuple, workingMemory ) );
+            ret = new Boolean( alpha.isAllowed( factHandle.getObject(), tuple, workingMemory ) );
             this.alphaChecks.put( factHandle, ret );
         }
 

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/ColumnConstraints.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/ColumnConstraints.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/ColumnConstraints.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -85,7 +85,7 @@
         if ( this.alphaPresent ) {
             for ( int i = 0, length = this.alphaConstraints.length; i < length; i++ ) {
                 // escape immediately if some condition does not match
-                if ( !this.alphaConstraints[i].isAllowed( factHandle,
+                if ( !this.alphaConstraints[i].isAllowed( factHandle.getObject(),
                                                           tuple,
                                                           workingMemory ) ) {
                     return false;

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsWorkingMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsWorkingMemory.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsWorkingMemory.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -71,7 +71,7 @@
     implements
     EventSupport,
     PropertyChangeListener {
-    private static final long serialVersionUID       = -2524904474925421759L;
+    private static final long serialVersionUID       = 320;
 
     private final Map         queryResults;
 
@@ -326,8 +326,8 @@
                              final Object object,
                              final Rule rule,
                              final Activation activation) throws FactException {
-        this.getLock().lock();
         try {
+            this.getLock().lock();
             final PropagationContext propagationContext = new PropagationContextImpl( this.propagationIdCounter++,
                                                                                       PropagationContext.MODIFICATION,
                                                                                       rule,

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-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AlphaNode.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -131,7 +131,7 @@
                              final PropagationContext context,
                              final ReteooWorkingMemory workingMemory) throws FactException {
         final Set memory = (Set) workingMemory.getNodeMemory( this );
-        if ( this.constraint.isAllowed( handle,
+        if ( this.constraint.isAllowed( handle.getObject(),
                                         null,
                                         workingMemory ) ) {
             memory.add( handle );
@@ -157,7 +157,7 @@
                              final ReteooWorkingMemory workingMemory) {
         final Set memory = (Set) workingMemory.getNodeMemory( this );
 
-        if ( this.constraint.isAllowed( handle,
+        if ( this.constraint.isAllowed( handle.getObject(),
                                         null,
                                         workingMemory ) ) {
             if ( memory.add( handle ) ) {

Added: 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-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/FromNode.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -0,0 +1,236 @@
+package org.drools.reteoo;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.RuleBaseConfiguration;
+import org.drools.common.BetaNodeBinder;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.NodeMemory;
+import org.drools.common.PropagationContextImpl;
+import org.drools.rule.Declaration;
+import org.drools.rule.EvalCondition;
+import org.drools.rule.From;
+import org.drools.spi.Constraint;
+import org.drools.spi.DataProvider;
+import org.drools.spi.FieldConstraint;
+import org.drools.spi.PropagationContext;
+
+public class FromNode extends TupleSource
+    implements
+    TupleSink,
+    NodeMemory {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 320;
+
+    private DataProvider      dataProvider;
+    private TupleSource       tupleSource;
+    private FieldConstraint[] constraints;
+    private BetaNodeBinder    binder;
+
+    public FromNode(final int id,
+                    final DataProvider dataProvider,    
+                    final TupleSource tupleSource,
+                    final FieldConstraint[] constraints,
+                    final BetaNodeBinder binder) {
+        super( id );
+        this.dataProvider = dataProvider;
+        this.tupleSource = tupleSource;
+        this.constraints = constraints;
+        if ( binder == null ) {
+            this.binder = new BetaNodeBinder();
+        } else {
+            this.binder = binder;
+        }
+    }
+
+    /**
+     * This method isn't as efficient as it could be, as its using the standard join node mechanisms - so everything is bidirectionally
+     * linked. As FactHandle's are never retracted, this relationship does not need to be maintined - but as this optimisation would 
+     * need refactoring, I've used the standard join node mechanism for now. 
+     * 
+     */
+    public void assertTuple(ReteTuple leftTuple,
+                            PropagationContext context,
+                            ReteooWorkingMemory workingMemory) {
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+
+        memory.add( workingMemory,
+                    leftTuple );
+
+        for ( Iterator it = this.dataProvider.getResults( leftTuple ); it.hasNext(); ) {
+            Object object = it.next();
+            
+            // First alpha node filters
+            boolean isAllowed = true;
+            for ( int i = 0, length = this.constraints.length; i < length; i++ ) {
+                if ( !this.constraints[i].isAllowed( object, leftTuple, workingMemory ) ) {
+                    isAllowed = false;
+                    break;
+                }
+            }
+            
+            if ( !isAllowed ) {
+                continue;
+            }
+            
+            final InternalFactHandle handle = workingMemory.getFactHandleFactory().newFactHandle( object );
+            final ObjectMatches objectMatches = new ObjectMatches( (DefaultFactHandle) handle );
+
+            if ( binder.isAllowed( handle,
+                                   leftTuple,
+                                   workingMemory ) ) {
+                final TupleMatch tupleMatch = new TupleMatch( leftTuple,
+                                                              objectMatches );
+
+                leftTuple.addTupleMatch( (DefaultFactHandle) handle,
+                                         tupleMatch );
+
+                propagateAssertTuple( new ReteTuple( leftTuple,
+                                                     (DefaultFactHandle) handle ),
+                                      tupleMatch,
+                                      context,
+                                      workingMemory );
+            }
+        }
+    }
+
+    /**
+     * This could be made more intelligent by finding out if the modified Fact is depended upon by the requiredDeclarations.
+     * If it isn't then we can continue to just propagate as a normal modify, without having to retrieve and check values 
+     * from the DataProvider.
+     */
+    public void modifyTuple(ReteTuple leftTuple,
+                            PropagationContext context,
+                            ReteooWorkingMemory workingMemory) {
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+
+        // We remove the tuple as now its modified it needs to go to the top of
+        // the stack, which is added back in else where
+        memory.remove( workingMemory,
+                       leftTuple );
+
+        final Map matches = leftTuple.getTupleMatches();
+
+        if ( matches.isEmpty() ) {
+            // No child propagations, so try as a new assert, will ensure the
+            // tuple is added to the top of the memory
+            assertTuple( leftTuple,
+                         context,
+                         workingMemory );
+        } else {
+            // first purge the network of all future uses of the 'from' facts           
+            for ( final Iterator it = matches.values().iterator(); it.hasNext(); ) {
+                final TupleMatch tupleMatch = (TupleMatch) it.next();
+                workingMemory.getFactHandleFactory().destroyFactHandle( tupleMatch.getObjectMatches().getFactHandle() );
+                propagateRetractTuple( tupleMatch,
+                                       context,
+                                       workingMemory );
+            }      
+            
+            // now all existing matches must now be cleared and the DataProvider re-processed.
+            leftTuple.clearTupleMatches();
+            
+            assertTuple( leftTuple,
+                         context,
+                         workingMemory );            
+            
+        }
+    }
+
+    public void retractTuple(ReteTuple leftTuple,
+                             PropagationContext context,
+                             ReteooWorkingMemory workingMemory) {
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+        memory.remove( workingMemory,
+                       leftTuple );
+        
+        final Map matches = leftTuple.getTupleMatches();
+
+        if ( !matches.isEmpty() ) {
+            for ( final Iterator it = matches.values().iterator(); it.hasNext(); ) {
+                final TupleMatch tupleMatch = (TupleMatch) it.next();
+                workingMemory.getFactHandleFactory().destroyFactHandle( tupleMatch.getObjectMatches().getFactHandle() );
+                propagateRetractTuple( tupleMatch,
+                                       context,
+                                       workingMemory );
+            }
+        }
+    }
+
+    public List getPropagatedTuples(ReteooWorkingMemory workingMemory,
+                                    TupleSink sink) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public void attach() {
+        this.tupleSource.addTupleSink( this );
+    }
+
+    public void attach(ReteooWorkingMemory[] workingMemories) {
+        attach();
+
+        for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
+            final ReteooWorkingMemory workingMemory = workingMemories[i];
+            final PropagationContext propagationContext = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(),
+                                                                                      PropagationContext.RULE_ADDITION,
+                                                                                      null,
+                                                                                      null );
+            this.tupleSource.updateNewNode( workingMemory,
+                                            propagationContext );
+        }
+    }
+
+    public void remove(BaseNode node,
+                       ReteooWorkingMemory[] workingMemories) {
+        getTupleSinks().remove( node );
+        removeShare();
+
+        if ( this.sharedCount < 0 ) {
+            for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
+                workingMemories[i].clearNodeMemory( this );
+            }
+            this.tupleSource.remove( this,
+                                     workingMemories );
+        }
+    }
+
+    public void updateNewNode(ReteooWorkingMemory workingMemory,
+                              PropagationContext context) {
+        this.attachingNewNode = true;
+
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+
+        // @todo:as there is no right memory
+
+        //        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" );
+        //                }
+        //            }
+        //        }
+
+        this.attachingNewNode = false;
+    }
+
+    public Object createMemory(RuleBaseConfiguration config) {
+        return new BetaMemory( config,
+                               this.binder );
+    }
+}

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-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteTuple.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -203,6 +203,10 @@
         this.linkedTuples.clear();
     }
 
+    public void clearTupleMatches() {
+        this.matches.clear();
+    }    
+    
     public void addTupleMatch(final DefaultFactHandle handle,
                               final TupleMatch node) {
         if ( this.matches == Collections.EMPTY_MAP ) {

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-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooBuilder.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -41,6 +41,7 @@
 import org.drools.rule.Declaration;
 import org.drools.rule.EvalCondition;
 import org.drools.rule.Exists;
+import org.drools.rule.From;
 import org.drools.rule.GroupElement;
 import org.drools.rule.InvalidPatternException;
 import org.drools.rule.LiteralConstraint;
@@ -555,7 +556,64 @@
 
         return node;
     }
+    
+    private void attachFrom(final TupleSource tupleSource,
+                            final From from) {
+        Column column = from.getColumn();
+        
+        // Adjusting offset in case a previous Initial-Fact was added to the network
+        column.adjustOffset( this.currentOffsetAdjustment );
+        
+        final List constraints = column.getConstraints();
 
+        // Check if the Column is bound
+        if ( column.getDeclaration() != null ) {
+            final Declaration declaration = column.getDeclaration();
+            // Add the declaration the map of previously bound declarations
+            this.declarations.put( declaration.getIdentifier(),
+                                   declaration );
+        }
+
+        final List predicateConstraints = new ArrayList();
+        final List alphaNodeConstraints = new ArrayList();
+        
+        for ( final Iterator it = constraints.iterator(); it.hasNext(); ) {
+            final Object object = it.next();
+            // Check if its a declaration
+            if ( object instanceof Declaration ) {
+                final Declaration declaration = (Declaration) object;
+                // Add the declaration the map of previously bound declarations
+                this.declarations.put( declaration.getIdentifier(),
+                                       declaration );
+                continue;
+            }
+
+            final FieldConstraint fieldConstraint = (FieldConstraint) object;
+            if ( fieldConstraint instanceof LiteralConstraint ) {
+                alphaNodeConstraints.add( fieldConstraint );
+            } else {
+                checkUnboundDeclarations( fieldConstraint.getRequiredDeclarations() );
+                predicateConstraints.add( fieldConstraint );
+            }
+        }
+        
+        
+        BetaNodeBinder binder;
+
+        if ( !predicateConstraints.isEmpty() ) {
+            binder = new BetaNodeBinder( (FieldConstraint[]) predicateConstraints.toArray( new FieldConstraint[predicateConstraints.size()] ) );
+        } else {
+            binder = new BetaNodeBinder();
+        }
+        
+        FromNode node = new FromNode( id, 
+                                      from.getDataProvider(),
+                                      this.tupleSource,
+                                      ( FieldConstraint[] ) alphaNodeConstraints.toArray( new FieldConstraint[ alphaNodeConstraints.size() ] ),
+                                      binder );        
+                
+    }    
+
     private ObjectSource attachNode(final ObjectSource candidate) {
         ObjectSource node = (ObjectSource) this.attachedNodes.get( candidate );
 

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooWorkingMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooWorkingMemory.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooWorkingMemory.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -48,7 +48,7 @@
     /**
      * 
      */
-    private static final long serialVersionUID = -5107074490638575715L;
+    private static final long serialVersionUID = 320;
 
     /**
      * Construct.
@@ -87,8 +87,8 @@
                              final Object object,
                              final Rule rule,
                              final Activation activation) throws FactException {
-        this.lock.lock();
         try {
+            this.lock.lock();
             final int status = ((InternalFactHandle) factHandle).getEqualityKey().getStatus();
             final InternalFactHandle handle = (InternalFactHandle) factHandle;
             final Object originalObject = handle.getObject();

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-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/TerminalNode.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -52,7 +52,7 @@
     /**
      * 
      */
-    private static final long serialVersionUID = -4172639826881353001L;
+    private static final long serialVersionUID = 320;
     /** The rule to invoke upon match. */
     private final Rule        rule;
     private final TupleSource tupleSource;

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/AndCompositeRestriction.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/AndCompositeRestriction.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/AndCompositeRestriction.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -4,7 +4,6 @@
 import java.util.Set;
 
 import org.drools.WorkingMemory;
-import org.drools.common.InternalFactHandle;
 import org.drools.spi.Restriction;
 import org.drools.spi.Tuple;
 
@@ -17,13 +16,11 @@
     }
 
     public boolean isAllowed(final Object object,
-                             final InternalFactHandle handle,
                              final Tuple tuple,
                              final WorkingMemory workingMemory) {
 
         for ( int i = 0, ilength = this.restrictions.length; i < ilength; i++ ) {
             if ( !restrictions[i].isAllowed( object,
-                                             handle,
                                              tuple,
                                              workingMemory ) ) {
                 return false;

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Column.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Column.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Column.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -33,7 +33,7 @@
     /**
      * 
      */
-    private static final long serialVersionUID = 9167552040211010022L;
+    private static final long serialVersionUID = 320;
     private final ObjectType  objectType;
     private List              constraints      = Collections.EMPTY_LIST;
     final Declaration         declaration;

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/From.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/From.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/From.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -0,0 +1,25 @@
+package org.drools.rule;
+
+import java.io.Serializable;
+
+import org.drools.spi.DataProvider;
+
+public class From implements Serializable{
+    private Column column;   
+    
+    private DataProvider dataProvider;
+    
+    public From(final Column column,
+                final DataProvider dataProvider) {
+        this.column = column;
+        this.dataProvider = dataProvider;
+    }
+
+    public Column getColumn() {
+        return column;
+    }
+
+    public DataProvider getDataProvider() {
+        return dataProvider;
+    }    
+}

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/LiteralConstraint.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/LiteralConstraint.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/LiteralConstraint.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -17,7 +17,6 @@
  */
 
 import org.drools.WorkingMemory;
-import org.drools.common.InternalFactHandle;
 import org.drools.spi.Evaluator;
 import org.drools.spi.FieldConstraint;
 import org.drools.spi.FieldExtractor;
@@ -71,10 +70,10 @@
         return this.restriction.getRequiredDeclarations();
     }
 
-    public boolean isAllowed(final InternalFactHandle handle,
+    public boolean isAllowed(final Object object,
                              final Tuple tuple,
                              final WorkingMemory workingMemory) {
-        return this.restriction.isAllowed( this.extractor.getValue( handle.getObject() ), handle, tuple, workingMemory );
+        return this.restriction.isAllowed( this.extractor.getValue( object ), tuple, workingMemory );
     }
 
     public String toString() {

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/LiteralRestriction.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/LiteralRestriction.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/LiteralRestriction.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -17,7 +17,6 @@
  */
 
 import org.drools.WorkingMemory;
-import org.drools.common.InternalFactHandle;
 import org.drools.spi.Evaluator;
 import org.drools.spi.FieldConstraint;
 import org.drools.spi.FieldExtractor;
@@ -64,7 +63,6 @@
     }
 
     public boolean isAllowed(final Object object,
-                             final InternalFactHandle handle,
                              final Tuple tuple,
                              final WorkingMemory workingMemory) {
         return this.evaluator.evaluate( object,

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/MultiRestrictionFieldConstraint.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/MultiRestrictionFieldConstraint.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/MultiRestrictionFieldConstraint.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -4,7 +4,6 @@
 import java.util.Set;
 
 import org.drools.WorkingMemory;
-import org.drools.common.InternalFactHandle;
 import org.drools.spi.Evaluator;
 import org.drools.spi.Extractor;
 import org.drools.spi.FieldConstraint;
@@ -40,11 +39,10 @@
         return this.restrictions.getRequiredDeclarations();
     }
 
-    public boolean isAllowed(final InternalFactHandle handle,
+    public boolean isAllowed(final Object object,
                              final Tuple tuple,
                              final WorkingMemory workingMemory) {
-        return this.restrictions.isAllowed( this.extractor.getValue( handle.getObject() ),
-                                            handle,
+        return this.restrictions.isAllowed( this.extractor.getValue( object ),
                                             tuple,
                                             workingMemory );
     }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/OrCompositeRestriction.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/OrCompositeRestriction.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/OrCompositeRestriction.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -5,7 +5,6 @@
 import java.util.Set;
 
 import org.drools.WorkingMemory;
-import org.drools.common.InternalFactHandle;
 import org.drools.spi.Restriction;
 import org.drools.spi.Tuple;
 
@@ -18,13 +17,11 @@
     }
 
     public boolean isAllowed(final Object object,
-                             final InternalFactHandle handle,
                              final Tuple tuple,
                              final WorkingMemory workingMemory) {
 
         for ( int i = 0, ilength = this.restrictions.length; i < ilength; i++ ) {
             if ( restrictions[i].isAllowed( object,
-                                            handle,
                                             tuple,
                                             workingMemory ) ) {
                 return true;

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/PredicateConstraint.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/PredicateConstraint.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/PredicateConstraint.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -18,7 +18,6 @@
 
 import org.drools.RuntimeDroolsException;
 import org.drools.WorkingMemory;
-import org.drools.common.InternalFactHandle;
 import org.drools.spi.FieldConstraint;
 import org.drools.spi.PredicateExpression;
 import org.drools.spi.Tuple;
@@ -85,12 +84,12 @@
         return "[PredicateConstraint declarations=" + this.requiredDeclarations  + "]";
     }    
     
-    public boolean isAllowed(final InternalFactHandle handle,
+    public boolean isAllowed(final Object object,
                              final Tuple tuple,
                              final WorkingMemory workingMemory) {
         try {
-            return this.expression.evaluate( tuple,
-                                             handle,
+            return this.expression.evaluate( object,
+                                             tuple,
                                              this.declaration,
                                              this.requiredDeclarations,
                                              workingMemory );

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/ReturnValueConstraint.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/ReturnValueConstraint.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/ReturnValueConstraint.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -18,7 +18,6 @@
 
 import org.drools.RuntimeDroolsException;
 import org.drools.WorkingMemory;
-import org.drools.common.InternalFactHandle;
 import org.drools.spi.Evaluator;
 import org.drools.spi.FieldConstraint;
 import org.drools.spi.FieldExtractor;
@@ -77,11 +76,10 @@
         return this.restriction.getEvaluator();
     }
 
-    public boolean isAllowed(final InternalFactHandle handle,
+    public boolean isAllowed(final Object object,
                              final Tuple tuple,
                              final WorkingMemory workingMemory) {
-        return this.restriction.isAllowed( this.fieldExtractor.getValue( handle.getObject() ),
-                                           handle,
+        return this.restriction.isAllowed( this.fieldExtractor.getValue( object ),
                                            tuple,
                                            workingMemory );
     }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/ReturnValueRestriction.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/ReturnValueRestriction.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/ReturnValueRestriction.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -20,7 +20,6 @@
 
 import org.drools.RuntimeDroolsException;
 import org.drools.WorkingMemory;
-import org.drools.common.InternalFactHandle;
 import org.drools.spi.Evaluator;
 import org.drools.spi.FieldConstraint;
 import org.drools.spi.FieldExtractor;
@@ -93,7 +92,6 @@
     }
 
     public boolean isAllowed(final Object object,
-                             final InternalFactHandle handle,
                              final Tuple tuple,
                              final WorkingMemory workingMemory) {
         try {

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/VariableConstraint.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/VariableConstraint.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/VariableConstraint.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -17,7 +17,6 @@
  */
 
 import org.drools.WorkingMemory;
-import org.drools.common.InternalFactHandle;
 import org.drools.spi.Evaluator;
 import org.drools.spi.FieldConstraint;
 import org.drools.spi.FieldExtractor;
@@ -61,11 +60,10 @@
         return this.restriction.getEvaluator();
     }
 
-    public boolean isAllowed(final InternalFactHandle handle,
+    public boolean isAllowed(final Object object,
                              final Tuple tuple,
                              final WorkingMemory workingMemory) {
-        return this.restriction.isAllowed( this.fieldExtractor.getValue( handle.getObject() ),
-                                           handle,
+        return this.restriction.isAllowed( this.fieldExtractor.getValue( object ),
                                            tuple,
                                            workingMemory );
     }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/VariableRestriction.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/VariableRestriction.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/VariableRestriction.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -19,7 +19,6 @@
 import java.util.Arrays;
 
 import org.drools.WorkingMemory;
-import org.drools.common.InternalFactHandle;
 import org.drools.spi.Evaluator;
 import org.drools.spi.FieldConstraint;
 import org.drools.spi.FieldExtractor;
@@ -57,7 +56,6 @@
     }
 
     public boolean isAllowed(final Object object,
-                             final InternalFactHandle handle,
                              final Tuple tuple,
                              final WorkingMemory workingMemory) {
         return this.evaluator.evaluate( object,

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/DataProvider.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/DataProvider.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/DataProvider.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -0,0 +1,13 @@
+package org.drools.spi;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.drools.rule.Declaration;
+
+public interface DataProvider {
+    
+    public Declaration[] getRequiredDeclarations();
+    
+   public Iterator getResults(Tuple tuple); 
+}

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/FieldConstraint.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/FieldConstraint.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/FieldConstraint.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -17,13 +17,12 @@
  */
 
 import org.drools.WorkingMemory;
-import org.drools.common.InternalFactHandle;
 import org.drools.rule.Declaration;
 
 public interface FieldConstraint
     extends
     Constraint {
-    public boolean isAllowed(InternalFactHandle handle,
+    public boolean isAllowed(Object object,
                              Tuple tuple,
                              WorkingMemory workingMemory);
 

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/PredicateExpression.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/PredicateExpression.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/PredicateExpression.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -23,8 +23,8 @@
 public interface PredicateExpression
     extends
     Invoker {
-    public boolean evaluate(Tuple tuple,
-                            FactHandle factHandle,
+    public boolean evaluate(Object object,
+                            Tuple tuple,
                             Declaration declaration,
                             Declaration[] requiredDeclarations,
                             WorkingMemory workingMemory) throws Exception;

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/Restriction.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/Restriction.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/Restriction.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -3,14 +3,12 @@
 import java.io.Serializable;
 
 import org.drools.WorkingMemory;
-import org.drools.common.InternalFactHandle;
 import org.drools.rule.Declaration;
 
 public interface Restriction extends Serializable {
     Declaration[] getRequiredDeclarations();
     
     public boolean isAllowed(Object object,
-                             InternalFactHandle handle,
                              Tuple tuple,
                              WorkingMemory workingMemory);
 }

Added: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/FromNodeTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/FromNodeTest.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/FromNodeTest.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -0,0 +1,423 @@
+package org.drools.reteoo;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+import org.drools.Cheese;
+import org.drools.FactHandle;
+import org.drools.RuleBaseFactory;
+import org.drools.base.ClassFieldExtractor;
+import org.drools.base.ClassObjectType;
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.Operator;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.PropagationContextImpl;
+import org.drools.rule.Column;
+import org.drools.rule.Declaration;
+import org.drools.rule.From;
+import org.drools.rule.LiteralConstraint;
+import org.drools.rule.VariableConstraint;
+import org.drools.spi.DataProvider;
+import org.drools.spi.Evaluator;
+import org.drools.spi.FieldConstraint;
+import org.drools.spi.FieldValue;
+import org.drools.spi.MockField;
+import org.drools.spi.PropagationContext;
+import org.drools.spi.Tuple;
+
+import junit.framework.TestCase;
+
+public class FromNodeTest extends TestCase {
+
+    public void testAlphaNode() {
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+        final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory( 1,
+                                                                           (ReteooRuleBase) RuleBaseFactory.newRuleBase() );
+        final ClassFieldExtractor extractor = new ClassFieldExtractor( Cheese.class,
+                                                                       "type" );
+
+        final FieldValue field = new MockField( "stilton" );
+        final LiteralConstraint constraint = new LiteralConstraint( extractor,
+                                                                    ValueType.STRING_TYPE.getEvaluator( Operator.EQUAL ),
+                                                                    field );
+
+        List list = new ArrayList();
+        Cheese cheese1 = new Cheese( "cheddar",
+                                     20 );
+        Cheese cheese2 = new Cheese( "brie",
+                                     20 );
+        list.add( cheese1 );
+        list.add( cheese2 );
+        MockDataProvider dataProvider = new MockDataProvider( list );
+
+        FromNode from = new FromNode( 3,
+                                      dataProvider,
+                                      null,
+                                      new FieldConstraint[]{constraint},
+                                      null );
+        MockTupleSink sink = new MockTupleSink( 5 );
+        from.addTupleSink( sink );
+
+        Person person1 = new Person( "xxx1",
+                                     30 );
+        FactHandle person1Handle = workingMemory.assertObject( person1 );
+        ReteTuple tuple1 = new ReteTuple( (DefaultFactHandle) person1Handle );
+        from.assertTuple( tuple1,
+                          context,
+                          workingMemory );
+
+        // nothing should be asserted, as cheese1 is cheddar and we are filtering on stilton
+        assertEquals( 0,
+                      sink.getAsserted().size() );
+
+        //Set cheese1 to stilton and it should now propagate
+        cheese1.setType( "stilton" );
+        Person person2 = new Person( "xxx2",
+                                     30 );
+        FactHandle person2Handle = workingMemory.assertObject( person2 );
+        ReteTuple tuple2 = new ReteTuple( (DefaultFactHandle) person2Handle );
+        from.assertTuple( tuple2,
+                          context,
+                          workingMemory );
+
+        List asserted = sink.getAsserted();
+        assertEquals( 1,
+                      asserted.size() );
+        ReteTuple tuple = (ReteTuple) ((Object[]) asserted.get( 0 ))[0];
+        assertSame( person2,
+                    tuple.getFactHandles()[0].getObject() );
+        assertSame( cheese1,
+                    tuple.getFactHandles()[1].getObject() );
+
+        cheese2.setType( "stilton" );
+        Person person3 = new Person( "xxx2",
+                                     30 );
+        FactHandle person3Handle = workingMemory.assertObject( person3 );
+        ReteTuple tuple3 = new ReteTuple( (DefaultFactHandle) person3Handle );
+        from.assertTuple( tuple3,
+                          context,
+                          workingMemory );
+
+        assertEquals( 3,
+                      asserted.size() );
+        tuple = (ReteTuple) ((Object[]) asserted.get( 1 ))[0];
+        assertSame( person3,
+                    tuple.getFactHandles()[0].getObject() );
+        assertSame( cheese1,
+                    tuple.getFactHandles()[1].getObject() );
+        tuple = (ReteTuple) ((Object[]) asserted.get( 2 ))[0];
+        assertSame( person3,
+                    tuple.getFactHandles()[0].getObject() );
+        assertSame( cheese2,
+                    tuple.getFactHandles()[1].getObject() );
+
+        assertNotSame( cheese1,
+                       cheese2 );
+    }
+
+    public void testBetaNode() {
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+
+        final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory( 1,
+                                                                           (ReteooRuleBase) RuleBaseFactory.newRuleBase() );
+
+        final ClassFieldExtractor priceExtractor = new ClassFieldExtractor( Cheese.class,
+                                                                            "price" );
+
+        final ClassFieldExtractor ageExtractor = new ClassFieldExtractor( Person.class,
+                                                                          "age" );
+
+        Declaration declaration = new Declaration( "age",
+                                                   ageExtractor,
+                                                   0 );
+
+        VariableConstraint variableConstraint = new VariableConstraint( priceExtractor,
+                                                                        declaration,
+                                                                        ValueType.INTEGER_TYPE.getEvaluator( Operator.EQUAL ) );
+
+        List list = new ArrayList();
+        Cheese cheese1 = new Cheese( "cheddar",
+                                     18 );
+        Cheese cheese2 = new Cheese( "brie",
+                                     12 );
+        list.add( cheese1 );
+        list.add( cheese2 );
+        MockDataProvider dataProvider = new MockDataProvider( list );
+
+        FromNode from = new FromNode( 3,
+                                      dataProvider,
+                                      null,
+                                      new FieldConstraint[]{variableConstraint},
+                                      null );
+        MockTupleSink sink = new MockTupleSink( 5 );
+        from.addTupleSink( sink );
+
+        Person person1 = new Person( "xxx1",
+                                     30 );
+        FactHandle person1Handle = workingMemory.assertObject( person1 );
+        ReteTuple tuple1 = new ReteTuple( (DefaultFactHandle) person1Handle );
+        from.assertTuple( tuple1,
+                          context,
+                          workingMemory );
+
+        // nothing should be asserted, as cheese1 is cheddar and we are filtering on stilton
+        assertEquals( 0,
+                      sink.getAsserted().size() );
+
+        //Set cheese1 to stilton and it should now propagate
+        cheese1.setPrice( 30 );
+        Person person2 = new Person( "xxx2",
+                                     30 );
+        FactHandle person2Handle = workingMemory.assertObject( person2 );
+        ReteTuple tuple2 = new ReteTuple( (DefaultFactHandle) person2Handle );
+        from.assertTuple( tuple2,
+                          context,
+                          workingMemory );
+
+        List asserted = sink.getAsserted();
+        assertEquals( 1,
+                      asserted.size() );
+        ReteTuple tuple = (ReteTuple) ((Object[]) asserted.get( 0 ))[0];
+        assertSame( person2,
+                    tuple.getFactHandles()[0].getObject() );
+        assertSame( cheese1,
+                    tuple.getFactHandles()[1].getObject() );
+
+        cheese2.setPrice( 30 );
+        Person person3 = new Person( "xxx2",
+                                     30 );
+        FactHandle person3Handle = workingMemory.assertObject( person3 );
+        ReteTuple tuple3 = new ReteTuple( (DefaultFactHandle) person3Handle );
+        from.assertTuple( tuple3,
+                          context,
+                          workingMemory );
+
+        assertEquals( 3,
+                      asserted.size() );
+        tuple = (ReteTuple) ((Object[]) asserted.get( 1 ))[0];
+        assertSame( person3,
+                    tuple.getFactHandles()[0].getObject() );
+        assertSame( cheese1,
+                    tuple.getFactHandles()[1].getObject() );
+        tuple = (ReteTuple) ((Object[]) asserted.get( 2 ))[0];
+        assertSame( person3,
+                    tuple.getFactHandles()[0].getObject() );
+        assertSame( cheese2,
+                    tuple.getFactHandles()[1].getObject() );
+
+        assertNotSame( cheese1,
+                       cheese2 );
+    }
+
+    public void testRestract() {
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+        final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory( 1,
+                                                                           (ReteooRuleBase) RuleBaseFactory.newRuleBase() );
+        final ClassFieldExtractor extractor = new ClassFieldExtractor( Cheese.class,
+                                                                       "type" );
+
+        final FieldValue field = new MockField( "stilton" );
+        final LiteralConstraint constraint = new LiteralConstraint( extractor,
+                                                                    ValueType.STRING_TYPE.getEvaluator( Operator.EQUAL ),
+                                                                    field );
+
+        List list = new ArrayList();
+        Cheese cheese1 = new Cheese( "stilton",
+                                     5 );
+        Cheese cheese2 = new Cheese( "stilton",
+                                     15 );
+        list.add( cheese1 );
+        list.add( cheese2 );
+        MockDataProvider dataProvider = new MockDataProvider( list );
+
+        FromNode from = new FromNode( 3,
+                                      dataProvider,
+                                      null,
+                                      new FieldConstraint[]{constraint},
+                                      null );
+        MockTupleSink sink = new MockTupleSink( 5 );
+        from.addTupleSink( sink );
+
+        List asserted = sink.getAsserted();
+
+        Person person1 = new Person( "xxx2",
+                                     30 );
+        FactHandle person1Handle = workingMemory.assertObject( person1 );
+        ReteTuple tuple = new ReteTuple( (DefaultFactHandle) person1Handle );
+        from.assertTuple( tuple,
+                          context,
+                          workingMemory );
+
+        assertEquals( 2,
+                      asserted.size() );
+
+        BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( from );
+        assertEquals( 1,
+                      memory.getLeftTupleMemory().size() );
+        assertEquals( 0,
+                      memory.getRightObjectMemory().size() );
+        assertEquals( 2,
+                      tuple.getTupleMatches().size() );
+
+        list = new ArrayList();
+        for ( Iterator it = tuple.getTupleMatches().values().iterator(); it.hasNext(); ) {
+            TupleMatch tupleMatch = (TupleMatch) it.next();
+            list.add( tupleMatch.getObjectMatches().getFactHandle().getObject() );
+        }
+        assertEquals( 2,
+                      list.size() );
+        assertTrue( list.contains( cheese1 ) );
+        assertTrue( list.contains( cheese2 ) );
+
+        from.retractTuple( tuple,
+                           context,
+                           workingMemory );
+        assertEquals( 0,
+                      memory.getLeftTupleMemory().size() );
+        assertEquals( 0,
+                      memory.getRightObjectMemory().size() );
+    }
+
+    public void testModify() {
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       null,
+                                                                       null );
+        final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory( 1,
+                                                                           (ReteooRuleBase) RuleBaseFactory.newRuleBase() );
+        final ClassFieldExtractor extractor = new ClassFieldExtractor( Cheese.class,
+                                                                       "type" );
+
+        final FieldValue field = new MockField( "stilton" );
+        final LiteralConstraint constraint = new LiteralConstraint( extractor,
+                                                                    ValueType.STRING_TYPE.getEvaluator( Operator.EQUAL ),
+                                                                    field );
+
+        List list = new ArrayList();
+        Cheese cheese1 = new Cheese( "cheddar",
+                                     20 );
+        Cheese cheese2 = new Cheese( "brie",
+                                     20 );
+        list.add( cheese1 );
+        list.add( cheese2 );
+        MockDataProvider dataProvider = new MockDataProvider( list );
+
+        FromNode from = new FromNode( 3,
+                                      dataProvider,
+                                      null,
+                                      new FieldConstraint[]{constraint},
+                                      null );
+        MockTupleSink sink = new MockTupleSink( 5 );
+        from.addTupleSink( sink );
+
+        Person person1 = new Person( "xxx1",
+                                     30 );
+        FactHandle person1Handle = workingMemory.assertObject( person1 );
+        ReteTuple tuple1 = new ReteTuple( (DefaultFactHandle) person1Handle );
+        from.assertTuple( tuple1,
+                          context,
+                          workingMemory );
+
+        // nothing should be asserted, as cheese1 is cheddar and we are filtering on stilton
+        assertEquals( 0,
+                      sink.getAsserted().size() );
+
+        //Set cheese1 to stilton and it should now propagate
+        cheese1.setType( "stilton" );
+        from.modifyTuple( tuple1,
+                          context,
+                          workingMemory );
+        List asserted = sink.getAsserted();
+        assertEquals( 1,
+                      asserted.size() );
+        ReteTuple tuple = (ReteTuple) ((Object[]) asserted.get( 0 ))[0];
+        assertSame( person1,
+                    tuple.getFactHandles()[0].getObject() );
+        assertSame( cheese1,
+                    tuple.getFactHandles()[1].getObject() );
+        
+        cheese2.setType( "stilton" );           
+        from.modifyTuple( tuple1,
+                          context,
+                          workingMemory );        
+
+        // A modify when using from involves a retract and an assert - so make sure there was a retraction and no modify propagations
+        assertEquals( 0 , sink.getModified().size() );
+        assertEquals( 1, sink.getRetracted().size() );
+        
+        assertEquals( 3,
+                      asserted.size() );
+        tuple = (ReteTuple) ((Object[]) asserted.get( 1 ))[0];
+        assertSame( person1,
+                    tuple.getFactHandles()[0].getObject() );
+        assertSame( cheese1,
+                    tuple.getFactHandles()[1].getObject() );    
+        
+        tuple = (ReteTuple) ((Object[]) asserted.get( 2 ))[0];
+        assertSame( person1,
+                    tuple.getFactHandles()[0].getObject() );
+        assertSame( cheese2,
+                    tuple.getFactHandles()[1].getObject() );    
+        
+        // Double check the nodes memory
+        BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( from );
+        assertEquals( 1,
+                      memory.getLeftTupleMemory().size() );
+        assertEquals( 0,
+                      memory.getRightObjectMemory().size() );
+        assertEquals( 2,
+                      tuple1.getTupleMatches().size() );        
+    }
+
+    public static class MockDataProvider
+        implements
+        DataProvider {
+
+        private Collection collection;
+
+        public Declaration[] getRequiredDeclarations() {
+            return null;
+        }
+
+        public MockDataProvider(Collection collection) {
+            this.collection = collection;
+        }
+
+        public Iterator getResults(Tuple tuple) {
+            return this.collection.iterator();
+        }
+    }
+
+    public static class Person {
+        private String name;
+        private int    age;
+
+        public Person(String name,
+                      int age) {
+            super();
+            this.name = name;
+            this.age = age;
+        }
+
+        public int getAge() {
+            return age;
+        }
+
+        public String getName() {
+            return name;
+        }
+    }
+}

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-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockTupleSource.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -38,7 +38,6 @@
 
     public void attach() {
         this.attached++;
-
     }
 
     public int getAttached() {

Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/rule/FieldConstraintTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/rule/FieldConstraintTest.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/rule/FieldConstraintTest.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -78,7 +78,7 @@
         final InternalFactHandle cheddarHandle = (InternalFactHandle) workingMemory.assertObject( cheddar );
 
         // check constraint
-        assertTrue( constraint.isAllowed( cheddarHandle,
+        assertTrue( constraint.isAllowed( cheddarHandle.getObject(),
                                           null,
                                           workingMemory ) );
 
@@ -88,7 +88,7 @@
         final InternalFactHandle stiltonHandle = (InternalFactHandle) workingMemory.assertObject( stilton );
 
         // check constraint
-        assertFalse( constraint.isAllowed( stiltonHandle,
+        assertFalse( constraint.isAllowed( stiltonHandle.getObject(),
                                            null,
                                            workingMemory ) );
     }
@@ -131,13 +131,13 @@
              */
             private static final long serialVersionUID = -7805842671538257493L;
 
-            public boolean evaluate(Tuple tuple,
-                                    FactHandle factHandle,
+            public boolean evaluate(Object  object,
+                                    Tuple tuple,
                                     Declaration declaration,
                                     Declaration[] declarations,
                                     WorkingMemory workingMemory) {
                 int price1 = ((Integer) declarations[0].getValue( workingMemory.getObject( tuple.get( declarations[0] ) ) )).intValue();
-                int price2 = ((Integer) declaration.getValue( workingMemory.getObject( factHandle ) )).intValue();
+                int price2 = ((Integer) declaration.getValue( object )).intValue();
 
                 return (price2 == (price1 * 2));
 
@@ -160,7 +160,7 @@
         tuple = new InstrumentedReteTuple( tuple,
                                            f1 );
 
-        assertTrue( constraint1.isAllowed( f1,
+        assertTrue( constraint1.isAllowed( f1.getObject(),
                                            tuple,
                                            workingMemory ) );
     }
@@ -228,11 +228,11 @@
         tuple = new InstrumentedReteTuple( tuple,
                                            f1 );
 
-        assertTrue( constraint1.isAllowed( f1,
+        assertTrue( constraint1.isAllowed( f1.getObject(),
                                            tuple,
                                            workingMemory ) );
 
-        assertFalse( constraint2.isAllowed( f1,
+        assertFalse( constraint2.isAllowed( f1.getObject(),
                                             tuple,
                                             workingMemory ) );
 
@@ -241,7 +241,7 @@
 
         final InternalFactHandle f2 = (InternalFactHandle) workingMemory.assertObject( cheddar2 );
 
-        assertTrue( constraint2.isAllowed( f2,
+        assertTrue( constraint2.isAllowed( f2.getObject(),
                                            tuple,
                                            workingMemory ) );
     }

Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/spi/MockConstraint.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/spi/MockConstraint.java	2006-08-10 16:55:59 UTC (rev 5712)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/spi/MockConstraint.java	2006-08-10 16:59:10 UTC (rev 5713)
@@ -17,7 +17,6 @@
  */
 
 import org.drools.WorkingMemory;
-import org.drools.common.InternalFactHandle;
 import org.drools.rule.Declaration;
 
 public class MockConstraint
@@ -33,7 +32,7 @@
 
     public boolean            isAllowed        = true;
 
-    public boolean isAllowed(final InternalFactHandle handle,
+    public boolean isAllowed(final Object object,
                              final Tuple tuple,
                              final WorkingMemory workingMemory) {
         return this.isAllowed;




More information about the jboss-svn-commits mailing list