[jboss-svn-commits] JBL Code SVN: r34206 - in labs/jbossrules/branches/trunk_20100722_esteban_diega: drools-compiler/src/test/java/org/drools/integrationtests and 8 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Mon Jul 26 16:05:44 EDT 2010


Author: eaa
Date: 2010-07-26 16:05:42 -0400 (Mon, 26 Jul 2010)
New Revision: 34206

Added:
   labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-api/src/main/java/org/drools/event/process/ProcessNodeExceptionOccurredEvent.java
   labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/RuleFlowNodeExceptionOccurredEvent.java
   labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/process/impl/ProcessNodeExceptionOccurredEventImpl.java
   labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/workflow/instance/impl/ManagedRuntimeException.java
Modified:
   labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-api/src/main/java/org/drools/event/process/DefaultProcessEventListener.java
   labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-api/src/main/java/org/drools/event/process/ProcessEventListener.java
   labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-compiler/src/test/java/org/drools/integrationtests/ProcessEventListenerTest.java
   labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/audit/WorkingMemoryLogger.java
   labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/DebugRuleFlowEventListener.java
   labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/DefaultRuleFlowEventListener.java
   labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/RuleFlowEventListener.java
   labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/RuleFlowEventListenerExtension.java
   labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/RuleFlowEventSupport.java
   labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/impl/StatefulKnowledgeSessionImpl.java
   labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/management/KnowledgeSessionMonitoring.java
   labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/workflow/instance/impl/NodeInstanceImpl.java
   labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/test/java/org/drools/event/process/ProcessEventSupportTest.java
   labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-persistence-jpa/src/test/java/org/drools/persistence/session/PersistentStatefulSessionTest.java
Log:
JBRULES-2595: Extend ProcessEventListener to add support for low-level exceptions occurred in a process execution
	- Created a new ProcessNodeExceptionOccurredEvent event. This event is fired when a RuntimeException is thrown inside internalTrigger() method of a NodeInstanceImpl subclass.
	- ProcessEventListener adds support for this new event.
	

Modified: labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-api/src/main/java/org/drools/event/process/DefaultProcessEventListener.java
===================================================================
--- labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-api/src/main/java/org/drools/event/process/DefaultProcessEventListener.java	2010-07-26 18:14:07 UTC (rev 34205)
+++ labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-api/src/main/java/org/drools/event/process/DefaultProcessEventListener.java	2010-07-26 20:05:42 UTC (rev 34206)
@@ -36,4 +36,9 @@
         // intentionally left blank
     }
 
+    public void onNodeException(ProcessNodeExceptionOccurredEvent event) {
+        // intentionally left blank
+    }
+
+
 }
\ No newline at end of file

Modified: labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-api/src/main/java/org/drools/event/process/ProcessEventListener.java
===================================================================
--- labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-api/src/main/java/org/drools/event/process/ProcessEventListener.java	2010-07-26 18:14:07 UTC (rev 34205)
+++ labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-api/src/main/java/org/drools/event/process/ProcessEventListener.java	2010-07-26 20:05:42 UTC (rev 34206)
@@ -38,4 +38,6 @@
 
     void afterNodeLeft(ProcessNodeLeftEvent event);
 
+    void onNodeException(ProcessNodeExceptionOccurredEvent event);
+
 }
\ No newline at end of file

Added: labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-api/src/main/java/org/drools/event/process/ProcessNodeExceptionOccurredEvent.java
===================================================================
--- labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-api/src/main/java/org/drools/event/process/ProcessNodeExceptionOccurredEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-api/src/main/java/org/drools/event/process/ProcessNodeExceptionOccurredEvent.java	2010-07-26 20:05:42 UTC (rev 34206)
@@ -0,0 +1,25 @@
+package org.drools.event.process;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public interface ProcessNodeExceptionOccurredEvent
+    extends
+    ProcessNodeEvent {
+
+    Throwable getError();
+
+}

Modified: labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-compiler/src/test/java/org/drools/integrationtests/ProcessEventListenerTest.java
===================================================================
--- labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-compiler/src/test/java/org/drools/integrationtests/ProcessEventListenerTest.java	2010-07-26 18:14:07 UTC (rev 34205)
+++ labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-compiler/src/test/java/org/drools/integrationtests/ProcessEventListenerTest.java	2010-07-26 20:05:42 UTC (rev 34206)
@@ -29,6 +29,7 @@
 import org.drools.event.ProcessEvent;
 import org.drools.event.RuleFlowCompletedEvent;
 import org.drools.event.RuleFlowEventListenerExtension;
+import org.drools.event.RuleFlowNodeExceptionOccurredEvent;
 import org.drools.event.RuleFlowGroupActivatedEvent;
 import org.drools.event.RuleFlowGroupDeactivatedEvent;
 import org.drools.event.RuleFlowNodeTriggeredEvent;
@@ -161,6 +162,11 @@
             	System.out.println("afterRuleFlowNodeLeft " + event);
                 processEventList.add(event);
             }     
+
+            public void ruleFlowNodeExceptionOccurred(RuleFlowNodeExceptionOccurredEvent event, WorkingMemory workingMemory) {
+                System.out.println("ruleFlowExceptionOccurred " + event);
+                processEventList.add(event);
+            }
         };
 
 

