Search in sources :

Example 1 with FunctionDefinition

use of io.serverlessworkflow.api.functions.FunctionDefinition in project kogito-runtimes by kiegroup.

the class CompositeContextNodeHandler method getActionNode.

private NodeFactory<?, ?> getActionNode(RuleFlowNodeContainerFactory<?, ?> embeddedSubProcess, FunctionRef functionRef, String inputVar, String outputVar, String collectVar, String... extraVariables) {
    JsonNode functionArgs = functionRef.getArguments();
    String actionName = functionRef.getRefName();
    FunctionDefinition actionFunction = workflow.getFunctions().getFunctionDefs().stream().filter(wf -> wf.getName().equals(actionName)).findFirst().orElseThrow(() -> new IllegalArgumentException("cannot find function " + actionName));
    ActionType actionType = ActionType.from(actionFunction);
    String operation = actionType.getOperation(actionFunction);
    switch(actionType) {
        case SCRIPT:
            return embeddedSubProcess.actionNode(parserContext.newId()).name(actionName).action(JavaDialect.ID, functionRef.getArguments().get(SCRIPT_TYPE_PARAM).asText());
        case EXPRESSION:
            return embeddedSubProcess.actionNode(parserContext.newId()).name(actionName).action(ExpressionActionSupplier.of(workflow, operation).withVarNames(inputVar, outputVar).withCollectVar(collectVar).withAddInputVars(extraVariables).build());
        case SYSOUT:
            return embeddedSubProcess.actionNode(parserContext.newId()).name(actionName).action(new SysoutActionSupplier(workflow.getExpressionLang(), functionRef.getArguments().get(SYSOUT_TYPE_PARAM).asText(), inputVar, extraVariables));
        case SERVICE:
            WorkItemNodeFactory<?> serviceFactory = addServiceParameters(embeddedSubProcess.workItemNode(parserContext.newId()).name(actionName).metaData(TaskDescriptor.KEY_WORKITEM_TYPE, SERVICE_TASK_TYPE).workName(SERVICE_TASK_TYPE).inMapping(inputVar, WORKITEM_PARAM).outMapping(WORKITEM_PARAM, outputVar), actionFunction, operation);
            if (functionArgs == null || functionArgs.isEmpty()) {
                serviceFactory.workParameter(WORKITEM_PARAM_TYPE, ServerlessWorkflowParser.JSON_NODE);
            } else {
                processArgs(serviceFactory, functionArgs, WORKITEM_PARAM, ObjectResolver.class);
            }
            return serviceFactory;
        case REST:
            WorkItemNodeFactory<?> workItemFactory = addRestParameters(embeddedSubProcess.workItemNode(parserContext.newId()).name(actionFunction.getName()).metaData(TaskDescriptor.KEY_WORKITEM_TYPE, RestWorkItemHandler.REST_TASK_TYPE).workName(RestWorkItemHandler.REST_TASK_TYPE).workParameter(RestWorkItemHandler.BODY_BUILDER, new RestBodyBuilderSupplier()).inMapping(inputVar, RestWorkItemHandler.CONTENT_DATA).outMapping(RestWorkItemHandler.RESULT, outputVar), actionFunction, operation);
            if (functionArgs != null && !functionArgs.isEmpty()) {
                processArgs(workItemFactory, functionArgs, RestWorkItemHandler.CONTENT_DATA, ObjectResolver.class);
            }
            return workItemFactory;
        case OPENAPI:
            return OpenApiTaskDescriptor.builderFor(ServerlessWorkflowUtils.getOpenApiURI(actionFunction), ServerlessWorkflowUtils.getOpenApiOperationId(actionFunction)).withExprLang(workflow.getExpressionLang()).withModelParameter(WORKITEM_PARAM).withArgs(functionsToMap(functionArgs), JsonNodeResolver.class, JsonNode.class).build(embeddedSubProcess.workItemNode(parserContext.newId())).name(functionRef.getRefName()).inMapping(inputVar, WORKITEM_PARAM).outMapping(WORKITEM_RESULT, outputVar);
        default:
            return emptyNode(embeddedSubProcess, actionName);
    }
}
Also used : SysoutActionSupplier(org.kie.kogito.serverless.workflow.suppliers.SysoutActionSupplier) RestBodyBuilderSupplier(org.kie.kogito.serverless.workflow.suppliers.RestBodyBuilderSupplier) JsonNode(com.fasterxml.jackson.databind.JsonNode) FunctionDefinition(io.serverlessworkflow.api.functions.FunctionDefinition)

