diff --git a/src/main/java/liqp/LValue.java b/src/main/java/liqp/LValue.java index 0fead747..b09ad898 100644 --- a/src/main/java/liqp/LValue.java +++ b/src/main/java/liqp/LValue.java @@ -279,16 +279,16 @@ public BigDecimal asStrictNumber(Object number) { if (number == null) { return null; } - if (number instanceof BigDecimal) { - return (BigDecimal) number; + if (number instanceof PlainBigDecimal) { + return (PlainBigDecimal) number; } - return new BigDecimal(number.toString().trim()); + return new PlainBigDecimal(number.toString().trim()); } // mimic ruby's `BigDecimal.to_f` with standard java capabilities // same time provide expected out for java.math.BigDecimal - public static String asFormattedNumber(BigDecimal bd) { - return bd.setScale(Math.max(1, bd.stripTrailingZeros().scale()), RoundingMode.UNNECESSARY).toPlainString(); + public static BigDecimal asFormattedNumber(BigDecimal bd) { + return bd.setScale(Math.max(1, bd.stripTrailingZeros().scale()), RoundingMode.UNNECESSARY); } /** diff --git a/src/main/java/liqp/PlainBigDecimal.java b/src/main/java/liqp/PlainBigDecimal.java new file mode 100644 index 00000000..a833c63c --- /dev/null +++ b/src/main/java/liqp/PlainBigDecimal.java @@ -0,0 +1,22 @@ +package liqp; + +import java.math.BigDecimal; + +/** + * A {@link BigDecimal} with a {@link #toString()} method that is equivalent to calling + * {@link #toPlainString()}. + * + * @author Christian Kohlschütter + */ +public final class PlainBigDecimal extends BigDecimal { + private static final long serialVersionUID = 1L; + + public PlainBigDecimal(String val) { + super(val); + } + + @Override + public String toString() { + return toPlainString(); + } +} diff --git a/src/main/java/liqp/filters/Abs.java b/src/main/java/liqp/filters/Abs.java index 67f9e2ea..97bf33e9 100644 --- a/src/main/java/liqp/filters/Abs.java +++ b/src/main/java/liqp/filters/Abs.java @@ -1,6 +1,6 @@ package liqp.filters; -import java.math.BigDecimal; +import liqp.PlainBigDecimal; public class Abs extends Filter { @@ -29,7 +29,7 @@ public Object apply(Object value, Object... params) { } if (super.isNumber(value) || super.canBeDouble(value)) { - return asFormattedNumber(new BigDecimal(super.asNumber(value).toString()).abs()); + return asFormattedNumber(new PlainBigDecimal(super.asNumber(value).toString()).abs()); } return 0; diff --git a/src/main/java/liqp/filters/Minus.java b/src/main/java/liqp/filters/Minus.java index 1657a1b7..583d290c 100644 --- a/src/main/java/liqp/filters/Minus.java +++ b/src/main/java/liqp/filters/Minus.java @@ -2,6 +2,8 @@ import java.math.BigDecimal; +import liqp.PlainBigDecimal; + public class Minus extends Filter { /* @@ -24,8 +26,8 @@ public Object apply(Object value, Object... params) { return super.asNumber(value).longValue() - super.asNumber(rhsObj).longValue(); } - BigDecimal first = new BigDecimal(super.asNumber(value).toString()); - BigDecimal second = new BigDecimal(super.asNumber(rhsObj).toString()); + BigDecimal first = new PlainBigDecimal(super.asNumber(value).toString()); + BigDecimal second = new PlainBigDecimal(super.asNumber(rhsObj).toString()); return asFormattedNumber(first.subtract(second)); } } diff --git a/src/main/java/liqp/filters/Modulo.java b/src/main/java/liqp/filters/Modulo.java index 01ae5f43..0d3c7957 100644 --- a/src/main/java/liqp/filters/Modulo.java +++ b/src/main/java/liqp/filters/Modulo.java @@ -2,6 +2,7 @@ import java.math.BigDecimal; +import liqp.PlainBigDecimal; import liqp.TemplateContext; public class Modulo extends Filter { @@ -26,8 +27,8 @@ public Object apply(Object value, TemplateContext context, Object... params) { return super.asNumber(value).longValue() % super.asNumber(rhsObj).longValue(); } - BigDecimal first = new BigDecimal(super.asNumber(value).toString()); - BigDecimal second = new BigDecimal(super.asNumber(rhsObj).toString()); + BigDecimal first = new PlainBigDecimal(super.asNumber(value).toString()); + BigDecimal second = new PlainBigDecimal(super.asNumber(rhsObj).toString()); return asFormattedNumber(first.remainder(second)); } } diff --git a/src/main/java/liqp/filters/Plus.java b/src/main/java/liqp/filters/Plus.java index 678f472c..e8bbde92 100644 --- a/src/main/java/liqp/filters/Plus.java +++ b/src/main/java/liqp/filters/Plus.java @@ -2,6 +2,8 @@ import java.math.BigDecimal; +import liqp.PlainBigDecimal; + public class Plus extends Filter { /* @@ -23,8 +25,8 @@ public Object apply(Object value, Object... params) { if (super.canBeInteger(value) && super.canBeInteger(rhsObj)) { return super.asNumber(value).longValue() + super.asNumber(rhsObj).longValue(); } - BigDecimal first = new BigDecimal(super.asNumber(value).toString()); - BigDecimal second = new BigDecimal(super.asNumber(rhsObj).toString()); + BigDecimal first = new PlainBigDecimal(super.asNumber(value).toString()); + BigDecimal second = new PlainBigDecimal(super.asNumber(rhsObj).toString()); return asFormattedNumber(first.add(second)); } } diff --git a/src/main/java/liqp/filters/Round.java b/src/main/java/liqp/filters/Round.java index 03737c4c..f089a776 100644 --- a/src/main/java/liqp/filters/Round.java +++ b/src/main/java/liqp/filters/Round.java @@ -1,9 +1,10 @@ package liqp.filters; -import java.math.BigDecimal; import java.math.RoundingMode; import java.text.DecimalFormat; +import liqp.PlainBigDecimal; + public class Round extends Filter { @Override @@ -32,6 +33,6 @@ public Object apply(Object value, Object... params) { DecimalFormat formatter = new DecimalFormat(formatBuilder.toString()); formatter.setRoundingMode(RoundingMode.HALF_UP); - return new BigDecimal(formatter.format(number)); + return new PlainBigDecimal(formatter.format(number)); } } diff --git a/src/main/java/liqp/filters/Times.java b/src/main/java/liqp/filters/Times.java index 9d898da3..0be4932a 100644 --- a/src/main/java/liqp/filters/Times.java +++ b/src/main/java/liqp/filters/Times.java @@ -2,6 +2,8 @@ import java.math.BigDecimal; +import liqp.PlainBigDecimal; + public class Times extends Filter { /* @@ -24,8 +26,8 @@ public Object apply(Object value, Object... params) { return super.asNumber(value).longValue() * super.asNumber(rhsObj).longValue(); } - BigDecimal first = new BigDecimal(super.asNumber(value).toString()); - BigDecimal second = new BigDecimal(super.asNumber(rhsObj).toString()); + BigDecimal first = new PlainBigDecimal(super.asNumber(value).toString()); + BigDecimal second = new PlainBigDecimal(super.asNumber(rhsObj).toString()); return first.multiply(second); } } diff --git a/src/main/java/liqp/nodes/ContainsNode.java b/src/main/java/liqp/nodes/ContainsNode.java index f9a5aee4..4923bbf1 100644 --- a/src/main/java/liqp/nodes/ContainsNode.java +++ b/src/main/java/liqp/nodes/ContainsNode.java @@ -1,11 +1,11 @@ package liqp.nodes; -import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import liqp.LValue; +import liqp.PlainBigDecimal; import liqp.TemplateContext; import liqp.parser.Inspectable; import liqp.parser.LiquidSupport; @@ -51,7 +51,7 @@ public Object render(TemplateContext context) { private Object toSingleNumberType(Object needle) { if (needle instanceof Number) { - needle = LValue.asFormattedNumber(new BigDecimal(needle.toString())); + needle = LValue.asFormattedNumber(new PlainBigDecimal(needle.toString())); } return needle; } @@ -60,7 +60,7 @@ private List toSingleNumberType(List asList) { ArrayList res = new ArrayList<>(asList.size()); for(Object item: asList) { if (item instanceof Number) { - res.add(LValue.asFormattedNumber(new BigDecimal(item.toString()))); + res.add(LValue.asFormattedNumber(new PlainBigDecimal(item.toString()))); } else { res.add(item); } diff --git a/src/main/java/liqp/nodes/OutputNode.java b/src/main/java/liqp/nodes/OutputNode.java index 0b60e916..558122b6 100644 --- a/src/main/java/liqp/nodes/OutputNode.java +++ b/src/main/java/liqp/nodes/OutputNode.java @@ -1,5 +1,6 @@ package liqp.nodes; +import liqp.PlainBigDecimal; import liqp.TemplateContext; import liqp.TemplateParser; import liqp.exceptions.LiquidException; @@ -51,12 +52,12 @@ public Object render(TemplateContext context) { } context.addError(new LiquidException("unexpected output: " + localUnparsed, unparsedline, unparsedPosition, null)); } - } - if (value instanceof BigDecimal) { - value = ((BigDecimal) value).toPlainString(); + if (value instanceof BigDecimal && !(value instanceof PlainBigDecimal)) { + value = new PlainBigDecimal(value.toString()); } + return value; } } diff --git a/src/test/java/liqp/filters/TimesTest.java b/src/test/java/liqp/filters/TimesTest.java index 3426ef34..2438a535 100644 --- a/src/test/java/liqp/filters/TimesTest.java +++ b/src/test/java/liqp/filters/TimesTest.java @@ -5,15 +5,16 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import liqp.LValue; +import java.math.BigDecimal; + import org.antlr.v4.runtime.RecognitionException; import org.junit.Test; +import liqp.LValue; +import liqp.PlainBigDecimal; import liqp.Template; import liqp.TemplateParser; -import java.math.BigDecimal; - public class TimesTest { @Test @@ -71,8 +72,11 @@ public void applyoriginaltest() { assertThat(filter.apply(3L, 4L), is((Object)12L)); // assert_template_result "0", "{{ 'foo' | times:4 }}" // see: applyTest() assertTrue(String.valueOf(filter.apply(2.1, 3L)).matches("6[.,]3")); - assertEquals("7.25", LValue.asFormattedNumber((BigDecimal) filter.apply(0.0725, 100))); - assertEquals("-7.25", LValue.asFormattedNumber((BigDecimal) filter.apply(-0.0725, 100))); - assertEquals("7.25", LValue.asFormattedNumber((BigDecimal) filter.apply(-0.0725, -100))); + assertEquals(new PlainBigDecimal("7.25"), LValue.asFormattedNumber((BigDecimal) filter.apply( + 0.0725, 100))); + assertEquals(new PlainBigDecimal("-7.25"), LValue.asFormattedNumber((BigDecimal) filter.apply( + -0.0725, 100))); + assertEquals(new PlainBigDecimal("7.25"), LValue.asFormattedNumber((BigDecimal) filter.apply( + -0.0725, -100))); } } diff --git a/src/test/java/liqp/nodes/GtNodeTest.java b/src/test/java/liqp/nodes/GtNodeTest.java index 4cb2d34e..c336b71c 100644 --- a/src/test/java/liqp/nodes/GtNodeTest.java +++ b/src/test/java/liqp/nodes/GtNodeTest.java @@ -15,14 +15,14 @@ import java.util.List; import java.util.Map; -import liqp.exceptions.LiquidException; -import liqp.parser.Flavor; import org.antlr.v4.runtime.RecognitionException; import org.junit.Test; import liqp.Template; import liqp.TemplateParser; import liqp.TemplateTest; +import liqp.exceptions.LiquidException; +import liqp.parser.Flavor; import liqp.parser.Inspectable; public class GtNodeTest { @@ -126,4 +126,12 @@ public void testBug267StringVsNumber() { assertTrue(e.getMessage().contains("not the same type")); } } + + @Test + public void testFilterCompare() { + String result = new TemplateParser.Builder().withFlavor(Flavor.JEKYLL).build() // + .parse("{% assign score = 0 | plus: 1.0 %}{% if score > 0 %}true{% else %}false{% endif %}") + .render(); + assertTrue(Boolean.parseBoolean(result)); + } }