[jboss-svn-commits] JBL Code SVN: r9865 - in labs/jbossrules/trunk/drools-core/src: main/java/org/drools/common and 16 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Wed Feb 28 21:32:56 EST 2007


Author: KrisVerlaenen
Date: 2007-02-28 21:32:55 -0500 (Wed, 28 Feb 2007)
New Revision: 9865

Added:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InternalRuleFlowGroup.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/RuleFlowGroupImpl.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/RuleFlowGroupNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/core/
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/core/IProcess.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/core/impl/
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/core/impl/Process.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/IDataType.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/IDataTypeFactory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/InstanceDataTypeFactory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/NewInstanceDataTypeFactory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/BooleanDataType.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/FloatDataType.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/IntegerDataType.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/ListDataType.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/StringDataType.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/UndefinedDataType.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/instance/
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/instance/IProcessInstance.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/instance/impl/
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/instance/impl/ProcessInstance.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IConnection.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IConstraint.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IEndNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IJoin.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/INode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IRuleFlowProcess.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IRuleFlowProcessValidationError.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IRuleFlowProcessValidator.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IRuleSetNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/ISplit.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IStartNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IVariable.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/
   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/Constraint.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/EndNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/Join.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/Node.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/RuleFlowProcess.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/RuleFlowProcessValidationError.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/RuleFlowProcessValidator.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/RuleSetNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/Split.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/StartNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/Variable.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/IRuleFlowNodeInstance.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/IRuleFlowProcessInstance.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/EndNodeInstance.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/RuleFlowJoinInstance.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/RuleFlowNodeInstance.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/RuleFlowProcessInstance.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/RuleFlowSequenceNodeInstance.java
   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/StartNodeInstance.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/RuleFlowGroup.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/RuleFlowGroupTest.java
Removed:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/RuleFlowGroupImpl.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/RuleFlowGroupNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/RuleFlowGroup.java
Modified:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/Agenda.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/RuleBase.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/SynchronizedWorkingMemory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/WorkingMemory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractRuleBase.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AgendaItem.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/DefaultAgenda.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/RuleTerminalNode.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/AgendaTest.java
Log:
JBRULES-619: Rule Flow Core Implementation
 - first implementation of ruleflow in core

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/Agenda.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/Agenda.java	2007-03-01 02:19:52 UTC (rev 9864)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/Agenda.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -20,7 +20,23 @@
     public AgendaGroup getAgendaGroup(String name);
     
     public RuleFlowGroup getRuleFlowGroup(String name);
+    
+    /**
+     * Activates the <code>RuleFlowGroup</code> with the given name.
+     * All activations in the given <code>RuleFlowGroup</code> are added to the agenda.
+     * As long as the <code>RuleFlowGroup</code> remains active,
+     * its activations are automatically added to the agenda. 
+     */
+    public void activateRuleFlowGroup(String name);
 
+    /**
+     * Deactivates the <code>RuleFlowGroup</code> with the given name.
+     * All activations in the given <code>RuleFlowGroup</code> are removed from the agenda.
+     * As long as the <code>RuleFlowGroup</code> remains deactive,
+     * its activations are not added to the agenda
+     */
+    public void deactivateRuleFlowGroup(String name);
+
     public AgendaGroup[] getAgendaGroups();
 
     public AgendaGroup[] getStack();

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/RuleBase.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/RuleBase.java	2007-03-01 02:19:52 UTC (rev 9864)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/RuleBase.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -22,6 +22,7 @@
 import java.util.Set;
 
 import org.drools.rule.Package;
+import org.drools.ruleflow.common.core.IProcess;
 
 /**
  * Active collection of <code>Rule</code>s.
@@ -124,6 +125,12 @@
 
     void removePackage(String packageName);
 
+    void addProcess(IProcess process);
+
+    void removeProcess(String id);
+    
+    IProcess getProcess(String id);
+
     void removeRule(String packageName,
                     String ruleName);
 

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/SynchronizedWorkingMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/SynchronizedWorkingMemory.java	2007-03-01 02:19:52 UTC (rev 9864)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/SynchronizedWorkingMemory.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -21,6 +21,7 @@
 
 import org.drools.event.AgendaEventListener;
 import org.drools.event.WorkingMemoryEventListener;
+import org.drools.ruleflow.common.instance.IProcessInstance;
 import org.drools.spi.AgendaFilter;
 import org.drools.spi.AgendaGroup;
 import org.drools.spi.AsyncExceptionHandler;
@@ -182,4 +183,8 @@
         this.workingMemory.setGlobal( name,
                                       value );
     }
+    
+    public synchronized IProcessInstance startProcess(String processId) {
+    	return this.workingMemory.startProcess(processId);
+    }
 }
\ No newline at end of file

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/WorkingMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/WorkingMemory.java	2007-03-01 02:19:52 UTC (rev 9864)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/WorkingMemory.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -22,6 +22,7 @@
 
 import org.drools.event.AgendaEventListener;
 import org.drools.event.WorkingMemoryEventListener;
+import org.drools.ruleflow.common.instance.IProcessInstance;
 import org.drools.spi.AgendaFilter;
 import org.drools.spi.AgendaGroup;
 import org.drools.spi.AsyncExceptionHandler;
@@ -298,4 +299,9 @@
      * 
      */
     void dispose();
+    
+    /**
+     * Starts a new process instance for the process with the given id. 
+     */
+    IProcessInstance startProcess(String processId);
 }
\ No newline at end of file

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractRuleBase.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractRuleBase.java	2007-03-01 02:19:52 UTC (rev 9864)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractRuleBase.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -43,6 +43,7 @@
 import org.drools.rule.Package;
 import org.drools.rule.PackageCompilationData;
 import org.drools.rule.Rule;
+import org.drools.ruleflow.common.core.IProcess;
 import org.drools.spi.FactHandleFactory;
 
 /**
@@ -68,6 +69,8 @@
 
     protected Map                                   pkgs;
 
+    protected Map                                   processes;
+
     protected transient CompositePackageClassLoader packageClassLoader;
 
     /** The fact handle factory. */
@@ -112,6 +115,7 @@
 
         this.packageClassLoader = new CompositePackageClassLoader( Thread.currentThread().getContextClassLoader() );
         this.pkgs = new HashMap();
+        this.processes = new HashMap();
         this.globals = new HashMap();
         this.workingMemories = new WeakHashMap();
     }
@@ -216,6 +220,10 @@
         return this.factHandleFactory.newInstance();
     }
 
+    public IProcess[] getProcesses() {
+        return (IProcess[]) this.processes.values().toArray( new IProcess[this.processes.size()] );
+    }
+
     public Package[] getPackages() {
         return (Package[]) this.pkgs.values().toArray( new Package[this.pkgs.size()] );
     }
@@ -445,7 +453,19 @@
     }
 
     protected abstract void removeRule(Rule rule);
+    
+    public void addProcess(IProcess process) {
+    	processes.put(process.getId(), process);
+    }
 
+    public void removeProcess(String id) {
+    	processes.remove(id);
+    }
+    
+    public IProcess getProcess(String id) {
+    	return (IProcess) processes.get(id);
+    }
+
     protected void addWorkingMemory(final WorkingMemory workingMemory,
                                     final boolean keepReference) {
         if ( keepReference ) {

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java	2007-03-01 02:19:52 UTC (rev 9864)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -46,6 +46,11 @@
 import org.drools.event.WorkingMemoryEventListener;
 import org.drools.event.WorkingMemoryEventSupport;
 import org.drools.rule.Rule;
+import org.drools.ruleflow.common.core.IProcess;
+import org.drools.ruleflow.common.instance.IProcessInstance;
+import org.drools.ruleflow.core.IRuleFlowProcess;
+import org.drools.ruleflow.instance.IRuleFlowProcessInstance;
+import org.drools.ruleflow.instance.impl.RuleFlowProcessInstance;
 import org.drools.spi.Activation;
 import org.drools.spi.AgendaFilter;
 import org.drools.spi.AgendaGroup;
@@ -1139,5 +1144,21 @@
                            this.activationOrigin );
         }
     }
+    
+    public IProcessInstance startProcess(String processId) {
+    	IProcess process = getRuleBase().getProcess(processId);
+    	if (process == null) {
+    		throw new IllegalArgumentException("Unknown process ID: " + processId);
+    	}
+    	if (process instanceof IRuleFlowProcess) {
+            IRuleFlowProcessInstance processInstance = new RuleFlowProcessInstance();
+            processInstance.setAgenda(agenda);
+            processInstance.setProcess(process);
+            processInstance.start();
+            return processInstance;
+    	} else {
+    		throw new IllegalArgumentException("Unknown process type: " + process.getClass());
+    	}
+    }
 
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AgendaItem.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AgendaItem.java	2007-03-01 02:19:52 UTC (rev 9864)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AgendaItem.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -23,7 +23,6 @@
 import org.drools.spi.Activation;
 import org.drools.spi.AgendaGroup;
 import org.drools.spi.PropagationContext;
-import org.drools.spi.RuleFlowGroup;
 import org.drools.spi.Tuple;
 import org.drools.util.LinkedList;
 import org.drools.util.Queue;
@@ -77,7 +76,7 @@
 
     private ActivationGroupNode      activationGroupNode;
 
