diff --git a/pom.xml b/pom.xml index 3b2274db0..0c0270af5 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ com.hubspot.jinjava jinjava - 2.3.7-SNAPSHOT + 2.4.0-SNAPSHOT Jinja templating engine implemented in Java https://github.com/HubSpot/jinjava diff --git a/src/main/java/com/hubspot/jinjava/lib/filter/FloatFilter.java b/src/main/java/com/hubspot/jinjava/lib/filter/FloatFilter.java index 866b19a7d..f5bf4e7db 100644 --- a/src/main/java/com/hubspot/jinjava/lib/filter/FloatFilter.java +++ b/src/main/java/com/hubspot/jinjava/lib/filter/FloatFilter.java @@ -1,5 +1,8 @@ package com.hubspot.jinjava.lib.filter; +import java.text.NumberFormat; +import java.util.Locale; + import org.apache.commons.lang3.math.NumberUtils; import com.hubspot.jinjava.doc.annotations.JinjavaDoc; @@ -37,11 +40,22 @@ public Object filter(Object var, JinjavaInterpreter interpreter, String... args) return defaultVal; } + if (Float.class.isAssignableFrom(var.getClass())) { + return var; + } if (Number.class.isAssignableFrom(var.getClass())) { return ((Number) var).floatValue(); } - return NumberUtils.toFloat(var.toString(), defaultVal); + Locale locale = interpreter.getConfig().getLocale(); + NumberFormat numberFormat = NumberFormat.getNumberInstance(locale); + float result; + try { + result = numberFormat.parse(var.toString()).floatValue(); + } catch (Exception e) { + result = defaultVal; + } + return result; } } diff --git a/src/main/java/com/hubspot/jinjava/lib/filter/IntFilter.java b/src/main/java/com/hubspot/jinjava/lib/filter/IntFilter.java index 1b5f7b7d6..49e55c646 100644 --- a/src/main/java/com/hubspot/jinjava/lib/filter/IntFilter.java +++ b/src/main/java/com/hubspot/jinjava/lib/filter/IntFilter.java @@ -1,5 +1,8 @@ package com.hubspot.jinjava.lib.filter; +import java.text.NumberFormat; +import java.util.Locale; + import org.apache.commons.lang3.math.NumberUtils; import com.hubspot.jinjava.doc.annotations.JinjavaDoc; @@ -8,7 +11,7 @@ import com.hubspot.jinjava.interpret.JinjavaInterpreter; /** - * int(value, default=0) Convert the value into an integer. If the conversion doesn’t work it will return 0. You can override this default using the first parameter. + * int(value, default=0) Convert the value into an integer. If the conversion doesn't work it will return 0. You can override this default using the first parameter. */ @JinjavaDoc( value = "Convert the value into an integer.", @@ -46,7 +49,16 @@ public Object filter(Object var, JinjavaInterpreter interpreter, return ((Number) var).intValue(); } - return NumberUtils.toInt(var.toString(), defaultVal); + Locale locale = interpreter.getConfig().getLocale(); + NumberFormat numberFormat = NumberFormat.getNumberInstance(locale); + numberFormat.setParseIntegerOnly(true); + int result; + try { + result = numberFormat.parse(var.toString()).intValue(); + } catch (Exception e) { + result = defaultVal; + } + return result; } } diff --git a/src/test/java/com/hubspot/jinjava/lib/filter/FloatFilterTest.java b/src/test/java/com/hubspot/jinjava/lib/filter/FloatFilterTest.java new file mode 100644 index 000000000..df9503db0 --- /dev/null +++ b/src/test/java/com/hubspot/jinjava/lib/filter/FloatFilterTest.java @@ -0,0 +1,94 @@ +/********************************************************************** + Copyright (c) 2018 HubSpot Inc. + + 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.hubspot.jinjava.lib.filter; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.nio.charset.StandardCharsets; +import java.time.ZoneOffset; +import java.util.Locale; + +import org.junit.Before; +import org.junit.Test; + +import com.hubspot.jinjava.Jinjava; +import com.hubspot.jinjava.JinjavaConfig; +import com.hubspot.jinjava.interpret.JinjavaInterpreter; + +public class FloatFilterTest { + + private static final Locale FRENCH_LOCALE = new Locale("fr", "FR"); + private static final JinjavaConfig FRENCH_LOCALE_CONFIG = new JinjavaConfig(StandardCharsets.UTF_8, FRENCH_LOCALE, ZoneOffset.UTC, 10); + + FloatFilter filter; + JinjavaInterpreter interpreter; + + @Before + public void setup() { + interpreter = new Jinjava().newInterpreter(); + filter = new FloatFilter(); + } + + @Test + public void itReturnsSameWhenVarIsNumber() { + Float var = 123.4f; + assertThat(filter.filter(var, interpreter)).isSameAs(var); + } + + @Test + public void itReturnsDefaultWhenVarIsNull() { + assertThat(filter.filter(null, interpreter)).isEqualTo(0.0f); + assertThat(filter.filter(null, interpreter, "123.45")).isEqualTo(123.45f); + } + + @Test + public void itIgnoresGivenDefaultIfNaN() { + assertThat(filter.filter(null, interpreter, "foo")).isEqualTo(0.0f); + } + + @Test + public void itReturnsVarAsFloat() { + assertThat(filter.filter("123.45", interpreter)).isEqualTo(123.45f); + } + + @Test + public void itInterpretsUsCommasAndPeriodsWithUsLocale() { + assertThat(filter.filter("123,123.45", interpreter)).isEqualTo(123123.45f); + } + + @Test + public void itInterpretsFrenchCommasAndPeriodsWithUsLocale() { + assertThat(filter.filter("123.123,45", interpreter)).isEqualTo(123.123f); + } + + @Test + public void itReturnsDefaultWhenUnableToParseVar() { + assertThat(filter.filter("foo", interpreter)).isEqualTo(0.0f); + } + + @Test + public void itInterpretsUsCommasAndPeriodsWithFrenchLocale() { + interpreter = new Jinjava(FRENCH_LOCALE_CONFIG).newInterpreter(); + assertThat(filter.filter("123,123.12", interpreter)).isEqualTo(123.123f); + } + + @Test + public void itInterpretsFrenchCommasAndPeriodsWithFrenchLocale() { + interpreter = new Jinjava(FRENCH_LOCALE_CONFIG).newInterpreter(); + assertThat(filter.filter("123\u00A0123,45", interpreter)).isEqualTo(123123.45f); + } + +} diff --git a/src/test/java/com/hubspot/jinjava/lib/filter/IntFilterTest.java b/src/test/java/com/hubspot/jinjava/lib/filter/IntFilterTest.java index 62fd7f55f..e0a3874f1 100644 --- a/src/test/java/com/hubspot/jinjava/lib/filter/IntFilterTest.java +++ b/src/test/java/com/hubspot/jinjava/lib/filter/IntFilterTest.java @@ -2,14 +2,22 @@ import static org.assertj.core.api.Assertions.assertThat; +import java.nio.charset.StandardCharsets; +import java.time.ZoneOffset; +import java.util.Locale; + import org.junit.Before; import org.junit.Test; import com.hubspot.jinjava.Jinjava; +import com.hubspot.jinjava.JinjavaConfig; import com.hubspot.jinjava.interpret.JinjavaInterpreter; public class IntFilterTest { + private static final Locale FRENCH_LOCALE = new Locale("fr", "FR"); + private static final JinjavaConfig FRENCH_LOCALE_CONFIG = new JinjavaConfig(StandardCharsets.UTF_8, FRENCH_LOCALE, ZoneOffset.UTC, 10); + IntFilter filter; JinjavaInterpreter interpreter; @@ -21,7 +29,7 @@ public void setup() { @Test public void itReturnsSameWhenVarIsNumber() { - Integer var = Integer.valueOf(123); + Integer var = 123; assertThat(filter.filter(var, interpreter)).isSameAs(var); } @@ -41,9 +49,31 @@ public void itReturnsVarAsInt() { assertThat(filter.filter("123", interpreter)).isEqualTo(123); } + @Test + public void itInterpretsUsCommasAndPeriodsWithUsLocale() { + assertThat(filter.filter("123,123.12", interpreter)).isEqualTo(123123); + } + + @Test + public void itInterpretsFrenchCommasAndPeriodsWithUsLocale() { + assertThat(filter.filter("123.123,12", interpreter)).isEqualTo(123); + } + @Test public void itReturnsDefaultWhenUnableToParseVar() { assertThat(filter.filter("foo", interpreter)).isEqualTo(0); } + @Test + public void itInterpretsUsCommasAndPeriodsWithFrenchLocale() { + interpreter = new Jinjava(FRENCH_LOCALE_CONFIG).newInterpreter(); + assertThat(filter.filter("123,123.12", interpreter)).isEqualTo(123); + } + + @Test + public void itInterpretsFrenchCommasAndPeriodsWithFrenchLocale() { + interpreter = new Jinjava(FRENCH_LOCALE_CONFIG).newInterpreter(); + assertThat(filter.filter("123\u00A0123,12", interpreter)).isEqualTo(123123); + } + }