105
105
import jakarta .validation .constraints .Size ;
106
106
import jakarta .validation .constraintvalidation .ValidationTarget ;
107
107
108
+ import org .hibernate .validator .cfg .ConstraintMapping ;
108
109
import org .hibernate .validator .constraints .BitcoinAddress ;
109
110
import org .hibernate .validator .constraints .CodePointLength ;
110
111
import org .hibernate .validator .constraints .ConstraintComposition ;
372
373
* @author Gunnar Morling
373
374
* @author Guillaume Smet
374
375
*/
375
- public class ConstraintHelper {
376
+ public abstract class ConstraintHelper {
376
377
377
378
public static final String GROUPS = "groups" ;
378
379
public static final String PAYLOAD = "payload" ;
@@ -385,9 +386,6 @@ public class ConstraintHelper {
385
386
private static final String JODA_TIME_CLASS_NAME = "org.joda.time.ReadableInstant" ;
386
387
private static final String JAVA_MONEY_CLASS_NAME = "javax.money.MonetaryAmount" ;
387
388
388
- @ Immutable
389
- private final Map <Class <? extends Annotation >, List <? extends ConstraintValidatorDescriptor <?>>> enabledBuiltinConstraints ;
390
-
391
389
private final ConcurrentMap <Class <? extends Annotation >, Boolean > externalConstraints = new ConcurrentHashMap <>();
392
390
393
391
private final ConcurrentMap <Class <? extends Annotation >, Boolean > multiValueConstraints = new ConcurrentHashMap <>();
@@ -399,21 +397,20 @@ public class ConstraintHelper {
399
397
private Boolean jodaTimeInClassPath ;
400
398
401
399
public static ConstraintHelper forAllBuiltinConstraints () {
402
- return new ConstraintHelper ( new HashSet <>( Arrays . asList ( BuiltinConstraint . values () ) ) );
400
+ return new StaticConstraintHelper ( );
403
401
}
404
402
405
403
public static ConstraintHelper forBuiltinConstraints (Set <String > enabledConstraints ) {
406
- return new ConstraintHelper ( BuiltinConstraint .resolve ( enabledConstraints ) );
404
+ return new DynamicConstraintHelper ( BuiltinConstraint .resolve ( enabledConstraints ) );
407
405
}
408
406
409
407
@ SuppressWarnings ("deprecation" )
410
- private ConstraintHelper (Set <BuiltinConstraint > enabledBuiltinConstraints ) {
408
+ protected Map < Class <? extends Annotation >, List <? extends ConstraintValidatorDescriptor <?>>> resolve (Set <BuiltinConstraint > enabledBuiltinConstraints ) {
411
409
if ( enabledBuiltinConstraints .isEmpty () ) {
412
- this .enabledBuiltinConstraints = Collections .emptyMap ();
413
- return ;
410
+ return Collections .emptyMap ();
414
411
}
415
412
416
- Map <Class <? extends Annotation >, List <ConstraintValidatorDescriptor <?>>> tmpConstraints = new HashMap <>();
413
+ Map <Class <? extends Annotation >, List <? extends ConstraintValidatorDescriptor <?>>> tmpConstraints = new HashMap <>();
417
414
418
415
// Bean Validation constraints
419
416
@@ -832,21 +829,27 @@ private ConstraintHelper(Set<BuiltinConstraint> enabledBuiltinConstraints) {
832
829
putBuiltinConstraint ( tmpConstraints , BitcoinAddress .class , BitcoinAddressValidator .class );
833
830
}
834
831
835
- this . enabledBuiltinConstraints = Collections . unmodifiableMap ( tmpConstraints ) ;
832
+ return tmpConstraints ;
836
833
}
837
834
838
- private static <A extends Annotation > void putBuiltinConstraint (Map <Class <? extends Annotation >, List <ConstraintValidatorDescriptor <?>>> validators ,
839
- Class <A > constraintType ) {
835
+ private static <A extends Annotation > void putBuiltinConstraint (
836
+ Map <Class <? extends Annotation >, List <? extends ConstraintValidatorDescriptor <?>>> validators ,
837
+ Class <A > constraintType
838
+ ) {
840
839
validators .put ( constraintType , Collections .emptyList () );
841
840
}
842
841
843
- private static <A extends Annotation > void putBuiltinConstraint (Map <Class <? extends Annotation >, List <ConstraintValidatorDescriptor <?>>> validators ,
844
- Class <A > constraintType , Class <? extends ConstraintValidator <A , ?>> validatorType ) {
842
+ private static <A extends Annotation > void putBuiltinConstraint (
843
+ Map <Class <? extends Annotation >, List <? extends ConstraintValidatorDescriptor <?>>> validators ,
844
+ Class <A > constraintType , Class <? extends ConstraintValidator <A , ?>> validatorType
845
+ ) {
845
846
validators .put ( constraintType , Collections .singletonList ( ConstraintValidatorDescriptor .forBuiltinClass ( validatorType , constraintType ) ) );
846
847
}
847
848
848
- private static <A extends Annotation > void putBuiltinConstraints (Map <Class <? extends Annotation >, List <ConstraintValidatorDescriptor <?>>> validators ,
849
- Class <A > constraintType , List <Class <? extends ConstraintValidator <A , ?>>> validatorTypes ) {
849
+ private static <A extends Annotation > void putBuiltinConstraints (
850
+ Map <Class <? extends Annotation >, List <? extends ConstraintValidatorDescriptor <?>>> validators ,
851
+ Class <A > constraintType , List <Class <? extends ConstraintValidator <A , ?>>> validatorTypes
852
+ ) {
850
853
List <ConstraintValidatorDescriptor <?>> descriptors = new ArrayList <>( validatorTypes .size () );
851
854
852
855
for ( Class <? extends ConstraintValidator <A , ?>> validatorType : validatorTypes ) {
@@ -873,14 +876,13 @@ public static Set<String> getBuiltinConstraints() {
873
876
* <li>internally registered validators for built-in constraints</li>
874
877
* <li>XML configuration and</li>
875
878
* <li>programmatically registered validators (see
876
- * {@link org.hibernate.validator.cfg. ConstraintMapping#constraintDefinition(Class)}).</li>
879
+ * {@link ConstraintMapping#constraintDefinition(Class)}).</li>
877
880
* </ul>
878
881
*
879
882
* The result is cached internally.
880
883
*
881
884
* @param annotationType The constraint annotation type.
882
885
* @param <A> the type of the annotation
883
- *
884
886
* @return The validator classes for the given type.
885
887
*/
886
888
public <A extends Annotation > List <ConstraintValidatorDescriptor <A >> getAllValidatorDescriptors (Class <A > annotationType ) {
@@ -895,7 +897,6 @@ public <A extends Annotation> List<ConstraintValidatorDescriptor<A>> getAllValid
895
897
* @param annotationType The annotation of interest.
896
898
* @param validationTarget The target, either annotated element or parameters.
897
899
* @param <A> the type of the annotation
898
- *
899
900
* @return A list with matching validator descriptors.
900
901
*/
901
902
public <A extends Annotation > List <ConstraintValidatorDescriptor <A >> findValidatorDescriptors (Class <A > annotationType , ValidationTarget validationTarget ) {
@@ -937,9 +938,8 @@ public <A extends Annotation> void putValidatorDescriptors(Class<A> annotationTy
937
938
* Checks whether a given annotation is a multi value constraint or not.
938
939
*
939
940
* @param annotationType the annotation type to check.
940
- *
941
941
* @return {@code true} if the specified annotation is a multi value constraints, {@code false}
942
- * otherwise.
942
+ * otherwise.
943
943
*/
944
944
public boolean isMultiValueConstraint (Class <? extends Annotation > annotationType ) {
945
945
if ( isJdkAnnotation ( annotationType ) ) {
@@ -974,7 +974,6 @@ public boolean isMultiValueConstraint(Class<? extends Annotation> annotationType
974
974
*
975
975
* @param multiValueConstraint the multi-value constraint annotation from which to retrieve the contained constraints
976
976
* @param <A> the type of the annotation
977
- *
978
977
* @return A list of constraint annotations, may be empty but never {@code null}.
979
978
*/
980
979
public <A extends Annotation > List <Annotation > getConstraintsFromMultiValueConstraint (A multiValueConstraint ) {
@@ -997,7 +996,6 @@ public <A extends Annotation> List<Annotation> getConstraintsFromMultiValueConst
997
996
* </ul>
998
997
*
999
998
* @param annotationType The annotation type to test.
1000
- *
1001
999
* @return {@code true} if the annotation fulfills the above conditions, {@code false} otherwise.
1002
1000
*/
1003
1001
public boolean isConstraintAnnotation (Class <? extends Annotation > annotationType ) {
@@ -1139,32 +1137,84 @@ private boolean isJavaMoneyInClasspath() {
1139
1137
* Returns the default validators for the given constraint type.
1140
1138
*
1141
1139
* @param annotationType The constraint annotation type.
1142
- *
1143
1140
* @return A list with the default validators as retrieved from
1144
- * {@link Constraint#validatedBy()} or the list of validators for
1145
- * built-in constraints.
1141
+ * {@link Constraint#validatedBy()} or the list of validators for
1142
+ * built-in constraints.
1146
1143
*/
1147
1144
@ SuppressWarnings ("unchecked" )
1148
- private <A extends Annotation > List <ConstraintValidatorDescriptor <A >> getDefaultValidatorDescriptors (Class <A > annotationType ) {
1149
- //safe cause all CV for a given annotation A are CV<A, ?>
1150
- final List <ConstraintValidatorDescriptor <A >> builtInValidators = (List <ConstraintValidatorDescriptor <A >>) enabledBuiltinConstraints
1151
- .get ( annotationType );
1145
+ protected abstract <A extends Annotation > List <ConstraintValidatorDescriptor <A >> getDefaultValidatorDescriptors (Class <A > annotationType );
1152
1146
1153
- if ( builtInValidators != null ) {
1154
- return builtInValidators ;
1147
+ private static boolean isClassPresent (String className ) {
1148
+ return IsClassPresent .action ( className , ConstraintHelper .class .getClassLoader () );
1149
+ }
1150
+
1151
+ private static class StaticConstraintHelper extends ConstraintHelper {
1152
+
1153
+ @ Immutable
1154
+ private final Map <Class <? extends Annotation >, List <? extends ConstraintValidatorDescriptor <?>>> enabledBuiltinConstraints ;
1155
+
1156
+ private StaticConstraintHelper () {
1157
+ this .enabledBuiltinConstraints = Collections .unmodifiableMap ( resolve ( new HashSet <>( Arrays .asList ( BuiltinConstraint .values () ) ) ) );
1155
1158
}
1156
1159
1157
- Class <? extends ConstraintValidator <A , ?>>[] validatedBy = (Class <? extends ConstraintValidator <A , ?>>[]) annotationType
1158
- .getAnnotation ( Constraint .class )
1159
- .validatedBy ();
1160
+ @ SuppressWarnings ("unchecked" )
1161
+ @ Override
1162
+ protected <A extends Annotation > List <ConstraintValidatorDescriptor <A >> getDefaultValidatorDescriptors (Class <A > annotationType ) {
1163
+ //safe cause all CV for a given annotation A are CV<A, ?>
1164
+ final List <ConstraintValidatorDescriptor <A >> builtInValidators = (List <ConstraintValidatorDescriptor <A >>) enabledBuiltinConstraints
1165
+ .get ( annotationType );
1166
+
1167
+ if ( builtInValidators != null ) {
1168
+ return builtInValidators ;
1169
+ }
1170
+
1171
+ Class <? extends ConstraintValidator <A , ?>>[] validatedBy = (Class <? extends ConstraintValidator <A , ?>>[]) annotationType
1172
+ .getAnnotation ( Constraint .class )
1173
+ .validatedBy ();
1160
1174
1161
- return Stream .of ( validatedBy )
1162
- .map ( c -> ConstraintValidatorDescriptor .forClass ( c , annotationType ) )
1163
- .collect ( Collectors .collectingAndThen ( Collectors .toList (), CollectionHelper ::toImmutableList ) );
1175
+ return Stream .of ( validatedBy )
1176
+ .map ( c -> ConstraintValidatorDescriptor .forClass ( c , annotationType ) )
1177
+ .collect ( Collectors .collectingAndThen ( Collectors .toList (), CollectionHelper ::toImmutableList ) );
1178
+ }
1164
1179
}
1165
1180
1166
- private static boolean isClassPresent (String className ) {
1167
- return IsClassPresent .action ( className , ConstraintHelper .class .getClassLoader () );
1181
+ private static class DynamicConstraintHelper extends ConstraintHelper {
1182
+
1183
+ @ Immutable
1184
+ private final Map <Class <? extends Annotation >, List <? extends ConstraintValidatorDescriptor <?>>> enabledBuiltinConstraints ;
1185
+
1186
+ private DynamicConstraintHelper (Set <BuiltinConstraint > initialConstraints ) {
1187
+ this .enabledBuiltinConstraints = new HashMap <>( resolve ( initialConstraints ) );
1188
+ }
1189
+
1190
+ @ SuppressWarnings ("unchecked" )
1191
+ @ Override
1192
+ protected <A extends Annotation > List <ConstraintValidatorDescriptor <A >> getDefaultValidatorDescriptors (Class <A > annotationType ) {
1193
+ //safe cause all CV for a given annotation A are CV<A, ?>
1194
+ final List <ConstraintValidatorDescriptor <A >> builtInValidators = (List <ConstraintValidatorDescriptor <A >>) enabledBuiltinConstraints
1195
+ .get ( annotationType );
1196
+
1197
+ if ( builtInValidators != null ) {
1198
+ return builtInValidators ;
1199
+ }
1200
+ else {
1201
+ // let's give it a try and see if we can find this constraint among the built-in ones:
1202
+ Set <BuiltinConstraint > builtinConstraints = BuiltinConstraint .resolve ( Collections .singleton ( annotationType .getName () ) );
1203
+ if ( !builtinConstraints .isEmpty () ) {
1204
+ Map <Class <? extends Annotation >, List <? extends ConstraintValidatorDescriptor <?>>> additionalDescriptors = resolve ( builtinConstraints );
1205
+ enabledBuiltinConstraints .putAll ( additionalDescriptors );
1206
+ return (List <ConstraintValidatorDescriptor <A >>) additionalDescriptors .get ( annotationType );
1207
+ }
1208
+ }
1209
+
1210
+ Class <? extends ConstraintValidator <A , ?>>[] validatedBy = (Class <? extends ConstraintValidator <A , ?>>[]) annotationType
1211
+ .getAnnotation ( Constraint .class )
1212
+ .validatedBy ();
1213
+
1214
+ return Stream .of ( validatedBy )
1215
+ .map ( c -> ConstraintValidatorDescriptor .forClass ( c , annotationType ) )
1216
+ .collect ( Collectors .collectingAndThen ( Collectors .toList (), CollectionHelper ::toImmutableList ) );
1217
+ }
1168
1218
}
1169
1219
1170
1220
/**
@@ -1183,8 +1233,10 @@ private <A extends Annotation> void put(Class<A> annotationType, List<Constraint
1183
1233
constraintValidatorDescriptors .put ( annotationType , validatorDescriptors );
1184
1234
}
1185
1235
1186
- private <A extends Annotation > List <ConstraintValidatorDescriptor <A >> computeIfAbsent (Class <A > annotationType ,
1187
- Function <? super Class <A >, List <ConstraintValidatorDescriptor <A >>> mappingFunction ) {
1236
+ private <A extends Annotation > List <ConstraintValidatorDescriptor <A >> computeIfAbsent (
1237
+ Class <A > annotationType ,
1238
+ Function <? super Class <A >, List <ConstraintValidatorDescriptor <A >>> mappingFunction
1239
+ ) {
1188
1240
return (List <ConstraintValidatorDescriptor <A >>) constraintValidatorDescriptors .computeIfAbsent (
1189
1241
annotationType ,
1190
1242
(Function <? super Class <? extends Annotation >, ? extends List <? extends ConstraintValidatorDescriptor <?>>>) mappingFunction
0 commit comments