-    private RuleFlowGroupNode        ruleFlowGroupNode;
+    private RuleFlowGroupNode     	 ruleFlowGroupNode;
 
     // ------------------------------------------------------------
     // Constructors

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/DefaultAgenda.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/DefaultAgenda.java	2007-03-01 02:19:52 UTC (rev 9864)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/DefaultAgenda.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -265,7 +265,7 @@
     }
 
     public RuleFlowGroup getRuleFlowGroup(final String name) {
-        RuleFlowGroupImpl ruleFlowGroup = (RuleFlowGroupImpl) this.ruleFlowGroups.get( name );
+    	RuleFlowGroup ruleFlowGroup = (RuleFlowGroup) this.ruleFlowGroups.get( name );
         if ( ruleFlowGroup == null ) {
             ruleFlowGroup = new RuleFlowGroupImpl( name );
             this.ruleFlowGroups.put( name,
@@ -273,6 +273,14 @@
         }
         return ruleFlowGroup;
     }
+    
+    public void activateRuleFlowGroup(String name) {
+    	((InternalRuleFlowGroup) getRuleFlowGroup(name)).setActive(true);
+    }
+    
+    public void deactivateRuleFlowGroup(String name) {
+    	((InternalRuleFlowGroup) getRuleFlowGroup(name)).setActive(false);
+    }
 
     /* (non-Javadoc)
      * @see org.drools.common.AgendaI#focusStackSize()
@@ -371,8 +379,12 @@
                 item.getActivationGroupNode().getActivationGroup().removeActivation( item );
             }
 
-            eventsupport.getAgendaEventSupport().fireActivationCancelled( item,
-                                                                          this.workingMemory );
+            if ( item.getRuleFlowGroupNode() != null ) {
+                final InternalRuleFlowGroup ruleFlowGroup = item.getRuleFlowGroupNode().getRuleFlowGroup();
+                ruleFlowGroup.removeActivation( item );
+            }
+
+            eventsupport.getAgendaEventSupport().fireActivationCancelled( item, this.workingMemory  );
         }
         ((AgendaGroupImpl) agendaGroup).clear();
     }
@@ -401,8 +413,13 @@
             if ( activation.isActivated() ) {
                 activation.setActivated( false );
                 activation.remove();
-                eventsupport.getAgendaEventSupport().fireActivationCancelled( activation,
-                                                                              this.workingMemory );
+                
+                if ( activation.getRuleFlowGroupNode() != null ) {
+                    final InternalRuleFlowGroup ruleFlowGroup = activation.getRuleFlowGroupNode().getRuleFlowGroup();
+                    ruleFlowGroup.removeActivation( activation );
+                }
+
+                eventsupport.getAgendaEventSupport().fireActivationCancelled( activation, this.workingMemory  );
             }
         }
         activationGroup.clear();
@@ -473,15 +490,8 @@
         }
 
         if ( activation.getRuleFlowGroupNode() != null ) {
-            // Now the rule has fired, remove it and check if the rule flow group is empty
-            // if its empty, activate the child groups. We do this after the consequence 
-            // fired as we don't want to populate the Agenda prior to the rule actually firing.
-            final RuleFlowGroup ruleFlowGroup = activation.getRuleFlowGroupNode().getRuleFlowGroup();
+            final InternalRuleFlowGroup ruleFlowGroup = activation.getRuleFlowGroupNode().getRuleFlowGroup();
             ruleFlowGroup.removeActivation( activation );
-
-            if ( ruleFlowGroup.isEmpty() ) {
-                ruleFlowGroup.activateChildren();
-            }
         }
 
         eventsupport.getAgendaEventSupport().fireAfterActivationFired( activation );                        

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InternalRuleFlowGroup.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InternalRuleFlowGroup.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InternalRuleFlowGroup.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,25 @@
+package org.drools.common;
+
+import org.drools.spi.Activation;
+import org.drools.spi.RuleFlowGroup;
+
+public interface InternalRuleFlowGroup extends RuleFlowGroup {
+
+    void addActivation(Activation activation);
+
+    void removeActivation(Activation activation);
+    
+    /**
+     * Activates or deactivates this <code>RuleFlowGroup</code>.
+     * When activating, all activations of this <code>RuleFlowGroup</code> are added
+     * to the agenda.
+     * As long as the <code>RuleFlowGroup</code> remains active,
+     * its activations are automatically added to the agenda. 
+     * When deactivating, all activations of this <code>RuleFlowGroup</code> are removed
+     * to the agenda.
+     * As long as the <code>RuleFlowGroup</code> remains deactive,
+     * its activations are not added to the agenda. 
+     */
+    void setActive(boolean active);
+
+}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/RuleFlowGroupImpl.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/RuleFlowGroupImpl.java	2007-03-01 02:19:52 UTC (rev 9864)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/RuleFlowGroupImpl.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -1,195 +0,0 @@
-package org.drools.common;
-
-/*
- * 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.
- */
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import org.drools.conflict.DepthConflictResolver;
-import org.drools.spi.Activation;
-import org.drools.spi.AgendaGroup;
-import org.drools.spi.RuleFlowGroup;
-import org.drools.util.BinaryHeapQueue;
-import org.drools.util.Iterator;
-import org.drools.util.LinkedList;
-import org.drools.util.ObjectHashMap;
-import org.drools.util.Queueable;
-import org.drools.util.LinkedList.LinkedListIterator;
-
-/**
- * <code>AgendaGroup</code> implementation that uses a <code>PriorityQueue</code> to prioritise the evaluation of added
- * <code>ActivationQueue</code>s. The <code>AgendaGroup</code> also maintains a <code>Map</code> of <code>ActivationQueues</code> 
- * for requested salience values.
- * 
- * @see PriorityQueue
- * @see ActivationQueue
- * 
- * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
- * @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
- *
- */
-public class RuleFlowGroupImpl
-    implements
-    RuleFlowGroup {
-
-    private static final long serialVersionUID = 320L;
-
-    private final String      name;
-
-    private final LinkedList  list;
-
-    private List              childNodes       = Collections.EMPTY_LIST;
-
-    /**
-     * Construct an <code>AgendaGroup</code> with the given name.
-     * 
-     * @param name
-     *      The <AgendaGroup> name.
-     */
-    public RuleFlowGroupImpl(final String name) {
-        this.name = name;
-        this.list = new LinkedList();
-    }
-
-    /* (non-Javadoc)
-     * @see org.drools.spi.AgendaGroup#getName()
-     */
-    /* (non-Javadoc)
-     * @see org.drools.common.RuleFlowGroup#getName()
-     */
-    public String getName() {
-        return this.name;
-    }
-
-    /* (non-Javadoc)
-     * @see org.drools.common.RuleFlowGroup#addChild(org.drools.common.RuleFlowGroup)
-     */
-    public void addChild(final RuleFlowGroup child) {
-        if ( this.childNodes == Collections.EMPTY_LIST ) {
-            this.childNodes = new ArrayList( 1 );
-        }
-        this.childNodes.add( child );
-    }
-
-    /* (non-Javadoc)
-     * @see org.drools.common.RuleFlowGroup#removeChild(org.drools.common.RuleFlowGroup)
-     */
-    public boolean removeChild(final RuleFlowGroup child) {
-        return this.childNodes.remove( child );
-    }
-
-    /* (non-Javadoc)
-     * @see org.drools.common.RuleFlowGroup#activate()
-     */
-    public void activate() {
-        // iterate all activations adding them to their AgendaGroups
-        LinkedListIterator it = this.list.iterator();
-        for ( RuleFlowGroupNode node = (RuleFlowGroupNode) it.next(); node != null; node = (RuleFlowGroupNode) it.next() ) {
-            Activation activation = node.getActivation();
-            ( (AgendaGroupImpl) activation.getAgendaGroup() ).add( activation );
-        }
-    }
-
-    /* (non-Javadoc)
-     * @see org.drools.common.RuleFlowGroup#activateChildren()
-     */
-    public void activateChildren() {
-        // do we have any children still to fire, if so remove them from the AgendaGroups
-        if ( !this.list.isEmpty() ) {
-            clear();
-        }
-
-        // iterate all children calling activate
-        for ( java.util.Iterator it = this.childNodes.iterator(); it.hasNext(); ) {
-            ((RuleFlowGroup) it.next() ).activate();
-        }
-    }
-
-    /* (non-Javadoc)
-     * @see org.drools.common.RuleFlowGroup#clear()
-     */
-    public void clear() {
-        LinkedListIterator it = this.list.iterator();
-        for ( RuleFlowGroupNode node = (RuleFlowGroupNode) it.next(); node != null; node = (RuleFlowGroupNode) it.next() ) {
-            Activation activation = node.getActivation();
-            activation.remove();
-        }
-    }
-
-    /* (non-Javadoc)
-     * @see org.drools.spi.AgendaGroup#size()
-     */
-    /* (non-Javadoc)
-     * @see org.drools.common.RuleFlowGroup#size()
-     */
-    public int size() {
-        return this.list.size();
-    }
-
-    public void addActivation(final Activation activation) {
-        final RuleFlowGroupNode node = new RuleFlowGroupNode( activation,
-                                                              this );
-        activation.setRuleFlowGroupNode( node );
-        this.list.add( node );
-    }
-
-    public void removeActivation(final Activation activation) {
-        final RuleFlowGroupNode node = activation.getRuleFlowGroupNode();
-        this.list.remove( node );
-        activation.setActivationGroupNode( null );
-    }
-
-    /* (non-Javadoc)
-     * @see org.drools.common.RuleFlowGroup#isEmpty()
-     */
-    public boolean isEmpty() {
-        return this.list.isEmpty();
-    }
-
-    /* (non-Javadoc)
-     * @see org.drools.common.RuleFlowGroup#getActivations()
-     */
-    public Activation[] getActivations() {
-        //return (Activation[]) this.activations.toArray( new AgendaItem[this.queue.size()] );
-        return null;
-    }
-    
-    public java.util.Iterator iterator() {
-        return this.list.javaUtilIterator();
-    }
-
-    public String toString() {
-        return "RuleFlowGroup '" + this.name + "'";
-    }
-
-    public boolean equal(final Object object) {
-        if ( (object == null) || !(object instanceof RuleFlowGroupImpl) ) {
-            return false;
-        }
-
-        if ( ((RuleFlowGroupImpl) object).name.equals( this.name ) ) {
-            return true;
-        }
-
-        return false;
-    }
-
-    public int hashCode() {
-        return this.name.hashCode();
-    }
-}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/RuleFlowGroupImpl.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/RuleFlowGroupImpl.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/RuleFlowGroupImpl.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,172 @@
+package org.drools.common;
+/*
+ * 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.
+ */
+
+import org.drools.ruleflow.instance.IRuleFlowNodeInstance;
+import org.drools.ruleflow.instance.impl.RuleFlowSequenceNodeInstance;
+import org.drools.spi.Activation;
+import org.drools.util.LinkedList;
+import org.drools.util.LinkedList.LinkedListIterator;
+
+/**
+ * Implementation of a <code>RuleFlowGroup</code> that collects activations
+ * of rules of this ruleflow-group.
+ * If this group is activated, all its activations are added to the agenda.
+ * As long as this group is active, its activations are added to the agenda.
+ * Deactivating the group removes all its activations from the agenda and
+ * collects them until it is activated again.
+ * By default, <code>RuleFlowGroups</code> are automatically deactivated when there are no more
+ * activations in the <code>RuleFlowGroup</code>.  However, this can be configured.  
+ * 
+ * @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ *
+ */
+public class RuleFlowGroupImpl extends RuleFlowSequenceNodeInstance implements InternalRuleFlowGroup {
+
+    private static final long serialVersionUID = 320L;
+
+    private final String      name;
+    private boolean active = false;
+    private final LinkedList  list;
+    private boolean autoDeactivate = true;
+
+    /**
+     * Construct a <code>RuleFlowGroupImpl</code> with the given name.
+     * 
+     * @param name
+     *      The RuleFlowGroup name.
+     */
+    public RuleFlowGroupImpl(final String name) {
+        this.name = name;
+        this.list = new LinkedList();
+    }
+
+    public String getName() {
+        return this.name;
+    }
+    
+    public void setActive(boolean active) {
+    	if (this.active == active) {
+    		return;
+    	}
+    	this.active = active;
+    	if (active) {
+    		triggerActivations();
+    	} else {
+            LinkedListIterator it = this.list.iterator();
+            for (RuleFlowGroupNode node = (RuleFlowGroupNode) it.next(); node != null; node = (RuleFlowGroupNode) it.next()) {
+                Activation activation = node.getActivation();
+                activation.remove();
+                if ( activation.getActivationGroupNode() != null ) {
+                	activation.getActivationGroupNode().getActivationGroup().removeActivation( activation );
+                }
+            }
+    	}
+    }
+    
+    public boolean isActive() {
+    	return active;
+    }
+    
+    public boolean isAutoDeactivate() {
+    	return autoDeactivate;
+    }
+    
+    public void setAutoDeactivate(boolean autoDeactivate) {
+    	this.autoDeactivate = autoDeactivate;
+    	if (autoDeactivate && active && list.isEmpty()) {
+    		active = false;
+    	}
+    }
+
+    private void triggerActivations() {
+        // iterate all activations adding them to their AgendaGroups
+        LinkedListIterator it = this.list.iterator();
+        for (RuleFlowGroupNode node = (RuleFlowGroupNode) it.next(); node != null; node = (RuleFlowGroupNode) it.next()) {
+            Activation activation = node.getActivation();
+            ((AgendaGroupImpl) activation.getAgendaGroup()).add(activation);
+        }
+    }
+
+    public void clear() {
+        LinkedListIterator it = this.list.iterator();
+        for (RuleFlowGroupNode node = (RuleFlowGroupNode) it.next(); node != null; node = (RuleFlowGroupNode) it.next()) {
+            node.getActivation().remove();
+        }
+    }
+
+    public int size() {
+        return this.list.size();
+    }
+
+    public void addActivation(final Activation activation) {
+        final RuleFlowGroupNode node = new RuleFlowGroupNode(activation, this);
+        activation.setRuleFlowGroupNode(node);
+    	list.add( node );
+        if (active) {
+        	((AgendaGroupImpl) activation.getAgendaGroup()).add(activation);
+        }
+    }
+
+    public void removeActivation(final Activation activation) {
+        final RuleFlowGroupNode node = activation.getRuleFlowGroupNode();
+        list.remove(node);
+        activation.setActivationGroupNode(null);
+        if (autoDeactivate) {
+        	if (list.isEmpty()) {
+        		this.active = false;
+        		// only trigger next node if this RuleFlowGroup was
+        		// triggered from inside a process instance
+        		if (getProcessInstance() != null) {
+        			triggerCompleted();
+        		}
+        	}
+        }
+    }
+
+    public boolean isEmpty() {
+        return this.list.isEmpty();
+    }
+
+    public java.util.Iterator iterator() {
+        return this.list.javaUtilIterator();
+    }
+
+    public String toString() {
+        return "RuleFlowGroup '" + this.name + "'";
+    }
+
+    public boolean equal(final Object object) {
+        if ( (object == null) || !(object instanceof RuleFlowGroupImpl) ) {
+            return false;
+        }
+
+        if ( ((RuleFlowGroupImpl) object).name.equals( this.name ) ) {
+            return true;
+        }
+
+        return false;
+    }
+
+    public int hashCode() {
+        return this.name.hashCode();
+    }
+
+	public void trigger(IRuleFlowNodeInstance parent) {
+		setActive(true);
+	}
+}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/RuleFlowGroupNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/RuleFlowGroupNode.java	2007-03-01 02:19:52 UTC (rev 9864)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/RuleFlowGroupNode.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -1,29 +0,0 @@
-package org.drools.common;
-
-import org.drools.spi.Activation;
-import org.drools.spi.ActivationGroup;
-import org.drools.spi.RuleFlowGroup;
-import org.drools.util.AbstractBaseLinkedListNode;
-
-public class RuleFlowGroupNode extends AbstractBaseLinkedListNode {
-
-    private Activation    activation;
-
-    private RuleFlowGroup ruleFlowGroup;
-
-    public RuleFlowGroupNode(final Activation activation,
-                             final RuleFlowGroup ruleFlowGroup) {
-        super();
-        this.activation = activation;
-        this.ruleFlowGroup = ruleFlowGroup;
-    }
-
-    public Activation getActivation() {
-        return this.activation;
-    }
-
-    public RuleFlowGroup getRuleFlowGroup() {
-        return this.ruleFlowGroup;
-    }
-
-}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/RuleFlowGroupNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/RuleFlowGroupNode.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/RuleFlowGroupNode.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,43 @@
+package org.drools.common;
+/*
+ * 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.
+ */
+
+import org.drools.spi.Activation;
+import org.drools.util.AbstractBaseLinkedListNode;
+
+public class RuleFlowGroupNode extends AbstractBaseLinkedListNode {
+
+	private static final long serialVersionUID = -6507208076979260126L;
+
+	private Activation    activation;
+    private InternalRuleFlowGroup ruleFlowGroup;
+
+    public RuleFlowGroupNode(final Activation activation,
+                             final InternalRuleFlowGroup ruleFlowGroup) {
+        super();
+        this.activation = activation;
+        this.ruleFlowGroup = ruleFlowGroup;
+    }
+
+    public Activation getActivation() {
+        return this.activation;
+    }
+
+    public InternalRuleFlowGroup getRuleFlowGroup() {
+        return this.ruleFlowGroup;
+    }
+
+}

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/RuleTerminalNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/RuleTerminalNode.java	2007-03-01 02:19:52 UTC (rev 9864)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/RuleTerminalNode.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -22,12 +22,11 @@
 import org.drools.common.AgendaGroupImpl;
 import org.drools.common.AgendaItem;
 import org.drools.common.BaseNode;
-import org.drools.common.DefaultAgenda;
 import org.drools.common.InternalAgenda;
+import org.drools.common.InternalRuleFlowGroup;
 import org.drools.common.InternalWorkingMemory;
 import org.drools.common.NodeMemory;
 import org.drools.common.PropagationContextImpl;
-import org.drools.common.RuleFlowGroupImpl;
 import org.drools.common.ScheduledAgendaItem;
 import org.drools.rule.GroupElement;
 import org.drools.rule.Rule;
@@ -225,6 +224,7 @@
                 memory.getActivationGroup().addActivation( item );
             }
 
+            item.setAgendaGroup( agendaGroup );
             if ( this.rule.getRuleFlowGroup() == null ) {
                 // No RuleFlowNode so add  it directly to  the Agenda
 
@@ -239,11 +239,9 @@
                 if ( memory.getRuleFlowGroup() == null ) {
                     memory.setRuleFlowGroup( workingMemory.getAgenda().getRuleFlowGroup( this.rule.getRuleFlowGroup() ) );
                 }
-                memory.getRuleFlowGroup().addActivation( item );
-            }
+                ((InternalRuleFlowGroup) memory.getRuleFlowGroup()).addActivation( item );
+            }  
 
-            item.setAgendaGroup( agendaGroup );
-
             tuple.setActivation( item );
             memory.getTupleMemory().add( tuple );
 
@@ -269,9 +267,14 @@
             activation.remove();
 
             if ( activation.getActivationGroupNode() != null ) {
-                activation.getActivationGroupNode().getActivationGroup().removeActivation( activation );
+            	activation.getActivationGroupNode().getActivationGroup().removeActivation( activation );
             }
 
