in jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/SplitInstance.java [77:250]
protected void executeStrategy(Split split, String type) {
// TODO make different strategies for each type
switch (split.getType()) {
case Split.TYPE_AND:
triggerCompleted(Node.CONNECTION_DEFAULT_TYPE, true);
break;
case Split.TYPE_XOR:
List<Connection> outgoing = split.getDefaultOutgoingConnections();
int priority = Integer.MAX_VALUE;
Connection selected = null;
for (final Iterator<Connection> iterator = outgoing.iterator(); iterator.hasNext();) {
final Connection connection = iterator.next();
Collection<Constraint> constraints = split.getConstraints(connection);
if (constraints != null) {
for (Constraint constraint : constraints) {
if (constraint instanceof ConstraintEvaluator && constraint.getPriority() < priority && !constraint.isDefault()) {
try {
if (((ConstraintEvaluator) constraint).evaluate(this,
connection,
constraint)) {
selected = connection;
priority = constraint.getPriority();
}
} catch (RuntimeException e) {
throw new RuntimeException(
"Exception when trying to evaluate constraint "
+ constraint.getName() + " in split "
+ split.getName(),
e);
}
}
}
}
}
((NodeInstanceContainer) getNodeInstanceContainer()).removeNodeInstance(this);
if (selected == null) {
for (final Iterator<Connection> iterator = outgoing.iterator(); iterator.hasNext();) {
final Connection connection = iterator.next();
if (split.isDefault(connection)) {
selected = connection;
break;
}
}
}
if (selected == null) {
throw new IllegalArgumentException("XOR split could not find at least one valid outgoing connection for split " + getSplit().getName());
}
if (!hasLoop(selected.getTo(), split)) {
setLevel(1);
((NodeInstanceContainer) getNodeInstanceContainer()).setCurrentLevel(1);
}
triggerConnection(selected);
break;
case Split.TYPE_OR:
((NodeInstanceContainer) getNodeInstanceContainer()).removeNodeInstance(this);
outgoing = split.getDefaultOutgoingConnections();
boolean found = false;
List<NodeInstanceTrigger> nodeInstances =
new ArrayList<>();
List<Connection> outgoingCopy = new ArrayList<>(outgoing);
while (!outgoingCopy.isEmpty()) {
priority = Integer.MAX_VALUE;
Connection selectedConnection = null;
ConstraintEvaluator selectedConstraint = null;
for (final Iterator<Connection> iterator = outgoingCopy.iterator(); iterator.hasNext();) {
final Connection connection = iterator.next();
Collection<Constraint> constraints = split.getConstraints(connection);
if (constraints != null) {
for (Constraint constraint : constraints) {
if (constraint instanceof ConstraintEvaluator && constraint.getPriority() < priority
&& !constraint.isDefault()) {
priority = constraint.getPriority();
selectedConnection = connection;
selectedConstraint = (ConstraintEvaluator) constraint;
}
}
}
}
if (selectedConstraint == null) {
break;
}
if (selectedConstraint.evaluate(this,
selectedConnection,
selectedConstraint)) {
nodeInstances.add(new NodeInstanceTrigger(followConnection(selectedConnection), selectedConnection.getToType()));
found = true;
}
outgoingCopy.remove(selectedConnection);
}
for (NodeInstanceTrigger nodeInstance : nodeInstances) {
// stop if this process instance has been aborted / completed
if (getProcessInstance().getState() != KogitoProcessInstance.STATE_ACTIVE) {
return;
}
triggerNodeInstance(nodeInstance.getNodeInstance(), nodeInstance.getToType());
}
if (!found) {
final Iterator<Connection> iterator = outgoing.iterator();
while (!found && iterator.hasNext()) {
final Connection connection = iterator.next();
Collection<Constraint> constraints = split.getConstraints(connection);
if (constraints != null) {
for (Constraint constraint : constraints) {
if (constraint != null && constraint.isDefault()) {
triggerConnection(connection);
found = true;
break;
}
}
}
if (!found && split.isDefault(connection)) {
triggerConnection(connection);
found = true;
}
}
}
if (!found) {
throw new IllegalArgumentException("OR split could not find at least one valid outgoing connection for split " + getSplit().getName());
}
break;
case Split.TYPE_XAND:
((org.jbpm.workflow.instance.NodeInstanceContainer) getNodeInstanceContainer()).removeNodeInstance(this);
org.kie.api.definition.process.Node node = getNode();
List<Connection> connections = null;
if (node != null) {
connections = node.getOutgoingConnections(type);
}
if (connections == null || connections.isEmpty()) {
((org.jbpm.workflow.instance.NodeInstanceContainer) getNodeInstanceContainer())
.nodeInstanceCompleted(this, type);
} else {
ExclusiveGroupInstance groupInstance = new ExclusiveGroupInstance();
org.kie.api.runtime.process.NodeInstanceContainer parent = getNodeInstanceContainer();
if (parent instanceof ContextInstanceContainer) {
((ContextInstanceContainer) parent).addContextInstance(ExclusiveGroup.EXCLUSIVE_GROUP, groupInstance);
} else {
throw new IllegalArgumentException(
"An Exclusive AND is only possible if the parent is a context instance container");
}
Map<org.jbpm.workflow.instance.NodeInstance, String> nodeInstancesMap = new HashMap<>();
for (Connection connection : connections) {
nodeInstancesMap.put(followConnection(connection), connection.getToType());
}
for (KogitoNodeInstance nodeInstance : nodeInstancesMap.keySet()) {
groupInstance.addNodeInstance(nodeInstance);
}
for (Map.Entry<org.jbpm.workflow.instance.NodeInstance, String> entry : nodeInstancesMap.entrySet()) {
// stop if this process instance has been aborted / completed
if (getProcessInstance().getState() != KogitoProcessInstance.STATE_ACTIVE) {
return;
}
boolean hidden = false;
if (getNode().getMetaData().get("hidden") != null) {
hidden = true;
}
leaveTime = new Date();
InternalKnowledgeRuntime kruntime = getProcessInstance().getKnowledgeRuntime();
if (!hidden) {
((InternalProcessRuntime) kruntime.getProcessRuntime())
.getProcessEventSupport().fireBeforeNodeLeft(this, kruntime);
}
(entry.getKey()).trigger(this, entry.getValue());
if (!hidden) {
((InternalProcessRuntime) kruntime.getProcessRuntime())
.getProcessEventSupport().fireAfterNodeLeft(this, kruntime);
}
}
}
break;
default:
throw new IllegalArgumentException("Illegal split type " + split.getType());
}
}