|
21 | 21 | import java.lang.annotation.Repeatable;
|
22 | 22 | import java.lang.annotation.Retention;
|
23 | 23 | import java.lang.annotation.Target;
|
| 24 | +import java.lang.reflect.Field; |
| 25 | +import java.util.ArrayList; |
| 26 | +import java.util.Arrays; |
| 27 | +import java.util.LinkedHashSet; |
| 28 | +import java.util.LinkedList; |
| 29 | +import java.util.List; |
24 | 30 | import java.util.Locale;
|
| 31 | +import java.util.Set; |
25 | 32 | import javax.validation.Constraint;
|
26 | 33 | import javax.validation.ConstraintValidator;
|
27 | 34 | import javax.validation.ConstraintValidatorContext;
|
28 | 35 | import javax.validation.Payload;
|
| 36 | +import javax.validation.Valid; |
29 | 37 | import javax.validation.Validation;
|
30 | 38 | import javax.validation.Validator;
|
| 39 | +import javax.validation.constraints.NotNull; |
31 | 40 | import javax.validation.constraints.Pattern;
|
32 | 41 | import javax.validation.constraints.Size;
|
33 | 42 |
|
@@ -138,6 +147,43 @@ public void testApplyMessageSourceResolvableToStringArgumentValueWithAlwaysUseMe
|
138 | 147 | is("Email required"));
|
139 | 148 | }
|
140 | 149 |
|
| 150 | + @Test // SPR-16177 |
| 151 | + public void testWithList() { |
| 152 | + Parent parent = new Parent(); |
| 153 | + parent.setName("Parent whit list"); |
| 154 | + parent.getChildList().addAll(createChildren(parent)); |
| 155 | + |
| 156 | + BeanPropertyBindingResult errors = new BeanPropertyBindingResult(parent, "parent"); |
| 157 | + validatorAdapter.validate(parent, errors); |
| 158 | + |
| 159 | + assertTrue(errors.getErrorCount() > 0); |
| 160 | + } |
| 161 | + |
| 162 | + @Test // SPR-16177 |
| 163 | + public void testWithSet() { |
| 164 | + Parent parent = new Parent(); |
| 165 | + parent.setName("Parent whith set"); |
| 166 | + parent.getChildSet().addAll(createChildren(parent)); |
| 167 | + |
| 168 | + BeanPropertyBindingResult errors = new BeanPropertyBindingResult(parent, "parent"); |
| 169 | + validatorAdapter.validate(parent, errors); |
| 170 | + |
| 171 | + assertTrue(errors.getErrorCount() > 0); |
| 172 | + } |
| 173 | + |
| 174 | + private List<Child> createChildren(Parent parent) { |
| 175 | + Child child1 = new Child(); |
| 176 | + child1.setName("Child1"); |
| 177 | + child1.setAge(null); |
| 178 | + child1.setParent(parent); |
| 179 | + |
| 180 | + Child child2 = new Child(); |
| 181 | + child2.setName(null); |
| 182 | + child2.setAge(17); |
| 183 | + child2.setParent(parent); |
| 184 | + |
| 185 | + return Arrays.asList(child1, child2); |
| 186 | + } |
141 | 187 |
|
142 | 188 | @Same(field = "password", comparingField = "confirmPassword")
|
143 | 189 | @Same(field = "email", comparingField = "confirmEmail")
|
@@ -255,4 +301,141 @@ public boolean isValid(Object value, ConstraintValidatorContext context) {
|
255 | 301 | }
|
256 | 302 | }
|
257 | 303 |
|
| 304 | + |
| 305 | + public static class Parent { |
| 306 | + |
| 307 | + private Integer id; |
| 308 | + |
| 309 | + @NotNull |
| 310 | + private String name; |
| 311 | + |
| 312 | + @Valid |
| 313 | + private Set<Child> childSet = new LinkedHashSet<>(); |
| 314 | + |
| 315 | + @Valid |
| 316 | + private List<Child> childList = new LinkedList<>(); |
| 317 | + |
| 318 | + public Integer getId() { |
| 319 | + return id; |
| 320 | + } |
| 321 | + |
| 322 | + public void setId(Integer id) { |
| 323 | + this.id = id; |
| 324 | + } |
| 325 | + |
| 326 | + public String getName() { |
| 327 | + return name; |
| 328 | + } |
| 329 | + |
| 330 | + public void setName(String name) { |
| 331 | + this.name = name; |
| 332 | + } |
| 333 | + |
| 334 | + public Set<Child> getChildSet() { |
| 335 | + return childSet; |
| 336 | + } |
| 337 | + |
| 338 | + public void setChildSet(Set<Child> childSet) { |
| 339 | + this.childSet = childSet; |
| 340 | + } |
| 341 | + |
| 342 | + public List<Child> getChildList() { |
| 343 | + return childList; |
| 344 | + } |
| 345 | + |
| 346 | + public void setChildList(List<Child> childList) { |
| 347 | + this.childList = childList; |
| 348 | + } |
| 349 | + } |
| 350 | + |
| 351 | + |
| 352 | + @AnythingValid |
| 353 | + public static class Child { |
| 354 | + |
| 355 | + private Integer id; |
| 356 | + |
| 357 | + @javax.validation.constraints.NotNull |
| 358 | + private String name; |
| 359 | + |
| 360 | + @javax.validation.constraints.NotNull |
| 361 | + private Integer age; |
| 362 | + |
| 363 | + @javax.validation.constraints.NotNull |
| 364 | + private Parent parent; |
| 365 | + |
| 366 | + public Integer getId() { |
| 367 | + return id; |
| 368 | + } |
| 369 | + |
| 370 | + public void setId(Integer id) { |
| 371 | + this.id = id; |
| 372 | + } |
| 373 | + |
| 374 | + public String getName() { |
| 375 | + return name; |
| 376 | + } |
| 377 | + |
| 378 | + public void setName(String name) { |
| 379 | + this.name = name; |
| 380 | + } |
| 381 | + |
| 382 | + public Integer getAge() { |
| 383 | + return age; |
| 384 | + } |
| 385 | + |
| 386 | + public void setAge(Integer age) { |
| 387 | + this.age = age; |
| 388 | + } |
| 389 | + |
| 390 | + public Parent getParent() { |
| 391 | + return parent; |
| 392 | + } |
| 393 | + |
| 394 | + public void setParent(Parent parent) { |
| 395 | + this.parent = parent; |
| 396 | + } |
| 397 | + } |
| 398 | + |
| 399 | + |
| 400 | + @Constraint(validatedBy = AnythingValidator.class) |
| 401 | + @Retention(RUNTIME) |
| 402 | + public @interface AnythingValid { |
| 403 | + |
| 404 | + String message() default "{AnythingValid.message}"; |
| 405 | + |
| 406 | + Class<?>[] groups() default {}; |
| 407 | + |
| 408 | + Class<? extends Payload>[] payload() default {}; |
| 409 | + } |
| 410 | + |
| 411 | + |
| 412 | + public static class AnythingValidator implements ConstraintValidator<AnythingValid, Object> { |
| 413 | + |
| 414 | + private static final String ID = "id"; |
| 415 | + |
| 416 | + @Override |
| 417 | + public void initialize(AnythingValid constraintAnnotation) { |
| 418 | + } |
| 419 | + |
| 420 | + @Override |
| 421 | + public boolean isValid(Object value, ConstraintValidatorContext context) { |
| 422 | + List<Field> fieldsErros = new ArrayList<>(); |
| 423 | + Arrays.asList(value.getClass().getDeclaredFields()).forEach(f -> { |
| 424 | + f.setAccessible(true); |
| 425 | + try { |
| 426 | + if (!f.getName().equals(ID) && f.get(value) == null) { |
| 427 | + fieldsErros.add(f); |
| 428 | + context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate()) |
| 429 | + .addNode(f.getName()) |
| 430 | + .addConstraintViolation(); |
| 431 | + } |
| 432 | + } catch (IllegalAccessException ex) { |
| 433 | + throw new IllegalStateException(ex); |
| 434 | + } |
| 435 | + |
| 436 | + }); |
| 437 | + return fieldsErros.isEmpty(); |
| 438 | + } |
| 439 | + } |
| 440 | + |
258 | 441 | }
|
0 commit comments