
org.yaoqiang.bpmn.engine.operation.FlowNodeExecute Maven / Gradle / Ivy
package org.yaoqiang.bpmn.engine.operation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
import org.yaoqiang.bpmn.engine.runtime.Execution;
import org.yaoqiang.bpmn.model.elements.activities.Activity;
import org.yaoqiang.bpmn.model.elements.activities.SubProcess;
import org.yaoqiang.bpmn.model.elements.core.common.FlowNode;
import org.yaoqiang.bpmn.model.elements.core.common.SequenceFlow;
import org.yaoqiang.bpmn.model.elements.events.BoundaryEvent;
import org.yaoqiang.bpmn.model.elements.gateways.ExclusiveGateway;
import org.yaoqiang.bpmn.model.elements.gateways.Gateway;
import org.yaoqiang.bpmn.model.elements.gateways.InclusiveGateway;
import org.yaoqiang.bpmn.model.elements.gateways.ParallelGateway;
/**
* FlowNodeExecute
*
* @author Shi Yaoqiang([email protected])
*/
public class FlowNodeExecute implements ExecutionOperation {
private static Logger log = Logger.getLogger(FlowNodeExecute.class.getName());
public void execute(Execution execution) {
FlowNode flowNode = execution.getFlowNode();
if (flowNode instanceof Gateway) {
if (flowNode instanceof ParallelGateway) {
executeParallelGateway(execution);
} else if (flowNode instanceof ExclusiveGateway) {
executeExclusiveGateway(execution);
} else if (flowNode instanceof InclusiveGateway) {
executeInclusiveGateway(execution);
}
} else if (flowNode instanceof Activity) {
Set events = ((Activity) flowNode).getBoundaryEventRefs();
boolean fireEvent = false;
if (events != null) {
for (BoundaryEvent event : events) {
if (Math.random() > 0.5) {
fireEvent = true;
execution.executeFlowNode(event);
}
}
}
if (!fireEvent) {
if (flowNode instanceof SubProcess) {
executeSubProcess(execution);
} else {
executeFlowNode(execution);
}
}
} else {
executeFlowNode(execution);
}
}
private void executeParallelGateway(Execution execution) {
FlowNode flowNode = execution.getFlowNode();
List outgoingSequenceFlows = flowNode.getOutgoingSequenceFlows();
execution.inactivate();
List joinedExecutions = execution.findInactiveConcurrentExecutions(flowNode);
int nbrOfExecutionsToJoin = flowNode.getIncomingSequenceFlows().size();
int nbrOfExecutionsJoined = joinedExecutions.size();
if (nbrOfExecutionsJoined == nbrOfExecutionsToJoin) {
log.fine("Parallel gateway '" + flowNode.getName() + "' activates: " + nbrOfExecutionsJoined + " of " + nbrOfExecutionsToJoin + " joined");
execution.takeAll(outgoingSequenceFlows, joinedExecutions);
} else {
log.fine("Parallel gateway '" + flowNode.getName() + "' does not activate: " + nbrOfExecutionsJoined + " of " + nbrOfExecutionsToJoin + " joined");
}
}
private void executeExclusiveGateway(Execution execution) {
FlowNode flowNode = execution.getFlowNode();
log.fine("Leaving Exclusive gateway '" + flowNode.getName() + "'");
SequenceFlow defaultSequenceFlow = ((ExclusiveGateway) flowNode).getDefaultSequenceFlow();
int randomFlow = (int) Math.floor(Math.random() * flowNode.getOutgoingSequenceFlows().size());
SequenceFlow outgoingSequenceFlow = flowNode.getOutgoingSequenceFlows().get(randomFlow);
if (outgoingSequenceFlow == defaultSequenceFlow) {
log.fine("Default Sequence flow '" + outgoingSequenceFlow.getId() + " '" + "selected as outgoing sequence flow.");
} else {
log.fine("Sequence flow '" + outgoingSequenceFlow.getId() + " '" + "selected as outgoing sequence flow.");
execution.take(outgoingSequenceFlow);
}
}
private void executeInclusiveGateway(Execution execution) {
FlowNode flowNode = execution.getFlowNode();
if (!activeConcurrentExecutionsExist(execution)) {
log.fine("Inclusive gateway '" + flowNode.getName() + "' activates");
SequenceFlow defaultSequenceFlow = ((InclusiveGateway) flowNode).getDefaultSequenceFlow();
List joinedExecutions = execution.findInactiveConcurrentExecutions(flowNode);
List sequenceFlowToTake = new ArrayList();
for (SequenceFlow outgoingSequenceFlow : flowNode.getOutgoingSequenceFlows()) {
if (outgoingSequenceFlow != defaultSequenceFlow && Math.random() > 0.5) {
sequenceFlowToTake.add(outgoingSequenceFlow);
}
}
if (sequenceFlowToTake.size() > 0) {
execution.takeAll(sequenceFlowToTake, joinedExecutions);
} else if (defaultSequenceFlow != null) {
execution.take(defaultSequenceFlow);
} else {
execution.take(flowNode.getOutgoingSequenceFlows().get(0));
}
} else {
log.fine("Inclusive gateway '" + flowNode.getName() + "' does not activate");
}
}
private void executeSubProcess(Execution execution) {
FlowNode flowNode = execution.getFlowNode();
List startFlowNodes = new ArrayList();
for (FlowNode node : ((SubProcess) flowNode).getFlowNodes()) {
if (node.getIncomingSequenceFlows().isEmpty()) {
startFlowNodes.add(node);
}
}
if (startFlowNodes.isEmpty()) {
executeFlowNode(execution);
} else {
for (FlowNode startFlowNode : startFlowNodes) {
execution.executeFlowNode(startFlowNode);
}
}
}
private void executeFlowNode(Execution execution) {
FlowNode flowNode = execution.getFlowNode();
List outgoingSequenceFlows = flowNode.getOutgoingSequenceFlows();
if (outgoingSequenceFlows.isEmpty()) {
execution.end();
} else {
List sequenceFlowToTake = new ArrayList();
SequenceFlow defaultSequenceFlow = null;
if (flowNode instanceof Activity) {
defaultSequenceFlow = ((Activity) flowNode).getDefaultSequenceFlow();
}
for (SequenceFlow outgoingSequenceFlow : flowNode.getOutgoingSequenceFlows()) {
if (outgoingSequenceFlow != defaultSequenceFlow && Math.random() > 0.5) {
sequenceFlowToTake.add(outgoingSequenceFlow);
}
}
if (sequenceFlowToTake.size() > 0) {
execution.takeAll(sequenceFlowToTake, Collections. emptyList());
} else if (defaultSequenceFlow != null) {
execution.take(defaultSequenceFlow);
} else {
execution.take(flowNode.getOutgoingSequenceFlows().get(0));
}
}
}
private boolean activeConcurrentExecutionsExist(Execution execution) {
FlowNode flowNode = execution.getFlowNode();
if (execution.isConcurrent()) {
for (Execution concurrentExecution : execution.getParent().getExecutions()) {
if (concurrentExecution.isActive() && concurrentExecution.getFlowNode() != flowNode) {
// TODO: when is transitionBeingTaken cleared? Should we clear it?
boolean reachable = false;
SequenceFlow sequenceFlow = concurrentExecution.getSequenceFlow();
if (sequenceFlow != null) {
reachable = isReachable(sequenceFlow.getTargetFlowNode(), flowNode, new HashSet());
} else {
reachable = isReachable(concurrentExecution.getFlowNode(), flowNode, new HashSet());
}
if (reachable) {
log.fine("an active concurrent execution found: '" + concurrentExecution.getFlowNode());
return true;
}
}
}
}
return false;
}
private boolean isReachable(FlowNode srcFlowNode, FlowNode targetFlowNode, Set visitedFlowNodes) {
if (srcFlowNode.equals(targetFlowNode)) {
return true;
}
// To avoid infinite looping, we must capture every node we visit
// and check before going further in the graph if we have already visitied the node.
visitedFlowNodes.add(srcFlowNode);
List transitionList = srcFlowNode.getOutgoingSequenceFlows();
if (transitionList != null && transitionList.size() > 0) {
for (SequenceFlow pvmTransition : transitionList) {
FlowNode destinationActivity = pvmTransition.getTargetFlowNode();
if (destinationActivity != null && !visitedFlowNodes.contains(destinationActivity)) {
boolean reachable = isReachable(destinationActivity, targetFlowNode, visitedFlowNodes);
// If false, we should investigate other paths, and not yet return the result
if (reachable) {
return true;
}
}
}
}
return false;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy