From 1ed8f14307bc3dcba26673828b00f9e6c35144a9 Mon Sep 17 00:00:00 2001 From: uklimaschewski Date: Mon, 10 Oct 2022 10:29:14 +0200 Subject: [PATCH] adds configuration possibility to allow/disallow to overwrite constant (allowed is default) --- docs/configuration/configuration.md | 7 ++++++ .../java/com/ezylang/evalex/Expression.java | 10 +++++++- .../config/ExpressionConfiguration.java | 6 +++++ .../ExpressionEvaluatorConstantsTest.java | 25 +++++++++++++++++++ .../config/ExpressionConfigurationTest.java | 1 + 5 files changed, 48 insertions(+), 1 deletion(-) diff --git a/docs/configuration/configuration.md b/docs/configuration/configuration.md index a1efe081..c612eeae 100644 --- a/docs/configuration/configuration.md +++ b/docs/configuration/configuration.md @@ -13,6 +13,7 @@ Example usage, showing all default configuration values: ```java ExpressionConfiguration configuration = ExpressionConfiguration.builder() + .allowOverwriteConstants(true) .arraysAllowed(true) .dataAccessorSupplier(MapBasedDataAccessor::new) .decimalPlacesRounding(ExpressionConfiguration.DECIMAL_PLACES_ROUNDING_UNLIMITED) @@ -22,12 +23,18 @@ ExpressionConfiguration configuration = ExpressionConfiguration.builder() .mathContext(ExpressionConfiguration.DEFAULT_MATH_CONTEXT) .operatorDictionary(ExpressionConfiguration.StandardOperatorsDictionary) .powerOfPrecedence(OperatorIfc.OPERATOR_PRECEDENCE_POWER) + .stripTrailingZeros(true) .structuresAllowed(true) .build(); Expression expression = new Expression("2.128 + a", configuration); ``` +### Allow to Overwrite Constants + +If set to true (default), then variables can be set that have the name of a constant. In that case, +the constant value will be removed and a variable value will be set. + ### Arrays allowed Specifies if the array index function is allowed (default is true). If set to false, the expression diff --git a/src/main/java/com/ezylang/evalex/Expression.java b/src/main/java/com/ezylang/evalex/Expression.java index 5f88735d..510e4973 100644 --- a/src/main/java/com/ezylang/evalex/Expression.java +++ b/src/main/java/com/ezylang/evalex/Expression.java @@ -253,6 +253,14 @@ public void validate() throws ParseException { * @return The Expression instance, to allow chaining of methods. */ public Expression with(String variable, Object value) { + if (constants.containsKey(variable)) { + if (configuration.isAllowOverwriteConstants()) { + constants.remove(variable); + } else { + throw new UnsupportedOperationException( + String.format("Can't set value for constant '%s'", variable)); + } + } getDataAccessor().setData(variable, new EvaluationValue(value)); return this; } @@ -281,7 +289,7 @@ public Expression and(String variable, Object value) { */ public Expression withValues(Map values) { for (Map.Entry entry : values.entrySet()) { - getDataAccessor().setData(entry.getKey(), new EvaluationValue(entry.getValue())); + with(entry.getKey(), entry.getValue()); } return this; } diff --git a/src/main/java/com/ezylang/evalex/config/ExpressionConfiguration.java b/src/main/java/com/ezylang/evalex/config/ExpressionConfiguration.java index 30b88950..f3db66fa 100644 --- a/src/main/java/com/ezylang/evalex/config/ExpressionConfiguration.java +++ b/src/main/java/com/ezylang/evalex/config/ExpressionConfiguration.java @@ -270,6 +270,12 @@ public class ExpressionConfiguration { */ @Builder.Default @Getter private final boolean stripTrailingZeros = true; + /** + * If set to true (default), then variables can be set that have the name of a constant. In that + * case, the constant value will be removed and a variable value will be set. + */ + @Builder.Default @Getter private final boolean allowOverwriteConstants = true; + /** * Convenience method to create a default configuration. * diff --git a/src/test/java/com/ezylang/evalex/ExpressionEvaluatorConstantsTest.java b/src/test/java/com/ezylang/evalex/ExpressionEvaluatorConstantsTest.java index 1baedd4e..eb725a37 100644 --- a/src/test/java/com/ezylang/evalex/ExpressionEvaluatorConstantsTest.java +++ b/src/test/java/com/ezylang/evalex/ExpressionEvaluatorConstantsTest.java @@ -16,6 +16,7 @@ package com.ezylang.evalex; 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; @@ -62,4 +63,28 @@ void testCustomConstantsMixedCase() throws EvaluationException, ParseException { assertThat(expression.evaluate().getStringValue()).isEqualTo("6.4"); } + + @Test + void testOverwriteConstantsWith() throws EvaluationException, ParseException { + Expression expression = new Expression("e"); + assertThat(expression.with("e", 9).evaluate().getStringValue()).isEqualTo("9"); + } + + @Test + void testOverwriteConstantsWithValues() throws EvaluationException, ParseException { + Map values = new HashMap<>(); + values.put("E", 6); + Expression expression = new Expression("e"); + assertThat(expression.withValues(values).evaluate().getStringValue()).isEqualTo("6"); + } + + @Test + void testOverwriteConstantsNotAllowed() { + Expression expression = + new Expression( + "e", ExpressionConfiguration.builder().allowOverwriteConstants(false).build()); + assertThatThrownBy(() -> expression.with("e", 9)) + .isInstanceOf(UnsupportedOperationException.class) + .hasMessage("Can't set value for constant 'e'"); + } } diff --git a/src/test/java/com/ezylang/evalex/config/ExpressionConfigurationTest.java b/src/test/java/com/ezylang/evalex/config/ExpressionConfigurationTest.java index 31fce8f6..6a245f7d 100644 --- a/src/test/java/com/ezylang/evalex/config/ExpressionConfigurationTest.java +++ b/src/test/java/com/ezylang/evalex/config/ExpressionConfigurationTest.java @@ -53,6 +53,7 @@ void testDefaultSetup() { assertThat(configuration.getDecimalPlacesRounding()) .isEqualTo(ExpressionConfiguration.DECIMAL_PLACES_ROUNDING_UNLIMITED); assertThat(configuration.isStripTrailingZeros()).isTrue(); + assertThat(configuration.isAllowOverwriteConstants()).isTrue(); } @Test