Skip to content

Commit c589d91

Browse files
committed
HV-1122 Organizing constraint validators by a dedicated descriptor type;
This allows to add Lambda-based constraints without generating a dedicated class for each lambda constraint.
1 parent 691f20b commit c589d91

File tree

13 files changed

+273
-145
lines changed

13 files changed

+273
-145
lines changed

engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstraintDefinitionContextImpl.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66
*/
77
package org.hibernate.validator.internal.cfg.context;
88

9-
import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet;
10-
119
import java.lang.annotation.Annotation;
10+
import java.util.HashSet;
1211
import java.util.Set;
1312

1413
import javax.validation.ConstraintValidator;
1514

1615
import org.hibernate.validator.cfg.context.ConstraintDefinitionContext;
1716
import org.hibernate.validator.internal.engine.constraintdefinition.ConstraintDefinitionContribution;
17+
import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorDescriptor;
1818
import org.hibernate.validator.internal.util.CollectionHelper;
1919

2020
/**
@@ -32,7 +32,7 @@ class ConstraintDefinitionContextImpl<A extends Annotation>
3232

3333
private boolean includeExistingValidators = true;
3434

35-
private final Set<Class<? extends ConstraintValidator<A, ?>>> validatorTypes = newHashSet();
35+
private final Set<ConstraintValidatorDescriptor<A>> validatorTypes = new HashSet<>();
3636

3737
ConstraintDefinitionContextImpl(DefaultConstraintMapping mapping, Class<A> annotationType) {
3838
super( mapping );
@@ -47,13 +47,13 @@ public ConstraintDefinitionContext<A> includeExistingValidators(boolean includeE
4747

4848
@Override
4949
public ConstraintDefinitionContext<A> validatedBy(Class<? extends ConstraintValidator<A, ?>> validator) {
50-
validatorTypes.add( validator );
50+
validatorTypes.add( ConstraintValidatorDescriptor.forClass( validator ) );
5151
return this;
5252
}
5353

5454
@SuppressWarnings("unchecked")
5555
ConstraintDefinitionContribution<A> build() {
56-
return new ConstraintDefinitionContribution<A>(
56+
return new ConstraintDefinitionContribution<>(
5757
annotationType,
5858
CollectionHelper.newArrayList( validatorTypes ),
5959
includeExistingValidators );

engine/src/main/java/org/hibernate/validator/internal/engine/constraintdefinition/ConstraintDefinitionContribution.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
import java.lang.annotation.Annotation;
1010
import java.util.ArrayList;
1111
import java.util.List;
12-
import javax.validation.ConstraintValidator;
12+
13+
import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorDescriptor;
1314

1415
/**
1516
* Type-safe wrapper class for a constraint annotation and its potential list of constraint validators.
@@ -18,11 +19,11 @@
1819
*/
1920
public class ConstraintDefinitionContribution<A extends Annotation> {
2021
private final Class<A> constraintType;
21-
private final List<Class<? extends ConstraintValidator<A, ?>>> constraintValidators = new ArrayList<Class<? extends ConstraintValidator<A, ?>>>();
22+
private final List<ConstraintValidatorDescriptor<A>> constraintValidators = new ArrayList<>();
2223
private final boolean includeExisting;
2324

2425
public ConstraintDefinitionContribution(Class<A> constraintType,
25-
List<Class<? extends ConstraintValidator<A, ?>>> constraintValidators,
26+
List<ConstraintValidatorDescriptor<A>> constraintValidators,
2627
boolean includeExisting) {
2728
this.constraintType = constraintType;
2829
this.constraintValidators.addAll( constraintValidators );
@@ -43,7 +44,7 @@ public Class<A> getConstraintType() {
4344
*
4445
* @return a list of constraint validator types for the constraint type of this instance.
4546
*/
46-
public List<Class<? extends ConstraintValidator<A, ?>>> getConstraintValidators() {
47+
public List<ConstraintValidatorDescriptor<A>> getConstraintValidators() {
4748
return constraintValidators;
4849
}
4950

@@ -94,5 +95,3 @@ public String toString() {
9495
'}';
9596
}
9697
}
97-
98-
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Hibernate Validator, declare and validate application constraints
3+
*
4+
* License: Apache License, Version 2.0
5+
* See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
6+
*/
7+
package org.hibernate.validator.internal.engine.constraintvalidation;
8+
9+
import java.lang.annotation.Annotation;
10+
import java.lang.reflect.Type;
11+
import java.util.Arrays;
12+
import java.util.EnumSet;
13+
14+
import javax.validation.ConstraintValidator;
15+
import javax.validation.ConstraintValidatorFactory;
16+
import javax.validation.constraintvalidation.SupportedValidationTarget;
17+
import javax.validation.constraintvalidation.ValidationTarget;
18+
19+
import org.hibernate.validator.internal.util.TypeHelper;
20+
import org.hibernate.validator.internal.util.logging.Log;
21+
import org.hibernate.validator.internal.util.logging.LoggerFactory;
22+
23+
/**
24+
* Represents an implementation of {@link ConstraintValidator}.
25+
*
26+
* @author Gunnar Morling
27+
*/
28+
class ClassBasedValidatorDescriptor<A extends Annotation> implements ConstraintValidatorDescriptor<A> {
29+
30+
private static final long serialVersionUID = -8207687559460098548L;
31+
private static final Log LOG = LoggerFactory.make();
32+
33+
private final Class<? extends ConstraintValidator<A, ?>> validatorClass;
34+
35+
public ClassBasedValidatorDescriptor(Class<? extends ConstraintValidator<A, ?>> validatorClass) {
36+
this.validatorClass = validatorClass;
37+
}
38+
39+
@Override
40+
public Class<? extends ConstraintValidator<A, ?>> getValidatorClass() {
41+
return validatorClass;
42+
}
43+
44+
@Override
45+
public ConstraintValidator<A, ?> newInstance(ConstraintValidatorFactory constraintFactory) {
46+
ConstraintValidator<A, ?> constraintValidator = constraintFactory.getInstance( validatorClass );
47+
48+
if ( constraintValidator == null ) {
49+
throw LOG.getConstraintFactoryMustNotReturnNullException( validatorClass );
50+
}
51+
52+
return constraintValidator;
53+
}
54+
55+
@Override
56+
public Type getValidatedType() {
57+
return TypeHelper.extractType( validatorClass );
58+
}
59+
60+
@Override
61+
public EnumSet<ValidationTarget> getValidationTargets() {
62+
SupportedValidationTarget supportedTargetAnnotation = validatorClass.getAnnotation(
63+
SupportedValidationTarget.class
64+
);
65+
66+
//by default constraints target the annotated element
67+
if ( supportedTargetAnnotation == null ) {
68+
return EnumSet.of( ValidationTarget.ANNOTATED_ELEMENT );
69+
}
70+
else {
71+
return EnumSet.copyOf( Arrays.asList( supportedTargetAnnotation.value() ) );
72+
}
73+
}
74+
}

engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ private ConstraintTree(ConstraintDescriptorImpl<A> descriptor, ConstraintTree<?>
7070
}
7171

7272
private <U extends Annotation> ConstraintTree<U> createConstraintTree(ConstraintDescriptorImpl<U> composingDescriptor) {
73-
return new ConstraintTree<U>( composingDescriptor, this );
73+
return new ConstraintTree<>( composingDescriptor, this );
7474
}
7575

7676
public final List<ConstraintTree<?>> getChildren() {
@@ -92,8 +92,8 @@ public final <T> boolean validateConstraints(ValidationContext<T> executionConte
9292
return true;
9393
}
9494

95-
private <T, V> void validateConstraints(ValidationContext<T> validationContext,
96-
ValueContext<?, V> valueContext,
95+
private <T> void validateConstraints(ValidationContext<T> validationContext,
96+
ValueContext<?, ?> valueContext,
9797
Set<ConstraintViolation<T>> constraintViolations) {
9898
CompositionResult compositionResult = validateComposingConstraints(
9999
validationContext, valueContext, constraintViolations
@@ -113,7 +113,7 @@ private <T, V> void validateConstraints(ValidationContext<T> validationContext,
113113
}
114114

115115
// find the right constraint validator
116-
ConstraintValidator<A, V> validator = getInitializedConstraintValidator( validationContext, valueContext );
116+
ConstraintValidator<A, ?> validator = getInitializedConstraintValidator( validationContext, valueContext );
117117

118118
// create a constraint validator context
119119
ConstraintValidatorContextImpl constraintValidatorContext = new ConstraintValidatorContextImpl(
@@ -151,7 +151,7 @@ private <T, V> void validateConstraints(ValidationContext<T> validationContext,
151151
}
152152
}
153153

154-
private <T, V> ConstraintValidator<A, V> getInitializedConstraintValidator(ValidationContext<T> validationContext,
154+
private <T, V> ConstraintValidator<A, ?> getInitializedConstraintValidator(ValidationContext<T> validationContext,
155155
ValueContext<?, V> valueContext) {
156156
Type validatedValueType = valueContext.getDeclaredTypeOfValidatedElement();
157157
@SuppressWarnings("unchecked")
@@ -182,7 +182,7 @@ else if ( UnwrapMode.UNWRAP.equals( valueContext.getUnwrapMode() )
182182
}
183183
}
184184

185-
private <T, V> ConstraintValidator<A, V> getInitializedValidatorInstanceForWrappedInstance(ValidationContext<T> validationContext, ValueContext<?, V> valueContext, Type validatedValueType, ValidatedValueUnwrapper<V> validatedValueUnwrapper) {
185+
private <T, V> ConstraintValidator<A, ?> getInitializedValidatorInstanceForWrappedInstance(ValidationContext<T> validationContext, ValueContext<?, V> valueContext, Type validatedValueType, ValidatedValueUnwrapper<V> validatedValueUnwrapper) {
186186
// make sure that unwrapper is set
187187
if ( validatedValueUnwrapper == null ) {
188188
throw log.getNoUnwrapperFoundForTypeException(
@@ -193,7 +193,7 @@ private <T, V> ConstraintValidator<A, V> getInitializedValidatorInstanceForWrapp
193193
valueContext.setValidatedValueHandler( validatedValueUnwrapper );
194194
validatedValueType = validatedValueUnwrapper.getValidatedValueType( validatedValueType );
195195

196-
ConstraintValidator<A, V> validator = validationContext.getConstraintValidatorManager()
196+
ConstraintValidator<A, ?> validator = validationContext.getConstraintValidatorManager()
197197
.getInitializedValidator(
198198
validatedValueType,
199199
descriptor,
@@ -228,7 +228,7 @@ private void throwExceptionForNullValidator(Type validatedValueType, String path
228228
}
229229
}
230230

231-
private <T, V> ConstraintValidator<A, V> getConstraintValidatorInstanceForAutomaticUnwrapping(
231+
private <T, V> ConstraintValidator<A, ?> getConstraintValidatorInstanceForAutomaticUnwrapping(
232232
ValidationContext<T> validationContext,
233233
ValueContext<?, V> valueContext
234234
) {
@@ -244,15 +244,15 @@ private <T, V> ConstraintValidator<A, V> getConstraintValidatorInstanceForAutoma
244244

245245
// there is an unwrapper - need to find out for which type (wrapper or wrapped value there
246246
// are constraint validators available
247-
ConstraintValidator<A, V> validatorForWrappedValue = validationContext.getConstraintValidatorManager()
247+
ConstraintValidator<A, ?> validatorForWrappedValue = validationContext.getConstraintValidatorManager()
248248
.getInitializedValidator(
249249
validatedValueUnwrapper.getValidatedValueType( validatedValueType ),
250250
descriptor,
251251
validationContext.getConstraintValidatorFactory()
252252
);
253253

254254

255-
ConstraintValidator<A, V> validatorForWrapper = validationContext.getConstraintValidatorManager()
255+
ConstraintValidator<A, ?> validatorForWrapper = validationContext.getConstraintValidatorManager()
256256
.getInitializedValidator(
257257
valueContext.getDeclaredTypeOfValidatedElement(),
258258
descriptor,
@@ -291,13 +291,13 @@ private <T, V> ConstraintValidator<A, V> getConstraintValidatorInstanceForAutoma
291291
}
292292
}
293293

294-
private <T, V> ConstraintValidator<A, V> getConstraintValidatorNoUnwrapping(ValidationContext<T> validationContext,
295-
ValueContext<?, V> valueContext) {
294+
private <T> ConstraintValidator<A, ?> getConstraintValidatorNoUnwrapping(ValidationContext<T> validationContext,
295+
ValueContext<?, ?> valueContext) {
296296
// make sure no unwrapper is set
297297
valueContext.setValidatedValueHandler( null );
298298

299299
Type validatedValueType = valueContext.getDeclaredTypeOfValidatedElement();
300-
ConstraintValidator<A, V> validator = validationContext.getConstraintValidatorManager()
300+
ConstraintValidator<A, ?> validator = validationContext.getConstraintValidatorManager()
301301
.getInitializedValidator(
302302
validatedValueType,
303303
descriptor,
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Hibernate Validator, declare and validate application constraints
3+
*
4+
* License: Apache License, Version 2.0
5+
* See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
6+
*/
7+
package org.hibernate.validator.internal.engine.constraintvalidation;
8+
9+
import java.io.Serializable;
10+
import java.lang.annotation.Annotation;
11+
import java.lang.reflect.Type;
12+
import java.util.EnumSet;
13+
14+
import javax.validation.ConstraintValidator;
15+
import javax.validation.ConstraintValidatorFactory;
16+
import javax.validation.constraintvalidation.ValidationTarget;
17+
18+
/**
19+
* Represents a specific validator type.
20+
*
21+
* @author Gunnar Morling
22+
*/
23+
public interface ConstraintValidatorDescriptor<A extends Annotation> extends Serializable {
24+
25+
Class<? extends ConstraintValidator<A, ?>> getValidatorClass();
26+
EnumSet<ValidationTarget> getValidationTargets();
27+
Type getValidatedType();
28+
ConstraintValidator<A, ?> newInstance(ConstraintValidatorFactory constraintFactory);
29+
30+
static <A extends Annotation> ConstraintValidatorDescriptor<A> forClass(Class<? extends ConstraintValidator<A, ?>> validatorClass) {
31+
return new ClassBasedValidatorDescriptor<>( validatorClass );
32+
}
33+
}

0 commit comments

Comments
 (0)