[jboss-svn-commits] JBL Code SVN: r8701 - in labs/jbossrules/trunk/drools-core/src: main/java/org/drools main/java/org/drools/common test/java/org/drools/reteoo

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Fri Jan 5 05:38:08 EST 2007


Author: michael.neale at jboss.com
Date: 2007-01-05 05:38:02 -0500 (Fri, 05 Jan 2007)
New Revision: 8701

Added:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/Otherwise.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/OtherwiseTest.java
Modified:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java
Log:
JBRULES-600 Otherwise first cut.

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/Otherwise.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/Otherwise.java	2007-01-05 02:44:18 UTC (rev 8700)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/Otherwise.java	2007-01-05 10:38:02 UTC (rev 8701)
@@ -0,0 +1,12 @@
+package org.drools;
+
+/**
+ * This class is essentually a named fact that will be asserted when the engine
+ * has not matched any rules.
+ * 
+ * @author Michael Neale
+ *
+ */
+public class Otherwise {
+
+}


Property changes on: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/Otherwise.java
___________________________________________________________________
Name: svn:eol-style
   + native

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-01-05 02:44:18 UTC (rev 8700)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java	2007-01-05 10:38:02 UTC (rev 8701)
@@ -33,6 +33,7 @@
 import org.drools.FactHandle;
 import org.drools.NoSuchFactHandleException;
 import org.drools.NoSuchFactObjectException;
+import org.drools.Otherwise;
 import org.drools.QueryResults;
 import org.drools.RuleBase;
 import org.drools.RuleBaseConfiguration;
@@ -342,21 +343,73 @@
         if ( !this.factQueue.isEmpty() ) {
             propagateQueuedActions();
         }
