use of io.automatiko.engine.workflow.process.core.WorkflowProcess 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.WorkflowProcess 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.WorkflowProcess in project automatiko-engine by automatiko-io.
the class CompositeContextNodeInstance method processInputMappings.
@SuppressWarnings({ "unchecked", "rawtypes" })
protected void processInputMappings() {
VariableScopeInstance compositeVariableScopeInstance = (VariableScopeInstance) getContextInstance(VARIABLE_SCOPE);
for (DataAssociation association : getCompositeContextNode().getInAssociations()) {
if (association.getTransformation() != null) {
Transformation transformation = association.getTransformation();
DataTransformer transformer = DataTransformerRegistry.get().find(transformation.getLanguage());
if (transformer != null) {
Object parameterValue = transformer.transform(transformation.getCompiledExpression(), getProcessInstance().getVariables());
if (parameterValue != null) {
compositeVariableScopeInstance.setVariable(association.getTarget(), parameterValue);
}
}
} else if (association.getAssignments() == null || association.getAssignments().isEmpty()) {
Object parameterValue = null;
VariableScopeInstance variableScopeInstance = (VariableScopeInstance) resolveContextInstance(VARIABLE_SCOPE, association.getSources().get(0));
if (variableScopeInstance != null) {
parameterValue = variableScopeInstance.getVariable(association.getSources().get(0));
} else {
try {
ExpressionEvaluator evaluator = (ExpressionEvaluator) ((WorkflowProcess) getProcessInstance().getProcess()).getDefaultContext(ExpressionEvaluator.EXPRESSION_EVALUATOR);
parameterValue = evaluator.evaluate(association.getSources().get(0), new NodeInstanceResolverFactory(this));
} catch (Throwable t) {
logger.error("Could not find variable scope for variable {}", association.getSources().get(0));
logger.error("Continuing without setting parameter.");
}
}
if (parameterValue != null) {
compositeVariableScopeInstance.setVariable(association.getTarget(), parameterValue);
}
} else {
association.getAssignments().stream().forEach(assignment -> handleAssignment(assignment, compositeVariableScopeInstance));
}
}
}
use of io.automatiko.engine.workflow.process.core.WorkflowProcess in project automatiko-engine by automatiko-io.
the class CompositeContextNodeInstance method triggerCompleted.
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public void triggerCompleted(String outType) {
VariableScopeInstance compositeVariableScopeInstance = (VariableScopeInstance) getContextInstance(VARIABLE_SCOPE);
for (DataAssociation association : getCompositeContextNode().getOutAssociations()) {
if (association.getTransformation() != null) {
Transformation transformation = association.getTransformation();
DataTransformer transformer = DataTransformerRegistry.get().find(transformation.getLanguage());
if (transformer != null) {
Object parameterValue = transformer.transform(transformation.getCompiledExpression(), compositeVariableScopeInstance.getVariables());
if (parameterValue != null) {
getProcessInstance().setVariable(association.getTarget(), parameterValue);
}
}
} else if (association.getAssignments() == null || association.getAssignments().isEmpty()) {
Object parameterValue = null;
VariableScopeInstance variableScopeInstance = (VariableScopeInstance) resolveContextInstance(VARIABLE_SCOPE, association.getSources().get(0));
if (variableScopeInstance != null) {
parameterValue = variableScopeInstance.getVariable(association.getSources().get(0));
} else {
try {
ExpressionEvaluator evaluator = (ExpressionEvaluator) ((WorkflowProcess) getProcessInstance().getProcess()).getDefaultContext(ExpressionEvaluator.EXPRESSION_EVALUATOR);
parameterValue = evaluator.evaluate(association.getSources().get(0), new NodeInstanceResolverFactory(this));
} catch (Throwable t) {
logger.error("Could not find variable scope for variable {}", association.getSources().get(0));
logger.error("Continuing without setting parameter.");
}
}
if (parameterValue != null) {
getProcessInstance().setVariable(association.getTarget(), parameterValue);
}
} else {
association.getAssignments().stream().forEach(assignment -> handleAssignment(assignment, compositeVariableScopeInstance));
}
}
super.triggerCompleted(outType);
}
use of io.automatiko.engine.workflow.process.core.WorkflowProcess in project automatiko-engine by automatiko-io.
the class SubProcessNode method internalSubProcess.
public void internalSubProcess(Collection<io.automatiko.engine.api.workflow.Process> availableProcesses) {
io.automatiko.engine.api.workflow.Process process = (io.automatiko.engine.api.workflow.Process<Map<String, Object>>) availableProcesses.stream().filter(p -> p.id().equals(processId)).findFirst().orElse(null);
if (process == null) {
return;
}
this.subProcessFactory = new SubProcessFactory<Object>() {
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public Map<String, Object> bind(ProcessContext ctx) {
Map<String, Object> parameters = new HashMap<String, Object>();
for (Iterator<DataAssociation> iterator = getInAssociations().iterator(); iterator.hasNext(); ) {
DataAssociation mapping = iterator.next();
Object parameterValue = null;
if (mapping.getTransformation() != null) {
Transformation transformation = mapping.getTransformation();
DataTransformer transformer = DataTransformerRegistry.get().find(transformation.getLanguage());
if (transformer != null) {
parameterValue = transformer.transform(transformation.getCompiledExpression(), getSourceParameters(ctx, mapping));
}
} else if (mapping.getAssignments() == null || mapping.getAssignments().isEmpty()) {
VariableScopeInstance variableScopeInstance = (VariableScopeInstance) ((NodeInstance) ctx.getNodeInstance()).resolveContextInstance(VariableScope.VARIABLE_SCOPE, mapping.getSources().get(0));
if (variableScopeInstance != null) {
parameterValue = variableScopeInstance.getVariable(mapping.getSources().get(0));
} else {
try {
ExpressionEvaluator evaluator = (ExpressionEvaluator) ((WorkflowProcess) ctx.getProcessInstance().getProcess()).getDefaultContext(ExpressionEvaluator.EXPRESSION_EVALUATOR);
parameterValue = evaluator.evaluate(mapping.getSources().get(0), new NodeInstanceResolverFactory((NodeInstance) ctx.getNodeInstance()));
} catch (Throwable t) {
parameterValue = VariableUtil.resolveVariable(mapping.getSources().get(0), ctx.getNodeInstance());
if (parameterValue != null) {
parameters.put(mapping.getTarget(), parameterValue);
}
}
}
} else {
mapping.getAssignments().stream().forEach(a -> handleAssignment(ctx, parameters, a));
}
if (parameterValue != null) {
parameters.put(mapping.getTarget(), parameterValue);
}
}
return parameters;
}
@Override
public ProcessInstance createInstance(Object model) {
Model data = (Model) process.createModel();
data.fromMap((Map<String, Object>) model);
return process.createInstance(data);
}
@Override
public void unbind(ProcessContext ctx, Object model) {
Map<String, Object> result = ((Model) model).toMap();
for (Iterator<DataAssociation> iterator = getOutAssociations().iterator(); iterator.hasNext(); ) {
DataAssociation mapping = iterator.next();
if (mapping.getTransformation() != null) {
Transformation transformation = mapping.getTransformation();
DataTransformer transformer = DataTransformerRegistry.get().find(transformation.getLanguage());
if (transformer != null) {
Map<String, Object> dataSet = new HashMap<String, Object>();
if (ctx.getNodeInstance().getNodeInstanceContainer() instanceof CompositeContextNodeInstance) {
VariableScopeInstance variableScopeInstance = (VariableScopeInstance) ((CompositeContextNodeInstance) ctx.getNodeInstance().getNodeInstanceContainer()).getContextInstance(VariableScope.VARIABLE_SCOPE);
if (variableScopeInstance != null) {
dataSet.putAll(variableScopeInstance.getVariables());
}
}
dataSet.putAll(result);
Object parameterValue = transformer.transform(transformation.getCompiledExpression(), dataSet);
VariableScopeInstance variableScopeInstance = (VariableScopeInstance) ((NodeInstance) ctx.getNodeInstance()).resolveContextInstance(VariableScope.VARIABLE_SCOPE, mapping.getTarget());
if (variableScopeInstance != null && parameterValue != null) {
variableScopeInstance.setVariable(ctx.getNodeInstance(), mapping.getTarget(), parameterValue);
}
}
} else {
VariableScopeInstance variableScopeInstance = (VariableScopeInstance) ((NodeInstance) ctx.getNodeInstance()).resolveContextInstance(VariableScope.VARIABLE_SCOPE, mapping.getTarget());
if (variableScopeInstance != null) {
Object value = result.get(mapping.getSources().get(0));
if (value == null) {
try {
value = MVEL.eval(mapping.getSources().get(0), result);
} catch (Throwable t) {
// do nothing
}
}
variableScopeInstance.setVariable(ctx.getNodeInstance(), mapping.getTarget(), value);
} else {
String output = mapping.getSources().get(0);
String target = mapping.getTarget();
Matcher matcher = PatternConstants.PARAMETER_MATCHER.matcher(target);
if (matcher.find()) {
String paramName = matcher.group(1);
String expression = paramName + " = " + output;
Serializable compiled = MVEL.compileExpression(expression);
MVEL.executeExpression(compiled, result);
}
}
}
}
}
@SuppressWarnings("unchecked")
@Override
public void abortInstance(String instanceId) {
process.instances().findById(instanceId).ifPresent(pi -> {
try {
((ProcessInstance<?>) pi).abort();
} catch (IllegalArgumentException e) {
// ignore it as this might be thrown in case of canceling already aborted instance
}
});
}
private void handleAssignment(ProcessContext ctx, Map<String, Object> output, Assignment assignment) {
AssignmentAction action = (AssignmentAction) assignment.getMetaData("Action");
try {
WorkItemImpl workItem = new WorkItemImpl();
action.execute(workItem, ctx);
output.putAll(workItem.getParameters());
} catch (WorkItemExecutionError e) {
throw e;
} catch (Exception e) {
throw new RuntimeException("unable to execute Assignment", e);
}
}
};
}
Aggregations