[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