From 4783518b03b58c67002167bb2b8b8ba547ab624b Mon Sep 17 00:00:00 2001 From: Ricardo Zanini Date: Fri, 18 Jul 2025 19:44:32 -0400 Subject: [PATCH 1/3] Introduce Java Fluent DSL Signed-off-by: Ricardo Zanini --- .../api/types/SwitchCaseFunction.java | 4 + fluent/java/pom.xml | 42 +++ .../fluent/java/CallTaskJavaBuilder.java | 47 +++ .../fluent/java/DoTaskJavaBuilder.java | 73 +++++ .../fluent/java/ForTaskJavaBuilder.java | 95 ++++++ .../fluent/java/JavaForEach.java | 21 ++ .../fluent/java/JavaSwitchCase.java | 21 ++ .../java/JavaTransformationHandlers.java | 44 +++ .../fluent/java/JavaWorkflowBuilder.java | 50 ++++ .../fluent/java/SwitchTaskJavaBuilder.java | 90 ++++++ .../fluent/java/JavaWorkflowBuilderTest.java | 277 ++++++++++++++++++ fluent/pom.xml | 11 + .../fluent/standard/BaseDoTaskBuilder.java | 166 +++++++++++ .../fluent/standard/BaseWorkflowBuilder.java | 102 +++++++ .../fluent/standard/DoTaskBuilder.java | 133 +-------- .../fluent/standard/ForEach.java | 21 ++ .../fluent/standard/ForTaskBuilder.java | 21 +- .../fluent/standard/SwitchCase.java | 21 ++ .../fluent/standard/SwitchTaskBuilder.java | 18 +- .../fluent/standard/TaskBaseBuilder.java | 26 +- .../standard/TransformationHandlers.java | 29 ++ .../fluent/standard/TryTaskBuilder.java | 15 +- .../fluent/standard/WorkflowBuilder.java | 62 +--- .../fluent/standard/WorkflowBuilderTest.java | 2 +- 24 files changed, 1187 insertions(+), 204 deletions(-) create mode 100644 fluent/java/pom.xml create mode 100644 fluent/java/src/main/java/io/serverlessworkflow/fluent/java/CallTaskJavaBuilder.java create mode 100644 fluent/java/src/main/java/io/serverlessworkflow/fluent/java/DoTaskJavaBuilder.java create mode 100644 fluent/java/src/main/java/io/serverlessworkflow/fluent/java/ForTaskJavaBuilder.java create mode 100644 fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaForEach.java create mode 100644 fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaSwitchCase.java create mode 100644 fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaTransformationHandlers.java create mode 100644 fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaWorkflowBuilder.java create mode 100644 fluent/java/src/main/java/io/serverlessworkflow/fluent/java/SwitchTaskJavaBuilder.java create mode 100644 fluent/java/src/test/java/io/serverlessworkflow/fluent/java/JavaWorkflowBuilderTest.java create mode 100644 fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseDoTaskBuilder.java create mode 100644 fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseWorkflowBuilder.java create mode 100644 fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/ForEach.java create mode 100644 fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/SwitchCase.java create mode 100644 fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/TransformationHandlers.java diff --git a/experimental/types/src/main/java/io/serverlessworkflow/api/types/SwitchCaseFunction.java b/experimental/types/src/main/java/io/serverlessworkflow/api/types/SwitchCaseFunction.java index 027ab178..51b4175a 100644 --- a/experimental/types/src/main/java/io/serverlessworkflow/api/types/SwitchCaseFunction.java +++ b/experimental/types/src/main/java/io/serverlessworkflow/api/types/SwitchCaseFunction.java @@ -27,6 +27,10 @@ public SwitchCaseFunction withPredicate(Predicate predicate) { return this; } + public void setPredicate(Predicate predicate) { + this.predicate = predicate; + } + public Predicate predicate() { return predicate; } diff --git a/fluent/java/pom.xml b/fluent/java/pom.xml new file mode 100644 index 00000000..aa12ec97 --- /dev/null +++ b/fluent/java/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + io.serverlessworkflow + serverlessworkflow-fluent + 8.0.0-SNAPSHOT + + + Serverless Workflow :: Fluent :: Java + serverlessworkflow-fluent-java + + + 17 + 17 + UTF-8 + + + + + io.serverlessworkflow + serverlessworkflow-experimental-types + + + io.serverlessworkflow + serverlessworkflow-types + + + io.serverlessworkflow + serverlessworkflow-fluent-standard + + + + org.junit.jupiter + junit-jupiter-api + test + + + + \ No newline at end of file diff --git a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/CallTaskJavaBuilder.java b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/CallTaskJavaBuilder.java new file mode 100644 index 00000000..bcedd830 --- /dev/null +++ b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/CallTaskJavaBuilder.java @@ -0,0 +1,47 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.fluent.java; + +import io.serverlessworkflow.api.types.CallJava; +import io.serverlessworkflow.api.types.CallTaskJava; +import io.serverlessworkflow.fluent.standard.TaskBaseBuilder; +import java.util.function.Function; + +public class CallTaskJavaBuilder extends TaskBaseBuilder + implements JavaTransformationHandlers { + + private CallTaskJava callTaskJava; + + CallTaskJavaBuilder() { + callTaskJava = new CallTaskJava(new CallJava() {}); + super.setTask(callTaskJava.getCallJava()); + } + + @Override + protected CallTaskJavaBuilder self() { + return this; + } + + public CallTaskJavaBuilder function(Function function) { + this.callTaskJava = new CallTaskJava(CallJava.function(function)); + super.setTask(this.callTaskJava.getCallJava()); + return this; + } + + public CallTaskJava build() { + return this.callTaskJava; + } +} diff --git a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/DoTaskJavaBuilder.java b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/DoTaskJavaBuilder.java new file mode 100644 index 00000000..2149e63a --- /dev/null +++ b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/DoTaskJavaBuilder.java @@ -0,0 +1,73 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.fluent.java; + +import io.serverlessworkflow.api.types.Task; +import io.serverlessworkflow.api.types.TaskItem; +import io.serverlessworkflow.fluent.standard.BaseDoTaskBuilder; +import java.util.UUID; +import java.util.function.Consumer; + +public class DoTaskJavaBuilder extends BaseDoTaskBuilder + implements JavaTransformationHandlers { + + DoTaskJavaBuilder() { + super(); + } + + @Override + protected DoTaskJavaBuilder self() { + return this; + } + + @Override + protected DoTaskJavaBuilder newDo() { + return new DoTaskJavaBuilder(); + } + + public DoTaskJavaBuilder callFn(String name, Consumer consumer) { + final CallTaskJavaBuilder callTaskJavaBuilder = new CallTaskJavaBuilder(); + consumer.accept(callTaskJavaBuilder); + this.addTaskItem(new TaskItem(name, new Task().withCallTask(callTaskJavaBuilder.build()))); + return this; + } + + public DoTaskJavaBuilder callFn(Consumer consumer) { + return this.callFn(UUID.randomUUID().toString(), consumer); + } + + public DoTaskJavaBuilder forEachFn(String name, Consumer consumer) { + final ForTaskJavaBuilder forTaskJavaBuilder = new ForTaskJavaBuilder(); + consumer.accept(forTaskJavaBuilder); + this.addTaskItem(new TaskItem(name, new Task().withForTask(forTaskJavaBuilder.build()))); + return this; + } + + public DoTaskJavaBuilder forEachFn(Consumer consumer) { + return this.forEachFn(UUID.randomUUID().toString(), consumer); + } + + public DoTaskJavaBuilder switchCaseFn(String name, Consumer consumer) { + final SwitchTaskJavaBuilder switchTaskJavaBuilder = new SwitchTaskJavaBuilder(); + consumer.accept(switchTaskJavaBuilder); + this.addTaskItem(new TaskItem(name, new Task().withSwitchTask(switchTaskJavaBuilder.build()))); + return this; + } + + public DoTaskJavaBuilder switchCaseFn(Consumer consumer) { + return this.switchCaseFn(UUID.randomUUID().toString(), consumer); + } +} diff --git a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/ForTaskJavaBuilder.java b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/ForTaskJavaBuilder.java new file mode 100644 index 00000000..1649c8ea --- /dev/null +++ b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/ForTaskJavaBuilder.java @@ -0,0 +1,95 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.fluent.java; + +import io.serverlessworkflow.api.types.CallJava; +import io.serverlessworkflow.api.types.CallTaskJava; +import io.serverlessworkflow.api.types.ForTaskConfiguration; +import io.serverlessworkflow.api.types.ForTaskFunction; +import io.serverlessworkflow.api.types.Task; +import io.serverlessworkflow.api.types.TaskItem; +import io.serverlessworkflow.fluent.standard.TaskBaseBuilder; +import io.serverlessworkflow.impl.expressions.LoopFunction; +import io.serverlessworkflow.impl.expressions.LoopPredicate; +import io.serverlessworkflow.impl.expressions.LoopPredicateIndex; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.UUID; +import java.util.function.Consumer; +import java.util.function.Function; + +public class ForTaskJavaBuilder extends TaskBaseBuilder + implements JavaTransformationHandlers { + + private final ForTaskFunction forTaskFunction; + private final List items; + + ForTaskJavaBuilder() { + this.forTaskFunction = new ForTaskFunction(); + this.forTaskFunction.withFor(new ForTaskConfiguration()); + this.items = new ArrayList<>(); + super.setTask(forTaskFunction); + } + + @Override + protected ForTaskJavaBuilder self() { + return this; + } + + public ForTaskJavaBuilder whileCondition(LoopPredicate predicate) { + this.forTaskFunction.withWhile(predicate); + return this; + } + + public ForTaskJavaBuilder whileCondition(LoopPredicateIndex predicate) { + this.forTaskFunction.withWhile(predicate); + return this; + } + + public ForTaskJavaBuilder collection(Function> collectionF) { + this.forTaskFunction.withCollection(collectionF); + return this; + } + + public ForTaskJavaBuilder doTasks(String name, LoopFunction function) { + this.items.add( + new TaskItem( + name, + new Task() + .withCallTask( + new CallTaskJava( + CallJava.loopFunction( + function, this.forTaskFunction.getFor().getEach()))))); + return this; + } + + public ForTaskJavaBuilder doTasks(LoopFunction function) { + return this.doTasks(UUID.randomUUID().toString(), function); + } + + public ForTaskJavaBuilder doTasks(Consumer consumer) { + final DoTaskJavaBuilder builder = new DoTaskJavaBuilder(); + consumer.accept(builder); + this.items.addAll(builder.build().getDo()); + return this; + } + + public ForTaskFunction build() { + this.forTaskFunction.setDo(this.items); + return this.forTaskFunction; + } +} diff --git a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaForEach.java b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaForEach.java new file mode 100644 index 00000000..7c0fd8a0 --- /dev/null +++ b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaForEach.java @@ -0,0 +1,21 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.fluent.java; + +@FunctionalInterface +public interface JavaForEach { + void configure(ForTaskJavaBuilder builder); +} diff --git a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaSwitchCase.java b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaSwitchCase.java new file mode 100644 index 00000000..98870713 --- /dev/null +++ b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaSwitchCase.java @@ -0,0 +1,21 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.fluent.java; + +@FunctionalInterface +public interface JavaSwitchCase { + void configure(SwitchTaskJavaBuilder consumer); +} diff --git a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaTransformationHandlers.java b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaTransformationHandlers.java new file mode 100644 index 00000000..c8651b83 --- /dev/null +++ b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaTransformationHandlers.java @@ -0,0 +1,44 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.fluent.java; + +import io.serverlessworkflow.api.types.Export; +import io.serverlessworkflow.api.types.ExportAsFunction; +import io.serverlessworkflow.api.types.Input; +import io.serverlessworkflow.api.types.InputFromFunction; +import io.serverlessworkflow.api.types.Output; +import io.serverlessworkflow.api.types.OutputAsFunction; +import io.serverlessworkflow.fluent.standard.TransformationHandlers; +import java.util.function.Function; + +public interface JavaTransformationHandlers> + extends TransformationHandlers { + + default B exportAsFn(Function function) { + setExport(new Export().withAs(new ExportAsFunction().withFunction(function))); + return (B) this; + } + + default B inputFrom(Function function) { + setInput(new Input().withFrom(new InputFromFunction().withFunction(function))); + return (B) this; + } + + default B outputAs(Function function) { + setOutput(new Output().withAs(new OutputAsFunction().withFunction(function))); + return (B) this; + } +} diff --git a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaWorkflowBuilder.java b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaWorkflowBuilder.java new file mode 100644 index 00000000..5cfee3fd --- /dev/null +++ b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaWorkflowBuilder.java @@ -0,0 +1,50 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.fluent.java; + +import io.serverlessworkflow.fluent.standard.BaseWorkflowBuilder; +import java.util.UUID; + +public class JavaWorkflowBuilder extends BaseWorkflowBuilder + implements JavaTransformationHandlers { + + private JavaWorkflowBuilder(final String name, final String namespace, final String version) { + super(name, namespace, version); + } + + public static JavaWorkflowBuilder workflow(final String name, final String namespace) { + return new JavaWorkflowBuilder(name, namespace, DEFAULT_VERSION); + } + + public static JavaWorkflowBuilder workflow(final String name) { + return new JavaWorkflowBuilder(name, DEFAULT_NAMESPACE, DEFAULT_VERSION); + } + + public static JavaWorkflowBuilder workflow() { + return new JavaWorkflowBuilder( + UUID.randomUUID().toString(), DEFAULT_NAMESPACE, DEFAULT_VERSION); + } + + @Override + protected DoTaskJavaBuilder newDo() { + return new DoTaskJavaBuilder(); + } + + @Override + protected JavaWorkflowBuilder self() { + return this; + } +} diff --git a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/SwitchTaskJavaBuilder.java b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/SwitchTaskJavaBuilder.java new file mode 100644 index 00000000..8b9d98e6 --- /dev/null +++ b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/SwitchTaskJavaBuilder.java @@ -0,0 +1,90 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.fluent.java; + +import io.serverlessworkflow.api.types.FlowDirective; +import io.serverlessworkflow.api.types.FlowDirectiveEnum; +import io.serverlessworkflow.api.types.SwitchCase; +import io.serverlessworkflow.api.types.SwitchCaseFunction; +import io.serverlessworkflow.api.types.SwitchItem; +import io.serverlessworkflow.api.types.SwitchTask; +import io.serverlessworkflow.fluent.standard.TaskBaseBuilder; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.function.Consumer; +import java.util.function.Predicate; + +public class SwitchTaskJavaBuilder extends TaskBaseBuilder + implements JavaTransformationHandlers { + + private final SwitchTask switchTask; + private final List switchItems; + + SwitchTaskJavaBuilder() { + this.switchTask = new SwitchTask(); + this.switchItems = new ArrayList<>(); + super.setTask(switchTask); + } + + @Override + protected SwitchTaskJavaBuilder self() { + return this; + } + + public SwitchTaskJavaBuilder items(Consumer consumer) { + return this.items(UUID.randomUUID().toString(), consumer); + } + + public SwitchTaskJavaBuilder items(String name, Consumer consumer) { + final SwitchCaseJavaBuilder switchCase = new SwitchCaseJavaBuilder(); + consumer.accept(switchCase); + this.switchItems.add(new SwitchItem(name, switchCase.build())); + return this; + } + + public SwitchTask build() { + this.switchTask.setSwitch(this.switchItems); + return switchTask; + } + + public static final class SwitchCaseJavaBuilder { + private final SwitchCaseFunction switchCase; + + SwitchCaseJavaBuilder() { + this.switchCase = new SwitchCaseFunction(); + } + + public SwitchCaseJavaBuilder when(Predicate when) { + this.switchCase.setPredicate(when); + return this; + } + + public SwitchCaseJavaBuilder then(FlowDirective then) { + this.switchCase.setThen(then); + return this; + } + + public SwitchCaseJavaBuilder then(FlowDirectiveEnum then) { + this.switchCase.setThen(new FlowDirective().withFlowDirectiveEnum(then)); + return this; + } + + public SwitchCase build() { + return this.switchCase; + } + } +} diff --git a/fluent/java/src/test/java/io/serverlessworkflow/fluent/java/JavaWorkflowBuilderTest.java b/fluent/java/src/test/java/io/serverlessworkflow/fluent/java/JavaWorkflowBuilderTest.java new file mode 100644 index 00000000..160f783d --- /dev/null +++ b/fluent/java/src/test/java/io/serverlessworkflow/fluent/java/JavaWorkflowBuilderTest.java @@ -0,0 +1,277 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.fluent.java; + +import static org.junit.jupiter.api.Assertions.*; + +import io.serverlessworkflow.api.types.*; +import io.serverlessworkflow.fluent.standard.BaseWorkflowBuilder; +// if you reuse anything +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +/** Tests for JavaWorkflowBuilder + Java DSL extensions. */ +class JavaWorkflowBuilderTest { + + @Test + @DisplayName("Default Java workflow has auto-generated name and default namespace/version") + void testDefaults() { + Workflow wf = JavaWorkflowBuilder.workflow().build(); + assertNotNull(wf); + Document doc = wf.getDocument(); + assertNotNull(doc); + assertEquals(BaseWorkflowBuilder.DEFAULT_NAMESPACE, doc.getNamespace()); + assertEquals(BaseWorkflowBuilder.DEFAULT_VERSION, doc.getVersion()); + assertEquals(BaseWorkflowBuilder.DSL, doc.getDsl()); + assertNotNull(doc.getName()); + } + + @Test + @DisplayName("Spec style forEach still works inside Java workflow") + void testSpecForEachInJavaWorkflow() { + Workflow wf = + JavaWorkflowBuilder.workflow("specLoopFlow") + .doTasks( + d -> + d.forEach(f -> f.each("pet").in("$.pets")) + .set("markDone", s -> s.expr("$.done = true"))) + .build(); + + List items = wf.getDo(); + assertEquals(2, items.size()); + + TaskItem loopItem = items.get(0); + assertNotNull(loopItem.getTask().getForTask(), "Spec ForTask should be present"); + + TaskItem setItem = items.get(1); + assertNotNull(setItem.getTask().getSetTask()); + SetTask st = setItem.getTask().getSetTask(); + assertEquals("$.done = true", st.getSet().getString()); + } + + @Test + @DisplayName("Java style forEach with collection + whileCondition builds ForTaskFunction") + void testJavaForEach() { + Workflow wf = + JavaWorkflowBuilder.workflow("javaLoopFlow") + .doTasks( + d -> + d.forEachFn( + j -> + j.collection(ctx -> List.of("a", "b", "c")) + .whileCondition((String val, Object ctx) -> !val.equals("c")) + .doTasks( + inner -> inner.set("loopFlag", s -> s.expr("$.flag = true"))))) + .build(); + + List items = wf.getDo(); + assertEquals(1, items.size()); + + TaskItem loopItem = items.get(0); + Task task = loopItem.getTask(); + + assertNotNull(task.getForTask(), "Java ForTaskFunction should be present"); + + // Basic structural checks on nested do inside the function loop + ForTaskFunction fn = (ForTaskFunction) task.getForTask(); + assertNotNull(fn.getDo(), "Nested 'do' list inside ForTaskFunction should be populated"); + assertEquals(1, fn.getDo().size()); + Task nested = fn.getDo().get(0).getTask(); + assertNotNull(nested.getSetTask()); + } + + @Test + @DisplayName("Mixed spec and Java loops in one workflow") + void testMixedLoops() { + Workflow wf = + JavaWorkflowBuilder.workflow("mixed") + .doTasks( + d -> + d.forEach(f -> f.each("item").in("$.array")) // spec + .forEachFn(j -> j.collection(ctx -> List.of(1, 2, 3))) // java + ) + .build(); + + List items = wf.getDo(); + assertEquals(2, items.size()); + + Task specLoop = items.get(0).getTask(); + Task javaLoop = items.get(1).getTask(); + + assertNotNull(specLoop.getForTask()); + assertNotNull(javaLoop.getForTask()); + } + + @Test + @DisplayName("Java functional exportAsFn/inputFrom/outputAs set function wrappers (not literals)") + void testJavaFunctionalIO() { + AtomicBoolean exportCalled = new AtomicBoolean(false); + AtomicBoolean inputCalled = new AtomicBoolean(false); + AtomicBoolean outputCalled = new AtomicBoolean(false); + + Workflow wf = + JavaWorkflowBuilder.workflow("fnIO") + .doTasks( + d -> + d.set("init", s -> s.expr("$.x = 1")) + .forEachFn( + j -> + j.collection( + ctx -> { + inputCalled.set(true); + return List.of("x", "y"); + }) + .doTasks( + inner -> + inner + .set("calc", s -> s.expr("$.y = $.x + 1")) + .exportAsFn( + item -> { + exportCalled.set(true); + return Map.of("computed", 42); + }) + .outputAs( + item -> { + outputCalled.set(true); + return Map.of("out", true); + })))) + .build(); + + // Top-level 'do' structure + assertEquals(2, wf.getDo().size()); + + // Find nested forTaskFunction + Task forTaskFnHolder = wf.getDo().get(1).getTask(); + ForTaskFunction fn = (ForTaskFunction) forTaskFnHolder.getForTask(); + assertNotNull(fn); + + // Inspect nested tasks inside the function loop + List nested = fn.getDo(); + assertEquals(1, nested.size()); + TaskBase nestedTask = nested.get(0).getTask().getSetTask(); + assertNotNull(nestedTask); + + // Because functions are likely stored as opaque objects, we check that + // export / output structures exist and are not expression-based. + Export export = fn.getExport(); + assertNotNull(export, "Export should be set via functional variant"); + assertNull( + export.getAs() != null ? export.getAs().getString() : null, + "Export 'as' should not be a plain string when using function variant"); + + Output out = fn.getOutput(); + // If functional output maps to an OutputAsFunction wrapper, adapt the checks: + if (out != null && out.getAs() != null) { + // Expect no literal string if function used + assertNull(out.getAs().getString(), "Output 'as' should not be a literal string"); + } + + // We can't *invoke* lambdas here (unless your runtime exposes them), + // but we verified structural placement. Flipping AtomicBooleans in creation lambdas + // (collection) at least shows one function executed during build (if it is executed now; + // if they are deferred, remove those assertions.) + } + + @Test + @DisplayName("callJava task added and retains name + CallTask union") + void testCallJavaTask() { + Workflow wf = + JavaWorkflowBuilder.workflow("callJavaFlow") + .doTasks( + d -> + d.callFn( + "invokeHandler", + cj -> { + // configure your CallTaskJavaBuilder here + // e.g., cj.className("com.acme.Handler").arg("key", "value"); + })) + .build(); + + List items = wf.getDo(); + assertEquals(1, items.size()); + TaskItem ti = items.get(0); + + assertEquals("invokeHandler", ti.getName()); + Task task = ti.getTask(); + assertNotNull(task.getCallTask(), "CallTask should be present for callJava"); + // Additional assertions if CallTaskJavaBuilder populates fields + // e.g., assertEquals("com.acme.Handler", task.getCallTask().getCallJava().getClassName()); + } + + @Test + @DisplayName("switchCaseFn (Java variant) coexists with spec tasks") + void testSwitchCaseJava() { + Workflow wf = + JavaWorkflowBuilder.workflow("switchJava") + .doTasks( + d -> + d.set("prepare", s -> s.expr("$.ready = true")) + .switchCase( + sw -> { + // configure Java switch builder (cases / predicates) + })) + .build(); + + List items = wf.getDo(); + assertEquals(2, items.size()); + + Task specSet = items.get(0).getTask(); + Task switchTask = items.get(1).getTask(); + + assertNotNull(specSet.getSetTask()); + assertNotNull(switchTask.getSwitchTask(), "SwitchTask union should be present"); + } + + @Test + @DisplayName("Combined: spec set + java forEach + callJava inside nested do") + void testCompositeScenario() { + Workflow wf = + JavaWorkflowBuilder.workflow("composite") + .doTasks( + d -> + d.set("init", s -> s.expr("$.val = 0")) + .forEachFn( + j -> + j.collection(ctx -> List.of("a", "b")) + .doTasks( + inner -> + inner + .callFn( + cj -> { + // customizing Java call + }) + .set("flag", s -> s.expr("$.flag = true"))))) + .build(); + + assertEquals(2, wf.getDo().size()); + + Task loopHolder = wf.getDo().get(1).getTask(); + ForTaskFunction fn = (ForTaskFunction) loopHolder.getForTask(); + assertNotNull(fn); + + List nested = fn.getDo(); + assertEquals(2, nested.size()); + + Task nestedCall = nested.get(0).getTask(); + Task nestedSet = nested.get(1).getTask(); + + assertNotNull(nestedCall.getCallTask()); + assertNotNull(nestedSet.getSetTask()); + } +} diff --git a/fluent/pom.xml b/fluent/pom.xml index 71d54a64..1af30562 100644 --- a/fluent/pom.xml +++ b/fluent/pom.xml @@ -25,11 +25,22 @@ serverlessworkflow-types ${project.version} + + io.serverlessworkflow + serverlessworkflow-experimental-types + ${project.version} + + + io.serverlessworkflow + serverlessworkflow-fluent-standard + ${project.version} + standard + java \ No newline at end of file diff --git a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseDoTaskBuilder.java b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseDoTaskBuilder.java new file mode 100644 index 00000000..91073c7e --- /dev/null +++ b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseDoTaskBuilder.java @@ -0,0 +1,166 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.fluent.standard; + +import io.serverlessworkflow.api.types.CallTask; +import io.serverlessworkflow.api.types.DoTask; +import io.serverlessworkflow.api.types.Task; +import io.serverlessworkflow.api.types.TaskItem; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.function.Consumer; + +public abstract class BaseDoTaskBuilder> extends TaskBaseBuilder { + private final DoTask doTask; + private final List list; + + protected BaseDoTaskBuilder() { + this.doTask = new DoTask(); + this.list = new ArrayList<>(); + this.setTask(doTask); + } + + protected abstract T self(); + + protected abstract T newDo(); + + protected final void addTaskItem(TaskItem taskItem) { + if (taskItem != null) { + this.list.add(taskItem); + } + } + + protected final void addTaskItem(List taskItem) { + if (taskItem != null) { + this.list.addAll(taskItem); + } + } + + public T set(String name, Consumer itemsConfigurer) { + final SetTaskBuilder setBuilder = new SetTaskBuilder(); + itemsConfigurer.accept(setBuilder); + this.list.add(new TaskItem(name, new Task().withSetTask(setBuilder.build()))); + return self(); + } + + public T set(Consumer itemsConfigurer) { + return this.set(UUID.randomUUID().toString(), itemsConfigurer); + } + + public T set(String name, final String expr) { + return this.set(name, s -> s.expr(expr)); + } + + public T set(final String expr) { + return this.set(UUID.randomUUID().toString(), s -> s.expr(expr)); + } + + public T forEach(String name, ForEach itemsConfigurer) { + final ForTaskBuilder forBuilder = new ForTaskBuilder<>(newDo()); + itemsConfigurer.configure(forBuilder); + this.list.add(new TaskItem(name, new Task().withForTask(forBuilder.build()))); + return self(); + } + + public T forEach(ForEach itemsConfigurer) { + return this.forEach(UUID.randomUUID().toString(), itemsConfigurer); + } + + public T switchCase(String name, SwitchCase itemsConfigurer) { + final SwitchTaskBuilder switchBuilder = new SwitchTaskBuilder(); + itemsConfigurer.configure(switchBuilder); + this.list.add(new TaskItem(name, new Task().withSwitchTask(switchBuilder.build()))); + return self(); + } + + public T switchCase(SwitchCase itemsConfigurer) { + return this.switchCase(UUID.randomUUID().toString(), itemsConfigurer); + } + + public T raise(String name, Consumer itemsConfigurer) { + final RaiseTaskBuilder raiseBuilder = new RaiseTaskBuilder(); + itemsConfigurer.accept(raiseBuilder); + this.list.add(new TaskItem(name, new Task().withRaiseTask(raiseBuilder.build()))); + return self(); + } + + public T raise(Consumer itemsConfigurer) { + return this.raise(UUID.randomUUID().toString(), itemsConfigurer); + } + + public T fork(String name, Consumer itemsConfigurer) { + final ForkTaskBuilder forkBuilder = new ForkTaskBuilder(); + itemsConfigurer.accept(forkBuilder); + this.list.add(new TaskItem(name, new Task().withForkTask(forkBuilder.build()))); + return self(); + } + + public T fork(Consumer itemsConfigurer) { + return this.fork(UUID.randomUUID().toString(), itemsConfigurer); + } + + public T listen(String name, Consumer itemsConfigurer) { + final ListenTaskBuilder listenBuilder = new ListenTaskBuilder(); + itemsConfigurer.accept(listenBuilder); + this.list.add(new TaskItem(name, new Task().withListenTask(listenBuilder.build()))); + return self(); + } + + public T listen(Consumer itemsConfigurer) { + return this.listen(UUID.randomUUID().toString(), itemsConfigurer); + } + + public T emit(String name, Consumer itemsConfigurer) { + final EmitTaskBuilder emitBuilder = new EmitTaskBuilder(); + itemsConfigurer.accept(emitBuilder); + this.list.add(new TaskItem(name, new Task().withEmitTask(emitBuilder.build()))); + return self(); + } + + public T emit(Consumer itemsConfigurer) { + return this.emit(UUID.randomUUID().toString(), itemsConfigurer); + } + + public T tryTask(String name, Consumer> itemsConfigurer) { + final TryTaskBuilder tryBuilder = new TryTaskBuilder<>(this.newDo()); + itemsConfigurer.accept(tryBuilder); + this.list.add(new TaskItem(name, new Task().withTryTask(tryBuilder.build()))); + return self(); + } + + public T tryTask(Consumer> itemsConfigurer) { + return this.tryTask(UUID.randomUUID().toString(), itemsConfigurer); + } + + public T callHTTP(String name, Consumer itemsConfigurer) { + final CallHTTPTaskBuilder callHTTPBuilder = new CallHTTPTaskBuilder(); + itemsConfigurer.accept(callHTTPBuilder); + this.list.add( + new TaskItem( + name, new Task().withCallTask(new CallTask().withCallHTTP(callHTTPBuilder.build())))); + return self(); + } + + public T callHTTP(Consumer itemsConfigurer) { + return this.callHTTP(UUID.randomUUID().toString(), itemsConfigurer); + } + + public DoTask build() { + this.doTask.setDo(this.list); + return this.doTask; + } +} diff --git a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseWorkflowBuilder.java b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseWorkflowBuilder.java new file mode 100644 index 00000000..e6db176f --- /dev/null +++ b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseWorkflowBuilder.java @@ -0,0 +1,102 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.fluent.standard; + +import io.serverlessworkflow.api.types.Document; +import io.serverlessworkflow.api.types.Export; +import io.serverlessworkflow.api.types.Input; +import io.serverlessworkflow.api.types.Output; +import io.serverlessworkflow.api.types.Workflow; +import java.util.function.Consumer; + +public abstract class BaseWorkflowBuilder< + W extends BaseWorkflowBuilder, DB extends BaseDoTaskBuilder> + implements TransformationHandlers { + + public static final String DSL = "1.0.0"; + public static final String DEFAULT_VERSION = "0.0.1"; + public static final String DEFAULT_NAMESPACE = "org.acme"; + + private final Workflow workflow; + private final Document document; + + protected BaseWorkflowBuilder(final String name, final String namespace, final String version) { + this.document = new Document(); + this.document.setName(name); + this.document.setNamespace(namespace); + this.document.setVersion(version); + this.document.setDsl(DSL); + this.workflow = new Workflow(); + this.workflow.setDocument(this.document); + } + + protected abstract DB newDo(); + + protected abstract W self(); + + @Override + public void setOutput(Output output) { + this.workflow.setOutput(output); + } + + @Override + public void setExport(Export export) { + // TODO: build another interface with only Output and Input + } + + @Override + public void setInput(Input input) { + this.workflow.setInput(input); + } + + public W document(Consumer documentBuilderConsumer) { + final DocumentBuilder documentBuilder = new DocumentBuilder(this.document); + documentBuilderConsumer.accept(documentBuilder); + return self(); + } + + public W use(Consumer useBuilderConsumer) { + final UseBuilder builder = new UseBuilder(); + useBuilderConsumer.accept(builder); + this.workflow.setUse(builder.build()); + return self(); + } + + public W doTasks(Consumer doTaskConsumer) { + final DB doTaskBuilder = newDo(); + doTaskConsumer.accept(doTaskBuilder); + this.workflow.setDo(doTaskBuilder.build().getDo()); + return self(); + } + + public W input(Consumer inputBuilderConsumer) { + final InputBuilder inputBuilder = new InputBuilder(); + inputBuilderConsumer.accept(inputBuilder); + this.workflow.setInput(inputBuilder.build()); + return self(); + } + + public W output(Consumer outputBuilderConsumer) { + final OutputBuilder outputBuilder = new OutputBuilder(); + outputBuilderConsumer.accept(outputBuilder); + this.workflow.setOutput(outputBuilder.build()); + return self(); + } + + public Workflow build() { + return this.workflow; + } +} diff --git a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/DoTaskBuilder.java b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/DoTaskBuilder.java index 3de5cfe7..51221463 100644 --- a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/DoTaskBuilder.java +++ b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/DoTaskBuilder.java @@ -15,24 +15,10 @@ */ package io.serverlessworkflow.fluent.standard; -import io.serverlessworkflow.api.types.CallTask; -import io.serverlessworkflow.api.types.DoTask; -import io.serverlessworkflow.api.types.Task; -import io.serverlessworkflow.api.types.TaskItem; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import java.util.function.Consumer; - -public class DoTaskBuilder extends TaskBaseBuilder { - - private final DoTask doTask; - private final List list; +public class DoTaskBuilder extends BaseDoTaskBuilder { DoTaskBuilder() { - this.doTask = new DoTask(); - this.list = new ArrayList<>(); - this.setTask(doTask); + super(); } @Override @@ -40,117 +26,8 @@ protected DoTaskBuilder self() { return this; } - public DoTaskBuilder set(String name, Consumer itemsConfigurer) { - final SetTaskBuilder setBuilder = new SetTaskBuilder(); - itemsConfigurer.accept(setBuilder); - this.list.add(new TaskItem(name, new Task().withSetTask(setBuilder.build()))); - return this; - } - - public DoTaskBuilder set(Consumer itemsConfigurer) { - return this.set(UUID.randomUUID().toString(), itemsConfigurer); - } - - public DoTaskBuilder set(String name, final String expr) { - return this.set(name, s -> s.expr(expr)); - } - - public DoTaskBuilder set(final String expr) { - return this.set(UUID.randomUUID().toString(), s -> s.expr(expr)); - } - - public DoTaskBuilder forEach(String name, Consumer itemsConfigurer) { - final ForTaskBuilder forBuilder = new ForTaskBuilder(); - itemsConfigurer.accept(forBuilder); - this.list.add(new TaskItem(name, new Task().withForTask(forBuilder.build()))); - return this; - } - - public DoTaskBuilder forEach(Consumer itemsConfigurer) { - return this.forEach(UUID.randomUUID().toString(), itemsConfigurer); - } - - public DoTaskBuilder switchTask(String name, Consumer itemsConfigurer) { - final SwitchTaskBuilder switchBuilder = new SwitchTaskBuilder(); - itemsConfigurer.accept(switchBuilder); - this.list.add(new TaskItem(name, new Task().withSwitchTask(switchBuilder.build()))); - return this; - } - - public DoTaskBuilder switchTask(Consumer itemsConfigurer) { - return this.switchTask(UUID.randomUUID().toString(), itemsConfigurer); - } - - public DoTaskBuilder raise(String name, Consumer itemsConfigurer) { - final RaiseTaskBuilder raiseBuilder = new RaiseTaskBuilder(); - itemsConfigurer.accept(raiseBuilder); - this.list.add(new TaskItem(name, new Task().withRaiseTask(raiseBuilder.build()))); - return this; - } - - public DoTaskBuilder raise(Consumer itemsConfigurer) { - return this.raise(UUID.randomUUID().toString(), itemsConfigurer); - } - - public DoTaskBuilder fork(String name, Consumer itemsConfigurer) { - final ForkTaskBuilder forkBuilder = new ForkTaskBuilder(); - itemsConfigurer.accept(forkBuilder); - this.list.add(new TaskItem(name, new Task().withForkTask(forkBuilder.build()))); - return this; - } - - public DoTaskBuilder fork(Consumer itemsConfigurer) { - return this.fork(UUID.randomUUID().toString(), itemsConfigurer); - } - - public DoTaskBuilder listen(String name, Consumer itemsConfigurer) { - final ListenTaskBuilder listenBuilder = new ListenTaskBuilder(); - itemsConfigurer.accept(listenBuilder); - this.list.add(new TaskItem(name, new Task().withListenTask(listenBuilder.build()))); - return this; - } - - public DoTaskBuilder listen(Consumer itemsConfigurer) { - return this.listen(UUID.randomUUID().toString(), itemsConfigurer); - } - - public DoTaskBuilder emit(String name, Consumer itemsConfigurer) { - final EmitTaskBuilder emitBuilder = new EmitTaskBuilder(); - itemsConfigurer.accept(emitBuilder); - this.list.add(new TaskItem(name, new Task().withEmitTask(emitBuilder.build()))); - return this; - } - - public DoTaskBuilder emit(Consumer itemsConfigurer) { - return this.emit(UUID.randomUUID().toString(), itemsConfigurer); - } - - public DoTaskBuilder tryTask(String name, Consumer itemsConfigurer) { - final TryTaskBuilder tryBuilder = new TryTaskBuilder(); - itemsConfigurer.accept(tryBuilder); - this.list.add(new TaskItem(name, new Task().withTryTask(tryBuilder.build()))); - return this; - } - - public DoTaskBuilder tryTask(Consumer itemsConfigurer) { - return this.tryTask(UUID.randomUUID().toString(), itemsConfigurer); - } - - public DoTaskBuilder callHTTP(String name, Consumer itemsConfigurer) { - final CallHTTPTaskBuilder callHTTPBuilder = new CallHTTPTaskBuilder(); - itemsConfigurer.accept(callHTTPBuilder); - this.list.add( - new TaskItem( - name, new Task().withCallTask(new CallTask().withCallHTTP(callHTTPBuilder.build())))); - return this; - } - - public DoTaskBuilder callHTTP(Consumer itemsConfigurer) { - return this.callHTTP(UUID.randomUUID().toString(), itemsConfigurer); - } - - public DoTask build() { - this.doTask.setDo(this.list); - return this.doTask; + @Override + protected DoTaskBuilder newDo() { + return new DoTaskBuilder(); } } diff --git a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/ForEach.java b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/ForEach.java new file mode 100644 index 00000000..9756ef6b --- /dev/null +++ b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/ForEach.java @@ -0,0 +1,21 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.fluent.standard; + +@FunctionalInterface +public interface ForEach> { + void configure(ForTaskBuilder builder); +} diff --git a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/ForTaskBuilder.java b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/ForTaskBuilder.java index e755eebd..e932e368 100644 --- a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/ForTaskBuilder.java +++ b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/ForTaskBuilder.java @@ -19,44 +19,47 @@ import io.serverlessworkflow.api.types.ForTaskConfiguration; import java.util.function.Consumer; -public class ForTaskBuilder extends TaskBaseBuilder { +public class ForTaskBuilder> + extends TaskBaseBuilder> { private final ForTask forTask; private final ForTaskConfiguration forTaskConfiguration; + private final T doTaskBuilderFactory; - ForTaskBuilder() { + ForTaskBuilder(T doTaskBuilderFactory) { super(); forTask = new ForTask(); forTaskConfiguration = new ForTaskConfiguration(); + this.doTaskBuilderFactory = doTaskBuilderFactory; super.setTask(forTask); } - protected ForTaskBuilder self() { + protected ForTaskBuilder self() { return this; } - public ForTaskBuilder each(String each) { + public ForTaskBuilder each(String each) { forTaskConfiguration.setEach(each); return this; } - public ForTaskBuilder in(String in) { + public ForTaskBuilder in(String in) { this.forTaskConfiguration.setIn(in); return this; } - public ForTaskBuilder at(String at) { + public ForTaskBuilder at(String at) { this.forTaskConfiguration.setAt(at); return this; } - public ForTaskBuilder whileCondition(final String expression) { + public ForTaskBuilder whileCondition(final String expression) { this.forTask.setWhile(expression); return this; } - public ForTaskBuilder doTasks(Consumer doBuilderConsumer) { - final DoTaskBuilder doTaskBuilder = new DoTaskBuilder(); + public ForTaskBuilder doTasks(Consumer doBuilderConsumer) { + final T doTaskBuilder = this.doTaskBuilderFactory.newDo(); doBuilderConsumer.accept(doTaskBuilder); this.forTask.setDo(doTaskBuilder.build().getDo()); return this; diff --git a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/SwitchCase.java b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/SwitchCase.java new file mode 100644 index 00000000..f7805dd2 --- /dev/null +++ b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/SwitchCase.java @@ -0,0 +1,21 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.fluent.standard; + +@FunctionalInterface +public interface SwitchCase { + void configure(SwitchTaskBuilder consumer); +} diff --git a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/SwitchTaskBuilder.java b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/SwitchTaskBuilder.java index 12e027ee..fca04cdf 100644 --- a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/SwitchTaskBuilder.java +++ b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/SwitchTaskBuilder.java @@ -15,11 +15,14 @@ */ package io.serverlessworkflow.fluent.standard; +import io.serverlessworkflow.api.types.FlowDirective; +import io.serverlessworkflow.api.types.FlowDirectiveEnum; import io.serverlessworkflow.api.types.SwitchCase; import io.serverlessworkflow.api.types.SwitchItem; import io.serverlessworkflow.api.types.SwitchTask; import java.util.ArrayList; import java.util.List; +import java.util.UUID; import java.util.function.Consumer; public class SwitchTaskBuilder extends TaskBaseBuilder { @@ -39,7 +42,11 @@ protected SwitchTaskBuilder self() { return this; } - public SwitchTaskBuilder switchTask( + public SwitchTaskBuilder items(Consumer switchCaseConsumer) { + return this.items(UUID.randomUUID().toString(), switchCaseConsumer); + } + + public SwitchTaskBuilder items( final String name, Consumer switchCaseConsumer) { final SwitchCaseBuilder switchCaseBuilder = new SwitchCaseBuilder(); switchCaseConsumer.accept(switchCaseBuilder); @@ -64,8 +71,13 @@ public SwitchCaseBuilder when(String when) { return this; } - public SwitchCaseBuilder then(String then) { - this.switchCase.setWhen(then); + public SwitchCaseBuilder then(FlowDirective then) { + this.switchCase.setThen(then); + return this; + } + + public SwitchCaseBuilder then(FlowDirectiveEnum then) { + this.switchCase.setThen(new FlowDirective().withFlowDirectiveEnum(then)); return this; } diff --git a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/TaskBaseBuilder.java b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/TaskBaseBuilder.java index 31d30b3f..e4b9a623 100644 --- a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/TaskBaseBuilder.java +++ b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/TaskBaseBuilder.java @@ -21,24 +21,42 @@ import io.serverlessworkflow.api.types.ExternalResource; import io.serverlessworkflow.api.types.FlowDirective; import io.serverlessworkflow.api.types.FlowDirectiveEnum; +import io.serverlessworkflow.api.types.Input; +import io.serverlessworkflow.api.types.Output; import io.serverlessworkflow.api.types.SchemaExternal; import io.serverlessworkflow.api.types.SchemaInline; import io.serverlessworkflow.api.types.SchemaUnion; import io.serverlessworkflow.api.types.TaskBase; import java.util.function.Consumer; -public abstract class TaskBaseBuilder> { - protected abstract T self(); - +public abstract class TaskBaseBuilder> + implements TransformationHandlers { private TaskBase task; protected TaskBaseBuilder() {} + protected abstract T self(); + protected void setTask(TaskBase task) { this.task = task; } - public T _if(String id) { + @Override + public void setInput(Input input) { + this.task.setInput(input); + } + + @Override + public void setExport(Export export) { + this.task.setExport(export); + } + + @Override + public void setOutput(Output output) { + this.task.setOutput(output); + } + + public T ifClause(String id) { this.task.setIf(id); return self(); } diff --git a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/TransformationHandlers.java b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/TransformationHandlers.java new file mode 100644 index 00000000..298f2fbe --- /dev/null +++ b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/TransformationHandlers.java @@ -0,0 +1,29 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.fluent.standard; + +import io.serverlessworkflow.api.types.Export; +import io.serverlessworkflow.api.types.Input; +import io.serverlessworkflow.api.types.Output; + +public interface TransformationHandlers { + + void setOutput(final Output output); + + void setExport(final Export export); + + void setInput(final Input input); +} diff --git a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/TryTaskBuilder.java b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/TryTaskBuilder.java index 2e022503..0ff46fe4 100644 --- a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/TryTaskBuilder.java +++ b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/TryTaskBuilder.java @@ -34,27 +34,30 @@ import io.serverlessworkflow.api.types.TryTaskCatch; import java.util.function.Consumer; -public class TryTaskBuilder extends TaskBaseBuilder { +public class TryTaskBuilder> + extends TaskBaseBuilder> { private final TryTask tryTask; + private final T doTaskBuilderFactory; - TryTaskBuilder() { + TryTaskBuilder(T doTaskBuilderFactory) { this.tryTask = new TryTask(); + this.doTaskBuilderFactory = doTaskBuilderFactory; } @Override - protected TryTaskBuilder self() { + protected TryTaskBuilder self() { return this; } - public TryTaskBuilder tryHandler(Consumer consumer) { - final DoTaskBuilder doTaskBuilder = new DoTaskBuilder(); + public TryTaskBuilder tryHandler(Consumer consumer) { + final T doTaskBuilder = this.doTaskBuilderFactory.newDo(); consumer.accept(doTaskBuilder); this.tryTask.setTry(doTaskBuilder.build().getDo()); return this; } - public TryTaskBuilder catchHandler(Consumer consumer) { + public TryTaskBuilder catchHandler(Consumer consumer) { final TryTaskCatchBuilder catchBuilder = new TryTaskCatchBuilder(); consumer.accept(catchBuilder); this.tryTask.setCatch(catchBuilder.build()); diff --git a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/WorkflowBuilder.java b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/WorkflowBuilder.java index 742b5761..7d194c34 100644 --- a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/WorkflowBuilder.java +++ b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/WorkflowBuilder.java @@ -15,28 +15,17 @@ */ package io.serverlessworkflow.fluent.standard; -import io.serverlessworkflow.api.types.Document; -import io.serverlessworkflow.api.types.Workflow; import java.util.UUID; -import java.util.function.Consumer; -public class WorkflowBuilder { - - private static final String DSL = "1.0.0"; - private static final String DEFAULT_VERSION = "0.0.1"; - private static final String DEFAULT_NAMESPACE = "org.acme"; - - private final Workflow workflow; - private final Document document; +public class WorkflowBuilder extends BaseWorkflowBuilder { private WorkflowBuilder(final String name, final String namespace, final String version) { - this.document = new Document(); - this.document.setName(name); - this.document.setNamespace(namespace); - this.document.setVersion(version); - this.document.setDsl(DSL); - this.workflow = new Workflow(); - this.workflow.setDocument(this.document); + super(name, namespace, version); + } + + @Override + protected DoTaskBuilder newDo() { + return new DoTaskBuilder(); } public static WorkflowBuilder workflow( @@ -56,41 +45,8 @@ public static WorkflowBuilder workflow() { return new WorkflowBuilder(UUID.randomUUID().toString(), DEFAULT_NAMESPACE, DEFAULT_VERSION); } - public WorkflowBuilder document(Consumer documentBuilderConsumer) { - final DocumentBuilder documentBuilder = new DocumentBuilder(this.document); - documentBuilderConsumer.accept(documentBuilder); - return this; - } - - public WorkflowBuilder use(Consumer useBuilderConsumer) { - final UseBuilder builder = new UseBuilder(); - useBuilderConsumer.accept(builder); - this.workflow.setUse(builder.build()); - return this; - } - - public WorkflowBuilder doTasks(Consumer doTaskConsumer) { - final DoTaskBuilder doTaskBuilder = new DoTaskBuilder(); - doTaskConsumer.accept(doTaskBuilder); - this.workflow.setDo(doTaskBuilder.build().getDo()); + @Override + protected WorkflowBuilder self() { return this; } - - public WorkflowBuilder input(Consumer inputBuilderConsumer) { - final InputBuilder inputBuilder = new InputBuilder(); - inputBuilderConsumer.accept(inputBuilder); - this.workflow.setInput(inputBuilder.build()); - return this; - } - - public WorkflowBuilder output(Consumer outputBuilderConsumer) { - final OutputBuilder outputBuilder = new OutputBuilder(); - outputBuilderConsumer.accept(outputBuilder); - this.workflow.setOutput(outputBuilder.build()); - return this; - } - - public Workflow build() { - return this.workflow; - } } diff --git a/fluent/standard/src/test/java/io/serverlessworkflow/fluent/standard/WorkflowBuilderTest.java b/fluent/standard/src/test/java/io/serverlessworkflow/fluent/standard/WorkflowBuilderTest.java index e29a27b9..2c334c0b 100644 --- a/fluent/standard/src/test/java/io/serverlessworkflow/fluent/standard/WorkflowBuilderTest.java +++ b/fluent/standard/src/test/java/io/serverlessworkflow/fluent/standard/WorkflowBuilderTest.java @@ -128,7 +128,7 @@ void testDoTaskMultipleTypes() { d -> d.set("init", s -> s.expr("$.init = true")) .forEach("items", f -> f.each("item").in("$.list")) - .switchTask( + .switchCase( "choice", sw -> { // no-op configuration From 3e2fdf8e50e444bb8dbbc1a8117ad248f68f29e0 Mon Sep 17 00:00:00 2001 From: Ricardo Zanini Date: Mon, 21 Jul 2025 13:33:21 -0400 Subject: [PATCH 2/3] Fix taskItems builder - refactor Signed-off-by: Ricardo Zanini --- .../fluent/java/DoTaskJavaBuilder.java | 33 ++-- .../fluent/java/ForTaskJavaBuilder.java | 6 +- .../fluent/java/JavaForEach.java | 21 --- .../fluent/java/JavaSwitchCase.java | 21 --- .../fluent/java/JavaWorkflowBuilder.java | 3 +- .../fluent/java/TaskItemListJavaBuilder.java | 74 ++++++++ .../fluent/java/JavaWorkflowBuilderTest.java | 24 ++- .../fluent/standard/BaseDoTaskBuilder.java | 145 ++++++--------- .../standard/BaseTaskItemListBuilder.java | 176 ++++++++++++++++++ .../fluent/standard/BaseWorkflowBuilder.java | 22 ++- .../fluent/standard/DoTaskBuilder.java | 9 +- .../fluent/standard/ForTaskBuilder.java | 14 +- .../fluent/standard/SwitchCase.java | 21 --- ...{ForEach.java => TaskItemListBuilder.java} | 18 +- .../fluent/standard/TryTaskBuilder.java | 8 +- .../fluent/standard/WorkflowBuilder.java | 3 +- 16 files changed, 381 insertions(+), 217 deletions(-) delete mode 100644 fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaForEach.java delete mode 100644 fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaSwitchCase.java create mode 100644 fluent/java/src/main/java/io/serverlessworkflow/fluent/java/TaskItemListJavaBuilder.java create mode 100644 fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseTaskItemListBuilder.java delete mode 100644 fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/SwitchCase.java rename fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/{ForEach.java => TaskItemListBuilder.java} (68%) diff --git a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/DoTaskJavaBuilder.java b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/DoTaskJavaBuilder.java index 2149e63a..7dc2e75a 100644 --- a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/DoTaskJavaBuilder.java +++ b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/DoTaskJavaBuilder.java @@ -15,17 +15,14 @@ */ package io.serverlessworkflow.fluent.java; -import io.serverlessworkflow.api.types.Task; -import io.serverlessworkflow.api.types.TaskItem; import io.serverlessworkflow.fluent.standard.BaseDoTaskBuilder; -import java.util.UUID; import java.util.function.Consumer; -public class DoTaskJavaBuilder extends BaseDoTaskBuilder +public class DoTaskJavaBuilder extends BaseDoTaskBuilder implements JavaTransformationHandlers { DoTaskJavaBuilder() { - super(); + super(new TaskItemListJavaBuilder()); } @Override @@ -33,41 +30,33 @@ protected DoTaskJavaBuilder self() { return this; } - @Override - protected DoTaskJavaBuilder newDo() { - return new DoTaskJavaBuilder(); - } - public DoTaskJavaBuilder callFn(String name, Consumer consumer) { - final CallTaskJavaBuilder callTaskJavaBuilder = new CallTaskJavaBuilder(); - consumer.accept(callTaskJavaBuilder); - this.addTaskItem(new TaskItem(name, new Task().withCallTask(callTaskJavaBuilder.build()))); + this.innerListBuilder().callFn(name, consumer); return this; } public DoTaskJavaBuilder callFn(Consumer consumer) { - return this.callFn(UUID.randomUUID().toString(), consumer); + this.innerListBuilder().callFn(consumer); + return this; } public DoTaskJavaBuilder forEachFn(String name, Consumer consumer) { - final ForTaskJavaBuilder forTaskJavaBuilder = new ForTaskJavaBuilder(); - consumer.accept(forTaskJavaBuilder); - this.addTaskItem(new TaskItem(name, new Task().withForTask(forTaskJavaBuilder.build()))); + this.innerListBuilder().forEachFn(name, consumer); return this; } public DoTaskJavaBuilder forEachFn(Consumer consumer) { - return this.forEachFn(UUID.randomUUID().toString(), consumer); + this.innerListBuilder().forEachFn(consumer); + return this; } public DoTaskJavaBuilder switchCaseFn(String name, Consumer consumer) { - final SwitchTaskJavaBuilder switchTaskJavaBuilder = new SwitchTaskJavaBuilder(); - consumer.accept(switchTaskJavaBuilder); - this.addTaskItem(new TaskItem(name, new Task().withSwitchTask(switchTaskJavaBuilder.build()))); + this.innerListBuilder().switchCaseFn(name, consumer); return this; } public DoTaskJavaBuilder switchCaseFn(Consumer consumer) { - return this.switchCaseFn(UUID.randomUUID().toString(), consumer); + this.innerListBuilder().switchCaseFn(consumer); + return this; } } diff --git a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/ForTaskJavaBuilder.java b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/ForTaskJavaBuilder.java index 1649c8ea..1c1508a9 100644 --- a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/ForTaskJavaBuilder.java +++ b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/ForTaskJavaBuilder.java @@ -81,10 +81,10 @@ public ForTaskJavaBuilder doTasks(LoopFunction function) { return this.doTasks(UUID.randomUUID().toString(), function); } - public ForTaskJavaBuilder doTasks(Consumer consumer) { - final DoTaskJavaBuilder builder = new DoTaskJavaBuilder(); + public ForTaskJavaBuilder doTasks(Consumer consumer) { + final TaskItemListJavaBuilder builder = new TaskItemListJavaBuilder(); consumer.accept(builder); - this.items.addAll(builder.build().getDo()); + this.items.addAll(builder.build()); return this; } diff --git a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaForEach.java b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaForEach.java deleted file mode 100644 index 7c0fd8a0..00000000 --- a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaForEach.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2020-Present The Serverless Workflow Specification Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.serverlessworkflow.fluent.java; - -@FunctionalInterface -public interface JavaForEach { - void configure(ForTaskJavaBuilder builder); -} diff --git a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaSwitchCase.java b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaSwitchCase.java deleted file mode 100644 index 98870713..00000000 --- a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaSwitchCase.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2020-Present The Serverless Workflow Specification Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.serverlessworkflow.fluent.java; - -@FunctionalInterface -public interface JavaSwitchCase { - void configure(SwitchTaskJavaBuilder consumer); -} diff --git a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaWorkflowBuilder.java b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaWorkflowBuilder.java index 5cfee3fd..5d90b598 100644 --- a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaWorkflowBuilder.java +++ b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/JavaWorkflowBuilder.java @@ -18,7 +18,8 @@ import io.serverlessworkflow.fluent.standard.BaseWorkflowBuilder; import java.util.UUID; -public class JavaWorkflowBuilder extends BaseWorkflowBuilder +public class JavaWorkflowBuilder + extends BaseWorkflowBuilder implements JavaTransformationHandlers { private JavaWorkflowBuilder(final String name, final String namespace, final String version) { diff --git a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/TaskItemListJavaBuilder.java b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/TaskItemListJavaBuilder.java new file mode 100644 index 00000000..4622e64a --- /dev/null +++ b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/TaskItemListJavaBuilder.java @@ -0,0 +1,74 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.fluent.java; + +import io.serverlessworkflow.api.types.Task; +import io.serverlessworkflow.api.types.TaskItem; +import io.serverlessworkflow.fluent.standard.BaseTaskItemListBuilder; +import java.util.UUID; +import java.util.function.Consumer; + +public class TaskItemListJavaBuilder extends BaseTaskItemListBuilder { + + TaskItemListJavaBuilder() { + super(); + } + + @Override + protected TaskItemListJavaBuilder self() { + return this; + } + + @Override + protected TaskItemListJavaBuilder newItemListBuilder() { + return new TaskItemListJavaBuilder(); + } + + public TaskItemListJavaBuilder callFn(String name, Consumer consumer) { + this.requireNameAndConfig(name, consumer); + final CallTaskJavaBuilder callTaskJavaBuilder = new CallTaskJavaBuilder(); + consumer.accept(callTaskJavaBuilder); + return addTaskItem(new TaskItem(name, new Task().withCallTask(callTaskJavaBuilder.build()))); + } + + public TaskItemListJavaBuilder callFn(Consumer consumer) { + return this.callFn(UUID.randomUUID().toString(), consumer); + } + + public TaskItemListJavaBuilder forEachFn(String name, Consumer consumer) { + this.requireNameAndConfig(name, consumer); + final ForTaskJavaBuilder forTaskJavaBuilder = new ForTaskJavaBuilder(); + consumer.accept(forTaskJavaBuilder); + return this.addTaskItem(new TaskItem(name, new Task().withForTask(forTaskJavaBuilder.build()))); + } + + public TaskItemListJavaBuilder forEachFn(Consumer consumer) { + return this.forEachFn(UUID.randomUUID().toString(), consumer); + } + + public TaskItemListJavaBuilder switchCaseFn( + String name, Consumer consumer) { + this.requireNameAndConfig(name, consumer); + final SwitchTaskJavaBuilder switchTaskJavaBuilder = new SwitchTaskJavaBuilder(); + consumer.accept(switchTaskJavaBuilder); + return this.addTaskItem( + new TaskItem(name, new Task().withSwitchTask(switchTaskJavaBuilder.build()))); + } + + public TaskItemListJavaBuilder switchCaseFn(Consumer consumer) { + return this.switchCaseFn(UUID.randomUUID().toString(), consumer); + } +} diff --git a/fluent/java/src/test/java/io/serverlessworkflow/fluent/java/JavaWorkflowBuilderTest.java b/fluent/java/src/test/java/io/serverlessworkflow/fluent/java/JavaWorkflowBuilderTest.java index 160f783d..6fae038b 100644 --- a/fluent/java/src/test/java/io/serverlessworkflow/fluent/java/JavaWorkflowBuilderTest.java +++ b/fluent/java/src/test/java/io/serverlessworkflow/fluent/java/JavaWorkflowBuilderTest.java @@ -138,19 +138,17 @@ void testJavaFunctionalIO() { return List.of("x", "y"); }) .doTasks( - inner -> - inner - .set("calc", s -> s.expr("$.y = $.x + 1")) - .exportAsFn( - item -> { - exportCalled.set(true); - return Map.of("computed", 42); - }) - .outputAs( - item -> { - outputCalled.set(true); - return Map.of("out", true); - })))) + inner -> inner.set("calc", s -> s.expr("$.y = $.x + 1"))) + .exportAsFn( + item -> { + exportCalled.set(true); + return Map.of("computed", 42); + }) + .outputAs( + item -> { + outputCalled.set(true); + return Map.of("out", true); + }))) .build(); // Top-level 'do' structure diff --git a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseDoTaskBuilder.java b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseDoTaskBuilder.java index 91073c7e..302c633e 100644 --- a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseDoTaskBuilder.java +++ b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseDoTaskBuilder.java @@ -15,152 +15,129 @@ */ package io.serverlessworkflow.fluent.standard; -import io.serverlessworkflow.api.types.CallTask; import io.serverlessworkflow.api.types.DoTask; -import io.serverlessworkflow.api.types.Task; -import io.serverlessworkflow.api.types.TaskItem; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; import java.util.function.Consumer; -public abstract class BaseDoTaskBuilder> extends TaskBaseBuilder { +public abstract class BaseDoTaskBuilder< + TASK extends TaskBaseBuilder, LIST extends BaseTaskItemListBuilder> + extends TaskBaseBuilder { private final DoTask doTask; - private final List list; + private final BaseTaskItemListBuilder taskItemListBuilder; - protected BaseDoTaskBuilder() { + protected BaseDoTaskBuilder(BaseTaskItemListBuilder taskItemListBuilder) { this.doTask = new DoTask(); - this.list = new ArrayList<>(); + this.taskItemListBuilder = taskItemListBuilder; this.setTask(doTask); } - protected abstract T self(); + protected abstract TASK self(); - protected abstract T newDo(); - - protected final void addTaskItem(TaskItem taskItem) { - if (taskItem != null) { - this.list.add(taskItem); - } - } - - protected final void addTaskItem(List taskItem) { - if (taskItem != null) { - this.list.addAll(taskItem); - } + protected LIST innerListBuilder() { + return (LIST) taskItemListBuilder; } - public T set(String name, Consumer itemsConfigurer) { - final SetTaskBuilder setBuilder = new SetTaskBuilder(); - itemsConfigurer.accept(setBuilder); - this.list.add(new TaskItem(name, new Task().withSetTask(setBuilder.build()))); + public TASK set(String name, Consumer itemsConfigurer) { + taskItemListBuilder.set(name, itemsConfigurer); return self(); } - public T set(Consumer itemsConfigurer) { - return this.set(UUID.randomUUID().toString(), itemsConfigurer); + public TASK set(Consumer itemsConfigurer) { + taskItemListBuilder.set(itemsConfigurer); + return self(); } - public T set(String name, final String expr) { - return this.set(name, s -> s.expr(expr)); + public TASK set(String name, final String expr) { + taskItemListBuilder.set(name, s -> s.expr(expr)); + return self(); } - public T set(final String expr) { - return this.set(UUID.randomUUID().toString(), s -> s.expr(expr)); + public TASK set(final String expr) { + taskItemListBuilder.set(expr); + return self(); } - public T forEach(String name, ForEach itemsConfigurer) { - final ForTaskBuilder forBuilder = new ForTaskBuilder<>(newDo()); - itemsConfigurer.configure(forBuilder); - this.list.add(new TaskItem(name, new Task().withForTask(forBuilder.build()))); + public TASK forEach(String name, Consumer> itemsConfigurer) { + taskItemListBuilder.forEach(name, itemsConfigurer); return self(); } - public T forEach(ForEach itemsConfigurer) { - return this.forEach(UUID.randomUUID().toString(), itemsConfigurer); + public TASK forEach(Consumer> itemsConfigurer) { + taskItemListBuilder.forEach(itemsConfigurer); + return self(); } - public T switchCase(String name, SwitchCase itemsConfigurer) { - final SwitchTaskBuilder switchBuilder = new SwitchTaskBuilder(); - itemsConfigurer.configure(switchBuilder); - this.list.add(new TaskItem(name, new Task().withSwitchTask(switchBuilder.build()))); + public TASK switchCase(String name, Consumer itemsConfigurer) { + taskItemListBuilder.switchCase(name, itemsConfigurer); return self(); } - public T switchCase(SwitchCase itemsConfigurer) { - return this.switchCase(UUID.randomUUID().toString(), itemsConfigurer); + public TASK switchCase(Consumer itemsConfigurer) { + taskItemListBuilder.switchCase(itemsConfigurer); + return self(); } - public T raise(String name, Consumer itemsConfigurer) { - final RaiseTaskBuilder raiseBuilder = new RaiseTaskBuilder(); - itemsConfigurer.accept(raiseBuilder); - this.list.add(new TaskItem(name, new Task().withRaiseTask(raiseBuilder.build()))); + public TASK raise(String name, Consumer itemsConfigurer) { + taskItemListBuilder.raise(name, itemsConfigurer); return self(); } - public T raise(Consumer itemsConfigurer) { - return this.raise(UUID.randomUUID().toString(), itemsConfigurer); + public TASK raise(Consumer itemsConfigurer) { + taskItemListBuilder.raise(itemsConfigurer); + return self(); } - public T fork(String name, Consumer itemsConfigurer) { - final ForkTaskBuilder forkBuilder = new ForkTaskBuilder(); - itemsConfigurer.accept(forkBuilder); - this.list.add(new TaskItem(name, new Task().withForkTask(forkBuilder.build()))); + public TASK fork(String name, Consumer itemsConfigurer) { + taskItemListBuilder.fork(name, itemsConfigurer); return self(); } - public T fork(Consumer itemsConfigurer) { - return this.fork(UUID.randomUUID().toString(), itemsConfigurer); + public TASK fork(Consumer itemsConfigurer) { + taskItemListBuilder.fork(itemsConfigurer); + return self(); } - public T listen(String name, Consumer itemsConfigurer) { - final ListenTaskBuilder listenBuilder = new ListenTaskBuilder(); - itemsConfigurer.accept(listenBuilder); - this.list.add(new TaskItem(name, new Task().withListenTask(listenBuilder.build()))); + public TASK listen(String name, Consumer itemsConfigurer) { + taskItemListBuilder.listen(name, itemsConfigurer); return self(); } - public T listen(Consumer itemsConfigurer) { - return this.listen(UUID.randomUUID().toString(), itemsConfigurer); + public TASK listen(Consumer itemsConfigurer) { + taskItemListBuilder.listen(itemsConfigurer); + return self(); } - public T emit(String name, Consumer itemsConfigurer) { - final EmitTaskBuilder emitBuilder = new EmitTaskBuilder(); - itemsConfigurer.accept(emitBuilder); - this.list.add(new TaskItem(name, new Task().withEmitTask(emitBuilder.build()))); + public TASK emit(String name, Consumer itemsConfigurer) { + taskItemListBuilder.emit(name, itemsConfigurer); return self(); } - public T emit(Consumer itemsConfigurer) { - return this.emit(UUID.randomUUID().toString(), itemsConfigurer); + public TASK emit(Consumer itemsConfigurer) { + taskItemListBuilder.emit(itemsConfigurer); + return self(); } - public T tryTask(String name, Consumer> itemsConfigurer) { - final TryTaskBuilder tryBuilder = new TryTaskBuilder<>(this.newDo()); - itemsConfigurer.accept(tryBuilder); - this.list.add(new TaskItem(name, new Task().withTryTask(tryBuilder.build()))); + public TASK tryTask(String name, Consumer> itemsConfigurer) { + taskItemListBuilder.tryTask(name, itemsConfigurer); return self(); } - public T tryTask(Consumer> itemsConfigurer) { - return this.tryTask(UUID.randomUUID().toString(), itemsConfigurer); + public TASK tryTask(Consumer> itemsConfigurer) { + taskItemListBuilder.tryTask(itemsConfigurer); + return self(); } - public T callHTTP(String name, Consumer itemsConfigurer) { - final CallHTTPTaskBuilder callHTTPBuilder = new CallHTTPTaskBuilder(); - itemsConfigurer.accept(callHTTPBuilder); - this.list.add( - new TaskItem( - name, new Task().withCallTask(new CallTask().withCallHTTP(callHTTPBuilder.build())))); + public TASK callHTTP(String name, Consumer itemsConfigurer) { + taskItemListBuilder.callHTTP(name, itemsConfigurer); return self(); } - public T callHTTP(Consumer itemsConfigurer) { - return this.callHTTP(UUID.randomUUID().toString(), itemsConfigurer); + public TASK callHTTP(Consumer itemsConfigurer) { + taskItemListBuilder.callHTTP(itemsConfigurer); + return self(); } public DoTask build() { - this.doTask.setDo(this.list); + this.doTask.setDo(this.taskItemListBuilder.build()); return this.doTask; } } diff --git a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseTaskItemListBuilder.java b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseTaskItemListBuilder.java new file mode 100644 index 00000000..6c60a9af --- /dev/null +++ b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseTaskItemListBuilder.java @@ -0,0 +1,176 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.fluent.standard; + +import io.serverlessworkflow.api.types.CallTask; +import io.serverlessworkflow.api.types.Task; +import io.serverlessworkflow.api.types.TaskBase; +import io.serverlessworkflow.api.types.TaskItem; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.function.Consumer; + +/** + * A builder for an ordered {@link TaskItem} list. + * + *

