Skip to content

Commit 0c286a3

Browse files
authored
Merge pull request #42 from avaje/feature/digits
Support for Digits, Positive, Negative, Min, Max
2 parents cc5b967 + be23e8d commit 0c286a3

File tree

4 files changed

+176
-21
lines changed

4 files changed

+176
-21
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package example.jakarta;
2+
3+
import jakarta.validation.Valid;
4+
import jakarta.validation.constraints.*;
5+
6+
@Valid
7+
public class JNums {
8+
9+
@Digits(integer = 5, fraction = 3)
10+
public String digits = "1234.12";
11+
12+
@Positive
13+
public int positive = 3;
14+
15+
@PositiveOrZero
16+
public int positiveOrZero = 0;
17+
18+
@Negative
19+
public int negative = -3;
20+
21+
@NegativeOrZero
22+
public int negativeOrZero = 0;
23+
24+
@Max(20)
25+
public int max = 0;
26+
27+
@Min(5)
28+
public int min = 6;
29+
30+
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package example.jakarta;
2+
3+
import io.avaje.validation.ConstraintViolation;
4+
import io.avaje.validation.ConstraintViolationException;
5+
import io.avaje.validation.Validator;
6+
import org.junit.jupiter.api.Test;
7+
8+
import java.util.ArrayList;
9+
import java.util.Locale;
10+
11+
import static org.assertj.core.api.Assertions.assertThat;
12+
import static org.assertj.core.api.Assertions.fail;
13+
14+
class JNumsTest {
15+
16+
final Validator validator = Validator.builder().build();
17+
18+
@Test
19+
void valid() {
20+
validator.validate(new JNums());
21+
}
22+
23+
@Test
24+
void digits() {
25+
var bean = new JNums();
26+
bean.digits = "12345678";
27+
var violation = one(bean);
28+
assertThat(violation.message()).isEqualTo("numeric value out of bounds (<5 digits>.<3 digits> expected)");
29+
}
30+
31+
@Test
32+
void digitsDE() {
33+
var bean = new JNums();
34+
bean.digits = "12345678";
35+
var violation = one(bean, Locale.GERMAN);
36+
assertThat(violation.message()).isEqualTo("numerischer Wert außerhalb des gültigen Bereichs (<5 digits>.<3 digits> erwartet)");
37+
}
38+
39+
@Test
40+
void positive() {
41+
var bean = new JNums();
42+
bean.positive = -1;
43+
var violation = one(bean);
44+
assertThat(violation.message()).isEqualTo("must be greater than 0");
45+
}
46+
47+
@Test
48+
void positiveDE() {
49+
var bean = new JNums();
50+
bean.positive = -1;
51+
var violation = one(bean, Locale.GERMAN);
52+
assertThat(violation.message()).isEqualTo("muss größer als 0 sein");
53+
}
54+
55+
@Test
56+
void positiveOrZero() {
57+
var bean = new JNums();
58+
bean.positiveOrZero = -1;
59+
var violation = one(bean);
60+
assertThat(violation.message()).isEqualTo("must be greater than or equal to 0");
61+
}
62+
63+
@Test
64+
void positiveOrZeroDE() {
65+
var bean = new JNums();
66+
bean.positiveOrZero = -1;
67+
var violation = one(bean, Locale.GERMAN);
68+
assertThat(violation.message()).isEqualTo("muss größer-gleich 0 sein");
69+
}
70+
71+
@Test
72+
void negative() {
73+
var bean = new JNums();
74+
bean.negative = 1;
75+
var violation = one(bean);
76+
assertThat(violation.message()).isEqualTo("must be less than 0");
77+
}
78+
79+
@Test
80+
void negativeDE() {
81+
var bean = new JNums();
82+
bean.negative = 1;
83+
var violation = one(bean, Locale.GERMAN);
84+
assertThat(violation.message()).isEqualTo("muss kleiner als 0 sein");
85+
}
86+
87+
@Test
88+
void negativeOrZero() {
89+
var bean = new JNums();
90+
bean.negativeOrZero = 1;
91+
var violation = one(bean);
92+
assertThat(violation.message()).isEqualTo("must be less than or equal to 0");
93+
}
94+
95+
@Test
96+
void negativeOrZeroDE() {
97+
var bean = new JNums();
98+
bean.negativeOrZero = 1;
99+
var violation = one(bean, Locale.GERMAN);
100+
assertThat(violation.message()).isEqualTo("muss kleiner-gleich 0 sein");
101+
}
102+
103+
ConstraintViolation one(Object any) {
104+
return one(any, Locale.ENGLISH);
105+
}
106+
107+
ConstraintViolation one(Object any, Locale locale) {
108+
try {
109+
validator.validate(any, locale);
110+
fail("not expected");
111+
return null;
112+
} catch (ConstraintViolationException e) {
113+
var violations = new ArrayList<>(e.violations());
114+
assertThat(violations).hasSize(1);
115+
return violations.get(0);
116+
}
117+
}
118+
}

validator-generator/src/main/java/io/avaje/validation/generator/AnnotationUtil.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@ interface Handler {
4444
handlers.put("io.avaje.validation.constraints.FutureOrPresent", jakartaHandler);
4545
handlers.put("jakarta.validation.constraints.FutureOrPresent", jakartaHandler);
4646

47+
final String[] keys = {"Digits", "Positive", "PositiveOrZero", "Negative", "NegativeOrZero", "Max", "Min"};
48+
for (String key : keys) {
49+
handlers.put("io.avaje.validation.constraints." + key, jakartaHandler);
50+
handlers.put("jakarta.validation.constraints." + key, jakartaHandler);
51+
}
52+
53+
4754
final var jakartaDecimal = new JakartaDecimal();
4855
handlers.put("io.avaje.validation.constraints.DecimalMax", jakartaDecimal);
4956
handlers.put("io.avaje.validation.constraints.DecimalMin", jakartaDecimal);

validator/src/main/java/io/avaje/validation/core/adapters/NumberAdapters.java

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ private NumberAdapters() {}
1717
public static final ValidationContext.AnnotationFactory FACTORY =
1818
(annotationType, context, attributes) ->
1919
switch (annotationType.getSimpleName()) {
20-
case "Digits" -> new DigitsAdapter(context.message("Digits", attributes), attributes);
21-
case "Positive" -> new PositiveAdapter(context.message("Positive", attributes));
20+
case "Digits" -> new DigitsAdapter(context.message2(attributes), attributes);
21+
case "Positive" -> new PositiveAdapter(context.message2(attributes));
2222
case "PositiveOrZero" -> new PositiveAdapter(
23-
context.message("PositiveOrZero", attributes), true);
24-
case "Negative" -> new NegativeAdapter(context.message("Negative", attributes));
23+
context.message2(attributes), true);
24+
case "Negative" -> new NegativeAdapter(context.message2(attributes));
2525
case "NegativeOrZero" -> new NegativeAdapter(
26-
context.message("NegativeOrZero", attributes), true);
27-
case "Max" -> new MaxAdapter(context.message("Max", attributes), attributes);
28-
case "Min" -> new MinAdapter(context.message("Min", attributes), attributes);
26+
context.message2(attributes), true);
27+
case "Max" -> new MaxAdapter(context.message2(attributes), attributes);
28+
case "Min" -> new MinAdapter(context.message2(attributes), attributes);
2929
case "DecimalMax" -> new DecimalMaxAdapter(
3030
context.message2(attributes), attributes);
3131
case "DecimalMin" -> new DecimalMinAdapter(
@@ -98,10 +98,10 @@ public boolean validate(Number number, ValidationRequest req, String propertyNam
9898

9999
private static final class MaxAdapter implements ValidationAdapter<Number> {
100100

101-
private final String message;
101+
private final ValidationContext.Message message;
102102
private final long value;
103103

104-
public MaxAdapter(String message, Map<String, Object> attributes) {
104+
public MaxAdapter(ValidationContext.Message message, Map<String, Object> attributes) {
105105
this.message = message;
106106
this.value = (long) attributes.get("value");
107107
}
@@ -114,7 +114,7 @@ public boolean validate(Number number, ValidationRequest req, String propertyNam
114114
return true;
115115
}
116116

117-
if (NumberComparatorHelper.compare(number, value, GREATER_THAN) < 0) {
117+
if (NumberComparatorHelper.compare(number, value, GREATER_THAN) > 0) {
118118
req.addViolation(message, propertyName);
119119
return false;
120120
}
@@ -125,10 +125,10 @@ public boolean validate(Number number, ValidationRequest req, String propertyNam
125125

126126
private static final class MinAdapter implements ValidationAdapter<Number> {
127127

128-
private final String message;
128+
private final ValidationContext.Message message;
129129
private final long value;
130130

131-
public MinAdapter(String message, Map<String, Object> attributes) {
131+
public MinAdapter(ValidationContext.Message message, Map<String, Object> attributes) {
132132
this.message = message;
133133
this.value = (long) attributes.get("value");
134134
}
@@ -141,7 +141,7 @@ public boolean validate(Number number, ValidationRequest req, String propertyNam
141141
return true;
142142
}
143143

144-
if (NumberComparatorHelper.compare(number, value, LESS_THAN) > 0) {
144+
if (NumberComparatorHelper.compare(number, value, LESS_THAN) < 0) {
145145
req.addViolation(message, propertyName);
146146
return false;
147147
}
@@ -152,11 +152,11 @@ public boolean validate(Number number, ValidationRequest req, String propertyNam
152152

153153
private static final class DigitsAdapter implements ValidationAdapter<Object> {
154154

155-
private final String message;
155+
private final ValidationContext.Message message;
156156
private final int integer;
157157
private final int fraction;
158158

159-
public DigitsAdapter(String message, Map<String, Object> attributes) {
159+
public DigitsAdapter(ValidationContext.Message message, Map<String, Object> attributes) {
160160
this.message = message;
161161
this.integer = (int) attributes.get("integer");
162162
this.fraction = (int) attributes.get("fraction");
@@ -191,15 +191,15 @@ public boolean validate(Object value, ValidationRequest req, String propertyName
191191

192192
private static final class PositiveAdapter implements ValidationAdapter<Object> {
193193

194-
private final String message;
194+
private final ValidationContext.Message message;
195195
private final boolean inclusive;
196196

197-
public PositiveAdapter(String message) {
197+
public PositiveAdapter(ValidationContext.Message message) {
198198
this.message = message;
199199
this.inclusive = false;
200200
}
201201

202-
public PositiveAdapter(String message, boolean inclusive) {
202+
public PositiveAdapter(ValidationContext.Message message, boolean inclusive) {
203203
this.message = message;
204204
this.inclusive = inclusive;
205205
}
@@ -225,15 +225,15 @@ public boolean validate(Object value, ValidationRequest req, String propertyName
225225

226226
private static final class NegativeAdapter implements ValidationAdapter<Object> {
227227

228-
private final String message;
228+
private final ValidationContext.Message message;
229229
private final boolean inclusive;
230230

231-
public NegativeAdapter(String message, boolean inclusive) {
231+
public NegativeAdapter(ValidationContext.Message message, boolean inclusive) {
232232
this.message = message;
233233
this.inclusive = inclusive;
234234
}
235235

236-
public NegativeAdapter(String message) {
236+
public NegativeAdapter(ValidationContext.Message message) {
237237
this.message = message;
238238
this.inclusive = false;
239239
}

0 commit comments

Comments
 (0)