diff --git a/experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncForTaskBuilder.java b/experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncForTaskBuilder.java index 98b9883cb..4f9faf52f 100644 --- a/experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncForTaskBuilder.java +++ b/experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncForTaskBuilder.java @@ -31,7 +31,6 @@ 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; @@ -71,6 +70,9 @@ public FuncForTaskBuilder collection(Function> collectionF) } public FuncForTaskBuilder tasks(String name, LoopFunction function) { + if (name == null || name.isBlank()) { + name = "for-task-" + this.items.size(); + } this.items.add( new TaskItem( name, @@ -83,7 +85,7 @@ public FuncForTaskBuilder tasks(String name, LoopFunction fun } public FuncForTaskBuilder tasks(LoopFunction function) { - return this.tasks(UUID.randomUUID().toString(), function); + return this.tasks(null, function); } @Override diff --git a/experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncForkTaskBuilder.java b/experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncForkTaskBuilder.java index 02d141a8d..9b19af03d 100644 --- a/experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncForkTaskBuilder.java +++ b/experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncForkTaskBuilder.java @@ -27,7 +27,6 @@ import io.serverlessworkflow.fluent.spec.spi.ForkTaskFluent; import java.util.ArrayList; import java.util.List; -import java.util.UUID; import java.util.function.Consumer; import java.util.function.Function; @@ -57,6 +56,9 @@ public FuncForkTaskBuilder branch(String name, Function function) { public FuncForkTaskBuilder branch( String name, Function function, Class argParam) { + if (name == null || name.isBlank()) { + name = "branch-" + this.items.size(); + } this.items.add( new TaskItem( name, @@ -65,7 +67,7 @@ public FuncForkTaskBuilder branch( } public FuncForkTaskBuilder branch(Function function) { - return this.branch(UUID.randomUUID().toString(), function); + return this.branch(null, function); } @Override diff --git a/experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncSwitchTaskBuilder.java b/experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncSwitchTaskBuilder.java index 17f909904..5e3838702 100644 --- a/experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncSwitchTaskBuilder.java +++ b/experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncSwitchTaskBuilder.java @@ -28,7 +28,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; -import java.util.UUID; import java.util.function.Consumer; import java.util.function.Predicate; @@ -52,7 +51,7 @@ protected FuncSwitchTaskBuilder self() { } public FuncSwitchTaskBuilder onPredicate(Consumer consumer) { - return this.onPredicate(UUID.randomUUID().toString(), consumer); + return this.onPredicate(null, consumer); } public FuncSwitchTaskBuilder onPredicate( @@ -70,8 +69,7 @@ public FuncSwitchTaskBuilder onPredicate( return this.onDefault(switchCaseValue.getThen().getString()); } } - - this.switchItems.add(new SwitchItem(name, switchCase.build())); + this.switchItems.add(new SwitchItem(defaultItemNameIfBlank(name), switchCase.build())); return this; } @@ -79,10 +77,15 @@ public FuncSwitchTaskBuilder onPredicate( public FuncSwitchTaskBuilder on(String name, Consumer switchCaseConsumer) { final SwitchCaseBuilder switchCase = new SwitchCaseBuilder(); switchCaseConsumer.accept(switchCase); - this.switchItems.add(new SwitchItem(name, switchCase.build())); + this.switchItems.add(new SwitchItem(defaultItemNameIfBlank(name), switchCase.build())); return this; } + @Override + public int switchItemCount() { + return this.switchItems.size(); + } + public SwitchTask build() { this.switchTask.setSwitch(this.switchItems); return switchTask; diff --git a/experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncTaskItemListBuilder.java b/experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncTaskItemListBuilder.java index cbf954d11..3e87e469e 100644 --- a/experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncTaskItemListBuilder.java +++ b/experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncTaskItemListBuilder.java @@ -23,12 +23,13 @@ import io.serverlessworkflow.fluent.func.spi.FuncDoFluent; import io.serverlessworkflow.fluent.spec.BaseTaskItemListBuilder; import java.util.List; -import java.util.UUID; import java.util.function.Consumer; public class FuncTaskItemListBuilder extends BaseTaskItemListBuilder implements FuncDoFluent { + protected static final String TYPE_FUNCTION = "function"; + public FuncTaskItemListBuilder() { super(); } @@ -49,7 +50,7 @@ protected FuncTaskItemListBuilder newItemListBuilder() { @Override public FuncTaskItemListBuilder function(String name, Consumer consumer) { - name = this.defaultNameAndRequireConfig(name, consumer); + name = this.defaultNameAndRequireConfig(name, consumer, TYPE_FUNCTION); final FuncCallTaskBuilder callTaskJavaBuilder = new FuncCallTaskBuilder(); consumer.accept(callTaskJavaBuilder); return addTaskItem(new TaskItem(name, new Task().withCallTask(callTaskJavaBuilder.build()))); @@ -57,12 +58,12 @@ public FuncTaskItemListBuilder function(String name, Consumer consumer) { - return this.function(UUID.randomUUID().toString(), consumer); + return this.function(null, consumer); } @Override public FuncTaskItemListBuilder set(String name, Consumer itemsConfigurer) { - name = this.defaultNameAndRequireConfig(name, itemsConfigurer); + name = this.defaultNameAndRequireConfig(name, itemsConfigurer, TYPE_SET); final FuncSetTaskBuilder funcSetTaskBuilder = new FuncSetTaskBuilder(); itemsConfigurer.accept(funcSetTaskBuilder); return this.addTaskItem(new TaskItem(name, new Task().withSetTask(funcSetTaskBuilder.build()))); @@ -75,7 +76,7 @@ public FuncTaskItemListBuilder set(String name, String expr) { @Override public FuncTaskItemListBuilder emit(String name, Consumer itemsConfigurer) { - name = this.defaultNameAndRequireConfig(name, itemsConfigurer); + name = this.defaultNameAndRequireConfig(name, itemsConfigurer, TYPE_EMIT); final FuncEmitTaskBuilder emitTaskJavaBuilder = new FuncEmitTaskBuilder(); itemsConfigurer.accept(emitTaskJavaBuilder); return this.addTaskItem( @@ -85,7 +86,7 @@ public FuncTaskItemListBuilder emit(String name, Consumer i @Override public FuncTaskItemListBuilder listen( String name, Consumer itemsConfigurer) { - name = this.defaultNameAndRequireConfig(name, itemsConfigurer); + name = this.defaultNameAndRequireConfig(name, itemsConfigurer, TYPE_LISTEN); final FuncListenTaskBuilder listenTaskJavaBuilder = new FuncListenTaskBuilder(); itemsConfigurer.accept(listenTaskJavaBuilder); return this.addTaskItem( @@ -95,7 +96,7 @@ public FuncTaskItemListBuilder listen( @Override public FuncTaskItemListBuilder forEach( String name, Consumer itemsConfigurer) { - name = this.defaultNameAndRequireConfig(name, itemsConfigurer); + name = this.defaultNameAndRequireConfig(name, itemsConfigurer, TYPE_FOR); final FuncForTaskBuilder forTaskJavaBuilder = new FuncForTaskBuilder(); itemsConfigurer.accept(forTaskJavaBuilder); return this.addTaskItem(new TaskItem(name, new Task().withForTask(forTaskJavaBuilder.build()))); @@ -104,7 +105,7 @@ public FuncTaskItemListBuilder forEach( @Override public FuncTaskItemListBuilder switchCase( String name, Consumer itemsConfigurer) { - name = this.defaultNameAndRequireConfig(name, itemsConfigurer); + name = this.defaultNameAndRequireConfig(name, itemsConfigurer, TYPE_SWITCH); final FuncSwitchTaskBuilder funcSwitchTaskBuilder = new FuncSwitchTaskBuilder(); itemsConfigurer.accept(funcSwitchTaskBuilder); return this.addTaskItem( @@ -113,7 +114,7 @@ public FuncTaskItemListBuilder switchCase( @Override public FuncTaskItemListBuilder fork(String name, Consumer itemsConfigurer) { - name = this.defaultNameAndRequireConfig(name, itemsConfigurer); + name = this.defaultNameAndRequireConfig(name, itemsConfigurer, TYPE_FORK); final FuncForkTaskBuilder forkTaskJavaBuilder = new FuncForkTaskBuilder(); itemsConfigurer.accept(forkTaskJavaBuilder); return this.addTaskItem( @@ -123,7 +124,7 @@ public FuncTaskItemListBuilder fork(String name, Consumer i @Override public FuncTaskItemListBuilder http( String name, Consumer itemsConfigurer) { - name = this.defaultNameAndRequireConfig(name, itemsConfigurer); + name = this.defaultNameAndRequireConfig(name, itemsConfigurer, TYPE_HTTP); final FuncCallHttpTaskBuilder httpTaskJavaBuilder = new FuncCallHttpTaskBuilder(); itemsConfigurer.accept(httpTaskJavaBuilder); @@ -140,7 +141,7 @@ public FuncTaskItemListBuilder http( @Override public FuncTaskItemListBuilder openapi( String name, Consumer itemsConfigurer) { - name = this.defaultNameAndRequireConfig(name, itemsConfigurer); + name = this.defaultNameAndRequireConfig(name, itemsConfigurer, TYPE_OPENAPI); final FuncCallOpenAPITaskBuilder openAPITaskBuilder = new FuncCallOpenAPITaskBuilder(); itemsConfigurer.accept(openAPITaskBuilder); diff --git a/experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/spi/CallFnFluent.java b/experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/spi/CallFnFluent.java index 99695aa40..d2257c40e 100644 --- a/experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/spi/CallFnFluent.java +++ b/experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/spi/CallFnFluent.java @@ -16,7 +16,6 @@ package io.serverlessworkflow.fluent.func.spi; import io.serverlessworkflow.fluent.spec.TaskBaseBuilder; -import java.util.UUID; import java.util.function.Consumer; public interface CallFnFluent, LIST> { @@ -24,6 +23,6 @@ public interface CallFnFluent, LIST> { LIST function(String name, Consumer cfg); default LIST function(Consumer cfg) { - return this.function(UUID.randomUUID().toString(), cfg); + return this.function(null, cfg); } } diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/BaseTaskItemListBuilder.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/BaseTaskItemListBuilder.java index d6d2e2292..882631fdd 100644 --- a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/BaseTaskItemListBuilder.java +++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/BaseTaskItemListBuilder.java @@ -21,7 +21,6 @@ import java.util.Collections; import java.util.List; import java.util.Objects; -import java.util.UUID; import java.util.function.Consumer; /** @@ -35,6 +34,17 @@ */ public abstract class BaseTaskItemListBuilder> { + protected final String TYPE_SET = "set"; + protected final String TYPE_FOR = "for"; + protected final String TYPE_SWITCH = "switch"; + protected final String TYPE_RAISE = "raise"; + protected final String TYPE_FORK = "fork"; + protected final String TYPE_LISTEN = "listen"; + protected final String TYPE_EMIT = "emit"; + protected final String TYPE_TRY = "try"; + protected final String TYPE_HTTP = "http"; + protected final String TYPE_OPENAPI = "openapi"; + private final List list; public BaseTaskItemListBuilder() { @@ -59,11 +69,14 @@ protected final SELF addTaskItem(TaskItem taskItem) { return self(); } - protected final String defaultNameAndRequireConfig(String name, Consumer cfg) { + protected final String defaultNameAndRequireConfig( + String name, Consumer cfg, String taskType) { + Objects.requireNonNull(cfg, "Configurer must not be null"); + if (name == null || name.isBlank()) { - name = UUID.randomUUID().toString(); + return taskType + "-" + this.list.size(); } - Objects.requireNonNull(cfg, "Configurer must not be null"); + return name; } diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/SwitchTaskBuilder.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/SwitchTaskBuilder.java index 7d517fb1e..3db8c7a4b 100644 --- a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/SwitchTaskBuilder.java +++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/SwitchTaskBuilder.java @@ -42,14 +42,19 @@ protected SwitchTaskBuilder self() { @Override public SwitchTaskBuilder on( - final String name, Consumer switchCaseConsumer) { + String name, Consumer switchCaseConsumer) { final SwitchTaskFluent.SwitchCaseBuilder switchCaseBuilder = new SwitchTaskFluent.SwitchCaseBuilder(); switchCaseConsumer.accept(switchCaseBuilder); - this.switchItems.add(new SwitchItem(name, switchCaseBuilder.build())); + this.switchItems.add(new SwitchItem(defaultItemNameIfBlank(name), switchCaseBuilder.build())); return this; } + @Override + public int switchItemCount() { + return this.switchItems.size(); + } + public SwitchTask build() { this.switchTask.setSwitch(this.switchItems); return this.switchTask; diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/TaskItemListBuilder.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/TaskItemListBuilder.java index 6a0736b00..0c292519e 100644 --- a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/TaskItemListBuilder.java +++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/TaskItemListBuilder.java @@ -45,7 +45,7 @@ protected TaskItemListBuilder newItemListBuilder() { @Override public TaskItemListBuilder set(String name, Consumer itemsConfigurer) { - name = defaultNameAndRequireConfig(name, itemsConfigurer); + name = defaultNameAndRequireConfig(name, itemsConfigurer, TYPE_SET); final SetTaskBuilder setBuilder = new SetTaskBuilder(); itemsConfigurer.accept(setBuilder); return addTaskItem(new TaskItem(name, new Task().withSetTask(setBuilder.build()))); @@ -59,7 +59,7 @@ public TaskItemListBuilder set(String name, final String expr) { @Override public TaskItemListBuilder forEach( String name, Consumer> itemsConfigurer) { - name = defaultNameAndRequireConfig(name, itemsConfigurer); + name = defaultNameAndRequireConfig(name, itemsConfigurer, TYPE_FOR); final ForEachTaskBuilder forBuilder = new ForEachTaskBuilder<>(newItemListBuilder()); itemsConfigurer.accept(forBuilder); @@ -68,7 +68,7 @@ public TaskItemListBuilder forEach( @Override public TaskItemListBuilder switchCase(String name, Consumer itemsConfigurer) { - name = defaultNameAndRequireConfig(name, itemsConfigurer); + name = defaultNameAndRequireConfig(name, itemsConfigurer, TYPE_SWITCH); final SwitchTaskBuilder switchBuilder = new SwitchTaskBuilder(); itemsConfigurer.accept(switchBuilder); return addTaskItem(new TaskItem(name, new Task().withSwitchTask(switchBuilder.build()))); @@ -76,7 +76,7 @@ public TaskItemListBuilder switchCase(String name, Consumer i @Override public TaskItemListBuilder raise(String name, Consumer itemsConfigurer) { - name = defaultNameAndRequireConfig(name, itemsConfigurer); + name = defaultNameAndRequireConfig(name, itemsConfigurer, TYPE_RAISE); final RaiseTaskBuilder raiseBuilder = new RaiseTaskBuilder(); itemsConfigurer.accept(raiseBuilder); return addTaskItem(new TaskItem(name, new Task().withRaiseTask(raiseBuilder.build()))); @@ -84,7 +84,7 @@ public TaskItemListBuilder raise(String name, Consumer itemsCo @Override public TaskItemListBuilder fork(String name, Consumer itemsConfigurer) { - name = defaultNameAndRequireConfig(name, itemsConfigurer); + name = defaultNameAndRequireConfig(name, itemsConfigurer, TYPE_FORK); final ForkTaskBuilder forkBuilder = new ForkTaskBuilder(); itemsConfigurer.accept(forkBuilder); return addTaskItem(new TaskItem(name, new Task().withForkTask(forkBuilder.build()))); @@ -92,7 +92,7 @@ public TaskItemListBuilder fork(String name, Consumer itemsConf @Override public TaskItemListBuilder listen(String name, Consumer itemsConfigurer) { - name = defaultNameAndRequireConfig(name, itemsConfigurer); + name = defaultNameAndRequireConfig(name, itemsConfigurer, TYPE_LISTEN); final ListenTaskBuilder listenBuilder = new ListenTaskBuilder(); itemsConfigurer.accept(listenBuilder); return addTaskItem(new TaskItem(name, new Task().withListenTask(listenBuilder.build()))); @@ -100,7 +100,7 @@ public TaskItemListBuilder listen(String name, Consumer items @Override public TaskItemListBuilder emit(String name, Consumer itemsConfigurer) { - name = defaultNameAndRequireConfig(name, itemsConfigurer); + name = defaultNameAndRequireConfig(name, itemsConfigurer, TYPE_EMIT); final EmitTaskBuilder emitBuilder = new EmitTaskBuilder(); itemsConfigurer.accept(emitBuilder); return addTaskItem(new TaskItem(name, new Task().withEmitTask(emitBuilder.build()))); @@ -109,7 +109,7 @@ public TaskItemListBuilder emit(String name, Consumer itemsConf @Override public TaskItemListBuilder tryCatch( String name, Consumer> itemsConfigurer) { - name = defaultNameAndRequireConfig(name, itemsConfigurer); + name = defaultNameAndRequireConfig(name, itemsConfigurer, TYPE_TRY); final TryTaskBuilder tryBuilder = new TryTaskBuilder<>(this.newItemListBuilder()); itemsConfigurer.accept(tryBuilder); @@ -118,7 +118,7 @@ public TaskItemListBuilder tryCatch( @Override public TaskItemListBuilder http(String name, Consumer itemsConfigurer) { - name = defaultNameAndRequireConfig(name, itemsConfigurer); + name = defaultNameAndRequireConfig(name, itemsConfigurer, TYPE_HTTP); final CallHttpTaskBuilder callHTTPBuilder = new CallHttpTaskBuilder(); itemsConfigurer.accept(callHTTPBuilder); @@ -134,7 +134,7 @@ public TaskItemListBuilder http(String name, Consumer items @Override public TaskItemListBuilder openapi( String name, Consumer itemsConfigurer) { - name = defaultNameAndRequireConfig(name, itemsConfigurer); + name = defaultNameAndRequireConfig(name, itemsConfigurer, TYPE_OPENAPI); final CallOpenAPITaskBuilder callOpenAPIBuilder = new CallOpenAPITaskBuilder(); itemsConfigurer.accept(callOpenAPIBuilder); diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/CallHttpFluent.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/CallHttpFluent.java index 11fd9e2ae..5c3617cb0 100644 --- a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/CallHttpFluent.java +++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/CallHttpFluent.java @@ -16,7 +16,6 @@ package io.serverlessworkflow.fluent.spec.spi; import io.serverlessworkflow.fluent.spec.TaskBaseBuilder; -import java.util.UUID; import java.util.function.Consumer; public interface CallHttpFluent, LIST> { @@ -24,6 +23,6 @@ public interface CallHttpFluent, LIST> { LIST http(String name, Consumer itemsConfigurer); default LIST http(Consumer itemsConfigurer) { - return this.http(UUID.randomUUID().toString(), itemsConfigurer); + return this.http(null, itemsConfigurer); } } diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/CallOpenAPIFluent.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/CallOpenAPIFluent.java index cafa61af4..56dc46d6e 100644 --- a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/CallOpenAPIFluent.java +++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/CallOpenAPIFluent.java @@ -16,7 +16,6 @@ package io.serverlessworkflow.fluent.spec.spi; import io.serverlessworkflow.fluent.spec.TaskBaseBuilder; -import java.util.UUID; import java.util.function.Consumer; public interface CallOpenAPIFluent, LIST> { @@ -24,6 +23,6 @@ public interface CallOpenAPIFluent, LIST> { LIST openapi(String name, Consumer itemsConfigurer); default LIST openapi(Consumer itemsConfigurer) { - return this.openapi(UUID.randomUUID().toString(), itemsConfigurer); + return this.openapi(null, itemsConfigurer); } } diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/EmitFluent.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/EmitFluent.java index 06ab8d12e..841bd4639 100644 --- a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/EmitFluent.java +++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/EmitFluent.java @@ -16,7 +16,6 @@ package io.serverlessworkflow.fluent.spec.spi; import io.serverlessworkflow.fluent.spec.TaskBaseBuilder; -import java.util.UUID; import java.util.function.Consumer; public interface EmitFluent, LIST> { @@ -24,6 +23,6 @@ public interface EmitFluent, LIST> { LIST emit(String name, Consumer itemsConfigurer); default LIST emit(Consumer itemsConfigurer) { - return emit(UUID.randomUUID().toString(), itemsConfigurer); + return emit(null, itemsConfigurer); } } diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/ForEachFluent.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/ForEachFluent.java index 53a35e574..e0ae0562a 100644 --- a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/ForEachFluent.java +++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/ForEachFluent.java @@ -16,7 +16,6 @@ package io.serverlessworkflow.fluent.spec.spi; import io.serverlessworkflow.fluent.spec.TaskBaseBuilder; -import java.util.UUID; import java.util.function.Consumer; public interface ForEachFluent, LIST> { @@ -24,6 +23,6 @@ public interface ForEachFluent, LIST> { LIST forEach(String name, Consumer itemsConfigurer); default LIST forEach(Consumer itemsConfigurer) { - return this.forEach(UUID.randomUUID().toString(), itemsConfigurer); + return this.forEach(null, itemsConfigurer); } } diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/ForkFluent.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/ForkFluent.java index 708c41f84..7c7c50703 100644 --- a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/ForkFluent.java +++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/ForkFluent.java @@ -16,7 +16,6 @@ package io.serverlessworkflow.fluent.spec.spi; import io.serverlessworkflow.fluent.spec.TaskBaseBuilder; -import java.util.UUID; import java.util.function.Consumer; public interface ForkFluent, LIST> { @@ -24,6 +23,6 @@ public interface ForkFluent, LIST> { LIST fork(String name, Consumer itemsConfigurer); default LIST fork(Consumer itemsConfigurer) { - return this.fork(UUID.randomUUID().toString(), itemsConfigurer); + return this.fork(null, itemsConfigurer); } } diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/ListenFluent.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/ListenFluent.java index ec950456e..9d2edf2fe 100644 --- a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/ListenFluent.java +++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/ListenFluent.java @@ -16,7 +16,6 @@ package io.serverlessworkflow.fluent.spec.spi; import io.serverlessworkflow.fluent.spec.TaskBaseBuilder; -import java.util.UUID; import java.util.function.Consumer; public interface ListenFluent, LIST> { @@ -24,6 +23,6 @@ public interface ListenFluent, LIST> { LIST listen(String name, Consumer itemsConfigurer); default LIST listen(Consumer itemsConfigurer) { - return this.listen(UUID.randomUUID().toString(), itemsConfigurer); + return this.listen(null, itemsConfigurer); } } diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/RaiseFluent.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/RaiseFluent.java index 699162d95..b6b08deb5 100644 --- a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/RaiseFluent.java +++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/RaiseFluent.java @@ -16,7 +16,6 @@ package io.serverlessworkflow.fluent.spec.spi; import io.serverlessworkflow.fluent.spec.TaskBaseBuilder; -import java.util.UUID; import java.util.function.Consumer; public interface RaiseFluent, LIST> { @@ -24,6 +23,6 @@ public interface RaiseFluent, LIST> { LIST raise(String name, Consumer itemsConfigurer); default LIST raise(Consumer itemsConfigurer) { - return this.raise(UUID.randomUUID().toString(), itemsConfigurer); + return this.raise(null, itemsConfigurer); } } diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/SetFluent.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/SetFluent.java index 3bd743e74..4debb8281 100644 --- a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/SetFluent.java +++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/SetFluent.java @@ -16,7 +16,6 @@ package io.serverlessworkflow.fluent.spec.spi; import io.serverlessworkflow.fluent.spec.TaskBaseBuilder; -import java.util.UUID; import java.util.function.Consumer; public interface SetFluent, LIST> { @@ -26,10 +25,10 @@ public interface SetFluent, LIST> { LIST set(String name, final String expr); default LIST set(final String expr) { - return this.set(UUID.randomUUID().toString(), expr); + return this.set(null, expr); } default LIST set(Consumer itemsConfigurer) { - return this.set(UUID.randomUUID().toString(), itemsConfigurer); + return this.set(null, itemsConfigurer); } } diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/SwitchFluent.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/SwitchFluent.java index affba92ed..d88453c5e 100644 --- a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/SwitchFluent.java +++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/SwitchFluent.java @@ -16,7 +16,6 @@ package io.serverlessworkflow.fluent.spec.spi; import io.serverlessworkflow.fluent.spec.TaskBaseBuilder; -import java.util.UUID; import java.util.function.Consumer; public interface SwitchFluent, LIST> { @@ -24,6 +23,6 @@ public interface SwitchFluent, LIST> { LIST switchCase(String name, Consumer itemsConfigurer); default LIST switchCase(Consumer itemsConfigurer) { - return this.switchCase(UUID.randomUUID().toString(), itemsConfigurer); + return this.switchCase(null, itemsConfigurer); } } diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/SwitchTaskFluent.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/SwitchTaskFluent.java index 8273876e0..9c1be6b5e 100644 --- a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/SwitchTaskFluent.java +++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/SwitchTaskFluent.java @@ -20,14 +20,13 @@ import io.serverlessworkflow.api.types.SwitchCase; import io.serverlessworkflow.api.types.SwitchTask; import io.serverlessworkflow.fluent.spec.TaskBaseBuilder; -import java.util.UUID; import java.util.function.Consumer; public interface SwitchTaskFluent> { String DEFAULT_CASE = "default"; default SELF on(Consumer switchCaseConsumer) { - return this.on(UUID.randomUUID().toString(), switchCaseConsumer); + return this.on(null, switchCaseConsumer); } SELF on(final String name, Consumer switchCaseConsumer); @@ -40,6 +39,15 @@ default SELF onDefault(FlowDirectiveEnum directiveEnum) { return this.on(DEFAULT_CASE, c -> c.then(directiveEnum)); } + int switchItemCount(); + + default String defaultItemNameIfBlank(String name) { + if (name == null || name.isBlank()) { + return "switch-item-" + switchItemCount(); + } + return name; + } + SwitchTask build(); final class SwitchCaseBuilder { diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/TryCatchFluent.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/TryCatchFluent.java index ea2f82af1..ca84558b8 100644 --- a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/TryCatchFluent.java +++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/TryCatchFluent.java @@ -16,13 +16,12 @@ package io.serverlessworkflow.fluent.spec.spi; import io.serverlessworkflow.fluent.spec.TaskBaseBuilder; -import java.util.UUID; import java.util.function.Consumer; public interface TryCatchFluent, LIST> { LIST tryCatch(String name, Consumer itemsConfigurer); default LIST tryCatch(Consumer itemsConfigurer) { - return this.tryCatch(UUID.randomUUID().toString(), itemsConfigurer); + return this.tryCatch(null, itemsConfigurer); } } diff --git a/fluent/spec/src/test/java/io/serverlessworkflow/fluent/spec/TaskItemDefaultNamingTest.java b/fluent/spec/src/test/java/io/serverlessworkflow/fluent/spec/TaskItemDefaultNamingTest.java new file mode 100644 index 000000000..0c0d3887a --- /dev/null +++ b/fluent/spec/src/test/java/io/serverlessworkflow/fluent/spec/TaskItemDefaultNamingTest.java @@ -0,0 +1,212 @@ +/* + * 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.spec; + +import static io.serverlessworkflow.fluent.spec.dsl.DSL.http; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import io.serverlessworkflow.api.types.ForkTaskConfiguration; +import io.serverlessworkflow.api.types.TaskItem; +import io.serverlessworkflow.api.types.TryTask; +import io.serverlessworkflow.api.types.Workflow; +import java.util.List; +import org.junit.jupiter.api.Test; + +/** + * Unit tests to verify that TaskItems without explicit names are automatically assigned a + * deterministic name in the format "taskType-index" (e.g., "set-0", "http-1"). + */ +public class TaskItemDefaultNamingTest { + + @Test + void testTopLevelDoListAutoNaming() { + Workflow wf = + WorkflowBuilder.workflow("flowAutoNameTopLevel") + .tasks( + d -> + d.set(null, s -> s.expr("$.foo = 'bar'")) + .http(null, http().GET().endpoint("http://example.com")) + .emit("", e -> e.event(ev -> ev.type("test.event"))) + .set("explicitName", s -> s.expr("$.x = 1")) // Explicit name should be kept + .fork(null, ForkTaskBuilder::build) // No-op fork to check index 4 + ) + .build(); + + List items = wf.getDo(); + assertNotNull(items, "Do list must not be null"); + assertEquals(5, items.size(), "There should be five tasks"); + + // Verify deterministic auto-naming based on list insertion order + assertEquals("set-0", items.get(0).getName(), "First task should be set-0"); + assertEquals("http-1", items.get(1).getName(), "Second task should be http-1"); + assertEquals("emit-2", items.get(2).getName(), "Third task (empty string) should be emit-2"); + + // Verify explicit names are not overwritten + assertEquals("explicitName", items.get(3).getName(), "Explicit name must be preserved"); + + // Verify index correctly counts past explicit names + assertEquals("fork-4", items.get(4).getName(), "Fifth task should be fork-4"); + } + + @Test + void testNestedTryCatchTaskAutoNaming() { + Workflow wf = + WorkflowBuilder.workflow("flowAutoNameTryCatch") + .tasks( + d -> + d.tryCatch( + null, + t -> + t.tryHandler( + tb -> + tb.set(null, s -> s.expr("$.start = true")) + .http(null, http().GET().endpoint("http://test")) + .set(null, s -> s.expr("$.end = true"))))) + .build(); + + List topItems = wf.getDo(); + assertEquals(1, topItems.size()); + assertEquals("try-0", topItems.get(0).getName(), "Top level tryCatch should be try-0"); + + TryTask tryTask = topItems.get(0).getTask().getTryTask(); + assertNotNull(tryTask, "TryTask should be present"); + + List nestedTryItems = tryTask.getTry(); + assertNotNull(nestedTryItems, "Nested try items must not be null"); + assertEquals(3, nestedTryItems.size()); + + // Verify inner builder list indexes independently of the outer builder + assertEquals("set-0", nestedTryItems.get(0).getName()); + assertEquals("http-1", nestedTryItems.get(1).getName()); + assertEquals("set-2", nestedTryItems.get(2).getName()); + } + + @Test + void testNestedForEachTaskAutoNaming() { + Workflow wf = + WorkflowBuilder.workflow("flowAutoNameForEach") + .tasks( + d -> + d.forEach( + null, + f -> + f.each("item") + .in("$.list") + // Define tasks to be executed for each item in the forEach loop + .tasks( + tb -> + tb.http(null, http().POST().endpoint("http://test")) + .set(null, s -> s.expr("$.processed = true"))))) + .build(); + + List topItems = wf.getDo(); + assertEquals(1, topItems.size()); + assertEquals("for-0", topItems.get(0).getName()); + + // Fetch the inner 'do' tasks of the 'for' loop + List nestedForItems = topItems.get(0).getTask().getForTask().getDo(); + assertNotNull(nestedForItems, "Nested forEach items must not be null"); + assertEquals(2, nestedForItems.size()); + + assertEquals("http-0", nestedForItems.get(0).getName()); + assertEquals("set-1", nestedForItems.get(1).getName()); + } + + @Test + void testNestedForkTaskAutoNaming() { + Workflow wf = + WorkflowBuilder.workflow("flowAutoNameFork") + .tasks( + d -> + d.fork( + null, + f -> + f.branches( + b -> + b.set(null, s -> s.expr("$.a = 1")) + .set(null, s -> s.expr("$.a = 2")) + .http(null, http().GET().endpoint("http://b"))))) + .build(); + + List topItems = wf.getDo(); + assertEquals(1, topItems.size(), "Should have one top-level task"); + assertEquals("fork-0", topItems.get(0).getName(), "Top level fork should be fork-0"); + + // Retrieve the ForkTaskConfiguration + ForkTaskConfiguration forkConfig = topItems.get(0).getTask().getForkTask().getFork(); + assertNotNull(forkConfig, "Fork configuration must not be null"); + + // The branches are just a List built by the inner TaskItemListBuilder + List branches = forkConfig.getBranches(); + assertNotNull(branches, "Branches list must not be null"); + assertEquals(3, branches.size(), "Should have 3 branch tasks"); + + // Verify the inner TaskItemListBuilder isolated its own 0-based index + assertEquals("set-0", branches.get(0).getName(), "First branch should be set-0"); + assertEquals("set-1", branches.get(1).getName(), "Second branch should be set-1"); + assertEquals("http-2", branches.get(2).getName(), "Third branch should be http-2"); + } + + @Test + void testDeterministicNamingAcrossInstances() { + // Build the first workflow instance + Workflow wf1 = + WorkflowBuilder.workflow("workflowOne") + .tasks( + d -> + d.set(null, s -> s.expr("$.a = 1")) + .http(null, http().GET().endpoint("http://example.com")) + .emit("customEmit", e -> e.event(ev -> ev.type("test"))) + .tryCatch( + null, t -> t.tryHandler(tb -> tb.set(null, s -> s.expr("$.b = 2"))))) + .build(); + + // Build the second workflow instance with the exact same task structure + Workflow wf2 = + WorkflowBuilder.workflow("workflowTwo") + .tasks( + d -> + d.set(null, s -> s.expr("$.a = 1")) + .http(null, http().GET().endpoint("http://example.com")) + .emit("customEmit", e -> e.event(ev -> ev.type("test"))) + .tryCatch( + null, t -> t.tryHandler(tb -> tb.set(null, s -> s.expr("$.b = 2"))))) + .build(); + + List tasks1 = wf1.getDo(); + List tasks2 = wf2.getDo(); + + assertEquals(4, tasks1.size(), "Should have exactly 4 tasks"); + assertEquals( + tasks1.size(), tasks2.size(), "Both workflows should have the same number of tasks"); + + // Verify all top-level task names match exactly between the two instances + for (int i = 0; i < tasks1.size(); i++) { + assertEquals( + tasks1.get(i).getName(), + tasks2.get(i).getName(), + "Task names at index " + i + " must match exactly across instances"); + } + + // Double-check the nested task inside the tryCatch block to ensure deep determinism + String nestedName1 = tasks1.get(3).getTask().getTryTask().getTry().get(0).getName(); + String nestedName2 = tasks2.get(3).getTask().getTryTask().getTry().get(0).getName(); + + assertEquals("set-0", nestedName1, "Nested task should reset to 0-based index"); + assertEquals(nestedName1, nestedName2, "Nested task names must match exactly across instances"); + } +}