From 58406a94e694808d0f953df9d7e97747cf37bd3b Mon Sep 17 00:00:00 2001 From: Udo Klimaschewski Date: Sat, 25 Mar 2023 14:12:12 +0100 Subject: [PATCH] - fixes bug with usage of array index on quoted structure property (#369) * fixes bug with usage of array index on quoted structure property * documents how to use quoted names of structure elements, that contain spaces in their names * disables local CI sonar checks, uses SonarCloud automatic analysis * adds JaCoCo code coverage check to pom.xml and build.yml, removes sonar code coverage badge --- .github/workflows/build.yml | 4 +- README.md | 3 +- docs/concepts/datatypes.md | 29 ++++++++++++++ docs/index.md | 2 +- pom.xml | 26 +++++++++++++ .../com/ezylang/evalex/parser/Tokenizer.java | 1 + .../ExpressionEvaluatorStructureTest.java | 38 +++++++++++++++++++ 7 files changed, 99 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6fe0ecd..bb8fe2b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,7 +25,9 @@ jobs: distribution: 'corretto' cache: maven - name: Verify and analyze with SonarCloud - run: mvn --batch-mode verify sonar:sonar -Dsonar.projectKey=ezylang_EvalEx -Dsonar.organization=ezylang -Dsonar.host.url=https://sonarcloud.io -Dsonar.coverage.jacoco.xmlReportPaths=/home/runner/work/EvalEx/EvalEx/target/site/jacoco/jacoco.xml + ## automatic analysis is enabled in SonarCloud, so it is disabled here + ## run: mvn --batch-mode verify sonar:sonar -Dsonar.projectKey=ezylang_EvalEx -Dsonar.organization=ezylang -Dsonar.host.url=https://sonarcloud.io -Dsonar.coverage.jacoco.xmlReportPaths=/home/runner/work/EvalEx/EvalEx/target/site/jacoco/jacoco.xml + run: mvn --batch-mode clean verify env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} \ No newline at end of file diff --git a/README.md b/README.md index 942d1aa..d1bf59c 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,6 @@ EvalEx - Java Expression Evaluator [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=ezylang_EvalEx&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=ezylang_EvalEx) [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=ezylang_EvalEx&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=ezylang_EvalEx) [![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=ezylang_EvalEx&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=ezylang_EvalEx) -[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=ezylang_EvalEx&metric=coverage)](https://sonarcloud.io/summary/new_code?id=ezylang_EvalEx) [![Maven Central](https://img.shields.io/maven-central/v/com.ezylang/EvalEx.svg?label=Maven%20Central)](https://search.maven.org/search?q=a:%22EvalEx%22) | :warning: Version 3 of EvalEx is a complete rewrite of the popular expression evaluator. See [the new documentation area](https://ezylang.github.io/EvalEx/concepts/changes.html) for an overview of the changes. | @@ -174,7 +173,7 @@ big-math to EvalEx. ## Author and License -Copyright 2012-2022 by Udo Klimaschewski +Copyright 2012-2023 by Udo Klimaschewski **Thanks to all who contributed to this project: [Contributors](https://github.com/ezylang/EvalEx/graphs/contributors)** diff --git a/docs/concepts/datatypes.md b/docs/concepts/datatypes.md index c45615e..2534728 100644 --- a/docs/concepts/datatypes.md +++ b/docs/concepts/datatypes.md @@ -129,6 +129,35 @@ BigDecimal result = expression.evaluate().getNumberValue(); System.out.println(result); // prints 44.85 ``` +#### Structure elements containing spaces in name +If your structure has element names that contain spaces, you can use double quotes in the expression to access them. + +```java +Map data = new HashMap<>(); +data.put("property 1", 12345); + +Expression expression = new Expression("data.\"property 1\"") + .with("data", data); + +BigDecimal result = expression.evaluate().getNumberValue(); + +System.out.println(result); // prints 12345 +``` + +This also works with arrays. + +```java +Map data = new HashMap<>(); +data.put("property 1", Arrays.asList(1, 2, 3)); + +Expression expression = new Expression("data.\"property 1\"[1]") + .with("data", data); + +BigDecimal result = expression.evaluate().getNumberValue(); + +System.out.println(result); // prints 2 +``` + ### EXPRESSION_NODE A string expression is converted into an abstract syntax tree (AST), which represents the expression diff --git a/docs/index.md b/docs/index.md index 0af82c3..2719777 100644 --- a/docs/index.md +++ b/docs/index.md @@ -163,7 +163,7 @@ big-math to EvalEx. ## Author and License -Copyright 2012-2022 by Udo Klimaschewski +Copyright 2012-2023 by Udo Klimaschewski **Thanks to all who contributed to this project: [Contributors](https://github.com/ezylang/EvalEx/graphs/contributors)** diff --git a/pom.xml b/pom.xml index b2cbbf5..d4835b9 100644 --- a/pom.xml +++ b/pom.xml @@ -156,6 +156,32 @@ prepare-agent + + check + prepare-package + + check + + + + + BUNDLE + + + INSTRUCTION + COVEREDRATIO + 1.0 + + + CLASS + MISSEDCOUNT + 0 + + + + + + report prepare-package diff --git a/src/main/java/com/ezylang/evalex/parser/Tokenizer.java b/src/main/java/com/ezylang/evalex/parser/Tokenizer.java index 3a6a23b..abb2085 100644 --- a/src/main/java/com/ezylang/evalex/parser/Tokenizer.java +++ b/src/main/java/com/ezylang/evalex/parser/Tokenizer.java @@ -268,6 +268,7 @@ public class Tokenizer { case BRACE_CLOSE: case VARIABLE_OR_CONSTANT: case ARRAY_CLOSE: + case STRING_LITERAL: return false; default: return true; diff --git a/src/test/java/com/ezylang/evalex/ExpressionEvaluatorStructureTest.java b/src/test/java/com/ezylang/evalex/ExpressionEvaluatorStructureTest.java index 9420984..9e144ab 100644 --- a/src/test/java/com/ezylang/evalex/ExpressionEvaluatorStructureTest.java +++ b/src/test/java/com/ezylang/evalex/ExpressionEvaluatorStructureTest.java @@ -20,7 +20,9 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.ezylang.evalex.parser.ParseException; import java.math.BigDecimal; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.junit.jupiter.api.Test; @@ -106,4 +108,40 @@ class ExpressionEvaluatorStructureTest extends BaseExpressionEvaluatorTest { .extracting("startPosition") .isEqualTo(14); } + + @Test + void testStructureWithSpaceInName() throws EvaluationException, ParseException { + Map testStructure = new HashMap<>(); + testStructure.put("field 1", new BigDecimal(88)); + + Expression expression = createExpression("a.\"field 1\"").with("a", testStructure); + + assertThat(expression.evaluate().getStringValue()).isEqualTo("88"); + } + + @Test + void testTripleStructureWithSpaces() throws ParseException, EvaluationException { + Map structure = new HashMap<>(); + Map subStructure = new HashMap<>(); + subStructure.put("prop c", 99); + structure.put("prop b", List.of(subStructure)); + + Expression expression = createExpression("a.\"prop b\"[0].\"prop c\"").with("a", structure); + + assertThat(expression.evaluate().getStringValue()).isEqualTo("99"); + } + + @Test + void testStructureWithSpaceInNameAndArrayAccess() throws EvaluationException, ParseException { + Map> structure = + new HashMap<>() { + { + put("b prop", Arrays.asList(1, 2, 3)); + } + }; + + Expression expression = createExpression("a.\"b prop\"[1]").with("a", structure); + + assertThat(expression.evaluate().getStringValue()).isEqualTo("2"); + } } -- 2.51.2