diff --git a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaForExecutorBuilder.java b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaForExecutorBuilder.java index 672f6aca..0d80fa6d 100644 --- a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaForExecutorBuilder.java +++ b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaForExecutorBuilder.java @@ -39,7 +39,6 @@ protected JavaForExecutorBuilder( WorkflowApplication application, ResourceLoader resourceLoader) { super(position, task, workflow, application, resourceLoader); - if (task instanceof ForTaskFunction taskFunctions) {} } protected Optional buildWhileFilter() { diff --git a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/func/JavaExpressionFactory.java b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/func/JavaExpressionFactory.java index 2f1820a0..48f8b804 100644 --- a/experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/func/JavaExpressionFactory.java +++ b/experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/func/JavaExpressionFactory.java @@ -15,6 +15,8 @@ */ package io.serverlessworkflow.impl.expressions.func; +import io.serverlessworkflow.api.types.TaskBase; +import io.serverlessworkflow.api.types.TaskMetadata; import io.serverlessworkflow.impl.TaskContext; import io.serverlessworkflow.impl.WorkflowContext; import io.serverlessworkflow.impl.WorkflowFilter; @@ -22,6 +24,7 @@ import io.serverlessworkflow.impl.WorkflowModelFactory; import io.serverlessworkflow.impl.expressions.Expression; import io.serverlessworkflow.impl.expressions.ExpressionFactory; +import java.util.Optional; import java.util.function.BiFunction; import java.util.function.BiPredicate; import java.util.function.Function; @@ -29,6 +32,7 @@ public class JavaExpressionFactory implements ExpressionFactory { + public static final String IF_PREDICATE = "if_predicate"; private final WorkflowModelFactory modelFactory = new JavaModelFactory(); private final Expression dummyExpression = new Expression() { @@ -49,7 +53,7 @@ public WorkflowFilter buildFilter(String expr, Object value) { if (value instanceof Function func) { return (w, t, n) -> modelFactory.fromAny(func.apply(n.asJavaObject())); } else if (value instanceof Predicate pred) { - return (w, t, n) -> modelFactory.from(pred.test(n.asJavaObject())); + return fromPredicate(pred); } else if (value instanceof BiPredicate pred) { return (w, t, n) -> modelFactory.from(pred.test(w, t)); } else if (value instanceof BiFunction func) { @@ -61,6 +65,20 @@ public WorkflowFilter buildFilter(String expr, Object value) { } } + @SuppressWarnings({"rawtypes", "unchecked"}) + private WorkflowFilter fromPredicate(Predicate pred) { + return (w, t, n) -> modelFactory.from(pred.test(n.asJavaObject())); + } + + @Override + public Optional buildIfFilter(TaskBase task) { + TaskMetadata metadata = task.getMetadata(); + return metadata != null + && metadata.getAdditionalProperties().get(IF_PREDICATE) instanceof Predicate pred + ? Optional.of(fromPredicate(pred)) + : ExpressionFactory.super.buildIfFilter(task); + } + @Override public WorkflowModelFactory modelFactory() { return modelFactory; diff --git a/experimental/lambda/src/test/java/io/serverless/workflow/impl/CallTest.java b/experimental/lambda/src/test/java/io/serverless/workflow/impl/CallTest.java index b32fd5e7..12b8353b 100644 --- a/experimental/lambda/src/test/java/io/serverless/workflow/impl/CallTest.java +++ b/experimental/lambda/src/test/java/io/serverless/workflow/impl/CallTest.java @@ -25,6 +25,7 @@ import io.serverlessworkflow.api.types.SwitchTask; import io.serverlessworkflow.api.types.Task; import io.serverlessworkflow.api.types.TaskItem; +import io.serverlessworkflow.api.types.TaskMetadata; import io.serverlessworkflow.api.types.Workflow; import io.serverlessworkflow.api.types.func.CallJava; import io.serverlessworkflow.api.types.func.CallTaskJava; @@ -32,9 +33,11 @@ import io.serverlessworkflow.api.types.func.SwitchCaseFunction; import io.serverlessworkflow.impl.WorkflowApplication; import io.serverlessworkflow.impl.WorkflowDefinition; +import io.serverlessworkflow.impl.expressions.func.JavaExpressionFactory; import java.util.Collection; import java.util.List; import java.util.concurrent.ExecutionException; +import java.util.function.Predicate; import org.junit.jupiter.api.Test; class CallTest { @@ -140,6 +143,35 @@ void testSwitch() throws InterruptedException, ExecutionException { } } + @Test + void testIf() throws InterruptedException, ExecutionException { + try (WorkflowApplication app = WorkflowApplication.builder().build()) { + Workflow workflow = + new Workflow() + .withDocument( + new Document().withNamespace("test").withName("testIf").withVersion("1.0")) + .withDo( + List.of( + new TaskItem( + "java", + new Task() + .withCallTask( + new CallTaskJava( + (CallJava) + CallJava.function(CallTest::zero) + .withMetadata( + new TaskMetadata() + .withAdditionalProperty( + JavaExpressionFactory.IF_PREDICATE, + (Predicate) + CallTest::isOdd))))))); + + WorkflowDefinition definition = app.workflowDefinition(workflow); + assertThat(definition.instance(3).start().get().asNumber().orElseThrow()).isEqualTo(0); + assertThat(definition.instance(4).start().get().asNumber().orElseThrow()).isEqualTo(4); + } + } + public static boolean isEven(Object model, Integer number) { return !isOdd(number); } diff --git a/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowUtils.java b/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowUtils.java index d9bf2824..4a343e3c 100644 --- a/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowUtils.java +++ b/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowUtils.java @@ -116,6 +116,13 @@ public static Optional optionalFilter(WorkflowApplication app, S return str != null ? Optional.of(buildWorkflowFilter(app, str)) : Optional.empty(); } + public static Optional optionalFilter( + WorkflowApplication app, Object obj, String str) { + return str != null || obj != null + ? Optional.of(buildWorkflowFilter(app, str, obj)) + : Optional.empty(); + } + public static String toString(UriTemplate template) { URI uri = template.getLiteralUri(); return uri != null ? uri.toString() : template.getLiteralUriTemplate(); diff --git a/impl/core/src/main/java/io/serverlessworkflow/impl/executors/AbstractTaskExecutor.java b/impl/core/src/main/java/io/serverlessworkflow/impl/executors/AbstractTaskExecutor.java index 414c82c6..a9681f39 100644 --- a/impl/core/src/main/java/io/serverlessworkflow/impl/executors/AbstractTaskExecutor.java +++ b/impl/core/src/main/java/io/serverlessworkflow/impl/executors/AbstractTaskExecutor.java @@ -15,7 +15,8 @@ */ package io.serverlessworkflow.impl.executors; -import static io.serverlessworkflow.impl.WorkflowUtils.*; +import static io.serverlessworkflow.impl.WorkflowUtils.buildWorkflowFilter; +import static io.serverlessworkflow.impl.WorkflowUtils.getSchemaValidator; import io.serverlessworkflow.api.types.Export; import io.serverlessworkflow.api.types.FlowDirective; @@ -101,7 +102,7 @@ protected AbstractTaskExecutorBuilder( this.contextSchemaValidator = getSchemaValidator(application.validatorFactory(), resourceLoader, export.getSchema()); } - this.ifFilter = optionalFilter(application, task.getIf()); + this.ifFilter = application.expressionFactory().buildIfFilter(task); } protected final TransitionInfoBuilder next( diff --git a/impl/core/src/main/java/io/serverlessworkflow/impl/expressions/ExpressionFactory.java b/impl/core/src/main/java/io/serverlessworkflow/impl/expressions/ExpressionFactory.java index 696e4fda..cb14555e 100644 --- a/impl/core/src/main/java/io/serverlessworkflow/impl/expressions/ExpressionFactory.java +++ b/impl/core/src/main/java/io/serverlessworkflow/impl/expressions/ExpressionFactory.java @@ -15,8 +15,10 @@ */ package io.serverlessworkflow.impl.expressions; +import io.serverlessworkflow.api.types.TaskBase; import io.serverlessworkflow.impl.WorkflowFilter; import io.serverlessworkflow.impl.WorkflowModelFactory; +import java.util.Optional; public interface ExpressionFactory { /** @@ -29,4 +31,8 @@ public interface ExpressionFactory { WorkflowFilter buildFilter(String expr, Object value); WorkflowModelFactory modelFactory(); + + default Optional buildIfFilter(TaskBase task) { + return task.getIf() != null ? Optional.of(buildFilter(task.getIf(), null)) : Optional.empty(); + } }