This builder only knows how to append new TaskItems of various flavors, but does NOT expose + * {@link TaskBase}‑level methods like export(), input(), etc. Those belong on {@link + * TaskBaseBuilder} subclasses. + * + * @param the concrete builder type + */ +public abstract class BaseTaskItemListBuilder> { + + private final List list; + + public BaseTaskItemListBuilder() { + this.list = new ArrayList<>(); + } + + protected abstract SELF self(); + + protected abstract SELF newItemListBuilder(); + + protected SELF addTaskItem(TaskItem taskItem) { + Objects.requireNonNull(taskItem, "taskItem must not be null"); + list.add(taskItem); + return self(); + } + + protected void requireNameAndConfig(String name, Consumer cfg) { + Objects.requireNonNull(name, "Task name must not be null"); + Objects.requireNonNull(cfg, "Configurer must not be null"); + } + + public SELF set(String name, Consumer itemsConfigurer) { + requireNameAndConfig(name, itemsConfigurer); + final SetTaskBuilder setBuilder = new SetTaskBuilder(); + itemsConfigurer.accept(setBuilder); + return addTaskItem(new TaskItem(name, new Task().withSetTask(setBuilder.build()))); + } + + public SELF set(Consumer itemsConfigurer) { + return this.set(UUID.randomUUID().toString(), itemsConfigurer); + } + + public SELF set(String name, final String expr) { + return this.set(name, s -> s.expr(expr)); + } + + public SELF set(final String expr) { + return this.set(UUID.randomUUID().toString(), s -> s.expr(expr)); + } + + public SELF forEach(String name, Consumer> itemsConfigurer) { + requireNameAndConfig(name, itemsConfigurer); + final ForTaskBuilder forBuilder = new ForTaskBuilder<>(newItemListBuilder()); + itemsConfigurer.accept(forBuilder); + return addTaskItem(new TaskItem(name, new Task().withForTask(forBuilder.build()))); + } + + public SELF forEach(Consumer> itemsConfigurer) { + return this.forEach(UUID.randomUUID().toString(), itemsConfigurer); + } + + public SELF switchCase(String name, Consumer itemsConfigurer) { + requireNameAndConfig(name, itemsConfigurer); + final SwitchTaskBuilder switchBuilder = new SwitchTaskBuilder(); + itemsConfigurer.accept(switchBuilder); + return addTaskItem(new TaskItem(name, new Task().withSwitchTask(switchBuilder.build()))); + } + + public SELF switchCase(Consumer itemsConfigurer) { + return this.switchCase(UUID.randomUUID().toString(), itemsConfigurer); + } + + public SELF raise(String name, Consumer itemsConfigurer) { + requireNameAndConfig(name, itemsConfigurer); + final RaiseTaskBuilder raiseBuilder = new RaiseTaskBuilder(); + itemsConfigurer.accept(raiseBuilder); + return addTaskItem(new TaskItem(name, new Task().withRaiseTask(raiseBuilder.build()))); + } + + public SELF raise(Consumer itemsConfigurer) { + return this.raise(UUID.randomUUID().toString(), itemsConfigurer); + } + + public SELF fork(String name, Consumer itemsConfigurer) { + requireNameAndConfig(name, itemsConfigurer); + final ForkTaskBuilder forkBuilder = new ForkTaskBuilder(); + itemsConfigurer.accept(forkBuilder); + return addTaskItem(new TaskItem(name, new Task().withForkTask(forkBuilder.build()))); + } + + public SELF fork(Consumer itemsConfigurer) { + return this.fork(UUID.randomUUID().toString(), itemsConfigurer); + } + + public SELF listen(String name, Consumer itemsConfigurer) { + requireNameAndConfig(name, itemsConfigurer); + final ListenTaskBuilder listenBuilder = new ListenTaskBuilder(); + itemsConfigurer.accept(listenBuilder); + return addTaskItem(new TaskItem(name, new Task().withListenTask(listenBuilder.build()))); + } + + public SELF listen(Consumer itemsConfigurer) { + return this.listen(UUID.randomUUID().toString(), itemsConfigurer); + } + + public SELF emit(String name, Consumer itemsConfigurer) { + requireNameAndConfig(name, itemsConfigurer); + final EmitTaskBuilder emitBuilder = new EmitTaskBuilder(); + itemsConfigurer.accept(emitBuilder); + return addTaskItem(new TaskItem(name, new Task().withEmitTask(emitBuilder.build()))); + } + + public SELF emit(Consumer itemsConfigurer) { + return this.emit(UUID.randomUUID().toString(), itemsConfigurer); + } + + public SELF tryTask(String name, Consumer> itemsConfigurer) { + requireNameAndConfig(name, itemsConfigurer); + final TryTaskBuilder tryBuilder = new TryTaskBuilder<>(this.newItemListBuilder()); + itemsConfigurer.accept(tryBuilder); + return addTaskItem(new TaskItem(name, new Task().withTryTask(tryBuilder.build()))); + } + + public SELF tryTask(Consumer> itemsConfigurer) { + return this.tryTask(UUID.randomUUID().toString(), itemsConfigurer); + } + + public SELF callHTTP(String name, Consumer itemsConfigurer) { + requireNameAndConfig(name, itemsConfigurer); + final CallHTTPTaskBuilder callHTTPBuilder = new CallHTTPTaskBuilder(); + itemsConfigurer.accept(callHTTPBuilder); + return addTaskItem( + new TaskItem( + name, new Task().withCallTask(new CallTask().withCallHTTP(callHTTPBuilder.build())))); + } + + public SELF callHTTP(Consumer itemsConfigurer) { + return this.callHTTP(UUID.randomUUID().toString(), itemsConfigurer); + } + + /** + * @return an immutable snapshot of all {@link TaskItem}s added so far + */ + public List build() { + return Collections.unmodifiableList(list); + } +} diff --git a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseWorkflowBuilder.java b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseWorkflowBuilder.java index e6db176f..cc33453e 100644 --- a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseWorkflowBuilder.java +++ b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseWorkflowBuilder.java @@ -23,7 +23,9 @@ import java.util.function.Consumer; public abstract class BaseWorkflowBuilder< - W extends BaseWorkflowBuilder, DB extends BaseDoTaskBuilder> + SELF extends BaseWorkflowBuilder, + DO extends BaseDoTaskBuilder, + LIST extends BaseTaskItemListBuilder> implements TransformationHandlers { public static final String DSL = "1.0.0"; @@ -43,9 +45,9 @@ protected BaseWorkflowBuilder(final String name, final String namespace, final S this.workflow.setDocument(this.document); } - protected abstract DB newDo(); + protected abstract DO newDo(); - protected abstract W self(); + protected abstract SELF self(); @Override public void setOutput(Output output) { @@ -55,6 +57,8 @@ public void setOutput(Output output) { @Override public void setExport(Export export) { // TODO: build another interface with only Output and Input + throw new UnsupportedOperationException( + "export() is not supported on the workflow root; only tasks may export"); } @Override @@ -62,34 +66,34 @@ public void setInput(Input input) { this.workflow.setInput(input); } - public W document(Consumer documentBuilderConsumer) { + public SELF document(Consumer documentBuilderConsumer) { final DocumentBuilder documentBuilder = new DocumentBuilder(this.document); documentBuilderConsumer.accept(documentBuilder); return self(); } - public W use(Consumer useBuilderConsumer) { + public SELF use(Consumer useBuilderConsumer) { final UseBuilder builder = new UseBuilder(); useBuilderConsumer.accept(builder); this.workflow.setUse(builder.build()); return self(); } - public W doTasks(Consumer doTaskConsumer) { - final DB doTaskBuilder = newDo(); + public SELF doTasks(Consumer doTaskConsumer) { + final DO doTaskBuilder = newDo(); doTaskConsumer.accept(doTaskBuilder); this.workflow.setDo(doTaskBuilder.build().getDo()); return self(); } - public W input(Consumer inputBuilderConsumer) { + public SELF input(Consumer inputBuilderConsumer) { final InputBuilder inputBuilder = new InputBuilder(); inputBuilderConsumer.accept(inputBuilder); this.workflow.setInput(inputBuilder.build()); return self(); } - public W output(Consumer outputBuilderConsumer) { + public SELF output(Consumer outputBuilderConsumer) { final OutputBuilder outputBuilder = new OutputBuilder(); outputBuilderConsumer.accept(outputBuilder); this.workflow.setOutput(outputBuilder.build()); diff --git a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/DoTaskBuilder.java b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/DoTaskBuilder.java index 51221463..dee523b3 100644 --- a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/DoTaskBuilder.java +++ b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/DoTaskBuilder.java @@ -15,19 +15,14 @@ */ package io.serverlessworkflow.fluent.standard; -public class DoTaskBuilder extends BaseDoTaskBuilder { +public class DoTaskBuilder extends BaseDoTaskBuilder { DoTaskBuilder() { - super(); + super(new TaskItemListBuilder()); } @Override protected DoTaskBuilder self() { return this; } - - @Override - protected DoTaskBuilder newDo() { - return new DoTaskBuilder(); - } } diff --git a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/ForTaskBuilder.java b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/ForTaskBuilder.java index e932e368..3a05904b 100644 --- a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/ForTaskBuilder.java +++ b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/ForTaskBuilder.java @@ -19,18 +19,18 @@ import io.serverlessworkflow.api.types.ForTaskConfiguration; import java.util.function.Consumer; -public class ForTaskBuilder> +public class ForTaskBuilder> extends TaskBaseBuilder> { private final ForTask forTask; private final ForTaskConfiguration forTaskConfiguration; - private final T doTaskBuilderFactory; + private final T taskItemListBuilder; - ForTaskBuilder(T doTaskBuilderFactory) { + ForTaskBuilder(T taskItemListBuilder) { super(); forTask = new ForTask(); forTaskConfiguration = new ForTaskConfiguration(); - this.doTaskBuilderFactory = doTaskBuilderFactory; + this.taskItemListBuilder = taskItemListBuilder; super.setTask(forTask); } @@ -59,9 +59,9 @@ public ForTaskBuilder whileCondition(final String expression) { } public ForTaskBuilder doTasks(Consumer doBuilderConsumer) { - final T doTaskBuilder = this.doTaskBuilderFactory.newDo(); - doBuilderConsumer.accept(doTaskBuilder); - this.forTask.setDo(doTaskBuilder.build().getDo()); + final T taskItemListBuilder = this.taskItemListBuilder.newItemListBuilder(); + doBuilderConsumer.accept(taskItemListBuilder); + this.forTask.setDo(taskItemListBuilder.build()); return this; } diff --git a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/SwitchCase.java b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/SwitchCase.java deleted file mode 100644 index f7805dd2..00000000 --- a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/SwitchCase.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2020-Present The Serverless Workflow Specification Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.serverlessworkflow.fluent.standard; - -@FunctionalInterface -public interface SwitchCase { - void configure(SwitchTaskBuilder consumer); -} diff --git a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/ForEach.java b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/TaskItemListBuilder.java similarity index 68% rename from fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/ForEach.java rename to fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/TaskItemListBuilder.java index 9756ef6b..ebc3353c 100644 --- a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/ForEach.java +++ b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/TaskItemListBuilder.java @@ -15,7 +15,19 @@ */ package io.serverlessworkflow.fluent.standard; -@FunctionalInterface -public interface ForEach> { - void configure(ForTaskBuilder builder); +public class TaskItemListBuilder extends BaseTaskItemListBuilder { + + TaskItemListBuilder() { + super(); + } + + @Override + protected TaskItemListBuilder self() { + return this; + } + + @Override + protected TaskItemListBuilder newItemListBuilder() { + return new TaskItemListBuilder(); + } } diff --git a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/TryTaskBuilder.java b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/TryTaskBuilder.java index 0ff46fe4..677a36f0 100644 --- a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/TryTaskBuilder.java +++ b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/TryTaskBuilder.java @@ -34,7 +34,7 @@ import io.serverlessworkflow.api.types.TryTaskCatch; import java.util.function.Consumer; -public class TryTaskBuilder> +public class TryTaskBuilder> extends TaskBaseBuilder> { private final TryTask tryTask; @@ -51,9 +51,9 @@ protected TryTaskBuilder self() { } public TryTaskBuilder tryHandler(Consumer consumer) { - final T doTaskBuilder = this.doTaskBuilderFactory.newDo(); - consumer.accept(doTaskBuilder); - this.tryTask.setTry(doTaskBuilder.build().getDo()); + final T taskItemListBuilder = this.doTaskBuilderFactory.newItemListBuilder(); + consumer.accept(taskItemListBuilder); + this.tryTask.setTry(taskItemListBuilder.build()); return this; } diff --git a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/WorkflowBuilder.java b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/WorkflowBuilder.java index 7d194c34..278e1df8 100644 --- a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/WorkflowBuilder.java +++ b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/WorkflowBuilder.java @@ -17,7 +17,8 @@ import java.util.UUID; -public class WorkflowBuilder extends BaseWorkflowBuilder { +public class WorkflowBuilder + extends BaseWorkflowBuilder { private WorkflowBuilder(final String name, final String namespace, final String version) { super(name, namespace, version); From 6fc3f0a924793f8d5a4bdf9a0bb98d42803a0f69 Mon Sep 17 00:00:00 2001 From: Ricardo Zanini Date: Mon, 21 Jul 2025 15:14:24 -0400 Subject: [PATCH 3/3] Add tests to the lambda module, integrate the DSL Signed-off-by: Ricardo Zanini --- experimental/lambda/pom.xml | 45 +++++---- .../io/serverless/workflow/impl/CallTest.java | 16 ++-- .../workflow/impl/FluentDSLCallTest.java | 96 +++++++++++++++++++ experimental/pom.xml | 5 + .../fluent/java/CallTaskJavaBuilder.java | 2 +- .../fluent/java/DoTaskJavaBuilder.java | 20 ++-- .../fluent/java/ForTaskJavaBuilder.java | 12 +-- .../fluent/java/TaskItemListJavaBuilder.java | 19 ++-- .../fluent/java/JavaWorkflowBuilderTest.java | 41 ++++---- .../fluent/standard/BaseDoTaskBuilder.java | 16 ++-- .../standard/BaseTaskItemListBuilder.java | 12 +-- .../fluent/standard/BaseWorkflowBuilder.java | 2 +- .../fluent/standard/ForTaskBuilder.java | 4 +- .../fluent/standard/WorkflowBuilderTest.java | 32 +++---- 14 files changed, 213 insertions(+), 109 deletions(-) create mode 100644 experimental/lambda/src/test/java/io/serverless/workflow/impl/FluentDSLCallTest.java diff --git a/experimental/lambda/pom.xml b/experimental/lambda/pom.xml index 72e4c0b2..5c20338c 100644 --- a/experimental/lambda/pom.xml +++ b/experimental/lambda/pom.xml @@ -1,22 +1,27 @@ - - 4.0.0 - - io.serverlessworkflow - serverlessworkflow-experimental - 8.0.0-SNAPSHOT - - serverlessworkflow-experimental-lambda - ServelessWorkflow:: Experimental:: lambda - - - io.serverlessworkflow - serverlessworkflow-experimental-types - - - io.serverlessworkflow - serverlessworkflow-impl-core - - + + 4.0.0 + + io.serverlessworkflow + serverlessworkflow-experimental + 8.0.0-SNAPSHOT + + serverlessworkflow-experimental-lambda + ServelessWorkflow:: Experimental:: lambda + + + io.serverlessworkflow + serverlessworkflow-experimental-types + + + io.serverlessworkflow + serverlessworkflow-impl-core + + + io.serverlessworkflow + serverlessworkflow-fluent-java + + org.junit.jupiter junit-jupiter-api test @@ -41,5 +46,5 @@ logback-classic test - + \ No newline at end of file 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 9118ec06..7d95410b 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 @@ -80,7 +80,7 @@ void testForLoop() throws InterruptedException, ExecutionException { new Task() .withForTask( new ForTaskFunction() - .withWhile(this::isEven) + .withWhile(CallTest::isEven) .withCollection(v -> (Collection) v) .withFor(forConfig) .withDo( @@ -91,7 +91,7 @@ void testForLoop() throws InterruptedException, ExecutionException { .withCallTask( new CallTaskJava( CallJava.loopFunction( - this::sum, + CallTest::sum, forConfig.getEach())))))))))); assertThat( @@ -124,7 +124,7 @@ void testSwitch() throws InterruptedException, ExecutionException { new SwitchItem( "odd", new SwitchCaseFunction() - .withPredicate(this::isOdd) + .withPredicate(CallTest::isOdd) .withThen( new FlowDirective() .withFlowDirectiveEnum( @@ -132,7 +132,7 @@ void testSwitch() throws InterruptedException, ExecutionException { new TaskItem( "java", new Task() - .withCallTask(new CallTaskJava(CallJava.function(this::zero)))))); + .withCallTask(new CallTaskJava(CallJava.function(CallTest::zero)))))); WorkflowDefinition definition = app.workflowDefinition(workflow); assertThat(definition.instance(3).start().get().asNumber().orElseThrow()).isEqualTo(3); @@ -140,19 +140,19 @@ void testSwitch() throws InterruptedException, ExecutionException { } } - private boolean isEven(Object model, Integer number) { + public static boolean isEven(Object model, Integer number) { return !isOdd(number); } - private boolean isOdd(Integer number) { + public static boolean isOdd(Integer number) { return number % 2 != 0; } - private int zero(Integer value) { + public static int zero(Integer value) { return 0; } - private Integer sum(Object model, Integer item) { + public static Integer sum(Object model, Integer item) { return model instanceof Collection ? item : (Integer) model + item; } } diff --git a/experimental/lambda/src/test/java/io/serverless/workflow/impl/FluentDSLCallTest.java b/experimental/lambda/src/test/java/io/serverless/workflow/impl/FluentDSLCallTest.java new file mode 100644 index 00000000..dd4f9a29 --- /dev/null +++ b/experimental/lambda/src/test/java/io/serverless/workflow/impl/FluentDSLCallTest.java @@ -0,0 +1,96 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverless.workflow.impl; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.serverlessworkflow.api.types.FlowDirectiveEnum; +import io.serverlessworkflow.api.types.Workflow; +import io.serverlessworkflow.fluent.java.JavaWorkflowBuilder; +import io.serverlessworkflow.impl.WorkflowApplication; +import io.serverlessworkflow.impl.WorkflowDefinition; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.ExecutionException; +import org.junit.jupiter.api.Test; + +public class FluentDSLCallTest { + + @Test + void testJavaFunction() throws InterruptedException, ExecutionException { + try (WorkflowApplication app = WorkflowApplication.builder().build()) { + final Workflow workflow = + JavaWorkflowBuilder.workflow("testJavaCall") + .tasks(tasks -> tasks.callFn(f -> f.fn(JavaFunctions::getName))) + .build(); + assertThat( + app.workflowDefinition(workflow) + .instance(new Person("Francisco", 33)) + .start() + .get() + .asText() + .orElseThrow()) + .isEqualTo("Francisco Javierito"); + } + } + + @Test + void testForLoop() throws InterruptedException, ExecutionException { + try (WorkflowApplication app = WorkflowApplication.builder().build()) { + Workflow workflow = + JavaWorkflowBuilder.workflow() + .tasks( + t -> + t.forFn( + f -> + f.whileC(CallTest::isEven) + .collection(v -> (Collection) v) + .tasks(CallTest::sum))) + .build(); + + assertThat( + app.workflowDefinition(workflow) + .instance(List.of(2, 4, 6)) + .start() + .get() + .asNumber() + .orElseThrow()) + .isEqualTo(12); + } + } + + @Test + void testSwitch() throws InterruptedException, ExecutionException { + try (WorkflowApplication app = WorkflowApplication.builder().build()) { + Workflow workflow = + JavaWorkflowBuilder.workflow() + .tasks( + tasks -> + tasks + .switchFn( + switchOdd -> + switchOdd.items( + item -> + item.when(CallTest::isOdd).then(FlowDirectiveEnum.END))) + .callFn(callJava -> callJava.fn(CallTest::zero))) + .build(); + + WorkflowDefinition definition = app.workflowDefinition(workflow); + assertThat(definition.instance(3).start().get().asNumber().orElseThrow()).isEqualTo(3); + assertThat(definition.instance(4).start().get().asNumber().orElseThrow()).isEqualTo(0); + } + } +} diff --git a/experimental/pom.xml b/experimental/pom.xml index 409e68c2..e269b7b0 100644 --- a/experimental/pom.xml +++ b/experimental/pom.xml @@ -30,6 +30,11 @@ serverlessworkflow-experimental-types ${project.version} + + io.serverlessworkflow + serverlessworkflow-fluent-java + ${project.version} + diff --git a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/CallTaskJavaBuilder.java b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/CallTaskJavaBuilder.java index bcedd830..8149ebba 100644 --- a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/CallTaskJavaBuilder.java +++ b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/CallTaskJavaBuilder.java @@ -35,7 +35,7 @@ protected CallTaskJavaBuilder self() { return this; } - public CallTaskJavaBuilder function(Function function) { + public CallTaskJavaBuilder fn(Function function) { this.callTaskJava = new CallTaskJava(CallJava.function(function)); super.setTask(this.callTaskJava.getCallJava()); return this; diff --git a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/DoTaskJavaBuilder.java b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/DoTaskJavaBuilder.java index 7dc2e75a..b17cf643 100644 --- a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/DoTaskJavaBuilder.java +++ b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/DoTaskJavaBuilder.java @@ -31,32 +31,32 @@ protected DoTaskJavaBuilder self() { } public DoTaskJavaBuilder callFn(String name, Consumer consumer) { - this.innerListBuilder().callFn(name, consumer); + this.innerListBuilder().callJava(name, consumer); return this; } public DoTaskJavaBuilder callFn(Consumer consumer) { - this.innerListBuilder().callFn(consumer); + this.innerListBuilder().callJava(consumer); return this; } - public DoTaskJavaBuilder forEachFn(String name, Consumer consumer) { - this.innerListBuilder().forEachFn(name, consumer); + public DoTaskJavaBuilder forFn(String name, Consumer consumer) { + this.innerListBuilder().forFn(name, consumer); return this; } - public DoTaskJavaBuilder forEachFn(Consumer consumer) { - this.innerListBuilder().forEachFn(consumer); + public DoTaskJavaBuilder forFn(Consumer consumer) { + this.innerListBuilder().forFn(consumer); return this; } - public DoTaskJavaBuilder switchCaseFn(String name, Consumer consumer) { - this.innerListBuilder().switchCaseFn(name, consumer); + public DoTaskJavaBuilder switchFn(String name, Consumer consumer) { + this.innerListBuilder().switchFn(name, consumer); return this; } - public DoTaskJavaBuilder switchCaseFn(Consumer consumer) { - this.innerListBuilder().switchCaseFn(consumer); + public DoTaskJavaBuilder switchFn(Consumer consumer) { + this.innerListBuilder().switchFn(consumer); return this; } } diff --git a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/ForTaskJavaBuilder.java b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/ForTaskJavaBuilder.java index 1c1508a9..241272f0 100644 --- a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/ForTaskJavaBuilder.java +++ b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/ForTaskJavaBuilder.java @@ -50,12 +50,12 @@ protected ForTaskJavaBuilder self() { return this; } - public ForTaskJavaBuilder whileCondition(LoopPredicate predicate) { + public ForTaskJavaBuilder whileC(LoopPredicate predicate) { this.forTaskFunction.withWhile(predicate); return this; } - public ForTaskJavaBuilder whileCondition(LoopPredicateIndex predicate) { + public ForTaskJavaBuilder whileC(LoopPredicateIndex predicate) { this.forTaskFunction.withWhile(predicate); return this; } @@ -65,7 +65,7 @@ public ForTaskJavaBuilder collection(Function> collectionF) return this; } - public ForTaskJavaBuilder doTasks(String name, LoopFunction function) { + public ForTaskJavaBuilder tasks(String name, LoopFunction function) { this.items.add( new TaskItem( name, @@ -77,11 +77,11 @@ public ForTaskJavaBuilder doTasks(String name, LoopFunction f return this; } - public ForTaskJavaBuilder doTasks(LoopFunction function) { - return this.doTasks(UUID.randomUUID().toString(), function); + public ForTaskJavaBuilder tasks(LoopFunction function) { + return this.tasks(UUID.randomUUID().toString(), function); } - public ForTaskJavaBuilder doTasks(Consumer consumer) { + public ForTaskJavaBuilder tasks(Consumer consumer) { final TaskItemListJavaBuilder builder = new TaskItemListJavaBuilder(); consumer.accept(builder); this.items.addAll(builder.build()); diff --git a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/TaskItemListJavaBuilder.java b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/TaskItemListJavaBuilder.java index 4622e64a..40fa250b 100644 --- a/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/TaskItemListJavaBuilder.java +++ b/fluent/java/src/main/java/io/serverlessworkflow/fluent/java/TaskItemListJavaBuilder.java @@ -37,30 +37,29 @@ protected TaskItemListJavaBuilder newItemListBuilder() { return new TaskItemListJavaBuilder(); } - public TaskItemListJavaBuilder callFn(String name, Consumer consumer) { + public TaskItemListJavaBuilder callJava(String name, Consumer consumer) { this.requireNameAndConfig(name, consumer); final CallTaskJavaBuilder callTaskJavaBuilder = new CallTaskJavaBuilder(); consumer.accept(callTaskJavaBuilder); return addTaskItem(new TaskItem(name, new Task().withCallTask(callTaskJavaBuilder.build()))); } - public TaskItemListJavaBuilder callFn(Consumer consumer) { - return this.callFn(UUID.randomUUID().toString(), consumer); + public TaskItemListJavaBuilder callJava(Consumer consumer) { + return this.callJava(UUID.randomUUID().toString(), consumer); } - public TaskItemListJavaBuilder forEachFn(String name, Consumer consumer) { + public TaskItemListJavaBuilder forFn(String name, Consumer consumer) { this.requireNameAndConfig(name, consumer); final ForTaskJavaBuilder forTaskJavaBuilder = new ForTaskJavaBuilder(); consumer.accept(forTaskJavaBuilder); return this.addTaskItem(new TaskItem(name, new Task().withForTask(forTaskJavaBuilder.build()))); } - public TaskItemListJavaBuilder forEachFn(Consumer consumer) { - return this.forEachFn(UUID.randomUUID().toString(), consumer); + public TaskItemListJavaBuilder forFn(Consumer consumer) { + return this.forFn(UUID.randomUUID().toString(), consumer); } - public TaskItemListJavaBuilder switchCaseFn( - String name, Consumer consumer) { + public TaskItemListJavaBuilder switchFn(String name, Consumer consumer) { this.requireNameAndConfig(name, consumer); final SwitchTaskJavaBuilder switchTaskJavaBuilder = new SwitchTaskJavaBuilder(); consumer.accept(switchTaskJavaBuilder); @@ -68,7 +67,7 @@ public TaskItemListJavaBuilder switchCaseFn( new TaskItem(name, new Task().withSwitchTask(switchTaskJavaBuilder.build()))); } - public TaskItemListJavaBuilder switchCaseFn(Consumer consumer) { - return this.switchCaseFn(UUID.randomUUID().toString(), consumer); + public TaskItemListJavaBuilder switchFn(Consumer consumer) { + return this.switchFn(UUID.randomUUID().toString(), consumer); } } diff --git a/fluent/java/src/test/java/io/serverlessworkflow/fluent/java/JavaWorkflowBuilderTest.java b/fluent/java/src/test/java/io/serverlessworkflow/fluent/java/JavaWorkflowBuilderTest.java index 6fae038b..ef037cad 100644 --- a/fluent/java/src/test/java/io/serverlessworkflow/fluent/java/JavaWorkflowBuilderTest.java +++ b/fluent/java/src/test/java/io/serverlessworkflow/fluent/java/JavaWorkflowBuilderTest.java @@ -43,11 +43,11 @@ void testDefaults() { } @Test - @DisplayName("Spec style forEach still works inside Java workflow") + @DisplayName("Spec style forE still works inside Java workflow") void testSpecForEachInJavaWorkflow() { Workflow wf = JavaWorkflowBuilder.workflow("specLoopFlow") - .doTasks( + .tasks( d -> d.forEach(f -> f.each("pet").in("$.pets")) .set("markDone", s -> s.expr("$.done = true"))) @@ -66,17 +66,17 @@ void testSpecForEachInJavaWorkflow() { } @Test - @DisplayName("Java style forEach with collection + whileCondition builds ForTaskFunction") + @DisplayName("Java style forE with collection + whileC builds ForTaskFunction") void testJavaForEach() { Workflow wf = JavaWorkflowBuilder.workflow("javaLoopFlow") - .doTasks( + .tasks( d -> - d.forEachFn( + d.forFn( j -> j.collection(ctx -> List.of("a", "b", "c")) - .whileCondition((String val, Object ctx) -> !val.equals("c")) - .doTasks( + .whileC((String val, Object ctx) -> !val.equals("c")) + .tasks( inner -> inner.set("loopFlag", s -> s.expr("$.flag = true"))))) .build(); @@ -101,10 +101,10 @@ void testJavaForEach() { void testMixedLoops() { Workflow wf = JavaWorkflowBuilder.workflow("mixed") - .doTasks( + .tasks( d -> d.forEach(f -> f.each("item").in("$.array")) // spec - .forEachFn(j -> j.collection(ctx -> List.of(1, 2, 3))) // java + .forFn(j -> j.collection(ctx -> List.of(1, 2, 3))) // java ) .build(); @@ -127,18 +127,17 @@ void testJavaFunctionalIO() { Workflow wf = JavaWorkflowBuilder.workflow("fnIO") - .doTasks( + .tasks( d -> d.set("init", s -> s.expr("$.x = 1")) - .forEachFn( + .forFn( j -> j.collection( ctx -> { inputCalled.set(true); return List.of("x", "y"); }) - .doTasks( - inner -> inner.set("calc", s -> s.expr("$.y = $.x + 1"))) + .tasks(inner -> inner.set("calc", s -> s.expr("$.y = $.x + 1"))) .exportAsFn( item -> { exportCalled.set(true); @@ -191,7 +190,7 @@ void testJavaFunctionalIO() { void testCallJavaTask() { Workflow wf = JavaWorkflowBuilder.workflow("callJavaFlow") - .doTasks( + .tasks( d -> d.callFn( "invokeHandler", @@ -217,10 +216,10 @@ void testCallJavaTask() { void testSwitchCaseJava() { Workflow wf = JavaWorkflowBuilder.workflow("switchJava") - .doTasks( + .tasks( d -> d.set("prepare", s -> s.expr("$.ready = true")) - .switchCase( + .switchC( sw -> { // configure Java switch builder (cases / predicates) })) @@ -237,20 +236,20 @@ void testSwitchCaseJava() { } @Test - @DisplayName("Combined: spec set + java forEach + callJava inside nested do") + @DisplayName("Combined: spec set + java forE + callJava inside nested do") void testCompositeScenario() { Workflow wf = JavaWorkflowBuilder.workflow("composite") - .doTasks( + .tasks( d -> d.set("init", s -> s.expr("$.val = 0")) - .forEachFn( + .forFn( j -> j.collection(ctx -> List.of("a", "b")) - .doTasks( + .tasks( inner -> inner - .callFn( + .callJava( cj -> { // customizing Java call }) diff --git a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseDoTaskBuilder.java b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseDoTaskBuilder.java index 302c633e..fab86cdd 100644 --- a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseDoTaskBuilder.java +++ b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseDoTaskBuilder.java @@ -66,13 +66,13 @@ public TASK forEach(Consumer> itemsConfigurer) { return self(); } - public TASK switchCase(String name, Consumer itemsConfigurer) { - taskItemListBuilder.switchCase(name, itemsConfigurer); + public TASK switchC(String name, Consumer itemsConfigurer) { + taskItemListBuilder.switchC(name, itemsConfigurer); return self(); } - public TASK switchCase(Consumer itemsConfigurer) { - taskItemListBuilder.switchCase(itemsConfigurer); + public TASK switchC(Consumer itemsConfigurer) { + taskItemListBuilder.switchC(itemsConfigurer); return self(); } @@ -116,13 +116,13 @@ public TASK emit(Consumer itemsConfigurer) { return self(); } - public TASK tryTask(String name, Consumer> itemsConfigurer) { - taskItemListBuilder.tryTask(name, itemsConfigurer); + public TASK tryC(String name, Consumer> itemsConfigurer) { + taskItemListBuilder.tryC(name, itemsConfigurer); return self(); } - public TASK tryTask(Consumer> itemsConfigurer) { - taskItemListBuilder.tryTask(itemsConfigurer); + public TASK tryC(Consumer> itemsConfigurer) { + taskItemListBuilder.tryC(itemsConfigurer); return self(); } diff --git a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseTaskItemListBuilder.java b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseTaskItemListBuilder.java index 6c60a9af..566b493a 100644 --- a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseTaskItemListBuilder.java +++ b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseTaskItemListBuilder.java @@ -88,15 +88,15 @@ public SELF forEach(Consumer> itemsConfigurer) { return this.forEach(UUID.randomUUID().toString(), itemsConfigurer); } - public SELF switchCase(String name, Consumer itemsConfigurer) { + public SELF switchC(String name, Consumer itemsConfigurer) { requireNameAndConfig(name, itemsConfigurer); final SwitchTaskBuilder switchBuilder = new SwitchTaskBuilder(); itemsConfigurer.accept(switchBuilder); return addTaskItem(new TaskItem(name, new Task().withSwitchTask(switchBuilder.build()))); } - public SELF switchCase(Consumer itemsConfigurer) { - return this.switchCase(UUID.randomUUID().toString(), itemsConfigurer); + public SELF switchC(Consumer itemsConfigurer) { + return this.switchC(UUID.randomUUID().toString(), itemsConfigurer); } public SELF raise(String name, Consumer itemsConfigurer) { @@ -143,15 +143,15 @@ public SELF emit(Consumer itemsConfigurer) { return this.emit(UUID.randomUUID().toString(), itemsConfigurer); } - public SELF tryTask(String name, Consumer> itemsConfigurer) { + public SELF tryC(String name, Consumer> itemsConfigurer) { requireNameAndConfig(name, itemsConfigurer); final TryTaskBuilder tryBuilder = new TryTaskBuilder<>(this.newItemListBuilder()); itemsConfigurer.accept(tryBuilder); return addTaskItem(new TaskItem(name, new Task().withTryTask(tryBuilder.build()))); } - public SELF tryTask(Consumer> itemsConfigurer) { - return this.tryTask(UUID.randomUUID().toString(), itemsConfigurer); + public SELF tryC(Consumer> itemsConfigurer) { + return this.tryC(UUID.randomUUID().toString(), itemsConfigurer); } public SELF callHTTP(String name, Consumer itemsConfigurer) { diff --git a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseWorkflowBuilder.java b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseWorkflowBuilder.java index cc33453e..b93bdda0 100644 --- a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseWorkflowBuilder.java +++ b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/BaseWorkflowBuilder.java @@ -79,7 +79,7 @@ public SELF use(Consumer useBuilderConsumer) { return self(); } - public SELF doTasks(Consumer doTaskConsumer) { + public SELF tasks(Consumer doTaskConsumer) { final DO doTaskBuilder = newDo(); doTaskConsumer.accept(doTaskBuilder); this.workflow.setDo(doTaskBuilder.build().getDo()); diff --git a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/ForTaskBuilder.java b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/ForTaskBuilder.java index 3a05904b..ba0cec7c 100644 --- a/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/ForTaskBuilder.java +++ b/fluent/standard/src/main/java/io/serverlessworkflow/fluent/standard/ForTaskBuilder.java @@ -53,12 +53,12 @@ public ForTaskBuilder at(String at) { return this; } - public ForTaskBuilder whileCondition(final String expression) { + public ForTaskBuilder whileC(final String expression) { this.forTask.setWhile(expression); return this; } - public ForTaskBuilder doTasks(Consumer doBuilderConsumer) { + public ForTaskBuilder tasks(Consumer doBuilderConsumer) { final T taskItemListBuilder = this.taskItemListBuilder.newItemListBuilder(); doBuilderConsumer.accept(taskItemListBuilder); this.forTask.setDo(taskItemListBuilder.build()); diff --git a/fluent/standard/src/test/java/io/serverlessworkflow/fluent/standard/WorkflowBuilderTest.java b/fluent/standard/src/test/java/io/serverlessworkflow/fluent/standard/WorkflowBuilderTest.java index 2c334c0b..cdf1c3ba 100644 --- a/fluent/standard/src/test/java/io/serverlessworkflow/fluent/standard/WorkflowBuilderTest.java +++ b/fluent/standard/src/test/java/io/serverlessworkflow/fluent/standard/WorkflowBuilderTest.java @@ -99,7 +99,7 @@ void testUseAuthenticationsBasic() { void testDoTaskSetAndForEach() { Workflow wf = WorkflowBuilder.workflow("flowDo") - .doTasks( + .tasks( d -> d.set("initCtx", "$.foo = 'bar'") .forEach("item", f -> f.each("item").at("$.list"))) @@ -124,11 +124,11 @@ void testDoTaskSetAndForEach() { void testDoTaskMultipleTypes() { Workflow wf = WorkflowBuilder.workflow("flowMixed") - .doTasks( + .tasks( d -> d.set("init", s -> s.expr("$.init = true")) .forEach("items", f -> f.each("item").in("$.list")) - .switchCase( + .switchC( "choice", sw -> { // no-op configuration @@ -154,7 +154,7 @@ void testDoTaskMultipleTypes() { assertEquals("init", setItem.getName()); assertNotNull(setItem.getTask().getSetTask(), "SetTask should be present"); - // forEach task + // forE task TaskItem forItem = items.get(1); assertEquals("items", forItem.getName()); assertNotNull(forItem.getTask().getForTask(), "ForTask should be present"); @@ -179,7 +179,7 @@ void testDoTaskMultipleTypes() { void testDoTaskListenOne() { Workflow wf = WorkflowBuilder.workflow("flowListen") - .doTasks( + .tasks( d -> d.listen( "waitCheck", @@ -205,7 +205,7 @@ void testDoTaskListenOne() { void testDoTaskEmitEvent() { Workflow wf = WorkflowBuilder.workflow("flowEmit") - .doTasks( + .tasks( d -> d.emit( "emitEvent", @@ -256,9 +256,9 @@ void testDoTaskEmitEvent() { void testDoTaskTryCatchWithRetry() { Workflow wf = WorkflowBuilder.workflow("flowTry") - .doTasks( + .tasks( d -> - d.tryTask( + d.tryC( "tryBlock", t -> t.tryHandler(tb -> tb.set("init", s -> s.expr("$.start = true"))) @@ -304,9 +304,9 @@ void testDoTaskTryCatchWithRetry() { void testDoTaskTryCatchErrorsFiltering() { Workflow wf = WorkflowBuilder.workflow("flowCatch") - .doTasks( + .tasks( d -> - d.tryTask( + d.tryC( "tryBlock", t -> t.tryHandler(tb -> tb.set("foo", s -> s.expr("$.foo = 'bar'"))) @@ -402,7 +402,7 @@ void testWorkflowInputInlineSchemaAndFromObject() { void testDoTaskCallHTTPBasic() { Workflow wf = WorkflowBuilder.workflow("flowCallBasic") - .doTasks( + .tasks( d -> d.callHTTP( "basicCall", @@ -428,7 +428,7 @@ void testDoTaskCallHTTPBasic() { void testDoTaskCallHTTPHeadersConsumerAndMap() { Workflow wf = WorkflowBuilder.workflow("flowCallHeaders") - .doTasks( + .tasks( d -> d.callHTTP( "hdrCall", @@ -444,7 +444,7 @@ void testDoTaskCallHTTPHeadersConsumerAndMap() { Workflow wf2 = WorkflowBuilder.workflow() - .doTasks( + .tasks( d -> d.callHTTP( c -> @@ -460,7 +460,7 @@ void testDoTaskCallHTTPHeadersConsumerAndMap() { void testDoTaskCallHTTPQueryConsumerAndMap() { Workflow wf = WorkflowBuilder.workflow("flowCallQuery") - .doTasks( + .tasks( d -> d.callHTTP( "qryCall", @@ -476,7 +476,7 @@ void testDoTaskCallHTTPQueryConsumerAndMap() { Workflow wf2 = WorkflowBuilder.workflow() - .doTasks( + .tasks( d -> d.callHTTP( c -> c.method("GET").endpoint("uri").query(Map.of("q1", "x", "q2", "y")))) @@ -498,7 +498,7 @@ void testDoTaskCallHTTPQueryConsumerAndMap() { void testDoTaskCallHTTPRedirectAndOutput() { Workflow wf = WorkflowBuilder.workflow("flowCallOpts") - .doTasks( + .tasks( d -> d.callHTTP( "optCall",