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 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 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 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 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 constructor, Object[] parameterValues, Class... groups) { + private Set> validateConstructorParameters(Constructor 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 constructor, T createdObject, Class... groups) { + private Set> validateConstructorReturnValue(Constructor 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 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 clazz, Set> metaConstraints, Group defaultSequenceMember) { + private boolean validateConstraintsForSingleDefaultGroupElement(BaseBeanValidationContext validationContext, ValueContext valueContext, final Map, HibernateConstrainedType> validatedInterfaces, + HibernateConstrainedType 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 buildNewLocalExecutionContext(CascadingMetaD return newValueContext; } - private Set> validateValueInContext(BaseBeanValidationContext validationContext, Object value, PathImpl propertyPath, - ValidationOrder validationOrder) { - BeanValueContext valueContext = getValueContextForValueValidation( validationContext.getRootBeanClass(), propertyPath ); + private Set> validateValueInContext(BaseBeanValidationContext validationContext, Object value, HibernateConstrainedType constrainedType, + PathImpl propertyPath, ValidationOrder validationOrder) { + BeanValueContext 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 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 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 getValueContextForValueValidation(Class rootBeanClass, + private BeanValueContext getValueContextForValueValidation(HibernateConstrainedType hibernateConstrainedType, PathImpl propertyPath) { - Class clazz = rootBeanClass; + HibernateConstrainedType constrainedType = hibernateConstrainedType; BeanMetaData beanMetaData = null; PropertyMetaData propertyMetaData = null; @@ -1232,7 +1264,7 @@ private BeanValueContext 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 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 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 clazzz : hierarchy ) { + result.add( (NormalizedJavaBeanConstrainedType) 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 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 beanConfiguration : getBeanConfigurationForHierarchy( provider, clazz ) ) { + for ( BeanConfiguration 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 clazz : ClassHierarchyHelper.getHierarchy( beanClass ) ) { - BeanConfiguration configuration = provider.getBeanConfiguration( clazz ); + for ( HibernateConstrainedType type : constrainedType.getHierarchy() ) { + BeanConfiguration 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 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 beanConfiguration : getBeanConfigurationForHierarchy( provider, clazz ) ) { + for ( BeanConfiguration 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 clazz : ClassHierarchyHelper.getHierarchy( beanClass ) ) { + for ( HibernateConstrainedType clazz : constrainedType.getHierarchy() ) { BeanConfiguration 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 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 defaultGroupSequenceProvider, - Set constraintMetaDataSet, - ValidationOrderGenerator validationOrderGenerator) { + public BeanMetaDataImpl(HibernateConstrainedType constrainedType, + List> defaultGroupSequence, + DefaultGroupSequenceProvider 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) beanMetaData ); } - this.beanMetadataHierarchyWithoutInterfaces = CollectionHelper.toImmutableList( beanMetadataHierarchy ); - + this.beanMetadataHierarchyWithoutInterfaces = CollectionHelper.toImmutableList( beanMetadataHierarchyTmp ); - DefaultGroupSequenceContext defaultGroupContext = getDefaultGroupSequenceData( beanClass, defaultGroupSequence, defaultGroupSequenceProvider, validationOrderGenerator ); + DefaultGroupSequenceContext 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 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 getBeanConfiguration(Class beanClass); + BeanConfiguration 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 getBeanConfiguration(Class beanClass) { - return (BeanConfiguration) configuredBeans.get( beanClass.getName() ); + public BeanConfiguration getBeanConfiguration(HibernateConstrainedType constrainedType) { + return (BeanConfiguration) configuredBeans.get( constrainedType ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlMetaDataProvider.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlMetaDataProvider.java index 51320ed3b5..66d420cae3 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlMetaDataProvider.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlMetaDataProvider.java @@ -11,7 +11,9 @@ 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.constrainedtype.JavaBeanConstrainedType; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptions; import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; @@ -32,7 +34,7 @@ public class XmlMetaDataProvider 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; @@ -49,28 +51,30 @@ public XmlMetaDataProvider(ConstraintCreationContext constraintCreationContext, annotationProcessingOptions = mappingParser.getAnnotationProcessingOptions(); } - private static Map> createBeanConfigurations(MappingXmlParser mappingParser) { - final Map> configuredBeans = new HashMap<>(); + private static Map, BeanConfiguration> createBeanConfigurations(MappingXmlParser mappingParser) { + final Map, BeanConfiguration> configuredBeans = new HashMap<>(); for ( Class clazz : mappingParser.getXmlConfiguredClasses() ) { Set constrainedElements = mappingParser.getConstrainedElementsForClass( clazz ); + JavaBeanConstrainedType constrainedType = new JavaBeanConstrainedType<>( clazz ); + BeanConfiguration beanConfiguration = new BeanConfiguration<>( ConfigurationSource.XML, - clazz, + constrainedType, constrainedElements, mappingParser.getDefaultSequenceForClass( clazz ), null ); - configuredBeans.put( clazz.getName(), beanConfiguration ); + configuredBeans.put( constrainedType, beanConfiguration ); } return configuredBeans; } @Override @SuppressWarnings("unchecked") - public BeanConfiguration getBeanConfiguration(Class beanClass) { - return (BeanConfiguration) configuredBeans.get( beanClass.getName() ); + public BeanConfiguration getBeanConfiguration(HibernateConstrainedType constrainedType) { + return (BeanConfiguration) configuredBeans.get( constrainedType ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/BeanConfiguration.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/BeanConfiguration.java index c126eab0db..c532980e89 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/BeanConfiguration.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/BeanConfiguration.java @@ -9,6 +9,7 @@ import java.util.List; import java.util.Set; +import org.hibernate.validator.engine.HibernateConstrainedType; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.spi.group.DefaultGroupSequenceProvider; @@ -24,7 +25,7 @@ public class BeanConfiguration { private final ConfigurationSource source; - private final Class beanClass; + private final HibernateConstrainedType constrainedType; private final Set constrainedElements; @@ -36,7 +37,7 @@ public class BeanConfiguration { * Creates a new bean configuration. * * @param source The source of this configuration. - * @param beanClass The type represented by this configuration. + * @param constrainedType The type represented by this configuration. * @param constrainedElements The constraint elements representing this type's fields, * methods etc. * @param defaultGroupSequence The default group sequence for the given type as configured by @@ -46,13 +47,13 @@ public class BeanConfiguration { */ public BeanConfiguration( ConfigurationSource source, - Class beanClass, + HibernateConstrainedType constrainedType, Set constrainedElements, List> defaultGroupSequence, DefaultGroupSequenceProvider defaultGroupSequenceProvider) { this.source = source; - this.beanClass = beanClass; + this.constrainedType = constrainedType; this.constrainedElements = CollectionHelper.newHashSet( constrainedElements ); this.defaultGroupSequence = defaultGroupSequence; this.defaultGroupSequenceProvider = defaultGroupSequenceProvider; @@ -62,8 +63,8 @@ public ConfigurationSource getSource() { return source; } - public Class getBeanClass() { - return beanClass; + public HibernateConstrainedType getConstrainedType() { + return constrainedType; } public Set getConstrainedElements() { @@ -80,7 +81,7 @@ public DefaultGroupSequenceProvider getDefaultGroupSequenceProvider() @Override public String toString() { - return "BeanConfiguration [beanClass=" + beanClass.getSimpleName() + return "BeanConfiguration [beanClass=" + constrainedType.getActuallClass().getSimpleName() + ", source=" + source + ", constrainedElements=" + constrainedElements + ", defaultGroupSequence=" + defaultGroupSequence @@ -93,7 +94,7 @@ public int hashCode() { final int prime = 31; int result = 1; result = prime * result - + ( ( beanClass == null ) ? 0 : beanClass.hashCode() ); + + ( ( constrainedType == null ) ? 0 : constrainedType.hashCode() ); result = prime * result + ( ( source == null ) ? 0 : source.hashCode() ); return result; } @@ -110,12 +111,12 @@ public boolean equals(Object obj) { return false; } BeanConfiguration other = (BeanConfiguration) obj; - if ( beanClass == null ) { - if ( other.beanClass != null ) { + if ( constrainedType == null ) { + if ( other.constrainedType != null ) { return false; } } - else if ( !beanClass.equals( other.beanClass ) ) { + else if ( !constrainedType.equals( other.constrainedType ) ) { return false; } if ( source != other.source ) { diff --git a/engine/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java b/engine/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java index e1c5ca96fc..0ad9be521c 100644 --- a/engine/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java @@ -555,7 +555,7 @@ private BeanConfiguration getBeanConfiguration(Class type) { ); for ( BeanConfiguration beanConfiguration : beanConfigurations ) { - if ( beanConfiguration.getBeanClass() == type ) { + if ( beanConfiguration.getConstrainedType().getActuallClass() == type ) { @SuppressWarnings("unchecked") BeanConfiguration configuration = (BeanConfiguration) beanConfiguration; return configuration; diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java index 09a67ac8f4..788d49b3b4 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java @@ -9,6 +9,7 @@ import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertThat; import static org.hibernate.validator.testutil.ConstraintViolationAssert.pathWith; import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; +import static org.hibernate.validator.testutils.BeanMetadataManagerUtil.getBeanMetadata; import static org.hibernate.validator.testutils.ConstraintValidatorInitializationHelper.getDummyConstraintCreationContext; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; @@ -202,7 +203,7 @@ public void testCreationOfExecutablePath() throws Exception { new MethodValidationConfiguration.Builder().build() ); - ExecutableMetaData executableMetaData = beanMetaDataManager.getBeanMetaData( Container.class ) + ExecutableMetaData executableMetaData = getBeanMetadata( beanMetaDataManager, Container.class ) .getMetaDataFor( executable ).get(); PathImpl methodParameterPath = PathImpl.createPathForExecutable( executableMetaData ); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/BeanMetaDataManagerTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/BeanMetaDataManagerTest.java index 306006d7d0..98c1e5465f 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/BeanMetaDataManagerTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/BeanMetaDataManagerTest.java @@ -6,6 +6,7 @@ */ package org.hibernate.validator.test.internal.metadata; +import static org.hibernate.validator.testutils.BeanMetadataManagerUtil.getBeanMetadata; import static org.hibernate.validator.testutils.ConstraintValidatorInitializationHelper.getDummyConstraintCreationContext; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotSame; @@ -73,9 +74,9 @@ public void testBeanMetaDataCanBeGarbageCollected() throws Exception { List memoryConsumer = new ArrayList<>(); for ( int i = 0; i < LOOP_COUNT; i++ ) { Class c = new CustomClassLoader().loadClass( Engine.class.getName() ); - BeanMetaData meta = metaDataManager.getBeanMetaData( c ); - assertNotSame( meta.getBeanClass(), lastIterationsBean, "The classes should differ in each iteration" ); - lastIterationsBean = meta.getBeanClass(); + BeanMetaData meta = getBeanMetadata( metaDataManager, c ); + assertNotSame( meta.getConstrainedType().getActuallClass(), lastIterationsBean, "The classes should differ in each iteration" ); + lastIterationsBean = meta.getConstrainedType().getActuallClass(); totalCreatedMetaDataInstances++; cachedBeanMetaDataInstances = metaDataManager.numberOfCachedBeanMetaDataInstances(); @@ -103,14 +104,14 @@ public void testBeanMetaDataCanBeGarbageCollected() throws Exception { @Test public void testGetMetaDataForConstrainedEntity() { - BeanMetaData beanMetaData = metaDataManager.getBeanMetaData( Engine.class ); + BeanMetaData beanMetaData = getBeanMetadata( metaDataManager, Engine.class ); assertTrue( beanMetaData instanceof BeanMetaDataImpl ); assertTrue( beanMetaData.hasConstraints() ); } @Test public void testGetMetaDataForUnConstrainedEntity() { - BeanMetaData beanMetaData = metaDataManager.getBeanMetaData( UnconstrainedEntity.class ); + BeanMetaData beanMetaData = getBeanMetadata( metaDataManager, UnconstrainedEntity.class ); assertTrue( beanMetaData instanceof BeanMetaDataImpl, "#getBeanMetaData should always return a valid BeanMetaData instance. Returned class: " + beanMetaData.getClass() diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ExecutableMetaDataTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ExecutableMetaDataTest.java index 172df763ed..bc5320ec79 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ExecutableMetaDataTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ExecutableMetaDataTest.java @@ -7,6 +7,7 @@ package org.hibernate.validator.test.internal.metadata.aggregated; import static org.assertj.core.api.Assertions.assertThat; +import static org.hibernate.validator.testutils.BeanMetadataManagerUtil.getBeanMetadata; import static org.hibernate.validator.testutils.ConstraintValidatorInitializationHelper.getDummyConstraintCreationContext; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; @@ -67,7 +68,7 @@ public void setupBeanMetaData() { new MethodValidationConfiguration.Builder().build() ); - beanMetaData = beanMetaDataManager.getBeanMetaData( CustomerRepositoryExt.class ); + beanMetaData = getBeanMetadata( beanMetaDataManager, CustomerRepositoryExt.class ); } @Test @@ -173,7 +174,7 @@ public void getIdentifierForConstructor() throws Exception { @TestForIssue(jiraKey = "HV-1011") public void getIdentifierForOverridingGenericMethod() throws Exception { Method method = JobRepositoryImpl.class.getMethod( "createJob", UUID.class ); - BeanMetaData beanMetaData = beanMetaDataManager.getBeanMetaData( JobRepositoryImpl.class ); + BeanMetaData beanMetaData = getBeanMetadata( beanMetaDataManager, JobRepositoryImpl.class ); ExecutableMetaData methodMetaData = beanMetaData.getMetaDataFor( method ).get(); assertThat( methodMetaData.getSignatures() ) @@ -181,7 +182,7 @@ public void getIdentifierForOverridingGenericMethod() throws Exception { .containsOnly( "createJob(java.lang.Object)", "createJob(java.util.UUID)" ); method = JobRepository.class.getMethod( "createJob", Object.class ); - beanMetaData = beanMetaDataManager.getBeanMetaData( JobRepository.class ); + beanMetaData = getBeanMetadata( beanMetaDataManager, JobRepository.class ); methodMetaData = beanMetaData.getMetaDataFor( method ).get(); assertThat( methodMetaData.getSignatures() ) @@ -189,7 +190,7 @@ public void getIdentifierForOverridingGenericMethod() throws Exception { .containsOnly( "createJob(java.lang.Object)" ); method = SpecialJobRepositoryImpl.class.getMethod( "createJob", Object.class ); - beanMetaData = beanMetaDataManager.getBeanMetaData( SpecialJobRepositoryImpl.class ); + beanMetaData = getBeanMetadata( beanMetaDataManager, SpecialJobRepositoryImpl.class ); methodMetaData = beanMetaData.getMetaDataFor( method ).get(); assertThat( methodMetaData.getSignatures() ) @@ -201,7 +202,7 @@ public void getIdentifierForOverridingGenericMethod() throws Exception { @TestForIssue(jiraKey = "HV-1011") public void getIdentifierForOverloadedMethod() throws Exception { Method method = SpecialJobRepositoryImpl.class.getMethod( "createJob", String.class ); - BeanMetaData beanMetaData = beanMetaDataManager.getBeanMetaData( SpecialJobRepositoryImpl.class ); + BeanMetaData beanMetaData = getBeanMetadata( beanMetaDataManager, SpecialJobRepositoryImpl.class ); ExecutableMetaData methodMetaData = beanMetaData.getMetaDataFor( method ).get(); assertThat( methodMetaData.getSignatures() ) diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ParameterMetaDataTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ParameterMetaDataTest.java index 189b3a75d0..7d120366bd 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ParameterMetaDataTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ParameterMetaDataTest.java @@ -7,6 +7,7 @@ package org.hibernate.validator.test.internal.metadata.aggregated; import static org.assertj.core.api.Assertions.assertThat; +import static org.hibernate.validator.testutils.BeanMetadataManagerUtil.getBeanMetadata; import static org.hibernate.validator.testutils.ConstraintValidatorInitializationHelper.getDummyConstraintCreationContext; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; @@ -67,7 +68,7 @@ public void setupBeanMetaData() { new MethodValidationConfiguration.Builder().build() ); - beanMetaData = beanMetaDataManager.getBeanMetaData( CustomerRepository.class ); + beanMetaData = getBeanMetadata( beanMetaDataManager, CustomerRepository.class ); } @Test @@ -135,7 +136,7 @@ public void parameterNameInInheritanceHierarchy() throws Exception { Collections.emptyList(), new MethodValidationConfiguration.Builder().build() ); - BeanMetaData localBeanMetaData = beanMetaDataManager.getBeanMetaData( ServiceImpl.class ); + BeanMetaData localBeanMetaData = getBeanMetadata( beanMetaDataManager, ServiceImpl.class ); Method method = Service.class.getMethod( "sayHello", String.class ); ExecutableMetaData methodMetaData = localBeanMetaData.getMetaDataFor( method ).get(); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/PropertyMetaDataTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/PropertyMetaDataTest.java index e7a723fd00..8eee16877e 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/PropertyMetaDataTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/PropertyMetaDataTest.java @@ -7,6 +7,7 @@ package org.hibernate.validator.test.internal.metadata.aggregated; import static org.assertj.core.api.Assertions.assertThat; +import static org.hibernate.validator.testutils.BeanMetadataManagerUtil.getBeanMetadata; import static org.hibernate.validator.testutils.ConstraintValidatorInitializationHelper.getDummyConstraintCreationContext; import java.util.Collections; @@ -54,21 +55,21 @@ public void setupBeanMetaDataManager() { @Test public void locallyDefinedGroupConversion() { - PropertyMetaData property = beanMetaDataManager.getBeanMetaData( User1.class ).getMetaDataFor( "addresses" ); + PropertyMetaData property = getBeanMetadata( beanMetaDataManager, User1.class ).getMetaDataFor( "addresses" ); assertThat( property.getCascadables().iterator().next().getCascadingMetaData().convertGroup( Default.class ) ).isEqualTo( BasicPostal.class ); } @Test public void groupConversionDefinedInHierarchy() { - PropertyMetaData property = beanMetaDataManager.getBeanMetaData( User2.class ).getMetaDataFor( "addresses" ); + PropertyMetaData property = getBeanMetadata( beanMetaDataManager, User2.class ).getMetaDataFor( "addresses" ); assertThat( property.getCascadables().iterator().next().getCascadingMetaData().convertGroup( Default.class ) ).isEqualTo( BasicPostal.class ); } @Test(expectedExceptions = ConstraintDeclarationException.class, expectedExceptionsMessageRegExp = "HV000124.*") public void groupConversionInHierarchyWithSameFrom() { - beanMetaDataManager.getBeanMetaData( User3.class ).getMetaDataFor( "addresses" ); + getBeanMetadata( beanMetaDataManager, User3.class ).getMetaDataFor( "addresses" ); } public interface Complete extends Default { diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTest.java index 21ab1a450c..f639bbf275 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTest.java @@ -29,6 +29,7 @@ import javax.validation.metadata.ConstraintDescriptor; import org.hibernate.validator.constraints.ScriptAssert; +import org.hibernate.validator.internal.engine.constrainedtype.JavaBeanConstrainedType; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; @@ -65,7 +66,7 @@ public void setUpProvider() { @Test public void testGetConstructorMetaData() throws Exception { - BeanConfiguration beanConfiguration = provider.getBeanConfiguration( Foo.class ); + BeanConfiguration beanConfiguration = provider.getBeanConfiguration( new JavaBeanConstrainedType<>( Foo.class ) ); ConstrainedExecutable constructor = findConstrainedConstructor( beanConfiguration, Foo.class, String.class ); @@ -82,7 +83,7 @@ public void testGetConstructorMetaData() throws Exception { @Test public void testGetCrossParameterMetaData() throws Exception { //when - BeanConfiguration beanConfiguration = provider.getBeanConfiguration( Calendar.class ); + BeanConfiguration beanConfiguration = provider.getBeanConfiguration( new JavaBeanConstrainedType<>( Calendar.class ) ); ConstrainedExecutable createEvent = findConstrainedMethod( beanConfiguration, @@ -117,14 +118,14 @@ public void testGetCrossParameterMetaData() throws Exception { @Test public void configurationsHaveAnnotationSource() { - BeanConfiguration beanConfiguration = provider.getBeanConfiguration( User.class ); + BeanConfiguration beanConfiguration = provider.getBeanConfiguration( new JavaBeanConstrainedType<>( User.class ) ); assertThat( beanConfiguration.getSource() ).isEqualTo( ConfigurationSource.ANNOTATION ); } @Test public void noGroupConversionOnField() throws Exception { //when - BeanConfiguration beanConfiguration = provider.getBeanConfiguration( User.class ); + BeanConfiguration beanConfiguration = provider.getBeanConfiguration( new JavaBeanConstrainedType<>( User.class ) ); ConstrainedField field = findConstrainedField( beanConfiguration, User.class, "mail" ); //then @@ -134,7 +135,7 @@ public void noGroupConversionOnField() throws Exception { @Test public void singleGroupConversionOnField() throws Exception { //when - BeanConfiguration beanConfiguration = provider.getBeanConfiguration( User.class ); + BeanConfiguration beanConfiguration = provider.getBeanConfiguration( new JavaBeanConstrainedType<>( User.class ) ); ConstrainedField field = findConstrainedField( beanConfiguration, User.class, "phone" ); //then @@ -147,7 +148,7 @@ public void singleGroupConversionOnField() throws Exception { @Test public void multipleGroupConversionsOnField() throws Exception { //when - BeanConfiguration beanConfiguration = provider.getBeanConfiguration( User.class ); + BeanConfiguration beanConfiguration = provider.getBeanConfiguration( new JavaBeanConstrainedType<>( User.class ) ); ConstrainedField field = findConstrainedField( beanConfiguration, User.class, "address" ); //then @@ -160,13 +161,13 @@ public void multipleGroupConversionsOnField() throws Exception { @Test(expectedExceptions = ConstraintDeclarationException.class, expectedExceptionsMessageRegExp = "HV000124.*") public void multipleGroupConversionsOnFieldWithSameFromCauseException() { - provider.getBeanConfiguration( User2.class ); + provider.getBeanConfiguration( new JavaBeanConstrainedType<>( User2.class ) ); } @Test public void noGroupConversionOnMethod() throws Exception { //when - BeanConfiguration beanConfiguration = provider.getBeanConfiguration( User.class ); + BeanConfiguration beanConfiguration = provider.getBeanConfiguration( new JavaBeanConstrainedType<>( User.class ) ); ConstrainedExecutable method = findConstrainedMethod( beanConfiguration, User.class, "getMail1" ); //then @@ -176,7 +177,7 @@ public void noGroupConversionOnMethod() throws Exception { @Test public void singleGroupConversionOnMethod() throws Exception { //when - BeanConfiguration beanConfiguration = provider.getBeanConfiguration( User.class ); + BeanConfiguration beanConfiguration = provider.getBeanConfiguration( new JavaBeanConstrainedType<>( User.class ) ); ConstrainedExecutable method = findConstrainedMethod( beanConfiguration, User.class, "getPhone1" ); //then @@ -189,7 +190,7 @@ public void singleGroupConversionOnMethod() throws Exception { @Test public void multipleGroupConversionsOnMethod() throws Exception { //when - BeanConfiguration beanConfiguration = provider.getBeanConfiguration( User.class ); + BeanConfiguration beanConfiguration = provider.getBeanConfiguration( new JavaBeanConstrainedType<>( User.class ) ); ConstrainedExecutable method = findConstrainedMethod( beanConfiguration, User.class, "getAddress1" ); //then @@ -203,7 +204,7 @@ public void multipleGroupConversionsOnMethod() throws Exception { @Test public void noGroupConversionOnParameter() throws Exception { //when - BeanConfiguration beanConfiguration = provider.getBeanConfiguration( User.class ); + BeanConfiguration beanConfiguration = provider.getBeanConfiguration( new JavaBeanConstrainedType<>( User.class ) ); ConstrainedExecutable method = findConstrainedMethod( beanConfiguration, User.class, @@ -218,7 +219,7 @@ public void noGroupConversionOnParameter() throws Exception { @Test public void singleGroupConversionOnParameter() throws Exception { //when - BeanConfiguration beanConfiguration = provider.getBeanConfiguration( User.class ); + BeanConfiguration beanConfiguration = provider.getBeanConfiguration( new JavaBeanConstrainedType<>( User.class ) ); ConstrainedExecutable method = findConstrainedMethod( beanConfiguration, User.class, @@ -236,7 +237,7 @@ public void singleGroupConversionOnParameter() throws Exception { @Test public void multipleGroupConversionsOnParameter() throws Exception { //when - BeanConfiguration beanConfiguration = provider.getBeanConfiguration( User.class ); + BeanConfiguration beanConfiguration = provider.getBeanConfiguration( new JavaBeanConstrainedType<>( User.class ) ); ConstrainedExecutable method = findConstrainedMethod( beanConfiguration, User.class, @@ -254,13 +255,13 @@ public void multipleGroupConversionsOnParameter() throws Exception { @Test(expectedExceptions = ConstraintDeclarationException.class, expectedExceptionsMessageRegExp = "HV000124.*") public void multipleGroupConversionsOnParameterWithSameFromCauseException() { - provider.getBeanConfiguration( User4.class ); + provider.getBeanConfiguration( new JavaBeanConstrainedType<>( User4.class ) ); } @Test public void singleGroupConversionOnConstructor() throws Exception { //when - BeanConfiguration beanConfiguration = provider.getBeanConfiguration( User.class ); + BeanConfiguration beanConfiguration = provider.getBeanConfiguration( new JavaBeanConstrainedType<>( User.class ) ); ConstrainedExecutable constructor = findConstrainedConstructor( beanConfiguration, User.class ); //then @@ -273,7 +274,7 @@ public void singleGroupConversionOnConstructor() throws Exception { @Test public void multipleGroupConversionsOnConstructorParameter() throws Exception { //when - BeanConfiguration beanConfiguration = provider.getBeanConfiguration( User.class ); + BeanConfiguration beanConfiguration = provider.getBeanConfiguration( new JavaBeanConstrainedType<>( User.class ) ); ConstrainedExecutable constructor = findConstrainedConstructor( beanConfiguration, User.class, Address.class ); //then @@ -287,7 +288,7 @@ public void multipleGroupConversionsOnConstructorParameter() throws Exception { @Test @TestForIssue(jiraKey = "HV-626") public void onlyLocallyDefinedConstraintsAreConsidered() { - BeanConfiguration beanConfiguration = provider.getBeanConfiguration( Person.class ); + BeanConfiguration beanConfiguration = provider.getBeanConfiguration( new JavaBeanConstrainedType<>( ( Person.class ) ) ); ConstrainedType personType = findConstrainedType( beanConfiguration, Person.class ); assertThat( personType.getConstraints() ).hasSize( 1 ); @@ -300,7 +301,7 @@ public void onlyLocallyDefinedConstraintsAreConsidered() { @Test(expectedExceptions = ConstraintDeclarationException.class, expectedExceptionsMessageRegExp = "HV000124.*") public void groupConversionWithSameFromInSingleAndListAnnotationCauseException() { - provider.getBeanConfiguration( User3.class ); + provider.getBeanConfiguration( new JavaBeanConstrainedType<>( User3.class ) ); } private static class Foo { diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/TypeAnnotationMetaDataRetrievalTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/TypeAnnotationMetaDataRetrievalTest.java index ee70424dab..87cdceb249 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/TypeAnnotationMetaDataRetrievalTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/TypeAnnotationMetaDataRetrievalTest.java @@ -19,6 +19,7 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; +import org.hibernate.validator.internal.engine.constrainedtype.JavaBeanConstrainedType; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider; @@ -51,7 +52,7 @@ public void setup() { @Test public void testFieldTypeArgument() throws Exception { - BeanConfiguration beanConfiguration = provider.getBeanConfiguration( A.class ); + BeanConfiguration beanConfiguration = provider.getBeanConfiguration( new JavaBeanConstrainedType<>( A.class ) ); ConstrainedField field = findConstrainedField( beanConfiguration, A.class, "names" ); assertThat( field.getTypeArgumentConstraints().size() ).isEqualTo( 2 ); @@ -62,7 +63,7 @@ public void testFieldTypeArgument() throws Exception { @Test public void testGetterTypeArgument() throws Exception { - BeanConfiguration beanConfiguration = provider.getBeanConfiguration( B.class ); + BeanConfiguration beanConfiguration = provider.getBeanConfiguration( new JavaBeanConstrainedType<>( B.class ) ); ConstrainedExecutable executable = findConstrainedMethod( beanConfiguration, B.class, "getNames" ); assertThat( executable.getTypeArgumentConstraints().size() ).isEqualTo( 2 ); @@ -73,7 +74,7 @@ public void testGetterTypeArgument() throws Exception { @Test public void testReturnValueTypeArgument() throws Exception { - BeanConfiguration beanConfiguration = provider.getBeanConfiguration( C.class ); + BeanConfiguration beanConfiguration = provider.getBeanConfiguration( new JavaBeanConstrainedType<>( C.class ) ); ConstrainedExecutable executable = findConstrainedMethod( beanConfiguration, C.class, "returnNames" ); assertThat( executable.getTypeArgumentConstraints().size() ).isEqualTo( 2 ); @@ -84,7 +85,7 @@ public void testReturnValueTypeArgument() throws Exception { @Test public void testExecutableParameterTypeArgument() throws Exception { - BeanConfiguration beanConfiguration = provider.getBeanConfiguration( D.class ); + BeanConfiguration beanConfiguration = provider.getBeanConfiguration( new JavaBeanConstrainedType<>( D.class ) ); ConstrainedExecutable executable = findConstrainedMethod( beanConfiguration, @@ -103,7 +104,7 @@ public void testExecutableParameterTypeArgument() throws Exception { @Test public void testConstructorParameterTypeArgument() throws Exception { - BeanConfiguration beanConfiguration = provider.getBeanConfiguration( E.class ); + BeanConfiguration beanConfiguration = provider.getBeanConfiguration( new JavaBeanConstrainedType<>( E.class ) ); ConstrainedExecutable executable = findConstrainedConstructor( beanConfiguration, @@ -122,8 +123,8 @@ public void testConstructorParameterTypeArgument() throws Exception { private List> getAnnotationsTypes(Collection> metaConstraints) { return metaConstraints.stream() - .map( m -> m.getDescriptor().getAnnotationType() ) - .collect( Collectors.toList() ); + .map( m -> m.getDescriptor().getAnnotationType() ) + .collect( Collectors.toList() ); } static class A { diff --git a/engine/src/test/java/org/hibernate/validator/testutils/BeanMetadataManagerUtil.java b/engine/src/test/java/org/hibernate/validator/testutils/BeanMetadataManagerUtil.java new file mode 100644 index 0000000000..2999a249aa --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/testutils/BeanMetadataManagerUtil.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.testutils; + +import org.hibernate.validator.internal.engine.constrainedtype.JavaBeanConstrainedType; +import org.hibernate.validator.internal.metadata.BeanMetaDataManager; +import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; + +/** + * A helper providing useful functions for simplifying metadata retrival in tests. + * + * @author Marko Bekhta + */ +public final class BeanMetadataManagerUtil { + + private BeanMetadataManagerUtil() { + } + + /** + * @return a {@link BeanMetaData} for a given {@code clazz} created by {@code manager}. + */ + public static BeanMetaData getBeanMetadata(BeanMetaDataManager manager, Class clazz) { + return manager.getBeanMetaData( new JavaBeanConstrainedType<>( clazz ) ); + } +}