[jboss-svn-commits] JBL Code SVN: r29630 - in labs/jbossrules/trunk: drools-compiler/src/test/java/org/drools/integrationtests and 5 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Thu Oct 15 19:14:17 EDT 2009


Author: tirelli
Date: 2009-10-15 19:14:17 -0400 (Thu, 15 Oct 2009)
New Revision: 29630

Added:
   labs/jbossrules/trunk/drools-compiler/src/test/resources/org/drools/integrationtests/test_ForallSlidingWindow.drl
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ForallNotNode.java
Modified:
   labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/PatternBuilder.java
   labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/FirstOrderLogicTest.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/marshalling/impl/InputMarshaller.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/marshalling/impl/OutputMarshaller.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/NodeTypeEnums.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/NotNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/ForallBuilder.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/GroupElementBuilder.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/GroupElement.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/GroupElementFactory.java
Log:
JBRULES-2288: fixing FORALL behavior

Modified: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/PatternBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/PatternBuilder.java	2009-10-15 20:47:19 UTC (rev 29629)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/PatternBuilder.java	2009-10-15 23:14:17 UTC (rev 29630)
@@ -210,14 +210,22 @@
         }
 
         for ( BehaviorDescr behaviorDescr : patternDescr.getBehaviors() ) {
-            if ( Behavior.BehaviorType.TIME_WINDOW.matches( behaviorDescr.getType() ) ) {
-                SlidingWindowDescr swd = (SlidingWindowDescr) behaviorDescr;
-                SlidingTimeWindow window = new SlidingTimeWindow( swd.getLength() );
-                pattern.addBehavior( window );
-            } else if ( Behavior.BehaviorType.LENGTH_WINDOW.matches( behaviorDescr.getType() ) ) {
-                SlidingWindowDescr swd = (SlidingWindowDescr) behaviorDescr;
-                SlidingLengthWindow window = new SlidingLengthWindow( (int) swd.getLength() );
-                pattern.addBehavior( window );
+            if( pattern.getObjectType().isEvent() ) {
+                if ( Behavior.BehaviorType.TIME_WINDOW.matches( behaviorDescr.getType() ) ) {
+                    SlidingWindowDescr swd = (SlidingWindowDescr) behaviorDescr;
+                    SlidingTimeWindow window = new SlidingTimeWindow( swd.getLength() );
+                    pattern.addBehavior( window );
+                } else if ( Behavior.BehaviorType.LENGTH_WINDOW.matches( behaviorDescr.getType() ) ) {
+                    SlidingWindowDescr swd = (SlidingWindowDescr) behaviorDescr;
+                    SlidingLengthWindow window = new SlidingLengthWindow( (int) swd.getLength() );
+                    pattern.addBehavior( window );
+                }
+            } else {
+                // Some behaviors can only be assigned to patterns declared as events
+                context.getErrors().add( new DescrBuildError( context.getParentDescr(),
+                                                              patternDescr,
+                                                              null,
+                                                              "A Sliding Window behavior can only be assigned to patterns declared with @role( event ). The pattern '" + pattern.getObjectType() + "' in the rule '" + context.getRule().getName() + "' is not declared as an Event." ) );
             }
         }
 

Modified: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/FirstOrderLogicTest.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/FirstOrderLogicTest.java	2009-10-15 20:47:19 UTC (rev 29629)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/FirstOrderLogicTest.java	2009-10-15 23:14:17 UTC (rev 29630)
@@ -6,6 +6,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 import junit.framework.Assert;
 import junit.framework.TestCase;
@@ -13,8 +14,10 @@
 import org.drools.Address;
 import org.drools.Cheese;
 import org.drools.Cheesery;
+import org.drools.ClockType;
 import org.drools.FactHandle;
 import org.drools.KnowledgeBase;
+import org.drools.KnowledgeBaseConfiguration;
 import org.drools.KnowledgeBaseFactory;
 import org.drools.Order;
 import org.drools.OrderItem;
@@ -26,6 +29,7 @@
 import org.drools.SpecialString;
 import org.drools.State;
 import org.drools.StatefulSession;
+import org.drools.StockTick;
 import org.drools.WorkingMemory;
 import org.drools.builder.KnowledgeBuilder;
 import org.drools.builder.KnowledgeBuilderFactory;
@@ -33,11 +37,15 @@
 import org.drools.compiler.DrlParser;
 import org.drools.compiler.DroolsParserException;
 import org.drools.compiler.PackageBuilder;
+import org.drools.integrationtests.eventgenerator.PseudoSessionClock;
 import org.drools.io.ResourceFactory;
 import org.drools.lang.descr.PackageDescr;
 import org.drools.rule.Package;
 import org.drools.rule.Rule;
+import org.drools.runtime.KnowledgeSessionConfiguration;
 import org.drools.runtime.StatefulKnowledgeSession;
+import org.drools.runtime.conf.ClockTypeOption;
+import org.drools.time.SessionPseudoClock;
 
 public class FirstOrderLogicTest extends TestCase {
     protected RuleBase getRuleBase() throws Exception {
@@ -76,7 +84,7 @@
                                150 ) );
         wm = SerializationHelper.getSerialisedStatefulSession( wm );
         results = (List) wm.getGlobal( "results" );
-        
+
         wm.insert( new Cheese( "provolone",
                                20 ) );
         wm.insert( new Person( "Bob",
@@ -90,7 +98,7 @@
 
         wm = SerializationHelper.getSerialisedStatefulSession( wm );
         results = (List) wm.getGlobal( "results" );
-        
+
         Assert.assertEquals( 1,
                              results.size() );
         Assert.assertEquals( 3,
@@ -106,7 +114,7 @@
 
         RuleBase ruleBase = getRuleBase();
         ruleBase.addPackage( pkg );
-        ruleBase    = SerializationHelper.serializeObject(ruleBase);
+        ruleBase = SerializationHelper.serializeObject( ruleBase );
         StatefulSession workingMemory = ruleBase.newStatefulSession();
 
         List results = new ArrayList();
@@ -115,12 +123,12 @@
 
         workingMemory = SerializationHelper.getSerialisedStatefulSession( workingMemory );
         results = (List) workingMemory.getGlobal( "results" );
-        
+
         workingMemory.insert( new Cheese( "stilton",
                                           10 ) );
         workingMemory = SerializationHelper.getSerialisedStatefulSession( workingMemory );
         results = (List) workingMemory.getGlobal( "results" );
-        
+
         workingMemory.insert( new Cheese( "brie",
                                           15 ) );
 
@@ -128,7 +136,7 @@
 
         workingMemory = SerializationHelper.getSerialisedStatefulSession( workingMemory );
         results = (List) workingMemory.getGlobal( "results" );
-        
+
         assertEquals( 1,
                       results.size() );
 
@@ -178,7 +186,7 @@
         cheese[index].setPrice( 9 );
         wm.update( cheeseHandles[index],
                    cheese[index] );
-        
+
         wm.fireAllRules();
 
         Assert.assertEquals( ++fireCount,
@@ -222,14 +230,14 @@
                                10 ) );
         wm = SerializationHelper.getSerialisedStatefulSession( wm );
         results = (List) wm.getGlobal( "results" );
-        
+
         wm.fireAllRules();
 
         Assert.assertEquals( 1,
                              results.size() );
         Assert.assertEquals( 1,
                              ((Collection) results.get( 0 )).size() );
-        
+
         wm.insert( new Cheese( "stilton",
                                7 ) );
         wm.insert( new Cheese( "stilton",
@@ -238,7 +246,7 @@
 
         wm = SerializationHelper.getSerialisedStatefulSession( wm );
         results = (List) wm.getGlobal( "results" );
-        
+
         Assert.assertEquals( 1,
                              results.size() );
         Assert.assertEquals( 1,
@@ -254,7 +262,7 @@
 
         RuleBase ruleBase = getRuleBase();
         ruleBase.addPackage( pkg );
-        ruleBase    = SerializationHelper.serializeObject(ruleBase);
+        ruleBase = SerializationHelper.serializeObject( ruleBase );
         final WorkingMemory workingMemory = ruleBase.newStatefulSession();
 
         final List list = new ArrayList();
@@ -321,7 +329,7 @@
                       builder.getErrors().getErrors().length );
         RuleBase ruleBase = getRuleBase();
         ruleBase.addPackage( pkg );
-        ruleBase    = SerializationHelper.serializeObject(ruleBase);
+        ruleBase = SerializationHelper.serializeObject( ruleBase );
         final WorkingMemory workingMemory = ruleBase.newStatefulSession();
 
         final List list = new ArrayList();
@@ -359,7 +367,7 @@
 
         RuleBase ruleBase = getRuleBase();
         ruleBase.addPackage( pkg );
-        ruleBase    = SerializationHelper.serializeObject(ruleBase);
+        ruleBase = SerializationHelper.serializeObject( ruleBase );
         final WorkingMemory workingMemory = ruleBase.newStatefulSession();
 
         final List list = new ArrayList();
@@ -398,7 +406,7 @@
 
         RuleBase ruleBase = getRuleBase();
         ruleBase.addPackage( pkg );
-        ruleBase    = SerializationHelper.serializeObject(ruleBase);
+        ruleBase = SerializationHelper.serializeObject( ruleBase );
         final WorkingMemory workingMemory = ruleBase.newStatefulSession();
 
         final List list = new ArrayList();
@@ -442,7 +450,7 @@
 
         RuleBase ruleBase = getRuleBase();
         ruleBase.addPackage( pkg );
-        ruleBase    = SerializationHelper.serializeObject(ruleBase);
+        ruleBase = SerializationHelper.serializeObject( ruleBase );
         final WorkingMemory workingMemory = ruleBase.newStatefulSession();
 
         final List list = new ArrayList();
@@ -479,7 +487,7 @@
         config.setRemoveIdentities( true );
         RuleBase ruleBase = getRuleBase( config );
         ruleBase.addPackage( pkg );
-        ruleBase    = SerializationHelper.serializeObject(ruleBase);
+        ruleBase = SerializationHelper.serializeObject( ruleBase );
         final WorkingMemory workingMemory = ruleBase.newStatefulSession();
 
         final List list = new ArrayList();
@@ -529,7 +537,7 @@
 
         RuleBase ruleBase = getRuleBase();
         ruleBase.addPackage( pkg );
-        ruleBase    = SerializationHelper.serializeObject(ruleBase);
+        ruleBase = SerializationHelper.serializeObject( ruleBase );
 
         final WorkingMemory workingMemory = ruleBase.newStatefulSession();
         final List results = new ArrayList();
@@ -646,7 +654,7 @@
         // add the package to a rulebase
         RuleBase ruleBase = getRuleBase();
         ruleBase.addPackage( pkg );
-        ruleBase    = SerializationHelper.serializeObject(ruleBase);
+        ruleBase = SerializationHelper.serializeObject( ruleBase );
         // load up the rulebase
         return ruleBase;
     }
@@ -658,7 +666,7 @@
 
         RuleBase ruleBase = getRuleBase();
         ruleBase.addPackage( pkg );
-        ruleBase    = SerializationHelper.serializeObject(ruleBase);
+        ruleBase = SerializationHelper.serializeObject( ruleBase );
         final WorkingMemory workingMemory = ruleBase.newStatefulSession();
 
         final List list = new ArrayList();
@@ -703,13 +711,10 @@
         assertEquals( 2,
                       list.size() );
 
-        //        TODO: in the future, we need to fix the following test case
-        //        // no cheese anymore, so should not fire again 
-        //        workingMemory.retract( stilton2 );
-        //        workingMemory.fireAllRules();
-        //        assertEquals( 2,
-        //                      list.size() );
-        //        
+        workingMemory.retract( stilton2 );
+        workingMemory.fireAllRules();
+        assertEquals( 2,
+                      list.size() );
 
     }
 
@@ -757,7 +762,7 @@
 
         RuleBase ruleBase = RuleBaseFactory.newRuleBase();
         ruleBase.addPackage( builder.getPackage() );
-        ruleBase    = SerializationHelper.serializeObject(ruleBase);
+        ruleBase = SerializationHelper.serializeObject( ruleBase );
         StatefulSession session = ruleBase.newStatefulSession();
 
         List list1 = new ArrayList();
@@ -822,7 +827,7 @@
 
         RuleBase ruleBase = getRuleBase();
         ruleBase.addPackage( pkg );
-        ruleBase    = SerializationHelper.serializeObject(ruleBase);
+        ruleBase = SerializationHelper.serializeObject( ruleBase );
         final WorkingMemory workingMemory = ruleBase.newStatefulSession();
 
         final List list = new ArrayList();
@@ -861,7 +866,7 @@
 
         RuleBase ruleBase = getRuleBase();
         ruleBase.addPackage( pkg );
-        ruleBase    = SerializationHelper.serializeObject(ruleBase);
+        ruleBase = SerializationHelper.serializeObject( ruleBase );
         final WorkingMemory workingMemory = ruleBase.newStatefulSession();
 
         final List list = new ArrayList();
@@ -894,7 +899,7 @@
 
         RuleBase ruleBase = getRuleBase();
         ruleBase.addPackage( pkg );
-        ruleBase    = SerializationHelper.serializeObject(ruleBase);
+        ruleBase = SerializationHelper.serializeObject( ruleBase );
         final WorkingMemory workingMemory = ruleBase.newStatefulSession();
 
         final List list = new ArrayList();
@@ -952,7 +957,7 @@
 
         RuleBase ruleBase = getRuleBase();
         ruleBase.addPackage( pkg );
-        ruleBase    = SerializationHelper.serializeObject(ruleBase);
+        ruleBase = SerializationHelper.serializeObject( ruleBase );
         final WorkingMemory workingMemory = ruleBase.newStatefulSession();
 
         final List list = new ArrayList();
@@ -1010,24 +1015,31 @@
 
         RuleBase ruleBase = getRuleBase();
         ruleBase.addPackage( pkg );
-        ruleBase    = SerializationHelper.serializeObject(ruleBase);
+        ruleBase = SerializationHelper.serializeObject( ruleBase );
         final WorkingMemory workingMemory = ruleBase.newStatefulSession();
 
         final List list = new ArrayList();
         workingMemory.setGlobal( "results",
                                  list );
-        
-        workingMemory.insert( new Cheese( "stilton", 10 ) );
-        workingMemory.insert( new Cheese( "brie", 10 ) );
-        workingMemory.insert( new Cheese( "brie", 10 ) );
-        workingMemory.insert( new Order( 1, "bob" ) );
-        workingMemory.insert( new Person( "bob", "stilton", 10 ) );
-        workingMemory.insert( new Person( "mark", "stilton" ) );
-        
+
+        workingMemory.insert( new Cheese( "stilton",
+                                          10 ) );
+        workingMemory.insert( new Cheese( "brie",
+                                          10 ) );
+        workingMemory.insert( new Cheese( "brie",
+                                          10 ) );
+        workingMemory.insert( new Order( 1,
+                                         "bob" ) );
+        workingMemory.insert( new Person( "bob",
+                                          "stilton",
+                                          10 ) );
+        workingMemory.insert( new Person( "mark",
+                                          "stilton" ) );
+
         workingMemory.fireAllRules();
-        
+
         //assertEquals( 1, list.size() );
-        
+
     }
 
     public void testCollectResultBetaConstraint() throws Exception {
@@ -1045,22 +1057,22 @@
         wm.insert( new Double( 10 ) );
         wm.insert( new Integer( 2 ) );
 
-//        ruleBase = SerializationHelper.serializeObject( ruleBase );
-//        wm = serializeWorkingMemory( ruleBase,
-//                                     wm );
-//        results = (List) wm.getGlobal( "results" );
+        //        ruleBase = SerializationHelper.serializeObject( ruleBase );
+        //        wm = serializeWorkingMemory( ruleBase,
+        //                                     wm );
+        //        results = (List) wm.getGlobal( "results" );
 
         wm.fireAllRules();
 
         Assert.assertEquals( 0,
                              results.size() );
-        
-        wm.insert( new Double(15) );
+
+        wm.insert( new Double( 15 ) );
         wm.fireAllRules();
-        
+
         Assert.assertEquals( 2,
                              results.size() );
-        
+
         Assert.assertEquals( "collect",
                              results.get( 0 ) );
         Assert.assertEquals( "accumulate",
@@ -1071,12 +1083,12 @@
         KnowledgeBuilder builder = KnowledgeBuilderFactory.newKnowledgeBuilder();
         builder.add( ResourceFactory.newInputStreamResource( getClass().getResourceAsStream( "test_FromWithOr.drl" ) ),
                      ResourceType.DRL );
-        
-        if( builder.hasErrors() ) {
+
+        if ( builder.hasErrors() ) {
             System.out.println( builder.getErrors() );
         }
         assertFalse( builder.hasErrors() );
-        
+
         KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
         kbase.addKnowledgePackages( builder.getKnowledgePackages() );
 
@@ -1084,27 +1096,128 @@
 
         final List<Address> results = new ArrayList<Address>();
         session.setGlobal( "results",
-                                 results );
+                           results );
 
         Address a1 = new Address();
-        a1.setZipCode("12345");
+        a1.setZipCode( "12345" );
         Address a2 = new Address();
-        a2.setZipCode("54321");
+        a2.setZipCode( "54321" );
         Address a3 = new Address();
-        a3.setZipCode("99999");
-        
+        a3.setZipCode( "99999" );
+
         Person p = new Person();
-        p.addAddress(a1);
-        p.addAddress(a2);
-        p.addAddress(a3);
-        
-        session.insert( p);
-        session.fireAllRules();   
-        
-        assertEquals( 2, results.size() );
+        p.addAddress( a1 );
+        p.addAddress( a2 );
+        p.addAddress( a3 );
+
+        session.insert( p );
+        session.fireAllRules();
+
+        assertEquals( 2,
+                      results.size() );
         assertTrue( results.contains( a1 ) );
         assertTrue( results.contains( a2 ) );
 
     }
 
+    public void testForallWithSlidingWindow() throws Exception {
+        final KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
+        kbuilder.add( ResourceFactory.newInputStreamResource( getClass().getResourceAsStream( "test_ForallSlidingWindow.drl" ) ),
+                      ResourceType.DRL );
+        assertFalse( kbuilder.getErrors().toString(),
+                     kbuilder.hasErrors() );
+
+        final KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
+        kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
+
+        final KnowledgeSessionConfiguration conf = KnowledgeBaseFactory.newKnowledgeSessionConfiguration();
+        conf.setOption( ClockTypeOption.get( ClockType.PSEUDO_CLOCK.getId() ) );
+        final StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession( conf,
+                                                                                     null );
+        final SessionPseudoClock clock = ksession.getSessionClock();
+        List<String> results = new ArrayList<String>();
+        ksession.setGlobal( "results",
+                            results );
+
+        // advance time... no events, so forall should fire
+        clock.advanceTime( 60,
+                           TimeUnit.SECONDS );
+        ksession.fireAllRules();
+        assertEquals( 1,
+                      results.size() );
+
+        int seq = 1;
+        // advance time... there are matching events now, but forall still not fire
+        ksession.insert( new StockTick( seq++,
+                                        "RHT",
+                                        10,
+                                        clock.getCurrentTime() ) ); // 60
+        clock.advanceTime( 5,
+                           TimeUnit.SECONDS );
+        ksession.fireAllRules();
+        assertEquals( 1,
+                      results.size() );
+        ksession.insert( new StockTick( seq++,
+                                        "RHT",
+                                        10,
+                                        clock.getCurrentTime() ) ); // 65
+        clock.advanceTime( 5,
+                           TimeUnit.SECONDS );
+        ksession.fireAllRules();
+        assertEquals( 1,
+                      results.size() );
+
+        // advance time... there are non-matching events now, so forall de-activates
+        ksession.insert( new StockTick( seq++,
+                                        "IBM",
+                                        10,
+                                        clock.getCurrentTime() ) ); // 70
+        clock.advanceTime( 10,
+                           TimeUnit.SECONDS );
+        ksession.fireAllRules();
+        assertEquals( 1,
+                      results.size() );
+
+        // advance time... there are non-matching events now, so forall is still deactivated
+        ksession.insert( new StockTick( seq++,
+                                        "RHT",
+                                        10,
+                                        clock.getCurrentTime() ) ); // 80
+        clock.advanceTime( 10,
+                           TimeUnit.SECONDS );
+        ksession.fireAllRules();
+        assertEquals( 1,
+                      results.size() );
+
+        // advance time... non-matching event expires now, so forall should fire
+        ksession.insert( new StockTick( seq++,
+                                        "RHT",
+                                        10,
+                                        clock.getCurrentTime() ) ); // 90
+        clock.advanceTime( 10,
+                           TimeUnit.SECONDS );
+        ksession.fireAllRules();
+        assertEquals( 2,
+                      results.size() );
+
+        // advance time... forall still matches and should not fire
+        ksession.insert( new StockTick( seq++,
+                                        "RHT",
+                                        10,
+                                        clock.getCurrentTime() ) ); // 100
+        clock.advanceTime( 10,
+                           TimeUnit.SECONDS );
+        ksession.fireAllRules();
+        assertEquals( 2,
+                      results.size() );
+
+        // advance time... forall still matches and should not fire
+        clock.advanceTime( 60,
+                           TimeUnit.SECONDS );
+        ksession.fireAllRules();
+        assertEquals( 2,
+                      results.size() );
+
+    }
+
 }

Added: labs/jbossrules/trunk/drools-compiler/src/test/resources/org/drools/integrationtests/test_ForallSlidingWindow.drl
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/resources/org/drools/integrationtests/test_ForallSlidingWindow.drl	                        (rev 0)
+++ labs/jbossrules/trunk/drools-compiler/src/test/resources/org/drools/integrationtests/test_ForallSlidingWindow.drl	2009-10-15 23:14:17 UTC (rev 29630)
@@ -0,0 +1,14 @@
+package org.drools;
+
+global java.util.List results;
+
+declare StockTick
+    @role( event )
+end
+
+rule "test nested CEs"	
+	when
+	    forall( StockTick( company == "RHT" ) over window:time( 30s ) )
+	then 
+		results.add("OK");		
+end
\ No newline at end of file

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/marshalling/impl/InputMarshaller.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/marshalling/impl/InputMarshaller.java	2009-10-15 20:47:19 UTC (rev 29629)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/marshalling/impl/InputMarshaller.java	2009-10-15 23:14:17 UTC (rev 29630)
@@ -473,7 +473,8 @@
                 }
                 break;
             }