Modified: labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/audit/WorkingMemoryLogger.java
===================================================================
--- labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/audit/WorkingMemoryLogger.java	2010-07-26 18:14:07 UTC (rev 34205)
+++ labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/audit/WorkingMemoryLogger.java	2010-07-26 20:05:42 UTC (rev 34206)
@@ -1,622 +1,634 @@
-package org.drools.audit;
-
-/*
- * Copyright 2005 JBoss Inc
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.drools.FactHandle;
-import org.drools.WorkingMemory;
-import org.drools.WorkingMemoryEventManager;
-import org.drools.audit.event.ActivationLogEvent;
-import org.drools.audit.event.ILogEventFilter;
-import org.drools.audit.event.LogEvent;
-import org.drools.audit.event.ObjectLogEvent;
-import org.drools.audit.event.RuleBaseLogEvent;
-import org.drools.audit.event.RuleFlowGroupLogEvent;
-import org.drools.audit.event.RuleFlowLogEvent;
-import org.drools.audit.event.RuleFlowNodeLogEvent;
-import org.drools.audit.event.RuleFlowVariableLogEvent;
-import org.drools.command.impl.CommandBasedStatefulKnowledgeSession;
-import org.drools.command.impl.KnowledgeCommandContext;
-import org.drools.common.InternalFactHandle;
-import org.drools.common.InternalWorkingMemory;
-import org.drools.definition.process.Node;
-import org.drools.definition.process.NodeContainer;
-import org.drools.event.ActivationCancelledEvent;
-import org.drools.event.ActivationCreatedEvent;
-import org.drools.event.AfterActivationFiredEvent;
-import org.drools.event.AfterFunctionRemovedEvent;
-import org.drools.event.AfterPackageAddedEvent;
-import org.drools.event.AfterPackageRemovedEvent;
-import org.drools.event.AfterRuleAddedEvent;
-import org.drools.event.AfterRuleBaseLockedEvent;
-import org.drools.event.AfterRuleBaseUnlockedEvent;
-import org.drools.event.AfterRuleRemovedEvent;
-import org.drools.event.AgendaEventListener;
-import org.drools.event.AgendaGroupPoppedEvent;
-import org.drools.event.AgendaGroupPushedEvent;
-import org.drools.event.BeforeActivationFiredEvent;
-import org.drools.event.BeforeFunctionRemovedEvent;
-import org.drools.event.BeforePackageAddedEvent;
-import org.drools.event.BeforePackageRemovedEvent;
-import org.drools.event.BeforeRuleAddedEvent;
-import org.drools.event.BeforeRuleBaseLockedEvent;
-import org.drools.event.BeforeRuleBaseUnlockedEvent;
-import org.drools.event.BeforeRuleRemovedEvent;
-import org.drools.event.KnowledgeRuntimeEventManager;
-import org.drools.event.ObjectInsertedEvent;
-import org.drools.event.ObjectRetractedEvent;
-import org.drools.event.ObjectUpdatedEvent;
-import org.drools.event.RuleBaseEventListener;
-import org.drools.event.RuleFlowCompletedEvent;
-import org.drools.event.RuleFlowEventListener;
-import org.drools.event.RuleFlowEventListenerExtension;
-import org.drools.event.RuleFlowGroupActivatedEvent;
-import org.drools.event.RuleFlowGroupDeactivatedEvent;
-import org.drools.event.RuleFlowNodeTriggeredEvent;
-import org.drools.event.RuleFlowStartedEvent;
-import org.drools.event.RuleFlowVariableChangeEvent;
-import org.drools.event.WorkingMemoryEventListener;
-import org.drools.impl.StatefulKnowledgeSessionImpl;
-import org.drools.impl.StatelessKnowledgeSessionImpl;
-import org.drools.rule.Declaration;
-import org.drools.runtime.process.NodeInstance;
-import org.drools.runtime.process.NodeInstanceContainer;
-import org.drools.spi.Activation;
-import org.drools.spi.Tuple;
-import org.drools.workflow.core.node.CompositeNode;
-import org.drools.workflow.core.node.ForEachNode;
-import org.drools.workflow.instance.node.CompositeNodeInstance;
-
-/**
- * A logger of events generated by a working memory.
- * It listens to the events generated by the working memory and
- * creates associated log event (containing a snapshot of the
- * state of the working event at that time).
- * 
- * Filters can be used to filter out unwanted events.
- * 
- * Subclasses of this class should implement the logEventCreated(LogEvent)
- * method and store this information, like for example log to file
- * or database.
- * 
- * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen </a>
- */
-public abstract class WorkingMemoryLogger
-    implements
-    WorkingMemoryEventListener,
-    AgendaEventListener,
-    RuleFlowEventListenerExtension,
-    RuleBaseEventListener {
-
-    private List<ILogEventFilter>    filters = new ArrayList<ILogEventFilter>();
-
-    public WorkingMemoryLogger() {
-    }
-
-    /**
-     * Creates a new working memory logger for the given working memory.
-     * 
-     * @param workingMemory
-     */
-    public WorkingMemoryLogger(final WorkingMemoryEventManager workingMemoryEventManager) {
-        workingMemoryEventManager.addEventListener( (WorkingMemoryEventListener) this );
-        workingMemoryEventManager.addEventListener( (AgendaEventListener) this );
-        workingMemoryEventManager.addEventListener( (RuleFlowEventListener) this );
-        workingMemoryEventManager.addEventListener( (RuleBaseEventListener) this );
-    }
-    
-    public WorkingMemoryLogger(final KnowledgeRuntimeEventManager session) {
-    	if (session instanceof StatefulKnowledgeSessionImpl) {
-    		WorkingMemoryEventManager eventManager = ((StatefulKnowledgeSessionImpl) session).session;
-    		eventManager.addEventListener( (WorkingMemoryEventListener) this );
-    		eventManager.addEventListener( (AgendaEventListener) this );
-    		eventManager.addEventListener( (RuleFlowEventListener) this );
-    		eventManager.addEventListener( (RuleBaseEventListener) this );
-    	} else if (session instanceof StatelessKnowledgeSessionImpl) {
-    		((StatelessKnowledgeSessionImpl) session).workingMemoryEventSupport.addEventListener( this );
-    		((StatelessKnowledgeSessionImpl) session).agendaEventSupport.addEventListener( this );
-    		((StatelessKnowledgeSessionImpl) session).ruleFlowEventSupport.addEventListener( this );
-    		((StatelessKnowledgeSessionImpl) session).getRuleBase().addEventListener( this );
-    	} else if (session instanceof CommandBasedStatefulKnowledgeSession) {
-    		WorkingMemoryEventManager eventManager = 
-    			((StatefulKnowledgeSessionImpl)((KnowledgeCommandContext)((CommandBasedStatefulKnowledgeSession) session).getCommandService().getContext()).getStatefulKnowledgesession()).session;
-    		eventManager.addEventListener( (WorkingMemoryEventListener) this );
-    		eventManager.addEventListener( (AgendaEventListener) this );
-    		eventManager.addEventListener( (RuleFlowEventListener) this );
-    		eventManager.addEventListener( (RuleBaseEventListener) this );
-    	} else {
-    		throw new IllegalArgumentException("Not supported session in logger: " + session.getClass());
-    	}
-    }
-
-    @SuppressWarnings("unchecked")
-	public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
-        filters = (List<ILogEventFilter>) in.readObject();
-    }
-
-    public void writeExternal(ObjectOutput out) throws IOException {
-        out.writeObject(filters);
-    }
-
-    /**
-     * This method is invoked every time a new log event is created.
-     * Subclasses should implement this method and store the event,
-     * like for example log to a file or database.
-     * 
-     * @param logEvent
-     */
-    public abstract void logEventCreated(LogEvent logEvent);
-
-    /**
-     * This method is invoked every time a new log event is created.
-     * It filters out unwanted events.
-     * 
-     * @param logEvent
-     */
-    private void filterLogEvent(final LogEvent logEvent) {
-        for ( ILogEventFilter filter: this.filters) {
-            // do nothing if one of the filters doesn't accept the event
-            if ( !filter.acceptEvent( logEvent ) ) {
-                return;
-            }
-        }
-        // if all the filters accepted the event, signal the creation
-        // of the event
-        logEventCreated( logEvent );
-    }
-
-    /**
-     * Adds the given filter to the list of filters for this event log.
-     * A log event must be accepted by all the filters to be entered in
-     * the event log.
-     *
-     * @param filter The filter that should be added.
-     */
-    public void addFilter(final ILogEventFilter filter) {
-        if ( filter == null ) {
-            throw new NullPointerException();
-        }
-        this.filters.add( filter );
-    }
-
-    /**
-     * Removes the given filter from the list of filters for this event log.
-     * If the given filter was not a filter of this event log, nothing
-     * happens.
-     *
-     * @param filter The filter that should be removed.
-     */
-    public void removeFilter(final ILogEventFilter filter) {
-        this.filters.remove( filter );
-    }
-
-    /**
-     * Clears all filters of this event log.
-     */
-    public void clearFilters() {
-        this.filters.clear();
-    }
-
-    /**
-     * @see org.drools.event.WorkingMemoryEventListener
-     */
-    public void objectInserted(final ObjectInsertedEvent event) {
-        filterLogEvent( new ObjectLogEvent( LogEvent.INSERTED,
-                                            ((InternalFactHandle) event.getFactHandle()).getId(),
-                                            event.getObject().toString() ) );
-    }
-
-    /**
-     * @see org.drools.event.WorkingMemoryEventListener
-     */
-    public void objectUpdated(final ObjectUpdatedEvent event) {
-        filterLogEvent( new ObjectLogEvent( LogEvent.UPDATED,
-                                            ((InternalFactHandle) event.getFactHandle()).getId(),
-                                            event.getObject().toString() ) );
-    }
-
-    /**
-     * @see org.drools.event.WorkingMemoryEventListener
-     */
-    public void objectRetracted(final ObjectRetractedEvent event) {
-        filterLogEvent( new ObjectLogEvent( LogEvent.RETRACTED,
-                                            ((InternalFactHandle) event.getFactHandle()).getId(),
-                                            event.getOldObject().toString() ) );
-    }
-
-    /**
-     * @see org.drools.event.AgendaEventListener
-     */
-    public void activationCreated(final ActivationCreatedEvent event,
-                                  final WorkingMemory workingMemory) {
-        filterLogEvent( new ActivationLogEvent( LogEvent.ACTIVATION_CREATED,
-                                                getActivationId( event.getActivation() ),
-                                                event.getActivation().getRule().getName(),
-                                                extractDeclarations( event.getActivation(), workingMemory ),
-    											event.getActivation().getRule().getRuleFlowGroup() ) );
-	}
-
-    /**
-     * @see org.drools.event.AgendaEventListener
-     */
-    public void activationCancelled(final ActivationCancelledEvent event,
-                                    final WorkingMemory workingMemory) {
-        filterLogEvent( new ActivationLogEvent( LogEvent.ACTIVATION_CANCELLED,
-                                                getActivationId( event.getActivation() ),
-                                                event.getActivation().getRule().getName(),
-                                                extractDeclarations( event.getActivation(), workingMemory ),
-    											event.getActivation().getRule().getRuleFlowGroup() ) );
-    }
-
-    /**
-     * @see org.drools.event.AgendaEventListener
-     */
-    public void beforeActivationFired(final BeforeActivationFiredEvent event,
-                                      final WorkingMemory workingMemory) {
-        filterLogEvent( new ActivationLogEvent( LogEvent.BEFORE_ACTIVATION_FIRE,
-                                                getActivationId( event.getActivation() ),
-                                                event.getActivation().getRule().getName(),
-                                                extractDeclarations( event.getActivation(), workingMemory ),
-    											event.getActivation().getRule().getRuleFlowGroup() ) );
-    }
-
-    /**
-     * @see org.drools.event.AgendaEventListener
-     */
-    public void afterActivationFired(final AfterActivationFiredEvent event,
-                                     final WorkingMemory workingMemory) {
-        filterLogEvent( new ActivationLogEvent( LogEvent.AFTER_ACTIVATION_FIRE,
-                                                getActivationId( event.getActivation() ),
-                                                event.getActivation().getRule().getName(),
-                                                extractDeclarations( event.getActivation(), workingMemory ),
-    											event.getActivation().getRule().getRuleFlowGroup() ) );
-    }
-
-    /**
-     * Creates a string representation of the declarations of an activation.
-     * This is a list of name-value-pairs for each of the declarations in the
-     * tuple of the activation.  The name is the identifier (=name) of the
-     * declaration, and the value is a toString of the value of the
-     * parameter, followed by the id of the fact between parentheses.
-     * 
-     * @param activation The activation from which the declarations should be extracted
-     * @return A String represetation of the declarations of the activation.
-     */
-    private String extractDeclarations(final Activation activation,  final WorkingMemory workingMemory) {
-        final StringBuilder result = new StringBuilder();
-        final Tuple tuple = activation.getTuple();
-        final Map<?, ?> declarations = activation.getSubRule().getOuterDeclarations();
-        for ( Iterator<?> it = declarations.values().iterator(); it.hasNext(); ) {
-            final Declaration declaration = (Declaration) it.next();
-            final FactHandle handle = tuple.get( declaration );
-            if ( handle instanceof InternalFactHandle ) {
-                final InternalFactHandle handleImpl = (InternalFactHandle) handle;
-                if ( handleImpl.getId() == -1 ) {
-                    // This handle is now invalid, probably due to an fact retraction
-                    continue;
-                }
-                final Object value = declaration.getValue( (InternalWorkingMemory) workingMemory, handleImpl.getObject() );
-
-                result.append( declaration.getIdentifier() );
-                result.append( "=" );
-                if ( value == null ) {
-                    // this should never occur
-                    result.append( "null" );
-                } else {
-                    result.append( value );
-                    result.append( "(" );
-                    result.append( handleImpl.getId() );
-                    result.append( ")" );
-                }
-            }
-            if ( it.hasNext() ) {
-                result.append( "; " );
-            }
-        }
-        return result.toString();
-    }
-
-    /**
-     * Returns a String that can be used as unique identifier for an
-     * activation.  Since the activationId is the same for all assertions
-     * that are created during a single insert, update or retract, the
-     * key of the tuple of the activation is added too (which is a set
-     * of fact handle ids). 
-     * 
-     * @param activation The activation for which a unique id should be generated
-     * @return A unique id for the activation
-     */
-    private static String getActivationId(final Activation activation) {
-        final StringBuilder result = new StringBuilder( activation.getRule().getName() );
-        result.append( " [" );
-        final Tuple tuple = activation.getTuple();
-        final FactHandle[] handles = tuple.getFactHandles();
-        for ( int i = 0; i < handles.length; i++ ) {
-            result.append( ((InternalFactHandle) handles[i]).getId() );
-            if ( i < handles.length - 1 ) {
-                result.append( ", " );
-            }
-        }
-        return result.append( "]" ).toString();
-    }
-    
-    public void agendaGroupPopped(final AgendaGroupPoppedEvent event,
-                                  final WorkingMemory workingMemory) {
-        // we don't audit this yet     
-    }
-
-    public void agendaGroupPushed(final AgendaGroupPushedEvent event,
-                                  final WorkingMemory workingMemory) {
-        // we don't audit this yet        
-    }
-    
-    public void beforeRuleFlowStarted(RuleFlowStartedEvent event,
-            					      WorkingMemory workingMemory) {
-        filterLogEvent( new RuleFlowLogEvent( LogEvent.BEFORE_RULEFLOW_CREATED,
-        		event.getProcessInstance().getProcessId(),
-                event.getProcessInstance().getProcessName(),
-                event.getProcessInstance().getId()) );
-    }
-
-    public void afterRuleFlowStarted(RuleFlowStartedEvent event,
-                                     WorkingMemory workingMemory) {
-        filterLogEvent(new RuleFlowLogEvent(LogEvent.AFTER_RULEFLOW_CREATED,
-                event.getProcessInstance().getProcessId(),
-                event.getProcessInstance().getProcessName(),
-                event.getProcessInstance().getId()) );
-    }
-
-    public void beforeRuleFlowCompleted(RuleFlowCompletedEvent event,
-              					  WorkingMemory workingMemory) {
-        filterLogEvent( new RuleFlowLogEvent( LogEvent.BEFORE_RULEFLOW_COMPLETED,
-        		event.getProcessInstance().getProcessId(),
-                event.getProcessInstance().getProcessName(),
-                event.getProcessInstance().getId()) );
-    }
-    
-    public void afterRuleFlowCompleted(RuleFlowCompletedEvent event,
-                                       WorkingMemory workingMemory) {
-        filterLogEvent(new RuleFlowLogEvent(LogEvent.AFTER_RULEFLOW_COMPLETED,
-                event.getProcessInstance().getProcessId(),
-                event.getProcessInstance().getProcessName(),
-                event.getProcessInstance().getId()) );
-    }
-
-    public void beforeRuleFlowGroupActivated(
-            RuleFlowGroupActivatedEvent event,
-            WorkingMemory workingMemory) {
-        filterLogEvent(new RuleFlowGroupLogEvent(
-                LogEvent.BEFORE_RULEFLOW_GROUP_ACTIVATED, event
-                        .getRuleFlowGroup().getName(), event.getRuleFlowGroup()
-                        .size()));
-    }
-    
-    public void afterRuleFlowGroupActivated(
-            RuleFlowGroupActivatedEvent event,
-            WorkingMemory workingMemory) {
-        filterLogEvent(new RuleFlowGroupLogEvent(
-                LogEvent.AFTER_RULEFLOW_GROUP_ACTIVATED,
-                event.getRuleFlowGroup().getName(),
-                event.getRuleFlowGroup().size()));
-    }
-
-    public void beforeRuleFlowGroupDeactivated(
-            RuleFlowGroupDeactivatedEvent event, 
-            WorkingMemory workingMemory) {
-        filterLogEvent(new RuleFlowGroupLogEvent(
-                LogEvent.BEFORE_RULEFLOW_GROUP_DEACTIVATED,
-                event.getRuleFlowGroup().getName(),
-                event.getRuleFlowGroup().size()));
-    }
-    
-    public void afterRuleFlowGroupDeactivated(
-            RuleFlowGroupDeactivatedEvent event,
-            WorkingMemory workingMemory) {
-        filterLogEvent(new RuleFlowGroupLogEvent(
-                LogEvent.AFTER_RULEFLOW_GROUP_DEACTIVATED,
-                event.getRuleFlowGroup().getName(),
-                event.getRuleFlowGroup().size()));
-    }
-
-    public void beforeRuleFlowNodeTriggered(RuleFlowNodeTriggeredEvent event,
-                                            WorkingMemory workingMemory) {
-        filterLogEvent(new RuleFlowNodeLogEvent(LogEvent.BEFORE_RULEFLOW_NODE_TRIGGERED,
-                createNodeId(event.getRuleFlowNodeInstance()),
-                event.getRuleFlowNodeInstance().getNodeName(),
-                createNodeInstanceId(event.getRuleFlowNodeInstance()),
-                event.getProcessInstance().getProcessId(),
-                event.getProcessInstance().getProcessName(),
-                event.getProcessInstance().getId()) );
-    }
-
-    public void afterRuleFlowNodeTriggered(RuleFlowNodeTriggeredEvent event,
-                                           WorkingMemory workingMemory) {
-        filterLogEvent(new RuleFlowNodeLogEvent(LogEvent.AFTER_RULEFLOW_NODE_TRIGGERED,
-                createNodeId(event.getRuleFlowNodeInstance()),
-                event.getRuleFlowNodeInstance().getNodeName(),
-                createNodeInstanceId(event.getRuleFlowNodeInstance()),
-                event.getProcessInstance().getProcessId(), 
-                event.getProcessInstance().getProcessName(),
-                event.getProcessInstance().getId()) );
-    }
-    
-    public void beforeVariableChange(RuleFlowVariableChangeEvent event,
-                                     WorkingMemory workingMemory) {
-		filterLogEvent(new RuleFlowVariableLogEvent(LogEvent.BEFORE_VARIABLE_INSTANCE_CHANGED,
-			event.getVariableId(),
-			event.getVariableInstanceId(),
-			event.getProcessInstance().getProcessId(),
-			event.getProcessInstance().getProcessName(),
-			event.getProcessInstance().getId(),
-			event.getValue() == null ? "null" : event.getValue().toString() ));
-    }
-
-    public void afterVariableChange(RuleFlowVariableChangeEvent event,
-                                    WorkingMemory workingMemory) {
-		filterLogEvent(new RuleFlowVariableLogEvent(LogEvent.AFTER_VARIABLE_INSTANCE_CHANGED,
-			event.getVariableId(),
-			event.getVariableInstanceId(),
-			event.getProcessInstance().getProcessId(),
-			event.getProcessInstance().getProcessName(),
-			event.getProcessInstance().getId(),
-			event.getValue() == null ? "null" : event.getValue().toString() ));
-    }
-
-    private String createNodeId(NodeInstance nodeInstance) {
-    	Node node = ((org.drools.workflow.instance.NodeInstance) nodeInstance).getNode();
-    	if (node == null) {
-    		return "";
-    	}
-    	String nodeId = "" + node.getId();
-    	NodeContainer nodeContainer = node.getNodeContainer();
-    	while (nodeContainer != null) {
-    		if (nodeContainer instanceof CompositeNode) {
-    			node = (CompositeNode) nodeContainer;
-    			nodeContainer = node.getNodeContainer();
-    			// filter out hidden compositeNode inside ForEach node
-    			if (!(nodeContainer instanceof ForEachNode)) {
-        			nodeId = node.getId() + ":" + nodeId;
-    			}
-    		} else {
-    			break;
-    		}
-    	}
-    	return nodeId;
-    }
-
-    private String createNodeInstanceId(NodeInstance nodeInstance) {
-    	String nodeInstanceId = "" + nodeInstance.getId();
-    	NodeInstanceContainer nodeContainer = nodeInstance.getNodeInstanceContainer();
-    	while (nodeContainer != null) {
-    		if (nodeContainer instanceof CompositeNodeInstance) {
-    			nodeInstance = (CompositeNodeInstance) nodeContainer;
-    			nodeInstanceId = nodeInstance.getId() + ":" + nodeInstanceId;
-    			nodeContainer = nodeInstance.getNodeInstanceContainer();
-    		} else {
-    			break;
-    		}
-    	}
-    	return nodeInstanceId;
-    }
-
-    public void beforeRuleFlowNodeLeft(RuleFlowNodeTriggeredEvent event,
-    										WorkingMemory workingMemory) {
-        filterLogEvent(new RuleFlowNodeLogEvent(LogEvent.BEFORE_RULEFLOW_NODE_EXITED,
-            createNodeId(event.getRuleFlowNodeInstance()),
-            event.getRuleFlowNodeInstance().getNodeName(),
-            createNodeInstanceId(event.getRuleFlowNodeInstance()),
-            event.getProcessInstance().getProcessId(),
-            event.getProcessInstance().getProcessName(),
-            event.getProcessInstance().getId()) );
-    }
-
-    public void afterRuleFlowNodeLeft(RuleFlowNodeTriggeredEvent event,
-    								  WorkingMemory workingMemory) {
-        filterLogEvent(new RuleFlowNodeLogEvent(LogEvent.AFTER_RULEFLOW_NODE_EXITED,
-            createNodeId(event.getRuleFlowNodeInstance()),
-            event.getRuleFlowNodeInstance().getNodeName(),
-            createNodeInstanceId(event.getRuleFlowNodeInstance()),
-            event.getProcessInstance().getProcessId(), 
-            event.getProcessInstance().getProcessName(),
-            event.getProcessInstance().getId()) );
-    }
-
-    public void afterPackageAdded(AfterPackageAddedEvent event) {
-        filterLogEvent( new RuleBaseLogEvent( LogEvent.AFTER_PACKAGE_ADDED,
-                                              event.getPackage().getName(),
-                                              null ) );
-    }
-
-    public void afterPackageRemoved(AfterPackageRemovedEvent event) {
-        filterLogEvent( new RuleBaseLogEvent( LogEvent.AFTER_PACKAGE_REMOVED,
-                                              event.getPackage().getName(),
-                                              null ) );
-    }
-
-    public void afterRuleAdded(AfterRuleAddedEvent event) {
-        filterLogEvent( new RuleBaseLogEvent( LogEvent.AFTER_RULE_ADDED,
-                                              event.getPackage().getName(),
-                                              event.getRule().getName() ) );
-    }
-
-    public void afterRuleRemoved(AfterRuleRemovedEvent event) {
-        filterLogEvent( new RuleBaseLogEvent( LogEvent.AFTER_RULE_REMOVED,
-                                              event.getPackage().getName(),
-                                              event.getRule().getName() ) );
-    }
-
-    public void beforePackageAdded(BeforePackageAddedEvent event) {
-        filterLogEvent( new RuleBaseLogEvent( LogEvent.BEFORE_PACKAGE_ADDED,
-                                              event.getPackage().getName(),
-                                              null ) );
-    }
-
-    public void beforePackageRemoved(BeforePackageRemovedEvent event) {
-        filterLogEvent( new RuleBaseLogEvent( LogEvent.BEFORE_PACKAGE_REMOVED,
-                                              event.getPackage().getName(),
-                                              null ) );
-    }
-
-    public void beforeRuleAdded(BeforeRuleAddedEvent event) {
-        filterLogEvent( new RuleBaseLogEvent( LogEvent.BEFORE_RULE_ADDED,
-                                              event.getPackage().getName(),
-                                              event.getRule().getName() ) );
-    }
-
-    public void beforeRuleRemoved(BeforeRuleRemovedEvent event) {
-        filterLogEvent( new RuleBaseLogEvent( LogEvent.BEFORE_RULE_REMOVED,
-                                              event.getPackage().getName(),
-                                              event.getRule().getName() ) );
-    }
-    
-    public void afterFunctionRemoved(AfterFunctionRemovedEvent event) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    public void afterRuleBaseLocked(AfterRuleBaseLockedEvent event) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    public void afterRuleBaseUnlocked(AfterRuleBaseUnlockedEvent event) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    public void beforeFunctionRemoved(BeforeFunctionRemovedEvent event) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    public void beforeRuleBaseLocked(BeforeRuleBaseLockedEvent event) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    public void beforeRuleBaseUnlocked(BeforeRuleBaseUnlockedEvent event) {
-        // TODO Auto-generated method stub
-        
-    }        
-}
+package org.drools.audit;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.FactHandle;
+import org.drools.WorkingMemory;
+import org.drools.WorkingMemoryEventManager;
+import org.drools.audit.event.ActivationLogEvent;
+import org.drools.audit.event.ILogEventFilter;
+import org.drools.audit.event.LogEvent;
+import org.drools.audit.event.ObjectLogEvent;
+import org.drools.audit.event.RuleBaseLogEvent;
+import org.drools.audit.event.RuleFlowGroupLogEvent;
+import org.drools.audit.event.RuleFlowLogEvent;
+import org.drools.audit.event.RuleFlowNodeLogEvent;
+import org.drools.audit.event.RuleFlowVariableLogEvent;
+import org.drools.command.impl.CommandBasedStatefulKnowledgeSession;
+import org.drools.command.impl.KnowledgeCommandContext;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.definition.process.Node;
+import org.drools.definition.process.NodeContainer;
+import org.drools.event.ActivationCancelledEvent;
+import org.drools.event.ActivationCreatedEvent;
+import org.drools.event.AfterActivationFiredEvent;
+import org.drools.event.AfterFunctionRemovedEvent;
+import org.drools.event.AfterPackageAddedEvent;
+import org.drools.event.AfterPackageRemovedEvent;
+import org.drools.event.AfterRuleAddedEvent;
+import org.drools.event.AfterRuleBaseLockedEvent;
+import org.drools.event.AfterRuleBaseUnlockedEvent;
+import org.drools.event.AfterRuleRemovedEvent;
+import org.drools.event.AgendaEventListener;
+import org.drools.event.AgendaGroupPoppedEvent;
+import org.drools.event.AgendaGroupPushedEvent;
+import org.drools.event.BeforeActivationFiredEvent;
+import org.drools.event.BeforeFunctionRemovedEvent;
+import org.drools.event.BeforePackageAddedEvent;
+import org.drools.event.BeforePackageRemovedEvent;
+import org.drools.event.BeforeRuleAddedEvent;
+import org.drools.event.BeforeRuleBaseLockedEvent;
+import org.drools.event.BeforeRuleBaseUnlockedEvent;
+import org.drools.event.BeforeRuleRemovedEvent;
+import org.drools.event.KnowledgeRuntimeEventManager;
+import org.drools.event.ObjectInsertedEvent;
+import org.drools.event.ObjectRetractedEvent;
+import org.drools.event.ObjectUpdatedEvent;
+import org.drools.event.RuleBaseEventListener;
+import org.drools.event.RuleFlowCompletedEvent;
+import org.drools.event.RuleFlowEventListener;
+import org.drools.event.RuleFlowEventListenerExtension;
+import org.drools.event.RuleFlowNodeExceptionOccurredEvent;
+import org.drools.event.RuleFlowGroupActivatedEvent;
+import org.drools.event.RuleFlowGroupDeactivatedEvent;
+import org.drools.event.RuleFlowNodeTriggeredEvent;
+import org.drools.event.RuleFlowStartedEvent;
+import org.drools.event.RuleFlowVariableChangeEvent;
+import org.drools.event.WorkingMemoryEventListener;
+import org.drools.impl.StatefulKnowledgeSessionImpl;
+import org.drools.impl.StatelessKnowledgeSessionImpl;
+import org.drools.rule.Declaration;
+import org.drools.runtime.process.NodeInstance;
+import org.drools.runtime.process.NodeInstanceContainer;
+import org.drools.spi.Activation;
+import org.drools.spi.Tuple;
+import org.drools.workflow.core.node.CompositeNode;
+import org.drools.workflow.core.node.ForEachNode;
+import org.drools.workflow.instance.node.CompositeNodeInstance;
+
+/**
+ * A logger of events generated by a working memory.
+ * It listens to the events generated by the working memory and
+ * creates associated log event (containing a snapshot of the
+ * state of the working event at that time).
+ * 
+ * Filters can be used to filter out unwanted events.
+ * 
+ * Subclasses of this class should implement the logEventCreated(LogEvent)
+ * method and store this information, like for example log to file
+ * or database.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen </a>
+ */
+public abstract class WorkingMemoryLogger
+    implements
+    WorkingMemoryEventListener,
+    AgendaEventListener,
+    RuleFlowEventListenerExtension,
+    RuleBaseEventListener {
+
+    private List<ILogEventFilter>    filters = new ArrayList<ILogEventFilter>();
+
+    public WorkingMemoryLogger() {
+    }
+
+    /**
+     * Creates a new working memory logger for the given working memory.
+     * 
+     * @param workingMemory
+     */
+    public WorkingMemoryLogger(final WorkingMemoryEventManager workingMemoryEventManager) {
+        workingMemoryEventManager.addEventListener( (WorkingMemoryEventListener) this );
+        workingMemoryEventManager.addEventListener( (AgendaEventListener) this );
+        workingMemoryEventManager.addEventListener( (RuleFlowEventListener) this );
+        workingMemoryEventManager.addEventListener( (RuleBaseEventListener) this );
+    }
+    
+    public WorkingMemoryLogger(final KnowledgeRuntimeEventManager session) {
+    	if (session instanceof StatefulKnowledgeSessionImpl) {
+    		WorkingMemoryEventManager eventManager = ((StatefulKnowledgeSessionImpl) session).session;
+    		eventManager.addEventListener( (WorkingMemoryEventListener) this );
+    		eventManager.addEventListener( (AgendaEventListener) this );
+    		eventManager.addEventListener( (RuleFlowEventListener) this );
+    		eventManager.addEventListener( (RuleBaseEventListener) this );
+    	} else if (session instanceof StatelessKnowledgeSessionImpl) {
+    		((StatelessKnowledgeSessionImpl) session).workingMemoryEventSupport.addEventListener( this );
+    		((StatelessKnowledgeSessionImpl) session).agendaEventSupport.addEventListener( this );
+    		((StatelessKnowledgeSessionImpl) session).ruleFlowEventSupport.addEventListener( this );
+    		((StatelessKnowledgeSessionImpl) session).getRuleBase().addEventListener( this );
+    	} else if (session instanceof CommandBasedStatefulKnowledgeSession) {
+    		WorkingMemoryEventManager eventManager = 
+    			((StatefulKnowledgeSessionImpl)((KnowledgeCommandContext)((CommandBasedStatefulKnowledgeSession) session).getCommandService().getContext()).getStatefulKnowledgesession()).session;
+    		eventManager.addEventListener( (WorkingMemoryEventListener) this );
+    		eventManager.addEventListener( (AgendaEventListener) this );
+    		eventManager.addEventListener( (RuleFlowEventListener) this );
+    		eventManager.addEventListener( (RuleBaseEventListener) this );
+    	} else {
+    		throw new IllegalArgumentException("Not supported session in logger: " + session.getClass());
+    	}
+    }
+
+    @SuppressWarnings("unchecked")
+	public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+        filters = (List<ILogEventFilter>) in.readObject();
+    }
+
+    public void writeExternal(ObjectOutput out) throws IOException {
+        out.writeObject(filters);
+    }
+
+    /**
+     * This method is invoked every time a new log event is created.
+     * Subclasses should implement this method and store the event,
+     * like for example log to a file or database.
+     * 
+     * @param logEvent
+     */
+    public abstract void logEventCreated(LogEvent logEvent);
+
+    /**
+     * This method is invoked every time a new log event is created.
+     * It filters out unwanted events.
+     * 
+     * @param logEvent
+     */
+    private void filterLogEvent(final LogEvent logEvent) {
+        for ( ILogEventFilter filter: this.filters) {
+            // do nothing if one of the filters doesn't accept the event
+            if ( !filter.acceptEvent( logEvent ) ) {
+                return;
+            }
+        }
+        // if all the filters accepted the event, signal the creation
+        // of the event
+        logEventCreated( logEvent );
+    }
+
+    /**
+     * Adds the given filter to the list of filters for this event log.
+     * A log event must be accepted by all the filters to be entered in
+     * the event log.
+     *
+     * @param filter The filter that should be added.
+     */
+    public void addFilter(final ILogEventFilter filter) {
+        if ( filter == null ) {
+            throw new NullPointerException();
+        }
+        this.filters.add( filter );
+    }
+
+    /**
+     * Removes the given filter from the list of filters for this event log.
+     * If the given filter was not a filter of this event log, nothing
+     * happens.
+     *
+     * @param filter The filter that should be removed.
+     */
+    public void removeFilter(final ILogEventFilter filter) {
+        this.filters.remove( filter );
+    }
+
+    /**
+     * Clears all filters of this event log.
+     */
+    public void clearFilters() {
+        this.filters.clear();
+    }
+
+    /**
+     * @see org.drools.event.WorkingMemoryEventListener
+     */
+    public void objectInserted(final ObjectInsertedEvent event) {
+        filterLogEvent( new ObjectLogEvent( LogEvent.INSERTED,
+                                            ((InternalFactHandle) event.getFactHandle()).getId(),
+                                            event.getObject().toString() ) );
+    }
+
+    /**
+     * @see org.drools.event.WorkingMemoryEventListener
+     */
+    public void objectUpdated(final ObjectUpdatedEvent event) {
+        filterLogEvent( new ObjectLogEvent( LogEvent.UPDATED,
+                                            ((InternalFactHandle) event.getFactHandle()).getId(),
+                                            event.getObject().toString() ) );
+    }
+
+    /**
+     * @see org.drools.event.WorkingMemoryEventListener
+     */
+    public void objectRetracted(final ObjectRetractedEvent event) {
+        filterLogEvent( new ObjectLogEvent( LogEvent.RETRACTED,
+                                            ((InternalFactHandle) event.getFactHandle()).getId(),
+                                            event.getOldObject().toString() ) );
+    }
+
+    /**
+     * @see org.drools.event.AgendaEventListener
+     */
+    public void activationCreated(final ActivationCreatedEvent event,
+                                  final WorkingMemory workingMemory) {
+        filterLogEvent( new ActivationLogEvent( LogEvent.ACTIVATION_CREATED,
+                                                getActivationId( event.getActivation() ),
+                                                event.getActivation().getRule().getName(),
+                                                extractDeclarations( event.getActivation(), workingMemory ),
+    											event.getActivation().getRule().getRuleFlowGroup() ) );
+	}
+
+    /**
+     * @see org.drools.event.AgendaEventListener
+     */
+    public void activationCancelled(final ActivationCancelledEvent event,
+                                    final WorkingMemory workingMemory) {
+        filterLogEvent( new ActivationLogEvent( LogEvent.ACTIVATION_CANCELLED,
+                                                getActivationId( event.getActivation() ),
+                                                event.getActivation().getRule().getName(),
+                                                extractDeclarations( event.getActivation(), workingMemory ),
+    											event.getActivation().getRule().getRuleFlowGroup() ) );
+    }
+
+    /**
+     * @see org.drools.event.AgendaEventListener
+     */
+    public void beforeActivationFired(final BeforeActivationFiredEvent event,
+                                      final WorkingMemory workingMemory) {
+        filterLogEvent( new ActivationLogEvent( LogEvent.BEFORE_ACTIVATION_FIRE,
+                                                getActivationId( event.getActivation() ),
+                                                event.getActivation().getRule().getName(),
+                                                extractDeclarations( event.getActivation(), workingMemory ),
+    											event.getActivation().getRule().getRuleFlowGroup() ) );
+    }
+
+    /**
+     * @see org.drools.event.AgendaEventListener
+     */
+    public void afterActivationFired(final AfterActivationFiredEvent event,
+                                     final WorkingMemory workingMemory) {
+        filterLogEvent( new ActivationLogEvent( LogEvent.AFTER_ACTIVATION_FIRE,
+                                                getActivationId( event.getActivation() ),
+                                                event.getActivation().getRule().getName(),
+                                                extractDeclarations( event.getActivation(), workingMemory ),
+    											event.getActivation().getRule().getRuleFlowGroup() ) );
+    }
+
+    /**
+     * Creates a string representation of the declarations of an activation.
+     * This is a list of name-value-pairs for each of the declarations in the
+     * tuple of the activation.  The name is the identifier (=name) of the
+     * declaration, and the value is a toString of the value of the
+     * parameter, followed by the id of the fact between parentheses.
+     * 
+     * @param activation The activation from which the declarations should be extracted
+     * @return A String represetation of the declarations of the activation.
+     */
+    private String extractDeclarations(final Activation activation,  final WorkingMemory workingMemory) {
+        final StringBuilder result = new StringBuilder();
+        final Tuple tuple = activation.getTuple();
+        final Map<?, ?> declarations = activation.getSubRule().getOuterDeclarations();
+        for ( Iterator<?> it = declarations.values().iterator(); it.hasNext(); ) {
+            final Declaration declaration = (Declaration) it.next();
+            final FactHandle handle = tuple.get( declaration );
+            if ( handle instanceof InternalFactHandle ) {
+                final InternalFactHandle handleImpl = (InternalFactHandle) handle;
+                if ( handleImpl.getId() == -1 ) {
+                    // This handle is now invalid, probably due to an fact retraction
+                    continue;
+                }
+                final Object value = declaration.getValue( (InternalWorkingMemory) workingMemory, handleImpl.getObject() );
+
+                result.append( declaration.getIdentifier() );
+                result.append( "=" );
+                if ( value == null ) {
+                    // this should never occur
+                    result.append( "null" );
+                } else {
+                    result.append( value );
+                    result.append( "(" );
+                    result.append( handleImpl.getId() );
+                    result.append( ")" );
+                }
+            }
+            if ( it.hasNext() ) {
+                result.append( "; " );
+            }
+        }
+        return result.toString();
+    }
+
+    /**
+     * Returns a String that can be used as unique identifier for an
+     * activation.  Since the activationId is the same for all assertions
+     * that are created during a single insert, update or retract, the
+     * key of the tuple of the activation is added too (which is a set
+     * of fact handle ids). 
+     * 
+     * @param activation The activation for which a unique id should be generated
+     * @return A unique id for the activation
+     */
+    private static String getActivationId(final Activation activation) {
+        final StringBuilder result = new StringBuilder( activation.getRule().getName() );
+        result.append( " [" );
+        final Tuple tuple = activation.getTuple();
+        final FactHandle[] handles = tuple.getFactHandles();
+        for ( int i = 0; i < handles.length; i++ ) {
+            result.append( ((InternalFactHandle) handles[i]).getId() );
+            if ( i < handles.length - 1 ) {
+                result.append( ", " );
+            }
+        }
+        return result.append( "]" ).toString();
+    }
+    
+    public void agendaGroupPopped(final AgendaGroupPoppedEvent event,
+                                  final WorkingMemory workingMemory) {
+        // we don't audit this yet     
+    }
+
+    public void agendaGroupPushed(final AgendaGroupPushedEvent event,
+                                  final WorkingMemory workingMemory) {
+        // we don't audit this yet        
+    }
+    
+    public void beforeRuleFlowStarted(RuleFlowStartedEvent event,
+            					      WorkingMemory workingMemory) {
+        filterLogEvent( new RuleFlowLogEvent( LogEvent.BEFORE_RULEFLOW_CREATED,
+        		event.getProcessInstance().getProcessId(),
+                event.getProcessInstance().getProcessName(),
+                event.getProcessInstance().getId()) );
+    }
+
+    public void afterRuleFlowStarted(RuleFlowStartedEvent event,
+                                     WorkingMemory workingMemory) {
+        filterLogEvent(new RuleFlowLogEvent(LogEvent.AFTER_RULEFLOW_CREATED,
+                event.getProcessInstance().getProcessId(),
+                event.getProcessInstance().getProcessName(),
+                event.getProcessInstance().getId()) );
+    }
+
+    public void beforeRuleFlowCompleted(RuleFlowCompletedEvent event,
+              					  WorkingMemory workingMemory) {
+        filterLogEvent( new RuleFlowLogEvent( LogEvent.BEFORE_RULEFLOW_COMPLETED,
+        		event.getProcessInstance().getProcessId(),
+                event.getProcessInstance().getProcessName(),
+                event.getProcessInstance().getId()) );
+    }
+    
+    public void afterRuleFlowCompleted(RuleFlowCompletedEvent event,
+                                       WorkingMemory workingMemory) {
+        filterLogEvent(new RuleFlowLogEvent(LogEvent.AFTER_RULEFLOW_COMPLETED,
+                event.getProcessInstance().getProcessId(),
+                event.getProcessInstance().getProcessName(),
+                event.getProcessInstance().getId()) );
+    }
+
+    public void beforeRuleFlowGroupActivated(
+            RuleFlowGroupActivatedEvent event,
+            WorkingMemory workingMemory) {
+        filterLogEvent(new RuleFlowGroupLogEvent(
+                LogEvent.BEFORE_RULEFLOW_GROUP_ACTIVATED, event
+                        .getRuleFlowGroup().getName(), event.getRuleFlowGroup()
+                        .size()));
+    }
+    
+    public void afterRuleFlowGroupActivated(
+            RuleFlowGroupActivatedEvent event,
+            WorkingMemory workingMemory) {
+        filterLogEvent(new RuleFlowGroupLogEvent(
+                LogEvent.AFTER_RULEFLOW_GROUP_ACTIVATED,
+                event.getRuleFlowGroup().getName(),
+                event.getRuleFlowGroup().size()));
+    }
+
+    public void beforeRuleFlowGroupDeactivated(
+            RuleFlowGroupDeactivatedEvent event, 
+            WorkingMemory workingMemory) {
+        filterLogEvent(new RuleFlowGroupLogEvent(
+                LogEvent.BEFORE_RULEFLOW_GROUP_DEACTIVATED,
+                event.getRuleFlowGroup().getName(),
+                event.getRuleFlowGroup().size()));
+    }
+    
+    public void afterRuleFlowGroupDeactivated(
+            RuleFlowGroupDeactivatedEvent event,
+            WorkingMemory workingMemory) {
+        filterLogEvent(new RuleFlowGroupLogEvent(
+                LogEvent.AFTER_RULEFLOW_GROUP_DEACTIVATED,
+                event.getRuleFlowGroup().getName(),
+                event.getRuleFlowGroup().size()));
+    }
+
+    public void beforeRuleFlowNodeTriggered(RuleFlowNodeTriggeredEvent event,
+                                            WorkingMemory workingMemory) {
+        filterLogEvent(new RuleFlowNodeLogEvent(LogEvent.BEFORE_RULEFLOW_NODE_TRIGGERED,
+                createNodeId(event.getRuleFlowNodeInstance()),
+                event.getRuleFlowNodeInstance().getNodeName(),
+                createNodeInstanceId(event.getRuleFlowNodeInstance()),
+                event.getProcessInstance().getProcessId(),
+                event.getProcessInstance().getProcessName(),
+                event.getProcessInstance().getId()) );
+    }
+
+    public void afterRuleFlowNodeTriggered(RuleFlowNodeTriggeredEvent event,
+                                           WorkingMemory workingMemory) {
+        filterLogEvent(new RuleFlowNodeLogEvent(LogEvent.AFTER_RULEFLOW_NODE_TRIGGERED,
+                createNodeId(event.getRuleFlowNodeInstance()),
+                event.getRuleFlowNodeInstance().getNodeName(),
+                createNodeInstanceId(event.getRuleFlowNodeInstance()),
+                event.getProcessInstance().getProcessId(), 
+                event.getProcessInstance().getProcessName(),
+                event.getProcessInstance().getId()) );
+    }
+    
+    public void beforeVariableChange(RuleFlowVariableChangeEvent event,
+                                     WorkingMemory workingMemory) {
+		filterLogEvent(new RuleFlowVariableLogEvent(LogEvent.BEFORE_VARIABLE_INSTANCE_CHANGED,
+			event.getVariableId(),
+			event.getVariableInstanceId(),
+			event.getProcessInstance().getProcessId(),
+			event.getProcessInstance().getProcessName(),
+			event.getProcessInstance().getId(),
+			event.getValue() == null ? "null" : event.getValue().toString() ));
+    }
+
+    public void afterVariableChange(RuleFlowVariableChangeEvent event,
+                                    WorkingMemory workingMemory) {
+		filterLogEvent(new RuleFlowVariableLogEvent(LogEvent.AFTER_VARIABLE_INSTANCE_CHANGED,
+			event.getVariableId(),
+			event.getVariableInstanceId(),
+			event.getProcessInstance().getProcessId(),
+			event.getProcessInstance().getProcessName(),
+			event.getProcessInstance().getId(),
+			event.getValue() == null ? "null" : event.getValue().toString() ));
+    }
+
+    public void ruleFlowNodeExceptionOccurred(RuleFlowNodeExceptionOccurredEvent event,
+                                WorkingMemory workingMemory) {
+//		filterLogEvent(new RuleFlowVariableLogEvent(LogEvent.AFTER_VARIABLE_INSTANCE_CHANGED,
+//			event.getVariableId(),
+//			event.getVariableInstanceId(),
+//			event.getProcessInstance().getProcessId(),
+//			event.getProcessInstance().getProcessName(),
+//			event.getProcessInstance().getId(),
+//			event.getValue() == null ? "null" : event.getValue().toString() ));
+    }
+
+    private String createNodeId(NodeInstance nodeInstance) {
+    	Node node = ((org.drools.workflow.instance.NodeInstance) nodeInstance).getNode();
+    	if (node == null) {
+    		return "";
+    	}
+    	String nodeId = "" + node.getId();
+    	NodeContainer nodeContainer = node.getNodeContainer();
+    	while (nodeContainer != null) {
+    		if (nodeContainer instanceof CompositeNode) {
+    			node = (CompositeNode) nodeContainer;
+    			nodeContainer = node.getNodeContainer();
+    			// filter out hidden compositeNode inside ForEach node
+    			if (!(nodeContainer instanceof ForEachNode)) {
+        			nodeId = node.getId() + ":" + nodeId;
+    			}
+    		} else {
+    			break;
+    		}
+    	}
+    	return nodeId;
+    }
+
+    private String createNodeInstanceId(NodeInstance nodeInstance) {
+    	String nodeInstanceId = "" + nodeInstance.getId();
+    	NodeInstanceContainer nodeContainer = nodeInstance.getNodeInstanceContainer();
+    	while (nodeContainer != null) {
+    		if (nodeContainer instanceof CompositeNodeInstance) {
+    			nodeInstance = (CompositeNodeInstance) nodeContainer;
+    			nodeInstanceId = nodeInstance.getId() + ":" + nodeInstanceId;
+    			nodeContainer = nodeInstance.getNodeInstanceContainer();
+    		} else {
+    			break;
+    		}
+    	}
+    	return nodeInstanceId;
+    }
+
+    public void beforeRuleFlowNodeLeft(RuleFlowNodeTriggeredEvent event,
+    										WorkingMemory workingMemory) {
+        filterLogEvent(new RuleFlowNodeLogEvent(LogEvent.BEFORE_RULEFLOW_NODE_EXITED,
+            createNodeId(event.getRuleFlowNodeInstance()),
+            event.getRuleFlowNodeInstance().getNodeName(),
+            createNodeInstanceId(event.getRuleFlowNodeInstance()),
+            event.getProcessInstance().getProcessId(),
+            event.getProcessInstance().getProcessName(),
+            event.getProcessInstance().getId()) );
+    }
+
+    public void afterRuleFlowNodeLeft(RuleFlowNodeTriggeredEvent event,
+    								  WorkingMemory workingMemory) {
+        filterLogEvent(new RuleFlowNodeLogEvent(LogEvent.AFTER_RULEFLOW_NODE_EXITED,
+            createNodeId(event.getRuleFlowNodeInstance()),
+            event.getRuleFlowNodeInstance().getNodeName(),
+            createNodeInstanceId(event.getRuleFlowNodeInstance()),
+            event.getProcessInstance().getProcessId(), 
+            event.getProcessInstance().getProcessName(),
+            event.getProcessInstance().getId()) );
+    }
+
+    public void afterPackageAdded(AfterPackageAddedEvent event) {
+        filterLogEvent( new RuleBaseLogEvent( LogEvent.AFTER_PACKAGE_ADDED,
+                                              event.getPackage().getName(),
+                                              null ) );
+    }
+
+    public void afterPackageRemoved(AfterPackageRemovedEvent event) {
+        filterLogEvent( new RuleBaseLogEvent( LogEvent.AFTER_PACKAGE_REMOVED,
+                                              event.getPackage().getName(),
+                                              null ) );
+    }
+
+    public void afterRuleAdded(AfterRuleAddedEvent event) {
+        filterLogEvent( new RuleBaseLogEvent( LogEvent.AFTER_RULE_ADDED,
+                                              event.getPackage().getName(),
+                                              event.getRule().getName() ) );
+    }
+
+    public void afterRuleRemoved(AfterRuleRemovedEvent event) {
+        filterLogEvent( new RuleBaseLogEvent( LogEvent.AFTER_RULE_REMOVED,
+                                              event.getPackage().getName(),
+                                              event.getRule().getName() ) );
+    }
+
+    public void beforePackageAdded(BeforePackageAddedEvent event) {
+        filterLogEvent( new RuleBaseLogEvent( LogEvent.BEFORE_PACKAGE_ADDED,
+                                              event.getPackage().getName(),
+                                              null ) );
+    }
+
+    public void beforePackageRemoved(BeforePackageRemovedEvent event) {
+        filterLogEvent( new RuleBaseLogEvent( LogEvent.BEFORE_PACKAGE_REMOVED,
+                                              event.getPackage().getName(),
+                                              null ) );
+    }
+
+    public void beforeRuleAdded(BeforeRuleAddedEvent event) {
+        filterLogEvent( new RuleBaseLogEvent( LogEvent.BEFORE_RULE_ADDED,
+                                              event.getPackage().getName(),
+                                              event.getRule().getName() ) );
+    }
+
+    public void beforeRuleRemoved(BeforeRuleRemovedEvent event) {
+        filterLogEvent( new RuleBaseLogEvent( LogEvent.BEFORE_RULE_REMOVED,
+                                              event.getPackage().getName(),
+                                              event.getRule().getName() ) );
+    }
+    
+    public void afterFunctionRemoved(AfterFunctionRemovedEvent event) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    public void afterRuleBaseLocked(AfterRuleBaseLockedEvent event) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    public void afterRuleBaseUnlocked(AfterRuleBaseUnlockedEvent event) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    public void beforeFunctionRemoved(BeforeFunctionRemovedEvent event) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    public void beforeRuleBaseLocked(BeforeRuleBaseLockedEvent event) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    public void beforeRuleBaseUnlocked(BeforeRuleBaseUnlockedEvent event) {
+        // TODO Auto-generated method stub
+        
+    }        
+}

