Skip to content

Commit 423a424

Browse files
committed
Improving API to allow strong typing
Signed-off-by: fjtirado <ftirados@redhat.com>
1 parent d7701a5 commit 423a424

File tree

13 files changed

+171
-23
lines changed

13 files changed

+171
-23
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
});
@@ -64,9 +65,17 @@ protected Optional<WorkflowFilter> buildWhileFilter() {
6465
return super.buildWhileFilter();
6566
}
6667

68+
private Object collectionFilterObject(ForTaskFunction taskFunctions) {
69+
return taskFunctions.getForClass().isPresent()
70+
? new TypedFunction(
71+
taskFunctions.getCollection(), taskFunctions.getForClass().orElseThrow())
72+
: taskFunctions.getCollection();
73+
}
74+
6775
protected WorkflowFilter buildCollectionFilter() {
6876
return task instanceof ForTaskFunction taskFunctions
69-
? WorkflowUtils.buildWorkflowFilter(application, null, taskFunctions.getCollection())
77+
? WorkflowUtils.buildWorkflowFilter(
78+
application, null, collectionFilterObject(taskFunctions))
7079
: super.buildCollectionFilter();
7180
}
7281
}

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
}
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) {}

fluent/agentic/src/main/java/io/serverlessworkflow/fluent/agentic/AgentAdapters.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public static Function<Cognisphere, Object> toFunction(AgentExecutor exec) {
3838
return exec::invoke;
3939
}
4040

41-
public static LoopPredicateIndex<Object, Object> toWhile(Predicate<Cognisphere> exit) {
42-
return (model, item, idx) -> !exit.test((Cognisphere) model);
41+
public static LoopPredicateIndex<Cognisphere, Object> toWhile(Predicate<Cognisphere> exit) {
42+
return (model, item, idx) -> !exit.test(model);
4343
}
4444
}

fluent/agentic/src/main/java/io/serverlessworkflow/fluent/agentic/LoopAgentsBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public LoopAgentsBuilder maxIterations(int maxIterations) {
6161
}
6262

6363
public LoopAgentsBuilder exitCondition(Predicate<Cognisphere> exitCondition) {
64-
this.forTask.withWhile(AgentAdapters.toWhile(exitCondition));
64+
this.forTask.withWhile(AgentAdapters.toWhile(exitCondition), Cognisphere.class);
6565
return this;
6666
}
6767

0 commit comments

Comments
 (0)