-            case NodeTypeEnums.NotNode : {
+            case NodeTypeEnums.NotNode : 
+            case NodeTypeEnums.ForallNotNode : {
                 BetaMemory memory = (BetaMemory) context.wm.getNodeMemory( (BetaNode) sink );
                 int type = stream.readShort();
                 if ( type == PersisterEnums.LEFT_TUPLE_NOT_BLOCKED ) {

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/marshalling/impl/OutputMarshaller.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/marshalling/impl/OutputMarshaller.java	2009-10-15 20:47:19 UTC (rev 29629)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/marshalling/impl/OutputMarshaller.java	2009-10-15 23:14:17 UTC (rev 29630)
@@ -449,7 +449,8 @@
                 stream.writeShort( PersisterEnums.END );
                 break;
             }
-            case NodeTypeEnums.NotNode : {
+            case NodeTypeEnums.NotNode : 
+            case NodeTypeEnums.ForallNotNode : {
                 if ( leftTuple.getBlocker() == null ) {
                     // is not blocked so has children
                     stream.writeShort( PersisterEnums.LEFT_TUPLE_NOT_BLOCKED );

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ForallNotNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ForallNotNode.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ForallNotNode.java	2009-10-15 23:14:17 UTC (rev 29630)
@@ -0,0 +1,130 @@
+package org.drools.reteoo;
+
+/*
+ * Copyright 20059 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.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+import org.drools.common.BetaConstraints;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.builder.BuildContext;
+import org.drools.rule.Behavior;
+import org.drools.spi.ObjectType;
+import org.drools.spi.PropagationContext;
+
+/**
+ * A 'forall' conditional element is translated into a specific set of notes in the network. As 
+ * an example, the following construction:
+ * 
+ * forall( Bus( color == RED ) )
+ * 
+ * Is translated into:
+ * 
+ * not*( $bus : Bus( ) and not ( Bus( this == $bus, color == RED ) ) )
+ * 
+ * This class implements the modified 'not' node that corresponds to the 'not*' CE above.
+ * It behaves like a not node in all aspects but for the right activations that never trigger
+ * propagations.  
+ * 
+ * @author <a href="mailto:tirelli at post.com">Edson Tirelli</a>
+ */
+public class ForallNotNode extends NotNode {
+    private static final long serialVersionUID = 510L;
+
+    private ObjectType        baseObjectType   = null;
+
+    // ------------------------------------------------------------
+    // Instance methods
+    // ------------------------------------------------------------
+    public ForallNotNode() {
+    }
+
+    /**
+     * Construct.
+     *
+     * @param leftInput
+     *            The left input <code>TupleSource</code>.
+     * @param rightInput
+     *            The right input <code>TupleSource</code>.
+     * @param objectType 
+     */
+    public ForallNotNode(final int id,
+                         final LeftTupleSource leftInput,
+                         final ObjectSource rightInput,
+                         final BetaConstraints joinNodeBinder,
+                         final Behavior[] behaviors,
+                         final BuildContext context,
+                         ObjectType objectType) {
+        super( id,
+               leftInput,
+               rightInput,
+               joinNodeBinder,
+               behaviors,
+               context );
+        this.baseObjectType = objectType;
+    }
+
+    public void readExternal(ObjectInput in) throws IOException,
+                                            ClassNotFoundException {
+        super.readExternal( in );
+        baseObjectType = (ObjectType) in.readObject();
+    }
+
+    public void writeExternal(ObjectOutput out) throws IOException {
+        super.writeExternal( out );
+        out.writeObject( baseObjectType );
+    }
+
+    @Override
+    protected void propagateRetractLeftTuple(PropagationContext context,
+                                             InternalWorkingMemory workingMemory,
+                                             LeftTuple leftTuple) {
+        if ( !this.baseObjectType.isAssignableFrom( workingMemory.getObjectTypeConfigurationRegistry().getObjectTypeConf( context.getEntryPoint(),
+                                                                                                                          ((InternalFactHandle) context.getFactHandle()).getObject() ).getConcreteObjectTypeNode().getObjectType() ) ) {
+            this.sink.propagateRetractLeftTuple( leftTuple,
+                                                 context,
+                                                 workingMemory );
+        }
+    }
+
+    @Override
+    protected void propagateAssertLeftTuple(PropagationContext context,
+                                            InternalWorkingMemory workingMemory,
+                                            LeftTuple leftTuple) {
+        if ( !this.baseObjectType.isAssignableFrom( workingMemory.getObjectTypeConfigurationRegistry().getObjectTypeConf( context.getEntryPoint(),
+                                                                                                                          ((InternalFactHandle) context.getFactHandle()).getObject() ).getConcreteObjectTypeNode().getObjectType() ) ) {
+            this.sink.propagateAssertLeftTuple( leftTuple,
+                                                context,
+                                                workingMemory,
+                                                this.tupleMemoryEnabled );
+        }
+    }
+
+    public short getType() {
+        return NodeTypeEnums.ForallNotNode;
+    }
+
+    public ObjectType getBaseObjectType() {
+        return baseObjectType;
+    }
+
+    public void setBaseObjectType(ObjectType baseObjectType) {
+        this.baseObjectType = baseObjectType;
+    }
+}

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/NodeTypeEnums.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/NodeTypeEnums.java	2009-10-15 20:47:19 UTC (rev 29629)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/NodeTypeEnums.java	2009-10-15 23:14:17 UTC (rev 29630)
@@ -11,4 +11,5 @@
     public static final short RightInputAdaterNode = 7;
     public static final short QueryTerminalNode    = 8;
     public static final short RuleTerminalNode     = 9;
+    public static final short ForallNotNode        = 10;
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/NotNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/NotNode.java	2009-10-15 20:47:19 UTC (rev 29629)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/NotNode.java	2009-10-15 23:14:17 UTC (rev 29630)
@@ -177,9 +177,10 @@
                 // this is now blocked so remove from memory
                 memory.getLeftTupleMemory().remove( leftTuple );
 
-                this.sink.propagateRetractLeftTuple( leftTuple,
-                                                     context,
-                                                     workingMemory );
+                // subclasses like ForallNotNode might override this propagation
+                propagateRetractLeftTuple( context,
+                                           workingMemory,
+                                           leftTuple );
             }
 
             leftTuple = temp;
@@ -189,6 +190,22 @@
     }
 
     /**
+     * This is a hook method so that subclasses (like ForallNotNode) can 
+     * override the default behaviour.
+     * 
+     * @param context
+     * @param workingMemory
+     * @param leftTuple
+     */
+    protected void propagateRetractLeftTuple(final PropagationContext context,
+                                             final InternalWorkingMemory workingMemory,
+                                             LeftTuple leftTuple) {
+        this.sink.propagateRetractLeftTuple( leftTuple,
+                                             context,
+                                             workingMemory );
+    }
+
+    /**
      * Retract the <code>FactHandleImpl</code>. If the handle has any
      * <code>ReteTuple</code> matches then those matches copied are propagated
      * as new joins.
@@ -243,10 +260,10 @@
                 // was previous blocked and not in memory, so add
                 memory.getLeftTupleMemory().add( leftTuple );
 
-                this.sink.propagateAssertLeftTuple( leftTuple,
-                                                    context,
-                                                    workingMemory,
-                                                    this.tupleMemoryEnabled );
+                // subclasses like ForallNotNode might override this propagation
+                propagateAssertLeftTuple( context,
+                                          workingMemory,
+                                          leftTuple );
             }
 
             leftTuple = temp;
@@ -255,6 +272,23 @@
     }
 
     /**
+     * This is a hook method so that subclasses (like ForallNotNode) can 
+     * override the default behaviour.
+     * 
+     * @param context
+     * @param workingMemory
+     * @param leftTuple
+     */
+    protected void propagateAssertLeftTuple(final PropagationContext context,
+                                            final InternalWorkingMemory workingMemory,
+                                            LeftTuple leftTuple) {
+        this.sink.propagateAssertLeftTuple( leftTuple,
+                                            context,
+                                            workingMemory,
+                                            this.tupleMemoryEnabled );
+    }
+
+    /**
      * Retract the
      * <code>ReteTuple<code>, any resulting proppagated joins are also retracted.
      *
@@ -309,6 +343,6 @@
             source = source.source;
         }
 
-        return "[NotNode - " + ((ObjectTypeNode) source).getObjectType() + "]";
+        return "[" + getClass().getSimpleName() + "(" + this.getId() + ") - " + ((ObjectTypeNode) source).getObjectType() + "]";
     }
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/ForallBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/ForallBuilder.java	2009-10-15 20:47:19 UTC (rev 29629)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/ForallBuilder.java	2009-10-15 23:14:17 UTC (rev 29630)
@@ -16,8 +16,17 @@
 
 package org.drools.reteoo.builder;
 
+import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.List;
 
+import org.drools.common.BetaConstraints;
+import org.drools.common.TupleStartEqualsConstraint;
+import org.drools.reteoo.LeftTupleSource;
+import org.drools.reteoo.NotNode;
+import org.drools.reteoo.ObjectSource;
+import org.drools.reteoo.RightInputAdapterNode;
+import org.drools.rule.Behavior;
 import org.drools.rule.Forall;
 import org.drools.rule.GroupElement;
 import org.drools.rule.GroupElementFactory;
@@ -48,7 +57,8 @@
         final GroupElement and = GroupElementFactory.newAndInstance();
         and.addChild( forall.getBasePattern() );
 
-        final GroupElement not2 = GroupElementFactory.newNotInstance();
+        final GroupElement not2 = GroupElementFactory.newForallNotInstance();
+        not2.setForallBaseObjectType( forall.getBasePattern().getObjectType() );
         if ( forall.getRemainingPatterns().size() == 1 ) {
             not2.addChild( (Pattern) forall.getRemainingPatterns().get( 0 ) );
             and.addChild( not2 );
@@ -71,6 +81,7 @@
         builder.build( context,
                        utils,
                        not );
+
     }
 
     /**

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/GroupElementBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/GroupElementBuilder.java	2009-10-15 20:47:19 UTC (rev 29629)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/GroupElementBuilder.java	2009-10-15 23:14:17 UTC (rev 29630)
@@ -27,6 +27,7 @@
 import org.drools.common.BetaConstraints;
 import org.drools.common.TupleStartEqualsConstraint;
 import org.drools.reteoo.ExistsNode;
+import org.drools.reteoo.ForallNotNode;
 import org.drools.reteoo.JoinNode;
 import org.drools.reteoo.LeftInputAdapterNode;
 import org.drools.reteoo.LeftTupleSource;
@@ -36,6 +37,7 @@
 import org.drools.rule.Behavior;
 import org.drools.rule.GroupElement;
 import org.drools.rule.RuleConditionElement;
+import org.drools.rule.GroupElement.Type;
 
 /**
  * @author etirelli
@@ -45,7 +47,7 @@
     implements
     ReteooComponentBuilder {
 
-    private final Map geBuilders = new HashMap();
+    private final Map<Type, ReteooComponentBuilder> geBuilders = new HashMap<Type, ReteooComponentBuilder>();
 
     public GroupElementBuilder() {
         this.geBuilders.put( GroupElement.AND,
@@ -54,6 +56,8 @@
                              new OrBuilder() );
         this.geBuilders.put( GroupElement.NOT,
                              new NotBuilder() );
+        this.geBuilders.put( GroupElement.FORALL_NOT,
+                             new NotBuilder() );
         this.geBuilders.put( GroupElement.EXISTS,
                              new ExistsBuilder() );
     }
@@ -66,7 +70,7 @@
                       final RuleConditionElement rce) {
         final GroupElement ge = (GroupElement) rce;
 
-        final ReteooComponentBuilder builder = (ReteooComponentBuilder) this.geBuilders.get( ge.getType() );
+        final ReteooComponentBuilder builder = this.geBuilders.get( ge.getType() );
         
         context.push( ge );
 
@@ -84,7 +88,7 @@
                                           final RuleConditionElement rce) {
         final GroupElement ge = (GroupElement) rce;
 
-        final ReteooComponentBuilder builder = (ReteooComponentBuilder) this.geBuilders.get( ge.getType() );
+        final ReteooComponentBuilder builder = this.geBuilders.get( ge.getType() );
 
         return builder.requiresLeftActivation( utils,
                                                rce );
@@ -243,7 +247,7 @@
 
                 // create a tuple start equals constraint and set it in the context
                 final TupleStartEqualsConstraint constraint = TupleStartEqualsConstraint.getInstance();
-                final List predicates = new ArrayList();
+                final List<TupleStartEqualsConstraint> predicates = new ArrayList<TupleStartEqualsConstraint>();
                 predicates.add( constraint );
                 context.setBetaconstraints( predicates );
 
@@ -257,13 +261,25 @@
             // then attach the NOT node. It will work both as a simple not node
             // or as subnetwork join node as the context was set appropriatelly
             // in each case
+            NotNode node = null;
+            if( GroupElement.FORALL_NOT.equals( not.getType() ) ) {
+                node = new ForallNotNode( context.getNextId(),
+                             context.getTupleSource(),
+                             context.getObjectSource(),
+                             betaConstraints,
+                             behaviors,
+                             context,
+                             not.getForallBaseObjectType() );
+            } else {
+                node = new NotNode( context.getNextId(),
+                                    context.getTupleSource(),
+                                    context.getObjectSource(),
+                                    betaConstraints,
+                                    behaviors,
+                                    context );
+            }
             context.setTupleSource( (LeftTupleSource) utils.attachNode( context,
-                                                                        new NotNode( context.getNextId(),
-                                                                                     context.getTupleSource(),
-                                                                                     context.getObjectSource(),
-                                                                                     betaConstraints,
-                                                                                     behaviors,
-                                                                                     context ) ) );
+                                                                        node ) );
             context.setBetaconstraints( null );
             context.setObjectSource( null );
 
@@ -323,7 +339,7 @@
 
                 // create a tuple start equals constraint and set it in the context
                 final TupleStartEqualsConstraint constraint = TupleStartEqualsConstraint.getInstance();
-                final List predicates = new ArrayList();
+                final List<TupleStartEqualsConstraint> predicates = new ArrayList<TupleStartEqualsConstraint>();
                 predicates.add( constraint );
                 context.setBetaconstraints( predicates );
 

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/GroupElement.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/GroupElement.java	2009-10-15 20:47:19 UTC (rev 29629)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/GroupElement.java	2009-10-15 23:14:17 UTC (rev 29630)
@@ -28,20 +28,23 @@
 import java.util.Map;
 
 import org.drools.RuntimeDroolsException;
+import org.drools.spi.ObjectType;
 
 public class GroupElement extends ConditionalElement
     implements
     Externalizable {
 
-    private static final long serialVersionUID = 400L;
+    private static final long serialVersionUID     = 510L;
 
-    public static final Type AND = Type.AND;
-    public static final Type OR = Type.OR;
-    public static final Type NOT = Type.NOT;
-    public static final Type EXISTS = Type.EXISTS;
+    public static final Type  AND                  = Type.AND;
+    public static final Type  OR                   = Type.OR;
+    public static final Type  NOT                  = Type.NOT;
+    public static final Type  EXISTS               = Type.EXISTS;
+    public static final Type  FORALL_NOT           = Type.FORALL_NOT;
 
-    private Type              type             = null;
-    private List              children         = new ArrayList();
+    private Type              type                 = null;
+    private List              children             = new ArrayList();
+    private ObjectType        forallBaseObjectType = null;
 
     public GroupElement() {
         this( Type.AND );
@@ -113,6 +116,14 @@
         return (Declaration) this.type.getInnerDeclarations( this.children ).get( identifier );
     }
 
+    public void setForallBaseObjectType(ObjectType objectType) {
+        this.forallBaseObjectType = objectType;
+    }
+
+    public ObjectType getForallBaseObjectType() {
+        return this.forallBaseObjectType;
+    }
+
     /**
      * Optimize the group element subtree by removing redundancies
      * like an AND inside another AND, OR inside OR, single branches
@@ -301,7 +312,7 @@
     }
 
     public boolean isNot() {
-        return NOT.equals( this.type );
+        return NOT.equals( this.type ) || FORALL_NOT.equals( this.type );
     }
 
     public boolean isExists() {
@@ -325,10 +336,12 @@
      */
     public static enum Type {
 
-        AND(false), 
-        OR(false), 
-        NOT(true), 
-        EXISTS(true);
+        AND(
+                false), OR(
+                false), NOT(
+                true), EXISTS(
+                true), FORALL_NOT(
+                true);
 
         private final boolean scopeDelimiter;
 

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/GroupElementFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/GroupElementFactory.java	2009-10-15 20:47:19 UTC (rev 29629)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/GroupElementFactory.java	2009-10-15 23:14:17 UTC (rev 29630)
@@ -38,6 +38,10 @@
         return new GroupElement( GroupElement.NOT );
     }
 
+    public static GroupElement newForallNotInstance() {
+        return new GroupElement( GroupElement.FORALL_NOT );
+    }
+
     public static GroupElement newExistsInstance() {
         return new GroupElement( GroupElement.EXISTS );
     }



More information about the jboss-svn-commits mailing list