use of io.automatiko.engine.workflow.process.core.node.CompositeContextNode in project automatiko-engine by automatiko-io.
the class CompositeContextNodeHandler method writeNode.
public void writeNode(Node node, StringBuilder xmlDump, int metaDataType) {
CompositeContextNode compositeNode = (CompositeContextNode) node;
String nodeType = "subProcess";
if (node.getMetaData().get("Transaction") != null) {
nodeType = "transaction";
}
writeNode(nodeType, compositeNode, xmlDump, metaDataType);
if (compositeNode instanceof EventSubProcessNode) {
xmlDump.append(" triggeredByEvent=\"true\" ");
}
Object isForCompensationObject = compositeNode.getMetaData("isForCompensation");
if (isForCompensationObject != null && ((Boolean) isForCompensationObject)) {
xmlDump.append("isForCompensation=\"true\" ");
}
xmlDump.append(">" + EOL);
writeExtensionElements(compositeNode, xmlDump);
// variables
VariableScope variableScope = (VariableScope) compositeNode.getDefaultContext(VariableScope.VARIABLE_SCOPE);
if (variableScope != null && !variableScope.getVariables().isEmpty()) {
xmlDump.append(" <!-- variables -->" + EOL);
for (Variable variable : variableScope.getVariables()) {
xmlDump.append(" <property id=\"" + XmlBPMNProcessDumper.replaceIllegalCharsAttribute(variable.getName()) + "\" ");
if (variable.getType() != null) {
xmlDump.append("itemSubjectRef=\"" + XmlBPMNProcessDumper.getUniqueNodeId(compositeNode) + "-" + XmlBPMNProcessDumper.replaceIllegalCharsAttribute(variable.getName()) + "Item\"");
}
// TODO: value
xmlDump.append("/>" + EOL);
}
}
// nodes
List<Node> subNodes = getSubNodes(compositeNode);
XmlBPMNProcessDumper.INSTANCE.visitNodes(subNodes, xmlDump, metaDataType);
// connections
visitConnectionsAndAssociations(compositeNode, xmlDump, metaDataType);
endNode(nodeType, xmlDump);
}
use of io.automatiko.engine.workflow.process.core.node.CompositeContextNode in project automatiko-engine by automatiko-io.
the class ServerlessWorkflowParser method addErrorHandlingToState.
protected void addErrorHandlingToState(Workflow workflow, State state, ServerlessWorkflowFactory factory, AtomicLong ids, WorkflowProcess process, CompositeContextNode subprocess) {
if (state.getOnErrors() != null) {
for (io.serverlessworkflow.api.error.Error error : state.getOnErrors()) {
List<ErrorDefinition> defs = new ArrayList<>();
if (error.getErrorRef() != null) {
workflow.getErrors().getErrorDefs().stream().filter(err -> err.getName().equals(error.getErrorRef())).forEach(err -> defs.add(err));
} else {
workflow.getErrors().getErrorDefs().stream().filter(err -> error.getErrorRefs().contains(err.getName())).forEach(err -> defs.add(err));
}
BoundaryEventNode errorNode = factory.errorBoundaryEventNode(ids.getAndIncrement(), defs, null, process, subprocess, workflow);
if (error.getEnd() != null) {
EndNode onErrorEnd = factory.endNode(ids.getAndIncrement(), state.getName() + "onErrorEnd", error.getEnd().isTerminate(), process);
if (error.getEnd().getProduceEvents() != null && !error.getEnd().getProduceEvents().isEmpty()) {
produceEvents(error.getEnd().getProduceEvents(), factory, workflow, ids, process, errorNode.getId(), onErrorEnd.getId());
} else {
factory.connect(errorNode.getId(), onErrorEnd.getId(), "connect_" + errorNode.getId() + "_" + onErrorEnd.getId(), process, false);
}
} else {
if (error.getTransition().getNextState() != null) {
for (io.automatiko.engine.api.definition.process.Node node : process.getNodes()) {
if (node.getName().equals(error.getTransition().getNextState())) {
if (error.getTransition().getProduceEvents() != null && !error.getTransition().getProduceEvents().isEmpty()) {
produceEvents(error.getTransition().getProduceEvents(), factory, workflow, ids, process, errorNode.getId(), node.getId());
} else {
factory.connect(errorNode.getId(), node.getId(), "connect_" + errorNode.getId() + "_" + node.getId(), process, false);
}
break;
}
}
}
}
}
}
}
use of io.automatiko.engine.workflow.process.core.node.CompositeContextNode in project automatiko-engine by automatiko-io.
the class ServerlessWorkflowParser method parse.
public Process parse(Reader workflowFile) {
AtomicLong ids = new AtomicLong(0);
Workflow workflow = Workflow.fromSource(toString(workflowFile));
ServerlessWorkflowFactory factory = new ServerlessWorkflowFactory();
if (!"jq".equalsIgnoreCase(workflow.getExpressionLang())) {
throw new IllegalArgumentException("Not supported expression language, only 'jq' is supported");
}
WorkflowProcess process = factory.createProcess(workflow);
State start = WorkflowUtils.getStartingState(workflow);
Node startNode;
if (start.getType().equals(DefaultState.Type.EVENT)) {
List<Node> nodes = new ArrayList<>();
EventState eventState = (EventState) start;
for (OnEvents onEvent : eventState.getOnEvents()) {
if (eventState.isExclusive()) {
// use event based gateway
Join join = factory.joinNode(ids.getAndIncrement(), "join_" + eventState.getName(), Join.TYPE_XOR, process);
for (String eventRef : onEvent.getEventRefs()) {
EventDefinition event = WorkflowUtils.getDefinedConsumedEvents(workflow).stream().filter(e -> e.getName().equals(eventRef)).findFirst().get();
StartNode startMessageNode = factory.messageStartNode(ids.getAndIncrement(), event, onEvent, process);
factory.connect(startMessageNode.getId(), join.getId(), "connection_" + startMessageNode.getId() + "_" + join.getId(), process, false);
}
buildActionsForState(workflow, onEvent.getActions(), process, factory, ids, (first, last) -> {
factory.connect(join.getId(), first.getId(), join.getId() + "_" + first.getId(), process, false);
nodes.add(last);
}, (first, last) -> {
}, false);
} else {
// use parallel gateway
Join parallelJoin = factory.joinNode(ids.getAndIncrement(), "join_" + eventState.getName(), Join.TYPE_AND, process);
for (String eventRef : onEvent.getEventRefs()) {
EventDefinition event = WorkflowUtils.getDefinedConsumedEvents(workflow).stream().filter(e -> e.getName().equals(eventRef)).findFirst().get();
StartNode startMessageNode = factory.messageStartNode(ids.getAndIncrement(), event, onEvent, process);
factory.connect(startMessageNode.getId(), parallelJoin.getId(), "connection_" + startMessageNode.getId() + "_" + parallelJoin.getId(), process, false);
}
buildActionsForState(workflow, onEvent.getActions(), process, factory, ids, (first, last) -> {
factory.connect(parallelJoin.getId(), first.getId(), parallelJoin.getId() + "_" + first.getId(), process, false);
nodes.add(last);
}, (first, last) -> {
}, false);
}
}
// start node becomes the last node after message event handling so other parts are connected to it
startNode = nodes.get(0);
if (eventState.getStateDataFilter() != null && eventState.getStateDataFilter().getOutput() != null) {
ActionNode stateDataFilterActionNode = factory.stateDataFilterActionNode(ids.getAndIncrement(), "", process, eventState.getStateDataFilter().getOutput());
factory.connect(startNode.getId(), stateDataFilterActionNode.getId(), "connection_" + startNode.getId() + "_" + stateDataFilterActionNode.getId(), process, false);
startNode = stateDataFilterActionNode;
}
if (eventState.getEnd() != null) {
EndNode endNode = factory.endNode(ids.getAndIncrement(), eventState.getName() + "-end", eventState.getEnd().isTerminate(), process);
if (eventState.getEnd().getProduceEvents() != null && !eventState.getEnd().getProduceEvents().isEmpty()) {
produceEvents(eventState.getEnd().getProduceEvents(), factory, workflow, ids, process, startNode.getId(), endNode.getId());
} else {
factory.connect(startNode.getId(), endNode.getId(), "connection_" + startNode.getId() + "_" + endNode.getId(), process, false);
}
}
} else {
startNode = factory.startNode(ids.getAndIncrement(), start.getName() + "-start", process);
}
// map of state names to node ids for connecting purpose
Map<String, Long> mappedNodes = new LinkedHashMap<>();
Node currentNode = null;
// process all states and create proper node representation for each state
for (State state : workflow.getStates()) {
if (state.getType().equals(Type.INJECT)) {
ActionNode actionNode = factory.injectStateNode(ids.getAndIncrement(), state.getName(), process, ((InjectState) state).getData().toString());
mappedNodes.put(state.getName(), actionNode.getId());
if (state.getEnd() != null) {
EndNode endNode = factory.endNode(ids.getAndIncrement(), state.getName() + "-end", state.getEnd().isTerminate(), process);
if (state.getEnd().getProduceEvents() != null && !state.getEnd().getProduceEvents().isEmpty()) {
produceEvents(state.getEnd().getProduceEvents(), factory, workflow, ids, process, actionNode.getId(), endNode.getId());
} else {
factory.connect(actionNode.getId(), endNode.getId(), "connection_" + actionNode.getId() + "_" + endNode.getId(), process, false);
}
}
setUniqueId(actionNode, state);
currentNode = actionNode;
} else if (state.getType().equals(DefaultState.Type.OPERATION)) {
OperationState operationState = (OperationState) state;
CompositeContextNode embeddedSubProcess = factory.subProcessNode(ids.getAndIncrement(), state.getName(), process);
currentNode = embeddedSubProcess;
setUniqueId(embeddedSubProcess, state);
// handle state data inputs
Assignment inputAssignment = new Assignment("jq", "", "");
inputAssignment.setMetaData("Action", new InputJqAssignmentAction(state.getStateDataFilter() == null ? null : factory.unwrapExpression(state.getStateDataFilter().getInput())));
embeddedSubProcess.addInAssociation(new DataAssociation(Collections.emptyList(), "", Arrays.asList(inputAssignment), null));
// handle state data outputs
Assignment outputAssignment = new Assignment("jq", "", "");
outputAssignment.setMetaData("Action", new OutputJqAssignmentAction(state.getStateDataFilter() == null ? null : factory.unwrapExpression(state.getStateDataFilter().getOutput())));
embeddedSubProcess.addOutAssociation(new DataAssociation(Collections.emptyList(), "", Arrays.asList(outputAssignment), null));
mappedNodes.put(state.getName(), embeddedSubProcess.getId());
StartNode embeddedStartNode = factory.startNode(ids.getAndIncrement(), "EmbeddedStart", embeddedSubProcess);
EndNode embeddedEndNode = factory.endNode(ids.getAndIncrement(), "EmbeddedEnd", false, embeddedSubProcess);
if (operationState.getActions() == null || operationState.getActions().isEmpty()) {
factory.connect(embeddedStartNode.getId(), embeddedEndNode.getId(), embeddedStartNode.getId() + "_" + embeddedEndNode.getId(), embeddedSubProcess, false);
if (state.getEnd() != null) {
EndNode endNode = factory.endNode(ids.getAndIncrement(), state.getName() + "-end", state.getEnd().isTerminate(), process);
if (state.getEnd().getProduceEvents() != null && !state.getEnd().getProduceEvents().isEmpty()) {
produceEvents(state.getEnd().getProduceEvents(), factory, workflow, ids, process, embeddedSubProcess.getId(), endNode.getId());
} else {
factory.connect(embeddedSubProcess.getId(), endNode.getId(), "connection_" + embeddedSubProcess.getId() + "_" + endNode.getId(), process, false);
}
}
// ensure that start node is connected
if (state.equals(start) && currentNode != null) {
factory.connect(startNode.getId(), currentNode.getId(), "connection_" + startNode.getId() + "_" + currentNode.getId(), process, false);
}
continue;
}
if (operationState.getActionMode() == null || operationState.getActionMode() == ActionMode.SEQUENTIAL) {
buildActionsForState(workflow, operationState.getActions(), embeddedSubProcess, factory, ids, (first, last) -> {
factory.connect(embeddedStartNode.getId(), first.getId(), embeddedStartNode.getId() + "_" + first.getId(), embeddedSubProcess, false);
factory.connect(last.getId(), embeddedEndNode.getId(), last.getId() + "_" + embeddedEndNode.getId(), embeddedSubProcess, false);
}, (first, last) -> {
}, false);
} else {
Split split = factory.splitNode(ids.getAndIncrement(), "parallel-split-" + state.getName(), Split.TYPE_AND, embeddedSubProcess);
Join join = factory.joinNode(ids.getAndIncrement(), "parallel-join-" + state.getName(), Join.TYPE_AND, embeddedSubProcess);
factory.connect(embeddedStartNode.getId(), split.getId(), embeddedStartNode.getId() + "_" + split.getId(), embeddedSubProcess, false);
factory.connect(join.getId(), embeddedEndNode.getId(), join.getId() + "_" + embeddedEndNode.getId(), embeddedSubProcess, false);
buildActionsForState(workflow, operationState.getActions(), embeddedSubProcess, factory, ids, (first, last) -> {
}, (first, last) -> {
factory.connect(split.getId(), first.getId(), split.getId() + "_" + first.getId(), embeddedSubProcess, false);
factory.connect(last.getId(), join.getId(), last.getId() + "_" + join.getId(), embeddedSubProcess, false);
}, true);
}
if (state.getEnd() != null) {
EndNode endNode = factory.endNode(ids.getAndIncrement(), state.getName() + "-end", state.getEnd().isTerminate(), process);
if (state.getEnd().getProduceEvents() != null && !state.getEnd().getProduceEvents().isEmpty()) {
produceEvents(state.getEnd().getProduceEvents(), factory, workflow, ids, process, embeddedSubProcess.getId(), endNode.getId());
} else {
factory.connect(embeddedSubProcess.getId(), endNode.getId(), "connection_" + embeddedSubProcess.getId() + "_" + endNode.getId(), process, false);
}
}
} else if (state.getType().equals(DefaultState.Type.EVENT)) {
EventState eventState = (EventState) state;
if (eventState.equals(start)) {
// event state that is start node is already handled
continue;
}
for (OnEvents onEvent : eventState.getOnEvents()) {
CompositeContextNode embeddedSubProcess = factory.subProcessNode(ids.getAndIncrement(), state.getName(), process);
setUniqueId(embeddedSubProcess, state);
currentNode = embeddedSubProcess;
// handle state data inputs
Assignment inputAssignment = new Assignment("jq", "", "");
inputAssignment.setMetaData("Action", new InputJqAssignmentAction(state.getStateDataFilter() == null ? null : factory.unwrapExpression(state.getStateDataFilter().getInput())));
embeddedSubProcess.addInAssociation(new DataAssociation(Collections.emptyList(), "", Arrays.asList(inputAssignment), null));
// handle state data outputs
Assignment outputAssignment = new Assignment("jq", "", "");
outputAssignment.setMetaData("Action", new OutputJqAssignmentAction(state.getStateDataFilter() == null ? null : factory.unwrapExpression(state.getStateDataFilter().getOutput())));
embeddedSubProcess.addOutAssociation(new DataAssociation(Collections.emptyList(), "", Arrays.asList(outputAssignment), null));
mappedNodes.put(state.getName(), embeddedSubProcess.getId());
StartNode embeddedStartNode = factory.startNode(ids.getAndIncrement(), "EmbeddedStart", embeddedSubProcess);
EndNode embeddedEndNode = factory.endNode(ids.getAndIncrement(), "EmbeddedEnd", false, embeddedSubProcess);
if (eventState.isExclusive()) {
// use event based gateway
Split eventSplit = factory.eventBasedSplit(ids.getAndIncrement(), "split_" + state.getName(), embeddedSubProcess);
Join join = factory.joinNode(ids.getAndIncrement(), "join_" + state.getName(), Join.TYPE_XOR, embeddedSubProcess);
factory.connect(embeddedStartNode.getId(), eventSplit.getId(), "connection_" + embeddedStartNode.getId() + "_" + eventSplit.getId(), embeddedSubProcess, false);
for (String eventRef : onEvent.getEventRefs()) {
EventDefinition event = WorkflowUtils.getDefinedConsumedEvents(workflow).stream().filter(e -> e.getName().equals(eventRef)).findFirst().get();
EventNode eventNode = factory.consumeEventNode(ids.getAndIncrement(), event, onEvent.getEventDataFilter(), embeddedSubProcess);
factory.connect(eventSplit.getId(), eventNode.getId(), "connection_" + eventSplit.getId() + "_" + eventNode.getId(), embeddedSubProcess, false);
factory.connect(eventNode.getId(), join.getId(), "connection_" + eventNode.getId() + "_" + join.getId(), embeddedSubProcess, false);
}
buildActionsForState(workflow, onEvent.getActions(), embeddedSubProcess, factory, ids, (first, last) -> {
factory.connect(join.getId(), first.getId(), join.getId() + "_" + first.getId(), embeddedSubProcess, false);
factory.connect(last.getId(), embeddedEndNode.getId(), last.getId() + "_" + embeddedEndNode.getId(), embeddedSubProcess, false);
}, (first, last) -> {
}, false);
} else {
// use parallel gateway
Split parallelSplit = factory.splitNode(ids.getAndIncrement(), "split_" + state.getName(), Split.TYPE_AND, embeddedSubProcess);
Join parallelJoin = factory.joinNode(ids.getAndIncrement(), "join_" + state.getName(), Join.TYPE_AND, embeddedSubProcess);
factory.connect(embeddedStartNode.getId(), parallelSplit.getId(), "connection_" + embeddedStartNode.getId() + "_" + parallelSplit.getId(), embeddedSubProcess, false);
for (String eventRef : onEvent.getEventRefs()) {
EventDefinition event = WorkflowUtils.getDefinedConsumedEvents(workflow).stream().filter(e -> e.getName().equals(eventRef)).findFirst().get();
EventNode eventNode = factory.consumeEventNode(ids.getAndIncrement(), event, onEvent.getEventDataFilter(), embeddedSubProcess);
factory.connect(parallelSplit.getId(), eventNode.getId(), "connection_" + parallelSplit.getId() + "_" + eventNode.getId(), embeddedSubProcess, false);
factory.connect(eventNode.getId(), parallelJoin.getId(), "connection_" + eventNode.getId() + "_" + parallelJoin.getId(), embeddedSubProcess, false);
}
buildActionsForState(workflow, onEvent.getActions(), embeddedSubProcess, factory, ids, (first, last) -> {
factory.connect(parallelJoin.getId(), first.getId(), parallelJoin.getId() + "_" + first.getId(), embeddedSubProcess, false);
factory.connect(last.getId(), embeddedEndNode.getId(), last.getId() + "_" + embeddedEndNode.getId(), embeddedSubProcess, false);
}, (first, last) -> {
}, false);
}
if (state.getEnd() != null) {
EndNode endNode = factory.endNode(ids.getAndIncrement(), state.getName() + "-end", state.getEnd().isTerminate(), process);
if (state.getEnd().getProduceEvents() != null && !state.getEnd().getProduceEvents().isEmpty()) {
produceEvents(state.getEnd().getProduceEvents(), factory, workflow, ids, process, embeddedSubProcess.getId(), endNode.getId());
} else {
factory.connect(embeddedSubProcess.getId(), endNode.getId(), "connection_" + embeddedSubProcess.getId() + "_" + endNode.getId(), process, false);
}
}
}
} else if (state.getType().equals(DefaultState.Type.CALLBACK)) {
CallbackState callcackState = (CallbackState) state;
CompositeContextNode embeddedSubProcess = factory.subProcessNode(ids.getAndIncrement(), state.getName(), process);
currentNode = embeddedSubProcess;
setUniqueId(embeddedSubProcess, state);
// handle state data inputs
Assignment inputAssignment = new Assignment("jq", "", "");
inputAssignment.setMetaData("Action", new InputJqAssignmentAction(state.getStateDataFilter() == null ? null : factory.unwrapExpression(state.getStateDataFilter().getInput())));
embeddedSubProcess.addInAssociation(new DataAssociation(Collections.emptyList(), "", Arrays.asList(inputAssignment), null));
// handle state data outputs
Assignment outputAssignment = new Assignment("jq", "", "");
outputAssignment.setMetaData("Action", new OutputJqAssignmentAction(state.getStateDataFilter() == null ? null : factory.unwrapExpression(state.getStateDataFilter().getOutput())));
embeddedSubProcess.addOutAssociation(new DataAssociation(Collections.emptyList(), "", Arrays.asList(outputAssignment), null));
mappedNodes.put(state.getName(), embeddedSubProcess.getId());
StartNode embeddedStartNode = factory.startNode(ids.getAndIncrement(), "EmbeddedStart", embeddedSubProcess);
EndNode embeddedEndNode = factory.endNode(ids.getAndIncrement(), "EmbeddedEnd", false, embeddedSubProcess);
EventDefinition event = WorkflowUtils.getDefinedConsumedEvents(workflow).stream().filter(e -> e.getName().equals(callcackState.getEventRef())).findFirst().get();
EventNode eventNode = factory.consumeEventNode(ids.getAndIncrement(), event, callcackState.getEventDataFilter(), embeddedSubProcess);
buildActionsForState(workflow, Collections.singletonList(callcackState.getAction()), embeddedSubProcess, factory, ids, (first, last) -> {
factory.connect(embeddedStartNode.getId(), first.getId(), embeddedStartNode.getId() + "_" + first.getId(), embeddedSubProcess, false);
factory.connect(last.getId(), eventNode.getId(), last.getId() + "_" + eventNode.getId(), embeddedSubProcess, false);
}, (first, last) -> {
}, false);
factory.connect(eventNode.getId(), embeddedEndNode.getId(), "connection_" + eventNode.getId() + "_" + embeddedEndNode.getId(), embeddedSubProcess, false);
if (state.getEnd() != null) {
EndNode endNode = factory.endNode(ids.getAndIncrement(), state.getName() + "-end", state.getEnd().isTerminate(), process);
if (state.getEnd().getProduceEvents() != null && !state.getEnd().getProduceEvents().isEmpty()) {
produceEvents(state.getEnd().getProduceEvents(), factory, workflow, ids, process, embeddedSubProcess.getId(), endNode.getId());
} else {
factory.connect(embeddedSubProcess.getId(), endNode.getId(), "connection_" + embeddedSubProcess.getId() + "_" + endNode.getId(), process, false);
}
}
} else if (state.getType().equals(Type.SLEEP)) {
TimerNode sleep = factory.timerNode(ids.getAndIncrement(), "sleep-" + state.getName(), ((SleepState) state).getDuration(), process);
mappedNodes.put(state.getName(), sleep.getId());
setUniqueId(sleep, state);
if (state.getEnd() != null) {
EndNode endNode = factory.endNode(ids.getAndIncrement(), state.getName() + "-end", state.getEnd().isTerminate(), process);
if (state.getEnd().getProduceEvents() != null && !state.getEnd().getProduceEvents().isEmpty()) {
produceEvents(state.getEnd().getProduceEvents(), factory, workflow, ids, process, sleep.getId(), endNode.getId());
} else {
factory.connect(sleep.getId(), endNode.getId(), "connection_" + sleep.getId() + "_" + endNode.getId(), process, false);
}
}
currentNode = sleep;
} else if (state.getType().equals(DefaultState.Type.PARALLEL)) {
ParallelState parallelState = (ParallelState) state;
CompositeContextNode embeddedSubProcess = factory.subProcessNode(ids.getAndIncrement(), state.getName(), process);
setUniqueId(embeddedSubProcess, state);
currentNode = embeddedSubProcess;
// handle state data inputs
Assignment inputAssignment = new Assignment("jq", "", "");
inputAssignment.setMetaData("Action", new InputJqAssignmentAction(state.getStateDataFilter() == null ? null : factory.unwrapExpression(state.getStateDataFilter().getInput())));
embeddedSubProcess.addInAssociation(new DataAssociation(Collections.emptyList(), "", Arrays.asList(inputAssignment), null));
// handle state data outputs
Assignment outputAssignment = new Assignment("jq", "", "");
outputAssignment.setMetaData("Action", new OutputJqAssignmentAction(state.getStateDataFilter() == null ? null : factory.unwrapExpression(state.getStateDataFilter().getOutput())));
embeddedSubProcess.addOutAssociation(new DataAssociation(Collections.emptyList(), "", Arrays.asList(outputAssignment), null));
mappedNodes.put(state.getName(), embeddedSubProcess.getId());
StartNode embeddedStartNode = factory.startNode(ids.getAndIncrement(), "EmbeddedStart", embeddedSubProcess);
EndNode embeddedEndNode = factory.endNode(ids.getAndIncrement(), "EmbeddedEnd", false, embeddedSubProcess);
Split parallelSplit = factory.splitNode(ids.getAndIncrement(), "split_" + state.getName(), Split.TYPE_AND, embeddedSubProcess);
Join parallelJoin;
if (parallelState.getCompletionType().equals(CompletionType.AT_LEAST)) {
parallelJoin = factory.joinNode(ids.getAndIncrement(), "join_" + state.getName(), Join.TYPE_N_OF_M, embeddedSubProcess);
parallelJoin.setN(parallelState.getNumCompleted());
} else {
parallelJoin = factory.joinNode(ids.getAndIncrement(), "join_" + state.getName(), Join.TYPE_AND, embeddedSubProcess);
}
factory.connect(embeddedStartNode.getId(), parallelSplit.getId(), "connection_" + embeddedStartNode.getId() + "_" + parallelSplit.getId(), embeddedSubProcess, false);
for (Branch branch : parallelState.getBranches()) {
buildActionsForState(workflow, branch.getActions(), embeddedSubProcess, factory, ids, (first, last) -> {
factory.connect(parallelSplit.getId(), first.getId(), parallelSplit.getId() + "_" + first.getId(), embeddedSubProcess, false);
factory.connect(last.getId(), parallelJoin.getId(), last.getId() + "_" + parallelJoin.getId(), embeddedSubProcess, false);
}, (first, last) -> {
}, true);
}
factory.connect(parallelJoin.getId(), embeddedEndNode.getId(), "connection_" + parallelJoin.getId() + "_" + embeddedEndNode.getId(), embeddedSubProcess, false);
if (state.getEnd() != null) {
EndNode endNode = factory.endNode(ids.getAndIncrement(), state.getName() + "-end", state.getEnd().isTerminate(), process);
if (state.getEnd().getProduceEvents() != null && !state.getEnd().getProduceEvents().isEmpty()) {
produceEvents(state.getEnd().getProduceEvents(), factory, workflow, ids, process, embeddedSubProcess.getId(), endNode.getId());
} else {
factory.connect(embeddedSubProcess.getId(), endNode.getId(), "connection_" + embeddedSubProcess.getId() + "_" + endNode.getId(), process, false);
}
}
} else if (state.getType().equals(DefaultState.Type.FOREACH)) {
}
// ensure that start node is connected
if (state.equals(start) && currentNode != null) {
factory.connect(startNode.getId(), currentNode.getId(), "connection_" + startNode.getId() + "_" + currentNode.getId(), process, false);
}
}
for (State state : workflow.getStates()) {
if (state.getType().equals(Type.SWITCH)) {
// switch state must be processed at the end as it needs to reference other nodes by id
SwitchState switchState = (SwitchState) state;
if (switchState.getDataConditions() != null && !switchState.getDataConditions().isEmpty()) {
Split splitNode = factory.splitNode(ids.getAndIncrement(), "split_" + state.getName(), Split.TYPE_XOR, process);
currentNode = splitNode;
setUniqueId(splitNode, state);
mappedNodes.put(state.getName(), splitNode.getId());
int priority = 1;
for (DataCondition condition : switchState.getDataConditions()) {
boolean isDefaultConstraint = false;
if (switchState.getDefaultCondition() != null && switchState.getDefaultCondition().getTransition() != null && condition.getTransition() != null && condition.getTransition().getNextState().equals(switchState.getDefaultCondition().getTransition().getNextState())) {
isDefaultConstraint = true;
}
if (switchState.getDefaultCondition() != null && switchState.getDefaultCondition().getEnd() != null && condition.getEnd() != null) {
isDefaultConstraint = true;
}
Connection outgoingConnection = null;
long target = 0;
if (condition.getEnd() != null) {
EndNode endNode = factory.endNode(ids.getAndIncrement(), "end_" + switchState.getName(), false, process);
target = endNode.getId();
outgoingConnection = factory.connect(splitNode.getId(), endNode.getId(), "connection_" + splitNode.getId() + "_" + endNode.getId(), process, false);
} else if (condition.getTransition() != null && condition.getTransition().getNextState() != null) {
long source = splitNode.getId();
target = mappedNodes.get(condition.getTransition().getNextState());
outgoingConnection = factory.connect(source, target, "connection_" + source + "_" + target, process, false);
}
ReturnValueConstraintEvaluator returnValueConstraint = new ReturnValueConstraintEvaluator();
returnValueConstraint.setDialect("jq");
returnValueConstraint.setName(splitNode.getId() + "_" + target);
returnValueConstraint.setPriority(priority);
returnValueConstraint.setDefault(isDefaultConstraint);
returnValueConstraint.setType("DROOLS_DEFAULT");
returnValueConstraint.setConstraint(factory.unwrapExpression(condition.getCondition()));
returnValueConstraint.setEvaluator(new JqReturnValueEvaluator(factory.unwrapExpression(condition.getCondition())));
splitNode.setConstraint(outgoingConnection, returnValueConstraint);
}
} else if (switchState.getEventConditions() != null && !switchState.getEventConditions().isEmpty()) {
Split splitNode = factory.eventBasedSplit(ids.getAndIncrement(), "split_" + state.getName(), process);
currentNode = splitNode;
setUniqueId(splitNode, state);
mappedNodes.put(state.getName(), splitNode.getId());
for (EventCondition eventCondition : switchState.getEventConditions()) {
EventDefinition event = WorkflowUtils.getDefinedConsumedEvents(workflow).stream().filter(e -> e.getName().equals(eventCondition.getEventRef())).findFirst().get();
EventNode eventNode = factory.consumeEventNode(ids.getAndIncrement(), event, eventCondition.getEventDataFilter(), process);
factory.connect(splitNode.getId(), eventNode.getId(), "connection_" + splitNode.getId() + "_" + eventNode.getId(), process, false);
long target = 0;
if (eventCondition.getEnd() != null) {
EndNode endNode = factory.endNode(ids.getAndIncrement(), "end_" + switchState.getName(), false, process);
target = endNode.getId();
factory.connect(splitNode.getId(), endNode.getId(), "connection_" + splitNode.getId() + "_" + endNode.getId(), process, false);
} else if (eventCondition.getTransition() != null && eventCondition.getTransition().getNextState() != null) {
target = mappedNodes.get(eventCondition.getTransition().getNextState());
factory.connect(eventNode.getId(), target, "connection_" + eventNode.getId() + "_" + target, process, false);
}
}
if (switchState.getTimeouts() != null && switchState.getTimeouts().getEventTimeout() != null) {
TimerNode timer = factory.timerNode(ids.getAndIncrement(), "event-switch-timeout", switchState.getTimeouts().getEventTimeout(), process);
factory.connect(splitNode.getId(), timer.getId(), "connection_" + splitNode.getId() + "_" + timer.getId(), process, false);
EndNode endNode = factory.endNode(ids.getAndIncrement(), "end_" + switchState.getName(), false, process);
factory.connect(timer.getId(), endNode.getId(), "connection_" + timer.getId() + "_" + endNode.getId(), process, false);
}
}
// ensure that start node is connected
if (state.equals(start) && currentNode != null) {
factory.connect(startNode.getId(), currentNode.getId(), "connection_" + startNode.getId() + "_" + currentNode.getId(), process, false);
}
}
}
// next connect all nodes
for (State state : workflow.getStates()) {
if (!mappedNodes.containsKey(state.getName())) {
continue;
}
long source = mappedNodes.get(state.getName());
if (state.getTransition() != null && state.getTransition().getNextState() != null) {
long target = mappedNodes.get(state.getTransition().getNextState());
if (state.getTransition().getProduceEvents() != null && !state.getTransition().getProduceEvents().isEmpty()) {
produceEvents(state.getTransition().getProduceEvents(), factory, workflow, ids, process, source, target);
} else {
factory.connect(source, target, "connection_" + source + "_" + target, process, false);
}
}
}
// attach error handling
for (State state : workflow.getStates()) {
if (!mappedNodes.containsKey(state.getName())) {
continue;
}
long source = mappedNodes.get(state.getName());
if (process.getNode(source) instanceof CompositeContextNode) {
addErrorHandlingToState(workflow, state, factory, ids, process, (CompositeContextNode) process.getNode(source));
}
}
factory.validate((ExecutableProcess) process);
if (workflow.getTimeouts() != null && workflow.getTimeouts().getWorkflowExecTimeout() != null) {
factory.addExecutionTimeout(ids.getAndIncrement(), workflow.getTimeouts().getWorkflowExecTimeout(), (ExecutableProcess) process);
}
process.setMetaData("SW-Workflow", workflow);
return process;
}
use of io.automatiko.engine.workflow.process.core.node.CompositeContextNode in project automatiko-engine by automatiko-io.
the class ServerlessWorkflowFactory method subProcessNode.
public CompositeContextNode subProcessNode(long id, String name, NodeContainer nodeContainer) {
CompositeContextNode subProcessNode = new CompositeContextNode();
subProcessNode.setId(id);
subProcessNode.setName(name);
subProcessNode.setAutoComplete(true);
subProcessNode.setMetaData(UNIQUE_ID_PARAM, Long.toString(subProcessNode.getId()));
JsonVariableScope variableScope = new JsonVariableScope();
subProcessNode.addContext(variableScope);
subProcessNode.setDefaultContext(variableScope);
nodeContainer.addNode(subProcessNode);
return subProcessNode;
}
use of io.automatiko.engine.workflow.process.core.node.CompositeContextNode in project automatiko-engine by automatiko-io.
the class CompositeNodeHandler method writeNode.
public void writeNode(Node node, StringBuilder xmlDump, boolean includeMeta) {
super.writeNode(getNodeName(), node, xmlDump, includeMeta);
CompositeNode compositeNode = (CompositeNode) node;
writeAttributes(compositeNode, xmlDump, includeMeta);
xmlDump.append(">" + EOL);
if (includeMeta) {
writeMetaData(compositeNode, xmlDump);
}
for (String eventType : compositeNode.getActionTypes()) {
writeActions(eventType, compositeNode.getActions(eventType), xmlDump);
}
writeTimers(compositeNode.getTimers(), xmlDump);
if (compositeNode instanceof CompositeContextNode) {
VariableScope variableScope = (VariableScope) ((CompositeContextNode) compositeNode).getDefaultContext(VariableScope.VARIABLE_SCOPE);
if (variableScope != null) {
List<Variable> variables = variableScope.getVariables();
XmlWorkflowProcessDumper.visitVariables(variables, xmlDump);
}
ExceptionScope exceptionScope = (ExceptionScope) ((CompositeContextNode) compositeNode).getDefaultContext(ExceptionScope.EXCEPTION_SCOPE);
if (exceptionScope != null) {
XmlWorkflowProcessDumper.visitExceptionHandlers(exceptionScope.getExceptionHandlers(), xmlDump);
}
}
xmlDump.append(" </connections>" + EOL);
Map<String, CompositeNode.NodeAndType> inPorts = getInPorts(compositeNode);
xmlDump.append(" <in-ports>" + EOL);
for (Map.Entry<String, CompositeNode.NodeAndType> entry : inPorts.entrySet()) {
xmlDump.append(" <in-port type=\"" + entry.getKey() + "\" nodeId=\"" + entry.getValue().getNodeId() + "\" nodeInType=\"" + entry.getValue().getType() + "\" />" + EOL);
}
xmlDump.append(" </in-ports>" + EOL);
Map<String, CompositeNode.NodeAndType> outPorts = getOutPorts(compositeNode);
xmlDump.append(" <out-ports>" + EOL);
for (Map.Entry<String, CompositeNode.NodeAndType> entry : outPorts.entrySet()) {
xmlDump.append(" <out-port type=\"" + entry.getKey() + "\" nodeId=\"" + entry.getValue().getNodeId() + "\" nodeOutType=\"" + entry.getValue().getType() + "\" />" + EOL);
}
xmlDump.append(" </out-ports>" + EOL);
endNode(getNodeName(), xmlDump);
}
Aggregations