parameterResults = new ArrayList<>();
for (int i = 0; i < startNode.getParameters().size(); i++) {
if (token.getFunctionDefinition().isParameterLazy(i)) {
- parameterResults.add(new EvaluationValue(startNode.getParameters().get(i)));
+ parameterResults.add(convertValue(startNode.getParameters().get(i)));
} else {
parameterResults.add(evaluateSubtree(startNode.getParameters().get(i)));
}
@@ -219,7 +210,7 @@ public class Expression {
if (configuration.isStripTrailingZeros()) {
bigDecimal = bigDecimal.stripTrailingZeros();
}
- return new EvaluationValue(bigDecimal);
+ return EvaluationValue.numberValue(bigDecimal);
}
/**
@@ -266,7 +257,7 @@ public class Expression {
String.format("Can't set value for constant '%s'", variable));
}
}
- getDataAccessor().setData(variable, new EvaluationValue(value));
+ getDataAccessor().setData(variable, convertValue(value));
return this;
}
@@ -322,7 +313,18 @@ public class Expression {
* @return An {@link EvaluationValue} of type {@link EvaluationValue.DataType#NUMBER}.
*/
public EvaluationValue convertDoubleValue(double value) {
- return new EvaluationValue(value, configuration.getMathContext());
+ return convertValue(value);
+ }
+
+ /**
+ * Converts an object value to an {@link EvaluationValue} by considering the configuration {@link
+ * EvaluationValue(Object, ExpressionConfiguration)}.
+ *
+ * @param value The object value to covert.
+ * @return An {@link EvaluationValue} of the detected type and value.
+ */
+ public EvaluationValue convertValue(Object value) {
+ return new EvaluationValue(value, configuration);
}
/**
diff --git a/src/main/java/com/ezylang/evalex/config/ExpressionConfiguration.java b/src/main/java/com/ezylang/evalex/config/ExpressionConfiguration.java
index 86fd4a6..53b5549 100644
--- a/src/main/java/com/ezylang/evalex/config/ExpressionConfiguration.java
+++ b/src/main/java/com/ezylang/evalex/config/ExpressionConfiguration.java
@@ -15,9 +15,7 @@
*/
package com.ezylang.evalex.config;
-import com.ezylang.evalex.data.DataAccessorIfc;
-import com.ezylang.evalex.data.EvaluationValue;
-import com.ezylang.evalex.data.MapBasedDataAccessor;
+import com.ezylang.evalex.data.*;
import com.ezylang.evalex.functions.FunctionIfc;
import com.ezylang.evalex.functions.basic.*;
import com.ezylang.evalex.functions.datetime.*;
@@ -75,6 +73,9 @@ public class ExpressionConfiguration {
public static final MathContext DEFAULT_MATH_CONTEXT =
new MathContext(68, RoundingMode.HALF_EVEN);
+ /** The default zone id is the systemd default zone ID. */
+ public static final ZoneId DEFAULT_ZONE_ID = ZoneId.systemDefault();
+
/** The operator dictionary holds all operators that will be allowed in an expression. */
@Builder.Default
@Getter
@@ -227,8 +228,14 @@ public class ExpressionConfiguration {
*/
@Builder.Default @Getter private final boolean allowOverwriteConstants = true;
- /** Set the default zone id. By default, the system default zone id is used. */
- @Builder.Default @Getter private final ZoneId defaultZoneId = ZoneId.systemDefault();
+ /** The time zone id. By default, the system default zone id is used. */
+ @Builder.Default @Getter private final ZoneId zoneId = DEFAULT_ZONE_ID;
+
+ /** The converter to use when converting different data types to an {@link EvaluationValue}. */
+ @Builder.Default @Getter
+ private final EvaluationValueConverterIfc evaluationValueConverter =
+ new DefaultEvaluationValueConverter();
+
/**
* Convenience method to create a default configuration.
*
@@ -243,14 +250,12 @@ public class ExpressionConfiguration {
*
* @param operators variable number of arguments with a map entry holding the operator name and
* implementation.
- * Example:
- *
- * ExpressionConfiguration.defaultConfiguration()
- * .withAdditionalOperators(
- * Map.entry("++", new PrefixPlusPlusOperator()),
- * Map.entry("++", new PostfixPlusPlusOperator()));
- *
- *
+ * Example:
+ * ExpressionConfiguration.defaultConfiguration()
+ * .withAdditionalOperators(
+ * Map.entry("++", new PrefixPlusPlusOperator()),
+ * Map.entry("++", new PostfixPlusPlusOperator()));
+ *
* @return The modified configuration, to allow chaining of methods.
*/
@SafeVarargs
@@ -266,14 +271,12 @@ public class ExpressionConfiguration {
*
* @param functions variable number of arguments with a map entry holding the functions name and
* implementation.
- * Example:
- *
- * ExpressionConfiguration.defaultConfiguration()
- * .withAdditionalFunctions(
- * Map.entry("save", new SaveFunction()),
- * Map.entry("update", new UpdateFunction()));
- *
- *
+ * Example:
+ * ExpressionConfiguration.defaultConfiguration()
+ * .withAdditionalFunctions(
+ * Map.entry("save", new SaveFunction()),
+ * Map.entry("update", new UpdateFunction()));
+ *
* @return The modified configuration, to allow chaining of methods.
*/
@SafeVarargs
@@ -288,19 +291,19 @@ public class ExpressionConfiguration {
Map constants = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
- constants.put("TRUE", new EvaluationValue(true));
- constants.put("FALSE", new EvaluationValue(false));
+ constants.put("TRUE", EvaluationValue.booleanValue(true));
+ constants.put("FALSE", EvaluationValue.booleanValue(false));
constants.put(
"PI",
- new EvaluationValue(
+ EvaluationValue.numberValue(
new BigDecimal(
"3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679")));
constants.put(
"E",
- new EvaluationValue(
+ EvaluationValue.numberValue(
new BigDecimal(
"2.71828182845904523536028747135266249775724709369995957496696762772407663")));
- constants.put("NULL", new EvaluationValue(null));
+ constants.put("NULL", EvaluationValue.nullValue());
return constants;
}
diff --git a/src/main/java/com/ezylang/evalex/data/DefaultEvaluationValueConverter.java b/src/main/java/com/ezylang/evalex/data/DefaultEvaluationValueConverter.java
new file mode 100644
index 0000000..b05fcd3
--- /dev/null
+++ b/src/main/java/com/ezylang/evalex/data/DefaultEvaluationValueConverter.java
@@ -0,0 +1,88 @@
+/*
+ Copyright 2012-2023 Udo Klimaschewski
+
+ 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 com.ezylang.evalex.data;
+
+import com.ezylang.evalex.config.ExpressionConfiguration;
+import com.ezylang.evalex.data.conversion.*;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * The default implementation of the {@link EvaluationValueConverterIfc}, used in the standard
+ * configuration.
+ *
+ *
+ *
+ * | Input type | Converter used |
+ *
+ * | BigDecimal | NumberConverter |
+ * | Long, long | NumberConverter |
+ * | Integer, int | NumberConverter |
+ * | Short, short | NumberConverter |
+ * | Byte, byte | NumberConverter |
+ * | Double, double | NumberConverter * |
+ * | Float, float | NumberConverter * |
+ * | CharSequence , String | StringConverter |
+ * | Boolean, boolean | BooleanConverter |
+ * | Instant | DateTimeConverter |
+ * | Date | DateTimeConverter |
+ * | Calendar | DateTimeConverter |
+ * | ZonedDateTime | DateTimeConverter |
+ * | LocalDate | DateTimeConverter - the configured zone id will be used for conversion |
+ * | LocalDateTime | DateTimeConverter - the configured zone id will be used for conversion |
+ * | OffsetDateTime | DateTimeConverter |
+ * | Duration | DurationConverter |
+ * | ASTNode | ASTNode |
+ * | List<?> | ArrayConverter - each entry will be converted |
+ * | Map<?,?> | StructureConverter - each entry will be converted. |
+ *
+ *
+ * * Be careful with conversion problems when using float or double, which are fractional
+ * numbers. A (float)0.1 is e.g. converted to 0.10000000149011612
+ */
+public class DefaultEvaluationValueConverter implements EvaluationValueConverterIfc {
+
+ static List converters =
+ Arrays.asList(
+ new NumberConverter(),
+ new StringConverter(),
+ new BooleanConverter(),
+ new DateTimeConverter(),
+ new DurationConverter(),
+ new ExpressionNodeConverter(),
+ new ArrayConverter(),
+ new StructureConverter());
+
+ public EvaluationValue convertObject(Object object, ExpressionConfiguration configuration) {
+
+ if (object == null) {
+ return EvaluationValue.nullValue();
+ }
+
+ if (object instanceof EvaluationValue) {
+ return (EvaluationValue) object;
+ }
+
+ for (ConverterIfc converter : converters) {
+ if (converter.canConvert(object)) {
+ return converter.convert(object, configuration);
+ }
+ }
+
+ throw new IllegalArgumentException(
+ "Unsupported data type '" + object.getClass().getName() + "'");
+ }
+}
diff --git a/src/main/java/com/ezylang/evalex/data/EvaluationValue.java b/src/main/java/com/ezylang/evalex/data/EvaluationValue.java
index b3d5307..fd21a29 100644
--- a/src/main/java/com/ezylang/evalex/data/EvaluationValue.java
+++ b/src/main/java/com/ezylang/evalex/data/EvaluationValue.java
@@ -15,13 +15,17 @@
*/
package com.ezylang.evalex.data;
+import com.ezylang.evalex.config.ExpressionConfiguration;
import com.ezylang.evalex.parser.ASTNode;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
-import java.time.*;
-import java.util.*;
-import java.util.Map.Entry;
+import java.time.DateTimeException;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
import lombok.Value;
/**
@@ -74,147 +78,146 @@ public class EvaluationValue implements Comparable {
DataType dataType;
/**
- * Creates a new evaluation value by taking a good guess on the provided Java class and converting
- * it to one of the supported types.
- *
- *
- *
- * | Input type | Storage Type |
- *
- * | BigDecimal | BigDecimal |
- * | Long, long | BigDecimal |
- * | Integer, int | BigDecimal |
- * | Short, short | BigDecimal |
- * | Byte, byte | BigDecimal |
- * | Double, double | BigDecimal * |
- * | Float, float | BigDecimal * |
- * | CharSequence , String | String |
- * | Boolean, boolean | Boolean |
- * | Instant, instant | Instant |
- * | ZonedDateTime, zonedDateTime | Instant |
- * | LocalDate, localDate | Instant |
- * | OffsetDateTime, offsetDateTime | Instant |
- * | Duration, duration | Duration |
- * | ASTNode | ASTNode |
- * | List<?> | List<EvaluationValue> - each entry will be converted |
- * | Map<?,?> | Map<String><EvaluationValue> - each entry will be converted. |
- *
- *
- * * Be careful with conversion problems when using float or double, which are fractional
- * numbers. A (float)0.1 is e.g. converted to 0.10000000149011612
+ * Creates a new evaluation value by using the default converter and configuration.
*
- * @param value One of the supported data types.
+ * @param value Any object that the default converter can convert.
* @throws IllegalArgumentException if the data type can't be mapped.
+ * @see DefaultEvaluationValueConverter
+ * @deprecated Use {@link EvaluationValue(Object, ExpressionConfiguration)} instead.
*/
+ @Deprecated(since = "3.1.0", forRemoval = true)
public EvaluationValue(Object value) {
- BigDecimal number = convertToBigDecimal(value);
- if (number != null) {
- this.dataType = DataType.NUMBER;
- this.value = number;
- } else if (value == null) {
- this.dataType = DataType.NULL;
- this.value = null;
- } else if (value instanceof CharSequence) {
- this.dataType = DataType.STRING;
- this.value = ((CharSequence) value).toString();
- } else if (value instanceof Character) {
- this.dataType = DataType.STRING;
- this.value = ((Character) value).toString();
- } else if (value instanceof Boolean) {
- this.dataType = DataType.BOOLEAN;
- this.value = value;
- } else if (value instanceof Instant) {
- this.dataType = DataType.DATE_TIME;
- this.value = value;
- } else if (value instanceof ZonedDateTime) {
- this.dataType = DataType.DATE_TIME;
- this.value = ((ZonedDateTime) value).toInstant();
- } else if (value instanceof OffsetDateTime) {
- this.dataType = DataType.DATE_TIME;
- this.value = ((OffsetDateTime) value).toInstant();
- } else if (value instanceof LocalDate) {
- this.dataType = DataType.DATE_TIME;
- this.value = ((LocalDate) value).atStartOfDay().atOffset(ZoneOffset.UTC).toInstant();
- } else if (value instanceof Duration) {
- this.dataType = DataType.DURATION;
- this.value = value;
- } else if (value instanceof ASTNode) {
- this.dataType = DataType.EXPRESSION_NODE;
- this.value = value;
- } else if (value instanceof List) {
- this.dataType = DataType.ARRAY;
- this.value = convertToList((List>) value);
- } else if (value instanceof Map) {
- this.dataType = DataType.STRUCTURE;
- this.value = convertMapStructure((Map, ?>) value);
- } else if (value instanceof EvaluationValue) {
- this.dataType = ((EvaluationValue) value).getDataType();
- this.value = ((EvaluationValue) value).getValue();
- } else {
- throw new IllegalArgumentException(
- "Unsupported data type '" + value.getClass().getName() + "'");
- }
+ this(value, ExpressionConfiguration.defaultConfiguration());
}
- public EvaluationValue(double value, MathContext mathContext) {
- this.dataType = DataType.NUMBER;
- this.value = new BigDecimal(Double.toString(value), mathContext);
+ /**
+ * Creates a new evaluation value by using the configured converter and configuration.
+ *
+ * @param value One of the supported data types.
+ * @param configuration The expression configuration to use.
+ * @throws IllegalArgumentException if the data type can't be mapped.
+ * @see ExpressionConfiguration#getEvaluationValueConverter()
+ */
+ public EvaluationValue(Object value, ExpressionConfiguration configuration) {
+
+ EvaluationValue converted =
+ configuration.getEvaluationValueConverter().convertObject(value, configuration);
+
+ this.value = converted.getValue();
+ this.dataType = converted.getDataType();
}
- public EvaluationValue(LocalDateTime value, ZoneId zoneId) {
- this.dataType = DataType.DATE_TIME;
- this.value = value.atZone(zoneId).toInstant();
+ /**
+ * Private constructor to directly create an instance with a given type and value.
+ *
+ * @param value The value to set, no conversion will be done.
+ * @param dataType The data type to set.
+ */
+ private EvaluationValue(Object value, DataType dataType) {
+ this.dataType = dataType;
+ this.value = value;
}
/**
- * Converts a {@link Map} of objects to a {@link Map} of {@link EvaluationValue} values.
+ * Creates a new null value.
*
- * @return A {@link Map} of {@link EvaluationValue} values.
+ * @return A new null value.
*/
- private Map convertMapStructure(Map, ?> value) {
- Map structure = new HashMap<>();
- for (Entry, ?> entry : value.entrySet()) {
- String name = entry.getKey().toString();
- structure.put(name, new EvaluationValue(entry.getValue()));
- }
- return structure;
+ public static EvaluationValue nullValue() {
+ return new EvaluationValue(null, DataType.NULL);
}
/**
- * Converts a {@link List} of objects to a {@link List} of {@link EvaluationValue} values.
+ * Creates a new number value.
*
- * @return A {@link List} of {@link EvaluationValue} values.
+ * @param value The BigDecimal value to use.
+ * @return the new number value.
*/
- private List convertToList(List> value) {
- List array = new ArrayList<>();
- value.forEach(element -> array.add(new EvaluationValue(element)));
- return array;
+ public static EvaluationValue numberValue(BigDecimal value) {
+ return new EvaluationValue(value, DataType.NUMBER);
}
/**
- * Check and convert, if an {@link Object} can be converted to a {@link BigDecimal} value.
+ * Creates a new string value.
*
- * @return A {@link BigDecimal} value of the object, or null if it can't be
- * converted.
+ * @param value The String value to use.
+ * @return the new string value.
*/
- private BigDecimal convertToBigDecimal(Object value) {
- if (value instanceof BigDecimal) {
- return (BigDecimal) value;
- } else if (value instanceof Double) {
- return BigDecimal.valueOf((double) value);
- } else if (value instanceof Float) {
- return BigDecimal.valueOf((float) value);
- } else if (value instanceof Integer) {
- return BigDecimal.valueOf((int) value);
- } else if (value instanceof Long) {
- return BigDecimal.valueOf((long) value);
- } else if (value instanceof Short) {
- return BigDecimal.valueOf((short) value);
- } else if (value instanceof Byte) {
- return BigDecimal.valueOf((byte) value);
- } else {
- return null;
- }
+ public static EvaluationValue stringValue(String value) {
+ return new EvaluationValue(value, DataType.STRING);
+ }
+
+ /**
+ * Creates a new boolean value.
+ *
+ * @param value The Boolean value to use.
+ * @return the new boolean value.
+ */
+ public static EvaluationValue booleanValue(Boolean value) {
+ return new EvaluationValue(value, DataType.BOOLEAN);
+ }
+
+ /**
+ * Creates a new date-time value.
+ *
+ * @param value The Instant value to use.
+ * @return the new date-time value.
+ */
+ public static EvaluationValue dateTimeValue(Instant value) {
+ return new EvaluationValue(value, DataType.DATE_TIME);
+ }
+
+ /**
+ * Creates a new duration value.
+ *
+ * @param value The Duration value to use.
+ * @return the new duration value.
+ */
+ public static EvaluationValue durationValue(Duration value) {
+ return new EvaluationValue(value, DataType.DURATION);
+ }
+
+ /**
+ * Creates a new expression node value.
+ *
+ * @param value The ASTNode value to use.
+ * @return the new expression node value.
+ */
+ public static EvaluationValue expressionNodeValue(ASTNode value) {
+ return new EvaluationValue(value, DataType.EXPRESSION_NODE);
+ }
+
+ /**
+ * Creates a new array value.
+ *
+ * @param value The List value to use.
+ * @return the new array value.
+ */
+ public static EvaluationValue arrayValue(List> value) {
+ return new EvaluationValue(value, DataType.ARRAY);
+ }
+
+ /**
+ * Creates a new structure value.
+ *
+ * @param value The Map value to use.
+ * @return the new structure value.
+ */
+ public static EvaluationValue structureValue(Map, ?> value) {
+ return new EvaluationValue(value, DataType.STRUCTURE);
+ }
+
+ /**
+ * Creates a new evaluation value from a double value using the specified {@link MathContext}.
+ *
+ * @param value The double value.
+ * @param mathContext The math context to use.
+ * @deprecated since 3.1.0 - Use {@link EvaluationValue(Object, ExpressionConfiguration)}.
+ */
+ @Deprecated(since = "3.1.0", forRemoval = true)
+ public EvaluationValue(double value, MathContext mathContext) {
+ this.dataType = DataType.NUMBER;
+ this.value = new BigDecimal(Double.toString(value), mathContext);
}
/**
@@ -301,9 +304,9 @@ public class EvaluationValue implements Comparable {
public static EvaluationValue numberOfString(String value, MathContext mathContext) {
if (value.startsWith("0x") || value.startsWith("0X")) {
BigInteger hexToInteger = new BigInteger(value.substring(2), 16);
- return new EvaluationValue(new BigDecimal(hexToInteger, mathContext));
+ return EvaluationValue.numberValue(new BigDecimal(hexToInteger, mathContext));
} else {
- return new EvaluationValue(new BigDecimal(value, mathContext));
+ return EvaluationValue.numberValue(new BigDecimal(value, mathContext));
}
}
diff --git a/src/main/java/com/ezylang/evalex/data/EvaluationValueConverterIfc.java b/src/main/java/com/ezylang/evalex/data/EvaluationValueConverterIfc.java
new file mode 100644
index 0000000..b671860
--- /dev/null
+++ b/src/main/java/com/ezylang/evalex/data/EvaluationValueConverterIfc.java
@@ -0,0 +1,35 @@
+/*
+ Copyright 2012-2023 Udo Klimaschewski
+
+ 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 com.ezylang.evalex.data;
+
+import com.ezylang.evalex.config.ExpressionConfiguration;
+
+/**
+ * Converter interface to be implemented by configurable evaluation value converters. Converts an
+ * arbitrary object to an {@link EvaluationValue}, using the specified configuration.
+ */
+public interface EvaluationValueConverterIfc {
+
+ /**
+ * Called whenever an object has to be converted to an {@link EvaluationValue}.
+ *
+ * @param object The object holding the value.
+ * @param configuration The configuration to use.
+ * @return The converted {@link EvaluationValue}.
+ * @throws IllegalArgumentException if the object can't be converted.
+ */
+ EvaluationValue convertObject(Object object, ExpressionConfiguration configuration);
+}
diff --git a/src/main/java/com/ezylang/evalex/data/conversion/ArrayConverter.java b/src/main/java/com/ezylang/evalex/data/conversion/ArrayConverter.java
new file mode 100644
index 0000000..016f2ed
--- /dev/null
+++ b/src/main/java/com/ezylang/evalex/data/conversion/ArrayConverter.java
@@ -0,0 +1,37 @@
+/*
+ Copyright 2012-2023 Udo Klimaschewski
+
+ 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 com.ezylang.evalex.data.conversion;
+
+import com.ezylang.evalex.config.ExpressionConfiguration;
+import com.ezylang.evalex.data.EvaluationValue;
+import java.util.ArrayList;
+import java.util.List;
+
+/** Converter to convert to the ARRAY data type. */
+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)));
+
+ return EvaluationValue.arrayValue(array);
+ }
+
+ @Override
+ public boolean canConvert(Object object) {
+ return object instanceof List;
+ }
+}
diff --git a/src/main/java/com/ezylang/evalex/data/conversion/BooleanConverter.java b/src/main/java/com/ezylang/evalex/data/conversion/BooleanConverter.java
new file mode 100644
index 0000000..143f8cd
--- /dev/null
+++ b/src/main/java/com/ezylang/evalex/data/conversion/BooleanConverter.java
@@ -0,0 +1,32 @@
+/*
+ Copyright 2012-2023 Udo Klimaschewski
+
+ 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 com.ezylang.evalex.data.conversion;
+
+import com.ezylang.evalex.config.ExpressionConfiguration;
+import com.ezylang.evalex.data.EvaluationValue;
+
+/** Converter to convert to the BOOLEAN data type. */
+public class BooleanConverter implements ConverterIfc {
+ @Override
+ public EvaluationValue convert(Object object, ExpressionConfiguration configuration) {
+ return EvaluationValue.booleanValue((Boolean) object);
+ }
+
+ @Override
+ public boolean canConvert(Object object) {
+ return object instanceof Boolean;
+ }
+}
diff --git a/src/main/java/com/ezylang/evalex/data/conversion/ConverterIfc.java b/src/main/java/com/ezylang/evalex/data/conversion/ConverterIfc.java
new file mode 100644
index 0000000..6b01b17
--- /dev/null
+++ b/src/main/java/com/ezylang/evalex/data/conversion/ConverterIfc.java
@@ -0,0 +1,47 @@
+/*
+ Copyright 2012-2023 Udo Klimaschewski
+
+ 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 com.ezylang.evalex.data.conversion;
+
+import com.ezylang.evalex.config.ExpressionConfiguration;
+import com.ezylang.evalex.data.EvaluationValue;
+
+/**
+ * Converter interface used by the {@link com.ezylang.evalex.data.DefaultEvaluationValueConverter}.
+ */
+public interface ConverterIfc {
+
+ /**
+ * Called to convert a previously checked data type.
+ *
+ * @param object The object to convert.
+ * @param configuration The current expression configuration.
+ * @return The converted value.
+ */
+ EvaluationValue convert(Object object, ExpressionConfiguration configuration);
+
+ /**
+ * Checks, if a given object can be converted by this converter.
+ *
+ * @param object The object to convert.
+ * @return true if the object can be converted, false otherwise.
+ */
+ boolean canConvert(Object object);
+
+ default IllegalArgumentException illegalArgument(Object object) {
+ return new IllegalArgumentException(
+ "Unsupported data type '" + object.getClass().getName() + "'");
+ }
+}
diff --git a/src/main/java/com/ezylang/evalex/data/conversion/DateTimeConverter.java b/src/main/java/com/ezylang/evalex/data/conversion/DateTimeConverter.java
new file mode 100644
index 0000000..95278db
--- /dev/null
+++ b/src/main/java/com/ezylang/evalex/data/conversion/DateTimeConverter.java
@@ -0,0 +1,62 @@
+/*
+ Copyright 2012-2023 Udo Klimaschewski
+
+ 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 com.ezylang.evalex.data.conversion;
+
+import com.ezylang.evalex.config.ExpressionConfiguration;
+import com.ezylang.evalex.data.EvaluationValue;
+import java.time.*;
+import java.util.Calendar;
+import java.util.Date;
+
+/** Converter to convert to the DATE_TIME data type. */
+public class DateTimeConverter implements ConverterIfc {
+
+ @Override
+ public EvaluationValue convert(Object object, ExpressionConfiguration configuration) {
+
+ Instant instant;
+
+ if (object instanceof Instant) {
+ instant = (Instant) object;
+ } else if (object instanceof ZonedDateTime) {
+ instant = ((ZonedDateTime) object).toInstant();
+ } else if (object instanceof OffsetDateTime) {
+ instant = ((OffsetDateTime) object).toInstant();
+ } else if (object instanceof LocalDate) {
+ instant = ((LocalDate) object).atStartOfDay().atZone(configuration.getZoneId()).toInstant();
+ } else if (object instanceof LocalDateTime) {
+ instant = ((LocalDateTime) object).atZone(configuration.getZoneId()).toInstant();
+ } else if (object instanceof Date) {
+ instant = ((Date) object).toInstant();
+ } else if (object instanceof Calendar) {
+ instant = ((Calendar) object).toInstant();
+ } else {
+ throw illegalArgument(object);
+ }
+ return EvaluationValue.dateTimeValue(instant);
+ }
+
+ @Override
+ public boolean canConvert(Object object) {
+ return (object instanceof Instant
+ || object instanceof ZonedDateTime
+ || object instanceof OffsetDateTime
+ || object instanceof LocalDate
+ || object instanceof LocalDateTime
+ || object instanceof Date
+ || object instanceof Calendar);
+ }
+}
diff --git a/src/main/java/com/ezylang/evalex/data/conversion/DurationConverter.java b/src/main/java/com/ezylang/evalex/data/conversion/DurationConverter.java
new file mode 100644
index 0000000..43a95b5
--- /dev/null
+++ b/src/main/java/com/ezylang/evalex/data/conversion/DurationConverter.java
@@ -0,0 +1,33 @@
+/*
+ Copyright 2012-2023 Udo Klimaschewski
+
+ 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 com.ezylang.evalex.data.conversion;
+
+import com.ezylang.evalex.config.ExpressionConfiguration;
+import com.ezylang.evalex.data.EvaluationValue;
+import java.time.Duration;
+
+/** Converter to convert to the DURATION data type. */
+public class DurationConverter implements ConverterIfc {
+ @Override
+ public EvaluationValue convert(Object object, ExpressionConfiguration configuration) {
+ return EvaluationValue.durationValue((Duration) object);
+ }
+
+ @Override
+ public boolean canConvert(Object object) {
+ return object instanceof Duration;
+ }
+}
diff --git a/src/main/java/com/ezylang/evalex/data/conversion/ExpressionNodeConverter.java b/src/main/java/com/ezylang/evalex/data/conversion/ExpressionNodeConverter.java
new file mode 100644
index 0000000..9222819
--- /dev/null
+++ b/src/main/java/com/ezylang/evalex/data/conversion/ExpressionNodeConverter.java
@@ -0,0 +1,33 @@
+/*
+ Copyright 2012-2023 Udo Klimaschewski
+
+ 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 com.ezylang.evalex.data.conversion;
+
+import com.ezylang.evalex.config.ExpressionConfiguration;
+import com.ezylang.evalex.data.EvaluationValue;
+import com.ezylang.evalex.parser.ASTNode;
+
+/** Converter to convert to the EXPRESSION_NODE data type. */
+public class ExpressionNodeConverter implements ConverterIfc {
+ @Override
+ public EvaluationValue convert(Object object, ExpressionConfiguration configuration) {
+ return EvaluationValue.expressionNodeValue((ASTNode) object);
+ }
+
+ @Override
+ public boolean canConvert(Object object) {
+ return object instanceof ASTNode;
+ }
+}
diff --git a/src/main/java/com/ezylang/evalex/data/conversion/NumberConverter.java b/src/main/java/com/ezylang/evalex/data/conversion/NumberConverter.java
new file mode 100644
index 0000000..e73d51a
--- /dev/null
+++ b/src/main/java/com/ezylang/evalex/data/conversion/NumberConverter.java
@@ -0,0 +1,60 @@
+/*
+ Copyright 2012-2023 Udo Klimaschewski
+
+ 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 com.ezylang.evalex.data.conversion;
+
+import com.ezylang.evalex.config.ExpressionConfiguration;
+import com.ezylang.evalex.data.EvaluationValue;
+import java.math.BigDecimal;
+
+/** Converter to convert to the NUMBER data type. */
+public class NumberConverter implements ConverterIfc {
+
+ @Override
+ public EvaluationValue convert(Object object, ExpressionConfiguration configuration) {
+ BigDecimal bigDecimal;
+
+ if (object instanceof BigDecimal) {
+ bigDecimal = (BigDecimal) object;
+ } else if (object instanceof Double) {
+ bigDecimal = new BigDecimal(Double.toString((double) object), configuration.getMathContext());
+ } else if (object instanceof Float) {
+ bigDecimal = BigDecimal.valueOf((float) object);
+ } else if (object instanceof Integer) {
+ bigDecimal = BigDecimal.valueOf((int) object);
+ } else if (object instanceof Long) {
+ bigDecimal = BigDecimal.valueOf((long) object);
+ } else if (object instanceof Short) {
+ bigDecimal = BigDecimal.valueOf((short) object);
+ } else if (object instanceof Byte) {
+ bigDecimal = BigDecimal.valueOf((byte) object);
+ } else {
+ throw illegalArgument(object);
+ }
+
+ return EvaluationValue.numberValue(bigDecimal);
+ }
+
+ @Override
+ public boolean canConvert(Object object) {
+ return (object instanceof BigDecimal
+ || object instanceof Double
+ || object instanceof Float
+ || object instanceof Integer
+ || object instanceof Long
+ || object instanceof Short
+ || object instanceof Byte);
+ }
+}
diff --git a/src/main/java/com/ezylang/evalex/data/conversion/StringConverter.java b/src/main/java/com/ezylang/evalex/data/conversion/StringConverter.java
new file mode 100644
index 0000000..636a65b
--- /dev/null
+++ b/src/main/java/com/ezylang/evalex/data/conversion/StringConverter.java
@@ -0,0 +1,43 @@
+/*
+ Copyright 2012-2023 Udo Klimaschewski
+
+ 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 com.ezylang.evalex.data.conversion;
+
+import com.ezylang.evalex.config.ExpressionConfiguration;
+import com.ezylang.evalex.data.EvaluationValue;
+
+/** Converter to convert to the STRING data type. */
+public class StringConverter implements ConverterIfc {
+
+ @Override
+ public EvaluationValue convert(Object object, ExpressionConfiguration configuration) {
+ String string;
+
+ if (object instanceof CharSequence) {
+ string = ((CharSequence) object).toString();
+ } else if (object instanceof Character) {
+ string = ((Character) object).toString();
+ } else {
+ throw illegalArgument(object);
+ }
+
+ return EvaluationValue.stringValue(string);
+ }
+
+ @Override
+ public boolean canConvert(Object object) {
+ return (object instanceof CharSequence || object instanceof Character);
+ }
+}
diff --git a/src/main/java/com/ezylang/evalex/data/conversion/StructureConverter.java b/src/main/java/com/ezylang/evalex/data/conversion/StructureConverter.java
new file mode 100644
index 0000000..e8d0330
--- /dev/null
+++ b/src/main/java/com/ezylang/evalex/data/conversion/StructureConverter.java
@@ -0,0 +1,39 @@
+/*
+ Copyright 2012-2023 Udo Klimaschewski
+
+ 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 com.ezylang.evalex.data.conversion;
+
+import com.ezylang.evalex.config.ExpressionConfiguration;
+import com.ezylang.evalex.data.EvaluationValue;
+import java.util.HashMap;
+import java.util.Map;
+
+/** Converter to convert to the STRUCTURE data type. */
+public class StructureConverter implements ConverterIfc {
+ @Override
+ public EvaluationValue convert(Object object, ExpressionConfiguration configuration) {
+ Map structure = new HashMap<>();
+ for (Map.Entry, ?> entry : ((Map, ?>) object).entrySet()) {
+ String name = entry.getKey().toString();
+ structure.put(name, new EvaluationValue(entry.getValue(), configuration));
+ }
+ return EvaluationValue.structureValue(structure);
+ }
+
+ @Override
+ public boolean canConvert(Object object) {
+ return object instanceof Map;
+ }
+}
diff --git a/src/main/java/com/ezylang/evalex/functions/basic/AbsFunction.java b/src/main/java/com/ezylang/evalex/functions/basic/AbsFunction.java
index 18302ce..a1db7c5 100644
--- a/src/main/java/com/ezylang/evalex/functions/basic/AbsFunction.java
+++ b/src/main/java/com/ezylang/evalex/functions/basic/AbsFunction.java
@@ -29,7 +29,7 @@ public class AbsFunction extends AbstractFunction {
public EvaluationValue evaluate(
Expression expression, Token functionToken, EvaluationValue... parameterValues) {
- return new EvaluationValue(
+ return expression.convertValue(
parameterValues[0].getNumberValue().abs(expression.getConfiguration().getMathContext()));
}
}
diff --git a/src/main/java/com/ezylang/evalex/functions/basic/CeilingFunction.java b/src/main/java/com/ezylang/evalex/functions/basic/CeilingFunction.java
index 02db39c..ff87b36 100644
--- a/src/main/java/com/ezylang/evalex/functions/basic/CeilingFunction.java
+++ b/src/main/java/com/ezylang/evalex/functions/basic/CeilingFunction.java
@@ -31,6 +31,6 @@ public class CeilingFunction extends AbstractFunction {
EvaluationValue value = parameterValues[0];
- return new EvaluationValue(value.getNumberValue().setScale(0, RoundingMode.CEILING));
+ return expression.convertValue(value.getNumberValue().setScale(0, RoundingMode.CEILING));
}
}
diff --git a/src/main/java/com/ezylang/evalex/functions/basic/FactFunction.java b/src/main/java/com/ezylang/evalex/functions/basic/FactFunction.java
index aff60a5..eb25349 100644
--- a/src/main/java/com/ezylang/evalex/functions/basic/FactFunction.java
+++ b/src/main/java/com/ezylang/evalex/functions/basic/FactFunction.java
@@ -37,6 +37,6 @@ public class FactFunction extends AbstractFunction {
new BigDecimal(i, expression.getConfiguration().getMathContext()),
expression.getConfiguration().getMathContext());
}
- return new EvaluationValue(factorial);
+ return expression.convertValue(factorial);
}
}
diff --git a/src/main/java/com/ezylang/evalex/functions/basic/FloorFunction.java b/src/main/java/com/ezylang/evalex/functions/basic/FloorFunction.java
index edfde3e..65131c5 100644
--- a/src/main/java/com/ezylang/evalex/functions/basic/FloorFunction.java
+++ b/src/main/java/com/ezylang/evalex/functions/basic/FloorFunction.java
@@ -31,6 +31,6 @@ public class FloorFunction extends AbstractFunction {
EvaluationValue value = parameterValues[0];
- return new EvaluationValue(value.getNumberValue().setScale(0, RoundingMode.FLOOR));
+ return expression.convertValue(value.getNumberValue().setScale(0, RoundingMode.FLOOR));
}
}
diff --git a/src/main/java/com/ezylang/evalex/functions/basic/MaxFunction.java b/src/main/java/com/ezylang/evalex/functions/basic/MaxFunction.java
index 3a87a6a..b4c5ee6 100644
--- a/src/main/java/com/ezylang/evalex/functions/basic/MaxFunction.java
+++ b/src/main/java/com/ezylang/evalex/functions/basic/MaxFunction.java
@@ -34,6 +34,6 @@ public class MaxFunction extends AbstractFunction {
max = parameter.getNumberValue();
}
}
- return new EvaluationValue(max);
+ return expression.convertValue(max);
}
}
diff --git a/src/main/java/com/ezylang/evalex/functions/basic/MinFunction.java b/src/main/java/com/ezylang/evalex/functions/basic/MinFunction.java
index bbbb41e..8b13d4f 100644
--- a/src/main/java/com/ezylang/evalex/functions/basic/MinFunction.java
+++ b/src/main/java/com/ezylang/evalex/functions/basic/MinFunction.java
@@ -34,6 +34,6 @@ public class MinFunction extends AbstractFunction {
min = parameter.getNumberValue();
}
}
- return new EvaluationValue(min);
+ return expression.convertValue(min);
}
}
diff --git a/src/main/java/com/ezylang/evalex/functions/basic/NotFunction.java b/src/main/java/com/ezylang/evalex/functions/basic/NotFunction.java
index 46bee3b..9206411 100644
--- a/src/main/java/com/ezylang/evalex/functions/basic/NotFunction.java
+++ b/src/main/java/com/ezylang/evalex/functions/basic/NotFunction.java
@@ -31,6 +31,6 @@ public class NotFunction extends AbstractFunction {
boolean result = parameterValues[0].getBooleanValue();
- return new EvaluationValue(!result);
+ return expression.convertValue(!result);
}
}
diff --git a/src/main/java/com/ezylang/evalex/functions/basic/RoundFunction.java b/src/main/java/com/ezylang/evalex/functions/basic/RoundFunction.java
index 1d2c0e9..6970c40 100644
--- a/src/main/java/com/ezylang/evalex/functions/basic/RoundFunction.java
+++ b/src/main/java/com/ezylang/evalex/functions/basic/RoundFunction.java
@@ -35,7 +35,7 @@ public class RoundFunction extends AbstractFunction {
EvaluationValue value = parameterValues[0];
EvaluationValue precision = parameterValues[1];
- return new EvaluationValue(
+ return expression.convertValue(
value
.getNumberValue()
.setScale(
diff --git a/src/main/java/com/ezylang/evalex/functions/basic/SqrtFunction.java b/src/main/java/com/ezylang/evalex/functions/basic/SqrtFunction.java
index ef91138..ffe4ecc 100644
--- a/src/main/java/com/ezylang/evalex/functions/basic/SqrtFunction.java
+++ b/src/main/java/com/ezylang/evalex/functions/basic/SqrtFunction.java
@@ -40,7 +40,7 @@ public class SqrtFunction extends AbstractFunction {
MathContext mathContext = expression.getConfiguration().getMathContext();
if (x.compareTo(BigDecimal.ZERO) == 0) {
- return new EvaluationValue(BigDecimal.ZERO);
+ return expression.convertValue(BigDecimal.ZERO);
}
BigInteger n = x.movePointRight(mathContext.getPrecision() << 1).toBigInteger();
@@ -56,6 +56,6 @@ public class SqrtFunction extends AbstractFunction {
test = ix.subtract(ixPrev).abs();
} while (test.compareTo(BigInteger.ZERO) != 0 && test.compareTo(BigInteger.ONE) != 0);
- return new EvaluationValue(new BigDecimal(ix, mathContext.getPrecision()));
+ return expression.convertValue(new BigDecimal(ix, mathContext.getPrecision()));
}
}
diff --git a/src/main/java/com/ezylang/evalex/functions/basic/SumFunction.java b/src/main/java/com/ezylang/evalex/functions/basic/SumFunction.java
index 9010c2d..38817b0 100644
--- a/src/main/java/com/ezylang/evalex/functions/basic/SumFunction.java
+++ b/src/main/java/com/ezylang/evalex/functions/basic/SumFunction.java
@@ -32,6 +32,6 @@ public class SumFunction extends AbstractFunction {
for (EvaluationValue parameter : parameterValues) {
sum = sum.add(parameter.getNumberValue(), expression.getConfiguration().getMathContext());
}
- return new EvaluationValue(sum);
+ return expression.convertValue(sum);
}
}
diff --git a/src/main/java/com/ezylang/evalex/functions/datetime/AbstractDateTimeParseFunction.java b/src/main/java/com/ezylang/evalex/functions/datetime/AbstractDateTimeParseFunction.java
index 3a396ef..eefe27f 100644
--- a/src/main/java/com/ezylang/evalex/functions/datetime/AbstractDateTimeParseFunction.java
+++ b/src/main/java/com/ezylang/evalex/functions/datetime/AbstractDateTimeParseFunction.java
@@ -26,7 +26,7 @@ public abstract class AbstractDateTimeParseFunction extends AbstractFunction {
@Override
public EvaluationValue evaluate(
Expression expression, Token functionToken, EvaluationValue... parameterValues) {
- ZoneId zoneId = expression.getConfiguration().getDefaultZoneId();
+ ZoneId zoneId = expression.getConfiguration().getZoneId();
Instant instant;
if (parameterValues.length < 2) {
@@ -35,7 +35,7 @@ public abstract class AbstractDateTimeParseFunction extends AbstractFunction {
instant =
parse(parameterValues[0].getStringValue(), parameterValues[1].getStringValue(), zoneId);
}
- return new EvaluationValue(instant);
+ return expression.convertValue(instant);
}
protected abstract Instant parse(String value, String format, ZoneId zoneId);
diff --git a/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeFormatFunction.java b/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeFormatFunction.java
index 3596514..640a516 100644
--- a/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeFormatFunction.java
+++ b/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeFormatFunction.java
@@ -29,7 +29,7 @@ public class DateTimeFormatFunction extends AbstractFunction {
public EvaluationValue evaluate(
Expression expression, Token functionToken, EvaluationValue... parameterValues) {
String formatted;
- ZoneId zoneId = expression.getConfiguration().getDefaultZoneId();
+ ZoneId zoneId = expression.getConfiguration().getZoneId();
if (parameterValues.length < 2) {
formatted = parameterValues[0].getDateTimeValue().atZone(zoneId).toLocalDateTime().toString();
} else {
@@ -38,6 +38,6 @@ public class DateTimeFormatFunction extends AbstractFunction {
formatted =
parameterValues[0].getDateTimeValue().atZone(zoneId).toLocalDateTime().format(formatter);
}
- return new EvaluationValue(formatted);
+ return expression.convertValue(formatted);
}
}
diff --git a/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeFromEpochFunction.java b/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeFromEpochFunction.java
index 6432156..a0465e4 100644
--- a/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeFromEpochFunction.java
+++ b/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeFromEpochFunction.java
@@ -29,6 +29,6 @@ public class DateTimeFromEpochFunction extends AbstractFunction {
public EvaluationValue evaluate(
Expression expression, Token functionToken, EvaluationValue... parameterValues) {
BigDecimal millis = parameterValues[0].getNumberValue();
- return new EvaluationValue(Instant.ofEpochMilli(millis.longValue()));
+ return expression.convertValue(Instant.ofEpochMilli(millis.longValue()));
}
}
diff --git a/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeFunction.java b/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeFunction.java
index 56e1e25..935a548 100644
--- a/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeFunction.java
+++ b/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeFunction.java
@@ -36,8 +36,8 @@ public class DateTimeFunction extends AbstractFunction {
int second = parameterValues.length >= 6 ? parameterValues[5].getNumberValue().intValue() : 0;
int nanoOfs = parameterValues.length >= 7 ? parameterValues[6].getNumberValue().intValue() : 0;
- ZoneId zoneId = expression.getConfiguration().getDefaultZoneId();
- return new EvaluationValue(
+ ZoneId zoneId = expression.getConfiguration().getZoneId();
+ return expression.convertValue(
LocalDateTime.of(year, month, day, hour, minute, second, nanoOfs)
.atZone(zoneId)
.toInstant());
diff --git a/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeToEpochFunction.java b/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeToEpochFunction.java
index 2ee4f2e..7728913 100644
--- a/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeToEpochFunction.java
+++ b/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeToEpochFunction.java
@@ -26,6 +26,6 @@ public class DateTimeToEpochFunction extends AbstractFunction {
@Override
public EvaluationValue evaluate(
Expression expression, Token functionToken, EvaluationValue... parameterValues) {
- return new EvaluationValue(parameterValues[0].getDateTimeValue().toEpochMilli());
+ return expression.convertValue(parameterValues[0].getDateTimeValue().toEpochMilli());
}
}
diff --git a/src/main/java/com/ezylang/evalex/functions/datetime/DurationFromDaysFunction.java b/src/main/java/com/ezylang/evalex/functions/datetime/DurationFromDaysFunction.java
index 95fac80..fb27f18 100644
--- a/src/main/java/com/ezylang/evalex/functions/datetime/DurationFromDaysFunction.java
+++ b/src/main/java/com/ezylang/evalex/functions/datetime/DurationFromDaysFunction.java
@@ -29,6 +29,6 @@ public class DurationFromDaysFunction extends AbstractFunction {
public EvaluationValue evaluate(
Expression expression, Token functionToken, EvaluationValue... parameterValues) {
BigDecimal days = parameterValues[0].getNumberValue();
- return new EvaluationValue(Duration.ofDays(days.longValue()));
+ return expression.convertValue(Duration.ofDays(days.longValue()));
}
}
diff --git a/src/main/java/com/ezylang/evalex/functions/datetime/DurationFromMillisFunction.java b/src/main/java/com/ezylang/evalex/functions/datetime/DurationFromMillisFunction.java
index 2d544f7..c0ed23f 100644
--- a/src/main/java/com/ezylang/evalex/functions/datetime/DurationFromMillisFunction.java
+++ b/src/main/java/com/ezylang/evalex/functions/datetime/DurationFromMillisFunction.java
@@ -29,6 +29,6 @@ public class DurationFromMillisFunction extends AbstractFunction {
public EvaluationValue evaluate(
Expression expression, Token functionToken, EvaluationValue... parameterValues) {
BigDecimal millis = parameterValues[0].getNumberValue();
- return new EvaluationValue(Duration.ofMillis(millis.longValue()));
+ return expression.convertValue(Duration.ofMillis(millis.longValue()));
}
}
diff --git a/src/main/java/com/ezylang/evalex/functions/datetime/DurationParseFunction.java b/src/main/java/com/ezylang/evalex/functions/datetime/DurationParseFunction.java
index c7dc271..a5fda50 100644
--- a/src/main/java/com/ezylang/evalex/functions/datetime/DurationParseFunction.java
+++ b/src/main/java/com/ezylang/evalex/functions/datetime/DurationParseFunction.java
@@ -28,6 +28,6 @@ public class DurationParseFunction extends AbstractFunction {
public EvaluationValue evaluate(
Expression expression, Token functionToken, EvaluationValue... parameterValues) {
String text = parameterValues[0].getStringValue();
- return new EvaluationValue(Duration.parse(text));
+ return expression.convertValue(Duration.parse(text));
}
}
diff --git a/src/main/java/com/ezylang/evalex/functions/string/StringContains.java b/src/main/java/com/ezylang/evalex/functions/string/StringContains.java
index 886ebf0..4ed4c5c 100644
--- a/src/main/java/com/ezylang/evalex/functions/string/StringContains.java
+++ b/src/main/java/com/ezylang/evalex/functions/string/StringContains.java
@@ -30,6 +30,6 @@ public class StringContains extends AbstractFunction {
Expression expression, Token functionToken, EvaluationValue... parameterValues) {
String string = parameterValues[0].getStringValue();
String substring = parameterValues[1].getStringValue();
- return new EvaluationValue(string.toUpperCase().contains(substring.toUpperCase()));
+ return expression.convertValue(string.toUpperCase().contains(substring.toUpperCase()));
}
}
diff --git a/src/main/java/com/ezylang/evalex/functions/string/StringLowerFunction.java b/src/main/java/com/ezylang/evalex/functions/string/StringLowerFunction.java
index a3c7c38..a39fb82 100644
--- a/src/main/java/com/ezylang/evalex/functions/string/StringLowerFunction.java
+++ b/src/main/java/com/ezylang/evalex/functions/string/StringLowerFunction.java
@@ -27,6 +27,6 @@ public class StringLowerFunction extends AbstractFunction {
@Override
public EvaluationValue evaluate(
Expression expression, Token functionToken, EvaluationValue... parameterValues) {
- return new EvaluationValue(parameterValues[0].getStringValue().toLowerCase());
+ return expression.convertValue(parameterValues[0].getStringValue().toLowerCase());
}
}
diff --git a/src/main/java/com/ezylang/evalex/functions/string/StringUpperFunction.java b/src/main/java/com/ezylang/evalex/functions/string/StringUpperFunction.java
index efc223d..09fee04 100644
--- a/src/main/java/com/ezylang/evalex/functions/string/StringUpperFunction.java
+++ b/src/main/java/com/ezylang/evalex/functions/string/StringUpperFunction.java
@@ -27,6 +27,6 @@ public class StringUpperFunction extends AbstractFunction {
@Override
public EvaluationValue evaluate(
Expression expression, Token functionToken, EvaluationValue... parameterValues) {
- return new EvaluationValue(parameterValues[0].getStringValue().toUpperCase());
+ return expression.convertValue(parameterValues[0].getStringValue().toUpperCase());
}
}
diff --git a/src/main/java/com/ezylang/evalex/operators/arithmetic/InfixDivisionOperator.java b/src/main/java/com/ezylang/evalex/operators/arithmetic/InfixDivisionOperator.java
index 68624c4..f7e6667 100644
--- a/src/main/java/com/ezylang/evalex/operators/arithmetic/InfixDivisionOperator.java
+++ b/src/main/java/com/ezylang/evalex/operators/arithmetic/InfixDivisionOperator.java
@@ -42,7 +42,7 @@ public class InfixDivisionOperator extends AbstractOperator {
throw new EvaluationException(operatorToken, "Division by zero");
}
- return new EvaluationValue(
+ return expression.convertValue(
leftOperand
.getNumberValue()
.divide(
diff --git a/src/main/java/com/ezylang/evalex/operators/arithmetic/InfixMinusOperator.java b/src/main/java/com/ezylang/evalex/operators/arithmetic/InfixMinusOperator.java
index 918d362..2352827 100644
--- a/src/main/java/com/ezylang/evalex/operators/arithmetic/InfixMinusOperator.java
+++ b/src/main/java/com/ezylang/evalex/operators/arithmetic/InfixMinusOperator.java
@@ -37,26 +37,26 @@ public class InfixMinusOperator extends AbstractOperator {
EvaluationValue rightOperand = operands[1];
if (leftOperand.isNumberValue() && rightOperand.isNumberValue()) {
- return new EvaluationValue(
+ return expression.convertValue(
leftOperand
.getNumberValue()
.subtract(
rightOperand.getNumberValue(), expression.getConfiguration().getMathContext()));
} else if (leftOperand.isDateTimeValue() && rightOperand.isDateTimeValue()) {
- return new EvaluationValue(
+ return expression.convertValue(
Duration.ofMillis(
leftOperand.getDateTimeValue().toEpochMilli()
- rightOperand.getDateTimeValue().toEpochMilli()));
} else if (leftOperand.isDateTimeValue() && rightOperand.isDurationValue()) {
- return new EvaluationValue(
+ return expression.convertValue(
leftOperand.getDateTimeValue().minus(rightOperand.getDurationValue()));
} else if (leftOperand.isDurationValue() && rightOperand.isDurationValue()) {
- return new EvaluationValue(
+ return expression.convertValue(
leftOperand.getDurationValue().minus(rightOperand.getDurationValue()));
} else if (leftOperand.isDateTimeValue() && rightOperand.isNumberValue()) {
- return new EvaluationValue(
+ return expression.convertValue(
leftOperand
.getDateTimeValue()
.minus(Duration.ofMillis(rightOperand.getNumberValue().longValue())));
diff --git a/src/main/java/com/ezylang/evalex/operators/arithmetic/InfixModuloOperator.java b/src/main/java/com/ezylang/evalex/operators/arithmetic/InfixModuloOperator.java
index dcb9ff6..1c26368 100644
--- a/src/main/java/com/ezylang/evalex/operators/arithmetic/InfixModuloOperator.java
+++ b/src/main/java/com/ezylang/evalex/operators/arithmetic/InfixModuloOperator.java
@@ -42,7 +42,7 @@ public class InfixModuloOperator extends AbstractOperator {
throw new EvaluationException(operatorToken, "Division by zero");
}
- return new EvaluationValue(
+ return expression.convertValue(
leftOperand
.getNumberValue()
.remainder(
diff --git a/src/main/java/com/ezylang/evalex/operators/arithmetic/InfixMultiplicationOperator.java b/src/main/java/com/ezylang/evalex/operators/arithmetic/InfixMultiplicationOperator.java
index 5776c91..86787b5 100644
--- a/src/main/java/com/ezylang/evalex/operators/arithmetic/InfixMultiplicationOperator.java
+++ b/src/main/java/com/ezylang/evalex/operators/arithmetic/InfixMultiplicationOperator.java
@@ -36,7 +36,7 @@ public class InfixMultiplicationOperator extends AbstractOperator {
EvaluationValue rightOperand = operands[1];
if (leftOperand.isNumberValue() && rightOperand.isNumberValue()) {
- return new EvaluationValue(
+ return expression.convertValue(
leftOperand
.getNumberValue()
.multiply(
diff --git a/src/main/java/com/ezylang/evalex/operators/arithmetic/InfixPlusOperator.java b/src/main/java/com/ezylang/evalex/operators/arithmetic/InfixPlusOperator.java
index bcc795f..b3a5961 100644
--- a/src/main/java/com/ezylang/evalex/operators/arithmetic/InfixPlusOperator.java
+++ b/src/main/java/com/ezylang/evalex/operators/arithmetic/InfixPlusOperator.java
@@ -37,23 +37,23 @@ public class InfixPlusOperator extends AbstractOperator {
EvaluationValue rightOperand = operands[1];
if (leftOperand.isNumberValue() && rightOperand.isNumberValue()) {
- return new EvaluationValue(
+ return expression.convertValue(
leftOperand
.getNumberValue()
.add(rightOperand.getNumberValue(), expression.getConfiguration().getMathContext()));
} else if (leftOperand.isDateTimeValue() && rightOperand.isDurationValue()) {
- return new EvaluationValue(
+ return expression.convertValue(
leftOperand.getDateTimeValue().plus(rightOperand.getDurationValue()));
} else if (leftOperand.isDurationValue() && rightOperand.isDurationValue()) {
- return new EvaluationValue(
+ return expression.convertValue(
leftOperand.getDurationValue().plus(rightOperand.getDurationValue()));
} else if (leftOperand.isDateTimeValue() && rightOperand.isNumberValue()) {
- return new EvaluationValue(
+ return expression.convertValue(
leftOperand
.getDateTimeValue()
.plus(Duration.ofMillis(rightOperand.getNumberValue().longValue())));
} else {
- return new EvaluationValue(leftOperand.getStringValue() + rightOperand.getStringValue());
+ return expression.convertValue(leftOperand.getStringValue() + rightOperand.getStringValue());
}
}
}
diff --git a/src/main/java/com/ezylang/evalex/operators/arithmetic/InfixPowerOfOperator.java b/src/main/java/com/ezylang/evalex/operators/arithmetic/InfixPowerOfOperator.java
index f5d4f51..c81e59d 100644
--- a/src/main/java/com/ezylang/evalex/operators/arithmetic/InfixPowerOfOperator.java
+++ b/src/main/java/com/ezylang/evalex/operators/arithmetic/InfixPowerOfOperator.java
@@ -66,7 +66,7 @@ public class InfixPowerOfOperator extends AbstractOperator {
if (signOf2 == -1) {
result = BigDecimal.ONE.divide(result, mathContext.getPrecision(), RoundingMode.HALF_UP);
}
- return new EvaluationValue(result);
+ return expression.convertValue(result);
} else {
throw EvaluationException.ofUnsupportedDataTypeInOperation(operatorToken);
}
diff --git a/src/main/java/com/ezylang/evalex/operators/arithmetic/PrefixMinusOperator.java b/src/main/java/com/ezylang/evalex/operators/arithmetic/PrefixMinusOperator.java
index c82a968..1565a63 100644
--- a/src/main/java/com/ezylang/evalex/operators/arithmetic/PrefixMinusOperator.java
+++ b/src/main/java/com/ezylang/evalex/operators/arithmetic/PrefixMinusOperator.java
@@ -33,7 +33,7 @@ public class PrefixMinusOperator extends AbstractOperator {
EvaluationValue operand = operands[0];
if (operand.isNumberValue()) {
- return new EvaluationValue(
+ return expression.convertValue(
operand.getNumberValue().negate(expression.getConfiguration().getMathContext()));
} else {
throw EvaluationException.ofUnsupportedDataTypeInOperation(operatorToken);
diff --git a/src/main/java/com/ezylang/evalex/operators/arithmetic/PrefixPlusOperator.java b/src/main/java/com/ezylang/evalex/operators/arithmetic/PrefixPlusOperator.java
index 6b4436b..984a2cc 100644
--- a/src/main/java/com/ezylang/evalex/operators/arithmetic/PrefixPlusOperator.java
+++ b/src/main/java/com/ezylang/evalex/operators/arithmetic/PrefixPlusOperator.java
@@ -33,7 +33,7 @@ public class PrefixPlusOperator extends AbstractOperator {
EvaluationValue operator = operands[0];
if (operator.isNumberValue()) {
- return new EvaluationValue(
+ return expression.convertValue(
operator.getNumberValue().plus(expression.getConfiguration().getMathContext()));
} else {
throw EvaluationException.ofUnsupportedDataTypeInOperation(operatorToken);
diff --git a/src/main/java/com/ezylang/evalex/operators/booleans/InfixAndOperator.java b/src/main/java/com/ezylang/evalex/operators/booleans/InfixAndOperator.java
index d3c96f0..489adf7 100644
--- a/src/main/java/com/ezylang/evalex/operators/booleans/InfixAndOperator.java
+++ b/src/main/java/com/ezylang/evalex/operators/booleans/InfixAndOperator.java
@@ -30,6 +30,6 @@ public class InfixAndOperator extends AbstractOperator {
@Override
public EvaluationValue evaluate(
Expression expression, Token operatorToken, EvaluationValue... operands) {
- return new EvaluationValue(operands[0].getBooleanValue() && operands[1].getBooleanValue());
+ return expression.convertValue(operands[0].getBooleanValue() && operands[1].getBooleanValue());
}
}
diff --git a/src/main/java/com/ezylang/evalex/operators/booleans/InfixEqualsOperator.java b/src/main/java/com/ezylang/evalex/operators/booleans/InfixEqualsOperator.java
index b373c18..6bef6d8 100644
--- a/src/main/java/com/ezylang/evalex/operators/booleans/InfixEqualsOperator.java
+++ b/src/main/java/com/ezylang/evalex/operators/booleans/InfixEqualsOperator.java
@@ -30,6 +30,6 @@ public class InfixEqualsOperator extends AbstractOperator {
@Override
public EvaluationValue evaluate(
Expression expression, Token operatorToken, EvaluationValue... operands) {
- return new EvaluationValue(operands[0].equals(operands[1]));
+ return expression.convertValue(operands[0].equals(operands[1]));
}
}
diff --git a/src/main/java/com/ezylang/evalex/operators/booleans/InfixGreaterEqualsOperator.java b/src/main/java/com/ezylang/evalex/operators/booleans/InfixGreaterEqualsOperator.java
index d846842..7d871c8 100644
--- a/src/main/java/com/ezylang/evalex/operators/booleans/InfixGreaterEqualsOperator.java
+++ b/src/main/java/com/ezylang/evalex/operators/booleans/InfixGreaterEqualsOperator.java
@@ -30,6 +30,6 @@ public class InfixGreaterEqualsOperator extends AbstractOperator {
@Override
public EvaluationValue evaluate(
Expression expression, Token operatorToken, EvaluationValue... operands) {
- return new EvaluationValue(operands[0].compareTo(operands[1]) >= 0);
+ return expression.convertValue(operands[0].compareTo(operands[1]) >= 0);
}
}
diff --git a/src/main/java/com/ezylang/evalex/operators/booleans/InfixGreaterOperator.java b/src/main/java/com/ezylang/evalex/operators/booleans/InfixGreaterOperator.java
index 431d957..afca50c 100644
--- a/src/main/java/com/ezylang/evalex/operators/booleans/InfixGreaterOperator.java
+++ b/src/main/java/com/ezylang/evalex/operators/booleans/InfixGreaterOperator.java
@@ -30,6 +30,6 @@ public class InfixGreaterOperator extends AbstractOperator {
@Override
public EvaluationValue evaluate(
Expression expression, Token operatorToken, EvaluationValue... operands) {
- return new EvaluationValue(operands[0].compareTo(operands[1]) > 0);
+ return expression.convertValue(operands[0].compareTo(operands[1]) > 0);
}
}
diff --git a/src/main/java/com/ezylang/evalex/operators/booleans/InfixLessEqualsOperator.java b/src/main/java/com/ezylang/evalex/operators/booleans/InfixLessEqualsOperator.java
index 5fde2af..f7fa759 100644
--- a/src/main/java/com/ezylang/evalex/operators/booleans/InfixLessEqualsOperator.java
+++ b/src/main/java/com/ezylang/evalex/operators/booleans/InfixLessEqualsOperator.java
@@ -30,6 +30,6 @@ public class InfixLessEqualsOperator extends AbstractOperator {
@Override
public EvaluationValue evaluate(
Expression expression, Token operatorToken, EvaluationValue... operands) {
- return new EvaluationValue(operands[0].compareTo(operands[1]) <= 0);
+ return expression.convertValue(operands[0].compareTo(operands[1]) <= 0);
}
}
diff --git a/src/main/java/com/ezylang/evalex/operators/booleans/InfixLessOperator.java b/src/main/java/com/ezylang/evalex/operators/booleans/InfixLessOperator.java
index 3234fc3..78e9a32 100644
--- a/src/main/java/com/ezylang/evalex/operators/booleans/InfixLessOperator.java
+++ b/src/main/java/com/ezylang/evalex/operators/booleans/InfixLessOperator.java
@@ -30,6 +30,6 @@ public class InfixLessOperator extends AbstractOperator {
@Override
public EvaluationValue evaluate(
Expression expression, Token operatorToken, EvaluationValue... operands) {
- return new EvaluationValue(operands[0].compareTo(operands[1]) < 0);
+ return expression.convertValue(operands[0].compareTo(operands[1]) < 0);
}
}
diff --git a/src/main/java/com/ezylang/evalex/operators/booleans/InfixNotEqualsOperator.java b/src/main/java/com/ezylang/evalex/operators/booleans/InfixNotEqualsOperator.java
index 5f0d386..50fd130 100644
--- a/src/main/java/com/ezylang/evalex/operators/booleans/InfixNotEqualsOperator.java
+++ b/src/main/java/com/ezylang/evalex/operators/booleans/InfixNotEqualsOperator.java
@@ -30,6 +30,6 @@ public class InfixNotEqualsOperator extends AbstractOperator {
@Override
public EvaluationValue evaluate(
Expression expression, Token operatorToken, EvaluationValue... operands) {
- return new EvaluationValue(!operands[0].equals(operands[1]));
+ return expression.convertValue(!operands[0].equals(operands[1]));
}
}
diff --git a/src/main/java/com/ezylang/evalex/operators/booleans/InfixOrOperator.java b/src/main/java/com/ezylang/evalex/operators/booleans/InfixOrOperator.java
index dc4a8bc..f487287 100644
--- a/src/main/java/com/ezylang/evalex/operators/booleans/InfixOrOperator.java
+++ b/src/main/java/com/ezylang/evalex/operators/booleans/InfixOrOperator.java
@@ -30,6 +30,6 @@ public class InfixOrOperator extends AbstractOperator {
@Override
public EvaluationValue evaluate(
Expression expression, Token operatorToken, EvaluationValue... operands) {
- return new EvaluationValue(operands[0].getBooleanValue() || operands[1].getBooleanValue());
+ return expression.convertValue(operands[0].getBooleanValue() || operands[1].getBooleanValue());
}
}
diff --git a/src/main/java/com/ezylang/evalex/operators/booleans/PrefixNotOperator.java b/src/main/java/com/ezylang/evalex/operators/booleans/PrefixNotOperator.java
index aa95851..597fabb 100644
--- a/src/main/java/com/ezylang/evalex/operators/booleans/PrefixNotOperator.java
+++ b/src/main/java/com/ezylang/evalex/operators/booleans/PrefixNotOperator.java
@@ -28,6 +28,6 @@ public class PrefixNotOperator extends AbstractOperator {
@Override
public EvaluationValue evaluate(
Expression expression, Token operatorToken, EvaluationValue... operands) {
- return new EvaluationValue(!operands[0].getBooleanValue());
+ return expression.convertValue(!operands[0].getBooleanValue());
}
}
diff --git a/src/test/java/com/ezylang/evalex/config/TestConfigurationProvider.java b/src/test/java/com/ezylang/evalex/config/TestConfigurationProvider.java
index 6be6313..7cdeb0b 100644
--- a/src/test/java/com/ezylang/evalex/config/TestConfigurationProvider.java
+++ b/src/test/java/com/ezylang/evalex/config/TestConfigurationProvider.java
@@ -42,7 +42,7 @@ public class TestConfigurationProvider {
public EvaluationValue evaluate(
Expression expression, Token functionToken, EvaluationValue... parameterValues) {
// dummy implementation
- return new EvaluationValue("OK");
+ return expression.convertValue("OK");
}
}
diff --git a/src/test/java/com/ezylang/evalex/data/DefaultEvaluationValueConverterTest.java b/src/test/java/com/ezylang/evalex/data/DefaultEvaluationValueConverterTest.java
new file mode 100644
index 0000000..0302e33
--- /dev/null
+++ b/src/test/java/com/ezylang/evalex/data/DefaultEvaluationValueConverterTest.java
@@ -0,0 +1,52 @@
+/*
+ Copyright 2012-2023 Udo Klimaschewski
+
+ 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 com.ezylang.evalex.data;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import com.ezylang.evalex.config.ExpressionConfiguration;
+import org.junit.jupiter.api.Test;
+
+class DefaultEvaluationValueConverterTest {
+
+ private final DefaultEvaluationValueConverter converter = new DefaultEvaluationValueConverter();
+ private final ExpressionConfiguration defaultConfiguration =
+ ExpressionConfiguration.defaultConfiguration();
+
+ @Test
+ void testNull() {
+ EvaluationValue converted = converter.convertObject(null, defaultConfiguration);
+
+ assertThat(converted.getDataType()).isEqualTo(EvaluationValue.DataType.NULL);
+ }
+
+ @Test
+ void testNestedEvaluationValueNull() {
+ EvaluationValue converted =
+ converter.convertObject(EvaluationValue.stringValue("Hello"), defaultConfiguration);
+
+ assertThat(converted.getDataType()).isEqualTo(EvaluationValue.DataType.STRING);
+ assertThat(converted.getStringValue()).isEqualTo("Hello");
+ }
+
+ @Test
+ void testException() {
+ assertThatThrownBy(() -> converter.convertObject(new int[] {1, 2, 3}, defaultConfiguration))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Unsupported data type '[I'");
+ }
+}
diff --git a/src/test/java/com/ezylang/evalex/data/EvaluationValueTest.java b/src/test/java/com/ezylang/evalex/data/EvaluationValueTest.java
index bd0b06d..1c5d033 100644
--- a/src/test/java/com/ezylang/evalex/data/EvaluationValueTest.java
+++ b/src/test/java/com/ezylang/evalex/data/EvaluationValueTest.java
@@ -20,6 +20,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
import com.ezylang.evalex.EvaluationException;
import com.ezylang.evalex.Expression;
+import com.ezylang.evalex.config.ExpressionConfiguration;
import com.ezylang.evalex.parser.ASTNode;
import com.ezylang.evalex.parser.ParseException;
import com.ezylang.evalex.parser.Token;
@@ -131,34 +132,73 @@ class EvaluationValueTest {
}
@Test
- void testLocalDate() {
- LocalDate localDate = LocalDate.parse("2022-10-30");
- EvaluationValue value = new EvaluationValue(localDate);
+ void testLocalDateCETDaylightSavingTime() {
+ LocalDate localDate = LocalDate.parse("2022-10-20");
+ EvaluationValue value =
+ new EvaluationValue(
+ localDate, ExpressionConfiguration.builder().zoneId(ZoneId.of("CET")).build());
+
+ assertThat(value.isDateTimeValue()).isTrue();
+ assertDataIsCorrect(
+ value,
+ "2022-10-19T22:00:00Z",
+ BigDecimal.ZERO,
+ false,
+ localDate.atStartOfDay().atZone(ZoneId.of("CET")).toInstant(),
+ Duration.ZERO,
+ Instant.class);
+ }
+
+ @Test
+ void testLocalDateCETNoDaylightSavingTime() {
+ LocalDate localDate = LocalDate.parse("2022-11-30");
+ EvaluationValue value =
+ new EvaluationValue(
+ localDate, ExpressionConfiguration.builder().zoneId(ZoneId.of("CET")).build());
assertThat(value.isDateTimeValue()).isTrue();
assertDataIsCorrect(
value,
- "2022-10-30T00:00:00Z",
+ "2022-11-29T23:00:00Z",
BigDecimal.ZERO,
false,
- Instant.parse("2022-10-30T00:00:00Z"),
+ localDate.atStartOfDay().atZone(ZoneId.of("CET")).toInstant(),
Duration.ZERO,
Instant.class);
}
@Test
- void testLocalDateTime() {
- ZoneId zoneId = ZoneId.of("UTC+2");
- LocalDateTime localDateTime = LocalDateTime.parse("2022-10-30T11:20:30");
- EvaluationValue value = new EvaluationValue(localDateTime, zoneId);
+ void testLocalDateTimeDaylightSavingTime() {
+ LocalDateTime localDateTime = LocalDateTime.parse("2022-10-20T11:20:30");
+ EvaluationValue value =
+ new EvaluationValue(
+ localDateTime, ExpressionConfiguration.builder().zoneId(ZoneId.of("CET")).build());
+
+ assertThat(value.isDateTimeValue()).isTrue();
+ assertDataIsCorrect(
+ value,
+ "2022-10-20T09:20:30Z",
+ BigDecimal.ZERO,
+ false,
+ localDateTime.atZone(ZoneId.of("CET")).toInstant(),
+ Duration.ZERO,
+ Instant.class);
+ }
+
+ @Test
+ void testLocalDateTimeNoDaylightSavingTime() {
+ LocalDateTime localDateTime = LocalDateTime.parse("2022-11-20T11:20:30");
+ EvaluationValue value =
+ new EvaluationValue(
+ localDateTime, ExpressionConfiguration.builder().zoneId(ZoneId.of("CET")).build());
assertThat(value.isDateTimeValue()).isTrue();
assertDataIsCorrect(
value,
- "2022-10-30T09:20:30Z",
+ "2022-11-20T10:20:30Z",
BigDecimal.ZERO,
false,
- localDateTime.atZone(zoneId).toInstant(),
+ localDateTime.atZone(ZoneId.of("CET")).toInstant(),
Duration.ZERO,
Instant.class);
}
diff --git a/src/test/java/com/ezylang/evalex/data/conversion/ArrayConverterTest.java b/src/test/java/com/ezylang/evalex/data/conversion/ArrayConverterTest.java
new file mode 100644
index 0000000..5a378d3
--- /dev/null
+++ b/src/test/java/com/ezylang/evalex/data/conversion/ArrayConverterTest.java
@@ -0,0 +1,75 @@
+/*
+ Copyright 2012-2023 Udo Klimaschewski
+
+ 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 com.ezylang.evalex.data.conversion;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.ezylang.evalex.config.ExpressionConfiguration;
+import com.ezylang.evalex.data.EvaluationValue;
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.junit.jupiter.api.Test;
+
+class ArrayConverterTest {
+
+ private final ExpressionConfiguration defaultConfiguration =
+ ExpressionConfiguration.defaultConfiguration();
+
+ private final ArrayConverter converter = new ArrayConverter();
+
+ @Test
+ void testArrayMixed() {
+ EvaluationValue value =
+ converter.convert(
+ Arrays.asList(new BigDecimal(1), new BigDecimal(2), "hello", null),
+ defaultConfiguration);
+
+ assertThat(value.isArrayValue()).isTrue();
+ assertThat(value.getArrayValue()).hasSize(4);
+ assertThat(value.getArrayValue().get(0).isNumberValue()).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).isStringValue()).isTrue();
+ assertThat(value.getArrayValue().get(2).getStringValue()).isEqualTo("hello");
+ assertThat(value.getArrayValue().get(3).isNullValue()).isTrue();
+ assertThat(value.getArrayValue().get(3).getStringValue()).isNull();
+
+ assertThat(value.getValue()).isInstanceOf(List.class);
+ }
+
+ @Test
+ void testArrayEmpty() {
+ EvaluationValue value = converter.convert(Collections.EMPTY_LIST, defaultConfiguration);
+
+ assertThat(value.isArrayValue()).isTrue();
+ assertThat(value.getArrayValue()).isEmpty();
+ }
+
+ @Test
+ void testCanConvert() {
+ 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();
+ }
+}
diff --git a/src/test/java/com/ezylang/evalex/data/conversion/BooleanConverterTest.java b/src/test/java/com/ezylang/evalex/data/conversion/BooleanConverterTest.java
new file mode 100644
index 0000000..4266b90
--- /dev/null
+++ b/src/test/java/com/ezylang/evalex/data/conversion/BooleanConverterTest.java
@@ -0,0 +1,59 @@
+/*
+ Copyright 2012-2023 Udo Klimaschewski
+
+ 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 com.ezylang.evalex.data.conversion;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.ezylang.evalex.config.ExpressionConfiguration;
+import com.ezylang.evalex.data.EvaluationValue;
+import java.math.BigDecimal;
+import org.junit.jupiter.api.Test;
+
+class BooleanConverterTest {
+
+ private final ExpressionConfiguration defaultConfiguration =
+ ExpressionConfiguration.defaultConfiguration();
+
+ private final BooleanConverter converter = new BooleanConverter();
+
+ @Test
+ void testBooleanTrue() {
+ EvaluationValue value = converter.convert(true, defaultConfiguration);
+
+ assertThat(value.isBooleanValue()).isTrue();
+ assertThat(value.getBooleanValue()).isTrue();
+ }
+
+ @Test
+ void testBooleanFalse() {
+ EvaluationValue value = converter.convert(false, defaultConfiguration);
+
+ assertThat(value.isBooleanValue()).isTrue();
+ assertThat(value.getBooleanValue()).isFalse();
+ }
+
+ @Test
+ void testCanConvert() {
+ assertThat(converter.canConvert(true)).isTrue();
+ assertThat(converter.canConvert(Boolean.valueOf("false"))).isTrue();
+ }
+
+ @Test
+ void testCanNotConvert() {
+ assertThat(converter.canConvert("true")).isFalse();
+ assertThat(converter.canConvert(new BigDecimal(1))).isFalse();
+ }
+}
diff --git a/src/test/java/com/ezylang/evalex/data/conversion/DateTimeConverterTest.java b/src/test/java/com/ezylang/evalex/data/conversion/DateTimeConverterTest.java
new file mode 100644
index 0000000..b2d6830
--- /dev/null
+++ b/src/test/java/com/ezylang/evalex/data/conversion/DateTimeConverterTest.java
@@ -0,0 +1,152 @@
+/*
+ Copyright 2012-2023 Udo Klimaschewski
+
+ 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 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.*;
+import java.util.Calendar;
+import java.util.Date;
+import org.junit.jupiter.api.Test;
+
+class DateTimeConverterTest {
+
+ private final ExpressionConfiguration defaultConfiguration =
+ ExpressionConfiguration.defaultConfiguration();
+
+ private final ExpressionConfiguration cetConfiguration =
+ ExpressionConfiguration.builder().zoneId(ZoneId.of("Europe/Berlin")).build();
+
+ private final DateTimeConverter converter = new DateTimeConverter();
+
+ @Test
+ void testInstant() {
+ Instant now = Instant.now();
+
+ EvaluationValue converted = converter.convert(now, cetConfiguration);
+
+ assertThat(converted.getDataType()).isEqualTo(EvaluationValue.DataType.DATE_TIME);
+ assertThat(converted.getValue()).isEqualTo(now);
+ }
+
+ @Test
+ void testZonedDateTime() {
+ ZonedDateTime now = ZonedDateTime.now(ZoneId.of("US/Central"));
+
+ EvaluationValue converted = converter.convert(now, cetConfiguration);
+
+ assertThat(converted.getDataType()).isEqualTo(EvaluationValue.DataType.DATE_TIME);
+ assertThat(converted.getValue()).isEqualTo(now.toInstant());
+ }
+
+ @Test
+ void testOffsetDateTime() {
+ OffsetDateTime now = OffsetDateTime.now(ZoneId.of("US/Central"));
+
+ EvaluationValue converted = converter.convert(now, cetConfiguration);
+
+ assertThat(converted.getDataType()).isEqualTo(EvaluationValue.DataType.DATE_TIME);
+ assertThat(converted.getValue()).isEqualTo(now.toInstant());
+ }
+
+ @Test
+ void testLocalDateDaylightSaving() {
+ LocalDate localDate = LocalDate.parse("2022-10-20");
+
+ EvaluationValue converted = new EvaluationValue(localDate, cetConfiguration);
+
+ assertThat(converted.getDataType()).isEqualTo(EvaluationValue.DataType.DATE_TIME);
+ assertThat(converted.getValue().toString()).hasToString("2022-10-19T22:00:00Z");
+ }
+
+ @Test
+ void testLocalDateNoDaylightSaving() {
+ LocalDate localDate = LocalDate.parse("2022-11-20");
+
+ EvaluationValue converted = new EvaluationValue(localDate, cetConfiguration);
+
+ assertThat(converted.getDataType()).isEqualTo(EvaluationValue.DataType.DATE_TIME);
+ assertThat(converted.getValue().toString()).hasToString("2022-11-19T23:00:00Z");
+ }
+
+ @Test
+ void testLocalDateTimeDaylightSaving() {
+ LocalDateTime localDateTime = LocalDateTime.parse("2022-10-20T11:21:30");
+
+ EvaluationValue converted = new EvaluationValue(localDateTime, cetConfiguration);
+
+ assertThat(converted.getDataType()).isEqualTo(EvaluationValue.DataType.DATE_TIME);
+ assertThat(converted.getValue().toString()).hasToString("2022-10-20T09:21:30Z");
+ }
+
+ @Test
+ void testLocalDateTimeNoDaylightSaving() {
+ LocalDateTime localDateTime = LocalDateTime.parse("2022-11-20T11:21:30");
+
+ EvaluationValue converted = new EvaluationValue(localDateTime, cetConfiguration);
+
+ assertThat(converted.getDataType()).isEqualTo(EvaluationValue.DataType.DATE_TIME);
+ assertThat(converted.getValue().toString()).hasToString("2022-11-20T10:21:30Z");
+ }
+
+ @Test
+ void testDate() {
+ Date now = new Date();
+
+ EvaluationValue converted = converter.convert(now, cetConfiguration);
+
+ assertThat(converted.getDataType()).isEqualTo(EvaluationValue.DataType.DATE_TIME);
+ assertThat(converted.getValue()).isEqualTo(now.toInstant());
+ }
+
+ @Test
+ void testCalendar() {
+ Calendar now = Calendar.getInstance();
+
+ EvaluationValue converted = converter.convert(now, cetConfiguration);
+
+ assertThat(converted.getDataType()).isEqualTo(EvaluationValue.DataType.DATE_TIME);
+ assertThat(converted.getValue()).isEqualTo(now.toInstant());
+ }
+
+ @Test
+ void testCanConvert() {
+ assertThat(converter.canConvert(Instant.now())).isTrue();
+ assertThat(converter.canConvert(ZonedDateTime.now())).isTrue();
+ assertThat(converter.canConvert(OffsetDateTime.now())).isTrue();
+ assertThat(converter.canConvert(LocalDate.now())).isTrue();
+ assertThat(converter.canConvert(LocalDateTime.now())).isTrue();
+ assertThat(converter.canConvert(new Date())).isTrue();
+ assertThat(converter.canConvert(Calendar.getInstance())).isTrue();
+ }
+
+ @Test
+ void testCanNotConvert() {
+ assertThat(converter.canConvert("hello")).isFalse();
+ assertThat(converter.canConvert(new BigDecimal(1))).isFalse();
+ }
+
+ @Test
+ void testException() {
+ assertThatThrownBy(() -> converter.convert("hello", defaultConfiguration))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Unsupported data type 'java.lang.String'");
+ }
+}
diff --git a/src/test/java/com/ezylang/evalex/data/conversion/DuratinCoverterTest.java b/src/test/java/com/ezylang/evalex/data/conversion/DuratinCoverterTest.java
new file mode 100644
index 0000000..128cd75
--- /dev/null
+++ b/src/test/java/com/ezylang/evalex/data/conversion/DuratinCoverterTest.java
@@ -0,0 +1,53 @@
+/*
+ Copyright 2012-2023 Udo Klimaschewski
+
+ 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 com.ezylang.evalex.data.conversion;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.ezylang.evalex.config.ExpressionConfiguration;
+import com.ezylang.evalex.data.EvaluationValue;
+import java.math.BigDecimal;
+import java.time.Duration;
+import org.junit.jupiter.api.Test;
+
+class DuratinCoverterTest {
+
+ private final ExpressionConfiguration defaultConfiguration =
+ ExpressionConfiguration.defaultConfiguration();
+
+ private final DurationConverter converter = new DurationConverter();
+
+ @Test
+ void testDuration() {
+ Duration duration = Duration.ofMinutes(5);
+
+ EvaluationValue converted = converter.convert(duration, defaultConfiguration);
+
+ assertThat(converted.getDataType()).isEqualTo(EvaluationValue.DataType.DURATION);
+ assertThat(converted.getValue()).isEqualTo(duration);
+ }
+
+ @Test
+ void testCanConvert() {
+ assertThat(converter.canConvert(Duration.ofMinutes(10))).isTrue();
+ }
+
+ @Test
+ void testCanNotConvert() {
+ assertThat(converter.canConvert("hello")).isFalse();
+ assertThat(converter.canConvert(new BigDecimal(10))).isFalse();
+ }
+}
diff --git a/src/test/java/com/ezylang/evalex/data/conversion/ExpressionNodeConverterTest.java b/src/test/java/com/ezylang/evalex/data/conversion/ExpressionNodeConverterTest.java
new file mode 100644
index 0000000..276fb53
--- /dev/null
+++ b/src/test/java/com/ezylang/evalex/data/conversion/ExpressionNodeConverterTest.java
@@ -0,0 +1,56 @@
+/*
+ Copyright 2012-2023 Udo Klimaschewski
+
+ 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 com.ezylang.evalex.data.conversion;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.ezylang.evalex.config.ExpressionConfiguration;
+import com.ezylang.evalex.data.EvaluationValue;
+import com.ezylang.evalex.parser.ASTNode;
+import com.ezylang.evalex.parser.Token;
+import java.math.BigDecimal;
+import org.junit.jupiter.api.Test;
+
+class ExpressionNodeConverterTest {
+
+ private final ExpressionConfiguration defaultConfiguration =
+ ExpressionConfiguration.defaultConfiguration();
+
+ private final ExpressionNodeConverter converter = new ExpressionNodeConverter();
+
+ private final ASTNode testNode =
+ new ASTNode(new Token(1, "a", Token.TokenType.VARIABLE_OR_CONSTANT));
+
+ @Test
+ void testDuration() {
+
+ EvaluationValue converted = converter.convert(testNode, defaultConfiguration);
+
+ assertThat(converted.getDataType()).isEqualTo(EvaluationValue.DataType.EXPRESSION_NODE);
+ assertThat(converted.getExpressionNode().toJSON()).isEqualTo(testNode.toJSON());
+ }
+
+ @Test
+ void testCanConvert() {
+ assertThat(converter.canConvert(testNode)).isTrue();
+ }
+
+ @Test
+ void testCanNotConvert() {
+ assertThat(converter.canConvert("hello")).isFalse();
+ assertThat(converter.canConvert(new BigDecimal(10))).isFalse();
+ }
+}
diff --git a/src/test/java/com/ezylang/evalex/data/conversion/NumberConverterTest.java b/src/test/java/com/ezylang/evalex/data/conversion/NumberConverterTest.java
new file mode 100644
index 0000000..58f5496
--- /dev/null
+++ b/src/test/java/com/ezylang/evalex/data/conversion/NumberConverterTest.java
@@ -0,0 +1,122 @@
+/*
+ Copyright 2012-2023 Udo Klimaschewski
+
+ 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 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 org.junit.jupiter.api.Test;
+
+class NumberConverterTest {
+
+ private final ExpressionConfiguration defaultConfiguration =
+ ExpressionConfiguration.defaultConfiguration();
+
+ private final NumberConverter converter = new NumberConverter();
+
+ @Test
+ void testBigDecimal() {
+ BigDecimal value = new BigDecimal("23");
+
+ EvaluationValue converted = converter.convert(value, defaultConfiguration);
+
+ assertThat(converted.getDataType()).isEqualTo(EvaluationValue.DataType.NUMBER);
+ assertThat(converted.getValue()).isEqualTo(value);
+ }
+
+ @Test
+ void testDouble() {
+ double value = Double.parseDouble("2.5");
+
+ EvaluationValue converted = converter.convert(value, defaultConfiguration);
+
+ assertThat(converted.getDataType()).isEqualTo(EvaluationValue.DataType.NUMBER);
+ assertThat(converted.getNumberValue().toPlainString()).isEqualTo("2.5");
+ }
+
+ @Test
+ void testFloat() {
+ double value = Float.parseFloat("3.5");
+
+ EvaluationValue converted = converter.convert(value, defaultConfiguration);
+
+ assertThat(converted.getDataType()).isEqualTo(EvaluationValue.DataType.NUMBER);
+ assertThat(converted.getNumberValue().toPlainString()).isEqualTo("3.5");
+ }
+
+ @Test
+ void testInteger() {
+ EvaluationValue converted = converter.convert(5, defaultConfiguration);
+
+ assertThat(converted.getDataType()).isEqualTo(EvaluationValue.DataType.NUMBER);
+ assertThat(converted.getNumberValue().toPlainString()).isEqualTo("5");
+ }
+
+ @Test
+ void testLong() {
+ EvaluationValue converted = converter.convert(949345345343345673L, defaultConfiguration);
+
+ assertThat(converted.getDataType()).isEqualTo(EvaluationValue.DataType.NUMBER);
+ assertThat(converted.getNumberValue().toPlainString()).isEqualTo("949345345343345673");
+ }
+
+ @Test
+ void testShort() {
+ double value = Short.parseShort("7");
+
+ EvaluationValue converted = converter.convert(value, defaultConfiguration);
+
+ assertThat(converted.getDataType()).isEqualTo(EvaluationValue.DataType.NUMBER);
+ assertThat(converted.getNumberValue().toPlainString()).isEqualTo("7.0");
+ }
+
+ @Test
+ void testByte() {
+ double value = Byte.parseByte("4");
+
+ EvaluationValue converted = converter.convert(value, defaultConfiguration);
+
+ assertThat(converted.getDataType()).isEqualTo(EvaluationValue.DataType.NUMBER);
+ assertThat(converted.getNumberValue().toPlainString()).isEqualTo("4.0");
+ }
+
+ @Test
+ void testCanConvert() {
+ assertThat(converter.canConvert(new BigDecimal(8))).isTrue();
+ assertThat(converter.canConvert(Double.parseDouble("3.0"))).isTrue();
+ assertThat(converter.canConvert(Float.parseFloat("2.0"))).isTrue();
+ assertThat(converter.canConvert(3)).isTrue();
+ assertThat(converter.canConvert(3L)).isTrue();
+ assertThat(converter.canConvert(Short.parseShort("79"))).isTrue();
+ assertThat(converter.canConvert(Byte.parseByte("2"))).isTrue();
+ }
+
+ @Test
+ void testCanNotConvert() {
+ assertThat(converter.canConvert("hello")).isFalse();
+ assertThat(converter.canConvert(true)).isFalse();
+ }
+
+ @Test
+ void testException() {
+ assertThatThrownBy(() -> converter.convert("not a number", defaultConfiguration))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Unsupported data type 'java.lang.String'");
+ }
+}
diff --git a/src/test/java/com/ezylang/evalex/data/conversion/StringConverterTest.java b/src/test/java/com/ezylang/evalex/data/conversion/StringConverterTest.java
new file mode 100644
index 0000000..12088d9
--- /dev/null
+++ b/src/test/java/com/ezylang/evalex/data/conversion/StringConverterTest.java
@@ -0,0 +1,67 @@
+/*
+ Copyright 2012-2023 Udo Klimaschewski
+
+ 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 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 org.junit.jupiter.api.Test;
+
+class StringConverterTest {
+
+ private final ExpressionConfiguration defaultConfiguration =
+ ExpressionConfiguration.defaultConfiguration();
+
+ private final StringConverter converter = new StringConverter();
+
+ @Test
+ void testString() {
+ EvaluationValue converted = converter.convert("Hello World!", defaultConfiguration);
+
+ assertThat(converted.getDataType()).isEqualTo(EvaluationValue.DataType.STRING);
+ assertThat(converted.getValue()).isEqualTo("Hello World!");
+ }
+
+ @Test
+ void testCharacter() {
+ EvaluationValue converted = converter.convert('P', defaultConfiguration);
+
+ assertThat(converted.getDataType()).isEqualTo(EvaluationValue.DataType.STRING);
+ assertThat(converted.getValue()).isEqualTo("P");
+ }
+
+ @Test
+ void testCanConvert() {
+ assertThat(converter.canConvert("Hello")).isTrue();
+ assertThat(converter.canConvert('P')).isTrue();
+ }
+
+ @Test
+ void testCanNotConvert() {
+ assertThat(converter.canConvert(new BigDecimal(3))).isFalse();
+ assertThat(converter.canConvert(true)).isFalse();
+ }
+
+ @Test
+ void testException() {
+ assertThatThrownBy(() -> converter.convert(7, defaultConfiguration))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Unsupported data type 'java.lang.Integer'");
+ }
+}
diff --git a/src/test/java/com/ezylang/evalex/data/conversion/StructureConverterTest.java b/src/test/java/com/ezylang/evalex/data/conversion/StructureConverterTest.java
new file mode 100644
index 0000000..e78f1b1
--- /dev/null
+++ b/src/test/java/com/ezylang/evalex/data/conversion/StructureConverterTest.java
@@ -0,0 +1,77 @@
+/*
+ Copyright 2012-2023 Udo Klimaschewski
+
+ 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 com.ezylang.evalex.data.conversion;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.ezylang.evalex.config.ExpressionConfiguration;
+import com.ezylang.evalex.data.EvaluationValue;
+import java.math.BigDecimal;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.jupiter.api.Test;
+
+class StructureConverterTest {
+
+ private final ExpressionConfiguration defaultConfiguration =
+ ExpressionConfiguration.defaultConfiguration();
+
+ private final StructureConverter converter = new StructureConverter();
+
+ @Test
+ void testStructureMixed() {
+ Map testMap = new HashMap<>();
+
+ testMap.put("key1", "value1");
+ testMap.put("key2", 4);
+ testMap.put("key3", true);
+
+ EvaluationValue converted = converter.convert(testMap, defaultConfiguration);
+
+ assertThat(converted.getDataType()).isEqualTo(EvaluationValue.DataType.STRUCTURE);
+ assertThat(converted.getStructureValue()).hasSize(3);
+
+ assertThat(converted.getStructureValue().get("key1").isStringValue()).isTrue();
+ assertThat(converted.getStructureValue().get("key1").getStringValue()).isEqualTo("value1");
+
+ assertThat(converted.getStructureValue().get("key2").isNumberValue()).isTrue();
+ assertThat(converted.getStructureValue().get("key2").getNumberValue())
+ .isEqualTo(new BigDecimal("4"));
+
+ assertThat(converted.getStructureValue().get("key3").isBooleanValue()).isTrue();
+ assertThat(converted.getStructureValue().get("key3").getBooleanValue()).isTrue();
+ }
+
+ @Test
+ void testMapEmpty() {
+ EvaluationValue value = converter.convert(Collections.EMPTY_MAP, defaultConfiguration);
+
+ assertThat(value.isStructureValue()).isTrue();
+ assertThat(value.getStructureValue()).isEmpty();
+ }
+
+ @Test
+ void testCanConvert() {
+ assertThat(converter.canConvert(Collections.EMPTY_MAP)).isTrue();
+ }
+
+ @Test
+ void testCanNotConvert() {
+ assertThat(converter.canConvert(new int[] {1, 2, 3})).isFalse();
+ assertThat(converter.canConvert(new BigDecimal(1))).isFalse();
+ }
+}
diff --git a/src/test/java/com/ezylang/evalex/functions/basic/BasicFunctionsTest.java b/src/test/java/com/ezylang/evalex/functions/basic/BasicFunctionsTest.java
index b1e06ac..683a132 100644
--- a/src/test/java/com/ezylang/evalex/functions/basic/BasicFunctionsTest.java
+++ b/src/test/java/com/ezylang/evalex/functions/basic/BasicFunctionsTest.java
@@ -187,16 +187,19 @@ class BasicFunctionsTest extends BaseEvaluationTest {
// somehow, code coverage for the NotFunction traditional tests does not work on Google build
NotFunction notFunction = new NotFunction();
Expression expressionMock = Mockito.mock(Expression.class);
+ Mockito.when(expressionMock.convertValue(true)).thenReturn(EvaluationValue.booleanValue(true));
+ Mockito.when(expressionMock.convertValue(false))
+ .thenReturn(EvaluationValue.booleanValue(false));
Token token = new Token(1, "NOT", TokenType.FUNCTION, notFunction);
assertThat(
notFunction
- .evaluate(expressionMock, token, new EvaluationValue(true))
+ .evaluate(expressionMock, token, EvaluationValue.booleanValue(true))
.getBooleanValue())
.isFalse();
assertThat(
notFunction
- .evaluate(expressionMock, token, new EvaluationValue(false))
+ .evaluate(expressionMock, token, EvaluationValue.booleanValue(false))
.getBooleanValue())
.isTrue();
}
diff --git a/src/test/java/com/ezylang/evalex/functions/datetime/DateTimeFunctionsTest.java b/src/test/java/com/ezylang/evalex/functions/datetime/DateTimeFunctionsTest.java
index 0844f63..521d544 100644
--- a/src/test/java/com/ezylang/evalex/functions/datetime/DateTimeFunctionsTest.java
+++ b/src/test/java/com/ezylang/evalex/functions/datetime/DateTimeFunctionsTest.java
@@ -28,7 +28,7 @@ class DateTimeFunctionsTest extends BaseEvaluationTest {
private static final ExpressionConfiguration DateTimeTestConfiguration =
TestConfigurationProvider.StandardConfigurationWithAdditionalTestOperators.toBuilder()
- .defaultZoneId(ZoneId.of("UTC+2"))
+ .zoneId(ZoneId.of("UTC+2"))
.build();
@ParameterizedTest
diff --git a/src/test/java/com/ezylang/evalex/operators/arithmetic/ArithmeticOperatorsTest.java b/src/test/java/com/ezylang/evalex/operators/arithmetic/ArithmeticOperatorsTest.java
index ad1fe42..3a8db50 100644
--- a/src/test/java/com/ezylang/evalex/operators/arithmetic/ArithmeticOperatorsTest.java
+++ b/src/test/java/com/ezylang/evalex/operators/arithmetic/ArithmeticOperatorsTest.java
@@ -106,7 +106,7 @@ class ArithmeticOperatorsTest extends BaseEvaluationTest {
expression,
expectedResult,
TestConfigurationProvider.StandardConfigurationWithAdditionalTestOperators.toBuilder()
- .defaultZoneId(ZoneId.of("UTC+2"))
+ .zoneId(ZoneId.of("UTC+2"))
.build());
}
@@ -200,7 +200,7 @@ class ArithmeticOperatorsTest extends BaseEvaluationTest {
expression,
expectedResult,
TestConfigurationProvider.StandardConfigurationWithAdditionalTestOperators.toBuilder()
- .defaultZoneId(ZoneId.of("UTC+2"))
+ .zoneId(ZoneId.of("UTC+2"))
.build());
}