From abd5bf53500599651065dc829b4b30a5b760d705 Mon Sep 17 00:00:00 2001
From: marko-bekhta
Date: Fri, 30 Nov 2018 14:38:20 +0100
Subject: [PATCH] [value-context-changes] Introduce HibernateConstrainedType,
that wraps class
`HibernateConstrainedType` wraps a class and is used as a key for metadata
manager. It can also wrap strings or any other objects/data for metadata
of property holders and other kinds of objects.
---
.../engine/HibernateConstrainedType.java | 29 ++++
.../TypeConstraintMappingContextImpl.java | 3 +-
.../internal/engine/ValidatorImpl.java | 160 +++++++++++-------
.../JavaBeanConstrainedType.java | 83 +++++++++
.../NormalizedJavaBeanConstrainedType.java | 41 +++++
.../engine/constrainedtype/package-info.java | 11 ++
.../ValidationContextBuilder.java | 21 +--
.../metadata/BeanMetaDataManager.java | 3 +-
.../metadata/BeanMetaDataManagerImpl.java | 62 ++++---
.../PredefinedScopeBeanMetaDataManager.java | 94 +++++++---
.../AbstractConstraintMetaData.java | 18 ++
.../metadata/aggregated/BeanMetaData.java | 3 +-
.../aggregated/BeanMetaDataBuilder.java | 48 +++---
.../metadata/aggregated/BeanMetaDataImpl.java | 70 ++++----
.../aggregated/CascadingMetaData.java | 5 +-
.../metadata/aggregated/ClassMetaData.java | 13 +-
.../aggregated/ExecutableMetaData.java | 10 +-
.../metadata/aggregated/MetaDataBuilder.java | 19 ++-
.../aggregated/ParameterMetaData.java | 5 +-
.../metadata/aggregated/PropertyMetaData.java | 9 +-
.../AbstractPropertyConstraintLocation.java | 9 +-
.../location/BeanConstraintLocation.java | 20 ++-
.../metadata/location/ConstraintLocation.java | 3 +-
.../CrossParameterConstraintLocation.java | 9 +-
.../location/ParameterConstraintLocation.java | 8 +-
.../ReturnValueConstraintLocation.java | 8 +-
.../TypeArgumentConstraintLocation.java | 5 +-
.../provider/AnnotationMetaDataProvider.java | 15 +-
.../metadata/provider/MetaDataProvider.java | 3 +-
.../ProgrammaticMetaDataProvider.java | 13 +-
.../provider/XmlMetaDataProvider.java | 18 +-
.../metadata/raw/BeanConfiguration.java | 23 +--
.../test/cfg/ConstraintMappingTest.java | 2 +-
.../internal/engine/path/PathImplTest.java | 3 +-
.../metadata/BeanMetaDataManagerTest.java | 11 +-
.../aggregated/ExecutableMetaDataTest.java | 11 +-
.../aggregated/ParameterMetaDataTest.java | 5 +-
.../aggregated/PropertyMetaDataTest.java | 7 +-
.../AnnotationMetaDataProviderTest.java | 37 ++--
.../TypeAnnotationMetaDataRetrievalTest.java | 15 +-
.../testutils/BeanMetadataManagerUtil.java | 29 ++++
41 files changed, 660 insertions(+), 301 deletions(-)
create mode 100644 engine/src/main/java/org/hibernate/validator/engine/HibernateConstrainedType.java
create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/constrainedtype/JavaBeanConstrainedType.java
create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/constrainedtype/NormalizedJavaBeanConstrainedType.java
create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/constrainedtype/package-info.java
create mode 100644 engine/src/test/java/org/hibernate/validator/testutils/BeanMetadataManagerUtil.java
diff --git a/engine/src/main/java/org/hibernate/validator/engine/HibernateConstrainedType.java b/engine/src/main/java/org/hibernate/validator/engine/HibernateConstrainedType.java
new file mode 100644
index 0000000000..5cafa92f54
--- /dev/null
+++ b/engine/src/main/java/org/hibernate/validator/engine/HibernateConstrainedType.java
@@ -0,0 +1,29 @@
+/*
+ * Hibernate Validator, declare and validate application constraints
+ *
+ * License: Apache License, Version 2.0
+ * See the license.txt file in the root directory or .
+ */
+package org.hibernate.validator.engine;
+
+import java.util.List;
+
+/**
+ * An interface that represents a type/class of a bean that will be validated.
+ * Based on this type set of constraints will be determined, and applied to the
+ * validated object.
+ *
+ * @author Marko Bekhta
+ * @since 6.1
+ */
+public interface HibernateConstrainedType {
+
+ /**
+ * @return a class of an object that will be validated.
+ */
+ Class getActuallClass();
+
+ List> getHierarchy();
+
+ boolean isInterface();
+}
diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java
index 20c012e4e8..7a8577155d 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java
@@ -23,6 +23,7 @@
import org.hibernate.validator.cfg.context.MethodConstraintMappingContext;
import org.hibernate.validator.cfg.context.PropertyConstraintMappingContext;
import org.hibernate.validator.cfg.context.TypeConstraintMappingContext;
+import org.hibernate.validator.internal.engine.constrainedtype.JavaBeanConstrainedType;
import org.hibernate.validator.internal.engine.ConstraintCreationContext;
import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl.ConstraintType;
import org.hibernate.validator.internal.metadata.raw.BeanConfiguration;
@@ -231,7 +232,7 @@ public ConstructorConstraintMappingContext constructor(Class>... parameterType
BeanConfiguration build(ConstraintCreationContext constraintCreationContext) {
return new BeanConfiguration<>(
ConfigurationSource.API,
- beanClass,
+ new JavaBeanConstrainedType<>( beanClass ),
buildConstraintElements( constraintCreationContext ),
defaultGroupSequence,
getDefaultGroupSequenceProvider()
diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java
index 8b317201e6..31ce29f0da 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java
@@ -34,6 +34,8 @@
import javax.validation.valueextraction.ValueExtractor;
import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext;
+import org.hibernate.validator.engine.HibernateConstrainedType;
+import org.hibernate.validator.internal.engine.constrainedtype.JavaBeanConstrainedType;
import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager;
import org.hibernate.validator.internal.engine.groups.Group;
import org.hibernate.validator.internal.engine.groups.GroupWithInheritance;
@@ -148,18 +150,57 @@ public ValidatorImpl(ConstraintValidatorFactory constraintValidatorFactory,
@Override
public final Set> validate(T object, Class>... groups) {
+ HibernateConstrainedType constrainedType = object == null ? null : new JavaBeanConstrainedType<>( (Class) object.getClass() );
+ return validate( object, constrainedType, groups );
+ }
+
+ @Override
+ public final Set> validateProperty(T object, String propertyName, Class>... groups) {
+ HibernateConstrainedType constrainedType = object == null ? null : new JavaBeanConstrainedType<>( (Class) object.getClass() );
+ return validateProperty( object, propertyName, constrainedType, groups );
+ }
+
+ @Override
+ public final Set> validateValue(Class beanType, String propertyName, Object value, Class>... groups) {
+ HibernateConstrainedType constrainedType = beanType == null ? null : new JavaBeanConstrainedType<>( beanType );
+ return validateValue( beanType, propertyName, value, constrainedType, groups );
+ }
+
+ @Override
+ public Set> validateParameters(T object, Method method, Object[] parameterValues, Class>... groups) {
+ HibernateConstrainedType constrainedType = object == null ? null : new JavaBeanConstrainedType<>( ( (Class) object.getClass() ) );
+ return validateParameters( object, method, parameterValues, constrainedType, groups );
+ }
+
+ @Override
+ public Set> validateConstructorParameters(Constructor extends T> constructor, Object[] parameterValues, Class>... groups) {
+ HibernateConstrainedType constrainedType = constructor == null ? null : new JavaBeanConstrainedType<>( ( (Class) constructor.getDeclaringClass() ) );
+ return validateConstructorParameters( constructor, parameterValues, constrainedType, groups );
+ }
+
+ @Override
+ public Set> validateConstructorReturnValue(Constructor extends T> constructor, T createdObject, Class>... groups) {
+ HibernateConstrainedType constrainedType = constructor == null ? null : new JavaBeanConstrainedType<>( ( (Class) constructor.getDeclaringClass() ) );
+ return validateConstructorReturnValue( constructor, createdObject, constrainedType, groups );
+ }
+
+ @Override
+ public Set> validateReturnValue(T object, Method method, Object returnValue, Class>... groups) {
+ HibernateConstrainedType constrainedType = object == null ? null : new JavaBeanConstrainedType<>( ( (Class) object.getClass() ) );
+ return validateReturnValue( object, method, returnValue, constrainedType, groups );
+ }
+
+ private Set> validate(T object, HibernateConstrainedType constrainedType, Class>... groups) {
Contracts.assertNotNull( object, MESSAGES.validatedObjectMustNotBeNull() );
sanityCheckGroups( groups );
- @SuppressWarnings("unchecked")
- Class rootBeanClass = (Class) object.getClass();
- BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass );
+ BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( constrainedType );
if ( !rootBeanMetaData.hasConstraints() ) {
return Collections.emptySet();
}
- BaseBeanValidationContext validationContext = getValidationContextBuilder().forValidate( rootBeanClass, rootBeanMetaData, object );
+ BaseBeanValidationContext validationContext = getValidationContextBuilder().forValidate( constrainedType, rootBeanMetaData, object );
ValidationOrder validationOrder = determineGroupValidationOrder( groups );
BeanValueContext, Object> valueContext = ValueContexts.getLocalExecutionContextForBean(
@@ -172,22 +213,19 @@ public final Set> validate(T object, Class>... grou
return validateInContext( validationContext, valueContext, validationOrder );
}
- @Override
- public final Set> validateProperty(T object, String propertyName, Class>... groups) {
+ private Set> validateProperty(T object, String propertyName, HibernateConstrainedType constrainedType, Class>... groups) {
Contracts.assertNotNull( object, MESSAGES.validatedObjectMustNotBeNull() );
sanityCheckPropertyPath( propertyName );
sanityCheckGroups( groups );
- @SuppressWarnings("unchecked")
- Class rootBeanClass = (Class) object.getClass();
- BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass );
+ BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( constrainedType );
if ( !rootBeanMetaData.hasConstraints() ) {
return Collections.emptySet();
}
PathImpl propertyPath = PathImpl.createPathFromString( propertyName );
- BaseBeanValidationContext validationContext = getValidationContextBuilder().forValidateProperty( rootBeanClass, rootBeanMetaData, object,
+ BaseBeanValidationContext validationContext = getValidationContextBuilder().forValidateProperty( constrainedType, rootBeanMetaData, object,
propertyPath );
BeanValueContext, Object> valueContext = getValueContextForPropertyValidation( validationContext, propertyPath );
@@ -201,77 +239,71 @@ public final Set> validateProperty(T object, String p
return validateInContext( validationContext, valueContext, validationOrder );
}
- @Override
- public final Set> validateValue(Class beanType, String propertyName, Object value, Class>... groups) {
+ private Set> validateValue(Class beanType, String propertyName, Object value, HibernateConstrainedType constrainedType, Class>... groups) {
Contracts.assertNotNull( beanType, MESSAGES.beanTypeCannotBeNull() );
sanityCheckPropertyPath( propertyName );
sanityCheckGroups( groups );
- BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( beanType );
+ BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( constrainedType );
if ( !rootBeanMetaData.hasConstraints() ) {
return Collections.emptySet();
}
PathImpl propertyPath = PathImpl.createPathFromString( propertyName );
- BaseBeanValidationContext validationContext = getValidationContextBuilder().forValidateValue( beanType, rootBeanMetaData, propertyPath );
+ BaseBeanValidationContext validationContext = getValidationContextBuilder().forValidateValue( constrainedType, rootBeanMetaData, propertyPath );
ValidationOrder validationOrder = determineGroupValidationOrder( groups );
return validateValueInContext(
validationContext,
value,
+ constrainedType,
propertyPath,
validationOrder
);
}
- @Override
- public Set> validateParameters(T object, Method method, Object[] parameterValues, Class>... groups) {
+ private Set> validateParameters(T object, Method method, Object[] parameterValues, HibernateConstrainedType constrainedType, Class>... groups) {
Contracts.assertNotNull( object, MESSAGES.validatedObjectMustNotBeNull() );
Contracts.assertNotNull( method, MESSAGES.validatedMethodMustNotBeNull() );
Contracts.assertNotNull( parameterValues, MESSAGES.validatedParameterArrayMustNotBeNull() );
- return validateParameters( object, (Executable) method, parameterValues, groups );
+ return validateParameters( object, (Executable) method, parameterValues, constrainedType, groups );
}
- @Override
- public Set> validateConstructorParameters(Constructor extends T> constructor, Object[] parameterValues, Class>... groups) {
+ private Set> validateConstructorParameters(Constructor extends T> constructor, Object[] parameterValues, HibernateConstrainedType constrainedType, Class>... groups) {
Contracts.assertNotNull( constructor, MESSAGES.validatedConstructorMustNotBeNull() );
Contracts.assertNotNull( parameterValues, MESSAGES.validatedParameterArrayMustNotBeNull() );
- return validateParameters( null, constructor, parameterValues, groups );
+ return validateParameters( null, constructor, parameterValues, constrainedType, groups );
}
- @Override
- public Set> validateConstructorReturnValue(Constructor extends T> constructor, T createdObject, Class>... groups) {
+ private Set> validateConstructorReturnValue(Constructor extends T> constructor, T createdObject, HibernateConstrainedType constrainedType, Class>... groups) {
Contracts.assertNotNull( constructor, MESSAGES.validatedConstructorMustNotBeNull() );
Contracts.assertNotNull( createdObject, MESSAGES.validatedConstructorCreatedInstanceMustNotBeNull() );
- return validateReturnValue( null, constructor, createdObject, groups );
+ return validateReturnValue( null, constructor, createdObject, constrainedType, groups );
}
- @Override
- public Set> validateReturnValue(T object, Method method, Object returnValue, Class>... groups) {
+ private Set> validateReturnValue(T object, Method method, Object returnValue, HibernateConstrainedType constrainedType, Class>... groups) {
Contracts.assertNotNull( object, MESSAGES.validatedObjectMustNotBeNull() );
Contracts.assertNotNull( method, MESSAGES.validatedMethodMustNotBeNull() );
- return validateReturnValue( object, (Executable) method, returnValue, groups );
+ return validateReturnValue( object, (Executable) method, returnValue, constrainedType, groups );
}
- private Set> validateParameters(T object, Executable executable, Object[] parameterValues, Class>... groups) {
+ private Set> validateParameters(T object, Executable executable, Object[] parameterValues, HibernateConstrainedType constrainedType, Class>... groups) {
sanityCheckGroups( groups );
- @SuppressWarnings("unchecked")
- Class rootBeanClass = object != null ? (Class) object.getClass() : (Class) executable.getDeclaringClass();
- BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass );
+ BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( constrainedType );
if ( !rootBeanMetaData.hasConstraints() ) {
return Collections.emptySet();
}
ExecutableValidationContext validationContext = getValidationContextBuilder().forValidateParameters(
- rootBeanClass,
+ constrainedType,
rootBeanMetaData,
object,
executable,
@@ -285,19 +317,17 @@ private Set> validateParameters(T object, Executable
return validationContext.getFailingConstraints();
}
- private Set> validateReturnValue(T object, Executable executable, Object returnValue, Class>... groups) {
+ private Set> validateReturnValue(T object, Executable executable, Object returnValue, HibernateConstrainedType constrainedType, Class>... groups) {
sanityCheckGroups( groups );
- @SuppressWarnings("unchecked")
- Class rootBeanClass = object != null ? (Class) object.getClass() : (Class) executable.getDeclaringClass();
- BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass );
+ BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( constrainedType );
if ( !rootBeanMetaData.hasConstraints() ) {
return Collections.emptySet();
}
ExecutableValidationContext validationContext = getValidationContextBuilder().forValidateReturnValue(
- rootBeanClass,
+ constrainedType,
rootBeanMetaData,
object,
executable,
@@ -313,7 +343,7 @@ private Set> validateReturnValue(T object, Executable
@Override
public final BeanDescriptor getConstraintsForClass(Class> clazz) {
- return beanMetaDataManager.getBeanMetaData( clazz ).getBeanDescriptor();
+ return beanMetaDataManager.getBeanMetaData( new JavaBeanConstrainedType<>( clazz ) ).getBeanDescriptor();
}
@Override
@@ -453,7 +483,7 @@ private void validateConstraintsForCurrentGroup(BaseBeanValidationContext> val
private void validateConstraintsForDefaultGroup(BaseBeanValidationContext> validationContext, BeanValueContext valueContext) {
final BeanMetaData beanMetaData = valueContext.getCurrentBeanMetaData();
- final Map, Class>> validatedInterfaces = new HashMap<>();
+ final Map, HibernateConstrainedType>> validatedInterfaces = new HashMap<>();
// evaluating the constraints of a bean per class in hierarchy, this is necessary to detect potential default group re-definitions
for ( BeanMetaData super U> hostingBeanMetaData : beanMetaData.getBeanMetadataHierarchy() ) {
@@ -469,7 +499,7 @@ private void validateConstraintsForDefaultGroup(BaseBeanValidationContext>
boolean validationSuccessful = true;
for ( Group defaultSequenceMember : groupOfGroups ) {
- validationSuccessful = validateConstraintsForSingleDefaultGroupElement( validationContext, valueContext, validatedInterfaces, hostingBeanMetaData.getBeanClass(),
+ validationSuccessful = validateConstraintsForSingleDefaultGroupElement( validationContext, valueContext, validatedInterfaces, hostingBeanMetaData.getConstrainedType(),
metaConstraints, defaultSequenceMember );
}
@@ -484,7 +514,7 @@ private void validateConstraintsForDefaultGroup(BaseBeanValidationContext>
// fast path in case the default group sequence hasn't been redefined
else {
Set> metaConstraints = hostingBeanMetaData.getDirectMetaConstraints();
- validateConstraintsForSingleDefaultGroupElement( validationContext, valueContext, validatedInterfaces, hostingBeanMetaData.getBeanClass(), metaConstraints,
+ validateConstraintsForSingleDefaultGroupElement( validationContext, valueContext, validatedInterfaces, hostingBeanMetaData.getConstrainedType(), metaConstraints,
Group.DEFAULT_GROUP );
validationContext.markCurrentBeanAsProcessed( valueContext );
}
@@ -496,8 +526,8 @@ private void validateConstraintsForDefaultGroup(BaseBeanValidationContext>
}
}
- private boolean validateConstraintsForSingleDefaultGroupElement(BaseBeanValidationContext> validationContext, ValueContext valueContext, final Map, Class>> validatedInterfaces,
- Class super U> clazz, Set> metaConstraints, Group defaultSequenceMember) {
+ private boolean validateConstraintsForSingleDefaultGroupElement(BaseBeanValidationContext> validationContext, ValueContext valueContext, final Map, HibernateConstrainedType>> validatedInterfaces,
+ HibernateConstrainedType super U> constrainedType, Set> metaConstraints, Group defaultSequenceMember) {
boolean validationSuccessful = true;
valueContext.setCurrentGroup( defaultSequenceMember.getDefiningClass() );
@@ -505,13 +535,13 @@ private boolean validateConstraintsForSingleDefaultGroupElement(BaseBeanVali
for ( MetaConstraint> metaConstraint : metaConstraints ) {
// HV-466, an interface implemented more than one time in the hierarchy has to be validated only one
// time. An interface can define more than one constraint, we have to check the class we are validating.
- final Class> declaringClass = metaConstraint.getLocation().getDeclaringClass();
+ final HibernateConstrainedType> declaringClass = metaConstraint.getLocation().getDeclaringConstrainedType();
if ( declaringClass.isInterface() ) {
- Class> validatedForClass = validatedInterfaces.get( declaringClass );
- if ( validatedForClass != null && !validatedForClass.equals( clazz ) ) {
+ HibernateConstrainedType> validatedForClass = validatedInterfaces.get( declaringClass );
+ if ( validatedForClass != null && !validatedForClass.equals( constrainedType ) ) {
continue;
}
- validatedInterfaces.put( declaringClass, clazz );
+ validatedInterfaces.put( declaringClass, constrainedType );
}
boolean tmp = validateMetaConstraint( validationContext, valueContext, valueContext.getCurrentBean(), metaConstraint );
@@ -775,9 +805,9 @@ private BeanValueContext, Object> buildNewLocalExecutionContext(CascadingMetaD
return newValueContext;
}
- private Set> validateValueInContext(BaseBeanValidationContext validationContext, Object value, PathImpl propertyPath,
- ValidationOrder validationOrder) {
- BeanValueContext, Object> valueContext = getValueContextForValueValidation( validationContext.getRootBeanClass(), propertyPath );
+ private Set> validateValueInContext(BaseBeanValidationContext validationContext, Object value, HibernateConstrainedType constrainedType,
+ PathImpl propertyPath, ValidationOrder validationOrder) {
+ BeanValueContext, Object> valueContext = getValueContextForValueValidation( constrainedType, propertyPath );
valueContext.setCurrentValidatedValue( value );
BeanMetaData> beanMetaData = valueContext.getCurrentBeanMetaData();
@@ -1146,13 +1176,13 @@ private void validateReturnValueForSingleGroup(BaseBeanValidationContext
* the given property path.
*/
private BeanValueContext, V> getValueContextForPropertyValidation(BaseBeanValidationContext> validationContext, PathImpl propertyPath) {
- Class> clazz = validationContext.getRootBeanClass();
BeanMetaData> beanMetaData = validationContext.getRootBeanMetaData();
Object value = validationContext.getRootBean();
PropertyMetaData propertyMetaData = null;
Iterator propertyPathIter = propertyPath.iterator();
+ HibernateConstrainedType> constrainedType = null;
while ( propertyPathIter.hasNext() ) {
// cast is ok, since we are dealing with engine internal classes
NodeImpl propertyPathNode = (NodeImpl) propertyPathIter.next();
@@ -1169,7 +1199,6 @@ private BeanValueContext, V> getValueContextForPropertyValidation(BaseBean
if ( value == null ) {
throw LOG.getUnableToReachPropertyToValidateException( validationContext.getRootBean(), propertyPath );
}
- clazz = value.getClass();
// if we are in the case of an iterable and we want to validate an element of this iterable, we have to get the
// element value
@@ -1190,19 +1219,22 @@ else if ( propertyPathNode.getKey() != null ) {
throw LOG.getUnableToReachPropertyToValidateException( validationContext.getRootBean(), propertyPath );
}
- clazz = value.getClass();
- beanMetaData = beanMetaDataManager.getBeanMetaData( clazz );
+ // TODO: is there a better way of doing this?
+ constrainedType = propertyMetaData.getConstrainedTypeForPropertyPathAndValue( propertyPathNode, value );
+
+ beanMetaData = beanMetaDataManager.getBeanMetaData( constrainedType );
propertyMetaData = getBeanPropertyMetaData( beanMetaData, propertyPathNode );
}
else {
- beanMetaData = beanMetaDataManager.getBeanMetaData( clazz );
+ constrainedType = propertyMetaData.getConstrainedTypeForPropertyPathAndValue( propertyPathNode, value );
+ beanMetaData = beanMetaDataManager.getBeanMetaData( constrainedType );
}
}
}
if ( propertyMetaData == null ) {
// should only happen if the property path is empty, which should never happen
- throw LOG.getInvalidPropertyPathException( clazz, propertyPath.asString() );
+ throw LOG.getInvalidPropertyPathException( constrainedType.getActuallClass() , propertyPath.asString() );
}
propertyPath.removeLeafNode();
@@ -1216,14 +1248,14 @@ else if ( propertyPathNode.getKey() != null ) {
* We are only able to use the static types as we don't have the value.
*
*
- * @param rootBeanClass The class of the root bean.
+ * @param hibernateConstrainedType The class of the root bean.
* @param propertyPath The property path for which constraints have to be collected.
* @return Returns an instance of {@code ValueContext} which describes the local validation context associated to
* the given property path.
*/
- private BeanValueContext, V> getValueContextForValueValidation(Class> rootBeanClass,
+ private BeanValueContext, V> getValueContextForValueValidation(HibernateConstrainedType> hibernateConstrainedType,
PathImpl propertyPath) {
- Class> clazz = rootBeanClass;
+ HibernateConstrainedType> constrainedType = hibernateConstrainedType;
BeanMetaData> beanMetaData = null;
PropertyMetaData propertyMetaData = null;
@@ -1232,7 +1264,7 @@ private BeanValueContext, V> getValueContextForValueValidation(Class> ro
while ( propertyPathIter.hasNext() ) {
// cast is ok, since we are dealing with engine internal classes
NodeImpl propertyPathNode = (NodeImpl) propertyPathIter.next();
- beanMetaData = beanMetaDataManager.getBeanMetaData( clazz );
+ beanMetaData = beanMetaDataManager.getBeanMetaData( constrainedType );
propertyMetaData = getBeanPropertyMetaData( beanMetaData, propertyPathNode );
// if the property is not the leaf property, we set up the context for the next iteration
@@ -1242,19 +1274,19 @@ private BeanValueContext, V> getValueContextForValueValidation(Class> ro
if ( propertyPathNode.isIterable() ) {
propertyPathNode = (NodeImpl) propertyPathIter.next();
- clazz = ReflectionHelper.getClassFromType( ReflectionHelper.getCollectionElementType( propertyMetaData.getType() ) );
- beanMetaData = beanMetaDataManager.getBeanMetaData( clazz );
+ constrainedType = propertyMetaData.getConstrainedTypeForPropertyPath( propertyPathNode );
+ beanMetaData = beanMetaDataManager.getBeanMetaData( constrainedType );
propertyMetaData = getBeanPropertyMetaData( beanMetaData, propertyPathNode );
}
else {
- clazz = ReflectionHelper.getClassFromType( propertyMetaData.getType() );
+ constrainedType = propertyMetaData.getConstrainedTypeForPropertyPath( propertyPathNode );
}
}
}
if ( propertyMetaData == null ) {
// should only happen if the property path is empty, which should never happen
- throw LOG.getInvalidPropertyPathException( clazz, propertyPath.asString() );
+ throw LOG.getInvalidPropertyPathException( constrainedType.getActuallClass(), propertyPath.asString() );
}
propertyPath.removeLeafNode();
@@ -1370,7 +1402,7 @@ private boolean shouldFailFast(BaseBeanValidationContext> validationContext) {
private PropertyMetaData getBeanPropertyMetaData(BeanMetaData> beanMetaData, Path.Node propertyNode) {
if ( !ElementKind.PROPERTY.equals( propertyNode.getKind() ) ) {
- throw LOG.getInvalidPropertyPathException( beanMetaData.getBeanClass(), propertyNode.getName() );
+ throw LOG.getInvalidPropertyPathException( beanMetaData.getConstrainedType().getActuallClass(), propertyNode.getName() );
}
return beanMetaData.getMetaDataFor( propertyNode.getName() );
diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constrainedtype/JavaBeanConstrainedType.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constrainedtype/JavaBeanConstrainedType.java
new file mode 100644
index 0000000000..208424cc48
--- /dev/null
+++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constrainedtype/JavaBeanConstrainedType.java
@@ -0,0 +1,83 @@
+/*
+ * Hibernate Validator, declare and validate application constraints
+ *
+ * License: Apache License, Version 2.0
+ * See the license.txt file in the root directory or .
+ */
+package org.hibernate.validator.internal.engine.constrainedtype;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hibernate.validator.engine.HibernateConstrainedType;
+import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper;
+import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer;
+
+/**
+ * An implementation of {@link HibernateConstrainedType} for regular JavaBeans.
+ * Wrapps a {@link Class} object to adapt it to the needs of HV usages.
+ *
+ * @author Marko Bekhta
+ */
+public class JavaBeanConstrainedType implements HibernateConstrainedType {
+
+ private final Class clazz;
+
+ public JavaBeanConstrainedType(Class clazz) {
+ this.clazz = clazz;
+ }
+
+ @Override
+ public Class getActuallClass() {
+ return clazz;
+ }
+
+ @Override
+ public List> getHierarchy() {
+ List> hierarchy = ClassHierarchyHelper.getHierarchy( clazz );
+ List> result = new ArrayList<>( hierarchy.size() );
+ for ( Class super T> clazzz : hierarchy ) {
+ result.add( new JavaBeanConstrainedType<>( clazzz ) );
+ }
+ return result;
+ }
+
+ @Override
+ public boolean isInterface() {
+ return clazz.isInterface();
+ }
+
+ public HibernateConstrainedType normalize(BeanMetaDataClassNormalizer normalizer) {
+ return new NormalizedJavaBeanConstrainedType<>( normalizer, clazz );
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if ( this == o ) {
+ return true;
+ }
+ if ( o == null || !( o instanceof JavaBeanConstrainedType ) ) {
+ return false;
+ }
+
+ JavaBeanConstrainedType> that = (JavaBeanConstrainedType>) o;
+
+ if ( !clazz.equals( that.clazz ) ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return clazz.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "JavaBeanConstrainedType{" +
+ "clazz=" + clazz +
+ '}';
+ }
+}
diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constrainedtype/NormalizedJavaBeanConstrainedType.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constrainedtype/NormalizedJavaBeanConstrainedType.java
new file mode 100644
index 0000000000..5e7e2b3419
--- /dev/null
+++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constrainedtype/NormalizedJavaBeanConstrainedType.java
@@ -0,0 +1,41 @@
+/*
+ * Hibernate Validator, declare and validate application constraints
+ *
+ * License: Apache License, Version 2.0
+ * See the license.txt file in the root directory or .
+ */
+package org.hibernate.validator.internal.engine.constrainedtype;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hibernate.validator.engine.HibernateConstrainedType;
+import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper;
+import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer;
+
+/**
+ * Uses {@link org.hibernate.validator.metadata.BeanMetaDataClassNormalizer} before
+ * creating a {@link HibernateConstrainedType}.
+ *
+ * @author Marko Bekhta
+ */
+public class NormalizedJavaBeanConstrainedType extends JavaBeanConstrainedType {
+ private final BeanMetaDataClassNormalizer normalizer;
+
+ public NormalizedJavaBeanConstrainedType(BeanMetaDataClassNormalizer normalizer, Class clazz) {
+ super( (Class) normalizer.normalize( clazz ) );
+ this.normalizer = normalizer;
+ }
+
+ @Override
+ public List> getHierarchy() {
+ List> hierarchy = ClassHierarchyHelper.getHierarchy( getActuallClass() );
+ List> result = new ArrayList<>( hierarchy.size() );
+ //TODO : question - do we actually need to normalize anything here. Wouldn't it be enough to normalize only when
+ // the metadata is retrieved ?
+ for ( Class super T> clazzz : hierarchy ) {
+ result.add( (NormalizedJavaBeanConstrainedType super T>) new NormalizedJavaBeanConstrainedType<>( normalizer, normalizer.normalize( clazzz ) ) );
+ }
+ return result;
+ }
+}
diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constrainedtype/package-info.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constrainedtype/package-info.java
new file mode 100644
index 0000000000..4ded10bfd9
--- /dev/null
+++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constrainedtype/package-info.java
@@ -0,0 +1,11 @@
+/*
+ * Hibernate Validator, declare and validate application constraints
+ *
+ * License: Apache License, Version 2.0
+ * See the license.txt file in the root directory or .
+ */
+
+/**
+ * Classes implementing {@link org.hibernate.validator.engine.HibernateConstrainedType}.
+ */
+package org.hibernate.validator.internal.engine.constrainedtype;
diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContextBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContextBuilder.java
index 1d1d388d30..24c9fd8cf9 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContextBuilder.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContextBuilder.java
@@ -12,6 +12,7 @@
import javax.validation.TraversableResolver;
import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext;
+import org.hibernate.validator.engine.HibernateConstrainedType;
import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager;
import org.hibernate.validator.internal.engine.path.PathImpl;
import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData;
@@ -43,7 +44,7 @@ public ValidationContextBuilder(
this.validatorScopedContext = validatorScopedContext;
}
- public BaseBeanValidationContext forValidate(Class rootBeanClass, BeanMetaData rootBeanMetaData, T rootBean) {
+ public BaseBeanValidationContext forValidate(HibernateConstrainedType constrainedType, BeanMetaData rootBeanMetaData, T rootBean) {
return new BeanValidationContext<>(
constraintValidatorManager,
constraintValidatorFactory,
@@ -51,12 +52,12 @@ public BaseBeanValidationContext forValidate(Class rootBeanClass, Bean
traversableResolver,
constraintValidatorInitializationContext,
rootBean,
- rootBeanClass,
+ constrainedType.getActuallClass(),
rootBeanMetaData
);
}
- public BaseBeanValidationContext forValidateProperty(Class rootBeanClass, BeanMetaData rootBeanMetaData, T rootBean, PathImpl propertyPath) {
+ public BaseBeanValidationContext forValidateProperty(HibernateConstrainedType constrainedType, BeanMetaData rootBeanMetaData, T rootBean, PathImpl propertyPath) {
return new PropertyValidationContext<>(
constraintValidatorManager,
constraintValidatorFactory,
@@ -64,13 +65,13 @@ public BaseBeanValidationContext forValidateProperty(Class rootBeanCla
traversableResolver,
constraintValidatorInitializationContext,
rootBean,
- rootBeanClass,
+ constrainedType.getActuallClass(),
rootBeanMetaData,
propertyPath.getLeafNode().getName()
);
}
- public BaseBeanValidationContext forValidateValue(Class rootBeanClass, BeanMetaData rootBeanMetaData, PathImpl propertyPath) {
+ public BaseBeanValidationContext forValidateValue(HibernateConstrainedType constrainedType, BeanMetaData rootBeanMetaData, PathImpl propertyPath) {
return new PropertyValidationContext<>(
constraintValidatorManager,
constraintValidatorFactory,
@@ -78,14 +79,14 @@ public BaseBeanValidationContext forValidateValue(Class rootBeanClass,
traversableResolver,
constraintValidatorInitializationContext,
null, //root bean
- rootBeanClass,
+ constrainedType.getActuallClass(),
rootBeanMetaData,
propertyPath.getLeafNode().getName()
);
}
public ExecutableValidationContext forValidateParameters(
- Class rootBeanClass,
+ HibernateConstrainedType constrainedType,
BeanMetaData rootBeanMetaData,
T rootBean,
Executable executable,
@@ -97,7 +98,7 @@ public ExecutableValidationContext forValidateParameters(
traversableResolver,
constraintValidatorInitializationContext,
rootBean,
- rootBeanClass,
+ constrainedType.getActuallClass(),
rootBeanMetaData,
executable,
rootBeanMetaData.getMetaDataFor( executable ),
@@ -106,7 +107,7 @@ public ExecutableValidationContext forValidateParameters(
}
public ExecutableValidationContext forValidateReturnValue(
- Class rootBeanClass,
+ HibernateConstrainedType constrainedType,
BeanMetaData rootBeanMetaData,
T rootBean,
Executable executable,
@@ -118,7 +119,7 @@ public ExecutableValidationContext forValidateReturnValue(
traversableResolver,
constraintValidatorInitializationContext,
rootBean,
- rootBeanClass,
+ constrainedType.getActuallClass(),
rootBeanMetaData,
executable,
rootBeanMetaData.getMetaDataFor( executable ),
diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManager.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManager.java
index 127b7a3652..3491a3ded6 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManager.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManager.java
@@ -6,6 +6,7 @@
*/
package org.hibernate.validator.internal.metadata;
+import org.hibernate.validator.engine.HibernateConstrainedType;
import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData;
/**
@@ -16,7 +17,7 @@
*/
public interface BeanMetaDataManager {
- BeanMetaData getBeanMetaData(Class beanClass);
+ BeanMetaData getBeanMetaData(HibernateConstrainedType constrainedType);
void clear();
}
diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManagerImpl.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManagerImpl.java
index fc319ca2ea..c190bec323 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManagerImpl.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManagerImpl.java
@@ -12,15 +12,16 @@
import static org.hibernate.validator.internal.util.logging.Messages.MESSAGES;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
+import org.hibernate.validator.engine.HibernateConstrainedType;
import org.hibernate.validator.internal.engine.ConstraintCreationContext;
import org.hibernate.validator.internal.engine.MethodValidationConfiguration;
import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator;
import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData;
import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataBuilder;
-import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataImpl;
import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptions;
import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl;
import org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider;
@@ -32,7 +33,6 @@
import org.hibernate.validator.internal.util.Contracts;
import org.hibernate.validator.internal.util.ExecutableHelper;
import org.hibernate.validator.internal.util.ExecutableParameterNameProvider;
-import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper;
import org.hibernate.validator.internal.util.stereotypes.Immutable;
/**
@@ -51,7 +51,7 @@
* @author Gunnar Morling
* @author Chris Beckey <cbeckey@paypal.com>
* @author Guillaume Smet
-*/
+ */
public class BeanMetaDataManagerImpl implements BeanMetaDataManager {
/**
* The default initial capacity for this cache.
@@ -85,7 +85,7 @@ public class BeanMetaDataManagerImpl implements BeanMetaDataManager {
/**
* Used to cache the constraint meta data for validated entities
*/
- private final ConcurrentReferenceHashMap, BeanMetaData>> beanMetaDataCache;
+ private final ConcurrentReferenceHashMap, BeanMetaData>> beanMetaDataCache;
/**
* Used for resolving type parameters. Thread-safe.
@@ -141,20 +141,19 @@ public BeanMetaDataManagerImpl(ConstraintCreationContext constraintCreationConte
this.metaDataProviders = CollectionHelper.toImmutableList( tmpMetaDataProviders );
}
- @Override
@SuppressWarnings("unchecked")
- public BeanMetaData getBeanMetaData(Class beanClass) {
- Contracts.assertNotNull( beanClass, MESSAGES.beanTypeCannotBeNull() );
+ public BeanMetaData getBeanMetaData(HibernateConstrainedType constrainedType) {
+ Contracts.assertNotNull( constrainedType, MESSAGES.beanTypeCannotBeNull() );
// First, let's do a simple lookup as it's the default case
- BeanMetaData beanMetaData = (BeanMetaData) beanMetaDataCache.get( beanClass );
+ BeanMetaData beanMetaData = (BeanMetaData) beanMetaDataCache.get( constrainedType );
if ( beanMetaData != null ) {
return beanMetaData;
}
- beanMetaData = createBeanMetaData( beanClass );
- BeanMetaData previousBeanMetaData = (BeanMetaData) beanMetaDataCache.putIfAbsent( beanClass, beanMetaData );
+ beanMetaData = createBeanMetaData( constrainedType );
+ BeanMetaData previousBeanMetaData = (BeanMetaData) beanMetaDataCache.putIfAbsent( constrainedType, beanMetaData );
// we return the previous value if not null
if ( previousBeanMetaData != null ) {
@@ -178,22 +177,44 @@ public int numberOfCachedBeanMetaDataInstances() {
* data providers for the given type and its hierarchy.
*
* @param The type of interest.
- * @param clazz The type's class.
+ * @param constrainedType The type's class.
*
* @return A bean meta data object for the given type.
*/
- private BeanMetaDataImpl createBeanMetaData(Class clazz) {
+ private BeanMetaData createBeanMetaData(HibernateConstrainedType constrainedType) {
+ List> hierarchy = constrainedType.getHierarchy();
+
+ if ( hierarchy.isEmpty() ) {
+ // it means that our `constrained type is an interface and we don't care about super-type bean metadata.
+ // can happen if not a real class is passed for validation but for example a Validator#getConstraintsForClass(Class>)
+ // is called
+ hierarchy = Collections.singletonList( constrainedType );
+ }
+
+ List> list = new ArrayList<>( hierarchy.size() );
+ for ( int index = hierarchy.size() - 1; index > -1; index-- ) {
+ HibernateConstrainedType super T> type = hierarchy.get( index );
+ // we skip interfaces if any occur, unless constrained type is an interface itself...
+ if ( !constrainedType.equals( type ) && type.isInterface() ) {
+ continue;
+ }
+ list.add( 0, beanMetaDataCache.computeIfAbsent( type, cType -> findSingleBeanMetaData( cType, list ) ) );
+ }
+
+ return (BeanMetaData) list.get( 0 );
+ }
+
+ private BeanMetaData findSingleBeanMetaData(HibernateConstrainedType constrainedType, List> hierarchy) {
BeanMetaDataBuilder builder = BeanMetaDataBuilder.getInstance(
constraintCreationContext, executableHelper, parameterNameProvider,
- validationOrderGenerator, clazz, methodValidationConfiguration );
+ validationOrderGenerator, constrainedType, methodValidationConfiguration );
for ( MetaDataProvider provider : metaDataProviders ) {
- for ( BeanConfiguration super T> beanConfiguration : getBeanConfigurationForHierarchy( provider, clazz ) ) {
+ for ( BeanConfiguration super T> beanConfiguration : getBeanConfigurationForHierarchy( provider, constrainedType ) ) {
builder.add( beanConfiguration );
}
}
-
- return builder.build( this );
+ return builder.build( hierarchy );
}
/**
@@ -212,16 +233,17 @@ private AnnotationProcessingOptions getAnnotationProcessingOptionsFromNonDefault
* Returns a list with the configurations for all types contained in the given type's hierarchy (including
* implemented interfaces) starting at the specified type.
*
- * @param beanClass The type of interest.
+ * @param constrainedType The type of interest.
* @param The type of the class to get the configurations for.
+ *
* @return A set with the configurations for the complete hierarchy of the given type. May be empty, but never
* {@code null}.
*/
- private List> getBeanConfigurationForHierarchy(MetaDataProvider provider, Class beanClass) {
+ private List> getBeanConfigurationForHierarchy(MetaDataProvider provider, HibernateConstrainedType constrainedType) {
List> configurations = newArrayList();
- for ( Class super T> clazz : ClassHierarchyHelper.getHierarchy( beanClass ) ) {
- BeanConfiguration super T> configuration = provider.getBeanConfiguration( clazz );
+ for ( HibernateConstrainedType super T> type : constrainedType.getHierarchy() ) {
+ BeanConfiguration super T> configuration = provider.getBeanConfiguration( type );
if ( configuration != null ) {
configurations.add( configuration );
}
diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/PredefinedScopeBeanMetaDataManager.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/PredefinedScopeBeanMetaDataManager.java
index 6ee54a152c..71965e97ca 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/metadata/PredefinedScopeBeanMetaDataManager.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/PredefinedScopeBeanMetaDataManager.java
@@ -10,17 +10,20 @@
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import org.hibernate.validator.engine.HibernateConstrainedType;
import org.hibernate.validator.internal.engine.ConstraintCreationContext;
import org.hibernate.validator.internal.engine.MethodValidationConfiguration;
+import org.hibernate.validator.internal.engine.constrainedtype.JavaBeanConstrainedType;
+import org.hibernate.validator.internal.engine.constrainedtype.NormalizedJavaBeanConstrainedType;
import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator;
import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData;
import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataBuilder;
-import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataImpl;
import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptions;
import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl;
import org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider;
@@ -30,8 +33,6 @@
import org.hibernate.validator.internal.util.CollectionHelper;
import org.hibernate.validator.internal.util.ExecutableHelper;
import org.hibernate.validator.internal.util.ExecutableParameterNameProvider;
-import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper;
-import org.hibernate.validator.internal.util.classhierarchy.Filters;
import org.hibernate.validator.internal.util.logging.Log;
import org.hibernate.validator.internal.util.logging.LoggerFactory;
import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer;
@@ -45,7 +46,7 @@ public class PredefinedScopeBeanMetaDataManager implements BeanMetaDataManager {
/**
* Used to cache the constraint meta data for validated entities
*/
- private final Map, BeanMetaData>> beanMetaDataMap;
+ private final Map, BeanMetaData>> beanMetaDataMap;
public PredefinedScopeBeanMetaDataManager(ConstraintCreationContext constraintCreationContext,
ExecutableHelper executableHelper,
@@ -71,16 +72,17 @@ public PredefinedScopeBeanMetaDataManager(ConstraintCreationContext constraintCr
metaDataProviders.add( defaultProvider );
metaDataProviders.addAll( optionalMetaDataProviders );
- Map, BeanMetaData>> tmpBeanMetadataMap = new HashMap<>();
+ Map, BeanMetaData>> tmpBeanMetadataMap = new HashMap<>();
for ( Class> validatedClass : beanClassesToInitialize ) {
- BeanMetaData> beanMetaData = createBeanMetaData( this, constraintCreationContext, executableHelper, parameterNameProvider,
- javaBeanHelper, validationOrderGenerator, optionalMetaDataProviders, methodValidationConfiguration,
- metaDataProviders, validatedClass );
+ JavaBeanConstrainedType constrainedType = new NormalizedJavaBeanConstrainedType( beanMetaDataClassNormalizer, beanMetaDataClassNormalizer.normalize( validatedClass ) );
+ BeanMetaData> beanMetaData = createBeanMetaData( constraintCreationContext, executableHelper, parameterNameProvider,
+ javaBeanHelper, validationOrderGenerator, methodValidationConfiguration,
+ metaDataProviders, tmpBeanMetadataMap, constrainedType );
- tmpBeanMetadataMap.put( validatedClass, beanMetaData );
+ tmpBeanMetadataMap.put( beanMetaData.getConstrainedType(), beanMetaData );
for ( BeanMetaData> metaData : beanMetaData.getBeanMetadataHierarchy() ) {
- tmpBeanMetadataMap.put( metaData.getBeanClass(), metaData );
+ tmpBeanMetadataMap.put( metaData.getConstrainedType(), metaData );
}
}
@@ -91,10 +93,14 @@ public PredefinedScopeBeanMetaDataManager(ConstraintCreationContext constraintCr
@SuppressWarnings("unchecked")
@Override
- public BeanMetaData getBeanMetaData(Class beanClass) {
- BeanMetaData beanMetaData = (BeanMetaData) beanMetaDataMap.get( beanMetaDataClassNormalizer.normalize( beanClass ) );
+ public BeanMetaData getBeanMetaData(HibernateConstrainedType constrainedType) {
+ HibernateConstrainedType key = constrainedType;
+ if ( constrainedType instanceof JavaBeanConstrainedType ) {
+ key = ( (JavaBeanConstrainedType) constrainedType ).normalize( beanMetaDataClassNormalizer );
+ }
+ BeanMetaData beanMetaData = (BeanMetaData) beanMetaDataMap.get( key );
if ( beanMetaData == null ) {
- throw LOG.uninitializedBeanMetaData( beanClass );
+ throw LOG.uninitializedBeanMetaData( constrainedType.getActuallClass() );
}
return beanMetaData;
}
@@ -109,31 +115,68 @@ public void clear() {
* data providers for the given type and its hierarchy.
*
* @param The type of interest.
- * @param clazz The type's class.
+ * @param beanMetaDataCache The temporary map that might have some of the requried metadata already created
+ * @param constrainedType The type's class.
*
* @return A bean meta data object for the given type.
*/
- private static BeanMetaDataImpl createBeanMetaData(BeanMetaDataManager beanMetaDataManager,
- ConstraintCreationContext constraintCreationContext,
+ private static BeanMetaData createBeanMetaData(ConstraintCreationContext constraintCreationContext,
ExecutableHelper executableHelper,
ExecutableParameterNameProvider parameterNameProvider,
JavaBeanHelper javaBeanHelper,
ValidationOrderGenerator validationOrderGenerator,
- List optionalMetaDataProviders,
MethodValidationConfiguration methodValidationConfiguration,
List metaDataProviders,
- Class clazz) {
+ Map, BeanMetaData>> beanMetaDataCache,
+ HibernateConstrainedType constrainedType) {
+ List> hierarchy = constrainedType.getHierarchy();
+
+ if ( hierarchy.isEmpty() ) {
+ // it means that our `constrained type is an interface and we don't care about super-type bean metadata.
+ // can happen if not a real class is passed for validation but for example a Validator#getConstraintsForClass(Class>)
+ // is called
+ hierarchy = Collections.singletonList( constrainedType );
+ }
+
+ List> list = new ArrayList<>( hierarchy.size() );
+ for ( int index = hierarchy.size() - 1; index > -1; index-- ) {
+ HibernateConstrainedType super T> type = hierarchy.get( index );
+
+ // we skip interfaces if any occur, unless constrained type is an interface itself...
+ if ( !constrainedType.equals( type ) && type.isInterface() ) {
+ continue;
+ }
+
+ list.add( 0, beanMetaDataCache.computeIfAbsent(
+ type,
+ cType -> findSingleBeanMetaData( constraintCreationContext, executableHelper, parameterNameProvider,
+ validationOrderGenerator, methodValidationConfiguration,
+ metaDataProviders, type, list )
+ )
+ );
+ }
+
+ return (BeanMetaData) list.get( 0 );
+ }
+
+ private static BeanMetaData findSingleBeanMetaData(ConstraintCreationContext constraintCreationContext,
+ ExecutableHelper executableHelper,
+ ExecutableParameterNameProvider parameterNameProvider,
+ ValidationOrderGenerator validationOrderGenerator,
+ MethodValidationConfiguration methodValidationConfiguration,
+ List metaDataProviders,
+ HibernateConstrainedType constrainedType,
+ List> hierarchy) {
BeanMetaDataBuilder builder = BeanMetaDataBuilder.getInstance(
constraintCreationContext, executableHelper, parameterNameProvider,
- validationOrderGenerator, clazz, methodValidationConfiguration );
+ validationOrderGenerator, constrainedType, methodValidationConfiguration );
for ( MetaDataProvider provider : metaDataProviders ) {
- for ( BeanConfiguration super T> beanConfiguration : getBeanConfigurationForHierarchy( provider, clazz ) ) {
+ for ( BeanConfiguration super T> beanConfiguration : getBeanConfigurationForHierarchy( provider, constrainedType ) ) {
builder.add( beanConfiguration );
}
}
-
- return builder.build( beanMetaDataManager );
+ return builder.build( hierarchy );
}
/**
@@ -152,15 +195,16 @@ private static AnnotationProcessingOptions getAnnotationProcessingOptionsFromNon
* Returns a list with the configurations for all types contained in the given type's hierarchy (including
* implemented interfaces) starting at the specified type.
*
- * @param beanClass The type of interest.
+ * @param constrainedType The type of interest.
* @param The type of the class to get the configurations for.
+ *
* @return A set with the configurations for the complete hierarchy of the given type. May be empty, but never
* {@code null}.
*/
- private static List> getBeanConfigurationForHierarchy(MetaDataProvider provider, Class beanClass) {
+ private static List> getBeanConfigurationForHierarchy(MetaDataProvider provider, HibernateConstrainedType constrainedType) {
List> configurations = newArrayList();
- for ( Class super T> clazz : ClassHierarchyHelper.getHierarchy( beanClass ) ) {
+ for ( HibernateConstrainedType super T> clazz : constrainedType.getHierarchy() ) {
BeanConfiguration super T> configuration = provider.getBeanConfiguration( clazz );
if ( configuration != null ) {
configurations.add( configuration );
diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/AbstractConstraintMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/AbstractConstraintMetaData.java
index d0760f45ea..2d40dbde7f 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/AbstractConstraintMetaData.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/AbstractConstraintMetaData.java
@@ -25,12 +25,16 @@
import javax.validation.metadata.ContainerElementTypeDescriptor;
import javax.validation.metadata.GroupConversionDescriptor;
+import org.hibernate.validator.engine.HibernateConstrainedType;
+import org.hibernate.validator.internal.engine.constrainedtype.JavaBeanConstrainedType;
+import org.hibernate.validator.internal.engine.path.NodeImpl;
import org.hibernate.validator.internal.metadata.core.MetaConstraint;
import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl;
import org.hibernate.validator.internal.metadata.descriptor.ContainerElementTypeDescriptorImpl;
import org.hibernate.validator.internal.metadata.location.ConstraintLocation;
import org.hibernate.validator.internal.metadata.location.TypeArgumentConstraintLocation;
import org.hibernate.validator.internal.util.CollectionHelper;
+import org.hibernate.validator.internal.util.ReflectionHelper;
import org.hibernate.validator.internal.util.TypeVariables;
import org.hibernate.validator.internal.util.stereotypes.Immutable;
@@ -70,6 +74,20 @@ public AbstractConstraintMetaData(String name,
this.isConstrained = isConstrained;
}
+ public HibernateConstrainedType> getConstrainedTypeForPropertyPath(NodeImpl node) {
+ if ( node.getIndex() == null ) {
+ return new JavaBeanConstrainedType<>( ReflectionHelper.getClassFromType( getType() ) );
+ }
+ else {
+ // TODO: Do we need to make sure that actual index from the node is used and not the 'predefined' one from the helper logic?
+ return new JavaBeanConstrainedType<>( ReflectionHelper.getClassFromType( ReflectionHelper.getCollectionElementType( getType() ) ) );
+ }
+ }
+
+ public HibernateConstrainedType> getConstrainedTypeForPropertyPathAndValue(NodeImpl node, Object value) {
+ return new JavaBeanConstrainedType<>( value.getClass() );
+ }
+
@Override
public String getName() {
return name;
diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaData.java
index ab2bd3cc40..1abaa21fe9 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaData.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaData.java
@@ -14,6 +14,7 @@
import javax.validation.metadata.BeanDescriptor;
+import org.hibernate.validator.engine.HibernateConstrainedType;
import org.hibernate.validator.internal.engine.groups.Sequence;
import org.hibernate.validator.internal.metadata.core.MetaConstraint;
import org.hibernate.validator.internal.metadata.facets.Validatable;
@@ -30,7 +31,7 @@ public interface BeanMetaData extends Validatable {
/**
* @return the class of the bean.
*/
- Class getBeanClass();
+ HibernateConstrainedType getConstrainedType();
/**
* Returns {@code true} if the bean class for this bean meta data has any constraints at all, {@code false} otherwise.
diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataBuilder.java
index 3c12d06850..ef09334ff4 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataBuilder.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataBuilder.java
@@ -11,10 +11,10 @@
import java.util.List;
import java.util.Set;
+import org.hibernate.validator.engine.HibernateConstrainedType;
import org.hibernate.validator.internal.engine.ConstraintCreationContext;
import org.hibernate.validator.internal.engine.MethodValidationConfiguration;
import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator;
-import org.hibernate.validator.internal.metadata.BeanMetaDataManager;
import org.hibernate.validator.internal.metadata.raw.BeanConfiguration;
import org.hibernate.validator.internal.metadata.raw.ConfigurationSource;
import org.hibernate.validator.internal.metadata.raw.ConstrainedElement;
@@ -39,7 +39,7 @@ public class BeanMetaDataBuilder {
private final ConstraintCreationContext constraintCreationContext;
private final ValidationOrderGenerator validationOrderGenerator;
- private final Class beanClass;
+ private final HibernateConstrainedType constrainedType;
private final Set builders = newHashSet();
private final ExecutableHelper executableHelper;
private final ExecutableParameterNameProvider parameterNameProvider;
@@ -56,13 +56,13 @@ private BeanMetaDataBuilder(
ExecutableHelper executableHelper,
ExecutableParameterNameProvider parameterNameProvider,
ValidationOrderGenerator validationOrderGenerator,
- Class beanClass,
+ HibernateConstrainedType constrainedType,
MethodValidationConfiguration methodValidationConfiguration) {
- this.beanClass = beanClass;
this.constraintCreationContext = constraintCreationContext;
this.validationOrderGenerator = validationOrderGenerator;
this.executableHelper = executableHelper;
this.parameterNameProvider = parameterNameProvider;
+ this.constrainedType = constrainedType;
this.methodValidationConfiguration = methodValidationConfiguration;
}
@@ -71,19 +71,19 @@ public static BeanMetaDataBuilder getInstance(
ExecutableHelper executableHelper,
ExecutableParameterNameProvider parameterNameProvider,
ValidationOrderGenerator validationOrderGenerator,
- Class beanClass,
+ HibernateConstrainedType constrainedType,
MethodValidationConfiguration methodValidationConfiguration) {
return new BeanMetaDataBuilder<>(
constraintCreationContext,
executableHelper,
parameterNameProvider,
validationOrderGenerator,
- beanClass,
+ constrainedType,
methodValidationConfiguration );
}
public void add(BeanConfiguration super T> configuration) {
- if ( configuration.getBeanClass().equals( beanClass ) ) {
+ if ( configuration.getConstrainedType().equals( constrainedType ) ) {
if ( configuration.getDefaultGroupSequence() != null
&& ( sequenceSource == null || configuration.getSource()
.getPriority() >= sequenceSource.getPriority() ) ) {
@@ -117,7 +117,7 @@ private void addMetaDataToBuilder(ConstrainedElement constrainableElement, Set build(BeanMetaDataManager beanMetaDataManager) {
+ public BeanMetaDataImpl build(List> beanMetadataHierarchy) {
Set aggregatedElements = newHashSet();
for ( BuilderDelegate builder : builders ) {
@@ -135,17 +135,17 @@ public BeanMetaDataImpl build(BeanMetaDataManager beanMetaDataManager) {
}
return new BeanMetaDataImpl<>(
- beanMetaDataManager,
- beanClass,
+ constrainedType,
defaultGroupSequence,
defaultGroupSequenceProvider,
aggregatedElements,
- validationOrderGenerator
+ validationOrderGenerator,
+ beanMetadataHierarchy
);
}
private static class BuilderDelegate {
- private final Class> beanClass;
+ private final HibernateConstrainedType> constrainedType;
private final ConstrainedElement constrainedElement;
private final ConstraintCreationContext constraintCreationContext;
private final ExecutableHelper executableHelper;
@@ -156,14 +156,14 @@ private static class BuilderDelegate {
private final int hashCode;
public BuilderDelegate(
- Class> beanClass,
+ HibernateConstrainedType> constrainedType,
ConstrainedElement constrainedElement,
ConstraintCreationContext constraintCreationContext,
ExecutableHelper executableHelper,
ExecutableParameterNameProvider parameterNameProvider,
MethodValidationConfiguration methodValidationConfiguration
) {
- this.beanClass = beanClass;
+ this.constrainedType = constrainedType;
this.constrainedElement = constrainedElement;
this.constraintCreationContext = constraintCreationContext;
this.executableHelper = executableHelper;
@@ -174,7 +174,7 @@ public BuilderDelegate(
case FIELD:
ConstrainedField constrainedField = (ConstrainedField) constrainedElement;
metaDataBuilder = new PropertyMetaData.Builder(
- beanClass,
+ constrainedType,
constrainedField,
constraintCreationContext
);
@@ -187,9 +187,9 @@ public BuilderDelegate(
// HV-890 Not adding meta-data for private super-type methods to the method meta-data of this bean;
// It is not needed and it may conflict with sub-type methods of the same signature
- if ( !callable.isPrivate() || beanClass == callable.getDeclaringClass() ) {
+ if ( !callable.isPrivate() || constrainedType.getActuallClass() == callable.getDeclaringClass() ) {
methodBuilder = new ExecutableMetaData.Builder(
- beanClass,
+ constrainedType,
constrainedExecutable,
constraintCreationContext,
executableHelper,
@@ -200,17 +200,17 @@ public BuilderDelegate(
if ( constrainedElement.getKind() == ConstrainedElement.ConstrainedElementKind.GETTER ) {
metaDataBuilder = new PropertyMetaData.Builder(
- beanClass,
+ constrainedType,
constrainedExecutable,
constraintCreationContext
);
}
break;
case TYPE:
- ConstrainedType constrainedType = (ConstrainedType) constrainedElement;
+ ConstrainedType constrainedTypeElement = (ConstrainedType) constrainedElement;
metaDataBuilder = new ClassMetaData.Builder(
- beanClass,
constrainedType,
+ constrainedTypeElement,
constraintCreationContext
);
break;
@@ -236,7 +236,7 @@ public boolean add(ConstrainedElement constrainedElement) {
if ( !added && constrainedElement.getKind().isMethod() && methodBuilder == null ) {
ConstrainedExecutable constrainedMethod = (ConstrainedExecutable) constrainedElement;
methodBuilder = new ExecutableMetaData.Builder(
- beanClass,
+ constrainedType,
constrainedMethod,
constraintCreationContext,
executableHelper,
@@ -273,7 +273,7 @@ public int hashCode() {
private int buildHashCode() {
final int prime = 31;
int result = 1;
- result = prime * result + beanClass.hashCode();
+ result = prime * result + constrainedType.hashCode();
result = prime * result + constrainedElement.hashCode();
return result;
}
@@ -290,7 +290,7 @@ public boolean equals(Object obj) {
return false;
}
BuilderDelegate other = (BuilderDelegate) obj;
- if ( !beanClass.equals( other.beanClass ) ) {
+ if ( !constrainedType.equals( other.constrainedType ) ) {
return false;
}
if ( !constrainedElement.equals( other.constrainedElement ) ) {
diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java
index 499234a871..98b6c50e51 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java
@@ -27,10 +27,11 @@
import javax.validation.metadata.ConstructorDescriptor;
import javax.validation.metadata.PropertyDescriptor;
+import org.hibernate.validator.engine.HibernateConstrainedType;
+import org.hibernate.validator.internal.engine.constrainedtype.JavaBeanConstrainedType;
import org.hibernate.validator.internal.engine.groups.Sequence;
import org.hibernate.validator.internal.engine.groups.ValidationOrder;
import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator;
-import org.hibernate.validator.internal.metadata.BeanMetaDataManager;
import org.hibernate.validator.internal.metadata.core.MetaConstraint;
import org.hibernate.validator.internal.metadata.descriptor.BeanDescriptorImpl;
import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl;
@@ -40,7 +41,6 @@
import org.hibernate.validator.internal.util.CollectionHelper;
import org.hibernate.validator.internal.util.ExecutableHelper;
import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper;
-import org.hibernate.validator.internal.util.classhierarchy.Filters;
import org.hibernate.validator.internal.util.logging.Log;
import org.hibernate.validator.internal.util.logging.LoggerFactory;
import org.hibernate.validator.internal.util.stereotypes.Immutable;
@@ -76,7 +76,7 @@ public final class BeanMetaDataImpl implements BeanMetaData {
/**
* The root bean class for this meta data.
*/
- private final Class beanClass;
+ private final HibernateConstrainedType constrainedType;
/**
* Set of all constraints for this bean type (defined on any implemented interfaces or super types)
@@ -164,18 +164,19 @@ public final class BeanMetaDataImpl implements BeanMetaData {
/**
* Creates a new {@link BeanMetaDataImpl}
*
- * @param beanClass The Java type represented by this meta data object.
+ * @param constrainedType The Java type represented by this meta data object.
* @param defaultGroupSequence The default group sequence.
* @param defaultGroupSequenceProvider The default group sequence provider if set.
* @param constraintMetaDataSet All constraint meta data relating to the represented type.
*/
- public BeanMetaDataImpl(BeanMetaDataManager beanMetaDataManager, Class beanClass,
- List> defaultGroupSequence,
- DefaultGroupSequenceProvider super T> defaultGroupSequenceProvider,
- Set constraintMetaDataSet,
- ValidationOrderGenerator validationOrderGenerator) {
+ public BeanMetaDataImpl(HibernateConstrainedType constrainedType,
+ List> defaultGroupSequence,
+ DefaultGroupSequenceProvider super T> defaultGroupSequenceProvider,
+ Set constraintMetaDataSet,
+ ValidationOrderGenerator validationOrderGenerator,
+ List> beanMetadataHierarchy) {
this.validationOrderGenerator = validationOrderGenerator;
- this.beanClass = beanClass;
+ this.constrainedType = constrainedType;
this.propertyMetaDataMap = newHashMap();
Set propertyMetaDataSet = newHashSet();
@@ -219,22 +220,16 @@ else if ( constraintMetaData.getKind() == ElementKind.BEAN ) {
this.cascadedProperties = CollectionHelper.toImmutableSet( cascadedProperties );
this.allMetaConstraints = CollectionHelper.toImmutableSet( allMetaConstraints );
- // get the metadata for all other classes in hierarchy:
- List> hierarchy = ClassHierarchyHelper.getHierarchy(
- beanClass,
- Filters.excludeInterfaces()
- );
- List> beanMetadataHierarchy = new ArrayList<>( hierarchy.size() );
+ List> beanMetadataHierarchyTmp = new ArrayList<>( beanMetadataHierarchy.size() + 1 );
// metadata for a class `beanClass` should go as a first element in the list
- beanMetadataHierarchy.add( this );
- for ( int index = 1; index < hierarchy.size(); index++ ) {
- beanMetadataHierarchy.add( beanMetaDataManager.getBeanMetaData( hierarchy.get( index ) ) );
+ beanMetadataHierarchyTmp.add( this );
+ for ( BeanMetaData> beanMetaData : beanMetadataHierarchy ) {
+ beanMetadataHierarchyTmp.add( (BeanMetaData super T>) beanMetaData );
}
- this.beanMetadataHierarchyWithoutInterfaces = CollectionHelper.toImmutableList( beanMetadataHierarchy );
-
+ this.beanMetadataHierarchyWithoutInterfaces = CollectionHelper.toImmutableList( beanMetadataHierarchyTmp );
- DefaultGroupSequenceContext super T> defaultGroupContext = getDefaultGroupSequenceData( beanClass, defaultGroupSequence, defaultGroupSequenceProvider, validationOrderGenerator );
+ DefaultGroupSequenceContext super T> defaultGroupContext = getDefaultGroupSequenceData( constrainedType.getActuallClass(), defaultGroupSequence, defaultGroupSequenceProvider, validationOrderGenerator );
this.defaultGroupSequenceProvider = defaultGroupContext.defaultGroupSequenceProvider;
this.defaultGroupSequence = CollectionHelper.toImmutableList( defaultGroupContext.defaultGroupSequence );
this.validationOrder = defaultGroupContext.validationOrder;
@@ -250,8 +245,8 @@ else if ( constraintMetaData.getKind() == ElementKind.BEAN ) {
}
@Override
- public Class getBeanClass() {
- return beanClass;
+ public HibernateConstrainedType getConstrainedType() {
+ return constrainedType;
}
@Override
@@ -268,7 +263,7 @@ public BeanDescriptor getBeanDescriptor() {
beanDescriptor = this.beanDescriptor;
if ( beanDescriptor == null ) {
- beanDescriptor = createBeanDescriptor( beanClass, allMetaConstraints, propertyMetaDataMap, executableMetaDataMap,
+ beanDescriptor = createBeanDescriptor( constrainedType.getActuallClass(), allMetaConstraints, propertyMetaDataMap, executableMetaDataMap,
defaultGroupSequenceRedefined, resolvedDefaultGroupSequence );
this.beanDescriptor = beanDescriptor;
@@ -294,7 +289,7 @@ public PropertyMetaData getMetaDataFor(String propertyName) {
PropertyMetaData propertyMetaData = propertyMetaDataMap.get( propertyName );
if ( propertyMetaData == null ) {
- throw LOG.getPropertyNotDefinedByValidatedTypeException( beanClass, propertyName );
+ throw LOG.getPropertyNotDefinedByValidatedTypeException( constrainedType.getActuallClass(), propertyName );
}
return propertyMetaData;
@@ -323,7 +318,7 @@ public Optional getMetaDataFor(Executable executable) {
if ( executableMetaData == null ) {
// there is no executable metadata - specified object and method do not match
throw LOG.getMethodOrConstructorNotDefinedByValidatedTypeException(
- beanClass,
+ constrainedType.getActuallClass(),
executable
);
}
@@ -335,7 +330,7 @@ public Optional getMetaDataFor(Executable executable) {
public List> getDefaultGroupSequence(T beanState) {
if ( hasDefaultGroupSequenceProvider() ) {
List> providerDefaultGroupSequence = defaultGroupSequenceProvider.getValidationGroups( beanState );
- return getValidDefaultGroupSequence( beanClass, providerDefaultGroupSequence );
+ return getValidDefaultGroupSequence( constrainedType.getActuallClass(), providerDefaultGroupSequence );
}
return defaultGroupSequence;
@@ -346,8 +341,8 @@ public Iterator getDefaultValidationSequence(T beanState) {
if ( hasDefaultGroupSequenceProvider() ) {
List> providerDefaultGroupSequence = defaultGroupSequenceProvider.getValidationGroups( beanState );
return validationOrderGenerator.getDefaultValidationOrder(
- beanClass,
- getValidDefaultGroupSequence( beanClass, providerDefaultGroupSequence )
+ constrainedType.getActuallClass(),
+ getValidDefaultGroupSequence( constrainedType.getActuallClass(), providerDefaultGroupSequence )
)
.getSequenceIterator();
}
@@ -492,13 +487,16 @@ else if ( defaultGroupSequence != null && !defaultGroupSequence.isEmpty() ) {
private Set> getDirectConstraints() {
Set> constraints = newHashSet();
- Set> classAndInterfaces = newHashSet();
- classAndInterfaces.add( beanClass );
- classAndInterfaces.addAll( ClassHierarchyHelper.getDirectlyImplementedInterfaces( beanClass ) );
+ Set> classAndInterfaces = newHashSet();
+ classAndInterfaces.add( constrainedType );
+ for ( Class super T> directlyImplementedInterface : ClassHierarchyHelper.getDirectlyImplementedInterfaces( constrainedType.getActuallClass() ) ) {
+ classAndInterfaces.add( new JavaBeanConstrainedType<>( directlyImplementedInterface ) );
+ }
+
- for ( Class> clazz : classAndInterfaces ) {
+ for ( HibernateConstrainedType> type : classAndInterfaces ) {
for ( MetaConstraint> metaConstraint : allMetaConstraints ) {
- if ( metaConstraint.getLocation().getDeclaringClass().equals( clazz ) ) {
+ if ( metaConstraint.getLocation().getDeclaringConstrainedType().equals( type ) ) {
constraints.add( metaConstraint );
}
}
@@ -562,7 +560,7 @@ private boolean hasDefaultGroupSequenceProvider() {
@Override
public String toString() {
return "BeanMetaDataImpl"
- + "{beanClass=" + beanClass.getSimpleName()
+ + "{beanClass=" + constrainedType.getActuallClass().getSimpleName()
+ ", constraintCount=" + getMetaConstraints().size()
+ ", cascadedPropertiesCount=" + cascadedProperties.size()
+ ", defaultGroupSequence=" + getDefaultGroupSequence( null ) + '}';
diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/CascadingMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/CascadingMetaData.java
index 54f394a56e..96e456820f 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/CascadingMetaData.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/CascadingMetaData.java
@@ -12,6 +12,7 @@
import javax.validation.metadata.GroupConversionDescriptor;
import javax.validation.valueextraction.ValueExtractor;
+import org.hibernate.validator.internal.engine.constrainedtype.JavaBeanConstrainedType;
import org.hibernate.validator.internal.engine.valueextraction.AnnotatedObject;
import org.hibernate.validator.internal.engine.valueextraction.ArrayElement;
import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager;
@@ -62,6 +63,8 @@ public interface CascadingMetaData {
CascadingMetaData addRuntimeContainerSupport(ValueExtractorManager valueExtractorManager, Class> valueClass);
default BeanMetaData> getBeanMetaDataForCascadable(BeanMetaDataManager beanMetaDataManager, Object value) {
- return beanMetaDataManager.getBeanMetaData( value.getClass() );
+ // TODO: for now it's ok to keep the impl here. But it should be eventually moved to corresponding classes.
+ // As this would be different for property holders.
+ return beanMetaDataManager.getBeanMetaData( new JavaBeanConstrainedType<>( value.getClass() ) );
}
}
diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ClassMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ClassMetaData.java
index a9174ad4f1..2004ef0271 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ClassMetaData.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ClassMetaData.java
@@ -11,6 +11,7 @@
import javax.validation.ElementKind;
+import org.hibernate.validator.engine.HibernateConstrainedType;
import org.hibernate.validator.internal.engine.ConstraintCreationContext;
import org.hibernate.validator.internal.metadata.core.MetaConstraint;
import org.hibernate.validator.internal.metadata.descriptor.ClassDescriptorImpl;
@@ -27,12 +28,12 @@
*/
public class ClassMetaData extends AbstractConstraintMetaData {
- private ClassMetaData(Class> beanClass,
+ private ClassMetaData(HibernateConstrainedType> constrainedType,
Set> constraints,
Set> containerElementsConstraints) {
super(
- beanClass.getSimpleName(),
- beanClass,
+ constrainedType.getActuallClass().getSimpleName(),
+ constrainedType.getActuallClass(),
constraints,
containerElementsConstraints,
false,
@@ -84,8 +85,8 @@ public boolean equals(Object obj) {
}
public static class Builder extends MetaDataBuilder {
- public Builder(Class> beanClass, ConstrainedType constrainedType, ConstraintCreationContext constraintCreationContext) {
- super( beanClass, constraintCreationContext );
+ public Builder(HibernateConstrainedType> hibernateConstrainedType, ConstrainedType constrainedType, ConstraintCreationContext constraintCreationContext) {
+ super( hibernateConstrainedType, constraintCreationContext );
add( constrainedType );
}
@@ -103,7 +104,7 @@ public final void add(ConstrainedElement constrainedElement) {
@Override
public ClassMetaData build() {
return new ClassMetaData(
- getBeanClass(),
+ getConstrainedType(),
adaptOriginsAndImplicitGroups( getDirectConstraints() ),
adaptOriginsAndImplicitGroups( getContainerElementConstraints() )
);
diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java
index be8979bc73..82d151f39e 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java
@@ -21,6 +21,7 @@
import javax.validation.ElementKind;
import javax.validation.metadata.ParameterDescriptor;
+import org.hibernate.validator.engine.HibernateConstrainedType;
import org.hibernate.validator.internal.engine.ConstraintCreationContext;
import org.hibernate.validator.internal.engine.MethodValidationConfiguration;
import org.hibernate.validator.internal.metadata.aggregated.rule.MethodConfigurationRule;
@@ -275,13 +276,13 @@ public static class Builder extends MetaDataBuilder {
private final ExecutableParameterNameProvider parameterNameProvider;
public Builder(
- Class> beanClass,
+ HibernateConstrainedType> constrainedType,
ConstrainedExecutable constrainedExecutable,
ConstraintCreationContext constraintCreationContext,
ExecutableHelper executableHelper,
ExecutableParameterNameProvider parameterNameProvider,
MethodValidationConfiguration methodValidationConfiguration) {
- super( beanClass, constraintCreationContext );
+ super( constrainedType, constraintCreationContext );
this.executableHelper = executableHelper;
this.parameterNameProvider = parameterNameProvider;
@@ -310,7 +311,7 @@ private boolean isResolvedToSameMethodInHierarchy(Callable first, Callable other
return first.equals( other );
}
- return first.isResolvedToSameMethodInHierarchy( executableHelper, getBeanClass(), other );
+ return first.isResolvedToSameMethodInHierarchy( executableHelper, getConstrainedType().getActuallClass(), other );
}
private boolean overrides(Callable first, Callable other) {
@@ -412,7 +413,8 @@ private List findParameterMetaData() {
for ( ConstrainedParameter oneParameter : oneExecutable.getAllParameterMetaData() ) {
parameterBuilders.add(
new ParameterMetaData.Builder(
- callable.getDeclaringClass(),
+ // TODO: is ot OK to use this constrained type instead of calling the `callable.getDeclaringConstrainedType()` ?
+ getConstrainedType(),
oneParameter,
constraintCreationContext,
parameterNameProvider
diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/MetaDataBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/MetaDataBuilder.java
index 3a094ca28b..d5f6bd967b 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/MetaDataBuilder.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/MetaDataBuilder.java
@@ -11,6 +11,7 @@
import java.lang.annotation.Annotation;
import java.util.Set;
+import org.hibernate.validator.engine.HibernateConstrainedType;
import org.hibernate.validator.internal.engine.ConstraintCreationContext;
import org.hibernate.validator.internal.metadata.core.ConstraintOrigin;
import org.hibernate.validator.internal.metadata.core.MetaConstraint;
@@ -29,13 +30,13 @@ public abstract class MetaDataBuilder {
protected final ConstraintCreationContext constraintCreationContext;
- private final Class> beanClass;
+ private final HibernateConstrainedType> constrainedType;
private final Set> directConstraints = newHashSet();
private final Set> containerElementsConstraints = newHashSet();
private boolean isCascading = false;
- protected MetaDataBuilder(Class> beanClass, ConstraintCreationContext constraintCreationContext) {
- this.beanClass = beanClass;
+ protected MetaDataBuilder(HibernateConstrainedType> constrainedType, ConstraintCreationContext constraintCreationContext) {
+ this.constrainedType = constrainedType;
this.constraintCreationContext = constraintCreationContext;
}
@@ -85,8 +86,8 @@ protected boolean isCascading() {
return isCascading;
}
- protected Class> getBeanClass() {
- return beanClass;
+ protected HibernateConstrainedType> getConstrainedType() {
+ return constrainedType;
}
/**
@@ -113,20 +114,20 @@ protected Set> adaptOriginsAndImplicitGroups(Set MetaConstraint adaptOriginAndImplicitGroup(MetaConstraint constraint) {
- ConstraintOrigin definedIn = definedIn( beanClass, constraint.getLocation().getDeclaringClass() );
+ ConstraintOrigin definedIn = definedIn( constrainedType, constraint.getLocation().getDeclaringConstrainedType() );
if ( definedIn == ConstraintOrigin.DEFINED_LOCALLY ) {
return constraint;
}
- Class> constraintClass = constraint.getLocation().getDeclaringClass();
+ HibernateConstrainedType> constraintClass = constraint.getLocation().getDeclaringConstrainedType();
ConstraintDescriptorImpl descriptor = new ConstraintDescriptorImpl<>(
constraintCreationContext.getConstraintHelper(),
constraint.getLocation().getConstrainable(),
constraint.getDescriptor().getAnnotationDescriptor(),
constraint.getConstraintLocationKind(),
- constraintClass.isInterface() ? constraintClass : null,
+ constraintClass.isInterface() ? constraintClass.getActuallClass() : null,
definedIn,
constraint.getDescriptor().getConstraintType()
);
@@ -152,7 +153,7 @@ protected Set> adaptConstraints(ConstrainedElement constrained
* constraint was defined on the root bean,
* {@code ConstraintOrigin.DEFINED_IN_HIERARCHY} otherwise.
*/
- private ConstraintOrigin definedIn(Class> rootClass, Class> hierarchyClass) {
+ private ConstraintOrigin definedIn(HibernateConstrainedType> rootClass, HibernateConstrainedType> hierarchyClass) {
if ( hierarchyClass.equals( rootClass ) ) {
return ConstraintOrigin.DEFINED_LOCALLY;
}
diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ParameterMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ParameterMetaData.java
index fadcceb751..f0bda3dcbb 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ParameterMetaData.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ParameterMetaData.java
@@ -13,6 +13,7 @@
import javax.validation.ElementKind;
import javax.validation.metadata.ParameterDescriptor;
+import org.hibernate.validator.engine.HibernateConstrainedType;
import org.hibernate.validator.internal.engine.ConstraintCreationContext;
import org.hibernate.validator.internal.engine.path.PathImpl;
import org.hibernate.validator.internal.metadata.core.MetaConstraint;
@@ -113,11 +114,11 @@ public static class Builder extends MetaDataBuilder {
private Callable callableForNameRetrieval;
private CascadingMetaDataBuilder cascadingMetaDataBuilder;
- public Builder(Class> beanClass,
+ public Builder(HibernateConstrainedType> constrainedType,
ConstrainedParameter constrainedParameter,
ConstraintCreationContext constraintCreationContext,
ExecutableParameterNameProvider parameterNameProvider) {
- super( beanClass, constraintCreationContext );
+ super( constrainedType, constraintCreationContext );
this.parameterNameProvider = parameterNameProvider;
this.parameterType = constrainedParameter.getType();
diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java
index c5cb0683f2..446d781c46 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java
@@ -21,6 +21,7 @@
import javax.validation.ElementKind;
+import org.hibernate.validator.engine.HibernateConstrainedType;
import org.hibernate.validator.internal.engine.ConstraintCreationContext;
import org.hibernate.validator.internal.metadata.core.MetaConstraint;
import org.hibernate.validator.internal.metadata.core.MetaConstraints;
@@ -155,16 +156,16 @@ public static class Builder extends MetaDataBuilder {
private final Map cascadableBuilders = new HashMap<>();
private final Type propertyType;
- public Builder(Class> beanClass, ConstrainedField constrainedProperty, ConstraintCreationContext constraintCreationContext) {
- super( beanClass, constraintCreationContext );
+ public Builder(HibernateConstrainedType> constrainedType, ConstrainedField constrainedProperty, ConstraintCreationContext constraintCreationContext) {
+ super( constrainedType, constraintCreationContext );
this.propertyName = constrainedProperty.getField().getName();
this.propertyType = constrainedProperty.getField().getType();
add( constrainedProperty );
}
- public Builder(Class> beanClass, ConstrainedExecutable constrainedMethod, ConstraintCreationContext constraintCreationContext) {
- super( beanClass, constraintCreationContext );
+ public Builder(HibernateConstrainedType> constrainedType, ConstrainedExecutable constrainedMethod, ConstraintCreationContext constraintCreationContext) {
+ super( constrainedType, constraintCreationContext );
this.propertyName = constrainedMethod.getCallable().as( Property.class ).getPropertyName();
this.propertyType = constrainedMethod.getCallable().getType();
diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/AbstractPropertyConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/AbstractPropertyConstraintLocation.java
index 3d7e105ea3..51ccf690a5 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/AbstractPropertyConstraintLocation.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/AbstractPropertyConstraintLocation.java
@@ -8,6 +8,8 @@
import java.lang.reflect.Type;
+import org.hibernate.validator.engine.HibernateConstrainedType;
+import org.hibernate.validator.internal.engine.constrainedtype.JavaBeanConstrainedType;
import org.hibernate.validator.internal.engine.path.PathImpl;
import org.hibernate.validator.internal.properties.Property;
import org.hibernate.validator.internal.properties.PropertyAccessor;
@@ -28,14 +30,17 @@ public abstract class AbstractPropertyConstraintLocation imp
private final PropertyAccessor propertyAccessor;
+ private final HibernateConstrainedType> constrainedType;
+
AbstractPropertyConstraintLocation(T property) {
this.property = property;
this.propertyAccessor = property.createAccessor();
+ this.constrainedType = new JavaBeanConstrainedType<>( property.getDeclaringClass() );
}
@Override
- public Class> getDeclaringClass() {
- return property.getDeclaringClass();
+ public HibernateConstrainedType> getDeclaringConstrainedType() {
+ return constrainedType;
}
@Override
diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/BeanConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/BeanConstraintLocation.java
index 0ff0fd218f..e7210bab8e 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/BeanConstraintLocation.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/BeanConstraintLocation.java
@@ -8,6 +8,8 @@
import java.lang.reflect.Type;
+import org.hibernate.validator.engine.HibernateConstrainedType;
+import org.hibernate.validator.internal.engine.constrainedtype.JavaBeanConstrainedType;
import org.hibernate.validator.internal.engine.path.PathImpl;
import org.hibernate.validator.internal.properties.Constrainable;
import org.hibernate.validator.internal.util.ExecutableParameterNameProvider;
@@ -25,7 +27,7 @@ class BeanConstraintLocation implements ConstraintLocation {
/**
* The type hosting this location.
*/
- private final Class> declaringClass;
+ private final HibernateConstrainedType> declaringConstrainedType;
/**
* The type to be used for validator resolution for constraints at this location.
@@ -33,7 +35,7 @@ class BeanConstraintLocation implements ConstraintLocation {
private final Type typeForValidatorResolution;
BeanConstraintLocation(Class> declaringClass) {
- this.declaringClass = declaringClass;
+ this.declaringConstrainedType = new JavaBeanConstrainedType<>( declaringClass );
// HV-623 - create a ParameterizedType in case the class has type parameters. Needed for constraint validator
// resolution (HF)
@@ -43,8 +45,8 @@ class BeanConstraintLocation implements ConstraintLocation {
}
@Override
- public Class> getDeclaringClass() {
- return declaringClass;
+ public HibernateConstrainedType> getDeclaringConstrainedType() {
+ return declaringConstrainedType;
}
@Override
@@ -74,14 +76,14 @@ public ConstraintLocationKind getKind() {
@Override
public String toString() {
- return "BeanConstraintLocation [declaringClass=" + declaringClass + ", typeForValidatorResolution=" + typeForValidatorResolution + "]";
+ return "BeanConstraintLocation [declaringClass=" + declaringConstrainedType + ", typeForValidatorResolution=" + typeForValidatorResolution + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
- result = prime * result + ( ( declaringClass == null ) ? 0 : declaringClass.hashCode() );
+ result = prime * result + ( ( declaringConstrainedType == null ) ? 0 : declaringConstrainedType.hashCode() );
result = prime * result + ( ( typeForValidatorResolution == null ) ? 0 : typeForValidatorResolution.hashCode() );
return result;
}
@@ -98,12 +100,12 @@ public boolean equals(Object obj) {
return false;
}
BeanConstraintLocation other = (BeanConstraintLocation) obj;
- if ( declaringClass == null ) {
- if ( other.declaringClass != null ) {
+ if ( declaringConstrainedType == null ) {
+ if ( other.declaringConstrainedType != null ) {
return false;
}
}
- else if ( !declaringClass.equals( other.declaringClass ) ) {
+ else if ( !declaringConstrainedType.equals( other.declaringConstrainedType ) ) {
return false;
}
if ( typeForValidatorResolution == null ) {
diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java
index 20a53feee4..31ba5dbb1b 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java
@@ -10,6 +10,7 @@
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
+import org.hibernate.validator.engine.HibernateConstrainedType;
import org.hibernate.validator.internal.engine.path.PathImpl;
import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind;
import org.hibernate.validator.internal.properties.Callable;
@@ -69,7 +70,7 @@ static ConstraintLocation forParameter(Callable callable, int index) {
/**
* Returns the class hosting this location.
*/
- Class> getDeclaringClass();
+ HibernateConstrainedType> getDeclaringConstrainedType();
/**
* Returns the member represented by this location.
diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/CrossParameterConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/CrossParameterConstraintLocation.java
index 0f36fa5ed7..7f1a6573a2 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/CrossParameterConstraintLocation.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/CrossParameterConstraintLocation.java
@@ -8,6 +8,8 @@
import java.lang.reflect.Type;
+import org.hibernate.validator.engine.HibernateConstrainedType;
+import org.hibernate.validator.internal.engine.constrainedtype.JavaBeanConstrainedType;
import org.hibernate.validator.internal.engine.path.PathImpl;
import org.hibernate.validator.internal.properties.Callable;
import org.hibernate.validator.internal.properties.Constrainable;
@@ -26,14 +28,17 @@ class CrossParameterConstraintLocation implements ConstraintLocation {
private final ConstraintLocationKind kind;
+ private final HibernateConstrainedType> constrainedType;
+
CrossParameterConstraintLocation(Callable callable) {
this.callable = callable;
this.kind = ConstraintLocationKind.of( callable.getConstrainedElementKind() );
+ this.constrainedType = new JavaBeanConstrainedType<>( callable.getDeclaringClass() );
}
@Override
- public Class> getDeclaringClass() {
- return callable.getDeclaringClass();
+ public HibernateConstrainedType> getDeclaringConstrainedType() {
+ return constrainedType;
}
@Override
diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java
index 29392b77ff..e8b7264e70 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java
@@ -8,6 +8,8 @@
import java.lang.reflect.Type;
+import org.hibernate.validator.engine.HibernateConstrainedType;
+import org.hibernate.validator.internal.engine.constrainedtype.JavaBeanConstrainedType;
import org.hibernate.validator.internal.engine.path.PathImpl;
import org.hibernate.validator.internal.properties.Callable;
import org.hibernate.validator.internal.properties.Constrainable;
@@ -27,17 +29,19 @@ public class ParameterConstraintLocation implements ConstraintLocation {
private final int index;
private final Type typeForValidatorResolution;
private final ConstraintLocationKind kind;
+ private final HibernateConstrainedType> constrainedType;
public ParameterConstraintLocation(Callable callable, int index) {
this.callable = callable;
this.index = index;
this.typeForValidatorResolution = ReflectionHelper.boxedType( callable.getParameterGenericType( index ) );
this.kind = ConstraintLocationKind.of( callable.getConstrainedElementKind() );
+ this.constrainedType = new JavaBeanConstrainedType<>( callable.getDeclaringClass() );
}
@Override
- public Class> getDeclaringClass() {
- return callable.getDeclaringClass();
+ public HibernateConstrainedType> getDeclaringConstrainedType() {
+ return constrainedType;
}
@Override
diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ReturnValueConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ReturnValueConstraintLocation.java
index 6ee7b3f924..ac4cde579e 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ReturnValueConstraintLocation.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ReturnValueConstraintLocation.java
@@ -8,6 +8,8 @@
import java.lang.reflect.Type;
+import org.hibernate.validator.engine.HibernateConstrainedType;
+import org.hibernate.validator.internal.engine.constrainedtype.JavaBeanConstrainedType;
import org.hibernate.validator.internal.engine.path.PathImpl;
import org.hibernate.validator.internal.properties.Callable;
import org.hibernate.validator.internal.properties.Constrainable;
@@ -26,15 +28,17 @@ class ReturnValueConstraintLocation implements ConstraintLocation {
private final Callable callable;
private final ConstraintLocationKind kind;
+ private final HibernateConstrainedType> constrainedType;
ReturnValueConstraintLocation(Callable callable) {
this.callable = callable;
this.kind = ConstraintLocationKind.of( callable.getConstrainedElementKind() );
+ this.constrainedType = new JavaBeanConstrainedType<>( callable.getDeclaringClass() );
}
@Override
- public Class> getDeclaringClass() {
- return callable.getDeclaringClass();
+ public HibernateConstrainedType> getDeclaringConstrainedType() {
+ return constrainedType;
}
@Override
diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/TypeArgumentConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/TypeArgumentConstraintLocation.java
index 0f82da3644..557b249cd3 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/TypeArgumentConstraintLocation.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/TypeArgumentConstraintLocation.java
@@ -9,6 +9,7 @@
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
+import org.hibernate.validator.engine.HibernateConstrainedType;
import org.hibernate.validator.internal.engine.path.PathImpl;
import org.hibernate.validator.internal.properties.Constrainable;
import org.hibernate.validator.internal.util.ExecutableParameterNameProvider;
@@ -47,8 +48,8 @@ public class TypeArgumentConstraintLocation implements ConstraintLocation {
}
@Override
- public Class> getDeclaringClass() {
- return delegate.getDeclaringClass();
+ public HibernateConstrainedType> getDeclaringConstrainedType() {
+ return delegate.getDeclaringConstrainedType();
}
@Override
diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java
index bae009a3f7..b977a4f5b1 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java
@@ -38,7 +38,9 @@
import javax.validation.Valid;
import javax.validation.groups.ConvertGroup;
+import org.hibernate.validator.engine.HibernateConstrainedType;
import org.hibernate.validator.group.GroupSequenceProvider;
+import org.hibernate.validator.internal.engine.constrainedtype.JavaBeanConstrainedType;
import org.hibernate.validator.internal.engine.ConstraintCreationContext;
import org.hibernate.validator.internal.engine.valueextraction.ArrayElement;
import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder;
@@ -102,7 +104,7 @@ public AnnotationMetaDataProvider(ConstraintCreationContext constraintCreationCo
this.javaBeanHelper = javaBeanHelper;
this.annotationProcessingOptions = annotationProcessingOptions;
- this.objectBeanConfiguration = retrieveBeanConfiguration( Object.class );
+ this.objectBeanConfiguration = retrieveBeanConfiguration( new JavaBeanConstrainedType<>( Object.class ) );
}
@Override
@@ -112,12 +114,12 @@ public AnnotationProcessingOptions getAnnotationProcessingOptions() {
@Override
@SuppressWarnings("unchecked")
- public BeanConfiguration getBeanConfiguration(Class beanClass) {
- if ( Object.class.equals( beanClass ) ) {
+ public BeanConfiguration getBeanConfiguration(HibernateConstrainedType constrainedType) {
+ if ( Object.class.equals( constrainedType.getActuallClass() ) ) {
return (BeanConfiguration) objectBeanConfiguration;
}
- return retrieveBeanConfiguration( beanClass );
+ return retrieveBeanConfiguration( constrainedType );
}
/**
@@ -125,7 +127,8 @@ public BeanConfiguration getBeanConfiguration(Class beanClass) {
*
* @return Retrieves constraint related meta data from the annotations of the given type.
*/
- private BeanConfiguration retrieveBeanConfiguration(Class beanClass) {
+ private BeanConfiguration retrieveBeanConfiguration(HibernateConstrainedType constrainedType) {
+ Class beanClass = constrainedType.getActuallClass();
Set constrainedElements = getFieldMetaData( beanClass );
constrainedElements.addAll( getMethodMetaData( beanClass ) );
constrainedElements.addAll( getConstructorMetaData( beanClass ) );
@@ -143,7 +146,7 @@ private BeanConfiguration retrieveBeanConfiguration(Class beanClass) {
return new BeanConfiguration<>(
ConfigurationSource.ANNOTATION,
- beanClass,
+ constrainedType,
constrainedElements,
getDefaultGroupSequence( beanClass ),
getDefaultGroupSequenceProvider( beanClass )
diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/MetaDataProvider.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/MetaDataProvider.java
index 19de277cb5..e152fe4d9a 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/MetaDataProvider.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/MetaDataProvider.java
@@ -6,6 +6,7 @@
*/
package org.hibernate.validator.internal.metadata.provider;
+import org.hibernate.validator.engine.HibernateConstrainedType;
import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptions;
import org.hibernate.validator.internal.metadata.raw.BeanConfiguration;
@@ -36,5 +37,5 @@ public interface MetaDataProvider {
* Returns a bean configuration for the given type or {@code null} if this provider has no meta-data on the given
* type.
*/
- BeanConfiguration super T> getBeanConfiguration(Class beanClass);
+ BeanConfiguration super T> getBeanConfiguration(HibernateConstrainedType constrainedType);
}
diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/ProgrammaticMetaDataProvider.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/ProgrammaticMetaDataProvider.java
index 3d3d8828e7..c6e4cad814 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/ProgrammaticMetaDataProvider.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/ProgrammaticMetaDataProvider.java
@@ -13,6 +13,7 @@
import java.util.Map;
import java.util.Set;
+import org.hibernate.validator.engine.HibernateConstrainedType;
import org.hibernate.validator.internal.cfg.context.DefaultConstraintMapping;
import org.hibernate.validator.internal.engine.ConstraintCreationContext;
import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptions;
@@ -35,7 +36,7 @@ public class ProgrammaticMetaDataProvider implements MetaDataProvider {
// cached against the fqcn of a class. not a class instance itself (HV-479)
@Immutable
- private final Map> configuredBeans;
+ private final Map, BeanConfiguration>> configuredBeans;
private final AnnotationProcessingOptions annotationProcessingOptions;
public ProgrammaticMetaDataProvider(ConstraintCreationContext constraintCreationContext,
@@ -64,14 +65,14 @@ private static void assertUniquenessOfConfiguredTypes(Set> createBeanConfigurations(Set mappings,
+ private static Map, BeanConfiguration>> createBeanConfigurations(Set mappings,
ConstraintCreationContext constraintCreationContext) {
- final Map> configuredBeans = new HashMap<>();
+ final Map, BeanConfiguration>> configuredBeans = new HashMap<>();
for ( DefaultConstraintMapping mapping : mappings ) {
Set> beanConfigurations = mapping.getBeanConfigurations( constraintCreationContext );
for ( BeanConfiguration> beanConfiguration : beanConfigurations ) {
- configuredBeans.put( beanConfiguration.getBeanClass().getName(), beanConfiguration );
+ configuredBeans.put( beanConfiguration.getConstrainedType(), beanConfiguration );
}
}
return configuredBeans;
@@ -105,8 +106,8 @@ private static AnnotationProcessingOptions mergeAnnotationProcessingOptions(Set<
@Override
@SuppressWarnings("unchecked")
- public BeanConfiguration