Skip to content

Commit

Permalink
HV-1439 Detect built-in constraints right away and keep a cache of th…
Browse files Browse the repository at this point in the history
…e detected constraints
  • Loading branch information
gsmet committed Aug 3, 2017
1 parent 39e70a9 commit ca0a804
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 21 deletions.
Expand Up @@ -345,6 +345,7 @@ public HibernateValidatorContext usingContext() {
@Override
public void close() {
constraintValidatorManager.clear();
constraintHelper.clear();
for ( BeanMetaDataManager beanMetaDataManager : beanMetaDataManagers.values() ) {
beanMetaDataManager.clear();
}
Expand Down
Expand Up @@ -275,6 +275,7 @@
import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredMethods;
import org.hibernate.validator.internal.util.privilegedactions.GetMethod;
import org.hibernate.validator.internal.util.privilegedactions.LoadClass;
import org.hibernate.validator.internal.util.stereotypes.Immutable;

/**
* Keeps track of builtin constraints and their validator implementations, as well as already resolved validator definitions.
Expand All @@ -296,9 +297,13 @@ public class ConstraintHelper {
private static final String JODA_TIME_CLASS_NAME = "org.joda.time.ReadableInstant";
private static final String JAVA_MONEY_CLASS_NAME = "javax.money.MonetaryAmount";

// immutable
@Immutable
private final Map<Class<? extends Annotation>, List<? extends ConstraintValidatorDescriptor<?>>> builtinConstraints;

private final ConcurrentMap<Class<? extends Annotation>, Boolean> externalConstraints = new ConcurrentHashMap<>();

private final ConcurrentMap<Class<? extends Annotation>, Boolean> multiValueConstraints = new ConcurrentHashMap<>();

private final ValidatorDescriptorMap validatorDescriptors = new ValidatorDescriptorMap();

public ConstraintHelper() {
Expand Down Expand Up @@ -771,22 +776,24 @@ public boolean isMultiValueConstraint(Class<? extends Annotation> annotationType
return false;
}

boolean isMultiValueConstraint = false;
final Method method = run( GetMethod.action( annotationType, "value" ) );
if ( method != null ) {
Class<?> returnType = method.getReturnType();
if ( returnType.isArray() && returnType.getComponentType().isAnnotation() ) {
@SuppressWarnings("unchecked")
Class<? extends Annotation> componentType = (Class<? extends Annotation>) returnType.getComponentType();
if ( isConstraintAnnotation( componentType ) || isBuiltinConstraint( componentType ) ) {
isMultiValueConstraint = true;
}
else {
isMultiValueConstraint = false;
return multiValueConstraints.computeIfAbsent( annotationType, a -> {
boolean isMultiValueConstraint = false;
final Method method = run( GetMethod.action( a, "value" ) );
if ( method != null ) {
Class<?> returnType = method.getReturnType();
if ( returnType.isArray() && returnType.getComponentType().isAnnotation() ) {
@SuppressWarnings("unchecked")
Class<? extends Annotation> componentType = (Class<? extends Annotation>) returnType.getComponentType();
if ( isConstraintAnnotation( componentType ) ) {
isMultiValueConstraint = Boolean.TRUE;
}
else {
isMultiValueConstraint = Boolean.FALSE;
}
}
}
}
return isMultiValueConstraint;
return isMultiValueConstraint;
} );
}

/**
Expand Down Expand Up @@ -826,17 +833,23 @@ public <A extends Annotation> List<Annotation> getConstraintsFromMultiValueConst
* @return {@code true} if the annotation fulfills the above conditions, {@code false} otherwise.
*/
public boolean isConstraintAnnotation(Class<? extends Annotation> annotationType) {
if ( isBuiltinConstraint( annotationType ) ) {
return true;
}

if ( annotationType.getAnnotation( Constraint.class ) == null ) {
return false;
}

assertMessageParameterExists( annotationType );
assertGroupsParameterExists( annotationType );
assertPayloadParameterExists( annotationType );
assertValidationAppliesToParameterSetUpCorrectly( annotationType );
assertNoParameterStartsWithValid( annotationType );
return externalConstraints.computeIfAbsent( annotationType, a -> {
assertMessageParameterExists( a );
assertGroupsParameterExists( a );
assertPayloadParameterExists( a );
assertValidationAppliesToParameterSetUpCorrectly( a );
assertNoParameterStartsWithValid( a );

return true;
return Boolean.TRUE;
} );
}

private void assertNoParameterStartsWithValid(Class<? extends Annotation> annotationType) {
Expand Down Expand Up @@ -932,6 +945,11 @@ public boolean isJdkAnnotation(Class<? extends Annotation> annotation) {
( pakkage.getName().startsWith( "java." ) || pakkage.getName().startsWith( "jdk.internal" ) );
}

public void clear() {
externalConstraints.clear();
multiValueConstraints.clear();
}

private static boolean isJodaTimeInClasspath() {
return isClassPresent( JODA_TIME_CLASS_NAME );
}
Expand Down

0 comments on commit ca0a804

Please sign in to comment.