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

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Sun Jul 30 11:07:01 EDT 2006


Author: tirelli
Date: 2006-07-30 11:06:49 -0400 (Sun, 30 Jul 2006)
New Revision: 5354

Added:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AccumulateNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/Accumulator.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CalculatedObjectHandle.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/MockAccumulator.java
Log:
* JBRULES-336

   * Adding initial AccumulateNode implementation
   * Adding unit tests for it



Added: 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-07-29 22:08:33 UTC (rev 5353)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AccumulateNode.java	2006-07-30 15:06:49 UTC (rev 5354)
@@ -0,0 +1,311 @@
+/*
+ * 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 java.util.Map;
+
+import org.drools.common.BetaNodeBinder;
+import org.drools.common.DefaultFactHandle;
+import org.drools.spi.PropagationContext;
+import org.drools.util.LinkedList;
+import org.drools.util.LinkedListObjectWrapper;
+
+/**
+ * AccumulateNode
+ * A beta node capable of doing accumulate logic.
+ *
+ * Created: 04/06/2006
+ * @author <a href="mailto:tirelli at post.com">Edson Tirelli</a> 
+ *
+ * @version $Id$
+ */
+public class AccumulateNode extends BetaNode {
+
+    private static final long serialVersionUID = -4081578178269297948L;
+
+    // MENTAL NOTE: it MUST be stateless
+    private final Accumulator accumulator;
+
+    /**
+     * Construct.
+     * 
+     * @param leftInput
+     *            The left input <code>TupleSource</code>.
+     * @param rightInput
+     *            The right input <code>TupleSource</code>.
+     */
+    AccumulateNode(final int id,
+                   final TupleSource leftInput,
+                   final ObjectSource rightInput,
+                   final Accumulator accumulator) {
+        this( id,
+              leftInput,
+              rightInput,
+              accumulator,
+              new BetaNodeBinder() );
+    }
+
+    /**
+     * Construct.
+     * 
+     * @param leftInput
+     *            The left input <code>TupleSource</code>.
+     * @param rightInput
+     *            The right input <code>TupleSource</code>.
+     */
+    AccumulateNode(final int id,
+                   final TupleSource leftInput,
+                   final ObjectSource rightInput,
+                   final Accumulator accumulator,
+                   final BetaNodeBinder joinNodeBinder) {
+        super( id,
+               leftInput,
+               rightInput,
+               joinNodeBinder );
+        this.accumulator = accumulator;
+    }
+
+    /**
+     * @inheritDoc
+     * 
+     *  When a new tuple is asserted into an AccumulateNode, do this:
+     *  
+     *  1. Select all matching objects from right memory
+     *  2. Execute the initialization code using the tuple + matching objects
+     *  3. Execute the accumulation code for each combination of tuple+object
+     *  4. Execute the return code
+     *  5. Create a new CalculatedObjectHandle for the resulting object and add it to the tuple
+     *  6. Propagate the tuple
+     *  
+     *  The initialization, accumulation and return codes, in JBRules, are assembled
+     *  into a generated method code and called once for the whole match, as you can see
+     *  bellow:
+     *  
+     *   Object result = this.accumulator.accumulate( ... );
+     *  
+     */
+    public void assertTuple(ReteTuple leftTuple,
+                            PropagationContext context,
+                            ReteooWorkingMemory workingMemory) {
+
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+
+        memory.add( workingMemory,
+                    leftTuple );
+
+        final BetaNodeBinder binder = getJoinNodeBinder();
+
+        List matchingObjects = new ArrayList();
+        for ( final Iterator it = memory.rightObjectIterator( workingMemory,
+                                                              leftTuple ); it.hasNext(); ) {
+            final ObjectMatches objectMatches = (ObjectMatches) it.next();
+            final DefaultFactHandle handle = objectMatches.getFactHandle();
+
+            if ( attemptJoin( leftTuple, 
+                              handle, 
+                              objectMatches, 
+                              binder, 
+                              workingMemory ) != null ) {
+                matchingObjects.add( handle.getObject() );
+            }
+        }
+
+        Object result = this.accumulator.accumulate( leftTuple,
+                                                     matchingObjects,
+                                                     workingMemory );
+
+        DefaultFactHandle handle = new CalculatedObjectHandle( result );
+
+        propagateAssertTuple( leftTuple,
+                              handle,
+                              context,
+                              workingMemory );
+    }
+
+    /**
+     * @inheritDoc
+     * 
+     * As the accumulate node will always propagate the tuple,
+     * but will recalculate the accumulated result object every time,
+     * a modify is really a retract + assert. 
+     * 
+     */
+    public void modifyTuple(ReteTuple leftTuple,
+                            PropagationContext context,
+                            ReteooWorkingMemory workingMemory) {
+        
+        this.retractTuple( leftTuple, context, workingMemory );
+        this.assertTuple( leftTuple, context, workingMemory );
+
+    }
+
+    /**
+     * @inheritDoc
+     * 
+     * As the accumulate node will always propagate the tuple,
+     * it must always also retreat it.
+     * 
+     */
+    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();
+                tupleMatch.getObjectMatches().remove( tupleMatch );
+            }
+        }
+        
+        propagateRetractTuple( leftTuple,
+                               context,
+                               workingMemory );
+    }
+
+    /**
+     * @inheritDoc
+     * 
+     *  When a new object is asserted into an AccumulateNode, do this:
+     *  
+     *  1. Select all matching tuples from left memory
+     *  2. For each matching tuple, call a modify tuple
+     *  
+     */
+    public void assertObject(DefaultFactHandle handle,
+                             PropagationContext context,
+                             ReteooWorkingMemory workingMemory) {
+
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+        ObjectMatches objectMatches = memory.add( workingMemory,
+                                                  handle );
+
+        final BetaNodeBinder binder = getJoinNodeBinder();
+        for ( final Iterator it = memory.leftTupleIterator( workingMemory,
+                                                            handle ); it.hasNext(); ) {
+            final ReteTuple leftTuple = (ReteTuple) it.next();
+
+            if ( attemptJoin( leftTuple, 
+                              handle, 
+                              objectMatches, 
+                              binder, 
+                              workingMemory ) != null ) {
+                this.modifyTuple( leftTuple,
+                                  context,
+                                  workingMemory );
+            }
+        }
+
+    }
+
+    /**
+     * @inheritDoc
+     * 
+     * If an object is modified, iterate over all matching tuples
+     * and propagate a modify tuple for them.
+     * 
+     * NOTE: a modify tuple for accumulate node is exactly the 
+     * same as a retract+assert tuple, since the calculated object changes.
+     * So, a modify object is in fact a retract+assert object.
+     * 
+     */
+    public void modifyObject(DefaultFactHandle handle,
+                             PropagationContext context,
+                             ReteooWorkingMemory workingMemory) {
+        this.retractObject( handle,
+                            context,
+                            workingMemory );
+        this.assertObject( handle,
+                           context,
+                           workingMemory );
+    }
+
+    /**
+     *  @inheritDoc
+     *  
+     *  If an object is retract, call modify tuple for each
+     *  tuple match.
+     */
+    public void retractObject(DefaultFactHandle handle,
+                              PropagationContext context,
+                              ReteooWorkingMemory workingMemory) {
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+
+        // Remove the FactHandle from memory
+        final ObjectMatches objectMatches = memory.remove( workingMemory,
+                                                           handle );
+
+        for ( TupleMatch tupleMatch = objectMatches.getFirstTupleMatch(); tupleMatch != null; tupleMatch = (TupleMatch) tupleMatch.getNext() ) {
+            final ReteTuple leftTuple = tupleMatch.getTuple();
+            leftTuple.removeMatch( handle );
+
+            this.modifyTuple( leftTuple,
+                              context,
+                              workingMemory );
+        }
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public List getPropagatedTuples(ReteooWorkingMemory workingMemory,
+                                    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;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public void updateNewNode(ReteooWorkingMemory workingMemory,
+                              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();
+            final ReteTuple child = new ReteTuple( leftTuple );
+            leftTuple.addLinkedTuple( child );
+            ((TupleSink) getTupleSinks().get( getTupleSinks().size() - 1 )).assertTuple( child,
+                                                                                         context,
+                                                                                         workingMemory );
+        }
+        this.attachingNewNode = false;
+    }
+
+}


