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

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Mon Jan 22 23:30:53 EST 2007


Author: mark.proctor at jboss.com
Date: 2007-01-22 23:30:53 -0500 (Mon, 22 Jan 2007)
New Revision: 8987

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/RuleFlowGroupNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/RuleFlowGroup.java
Removed:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/RuleFlowNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/
Modified:
   labs/jbossrules/trunk/drools-core/.classpath
   labs/jbossrules/trunk/drools-core/.project
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/Agenda.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/dataproviders/MVELDataProvider.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/common/ScheduledAgendaItem.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/RuleTerminalNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Rule.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/Activation.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/AgendaTest.java
Log:
JBRULES-619 Rule Flow Core Implementation

Modified: labs/jbossrules/trunk/drools-core/.classpath
===================================================================
--- labs/jbossrules/trunk/drools-core/.classpath	2007-01-23 00:39:35 UTC (rev 8986)
+++ labs/jbossrules/trunk/drools-core/.classpath	2007-01-23 04:30:53 UTC (rev 8987)
@@ -5,9 +5,12 @@
 	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
 	<classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="var" path="M2_REPO/antlr/antlr/2.7.7/antlr-2.7.7.jar"/>
+	<classpathentry kind="var" path="M2_REPO/antlr/stringtemplate/3.0/stringtemplate-3.0.jar"/>
 	<classpathentry kind="var" path="M2_REPO/xpp3/xpp3/1.1.3.4.O/xpp3-1.1.3.4.O.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/antlr/antlr/3.0b5/antlr-3.0b5.jar"/>
 	<classpathentry kind="var" path="M2_REPO/junit/junit/3.8.1/junit-3.8.1.jar"/>
 	<classpathentry kind="var" path="M2_REPO/xstream/xstream/1.1.3/xstream-1.1.3.jar"/>
-	<classpathentry kind="var" path="M2_REPO/org/antlr/antlr/3.0b5/antlr-3.0b5.jar"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/mvel"/>
 	<classpathentry kind="output" path="target/classes"/>
 </classpath>

Modified: labs/jbossrules/trunk/drools-core/.project
===================================================================
--- labs/jbossrules/trunk/drools-core/.project	2007-01-23 00:39:35 UTC (rev 8986)
+++ labs/jbossrules/trunk/drools-core/.project	2007-01-23 04:30:53 UTC (rev 8987)
@@ -1,28 +1,14 @@
 <projectDescription>
   <name>drools-core</name>
-  <comment/>
+  <comment>A rule production system</comment>
   <projects/>
   <buildSpec>
     <buildCommand>
-      <name>org.eclipse.wst.common.modulecore.ComponentStructuralBuilder</name>
-      <arguments/>
-    </buildCommand>
-    <buildCommand>
       <name>org.eclipse.jdt.core.javabuilder</name>
       <arguments/>
     </buildCommand>
-    <buildCommand>
-      <name>org.eclipse.wst.validation.validationbuilder</name>
-      <arguments/>
-    </buildCommand>
-    <buildCommand>
-      <name>org.eclipse.wst.common.modulecore.ComponentStructuralBuilderDependencyResolver</name>
-      <arguments/>
-    </buildCommand>
   </buildSpec>
   <natures>
-    <nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
     <nature>org.eclipse.jdt.core.javanature</nature>
-    <nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
   </natures>
 </projectDescription>
\ No newline at end of file

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-01-23 00:39:35 UTC (rev 8986)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/Agenda.java	2007-01-23 04:30:53 UTC (rev 8987)
@@ -3,6 +3,7 @@
 import org.drools.spi.Activation;
 import org.drools.spi.ActivationGroup;
 import org.drools.spi.AgendaGroup;
