use of io.automatiko.engine.workflow.process.instance.NodeInstanceContainer in project automatiko-engine by automatiko-io.
the class CompensationScopeInstance method handleException.
public void handleException(io.automatiko.engine.api.runtime.process.NodeInstance nodeInstance, String activityRef, Object dunno) {
assert activityRef != null : "It should not be possible for the compensation activity reference to be null here.";
CompensationScope compensationScope = (CompensationScope) getExceptionScope();
// broadcast/general compensation in reverse order
if (activityRef.startsWith(IMPLICIT_COMPENSATION_PREFIX)) {
activityRef = activityRef.substring(IMPLICIT_COMPENSATION_PREFIX.length());
assert activityRef.equals(compensationScope.getContextContainerId()) : "Compensation activity ref [" + activityRef + "] does not match" + " Compensation Scope container id [" + compensationScope.getContextContainerId() + "]";
Map<String, ExceptionHandler> handlers = compensationScope.getExceptionHandlers();
List<String> completedNodeIds = ((WorkflowProcessInstanceImpl) getProcessInstance()).getCompletedNodeIds();
ListIterator<String> iter = completedNodeIds.listIterator(completedNodeIds.size());
while (iter.hasPrevious()) {
String completedId = iter.previous();
ExceptionHandler handler = handlers.get(completedId);
if (handler != null) {
handleException(nodeInstance, handler, completedId, null);
}
}
} else {
// Specific compensation
ExceptionHandler handler = compensationScope.getExceptionHandler(activityRef);
if (handler == null) {
throw new IllegalArgumentException("Could not find CompensationHandler for " + activityRef);
}
handleException(nodeInstance, handler, activityRef, null);
}
// Cancel all node instances created for compensation
while (!compensationInstances.isEmpty()) {
NodeInstance generatedInstance = compensationInstances.pop();
((NodeInstanceContainer) generatedInstance.getNodeInstanceContainer()).removeNodeInstance(generatedInstance);
}
}
use of io.automatiko.engine.workflow.process.instance.NodeInstanceContainer in project automatiko-engine by automatiko-io.
the class CompensationScopeInstance method handleException.
public void handleException(io.automatiko.engine.api.runtime.process.NodeInstance nodeInstance, ExceptionHandler handler, String compensationActivityRef, Object dunno) {
WorkflowProcessInstanceImpl processInstance = (WorkflowProcessInstanceImpl) getProcessInstance();
NodeInstanceContainer nodeInstanceContainer = (NodeInstanceContainer) getContextInstanceContainer();
if (handler instanceof CompensationHandler) {
CompensationHandler compensationHandler = (CompensationHandler) handler;
try {
Node handlerNode = compensationHandler.getnode();
if (handlerNode instanceof BoundaryEventNode) {
NodeInstance compensationHandlerNodeInstance = nodeInstanceContainer.getNodeInstance(handlerNode);
compensationInstances.add(compensationHandlerNodeInstance);
// The BoundaryEventNodeInstance.signalEvent() contains the necessary logic
// to check whether or not compensation may proceed (? : (not-active +
// completed))
EventNodeInstance eventNodeInstance = (EventNodeInstance) compensationHandlerNodeInstance;
eventNodeInstance.signalEvent("Compensation", compensationActivityRef);
} else if (handlerNode instanceof EventSubProcessNode) {
// Check that subprocess parent has completed.
List<String> completedIds = processInstance.getCompletedNodeIds();
if (completedIds.contains(((NodeImpl) handlerNode.getParentContainer()).getMetaData("UniqueId"))) {
NodeInstance subProcessNodeInstance = ((NodeInstanceContainer) nodeInstanceContainer).getNodeInstance((Node) handlerNode.getParentContainer());
compensationInstances.add(subProcessNodeInstance);
NodeInstance compensationHandlerNodeInstance = ((NodeInstanceContainer) subProcessNodeInstance).getNodeInstance(handlerNode);
compensationInstances.add(compensationHandlerNodeInstance);
EventSubProcessNodeInstance eventNodeInstance = (EventSubProcessNodeInstance) compensationHandlerNodeInstance;
eventNodeInstance.signalEvent("Compensation", compensationActivityRef);
}
}
assert handlerNode instanceof BoundaryEventNode || handlerNode instanceof EventSubProcessNode : "Unexpected compensation handler node type : " + handlerNode.getClass().getSimpleName();
} catch (Exception e) {
throwWorkflowRuntimeException(nodeInstanceContainer, processInstance, "Unable to execute compensation.", e);
}
} else {
Exception e = new IllegalArgumentException("Unsupported compensation handler: " + handler);
throwWorkflowRuntimeException(nodeInstanceContainer, processInstance, e.getMessage(), e);
}
}
use of io.automatiko.engine.workflow.process.instance.NodeInstanceContainer in project automatiko-engine by automatiko-io.
the class BoundaryEventNodeInstance method signalEvent.
@Override
public void signalEvent(String type, Object event) {
BoundaryEventNode boundaryNode = (BoundaryEventNode) getEventNode();
String attachedTo = boundaryNode.getAttachedToNodeId();
Collection<NodeInstance> nodeInstances = ((NodeInstanceContainer) getProcessInstance()).getNodeInstances(true);
if (type != null && type.startsWith("Compensation")) {
// if not active && completed, signal
if (!isAttachedToNodeActive(nodeInstances, attachedTo, type, event) && isAttachedToNodeCompleted(attachedTo)) {
super.signalEvent(type, event);
} else {
cancel();
}
} else {
if (isAttachedToNodeActive(nodeInstances, attachedTo, type, event)) {
super.signalEvent(type, event);
} else {
cancel();
}
}
}
use of io.automatiko.engine.workflow.process.instance.NodeInstanceContainer in project automatiko-engine by automatiko-io.
the class EndNodeInstance method internalTrigger.
public void internalTrigger(final NodeInstance from, String type) {
super.internalTrigger(from, type);
if (!io.automatiko.engine.workflow.process.core.Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
throw new IllegalArgumentException("An EndNode only accepts default incoming connections!");
}
leaveTime = new Date();
boolean hidden = false;
if (getNode().getMetaData().get(HIDDEN) != null) {
hidden = true;
}
if (getProcessInstance().isFunctionFlow(this) && getNodeInstanceContainer() instanceof ProcessInstance) {
// only when running as function flow and node is in the top level node container meaning process instance
// and not subprocesses
getProcessInstance().getMetaData().compute("ATK_FUNC_FLOW_NEXT", (k, v) -> {
if (v == null) {
v = new ArrayList<String>();
}
Process process = getProcessInstance().getProcess();
String version = "";
if (process.getVersion() != null && !process.getVersion().trim().isEmpty()) {
version = ".v" + process.getVersion().replaceAll("\\.", "_");
}
String defaultNextNode = process.getPackageName() + "." + process.getId() + version + "." + getNodeName().toLowerCase();
((List<String>) v).add((String) getNode().getMetaData().getOrDefault("functionType", defaultNextNode));
return v;
});
}
InternalProcessRuntime runtime = getProcessInstance().getProcessRuntime();
if (!hidden) {
runtime.getProcessEventSupport().fireBeforeNodeLeft(this, runtime);
}
((NodeInstanceContainer) getNodeInstanceContainer()).removeNodeInstance(this);
if (getEndNode().isTerminate()) {
if (getNodeInstanceContainer() instanceof CompositeNodeInstance) {
if (getEndNode().getScope() == PROCESS_SCOPE) {
getProcessInstance().setState(STATE_COMPLETED);
} else {
while (!getNodeInstanceContainer().getNodeInstances().isEmpty()) {
((io.automatiko.engine.workflow.process.instance.NodeInstance) getNodeInstanceContainer().getNodeInstances().iterator().next()).cancel();
}
((NodeInstanceContainer) getNodeInstanceContainer()).nodeInstanceCompleted(this, null);
}
} else {
((NodeInstanceContainer) getNodeInstanceContainer()).setState(STATE_COMPLETED);
}
} else {
((NodeInstanceContainer) getNodeInstanceContainer()).nodeInstanceCompleted(this, null);
}
if (!hidden) {
runtime.getProcessEventSupport().fireAfterNodeLeft(this, runtime);
}
String uniqueId = (String) getNode().getMetaData().get(UNIQUE_ID);
if (uniqueId == null) {
uniqueId = ((NodeImpl) getNode()).getUniqueId();
}
((WorkflowProcessInstanceImpl) getProcessInstance()).addCompletedNodeId(uniqueId);
}
use of io.automatiko.engine.workflow.process.instance.NodeInstanceContainer in project automatiko-engine by automatiko-io.
the class SplitInstance method executeStrategy.
protected void executeStrategy(Split split, String type) {
// TODO make different strategies for each type
String uniqueId = (String) getNode().getMetaData().get(UNIQUE_ID);
if (uniqueId == null) {
uniqueId = ((NodeImpl) getNode()).getUniqueId();
}
switch(split.getType()) {
case Split.TYPE_AND:
triggerCompleted(io.automatiko.engine.workflow.process.core.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 = (Connection) iterator.next();
ConstraintEvaluator constraint = (ConstraintEvaluator) split.getConstraint(connection);
if (constraint != null && constraint.getPriority() < priority && !constraint.isDefault()) {
try {
if (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 = (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);
((WorkflowProcessInstanceImpl) getProcessInstance()).addCompletedNodeId(uniqueId);
break;
case Split.TYPE_OR:
((NodeInstanceContainer) getNodeInstanceContainer()).removeNodeInstance(this);
outgoing = split.getDefaultOutgoingConnections();
boolean found = false;
List<NodeInstanceTrigger> nodeInstances = new ArrayList<NodeInstanceTrigger>();
List<Connection> outgoingCopy = new ArrayList<Connection>(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 = (Connection) iterator.next();
ConstraintEvaluator constraint = (ConstraintEvaluator) split.getConstraint(connection);
if (constraint != null && constraint.getPriority() < priority && !constraint.isDefault()) {
priority = constraint.getPriority();
selectedConnection = connection;
selectedConstraint = 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() == STATE_COMPLETED || getProcessInstance().getState() == STATE_ABORTED) {
return;
}
triggerNodeInstance(nodeInstance.getNodeInstance(), nodeInstance.getToType());
}
if (!found) {
for (final Iterator<Connection> iterator = outgoing.iterator(); iterator.hasNext(); ) {
final Connection connection = (Connection) iterator.next();
ConstraintEvaluator constraint = (ConstraintEvaluator) split.getConstraint(connection);
if (constraint != null && constraint.isDefault() || split.isDefault(connection)) {
triggerConnection(connection);
found = true;
break;
}
}
}
if (!found) {
throw new IllegalArgumentException("OR split could not find at least one valid outgoing connection for split " + getSplit().getName());
}
((WorkflowProcessInstanceImpl) getProcessInstance()).addCompletedNodeId(uniqueId);
break;
case Split.TYPE_XAND:
((io.automatiko.engine.workflow.process.instance.NodeInstanceContainer) getNodeInstanceContainer()).removeNodeInstance(this);
Node node = getNode();
List<Connection> connections = null;
if (node != null) {
connections = node.getOutgoingConnections(type);
}
if (connections == null || connections.isEmpty()) {
((io.automatiko.engine.workflow.process.instance.NodeInstanceContainer) getNodeInstanceContainer()).nodeInstanceCompleted(this, type);
} else {
ExclusiveGroupInstance groupInstance = new ExclusiveGroupInstance();
io.automatiko.engine.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<io.automatiko.engine.workflow.process.instance.NodeInstance, String> nodeInstancesMap = new HashMap<io.automatiko.engine.workflow.process.instance.NodeInstance, String>();
for (Connection connection : connections) {
nodeInstancesMap.put(followConnection(connection), connection.getToType());
}
for (NodeInstance nodeInstance : nodeInstancesMap.keySet()) {
groupInstance.addNodeInstance(nodeInstance);
}
for (Map.Entry<io.automatiko.engine.workflow.process.instance.NodeInstance, String> entry : nodeInstancesMap.entrySet()) {
// stop if this process instance has been aborted / completed
if (getProcessInstance().getState() != ProcessInstance.STATE_ACTIVE) {
return;
}
boolean hidden = false;
if (getNode().getMetaData().get("hidden") != null) {
hidden = true;
}
InternalProcessRuntime runtime = getProcessInstance().getProcessRuntime();
if (!hidden) {
runtime.getProcessEventSupport().fireBeforeNodeLeft(this, runtime);
}
((io.automatiko.engine.workflow.process.instance.NodeInstance) entry.getKey()).trigger(this, entry.getValue());
if (!hidden) {
runtime.getProcessEventSupport().fireAfterNodeLeft(this, runtime);
}
}
}
((WorkflowProcessInstanceImpl) getProcessInstance()).addCompletedNodeId(uniqueId);
break;
default:
throw new IllegalArgumentException("Illegal split type " + split.getType());
}
}
Aggregations