diff --git a/README.md b/README.md index bb01382e..950c2b60 100644 --- a/README.md +++ b/README.md @@ -167,7 +167,7 @@ Expression expression = new Expression("\"Hello \" + name + \", you are \" + age System.out.println(expression.evaluate().getStringValue()); // prints Hello Frank, you are 38 ``` -### Arrays (also multidimensional) are supported and can be passed as Java _Lists_. +### Arrays (also multidimensional) are supported and can be passed as Java _Lists_ or instances of Java arrays. See the [Documentation](https://ezylang.github.io/EvalEx/concepts/datatypes.html#array) for more details. @@ -177,7 +177,7 @@ Expression expression = new Expression("values[i-1] * factors[i-1]"); EvaluationValue result = expression .with("values", List.of(2, 3, 4)) - .and("factors", List.of(2, 4, 6)) + .and("factors", new Object[] {2, 4, 6}) .and("i", 1) .evaluate(); diff --git a/docs/concepts/datatypes.md b/docs/concepts/datatypes.md index 894d91c6..280d263a 100644 --- a/docs/concepts/datatypes.md +++ b/docs/concepts/datatypes.md @@ -83,8 +83,8 @@ Duration are stored as a _java.time.Duration_. The duration values are useful fo Arrays are stored internally as a _java.util.List<EvaluationValue>_. When passed as a variable, the list will be iterated and each entry will be converted using the data type conversion -rules. -So, for example, a list of double values will be converted to a list of _EvaluationValue_ +rules. Instances of _java.util.List_ and Java arrays can be passed as parameters. +So, for example, a list or array of double values will be converted to a list of _EvaluationValue_ objects of type _NUMBER_, with an internal BigDecimal representation. Arrays can hold mixed data types: diff --git a/docs/index.md b/docs/index.md index 2f36891f..fcfcb17a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -161,7 +161,7 @@ Expression expression = new Expression("\"Hello \" + name + \", you are \" + age System.out.println(expression.evaluate().getStringValue()); // prints Hello Frank, you are 38 ``` -### Arrays (also multidimensional) are supported and can be passed as Java _Lists_. +### Arrays (also multidimensional) are supported and can be passed as Java _Lists_ or instances of Java arrays. See the [Documentation](https://ezylang.github.io/EvalEx/concepts/datatypes.html#array) for more details. @@ -171,7 +171,7 @@ Expression expression = new Expression("values[i-1] * factors[i-1]"); EvaluationValue result = expression .with("values", List.of(2, 3, 4)) - .and("factors", List.of(2, 4, 6)) + .and("factors", new Object[] {2, 4, 6}) .and("i", 1) .evaluate(); diff --git a/src/main/java/com/ezylang/evalex/data/conversion/ArrayConverter.java b/src/main/java/com/ezylang/evalex/data/conversion/ArrayConverter.java index 016f2ed8..72ee145d 100644 --- a/src/main/java/com/ezylang/evalex/data/conversion/ArrayConverter.java +++ b/src/main/java/com/ezylang/evalex/data/conversion/ArrayConverter.java @@ -24,14 +24,23 @@ public class ArrayConverter implements ConverterIfc { @Override public EvaluationValue convert(Object object, ExpressionConfiguration configuration) { - List array = new ArrayList<>(); - ((List) object).forEach(element -> array.add(new EvaluationValue(element, configuration))); + List list = new ArrayList<>(); - return EvaluationValue.arrayValue(array); + if (object instanceof Object[]) { + for (Object element : (Object[]) object) { + list.add(new EvaluationValue(element, configuration)); + } + } else if (object instanceof List) { + ((List) object).forEach(element -> list.add(new EvaluationValue(element, configuration))); + } else { + throw illegalArgument(object); + } + + return EvaluationValue.arrayValue(list); } @Override public boolean canConvert(Object object) { - return object instanceof List; + return object instanceof List || object instanceof Object[]; } } diff --git a/src/test/java/com/ezylang/evalex/ExpressionEvaluatorArrayTest.java b/src/test/java/com/ezylang/evalex/ExpressionEvaluatorArrayTest.java index f175197d..b573bc7c 100644 --- a/src/test/java/com/ezylang/evalex/ExpressionEvaluatorArrayTest.java +++ b/src/test/java/com/ezylang/evalex/ExpressionEvaluatorArrayTest.java @@ -110,6 +110,17 @@ void testMixedArray() throws ParseException, EvaluationException { assertThat(expression3.evaluate().getStringValue()).isEqualTo("true"); } + @Test + void testArrayAndList() throws EvaluationException, ParseException { + Expression expression = + createExpression("values[i-1] * factors[i-1]") + .with("values", List.of(2, 3, 4)) + .and("factors", new Object[] {2, 4, 6}) + .and("i", 1); + + assertThat(expression.evaluate().getStringValue()).isEqualTo("4"); + } + @Test void testThrowsUnsupportedDataTypeForArray() { assertThatThrownBy(() -> createExpression("a[0]").with("a", "aString").evaluate()) diff --git a/src/test/java/com/ezylang/evalex/data/conversion/ArrayConverterTest.java b/src/test/java/com/ezylang/evalex/data/conversion/ArrayConverterTest.java index 5a378d3e..6efe2f6b 100644 --- a/src/test/java/com/ezylang/evalex/data/conversion/ArrayConverterTest.java +++ b/src/test/java/com/ezylang/evalex/data/conversion/ArrayConverterTest.java @@ -16,10 +16,12 @@ package com.ezylang.evalex.data.conversion; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.ezylang.evalex.config.ExpressionConfiguration; import com.ezylang.evalex.data.EvaluationValue; import java.math.BigDecimal; +import java.time.Instant; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -61,15 +63,44 @@ void testArrayEmpty() { assertThat(value.getArrayValue()).isEmpty(); } + @Test + void testArrayFromJavaArray() { + Instant now = Instant.now(); + Object[] array = + new Object[] {"1", 2, new BigDecimal(3), null, EvaluationValue.dateTimeValue(now)}; + + EvaluationValue value = converter.convert(array, defaultConfiguration); + + assertThat(value.isArrayValue()).isTrue(); + assertThat(value.getArrayValue()).hasSize(5); + assertThat(value.getArrayValue().get(0).isStringValue()).isTrue(); + assertThat(value.getArrayValue().get(0).getStringValue()).isEqualTo("1"); + assertThat(value.getArrayValue().get(1).isNumberValue()).isTrue(); + assertThat(value.getArrayValue().get(1).getStringValue()).isEqualTo("2"); + assertThat(value.getArrayValue().get(2).isNumberValue()).isTrue(); + assertThat(value.getArrayValue().get(2).getStringValue()).isEqualTo("3"); + assertThat(value.getArrayValue().get(3).isNullValue()).isTrue(); + assertThat(value.getArrayValue().get(3).getStringValue()).isNull(); + assertThat(value.getArrayValue().get(4).isDateTimeValue()).isTrue(); + assertThat(value.getArrayValue().get(4).getDateTimeValue()).isEqualTo(now); + } + @Test void testCanConvert() { + assertThat(converter.canConvert(new String[] {"1", "2", "3"})).isTrue(); assertThat(converter.canConvert(Collections.EMPTY_LIST)).isTrue(); assertThat(converter.canConvert(Arrays.asList(1, 2, 3))).isTrue(); } @Test void testCanNotConvert() { - assertThat(converter.canConvert(new String[] {"1", "2", "3"})).isFalse(); assertThat(converter.canConvert(new BigDecimal(1))).isFalse(); } + + @Test + void testIllegalArgumentException() { + assertThatThrownBy(() -> converter.convert("test", defaultConfiguration)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Unsupported data type 'java.lang.String'"); + } }