Skip to content

Commit 56e53f3

Browse files
committed
conditional helpers throw ClassCastExceptions when arguments are different classes fix #827
1 parent beee81a commit 56e53f3

2 files changed

Lines changed: 71 additions & 9 deletions

File tree

handlebars/src/main/java/com/github/jknack/handlebars/helper/ConditionalHelpers.java

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,15 @@
1717
*/
1818
package com.github.jknack.handlebars.helper;
1919

20+
import static org.apache.commons.lang3.Validate.isTrue;
21+
22+
import java.io.IOException;
23+
import java.util.Objects;
24+
2025
import com.github.jknack.handlebars.Handlebars;
2126
import com.github.jknack.handlebars.Helper;
2227
import com.github.jknack.handlebars.Options;
2328
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;
2829

2930
/**
3031
* Implementation of equals, greater, lessThan, and, or, etc.. operators.
@@ -59,7 +60,7 @@ public enum ConditionalHelpers implements Helper<Object> {
5960
eq {
6061
@Override public Object apply(final Object a, final Options options) throws IOException {
6162
Object b = options.param(0, null);
62-
boolean result = new EqualsBuilder().append(a, b).isEquals();
63+
boolean result = eq(a, b);
6364
if (options.tagType == TagType.SECTION) {
6465
return result ? options.fn() : options.inverse();
6566
}
@@ -94,7 +95,7 @@ public enum ConditionalHelpers implements Helper<Object> {
9495
neq {
9596
@Override public Object apply(final Object a, final Options options) throws IOException {
9697
Object b = options.param(0, null);
97-
boolean result = !new EqualsBuilder().append(a, b).isEquals();
98+
boolean result = !eq(a, b);
9899
if (options.tagType == TagType.SECTION) {
99100
return result ? options.fn() : options.inverse();
100101
}
@@ -394,8 +395,46 @@ public enum ConditionalHelpers implements Helper<Object> {
394395
* @return Int.
395396
*/
396397
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;
400439
}
401440
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.github.jknack.handlebars;
2+
3+
import java.io.IOException;
4+
5+
import org.junit.Test;
6+
7+
import com.github.jknack.handlebars.helper.ConditionalHelpers;
8+
9+
public class Issue827 extends v4Test {
10+
11+
@Override protected void configure(Handlebars handlebars) {
12+
handlebars.registerHelpers(ConditionalHelpers.class);
13+
}
14+
15+
@Test
16+
public void shouldIgnoreDifferentNumTypes() throws IOException {
17+
shouldCompileTo("{{gt 5 2.0}}", $(), "true");
18+
19+
shouldCompileTo("{{eq 5 2.0}}", $(), "false");
20+
21+
shouldCompileTo("{{eq 2 2.0}}", $(), "true");
22+
}
23+
}

0 commit comments

Comments
 (0)