+            if ( activation.getRuleFlowGroupNode() != null ) {
+                final InternalRuleFlowGroup ruleFlowGroup = activation.getRuleFlowGroupNode().getRuleFlowGroup();
+                ruleFlowGroup.removeActivation( activation );
+            }
+
             workingMemory.getAgendaEventSupport().fireActivationCancelled( activation,
                                                                            workingMemory );
             ((InternalAgenda) workingMemory.getAgenda()).decreaseActiveActivations();

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/core/IProcess.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/core/IProcess.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/core/IProcess.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,76 @@
+package org.drools.ruleflow.common.core;
+/*
+ * 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.
+ */
+
+/**
+ * Represents a some process definition.
+ * A process has a name and a unique id.
+ * When a new version of a process is created, the name stays the same,
+ * but the id and the version of the process should be different.
+ * Different types of processes could be defined (like RuleFlow).
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface IProcess {
+
+    /**
+     * Sets the id of this process.
+     * The id should uniquely identify this process.
+     * @param id the id of the process
+     */
+    void setId(String id);
+    /**
+     * Returns the id of this process.
+     * @return the id of this process
+     */
+    String getId();
+    
+    /**
+     * Sets the name of this process.
+     * @param name the name of this process
+     */
+    void setName(String name);
+    /**
+     * Returns the name of this process.
+     * If no name is specified, null is returned.
+     * @return the name of this process
+     */
+    String getName();
+    
+    /**
+     * Sets the version of this process.
+     * @param version the version of this process
+     */
+    void setVersion(String version);
+    /**
+     * Returns the version of this process.
+     * If no version is specified, null is returned.
+     * @return the version of this process
+     */
+    String getVersion();
+    
+    /**
+     * Sets the type of this process.
+     * @param type the type of this process
+     */
+    void setType(String type);
+    /**
+     * Returns the type of this process.
+     * @return the type of this process
+     */
+    String getType();
+    
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/core/impl/Process.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/core/impl/Process.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/core/impl/Process.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,78 @@
+package org.drools.ruleflow.common.core.impl;
+/*
+ * 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.
+ */
+
+import java.io.Serializable;
+
+import org.drools.ruleflow.common.core.IProcess;
+
+/**
+ * Default implementation of a Process
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class Process implements IProcess, Serializable {
+    private static final long serialVersionUID = 3904955335549399096L;
+    
+    private String id;
+    private String name;
+    private String version;
+    private String type;
+    
+    public void setId(String id) {
+        this.id = id;
+    }
+    
+    public String getId() {
+        return id;
+    }
+    
+    public void setName(String name) {
+        this.name = name;
+    }
+    
+    public String getName() {
+        return name;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+    
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+    
+    public boolean equals(Object o) {
+        if (o instanceof Process) {
+            return ((Process) o).getName().equals(name)
+                && ((Process) o).getVersion().equals(version);
+        }
+        return false;
+    }
+    
+    public int hashCode() {
+        return name.hashCode() + 3*version.hashCode();
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/IDataType.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/IDataType.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/IDataType.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,33 @@
+package org.drools.ruleflow.common.datatype;
+/*
+ * 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.
+ */
+
+import java.io.Serializable;
+
+/**
+ * Abstract representation of a datatype.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface IDataType extends Serializable {
+	
+	
+	/**
+	 * Returns true if the given value is a valid value of this data type.
+	 */
+	boolean verifyDataType(Object value);
+    
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/IDataTypeFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/IDataTypeFactory.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/IDataTypeFactory.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,27 @@
+package org.drools.ruleflow.common.datatype;
+/*
+ * 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.
+ */
+
+/**
+ * A factory for creating a datatype.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface IDataTypeFactory {
+    
+    IDataType createDataType();
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/InstanceDataTypeFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/InstanceDataTypeFactory.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/InstanceDataTypeFactory.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,48 @@
+package org.drools.ruleflow.common.datatype.impl;
+/*
+ * 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.
+ */
+
+import org.drools.ruleflow.common.datatype.IDataType;
+import org.drools.ruleflow.common.datatype.IDataTypeFactory;
+
+/**
+ * A data type factory that always returns the same instance of a given class.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class InstanceDataTypeFactory implements IDataTypeFactory {
+    
+    private Class dataTypeClass;
+    private IDataType instance;
+    
+    public InstanceDataTypeFactory(Class dataTypeClass) {
+        this.dataTypeClass = dataTypeClass;
+    }
+    
+    public IDataType createDataType() {
+        if (instance == null) {
+            try {
+                instance = (IDataType) dataTypeClass.newInstance();
+            } catch (IllegalAccessException e) {
+                throw new RuntimeException("Could not create data type for class " + dataTypeClass, e);
+            } catch (InstantiationException e) {
+            	throw new RuntimeException("Could not create data type for class " + dataTypeClass, e);
+            }
+        }
+        return instance;
+    }
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/NewInstanceDataTypeFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/NewInstanceDataTypeFactory.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/NewInstanceDataTypeFactory.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,44 @@
+package org.drools.ruleflow.common.datatype.impl;
+/*
+ * 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.
+ */
+
+import org.drools.ruleflow.common.datatype.IDataType;
+import org.drools.ruleflow.common.datatype.IDataTypeFactory;
+
+/**
+ * A data type factory that always returns a new instance of a given class.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class NewInstanceDataTypeFactory implements IDataTypeFactory {
+    
+    private Class dataTypeClass;
+    
+    public NewInstanceDataTypeFactory(Class dataTypeClass) {
+        this.dataTypeClass = dataTypeClass;
+    }
+    
+    public IDataType createDataType() {
+        try {
+            return (IDataType) dataTypeClass.newInstance();
+        } catch (IllegalAccessException e) {
+        	throw new RuntimeException("Could not create data type for class " + dataTypeClass, e);
+        } catch (InstantiationException e) {
+        	throw new RuntimeException("Could not create data type for class " + dataTypeClass, e);
+        }
+    }
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/BooleanDataType.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/BooleanDataType.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/BooleanDataType.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,35 @@
+package org.drools.ruleflow.common.datatype.impl.type;
+/*
+ * 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.
+ */
+
+import org.drools.ruleflow.common.datatype.IDataType;
+
+/**
+ * Representation of a boolean datatype.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public final class BooleanDataType implements IDataType {
+    
+    private static final long serialVersionUID = 3617855257384989752L;
+    
+    public boolean verifyDataType(Object value) {
+    	if (value instanceof Boolean) {
+    		return true;
+    	}
+        return false;
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/FloatDataType.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/FloatDataType.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/FloatDataType.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,38 @@
+package org.drools.ruleflow.common.datatype.impl.type;
+/*
+ * 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.
+ */
+
+import org.drools.ruleflow.common.datatype.IDataType;
+
+/**
+ * Representation of a float datatype.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public final class FloatDataType implements IDataType {
+
+    private static final long serialVersionUID = 3257008760991069747L;
+
+    public boolean verifyDataType(Object value) {
+    	if (value instanceof Float) {
+    		return true;
+    	} else if (value == null) {
+    		return true;
+    	} else {
+    		return false;
+    	}
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/IntegerDataType.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/IntegerDataType.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/IntegerDataType.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,38 @@
+package org.drools.ruleflow.common.datatype.impl.type;
+/*
+ * 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.
+ */
+
+import org.drools.ruleflow.common.datatype.IDataType;
+
+/**
+ * Representation of an integer datatype.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class IntegerDataType implements IDataType {
+
+    private static final long serialVersionUID = 3256443611980838707L;
+
+    public boolean verifyDataType(Object value) {
+    	if (value instanceof Integer) {
+    		return true;
+    	} else if (value == null) {
+    		return true;
+    	} else {
+    		return false;
+    	}
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/ListDataType.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/ListDataType.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/ListDataType.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,58 @@
+package org.drools.ruleflow.common.datatype.impl.type;
+/*
+ * 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.
+ */
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+
+import org.drools.ruleflow.common.datatype.IDataType;
+
+/**
+ * Representation of a list datatype.
+ * All elements in the list must have the same datatype.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class ListDataType implements IDataType, Serializable {
+    
+    private static final long serialVersionUID = 3689069551774415161L;
+
+    private IDataType dataType;
+    
+    public void setDataType(IDataType dataType) {
+        this.dataType = dataType;
+    }
+    
+    public IDataType getDataType() {
+        return dataType;
+    }
+
+    public boolean verifyDataType(Object value) {
+    	if (value == null) {
+    		return true;    		
+    	}
+    	if (value instanceof List) {
+            for (Iterator it = ((List) value).iterator(); it.hasNext(); ) {
+                if (!dataType.verifyDataType(it.next())) {
+                    return false;
+                }
+            }
+            return true;
+    	}
+    	return false;
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/StringDataType.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/StringDataType.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/StringDataType.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,38 @@
+package org.drools.ruleflow.common.datatype.impl.type;
+/*
+ * 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.
+ */
+
+import org.drools.ruleflow.common.datatype.IDataType;
+
+/**
+ * Representation of a string datatype.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class StringDataType implements IDataType {
+
+    private static final long serialVersionUID = 3258416135924758834L;
+
+    public boolean verifyDataType(Object value) {
+    	if (value instanceof String) {
+    		return true;
+    	} else if (value == null) {
+    		return true;
+    	} else {
+    		return false;
+    	}
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/UndefinedDataType.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/UndefinedDataType.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/datatype/impl/type/UndefinedDataType.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,43 @@
+package org.drools.ruleflow.common.datatype.impl.type;
+/*
+ * 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.
+ */
+
+import org.drools.ruleflow.common.datatype.IDataType;
+
+/**
+ * Representation of an undefined datatype.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public final class UndefinedDataType implements IDataType {
+    
+    private static final long serialVersionUID = 3690196546763699768L;
+    private static UndefinedDataType instance;
+    
+    public static UndefinedDataType getInstance() {
+        if (instance == null) {
+            instance = new UndefinedDataType();
+        }
+        return instance;
+    }
+
+    public boolean verifyDataType(Object value) {
+    	if (value == null) {
+    		return true;
+    	}
+		return false;
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/instance/IProcessInstance.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/instance/IProcessInstance.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/instance/IProcessInstance.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,46 @@
+package org.drools.ruleflow.common.instance;
+/*
+ * 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.
+ */
+
+import java.io.Serializable;
+
+import org.drools.ruleflow.common.core.IProcess;
+
+/**
+ * A process instance is the representation of a process during its execution.
+ * It contains all the runtime status information about the running process.
+ * A process can have multiple instances.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface IProcessInstance extends Serializable {
+
+	int STATE_PENDING = 0;
+	int STATE_ACTIVE = 1;
+	int STATE_COMPLETED = 2;
+	int STATE_ABORTED = 3;
+	int STATE_SUSPENDED = 4;
+
+	void setId(long id);
+    long getId();
+    
+    void setProcess(IProcess process);
+    IProcess getProcess();
+    
+    void setState(int state);
+    int getState();
+    
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/instance/impl/ProcessInstance.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/instance/impl/ProcessInstance.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/common/instance/impl/ProcessInstance.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,66 @@
+package org.drools.ruleflow.common.instance.impl;
+/*
+ * 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.
+ */
+
+import org.drools.ruleflow.common.core.IProcess;
+import org.drools.ruleflow.common.instance.IProcessInstance;
+
+/**
+ * Default implementation of a process instance.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public abstract class ProcessInstance implements IProcessInstance {
+
+    private long id;
+    private IProcess process;
+    private int state = STATE_PENDING;
+    
+    public void setId(long id) {
+        this.id = id;
+    }
+    
+    public long getId() {
+        return id;
+    }
+    
+    public void setProcess(IProcess process) {
+        this.process = process;
+    }
+    
+    public IProcess getProcess() {
+        return process;
+    }
+    
+    public void setState(int state) {
+        this.state = state;
+    }
+    
+    public int getState() {
+        return state;
+    }
+    
+    public String toString() {
+    	StringBuilder b = new StringBuilder("ProcessInstance ");
+    	b.append(getId());
+    	b.append(" [processId=");
+    	b.append(process.getId());
+    	b.append(",state=");
+    	b.append(state);
+    	b.append("]");
+    	return b.toString();
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IConnection.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IConnection.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IConnection.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,57 @@
+package org.drools.ruleflow.core;
+/*
+ * 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.
+ */
+
+/**
+ * Represents a connection between two nodes in a RuleFlow. 
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface IConnection {
+    
+	/**
+	 * The connection type
+	 */
+	int TYPE_NORMAL = 1;
+	int TYPE_ABORT = 2;
+	
+	/**
+	 * Returns the from node of the connection.
+	 * @return the from node of the connection.
+	 */
+    INode getFrom();    
+
+    /**
+     * Returns the to node of the connection
+     * @return the to node of the connection
+     */
+    INode getTo();    
+
+    /**
+     * Returns the connection type
+     * @return the connection type
+     */
+    int getType();
+    
+    /**
+     * Destroys the connection. This method also removes the
+     * connection on the <code>to</code> and <code>from</code> nodes.
+     * Onces a connection is destroyed, all methods throw
+     * an <code>IllegalStateException</code>.
+     */
+    void terminate();
+        
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IConstraint.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IConstraint.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IConstraint.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,64 @@
+package org.drools.ruleflow.core;
+/*
+ * 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.
+ */
+
+/**
+ * Represents a constraint in a RuleFlow.
+ * Can be used to specify conditions in (X)OR-splits. 
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface IConstraint {
+
+	/**
+	 * Typically this method returns the constraint
+	 * @return the constraint
+	 */
+	String getConstraint();
+	
+	/**
+	 * Method for setting the constraint
+	 * @param constraint 	the constraint
+	 */
+    void setConstraint(String constraint);
+    
+    /**
+     * Returns the name of the constraint
+     * @return the name of the constraint
+     */
+    String getName();
+    
+    /**
+     * Sets the name of the constraint
+     * @param name	the name of the constraint
+     */
+    void setName(String name);
+
+    /**
+     * Returns the priority of the constriant
+     * 
+     * @return the priority of the constraint
+     */
+    int getPriority();
+    
+    /**
+     * Method for setting the priority of the constraint
+     * 
+     * @param priority	the priority of the constraint
+     */
+    void setPriority(int priority);
+    
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IEndNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IEndNode.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IEndNode.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,33 @@
+package org.drools.ruleflow.core;
+/*
+ * 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.
+ */
+
+
+/**
+ * Represents an end node in a RuleFlow. 
+ * An end node has one incoming and no outgoing connections.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface IEndNode extends INode {
+    
+	/**
+	 * Convenience method for returning the incoming <code>IConnection</code>.
+	 * @return the incoming <code>IConnection</code>
+	 */
+    IConnection getFrom();
+    
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IJoin.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IJoin.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IJoin.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,64 @@
+package org.drools.ruleflow.core;
+/*
+ * 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.
+ */
+
+/**
+ * Represents a join node in a RuleFlow. 
+ * A join is a special kind of node with multiple incoming connections and
+ * one outgoing connection.  The type of join decides when the outgoing
+ * connections will be triggered (based on which incoming connections have
+ * been triggered).
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface IJoin extends INode {
+		
+    int TYPE_UNDEFINED = 0;
+    /**
+     * The outgoing connection of a join of this type is triggered
+     * when all its incoming connections have been triggered.
+     */ 
+    int TYPE_AND = 1;
+    /**
+     * The outgoing connection of a join of this type is triggered
+     * when one of its incoming connections has been triggered.
+     */ 
+    int TYPE_XOR = 2;
+    
+    /**
+     * Sets the type of the join.
+     * 
+     * @param type	The type of the join
+     * @throws IllegalArgumentException if type is null
+     */
+    void setType(int type);	
+    
+    /**
+     * Returns the type of the join.
+     * 
+     * @return the type of the join.
+     */    
+    int getType();
+        
+    /**
+     * Convenience method for returning the outgoing connection of the join
+     * 
+     * @return the outgoing connection of the join
+     */
+    IConnection getTo();
+        
+    
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/INode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/INode.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/INode.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,68 @@
+package org.drools.ruleflow.core;
+/*
+ * 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.
+ */
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * Represents a node in a RuleFlow. 
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface INode extends Serializable {
+    
+	/**
+	 * Returns the id of the node
+	 * 
+	 * @return the id of the node
+	 */
+    long getId();
+    
+    /**
+     * Method for setting the id of the node
+     * 
+     * @param id	the id of the node
+     */
+    void setId(long id);
+    
+    /**
+     * Returns the name of the node
+     * 
+     * @return the name of the node
+     */
+    String getName();
+    
+    /**
+     * Method for setting the name of the node
+     * 
+     * @param name 	the name of the node
+     */
+    void setName(String name);
+    
+    /**
+     * Returns the incoming connections
+     * @return the incoming connections 
+     */
+    List getIncomingConnections();
+    
+    /**
+     * Returns the outgoing connections
+     * @return the outgoing connections 
+     */
+    List getOutgoingConnections();
+        
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IRuleFlowProcess.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IRuleFlowProcess.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IRuleFlowProcess.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,91 @@
+package org.drools.ruleflow.core;
+/*
+ * 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.
+ */
+
+import java.util.List;
+
+import org.drools.ruleflow.common.core.IProcess;
+
+/**
+ * Represents a RuleFlow process. 
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface IRuleFlowProcess extends IProcess {
+    
+	/**
+	 * Returns the start node of this RuleFlow process.
+	 * 
+	 * @return	the start node
+	 */
+    IStartNode getStart();
+    
+    
+    /**
+     * Returns the nodes of this RuleFlow process.
+     * 
+     * @return	the nodes of this RuleFlow process
+     */
+    INode[] getNodes();
+    
+    /**
+     * Returns the node with the given id
+     * 
+     * @param id	the node id
+     * @return	the node with the given id
+     * @throws IllegalArgumentException if an unknown id is passed
+     */
+    INode getNode(long id);
+    
+	/**
+	 * Method for adding a node to this RuleFlow process. 
+	 * Note that the node will get an id unique for this process.
+	 * 
+	 * @param node	the node to be added
+	 * @throws IllegalArgumentException if <code>node</code> is null 
+	 */
+    void addNode(INode node);
+	
+    /**
+     * Method for removing a node from this RuleFlow process
+     * 
+     * @param node	the node to be removed
+     * @throws IllegalArgumentException if <code>node</code> is null or unknown
+     */
+    void removeNode(INode node);
+    
+    /**
+     * Returns the global variables used in this RuleFlow process
+     * 
+     * @return	a list of variables of this RuleFlow process
+     */
+    List getVariables();
+    
+    /**
+     * Sets the global variables used in this RuleFlow process
+     * 
+     * @param variables	the variables
+     * @throws IllegalArugmentException if <code>variables</code> is null
+     */
+    void setVariables(List variables);
+    
+    /**
+     * Returns the names of the global variables used in this RuleFlow process
+     * 
+     * @return	the variable names of this RuleFlow process
+     */
+    String[] getVariableNames();
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IRuleFlowProcessValidationError.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IRuleFlowProcessValidationError.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IRuleFlowProcessValidationError.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,45 @@
+package org.drools.ruleflow.core;
+/*
+ * 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.
+ */
+
+/**
+ * Represents a RuleFlow validation error. 
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface IRuleFlowProcessValidationError {
+
+	String NO_PROCESS_NAME = "RuleFlow process has no name.";
+	String NO_PROCESS_ID = "RuleFlow process has no id.";
+	String NO_START_NODE = "RuleFlow process has no start node.";
+	String START_NODE_WITHOUT_OUTGOING_NODES = "Start node has no outgoing connection.";
+	String END_NODE_HAS_NO_INCOMING_CONNECTIONS = "End node has no incoming connection.";
+	String NO_END_NODE = "No end node found.";
+	String RULE_SET_NODE_WITHOUT_INCOMING_CONNECTIONS = "RuleSet node has no incoming connection.";
+	String RULE_SET_NODE_WITHOUT_OUTGOING_CONNECTIONS = "RuleSet node has no outgoing connection.";
+	String RULE_SET_NODE_WITHOUT_RULE_SET_GROUP = "RuleSet node has no ruleflow-group specified.";
+	String SPLIT_WITHOUT_TYPE = "Split node has no type.";
+	String SPLIT_WITHOUT_INCOMING_CONNECTION = "Split node has no incoming connection.";
+	String SPLIT_NOT_ENOUGH_OUTGOING_CONNECTIONS = "Split node does not have enough outgoing connections.";
+	String SPLIT_OUTGOING_CONNECTION_WITHOUT_CONSTRAINT = "An outgoing connection of a split node has no constraint.";
+	String JOIN_WITHOUT_TYPE = "Join node has no type.";
+	String JOIN_NOT_ENOUGH_INCOMING_CONNECTIONS = "Join node does not have enough incoming connections.";
+	String JOIN_WITHOUT_OUTGOING_CONNECTION = "Join node has no outgoing connection.";
+	String VARIABLE_WITHOUT_TYPE = "A variable has no type.";
+	String ALL_NODES_CONNECTED_TO_START = "A node is not connected to the start node.";
+			
+	String getType();
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IRuleFlowProcessValidator.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IRuleFlowProcessValidator.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IRuleFlowProcessValidator.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,27 @@
+package org.drools.ruleflow.core;
+/*
+ * 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.
+ */
+
+/**
+ * A validator for validating a RuleFlow process. 
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface IRuleFlowProcessValidator {
+	
+    IRuleFlowProcessValidationError[] validateProcess(IRuleFlowProcess process);
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IRuleSetNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IRuleSetNode.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IRuleSetNode.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,53 @@
+package org.drools.ruleflow.core;
+/*
+ * 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.
+ */
+
+/**
+ * Represents a node containing a set of rules in a RuleFlow. 
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface IRuleSetNode extends INode {
+    
+    /**
+     * Returns the incoming connection of the RuleSetNode.
+     * 
+     * @return the incoming connection of the RuleSetNode.
+     */
+    IConnection getFrom();
+        
+    /**
+     * Returns the outgoing connection of the RuleSetNode.
+     * 
+     * @return the outgoing connection of the RuleSetNode.
+     */
+    IConnection getTo();
+    
+    /**
+     * Returns the ruleflow-group of the RuleSetNode.
+     * 
+     * @return the ruleflow-group of the RuleSetNode.
+     */
+    String getRuleFlowGroup();    
+
+    /**
+     * Sets the ruleflow-group of the RuleSetNode.
+     * 
+     * @param ruleFlowGroup	The ruleflow-group of the RuleSetNode
+     * @throws IllegalArgumentException if type is null
+     */
+    void setRuleFlowGroup(String ruleFlowGroup);	
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/ISplit.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/ISplit.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/ISplit.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,113 @@
+package org.drools.ruleflow.core;
+/*
+ * 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.
+ */
+
+import java.util.Map;
+
+/**
+ * Represents a split node in a RuleFlow. 
+ * A split is a special kind of node with one incoming connection and
+ * multiple outgoing connections.  The type of split decides which of the
+ * outgoing connections will be triggered when the incoming connection 
+ * has been triggered.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface ISplit extends INode {
+	
+	int TYPE_UNDEFINED = 0;
+    /**
+     * All outgoing connections of a split of this type are triggered
+     * when its incoming connection has been triggered.  A split of this
+     * type should have no constraints linked to any of its outgoing
+     * connections.
+     */ 
+	int TYPE_AND = 1;
+    /**
+     * Exactly one outgoing connection of a split of this type is triggered
+     * when its incoming connection has been triggered.  Which connection
+     * is based on the constraints associated with each of the connections:
+     * the connection with the highest priority whose constraint is satisfied
+     * is triggered.  
+     */ 
+	int TYPE_XOR = 2;
+    /**
+     * One or multiple outgoing connections of a split of this type are
+     * triggered when its incoming connection has been triggered.  Which
+     * connections is based on the constraints associated with each of the
+     * connections: all connections whose constraint is satisfied are
+     * triggered.  
+     */ 
+	int TYPE_OR = 3;
+    
+	/**
+     * Sets the type of the split.
+     * 
+     * @param type	The type of the split
+     * @throws IllegalArgumentException if type is null
+     */	
+    void setType(int type);
+    
+    /**
+     * Returns the type of the split.
+     * 
+     * @return the type of the split.
+     */  
+    int getType();
+    
+    /**
+     * Returns the corresponding constraint of the given outgoing connection
+     * 
+     * @param connection	the outgoing connection
+     * @return	the corresponding constraint of the given outgoing connection
+     * @throws IllegalArgumentException if <code>connection</code> is
+     * not a valid outgoing connection for this split
+     * @throws UnsupportedOperationException if this method is called
+     * on a split with split type of something else than XOR or OR
+     */
+    IConstraint getConstraint(IConnection connection);
+    
+    /**
+     * Method for setting a constraint corresponding to the given
+     * outgoing connection
+     * 
+     * @param connection	the outgoing connection
+     * @param constraint	the constraint 
+     * @throws IllegalArgumentException if <code>connection</code> is
+     * not a valid outgoing connection for this split
+     * @throws UnsupportedOperationException if the split type is 
+     * something else than XOR or OR
+     */
+    void setConstraint(IConnection connection, IConstraint constraint);
+    
+    /**
+     * Returns the constraints of the split.
+     * 
+     * @return a map containing for each connection the constraint associated with
+     * that connection, or null if no constraint has been specified yet for that connection
+     * @throws UnsupportedOperationException if this method is called
+     * on a split with split type of something else than XOR or OR
+     */
+    Map getConstraints();
+    
+    /**
+     * Convenience method for returning the incoming connection of the split.
+     * 
+     * @return the incoming connection ot the split.
+     */
+    IConnection getFrom();
+    
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IStartNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IStartNode.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IStartNode.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,32 @@
+package org.drools.ruleflow.core;
+/*
+ * 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.
+ */
+
+/**
+ * Represents a start node in a RuleFlow. 
+ * A start node has no incoming and one outgoing connection.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface IStartNode extends INode {
+
+	/**
+	 * Convenience method for returning the outgoing <code>IConnection</code>.
+	 * @return the outgoing <code>IConnection</code>
+	 */
+    IConnection getTo();
+    
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IVariable.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IVariable.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/IVariable.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,40 @@
+package org.drools.ruleflow.core;
+/*
+ * 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.
+ */
+
+import java.io.Serializable;
+
+import org.drools.ruleflow.common.datatype.IDataType;
+
+/**
+ * Represents a global variable used in a RuleFlow.
+ * A variable has a name (should be unique for this process), a datatype
+ * and possibly an initial value.  
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface IVariable {
+	
+    String getName();
+    void setName(String name);
+    
+    IDataType getType();
+    void setType(IDataType type);
+    
+	Serializable getValue();
+    void setValue(Serializable value);
+    
+}

Added: 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	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/Connection.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,107 @@
+package org.drools.ruleflow.core.impl;
+/*
+ * 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.
+ */
+
+import java.io.Serializable;
+
+import org.drools.ruleflow.core.IConnection;
+import org.drools.ruleflow.core.INode;
+
+/**
+ * Default implementation of a connection.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class Connection implements IConnection, Serializable {
+    
+    private static final long serialVersionUID = 3256439218229424434L;
+
+    private int type;
+    private Node from;
+    private Node to;
+    
+    private Connection() {
+    }
+    
+    /**
+     * Creates a new connection, given a from node, a to node 
+     * and a type.
+     * 
+     * @param from		The from node
+     * @param to		The to node
+     * @param type		The connection type
+     */
+    public Connection(INode from, INode to, int type) {
+    	if (from == null) {
+    		throw new IllegalArgumentException("From node is null!");
+    	}
+    	if (to == null) {
+    		throw new IllegalArgumentException("To node is null!");    		
+    	}
+    	if (from.equals(to)) {
+    		throw new IllegalArgumentException("To and from nodes are the same!");    		
+    	}
+    	this.from = (Node) from;
+        this.to = (Node) to;
+        this.type = type;
+    	this.from.addOutgoingConnection(this);
+    	this.to.addIncomingConnection(this);
+    }
+    
+    public synchronized void terminate() {
+    	from.removeOutgoingConnection(this);
+    	to.removeIncomingConnection(this);
+    	type = 0;
+    	from = null;
+    	to = null;
+    }
+
+    public INode getFrom() {
+    	return from;
+    }
+    
+    public INode getTo() {
+    	return to;
+    }
+    
+    public int getType() {
+    	return type;
+    }
+    
+    public boolean equals(Object object) {
+    	if (object instanceof Connection) {
+            Connection connection = (Connection) object;
+            return type == connection.getType() && getFrom().equals(connection.getFrom())
+                && getTo().equals(connection.getTo()); 
+        }
+        return false;
+    }
+    
+    public int hashCode() {
+        return getFrom().hashCode() + 3*getTo().hashCode() + 5*getType();
+    }
+    
+    public String toString() {
+    	StringBuilder sb = new StringBuilder("Connection ");
+    	sb.append(getFrom());
+    	sb.append(" - ");
+    	sb.append(getTo());
+    	sb.append(" [type=");
+    	sb.append(getType());
+    	sb.append("]");
+    	return sb.toString();
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/Constraint.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/Constraint.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/Constraint.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,62 @@
+package org.drools.ruleflow.core.impl;
+/*
+ * 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.
+ */
+
+import java.io.Serializable;
+
+import org.drools.ruleflow.core.IConstraint;
+
+/**
+ * Default implementation of a constraint.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class Constraint implements IConstraint, Serializable {
+
+    private static final long serialVersionUID = 3257849861633422902L;
+
+    private String name;
+    private String constraint;
+    private int priority;
+    
+    public String getConstraint() {
+        return constraint;
+    }
+    
+    public void setConstraint(String constraint) {
+        this.constraint = constraint;
+    }
+    
+    public String getName() {
+        return name;
+    }
+    
+    public void setName(String name) {
+        this.name = name;
+    }
+    
+    public String toString() {
+        return name;
+    }
+    
+    public int getPriority() {
+        return priority;
+    }
+    
+    public void setPriority(int priority) {
+        this.priority = priority;
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/EndNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/EndNode.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/EndNode.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,54 @@
+package org.drools.ruleflow.core.impl;
+/*
+ * 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.
+ */
+
+import java.util.List;
+
+import org.drools.ruleflow.core.IConnection;
+import org.drools.ruleflow.core.IEndNode;
+
+/**
+ * Default implementation of an end node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class EndNode extends Node implements IEndNode {
+    
+    private static final long serialVersionUID = 3906930075512484153L;
+    
+    public IConnection getFrom() {
+    	List list = getIncomingConnections();
+    	if (list.size() > 0) {
+    		return (IConnection) list.get(0);
+    	}
+		return null;
+    }
+    
+    protected void validateAddIncomingConnection(IConnection connection) {
+    	super.validateAddIncomingConnection(connection);
+    	if (getIncomingConnections().size() > 0) {    		
+            throw new IllegalArgumentException("An end node cannot have more than one incoming connection");
+        }
+    }
+
+    protected void validateAddOutgoingConnection(IConnection connection) {
+        throw new UnsupportedOperationException("An end node does not have an outgoing connection");
+    }
+
+    protected void validateRemoveOutgoingConnection(IConnection connection) {
+        throw new UnsupportedOperationException("An end node does not have an outgoing connection");
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/Join.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/Join.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/Join.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,62 @@
+package org.drools.ruleflow.core.impl;
+/*
+ * 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.
+ */
+
+import org.drools.ruleflow.core.IConnection;
+import org.drools.ruleflow.core.IJoin;
+
+/**
+ * Default implementation of a join.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class Join extends Node implements IJoin {
+    
+    private static final long serialVersionUID = 3257004367155573815L;
+
+    private int type;
+    
+    public Join() {
+    	this.type = TYPE_UNDEFINED;
+    }
+    
+    public void setType(int type) {
+    	this.type = type;
+    }
+    
+    public int getType() {
+        return type;
+    }
+    
+    public IConnection getTo() {
+    	if (getOutgoingConnections().size() > 0) {
+    		return (IConnection) getOutgoingConnections().get(0);
+    	}
+		return null;   	
+    }    
+
+    protected void validateAddOutgoingConnection(IConnection connection) {
+    	super.validateAddOutgoingConnection(connection);
+    	if (connection.getType() != IConnection.TYPE_NORMAL) {
+            throw new IllegalArgumentException("Unknown connection type :" + connection.getType()
+            		+ ", only NORMAL is allowed as outgoing connection.");
+        }
+    	if (getOutgoingConnections().size() > 0) {
+            throw new IllegalArgumentException("A join cannot have more than one outgoing connection");
+        }
+    }
+    
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/Node.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/Node.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/Node.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,181 @@
+package org.drools.ruleflow.core.impl;
+/*
+ * 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.
+ */
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.drools.ruleflow.core.IConnection;
+import org.drools.ruleflow.core.INode;
+
+/**
+ * Default implementation of a node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public abstract class Node implements INode, Serializable {
+    
+    protected static final Node[] EMPTY_NODE_ARRAY = new Node[0];
+    
+    private long id;
+    private String name;
+    private List incomingConnections;
+    private List outgoingConnections;
+    
+    public Node() {
+        this.id = -1;
+        incomingConnections = new ArrayList();
+        outgoingConnections = new ArrayList();        
+    }
+    
+    public long getId() {
+        return id;
+    }
+    
+    public void setId(long id) {
+        this.id = id;
+    }
+    
+    public String getName() {
+        return name;
+    }
+    
+    public void setName(String name) {
+        this.name = name;
+    }
+        
+    public List getIncomingConnections() {
+    	return Collections.unmodifiableList(incomingConnections);
+    }
+    
+    public List getOutgoingConnections() {
+    	return Collections.unmodifiableList(outgoingConnections);
+    }
+    
+    protected void addIncomingConnection(IConnection connection) {
+    	validateAddIncomingConnection(connection);
+    	incomingConnections.add(connection);
+    }
+    
+    /**
+	 * This method validates whether the given connection can be added. If the
+	 * connection cannot be added, an IllegalArgumentException is thrown.
+	 * <p>
+	 * 
+	 * @param connection
+	 *            the incoming connection to be added
+	 * @throws IllegalArgumentException
+	 *             is thrown if the connection is null, or if a connection is
+	 *             added twice. If subclasses want to change the rules for
+	 *             adding incoming connections the
+	 *             <code>validateAddIncomingConnection(IConnection connection)</code>
+	 *             should be overridden.
+	 */
+    protected void validateAddIncomingConnection(IConnection connection) {
+    	if (connection == null) {
+    		throw new IllegalArgumentException("Connection cannot be null");
+    	}
+    	if (incomingConnections.contains(connection)) {
+    		throw new IllegalArgumentException("Connection is already added");
+    	}
+    }
+    
+    protected void addOutgoingConnection(IConnection connection) {
+    	validateAddOutgoingConnection(connection);
+    	outgoingConnections.add(connection);
+    }
+    
+    /**
+	 * This method validates whether the given connection can be added. If the
+	 * connection cannot be added, an IllegalArgumentException is thrown.
+	 * <p>
+	 * 
+	 * @param connection
+	 *            the outgoin connection to be added
+	 * @throws IllegalArgumentException
+	 *             is thrown if the connection is null, or if a connection is
+	 *             added twice. If subclasses want to change the rules for
+	 *             adding outgoing connections the
+	 *             <code>validateAddIncomingConnection(IConnection connection)</code>
+	 *             should be overridden.
+	 */
+    protected void validateAddOutgoingConnection(IConnection connection) {
+    	if (connection == null) {
+    		throw new IllegalArgumentException("Connection cannot be null");
+    	}
+    	if (outgoingConnections.contains(connection)) {
+    		throw new IllegalArgumentException("Connection is already added");
+    	}
+    }
+    
+    protected void removeIncomingConnection(IConnection connection) {
+    	validateRemoveIncomingConnection(connection);
+    	incomingConnections.remove(connection);
+    }
+    
+    /**
+	 * This method validates whether the given connection can be removed
+	 * <p>
+	 * 
+	 * @param connection
+	 *            the incoming connection
+	 * @throws IllegalArgumentException
+	 *             is thrown if connectin is null, or unknown. If subclasses
+	 *             want to change the rules for removing incoming connections
+	 *             the
+	 *             <code>validateRemoveIncomingConnection(IConnection connection)</code>
+	 *             should be overridden.
+	 */
+    protected void validateRemoveIncomingConnection(IConnection connection) {
+    	if (connection == null) {
+    		throw new IllegalArgumentException("Connection is null");
+    	}
+    	if (!incomingConnections.contains(connection)) {
+    		throw new IllegalArgumentException("Given connection <"
+				+ connection + "> is not part of the incoming connections");
+    	}
+    }
+    
+    protected void removeOutgoingConnection(IConnection connection) {
+    	validateRemoveOutgoingConnection(connection);
+    	outgoingConnections.remove(connection);
+    }
+    
+    /**
+	 * This method validates whether the given connection can be removed
+	 * <p>
+	 * 
+	 * @param connection
+	 *            the outgoing connection
+	 * @throws IllegalArgumentException
+	 *             is thrown if connectin is null, or unknown. If subclasses
+	 *             want to change the rules for removing outgoing connections
+	 *             the
+	 *             <code>validateRemoveOutgoingConnection(IConnection connection)</code>
+	 *             should be overridden.
+	 */
+    protected void validateRemoveOutgoingConnection(IConnection connection) {
+    	if (connection == null) {
+    		throw new IllegalArgumentException("Connection is null");
+    	}
+    	if (!outgoingConnections.contains(connection)) {
+    		throw new IllegalArgumentException("Given connection <"
+				+ connection + "> is not part of the outgoing connections");
+    	}
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/RuleFlowProcess.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/RuleFlowProcess.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/RuleFlowProcess.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,133 @@
+package org.drools.ruleflow.core.impl;
+/*
+ * 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.
+ */
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.ruleflow.common.core.impl.Process;
+import org.drools.ruleflow.core.IEndNode;
+import org.drools.ruleflow.core.INode;
+import org.drools.ruleflow.core.IRuleFlowProcess;
+import org.drools.ruleflow.core.IStartNode;
+import org.drools.ruleflow.core.IVariable;
+
+/**
+ * Default implementation of a RuleFlow process.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class RuleFlowProcess extends Process implements IRuleFlowProcess {
+    
+    public static final String RULEFLOW_TYPE = "RuleFlow";
+
+    private static final long serialVersionUID = 3257005445309609272L;
+
+    private Map nodes;
+    private List variables;
+	private long lastNodeId;
+    
+    public RuleFlowProcess() {
+        super();
+        setType(RULEFLOW_TYPE);
+        nodes = new HashMap();
+        variables = new ArrayList();
+    }
+    
+    public IStartNode getStart() {
+    	for (Iterator it = nodes.values().iterator(); it.hasNext(); ) {
+    		INode node = (INode) it.next();
+    		if (node instanceof IStartNode) {
+    			return (IStartNode) node;
+    		}
+    	}
+		return null;
+    }
+    
+    public INode[] getNodes() {
+        return (INode[]) nodes.values().toArray(new INode[nodes.size()]);
+    }
+    
+    public INode getNode(long id) {
+    	Long idLong = new Long(id);
+    	if (!nodes.containsKey(idLong)) {
+    		throw new IllegalArgumentException("Unknown node id: " + id);
+    	} 
+        return (INode) nodes.get(idLong);
+    }   
+    
+    
+	private IEndNode getEnd() {
+    	for (Iterator it = nodes.values().iterator(); it.hasNext(); ) {
+    		INode node = (INode) it.next();
+    		if (node instanceof IEndNode) {
+    			return (IEndNode) node;
+    		}
+    	}
+		return null;
+    }
+	
+    public void removeNode(INode node) {
+    	if (node == null) {
+    		throw new IllegalArgumentException("Node is null");
+    	}
+    	INode n = (INode) nodes.remove(new Long(node.getId()));
+        if (n == null) {
+        	throw new IllegalArgumentException("Unknown node: " + node);
+        }
+    }
+    
+    public List getVariables() {
+        return variables;
+    }
+    
+    public void setVariables(List variables) {
+    	if (variables == null) {
+    		throw new IllegalArgumentException("Variables is null");    		
+    	}
+        this.variables = variables;
+    }
+
+    public String[] getVariableNames() {    	
+        String[] result = new String[variables.size()];        
+        for (int i = 0; i < variables.size(); i++) {
+            result[i] = ((IVariable) variables.get(i)).getName();
+        }
+        return result;
+    }
+
+	public void addNode(INode node) {
+		validateAddNode(node);
+		if (!nodes.containsValue(node)) {
+			node.setId(++lastNodeId);
+			nodes.put(new Long(node.getId()), node);
+		}
+    }
+	
+	private void validateAddNode(INode node) {
+		if ((node instanceof IStartNode) && (getStart() != null)) {
+			throw new IllegalArgumentException(
+				"A ruleflow process cannot have more than one start node!");
+		}
+		if ((node instanceof IEndNode) && (getEnd() != null)) {
+			throw new IllegalArgumentException(
+				"A ruleflow process cannot have more than one end node!");
+		}		
+	}
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/RuleFlowProcessValidationError.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/RuleFlowProcessValidationError.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/RuleFlowProcessValidationError.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,41 @@
+package org.drools.ruleflow.core.impl;
+/*
+ * 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.
+ */
+
+import org.drools.ruleflow.core.IRuleFlowProcessValidationError;
+
+/**
+ * Default implementation of a RuleFlow validation error.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class RuleFlowProcessValidationError implements
+		IRuleFlowProcessValidationError {
+
+	private String type;
+	
+	public RuleFlowProcessValidationError(String type) {
+		this.type = type;
+	}
+	
+	public String toString() {
+		return type;
+	}
+
+	public String getType() {
+		return type;
+	}
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/RuleFlowProcessValidator.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/RuleFlowProcessValidator.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/RuleFlowProcessValidator.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,207 @@
+package org.drools.ruleflow.core.impl;
+/*
+ * 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.
+ */
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.ruleflow.core.IConnection;
+import org.drools.ruleflow.core.IEndNode;
+import org.drools.ruleflow.core.IJoin;
+import org.drools.ruleflow.core.INode;
+import org.drools.ruleflow.core.IRuleSetNode;
+import org.drools.ruleflow.core.ISplit;
+import org.drools.ruleflow.core.IStartNode;
+import org.drools.ruleflow.core.IVariable;
+import org.drools.ruleflow.core.IRuleFlowProcess;
+import org.drools.ruleflow.core.IRuleFlowProcessValidationError;
+import org.drools.ruleflow.core.IRuleFlowProcessValidator;
+
+/**
+ * Default implementation of a RuleFlow validator.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class RuleFlowProcessValidator implements IRuleFlowProcessValidator {
+	
+    private static RuleFlowProcessValidator instance;
+    
+    private RuleFlowProcessValidator() {
+    }
+    
+    public static RuleFlowProcessValidator getInstance() {
+        if (instance == null) {
+            instance = new RuleFlowProcessValidator();
+        }
+        return instance;
+    }
+    
+    public IRuleFlowProcessValidationError[] validateProcess(IRuleFlowProcess process) {
+        List errors = new ArrayList();
+        
+        if (process.getName() == null) {
+            errors.add(new RuleFlowProcessValidationError(
+                    IRuleFlowProcessValidationError.NO_PROCESS_NAME));
+        }
+        
+        if (process.getId() == null || "".equals(process.getId())) {
+            errors.add(new RuleFlowProcessValidationError(
+                    IRuleFlowProcessValidationError.NO_PROCESS_ID));
+        }
+        
+        // check start node of process
+        if (process.getStart() == null) {
+            errors.add(new RuleFlowProcessValidationError(
+					IRuleFlowProcessValidationError.NO_START_NODE));
+        }
+        
+        boolean startNodeFound = false;
+        boolean endNodeFound = false;
+        INode[] nodes = process.getNodes();
+        for (int i = 0; i < nodes.length; i++) { 
+        	INode node = nodes[i];
+            if (node instanceof IStartNode) {
+                IStartNode startNode = (IStartNode) node;
+                startNodeFound = true;
+                if (startNode.getTo() == null) {
+                    errors.add(new RuleFlowProcessValidationError(
+							IRuleFlowProcessValidationError.START_NODE_WITHOUT_OUTGOING_NODES));
+                }
+            } else if (node instanceof IEndNode) {
+                IEndNode endNode = (IEndNode) node;
+                endNodeFound = true;            
+                if (endNode.getFrom() == null) {
+                    errors.add(new RuleFlowProcessValidationError(
+							IRuleFlowProcessValidationError.END_NODE_HAS_NO_INCOMING_CONNECTIONS));
+                }
+            } else if (node instanceof IRuleSetNode) {
+                IRuleSetNode ruleSetNode = (IRuleSetNode) node;
+                if (ruleSetNode.getFrom() == null) {
+					errors.add(new RuleFlowProcessValidationError(
+							IRuleFlowProcessValidationError.RULE_SET_NODE_WITHOUT_INCOMING_CONNECTIONS));                    
+                }
+                
+                if (ruleSetNode.getTo() == null) {
+					errors.add(new RuleFlowProcessValidationError(
+							IRuleFlowProcessValidationError.RULE_SET_NODE_WITHOUT_OUTGOING_CONNECTIONS));
+                }
+                String ruleFlowGroup = ruleSetNode.getRuleFlowGroup();
+                if (ruleFlowGroup == null || "".equals(ruleFlowGroup)) {
+                	errors.add(new RuleFlowProcessValidationError(
+							IRuleFlowProcessValidationError.RULE_SET_NODE_WITHOUT_RULE_SET_GROUP));
+                }
+            } else if (node instanceof ISplit) {
+                ISplit split = (ISplit) node;
+                if (split.getType() == ISplit.TYPE_UNDEFINED) {
+					errors.add(new RuleFlowProcessValidationError(
+							IRuleFlowProcessValidationError.SPLIT_WITHOUT_TYPE));
+                }
+                if (split.getFrom() == null) {
+					errors.add(new RuleFlowProcessValidationError(
+							IRuleFlowProcessValidationError.SPLIT_WITHOUT_INCOMING_CONNECTION));
+                }
+                if (split.getOutgoingConnections().size() < 2) {
+					errors.add(new RuleFlowProcessValidationError(
+							IRuleFlowProcessValidationError.SPLIT_NOT_ENOUGH_OUTGOING_CONNECTIONS));
+                }
+				if (split.getType() == ISplit.TYPE_XOR || split.getType() == ISplit.TYPE_OR) {
+                	for (Iterator it = split.getOutgoingConnections().iterator(); it.hasNext(); ) {
+                		IConnection connection = (IConnection) it.next();
+						if (split.getConstraint(connection) == null) {
+							errors.add(new RuleFlowProcessValidationError(
+									IRuleFlowProcessValidationError.SPLIT_OUTGOING_CONNECTION_WITHOUT_CONSTRAINT));
+                		}
+                	}
+                }
+            } else if (node instanceof IJoin) {
+                IJoin join = (IJoin) node;
+                if (join.getType() == IJoin.TYPE_UNDEFINED) {
+					errors.add(new RuleFlowProcessValidationError(
+							IRuleFlowProcessValidationError.JOIN_WITHOUT_TYPE));
+                }
+                if (join.getIncomingConnections().size() < 2) {
+					errors.add(new RuleFlowProcessValidationError(
+							IRuleFlowProcessValidationError.JOIN_NOT_ENOUGH_INCOMING_CONNECTIONS));
+                }
+                if (join.getTo() == null) {
+					errors.add(new RuleFlowProcessValidationError(
+							IRuleFlowProcessValidationError.JOIN_WITHOUT_OUTGOING_CONNECTION));
+                }
+            }
+        }
+        if (!startNodeFound) {
+			errors.add(new RuleFlowProcessValidationError(
+					IRuleFlowProcessValidationError.NO_START_NODE));
+        }
+        if (!endNodeFound) {
+            errors.add(new RuleFlowProcessValidationError(
+					IRuleFlowProcessValidationError.NO_END_NODE));
+        }
+        for (Iterator it = process.getVariables().iterator(); it.hasNext(); ) {
+        	IVariable variable = (IVariable) it.next();
+            if (variable.getType() == null) {
+				errors.add(new RuleFlowProcessValidationError(
+						IRuleFlowProcessValidationError.VARIABLE_WITHOUT_TYPE));
+            }
+        }
+        
+        checkAllNodesConnectedToStart(process, errors);
+		
+		return (IRuleFlowProcessValidationError[]) errors.toArray(new IRuleFlowProcessValidationError[errors.size()]);
+    }
+
+	private void checkAllNodesConnectedToStart(
+			IRuleFlowProcess process, 
+			List errors) {
+		Map processNodes = new HashMap();  
+        INode[] nodes = process.getNodes();
+        for (int i = 0; i < nodes.length; i++) { 
+        	INode node = nodes[i];
+			processNodes.put(node, Boolean.FALSE);
+		}
+		
+		INode start = process.getStart();
+		if (start != null) {
+			processNode(start, processNodes);		
+		}
+		
+		for (Iterator it = processNodes.keySet().iterator(); it.hasNext(); ) {
+			INode node = (INode) it.next();
+			if (Boolean.FALSE.equals(processNodes.get(node))) {
+				errors.add(new RuleFlowProcessValidationError(
+						IRuleFlowProcessValidationError.ALL_NODES_CONNECTED_TO_START));
+			}
+		}
+	}
+	
+	private void processNode(INode node, Map nodes) {
+		if (!nodes.containsKey(node)) {
+			throw new IllegalStateException("A process node is connected with "
+					+ "a node that does not belong to the process.");
+		}
+		Boolean prevValue = (Boolean) nodes.put(node, Boolean.TRUE);
+        if (prevValue == Boolean.FALSE) {
+    		for (Iterator it = node.getOutgoingConnections().iterator(); it.hasNext(); ) {
+    			IConnection connection = (IConnection) it.next();
+    			processNode(connection.getTo(), nodes);
+    		}
+        }
+	}
+	
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/RuleSetNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/RuleSetNode.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/RuleSetNode.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,78 @@
+package org.drools.ruleflow.core.impl;
+/*
+ * 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.
+ */
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.drools.ruleflow.core.IConnection;
+import org.drools.ruleflow.core.IRuleSetNode;
+
+/**
+ * Default implementation of a RuleSet node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class RuleSetNode extends Node implements IRuleSetNode {
+    
+    private static final long serialVersionUID = 3257285846544691769L;
+
+    private String ruleFlowGroup;
+    
+    public void setRuleFlowGroup(String ruleFlowGroup) {
+        this.ruleFlowGroup = ruleFlowGroup;
+    }
+    
+    public String getRuleFlowGroup() {
+        return ruleFlowGroup;
+    }
+    
+    public IConnection getFrom() {
+    	List list = getIncomingConnections();
+    	if (list.size() > 0) {
+    		return (IConnection) list.get(0);
+    	}
+		return null;
+    }
+    
+    public IConnection getTo() {
+    	List list = getOutgoingConnections();
+    	if (list.size() > 0) {
+    		return (IConnection) list.get(0);
+    	}
+		return null;
+    }
+    
+    protected void validateAddIncomingConnection(IConnection connection) {
+    	super.validateAddIncomingConnection(connection);
+    	if (getIncomingConnections().size() > 0) {
+    		throw new IllegalArgumentException(
+				"A RuleSetNode cannot have more than one incoming node");
+        }        
+    }    
+
+    protected void validateAddOutgoingConnection(IConnection connection) {
+    	super.validateAddOutgoingConnection(connection);
+    	for (Iterator it = getOutgoingConnections().iterator(); it.hasNext(); ) {
+    		IConnection conn = (IConnection) it.next();
+    		if (conn.getType() == connection.getType()) {
+    			throw new IllegalArgumentException(
+    				"A RuleSetNode can have at most one outgoing node");
+    		}
+    	}
+    }
+    
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/Split.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/Split.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/Split.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,131 @@
+package org.drools.ruleflow.core.impl;
+/*
+ * 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.
+ */
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.drools.ruleflow.core.IConnection;
+import org.drools.ruleflow.core.IConstraint;
+import org.drools.ruleflow.core.ISplit;
+
+/**
+ * Default implementation of a split node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class Split extends Node implements ISplit {
+    
+    private static final long serialVersionUID = 3258413949669159736L;
+
+    private int type;
+    private Map constraints;
+        
+    public Split() {
+    	type = TYPE_UNDEFINED;
+    	constraints = new HashMap();    	
+    }
+    
+    public Split(int type) {
+    	this.type = type;
+    	constraints = new HashMap();
+    }
+    
+    public void setType(int type) {
+        this.type = type;
+    }
+    
+    public int getType() {
+        return type;
+    }
+    
+    public IConstraint getConstraint(IConnection connection) {
+    	if (connection == null) {
+    		throw new IllegalArgumentException("connection is null");
+    	}
+    	
+    	// dirty hack because keys were entered wrong
+    	// probably caused by xstreams
+    	HashMap newMap = new HashMap();
+		for (Iterator it = constraints.entrySet().iterator(); it.hasNext(); ) {
+			Entry entry = (Entry) it.next();
+			newMap.put(entry.getKey(), entry.getValue());
+		}
+		constraints = newMap;
+		
+    	if (type == TYPE_OR || type == TYPE_XOR) {
+    		return (IConstraint) constraints.get(connection);
+    	}
+		throw new UnsupportedOperationException("Constraints are "
+			+ "only supported with XOR or OR split types, not with: "
+			+ getType());
+    }
+    
+    public void setConstraint(IConnection connection, IConstraint constraint) {    	  	
+    	if (type == TYPE_OR || type == TYPE_XOR) {
+    		if (connection == null) {
+        		throw new IllegalArgumentException("connection is null");
+        	}  
+    		if (!getOutgoingConnections().contains(connection)) {
+        		throw new IllegalArgumentException("connection is unknown:" + connection);
+        	}
+    		constraints.put(connection, constraint);
+    	} else {
+    		throw new UnsupportedOperationException("Constraints are "
+    				+ "only supported with XOR or OR split types, not with type:"
+    				+ getType());
+    	} 
+    }
+    
+    public Map getConstraints() {
+    	if (type == TYPE_OR || type == TYPE_XOR) {
+    		return Collections.unmodifiableMap(constraints);
+    	}
+		throw new UnsupportedOperationException("Constraints are "
+			+ "only supported with XOR or OR split types, not with: "
+			+ getType());
+    }
+    
+    public IConnection getFrom() {
+    	if (getIncomingConnections().size() > 0) {
+    		return (IConnection) getIncomingConnections().get(0);
+    	}
+		return null;
+    }
+    
+    protected void validateAddIncomingConnection(IConnection connection) {
+    	super.validateAddIncomingConnection(connection);
+    	if (getIncomingConnections().size() > 0) {
+            throw new IllegalArgumentException("A split cannot have more than one incoming connection");
+        }
+    }
+   
+    protected void validateAddOutgoingConnection(IConnection connection) {
+    	super.validateAddOutgoingConnection(connection);
+    	if (connection.getType() != IConnection.TYPE_NORMAL) {
+            throw new IllegalArgumentException("Unknown connection type :" + connection.getType()
+            		+ ", only NORMAL is allowed as outgoing connection.");
+        }    	
+    }
+    
+    public void removeOutgoingConnection(IConnection connection) {
+        super.removeOutgoingConnection(connection);
+        constraints.remove(connection);
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/StartNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/StartNode.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/StartNode.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,59 @@
+package org.drools.ruleflow.core.impl;
+/*
+ * 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.
+ */
+
+import java.util.List;
+
+import org.drools.ruleflow.core.IConnection;
+import org.drools.ruleflow.core.IStartNode;
+
+/**
+ * Default implementation of a start node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class StartNode extends Node implements IStartNode {
+
+    private static final long serialVersionUID = 3257564005806782517L;
+    
+    public IConnection getTo() {
+    	List list = getOutgoingConnections();
+    	if (list.size() > 0) {
+    		return (IConnection) list.get(0);
+    	}
+		return null;
+    }
+    
+    protected void validateAddOutgoingConnection(IConnection connection) {
+    	super.validateAddOutgoingConnection(connection);
+    	if (getOutgoingConnections().size() > 0) {    		
+            throw new IllegalArgumentException(
+        		"A start node cannot have more than one outgoing connection");
+        }
+    }
+
+
+    protected void validateAddIncomingConnection(IConnection connection) {
+        throw new UnsupportedOperationException(
+    		"A start node does not have an incoming connection");
+    }
+
+    protected void validateRemoveIncomingConnection(IConnection connection) {
+        throw new UnsupportedOperationException(
+    		"A start node does not have an incoming connection");
+    }
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/Variable.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/Variable.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/core/impl/Variable.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,80 @@
+package org.drools.ruleflow.core.impl;
+/*
+ * 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.
+ */
+
+import java.io.Serializable;
+
+import org.drools.ruleflow.common.datatype.IDataType;
+import org.drools.ruleflow.common.datatype.impl.type.UndefinedDataType;
+import org.drools.ruleflow.core.IVariable;
+
+/**
+ * Default implementation of a variable.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class Variable implements IVariable, Serializable {
+
+    private static final long serialVersionUID = 3256441400072353336L;
+
+    private String name;
+    private IDataType type;
+    private Serializable value;    
+    
+    public Variable() {
+    	type = UndefinedDataType.getInstance();
+    }
+    
+    public String getName() {
+        return name;
+    }
+    
+    public void setName(String name) {
+        this.name = name;
+    }
+    
+    public IDataType getType() {
+        return type;
+    }
+    
+    public void setType(IDataType type) {
+    	if (type == null) {
+    		throw new IllegalArgumentException("type is null");
+    	}
+        this.type = type;
+    }
+    
+    public Serializable getValue() {
+        return value;
+    }
+    
+    public void setValue(Serializable value) {
+    	if (this.type.verifyDataType(value)) {
+    		this.value = value;
+    	} else {
+    		StringBuilder sb = new StringBuilder();
+    		sb.append("Value <");
+    		sb.append(value);
+    		sb.append("> is not valid for datatype: ");
+    		sb.append(type);
+    		throw new IllegalArgumentException(sb.toString());
+    	}
+    }
+    
+    public String toString() {
+        return name;
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/IRuleFlowNodeInstance.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/IRuleFlowNodeInstance.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/IRuleFlowNodeInstance.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,44 @@
+package org.drools.ruleflow.instance;
+/*
+ * 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.
+ */
+
+/**
+ * Represents a node instance in a RuleFlow. This is the runtime counterpart
+ * of a node, containing all runtime state.  Node instance classes also
+ * contain the logic on what to do when it is being triggered (start
+ * executing) or completed (end of execution).
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface IRuleFlowNodeInstance {
+	
+	void setId(long id);
+
+	long getId();
+	
+	void setNodeId(long nodeId);
+
+	long getNodeId();
+
+	void setProcessInstance(IRuleFlowProcessInstance processInstance);
+
+	IRuleFlowProcessInstance getProcessInstance();
+
+	void trigger(IRuleFlowNodeInstance from);
+	
+	void triggerCompleted();
+	
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/IRuleFlowProcessInstance.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/IRuleFlowProcessInstance.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/IRuleFlowProcessInstance.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,52 @@
+package org.drools.ruleflow.instance;
+/*
+ * 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.
+ */
+
+import java.util.Collection;
+
+import org.drools.Agenda;
+import org.drools.ruleflow.common.instance.IProcessInstance;
+import org.drools.ruleflow.core.INode;
+import org.drools.ruleflow.core.IRuleFlowProcess;
+
+/**
+ * A process instance for a RuleFlow process.
+ * Contains a reference to all its node instances, and the agenda that
+ * is controlling the RuleFlow process.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public interface IRuleFlowProcessInstance extends IProcessInstance {
+	
+	IRuleFlowProcess getRuleFlowProcess();
+	
+	void addNodeInstance(IRuleFlowNodeInstance nodeInstance);
+
+	void removeNodeInstance(IRuleFlowNodeInstance nodeInstance);
+
+	Collection getNodeInstances();
+
+	IRuleFlowNodeInstance getFirstNodeInstance(long nodeId);
+	
+	void setAgenda(Agenda agenda);
+	
+	Agenda getAgenda();
+	
+	IRuleFlowNodeInstance getNodeInstance(INode node);
+	
+	void start();
+	
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/EndNodeInstance.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/EndNodeInstance.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/EndNodeInstance.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,36 @@
+package org.drools.ruleflow.instance.impl;
+/*
+ * 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.
+ */
+
+import org.drools.ruleflow.common.instance.IProcessInstance;
+import org.drools.ruleflow.instance.IRuleFlowNodeInstance;
+
+/**
+ * Runtime counterpart of an end node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class EndNodeInstance extends RuleFlowNodeInstance {
+
+	public void trigger(IRuleFlowNodeInstance from) {
+		getProcessInstance().setState(IProcessInstance.STATE_COMPLETED);
+	}
+
+	public void triggerCompleted() {
+		// this should never occur
+		throw new IllegalArgumentException("End nodes cannot be completed.");
+	}
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/RuleFlowJoinInstance.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/RuleFlowJoinInstance.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/RuleFlowJoinInstance.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,87 @@
+package org.drools.ruleflow.instance.impl;
+/*
+ * 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.
+ */
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.drools.ruleflow.core.IConnection;
+import org.drools.ruleflow.core.IJoin;
+import org.drools.ruleflow.core.INode;
+import org.drools.ruleflow.instance.IRuleFlowNodeInstance;
+
+/**
+ * Runtime counterpart of a join node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class RuleFlowJoinInstance extends RuleFlowNodeInstance implements IRuleFlowNodeInstance {
+
+	private Map triggers = new HashMap();
+	
+	protected IJoin getJoinNode() {
+		return (IJoin) getNode();
+	}
+	
+	public void trigger(IRuleFlowNodeInstance from) {
+		IJoin join = getJoinNode();
+		switch (join.getType()) {
+		case IJoin.TYPE_XOR:
+			triggerCompleted();
+			break;
+		case IJoin.TYPE_AND:
+			INode node = getProcessInstance().getRuleFlowProcess().getNode(from.getNodeId());
+			Integer count = (Integer) triggers.get(node);
+			if (count == null) {
+				triggers.put(node, new Integer(1));
+			} else {
+				triggers.put(node, new Integer(count.intValue() + 1));
+			}
+			checkActivation();
+			break;
+		default:
+			throw new IllegalArgumentException("Illegal join type " + join.getType());
+		}
+	}
+
+	private void checkActivation() {
+		// check whether all parent nodes have been triggered 
+        for (Iterator it = getJoinNode().getIncomingConnections().iterator(); it.hasNext(); ) {
+        	IConnection connection = (IConnection) it.next();
+            if (triggers.get(connection.getFrom()) == null) {
+            	return;
+            }
+        }
+        // if true, decrease trigger count for all parents and trigger children
+        for (Iterator it = getJoinNode().getIncomingConnections().iterator(); it.hasNext(); ) {
+        	IConnection connection = (IConnection) it.next();
+            Integer count = (Integer) triggers.get(connection.getFrom());
+            if (count.intValue() == 1) {
+            	triggers.remove(connection.getFrom());
+            } else {
+            	triggers.put(connection.getFrom(), new Integer(count.intValue() - 1));
+            }
+        }
+        triggerCompleted();
+	}
+	
+	public void triggerCompleted() {
+		getProcessInstance().getNodeInstance(
+			getJoinNode().getTo().getTo()).trigger(this);
+	}
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/RuleFlowNodeInstance.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/RuleFlowNodeInstance.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/RuleFlowNodeInstance.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,60 @@
+package org.drools.ruleflow.instance.impl;
+/*
+ * 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.
+ */
+
+import org.drools.ruleflow.core.INode;
+import org.drools.ruleflow.instance.IRuleFlowNodeInstance;
+import org.drools.ruleflow.instance.IRuleFlowProcessInstance;
+
+/**
+ * Default implementation of a RuleFlow node instance.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public abstract class RuleFlowNodeInstance implements IRuleFlowNodeInstance {
+
+	private long id;
+	private long nodeId;
+	private IRuleFlowProcessInstance processInstance;
+
+	public void setId(long id) {
+		this.id = id;
+	}
+	
+	public long getId() {
+		return id;
+	}
+	
+    public void setNodeId(long nodeId) {
+        this.nodeId = nodeId;
+    }
+    
+    public long getNodeId() {
+        return nodeId;
+    }
+    
+    public void setProcessInstance(IRuleFlowProcessInstance processInstance) {
+        this.processInstance = processInstance;
+    }
+    
+    public IRuleFlowProcessInstance getProcessInstance() {		
+        return processInstance;
+    }
+    
+    protected INode getNode() {
+    	return processInstance.getRuleFlowProcess().getNode(nodeId);
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/RuleFlowProcessInstance.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/RuleFlowProcessInstance.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/RuleFlowProcessInstance.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,140 @@
+package org.drools.ruleflow.instance.impl;
+/*
+ * 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.
+ */
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.drools.Agenda;
+import org.drools.ruleflow.common.instance.IProcessInstance;
+import org.drools.ruleflow.common.instance.impl.ProcessInstance;
+import org.drools.ruleflow.core.IEndNode;
+import org.drools.ruleflow.core.IJoin;
+import org.drools.ruleflow.core.INode;
+import org.drools.ruleflow.core.IRuleFlowProcess;
+import org.drools.ruleflow.core.IRuleSetNode;
+import org.drools.ruleflow.core.ISplit;
+import org.drools.ruleflow.core.IStartNode;
+import org.drools.ruleflow.instance.IRuleFlowNodeInstance;
+import org.drools.ruleflow.instance.IRuleFlowProcessInstance;
+
+/**
+ * Default implementation of a RuleFlow process instance.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class RuleFlowProcessInstance extends ProcessInstance implements IRuleFlowProcessInstance {
+    
+	private static final long serialVersionUID = -6760756665603399413L;
+	
+	private Agenda agenda;
+	private List nodeInstances = new ArrayList();
+	
+	public IRuleFlowProcess getRuleFlowProcess() {
+		return (IRuleFlowProcess) getProcess();
+	}
+
+    public void addNodeInstance(IRuleFlowNodeInstance nodeInstance) {
+        nodeInstances.add(nodeInstance);
+        nodeInstance.setProcessInstance(this);
+    }
+    
+    public void removeNodeInstance(IRuleFlowNodeInstance nodeInstance) {    	
+        nodeInstances.remove(nodeInstance);
+    }
+    
+    public Collection getNodeInstances() {
+        return Collections.unmodifiableCollection(nodeInstances);
+    }
+    
+    public IRuleFlowNodeInstance getFirstNodeInstance(long nodeId) {
+        for (Iterator iterator = nodeInstances.iterator(); iterator.hasNext(); ) {
+        	IRuleFlowNodeInstance nodeInstance = (IRuleFlowNodeInstance) iterator.next();
+            if (nodeInstance.getNodeId() == nodeId) {
+                return nodeInstance;
+            }
+        }
+        return null;
+    }
+    
+	public Agenda getAgenda() {
+		return agenda;
+	}
+
+	public void setAgenda(Agenda agenda) {
+		this.agenda = agenda;
+	}
+
+	public IRuleFlowNodeInstance getNodeInstance(INode node) {
+		if (node instanceof IRuleSetNode) {
+			IRuleFlowNodeInstance result = (IRuleFlowNodeInstance)
+				agenda.getRuleFlowGroup(((IRuleSetNode) node).getRuleFlowGroup());
+			result.setNodeId(node.getId());
+			addNodeInstance(result);
+			return result;
+		} else if (node instanceof ISplit) {
+			IRuleFlowNodeInstance result = getFirstNodeInstance(node.getId());
+			if (result == null) {
+				result = new RuleFlowSplitInstance();
+				result.setNodeId(node.getId());
+				addNodeInstance(result);
+				return result;
+			}
+		} else if (node instanceof IJoin) {
+			IRuleFlowNodeInstance result = getFirstNodeInstance(node.getId());
+			if (result == null) {
+				result = new RuleFlowJoinInstance();
+				result.setNodeId(node.getId());
+				addNodeInstance(result);
+			}
+			return result;
+		} else if (node instanceof IStartNode) {
+			IRuleFlowNodeInstance result = new StartNodeInstance();
+			result.setNodeId(node.getId());
+			addNodeInstance(result);
+			return result;
+		} else if (node instanceof IEndNode) {
+			IRuleFlowNodeInstance result = new EndNodeInstance();
+			result.setNodeId(node.getId());
+			addNodeInstance(result);
+			return result;
+		}
+		throw new IllegalArgumentException("Illegal node type: " + node.getClass());
+	}
+	
+	public void start() {
+		if (getState() != IProcessInstance.STATE_PENDING) {
+			throw new IllegalArgumentException(
+				"A process instance can only be started once");
+		}
+		setState(IProcessInstance.STATE_ACTIVE);
+		getNodeInstance(getRuleFlowProcess().getStart()).trigger(null);
+	}
+	
+	public String toString() {
+    	StringBuilder sb = new StringBuilder("RuleFlowProcessInstance");
+    	sb.append(getId());
+    	sb.append(" [processId=");
+    	sb.append(getProcess().getId());
+    	sb.append(",state=");
+    	sb.append(getState());
+    	sb.append("]");
+    	return sb.toString();
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/RuleFlowSequenceNodeInstance.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/RuleFlowSequenceNodeInstance.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/RuleFlowSequenceNodeInstance.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,41 @@
+package org.drools.ruleflow.instance.impl;
+/*
+ * 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.
+ */
+
+import org.drools.ruleflow.core.IRuleSetNode;
+import org.drools.ruleflow.instance.IRuleFlowNodeInstance;
+
+/**
+ * Runtime counterpart of a ruleset node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class RuleFlowSequenceNodeInstance extends RuleFlowNodeInstance {
+
+	protected IRuleSetNode getRuleSetNode() {
+		return (IRuleSetNode) getNode();
+	}
+	
+	public void trigger(IRuleFlowNodeInstance from) {
+    	getProcessInstance().getAgenda()
+			.activateRuleFlowGroup(getRuleSetNode().getRuleFlowGroup());
+	}
+
+	public void triggerCompleted() {
+		getProcessInstance().getNodeInstance(getRuleSetNode().getTo().getTo()).trigger(this);
+	}
+
+}
\ No newline at end of file

Added: 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	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/RuleFlowSplitInstance.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,56 @@
+package org.drools.ruleflow.instance.impl;
+/*
+ * 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.
+ */
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.drools.ruleflow.core.IConnection;
+import org.drools.ruleflow.core.ISplit;
+import org.drools.ruleflow.instance.IRuleFlowNodeInstance;
+
+/**
+ * Runtime counterpart of a split node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class RuleFlowSplitInstance extends RuleFlowNodeInstance implements IRuleFlowNodeInstance {
+
+	protected ISplit getSplitNode() {
+		return (ISplit) getNode();
+	}
+	
+	public void trigger(IRuleFlowNodeInstance from) {
+		ISplit split = getSplitNode();
+		switch (split.getType()) {
+		case ISplit.TYPE_AND:
+			List outgoing = split.getOutgoingConnections();
+			for (Iterator iterator = outgoing.iterator(); iterator.hasNext(); ) {
+				IConnection connection = (IConnection) iterator.next();
+				getProcessInstance().getNodeInstance(connection.getTo()).trigger(this);
+			}
+			break;
+		default:
+			throw new IllegalArgumentException("Illegal split type " + split.getType());
+		}
+	}
+
+	public void triggerCompleted() {
+		// TODO Auto-generated method stub
+		
+	}
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/StartNodeInstance.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/StartNodeInstance.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/ruleflow/instance/impl/StartNodeInstance.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,39 @@
+package org.drools.ruleflow.instance.impl;
+/*
+ * 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.
+ */
+
+import org.drools.ruleflow.core.IStartNode;
+import org.drools.ruleflow.instance.IRuleFlowNodeInstance;
+
+/**
+ * Runtime counterpart of a start node.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public class StartNodeInstance extends RuleFlowNodeInstance {
+
+	public void trigger(IRuleFlowNodeInstance from) {
+		triggerCompleted();
+	}
+	
+	public IStartNode getStartNode() {
+		return (IStartNode) getNode();
+	}
+
+	public void triggerCompleted() {
+		getProcessInstance().getNodeInstance(getStartNode().getTo().getTo()).trigger(this);
+	}
+}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/RuleFlowGroup.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/RuleFlowGroup.java	2007-03-01 02:19:52 UTC (rev 9864)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/RuleFlowGroup.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -1,31 +0,0 @@
-package org.drools.spi;
-
-import java.util.Iterator;
-
-
-public interface RuleFlowGroup {
-    public String getName();
-
-    public void addActivation(Activation activation);
-
-    public void removeActivation(Activation activation);
-
-    public Iterator iterator();
-
-    public boolean isEmpty();
-
-    public int size();
-
-    public void clear();	
-	
-	public abstract void addChild(final RuleFlowGroup child);
-
-	public abstract boolean removeChild(final RuleFlowGroup child);
-
-	public abstract void activate();
-
-	public abstract void activateChildren();
-
-	public abstract Activation[] getActivations();
-
-}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/RuleFlowGroup.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/RuleFlowGroup.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/RuleFlowGroup.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,41 @@
+package org.drools.spi;
+/*
+ * 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.
+ */
+
+import java.util.Iterator;
+
+public interface RuleFlowGroup {
+	
+    String getName();
+    
+    public Iterator iterator();
+
+    boolean isEmpty();
+    
+    int size();
+    
+    boolean isActive();
+
+    boolean isAutoDeactivate();
+    
+    /**
+     * Sets the auto-deactivate status of this RuleFlowGroup.
+     * If this is set to true, an active RuleFlowGroup automatically
+     * deactivates if it has no more activations.  If it had no
+     * activations when it was activated, it will be deactivated immediately. 
+     */
+    void setAutoDeactivate(boolean autoDeactivate);
+}
\ No newline at end of file

Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/AgendaTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/AgendaTest.java	2007-03-01 02:19:52 UTC (rev 9864)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/AgendaTest.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -676,6 +676,12 @@
 
     }
 
+    /** 
+     * Basic RuleFlowGroup test where there are three rules, each in their own
+     * RuleFlowGroup.  First only rule-flow-group-0 is activated and rule0 is
+     * executed.  When the two remaining groups are activated, the rule with the
+     * highest priority is executed first.
+     */ 
     public void testRuleFlowGroup() {
         final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
 
@@ -736,9 +742,6 @@
         final RuleFlowGroup ruleFlowGroup1 = agenda.getRuleFlowGroup( "rule-flow-group-1" );
         final RuleFlowGroup ruleFlowGroup2 = agenda.getRuleFlowGroup( "rule-flow-group-2" );
 
-        ruleFlowGroup0.addChild( ruleFlowGroup1 );
-        ruleFlowGroup0.addChild( ruleFlowGroup2 );
-
         final ReteTuple tuple0 = new ReteTuple( new DefaultFactHandle( 1,
                                                                        "cheese" ) );
         node0.assertTuple( tuple0,
@@ -774,7 +777,7 @@
                       agenda.agendaSize() );
 
         // Activate the RuleFlowGroup, the nodes stay in the group, but should now also be in the Agenda
-        ruleFlowGroup0.activate();
+        agenda.activateRuleFlowGroup("rule-flow-group-0");
         assertEquals( 2,
                       ruleFlowGroup0.size() );
         assertEquals( 2,
@@ -787,17 +790,23 @@
         assertEquals( 1,
                       agenda.agendaSize() );
 
-        // on firing the last activation the child rule flow groups should 
-        // activate and thus repopulate the agenda
+        // After firing all activations of RuleFlowGroup 0, the agenda is empty
         agenda.fireNextItem( null );
         assertEquals( 0,
                       ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+
+        // Now we activate two RuleFlowGroups together
+        // All their activations should be added to the agenda.
+        agenda.activateRuleFlowGroup("rule-flow-group-1");
+        agenda.activateRuleFlowGroup("rule-flow-group-2");
         assertEquals( 1,
-                      ruleFlowGroup1.size() );
+                	  ruleFlowGroup1.size() );
         assertEquals( 1,
-                      ruleFlowGroup2.size() );        
+                 	  ruleFlowGroup2.size() );        
         assertEquals( 2,
-                      agenda.agendaSize() );        
+                	  agenda.agendaSize() );        
 
         // we set the salience higher on rule2, so it sould fire first and empty ruleFlowGroup2
         agenda.fireNextItem( null );
@@ -808,7 +817,7 @@
         assertEquals( 1,
                       agenda.agendaSize() );
         
-        // this is the last activation, so everything shoud be empty after this
+        // this is the last activation, so everything should be empty after this
         agenda.fireNextItem( null );
         assertEquals( 0,
                       ruleFlowGroup0.size() );        
@@ -819,4 +828,383 @@
         assertEquals( 0,
                       agenda.agendaSize() );        
     }
+    
+    /**
+     * RuleFlowGroup test that makes sure that, if new activations are created
+     * for an active RuleFlowGroup, those activations get added to the agenda
+     * directly as well.
+     */
+    public void testRuleFlowGroup1() {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newWorkingMemory();
+
+        final InternalAgenda agenda = (InternalAgenda) workingMemory.getAgenda();
+
+        // create rule1
+        final Consequence consequence1 = new Consequence() {
+            private static final long serialVersionUID = -2596133893109870505L;
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory workingMemory) {
+            	// do nothing
+            }
+        };
+
+        final Rule rule1 = new Rule( "test-rule1" );
+        rule1.setRuleFlowGroup( "rule-flow-group-0" );
+        rule1.setConsequence( consequence1 );
+
+        final RuleTerminalNode node1 = new RuleTerminalNode( 4,
+                                                             new MockTupleSource( 2 ),
+                                                             rule1,
+                                                             rule1.getLhs() );
+        
+        // create context
+        final PropagationContext context0 = new PropagationContextImpl( 0,
+														                PropagationContext.ASSERTION,
+														                rule1,
+														                null );
+
+        // create rule0
+        final Consequence consequence0 = new Consequence() {
+            private static final long serialVersionUID = -2596133893109870505L;
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory w) {
+            	// activate rule1
+                final ReteTuple tuple1 = new ReteTuple( new DefaultFactHandle( 1, "cheese" ) );
+                node1.assertTuple( tuple1,
+                                   context0,
+                                   workingMemory );
+            }
+        };
+
+        final Rule rule0 = new Rule( "test-rule0" );
+        rule0.setRuleFlowGroup( "rule-flow-group-0" );
+        rule0.setConsequence( consequence0 );
+
+        final RuleTerminalNode node0 = new RuleTerminalNode( 3,
+                                                             new MockTupleSource( 2 ),
+                                                             rule0,
+                                                             rule0.getLhs() );
+
+        final RuleFlowGroup ruleFlowGroup0 = agenda.getRuleFlowGroup( "rule-flow-group-0" );
+
+        // Create one activation for rule0 only
+        final ReteTuple tuple0 = new ReteTuple( new DefaultFactHandle( 1, "cheese" ) );
+        node0.assertTuple( tuple0,
+                           context0,
+                           workingMemory );
+
+        // RuleFlowGroup should be populated, but the agenda shouldn't be
+        assertEquals( 1,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+
+        // Activate the RuleFlowGroup, the activation stays in the group, but should now also be in the Agenda
+        agenda.activateRuleFlowGroup("rule-flow-group-0");
+        assertEquals( 1,
+                      ruleFlowGroup0.size() );
+        assertEquals( 1,
+                      agenda.agendaSize() );
+
+        // As we fire the rule, an new activation is created for rule1, and it should be added to group AND the agenda. 
+        agenda.fireNextItem( null );
+        assertEquals( 1,
+                      ruleFlowGroup0.size() );
+        assertEquals( 1,
+                      agenda.agendaSize() );
+
+        // After firing all activations of RuleFlowGroup 0, the agenda is empty
+        agenda.fireNextItem( null );
+        assertEquals( 0,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );   
+    }
+    
+    /**
+     * RuleFlowGroup test that makes sure that, if an activation in an active
+     * RuleFlowGroup gets deactivated, the activation is no longer executed.
+     */
+    public void testRuleFlowGroup2() {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newWorkingMemory();
+
+        final InternalAgenda agenda = (InternalAgenda) workingMemory.getAgenda();
+
+        // create rule1
+        final Consequence consequence1 = new Consequence() {
+            private static final long serialVersionUID = -2596133893109870505L;
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory workingMemory) {
+            	// do nothing
+            }
+        };
+
+        final Rule rule1 = new Rule( "test-rule1" );
+        rule1.setRuleFlowGroup( "rule-flow-group-0" );
+        rule1.setConsequence( consequence1 );
+
+        final RuleTerminalNode node1 = new RuleTerminalNode( 4,
+                                                             new MockTupleSource( 2 ),
+                                                             rule1,
+                                                             rule1.getLhs() );
+        
+        // create context
+        final PropagationContext context0 = new PropagationContextImpl( 0,
+														                PropagationContext.ASSERTION,
+														                rule1,
+														                null );
+
+        final ReteTuple tuple1 = new ReteTuple( new DefaultFactHandle( 1, "cheese" ) );
+
+        // create rule0
+        final Consequence consequence0 = new Consequence() {
+            private static final long serialVersionUID = -2596133893109870505L;
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory w) {
+            	// deactivate rule1
+                node1.retractTuple( tuple1,
+                                    context0,
+                                    workingMemory );
+            }
+        };
+
+        final Rule rule0 = new Rule( "test-rule0" );
+        rule0.setRuleFlowGroup( "rule-flow-group-0" );
+        rule0.setConsequence( consequence0 );
+        rule0.setSalience(10);
+
+        final RuleTerminalNode node0 = new RuleTerminalNode( 3,
+                                                             new MockTupleSource( 2 ),
+                                                             rule0,
+                                                             rule0.getLhs() );
+
+        final RuleFlowGroup ruleFlowGroup0 = agenda.getRuleFlowGroup( "rule-flow-group-0" );
+
+        // Create an activation for both rules
+        final ReteTuple tuple0 = new ReteTuple( new DefaultFactHandle( 1, "cheese" ) );
+        node0.assertTuple( tuple0,
+                           context0,
+                           workingMemory );
+
+        node1.assertTuple( tuple1,
+                           context0,
+                           workingMemory );
+
+        // RuleFlowGroup should be populated, but the agenda shouldn't be
+        assertEquals( 2,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+
+        // Activate the RuleFlowGroup, the activations stay in the group, but should now also be in the Agenda
+        agenda.activateRuleFlowGroup("rule-flow-group-0");
+        assertEquals( 2,
+                      ruleFlowGroup0.size() );
+        assertEquals( 2,
+                      agenda.agendaSize() );
+
+        // As we fire the rule, rule0 should execute first, as it has higher salience.
+        // Rule0 should deactivate rule1 as well, so the everything should be empty
+        agenda.fireNextItem( null );
+        assertEquals( 0,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+
+    }
+    
+    /**
+     * RuleFlowGroup test that makes sure that, when deactivating a RuleFlowGroup,
+     * all activations for that group are no longer on the agenda.  When
+     * reactivating the RuleFlowGroup however, they get added to the agenda again. 
+     */
+    public void testRuleFlowGroup3() {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newWorkingMemory();
+
+        final InternalAgenda agenda = (InternalAgenda) workingMemory.getAgenda();
+
+        // create rule0
+        final Consequence consequence0 = new Consequence() {
+            private static final long serialVersionUID = -2596133893109870505L;
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory w) {
+            	// do nothing
+            }
+        };
+
+        final Rule rule0 = new Rule( "test-rule0" );
+        rule0.setRuleFlowGroup( "rule-flow-group-0" );
+        rule0.setConsequence( consequence0 );
+
+        final RuleTerminalNode node0 = new RuleTerminalNode( 1,
+                                                             new MockTupleSource( 2 ),
+                                                             rule0,
+                                                             rule0.getLhs() );
+
+        final RuleFlowGroup ruleFlowGroup0 = agenda.getRuleFlowGroup( "rule-flow-group-0" );
+
+        // create context
+        final PropagationContext context0 = new PropagationContextImpl( 0,
+														                PropagationContext.ASSERTION,
+														                rule0,
+														                null );
+
+        // Create two activation for this rule
+        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 );
+
+        // RuleFlowGroup should be populated, but the agenda shouldn't be
+        assertEquals( 2,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+
+        // Activate the RuleFlowGroup, the activations stay in the group, but 
+        // should now also be in the Agenda
+        agenda.activateRuleFlowGroup("rule-flow-group-0");
+        assertEquals( 2,
+                      ruleFlowGroup0.size() );
+        assertEquals( 2,
+                      agenda.agendaSize() );
+
+        // Reactivate an already active RuleFlowGroup should not have any effect
+        agenda.activateRuleFlowGroup("rule-flow-group-0");
+        assertEquals( 2,
+                      ruleFlowGroup0.size() );
+        assertEquals( 2,
+                      agenda.agendaSize() );
+
+        // Deactivate the RuleFlowGroup, the activations should be removed from
+        // the agenda but still in the RuleFlowGroup
+        agenda.deactivateRuleFlowGroup("rule-flow-group-0");
+        assertEquals( 2,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+
+        // Reactivate the RuleFlowGroup, the activations stay in the group, but 
+        // should now also be in the Agenda again
+        agenda.activateRuleFlowGroup("rule-flow-group-0");
+        assertEquals( 2,
+                      ruleFlowGroup0.size() );
+        assertEquals( 2,
+                      agenda.agendaSize() );
+
+    }
+
+    /**
+     * Test auto-deactivation of RuleFlowGroup. 
+     */
+    public void testRuleFlowGroup4() {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newWorkingMemory();
+
+        final InternalAgenda agenda = (InternalAgenda) workingMemory.getAgenda();
+
+        // create rule0
+        final Consequence consequence0 = new Consequence() {
+            private static final long serialVersionUID = -2596133893109870505L;
+            public void evaluate(KnowledgeHelper knowledgeHelper,
+                                 WorkingMemory w) {
+            	// do nothing
+            }
+        };
+
+        final Rule rule0 = new Rule( "test-rule0" );
+        rule0.setRuleFlowGroup( "rule-flow-group-0" );
+        rule0.setConsequence( consequence0 );
+
+        final RuleTerminalNode node0 = new RuleTerminalNode( 1,
+                                                             new MockTupleSource( 2 ),
+                                                             rule0,
+                                                             rule0.getLhs() );
+
+        final RuleFlowGroup ruleFlowGroup0 = agenda.getRuleFlowGroup( "rule-flow-group-0" );
+        assertTrue( ruleFlowGroup0.isAutoDeactivate() );
+        ruleFlowGroup0.setAutoDeactivate(false);
+        assertFalse( ruleFlowGroup0.isAutoDeactivate() );
+
+        // create context
+        final PropagationContext context0 = new PropagationContextImpl( 0,
+														                PropagationContext.ASSERTION,
+														                rule0,
+														                null );
+
+        // Create an activation for this rule
+        final ReteTuple tuple0 = new ReteTuple( new DefaultFactHandle( 1, "cheese" ) );
+        node0.assertTuple( tuple0,
+                           context0,
+                           workingMemory );
+        
+        // RuleFlowGroup should be populated, but the agenda shouldn't be
+        assertEquals( 1,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+
+        // Activate the RuleFlowGroup, the activations stay in the group, but 
+        // should now also be in the Agenda
+        agenda.activateRuleFlowGroup("rule-flow-group-0");
+        assertEquals( 1,
+                      ruleFlowGroup0.size() );
+        assertEquals( 1,
+                      agenda.agendaSize() );
+
+        // Execute activation
+        agenda.fireNextItem( null );
+        assertEquals( 0,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+        assertTrue(   ruleFlowGroup0.isActive() );
+        
+        // Set auto-deactivation status to true
+        ruleFlowGroup0.setAutoDeactivate(true);
+        assertTrue( ruleFlowGroup0.isAutoDeactivate() );
+        assertFalse( ruleFlowGroup0.isActive() );
+
+        // Add another activation and activate RuleFlowGroup again
+        final ReteTuple tuple1 = new ReteTuple( new DefaultFactHandle( 1, "cheese" ) );
+        node0.assertTuple( tuple1,
+                           context0,
+                           workingMemory );
+        agenda.activateRuleFlowGroup("rule-flow-group-0");
+        assertEquals( 1,
+                      ruleFlowGroup0.size() );
+        assertEquals( 1,
+                      agenda.agendaSize() );
+        assertTrue(   ruleFlowGroup0.isActive() );
+
+        // Execute the activation, the RuleFlowGroup should automatically deactivate
+        agenda.fireNextItem( null );
+        assertEquals( 0,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+        assertFalse( ruleFlowGroup0.isActive() );
+
+        // A new activation should now be added to the RuleFlowGroup but not to the agenda 
+        final ReteTuple tuple2 = new ReteTuple( new DefaultFactHandle( 1, "cheese" ) );
+        node0.assertTuple( tuple2,
+                           context0,
+                           workingMemory );
+        assertEquals( 1,
+                      ruleFlowGroup0.size() );
+        assertEquals( 0,
+                      agenda.agendaSize() );
+    }
+
 }

Added: 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	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/RuleFlowGroupTest.java	2007-03-01 02:32:55 UTC (rev 9865)
@@ -0,0 +1,279 @@
+package org.drools.reteoo;
+
+/*
+ * 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.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.DroolsTestCase;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalAgenda;
+import org.drools.common.PropagationContextImpl;
+import org.drools.common.RuleFlowGroupImpl;
+import org.drools.rule.Rule;
+import org.drools.ruleflow.common.instance.IProcessInstance;
+import org.drools.ruleflow.core.IConnection;
+import org.drools.ruleflow.core.IEndNode;
+import org.drools.ruleflow.core.IJoin;
+import org.drools.ruleflow.core.IRuleFlowProcess;
+import org.drools.ruleflow.core.IRuleSetNode;
+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.EndNode;
+import org.drools.ruleflow.core.impl.Join;
+import org.drools.ruleflow.core.impl.RuleFlowProcess;
+import org.drools.ruleflow.core.impl.RuleSetNode;
+import org.drools.ruleflow.core.impl.Split;
+import org.drools.ruleflow.core.impl.StartNode;
+import org.drools.ruleflow.instance.IRuleFlowProcessInstance;
+import org.drools.ruleflow.instance.impl.RuleFlowProcessInstance;
+import org.drools.spi.Consequence;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.PropagationContext;
+
+/**
+ * @author mproctor
+ */
+
+public class RuleFlowGroupTest extends DroolsTestCase {
+
+	public void testRuleFlowGroup() {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+
+        final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newWorkingMemory();
+
+        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
+        IStartNode start = new StartNode();
+        IRuleSetNode ruleSet0 = new RuleSetNode();
+        ruleSet0.setRuleFlowGroup("rule-flow-group-0");
+        IRuleSetNode ruleSet1 = new RuleSetNode();
+        ruleSet1.setRuleFlowGroup("rule-flow-group-1");
+        IRuleSetNode ruleSet2 = new RuleSetNode();
+        ruleSet2.setRuleFlowGroup("rule-flow-group-2");
+        IRuleSetNode ruleSet3 = new RuleSetNode();
+        ruleSet3.setRuleFlowGroup("rule-flow-group-3");
+        ISplit split = new Split();
+        split.setType(ISplit.TYPE_AND);
+        IJoin join = new Join();
+        join.setType(IJoin.TYPE_AND);
+        IEndNode end = new EndNode();
+        // connections
+        new Connection(start, ruleSet0, IConnection.TYPE_NORMAL);
+        new Connection(ruleSet0, split, IConnection.TYPE_NORMAL);
+        new Connection(split, ruleSet1, IConnection.TYPE_NORMAL);
+        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);
+        
+        // process
+        IRuleFlowProcess process = new RuleFlowProcess();
+        process.addNode(start);
+        process.addNode(ruleSet0);
+        process.addNode(ruleSet1);
+        process.addNode(ruleSet2);
+        process.addNode(ruleSet3);
+        process.addNode(split);
+        process.addNode(join);
+        process.addNode(end);
+
+        // proces instance
+        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 );
+
+        // 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( 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() );
+
+        // on firing the last activation the child rule flow groups should 
+        // activate and thus repopulate the agenda
+        agenda.fireNextItem( null );
+        assertEquals( 0,
+                      ruleFlowGroup0.size() );
+        assertEquals( 1,
+                      ruleFlowGroup1.size() );
+        assertEquals( 1,
+                      ruleFlowGroup2.size() );        
+        assertEquals( 2,
+                      agenda.agendaSize() );        
+
+        // we set the salience higher on rule2, so it sould fire first and empty ruleFlowGroup2
+        agenda.fireNextItem( null );
+        assertEquals( 1,
+                      ruleFlowGroup1.size() );
+        assertEquals( 0,
+                      ruleFlowGroup2.size() );        
+        assertEquals( 1,
+                      agenda.agendaSize() );
+        
+        // executing rule1, which should activate AND-join and thus group 3 
+        agenda.fireNextItem( null );
+        assertEquals( 0,
+                      ruleFlowGroup0.size() );        
+        assertEquals( 0,
+                      ruleFlowGroup1.size() );
+        assertEquals( 0,
+                      ruleFlowGroup2.size() );        
+        assertEquals( 1,
+                	  ruleFlowGroup3.size() );        
+        assertEquals( 1,
+                      agenda.agendaSize() );   
+        
+        // executing rule3, and finishing execution
+        agenda.fireNextItem( null );
+        assertEquals( 0,
+                      ruleFlowGroup0.size() );        
+        assertEquals( 0,
+                      ruleFlowGroup1.size() );
+        assertEquals( 0,
+                      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