use of io.automatiko.engine.workflow.process.core.node.CompositeNode in project automatiko-engine by automatiko-io.
the class NodeImpl method getUniqueId.
public String getUniqueId() {
String result = id + "";
NodeContainer nodeContainer = getParentContainer();
while (nodeContainer instanceof CompositeNode) {
CompositeNode composite = (CompositeNode) nodeContainer;
result = composite.getId() + ":" + result;
nodeContainer = composite.getParentContainer();
}
return result;
}
use of io.automatiko.engine.workflow.process.core.node.CompositeNode in project automatiko-engine by automatiko-io.
the class CompensationTest method createCompensationEventSubProcessProcess.
private ExecutableProcess createCompensationEventSubProcessProcess(String processId, String[] workItemNames, final List<String> eventList) throws Exception {
ExecutableProcess process = new ExecutableProcess();
process.setAutoComplete(true);
process.setId(processId);
process.setName("CESP Process");
process.setMetaData("Compensation", true);
NodeCreator<StartNode> startNodeCreator = new NodeCreator<StartNode>(process, StartNode.class);
NodeCreator<WorkItemNode> workItemNodeCreator = new NodeCreator<WorkItemNode>(process, WorkItemNode.class);
NodeCreator<CompositeContextNode> compNodeCreator = new NodeCreator<CompositeContextNode>(process, CompositeContextNode.class);
NodeCreator<EndNode> endNodeCreator = new NodeCreator<EndNode>(process, EndNode.class);
// outer process
StartNode startNode = startNodeCreator.createNode("start0");
WorkItemNode workItemNode = workItemNodeCreator.createNode("work0-pre");
workItemNode.getWork().setName(workItemNames[0]);
connect(startNode, workItemNode);
CompositeNode compositeNode = compNodeCreator.createNode("sub0");
connect(workItemNode, compositeNode);
workItemNode = workItemNodeCreator.createNode("work0-post");
workItemNode.getWork().setName(workItemNames[2]);
connect(compositeNode, workItemNode);
EndNode endNode = endNodeCreator.createNode("end0");
connect(workItemNode, endNode);
// 1rst level nested subprocess
startNodeCreator.setNodeContainer(compositeNode);
workItemNodeCreator.setNodeContainer(compositeNode);
endNodeCreator.setNodeContainer(compositeNode);
startNode = startNodeCreator.createNode("start1");
workItemNode = workItemNodeCreator.createNode("work1");
workItemNode.getWork().setName(workItemNames[1]);
connect(startNode, workItemNode);
endNode = endNodeCreator.createNode("end1");
connect(workItemNode, endNode);
// 2nd level nested event subprocess in 1rst level subprocess
NodeCreator<EventSubProcessNode> espNodeCreator = new NodeCreator<EventSubProcessNode>(compositeNode, EventSubProcessNode.class);
EventSubProcessNode espNode = espNodeCreator.createNode("eventSub1");
EventTypeFilter eventFilter = new NonAcceptingEventTypeFilter();
eventFilter.setType("Compensation");
espNode.addEvent(eventFilter);
addCompensationScope(espNode, process, (String) compositeNode.getMetaData("UniqueId"));
startNodeCreator.setNodeContainer(espNode);
endNodeCreator.setNodeContainer(espNode);
NodeCreator<ActionNode> actionNodeCreator = new NodeCreator<ActionNode>(espNode, ActionNode.class);
startNode = startNodeCreator.createNode("start1*");
ActionNode actionNode = actionNodeCreator.createNode("action1*");
actionNode.setName("Execute");
ProcessAction action = new ConsequenceAction("java", null);
action.setMetaData("Action", new Action() {
public void execute(ProcessContext context) throws Exception {
eventList.add("Executed action");
}
});
actionNode.setAction(action);
connect(startNode, actionNode);
endNode = endNodeCreator.createNode("end1*");
connect(actionNode, endNode);
return process;
}
use of io.automatiko.engine.workflow.process.core.node.CompositeNode in project automatiko-engine by automatiko-io.
the class CompensationTest method createNestedCompensationBoundaryEventProcess.
private ExecutableProcess createNestedCompensationBoundaryEventProcess(String processId, String[] workItemNames, final List<String> eventList) throws Exception {
ExecutableProcess process = new ExecutableProcess();
process.setAutoComplete(true);
process.setId(processId);
process.setName("CESP Process");
process.setMetaData("Compensation", true);
List<Variable> variables = new ArrayList<Variable>();
Variable variable = new Variable();
variable.setName("event");
ObjectDataType personDataType = new ObjectDataType(java.lang.String.class);
variable.setType(personDataType);
variables.add(variable);
process.getVariableScope().setVariables(variables);
NodeCreator<StartNode> startNodeCreator = new NodeCreator<StartNode>(process, StartNode.class);
NodeCreator<EndNode> endNodeCreator = new NodeCreator<EndNode>(process, EndNode.class);
NodeCreator<CompositeContextNode> compNodeCreator = new NodeCreator<CompositeContextNode>(process, CompositeContextNode.class);
// process level
CompositeContextNode compositeNode = compNodeCreator.createNode("sub0");
{
StartNode startNode = startNodeCreator.createNode("start0");
connect(startNode, compositeNode);
EndNode endNode = endNodeCreator.createNode("end0");
connect(compositeNode, endNode);
}
// 1rst level nested subprocess (contains compensation visibility scope)
{
startNodeCreator.setNodeContainer(compositeNode);
compNodeCreator.setNodeContainer(compositeNode);
endNodeCreator.setNodeContainer(compositeNode);
StartNode startNode = startNodeCreator.createNode("start1");
CompositeContextNode subCompNode = compNodeCreator.createNode("sub1");
connect(startNode, subCompNode);
EndNode endNode = endNodeCreator.createNode("end1");
connect(subCompNode, endNode);
compositeNode = subCompNode;
}
// 2nd level nested subprocess (contains compensation visibility scope)
NodeCreator<WorkItemNode> workItemNodeCreator = new NodeCreator<WorkItemNode>(compositeNode, WorkItemNode.class);
{
startNodeCreator.setNodeContainer(compositeNode);
compNodeCreator.setNodeContainer(compositeNode);
endNodeCreator.setNodeContainer(compositeNode);
StartNode startNode = startNodeCreator.createNode("start2");
CompositeContextNode subCompNode = compNodeCreator.createNode("sub2");
connect(startNode, subCompNode);
WorkItemNode workItemNode = workItemNodeCreator.createNode("work2");
workItemNode.getWork().setName(workItemNames[2]);
connect(subCompNode, workItemNode);
EndNode endNode = endNodeCreator.createNode("end2");
connect(workItemNode, endNode);
createBoundaryEventCompensationHandler(compositeNode, workItemNode, eventList, "2");
compositeNode = subCompNode;
}
// Fill 3rd level with process with compensation
{
startNodeCreator.setNodeContainer(compositeNode);
workItemNodeCreator.setNodeContainer(compositeNode);
endNodeCreator.setNodeContainer(compositeNode);
StartNode startNode = startNodeCreator.createNode("start");
Node lastNode = startNode;
WorkItemNode[] workItemNodes = new WorkItemNode[3];
for (int i = 0; i < 2; ++i) {
workItemNodes[i] = workItemNodeCreator.createNode("work-comp-" + (i + 1));
workItemNodes[i].getWork().setName(workItemNames[i]);
connect(lastNode, workItemNodes[i]);
lastNode = workItemNodes[i];
}
EndNode endNode = endNodeCreator.createNode("end");
connect(workItemNodes[1], endNode);
// Compensation (boundary event) handlers
for (int i = 0; i < 2; ++i) {
createBoundaryEventCompensationHandler(compositeNode, workItemNodes[i], eventList, "" + i + 1);
}
}
return process;
}
use of io.automatiko.engine.workflow.process.core.node.CompositeNode in project automatiko-engine by automatiko-io.
the class WorkflowProcessInstanceImpl method getEventDescriptions.
@Override
public Set<EventDescription<?>> getEventDescriptions() {
if (getState() == ProcessInstance.STATE_COMPLETED || getState() == ProcessInstance.STATE_ABORTED) {
return Collections.emptySet();
}
VariableScope variableScope = (VariableScope) ((ContextContainer) getProcess()).getDefaultContext(VariableScope.VARIABLE_SCOPE);
Set<EventDescription<?>> eventDesciptions = new LinkedHashSet<>();
List<EventListener> activeListeners = eventListeners.values().stream().flatMap(List::stream).collect(Collectors.toList());
activeListeners.addAll(externalEventListeners.values().stream().flatMap(List::stream).collect(Collectors.toList()));
activeListeners.forEach(el -> eventDesciptions.addAll(el.getEventDescriptions()));
((io.automatiko.engine.workflow.process.core.WorkflowProcess) getProcess()).getNodesRecursively().stream().filter(n -> n instanceof EventNodeInterface).forEach(n -> {
NamedDataType dataType = null;
if (((EventNodeInterface) n).getVariableName() != null) {
Map<String, Object> dataOutputs = (Map<String, Object>) n.getMetaData().get("DataOutputs");
if (dataOutputs != null) {
for (Entry<String, Object> dOut : dataOutputs.entrySet()) {
dataType = new NamedDataType(dOut.getKey(), dOut.getValue());
}
} else {
Variable eventVar = variableScope.findVariable(((EventNodeInterface) n).getVariableName());
if (eventVar != null) {
dataType = new NamedDataType(eventVar.getName(), eventVar.getType());
}
}
}
if (n instanceof BoundaryEventNode) {
BoundaryEventNode boundaryEventNode = (BoundaryEventNode) n;
StateBasedNodeInstance attachedToNodeInstance = (StateBasedNodeInstance) getNodeInstances(true).stream().filter(ni -> ni.getNode().getMetaData().get(UNIQUE_ID).equals(boundaryEventNode.getAttachedToNodeId())).findFirst().orElse(null);
if (attachedToNodeInstance != null) {
Map<String, String> properties = new HashMap<>();
properties.put("AttachedToID", attachedToNodeInstance.getNodeDefinitionId());
properties.put("AttachedToName", attachedToNodeInstance.getNodeName());
String eventType = EVENT_TYPE_SIGNAL;
String eventName = boundaryEventNode.getType();
Map<String, String> timerProperties = attachedToNodeInstance.extractTimerEventInformation();
if (timerProperties != null) {
properties.putAll(timerProperties);
eventType = "timer";
eventName = "timerTriggered";
}
eventDesciptions.add(new BaseEventDescription(eventName, (String) n.getMetaData().get(UNIQUE_ID), n.getName(), eventType, null, getId(), dataType, properties));
}
} else if (n instanceof EventSubProcessNode) {
EventSubProcessNode eventSubProcessNode = (EventSubProcessNode) n;
boolean isContainerActive = false;
if (eventSubProcessNode.getParentContainer() instanceof WorkflowProcess) {
isContainerActive = true;
} else if (eventSubProcessNode.getParentContainer() instanceof CompositeNode) {
isContainerActive = !getNodeInstances(((CompositeNode) eventSubProcessNode.getParentContainer()).getId()).isEmpty();
}
if (isContainerActive) {
Node startNode = eventSubProcessNode.findStartNode();
Map<Timer, ProcessAction> timers = eventSubProcessNode.getTimers();
if (timers != null && !timers.isEmpty()) {
getNodeInstances(eventSubProcessNode.getId()).forEach(ni -> {
Map<String, String> timerProperties = ((StateBasedNodeInstance) ni).extractTimerEventInformation();
if (timerProperties != null) {
eventDesciptions.add(new BaseEventDescription("timerTriggered", (String) startNode.getMetaData().get("UniqueId"), startNode.getName(), "timer", ni.getId(), getId(), null, timerProperties));
}
});
} else {
for (String eventName : eventSubProcessNode.getEvents()) {
if ("variableChanged".equals(eventName)) {
continue;
}
eventDesciptions.add(new BaseEventDescription(eventName, (String) startNode.getMetaData().get("UniqueId"), startNode.getName(), "signal", null, getId(), dataType));
}
}
}
} else if (n instanceof EventNode) {
NamedDataType finalDataType = dataType;
getNodeInstances(n.getId()).forEach(ni -> eventDesciptions.add(new BaseEventDescription(((EventNode) n).getType(), (String) n.getMetaData().get(UNIQUE_ID), n.getName(), (String) n.getMetaData().getOrDefault(EVENT_TYPE, EVENT_TYPE_SIGNAL), ni.getId(), getId(), finalDataType)));
} else if (n instanceof StateNode) {
getNodeInstances(n.getId()).forEach(ni -> eventDesciptions.add(new BaseEventDescription((String) n.getMetaData().get(CONDITION), (String) n.getMetaData().get(UNIQUE_ID), n.getName(), (String) n.getMetaData().getOrDefault(EVENT_TYPE, EVENT_TYPE_SIGNAL), ni.getId(), getId(), null)));
}
});
return eventDesciptions;
}
use of io.automatiko.engine.workflow.process.core.node.CompositeNode in project automatiko-engine by automatiko-io.
the class WorkflowProcessInstanceImpl method signalEvent.
@Override
@SuppressWarnings("unchecked")
public void signalEvent(String type, Object event) {
logger.debug("Signal {} received with data {} in process instance {}", type, event, getId());
synchronized (this) {
if (getState() != ProcessInstance.STATE_ACTIVE) {
return;
}
InternalProcessRuntime processRuntime = getProcessRuntime();
processRuntime.getProcessEventSupport().fireBeforeProcessSignaled(type, event, this, processRuntime);
if ("timerTriggered".equals(type)) {
TimerInstance timer = (TimerInstance) event;
if (timer.getId().equals(slaTimerId)) {
handleSLAViolation();
// no need to pass the event along as it was purely for SLA tracking
return;
}
}
if ("slaViolation".equals(type)) {
handleSLAViolation();
// no need to pass the event along as it was purely for SLA tracking
return;
}
List<NodeInstance> currentView = new ArrayList<>(this.nodeInstances);
try {
this.activatingNodeIds = new ArrayList<>();
List<EventListener> listeners = eventListeners.get(type);
if (listeners != null) {
for (EventListener listener : listeners) {
listener.signalEvent(type, event);
}
}
listeners = externalEventListeners.get(type);
if (listeners != null) {
for (EventListener listener : listeners) {
listener.signalEvent(type, event);
}
}
if (!type.startsWith("Compensation")) {
for (Node node : getWorkflowProcess().getNodes()) {
if (node instanceof EventNodeInterface && ((EventNodeInterface) node).acceptsEvent(type, event, getResolver(node, currentView))) {
if (node instanceof EventNode && ((EventNode) node).getFrom() == null) {
EventNodeInstance eventNodeInstance = (EventNodeInstance) getNodeInstance(node);
eventNodeInstance.signalEvent(type, event);
} else {
if (node instanceof EventSubProcessNode && (resolveVariables(((EventSubProcessNode) node).getEvents()).contains(type))) {
EventSubProcessNodeInstance eventNodeInstance = (EventSubProcessNodeInstance) getNodeInstance(node);
eventNodeInstance.signalEvent(type, event);
} else {
List<NodeInstance> nodeInstances = getNodeInstances(node.getId(), currentView);
if (nodeInstances != null && !nodeInstances.isEmpty()) {
for (NodeInstance nodeInstance : nodeInstances) {
((EventNodeInstanceInterface) nodeInstance).signalEvent(type, event);
}
}
}
}
} else if (node instanceof StartNode && ((StartNode) node).getTriggers() != null) {
boolean accepted = ((StartNode) node).getTriggers().stream().filter(EventTrigger.class::isInstance).anyMatch(t -> ((EventTrigger) t).getEventFilters().stream().anyMatch(e -> e.acceptsEvent(type, event)));
if (accepted && node.getMetaData().get("acceptStartSignal") != null) {
StartNodeInstance startNodeInstance = (StartNodeInstance) getNodeInstance(node);
startNodeInstance.signalEvent(type, event);
}
}
}
if (((io.automatiko.engine.workflow.process.core.WorkflowProcess) getWorkflowProcess()).isDynamic()) {
for (Node node : getWorkflowProcess().getNodes()) {
if (node.hasMatchingEventListner(type) && node.getIncomingConnections().isEmpty()) {
NodeInstance nodeInstance = getNodeInstance(node);
if (nodeInstance != null) {
if (event != null) {
Map<String, Object> dynamicParams = new HashMap<>(getVariables());
if (event instanceof Map) {
dynamicParams.putAll((Map<String, Object>) event);
} else if (event instanceof WorkflowProcessInstance) {
// ignore variables of process instance type
} else {
dynamicParams.put("Data", event);
}
nodeInstance.setDynamicParameters(dynamicParams);
}
nodeInstance.trigger(null, io.automatiko.engine.workflow.process.core.Node.CONNECTION_DEFAULT_TYPE);
}
} else if (this instanceof ExecutableProcessInstance && node instanceof CompositeNode) {
Optional<NodeInstance> instance = this.nodeInstances.stream().filter(ni -> ni.getNodeId() == node.getId()).findFirst();
instance.ifPresent(n -> ((CompositeNodeInstance) n).signalEvent(type, event));
}
}
}
}
} finally {
processRuntime.getProcessEventSupport().fireAfterProcessSignaled(type, event, this, processRuntime);
if (this.activatingNodeIds != null) {
this.activatingNodeIds.clear();
this.activatingNodeIds = null;
}
}
}
}
Aggregations