Skip to content

Commit

Permalink
[JBPM-10234] CancelNode should be able to cancel more than one instance
Browse files Browse the repository at this point in the history
  • Loading branch information
fjtirado committed Jun 25, 2024
1 parent 2ed7d56 commit a45c6f7
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;

import org.jbpm.workflow.instance.node.CompositeNodeInstance;
import org.kie.api.runtime.process.NodeInstance;
Expand All @@ -39,36 +40,32 @@ public CancelNodeInstanceAction(String attachedToNodeId) {

public void execute(ProcessContext context) throws Exception {

NodeInstanceContainer container = context.getNodeInstance().getNodeInstanceContainer();
NodeInstance nodeInstance = findNodeByUniqueId(container.getNodeInstances(), attachedToNodeId);
NodeInstanceContainer container = context.getNodeInstance().getNodeInstanceContainer();
Collection<NodeInstance> nodeInstances = findNodeByUniqueId(container.getNodeInstances(), attachedToNodeId);

if (nodeInstance == null) {
if (nodeInstances.isEmpty()) {
WorkflowProcessInstance pi = context.getNodeInstance().getProcessInstance();
nodeInstance = findNodeByUniqueId(pi.getNodeInstances(), attachedToNodeId);
nodeInstances = findNodeByUniqueId(pi.getNodeInstances(), attachedToNodeId);
}

if (nodeInstance != null) {
((org.jbpm.workflow.instance.NodeInstance) nodeInstance).cancel(SKIPPED);
}
nodeInstances.forEach(nodeInstance -> ((org.jbpm.workflow.instance.NodeInstance) nodeInstance).cancel(SKIPPED));
}

private NodeInstance findNodeByUniqueId(Collection<NodeInstance> nodeInstances, String uniqueId) {
private Collection<NodeInstance> findNodeByUniqueId(Collection<NodeInstance> nodeInstances, String uniqueId) {

Collection<NodeInstance> result = new HashSet<>();
if (nodeInstances != null && !nodeInstances.isEmpty()) {
for (NodeInstance nInstance : nodeInstances) {
String nodeUniqueId = (String) nInstance.getNode().getMetaData().get("UniqueId");
if (uniqueId.equals(nodeUniqueId)) {
return nInstance;
result.add(nInstance);
}
if (nInstance instanceof CompositeNodeInstance) {
NodeInstance nodeInstance = findNodeByUniqueId(((CompositeNodeInstance) nInstance).getNodeInstances(), uniqueId);
if (nodeInstance != null) {
return nodeInstance;
}
result.addAll(findNodeByUniqueId(((CompositeNodeInstance) nInstance).getNodeInstances(), uniqueId));
}
}
}
return null;
return result;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

Expand Down Expand Up @@ -63,35 +64,44 @@ public BoundaryEventNode getEventNode() {
public void triggerCompleted(String type, Object event) {
Collection<NodeInstance> nodeInstances = ((NodeInstanceContainer) getNodeInstanceContainer()).getNodeInstances();
String attachedTo = getEventNode().getAttachedToNodeId();
NodeInstance nodeInstance = getAttachedToNodeActive(nodeInstances, attachedTo, type, event);
Collection<NodeInstance> attachedNodeInstances = getAttachedToNodeActive(nodeInstances, attachedTo, type,
event);

List<DataAssociation> dataAssociation = getEventNode().getOutAssociations();
if(!dataAssociation.isEmpty()) {

Map<String, Object> outputData = new HashMap<>();
// this is for backward compatibility
outputData.put(dataAssociation.get(0).getSources().get(0), event);
// added normalized data
outputData.put("nodeInstance", nodeInstance);
outputData.put("signal", type);
outputData.put("event", event);
if(nodeInstance instanceof WorkItemNodeInstance) {
outputData.put("workItem", ((WorkItemNodeInstance) nodeInstance).getWorkItem());
}
if (!dataAssociation.isEmpty()) {

mapOutputSetVariables(this, getEventNode().getOutAssociations(), outputData);
for (NodeInstance nodeInstance : attachedNodeInstances) {
mapOutputData(dataAssociation, nodeInstance, type, event);
}
} else {
mapOutputData(dataAssociation, null, type, event);
}
triggerEvent(ExtendedNodeImpl.EVENT_NODE_BOUNDARY);
super.triggerCompleted();
}

private boolean isAttachedToNodeActive(Collection<NodeInstance> nodeInstances, String attachedTo, String type, Object event) {
return getAttachedToNodeActive(nodeInstances, attachedTo, type, event) != null;
return !getAttachedToNodeActive(nodeInstances, attachedTo, type, event).isEmpty();
}

private void mapOutputData(List<DataAssociation> dataAssociation, NodeInstance nodeInstance, String type,
Object event) {
Map<String, Object> outputData = new HashMap<>();
// this is for backward compatibility
outputData.put(dataAssociation.get(0).getSources().get(0), event);
// added normalized data
outputData.put("nodeInstance", nodeInstance);
outputData.put("signal", type);
outputData.put("event", event);
if (nodeInstance instanceof WorkItemNodeInstance) {
outputData.put("workItem", ((WorkItemNodeInstance) nodeInstance).getWorkItem());
}
mapOutputSetVariables(this, getEventNode().getOutAssociations(), outputData);
}


private NodeInstance getAttachedToNodeActive(Collection<NodeInstance> nodeInstances, String attachedTo, String type, Object event) {
private Collection<NodeInstance> getAttachedToNodeActive(Collection<NodeInstance> nodeInstances, String attachedTo,
String type, Object event) {
Collection<NodeInstance> result = new HashSet<>();
if (nodeInstances != null && !nodeInstances.isEmpty()) {
for (NodeInstance nInstance : nodeInstances) {
String nodeUniqueId = (String) nInstance.getNode().getMetaData().get("UniqueId");
Expand All @@ -100,21 +110,19 @@ private NodeInstance getAttachedToNodeActive(Collection<NodeInstance> nodeInstan
// in case this is timer event make sure it corresponds to the proper node instance
if (type.startsWith("Timer-")) {
if (Long.valueOf(nInstance.getId()).equals(event)) {
return nInstance;
result.add(nInstance);
}
} else {
return nInstance;
result.add(nInstance);
}
}
if (nInstance instanceof CompositeNodeInstance) {
NodeInstance nodeInstance = getAttachedToNodeActive(((CompositeNodeInstance) nInstance).getNodeInstances(), attachedTo, type, event);
if (nodeInstance != null) {
return nodeInstance;
}
else if (nInstance instanceof CompositeNodeInstance) {
result.addAll(getAttachedToNodeActive(((CompositeNodeInstance) nInstance).getNodeInstances(),
attachedTo, type, event));
}
}
}
return null;
return result;
}

private boolean isAttachedToNodeCompleted(String attachedTo) {
Expand Down

0 comments on commit a45c6f7

Please sign in to comment.