[jboss-svn-commits] JBL Code SVN: r11923 - in labs/jbossrules/trunk/drools-core/src: main/java/org/drools/ruleflow/instance/impl and 1 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Thu May 17 20:04:58 EDT 2007
Author: KrisVerlaenen
Date: 2007-05-17 20:04:58 -0400 (Thu, 17 May 2007)
New Revision: 11923
Modified:
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/Connection.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/RuleFlowSplitInstance.java
labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/RuleFlowGroupTest.java
Log:
Added OR and XOR split to ruleflow
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/Connection.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/Connection.java 2007-05-18 00:04:52 UTC (rev 11922)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/Connection.java 2007-05-18 00:04:58 UTC (rev 11923)
@@ -96,7 +96,7 @@
}
public int hashCode() {
- return getFrom().hashCode() + 3 * getTo().hashCode() + 5 * getType();
+ return (getFrom() == null ? 0 : getFrom().hashCode()) + 7 * (getTo() == null ? 0 : getTo().hashCode()) + 19 * getType();
}
public String toString() {
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/RuleFlowSplitInstance.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/RuleFlowSplitInstance.java 2007-05-18 00:04:52 UTC (rev 11922)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/RuleFlowSplitInstance.java 2007-05-18 00:04:58 UTC (rev 11923)
@@ -19,9 +19,13 @@
import java.util.Iterator;
import java.util.List;
+import org.drools.common.RuleFlowGroupNode;
import org.drools.ruleflow.core.IConnection;
+import org.drools.ruleflow.core.IConstraint;
import org.drools.ruleflow.core.ISplit;
import org.drools.ruleflow.instance.IRuleFlowNodeInstance;
+import org.drools.spi.Activation;
+import org.drools.spi.RuleFlowGroup;
/**
* Runtime counterpart of a split node.
@@ -40,12 +44,62 @@
final ISplit split = getSplitNode();
switch ( split.getType() ) {
case ISplit.TYPE_AND :
- final List outgoing = split.getOutgoingConnections();
+ List outgoing = split.getOutgoingConnections();
for ( final Iterator iterator = outgoing.iterator(); iterator.hasNext(); ) {
final IConnection connection = (IConnection) iterator.next();
getProcessInstance().getNodeInstance( connection.getTo() ).trigger( this );
}
break;
+ case ISplit.TYPE_XOR :
+ outgoing = split.getOutgoingConnections();
+ int priority = Integer.MAX_VALUE;
+ IConnection selected = null;
+ RuleFlowGroup systemRuleFlowGroup = getProcessInstance().getAgenda().getRuleFlowGroup("DROOLS_SYSTEM");
+ for ( final Iterator iterator = outgoing.iterator(); iterator.hasNext(); ) {
+ final IConnection connection = (IConnection) iterator.next();
+ IConstraint constraint = split.getConstraint(connection);
+ if (constraint != null && constraint.getPriority() < priority) {
+ String rule = "RuleFlow-" + getProcessInstance().getProcess().getId() + "-" +
+ getNode().getId() + "-" + connection.getTo().getId();
+ for (Iterator activations = systemRuleFlowGroup.iterator(); activations.hasNext(); ) {
+ Activation activation = ((RuleFlowGroupNode) activations.next()).getActivation();
+ if (rule.equals(activation.getRule().getName())) {
+ selected = connection;
+ priority = constraint.getPriority();
+ break;
+ }
+ }
+ }
+ }
+ if (selected == null) {
+ throw new IllegalArgumentException("XOR split could not find at least one valid outgoing connection for split " + getSplitNode().getName());
+ }
+ getProcessInstance().getNodeInstance( selected.getTo() ).trigger( this );
+ break;
+ case ISplit.TYPE_OR :
+ outgoing = split.getOutgoingConnections();
+ boolean found = false;
+ systemRuleFlowGroup = getProcessInstance().getAgenda().getRuleFlowGroup("DROOLS_SYSTEM");
+ for ( final Iterator iterator = outgoing.iterator(); iterator.hasNext(); ) {
+ final IConnection connection = (IConnection) iterator.next();
+ IConstraint constraint = split.getConstraint(connection);
+ if (constraint != null) {
+ String rule = "RuleFlow-" + getProcessInstance().getProcess().getId() + "-" +
+ getNode().getId() + "-" + connection.getTo().getId();
+ for (Iterator activations = systemRuleFlowGroup.iterator(); activations.hasNext(); ) {
+ Activation activation = (Activation) activations.next();
+ if (rule.equals(activation.getRule().getName())) {
+ getProcessInstance().getNodeInstance( connection.getTo() ).trigger( this );
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ throw new IllegalArgumentException("OR split could not find at least one valid outgoing connection for split " + getSplitNode().getName());
+ }
+ }
+ break;
default :
throw new IllegalArgumentException( "Illegal split type " + split.getType() );
}
Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/RuleFlowGroupTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/RuleFlowGroupTest.java 2007-05-18 00:04:52 UTC (rev 11922)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/RuleFlowGroupTest.java 2007-05-18 00:04:58 UTC (rev 11923)
@@ -30,6 +30,7 @@
import org.drools.rule.Rule;
import org.drools.ruleflow.common.instance.IProcessInstance;
import org.drools.ruleflow.core.IConnection;
+import org.drools.ruleflow.core.IConstraint;
import org.drools.ruleflow.core.IEndNode;
import org.drools.ruleflow.core.IJoin;
import org.drools.ruleflow.core.IRuleFlowProcess;
@@ -37,6 +38,7 @@
import org.drools.ruleflow.core.ISplit;
import org.drools.ruleflow.core.IStartNode;
import org.drools.ruleflow.core.impl.Connection;
+import org.drools.ruleflow.core.impl.Constraint;
import org.drools.ruleflow.core.impl.EndNode;
import org.drools.ruleflow.core.impl.Join;
import org.drools.ruleflow.core.impl.RuleFlowProcess;
@@ -295,4 +297,278 @@
assertEquals( IProcessInstance.STATE_COMPLETED,
processInstance.getState() );
}
+
+ /** XOR split and join */
+ public void testRuleFlowGroup2() {
+ final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+
+ final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();
+
+ final InternalAgenda agenda = (InternalAgenda) workingMemory.getAgenda();
+
+ final List list = new ArrayList();
+
+ // create the consequence
+ final Consequence consequence = new Consequence() {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -2596133893109870505L;
+
+ public void evaluate(KnowledgeHelper knowledgeHelper,
+ WorkingMemory workingMemory) {
+ list.add( knowledgeHelper.getRule() );
+ }
+ };
+
+ // create a rule for each rule flow groups
+ final Rule rule0 = new Rule( "test-rule0" );
+ rule0.setRuleFlowGroup( "rule-flow-group-0" );
+ rule0.setConsequence( consequence );
+
+ final RuleTerminalNode node0 = new RuleTerminalNode( 3,
+ new MockTupleSource( 2 ),
+ rule0,
+ rule0.getLhs() );
+
+ final Rule rule1 = new Rule( "test-rule1" );
+ rule1.setRuleFlowGroup( "rule-flow-group-1" );
+ rule1.setConsequence( consequence );
+
+ final RuleTerminalNode node1 = new RuleTerminalNode( 4,
+ new MockTupleSource( 2 ),
+ rule1,
+ rule1.getLhs() );
+
+ final Rule rule2 = new Rule( "test-rule2" );
+ rule2.setRuleFlowGroup( "rule-flow-group-2" );
+ rule2.setConsequence( consequence );
+ rule2.setSalience( 10 );
+
+ final RuleTerminalNode node2 = new RuleTerminalNode( 5,
+ new MockTupleSource( 2 ),
+ rule2,
+ rule2.getLhs() );
+
+ final Rule rule3 = new Rule( "test-rule3" );
+ rule3.setRuleFlowGroup( "rule-flow-group-3" );
+ rule3.setConsequence( consequence );
+
+ final RuleTerminalNode node3 = new RuleTerminalNode( 6,
+ new MockTupleSource( 2 ),
+ rule3,
+ rule3.getLhs() );
+
+ final PropagationContext context0 = new PropagationContextImpl( 0,
+ PropagationContext.ASSERTION,
+ rule0,
+ null );
+
+ // nodes
+ final IStartNode start = new StartNode();
+ final IRuleSetNode ruleSet0 = new RuleSetNode();
+ ruleSet0.setRuleFlowGroup( "rule-flow-group-0" );
+ final IRuleSetNode ruleSet1 = new RuleSetNode();
+ ruleSet1.setRuleFlowGroup( "rule-flow-group-1" );
+ final IRuleSetNode ruleSet2 = new RuleSetNode();
+ ruleSet2.setRuleFlowGroup( "rule-flow-group-2" );
+ final IRuleSetNode ruleSet3 = new RuleSetNode();
+ ruleSet3.setRuleFlowGroup( "rule-flow-group-3" );
+ final ISplit split = new Split();
+ split.setType( ISplit.TYPE_XOR );
+ final IJoin join = new Join();
+ join.setType( IJoin.TYPE_XOR );
+ final IEndNode end = new EndNode();
+ // connections
+ new Connection( start,
+ ruleSet0,
+ IConnection.TYPE_NORMAL );
+ new Connection( ruleSet0,
+ split,
+ IConnection.TYPE_NORMAL );
+ Connection out1 = new Connection( split,
+ ruleSet1,
+ IConnection.TYPE_NORMAL );
+ Connection out2 = new Connection( split,
+ ruleSet2,
+ IConnection.TYPE_NORMAL );
+ new Connection( ruleSet1,
+ join,
+ IConnection.TYPE_NORMAL );
+ new Connection( ruleSet2,
+ join,
+ IConnection.TYPE_NORMAL );
+ new Connection( join,
+ ruleSet3,
+ IConnection.TYPE_NORMAL );
+ new Connection( ruleSet3,
+ end,
+ IConnection.TYPE_NORMAL );
+ IConstraint constraint1 = new Constraint();
+ constraint1.setPriority(1);
+ split.setConstraint(out1, constraint1);
+ IConstraint constraint2 = new Constraint();
+ constraint2.setPriority(2);
+ split.setConstraint(out2, constraint2);
+
+ // process
+ final IRuleFlowProcess process = new RuleFlowProcess();
+ process.setId( "1" );
+ process.addNode( start );
+ process.addNode( ruleSet0 );
+ process.addNode( ruleSet1 );
+ process.addNode( ruleSet2 );
+ process.addNode( ruleSet3 );
+ process.addNode( split );
+ process.addNode( join );
+ process.addNode( end );
+
+ // rules for split
+ final Rule splitRule1 = new Rule( "RuleFlow-1-" + split.getId() + "-" + ruleSet1.getId());
+ splitRule1.setRuleFlowGroup( "DROOLS_SYSTEM" );
+ splitRule1.setConsequence( consequence );
+
+ final RuleTerminalNode splitNode1 = new RuleTerminalNode( 7,
+ new MockTupleSource( 2 ),
+ splitRule1,
+ splitRule1.getLhs() );
+
+ final Rule splitRule2 = new Rule( "RuleFlow-1-" + split.getId() + "-" + ruleSet2.getId());
+ splitRule2.setRuleFlowGroup( "DROOLS_SYSTEM" );
+ splitRule2.setConsequence( consequence );
+
+ final RuleTerminalNode splitNode2 = new RuleTerminalNode( 8,
+ new MockTupleSource( 2 ),
+ splitRule2,
+ splitRule2.getLhs() );
+
+ // proces instance
+ final IRuleFlowProcessInstance processInstance = new RuleFlowProcessInstance();
+ processInstance.setAgenda( agenda );
+ processInstance.setProcess( process );
+ assertEquals( IProcessInstance.STATE_PENDING,
+ processInstance.getState() );
+
+ final RuleFlowGroupImpl ruleFlowGroup0 = (RuleFlowGroupImpl) agenda.getRuleFlowGroup( "rule-flow-group-0" );
+ final RuleFlowGroupImpl ruleFlowGroup1 = (RuleFlowGroupImpl) agenda.getRuleFlowGroup( "rule-flow-group-1" );
+ final RuleFlowGroupImpl ruleFlowGroup2 = (RuleFlowGroupImpl) agenda.getRuleFlowGroup( "rule-flow-group-2" );
+ final RuleFlowGroupImpl ruleFlowGroup3 = (RuleFlowGroupImpl) agenda.getRuleFlowGroup( "rule-flow-group-3" );
+
+ final ReteTuple tuple0 = new ReteTuple( new DefaultFactHandle( 1,
+ "cheese" ) );
+ node0.assertTuple( tuple0,
+ context0,
+ workingMemory );
+
+ final ReteTuple tuple1 = new ReteTuple( new DefaultFactHandle( 1,
+ "cheese" ) );
+ node0.assertTuple( tuple1,
+ context0,
+ workingMemory );
+
+ final ReteTuple tuple2 = new ReteTuple( new DefaultFactHandle( 1,
+ "cheese" ) );
+ node1.assertTuple( tuple2,
+ context0,
+ workingMemory );
+
+ final ReteTuple tuple3 = new ReteTuple( new DefaultFactHandle( 1,
+ "cheese" ) );
+ node2.assertTuple( tuple3,
+ context0,
+ workingMemory );
+
+ final ReteTuple tuple4 = new ReteTuple( new DefaultFactHandle( 1,
+ "cheese" ) );
+ node3.assertTuple( tuple4,
+ context0,
+ workingMemory );
+
+ final ReteTuple splitTuple1 = new ReteTuple( new DefaultFactHandle( 1,
+ "cheese" ) );
+ splitNode1.assertTuple( splitTuple1,
+ context0,
+ workingMemory );
+
+ final ReteTuple splitTuple2 = new ReteTuple( new DefaultFactHandle( 1,
+ "cheese" ) );
+ splitNode1.assertTuple( splitTuple2,
+ context0,
+ workingMemory );
+
+ final RuleFlowGroupImpl systemRuleFlowGroup = (RuleFlowGroupImpl) agenda.getRuleFlowGroup( "DROOLS_SYSTEM" );
+
+
+
+ // RuleFlowGroups should be populated, but the agenda shouldn't
+ assertEquals( 2,
+ ruleFlowGroup0.size() );
+ assertEquals( 1,
+ ruleFlowGroup1.size() );
+ assertEquals( 1,
+ ruleFlowGroup2.size() );
+ assertEquals( 1,
+ ruleFlowGroup3.size() );
+ assertEquals( 2,
+ systemRuleFlowGroup.size() );
+ assertEquals( 0,
+ agenda.agendaSize() );
+
+ // Activate process instance, the activations stay in the group,
+ // but should now also be in the Agenda
+ processInstance.start();
+ assertEquals( IProcessInstance.STATE_ACTIVE,
+ processInstance.getState() );
+ assertEquals( 2,
+ ruleFlowGroup0.size() );
+ assertEquals( 2,
+ agenda.agendaSize() );
+
+ // As we fire each rule they are removed from both the Agenda and the RuleFlowGroup
+ agenda.fireNextItem( null );
+ assertEquals( 1,
+ ruleFlowGroup0.size() );
+ assertEquals( 1,
+ agenda.agendaSize() );
+
+ // XOR split should activate group1
+ agenda.fireNextItem( null );
+ workingMemory.executeQueuedActions();
+ assertEquals( 0,
+ ruleFlowGroup0.size() );
+ assertEquals( 1,
+ ruleFlowGroup1.size() );
+ assertEquals( 1,
+ ruleFlowGroup2.size() );
+ assertEquals( 1,
+ agenda.agendaSize() );
+
+ // executing group1, XOR join should activate group3
+ agenda.fireNextItem( null );
+ workingMemory.executeQueuedActions();
+ assertEquals( 0,
+ ruleFlowGroup1.size() );
+ assertEquals( 1,
+ ruleFlowGroup2.size() );
+ assertEquals( 1,
+ ruleFlowGroup3.size() );
+ assertEquals( 1,
+ agenda.agendaSize() );
+
+ // executing rule3, and finishing execution
+ agenda.fireNextItem( null );
+ workingMemory.executeQueuedActions();
+ assertEquals( 0,
+ ruleFlowGroup0.size() );
+ assertEquals( 0,
+ ruleFlowGroup1.size() );
+ assertEquals( 1,
+ ruleFlowGroup2.size() );
+ assertEquals( 0,
+ ruleFlowGroup3.size() );
+ assertEquals( 0,
+ agenda.agendaSize() );
+ assertEquals( IProcessInstance.STATE_COMPLETED,
+ processInstance.getState() );
+ }
}
More information about the jboss-svn-commits
mailing list