+import org.drools.spi.RuleFlowGroup;
 
 public interface Agenda {
 
@@ -17,6 +18,8 @@
     public AgendaGroup getFocus();
 
     public AgendaGroup getAgendaGroup(String name);
+    
+    public RuleFlowGroup getRuleFlowGroup(String name);
 
     public AgendaGroup[] getAgendaGroups();
 

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/dataproviders/MVELDataProvider.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/dataproviders/MVELDataProvider.java	2007-01-23 00:39:35 UTC (rev 8986)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/dataproviders/MVELDataProvider.java	2007-01-23 04:30:53 UTC (rev 8987)
@@ -1,5 +1,6 @@
 package org.drools.base.dataproviders;
 
+import java.io.Serializable;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
@@ -18,10 +19,10 @@
     implements
     DataProvider {
     //private final Expr              expression;
-    private final CompiledExpression expression;
+    private final Serializable expression;
     private final DroolsMVELFactory factory;
 
-    public MVELDataProvider(final CompiledExpression expression,
+    public MVELDataProvider(final Serializable expression,
                             final DroolsMVELFactory factory) {
         this.expression = expression;
         this.factory = factory;

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-01-23 00:39:35 UTC (rev 8986)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AgendaItem.java	2007-01-23 04:30:53 UTC (rev 8987)
@@ -21,7 +21,9 @@
 import org.drools.rule.GroupElement;
 import org.drools.rule.Rule;
 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;
@@ -52,7 +54,7 @@
 
     /** The rule. */
     private final Rule               rule;
-    
+
     /** The subrule */
     private final GroupElement       subrule;
 
@@ -71,8 +73,12 @@
 
     private boolean                  activated;
 
+    private AgendaGroupImpl          agendaGroup;
+
     private ActivationGroupNode      activationGroupNode;
 
+    private RuleFlowGroupNode        ruleFlowGroupNode;
+
     // ------------------------------------------------------------
     // Constructors
     // ------------------------------------------------------------
@@ -89,7 +95,7 @@
                       final Tuple tuple,
                       final PropagationContext context,
                       final Rule rule,
-                      final GroupElement subrule ) {
+                      final GroupElement subrule) {
         this.tuple = tuple;
         this.context = context;
         this.rule = rule;
@@ -206,6 +212,22 @@
         this.activationGroupNode = activationNode;
     }
 
+    public AgendaGroup getAgendaGroup() {
+        return agendaGroup;
+    }
+
+    public void setAgendaGroup(AgendaGroupImpl agendaGroup) {
+        this.agendaGroup = agendaGroup;
+    }
+
+    public RuleFlowGroupNode getRuleFlowGroupNode() {
+        return ruleFlowGroupNode;
+    }
+
+    public void setRuleFlowGroupNode(RuleFlowGroupNode ruleFlowGroupNode) {
+        this.ruleFlowGroupNode = ruleFlowGroupNode;
+    }
+
     public GroupElement getSubRule() {
         return this.subrule;
     }

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-01-23 00:39:35 UTC (rev 8986)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/DefaultAgenda.java	2007-01-23 04:30:53 UTC (rev 8987)
@@ -32,6 +32,7 @@
 import org.drools.spi.AgendaFilter;
 import org.drools.spi.AgendaGroup;
 import org.drools.spi.ConsequenceException;
+import org.drools.spi.RuleFlowGroup;
 import org.drools.util.LinkedListNode;
 import org.drools.util.Queueable;
 
@@ -63,7 +64,7 @@
     /**
      * 
      */
-    private static final long          serialVersionUID = -9112292414291983688L;
+    private static final long          serialVersionUID = 320L;
 
     /** Working memory of this Agenda. */
     private final WorkingMemory        workingMemory;
@@ -75,6 +76,8 @@
     private final Map                  agendaGroups;
 
     private final Map                  activationGroups;
+    
+    private final Map				   ruleFlowGroups;
 
     private final LinkedList           focusStack;
 
@@ -101,6 +104,7 @@
         this.knowledgeHelper = new DefaultKnowledgeHelper( this.workingMemory );
         this.agendaGroups = new HashMap();
         this.activationGroups = new HashMap();
+        this.ruleFlowGroups = new HashMap();
         this.focusStack = new LinkedList();
 
         // MAIN should always be the first AgendaGroup and can never be removed
@@ -256,6 +260,16 @@
         }
         return activationGroup;
     }
+    
+    public RuleFlowGroup getRuleFlowGroup(final String name) {
+    	RuleFlowGroupImpl ruleFlowGroup = (RuleFlowGroupImpl) this.ruleFlowGroups.get( name );
+        if ( ruleFlowGroup == null ) {
+        	ruleFlowGroup = new RuleFlowGroupImpl( name );
+            this.ruleFlowGroups.put( name,
+            						 ruleFlowGroup );
+        }
+        return ruleFlowGroup;
+    }    
 
     /* (non-Javadoc)
      * @see org.drools.common.AgendaI#focusStackSize()
@@ -429,11 +443,13 @@
         eventsupport.getAgendaEventSupport().fireBeforeActivationFired( activation, this.workingMemory  );
 
         if ( activation.getActivationGroupNode() != null ) {
+            // We know that this rule will cancel all other activatiosn in the group
+            // so lets remove the information now, before the consequence fires
             final ActivationGroup activationGroup = activation.getActivationGroupNode().getActivationGroup();
             activationGroup.removeActivation( activation );
             clearActivationGroup( activationGroup );
         }
-        activation.setActivated( false );
+        activation.setActivated( false );        
 
         try {
             this.knowledgeHelper.setActivation( activation );
@@ -444,6 +460,18 @@
             throw new ConsequenceException( e,
                                             activation.getRule() );
         }
+        
+        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();
+            ruleFlowGroup.removeActivation( activation );
+            
+            if ( ruleFlowGroup.isEmpty() ) {
+                ruleFlowGroup.activateChildren();
+            }
+        }
 
         eventsupport.getAgendaEventSupport().fireAfterActivationFired( activation );
     }

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-01-23 04:30:53 UTC (rev 8987)
@@ -0,0 +1,195 @@
+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/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-01-23 04:30:53 UTC (rev 8987)
@@ -0,0 +1,29 @@
+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;
+    }
+
+}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/RuleFlowNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/RuleFlowNode.java	2007-01-23 00:39:35 UTC (rev 8986)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/RuleFlowNode.java	2007-01-23 04:30:53 UTC (rev 8987)
@@ -1,176 +0,0 @@
-package org.drools.common;
-
-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.util.BinaryHeapQueue;
-import org.drools.util.Queueable;
-
-public class RuleFlowNode
-    implements
-    AgendaGroup {
-
-    private static final long     serialVersionUID = 320L;
-
-    private final String          name;
-
-    private final InternalAgenda  agenda;
-
-    /** @todo Maybe this should just be a LinkedList and we sort on use? */
-    private final BinaryHeapQueue queue;
-
-    private List                  childNodes       = Collections.EMPTY_LIST;
-
-    private final Object                lock;
-
-    /**
-     * Construct an <code>RuleFlowNode</code> with the given name.
-     * 
-     * @param name
-     *      The <RuleFlowNode> name.
-     */
-    public RuleFlowNode(final String name,
-                        final InternalAgenda agenda) {
-        this.name = name;
-        this.agenda = agenda;
-        this.queue = new BinaryHeapQueue( DepthConflictResolver.getInstance() );
-        this.lock = new Object();
-    }
-
-    /* (non-Javadoc)
-     * @see org.drools.spi.RuleFlowNode#getName()
-     */
-    public String getName() {
-        return this.name;
-    }
-
-    public void addChildNode(final RuleFlowNode child) {
-        if ( this.childNodes == Collections.EMPTY_LIST ) {
-            this.childNodes = new ArrayList( 1 );
-        }
-        this.childNodes.add( child );
-    }
-
-    public boolean removeChildNode(final RuleFlowNode child) {
-        return this.childNodes.remove( child );
-    }
-
-    public void clear() {
-        synchronized ( this.lock ) {
-            this.queue.clear();
-        }
-    }
-
-    /* (non-Javadoc)
-     * @see org.drools.spi.RuleFlowNode#size()
-     */
-    public int size() {
-        synchronized ( this.lock ) {
-            return this.queue.size();
-        }
-    }
-
-    public void add(final Activation activation) {
-        synchronized ( this.lock ) {
-            this.queue.enqueue( (Queueable) activation );
-        }
-    }
-
-    public Activation getNext() {
-        synchronized ( this.lock ) {
-            return (Activation) this.queue.dequeue();
-        }
-    }
-
-    /**
-     * Iterates a PriorityQueue removing empty entries until it finds a populated entry and return true,
-     * otherwise it returns false;
-     * 
-     * @param priorityQueue
-     * @return
-     */
-    public boolean isEmpty() {
-        synchronized ( this.lock ) {
-            return this.queue.isEmpty();
-        }
-    }
-
-    public Activation[] getActivations() {
-        synchronized ( this.lock ) {
-            return (Activation[]) this.queue.toArray( new AgendaItem[this.queue.size()] );
-        }
-    }
-
-    public Queueable[] getQueueable() {
-        return this.queue.getQueueable();
-    }
-
-    public void activate() {
-        Activation[] activations = null;
-        int i = 0;
-        // We need to make a sorted copy of the queue as an array
-        synchronized ( this.lock ) {
-            activations = new Activation[this.queue.size()];
-            while ( !this.queue.isEmpty() ) {
-                activations[i++] = (Activation) this.queue.dequeue();
-            }
-        }
-
-        // Make a runnable execution so we can fire all the activations
-        final ExecuteRuleFlowNode execute = new ExecuteRuleFlowNode( this.agenda,
-                                                               (RuleFlowNode[]) this.childNodes.toArray( new RuleFlowNode[this.childNodes.size()] ),
-                                                               activations );
-        final Thread thread = new Thread( execute );
-        thread.start();
-    }
-
-    public String toString() {
-        return "RuleFlowNode '" + this.name + "'";
-    }
-
-    public boolean equal(final Object object) {
-        if ( (object == null) || !(object instanceof RuleFlowNode) ) {
-            return false;
-        }
-
-        if ( ((RuleFlowNode) object).name.equals( this.name ) ) {
-            return true;
-        }
-
-        return false;
-    }
-
-    public int hashCode() {
-        return this.name.hashCode();
-    }
-
-    public static class ExecuteRuleFlowNode
-        implements
-        Runnable {
-        private final InternalAgenda agenda;
-        private final RuleFlowNode[] nodes;
-        private final Activation[]   activations;
-
-        public ExecuteRuleFlowNode(final InternalAgenda agenda,
-                                   final RuleFlowNode[] nodes,
-                                   final Activation[] activations) {
-            this.agenda = agenda;
-            this.nodes = nodes;
-            this.activations = activations;
-        }
-
-        public void run() {
-            for ( int i = 0, length = this.activations.length; i < length; i++ ) {
-                this.agenda.fireActivation( this.activations[i] );
-            }
-
-            for ( int i = 0, length = this.nodes.length; i < length; i++ ) {
-                this.nodes[i].activate();
-            }
-        }
-    }
-}

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/ScheduledAgendaItem.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/ScheduledAgendaItem.java	2007-01-23 00:39:35 UTC (rev 8986)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/ScheduledAgendaItem.java	2007-01-23 04:30:53 UTC (rev 8987)
@@ -22,6 +22,7 @@
 import org.drools.rule.GroupElement;
 import org.drools.rule.Rule;
 import org.drools.spi.Activation;