Property changes on: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AccumulateNode.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + id author date revision
Name: svn:eol-style
   + native

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/Accumulator.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/Accumulator.java	2006-07-29 22:08:33 UTC (rev 5353)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/Accumulator.java	2006-07-30 15:06:49 UTC (rev 5354)
@@ -0,0 +1,36 @@
+/*
+ * 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.List;
+
+import org.drools.WorkingMemory;
+
+/**
+ * Accumulator
+ *
+ * Created: 04/06/2006
+ * @author <a href="mailto:tirelli at post.com">Edson Tirelli</a> 
+ *
+ * @version $Id$
+ */
+public interface Accumulator extends Serializable {
+
+    public Object accumulate(ReteTuple leftTuple, List matchingObjects, WorkingMemory workingMemory);
+
+}


Property changes on: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/Accumulator.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + id author date revision
Name: svn:eol-style
   + native

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CalculatedObjectHandle.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CalculatedObjectHandle.java	2006-07-29 22:08:33 UTC (rev 5353)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CalculatedObjectHandle.java	2006-07-30 15:06:49 UTC (rev 5354)
@@ -0,0 +1,38 @@
+/*
+ * 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.common.DefaultFactHandle;
+
+/**
+ * CalculatedObjectHandle
+ *
+ * Created: 13/06/2006
+ * @author <a href="mailto:tirelli at post.com">Edson Tirelli</a> 
+ *
+ * @version $Id$
+ */
+
+public class CalculatedObjectHandle extends DefaultFactHandle {
+
+    private static final long serialVersionUID = -8026531400924584912L;
+    
+    public CalculatedObjectHandle(Object object) {
+        super(-1, object, 0);
+    }
+
+}


