[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