+import org.drools.spi.AgendaGroup;
 import org.drools.spi.PropagationContext;
 import org.drools.spi.Tuple;
 import org.drools.util.LinkedList;
@@ -69,7 +70,7 @@
 
     private boolean                  activated;
 
-    private ActivationGroupNode      activationGroupNode;
+    private ActivationGroupNode      activationGroupNode;       
 
     // ------------------------------------------------------------
     // Constructors
@@ -185,7 +186,19 @@
     public void setActivationGroupNode(final ActivationGroupNode activationGroupNode) {
         this.activationGroupNode = activationGroupNode;
     }
+    
+    public RuleFlowGroupNode getRuleFlowGroupNode() {
+        throw new UnsupportedOperationException( "Scheduled activations cannot be in a Rule Flow Group" );
+    }
 
+    public void setRuleFlowGroupNode(RuleFlowGroupNode ruleFlowGroupNode) {
+        throw new UnsupportedOperationException( "Scheduled activations cannot be in a Rule Flow Group" );
+    }    
+
+    public AgendaGroup getAgendaGroup() {
+        throw new UnsupportedOperationException( "Scheduled activations cannot be in an Agenda Group");
+    }
+    
     /*
      * (non-Javadoc)
      * 

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-01-23 00:39:35 UTC (rev 8986)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/RuleTerminalNode.java	2007-01-23 04:30:53 UTC (rev 8987)
@@ -26,6 +26,7 @@
 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;
@@ -34,6 +35,7 @@
 import org.drools.spi.AgendaGroup;
 import org.drools.spi.Duration;
 import org.drools.spi.PropagationContext;
+import org.drools.spi.RuleFlowGroup;
 import org.drools.util.Iterator;
 import org.drools.util.TupleHashTable;
 
@@ -221,11 +223,26 @@
                 }
                 memory.getActivationGroup().addActivation( item );
             }
+            
+            if ( this.rule.getRuleFlowGroup() == null ) {
+                // No RuleFlowNode so add  it directly to  the Agenda
+            	
+                // Makes sure the Lifo is added to the AgendaGroup priority queue
+                // If the AgendaGroup is already in the priority queue it just
+                // returns.
+                agendaGroup.add( item );            	
+            } else {
+            	//There is  a RuleFlowNode so add it there, instead  of the Agenda
+            	
+                // Lazy cache ruleFlowGroup
+                if ( memory.getRuleFlowGroup() == null ) {
+                    memory.setRuleFlowGroup( workingMemory.getAgenda().getRuleFlowGroup( this.rule.getRuleFlowGroup() ) );
+                }
+                memory.getRuleFlowGroup().addActivation( item );
+            }  
+            
+            item.setAgendaGroup( agendaGroup );
 
-            // Makes sure the Lifo is added to the AgendaGroup priority queue
-            // If the AgendaGroup is already in the priority queue it just
-            // returns.
-            agendaGroup.add( item );
             tuple.setActivation( item );
             memory.getTupleMemory().add( tuple );
 
@@ -384,6 +401,8 @@
         private AgendaGroupImpl   agendaGroup;
 
         private ActivationGroup   activationGroup;
+        
+        private RuleFlowGroup     ruleFlowGroup;
 
         private TupleHashTable    tupleMemory;
 
@@ -410,5 +429,13 @@
         public TupleHashTable getTupleMemory() {
             return this.tupleMemory;
         }
+
+		public RuleFlowGroup getRuleFlowGroup() {
+			return ruleFlowGroup;
+		}
+
+		public void setRuleFlowGroup(RuleFlowGroup ruleFlowGroup) {
+			this.ruleFlowGroup = ruleFlowGroup;
+		}                        
     }
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Rule.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Rule.java	2007-01-23 00:39:35 UTC (rev 8986)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Rule.java	2007-01-23 04:30:53 UTC (rev 8987)
@@ -83,7 +83,9 @@
     /** makes the rule's much the current focus */
     private boolean           autoFocus;
 