+        
+        boolean noneFired = true;
 
         if ( !this.firing ) {
             try {
                 this.firing = true;
-
+                
                 while ( this.agenda.fireNextItem( agendaFilter ) ) {
-                    ;
+                    noneFired = false;                    
                 }
             } finally {
                 this.firing = false;
+                if (noneFired) {
+                    doOtherwise(agendaFilter);
+                }
+                
             }
         }
     }
 
     /**
+     * This does the "otherwise" phase of processing.
+     * If no items are fired, then it will assert a temporary "Otherwise"
+     * fact and allow any rules to fire to handle "otherwise" cases.
+     */
+    private void doOtherwise(AgendaFilter agendaFilter) {
+        FactHandle handle = this.assertObject( new Otherwise() );
+        if ( !this.factQueue.isEmpty() ) {
+            propagateQueuedActions();
+        }
+        
+        while ( this.agenda.fireNextItem( agendaFilter ) ) {
+            ;
+        }
+        
+        this.retractObject( handle );
+    }
+
+
+//
+//        MN: The following is the traditional fireAllRules (without otherwise).
+//            Purely kept here as this implementation of otherwise is still experimental.    
+//    
+//    public synchronized void fireAllRules(final AgendaFilter agendaFilter) throws FactException {
+//        // If we're already firing a rule, then it'll pick up
+//        // the firing for any other assertObject(..) that get
+//        // nested inside, avoiding concurrent-modification
+//        // exceptions, depending on code paths of the actions.
+//
+//        if ( !this.factQueue.isEmpty() ) {
+//            propagateQueuedActions();
+//        }
+//
+//        if ( !this.firing ) {
+//            try {
+//                this.firing = true;
+//
+//                while ( this.agenda.fireNextItem( agendaFilter ) ) {
+//                    ;
+//                }
+//            } finally {
+//                this.firing = false;
+//            }
+//        }
+//    }    
+
+    /**
      * Returns the fact Object for the given <code>FactHandle</code>. It
      * actually attemps to return the value from the handle, before retrieving
      * it from objects map.

Added: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/OtherwiseTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/OtherwiseTest.java	2007-01-05 02:44:18 UTC (rev 8700)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/OtherwiseTest.java	2007-01-05 10:38:02 UTC (rev 8701)
@@ -0,0 +1,162 @@
+package org.drools.reteoo;
+
+import java.util.Map;
+
+import org.drools.Otherwise;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.base.ClassObjectType;
+import org.drools.base.ShadowProxyFactory;
+import org.drools.base.TestBean;
+import org.drools.examples.manners.Context;
+import org.drools.rule.Column;
+import org.drools.rule.Package;
+import org.drools.rule.Rule;
+import org.drools.rule.RuleConditionElement;
+import org.drools.spi.Consequence;
+import org.drools.spi.KnowledgeHelper;
+
+import junit.framework.TestCase;
+
+/**
+ * This tests the "otherwise" feature.
+ * @author Michael Neale
+ */
+public class OtherwiseTest extends TestCase {
+
+    public void testOneRuleFiringNoOtherwise() throws Exception {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.RETEOO );
+        
+        Package pkg = new Package( "Miss Manners" );
+        Rule rule1 = getRule("rule1");
+        pkg.addRule( rule1 );
+        
+        Rule ruleOtherwise = getOtherwise("rule2");
+        pkg.addRule( ruleOtherwise );
+        
+        ruleBase.addPackage( pkg );
+        
+        final WorkingMemory workingMemory = ruleBase.newWorkingMemory();
+        workingMemory.assertObject( new TestBean() );
+        workingMemory.fireAllRules();
+        
+        
+        assertTrue(((MockConsequence) rule1.getConsequence()).fired);
+        assertFalse(((MockConsequence) ruleOtherwise.getConsequence()).fired);
+         
+    }
+    
+    public void testTwoRulesFiringNoOtherwise() throws Exception {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.RETEOO );
+        
+        Package pkg = new Package( "Miss Manners" );
+        Rule rule1 = getRule("rule1");
+        pkg.addRule( rule1 );
+        Rule rule2 = getRule("rule2");
+        pkg.addRule( rule2 );
+        
+        Rule ruleOtherwise = getOtherwise("ruleOtherwise");
+        pkg.addRule( ruleOtherwise );
+        
+        ruleBase.addPackage( pkg );
+        
+        final WorkingMemory workingMemory = ruleBase.newWorkingMemory();
+        workingMemory.assertObject( new TestBean() );
+        workingMemory.fireAllRules();
+        
+        assertFalse(((MockConsequence) ruleOtherwise.getConsequence()).fired);  
+        assertTrue(((MockConsequence) rule1.getConsequence()).fired);
+        assertTrue(((MockConsequence) rule2.getConsequence()).fired);
+              
+    }
+    
+    public void testOtherwiseFiringWithOneRule() throws Exception {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.RETEOO );
+        
+        Package pkg = new Package( "Miss Manners" );
+        Rule rule1 = getRule("rule1");
+        pkg.addRule( rule1 );
+        
+        Rule ruleOtherwise = getOtherwise("rule2");
+        pkg.addRule( ruleOtherwise );
+        
+        ruleBase.addPackage( pkg );
+        
+        final WorkingMemory workingMemory = ruleBase.newWorkingMemory();
+        
+        workingMemory.fireAllRules();
+        
+        
+        assertFalse(((MockConsequence) rule1.getConsequence()).fired);
+        assertTrue(((MockConsequence) ruleOtherwise.getConsequence()).fired);
+        
+    }
+    
+    public void testOtherwiseFiringMultipleRules() throws Exception {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.RETEOO );
+        
+        Package pkg = new Package( "Miss Manners" );
+        Rule rule1 = getRule("rule1");
+        pkg.addRule( rule1 );
+        Rule rule2 = getRule("rule2");
+        pkg.addRule( rule2 );
+        
+        Rule ruleOtherwise1 = getOtherwise("other1");
+        pkg.addRule( ruleOtherwise1 );
+        Rule ruleOtherwise2 = getOtherwise("other2");
+        pkg.addRule( ruleOtherwise2 );
+
+        
+        
+        ruleBase.addPackage( pkg );
+        
+        final WorkingMemory workingMemory = ruleBase.newWorkingMemory();
+        
+        workingMemory.fireAllRules();
+        
+        
+        assertFalse(((MockConsequence) rule1.getConsequence()).fired);
+        assertFalse(((MockConsequence) rule2.getConsequence()).fired);
+        assertTrue(((MockConsequence) ruleOtherwise1.getConsequence()).fired);
+        assertTrue(((MockConsequence) ruleOtherwise2.getConsequence()).fired);
+        
+    }
+
+
+    
+    private Rule getOtherwise(String name) {
+        Rule rule = new Rule( name );
+        final Column pat = new Column( 0,
+                                       new ClassObjectType( Otherwise.class,
+                                                            ShadowProxyFactory.getProxy( Otherwise.class ) ) );
+        rule.addPattern( pat );
+        rule.setConsequence( new MockConsequence() );
+        return rule;
+    }
+
+    private Rule getRule(String name) {
+        Rule rule = new Rule( name );
+        
+        final Column pat = new Column( 0,
+                                                 new ClassObjectType( TestBean.class,
+                                                                      ShadowProxyFactory.getProxy( TestBean.class ) ) );
+        
+        rule.addPattern( pat );
+        rule.setConsequence(new MockConsequence());
+        
+        return rule;
+    }
+    
+    static class MockConsequence implements Consequence {
+
+        public boolean fired = false;
+        
+        public void evaluate(KnowledgeHelper knowledgeHelper,
+                             WorkingMemory workingMemory) throws Exception {
+            fired = true;
+        }
+        
+    }
+
+}


Property changes on: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/OtherwiseTest.java
___________________________________________________________________
Name: svn:eol-style
   + native




More information about the jboss-svn-commits mailing list