Modified: labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/DebugRuleFlowEventListener.java
===================================================================
--- labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/DebugRuleFlowEventListener.java	2010-07-26 18:14:07 UTC (rev 34205)
+++ labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/DebugRuleFlowEventListener.java	2010-07-26 20:05:42 UTC (rev 34206)
@@ -70,4 +70,11 @@
         System.err.println(event);
 	}
 
+    public void ruleFlowNodeExceptionOccurred(RuleFlowNodeExceptionOccurredEvent event,
+            WorkingMemory workingMemory) {
+        System.err.println(event);
+    }
+
+
+
 }

Modified: labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/DefaultRuleFlowEventListener.java
===================================================================
--- labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/DefaultRuleFlowEventListener.java	2010-07-26 18:14:07 UTC (rev 34205)
+++ labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/DefaultRuleFlowEventListener.java	2010-07-26 20:05:42 UTC (rev 34206)
@@ -66,4 +66,11 @@
         // intentionally left blank
 	}
 
+    public void ruleFlowNodeExceptionOccurred(RuleFlowNodeExceptionOccurredEvent event,
+            WorkingMemory workingMemory) {
+        // intentionally left blank
+    }
+
+
+
 }

Modified: labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/RuleFlowEventListener.java
===================================================================
--- labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/RuleFlowEventListener.java	2010-07-26 18:14:07 UTC (rev 34205)
+++ labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/RuleFlowEventListener.java	2010-07-26 20:05:42 UTC (rev 34206)
@@ -63,4 +63,7 @@
     void afterRuleFlowNodeLeft(RuleFlowNodeTriggeredEvent event,
     						   WorkingMemory workingMemory);
 
