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

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Thu Aug 6 16:37:19 EDT 2009


Author: tirelli
Date: 2009-08-06 16:37:18 -0400 (Thu, 06 Aug 2009)
New Revision: 28861

Added:
   labs/jbossrules/trunk/drools-compiler/src/test/resources/org/drools/integrationtests/test_AddRemoveListeners.drl
Modified:
   labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/MiscTest.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/impl/StatefulKnowledgeSessionImpl.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/impl/StatelessKnowledgeSessionImpl.java
Log:
JBRULES-2229: fixing event management from inside rule consequences.

Modified: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/MiscTest.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/MiscTest.java	2009-08-06 15:41:49 UTC (rev 28860)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/MiscTest.java	2009-08-06 20:37:18 UTC (rev 28861)
@@ -26,9 +26,7 @@
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.util.ArrayList;
-import java.util.Calendar;
 import java.util.Collection;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -154,14 +152,13 @@
 import org.drools.util.ObjectHashSet;
 import org.drools.util.ObjectHashMap.ObjectEntry;
 import org.drools.xml.XmlDumper;
-import org.mvel2.MVEL;
-import org.mvel2.ParserContext;
-import org.mvel2.compiler.CompiledExpression;
-import org.mvel2.compiler.ExpressionCompiler;
-import org.mvel2.optimizers.OptimizerFactory;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
 
 /** Run all the tests with the ReteOO engine implementation */
 public class MiscTest extends TestCase {
+    
+    private final Mockery context = new Mockery();
 
     protected RuleBase getRuleBase() throws Exception {
 
@@ -6935,6 +6932,40 @@
 
     }
 
+    public void testAddRemoveListeners() throws Exception {
+        final KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
+        kbuilder.add( ResourceFactory.newInputStreamResource( getClass().getResourceAsStream( "test_AddRemoveListeners.drl" ) ),
+                      ResourceType.DRL );
+        assertFalse( kbuilder.getErrors().toString(),
+                     kbuilder.hasErrors() );
 
+        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
+        kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
+        
+        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
+        
+        // creating listener as a jmock proxy
+        final org.drools.event.rule.WorkingMemoryEventListener wmeListener = context.mock(org.drools.event.rule.WorkingMemoryEventListener.class);
+        
+        context.checking(new Expectations() {{
+            exactly(2).of(wmeListener).objectInserted( with(any(org.drools.event.rule.ObjectInsertedEvent.class)) );
+        }});
+        
+        ksession.addEventListener( wmeListener );
+        
+        // listener will be notified of both facts insertion
+        ksession.insert( new Cheese("stilton") );
+        ksession.insert( wmeListener );
+        
+        // firing rules will remove listener
+        ksession.fireAllRules();
+        
+        // inserting another object into the working memory, listener should NOT be notified,
+        // since it is no longer listening.
+        ksession.insert( new Cheese("brie") );
+
+        context.assertIsSatisfied();
+    }
+
 }
 

Added: labs/jbossrules/trunk/drools-compiler/src/test/resources/org/drools/integrationtests/test_AddRemoveListeners.drl
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/resources/org/drools/integrationtests/test_AddRemoveListeners.drl	                        (rev 0)
+++ labs/jbossrules/trunk/drools-compiler/src/test/resources/org/drools/integrationtests/test_AddRemoveListeners.drl	2009-08-06 20:37:18 UTC (rev 28861)
@@ -0,0 +1,11 @@
+package org.drools
+
+import org.drools.event.rule.WorkingMemoryEventListener
+
+rule "remove listener"
+when
+	listener : WorkingMemoryEventListener();
+then
+	drools.getKnowledgeRuntime().removeEventListener(listener);
+	retract(listener);
+end

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/impl/StatefulKnowledgeSessionImpl.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/impl/StatefulKnowledgeSessionImpl.java	2009-08-06 15:41:49 UTC (rev 28860)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/impl/StatefulKnowledgeSessionImpl.java	2009-08-06 20:37:18 UTC (rev 28861)
@@ -82,10 +82,6 @@
     public ReteooWorkingMemory                                                session;
     public KnowledgeBaseImpl                                                  kbase;
 
