Search in sources :

Example 1 with Action

use of io.serverlessworkflow.api.actions.Action in project kogito-runtimes by kiegroup.

the class CompositeContextNodeHandler method handleActions.

protected final <T extends AbstractCompositeNodeFactory<?, ?>> T handleActions(T embeddedSubProcess, List<Action> actions, String outputVar, String... extraVariables) {
    if (actions != null && !actions.isEmpty()) {
        NodeFactory<?, ?> startNode = embeddedSubProcess.startNode(parserContext.newId()).name("EmbeddedStart");
        NodeFactory<?, ?> currentNode = startNode;
        for (Action action : actions) {
            currentNode = connect(currentNode, getActionNode(embeddedSubProcess, action, outputVar, extraVariables));
        }
        connect(currentNode, embeddedSubProcess.endNode(parserContext.newId()).name("EmbeddedEnd").terminate(true)).done();
    } else {
        connect(embeddedSubProcess.startNode(parserContext.newId()).name("EmbeddedStart"), embeddedSubProcess.endNode(parserContext.newId()).name("EmbeddedEnd").terminate(true)).done();
    }
    return embeddedSubProcess;
}
Also used : Action(io.serverlessworkflow.api.actions.Action)

Example 2 with Action

use of io.serverlessworkflow.api.actions.Action in project kogito-runtimes by kiegroup.

the class CompositeContextNodeHandler method getActionNode.

public MakeNodeResult getActionNode(RuleFlowNodeContainerFactory<?, ?> embeddedSubProcess, Action action, String collectVar, String... extraVariables) {
    ActionDataFilter actionFilter = action.getActionDataFilter();
    String fromExpr = null;
    String resultExpr = null;
    String toExpr = null;
    boolean useData = true;
    if (actionFilter != null) {
        fromExpr = actionFilter.getFromStateData();
        resultExpr = actionFilter.getResults();
        toExpr = actionFilter.getToStateData();
        useData = actionFilter.isUseResults();
    }
    if (action.getFunctionRef() != null) {
        return filterAndMergeNode(embeddedSubProcess, fromExpr, resultExpr, toExpr, useData, (factory, inputVar, outputVar) -> getActionNode(factory, action.getFunctionRef(), inputVar, outputVar, collectVar, extraVariables));
    } else if (action.getEventRef() != null) {
        return filterAndMergeNode(embeddedSubProcess, fromExpr, resultExpr, toExpr, useData, (factory, inputVar, outputVar) -> getActionNode(factory, action.getEventRef(), inputVar));
    } else if (action.getSubFlowRef() != null) {
        return filterAndMergeNode(embeddedSubProcess, fromExpr, resultExpr, toExpr, useData, (factory, inputVar, outputVar) -> getActionNode(factory, action.getSubFlowRef(), inputVar, outputVar));
    } else {
        throw new IllegalArgumentException("Action node " + action.getName() + " of state " + state.getName() + " does not have function or event defined");
    }
}
Also used : ServerlessWorkflowParser(org.kie.kogito.serverless.workflow.parser.ServerlessWorkflowParser) RestBodyBuilderSupplier(org.kie.kogito.serverless.workflow.suppliers.RestBodyBuilderSupplier) SysoutActionSupplier(org.kie.kogito.serverless.workflow.suppliers.SysoutActionSupplier) ObjectResolver(org.kie.kogito.serverless.workflow.ObjectResolver) Action(io.serverlessworkflow.api.actions.Action) HashMap(java.util.HashMap) NodeFactory(org.jbpm.ruleflow.core.factory.NodeFactory) ExpressionActionSupplier(org.kie.kogito.serverless.workflow.suppliers.ExpressionActionSupplier) Workflow(io.serverlessworkflow.api.Workflow) JsonNodeResolver(org.kie.kogito.serverless.workflow.JsonNodeResolver) JsonObjectUtils(org.kie.kogito.jackson.utils.JsonObjectUtils) OpenApiTaskDescriptor(org.jbpm.compiler.canonical.descriptors.OpenApiTaskDescriptor) WorkItemNodeFactory(org.jbpm.ruleflow.core.factory.WorkItemNodeFactory) FunctionDefinition(io.serverlessworkflow.api.functions.FunctionDefinition) Map(java.util.Map) CompositeContextNodeFactory(org.jbpm.ruleflow.core.factory.CompositeContextNodeFactory) JsonNode(com.fasterxml.jackson.databind.JsonNode) FunctionRef(io.serverlessworkflow.api.functions.FunctionRef) ParserContext(org.kie.kogito.serverless.workflow.parser.ParserContext) ExpressionWorkItemResolver(org.kie.kogito.process.expr.ExpressionWorkItemResolver) ActionDataFilter(io.serverlessworkflow.api.filters.ActionDataFilter) AbstractServiceTaskDescriptor(org.jbpm.compiler.canonical.descriptors.AbstractServiceTaskDescriptor) Iterator(java.util.Iterator) EventRef(io.serverlessworkflow.api.events.EventRef) RuleFlowNodeContainerFactory(org.jbpm.ruleflow.core.RuleFlowNodeContainerFactory) AbstractCompositeNodeFactory(org.jbpm.ruleflow.core.factory.AbstractCompositeNodeFactory) DataTypeResolver(org.jbpm.process.core.datatype.DataTypeResolver) JsonNodeVisitor(org.kie.kogito.jackson.utils.JsonNodeVisitor) ExpressionHandlerFactory(org.kie.kogito.process.expr.ExpressionHandlerFactory) List(java.util.List) State(io.serverlessworkflow.api.interfaces.State) RestWorkItemHandler(org.kogito.workitem.rest.RestWorkItemHandler) ExpressionHandlerUtils(org.kie.kogito.serverless.workflow.utils.ExpressionHandlerUtils) JavaDialect(org.drools.mvel.java.JavaDialect) Entry(java.util.Map.Entry) TaskDescriptor(org.jbpm.compiler.canonical.descriptors.TaskDescriptor) ServerlessWorkflowUtils(org.kie.kogito.serverless.workflow.utils.ServerlessWorkflowUtils) SubFlowRef(io.serverlessworkflow.api.functions.SubFlowRef) ActionDataFilter(io.serverlessworkflow.api.filters.ActionDataFilter)