+    void ruleFlowNodeExceptionOccurred(RuleFlowNodeExceptionOccurredEvent event,
+                                WorkingMemory workingMemory);
+
 }
\ No newline at end of file

Modified: labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/RuleFlowEventListenerExtension.java
===================================================================
--- labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/RuleFlowEventListenerExtension.java	2010-07-26 18:14:07 UTC (rev 34205)
+++ labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/RuleFlowEventListenerExtension.java	2010-07-26 20:05:42 UTC (rev 34206)
@@ -18,7 +18,6 @@
 package org.drools.event;
 
 import org.drools.WorkingMemory;
-import org.drools.event.process.ProcessEventListener;
 
 /**
  *

Modified: labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/RuleFlowEventSupport.java
===================================================================
--- labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/RuleFlowEventSupport.java	2010-07-26 18:14:07 UTC (rev 34205)
+++ labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/RuleFlowEventSupport.java	2010-07-26 20:05:42 UTC (rev 34206)
@@ -228,6 +228,22 @@
         }
     }
 
+    public void fireRuleFlowNodeExceptionOccurred(final ProcessInstance processInstance, final NodeInstance nodeInstance,
+                                        Throwable error,
+                                        WorkingMemory workingMemory) {
+        final Iterator<RuleFlowEventListener> iter = getEventListenersIterator();
+
+        if (iter.hasNext()) {
+            final RuleFlowNodeExceptionOccurredEvent event = new RuleFlowNodeExceptionOccurredEvent(
+        		nodeInstance, error);
+
+            do{
+                RuleFlowEventListener listener = iter.next();
+                listener.ruleFlowNodeExceptionOccurred(event, workingMemory);
+            } while (iter.hasNext());
+        }
+    }
+
     public void reset() {
         this.clear();
     }

Added: labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/RuleFlowNodeExceptionOccurredEvent.java
===================================================================
--- labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/RuleFlowNodeExceptionOccurredEvent.java	                        (rev 0)
+++ labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/RuleFlowNodeExceptionOccurredEvent.java	2010-07-26 20:05:42 UTC (rev 34206)
@@ -0,0 +1,43 @@
+/*
+ *  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.
+ *  under the License.
+ */
+
+package org.drools.event;
+
+import org.drools.runtime.process.NodeInstance;
+import org.drools.runtime.process.ProcessInstance;
+
+/**
+ * @author esteban
+ */
+public class RuleFlowNodeExceptionOccurredEvent extends RuleFlowNodeTriggeredEvent {
+
+    private static final long serialVersionUID = 501L;
+    private final Throwable error;
+    
+    public RuleFlowNodeExceptionOccurredEvent(NodeInstance nodeInstance, Throwable error) {
+        super(nodeInstance);
+        this.error = error;
+    }
+
+    public Throwable getError() {
+        return error;
+    }
+
+    @Override
+    public String toString() {
+        return "==>[RuleFlowExceptionOccurredEvent(error=" + error +  "; processName=" + getProcessInstance().getProcessName() + "; processId=" + getProcessInstance().getProcessId() + ")]";
+    }
+
+}

Added: labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/process/impl/ProcessNodeExceptionOccurredEventImpl.java
===================================================================
--- labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/process/impl/ProcessNodeExceptionOccurredEventImpl.java	                        (rev 0)
+++ labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/event/process/impl/ProcessNodeExceptionOccurredEventImpl.java	2010-07-26 20:05:42 UTC (rev 34206)
@@ -0,0 +1,25 @@
+package org.drools.event.process.impl;
+
+import org.drools.WorkingMemory;
+import org.drools.event.RuleFlowNodeExceptionOccurredEvent;
+import org.drools.event.process.ProcessNodeExceptionOccurredEvent;
+
+public class ProcessNodeExceptionOccurredEventImpl extends ProcessNodeEventImpl implements ProcessNodeExceptionOccurredEvent {
+
+    private Throwable error;
+
+    public ProcessNodeExceptionOccurredEventImpl(RuleFlowNodeExceptionOccurredEvent event, WorkingMemory workingMemory) {
+        super(event, workingMemory);
+        this.error = event.getError();
+    }
+
+    public Throwable getError() {
+        return this.error;
+    }
+
+    @Override
+    public String toString() {
+            return "==>[ProcessNodeExceptionOccurredEventImpl: getNodeInstance()=" + getNodeInstance() + ", getProcessInstance()="
+                            + getProcessInstance() + ", getKnowledgeRuntime()=" + getKnowledgeRuntime() + ", getError()= "+ getError() +"]";
+    }
+}

