Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* 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.impl.expressions;

import java.util.Collection;

abstract class AbstractProxyCollection<T> {

protected Collection<T> values;

protected AbstractProxyCollection(Collection<T> values) {
this.values = values;
}

public int size() {
return values.size();
}

public boolean isEmpty() {
return values.isEmpty();
}

public boolean contains(Object o) {
return values.contains(o);
}

public boolean remove(Object o) {
return values.remove(o);
}

public boolean containsAll(Collection<?> c) {
return values.containsAll(c);
}

public boolean retainAll(Collection<?> c) {
return values.retainAll(c);
}

public boolean removeAll(Collection<?> c) {
return values.removeAll(c);
}

public void clear() {
values.clear();
}

public boolean addAll(Collection<? extends T> c) {
return values.addAll(c);
}

public boolean add(T e) {
return values.add(e);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import io.serverlessworkflow.impl.WorkflowContext;
import io.serverlessworkflow.impl.WorkflowModel;
import io.serverlessworkflow.impl.WorkflowPredicate;
import java.util.Collection;
import java.util.Map;

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

private Object buildExpressionObject(Object obj, ExpressionFactory factory) {
if (obj instanceof ObjectExpression expr) {
return expr;
} else if (obj instanceof Map map) {
return buildExpressionMap(map, factory);
} else if (obj instanceof Collection col) {
return buildExpressionList(col, factory);
} else {
return obj;
}
}

private Object evaluateExpressionObject(
Object obj, WorkflowContext workflow, TaskContext task, WorkflowModel model) {
if (obj instanceof ObjectExpression expr) {
return toJavaObject(expr.eval(workflow, task, model));
} else if (obj instanceof Map map) {
return evaluateExpressionMap(map, workflow, task, model);
} else if (obj instanceof Collection col) {
return evaluateExpressionCollection(col, workflow, task, model);
} else {
return obj;
}
}

@Override
public WorkflowPredicate buildPredicate(ExpressionDescriptor desc) {
ObjectExpression expr = buildExpression(desc);
Expand All @@ -51,22 +75,32 @@ protected Object toJavaObject(Object eval) {
}

private Map<String, Object> buildExpressionMap(
Map<String, Object> origMap, ExpressionFactory factory) {
Map<String, Object> map, ExpressionFactory factory) {
return new ProxyMap(
origMap, o -> ExpressionUtils.isExpr(o) ? buildExpression(o.toString()) : o);
map,
o ->
ExpressionUtils.isExpr(o)
? buildExpression(o.toString())
: buildExpressionObject(o, factory));
}

private Object buildExpressionObject(Object obj, ExpressionFactory factory) {
return obj instanceof Map map ? buildExpressionMap(map, factory) : obj;
private Collection<Object> buildExpressionList(
Collection<Object> col, ExpressionFactory factory) {
return new ProxyCollection(
col,
o ->
ExpressionUtils.isExpr(o)
? buildExpression(o.toString())
: buildExpressionObject(o, factory));
}

private Map<String, Object> evaluateExpressionMap(
Map<String, Object> origMap, WorkflowContext workflow, TaskContext task, WorkflowModel n) {
return new ProxyMap(
origMap,
o ->
o instanceof ObjectExpression
? toJavaObject(((ObjectExpression) o).eval(workflow, task, n))
: o);
Map<String, Object> map, WorkflowContext workflow, TaskContext task, WorkflowModel n) {
return new ProxyMap(map, o -> evaluateExpressionObject(o, workflow, task, n));
}

private Collection<Object> evaluateExpressionCollection(
Collection<Object> col, WorkflowContext workflow, TaskContext task, WorkflowModel n) {
return new ProxyCollection(col, o -> evaluateExpressionObject(o, workflow, task, n));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* 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.impl.expressions;

import java.util.Collection;
import java.util.Iterator;
import java.util.function.UnaryOperator;

class ProxyCollection extends AbstractProxyCollection<Object> implements Collection<Object> {

private final UnaryOperator<Object> function;

public ProxyCollection(Collection<Object> values, UnaryOperator<Object> function) {
super(values);
this.function = function;
}

@Override
public Iterator<Object> iterator() {
return new ProxyIterator(values.iterator(), function);
}

@Override
public Object[] toArray() {
return processArray(values.toArray());
}

@Override
public <T> T[] toArray(T[] a) {
return processArray(values.toArray(a));
}

private <S> S[] processArray(S[] array) {
for (int i = 0; i < array.length; i++) {
array[i] = (S) function.apply(array[i]);
}
return array;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* 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.impl.expressions;

import java.util.Iterator;
import java.util.function.UnaryOperator;

class ProxyIterator implements Iterator<Object> {

private Iterator<Object> iter;
private final UnaryOperator<Object> function;

public ProxyIterator(Iterator<Object> iter, UnaryOperator<Object> function) {
this.iter = iter;
this.function = function;
}

@Override
public boolean hasNext() {
return iter.hasNext();
}

@Override
public Object next() {
return function.apply(iter.next());
}

@Override
public void remove() {
iter.remove();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,63 +83,14 @@ public Set<String> keySet() {

@Override
public Collection<Object> values() {
return new ProxyCollection(map.values());
return new ProxyCollection(map.values(), function);
}

@Override
public Set<Entry<String, Object>> entrySet() {
return new ProxyEntrySet(map.entrySet());
}

private abstract class AbstractProxyCollection<T> {

protected Collection<T> values;

protected AbstractProxyCollection(Collection<T> values) {
this.values = values;
}

public int size() {
return values.size();
}

public boolean isEmpty() {
return values.isEmpty();
}

public boolean contains(Object o) {
return values.contains(o);
}

public boolean remove(Object o) {
return values.remove(o);
}

public boolean containsAll(Collection<?> c) {
return values.containsAll(c);
}

public boolean retainAll(Collection<?> c) {
return values.retainAll(c);
}

public boolean removeAll(Collection<?> c) {
return values.removeAll(c);
}

public void clear() {
values.clear();
}

public boolean addAll(Collection<? extends T> c) {
return values.addAll(c);
}

public boolean add(T e) {
return values.add(e);
}
}

private class ProxyEntrySet extends AbstractProxyCollection<Entry<String, Object>>
implements Set<Entry<String, Object>> {

Expand Down Expand Up @@ -170,36 +121,6 @@ private <T> T[] processEntries(T[] array) {
}
}

private class ProxyCollection extends AbstractProxyCollection<Object>
implements Collection<Object> {

public ProxyCollection(Collection<Object> values) {
super(values);
}

@Override
public Iterator<Object> iterator() {
return new ProxyIterator(values.iterator());
}

@Override
public Object[] toArray() {
return processArray(values.toArray());
}

@Override
public <T> T[] toArray(T[] a) {
return processArray(values.toArray(a));
}

private <S> S[] processArray(S[] array) {
for (int i = 0; i < array.length; i++) {
array[i] = (S) processValue(array[i]);
}
return array;
}
}

private class ProxyEntry implements Entry<String, Object> {

private Entry<String, Object> entry;
Expand All @@ -224,30 +145,6 @@ public Object setValue(Object value) {
}
}

private class ProxyIterator implements Iterator<Object> {

private Iterator<Object> iter;

public ProxyIterator(Iterator<Object> iter) {
this.iter = iter;
}

@Override
public boolean hasNext() {
return iter.hasNext();
}

@Override
public Object next() {
return processValue(iter.next());
}

@Override
public void remove() {
iter.remove();
}
}

private class ProxyEntryIterator implements Iterator<Entry<String, Object>> {

private Iterator<Entry<String, Object>> iter;
Expand Down
Loading