diff --git a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/ReduceExpression.java b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/ReduceExpression.java index 35bb882..426c242 100644 --- a/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/ReduceExpression.java +++ b/src/main/java/io/github/jamsesso/jsonlogic/evaluator/expressions/ReduceExpression.java @@ -5,8 +5,8 @@ import io.github.jamsesso.jsonlogic.evaluator.JsonLogicEvaluationException; import io.github.jamsesso.jsonlogic.evaluator.JsonLogicEvaluator; import io.github.jamsesso.jsonlogic.evaluator.JsonLogicExpression; +import io.github.jamsesso.jsonlogic.utils.LocalContext; -import java.util.HashMap; import java.util.Map; public class ReduceExpression implements JsonLogicExpression { @@ -35,7 +35,7 @@ public Object evaluate(JsonLogicEvaluator evaluator, JsonLogicArray arguments, O return accumulator; } - Map context = new HashMap<>(); + Map context = new LocalContext(data); context.put("accumulator", accumulator); for (Object item : new ArrayLike(maybeArray)) { diff --git a/src/main/java/io/github/jamsesso/jsonlogic/utils/LocalContext.java b/src/main/java/io/github/jamsesso/jsonlogic/utils/LocalContext.java new file mode 100644 index 0000000..e59cb34 --- /dev/null +++ b/src/main/java/io/github/jamsesso/jsonlogic/utils/LocalContext.java @@ -0,0 +1,87 @@ +package io.github.jamsesso.jsonlogic.utils; + +import java.util.*; + +public class LocalContext implements Map{ + private final Map delegate = new HashMap<>(); + private final Map parent; + + public LocalContext(Object parent) { + if( parent instanceof Map) { + this.parent = (Map) parent; + }else{ + this.parent = new HashMap<>(); + } + } + + + @Override + public int size() { + return delegate.size() + parent.size(); + } + + @Override + public boolean isEmpty() { + return delegate.isEmpty() && parent.isEmpty(); + } + + @Override + public boolean containsKey(Object key) { + return delegate.containsKey(key) || parent.containsKey(key); + } + + @Override + public boolean containsValue(Object value) { + return delegate.containsValue(value) || parent.containsValue(value); + } + + @Override + public Object get(Object key) { + return delegate.get(key) != null ? delegate.get(key) : parent.get(key); + } + + @Override + public Object put(String key, Object value) { + return delegate.put(key, value); + } + + @Override + public Object remove(Object key) { + return delegate.remove(key); + } + + @Override + public void putAll(Map m) { + delegate.putAll(m); + } + + @Override + public void clear() { + delegate.clear(); + } + + @Override + public Set keySet() { + final Set keys = new HashSet<>(delegate.keySet()); + for( Object key : parent.keySet()){ + keys.add(""+key); + } + return keys; + } + + @Override + public Collection values() { + final List values = new ArrayList<>(delegate.values()); + values.addAll(parent.values()); + return values; + } + + @Override + public Set> entrySet() { + final Set> entries = new HashSet<>(delegate.entrySet()); + for( Map.Entry entry : parent.entrySet()){ + entries.add(new AbstractMap.SimpleEntry<>(""+entry.getKey(), entry.getValue())); + } + return entries; + } +} diff --git a/src/test/java/io/github/jamsesso/jsonlogic/ReduceExpressionTests.java b/src/test/java/io/github/jamsesso/jsonlogic/ReduceExpressionTests.java index 5b0d814..bdf0e08 100644 --- a/src/test/java/io/github/jamsesso/jsonlogic/ReduceExpressionTests.java +++ b/src/test/java/io/github/jamsesso/jsonlogic/ReduceExpressionTests.java @@ -2,6 +2,9 @@ import org.junit.Test; +import java.util.HashMap; +import java.util.Map; + import static org.junit.Assert.assertEquals; public class ReduceExpressionTests { @@ -19,4 +22,39 @@ public void testReduce() throws JsonLogicException { assertEquals(21.0, result); } + + @Test + public void testReduceWVariableAccess() throws JsonLogicException { + String json = "{\n" + + " \"reduce\": [\n" + + " {\n" + + " \"var\": \"data\"\n" + + " },\n" + + " {\n" + + " \"*\": [\n" + + " {\n" + + " \"var\": \"multiplicator\"\n" + + " },\n" + + " {\n" + + " \"+\": [\n" + + " {\n" + + " \"var\": \"current\"\n" + + " },\n" + + " {\n" + + " \"var\": \"accumulator\"\n" + + " }\n" + + " ]\n" + + " }\n" + + " ]\n" + + " },\n" + + " 0\n" + + " ]\n" + + "}"; + final Map data = new HashMap<>(); + data.put("multiplicator", 2); + data.put("data", new int[] {1, 2}); + Object result = jsonLogic.apply(json, data); + + assertEquals(8.0, result); + } }