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.invoke.MethodHandles;
11 import java.lang.reflect.Type;
12 import java.util.Arrays;
13 import java.util.EnumSet;
14
15 import javax.validation.ConstraintValidator;
16 import javax.validation.ConstraintValidatorFactory;
17 import javax.validation.constraintvalidation.SupportedValidationTarget;
18 import javax.validation.constraintvalidation.ValidationTarget;
19
20 import org.hibernate.validator.internal.util.TypeHelper;
21 import org.hibernate.validator.internal.util.logging.Log;
22 import org.hibernate.validator.internal.util.logging.LoggerFactory;
23
24 /**
25  * Represents an implementation of {@link ConstraintValidator}.
26  *
27  * @author Gunnar Morling
28  * @author Guillaume Smet
29  */

30 class ClassBasedValidatorDescriptor<A extends Annotation> implements ConstraintValidatorDescriptor<A> {
31
32     private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() );
33
34     private final Class<? extends ConstraintValidator<A, ?>> validatorClass;
35     private final Type validatedType;
36     private final EnumSet<ValidationTarget> validationTargets;
37
38     private ClassBasedValidatorDescriptor(Class<? extends ConstraintValidator<A, ?>> validatorClass) {
39         this.validatorClass = validatorClass;
40         this.validatedType = TypeHelper.extractValidatedType( validatorClass );
41         this.validationTargets = determineValidationTargets( validatorClass );
42     }
43
44     public static <T extends Annotation> ClassBasedValidatorDescriptor<T> of(Class<? extends ConstraintValidator<T, ?>> validatorClass,
45             Class<? extends Annotation> registeredConstraintAnnotationType) {
46         Type definedConstraintAnnotationType = TypeHelper.extractConstraintType( validatorClass );
47         if ( !registeredConstraintAnnotationType.equals( definedConstraintAnnotationType ) ) {
48             throw LOG.getConstraintValidatorDefinitionConstraintMismatchException( validatorClass, registeredConstraintAnnotationType,
49                     definedConstraintAnnotationType );
50         }
51
52         return new ClassBasedValidatorDescriptor<T>( validatorClass );
53     }
54
55     /**
56      * Constraint checking is relaxed for built-in constraints as they have been carefully crafted so we are sure types
57      * are right.
58      */

59     public static <T extends Annotation> ClassBasedValidatorDescriptor<T> ofBuiltin(Class<? extends ConstraintValidator<T, ?>> validatorClass,
60             Class<? extends Annotation> registeredConstraintAnnotationType) {
61         return new ClassBasedValidatorDescriptor<T>( validatorClass );
62     }
63
64     private static EnumSet<ValidationTarget> determineValidationTargets(Class<? extends ConstraintValidator<?, ?>> validatorClass) {
65         SupportedValidationTarget supportedTargetAnnotation = validatorClass.getAnnotation(
66                 SupportedValidationTarget.class );
67
68         // by default constraints target the annotated element
69         if ( supportedTargetAnnotation == null ) {
70             return EnumSet.of( ValidationTarget.ANNOTATED_ELEMENT );
71         }
72         else {
73             return EnumSet.copyOf( Arrays.asList( supportedTargetAnnotation.value() ) );
74         }
75     }
76
77     @Override
78     public Class<? extends ConstraintValidator<A, ?>> getValidatorClass() {
79         return validatorClass;
80     }
81
82     @Override
83     public ConstraintValidator<A, ?> newInstance(ConstraintValidatorFactory constraintValidatorFactory) {
84         ConstraintValidator<A, ?> constraintValidator = constraintValidatorFactory.getInstance( validatorClass );
85
86         if ( constraintValidator == null ) {
87             throw LOG.getConstraintValidatorFactoryMustNotReturnNullException( validatorClass );
88         }
89
90         return constraintValidator;
91     }
92
93     @Override
94     public Type getValidatedType() {
95         return validatedType;
96     }
97
98     @Override
99     public EnumSet<ValidationTarget> getValidationTargets() {
100         return validationTargets;
101     }
102 }
103