From 63be60dc99559c478d7735014cd3339bd5f44920 Mon Sep 17 00:00:00 2001 From: Ruslan Onyshkevych Date: Fri, 29 Mar 2024 15:52:19 -0400 Subject: [PATCH 1/3] add more lenient string parsing --- .../jinjava/el/TruthyTypeConverter.java | 58 +++++++++++++++++++ .../lib/exptest/ComparisonExpTestsTest.java | 11 ++++ 2 files changed, 69 insertions(+) diff --git a/src/main/java/com/hubspot/jinjava/el/TruthyTypeConverter.java b/src/main/java/com/hubspot/jinjava/el/TruthyTypeConverter.java index 25babab14..9caedb0d2 100644 --- a/src/main/java/com/hubspot/jinjava/el/TruthyTypeConverter.java +++ b/src/main/java/com/hubspot/jinjava/el/TruthyTypeConverter.java @@ -33,6 +33,12 @@ protected BigDecimal coerceToBigDecimal(Object value) { if (value instanceof DummyObject) { return BigDecimal.ZERO; } + + if (value instanceof String) { + String sanitizedValue = trimDecimal(trimCommas((String) value)); + return super.coerceToBigDecimal(sanitizedValue); + } + return super.coerceToBigDecimal(value); } @@ -41,6 +47,12 @@ protected BigInteger coerceToBigInteger(Object value) { if (value instanceof DummyObject) { return BigInteger.ZERO; } + + if (value instanceof String) { + String sanitizedValue = trimDecimal(trimCommas((String) value)); + return super.coerceToBigInteger(sanitizedValue); + } + return super.coerceToBigInteger(value); } @@ -49,6 +61,12 @@ protected Double coerceToDouble(Object value) { if (value instanceof DummyObject) { return 0d; } + + if (value instanceof String) { + String sanitizedValue = trimCommas((String) value); + return super.coerceToDouble(sanitizedValue); + } + return super.coerceToDouble(value); } @@ -57,6 +75,12 @@ protected Float coerceToFloat(Object value) { if (value instanceof DummyObject) { return 0f; } + + if (value instanceof String) { + String sanitizedValue = trimDecimal(trimCommas((String) value)); + return super.coerceToFloat(sanitizedValue); + } + return super.coerceToFloat(value); } @@ -65,14 +89,38 @@ protected Long coerceToLong(Object value) { if (value instanceof DummyObject) { return 0L; } + + if (value instanceof String) { + String sanitizedValue = trimDecimal(trimCommas((String) value)); + return super.coerceToLong(sanitizedValue); + } return super.coerceToLong(value); } + private String trimCommas(String value) { + if (!value.contains(",")) { + return value; + } + return value.replaceAll(",", ""); + } + + private String trimDecimal(String value) { + if (!value.contains(".")) { + return value; + } + return value.substring(0, value.indexOf(".")); + } + @Override protected Integer coerceToInteger(Object value) { if (value instanceof DummyObject) { return 0; } + + if (value instanceof String) { + String sanitizedValue = trimDecimal(trimCommas((String) value)); + return super.coerceToInteger(sanitizedValue); + } return super.coerceToInteger(value); } @@ -81,6 +129,11 @@ protected Short coerceToShort(Object value) { if (value instanceof DummyObject) { return 0; } + + if (value instanceof String) { + String sanitizedValue = trimDecimal(trimCommas((String) value)); + return super.coerceToShort(sanitizedValue); + } return super.coerceToShort(value); } @@ -89,6 +142,11 @@ protected Byte coerceToByte(Object value) { if (value instanceof DummyObject) { return 0; } + if (value instanceof String) { + String sanitizedValue = trimDecimal(trimCommas((String) value)); + return super.coerceToByte(sanitizedValue); + } + return super.coerceToByte(value); } diff --git a/src/test/java/com/hubspot/jinjava/lib/exptest/ComparisonExpTestsTest.java b/src/test/java/com/hubspot/jinjava/lib/exptest/ComparisonExpTestsTest.java index f2dd38e64..2a58dcfca 100644 --- a/src/test/java/com/hubspot/jinjava/lib/exptest/ComparisonExpTestsTest.java +++ b/src/test/java/com/hubspot/jinjava/lib/exptest/ComparisonExpTestsTest.java @@ -66,4 +66,15 @@ public void testAliases() { assertThat(jinjava.render("{{ 4 is >= 5 }}", new HashMap<>())).isEqualTo("false"); assertThat(jinjava.render("{{ 4 is != 5 }}", new HashMap<>())).isEqualTo("true"); } + + @Test + public void testFormattedStringParsing() { + assertThat(jinjava.render("{{ \"1,050.25\" is ge 4 }}", new HashMap<>())) + .isEqualTo("true"); + assertThat(jinjava.render("{{ \"4.1\" is gt 4 }}", new HashMap<>())) + .isEqualTo("false"); + assertThat(jinjava.render("{{ 4.0 is le 5.00 }}", new HashMap<>())).isEqualTo("true"); + assertThat(jinjava.render("{{ \"4,500.75\" is le 10000.00 }}", new HashMap<>())) + .isEqualTo("true"); + } } From 36f752a2b137bc4821357b2a3702e8ecca51f6cc Mon Sep 17 00:00:00 2001 From: Ruslan Onyshkevych Date: Sun, 31 Mar 2024 21:00:59 -0400 Subject: [PATCH 2/3] fix float parsing and move functions --- .../jinjava/el/TruthyTypeConverter.java | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/hubspot/jinjava/el/TruthyTypeConverter.java b/src/main/java/com/hubspot/jinjava/el/TruthyTypeConverter.java index 9caedb0d2..b37e35497 100644 --- a/src/main/java/com/hubspot/jinjava/el/TruthyTypeConverter.java +++ b/src/main/java/com/hubspot/jinjava/el/TruthyTypeConverter.java @@ -35,7 +35,7 @@ protected BigDecimal coerceToBigDecimal(Object value) { } if (value instanceof String) { - String sanitizedValue = trimDecimal(trimCommas((String) value)); + String sanitizedValue = trimCommas((String) value); return super.coerceToBigDecimal(sanitizedValue); } @@ -77,7 +77,7 @@ protected Float coerceToFloat(Object value) { } if (value instanceof String) { - String sanitizedValue = trimDecimal(trimCommas((String) value)); + String sanitizedValue = trimCommas((String) value); return super.coerceToFloat(sanitizedValue); } @@ -97,20 +97,6 @@ protected Long coerceToLong(Object value) { return super.coerceToLong(value); } - private String trimCommas(String value) { - if (!value.contains(",")) { - return value; - } - return value.replaceAll(",", ""); - } - - private String trimDecimal(String value) { - if (!value.contains(".")) { - return value; - } - return value.substring(0, value.indexOf(".")); - } - @Override protected Integer coerceToInteger(Object value) { if (value instanceof DummyObject) { @@ -150,6 +136,20 @@ protected Byte coerceToByte(Object value) { return super.coerceToByte(value); } + private String trimCommas(String value) { + if (!value.contains(",")) { + return value; + } + return value.replaceAll(",", ""); + } + + private String trimDecimal(String value) { + if (!value.contains(".")) { + return value; + } + return value.substring(0, value.indexOf(".")); + } + @Override protected String coerceToString(Object value) { if (value instanceof DummyObject) { From 16c40b8834862ca0ea13785f07d0cb63dd21af29 Mon Sep 17 00:00:00 2001 From: Ruslan Onyshkevych Date: Sun, 31 Mar 2024 21:41:41 -0400 Subject: [PATCH 3/3] do not allow extra characters after decimals --- .../jinjava/el/TruthyTypeConverter.java | 8 ++++++++ .../lib/exptest/ComparisonExpTestsTest.java | 18 +++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/hubspot/jinjava/el/TruthyTypeConverter.java b/src/main/java/com/hubspot/jinjava/el/TruthyTypeConverter.java index b37e35497..14ad09082 100644 --- a/src/main/java/com/hubspot/jinjava/el/TruthyTypeConverter.java +++ b/src/main/java/com/hubspot/jinjava/el/TruthyTypeConverter.java @@ -140,6 +140,10 @@ private String trimCommas(String value) { if (!value.contains(",")) { return value; } + + if (value.matches(".*\\..*,.*")) { + return value; + } return value.replaceAll(",", ""); } @@ -147,6 +151,10 @@ private String trimDecimal(String value) { if (!value.contains(".")) { return value; } + + if (!value.matches("\\d*\\.\\d*")) { + return value; + } return value.substring(0, value.indexOf(".")); } diff --git a/src/test/java/com/hubspot/jinjava/lib/exptest/ComparisonExpTestsTest.java b/src/test/java/com/hubspot/jinjava/lib/exptest/ComparisonExpTestsTest.java index 2a58dcfca..6992b57fa 100644 --- a/src/test/java/com/hubspot/jinjava/lib/exptest/ComparisonExpTestsTest.java +++ b/src/test/java/com/hubspot/jinjava/lib/exptest/ComparisonExpTestsTest.java @@ -1,13 +1,17 @@ package com.hubspot.jinjava.lib.exptest; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.google.common.collect.ImmutableMap; import com.hubspot.jinjava.BaseJinjavaTest; +import com.hubspot.jinjava.interpret.FatalTemplateErrorsException; import com.hubspot.jinjava.objects.date.PyishDate; import java.time.Instant; import java.util.HashMap; import java.util.Map; +import javax.el.ELException; +import javax.el.MethodNotFoundException; import org.junit.Test; public class ComparisonExpTestsTest extends BaseJinjavaTest { @@ -68,7 +72,7 @@ public void testAliases() { } @Test - public void testFormattedStringParsing() { + public void itParsesFormattedNumbers() { assertThat(jinjava.render("{{ \"1,050.25\" is ge 4 }}", new HashMap<>())) .isEqualTo("true"); assertThat(jinjava.render("{{ \"4.1\" is gt 4 }}", new HashMap<>())) @@ -77,4 +81,16 @@ public void testFormattedStringParsing() { assertThat(jinjava.render("{{ \"4,500.75\" is le 10000.00 }}", new HashMap<>())) .isEqualTo("true"); } + + @Test + public void itDoesNotAllowCommasAfterDecimalPointInNumbers() { + assertThat( + jinjava.renderForResult("{{ \"150.25,0\" is ge 4 }}", new HashMap<>()).getErrors() + ) + .isNotEmpty(); + assertThat( + jinjava.renderForResult("{{ \"150.25,0\" is ge 4.0 }}", new HashMap<>()).getErrors() + ) + .isNotEmpty(); + } }