-    private String            ActivationGroup;
+    private String            activationGroup;
+    
+    private String		      ruleFlowGroup;
 
     /** indicates that the rule is semantically correct. */
     private boolean           semanticallyValid = true;
@@ -278,14 +280,24 @@
     }
 
     public String getActivationGroup() {
-        return this.ActivationGroup;
+        return this.activationGroup;
     }
 
-    public void setXorGroup(final String activationGroup) {
-        this.ActivationGroup = activationGroup;
+    public void setActivationGroup(final String activationGroup) {
+        this.activationGroup = activationGroup;
     }
+    
+    
 
-    /**
+    public String getRuleFlowGroup() {
+		return ruleFlowGroup;
+	}
+
+	public void setRuleFlowGroup(String ruleFlowGroup) {
+		this.ruleFlowGroup = ruleFlowGroup;
+	}
+
+	/**
      * Retrieve a parameter <code>Declaration</code> by identifier.
      * 
      * @param identifier
@@ -435,7 +447,7 @@
         final Rule other = (Rule) object;
 
         return (this.name.equals( other.name ) && this.agendaGroup.equals( other.agendaGroup )
-                && ((this.ActivationGroup == null && other.ActivationGroup == null) || (this.ActivationGroup != null && this.ActivationGroup.equals( other.ActivationGroup ))) && this.salience == other.salience && this.noLoop == other.noLoop);
+                && ((this.activationGroup == null && other.activationGroup == null) || (this.activationGroup != null && this.activationGroup.equals( other.activationGroup ))) && this.salience == other.salience && this.noLoop == other.noLoop);
     }
 
     public int hashCode() {

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/Activation.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/Activation.java	2007-01-23 00:39:35 UTC (rev 8986)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/Activation.java	2007-01-23 04:30:53 UTC (rev 8987)
@@ -20,6 +20,7 @@
 
 import org.drools.common.ActivationGroupNode;
 import org.drools.common.LogicalDependency;
+import org.drools.common.RuleFlowGroupNode;
 import org.drools.rule.GroupElement;
 import org.drools.rule.Rule;
 import org.drools.util.LinkedList;
@@ -81,8 +82,14 @@
     public boolean isActivated();
 
     public void setActivated(boolean activated);
+    
+    public AgendaGroup getAgendaGroup();
 
     public ActivationGroupNode getActivationGroupNode();
 
     public void setActivationGroupNode(ActivationGroupNode activationGroupNode);
+    
+    public RuleFlowGroupNode getRuleFlowGroupNode();
+    
+    public void setRuleFlowGroupNode(RuleFlowGroupNode ruleFlowGroupNode);
 }
\ 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-01-23 04:30:53 UTC (rev 8987)
@@ -0,0 +1,31 @@
+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

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-01-23 00:39:35 UTC (rev 8986)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/AgendaTest.java	2007-01-23 04:30:53 UTC (rev 8987)
@@ -39,6 +39,7 @@
 import org.drools.spi.ConsequenceException;
 import org.drools.spi.KnowledgeHelper;
 import org.drools.spi.PropagationContext;
+import org.drools.spi.RuleFlowGroup;
 
 /**
  * @author mproctor
@@ -55,9 +56,9 @@
         final Rule rule1 = new Rule( "test-rule1" );
 
         final RuleTerminalNode node1 = new RuleTerminalNode( 3,
-                                                     new MockTupleSource( 2 ),
-                                                     rule1,
-                                                     rule1.getLhs());
+                                                             new MockTupleSource( 2 ),
+                                                             rule1,
+                                                             rule1.getLhs() );
 
         final ReteTuple tuple = new ReteTuple( new DefaultFactHandle( 1,
                                                                       "cheese" ) );
@@ -107,9 +108,9 @@
 
         final Rule rule = new Rule( "test-rule" );
         final RuleTerminalNode node = new RuleTerminalNode( 3,
-                                                    new MockTupleSource( 2 ),
-                                                    rule,
-                                                    rule.getLhs() );
+                                                            new MockTupleSource( 2 ),
+                                                            rule,
+                                                            rule.getLhs() );
 
         final Map results = new HashMap();
         // add consequence
@@ -230,9 +231,9 @@
         // create a rule for each agendaGroup
         final Rule rule0 = new Rule( "test-rule0" );
         final RuleTerminalNode node0 = new RuleTerminalNode( 3,
-                                                     new MockTupleSource( 2 ),
-                                                     rule0,
-                                                     rule0.getLhs() );
+                                                             new MockTupleSource( 2 ),
+                                                             rule0,
+                                                             rule0.getLhs() );
         rule0.setConsequence( consequence );
         final PropagationContext context0 = new PropagationContextImpl( 0,
                                                                         PropagationContext.ASSERTION,
@@ -242,9 +243,9 @@
         final Rule rule1 = new Rule( "test-rule1",
                                      "agendaGroup1" );
         final RuleTerminalNode node1 = new RuleTerminalNode( 5,
-                                                     new MockTupleSource( 4 ),
-                                                     rule1,
-                                                     rule1.getLhs() );
+                                                             new MockTupleSource( 4 ),
+                                                             rule1,
+                                                             rule1.getLhs() );
         rule1.setConsequence( consequence );
         final PropagationContext context1 = new PropagationContextImpl( 0,
                                                                         PropagationContext.ASSERTION,
@@ -254,9 +255,9 @@
         final Rule rule2 = new Rule( "test-rule2",
                                      "agendaGroup2" );
         final RuleTerminalNode node2 = new RuleTerminalNode( 7,
-                                                     new MockTupleSource( 6 ),
-                                                     rule2,
-                                                     rule2.getLhs() );
+                                                             new MockTupleSource( 6 ),
+                                                             rule2,
+                                                             rule2.getLhs() );
         rule2.setConsequence( consequence );
         final PropagationContext context2 = new PropagationContextImpl( 0,
                                                                         PropagationContext.ASSERTION,
@@ -266,9 +267,9 @@
         final Rule rule3 = new Rule( "test-rule3",
                                      "agendaGroup3" );
         final RuleTerminalNode node3 = new RuleTerminalNode( 9,
-                                                     new MockTupleSource( 8 ),
-                                                     rule3,
-                                                     rule3.getLhs() );
+                                                             new MockTupleSource( 8 ),
+                                                             rule3,
+                                                             rule3.getLhs() );
         rule3.setConsequence( consequence );
         final PropagationContext context3 = new PropagationContextImpl( 0,
                                                                         PropagationContext.ASSERTION,
@@ -447,9 +448,9 @@
         final Rule rule = new Rule( "test-rule",
                                     "agendaGroup" );
         final RuleTerminalNode node = new RuleTerminalNode( 2,
-                                                    new MockTupleSource( 2 ),
-                                                    rule,
-                                                    rule.getLhs() );
+                                                            new MockTupleSource( 2 ),
+                                                            rule,
+                                                            rule.getLhs() );
         rule.setConsequence( consequence );
         final PropagationContext context = new PropagationContextImpl( 0,
                                                                        PropagationContext.ASSERTION,
@@ -495,7 +496,7 @@
         //                      queue.size() );
     }
 
-    public void testXorGroup() {
+    public void testActivationGroup() {
         final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
 
         final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newWorkingMemory();
@@ -522,11 +523,11 @@
 
         // create a rule for each agendaGroup
         final Rule rule0 = new Rule( "test-rule0" );
-        rule0.setXorGroup( "activation-group-0" );
+        rule0.setActivationGroup( "activation-group-0" );
         final RuleTerminalNode node0 = new RuleTerminalNode( 3,
-                                                     new MockTupleSource( 2 ),
-                                                     rule0,
-                                                     rule0.getLhs() );
+                                                             new MockTupleSource( 2 ),
+                                                             rule0,
+                                                             rule0.getLhs() );
         rule0.setConsequence( consequence );
         final PropagationContext context0 = new PropagationContextImpl( 0,
                                                                         PropagationContext.ASSERTION,
@@ -534,11 +535,11 @@
                                                                         null );
 
         final Rule rule1 = new Rule( "test-rule1" );
-        rule1.setXorGroup( "activation-group-0" );
+        rule1.setActivationGroup( "activation-group-0" );
         final RuleTerminalNode node1 = new RuleTerminalNode( 5,
-                                                     new MockTupleSource( 4 ),
-                                                     rule1,
-                                                     rule1.getLhs() );
+                                                             new MockTupleSource( 4 ),
+                                                             rule1,
+                                                             rule1.getLhs() );
         rule1.setConsequence( consequence );
         final PropagationContext context1 = new PropagationContextImpl( 0,
                                                                         PropagationContext.ASSERTION,
@@ -547,9 +548,9 @@
 
         final Rule rule2 = new Rule( "test-rule2" );
         final RuleTerminalNode node2 = new RuleTerminalNode( 7,
-                                                     new MockTupleSource( 6 ),
-                                                     rule2,
-                                                     rule2.getLhs() );
+                                                             new MockTupleSource( 6 ),
+                                                             rule2,
+                                                             rule2.getLhs() );
         rule2.setConsequence( consequence );
         final PropagationContext context2 = new PropagationContextImpl( 0,
                                                                         PropagationContext.ASSERTION,
@@ -558,11 +559,11 @@
 
         final Rule rule3 = new Rule( "test-rule3",
                                      "agendaGroup3" );
-        rule3.setXorGroup( "activation-group-3" );
+        rule3.setActivationGroup( "activation-group-3" );
         final RuleTerminalNode node3 = new RuleTerminalNode( 9,
-                                                     new MockTupleSource( 8 ),
-                                                     rule3,
-                                                     rule3.getLhs() );
+                                                             new MockTupleSource( 8 ),
+                                                             rule3,
+                                                             rule3.getLhs() );
         rule3.setConsequence( consequence );
         final PropagationContext context3 = new PropagationContextImpl( 0,
                                                                         PropagationContext.ASSERTION,
@@ -661,4 +662,147 @@
 
     }
 
+    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 PropagationContext context0 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        rule0,
+                                                                        null );
+
+        final RuleFlowGroup ruleFlowGroup0 = agenda.getRuleFlowGroup( "rule-flow-group-0" );
+        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,
+                           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 );
+
+        // RuleFlowGroups should be populated, but the agenda shouldn't be
+        assertEquals( 2,
+                      ruleFlowGroup0.size() );
+        assertEquals( 1,
+                      ruleFlowGroup1.size() );
+        assertEquals( 1,
+                      ruleFlowGroup2.size() );        
+        assertEquals( 0,
+                      agenda.agendaSize() );
+
+        // Activate the RuleFlowGroup, the nodes stay in the group, but should now also be in the Agenda
+        ruleFlowGroup0.activate();
+        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() );
+        
+        // this is the last activation, so everything shoud be empty after this
+        agenda.fireNextItem( null );
+        assertEquals( 0,
+                      ruleFlowGroup0.size() );        
+        assertEquals( 0,
+                      ruleFlowGroup1.size() );
+        assertEquals( 0,
+                      ruleFlowGroup2.size() );        
+        assertEquals( 0,
+                      agenda.agendaSize() );        
+    }
 }




More information about the jboss-svn-commits mailing list