use of io.automatiko.engine.workflow.process.core.impl.NodeImpl in project automatiko-engine by automatiko-io.
the class CompositeNode method addIncomingConnection.
public void addIncomingConnection(String type, Connection connection) {
if (connection.getFrom().getParentContainer() == this) {
linkOutgoingConnections(connection.getFrom().getId(), connection.getFromType(), io.automatiko.engine.workflow.process.core.Node.CONNECTION_DEFAULT_TYPE);
} else {
super.addIncomingConnection(type, connection);
CompositeNode.NodeAndType inNode = internalGetLinkedIncomingNode(type);
if (inNode != null) {
CompositeNodeStart start = new CompositeNodeStart(this, connection.getFrom(), type);
internalAddNode(start);
NodeImpl node = (NodeImpl) inNode.getNode();
if (node != null) {
new ConnectionImpl(start, io.automatiko.engine.workflow.process.core.Node.CONNECTION_DEFAULT_TYPE, inNode.getNode(), inNode.getType());
}
}
}
}
use of io.automatiko.engine.workflow.process.core.impl.NodeImpl in project automatiko-engine by automatiko-io.
the class ProcessHandler method assignLanes.
private void assignLanes(NodeContainer nodeContainer, Map<String, String> laneMapping) {
for (Node node : nodeContainer.getNodes()) {
String lane = null;
String uniqueId = (String) node.getMetaData().get("UniqueId");
if (uniqueId != null) {
lane = laneMapping.get(uniqueId);
} else {
lane = laneMapping.get(XmlBPMNProcessDumper.getUniqueNodeId(node));
}
if (lane != null) {
((NodeImpl) node).setMetaData("Lane", lane);
if (node instanceof HumanTaskNode) {
((HumanTaskNode) node).setSwimlane(lane);
}
}
if (node instanceof NodeContainer) {
assignLanes((NodeContainer) node, laneMapping);
}
}
}
use of io.automatiko.engine.workflow.process.core.impl.NodeImpl in project automatiko-engine by automatiko-io.
the class ProcessHandler method handleIntermediateOrEndThrowCompensationEvent.
protected void handleIntermediateOrEndThrowCompensationEvent(ExtendedNodeImpl throwEventNode) {
if (throwEventNode.getMetaData("compensation-activityRef") != null) {
String activityRef = (String) throwEventNode.getMetaData().remove("compensation-activityRef");
NodeContainer nodeParent = (NodeContainer) throwEventNode.getParentContainer();
if (nodeParent instanceof EventSubProcessNode) {
boolean compensationEventSubProcess = false;
List<Trigger> startTriggers = ((EventSubProcessNode) nodeParent).findStartNode().getTriggers();
CESP_CHECK: for (Trigger trigger : startTriggers) {
if (trigger instanceof EventTrigger) {
for (EventFilter filter : ((EventTrigger) trigger).getEventFilters()) {
if (((EventTypeFilter) filter).getType().equals("Compensation")) {
compensationEventSubProcess = true;
break CESP_CHECK;
}
}
}
}
if (compensationEventSubProcess) {
// BPMN2 spec, p. 252, p. 248: intermediate and end compensation event
// visibility scope
nodeParent = (NodeContainer) ((NodeImpl) nodeParent).getParentContainer();
}
}
String parentId;
if (nodeParent instanceof ExecutableProcess) {
parentId = ((ExecutableProcess) nodeParent).getId();
} else {
parentId = (String) ((NodeImpl) nodeParent).getMetaData("UniqueId");
}
String compensationEvent;
if (activityRef.length() == 0) {
// general/implicit compensation
compensationEvent = CompensationScope.IMPLICIT_COMPENSATION_PREFIX + parentId;
} else {
// specific compensation
compensationEvent = activityRef;
}
throwEventNode.setMetaData("CompensationEvent", compensationEvent);
ConsequenceAction compensationAction = new ConsequenceAction("java", "");
compensationAction.setMetaData("Action", new ProcessInstanceCompensationAction(compensationEvent));
if (throwEventNode instanceof ActionNode) {
((ActionNode) throwEventNode).setAction(compensationAction);
} else if (throwEventNode instanceof EndNode) {
List<ProcessAction> actions = new ArrayList<ProcessAction>();
actions.add(compensationAction);
((EndNode) throwEventNode).setActions(EndNode.EVENT_NODE_ENTER, actions);
}
throwEventNode.setMetaData("TriggerType", "Compensation");
}
}
use of io.automatiko.engine.workflow.process.core.impl.NodeImpl in project automatiko-engine by automatiko-io.
the class ProcessHandler method linkAssociations.
public static void linkAssociations(Definitions definitions, NodeContainer nodeContainer, List<Association> associations) {
if (associations != null) {
for (Association association : associations) {
String sourceRef = association.getSourceRef();
Object source = null;
try {
source = findNodeOrDataStoreByUniqueId(definitions, nodeContainer, sourceRef, "Could not find source [" + sourceRef + "] for association " + association.getId() + "]");
} catch (IllegalArgumentException e) {
// source not found
}
String targetRef = association.getTargetRef();
Object target = null;
try {
target = findNodeOrDataStoreByUniqueId(definitions, nodeContainer, targetRef, "Could not find target [" + targetRef + "] for association [" + association.getId() + "]");
} catch (IllegalArgumentException e) {
// target not found
}
if (source == null || target == null) {
// TODO: ignoring this association for now
} else if (target instanceof DataStore || source instanceof DataStore) {
// TODO: ignoring data store associations for now
} else if (source instanceof EventNode) {
EventNode sourceNode = (EventNode) source;
Node targetNode = (Node) target;
checkBoundaryEventCompensationHandler(association, sourceNode, targetNode);
// make sure IsForCompensation is set to true on target
NodeImpl targetNodeImpl = (NodeImpl) target;
String isForCompensation = "isForCompensation";
Object compensationObject = targetNodeImpl.getMetaData(isForCompensation);
if (compensationObject == null) {
targetNodeImpl.setMetaData(isForCompensation, true);
logger.warn("Setting {} attribute to true for node {}", isForCompensation, targetRef);
} else if (!Boolean.parseBoolean(compensationObject.toString())) {
throw new IllegalArgumentException(isForCompensation + " attribute [" + compensationObject + "] should be true for Compensation Activity [" + targetRef + "]");
}
// put Compensation Handler in CompensationHandlerNode
NodeContainer sourceParent = sourceNode.getParentContainer();
NodeContainer targetParent = targetNode.getParentContainer();
if (!sourceParent.equals(targetParent)) {
throw new IllegalArgumentException("Compensation Associations may not cross (sub-)process boundaries,");
}
// connect boundary event to compensation activity
ConnectionImpl connection = new ConnectionImpl(sourceNode, NodeImpl.CONNECTION_DEFAULT_TYPE, targetNode, NodeImpl.CONNECTION_DEFAULT_TYPE);
connection.setMetaData("UniqueId", association.getId());
connection.setMetaData("hidden", true);
connection.setMetaData("association", true);
// Compensation use cases:
// - boundary event --associated-> activity
// - implicit sub process compensation handler + recursive?
/**
* BPMN2 spec, p.442: "A Compensation Event Sub-process becomes enabled when its
* parent Activity transitions into state Completed. At that time, a snapshot of
* the data associated with the parent Acitivity is taken and kept for later
* usage by the Compensation Event Sub-Process."
*/
}
}
}
}
use of io.automatiko.engine.workflow.process.core.impl.NodeImpl in project automatiko-engine by automatiko-io.
the class CompensationEventListener method signalEvent.
/**
* When signaling compensation, you can do that in 1 of 2 ways: 1.
* signalEvent("Compensation", <node-with-compensation-handler-id>) This is
* specific compensation, that only possibly triggers the compensation handler
* attached to the node referred to by the <node-with-compensation-handler-id>.
* 2. signalEvent("Compensation", "implicit:" +
* <node-container-containing-compensation-scope-id> ) This is implicit or
* general compensation, in which you trigger all visible compensation handlers
* (in the proper order, etc.) in the (sub-)process referred to by the
* <node-container-containing-compensation-scope-id>.
*/
public void signalEvent(String compensationType, Object activityRefStr) {
if (!(activityRefStr instanceof String)) {
throw new WorkflowRuntimeException(null, getProcessInstance(), "Compensation can only be triggered with String events, not an event of type " + (activityRefStr == null ? "null" : activityRefStr.getClass().getSimpleName()));
}
// 1. parse the activity ref (is it general or specific compensation?)
String activityRef = (String) activityRefStr;
String toCompensateNodeId = activityRef;
boolean generalCompensation = false;
if (activityRef.startsWith(IMPLICIT_COMPENSATION_PREFIX)) {
toCompensateNodeId = activityRef.substring(IMPLICIT_COMPENSATION_PREFIX.length());
generalCompensation = true;
}
io.automatiko.engine.workflow.base.core.Process process = (io.automatiko.engine.workflow.base.core.Process) instance.getProcess();
// 2. for specific compensation: find the node that will be compensated
// for general compensation: find the compensation scope container that contains
// all the visible compensation handlers
Node toCompensateNode = null;
ContextContainer compensationScopeContainer = null;
if (generalCompensation) {
if (toCompensateNodeId.equals(instance.getProcessId())) {
compensationScopeContainer = process;
} else {
compensationScopeContainer = (ContextContainer) findNode(toCompensateNodeId);
}
} else {
toCompensateNode = findNode(toCompensateNodeId);
}
// c. handle the exception (which also cleans up the generated node instances)
if (toCompensateNode != null || compensationScopeContainer != null) {
CompensationScope compensationScope = null;
if (compensationScopeContainer != null) {
compensationScope = (CompensationScope) compensationScopeContainer.getDefaultContext(COMPENSATION_SCOPE);
} else {
compensationScope = (CompensationScope) ((NodeImpl) toCompensateNode).resolveContext(COMPENSATION_SCOPE, toCompensateNodeId);
}
assert compensationScope != null : "Compensation scope for node [" + toCompensateNodeId + "] could not be found!";
CompensationScopeInstance scopeInstance;
if (compensationScope.getContextContainerId().equals(process.getId())) {
// process level compensation
scopeInstance = (CompensationScopeInstance) instance.getContextInstance(compensationScope);
} else {
// nested compensation
Stack<NodeInstance> generatedInstances;
if (toCompensateNode == null) {
// logic is the same if it's specific or general
generatedInstances = createNodeInstanceContainers((Node) compensationScopeContainer, true);
} else {
generatedInstances = createNodeInstanceContainers(toCompensateNode, false);
}
NodeInstance nodeInstanceContainer = generatedInstances.peek();
scopeInstance = ((CompensationScopeInstance) ((ContextInstanceContainer) nodeInstanceContainer).getContextInstance(compensationScope));
scopeInstance.addCompensationInstances(generatedInstances);
}
scopeInstance.handleException(null, activityRef, null);
}
}
Aggregations