Skip to content

Commit a41c351

Browse files
committed
[Fix #786] Evaluate embedded properties
Signed-off-by: fjtirado <[email protected]>
1 parent c868d49 commit a41c351

File tree

8 files changed

+505
-115
lines changed

8 files changed

+505
-115
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
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.impl.expressions;
17+
18+
import java.util.Collection;
19+
20+
abstract class AbstractProxyCollection<T> {
21+
22+
protected Collection<T> values;
23+
24+
protected AbstractProxyCollection(Collection<T> values) {
25+
this.values = values;
26+
}
27+
28+
public int size() {
29+
return values.size();
30+
}
31+
32+
public boolean isEmpty() {
33+
return values.isEmpty();
34+
}
35+
36+
public boolean contains(Object o) {
37+
return values.contains(o);
38+
}
39+
40+
public boolean remove(Object o) {
41+
return values.remove(o);
42+
}
43+
44+
public boolean containsAll(Collection<?> c) {
45+
return values.containsAll(c);
46+
}
47+
48+
public boolean retainAll(Collection<?> c) {
49+
return values.retainAll(c);
50+
}
51+
52+
public boolean removeAll(Collection<?> c) {
53+
return values.removeAll(c);
54+
}
55+
56+
public void clear() {
57+
values.clear();
58+
}
59+
60+
public boolean addAll(Collection<? extends T> c) {
61+
return values.addAll(c);
62+
}
63+
64+
public boolean add(T e) {
65+
return values.add(e);
66+
}
67+
}

impl/core/src/main/java/io/serverlessworkflow/impl/expressions/ObjectExpressionFactory.java

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import io.serverlessworkflow.impl.WorkflowContext;
2020
import io.serverlessworkflow.impl.WorkflowModel;
2121
import io.serverlessworkflow.impl.WorkflowPredicate;
22+
import java.util.Collection;
2223
import java.util.Map;
2324

2425
public abstract class ObjectExpressionFactory extends AbstractExpressionFactory {
@@ -31,13 +32,23 @@ protected ObjectExpression buildExpression(ExpressionDescriptor desc) {
3132
return expression::eval;
3233
} else if (desc.asObject() != null) {
3334
Object exprObj = buildExpressionObject(desc.asObject(), this);
34-
return exprObj instanceof Map map
35-
? (w, t, n) -> evaluateExpressionMap(map, w, t, n)
36-
: (w, t, n) -> desc.asObject();
35+
return (w, t, n) -> evaluateExpressionObject(exprObj, w, t, n);
3736
}
3837
throw new IllegalArgumentException("Both object and str are null");
3938
}
4039

40+
private Object evaluateExpressionObject(
41+
Object obj, WorkflowContext workflow, TaskContext task, WorkflowModel model) {
42+
if (obj instanceof ObjectExpression expr) {
43+
return toJavaObject(expr.eval(workflow, task, model));
44+
} else if (obj instanceof Map map) return evaluateExpressionMap(map, workflow, task, model);
45+
else if (obj instanceof Collection col) {
46+
return evaluateExpressionCollection(col, workflow, task, model);
47+
} else {
48+
return obj;
49+
}
50+
}
51+
4152
@Override
4253
public WorkflowPredicate buildPredicate(ExpressionDescriptor desc) {
4354
ObjectExpression expr = buildExpression(desc);
@@ -53,20 +64,40 @@ protected Object toJavaObject(Object eval) {
5364
private Map<String, Object> buildExpressionMap(
5465
Map<String, Object> origMap, ExpressionFactory factory) {
5566
return new ProxyMap(
56-
origMap, o -> ExpressionUtils.isExpr(o) ? buildExpression(o.toString()) : o);
67+
origMap,
68+
o ->
69+
ExpressionUtils.isExpr(o)
70+
? buildExpression(o.toString())
71+
: buildExpressionObject(o, factory));
72+
}
73+
74+
private Collection<Object> buildExpressionList(
75+
Collection<Object> origList, ExpressionFactory factory) {
76+
return new ProxyCollection(
77+
origList,
78+
o ->
79+
ExpressionUtils.isExpr(o)
80+
? buildExpression(o.toString())
81+
: buildExpressionObject(o, factory));
5782
}
5883

5984
private Object buildExpressionObject(Object obj, ExpressionFactory factory) {
60-
return obj instanceof Map map ? buildExpressionMap(map, factory) : obj;
85+
if (obj instanceof Map map) {
86+
return buildExpressionMap(map, factory);
87+
} else if (obj instanceof Collection col) {
88+
return buildExpressionList(col, factory);
89+
} else {
90+
return obj;
91+
}
6192
}
6293

6394
private Map<String, Object> evaluateExpressionMap(
6495
Map<String, Object> origMap, WorkflowContext workflow, TaskContext task, WorkflowModel n) {
65-
return new ProxyMap(
66-
origMap,
67-
o ->
68-
o instanceof ObjectExpression
69-
? toJavaObject(((ObjectExpression) o).eval(workflow, task, n))
70-
: o);
96+
return new ProxyMap(origMap, o -> evaluateExpressionObject(o, workflow, task, n));
97+
}
98+
99+
private Collection<Object> evaluateExpressionCollection(
100+
Collection<Object> origList, WorkflowContext workflow, TaskContext task, WorkflowModel n) {
101+
return new ProxyCollection(origList, o -> evaluateExpressionObject(o, workflow, task, n));
71102
}
72103
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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.impl.expressions;
17+
18+
import java.util.Collection;
19+
import java.util.Iterator;
20+
import java.util.function.UnaryOperator;
21+
22+
class ProxyCollection extends AbstractProxyCollection<Object> implements Collection<Object> {
23+
24+
private final UnaryOperator<Object> function;
25+
26+
public ProxyCollection(Collection<Object> values, UnaryOperator<Object> function) {
27+
super(values);
28+
this.function = function;
29+
}
30+
31+
@Override
32+
public Iterator<Object> iterator() {
33+
return new ProxyIterator(values.iterator(), function);
34+
}
35+
36+
@Override
37+
public Object[] toArray() {
38+
return processArray(values.toArray());
39+
}
40+
41+
@Override
42+
public <T> T[] toArray(T[] a) {
43+
return processArray(values.toArray(a));
44+
}
45+
46+
private <S> S[] processArray(S[] array) {
47+
for (int i = 0; i < array.length; i++) {
48+
array[i] = (S) function.apply(array[i]);
49+
}
50+
return array;
51+
}
52+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
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.impl.expressions;
17+
18+
import java.util.Iterator;
19+
import java.util.function.UnaryOperator;
20+
21+
class ProxyIterator implements Iterator<Object> {
22+
23+
private Iterator<Object> iter;
24+
private final UnaryOperator<Object> function;
25+
26+
public ProxyIterator(Iterator<Object> iter, UnaryOperator<Object> function) {
27+
this.iter = iter;
28+
this.function = function;
29+
}
30+
31+
@Override
32+
public boolean hasNext() {
33+
return iter.hasNext();
34+
}
35+
36+
@Override
37+
public Object next() {
38+
return function.apply(iter.next());
39+
}
40+
41+
@Override
42+
public void remove() {
43+
iter.remove();
44+
}
45+
}

0 commit comments

Comments
 (0)