|
17 | 17 | */ |
18 | 18 | package com.github.jknack.handlebars.helper; |
19 | 19 |
|
| 20 | +import static org.apache.commons.lang3.Validate.isTrue; |
| 21 | + |
| 22 | +import java.io.IOException; |
| 23 | +import java.util.Objects; |
| 24 | + |
20 | 25 | import com.github.jknack.handlebars.Handlebars; |
21 | 26 | import com.github.jknack.handlebars.Helper; |
22 | 27 | import com.github.jknack.handlebars.Options; |
23 | 28 | import com.github.jknack.handlebars.TagType; |
24 | | -import static org.apache.commons.lang3.Validate.isTrue; |
25 | | -import org.apache.commons.lang3.builder.EqualsBuilder; |
26 | | - |
27 | | -import java.io.IOException; |
28 | 29 |
|
29 | 30 | /** |
30 | 31 | * Implementation of equals, greater, lessThan, and, or, etc.. operators. |
@@ -59,7 +60,7 @@ public enum ConditionalHelpers implements Helper<Object> { |
59 | 60 | eq { |
60 | 61 | @Override public Object apply(final Object a, final Options options) throws IOException { |
61 | 62 | Object b = options.param(0, null); |
62 | | - boolean result = new EqualsBuilder().append(a, b).isEquals(); |
| 63 | + boolean result = eq(a, b); |
63 | 64 | if (options.tagType == TagType.SECTION) { |
64 | 65 | return result ? options.fn() : options.inverse(); |
65 | 66 | } |
@@ -94,7 +95,7 @@ public enum ConditionalHelpers implements Helper<Object> { |
94 | 95 | neq { |
95 | 96 | @Override public Object apply(final Object a, final Options options) throws IOException { |
96 | 97 | Object b = options.param(0, null); |
97 | | - boolean result = !new EqualsBuilder().append(a, b).isEquals(); |
| 98 | + boolean result = !eq(a, b); |
98 | 99 | if (options.tagType == TagType.SECTION) { |
99 | 100 | return result ? options.fn() : options.inverse(); |
100 | 101 | } |
@@ -394,8 +395,46 @@ public enum ConditionalHelpers implements Helper<Object> { |
394 | 395 | * @return Int. |
395 | 396 | */ |
396 | 397 | protected int cmp(final Object a, final Object b) { |
397 | | - isTrue(a instanceof Comparable, "Not a comparable: " + a); |
398 | | - isTrue(b instanceof Comparable, "Not a comparable: " + b); |
399 | | - return ((Comparable) a).compareTo(b); |
| 398 | + try { |
| 399 | + isTrue(a instanceof Comparable, "Not a comparable: " + a); |
| 400 | + isTrue(b instanceof Comparable, "Not a comparable: " + b); |
| 401 | + return ((Comparable) a).compareTo(b); |
| 402 | + } catch (ClassCastException x) { |
| 403 | + return Double.compare(toDoubleOrError(a, x), toDoubleOrError(b, x)); |
| 404 | + } |
| 405 | + } |
| 406 | + |
| 407 | + /** |
| 408 | + * Compare two values. Number equality are treated as equals on they are like: 2 vs 2.0 |
| 409 | + * |
| 410 | + * @param a First value. |
| 411 | + * @param b Second value. |
| 412 | + * @return True when equals. |
| 413 | + */ |
| 414 | + protected boolean eq(final Object a, final Object b) { |
| 415 | + boolean value = Objects.equals(a, b); |
| 416 | + if (!value) { |
| 417 | + if (a instanceof Number && b instanceof Number) { |
| 418 | + // int vs double: 2 vs 2.0 |
| 419 | + return ((Number) a).doubleValue() == ((Number) b).doubleValue(); |
| 420 | + } |
| 421 | + } |
| 422 | + return value; |
| 423 | + } |
| 424 | + |
| 425 | + /** |
| 426 | + * Generate double from value or throw existing exception. |
| 427 | + * @param value Value to cast. |
| 428 | + * @param x Exception. |
| 429 | + * @return Double. |
| 430 | + */ |
| 431 | + private double toDoubleOrError(final Object value, final RuntimeException x) { |
| 432 | + if (value instanceof Double) { |
| 433 | + return (Double) value; |
| 434 | + } |
| 435 | + if (value instanceof Number) { |
| 436 | + return ((Number) value).doubleValue(); |
| 437 | + } |
| 438 | + throw x; |
400 | 439 | } |
401 | 440 | } |
0 commit comments