[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