Example 3 with Action

use of io.serverlessworkflow.api.actions.Action in project automatiko-engine by automatiko-io.

the class ServerlessWorkflowFactory method stateDataFilterActionNode.

public ActionNode stateDataFilterActionNode(long id, String name, NodeContainer nodeContainer, String outputFilterString) {
    ActionNode actionNode = new ActionNode();
    actionNode.setId(id);
    actionNode.setName(name);
    String outputFilter = unwrapExpression(outputFilterString);
    ConsequenceAction processAction = new ConsequenceAction(null, "new io.automatiko.engine.workflow.base.instance.impl.jq.OutputJqAssignmentAction(" + escapeExpression(outputFilter) + ").execute(null, context);");
    io.automatiko.engine.workflow.base.instance.impl.Action injectAction = context -> {
        new OutputJqAssignmentAction(outputFilter).execute(null, context);
    };
    processAction.setMetaData(ACTION, injectAction);
    actionNode.setAction(processAction);
    nodeContainer.addNode(actionNode);
    return actionNode;
}
Also used : Arrays(java.util.Arrays) TimerNode(io.automatiko.engine.workflow.process.core.node.TimerNode) Metadata(io.automatiko.engine.workflow.process.executable.core.Metadata) ExecutableProcessValidator(io.automatiko.engine.workflow.process.executable.core.validation.ExecutableProcessValidator) Constants(io.serverlessworkflow.api.workflow.Constants) LoggerFactory(org.slf4j.LoggerFactory) Workflow(io.serverlessworkflow.api.Workflow) ObjectDataType(io.automatiko.engine.workflow.base.core.datatype.impl.type.ObjectDataType) FunctionTagDefinition(io.automatiko.engine.workflow.base.core.FunctionTagDefinition) NodeImpl(io.automatiko.engine.workflow.process.core.impl.NodeImpl) ConstraintImpl(io.automatiko.engine.workflow.process.core.impl.ConstraintImpl) CompositeContextNode(io.automatiko.engine.workflow.process.core.node.CompositeContextNode) Map(java.util.Map) JsonNode(com.fasterxml.jackson.databind.JsonNode) OnEvents(io.serverlessworkflow.api.events.OnEvents) TagDefinition(io.automatiko.engine.workflow.base.core.TagDefinition) ProcessAction(io.automatiko.engine.workflow.process.core.ProcessAction) ActionNode(io.automatiko.engine.workflow.process.core.node.ActionNode) Set(java.util.Set) JsonVariableScope(io.automatiko.engine.workflow.base.core.context.variable.JsonVariableScope) ErrorDefinition(io.serverlessworkflow.api.error.ErrorDefinition) WorkflowExecTimeout(io.serverlessworkflow.api.timeouts.WorkflowExecTimeout) VariableScope(io.automatiko.engine.workflow.base.core.context.variable.VariableScope) Collectors(java.util.stream.Collectors) TextNode(com.fasterxml.jackson.databind.node.TextNode) List(java.util.List) EventTypeFilter(io.automatiko.engine.workflow.base.core.event.EventTypeFilter) ProcessInstanceCompensationAction(io.automatiko.engine.workflow.base.instance.impl.actions.ProcessInstanceCompensationAction) WorkItemNode(io.automatiko.engine.workflow.process.core.node.WorkItemNode) Variable(io.automatiko.engine.workflow.base.core.context.variable.Variable) WorkImpl(io.automatiko.engine.workflow.base.core.impl.WorkImpl) Join(io.automatiko.engine.workflow.process.core.node.Join) StaticTagDefinition(io.automatiko.engine.workflow.base.core.StaticTagDefinition) ConsequenceAction(io.automatiko.engine.workflow.process.core.impl.ConsequenceAction) WorkflowUtils(io.serverlessworkflow.utils.WorkflowUtils) Work(io.automatiko.engine.workflow.base.core.Work) ProcessValidationError(io.automatiko.engine.workflow.base.core.validation.ProcessValidationError) SubProcessNode(io.automatiko.engine.workflow.process.core.node.SubProcessNode) Timer(io.automatiko.engine.workflow.base.core.timer.Timer) Assignment(io.automatiko.engine.workflow.process.core.node.Assignment) Action(io.serverlessworkflow.api.actions.Action) ServerlessExecutableProcess(io.automatiko.engine.workflow.process.executable.core.ServerlessExecutableProcess) NodeContainer(io.automatiko.engine.workflow.process.core.NodeContainer) Split(io.automatiko.engine.workflow.process.core.node.Split) HashMap(java.util.HashMap) Node(io.automatiko.engine.api.definition.process.Node) ArrayList(java.util.ArrayList) TaskInputJqAssignmentAction(io.automatiko.engine.workflow.base.instance.impl.jq.TaskInputJqAssignmentAction) ProduceEvent(io.serverlessworkflow.api.produce.ProduceEvent) HumanTaskNode(io.automatiko.engine.workflow.process.core.node.HumanTaskNode) OutputJqAssignmentAction(io.automatiko.engine.workflow.base.instance.impl.jq.OutputJqAssignmentAction) TaskOutputJqAssignmentAction(io.automatiko.engine.workflow.base.instance.impl.jq.TaskOutputJqAssignmentAction) DataAssociation(io.automatiko.engine.workflow.process.core.node.DataAssociation) FunctionDefinition(io.serverlessworkflow.api.functions.FunctionDefinition) BoundaryEventNode(io.automatiko.engine.workflow.process.core.node.BoundaryEventNode) ACTION(io.automatiko.engine.workflow.process.executable.core.Metadata.ACTION) Connection(io.automatiko.engine.api.definition.process.Connection) LinkedHashSet(java.util.LinkedHashSet) ActionDataFilter(io.serverlessworkflow.api.filters.ActionDataFilter) Logger(org.slf4j.Logger) ConnectionImpl(io.automatiko.engine.workflow.process.core.impl.ConnectionImpl) Iterator(java.util.Iterator) ExecutableProcess(io.automatiko.engine.workflow.process.executable.core.ExecutableProcess) DateTimeUtils(io.automatiko.engine.workflow.base.core.timer.DateTimeUtils) EventDefinition(io.serverlessworkflow.api.events.EventDefinition) RetryDefinition(io.serverlessworkflow.api.retry.RetryDefinition) End(io.serverlessworkflow.api.end.End) EventDataFilter(io.serverlessworkflow.api.filters.EventDataFilter) StartNode(io.automatiko.engine.workflow.process.core.node.StartNode) ServerlessFunctions(io.automatiko.engine.workflow.sw.ServerlessFunctions) Process(io.automatiko.engine.workflow.base.core.Process) ParameterDefinitionImpl(io.automatiko.engine.workflow.base.core.impl.ParameterDefinitionImpl) EventTrigger(io.automatiko.engine.workflow.process.core.node.EventTrigger) Collections(java.util.Collections) JsonNodeDataType(io.automatiko.engine.workflow.base.core.datatype.impl.type.JsonNodeDataType) EndNode(io.automatiko.engine.workflow.process.core.node.EndNode) EventNode(io.automatiko.engine.workflow.process.core.node.EventNode) ConsequenceAction(io.automatiko.engine.workflow.process.core.impl.ConsequenceAction) ActionNode(io.automatiko.engine.workflow.process.core.node.ActionNode) OutputJqAssignmentAction(io.automatiko.engine.workflow.base.instance.impl.jq.OutputJqAssignmentAction) TaskOutputJqAssignmentAction(io.automatiko.engine.workflow.base.instance.impl.jq.TaskOutputJqAssignmentAction)