Property changes on: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CalculatedObjectHandle.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + id author date revision
Name: svn:eol-style
   + native

Added: 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-07-29 22:08:33 UTC (rev 5353)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/AccumulateNodeTest.java	2006-07-30 15:06:49 UTC (rev 5354)
@@ -0,0 +1,519 @@
+/*
+ * 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.List;
+
+import junit.framework.Assert;
+
+import org.drools.DroolsTestCase;
+import org.drools.RuleBaseFactory;
+import org.drools.common.BetaNodeBinder;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.PropagationContextImpl;
+import org.drools.rule.Rule;
+import org.drools.spi.FieldConstraint;
+import org.drools.spi.MockConstraint;
+import org.drools.spi.PropagationContext;
+
+/**
+ * A test case for AccumulateNode
+ * 
+ * @author etirelli
+ */
+public class AccumulateNodeTest extends DroolsTestCase {
+
+    Rule                rule;
+    PropagationContext  context;
+    ReteooWorkingMemory workingMemory;
+    MockObjectSource    objectSource;
+    MockTupleSource     tupleSource;
+    MockTupleSink       sink;
+    BetaNode            node;
+    BetaMemory          memory;
+    MockConstraint      constraint = new MockConstraint();
+    MockAccumulator     accumulator;
+
+    /* (non-Javadoc)
+     * @see junit.framework.TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+        super.setUp();
+        this.rule = new Rule( "test-rule" );
+        this.context = new PropagationContextImpl( 0,
+                                                   PropagationContext.ASSERTION,
+                                                   null,
+                                                   null );
+        this.workingMemory = new ReteooWorkingMemory( 1,
+                                                      (ReteooRuleBase) RuleBaseFactory.newRuleBase() );
+
+        this.tupleSource = new MockTupleSource( 4 );
+        this.objectSource = new MockObjectSource( 4 );
+        this.sink = new MockTupleSink();
+
+        this.accumulator = new MockAccumulator();
+
+        this.node = new AccumulateNode( 15,
+                                        this.tupleSource,
+                                        this.objectSource,
+                                        this.accumulator,
+                                        new BetaNodeBinder( new FieldConstraint[]{this.constraint} ) );
+
+        this.node.addTupleSink( this.sink );
+
+        this.memory = (BetaMemory) this.workingMemory.getNodeMemory( this.node );
+
+        // check memories are empty
+        assertEquals( 0,
+                      this.memory.getLeftTupleMemory().size() );
+        assertEquals( 0,
+                      this.memory.getRightObjectMemory().size() );
+    }
+
+    /* (non-Javadoc)
+     * @see junit.framework.TestCase#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /**
+     * Test method for {@link org.drools.reteoo.AccumulateNode#updateNewNode(org.drools.reteoo.ReteooWorkingMemory, org.drools.spi.PropagationContext)}.
+     */
+    public void testUpdateNewNode() {
+        this.node.updateNewNode( workingMemory,
+                                 context );
+        Assert.assertEquals( "No tuple should be propagated",
+                             0,
+                             this.sink.getAsserted().size() );
+
+        this.node.assertTuple( new ReteTuple( new DefaultFactHandle() ),
+                               context,
+                               workingMemory );
+        this.node.assertTuple( new ReteTuple( new DefaultFactHandle() ),
+                               context,
+                               workingMemory );
+
+        Assert.assertEquals( "Two tuples should have been propagated",
+                             2,
+                             this.sink.getAsserted().size() );
+
+        final MockTupleSink otherSink = new MockTupleSink();
+
+        this.node.addTupleSink( otherSink );
+        this.node.updateNewNode( workingMemory,
+                                 context );
+
+        Assert.assertEquals( "Two tuples should have been propagated",
+                             2,
+                             otherSink.getAsserted().size() );
+    }
+
+    /**
+     * Test method for {@link org.drools.reteoo.AccumulateNode#getPropagatedTuples(org.drools.reteoo.ReteooWorkingMemory, org.drools.reteoo.TupleSink)}.
+     */
+    public void testGetPropagatedTuples() {
+
+        this.node.assertTuple( new ReteTuple( new DefaultFactHandle() ),
+                               context,
+                               workingMemory );
+        this.node.assertTuple( new ReteTuple( new DefaultFactHandle() ),
+                               context,
+                               workingMemory );
+
+        Assert.assertEquals( "Two tuples should have been propagated",
+                             2,
+                             this.sink.getAsserted().size() );
+
+        final ReteTuple t1 = (ReteTuple) ((Object[]) this.sink.getAsserted().get( 0 ))[0];
+        final ReteTuple t2 = (ReteTuple) ((Object[]) this.sink.getAsserted().get( 1 ))[0];
+
+        List propagated = this.node.getPropagatedTuples( workingMemory,
+                                                         sink );
+        Assert.assertEquals( "Wrong Tuple propagated",
+                             t1,
+                             propagated.get( 0 ) );
+        Assert.assertEquals( "Wrong Tuple propagated",
+                             t2,
+                             propagated.get( 1 ) );
+
+    }
+
+    /**
+     * Test method for {@link org.drools.reteoo.AccumulateNode#assertTuple(org.drools.reteoo.ReteTuple, org.drools.spi.PropagationContext, org.drools.reteoo.ReteooWorkingMemory)}.
+     */
+    public void testAssertTuple() {
+        final DefaultFactHandle f0 = new DefaultFactHandle( 0,
+                                                            "cheese" );
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        // assert tuple, should add one to left memory
+        this.node.assertTuple( tuple0,
+                               this.context,
+                               this.workingMemory );
+        // check memories 
+        assertEquals( 1,
+                      this.memory.getLeftTupleMemory().size() );
+        assertEquals( 0,
+                      this.memory.getRightObjectMemory().size() );
+        Assert.assertTrue( "An empty matching objects list should be propagated",
+                           this.accumulator.getMatchingObjects().isEmpty() );
+
+        // assert tuple, should add left memory 
+        final DefaultFactHandle f1 = new DefaultFactHandle( 1,
+                                                            "cheese" );
+        final ReteTuple tuple1 = new ReteTuple( f1 );
+        this.node.assertTuple( tuple1,
+                               this.context,
+                               this.workingMemory );
+        assertEquals( 2,
+                      this.memory.getLeftTupleMemory().size() );
+        Assert.assertTrue( "An empty matching objects list should be propagated",
+                           this.accumulator.getMatchingObjects().isEmpty() );
+
+        final ReteTuple tuple = (ReteTuple) this.memory.getLeftTupleMemory().iterator( this.workingMemory,
+                                                                                       f0 ).next();
+        assertEquals( tuple0,
+                      tuple );
+        assertEquals( tuple1,
+                      tuple.getNext() );
+
+        Assert.assertEquals( "Two tuples should have been propagated",
+                             2,
+                             this.sink.getAsserted().size() );
+    }
+
+    /**
+     * Test method for {@link org.drools.reteoo.AccumulateNode#assertTuple(org.drools.reteoo.ReteTuple, org.drools.spi.PropagationContext, org.drools.reteoo.ReteooWorkingMemory)}.
+     */
+    public void testAssertTupleWithObjects() {
+        final DefaultFactHandle f0 = new DefaultFactHandle( 0,
+                                                            "cheese" );
+        final DefaultFactHandle f1 = new DefaultFactHandle( 1,
+                                                            "other cheese" );
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        this.node.assertObject( f0,
+                                context,
+                                workingMemory );
+        this.node.assertObject( f1,
+                                context,
+                                workingMemory );
+
+        // assert tuple, should add one to left memory
+        this.node.assertTuple( tuple0,
+                               this.context,
+                               this.workingMemory );
+        // check memories 
+        assertEquals( 1,
+                      this.memory.getLeftTupleMemory().size() );
+        assertEquals( 2,
+                      this.memory.getRightObjectMemory().size() );
+        Assert.assertEquals( "Wrong number of elements in matching objects list ",
+                             2,
+                             this.accumulator.getMatchingObjects().size() );
+
+        // assert tuple, should add left memory 
+        final ReteTuple tuple1 = new ReteTuple( f1 );
+        this.node.assertTuple( tuple1,
+                               this.context,
+                               this.workingMemory );
+        assertEquals( 2,
+                      this.memory.getLeftTupleMemory().size() );
+        Assert.assertEquals( "Wrong number of elements in matching objects list ",
+                             2,
+                             this.accumulator.getMatchingObjects().size() );
+
+        final ReteTuple tuple = (ReteTuple) this.memory.getLeftTupleMemory().iterator( this.workingMemory,
+                                                                                       f0 ).next();
+        assertEquals( tuple0,
+                      tuple );
+        assertEquals( tuple1,
+                      tuple.getNext() );
+
+        Assert.assertEquals( "Two tuples should have been propagated",
+                             2,
+                             this.sink.getAsserted().size() );
+    }
+
+    /**
+     * Test method for {@link org.drools.reteoo.AccumulateNode#modifyTuple(org.drools.reteoo.ReteTuple, org.drools.spi.PropagationContext, org.drools.reteoo.ReteooWorkingMemory)}.
+     */
+    public void testModifyTuple() {
+        final DefaultFactHandle f0 = new DefaultFactHandle( 0,
+                                                            "cheese" );
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        // assert tuple, should add one to left memory
+        this.node.assertTuple( tuple0,
+                               this.context,
+                               this.workingMemory );
+        // check memories 
+        assertEquals( 1,
+                      this.memory.getLeftTupleMemory().size() );
+        assertEquals( 0,
+                      this.memory.getRightObjectMemory().size() );
+        Assert.assertTrue( "An empty matching objects list should be propagated",
+                           this.accumulator.getMatchingObjects().isEmpty() );
+
+        this.node.modifyTuple( tuple0,
+                               this.context,
+                               this.workingMemory );
+        assertEquals( 1,
+                      this.memory.getLeftTupleMemory().size() );
+        assertEquals( 1,
+                      this.sink.getRetracted().size() );
+        assertEquals( 2,
+                      this.sink.getAsserted().size() );
+        Assert.assertTrue( "An empty matching objects list should be propagated",
+                           this.accumulator.getMatchingObjects().isEmpty() );
+    }
+
+    /**
+     * Test method for {@link org.drools.reteoo.AccumulateNode#retractTuple(org.drools.reteoo.ReteTuple, org.drools.spi.PropagationContext, org.drools.reteoo.ReteooWorkingMemory)}.
+     */
+    public void testRetractTuple() {
+        final DefaultFactHandle f0 = new DefaultFactHandle( 0,
+                                                            "cheese" );
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        // assert tuple, should add one to left memory
+        this.node.assertTuple( tuple0,
+                               this.context,
+                               this.workingMemory );
+        // check memories 
+        assertEquals( 1,
+                      this.memory.getLeftTupleMemory().size() );
+        assertEquals( 0,
+                      this.memory.getRightObjectMemory().size() );
+        Assert.assertTrue( "An empty matching objects list should be propagated",
+                           this.accumulator.getMatchingObjects().isEmpty() );
+
+        this.node.retractTuple( tuple0,
+                                this.context,
+                                this.workingMemory );
+        assertEquals( 0,
+                      this.memory.getLeftTupleMemory().size() );
+        assertEquals( 1,
+                      this.sink.getRetracted().size() );
+        assertEquals( 1,
+                      this.sink.getAsserted().size() );
+    }
+
+    /**
+     * Test method for {@link org.drools.reteoo.AccumulateNode#assertObject(org.drools.common.DefaultFactHandle, org.drools.spi.PropagationContext, org.drools.reteoo.ReteooWorkingMemory)}.
+     */
+    public void testAssertObject() {
+        final DefaultFactHandle f0 = new DefaultFactHandle( 0,
+                                                            "cheese" );
+        final DefaultFactHandle f1 = new DefaultFactHandle( 1,
+                                                            "other cheese" );
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        // assert tuple, should add one to left memory
+        this.node.assertTuple( tuple0,
+                               this.context,
+                               this.workingMemory );
+
+        // check memory 
+        assertEquals( 1,
+                      this.memory.getLeftTupleMemory().size() );
+        assertEquals( 1,
+                      this.sink.getAsserted().size() );
+        assertEquals( 0,
+                      this.accumulator.getMatchingObjects().size() );
+
+        this.node.assertObject( f0,
+                                context,
+                                workingMemory );
+        assertEquals( 1,
+                      this.memory.getRightObjectMemory().size() );
+        assertEquals( 2,
+                      this.sink.getAsserted().size() );
+        assertEquals( 1,
+                      this.accumulator.getMatchingObjects().size() );
+
+        this.node.assertObject( f1,
+                                context,
+                                workingMemory );
+
+        assertEquals( 2,
+                      this.memory.getRightObjectMemory().size() );
+        assertEquals( 3,
+                      this.sink.getAsserted().size() );
+        assertEquals( 2,
+                      this.accumulator.getMatchingObjects().size() );
+
+    }
+
+    /**
+     * Test method for {@link org.drools.reteoo.AccumulateNode#modifyObject(org.drools.common.DefaultFactHandle, org.drools.spi.PropagationContext, org.drools.reteoo.ReteooWorkingMemory)}.
+     */
+    public void testModifyObject() {
+        final DefaultFactHandle f0 = new DefaultFactHandle( 0,
+                                                            "cheese" );
+        final DefaultFactHandle f1 = new DefaultFactHandle( 1,
+                                                            "other cheese" );
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        this.node.assertObject( f0,
+                                context,
+                                workingMemory );
+        this.node.assertObject( f1,
+                                context,
+                                workingMemory );
+
+        // assert tuple, should add one to left memory
+        this.node.assertTuple( tuple0,
+                               this.context,
+                               this.workingMemory );
+        // check memories 
+        assertEquals( 1,
+                      this.memory.getLeftTupleMemory().size() );
+        assertEquals( 2,
+                      this.memory.getRightObjectMemory().size() );
+        assertEquals( 1,
+                      this.sink.getAsserted().size() );
+        assertEquals( 0,
+                      this.sink.getRetracted().size() );
+        Assert.assertEquals( "Wrong number of elements in matching objects list ",
+                             2,
+                             this.accumulator.getMatchingObjects().size() );
+
+        // assert tuple, should add left memory 
+        this.node.modifyObject( f0,
+                                this.context,
+                                this.workingMemory );
+        assertEquals( 2,
+                      this.memory.getRightObjectMemory().size() );
+        assertEquals( 3,
+                      this.sink.getAsserted().size() );
+        assertEquals( 2,
+                      this.sink.getRetracted().size() );
+        Assert.assertEquals( "Wrong number of elements in matching objects list ",
+                             2,
+                             this.accumulator.getMatchingObjects().size() );
+
+        final ReteTuple tuple = (ReteTuple) this.memory.getLeftTupleMemory().iterator( this.workingMemory,
+                                                                                       f0 ).next();
+        assertEquals( tuple0,
+                      tuple );
+
+    }
+
+    /**
+     * Test method for {@link org.drools.reteoo.AccumulateNode#retractObject(org.drools.common.DefaultFactHandle, org.drools.spi.PropagationContext, org.drools.reteoo.ReteooWorkingMemory)}.
+     */
+    public void testRetractObject() {
+        final DefaultFactHandle f0 = new DefaultFactHandle( 0,
+                                                            "cheese" );
+        final DefaultFactHandle f1 = new DefaultFactHandle( 1,
+                                                            "other cheese" );
+        final ReteTuple tuple0 = new ReteTuple( f0 );
+
+        this.node.assertObject( f0,
+                                context,
+                                workingMemory );
+        this.node.assertObject( f1,
+                                context,
+                                workingMemory );
+        assertEquals( 2,
+                      this.memory.getRightObjectMemory().size() );
+
+        // assert tuple, should add one to left memory
+        this.node.assertTuple( tuple0,
+                               this.context,
+                               this.workingMemory );
+
+        // check memory 
+        assertEquals( 1,
+                      this.memory.getLeftTupleMemory().size() );
+        assertEquals( 0,
+                      this.sink.getRetracted().size() );
+        assertEquals( 1,
+                      this.sink.getAsserted().size() );
+        assertEquals( 2,
+                      this.accumulator.getMatchingObjects().size() );
+
+        this.node.retractObject( f1,
+                                 context,
+                                 workingMemory );
+        assertEquals( 1,
+                      this.memory.getRightObjectMemory().size() );
+        assertEquals( 1,
+                      this.sink.getRetracted().size() );
+        assertEquals( 2,
+                      this.sink.getAsserted().size() );
+        assertEquals( 1,
+                      this.accumulator.getMatchingObjects().size() );
+
+        this.node.retractObject( f0,
+                                 context,
+                                 workingMemory );
+        assertEquals( 0,
+                      this.memory.getRightObjectMemory().size() );
+        assertEquals( 2,
+                      this.sink.getRetracted().size() );
+        assertEquals( 3,
+                      this.sink.getAsserted().size() );
+        assertEquals( 0,
+                      this.accumulator.getMatchingObjects().size() );
+
+    }
+
+    public void testAttach() throws Exception {
+        assertEquals( 15,
+                      this.node.getId() );
+
+        assertLength( 0,
+                      this.objectSource.getObjectSinksAsList() );
+
+        assertLength( 0,
+                      this.tupleSource.getTupleSinks() );
+
+        this.node.attach();
+
+        assertLength( 1,
+                      this.objectSource.getObjectSinksAsList() );
+
+        assertLength( 1,
+                      this.tupleSource.getTupleSinks() );
+
+        assertSame( this.node,
+                    this.objectSource.getObjectSinks().getLastObjectSink() );
+
+        assertSame( this.node,
+                    this.tupleSource.getTupleSinks().get( 0 ) );
+    }
+
+    public void testMemory() {
+        final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory( 1,
+                                                                           (ReteooRuleBase) RuleBaseFactory.newRuleBase() );
+
+        final MockObjectSource objectSource = new MockObjectSource( 1 );
+        final MockTupleSource tupleSource = new MockTupleSource( 1 );
+
+        final AccumulateNode accumulateNode = new AccumulateNode( 2,
+                                                                  tupleSource,
+                                                                  objectSource,
+                                                                  this.accumulator );
+
+        final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( accumulateNode );
+
+        assertNotNull( memory );
+    }
+
+}