Modified: labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/impl/StatefulKnowledgeSessionImpl.java
===================================================================
--- labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/impl/StatefulKnowledgeSessionImpl.java	2010-07-26 18:14:07 UTC (rev 34205)
+++ labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/impl/StatefulKnowledgeSessionImpl.java	2010-07-26 20:05:42 UTC (rev 34206)
@@ -1,899 +1,907 @@
-package org.drools.impl;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.drools.FactException;
-import org.drools.KnowledgeBase;
-import org.drools.RuleBase;
-import org.drools.WorkingMemory;
-import org.drools.command.Command;
-import org.drools.command.Context;
-import org.drools.command.impl.ContextImpl;
-import org.drools.command.impl.GenericCommand;
-import org.drools.command.impl.KnowledgeCommandContext;
-import org.drools.command.runtime.BatchExecutionCommand;
-import org.drools.common.AbstractWorkingMemory;
-import org.drools.common.InternalAgenda;
-import org.drools.common.InternalFactHandle;
-import org.drools.common.InternalWorkingMemory;
-import org.drools.common.InternalWorkingMemoryEntryPoint;
-import org.drools.common.ObjectStore;
-import org.drools.common.ObjectTypeConfigurationRegistry;
-import org.drools.event.ActivationCancelledEvent;
-import org.drools.event.ActivationCreatedEvent;
-import org.drools.event.AfterActivationFiredEvent;
-import org.drools.event.AgendaGroupPoppedEvent;
-import org.drools.event.AgendaGroupPushedEvent;
-import org.drools.event.BeforeActivationFiredEvent;
-import org.drools.event.ObjectInsertedEvent;
-import org.drools.event.ObjectRetractedEvent;
-import org.drools.event.ObjectUpdatedEvent;
-import org.drools.event.RuleFlowCompletedEvent;
-import org.drools.event.RuleFlowGroupActivatedEvent;
-import org.drools.event.RuleFlowGroupDeactivatedEvent;
-import org.drools.event.RuleFlowNodeTriggeredEvent;
-import org.drools.event.RuleFlowStartedEvent;
-import org.drools.event.process.ProcessEventListener;
-import org.drools.event.process.impl.ProcessCompletedEventImpl;
-import org.drools.event.process.impl.ProcessNodeLeftEventImpl;
-import org.drools.event.process.impl.ProcessNodeTriggeredEventImpl;
-import org.drools.event.process.impl.ProcessStartedEventImpl;
-import org.drools.event.rule.AgendaEventListener;
-import org.drools.event.rule.WorkingMemoryEventListener;
-import org.drools.event.rule.impl.ActivationCancelledEventImpl;
-import org.drools.event.rule.impl.ActivationCreatedEventImpl;
-import org.drools.event.rule.impl.AfterActivationFiredEventImpl;
-import org.drools.event.rule.impl.AgendaGroupPoppedEventImpl;
-import org.drools.event.rule.impl.AgendaGroupPushedEventImpl;
-import org.drools.event.rule.impl.BeforeActivationFiredEventImpl;
-import org.drools.event.rule.impl.ObjectInsertedEventImpl;
-import org.drools.event.rule.impl.ObjectRetractedEventImpl;
-import org.drools.event.rule.impl.ObjectUpdatedEventImpl;
-import org.drools.reteoo.ReteooWorkingMemory;
-import org.drools.rule.EntryPoint;
-import org.drools.rule.Rule;
-import org.drools.runtime.Calendars;
-import org.drools.runtime.Channel;
-import org.drools.runtime.Environment;
-import org.drools.runtime.ExecutionResults;
-import org.drools.runtime.ExitPoint;
-import org.drools.runtime.Globals;
-import org.drools.runtime.StatefulKnowledgeSession;
-import org.drools.runtime.impl.ExecutionResultImpl;
-import org.drools.runtime.process.ProcessInstance;
-import org.drools.runtime.process.WorkItemManager;
-import org.drools.runtime.rule.Agenda;
-import org.drools.runtime.rule.AgendaFilter;
-import org.drools.runtime.rule.FactHandle;
-import org.drools.runtime.rule.LiveQuery;
-import org.drools.runtime.rule.QueryResults;
-import org.drools.runtime.rule.ViewChangedEventListener;
-import org.drools.runtime.rule.WorkingMemoryEntryPoint;
-import org.drools.runtime.rule.impl.AgendaImpl;
-import org.drools.runtime.rule.impl.NativeQueryResults;
-import org.drools.spi.Activation;
-import org.drools.time.SessionClock;
-
-public class StatefulKnowledgeSessionImpl
-    implements
-    StatefulKnowledgeSession,
-    InternalWorkingMemoryEntryPoint {
-    public ReteooWorkingMemory session;
-    public KnowledgeBaseImpl   kbase;
-
-    public StatefulKnowledgeSessionImpl(ReteooWorkingMemory session) {
-        this( session,
-              new KnowledgeBaseImpl( session.getRuleBase() ) );
-    }
-
-    public StatefulKnowledgeSessionImpl(ReteooWorkingMemory session,
-                                        KnowledgeBase kbase) {
-        this.session = session;
-        this.session.setKnowledgeRuntime( this );
-        this.kbase = (KnowledgeBaseImpl) kbase;
-    }
-
-    public int getId() {
-        return this.session.getId();
-    }
-
-    public WorkingMemoryEntryPoint getWorkingMemoryEntryPoint(String name) {
-        return session.getWorkingMemoryEntryPoint( name );
-    }
-
-    public Collection< ? extends org.drools.runtime.rule.WorkingMemoryEntryPoint> getWorkingMemoryEntryPoints() {
-        return session.getWorkingMemoryEntryPoints();
-    }
-
-    public void addEventListener(WorkingMemoryEventListener listener) {
-        WorkingMemoryEventListenerWrapper wrapper = new WorkingMemoryEventListenerWrapper( listener );
-        this.session.addEventListener( wrapper );
-    }
-
-    public void removeEventListener(WorkingMemoryEventListener 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() {
-        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.session.addEventListener( wrapper );
-    }
-
-    public Collection<AgendaEventListener> getAgendaEventListeners() {
-        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 = 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.session.addEventListener( wrapper );
-    }
-
-    public Collection<ProcessEventListener> getProcessEventListeners() {
-        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 = null;
-        if ( listener != null && !(listener instanceof ProcessEventListenerWrapper) ) {
-            wrapper = new ProcessEventListenerWrapper( listener );
-        } else {
-            wrapper = (ProcessEventListenerWrapper) listener;
-        }
-        this.session.removeEventListener( wrapper );
-    }
-
-    public KnowledgeBase getKnowledgeBase() {
-        if ( this.kbase == null ) {
-            this.kbase = new KnowledgeBaseImpl( session.getRuleBase() );
-        }
-        return this.kbase;
-    }
-
-    public int fireAllRules() {
-        return this.session.fireAllRules();
-    }
-
-    public int fireAllRules(int max) {
-        return this.session.fireAllRules( max );
-    }
-
-    public int fireAllRules(AgendaFilter agendaFilter) {
-        return this.session.fireAllRules( new AgendaFilterWrapper( agendaFilter ) );
-    }
-
-    public void fireUntilHalt() {
-        this.session.fireUntilHalt();
-    }
-
-    public void fireUntilHalt(AgendaFilter agendaFilter) {
-        this.session.fireUntilHalt( new AgendaFilterWrapper( agendaFilter ) );
-    }
-
-    @SuppressWarnings("unchecked")
-    public <T extends SessionClock> T getSessionClock() {
-        return (T) this.session.getSessionClock();
-    }
-
-    public void halt() {
-        this.session.halt();
-    }
-
-    public void dispose() {
-        this.session.dispose();
-    }
-
-    public FactHandle insert(Object object) {
-        return this.session.insert( object );
-    }
-
-    public void retract(FactHandle factHandle) {
-        this.session.retract( factHandle );
-
-    }
-
-    public void update(FactHandle factHandle) {
-        this.session.update( factHandle,
-                             ((InternalFactHandle) factHandle).getObject() );
-    }
-
-    public void update(FactHandle factHandle,
-                       Object object) {
-        this.session.update( factHandle,
-                             object );
-    }
-
-    public FactHandle getFactHandle(Object object) {
-        return this.session.getFactHandle( object );
-    }
-
-    public Object getObject(FactHandle factHandle) {
-        return this.session.getObject( factHandle );
-    }
-
-    public ProcessInstance getProcessInstance(long id) {
-        return this.session.getProcessInstance( id );
-    }
-
-    public void abortProcessInstance(long id) {
-        org.drools.process.instance.ProcessInstance processInstance = this.session.getProcessInstance( id );
-        if ( processInstance == null ) {
-            throw new IllegalArgumentException( "Could not find process instance for id " + id );
-        }
-        processInstance.setState( ProcessInstance.STATE_ABORTED );
-    }
-
-    public Collection<ProcessInstance> getProcessInstances() {
-        List<ProcessInstance> result = new ArrayList<ProcessInstance>();
-        result.addAll( this.session.getProcessInstances() );
-        return result;
-    }
-
-    public WorkItemManager getWorkItemManager() {
-        return this.session.getWorkItemManager();
-    }
-
-    public ProcessInstance startProcess(String processId) {
-        return this.session.startProcess( processId );
-    }
-
-    public ProcessInstance startProcess(String processId,
-                                        Map<String, Object> parameters) {
-        return this.session.startProcess( processId,
-                                          parameters );
-    }
-
-    public void signalEvent(String type,
-                            Object event) {
-        this.session.getSignalManager().signalEvent( type,
-                                                     event );
-    }
-
-    public void signalEvent(String type,
-                            Object event,
-                            long processInstanceId) {
-        this.session.getProcessInstance( processInstanceId ).signalEvent( type,
-                                                                          event );
-    }
-
-    public void setGlobal(String identifier,
-                          Object object) {
-        this.session.setGlobal( identifier,
-                                object );
-    }
-
-    public Object getGlobal(String identifier) {
-        return this.session.getGlobal( identifier );
-    }
-
-    public Globals getGlobals() {
-        return (Globals) this.session.getGlobalResolver();
-    }
-
-    public Calendars getCalendars() {
-        return this.session.getCalendars();
-    }
-
-    public Environment getEnvironment() {
-        return this.session.getEnvironment();
-    }
-
-    //    public Future<Object> asyncInsert(Object object) {
-    //        return new FutureAdapter( this.session.asyncInsert( object ) );
-    //    }
-    //
-    //    public Future<Object> asyncInsert(Object[] array) {
-    //        return new FutureAdapter( this.session.asyncInsert( array ) );
-    //    }
-    //
-    //    public Future<Object> asyncInsert(Iterable< ? > iterable) {
-    //        return new FutureAdapter( this.session.asyncInsert( iterable ) );
-    //    }
-    //
-    //    public Future< ? > asyncFireAllRules() {
-    //        return new FutureAdapter( this.session.asyncFireAllRules() );
-    //    }
-
-    public <T extends org.drools.runtime.rule.FactHandle> Collection<T> getFactHandles() {
-        return new ObjectStoreWrapper( session.getObjectStore(),
-                                       null,
-                                       ObjectStoreWrapper.FACT_HANDLE );
-    }
-
-    public <T extends org.drools.runtime.rule.FactHandle> Collection<T> getFactHandles(org.drools.runtime.ObjectFilter filter) {
-        return new ObjectStoreWrapper( session.getObjectStore(),
-                                       filter,
-                                       ObjectStoreWrapper.FACT_HANDLE );
-    }
-
-    public Collection<Object> getObjects() {
-        return new ObjectStoreWrapper( session.getObjectStore(),
-                                       null,
-                                       ObjectStoreWrapper.OBJECT );
-    }
-
-    public Collection<Object> getObjects(org.drools.runtime.ObjectFilter filter) {
-        return new ObjectStoreWrapper( session.getObjectStore(),
-                                       filter,
-                                       ObjectStoreWrapper.OBJECT );
-    }
-
-    public void retract(org.drools.FactHandle factHandle,
-                        boolean removeLogical,
-                        boolean updateEqualsMap,
-                        Rule rule,
-                        Activation activation) throws FactException {
-        ((AbstractWorkingMemory) this.session).retract( factHandle,
-                                                        removeLogical,
-                                                        updateEqualsMap,
-                                                        rule,
-                                                        activation );
-    }
-
-    public void update(FactHandle factHandle,
-                       Object object,
-                       Rule rule,
-                       Activation activation) throws FactException {
-        ((AbstractWorkingMemory) this.session).update( (org.drools.FactHandle) factHandle,
-                                                       object,
-                                                       rule,
-                                                       activation );
-    }
-
-    public EntryPoint getEntryPoint() {
-        return session.getEntryPoint();
-    }
-
-    public InternalWorkingMemory getInternalWorkingMemory() {
-        return session;
-    }
-
-    public org.drools.FactHandle getFactHandleByIdentity(Object object) {
-        return session.getFactHandleByIdentity( object );
-    }
-
-    public static abstract class AbstractImmutableCollection
-        implements
-        Collection {
-
-        public boolean add(Object o) {
-            throw new UnsupportedOperationException( "This is an immmutable Collection" );
-        }
-
-        public boolean addAll(Collection c) {
-            throw new UnsupportedOperationException( "This is an immmutable Collection" );
-        }
-
-        public void clear() {
-            throw new UnsupportedOperationException( "This is an immmutable Collection" );
-        }
-
-        public boolean remove(Object o) {
-            throw new UnsupportedOperationException( "This is an immmutable Collection" );
-        }
-
-        public boolean removeAll(Collection c) {
-            throw new UnsupportedOperationException( "This is an immmutable Collection" );
-        }
-
-        public boolean retainAll(Collection c) {
-            throw new UnsupportedOperationException( "This is an immmutable Collection" );
-        }
-    }
-
-    public static class ObjectStoreWrapper extends AbstractImmutableCollection {
-        public ObjectStore                     store;
-        public org.drools.runtime.ObjectFilter filter;
-        public int                             type;           // 0 == object, 1 == facthandle
-        public static final int                OBJECT      = 0;
-        public static final int                FACT_HANDLE = 1;
-
-        public ObjectStoreWrapper(ObjectStore store,
-                                  org.drools.runtime.ObjectFilter filter,
-                                  int type) {
-            this.store = store;
-            this.filter = filter;
-            this.type = type;
-        }
-
-        public boolean contains(Object object) {
-            if ( object instanceof FactHandle ) {
-                return this.store.getObjectForHandle( (InternalFactHandle) object ) != null;
-            } else {
-                return this.store.getHandleForObject( object ) != null;
-            }
-        }
-
-        public boolean containsAll(Collection c) {
-            for ( Object object : c ) {
-                if ( !contains( object ) ) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        public boolean isEmpty() {
-            if ( this.filter == null ) {
-                return this.store.isEmpty();
-            }
-
-            return size() == 0;
-        }
-
-        public int size() {
-            if ( this.filter == null ) {
-                return this.store.size();
-            }
-
-            int i = 0;
-            for ( Iterator it = iterator(); it.hasNext(); ) {
-                it.next();
-                i++;
-            }
-
-            return i;
-        }
-
-        public Iterator< ? > iterator() {
-            Iterator it = null;
-            if ( type == OBJECT ) {
-                if ( filter != null ) {
-                    it = store.iterateObjects( filter );
-                } else {
-                    it = store.iterateObjects();
-                }
-            } else {
-                if ( filter != null ) {
-                    it = store.iterateFactHandles( filter );
-                } else {
-                    it = store.iterateFactHandles();
-                }
-            }
-            return it;
-        }
-
-        public Object[] toArray() {
-            return toArray( new Object[size()] );
-        }
-
-        public Object[] toArray(Object[] array) {
-            if ( array == null || array.length != size() ) {
-                array = new Object[size()];
-            }
-
-            int i = 0;
-            for ( Iterator it = iterator(); it.hasNext(); ) {
-                array[i++] = it.next();
-            }
-
-            return array;
-        }
-    }
-
-    public static class WorkingMemoryEventListenerWrapper
-        implements
-        org.drools.event.WorkingMemoryEventListener {
-        private final WorkingMemoryEventListener listener;
-
-        public WorkingMemoryEventListenerWrapper(WorkingMemoryEventListener listener) {
-            this.listener = listener;
-        }
-
-        public void objectInserted(ObjectInsertedEvent event) {
-            listener.objectInserted( new ObjectInsertedEventImpl( event ) );
-        }
-
-        public void objectRetracted(ObjectRetractedEvent event) {
-            listener.objectRetracted( new ObjectRetractedEventImpl( event ) );
-        }
-
-        public void objectUpdated(ObjectUpdatedEvent event) {
-            listener.objectUpdated( new ObjectUpdatedEventImpl( event ) );
-        }
-
-        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 final AgendaEventListener listener;
-
-        public AgendaEventListenerWrapper(AgendaEventListener listener) {
-            this.listener = listener;
-        }
-
-        public void activationCancelled(ActivationCancelledEvent event,
-                                        WorkingMemory workingMemory) {
-
-            listener.activationCancelled( new ActivationCancelledEventImpl( event.getActivation(),
-                                                                            ((InternalWorkingMemory) workingMemory).getKnowledgeRuntime(),
-                                                                            event.getCause() ) );
-
-        }
-
-        public void activationCreated(ActivationCreatedEvent event,
-                                      WorkingMemory workingMemory) {
-            listener.activationCreated( new ActivationCreatedEventImpl( event.getActivation(),
-                                                                        ((InternalWorkingMemory) workingMemory).getKnowledgeRuntime() ) );
-        }
-
-        public void beforeActivationFired(BeforeActivationFiredEvent event,
-                                          WorkingMemory workingMemory) {
-            listener.beforeActivationFired( new BeforeActivationFiredEventImpl( event.getActivation(),
-                                                                                ((InternalWorkingMemory) workingMemory).getKnowledgeRuntime() ) );
-        }
-
-        public void afterActivationFired(AfterActivationFiredEvent event,
-                                         WorkingMemory workingMemory) {
-            listener.afterActivationFired( new AfterActivationFiredEventImpl( event.getActivation(),
-                                                                              ((InternalWorkingMemory) workingMemory).getKnowledgeRuntime() ) );
-        }
-
-        public void agendaGroupPopped(AgendaGroupPoppedEvent event,
-                                      WorkingMemory workingMemory) {
-            listener.agendaGroupPopped( new AgendaGroupPoppedEventImpl( event.getAgendaGroup(),
-                                                                        ((InternalWorkingMemory) workingMemory).getKnowledgeRuntime() ) );
-        }
-
-        public void agendaGroupPushed(AgendaGroupPushedEvent event,
-                                      WorkingMemory workingMemory) {
-            listener.agendaGroupPushed( new AgendaGroupPushedEventImpl( event.getAgendaGroup(),
-                                                                        ((InternalWorkingMemory) workingMemory).getKnowledgeRuntime() ) );
-        }
-
-        public AgendaEventListener 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 AgendaEventListenerWrapper ) {
-                return this.listener.equals( ((AgendaEventListenerWrapper) obj).unWrap() );
-            }
-            return this.listener.equals( obj );
-        }
-    }
-
-    public static class ProcessEventListenerWrapper
-        implements
-        org.drools.event.RuleFlowEventListener {
-        private final ProcessEventListener listener;
-
-        public ProcessEventListenerWrapper(ProcessEventListener listener) {
-            this.listener = listener;
-        }
-
-        public void beforeRuleFlowCompleted(RuleFlowCompletedEvent event,
-                                            WorkingMemory workingMemory) {
-            listener.beforeProcessCompleted( new ProcessCompletedEventImpl( event,
-                                                                            workingMemory ) );
-        }
-
-        public void beforeRuleFlowGroupActivated(RuleFlowGroupActivatedEvent event,
-                                                 WorkingMemory workingMemory) {
-        }
-
-        public void beforeRuleFlowGroupDeactivated(RuleFlowGroupDeactivatedEvent event,
-                                                   WorkingMemory workingMemory) {
-        }
-
-        public void beforeRuleFlowNodeLeft(RuleFlowNodeTriggeredEvent event,
-                                           WorkingMemory workingMemory) {
-            listener.beforeNodeLeft( new ProcessNodeLeftEventImpl( event,
-                                                                   workingMemory ) );
-        }
-
-        public void beforeRuleFlowNodeTriggered(RuleFlowNodeTriggeredEvent event,
-                                                WorkingMemory workingMemory) {
-            listener.beforeNodeTriggered( new ProcessNodeTriggeredEventImpl( event,
-                                                                             workingMemory ) );
-        }
-
-        public void beforeRuleFlowStarted(RuleFlowStartedEvent event,
-                                          WorkingMemory workingMemory) {
-            listener.beforeProcessStarted( new ProcessStartedEventImpl( event,
-                                                                        workingMemory ) );
-        }
-
-        public void afterRuleFlowCompleted(RuleFlowCompletedEvent event,
-                                           WorkingMemory workingMemory) {
-            listener.afterProcessCompleted( new ProcessCompletedEventImpl( event,
-                                                                           workingMemory ) );
-        }
-
-        public void afterRuleFlowGroupActivated(RuleFlowGroupActivatedEvent event,
-                                                WorkingMemory workingMemory) {
-        }
-
-        public void afterRuleFlowGroupDeactivated(RuleFlowGroupDeactivatedEvent event,
-                                                  WorkingMemory workingMemory) {
-        }
-
-        public void afterRuleFlowNodeLeft(RuleFlowNodeTriggeredEvent event,
-                                          WorkingMemory workingMemory) {
-            listener.afterNodeLeft( new ProcessNodeLeftEventImpl( event,
-                                                                  workingMemory ) );
-        }
-
-        public void afterRuleFlowNodeTriggered(RuleFlowNodeTriggeredEvent event,
-                                               WorkingMemory workingMemory) {
-            listener.afterNodeTriggered( new ProcessNodeTriggeredEventImpl( event,
-                                                                            workingMemory ) );
-        }
-
-        public void afterRuleFlowStarted(RuleFlowStartedEvent event,
-                                         WorkingMemory workingMemory) {
-            listener.afterProcessStarted( new ProcessStartedEventImpl( event,
-                                                                       workingMemory ) );
-        }
-
-        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 );
-        }
-
-    }
-
-    public static class AgendaFilterWrapper
-        implements
-        org.drools.spi.AgendaFilter {
-        private AgendaFilter filter;
-
-        public AgendaFilterWrapper(AgendaFilter filter) {
-            this.filter = filter;
-        }
-
-        public boolean accept(Activation activation) {
-            return filter.accept( activation );
-        }
-    }
-
-    public Agenda getAgenda() {
-        return new AgendaImpl( (InternalAgenda) this.session.getAgenda() );
-    }
-
-    /**
-     * @deprecated Use {@link #registerChannel(String, Channel)} instead.
-     */
-    @Deprecated
-    public void registerExitPoint(String name,
-                                  ExitPoint exitPoint) {
-        this.session.registerExitPoint( name,
-                                        exitPoint );
-    }
-
-    /**
-     * @deprecated Use {@link #unregisterChannel(String)} instead.
-     */
-    @Deprecated
-    public void unregisterExitPoint(String name) {
-        this.session.unregisterExitPoint( name );
-    }
-
-    public void registerChannel(String name,
-                                Channel channel) {
-        this.session.registerChannel( name,
-                                      channel );
-    }
-
-    public void unregisterChannel(String name) {
-        this.session.unregisterChannel( name );
-    }
-
-    public Map<String, Channel> getChannels() {
-        return this.session.getChannels();
-    }
-
-    public ObjectTypeConfigurationRegistry getObjectTypeConfigurationRegistry() {
-        return this.session.getObjectTypeConfigurationRegistry();
-    }
-
-    public RuleBase getRuleBase() {
-        return this.kbase.ruleBase;
-    }
-
-    public QueryResults getQueryResults(String query) {
-        return new NativeQueryResults( this.session.getQueryResults( query ) );
-    }
-
-    public QueryResults getQueryResults(String query,
-                                        Object[] arguments) {
-        return new NativeQueryResults( this.session.getQueryResults( query,
-                                                                     arguments ) );
-    }
-
-    private KnowledgeCommandContext commandContext = new KnowledgeCommandContext( new ContextImpl( "ksession",
-                                                                                                   null ),
-                                                                                  null,
-                                                                                  this.kbase,
-                                                                                  this,
-                                                                                  null );
-
-    public <T> T execute(Command<T> command) {
-        return execute( null,
-                        command );
-    }
-
-    public <T> T execute(Context context,
-                         Command<T> command) {
-        if ( !( command instanceof BatchExecutionCommand ) ) {
-            return (T) ((GenericCommand) command).execute( new KnowledgeCommandContext( context,
-                                                                             null,
-                                                                             this.kbase,
-                                                                             this,
-                                                                             null ) ) ;            
-        }
-        
-        ExecutionResultImpl results = null;
-        if ( context != null ) {
-            results = (ExecutionResultImpl) ((KnowledgeCommandContext) context).getExecutionResults();
-        }
-
-        if ( results == null ) {
-            results = new ExecutionResultImpl();
-        }
-
-        try {
-            session.startBatchExecution( results );
-            ((GenericCommand) command).execute( new KnowledgeCommandContext( context,
-                                                                             null,
-                                                                             this.kbase,
-                                                                             this,
-                                                                             results ) );
-            ExecutionResults result = session.getExecutionResult();
-            return (T) result;
-        } finally {
-            session.endBatchExecution();
-        }
-    }
-
-    public String getEntryPointId() {
-        return this.session.getEntryPointId();
-    }
-
-    public long getFactCount() {
-        return this.session.getFactCount();
-    }
-
-    public LiveQuery openLiveQuery(String query,
-                                   Object[] arguments,
-                                   ViewChangedEventListener listener) {
-        return this.session.openLiveQuery( query,
-                                           arguments,
-                                           listener );
-    }
-
-}
+package org.drools.impl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.FactException;
+import org.drools.KnowledgeBase;
+import org.drools.RuleBase;
+import org.drools.WorkingMemory;
+import org.drools.command.Command;
+import org.drools.command.Context;
+import org.drools.command.impl.ContextImpl;
+import org.drools.command.impl.GenericCommand;
+import org.drools.command.impl.KnowledgeCommandContext;
+import org.drools.command.runtime.BatchExecutionCommand;
+import org.drools.common.AbstractWorkingMemory;
+import org.drools.common.InternalAgenda;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.InternalWorkingMemoryEntryPoint;
+import org.drools.common.ObjectStore;
+import org.drools.common.ObjectTypeConfigurationRegistry;
+import org.drools.event.ActivationCancelledEvent;
+import org.drools.event.ActivationCreatedEvent;
+import org.drools.event.AfterActivationFiredEvent;
+import org.drools.event.AgendaGroupPoppedEvent;
+import org.drools.event.AgendaGroupPushedEvent;
+import org.drools.event.BeforeActivationFiredEvent;
+import org.drools.event.ObjectInsertedEvent;
+import org.drools.event.ObjectRetractedEvent;
+import org.drools.event.ObjectUpdatedEvent;
+import org.drools.event.RuleFlowCompletedEvent;
+import org.drools.event.RuleFlowGroupActivatedEvent;
+import org.drools.event.RuleFlowGroupDeactivatedEvent;
+import org.drools.event.RuleFlowNodeExceptionOccurredEvent;
+import org.drools.event.RuleFlowNodeTriggeredEvent;
+import org.drools.event.RuleFlowStartedEvent;
+import org.drools.event.RuleFlowVariableChangeEvent;
+import org.drools.event.process.ProcessEventListener;
+import org.drools.event.process.impl.ProcessCompletedEventImpl;
+import org.drools.event.process.impl.ProcessNodeExceptionOccurredEventImpl;
+import org.drools.event.process.impl.ProcessNodeLeftEventImpl;
+import org.drools.event.process.impl.ProcessNodeTriggeredEventImpl;
+import org.drools.event.process.impl.ProcessStartedEventImpl;
+import org.drools.event.rule.AgendaEventListener;
+import org.drools.event.rule.WorkingMemoryEventListener;
+import org.drools.event.rule.impl.ActivationCancelledEventImpl;
+import org.drools.event.rule.impl.ActivationCreatedEventImpl;
+import org.drools.event.rule.impl.AfterActivationFiredEventImpl;
+import org.drools.event.rule.impl.AgendaGroupPoppedEventImpl;
+import org.drools.event.rule.impl.AgendaGroupPushedEventImpl;
+import org.drools.event.rule.impl.BeforeActivationFiredEventImpl;
+import org.drools.event.rule.impl.ObjectInsertedEventImpl;
+import org.drools.event.rule.impl.ObjectRetractedEventImpl;
+import org.drools.event.rule.impl.ObjectUpdatedEventImpl;
+import org.drools.reteoo.ReteooWorkingMemory;
+import org.drools.rule.EntryPoint;
+import org.drools.rule.Rule;
+import org.drools.runtime.Calendars;
+import org.drools.runtime.Channel;
+import org.drools.runtime.Environment;
+import org.drools.runtime.ExecutionResults;
+import org.drools.runtime.ExitPoint;
+import org.drools.runtime.Globals;
+import org.drools.runtime.StatefulKnowledgeSession;
+import org.drools.runtime.impl.ExecutionResultImpl;
+import org.drools.runtime.process.ProcessInstance;
+import org.drools.runtime.process.WorkItemManager;
+import org.drools.runtime.rule.Agenda;
+import org.drools.runtime.rule.AgendaFilter;
+import org.drools.runtime.rule.FactHandle;
+import org.drools.runtime.rule.LiveQuery;
+import org.drools.runtime.rule.QueryResults;
+import org.drools.runtime.rule.ViewChangedEventListener;
+import org.drools.runtime.rule.WorkingMemoryEntryPoint;
+import org.drools.runtime.rule.impl.AgendaImpl;
+import org.drools.runtime.rule.impl.NativeQueryResults;
+import org.drools.spi.Activation;
+import org.drools.time.SessionClock;
+
+public class StatefulKnowledgeSessionImpl
+    implements
+    StatefulKnowledgeSession,
+    InternalWorkingMemoryEntryPoint {
+    public ReteooWorkingMemory session;
+    public KnowledgeBaseImpl   kbase;
+
+    public StatefulKnowledgeSessionImpl(ReteooWorkingMemory session) {
+        this( session,
+              new KnowledgeBaseImpl( session.getRuleBase() ) );
+    }
+
+    public StatefulKnowledgeSessionImpl(ReteooWorkingMemory session,
+                                        KnowledgeBase kbase) {
+        this.session = session;
+        this.session.setKnowledgeRuntime( this );
+        this.kbase = (KnowledgeBaseImpl) kbase;
+    }
+
+    public int getId() {
+        return this.session.getId();
+    }
+
+    public WorkingMemoryEntryPoint getWorkingMemoryEntryPoint(String name) {
+        return session.getWorkingMemoryEntryPoint( name );
+    }
+
+    public Collection< ? extends org.drools.runtime.rule.WorkingMemoryEntryPoint> getWorkingMemoryEntryPoints() {
+        return session.getWorkingMemoryEntryPoints();
+    }
+
+    public void addEventListener(WorkingMemoryEventListener listener) {
+        WorkingMemoryEventListenerWrapper wrapper = new WorkingMemoryEventListenerWrapper( listener );
+        this.session.addEventListener( wrapper );
+    }
+
+    public void removeEventListener(WorkingMemoryEventListener 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() {
+        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.session.addEventListener( wrapper );
+    }
+
+    public Collection<AgendaEventListener> getAgendaEventListeners() {
+        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 = 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.session.addEventListener( wrapper );
+    }
+
+    public Collection<ProcessEventListener> getProcessEventListeners() {
+        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 = null;
+        if ( listener != null && !(listener instanceof ProcessEventListenerWrapper) ) {
+            wrapper = new ProcessEventListenerWrapper( listener );
+        } else {
+            wrapper = (ProcessEventListenerWrapper) listener;
+        }
+        this.session.removeEventListener( wrapper );
+    }
+
+    public KnowledgeBase getKnowledgeBase() {
+        if ( this.kbase == null ) {
+            this.kbase = new KnowledgeBaseImpl( session.getRuleBase() );
+        }
+        return this.kbase;
+    }
+
+    public int fireAllRules() {
+        return this.session.fireAllRules();
+    }
+
+    public int fireAllRules(int max) {
+        return this.session.fireAllRules( max );
+    }
+
+    public int fireAllRules(AgendaFilter agendaFilter) {
+        return this.session.fireAllRules( new AgendaFilterWrapper( agendaFilter ) );
+    }
+
+    public void fireUntilHalt() {
+        this.session.fireUntilHalt();
+    }
+
+    public void fireUntilHalt(AgendaFilter agendaFilter) {
+        this.session.fireUntilHalt( new AgendaFilterWrapper( agendaFilter ) );
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T extends SessionClock> T getSessionClock() {
+        return (T) this.session.getSessionClock();
+    }
+
+    public void halt() {
+        this.session.halt();
+    }
+
+    public void dispose() {
+        this.session.dispose();
+    }
+
+    public FactHandle insert(Object object) {
+        return this.session.insert( object );
+    }
+
+    public void retract(FactHandle factHandle) {
+        this.session.retract( factHandle );
+
+    }
+
+    public void update(FactHandle factHandle) {
+        this.session.update( factHandle,
+                             ((InternalFactHandle) factHandle).getObject() );
+    }
+
+    public void update(FactHandle factHandle,
+                       Object object) {
+        this.session.update( factHandle,
+                             object );
+    }
+
+    public FactHandle getFactHandle(Object object) {
+        return this.session.getFactHandle( object );
+    }
+
+    public Object getObject(FactHandle factHandle) {
+        return this.session.getObject( factHandle );
+    }
+
+    public ProcessInstance getProcessInstance(long id) {
+        return this.session.getProcessInstance( id );
+    }
+
+    public void abortProcessInstance(long id) {
+        org.drools.process.instance.ProcessInstance processInstance = this.session.getProcessInstance( id );
+        if ( processInstance == null ) {
+            throw new IllegalArgumentException( "Could not find process instance for id " + id );
+        }
+        processInstance.setState( ProcessInstance.STATE_ABORTED );
+    }
+
+    public Collection<ProcessInstance> getProcessInstances() {
+        List<ProcessInstance> result = new ArrayList<ProcessInstance>();
+        result.addAll( this.session.getProcessInstances() );
+        return result;
+    }
+
+    public WorkItemManager getWorkItemManager() {
+        return this.session.getWorkItemManager();
+    }
+
+    public ProcessInstance startProcess(String processId) {
+        return this.session.startProcess( processId );
+    }
+
+    public ProcessInstance startProcess(String processId,
+                                        Map<String, Object> parameters) {
+        return this.session.startProcess( processId,
+                                          parameters );
+    }
+
+    public void signalEvent(String type,
+                            Object event) {
+        this.session.getSignalManager().signalEvent( type,
+                                                     event );
+    }
+
+    public void signalEvent(String type,
+                            Object event,
+                            long processInstanceId) {
+        this.session.getProcessInstance( processInstanceId ).signalEvent( type,
+                                                                          event );
+    }
+
+    public void setGlobal(String identifier,
+                          Object object) {
+        this.session.setGlobal( identifier,
+                                object );
+    }
+
+    public Object getGlobal(String identifier) {
+        return this.session.getGlobal( identifier );
+    }
+
+    public Globals getGlobals() {
+        return (Globals) this.session.getGlobalResolver();
+    }
+
+    public Calendars getCalendars() {
+        return this.session.getCalendars();
+    }
+
+    public Environment getEnvironment() {
+        return this.session.getEnvironment();
+    }
+
+    //    public Future<Object> asyncInsert(Object object) {
+    //        return new FutureAdapter( this.session.asyncInsert( object ) );
+    //    }
+    //
+    //    public Future<Object> asyncInsert(Object[] array) {
+    //        return new FutureAdapter( this.session.asyncInsert( array ) );
+    //    }
+    //
+    //    public Future<Object> asyncInsert(Iterable< ? > iterable) {
+    //        return new FutureAdapter( this.session.asyncInsert( iterable ) );
+    //    }
+    //
+    //    public Future< ? > asyncFireAllRules() {
+    //        return new FutureAdapter( this.session.asyncFireAllRules() );
+    //    }
+
+    public <T extends org.drools.runtime.rule.FactHandle> Collection<T> getFactHandles() {
+        return new ObjectStoreWrapper( session.getObjectStore(),
+                                       null,
+                                       ObjectStoreWrapper.FACT_HANDLE );
+    }
+
+    public <T extends org.drools.runtime.rule.FactHandle> Collection<T> getFactHandles(org.drools.runtime.ObjectFilter filter) {
+        return new ObjectStoreWrapper( session.getObjectStore(),
+                                       filter,
+                                       ObjectStoreWrapper.FACT_HANDLE );
+    }
+
+    public Collection<Object> getObjects() {
+        return new ObjectStoreWrapper( session.getObjectStore(),
+                                       null,
+                                       ObjectStoreWrapper.OBJECT );
+    }
+
+    public Collection<Object> getObjects(org.drools.runtime.ObjectFilter filter) {
+        return new ObjectStoreWrapper( session.getObjectStore(),
+                                       filter,
+                                       ObjectStoreWrapper.OBJECT );
+    }
+
+    public void retract(org.drools.FactHandle factHandle,
+                        boolean removeLogical,
+                        boolean updateEqualsMap,
+                        Rule rule,
+                        Activation activation) throws FactException {
+        ((AbstractWorkingMemory) this.session).retract( factHandle,
+                                                        removeLogical,
+                                                        updateEqualsMap,
+                                                        rule,
+                                                        activation );
+    }
+
+    public void update(FactHandle factHandle,
+                       Object object,
+                       Rule rule,
+                       Activation activation) throws FactException {
+        ((AbstractWorkingMemory) this.session).update( (org.drools.FactHandle) factHandle,
+                                                       object,
+                                                       rule,
+                                                       activation );
+    }
+
+    public EntryPoint getEntryPoint() {
+        return session.getEntryPoint();
+    }
+
+    public InternalWorkingMemory getInternalWorkingMemory() {
+        return session;
+    }
+
+    public org.drools.FactHandle getFactHandleByIdentity(Object object) {
+        return session.getFactHandleByIdentity( object );
+    }
+
+    public static abstract class AbstractImmutableCollection
+        implements
+        Collection {
+
+        public boolean add(Object o) {
+            throw new UnsupportedOperationException( "This is an immmutable Collection" );
+        }
+
+        public boolean addAll(Collection c) {
+            throw new UnsupportedOperationException( "This is an immmutable Collection" );
+        }
+
+        public void clear() {
+            throw new UnsupportedOperationException( "This is an immmutable Collection" );
+        }
+
+        public boolean remove(Object o) {
+            throw new UnsupportedOperationException( "This is an immmutable Collection" );
+        }
+
+        public boolean removeAll(Collection c) {
+            throw new UnsupportedOperationException( "This is an immmutable Collection" );
+        }
+
+        public boolean retainAll(Collection c) {
+            throw new UnsupportedOperationException( "This is an immmutable Collection" );
+        }
+    }
+
+    public static class ObjectStoreWrapper extends AbstractImmutableCollection {
+        public ObjectStore                     store;
+        public org.drools.runtime.ObjectFilter filter;
+        public int                             type;           // 0 == object, 1 == facthandle
+        public static final int                OBJECT      = 0;
+        public static final int                FACT_HANDLE = 1;
+
+        public ObjectStoreWrapper(ObjectStore store,
+                                  org.drools.runtime.ObjectFilter filter,
+                                  int type) {
+            this.store = store;
+            this.filter = filter;
+            this.type = type;
+        }
+
+        public boolean contains(Object object) {
+            if ( object instanceof FactHandle ) {
+                return this.store.getObjectForHandle( (InternalFactHandle) object ) != null;
+            } else {
+                return this.store.getHandleForObject( object ) != null;
+            }
+        }
+
+        public boolean containsAll(Collection c) {
+            for ( Object object : c ) {
+                if ( !contains( object ) ) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        public boolean isEmpty() {
+            if ( this.filter == null ) {
+                return this.store.isEmpty();
+            }
+
+            return size() == 0;
+        }
+
+        public int size() {
+            if ( this.filter == null ) {
+                return this.store.size();
+            }
+
+            int i = 0;
+            for ( Iterator it = iterator(); it.hasNext(); ) {
+                it.next();
+                i++;
+            }
+
+            return i;
+        }
+
+        public Iterator< ? > iterator() {
+            Iterator it = null;
+            if ( type == OBJECT ) {
+                if ( filter != null ) {
+                    it = store.iterateObjects( filter );
+                } else {
+                    it = store.iterateObjects();
+                }
+            } else {
+                if ( filter != null ) {
+                    it = store.iterateFactHandles( filter );
+                } else {
+                    it = store.iterateFactHandles();
+                }
+            }
+            return it;
+        }
+
+        public Object[] toArray() {
+            return toArray( new Object[size()] );
+        }
+
+        public Object[] toArray(Object[] array) {
+            if ( array == null || array.length != size() ) {
+                array = new Object[size()];
+            }
+
+            int i = 0;
+            for ( Iterator it = iterator(); it.hasNext(); ) {
+                array[i++] = it.next();
+            }
+
+            return array;
+        }
+    }
+
+    public static class WorkingMemoryEventListenerWrapper
+        implements
+        org.drools.event.WorkingMemoryEventListener {
+        private final WorkingMemoryEventListener listener;
+
+        public WorkingMemoryEventListenerWrapper(WorkingMemoryEventListener listener) {
+            this.listener = listener;
+        }
+
+        public void objectInserted(ObjectInsertedEvent event) {
+            listener.objectInserted( new ObjectInsertedEventImpl( event ) );
+        }
+
+        public void objectRetracted(ObjectRetractedEvent event) {
+            listener.objectRetracted( new ObjectRetractedEventImpl( event ) );
+        }
+
+        public void objectUpdated(ObjectUpdatedEvent event) {
+            listener.objectUpdated( new ObjectUpdatedEventImpl( event ) );
+        }
+
+        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 final AgendaEventListener listener;
+
+        public AgendaEventListenerWrapper(AgendaEventListener listener) {
+            this.listener = listener;
+        }
+
+        public void activationCancelled(ActivationCancelledEvent event,
+                                        WorkingMemory workingMemory) {
+
+            listener.activationCancelled( new ActivationCancelledEventImpl( event.getActivation(),
+                                                                            ((InternalWorkingMemory) workingMemory).getKnowledgeRuntime(),
+                                                                            event.getCause() ) );
+
+        }
+
+        public void activationCreated(ActivationCreatedEvent event,
+                                      WorkingMemory workingMemory) {
+            listener.activationCreated( new ActivationCreatedEventImpl( event.getActivation(),
+                                                                        ((InternalWorkingMemory) workingMemory).getKnowledgeRuntime() ) );
+        }
+
+        public void beforeActivationFired(BeforeActivationFiredEvent event,
+                                          WorkingMemory workingMemory) {
+            listener.beforeActivationFired( new BeforeActivationFiredEventImpl( event.getActivation(),
+                                                                                ((InternalWorkingMemory) workingMemory).getKnowledgeRuntime() ) );
+        }
+
+        public void afterActivationFired(AfterActivationFiredEvent event,
+                                         WorkingMemory workingMemory) {
+            listener.afterActivationFired( new AfterActivationFiredEventImpl( event.getActivation(),
+                                                                              ((InternalWorkingMemory) workingMemory).getKnowledgeRuntime() ) );
+        }
+
+        public void agendaGroupPopped(AgendaGroupPoppedEvent event,
+                                      WorkingMemory workingMemory) {
+            listener.agendaGroupPopped( new AgendaGroupPoppedEventImpl( event.getAgendaGroup(),
+                                                                        ((InternalWorkingMemory) workingMemory).getKnowledgeRuntime() ) );
+        }
+
+        public void agendaGroupPushed(AgendaGroupPushedEvent event,
+                                      WorkingMemory workingMemory) {
+            listener.agendaGroupPushed( new AgendaGroupPushedEventImpl( event.getAgendaGroup(),
+                                                                        ((InternalWorkingMemory) workingMemory).getKnowledgeRuntime() ) );
+        }
+
+        public AgendaEventListener 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 AgendaEventListenerWrapper ) {
+                return this.listener.equals( ((AgendaEventListenerWrapper) obj).unWrap() );
+            }
+            return this.listener.equals( obj );
+        }
+    }
+
+    public static class ProcessEventListenerWrapper
+        implements
+        org.drools.event.RuleFlowEventListener {
+        private final ProcessEventListener listener;
+
+        public ProcessEventListenerWrapper(ProcessEventListener listener) {
+            this.listener = listener;
+        }
+
+        public void beforeRuleFlowCompleted(RuleFlowCompletedEvent event,
+                                            WorkingMemory workingMemory) {
+            listener.beforeProcessCompleted( new ProcessCompletedEventImpl( event,
+                                                                            workingMemory ) );
+        }
+
+        public void beforeRuleFlowGroupActivated(RuleFlowGroupActivatedEvent event,
+                                                 WorkingMemory workingMemory) {
+        }
+
+        public void beforeRuleFlowGroupDeactivated(RuleFlowGroupDeactivatedEvent event,
+                                                   WorkingMemory workingMemory) {
+        }
+
+        public void beforeRuleFlowNodeLeft(RuleFlowNodeTriggeredEvent event,
+                                           WorkingMemory workingMemory) {
+            listener.beforeNodeLeft( new ProcessNodeLeftEventImpl( event,
+                                                                   workingMemory ) );
+        }
+
+        public void beforeRuleFlowNodeTriggered(RuleFlowNodeTriggeredEvent event,
+                                                WorkingMemory workingMemory) {
+            listener.beforeNodeTriggered( new ProcessNodeTriggeredEventImpl( event,
+                                                                             workingMemory ) );
+        }
+
+        public void beforeRuleFlowStarted(RuleFlowStartedEvent event,
+                                          WorkingMemory workingMemory) {
+            listener.beforeProcessStarted( new ProcessStartedEventImpl( event,
+                                                                        workingMemory ) );
+        }
+
+        public void afterRuleFlowCompleted(RuleFlowCompletedEvent event,
+                                           WorkingMemory workingMemory) {
+            listener.afterProcessCompleted( new ProcessCompletedEventImpl( event,
+                                                                           workingMemory ) );
+        }
+
+        public void afterRuleFlowGroupActivated(RuleFlowGroupActivatedEvent event,
+                                                WorkingMemory workingMemory) {
+        }
+
+        public void afterRuleFlowGroupDeactivated(RuleFlowGroupDeactivatedEvent event,
+                                                  WorkingMemory workingMemory) {
+        }
+
+        public void afterRuleFlowNodeLeft(RuleFlowNodeTriggeredEvent event,
+                                          WorkingMemory workingMemory) {
+            listener.afterNodeLeft( new ProcessNodeLeftEventImpl( event,
+                                                                  workingMemory ) );
+        }
+
+        public void afterRuleFlowNodeTriggered(RuleFlowNodeTriggeredEvent event,
+                                               WorkingMemory workingMemory) {
+            listener.afterNodeTriggered( new ProcessNodeTriggeredEventImpl( event,
+                                                                            workingMemory ) );
+        }
+
+        public void afterRuleFlowStarted(RuleFlowStartedEvent event,
+                                         WorkingMemory workingMemory) {
+            listener.afterProcessStarted( new ProcessStartedEventImpl( event,
+                                                                       workingMemory ) );
+        }
+
+        public void ruleFlowNodeExceptionOccurred(RuleFlowNodeExceptionOccurredEvent event,
+                WorkingMemory workingMemory) {
+            listener.onNodeException(new ProcessNodeExceptionOccurredEventImpl(event, workingMemory));
+        }
+
+        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 );
+        }
+
+    }
+
+    public static class AgendaFilterWrapper
+        implements
+        org.drools.spi.AgendaFilter {
+        private AgendaFilter filter;
+
+        public AgendaFilterWrapper(AgendaFilter filter) {
+            this.filter = filter;
+        }
+
+        public boolean accept(Activation activation) {
+            return filter.accept( activation );
+        }
+    }
+
+    public Agenda getAgenda() {
+        return new AgendaImpl( (InternalAgenda) this.session.getAgenda() );
+    }
+
+    /**
+     * @deprecated Use {@link #registerChannel(String, Channel)} instead.
+     */
+    @Deprecated
+    public void registerExitPoint(String name,
+                                  ExitPoint exitPoint) {
+        this.session.registerExitPoint( name,
+                                        exitPoint );
+    }
+
+    /**
+     * @deprecated Use {@link #unregisterChannel(String)} instead.
+     */
+    @Deprecated
+    public void unregisterExitPoint(String name) {
+        this.session.unregisterExitPoint( name );
+    }
+
+    public void registerChannel(String name,
+                                Channel channel) {
+        this.session.registerChannel( name,
+                                      channel );
+    }
+
+    public void unregisterChannel(String name) {
+        this.session.unregisterChannel( name );
+    }
+
+    public Map<String, Channel> getChannels() {
+        return this.session.getChannels();
+    }
+
+    public ObjectTypeConfigurationRegistry getObjectTypeConfigurationRegistry() {
+        return this.session.getObjectTypeConfigurationRegistry();
+    }
+
+    public RuleBase getRuleBase() {
+        return this.kbase.ruleBase;
+    }
+
+    public QueryResults getQueryResults(String query) {
+        return new NativeQueryResults( this.session.getQueryResults( query ) );
+    }
+
+    public QueryResults getQueryResults(String query,
+                                        Object[] arguments) {
+        return new NativeQueryResults( this.session.getQueryResults( query,
+                                                                     arguments ) );
+    }
+
+    private KnowledgeCommandContext commandContext = new KnowledgeCommandContext( new ContextImpl( "ksession",
+                                                                                                   null ),
+                                                                                  null,
+                                                                                  this.kbase,
+                                                                                  this,
+                                                                                  null );
+
+    public <T> T execute(Command<T> command) {
+        return execute( null,
+                        command );
+    }
+
+    public <T> T execute(Context context,
+                         Command<T> command) {
+        if ( !( command instanceof BatchExecutionCommand ) ) {
+            return (T) ((GenericCommand) command).execute( new KnowledgeCommandContext( context,
+                                                                             null,
+                                                                             this.kbase,
+                                                                             this,
+                                                                             null ) ) ;            
+        }
+        
+        ExecutionResultImpl results = null;
+        if ( context != null ) {
+            results = (ExecutionResultImpl) ((KnowledgeCommandContext) context).getExecutionResults();
+        }
+
+        if ( results == null ) {
+            results = new ExecutionResultImpl();
+        }
+
+        try {
+            session.startBatchExecution( results );
+            ((GenericCommand) command).execute( new KnowledgeCommandContext( context,
+                                                                             null,
+                                                                             this.kbase,
+                                                                             this,
+                                                                             results ) );
+            ExecutionResults result = session.getExecutionResult();
+            return (T) result;
+        } finally {
+            session.endBatchExecution();
+        }
+    }
+
+    public String getEntryPointId() {
+        return this.session.getEntryPointId();
+    }
+
+    public long getFactCount() {
+        return this.session.getFactCount();
+    }
+
+    public LiveQuery openLiveQuery(String query,
+                                   Object[] arguments,
+                                   ViewChangedEventListener listener) {
+        return this.session.openLiveQuery( query,
+                                           arguments,
+                                           listener );
+    }
+
+}