Example 4 with Action

use of io.serverlessworkflow.api.actions.Action in project automatiko-engine by automatiko-io.

the class ServerlessWorkflowParser method buildActionsForState.

protected void buildActionsForState(Workflow workflow, List<Action> actions, NodeContainer embeddedSubProcess, ServerlessWorkflowFactory factory, AtomicLong ids, BiConsumer<Node, Node> firstLastNodeConsumer, BiConsumer<Node, Node> actionConsumer, boolean isParallel) {
    Node firstNode = null;
    Node lastNode = null;
    Node prevNode = null;
    for (Action action : actions) {
        if (action.getFunctionRef() != null) {
            // handle function based action
            Optional<FunctionDefinition> functionDefinition = workflow.getFunctions().getFunctionDefs().stream().filter(functionDef -> functionDef.getName().equals(action.getFunctionRef().getRefName())).distinct().findFirst();
            if (functionDefinition.get().getType() == FunctionDefinition.Type.EXPRESSION) {
                ActionNode actionNode = factory.expressionActionStateNode(ids.getAndIncrement(), action.getName(), embeddedSubProcess, functionDefinition.get().getOperation(), action);
                if (firstNode == null) {
                    firstNode = actionNode;
                }
                lastNode = actionNode;
            } else if (functionDefinition.get().getType() == null || functionDefinition.get().getType() == FunctionDefinition.Type.REST) {
                WorkItemNode serviceNode = factory.serviceNode(ids.getAndIncrement(), action, functionDefinition.get(), embeddedSubProcess);
                if (firstNode == null) {
                    firstNode = serviceNode;
                }
                lastNode = serviceNode;
                if (workflow.getTimeouts() != null && workflow.getTimeouts().getActionExecTimeout() != null) {
                    serviceNode.setMetaData("timeout", String.valueOf(DateTimeUtils.parseDuration(workflow.getTimeouts().getActionExecTimeout())));
                }
                if (action.getRetryableErrors() != null && !action.getRetryableErrors().isEmpty()) {
                    List<ErrorDefinition> defs = new ArrayList<>();
                    for (String errorRef : action.getRetryableErrors()) {
                        ErrorDefinition errorDef = workflow.getErrors().getErrorDefs().stream().filter(error -> error.getName().equals(errorRef)).findFirst().orElseThrow(() -> new IllegalStateException("Missing error definition for " + errorRef));
                        defs.add(errorDef);
                    }
                    RetryDefinition retry = null;
                    BoundaryEventNode errorNode = factory.errorBoundaryEventNode(ids.getAndIncrement(), defs, retry, embeddedSubProcess, serviceNode, workflow);
                    EndNode onErrorEnd = factory.endNode(ids.getAndIncrement(), action.getName() + "onErrorEnd", false, embeddedSubProcess);
                    factory.connect(errorNode.getId(), onErrorEnd.getId(), "connect_" + errorNode.getId() + "_" + onErrorEnd.getId(), embeddedSubProcess, false);
                }
            } else {
                throw new UnsupportedOperationException(functionDefinition.get().getType() + " is not yet supported");
            }
        } else if (action.getSubFlowRef() != null) {
            // handler sub workflow action definition
            String workflowId = Objects.requireNonNull(action.getSubFlowRef().getWorkflowId(), "Workflow id for subworkflow is mandatory");
            boolean independent = false;
            if (action.getSubFlowRef().getOnParentComplete() != null && action.getSubFlowRef().getOnParentComplete().equals(OnParentComplete.CONTINUE)) {
                independent = true;
            }
            boolean waitForCompletion = true;
            if (action.getSubFlowRef().getInvoke().equals(Invoke.ASYNC)) {
                waitForCompletion = false;
            }
            SubProcessNode callactivity = factory.callActivity(ids.getAndIncrement(), action.getName(), workflowId, waitForCompletion, embeddedSubProcess);
            callactivity.setIndependent(independent);
            callactivity.setProcessVersion(action.getSubFlowRef().getVersion());
            if (firstNode == null) {
                firstNode = callactivity;
            }
            lastNode = callactivity;
        }
        if (action.getSleep() != null && action.getSleep().getBefore() != null) {
            TimerNode sleep = factory.timerNode(ids.getAndIncrement(), "sleep-before-" + action.getName(), action.getSleep().getBefore(), embeddedSubProcess);
            factory.connect(sleep.getId(), firstNode.getId(), "connection_" + sleep.getId() + "_" + firstNode.getId(), embeddedSubProcess, false);
            firstNode = sleep;
        }
        if (action.getSleep() != null && action.getSleep().getAfter() != null) {
            TimerNode sleep = factory.timerNode(ids.getAndIncrement(), "sleep-after-" + action.getName(), action.getSleep().getAfter(), embeddedSubProcess);
            factory.connect(lastNode.getId(), sleep.getId(), "connection_" + lastNode.getId() + "_" + sleep.getId(), embeddedSubProcess, false);
            lastNode = sleep;
        }
        actionConsumer.accept(firstNode, lastNode);
        if (isParallel && actions.size() > 1) {
            // reset first node as all of action nodes will be first nodes
            firstNode = null;
        } else {
            if (prevNode != null) {
                factory.connect(prevNode.getId(), lastNode.getId(), "connect_" + prevNode.getId() + "_" + lastNode.getId(), embeddedSubProcess, false);
            }
        }
        prevNode = lastNode;
    }
    firstLastNodeConsumer.accept(firstNode, lastNode);
}
Also used : Arrays(java.util.Arrays) TimerNode(io.automatiko.engine.workflow.process.core.node.TimerNode) Workflow(io.serverlessworkflow.api.Workflow) CompositeContextNode(io.automatiko.engine.workflow.process.core.node.CompositeContextNode) Map(java.util.Map) CompletionType(io.serverlessworkflow.api.states.ParallelState.CompletionType) EventState(io.serverlessworkflow.api.states.EventState) OnEvents(io.serverlessworkflow.api.events.OnEvents) Process(io.automatiko.engine.api.definition.process.Process) InputJqAssignmentAction(io.automatiko.engine.workflow.base.instance.impl.jq.InputJqAssignmentAction) Branch(io.serverlessworkflow.api.branches.Branch) JqReturnValueEvaluator(io.automatiko.engine.workflow.base.instance.impl.jq.JqReturnValueEvaluator) EventCondition(io.serverlessworkflow.api.switchconditions.EventCondition) Invoke(io.serverlessworkflow.api.functions.SubFlowRef.Invoke) InjectState(io.serverlessworkflow.api.states.InjectState) ActionNode(io.automatiko.engine.workflow.process.core.node.ActionNode) ErrorDefinition(io.serverlessworkflow.api.error.ErrorDefinition) Reader(java.io.Reader) UUID(java.util.UUID) ReturnValueConstraintEvaluator(io.automatiko.engine.workflow.base.instance.impl.ReturnValueConstraintEvaluator) ParallelState(io.serverlessworkflow.api.states.ParallelState) StandardCharsets(java.nio.charset.StandardCharsets) UncheckedIOException(java.io.UncheckedIOException) Objects(java.util.Objects) List(java.util.List) State(io.serverlessworkflow.api.interfaces.State) WorkItemNode(io.automatiko.engine.workflow.process.core.node.WorkItemNode) Optional(java.util.Optional) Join(io.automatiko.engine.workflow.process.core.node.Join) WorkflowUtils(io.serverlessworkflow.utils.WorkflowUtils) DefaultState(io.serverlessworkflow.api.states.DefaultState) SubProcessNode(io.automatiko.engine.workflow.process.core.node.SubProcessNode) DataCondition(io.serverlessworkflow.api.switchconditions.DataCondition) Assignment(io.automatiko.engine.workflow.process.core.node.Assignment) Action(io.serverlessworkflow.api.actions.Action) NodeContainer(io.automatiko.engine.workflow.process.core.NodeContainer) Split(io.automatiko.engine.workflow.process.core.node.Split) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) ProduceEvent(io.serverlessworkflow.api.produce.ProduceEvent) OutputJqAssignmentAction(io.automatiko.engine.workflow.base.instance.impl.jq.OutputJqAssignmentAction) DataAssociation(io.automatiko.engine.workflow.process.core.node.DataAssociation) FunctionDefinition(io.serverlessworkflow.api.functions.FunctionDefinition) OperationState(io.serverlessworkflow.api.states.OperationState) BoundaryEventNode(io.automatiko.engine.workflow.process.core.node.BoundaryEventNode) Type(io.serverlessworkflow.api.states.DefaultState.Type) BiConsumer(java.util.function.BiConsumer) WorkflowProcess(io.automatiko.engine.workflow.process.core.WorkflowProcess) Connection(io.automatiko.engine.api.definition.process.Connection) Node(io.automatiko.engine.workflow.process.core.Node) CallbackState(io.serverlessworkflow.api.states.CallbackState) ExecutableProcess(io.automatiko.engine.workflow.process.executable.core.ExecutableProcess) IOException(java.io.IOException) DateTimeUtils(io.automatiko.engine.workflow.base.core.timer.DateTimeUtils) OnParentComplete(io.serverlessworkflow.api.functions.SubFlowRef.OnParentComplete) EventDefinition(io.serverlessworkflow.api.events.EventDefinition) SleepState(io.serverlessworkflow.api.states.SleepState) RetryDefinition(io.serverlessworkflow.api.retry.RetryDefinition) AtomicLong(java.util.concurrent.atomic.AtomicLong) StartNode(io.automatiko.engine.workflow.process.core.node.StartNode) ActionMode(io.serverlessworkflow.api.states.OperationState.ActionMode) SwitchState(io.serverlessworkflow.api.states.SwitchState) Collections(java.util.Collections) EndNode(io.automatiko.engine.workflow.process.core.node.EndNode) EventNode(io.automatiko.engine.workflow.process.core.node.EventNode) InputJqAssignmentAction(io.automatiko.engine.workflow.base.instance.impl.jq.InputJqAssignmentAction) Action(io.serverlessworkflow.api.actions.Action) OutputJqAssignmentAction(io.automatiko.engine.workflow.base.instance.impl.jq.OutputJqAssignmentAction) ErrorDefinition(io.serverlessworkflow.api.error.ErrorDefinition) TimerNode(io.automatiko.engine.workflow.process.core.node.TimerNode) CompositeContextNode(io.automatiko.engine.workflow.process.core.node.CompositeContextNode) ActionNode(io.automatiko.engine.workflow.process.core.node.ActionNode) WorkItemNode(io.automatiko.engine.workflow.process.core.node.WorkItemNode) SubProcessNode(io.automatiko.engine.workflow.process.core.node.SubProcessNode) BoundaryEventNode(io.automatiko.engine.workflow.process.core.node.BoundaryEventNode) Node(io.automatiko.engine.workflow.process.core.Node) StartNode(io.automatiko.engine.workflow.process.core.node.StartNode) EndNode(io.automatiko.engine.workflow.process.core.node.EndNode) EventNode(io.automatiko.engine.workflow.process.core.node.EventNode) ActionNode(io.automatiko.engine.workflow.process.core.node.ActionNode) BoundaryEventNode(io.automatiko.engine.workflow.process.core.node.BoundaryEventNode) RetryDefinition(io.serverlessworkflow.api.retry.RetryDefinition) EndNode(io.automatiko.engine.workflow.process.core.node.EndNode) SubProcessNode(io.automatiko.engine.workflow.process.core.node.SubProcessNode) WorkItemNode(io.automatiko.engine.workflow.process.core.node.WorkItemNode) FunctionDefinition(io.serverlessworkflow.api.functions.FunctionDefinition) List(java.util.List) ArrayList(java.util.ArrayList) TimerNode(io.automatiko.engine.workflow.process.core.node.TimerNode)