Property changes on: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/AccumulateNodeTest.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + id author date revision
Name: svn:eol-style
   + native

Added: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockAccumulator.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockAccumulator.java	2006-07-29 22:08:33 UTC (rev 5353)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockAccumulator.java	2006-07-30 15:06:49 UTC (rev 5354)
@@ -0,0 +1,63 @@
+/*
+ * 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.Collections;
+import java.util.List;
+
+import org.drools.WorkingMemory;
+
+/**
+ * A Mock accumulator object.
+ * 
+ * @author etirelli
+ *
+ */
+public class MockAccumulator
+    implements
+    Accumulator {
+    
+    private static final long serialVersionUID = 8959310397185256783L;
+    
+    private ReteTuple leftTuple = null;
+    private List      matchingObjects = Collections.EMPTY_LIST;
+    private WorkingMemory workingMemory = null;
+
+    /* (non-Javadoc)
+     * @see org.drools.reteoo.Accumulator#accumulate(org.drools.reteoo.ReteTuple, java.util.List, org.drools.WorkingMemory)
+     */
+    public Object accumulate(ReteTuple leftTuple,
+                             List matchingObjects,
+                             WorkingMemory workingMemory) {
+        this.leftTuple = leftTuple;
+        this.matchingObjects = matchingObjects;
+        this.workingMemory = workingMemory;
+        return matchingObjects;
+    }
+
+    public ReteTuple getLeftTuple() {
+        return leftTuple;
+    }
+
+    public List getMatchingObjects() {
+        return matchingObjects;
+    }
+
+    public WorkingMemory getWorkingMemory() {
+        return workingMemory;
+    }
+
+}


Property changes on: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/MockAccumulator.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + id author date revision
Name: svn:eol-style
   + native




More information about the jboss-svn-commits mailing list