Modified: labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/management/KnowledgeSessionMonitoring.java
===================================================================
--- labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/management/KnowledgeSessionMonitoring.java	2010-07-26 18:14:07 UTC (rev 34205)
+++ labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/management/KnowledgeSessionMonitoring.java	2010-07-26 20:05:42 UTC (rev 34206)
@@ -39,6 +39,7 @@
 import org.drools.event.RuleFlowEventListener;
 import org.drools.event.RuleFlowGroupActivatedEvent;
 import org.drools.event.RuleFlowGroupDeactivatedEvent;
+import org.drools.event.RuleFlowNodeExceptionOccurredEvent;
 import org.drools.event.RuleFlowNodeTriggeredEvent;
 import org.drools.event.RuleFlowStartedEvent;
 import org.drools.management.KnowledgeSessionMonitoring.AgendaStats.AgendaStatsData;
@@ -439,8 +440,13 @@
 
 		public void beforeRuleFlowStarted(RuleFlowStartedEvent event, WorkingMemory workingMemory) {
 			// Do nothing
-		}    
+		}
 
+                public void ruleFlowNodeExceptionOccurred(RuleFlowNodeExceptionOccurredEvent event, WorkingMemory workingMemory) {
+                    // Do nothing
+                }
+
+
         public static class GlobalProcessStatsData {
         	
             public AtomicLong processInstancesStarted;

Added: labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/workflow/instance/impl/ManagedRuntimeException.java
===================================================================
--- labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/workflow/instance/impl/ManagedRuntimeException.java	                        (rev 0)
+++ labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/workflow/instance/impl/ManagedRuntimeException.java	2010-07-26 20:05:42 UTC (rev 34206)
@@ -0,0 +1,14 @@
+package org.drools.workflow.instance.impl;
+
+/**
+ * Wrapper of a RuntimeException. This exception means that the original
+ * RuntieException was already managed.
+ * @author esteban
+ */
+public class ManagedRuntimeException extends RuntimeException{
+
+    public ManagedRuntimeException(Throwable cause) {
+        super(cause);
+    }
+
+}

Modified: labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/workflow/instance/impl/NodeInstanceImpl.java
===================================================================
--- labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/workflow/instance/impl/NodeInstanceImpl.java	2010-07-26 18:14:07 UTC (rev 34205)
+++ labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/main/java/org/drools/workflow/instance/impl/NodeInstanceImpl.java	2010-07-26 20:05:42 UTC (rev 34206)
@@ -1,245 +1,246 @@
-package org.drools.workflow.instance.impl;
-
-/*
- * Copyright 2005 JBoss Inc
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.drools.WorkingMemory;
-import org.drools.common.EventSupport;
-import org.drools.common.InternalWorkingMemory;
-import org.drools.definition.process.Connection;
-import org.drools.definition.process.Node;
-import org.drools.process.core.Context;
-import org.drools.process.core.ContextContainer;
-import org.drools.process.core.context.exclusive.ExclusiveGroup;
-import org.drools.process.instance.ContextInstance;
-import org.drools.process.instance.ContextInstanceContainer;
-import org.drools.process.instance.ProcessInstance;
-import org.drools.process.instance.context.exclusive.ExclusiveGroupInstance;
-import org.drools.runtime.process.NodeInstance;
-import org.drools.runtime.process.NodeInstanceContainer;
-import org.drools.workflow.core.impl.NodeImpl;
-import org.drools.workflow.instance.WorkflowProcessInstance;
-import org.drools.workflow.instance.node.CompositeNodeInstance;
-
-/**
- * Default implementation of a RuleFlow node instance.
- * 
- * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
- */
-public abstract class NodeInstanceImpl implements org.drools.workflow.instance.NodeInstance, Serializable {
-
-	private static final long serialVersionUID = 4L;
-	
-	private long id;
-    private long nodeId;
-    private WorkflowProcessInstance processInstance;
-    private org.drools.workflow.instance.NodeInstanceContainer nodeInstanceContainer;
-
-    public void setId(final long id) {
-        this.id = id;
-    }
-
-    public long getId() {
-        return this.id;
-    }
-
-    public void setNodeId(final long nodeId) {
-        this.nodeId = nodeId;
-    }
-
-    public long getNodeId() {
-        return this.nodeId;
-    }
-    
-    public String getNodeName() {
-    	Node node = getNode();
-    	return node == null ? "" : node.getName();
-    }
-
-    public void setProcessInstance(final WorkflowProcessInstance processInstance) {
-        this.processInstance = processInstance;
-    }
-
-    public WorkflowProcessInstance getProcessInstance() {
-        return this.processInstance;
-    }
-
-    public NodeInstanceContainer getNodeInstanceContainer() {
-        return this.nodeInstanceContainer;
-    }
-    
-    public void setNodeInstanceContainer(NodeInstanceContainer nodeInstanceContainer) {
-        this.nodeInstanceContainer = (org.drools.workflow.instance.NodeInstanceContainer) nodeInstanceContainer;
-        if (nodeInstanceContainer != null) {
-            this.nodeInstanceContainer.addNodeInstance(this);
-        }
-    }
-
-    public Node getNode() {
-        return ((org.drools.workflow.core.NodeContainer)
-    		this.nodeInstanceContainer.getNodeContainer()).internalGetNode( this.nodeId );
-    }
-    
-    public boolean isInversionOfControl() {
-        return false;
-    }
-    
-    public void cancel() {
-        nodeInstanceContainer.removeNodeInstance(this);
-    }
-    
-    public final void trigger(NodeInstance from, String type) {
-    	boolean hidden = false;
-    	if (getNode().getMetaData("hidden") != null) {
-    		hidden = true;
-    	}
-    	WorkingMemory workingMemory = ((ProcessInstance) getProcessInstance()).getWorkingMemory();
-    	if (!hidden) {
-    		((EventSupport) workingMemory).getRuleFlowEventSupport().fireBeforeRuleFlowNodeTriggered(this, (InternalWorkingMemory) workingMemory);
-    	}
-        internalTrigger(from, type);
-        if (!hidden) {
-            ((EventSupport) workingMemory).getRuleFlowEventSupport().fireAfterRuleFlowNodeTriggered(this, (InternalWorkingMemory) workingMemory);
-        }
-    }
-    
-    public abstract void internalTrigger(NodeInstance from, String type);
-    
-    protected void triggerCompleted(String type, boolean remove) {
-        if (remove) {
-            ((org.drools.workflow.instance.NodeInstanceContainer) getNodeInstanceContainer())
-            	.removeNodeInstance(this);
-        }
-        Node node = getNode();
-        List<Connection> connections = null;
-        if (node != null) {
-        	connections = node.getOutgoingConnections(type);
-        }
-        if (connections == null || connections.isEmpty()) {
-        	((org.drools.workflow.instance.NodeInstanceContainer) getNodeInstanceContainer())
-        		.nodeInstanceCompleted(this, type);
-        } else {
-	        for (Connection connection: connections) {
-	        	// stop if this process instance has been aborted / completed
-	        	if (getProcessInstance().getState() != ProcessInstance.STATE_ACTIVE) {
-	        		return;
-	        	}
-	    		triggerConnection(connection);
-	        }
-        }
-    }
-    
-    protected void triggerConnection(Connection connection) {
-    	boolean hidden = false;
-    	if (getNode().getMetaData("hidden") != null) {
-    		hidden = true;
-    	}
-    	WorkingMemory workingMemory = ((ProcessInstance) getProcessInstance()).getWorkingMemory();
-    	if (!hidden) {
-    		((EventSupport) workingMemory).getRuleFlowEventSupport().fireBeforeRuleFlowNodeLeft(this, (InternalWorkingMemory) workingMemory);
-    	}
-    	// check for exclusive group first
-    	NodeInstanceContainer parent = getNodeInstanceContainer();
-    	if (parent instanceof ContextInstanceContainer) {
-    		List<ContextInstance> contextInstances = ((ContextInstanceContainer) parent).getContextInstances(ExclusiveGroup.EXCLUSIVE_GROUP);
-    		if (contextInstances != null) {
-    			for (ContextInstance contextInstance: new ArrayList<ContextInstance>(contextInstances)) {
-    				ExclusiveGroupInstance groupInstance = (ExclusiveGroupInstance) contextInstance;
-    				if (groupInstance.containsNodeInstance(this)) {
-    					for (NodeInstance nodeInstance: groupInstance.getNodeInstances()) {
-    						if (nodeInstance != this) {
-    							((org.drools.workflow.instance.NodeInstance) nodeInstance).cancel();
-    						}
-    					}
-    					((ContextInstanceContainer) parent).removeContextInstance(ExclusiveGroup.EXCLUSIVE_GROUP, contextInstance);
-    				}
-    				
-    			}
-    		}
-    	}
-    	// trigger next node
-        ((org.drools.workflow.instance.NodeInstance) ((org.drools.workflow.instance.NodeInstanceContainer) getNodeInstanceContainer())
-        	.getNodeInstance(connection.getTo())).trigger(this, connection.getToType());
-        if (!hidden) {
-            ((EventSupport) workingMemory).getRuleFlowEventSupport().fireAfterRuleFlowNodeLeft(this, (InternalWorkingMemory) workingMemory);
-        }
-    }
-    
-    public Context resolveContext(String contextId, Object param) {
-        return ((NodeImpl) getNode()).resolveContext(contextId, param);
-    }
-    
-    public ContextInstance resolveContextInstance(String contextId, Object param) {
-        Context context = resolveContext(contextId, param);
-        if (context == null) {
-            return null;
-        }
-        ContextInstanceContainer contextInstanceContainer
-        	= getContextInstanceContainer(context.getContextContainer());
-        if (contextInstanceContainer == null) {
-        	throw new IllegalArgumentException(
-    			"Could not find context instance container for context");
-        }
-        return contextInstanceContainer.getContextInstance(context);
-    }
-    
-    private ContextInstanceContainer getContextInstanceContainer(ContextContainer contextContainer) {
-    	ContextInstanceContainer contextInstanceContainer = null; 
-		if (this instanceof ContextInstanceContainer) {
-        	contextInstanceContainer = (ContextInstanceContainer) this;
-        } else {
-        	contextInstanceContainer = getEnclosingContextInstanceContainer(this);
-        }
-        while (contextInstanceContainer != null) {
-    		if (contextInstanceContainer.getContextContainer() == contextContainer) {
-    			return contextInstanceContainer;
-    		}
-    		contextInstanceContainer = getEnclosingContextInstanceContainer(
-				(NodeInstance) contextInstanceContainer);
-    	}
-        return null;
-    }
-    
-    private ContextInstanceContainer getEnclosingContextInstanceContainer(NodeInstance nodeInstance) {
-    	NodeInstanceContainer nodeInstanceContainer = nodeInstance.getNodeInstanceContainer();
-    	while (true) {
-    		if (nodeInstanceContainer instanceof ContextInstanceContainer) {
-    			return (ContextInstanceContainer) nodeInstanceContainer;
-    		}
-    		if (nodeInstanceContainer instanceof NodeInstance) {
-    			nodeInstanceContainer = ((NodeInstance) nodeInstanceContainer).getNodeInstanceContainer();
-    		} else {
-    			return null;
-    		}
-    	}
-    }
-    
-    public String getUniqueId() {
-    	String result = "" + getId();
-    	NodeInstanceContainer parent = getNodeInstanceContainer();
-    	while (parent instanceof CompositeNodeInstance) {
-    		CompositeNodeInstance nodeInstance = (CompositeNodeInstance) parent;
-    		result = nodeInstance.getId() + ":" + result;
-    		parent = nodeInstance.getNodeInstanceContainer();
-    	}
-    	return result;
-    }
-    
-}
+package org.drools.workflow.instance.impl;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.WorkingMemory;
+import org.drools.common.EventSupport;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.definition.process.Connection;
+import org.drools.definition.process.Node;
+import org.drools.process.core.Context;
+import org.drools.process.core.ContextContainer;
+import org.drools.process.core.context.exclusive.ExclusiveGroup;
+import org.drools.process.instance.ContextInstance;
+import org.drools.process.instance.ContextInstanceContainer;
+import org.drools.process.instance.ProcessInstance;
+import org.drools.process.instance.context.exclusive.ExclusiveGroupInstance;
+import org.drools.runtime.process.NodeInstance;
+import org.drools.runtime.process.NodeInstanceContainer;
+import org.drools.workflow.core.impl.NodeImpl;
+import org.drools.workflow.instance.WorkflowProcessInstance;
+import org.drools.workflow.instance.node.CompositeNodeInstance;
+
+/**
+ * Default implementation of a RuleFlow node instance.
+ * 
+ * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
+ */
+public abstract class NodeInstanceImpl implements org.drools.workflow.instance.NodeInstance, Serializable {
+
+    private static final long serialVersionUID = 4L;
+    private long id;
+    private long nodeId;
+    private WorkflowProcessInstance processInstance;
+    private org.drools.workflow.instance.NodeInstanceContainer nodeInstanceContainer;
+
+    public void setId(final long id) {
+        this.id = id;
+    }
+
+    public long getId() {
+        return this.id;
+    }
+
+    public void setNodeId(final long nodeId) {
+        this.nodeId = nodeId;
+    }
+
+    public long getNodeId() {
+        return this.nodeId;
+    }
+
+    public String getNodeName() {
+        Node node = getNode();
+        return node == null ? "" : node.getName();
+    }
+
+    public void setProcessInstance(final WorkflowProcessInstance processInstance) {
+        this.processInstance = processInstance;
+    }
+
+    public WorkflowProcessInstance getProcessInstance() {
+        return this.processInstance;
+    }
+
+    public NodeInstanceContainer getNodeInstanceContainer() {
+        return this.nodeInstanceContainer;
+    }
+
+    public void setNodeInstanceContainer(NodeInstanceContainer nodeInstanceContainer) {
+        this.nodeInstanceContainer = (org.drools.workflow.instance.NodeInstanceContainer) nodeInstanceContainer;
+        if (nodeInstanceContainer != null) {
+            this.nodeInstanceContainer.addNodeInstance(this);
+        }
+    }
+
+    public Node getNode() {
+        return ((org.drools.workflow.core.NodeContainer) this.nodeInstanceContainer.getNodeContainer()).internalGetNode(this.nodeId);
+    }
+
+    public boolean isInversionOfControl() {
+        return false;
+    }
+
+    public void cancel() {
+        nodeInstanceContainer.removeNodeInstance(this);
+    }
+
+    public final void trigger(NodeInstance from, String type) {
+        boolean hidden = false;
+        if (getNode().getMetaData("hidden") != null) {
+            hidden = true;
+        }
+        WorkingMemory workingMemory = ((ProcessInstance) getProcessInstance()).getWorkingMemory();
+        if (!hidden) {
+            ((EventSupport) workingMemory).getRuleFlowEventSupport().fireBeforeRuleFlowNodeTriggered(this, (InternalWorkingMemory) workingMemory);
+        }
+        try {
+            internalTrigger(from, type);
+        } catch (ManagedRuntimeException ex) {
+            throw ex;
+        } catch (RuntimeException ex) {
+            if (!hidden) {
+                ((EventSupport) workingMemory).getRuleFlowEventSupport().fireRuleFlowNodeExceptionOccurred(processInstance, this, ex, workingMemory);
+            }
+            throw new ManagedRuntimeException(ex);
+        }
+        if (!hidden) {
+            ((EventSupport) workingMemory).getRuleFlowEventSupport().fireAfterRuleFlowNodeTriggered(this, (InternalWorkingMemory) workingMemory);
+        }
+    }
+
+    public abstract void internalTrigger(NodeInstance from, String type);
+
+    protected void triggerCompleted(String type, boolean remove) {
+        if (remove) {
+            ((org.drools.workflow.instance.NodeInstanceContainer) getNodeInstanceContainer()).removeNodeInstance(this);
+        }
+        Node node = getNode();
+        List<Connection> connections = null;
+        if (node != null) {
+            connections = node.getOutgoingConnections(type);
+        }
+        if (connections == null || connections.isEmpty()) {
+            ((org.drools.workflow.instance.NodeInstanceContainer) getNodeInstanceContainer()).nodeInstanceCompleted(this, type);
+        } else {
+            for (Connection connection : connections) {
+                // stop if this process instance has been aborted / completed
+                if (getProcessInstance().getState() != ProcessInstance.STATE_ACTIVE) {
+                    return;
+                }
+                triggerConnection(connection);
+            }
+        }
+    }
+
+    protected void triggerConnection(Connection connection) {
+        boolean hidden = false;
+        if (getNode().getMetaData("hidden") != null) {
+            hidden = true;
+        }
+        WorkingMemory workingMemory = ((ProcessInstance) getProcessInstance()).getWorkingMemory();
+        if (!hidden) {
+            ((EventSupport) workingMemory).getRuleFlowEventSupport().fireBeforeRuleFlowNodeLeft(this, (InternalWorkingMemory) workingMemory);
+        }
+        // check for exclusive group first
+        NodeInstanceContainer parent = getNodeInstanceContainer();
+        if (parent instanceof ContextInstanceContainer) {
+            List<ContextInstance> contextInstances = ((ContextInstanceContainer) parent).getContextInstances(ExclusiveGroup.EXCLUSIVE_GROUP);
+            if (contextInstances != null) {
+                for (ContextInstance contextInstance : new ArrayList<ContextInstance>(contextInstances)) {
+                    ExclusiveGroupInstance groupInstance = (ExclusiveGroupInstance) contextInstance;
+                    if (groupInstance.containsNodeInstance(this)) {
+                        for (NodeInstance nodeInstance : groupInstance.getNodeInstances()) {
+                            if (nodeInstance != this) {
+                                ((org.drools.workflow.instance.NodeInstance) nodeInstance).cancel();
+                            }
+                        }
+                        ((ContextInstanceContainer) parent).removeContextInstance(ExclusiveGroup.EXCLUSIVE_GROUP, contextInstance);
+                    }
+
+                }
+            }
+        }
+        // trigger next node
+        ((org.drools.workflow.instance.NodeInstance) ((org.drools.workflow.instance.NodeInstanceContainer) getNodeInstanceContainer()).getNodeInstance(connection.getTo())).trigger(this, connection.getToType());
+        if (!hidden) {
+            ((EventSupport) workingMemory).getRuleFlowEventSupport().fireAfterRuleFlowNodeLeft(this, (InternalWorkingMemory) workingMemory);
+        }
+    }
+
+    public Context resolveContext(String contextId, Object param) {
+        return ((NodeImpl) getNode()).resolveContext(contextId, param);
+    }
+
+    public ContextInstance resolveContextInstance(String contextId, Object param) {
+        Context context = resolveContext(contextId, param);
+        if (context == null) {
+            return null;
+        }
+        ContextInstanceContainer contextInstanceContainer = getContextInstanceContainer(context.getContextContainer());
+        if (contextInstanceContainer == null) {
+            throw new IllegalArgumentException(
+                    "Could not find context instance container for context");
+        }
+        return contextInstanceContainer.getContextInstance(context);
+    }
+
+    private ContextInstanceContainer getContextInstanceContainer(ContextContainer contextContainer) {
+        ContextInstanceContainer contextInstanceContainer = null;
+        if (this instanceof ContextInstanceContainer) {
+            contextInstanceContainer = (ContextInstanceContainer) this;
+        } else {
+            contextInstanceContainer = getEnclosingContextInstanceContainer(this);
+        }
+        while (contextInstanceContainer != null) {
+            if (contextInstanceContainer.getContextContainer() == contextContainer) {
+                return contextInstanceContainer;
+            }
+            contextInstanceContainer = getEnclosingContextInstanceContainer(
+                    (NodeInstance) contextInstanceContainer);
+        }
+        return null;
+    }
+
+    private ContextInstanceContainer getEnclosingContextInstanceContainer(NodeInstance nodeInstance) {
+        NodeInstanceContainer nodeInstanceContainer = nodeInstance.getNodeInstanceContainer();
+        while (true) {
+            if (nodeInstanceContainer instanceof ContextInstanceContainer) {
+                return (ContextInstanceContainer) nodeInstanceContainer;
+            }
+            if (nodeInstanceContainer instanceof NodeInstance) {
+                nodeInstanceContainer = ((NodeInstance) nodeInstanceContainer).getNodeInstanceContainer();
+            } else {
+                return null;
+            }
+        }
+    }
+
+    public String getUniqueId() {
+        String result = "" + getId();
+        NodeInstanceContainer parent = getNodeInstanceContainer();
+        while (parent instanceof CompositeNodeInstance) {
+            CompositeNodeInstance nodeInstance = (CompositeNodeInstance) parent;
+            result = nodeInstance.getId() + ":" + result;
+            parent = nodeInstance.getNodeInstanceContainer();
+        }
+        return result;
+    }
+}

Modified: labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/test/java/org/drools/event/process/ProcessEventSupportTest.java
===================================================================
--- labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/test/java/org/drools/event/process/ProcessEventSupportTest.java	2010-07-26 18:14:07 UTC (rev 34205)
+++ labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-core/src/test/java/org/drools/event/process/ProcessEventSupportTest.java	2010-07-26 20:05:42 UTC (rev 34206)
@@ -123,6 +123,10 @@
 				processEventList.add(event);
 			}
 