Example 5 with Action

use of io.serverlessworkflow.api.actions.Action 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;
}
Also used : Arrays(java.util.Arrays) TimerNode(io.automatiko.engine.workflow.process.core.node.TimerNode) Workflow(io.serverlessworkflow.api.Workflow) CompositeContextNode(io.automatiko.engine.workflow.process.core.node.CompositeContextNode) Map(java.util.Map) CompletionType(io.serverlessworkflow.api.states.ParallelState.CompletionType) EventState(io.serverlessworkflow.api.states.EventState) OnEvents(io.serverlessworkflow.api.events.OnEvents) Process(io.automatiko.engine.api.definition.process.Process) InputJqAssignmentAction(io.automatiko.engine.workflow.base.instance.impl.jq.InputJqAssignmentAction) Branch(io.serverlessworkflow.api.branches.Branch) JqReturnValueEvaluator(io.automatiko.engine.workflow.base.instance.impl.jq.JqReturnValueEvaluator) EventCondition(io.serverlessworkflow.api.switchconditions.EventCondition) Invoke(io.serverlessworkflow.api.functions.SubFlowRef.Invoke) InjectState(io.serverlessworkflow.api.states.InjectState) ActionNode(io.automatiko.engine.workflow.process.core.node.ActionNode) ErrorDefinition(io.serverlessworkflow.api.error.ErrorDefinition) Reader(java.io.Reader) UUID(java.util.UUID) ReturnValueConstraintEvaluator(io.automatiko.engine.workflow.base.instance.impl.ReturnValueConstraintEvaluator) ParallelState(io.serverlessworkflow.api.states.ParallelState) StandardCharsets(java.nio.charset.StandardCharsets) UncheckedIOException(java.io.UncheckedIOException) Objects(java.util.Objects) List(java.util.List) State(io.serverlessworkflow.api.interfaces.State) WorkItemNode(io.automatiko.engine.workflow.process.core.node.WorkItemNode) Optional(java.util.Optional) Join(io.automatiko.engine.workflow.process.core.node.Join) WorkflowUtils(io.serverlessworkflow.utils.WorkflowUtils) DefaultState(io.serverlessworkflow.api.states.DefaultState) SubProcessNode(io.automatiko.engine.workflow.process.core.node.SubProcessNode) DataCondition(io.serverlessworkflow.api.switchconditions.DataCondition) Assignment(io.automatiko.engine.workflow.process.core.node.Assignment) Action(io.serverlessworkflow.api.actions.Action) NodeContainer(io.automatiko.engine.workflow.process.core.NodeContainer) Split(io.automatiko.engine.workflow.process.core.node.Split) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) ProduceEvent(io.serverlessworkflow.api.produce.ProduceEvent) OutputJqAssignmentAction(io.automatiko.engine.workflow.base.instance.impl.jq.OutputJqAssignmentAction) DataAssociation(io.automatiko.engine.workflow.process.core.node.DataAssociation) FunctionDefinition(io.serverlessworkflow.api.functions.FunctionDefinition) OperationState(io.serverlessworkflow.api.states.OperationState) BoundaryEventNode(io.automatiko.engine.workflow.process.core.node.BoundaryEventNode) Type(io.serverlessworkflow.api.states.DefaultState.Type) BiConsumer(java.util.function.BiConsumer) WorkflowProcess(io.automatiko.engine.workflow.process.core.WorkflowProcess) Connection(io.automatiko.engine.api.definition.process.Connection) Node(io.automatiko.engine.workflow.process.core.Node) CallbackState(io.serverlessworkflow.api.states.CallbackState) ExecutableProcess(io.automatiko.engine.workflow.process.executable.core.ExecutableProcess) IOException(java.io.IOException) DateTimeUtils(io.automatiko.engine.workflow.base.core.timer.DateTimeUtils) OnParentComplete(io.serverlessworkflow.api.functions.SubFlowRef.OnParentComplete) EventDefinition(io.serverlessworkflow.api.events.EventDefinition) SleepState(io.serverlessworkflow.api.states.SleepState) RetryDefinition(io.serverlessworkflow.api.retry.RetryDefinition) AtomicLong(java.util.concurrent.atomic.AtomicLong) StartNode(io.automatiko.engine.workflow.process.core.node.StartNode) ActionMode(io.serverlessworkflow.api.states.OperationState.ActionMode) SwitchState(io.serverlessworkflow.api.states.SwitchState) Collections(java.util.Collections) EndNode(io.automatiko.engine.workflow.process.core.node.EndNode) EventNode(io.automatiko.engine.workflow.process.core.node.EventNode) CompositeContextNode(io.automatiko.engine.workflow.process.core.node.CompositeContextNode) TimerNode(io.automatiko.engine.workflow.process.core.node.TimerNode) CompositeContextNode(io.automatiko.engine.workflow.process.core.node.CompositeContextNode) ActionNode(io.automatiko.engine.workflow.process.core.node.ActionNode) WorkItemNode(io.automatiko.engine.workflow.process.core.node.WorkItemNode) SubProcessNode(io.automatiko.engine.workflow.process.core.node.SubProcessNode) BoundaryEventNode(io.automatiko.engine.workflow.process.core.node.BoundaryEventNode) Node(io.automatiko.engine.workflow.process.core.Node) StartNode(io.automatiko.engine.workflow.process.core.node.StartNode) EndNode(io.automatiko.engine.workflow.process.core.node.EndNode) EventNode(io.automatiko.engine.workflow.process.core.node.EventNode) ArrayList(java.util.ArrayList) ActionNode(io.automatiko.engine.workflow.process.core.node.ActionNode) ReturnValueConstraintEvaluator(io.automatiko.engine.workflow.base.instance.impl.ReturnValueConstraintEvaluator) EventDefinition(io.serverlessworkflow.api.events.EventDefinition) LinkedHashMap(java.util.LinkedHashMap) Assignment(io.automatiko.engine.workflow.process.core.node.Assignment) CallbackState(io.serverlessworkflow.api.states.CallbackState) BoundaryEventNode(io.automatiko.engine.workflow.process.core.node.BoundaryEventNode) EventNode(io.automatiko.engine.workflow.process.core.node.EventNode) InjectState(io.serverlessworkflow.api.states.InjectState) Branch(io.serverlessworkflow.api.branches.Branch) ParallelState(io.serverlessworkflow.api.states.ParallelState) TimerNode(io.automatiko.engine.workflow.process.core.node.TimerNode) DataCondition(io.serverlessworkflow.api.switchconditions.DataCondition) WorkflowProcess(io.automatiko.engine.workflow.process.core.WorkflowProcess) StartNode(io.automatiko.engine.workflow.process.core.node.StartNode) EventState(io.serverlessworkflow.api.states.EventState) DataAssociation(io.automatiko.engine.workflow.process.core.node.DataAssociation) JqReturnValueEvaluator(io.automatiko.engine.workflow.base.instance.impl.jq.JqReturnValueEvaluator) Connection(io.automatiko.engine.api.definition.process.Connection) Workflow(io.serverlessworkflow.api.Workflow) Join(io.automatiko.engine.workflow.process.core.node.Join) InputJqAssignmentAction(io.automatiko.engine.workflow.base.instance.impl.jq.InputJqAssignmentAction) OutputJqAssignmentAction(io.automatiko.engine.workflow.base.instance.impl.jq.OutputJqAssignmentAction) EventCondition(io.serverlessworkflow.api.switchconditions.EventCondition) OnEvents(io.serverlessworkflow.api.events.OnEvents) SwitchState(io.serverlessworkflow.api.states.SwitchState) AtomicLong(java.util.concurrent.atomic.AtomicLong) EndNode(io.automatiko.engine.workflow.process.core.node.EndNode) EventState(io.serverlessworkflow.api.states.EventState) InjectState(io.serverlessworkflow.api.states.InjectState) ParallelState(io.serverlessworkflow.api.states.ParallelState) State(io.serverlessworkflow.api.interfaces.State) DefaultState(io.serverlessworkflow.api.states.DefaultState) OperationState(io.serverlessworkflow.api.states.OperationState) CallbackState(io.serverlessworkflow.api.states.CallbackState) SleepState(io.serverlessworkflow.api.states.SleepState) SwitchState(io.serverlessworkflow.api.states.SwitchState) AtomicLong(java.util.concurrent.atomic.AtomicLong) Split(io.automatiko.engine.workflow.process.core.node.Split) OperationState(io.serverlessworkflow.api.states.OperationState)

