jadex.bpmn.runtime.handler.DefaultStepHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jadex-kernel-bpmn Show documentation
Show all versions of jadex-kernel-bpmn Show documentation
The Jadex BPMN kernel provides a workflow kernel for the standardized business process modeling notation. The kernel relies on annotated BPMN diagrams, which include detailed execution information.
package jadex.bpmn.runtime.handler;
import java.util.List;
import jadex.bpmn.model.MActivity;
import jadex.bpmn.model.MBpmnModel;
import jadex.bpmn.model.MNamedIdElement;
import jadex.bpmn.model.MSequenceEdge;
import jadex.bpmn.model.MSubProcess;
import jadex.bpmn.runtime.IStepHandler;
import jadex.bpmn.runtime.ProcessThread;
import jadex.bridge.ComponentTerminatedException;
import jadex.bridge.IInternalAccess;
import jadex.bridge.component.IExecutionFeature;
import jadex.bridge.component.IMonitoringComponentFeature;
import jadex.bridge.service.types.monitoring.IMonitoringEvent;
import jadex.bridge.service.types.monitoring.IMonitoringService.PublishEventLevel;
import jadex.bridge.service.types.monitoring.IMonitoringService.PublishTarget;
import jadex.commons.IResultCommand;
import jadex.commons.SReflect;
/**
* Handles the transition of steps.
*/
public class DefaultStepHandler implements IStepHandler
{
/**
* Make a process step, i.e. find the next edge or activity for a just executed thread.
* @param activity The activity to execute.
* @param instance The process instance.
* @param thread The process thread.
*/
public void step(MActivity activity, IInternalAccess instance, ProcessThread thread, Object event)
{
assert instance.getComponentFeature(IExecutionFeature.class).isComponentThread();
// System.out.println("stephandler: "+thread.getId()+" "+instance.getComponentIdentifier().getLocalName()+": step "+activity+", data "+thread.getData());
// if("Participant_1".equals(instance.getComponentIdentifier().getLocalName()))
// {
// Thread.dumpStack();
// }
// // Hack!!! Should be in interpreter/thread?
thread.updateParametersAfterStep(activity, instance);
MNamedIdElement next = null;
ProcessThread remove = null; // Thread that needs to be removed (if any).
Exception ex = thread.getException();
// Store event (if any).
if(event!=null)
{
thread.setOrCreateParameterValue("$event", event);
// System.out.println("Event: "+activity+" "+thread+" "+event);
}
// For subprocesses not called
// // Cancel handlers
// if(activity instanceof MSubProcess)
// {
// ICancelable cancelable = (CompositeCancelable)thread.getWaitInfo();
// if(cancelable!=null)
// {
// cancelable.cancel();
// thread.setWaitInfo(null);
// }
// }
// Timer occurred flow
if(AbstractEventIntermediateTimerActivityHandler.TIMER_EVENT.equals(event))
{
// Cancel subflows.
remove = thread;
// Continue with timer edge.
List outedges = activity.getOutgoingSequenceEdges();
if(outedges!=null && outedges.size()==1)
{
next = outedges.get(0);
}
else if(outedges!=null && outedges.size()>1)
{
throw new RuntimeException("Cannot determine outgoing edge: "+activity);
}
}
// Find next element and context(s) to be removed.
else
{
boolean outside = false;
ProcessThread parent = thread.getParent();
while(next==null && !outside)
{
// Normal flow
if(ex==null)
{
List outgoing = activity.getOutgoingSequenceEdges();
if(outgoing!=null && outgoing.size()==1)
{
next = (MSequenceEdge)outgoing.get(0);
}
else if(outgoing!=null && outgoing.size()>1)
{
throw new UnsupportedOperationException("Activity has more than one one outgoing edge. Please overridge step() for disambiguation: "+activity);
}
// else no outgoing edge -> check parent context, if any.
}
// Exception flow.
else
{
List handlers = activity.getEventHandlers();
for(int i=0; handlers!=null && next==null && i cmd = thread.getParent().getLoopCommand();
if(!cmd.execute(null))
{
parent.setLoopCommand(null);
}
}
}
// When last thread or exception, mark current context for removal.
if((parent.getSubthreads()!=null && parent.getSubthreads().size()==1) || ex!=null)
{
activity = (MActivity)parent.getModelElement();
remove = parent;
parent.updateParametersAfterStep(activity, instance);
parent = parent.getParent();
// Cancel subprocess handlers.
if(activity instanceof MSubProcess)
{
List handlers = activity.getEventHandlers();
for(int i=0; handlers!=null && i1)
{
outside = true;
}
}
}
else
{
break;
}
// else
// {
// throw new RuntimeException("Thread context nulls in process: "+activity, ex);
// }
}
}
// Remove inner context(s), if any.
if(remove!=null)
{
thread = remove;
thread.setNonWaiting();
if(ex!=null)
thread.setException(ex);
// Todo: Callbacks for aborted threads (to abort external activities)
thread.removeSubcontext();
// for(Iterator it=remove.getAllThreads().iterator(); it.hasNext(); )
// {
// if(instance.hasEventTargets(PublishTarget.TOALL, PublishEventLevel.FINE))
// {
// instance.publishEvent(instance.createThreadEvent(IMonitoringEvent.EVENT_TYPE_DISPOSAL, thread), PublishTarget.TOALL);
// }
// }
if(instance.getComponentFeature0(IMonitoringComponentFeature.class)!=null && thread.getActivity()!=null && instance.getComponentFeature(IMonitoringComponentFeature.class).hasEventTargets(PublishTarget.TOALL, PublishEventLevel.FINE))
{
instance.getComponentFeature(IMonitoringComponentFeature.class).publishEvent(DefaultActivityHandler.getBpmnFeature(instance).createThreadEvent(IMonitoringEvent.EVENT_TYPE_MODIFICATION, thread), PublishTarget.TOALL);
}
}
if(ex!=null && next==null)
{
// Hack! Special case of terminated exception of itself e.g. during killing.
if(ex instanceof ComponentTerminatedException && instance.getComponentIdentifier().equals(((ComponentTerminatedException)ex).getComponentIdentifier()))
{
instance.getLogger().warning("Component terminated exception: "+ex);
}
else
{
// If component scope and exception terminate the component
instance.killComponent(ex);
// Does not work because components now tolerate exceptions in steps
// if(ex instanceof RuntimeException)
// {
// throw (RuntimeException)ex;
// }
// else
// {
// throw new RuntimeException("Unhandled exception in process: "+activity, ex);
// }
}
}
// Perform step settings, i.e. set next edge/activity or remove thread.
if(next instanceof MSequenceEdge)
{
// Sets the edge as well as the next activity
thread.setLastEdge((MSequenceEdge)next);
if(instance.getComponentFeature0(IMonitoringComponentFeature.class)!=null && thread.getActivity()!=null && instance.getComponentFeature(IMonitoringComponentFeature.class).hasEventTargets(PublishTarget.TOALL, PublishEventLevel.FINE))
{
instance.getComponentFeature(IMonitoringComponentFeature.class).publishEvent(DefaultActivityHandler.getBpmnFeature(instance).createThreadEvent(IMonitoringEvent.EVENT_TYPE_MODIFICATION, thread), PublishTarget.TOALL);
}
}
else if(next instanceof MActivity)
{
// Set the activity and the last edge to null
thread.setActivity((MActivity)next);
if(instance.getComponentFeature0(IMonitoringComponentFeature.class)!=null && thread.getActivity()!=null && instance.getComponentFeature(IMonitoringComponentFeature.class).hasEventTargets(PublishTarget.TOALL, PublishEventLevel.FINE))
{
instance.getComponentFeature(IMonitoringComponentFeature.class).publishEvent(DefaultActivityHandler.getBpmnFeature(instance).createThreadEvent(IMonitoringEvent.EVENT_TYPE_MODIFICATION, thread), PublishTarget.TOALL);
}
}
else if(next==null)
{
thread.setActivity(null);
if(thread.getParent()!=null)
{
thread.getParent().removeThread(thread);
}
}
else
{
throw new UnsupportedOperationException("Unknown outgoing element type: "+next);
}
}
}