-    public Map<WorkingMemoryEventListener, WorkingMemoryEventListenerWrapper> mappedWorkingMemoryListeners;
-    public Map<AgendaEventListener, AgendaEventListenerWrapper>               mappedAgendaListeners;
-    public Map<ProcessEventListener, ProcessEventListenerWrapper>             mappedProcessListeners;
-
     public StatefulKnowledgeSessionImpl(ReteooWorkingMemory session) {
         this( session,
               new KnowledgeBaseImpl( session.getRuleBase() ) );
@@ -96,25 +92,8 @@
         this.session = session;
         this.session.setKnowledgeRuntime( this );
         this.kbase = ( KnowledgeBaseImpl ) kbase;
-        this.mappedWorkingMemoryListeners = new IdentityHashMap<WorkingMemoryEventListener, WorkingMemoryEventListenerWrapper>();
-        this.mappedAgendaListeners = new IdentityHashMap<AgendaEventListener, AgendaEventListenerWrapper>();
-        this.mappedProcessListeners = new IdentityHashMap<ProcessEventListener, ProcessEventListenerWrapper>();
     }
     
-    public StatefulKnowledgeSessionImpl(ReteooWorkingMemory session,
-                                        KnowledgeBase kbase,
-                                        Map<WorkingMemoryEventListener, WorkingMemoryEventListenerWrapper> mappedWorkingMemoryListeners,
-                                        Map<AgendaEventListener, AgendaEventListenerWrapper>               mappedAgendaListeners,
-                                        Map<ProcessEventListener, ProcessEventListenerWrapper>             mappedProcessListeners) {                                        
-                                        
-        this.session = session;
-        this.session.setKnowledgeRuntime( this );
-        this.kbase = ( KnowledgeBaseImpl ) kbase;
-        this.mappedWorkingMemoryListeners = mappedWorkingMemoryListeners;
-        this.mappedAgendaListeners = mappedAgendaListeners;
-        this.mappedProcessListeners = mappedProcessListeners;
-    }    
-    
     public int getId() {
         return this.session.getId();
     }
