public ExecutionImpl destroyScope(CompositeElementImpl scope) { destroyTimers(scope); destroyVariables(scope, parent); // copy the current state from the child execution to the parent execution getParent().setNode(getNode()); getParent().setTransition(getTransition()); getParent().setPropagation(getPropagation()); getParent().setTransitionOrigin(getTransitionOrigin()); getParent().setPreviousTransition(getPreviousTransition()); getParent().setPreviousNode(getPreviousNode()); end(); parent.removeExecution(this); return parent; }
protected boolean isComplete(ExecutionImpl execution) { Activity activity = execution.getActivity(); ExecutionImpl concurrentRoot = execution.getParent(); List<ExecutionImpl> joinedExecutions = getJoinedExecutions(concurrentRoot, activity); boolean result = joinedExecutions.size() == activity.getIncomingTransitions().size(); if (LOG.isDebugEnabled()) { LOG.debug("All incoming executions have arrived at the gateway: " + result); } return result; }
/** * 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; }
/** * Joins the incoming executions. * Returns true if all executions have reached the gateway. */ protected boolean handleIncomingExecution(ExecutionImpl execution) { if (Execution.STATE_ACTIVE_CONCURRENT.equals(execution.getState())) { // force version increment in the parent execution Session session = EnvironmentImpl.getFromCurrent(Session.class); session.lock(execution.getParent(), lockMode); execution.setState(Execution.STATE_INACTIVE_JOIN); } execution.waitForSignal(); return isComplete(execution); }
execution.setActivity(null); } else if (Execution.STATE_ACTIVE_CONCURRENT.equals(execution.getState())) { concurrentRoot = execution.getParent(); execution.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; }