+                        public void onNodeException(ProcessNodeExceptionOccurredEvent event) {
+                            processEventList.add(event);
+                        }
+
         };
         session.addEventListener( processEventListener );
 

Modified: labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-persistence-jpa/src/test/java/org/drools/persistence/session/PersistentStatefulSessionTest.java
===================================================================
--- labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-persistence-jpa/src/test/java/org/drools/persistence/session/PersistentStatefulSessionTest.java	2010-07-26 18:14:07 UTC (rev 34205)
+++ labs/jbossrules/branches/trunk_20100722_esteban_diega/drools-persistence-jpa/src/test/java/org/drools/persistence/session/PersistentStatefulSessionTest.java	2010-07-26 20:05:42 UTC (rev 34206)
@@ -22,6 +22,7 @@
 import org.drools.event.process.ProcessCompletedEvent;
 import org.drools.event.process.ProcessEvent;
 import org.drools.event.process.ProcessEventListener;
+import org.drools.event.process.ProcessNodeExceptionOccurredEvent;
 import org.drools.event.process.ProcessNodeLeftEvent;
 import org.drools.event.process.ProcessNodeTriggeredEvent;
 import org.drools.event.process.ProcessStartedEvent;
@@ -535,6 +536,12 @@
 				System.out.println("Before process started");
 				events.add(event);				
 			}
+
+                        public void onNodeException(ProcessNodeExceptionOccurredEvent event) {
+                            System.out.println("On node exception");
+                                            events.add(event);
+                        }
+
         };
         ksession.addEventListener(listener);
         



More information about the jboss-svn-commits mailing list