@@ -129,49 +108,82 @@
 
     public void addEventListener(WorkingMemoryEventListener listener) {
         WorkingMemoryEventListenerWrapper wrapper = new WorkingMemoryEventListenerWrapper( listener );
-        this.mappedWorkingMemoryListeners.put( listener,
-                                               wrapper );
         this.session.addEventListener( wrapper );
     }
 
     public void removeEventListener(WorkingMemoryEventListener listener) {
-        WorkingMemoryEventListenerWrapper wrapper = this.mappedWorkingMemoryListeners.remove( listener );
+        WorkingMemoryEventListenerWrapper wrapper = null;
+        if( listener != null && ! ( listener instanceof WorkingMemoryEventListenerWrapper ) ) {
+            wrapper = new WorkingMemoryEventListenerWrapper( listener );
+        } else {
+            wrapper = (WorkingMemoryEventListenerWrapper) listener;
+        }
         this.session.removeEventListener( wrapper );
     }
 
     public Collection<WorkingMemoryEventListener> getWorkingMemoryEventListeners() {
-        return Collections.unmodifiableCollection( this.mappedWorkingMemoryListeners.keySet() );
+        List<WorkingMemoryEventListener> listeners = new ArrayList<WorkingMemoryEventListener>();
+        for( WorkingMemoryEventListener listener : ((List<WorkingMemoryEventListener>)this.session.getWorkingMemoryEventListeners()) ) {
+            if( listener instanceof WorkingMemoryEventListenerWrapper ) {
+                listeners.add( ((WorkingMemoryEventListenerWrapper)listener).unWrap() );
+            } else {
+                listeners.add( listener );
+            }
+        }
+        return Collections.unmodifiableCollection( listeners );
     }
 
     public void addEventListener(AgendaEventListener listener) {
         AgendaEventListenerWrapper wrapper = new AgendaEventListenerWrapper( listener );
-        this.mappedAgendaListeners.put( listener,
-                                        wrapper );
         this.session.addEventListener( wrapper );
     }
 
     public Collection<AgendaEventListener> getAgendaEventListeners() {
-        return Collections.unmodifiableCollection( this.mappedAgendaListeners.keySet() );
+        List<AgendaEventListener> listeners = new ArrayList<AgendaEventListener>();
+        for( AgendaEventListener listener : ((List<AgendaEventListener>)this.session.getAgendaEventListeners()) ) {
+            if( listener instanceof AgendaEventListenerWrapper ) {
+                listeners.add( ((AgendaEventListenerWrapper)listener).unWrap() );
+            } else {
+                listeners.add( listener );
+            }
+        }
+        return Collections.unmodifiableCollection( listeners );
     }
 
     public void removeEventListener(AgendaEventListener listener) {
-        AgendaEventListenerWrapper wrapper = this.mappedAgendaListeners.remove( listener );
+        AgendaEventListenerWrapper wrapper = null;
+        if( listener != null && ! ( listener instanceof AgendaEventListenerWrapper ) ) {
+            wrapper = new AgendaEventListenerWrapper( listener );
+        } else {
+            wrapper = (AgendaEventListenerWrapper) listener;
+        }
         this.session.removeEventListener( wrapper );
     }
 
     public void addEventListener(ProcessEventListener listener) {
         ProcessEventListenerWrapper wrapper = new ProcessEventListenerWrapper( listener );
-        this.mappedProcessListeners.put( listener,
-                                         wrapper );
         this.session.addEventListener( wrapper );
     }
 
     public Collection<ProcessEventListener> getProcessEventListeners() {
-        return Collections.unmodifiableCollection( this.mappedProcessListeners.keySet() );
+        List<ProcessEventListener> listeners = new ArrayList<ProcessEventListener>();
+        for( ProcessEventListener listener : ((List<ProcessEventListener>)this.session.getRuleFlowEventListeners()) ) {
+            if( listener instanceof ProcessEventListenerWrapper ) {
+                listeners.add( ((ProcessEventListenerWrapper)listener).unWrap() );
+            } else {
+                listeners.add( listener );
+            }
+        }
+        return Collections.unmodifiableCollection( listeners );
     }
 
     public void removeEventListener(ProcessEventListener listener) {
-        ProcessEventListenerWrapper wrapper = this.mappedProcessListeners.get( listener );
+        ProcessEventListenerWrapper wrapper = null;
+        if( listener != null && ! ( listener instanceof ProcessEventListenerWrapper ) ) {
+            wrapper = new ProcessEventListenerWrapper( listener );
+        } else {
+            wrapper = (ProcessEventListenerWrapper) listener;
+        }
         this.session.removeEventListener( wrapper );
     }
 
