Skip to content

Commit 0b0e73c

Browse files
fix: Add more helpers
1 parent 865aa10 commit 0b0e73c

File tree

8 files changed

+319
-0
lines changed

8 files changed

+319
-0
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package co.signal.handlebars;
2+
3+
import com.github.jknack.handlebars.Helper;
4+
import com.github.jknack.handlebars.Options;
5+
import com.google.common.collect.ImmutableList;
6+
7+
import java.io.IOException;
8+
9+
import static java.util.Arrays.asList;
10+
11+
public class ArrayHelper implements Helper<Object> {
12+
13+
@Override
14+
public Object apply(Object context, Options options) throws IOException {
15+
if (context == null || context == options.context.model()) {
16+
return ImmutableList.of();
17+
}
18+
19+
return ImmutableList.builder().add(context).addAll(asList(options.params)).build();
20+
}
21+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package co.signal.handlebars;
2+
3+
import com.github.jknack.handlebars.Helper;
4+
import com.github.jknack.handlebars.Options;
5+
import com.github.jknack.handlebars.TagType;
6+
7+
import java.io.IOException;
8+
import java.util.Collection;
9+
10+
public class ContainsHelper implements Helper<Object> {
11+
12+
@Override
13+
public Object apply(Object context, Options options) throws IOException {
14+
15+
String expected = options.param(0);
16+
17+
if (context == null || expected == null) {
18+
return false;
19+
}
20+
21+
boolean isMatch = Collection.class.isAssignableFrom(context.getClass())
22+
? ((Collection<?>) context).contains(expected)
23+
: context.toString().contains(expected);
24+
25+
if (options.tagType == TagType.SECTION) {
26+
return isMatch ? options.apply(options.fn) : "";
27+
}
28+
29+
return isMatch;
30+
}
31+
}

src/main/java/co/signal/handlebars/CustomHandlebars.java

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,62 @@ public Object apply(Object context, Options options) throws IOException {
7575
pickRandom {
7676
private final PickRandomHelper helper = new PickRandomHelper();
7777

78+
@Override
79+
public Object apply(Object context, Options options) throws IOException {
80+
return helper.apply(context, options);
81+
}
82+
},
83+
randomInt {
84+
private final RandomIntHelper helper = new RandomIntHelper();
85+
86+
@Override
87+
public Object apply(Object context, Options options) throws IOException {
88+
return helper.apply(null, options);
89+
}
90+
},
91+
randomDecimal {
92+
private final RandomDecimalHelper helper = new RandomDecimalHelper();
93+
94+
@Override
95+
public Object apply(Object context, Options options) throws IOException {
96+
return helper.apply(null, options);
97+
}
98+
},
99+
range {
100+
private final RangeHelper helper = new RangeHelper();
101+
102+
@Override
103+
public Object apply(Object context, Options options) throws IOException {
104+
return helper.apply(context, options);
105+
}
106+
},
107+
array {
108+
private final ArrayHelper helper = new ArrayHelper();
109+
110+
@Override
111+
public Object apply(Object context, Options options) throws IOException {
112+
return helper.apply(context, options);
113+
}
114+
},
115+
matches {
116+
private final MatchesRegexHelper helper = new MatchesRegexHelper();
117+
118+
@Override
119+
public Object apply(Object context, Options options) throws IOException {
120+
return helper.apply(context, options);
121+
}
122+
},
123+
contains {
124+
private final ContainsHelper helper = new ContainsHelper();
125+
126+
@Override
127+
public Object apply(Object context, Options options) throws IOException {
128+
return helper.apply(context, options);
129+
}
130+
},
131+
math {
132+
private final MathsHelper helper = new MathsHelper();
133+
78134
@Override
79135
public Object apply(Object context, Options options) throws IOException {
80136
return helper.apply(context, options);
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package co.signal.handlebars;
2+
3+
import com.github.jknack.handlebars.Helper;
4+
import com.github.jknack.handlebars.Options;
5+
import com.github.jknack.handlebars.TagType;
6+
7+
import java.io.IOException;
8+
9+
public class MatchesRegexHelper implements Helper<Object> {
10+
11+
@Override
12+
public Object apply(Object context, Options options) throws IOException {
13+
14+
String value = context.toString();
15+
String regex = options.param(0);
16+
17+
boolean isMatch = value.matches(regex);
18+
19+
if (options.tagType == TagType.SECTION) {
20+
return isMatch ? options.apply(options.fn) : "";
21+
}
22+
23+
return isMatch;
24+
}
25+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package co.signal.handlebars;
2+
3+
import com.github.jknack.handlebars.Helper;
4+
import com.github.jknack.handlebars.Options;
5+
6+
import java.io.IOException;
7+
import java.math.BigDecimal;
8+
import java.math.RoundingMode;
9+
10+
public class MathsHelper implements Helper<Object> {
11+
12+
@Override
13+
public Object apply(Object context, Options options) throws IOException {
14+
15+
BigDecimal left = coerceToBigDecimal(context);
16+
String operator = options.params[0].toString();
17+
BigDecimal right = coerceToBigDecimal(options.params[1]);
18+
19+
BigDecimal result = null;
20+
switch (operator) {
21+
case "+":
22+
result = left.add(right);
23+
break;
24+
case "-":
25+
result = left.subtract(right);
26+
break;
27+
case "*":
28+
case "x":
29+
result = left.multiply(right);
30+
break;
31+
case "/":
32+
result = left.divide(right, RoundingMode.HALF_UP);
33+
break;
34+
case "%":
35+
result = left.remainder(right);
36+
break;
37+
default:
38+
return null;
39+
}
40+
41+
return reduceToPrimitiveNumber(result);
42+
}
43+
44+
private static BigDecimal coerceToBigDecimal(Object value) {
45+
if (value instanceof Integer) {
46+
return new BigDecimal((int) value);
47+
}
48+
49+
if (value instanceof Long) {
50+
return new BigDecimal((long) value);
51+
}
52+
53+
if (value instanceof Double) {
54+
return BigDecimal.valueOf((double) value);
55+
}
56+
57+
if (value instanceof Float) {
58+
return BigDecimal.valueOf((float) value);
59+
}
60+
61+
if (value instanceof CharSequence) {
62+
return new BigDecimal(value.toString());
63+
}
64+
65+
return new BigDecimal(0);
66+
}
67+
68+
private static Object reduceToPrimitiveNumber(BigDecimal value) {
69+
if (value == null) {
70+
return null;
71+
}
72+
73+
if (value.scale() == 0) {
74+
if (value.longValue() <= Integer.MAX_VALUE) {
75+
return value.intValue();
76+
}
77+
78+
return value.longValue();
79+
}
80+
81+
return value.doubleValue();
82+
}
83+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package co.signal.handlebars;
2+
3+
import com.github.jknack.handlebars.Helper;
4+
import com.github.jknack.handlebars.Options;
5+
6+
import java.io.IOException;
7+
import java.util.concurrent.ThreadLocalRandom;
8+
9+
public class RandomDecimalHelper implements Helper<Void> {
10+
11+
@Override
12+
public Object apply(Void context, Options options) throws IOException {
13+
double lowerBound = coerceToDouble(options.hash("lower", Double.MIN_VALUE));
14+
double upperBound = coerceToDouble(options.hash("upper", Double.MAX_VALUE));
15+
16+
return ThreadLocalRandom.current().nextDouble(lowerBound, upperBound);
17+
}
18+
19+
public static Double coerceToDouble(Object value) {
20+
if (value == null) {
21+
return null;
22+
}
23+
24+
if (Number.class.isAssignableFrom(value.getClass())) {
25+
return ((Number) value).doubleValue();
26+
}
27+
28+
if (CharSequence.class.isAssignableFrom(value.getClass())) {
29+
return Double.parseDouble(value.toString());
30+
}
31+
32+
return null;
33+
}
34+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package co.signal.handlebars;
2+
3+
import com.github.jknack.handlebars.Helper;
4+
import com.github.jknack.handlebars.Options;
5+
6+
import java.io.IOException;
7+
import java.util.concurrent.ThreadLocalRandom;
8+
9+
public class RandomIntHelper implements Helper<Void> {
10+
11+
@Override
12+
public Object apply(Void context, Options options) throws IOException {
13+
int lowerBound = coerceToInt(options.hash("lower", Integer.MIN_VALUE));
14+
int upperBound = coerceToInt(options.hash("upper", Integer.MAX_VALUE));
15+
return ThreadLocalRandom.current().nextInt(lowerBound, upperBound);
16+
}
17+
18+
public static Integer coerceToInt(Object value) {
19+
if (value == null) {
20+
return null;
21+
}
22+
23+
if (Number.class.isAssignableFrom(value.getClass())) {
24+
return ((Number) value).intValue();
25+
}
26+
27+
if (CharSequence.class.isAssignableFrom(value.getClass())) {
28+
return Integer.parseInt(value.toString());
29+
}
30+
31+
return null;
32+
}
33+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package co.signal.handlebars;
2+
3+
import com.github.jknack.handlebars.Helper;
4+
import com.github.jknack.handlebars.Options;
5+
6+
import java.io.IOException;
7+
import java.util.stream.Collectors;
8+
import java.util.stream.Stream;
9+
10+
public class RangeHelper implements Helper<Object> {
11+
12+
@Override
13+
public Object apply(Object context, Options options) throws IOException {
14+
Integer lowerBound = coerceToInt(context);
15+
Integer upperBound = options.params.length > 0 ? coerceToInt(options.param(0)) : null;
16+
17+
int limit = (upperBound - lowerBound) + 1;
18+
return Stream.iterate(lowerBound, n -> n + 1).limit(limit).collect(Collectors.toList());
19+
}
20+
21+
public static Integer coerceToInt(Object value) {
22+
if (value == null) {
23+
return null;
24+
}
25+
26+
if (Number.class.isAssignableFrom(value.getClass())) {
27+
return ((Number) value).intValue();
28+
}
29+
30+
if (CharSequence.class.isAssignableFrom(value.getClass())) {
31+
return Integer.parseInt(value.toString());
32+
}
33+
34+
return null;
35+
}
36+
}

0 commit comments

Comments
 (0)