/** Must be called on process execution thread! Gets infos about the current threads. */ protected ProcessThreadInfo[] getThreadInfos() { List ret = null; ThreadContext tc = instance.getThreadContext(); Set threads = tc.getAllThreads(); if (threads != null) { ret = new ArrayList(); for (Iterator it = threads.iterator(); it.hasNext(); ) { ProcessThread pt = (ProcessThread) it.next(); ret.add( new ProcessThreadInfo( pt.getId(), pt.getActivity(), // pt.getLastEdge(), pt.getException(), pt.isWaiting(), pt.getData() == null ? new HashMap() : new HashMap(pt.getData()))); } } return (ProcessThreadInfo[]) ret.toArray(new ProcessThreadInfo[ret.size()]); }
/** * 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, BpmnInterpreter instance, ProcessThread thread, Object event) { // System.out.println(instance.getComponentIdentifier().getLocalName()+": step "+activity+", // data "+thread.getData()); // Hack!!! Should be in interpreter/thread? thread.updateParametersAfterStep(activity, instance); MNamedIdElement next = null; ThreadContext remove = null; // Context that needs to be removed (if any). Exception ex = thread.getException(); // Store event (if any). if (event != null) { thread.setParameterValue("$event", event); // System.out.println("Event: "+activity+" "+thread+" "+event); } // Timer occurred flow if (AbstractEventIntermediateTimerActivityHandler.TIMER_EVENT.equals(event)) { // Cancel subflows. remove = thread.getThreadContext().getSubcontext(thread); // Continue with timer edge. List outedges = activity.getOutgoingSequenceEdges(); if (outedges != null && outedges.size() == 1) { next = (MSequenceEdge) 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; ThreadContext context = thread.getThreadContext(); 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 < handlers.size(); i++) { MActivity handler = (MActivity) handlers.get(i); if (handler.getActivityType().equals("EventIntermediateError")) { // Todo: match exception types. // Class clazz = handler.getName()!=null ? SReflect.findClass0(clname, imports, // classloader); next = handler; } } } outside = context.getParent() == null; if (next == null && !outside) { // When last thread or exception, mark current context for removal. if (context.getThreads().size() == 1 || ex != null) { activity = (MActivity) context.getModelElement(); remove = context; context = context.getParent(); // Cancel subprocess handlers. if (activity instanceof MSubProcess) { List handlers = activity.getEventHandlers(); for (int i = 0; handlers != null && i < handlers.size(); i++) { MActivity handler = (MActivity) handlers.get(i); instance .getActivityHandler(handler) .cancel(handler, instance, remove.getInitiator()); } } } // If more threads are available in current context just exit loop. else if (context.getThreads().size() > 1) { outside = true; } } } } // Remove inner context(s), if any. if (remove != null) { thread = remove.getInitiator(); thread.setNonWaiting(); // Todo: Callbacks for aborted threads (to abort external activities) thread.getThreadContext().removeSubcontext(remove); } if (next != null) { // Todo: store exception as parameter!? if (ex != null) thread.setException(null); } else if (ex != null) { 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) { thread.setLastEdge((MSequenceEdge) next); } else if (next instanceof MActivity) { thread.setActivity((MActivity) next); } else if (next == null) { thread.getThreadContext().removeThread(thread); } else { throw new UnsupportedOperationException("Unknown outgoing element type: " + next); } }