@@ -490,7 +502,7 @@
     public static class WorkingMemoryEventListenerWrapper
         implements
         org.drools.event.WorkingMemoryEventListener {
-        private WorkingMemoryEventListener listener;
+        private final WorkingMemoryEventListener listener;
 
         public WorkingMemoryEventListenerWrapper(WorkingMemoryEventListener listener) {
             this.listener = listener;
@@ -511,12 +523,42 @@
         public WorkingMemoryEventListener unWrap() {
             return listener;
         }
+        
+        /**
+         * Since this is a class adapter for API compatibility, the 
+         * equals() and hashCode() methods simply delegate the calls 
+         * to the wrapped instance. That is implemented this way
+         * in order for them to be able to match corresponding instances
+         * in internal hash-based maps and sets.  
+         */
+        @Override
+        public int hashCode() {
+            return listener!=null ? listener.hashCode() : 0;
+        }
+        
+        /**
+         * Since this is a class adapter for API compatibility, the 
+         * equals() and hashCode() methods simply delegate the calls 
+         * to the wrapped instance. That is implemented this way
+         * in order for them to be able to match corresponding instances
+         * in internal hash-based maps and sets.  
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if( listener == null || obj == null ) {
+                return obj == listener;
+            }
+            if( obj instanceof WorkingMemoryEventListenerWrapper ) {
+                return this.listener.equals( ((WorkingMemoryEventListenerWrapper)obj).unWrap() );
+            }
+            return this.listener.equals( obj );
+        }
     }
 
     public static class AgendaEventListenerWrapper
         implements
         org.drools.event.AgendaEventListener {
-        private AgendaEventListener listener;
+        private final AgendaEventListener listener;
 
         public AgendaEventListenerWrapper(AgendaEventListener listener) {
             this.listener = listener;
@@ -565,12 +607,41 @@
             return listener;
         }
 
+        /**
+         * Since this is a class adapter for API compatibility, the 
+         * equals() and hashCode() methods simply delegate the calls 
+         * to the wrapped instance. That is implemented this way
+         * in order for them to be able to match corresponding instances
+         * in internal hash-based maps and sets.  
+         */
+        @Override
+        public int hashCode() {
+            return listener!=null ? listener.hashCode() : 0;
+        }
+        
+        /**
+         * Since this is a class adapter for API compatibility, the 
+         * equals() and hashCode() methods simply delegate the calls 
+         * to the wrapped instance. That is implemented this way
+         * in order for them to be able to match corresponding instances
+         * in internal hash-based maps and sets.  
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if( listener == null || obj == null ) {
+                return obj == listener;
+            }
+            if( obj instanceof AgendaEventListenerWrapper ) {
+                return this.listener.equals( ((AgendaEventListenerWrapper)obj).unWrap() );
+            }
+            return this.listener.equals( obj );
+        }
     }
 
     public static class ProcessEventListenerWrapper
         implements
         org.drools.event.RuleFlowEventListener {
-        private ProcessEventListener listener;
+        private final ProcessEventListener listener;
 
         public ProcessEventListenerWrapper(ProcessEventListener listener) {
             this.listener = listener;
@@ -643,6 +714,36 @@
         public ProcessEventListener unWrap() {
             return listener;
         }
+        
+        /**
+         * Since this is a class adapter for API compatibility, the 
+         * equals() and hashCode() methods simply delegate the calls 
+         * to the wrapped instance. That is implemented this way
+         * in order for them to be able to match corresponding instances
+         * in internal hash-based maps and sets.  
+         */
+        @Override
+        public int hashCode() {
+            return listener!=null ? listener.hashCode() : 0;
+        }
+        
+        /**
+         * Since this is a class adapter for API compatibility, the 
+         * equals() and hashCode() methods simply delegate the calls 
+         * to the wrapped instance. That is implemented this way
+         * in order for them to be able to match corresponding instances
+         * in internal hash-based maps and sets.  
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if( listener == null || obj == null ) {
+                return obj == listener;
+            }
+            if( obj instanceof ProcessEventListenerWrapper ) {
+                return this.listener.equals( ((ProcessEventListenerWrapper)obj).unWrap() );
+            }
+            return this.listener.equals( obj );
+        }
 
     }
 

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/impl/StatelessKnowledgeSessionImpl.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/impl/StatelessKnowledgeSessionImpl.java	2009-08-06 15:41:49 UTC (rev 28860)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/impl/StatelessKnowledgeSessionImpl.java	2009-08-06 20:37:18 UTC (rev 28861)
@@ -104,11 +104,10 @@
                                                               (SessionConfiguration) this.conf,
                                                               this.environment );
 
+            // we don't pass the mapped listener wrappers to the session constructor anymore,
+            // because they would be ignored anyway, since the wm already contains those listeners
             StatefulKnowledgeSessionImpl ksession = new StatefulKnowledgeSessionImpl( wm,
-                                                                                      new KnowledgeBaseImpl( this.ruleBase ),
-                                                                                      mappedWorkingMemoryListeners,
-                                                                                      mappedAgendaListeners,
-                                                                                      mappedProcessListeners );
+                                                                                      new KnowledgeBaseImpl( this.ruleBase ) );
 
             ((Globals) wm.getGlobalResolver()).setDelegate( this.sessionGlobals );
             wm.setKnowledgeRuntime( ksession );



More information about the jboss-svn-commits mailing list