Skip to content

Commit 20d2789

Browse files
authored
Merge pull request #683 from fjtirado/Strong_types
Improving API to allow strong typing
2 parents d7701a5 + 9f71979 commit 20d2789

File tree

16 files changed

+197
-26
lines changed

16 files changed

+197
-26
lines changed

experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaForExecutorBuilder.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import io.serverlessworkflow.api.types.ForTask;
2222
import io.serverlessworkflow.api.types.Workflow;
2323
import io.serverlessworkflow.api.types.func.ForTaskFunction;
24+
import io.serverlessworkflow.api.types.func.TypedFunction;
2425
import io.serverlessworkflow.impl.WorkflowApplication;
2526
import io.serverlessworkflow.impl.WorkflowFilter;
2627
import io.serverlessworkflow.impl.WorkflowPosition;
@@ -44,7 +45,7 @@ protected JavaForExecutorBuilder(
4445
protected Optional<WorkflowFilter> buildWhileFilter() {
4546
if (task instanceof ForTaskFunction taskFunctions) {
4647
final LoopPredicateIndex whilePred = taskFunctions.getWhilePredicate();
47-
Optional<Class<?>> modelClass = taskFunctions.getModelClass();
48+
Optional<Class<?>> whileClass = taskFunctions.getWhileClass();
4849
String varName = task.getFor().getEach();
4950
String indexName = task.getFor().getAt();
5051
if (whilePred != null) {
@@ -55,7 +56,7 @@ protected Optional<WorkflowFilter> buildWhileFilter() {
5556
.modelFactory()
5657
.from(
5758
whilePred.test(
58-
JavaFuncUtils.convert(n, modelClass),
59+
JavaFuncUtils.convert(n, whileClass),
5960
item,
6061
(Integer) safeObject(t.variables().get(indexName))));
6162
});
@@ -66,7 +67,15 @@ protected Optional<WorkflowFilter> buildWhileFilter() {
6667

6768
protected WorkflowFilter buildCollectionFilter() {
6869
return task instanceof ForTaskFunction taskFunctions
69-
? WorkflowUtils.buildWorkflowFilter(application, null, taskFunctions.getCollection())
70+
? WorkflowUtils.buildWorkflowFilter(
71+
application, null, collectionFilterObject(taskFunctions))
7072
: super.buildCollectionFilter();
7173
}
74+
75+
private Object collectionFilterObject(ForTaskFunction taskFunctions) {
76+
return taskFunctions.getForClass().isPresent()
77+
? new TypedFunction(
78+
taskFunctions.getCollection(), taskFunctions.getForClass().orElseThrow())
79+
: taskFunctions.getCollection();
80+
}
7281
}

experimental/lambda/src/main/java/io/serverlessworkflow/impl/executors/func/JavaSwitchExecutorBuilder.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@
2020
import io.serverlessworkflow.api.types.SwitchTask;
2121
import io.serverlessworkflow.api.types.Workflow;
2222
import io.serverlessworkflow.api.types.func.SwitchCaseFunction;
23+
import io.serverlessworkflow.api.types.func.TypedPredicate;
2324
import io.serverlessworkflow.impl.WorkflowApplication;
2425
import io.serverlessworkflow.impl.WorkflowFilter;
2526
import io.serverlessworkflow.impl.WorkflowPosition;
2627
import io.serverlessworkflow.impl.WorkflowUtils;
2728
import io.serverlessworkflow.impl.executors.SwitchExecutor.SwitchExecutorBuilder;
2829
import io.serverlessworkflow.impl.resources.ResourceLoader;
2930
import java.util.Optional;
31+
import java.util.function.Predicate;
3032

3133
public class JavaSwitchExecutorBuilder extends SwitchExecutorBuilder {
3234

@@ -42,7 +44,14 @@ protected JavaSwitchExecutorBuilder(
4244
@Override
4345
protected Optional<WorkflowFilter> buildFilter(SwitchCase switchCase) {
4446
return switchCase instanceof SwitchCaseFunction function
45-
? Optional.of(WorkflowUtils.buildWorkflowFilter(application, null, function.predicate()))
47+
? Optional.of(
48+
WorkflowUtils.buildWorkflowFilter(
49+
application, null, predObject(function.predicate(), function.predicateClass())))
4650
: super.buildFilter(switchCase);
4751
}
52+
53+
@SuppressWarnings({"unchecked", "rawtypes"})
54+
private Object predObject(Predicate<?> pred, Optional<Class<?>> predClass) {
55+
return predClass.isPresent() ? new TypedPredicate(pred, predClass.orElseThrow()) : pred;
56+
}
4857
}

experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/func/JavaExpressionFactory.java

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
import io.serverlessworkflow.api.types.TaskBase;
1919
import io.serverlessworkflow.api.types.TaskMetadata;
20+
import io.serverlessworkflow.api.types.func.TypedFunction;
21+
import io.serverlessworkflow.api.types.func.TypedPredicate;
2022
import io.serverlessworkflow.impl.TaskContext;
2123
import io.serverlessworkflow.impl.WorkflowContext;
2224
import io.serverlessworkflow.impl.WorkflowFilter;
@@ -52,8 +54,12 @@ public Expression buildExpression(String expression) {
5254
public WorkflowFilter buildFilter(String expr, Object value) {
5355
if (value instanceof Function func) {
5456
return (w, t, n) -> modelFactory.fromAny(func.apply(n.asJavaObject()));
57+
} else if (value instanceof TypedFunction func) {
58+
return (w, t, n) -> modelFactory.fromAny(func.function().apply(n.as(func.argClass())));
5559
} else if (value instanceof Predicate pred) {
5660
return fromPredicate(pred);
61+
} else if (value instanceof TypedPredicate pred) {
62+
return fromPredicate(pred);
5763
} else if (value instanceof BiPredicate pred) {
5864
return (w, t, n) -> modelFactory.from(pred.test(w, t));
5965
} else if (value instanceof BiFunction func) {
@@ -70,14 +76,23 @@ private WorkflowFilter fromPredicate(Predicate pred) {
7076
return (w, t, n) -> modelFactory.from(pred.test(n.asJavaObject()));
7177
}
7278

79+
@SuppressWarnings({"rawtypes", "unchecked"})
80+
private WorkflowFilter fromPredicate(TypedPredicate pred) {
81+
return (w, t, n) -> modelFactory.from(pred.pred().test(n.as(pred.argClass())));
82+
}
83+
7384
@Override
7485
public Optional<WorkflowFilter> buildIfFilter(TaskBase task) {
7586
TaskMetadata metadata = task.getMetadata();
76-
return metadata != null
77-
&& metadata.getAdditionalProperties().get(TaskMetadataKeys.IF_PREDICATE)
78-
instanceof Predicate pred
79-
? Optional.of(fromPredicate(pred))
80-
: ExpressionFactory.super.buildIfFilter(task);
87+
if (metadata != null) {
88+
Object obj = metadata.getAdditionalProperties().get(TaskMetadataKeys.IF_PREDICATE);
89+
if (obj instanceof Predicate pred) {
90+
return Optional.of(fromPredicate(pred));
91+
} else if (obj instanceof TypedPredicate pred) {
92+
return Optional.of(fromPredicate(pred));
93+
}
94+
}
95+
return ExpressionFactory.super.buildIfFilter(task);
8196
}
8297

8398
@Override

experimental/types/src/main/java/io/serverlessworkflow/api/types/func/ExportAsFunction.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package io.serverlessworkflow.api.types.func;
1717

1818
import io.serverlessworkflow.api.types.ExportAs;
19+
import java.util.Objects;
1920
import java.util.function.Function;
2021

2122
public class ExportAsFunction extends ExportAs {
@@ -24,4 +25,10 @@ public <T, V> ExportAs withFunction(Function<T, V> value) {
2425
setObject(value);
2526
return this;
2627
}
28+
29+
public <T, V> ExportAs withFunction(Function<T, V> value, Class<T> argClass) {
30+
Objects.requireNonNull(argClass);
31+
setObject(new TypedFunction<>(value, argClass));
32+
return this;
33+
}
2734
}

experimental/types/src/main/java/io/serverlessworkflow/api/types/func/ForTaskFunction.java

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ public class ForTaskFunction extends ForTask {
2626

2727
private static final long serialVersionUID = 1L;
2828
private LoopPredicateIndex<?, ?> whilePredicate;
29-
private Optional<Class<?>> modelClass;
29+
private Optional<Class<?>> whileClass;
3030
private Optional<Class<?>> itemClass;
31+
private Optional<Class<?>> forClass;
3132
private Function<?, Collection<?>> collection;
3233

3334
public <T, V> ForTaskFunction withWhile(LoopPredicate<T, V> whilePredicate) {
@@ -53,35 +54,45 @@ public <T, V> ForTaskFunction withWhile(LoopPredicateIndex<T, V> whilePredicate)
5354

5455
public <T, V> ForTaskFunction withWhile(
5556
LoopPredicateIndex<T, V> whilePredicate, Class<T> modelClass) {
56-
return withWhile(whilePredicate, Optional.of(modelClass), Optional.empty());
57+
return withWhile(whilePredicate, Optional.ofNullable(modelClass), Optional.empty());
5758
}
5859

5960
public <T, V> ForTaskFunction withWhile(
6061
LoopPredicateIndex<T, V> whilePredicate, Class<T> modelClass, Class<V> itemClass) {
61-
return withWhile(whilePredicate, Optional.of(modelClass), Optional.of(itemClass));
62+
return withWhile(whilePredicate, Optional.ofNullable(modelClass), Optional.of(itemClass));
6263
}
6364

6465
private <T, V> ForTaskFunction withWhile(
6566
LoopPredicateIndex<T, V> whilePredicate,
6667
Optional<Class<?>> modelClass,
6768
Optional<Class<?>> itemClass) {
6869
this.whilePredicate = whilePredicate;
69-
this.modelClass = modelClass;
70+
this.whileClass = modelClass;
7071
this.itemClass = itemClass;
7172
return this;
7273
}
7374

7475
public <T> ForTaskFunction withCollection(Function<T, Collection<?>> collection) {
76+
return withCollection(collection, null);
77+
}
78+
79+
public <T> ForTaskFunction withCollection(
80+
Function<T, Collection<?>> collection, Class<T> colArgClass) {
7581
this.collection = collection;
82+
this.forClass = Optional.ofNullable(colArgClass);
7683
return this;
7784
}
7885

7986
public LoopPredicateIndex<?, ?> getWhilePredicate() {
8087
return whilePredicate;
8188
}
8289

83-
public Optional<Class<?>> getModelClass() {
84-
return modelClass;
90+
public Optional<Class<?>> getWhileClass() {
91+
return whileClass;
92+
}
93+
94+
public Optional<Class<?>> getForClass() {
95+
return forClass;
8596
}
8697

8798
public Optional<Class<?>> getItemClass() {

experimental/types/src/main/java/io/serverlessworkflow/api/types/func/InputFromFunction.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package io.serverlessworkflow.api.types.func;
1717

1818
import io.serverlessworkflow.api.types.InputFrom;
19+
import java.util.Objects;
1920
import java.util.function.Function;
2021

2122
public class InputFromFunction extends InputFrom {
@@ -24,4 +25,10 @@ public <T, V> InputFrom withFunction(Function<T, V> value) {
2425
setObject(value);
2526
return this;
2627
}
28+
29+
public <T, V> InputFrom withFunction(Function<T, V> value, Class<T> argClass) {
30+
Objects.requireNonNull(argClass);
31+
setObject(new TypedFunction<>(value, argClass));
32+
return this;
33+
}
2734
}

experimental/types/src/main/java/io/serverlessworkflow/api/types/func/OutputAsFunction.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package io.serverlessworkflow.api.types.func;
1717

1818
import io.serverlessworkflow.api.types.OutputAs;
19+
import java.util.Objects;
1920
import java.util.function.Function;
2021

2122
public class OutputAsFunction extends OutputAs {
@@ -24,4 +25,10 @@ public <T, V> OutputAs withFunction(Function<T, V> value) {
2425
setObject(value);
2526
return this;
2627
}
28+
29+
public <T, V> OutputAs withFunction(Function<T, V> value, Class<T> argClass) {
30+
Objects.requireNonNull(argClass);
31+
setObject(new TypedFunction<>(value, argClass));
32+
return this;
33+
}
2734
}

experimental/types/src/main/java/io/serverlessworkflow/api/types/func/SwitchCaseFunction.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,32 @@
1616
package io.serverlessworkflow.api.types.func;
1717

1818
import io.serverlessworkflow.api.types.SwitchCase;
19+
import java.util.Optional;
1920
import java.util.function.Predicate;
2021

2122
public class SwitchCaseFunction extends SwitchCase {
2223

2324
private static final long serialVersionUID = 1L;
2425
private Predicate<?> predicate;
26+
private Optional<Class<?>> predicateClass;
2527

2628
public <T> SwitchCaseFunction withPredicate(Predicate<T> predicate) {
2729
this.predicate = predicate;
30+
this.predicateClass = Optional.empty();
2831
return this;
2932
}
3033

31-
public <T> void setPredicate(Predicate<T> predicate) {
34+
public <T> SwitchCaseFunction withPredicate(Predicate<T> predicate, Class<T> predicateClass) {
3235
this.predicate = predicate;
36+
this.predicateClass = Optional.ofNullable(predicateClass);
37+
return this;
3338
}
3439

3540
public Predicate<?> predicate() {
3641
return predicate;
3742
}
43+
44+
public Optional<Class<?>> predicateClass() {
45+
return predicateClass;
46+
}
3847
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright 2020-Present The Serverless Workflow Specification Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.serverlessworkflow.api.types.func;
17+
18+
import java.util.function.Function;
19+
20+
public record TypedFunction<T, V>(Function<T, V> function, Class<T> argClass) {}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright 2020-Present The Serverless Workflow Specification Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.serverlessworkflow.api.types.func;
17+
18+
import java.util.function.Predicate;
19+
20+
public record TypedPredicate<T>(Predicate<T> pred, Class<T> argClass) {}

0 commit comments

Comments
 (0)