/** * @return All executions currently waiting at the gateway. */ protected List<ExecutionImpl> getJoinedExecutions(ExecutionImpl concurrentRoot, Activity activity) { List<ExecutionImpl> joinedExecutions = new ArrayList<ExecutionImpl>(); Collection<ExecutionImpl> concurrentExecutions = concurrentRoot.getExecutions(); for (ExecutionImpl concurrentExecution: concurrentExecutions) { if ( (Execution.STATE_INACTIVE_JOIN.equals(concurrentExecution.getState())) && (concurrentExecution.getActivity()==activity) ) { joinedExecutions.add(concurrentExecution); } } if (LOG.isDebugEnabled()) { LOG.debug("Found " + joinedExecutions.size() + " executions currently waiting at the gateway"); } return joinedExecutions; }
public void signal(ActivityExecution execution, String signalName, Map<String, ? > parameters) throws Exception { ActivityImpl activity = (ActivityImpl) execution.getActivity(); ExecutionImpl scopedExecution = (ExecutionImpl) execution.getParent(); // If there are still active paths in the sub-process if ( (scopedExecution.getExecutions() != null) && (scopedExecution.getExecutions().size() > 1) ) { // not > 0 -> current execution is still a child if (LOG.isDebugEnabled()) { LOG.debug("Scoped execution " + scopedExecution.getId() + " has active child executions." + "Ending current execution, but scoped execution is not yet continued"); } execution.end(); // If no other paths are active in the sub-process } else { ExecutionImpl parent = scopedExecution.destroyScope(activity); // child execution will be ended automatically when parent ends if (LOG.isDebugEnabled()) { LOG.debug("Scoped execution " + scopedExecution.getId() + " has no active child executions." + "Destroying scope and proceeding from parent execution " + parent.getId()); } proceed(parent, findOutgoingSequenceFlow(parent, CONDITIONS_CHECKED)); } }
if (parent != null && parent.getExecutions().isEmpty() && Execution.STATE_INACTIVE_CONCURRENT_ROOT.equals(parent.getState()) ) { parent.end();
/** * Joins all the incoming executions currently waiting at the gateway. * * @return An execution that can be used to leave the gateway (one outgoing sequence flow) * or to create child executions on (fork behaviour when multiple outgoing sequence flow). */ protected ExecutionImpl join(ExecutionImpl execution) { Activity activity = execution.getActivity(); ExecutionImpl concurrentRoot = execution.getParent(); if (concurrentRoot == null) { return execution; } List<ExecutionImpl> joinedExecutions = getJoinedExecutions(concurrentRoot, activity); endJoinedExecutions(joinedExecutions); ExecutionImpl outgoingExecution = null; if (concurrentRoot.getExecutions().size() == 0) { outgoingExecution = concurrentRoot; outgoingExecution.setState(Execution.STATE_ACTIVE_ROOT); } else { outgoingExecution = concurrentRoot.createExecution(); outgoingExecution.setState(Execution.STATE_ACTIVE_CONCURRENT); } outgoingExecution.setActivity(activity); return outgoingExecution; }
/** * Section 14.3.2 of the BPMN 2.0 specification. * * The Inclusive Gateway is activated if * - At least one incoming sequence flow has at least one Token and * - for each empty incoming sequence flow, there is no Token in the graph anywhere * upstream of this sequence flow, i.e., there is no directed path (formed by Sequence Flow) * from a Token to this sequence flow unless * - the path visits the inclusive gateway or * - the path visits a node that has a directed path to a non-empty incoming sequence * flow of the inclusive gateway. */ protected boolean isComplete(ExecutionImpl incomingExecution) { String currentActivityId = incomingExecution.getActivityName(); // id is stored in the name attribute Collection<ExecutionImpl> allExecutions = incomingExecution.getProcessInstance().getExecutions(); BpmnProcessDefinition processDefinition = (BpmnProcessDefinition) incomingExecution.getProcessDefinition(); for (ExecutionImpl execution : allExecutions) { if (incomingExecution.getParent().equals(execution.getParent())) { String activityId = execution.getActivityName(); // id is stored in the name attribute if (activityId != null && !currentActivityId.equals(activityId)) { if (processDefinition.isReachable(activityId, currentActivityId)) { return false; } } } } return true; }
public static ProcessInstanceRef adoptExecution(Execution execution) { ProcessInstanceRef ref = new ProcessInstanceRef(); ref.setId(execution.getId()); ref.setKey(execution.getKey()); ref.setDefinitionId(execution.getProcessDefinitionId()); // Start date is only available through historyService HistoryService historyService = ProcessEngineUtil.retrieveProcessEngine().getHistoryService(); Date startDate = historyService.createHistoryProcessInstanceQuery() .processInstanceId(execution.getId()) .uniqueResult().getStartTime(); ref.setStartDate(startDate); ExecutionImpl processInstance = (ExecutionImpl) execution.getProcessInstance(); ProcessDefinitionImpl processDefinition = processInstance.getProcessDefinition(); TokenReference tok = execution2TokenReference(processInstance); Collection<? extends Execution> childExecutions = processInstance.getExecutions(); if (childExecutions != null) { for (Execution child : childExecutions) { ExecutionImpl childExecution = (ExecutionImpl) child; // set process definition on child execution from process instance childExecution.setProcessDefinition(processDefinition); TokenReference childTok = execution2TokenReference(childExecution); tok.getChildren().add(childTok); } } ref.setRootToken(tok); return ref; }