Example 2 with FunctionDefinition

use of io.serverlessworkflow.api.functions.FunctionDefinition in project kogito-runtimes by kiegroup.

the class BuildExpressionsTest method testReplaceExpr.

@Test
void testReplaceExpr() {
    Workflow flow = mock(Workflow.class);
    FunctionDefinition functionDefinition = new FunctionDefinition();
    functionDefinition.setType(Type.EXPRESSION);
    functionDefinition.setOperation(".pepe");
    functionDefinition.setName("pepe");
    Functions functions = new Functions(Collections.singletonList(functionDefinition));
    when(flow.getFunctions()).thenReturn(functions);
    assertEquals("\"fn:pepe\"", ExpressionHandlerUtils.replaceExpr(flow, "\"fn:pepe\""));
    assertEquals(".pepe", ExpressionHandlerUtils.replaceExpr(flow, "fn:pepe"));
    assertEquals(".pepe", ExpressionHandlerUtils.replaceExpr(flow, "${fn:pepe}"));
    assertThrows(IllegalArgumentException.class, () -> ExpressionHandlerUtils.replaceExpr(flow, "${fn:NoPepe}"));
}
Also used : Workflow(io.serverlessworkflow.api.Workflow) FunctionDefinition(io.serverlessworkflow.api.functions.FunctionDefinition) Functions(io.serverlessworkflow.api.workflow.Functions) Test(org.junit.jupiter.api.Test)

Example 3 with FunctionDefinition

use of io.serverlessworkflow.api.functions.FunctionDefinition 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 4 with FunctionDefinition

use of io.serverlessworkflow.api.functions.FunctionDefinition in project kogito-runtimes by kiegroup.

the class WorkflowUtilsTest method testResolveFunctionMetadata.

@Test
public void testResolveFunctionMetadata() {
    FunctionDefinition function = new FunctionDefinition().withName("testfunction1").withMetadata(Collections.singletonMap("testprop1", "customtestprop1val"));
    String testProp1Val = ServerlessWorkflowUtils.resolveFunctionMetadata(function, "testprop1", context);
    assertThat(testProp1Val).isNotNull().isEqualTo("customtestprop1val");
    String testProp2Val = ServerlessWorkflowUtils.resolveFunctionMetadata(function, "testprop2", context);
    assertThat(testProp2Val).isNotNull().isEqualTo("testprop2val");
}
Also used : FunctionDefinition(io.serverlessworkflow.api.functions.FunctionDefinition) Test(org.junit.jupiter.api.Test)

Aggregations

FunctionDefinition (io.serverlessworkflow.api.functions.FunctionDefinition)4 Workflow (io.serverlessworkflow.api.Workflow)2 JsonNode (com.fasterxml.jackson.databind.JsonNode)1 Connection (io.automatiko.engine.api.definition.process.Connection)1 Process (io.automatiko.engine.api.definition.process.Process)1 DateTimeUtils (io.automatiko.engine.workflow.base.core.timer.DateTimeUtils)1 ReturnValueConstraintEvaluator (io.automatiko.engine.workflow.base.instance.impl.ReturnValueConstraintEvaluator)1 InputJqAssignmentAction (io.automatiko.engine.workflow.base.instance.impl.jq.InputJqAssignmentAction)1 JqReturnValueEvaluator (io.automatiko.engine.workflow.base.instance.impl.jq.JqReturnValueEvaluator)1 OutputJqAssignmentAction (io.automatiko.engine.workflow.base.instance.impl.jq.OutputJqAssignmentAction)1 Node (io.automatiko.engine.workflow.process.core.Node)1 NodeContainer (io.automatiko.engine.workflow.process.core.NodeContainer)1 WorkflowProcess (io.automatiko.engine.workflow.process.core.WorkflowProcess)1 ActionNode (io.automatiko.engine.workflow.process.core.node.ActionNode)1 Assignment (io.automatiko.engine.workflow.process.core.node.Assignment)1 BoundaryEventNode (io.automatiko.engine.workflow.process.core.node.BoundaryEventNode)1 CompositeContextNode (io.automatiko.engine.workflow.process.core.node.CompositeContextNode)1 DataAssociation (io.automatiko.engine.workflow.process.core.node.DataAssociation)1 EndNode (io.automatiko.engine.workflow.process.core.node.EndNode)1 EventNode (io.automatiko.engine.workflow.process.core.node.EventNode)1