Aggregations

Connection (io.automatiko.engine.api.definition.process.Connection)5 DateTimeUtils (io.automatiko.engine.workflow.base.core.timer.DateTimeUtils)5 OutputJqAssignmentAction (io.automatiko.engine.workflow.base.instance.impl.jq.OutputJqAssignmentAction)5 NodeContainer (io.automatiko.engine.workflow.process.core.NodeContainer)5 ActionNode (io.automatiko.engine.workflow.process.core.node.ActionNode)5 Assignment (io.automatiko.engine.workflow.process.core.node.Assignment)5 BoundaryEventNode (io.automatiko.engine.workflow.process.core.node.BoundaryEventNode)5 CompositeContextNode (io.automatiko.engine.workflow.process.core.node.CompositeContextNode)5 DataAssociation (io.automatiko.engine.workflow.process.core.node.DataAssociation)5 EndNode (io.automatiko.engine.workflow.process.core.node.EndNode)5 EventNode (io.automatiko.engine.workflow.process.core.node.EventNode)5 Join (io.automatiko.engine.workflow.process.core.node.Join)5 Action (io.serverlessworkflow.api.actions.Action)5 JsonNode (com.fasterxml.jackson.databind.JsonNode)4 Workflow (io.serverlessworkflow.api.Workflow)4 FunctionDefinition (io.serverlessworkflow.api.functions.FunctionDefinition)4 List (java.util.List)4 Map (java.util.Map)4 Split (io.automatiko.engine.workflow.process.core.node.Split)3 StartNode (io.automatiko.engine.workflow.process.core.node.StartNode)3