diff --git a/hibernate-validator/src/main/docbook/en-US/modules/customoptions.xml b/hibernate-validator/src/main/docbook/en-US/modules/customoptions.xml index 91b0d70b50..5747fc875f 100644 --- a/hibernate-validator/src/main/docbook/en-US/modules/customoptions.xml +++ b/hibernate-validator/src/main/docbook/en-US/modules/customoptions.xml @@ -95,19 +95,18 @@ validator = factory.unwrap( HibernateValidatorFactory.class ) Programmatic constraint definition Another addition to the Bean Validation specification is the ability - to configure constraints via a fluent API.This API can be used exclusively - or in combination with annotations and xml. If used in combination - programmatic constraints are additive to constraints configured via the - standard configuration capabilties. + to configure constraints via a fluent API. This API can be used + exclusively or in combination with annotations and xml. If used in + combination programmatic constraints are additive to constraints + configured via the standard configuration capabilities. - The programmatic API is centered around the + The API is centered around the ConstraintMapping class which can be found together with its supporting classes in the - org.hibernate.validator.cfg package. - ConstraintMapping is the entry point to a fluent - API allowing the definition of constraints. shows how the API can be - used. + org.hibernate.validator.cfg package. Starting with the + instantiation of a new ConstraintMapping, + constraints can be defined in a fluent manner as shown in . Programmatic constraint definition @@ -115,73 +114,134 @@ validator = factory.unwrap( HibernateValidatorFactory.class ) ConstraintMapping mapping = new ConstraintMapping(); mapping.type( Car.class ) .property( "manufacturer", FIELD ) - .constraint( NotNullDef.class ) + .constraint( + create( NotNullDef.class ) ) .property( "licensePlate", FIELD ) - .constraint( NotNullDef.class ) - .constraint( SizeDef.class ) - .min( 2 ) - .max( 14 ) + .constraint( + create( NotNullDef.class ) ) + .constraint( + create( SizeDef.class ) + .min( 2 ) + .max( 14 ) ) .property( "seatCount", FIELD ) - .constraint( MinDef.class ) - .value ( 2 ) + .constraint( + create( MinDef.class ) + .value ( 2 ) ) .type( RentalCar.class ) - .property( "rentalStation", METHOD) - .constraint( NotNullDef.class ); + .property( "rentalStation", METHOD ) + .constraint( + create( NotNullDef.class ) ); - As you can see you can configure constraints on multiple classes and + As you can see constraints can be configured on multiple classes and properties using method chaining. The constraint definition classes NotNullDef, SizeDef and MinDef are helper classes which allow to configure - constraint parameters in a type-safe fashion. Definition classes exists - for all built-in constraints in the - org.hibernate.validator.cfg.defs package. For a - custom constraint you can either create your own definition class - extending ConstraintDef or you can use the - genericConstraint method as seen in org.hibernate.validator.cfg.defs package. + + + The create() method (as well as + createGeneric() introduced in the following) is + a static method defined on + org.hibernate.validator.cfg.ConstraintDef. It is + recommended to import this method statically which allows to use it as + shown in . + + + For custom constraints you can either create your own definition + classes extending ConstraintDef or you can use the + createGeneric() method as seen in . Programmatic constraint definition using - <classname>GenericConstraintDef</classname> + createGeneric() ConstraintMapping mapping = new ConstraintMapping(); mapping.type( Car.class ) .property( "licensePlate", FIELD ) - .genericConstraint( CheckCase.class ) - .param( "value", CaseMode.UPPER ); + .constraint( + createGeneric( CheckCase.class ) + .param( "value", CaseMode.UPPER ) ); - Last but not least, you can also define cascading constraints as - well as the default group sequence or the default group sequence provider - of an entity. + Not only standard class- and property-level constraints but also + method constraints can be configured using the API. As shown in methods are + identified by their name and their parameters (if there are any). Having + selected a method, constraints can be placed on the method's parameters + and/or return value. + + + Programmatic definition of method constraints + + ConstraintMapping mapping = new ConstraintMapping(); +mapping.type( Car.class ) + .method( "drive", String.class, Integer.class ) + .parameter( 0 ) + .constraint( + create( NotNullDef.class ) ) + .constraint( + create( MinDef.class ) + .value ( 1 ) ) + .parameter( 1 ) + .constraint( + create( NotNullDef.class ) ) + .returnValue() + .constraint( + create( NotNullDef.class ) ) + .method( "check" ) + .returnValue() + .constraint( + create( NotNullDef.class ) ); + + + Using the API it's also possible to mark properties, method + parameters and method return values as cascading (equivalent to annotating + them with @Valid). An example can be found in . - - Cascading constraints and default group redefinition + + Marking constraints for cascaded validation ConstraintMapping mapping = new ConstraintMapping(); mapping.type( Car.class ) - .valid( "driver", FIELD ) -.type( RentalCar.class) - .defaultGroupSequence( RentalCar.class, CarChecks.class ); + .property( "manufacturer", FIELD ) + .valid() + .property( "licensePlate", METHOD ) + .valid() + .method( "drive", String.class, Integer.class ) + .parameter( 0 ) + .valid() + .parameter( 1 ) + .valid() + .returnValue() + .valid() +.type( RentalCar.class ) + .property( "rentalStation", METHOD ) + .valid(); - - Cascading constraints and dynamic default group - redefinition + Last but not least you can configure the default group sequence or + the default group sequence provider of a type as shown in . + Configuration of default group sequence and default group + sequence provider ConstraintMapping mapping = new ConstraintMapping(); mapping.type( Car.class ) - .valid( "driver", FIELD ) -.type( RentalCar.class) + .defaultGroupSequence( Car.class, CarChecks.class ) +.type( RentalCar.class ) .defaultGroupSequenceProvider( RentalCarGroupSequenceProvider.class ); - Once you have your ConstraintMapping you will - have to pass it to the configuration. Since the programmatic configuration - is not part of the official Bean Validation specification you will have to - get hold of the Hibernate Validator specific configuration instance. See - . + Once a ConstraintMapping is set up it has to + be passed to the configuration. Since the programmatic API is not part of + the official Bean Validation specification you need to get hold of a + HibernateValidatorConfiguration instance as shown + in . Creating a Hibernate Validator specific configuration diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/CascadeDef.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/CascadeDef.java deleted file mode 100644 index b63f916600..0000000000 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/CascadeDef.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * JBoss, Home of Professional Open Source - * Copyright 2010, Red Hat, Inc. and/or its affiliates, and individual contributors - * by the @authors tag. See the copyright.txt in the distribution for a - * full listing of individual contributors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.hibernate.validator.cfg; - -import java.lang.annotation.ElementType; -import javax.validation.ValidationException; - -import org.hibernate.validator.util.ReflectionHelper; - -/** - * @author Hardy Ferentschik - */ -public class CascadeDef { - private final Class beanType; - private final ElementType elementType; - private final String property; - - public CascadeDef(Class beanType, String property, ElementType elementType) { - if ( beanType == null ) { - throw new ValidationException( "Null is not a valid bean type" ); - } - - if ( ElementType.FIELD.equals( elementType ) || ElementType.METHOD.equals( elementType ) ) { - if ( property == null || property.length() == 0 ) { - throw new ValidationException( "A valid property name has to be specified" ); - } - - if ( !ReflectionHelper.propertyExists( beanType, property, elementType ) ) { - throw new ValidationException( - "The class " + beanType + " does not have a property '" - + property + "' with access " + elementType - ); - } - } - - this.beanType = beanType; - this.property = property; - this.elementType = elementType; - } - - public ElementType getElementType() { - return elementType; - } - - public Class getBeanType() { - return beanType; - } - - public String getProperty() { - return property; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "CascadeDefinition" ); - sb.append( "{beanType=" ).append( beanType ); - sb.append( ", elementType=" ).append( elementType ); - sb.append( ", property='" ).append( property ).append( '\'' ); - sb.append( '}' ); - return sb.toString(); - } -} diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/ConstraintDef.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/ConstraintDef.java index df259c175c..fc1b81ad36 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/ConstraintDef.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/ConstraintDef.java @@ -17,15 +17,13 @@ package org.hibernate.validator.cfg; import java.lang.annotation.Annotation; -import java.lang.annotation.ElementType; -import java.lang.reflect.Constructor; -import java.util.HashMap; import java.util.Map; import javax.validation.Payload; -import javax.validation.ValidationException; import org.hibernate.validator.util.ReflectionHelper; +import static org.hibernate.validator.util.CollectionHelper.newHashMap; + /** * Base class for all constraint definition types. Each sub type represents a * single constraint annotation type and allows to add this constraint to a bean @@ -42,11 +40,9 @@ */ public abstract class ConstraintDef, A extends Annotation> { - // Note on visibility of members: In order to avoid the need for public - // getter methods for the fields of this class (which would pollute it's - // fluent API) they are protected instead of private. To get access to - // these fields outside of this class a ConstraintDefAccessor instance can - // be created from it, which offers public getter methods. + // Note on visibility of members: These members are intentionally made + // protected and published by a sub-class for internal use. There aren't + // public getters as they would pollute the fluent definition API. /** * The constraint annotation type of this definition. @@ -60,58 +56,41 @@ public abstract class ConstraintDef, A extends Ann */ protected final Map parameters; - /** - * The bean type of this definition. - */ - protected final Class beanType; + protected ConstraintDef(Class constraintType) { + this.constraintType = constraintType; + this.parameters = newHashMap(); + } - /** - * The element type of this definition. - */ - protected final ElementType elementType; + protected ConstraintDef(ConstraintDef original) { + this.constraintType = original.constraintType; + this.parameters = original.parameters; + } /** - * The property name of this definition, if it represents a property level constraint. + * Creates a new constraint definition. + * + * @param The type of the definition to be instantiated. + * @param clazz The class representing the definition to be instantiated. + * + * @return A new instance of the given constraint definition type. */ - protected final String property; + public static > C create(Class clazz) { + return ReflectionHelper.newInstance( clazz, "constraint definition" ); + } /** - * The constraint mapping owning this constraint definition. + * Creates a new generic constraint definition. + * + * @param The constraint annotation type of the generic definition to be + * created. + * @param clazz The class representing the annotation type of the definition + * to be instantiated. + * + * @return A new generic constraint definition for the given constraint + * annotation type. */ - protected final ConstraintMapping mapping; - - public ConstraintDef(Class beanType, Class constraintType, String property, ElementType elementType, ConstraintMapping mapping) { - this( beanType, constraintType, property, elementType, new HashMap(), mapping ); - } - - protected ConstraintDef(Class beanType, Class constraintType, String property, ElementType elementType, Map parameters, ConstraintMapping mapping) { - if ( beanType == null ) { - throw new ValidationException( "Null is not a valid bean type" ); - } - - if ( mapping == null ) { - throw new ValidationException( "ConstraintMapping cannot be null" ); - } - - if ( ElementType.FIELD.equals( elementType ) || ElementType.METHOD.equals( elementType ) ) { - if ( property == null || property.length() == 0 ) { - throw new ValidationException( "A property level constraint cannot have a null or empty property name" ); - } - - if ( !ReflectionHelper.propertyExists( beanType, property, elementType ) ) { - throw new ValidationException( - "The class " + beanType + " does not have a property '" - + property + "' with access " + elementType - ); - } - } - - this.beanType = beanType; - this.constraintType = constraintType; - this.parameters = parameters; - this.property = property; - this.elementType = elementType; - this.mapping = mapping; + public static GenericConstraintDef createGeneric(Class clazz) { + return new GenericConstraintDef( clazz ); } @SuppressWarnings("unchecked") @@ -139,53 +118,13 @@ public C payload(Class... payload) { return getThis(); } - public > D constraint(Class definition) { - final Constructor constructor = ReflectionHelper.getConstructor( - definition, Class.class, String.class, ElementType.class, ConstraintMapping.class - ); - - final D constraintDefinition = ReflectionHelper.newConstructorInstance( - constructor, beanType, property, elementType, mapping - ); - - mapping.addConstraintConfig( constraintDefinition ); - return constraintDefinition; - } - - public GenericConstraintDef genericConstraint(Class definition) { - - GenericConstraintDef constraintDefinition = new GenericConstraintDef( - beanType, definition, property, elementType, mapping - ); - - mapping.addConstraintConfig( constraintDefinition ); - return constraintDefinition; - } - - public ConstraintsForType property(String property, ElementType type) { - return new ConstraintsForType( beanType, property, type, mapping ); - } - - public ConstraintsForType type(Class type) { - return new ConstraintsForType( type, mapping ); - } - - public ConstraintsForType valid(String property, ElementType type) { - mapping.addCascadeConfig( new CascadeDef( beanType, property, type ) ); - return new ConstraintsForType( beanType, mapping ); - } - @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append( this.getClass().getName() ); - sb.append( "{beanType=" ).append( beanType ); sb.append( ", constraintType=" ).append( constraintType ); sb.append( ", parameters=" ).append( parameters ); - sb.append( ", elementType=" ).append( elementType ); - sb.append( ", property='" ).append( property ).append( '\'' ); sb.append( '}' ); return sb.toString(); } - } diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/ConstraintDefAccessor.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/ConstraintDefAccessor.java deleted file mode 100644 index e522b25ab2..0000000000 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/ConstraintDefAccessor.java +++ /dev/null @@ -1,93 +0,0 @@ -/* -* JBoss, Home of Professional Open Source -* Copyright 2010, Red Hat, Inc. and/or its affiliates, and individual contributors -* by the @authors tag. See the copyright.txt in the distribution for a -* full listing of individual contributors. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -package org.hibernate.validator.cfg; - -import java.lang.annotation.Annotation; -import java.lang.annotation.ElementType; -import java.util.Map; - -/** - * Provides public access to the fields of {@link ConstraintDef}. - * ConstraintDef's fields are intentionally made protected instead of private in - * order to avoid the need for getter methods, which would pollute - * ConstraintDef's fluent API. - * - * @author Hardy Ferentschik - * @author Gunnar Morling - */ -public final class ConstraintDefAccessor extends ConstraintDef, A> { - - /** - * @param - * The constraint annotation type of the accessor to create. - * - * Creates a new accessor for the given constraint definition. - * - * @param originalDef - * The constraint definition to provide access to. - */ - public static ConstraintDefAccessor getInstance(ConstraintDef originalDef) { - return new ConstraintDefAccessor( originalDef ); - } - - private ConstraintDefAccessor(ConstraintDef originalDef) { - super( - originalDef.beanType, - originalDef.constraintType, - originalDef.property, - originalDef.elementType, - originalDef.parameters, - originalDef.mapping - ); - } - - /** - * @return The constraint annotation type of this definition. - */ - public Class getConstraintType() { - return constraintType; - } - - /** - * @return A map with the annotation parameters of this definition. Keys are property names of - * this definition's annotation type, values are annotation parameter values of the appropriate types. - */ - public Map getParameters() { - return parameters; - } - - /** - * @return The bean type of this definition. - */ - public Class getBeanType() { - return beanType; - } - - /** - * @return The element type of this definition. - */ - public ElementType getElementType() { - return elementType; - } - - /** - * @return The property name of this definition, if it represents a property level constraint. - */ - public String getProperty() { - return property; - } -} diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/ConstraintMapping.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/ConstraintMapping.java index f3b49d439e..175c7f1798 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/ConstraintMapping.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/ConstraintMapping.java @@ -16,16 +16,10 @@ */ package org.hibernate.validator.cfg; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.hibernate.validator.group.DefaultGroupSequenceProvider; +import org.hibernate.validator.cfg.context.TypeConstraintMappingContext; +import org.hibernate.validator.cfg.context.impl.ConstraintMappingContext; +import org.hibernate.validator.cfg.context.impl.TypeConstraintMappingContextImpl; +import org.hibernate.validator.util.Contracts; /** * Top level class for constraints configured via the programmatic API. @@ -35,133 +29,31 @@ * @author Kevin Pollet - SERLI - (kevin.pollet@serli.om) */ public class ConstraintMapping { - private final Map, List>> constraintConfig; - private final Map, List> cascadeConfig; - private final Set> configuredClasses; - private final Map, List>> defaultGroupSequences; - private final Map, Class>> defaultGroupSequenceProviders; + + protected ConstraintMappingContext context; public ConstraintMapping() { - this.constraintConfig = new HashMap, List>>(); - this.cascadeConfig = new HashMap, List>(); - this.configuredClasses = new HashSet>(); - this.defaultGroupSequences = new HashMap, List>>(); - this.defaultGroupSequenceProviders = new HashMap, Class>>(); + context = new ConstraintMappingContext(); + } + + protected ConstraintMapping(ConstraintMapping original) { + this.context = original.context; } /** * Starts defining constraints on the specified bean class. * + * @param The type to be configured. * @param beanClass The bean class on which to define constraints. All constraints defined after calling this method * are added to the bean of the type {@code beanClass} until the next call of {@code type}. * * @return Instance allowing for defining constraints on the specified class. */ - public final ConstraintsForType type(Class beanClass) { - return new ConstraintsForType( beanClass, this ); - } - - /** - * Returns all constraint definitions registered with this mapping. - * - * @return A map with this mapping's constraint definitions. Each key in - * this map represents a bean type, for which the constraint - * definitions in the associated map value are configured. - */ - public final Map, List>> getConstraintConfig() { - - Map, List>> newDefinitions = new HashMap, List>>(); - - for ( Map.Entry, List>> entry : constraintConfig.entrySet() ) { - - List> newList = new ArrayList>(); - - for ( ConstraintDef definition : entry.getValue() ) { - newList.add( ConstraintDefAccessor.getInstance( definition ) ); - } - - newDefinitions.put( entry.getKey(), newList ); - } - - return newDefinitions; - } - - public final Map, List> getCascadeConfig() { - return cascadeConfig; - } - - public final Collection> getConfiguredClasses() { - return configuredClasses; - } - - public final List> getDefaultSequence(Class beanType) { - if ( defaultGroupSequences.containsKey( beanType ) ) { - return defaultGroupSequences.get( beanType ); - } - else { - return Collections.emptyList(); - } - } - - /** - * Returns the class of the default group sequence provider defined - * for the given bean type. - * - * @param beanType The bean type. - * - * @return The default group sequence provider defined class or {@code null} if none. - */ - public final Class> getDefaultGroupSequenceProvider(Class beanType) { - return defaultGroupSequenceProviders.get( beanType ); - } + public final TypeConstraintMappingContext type(Class beanClass) { - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "ConstraintMapping" ); - sb.append( "{cascadeConfig=" ).append( cascadeConfig ); - sb.append( ", constraintConfig=" ).append( constraintConfig ); - sb.append( ", configuredClasses=" ).append( configuredClasses ); - sb.append( ", defaultGroupSequences=" ).append( defaultGroupSequences ); - sb.append( '}' ); - return sb.toString(); - } + Contracts.assertNotNull( beanClass, "The bean type must not be null when creating a constraint mapping." ); - protected final void addCascadeConfig(CascadeDef cascade) { - Class beanClass = cascade.getBeanType(); - configuredClasses.add( beanClass ); - if ( cascadeConfig.containsKey( beanClass ) ) { - cascadeConfig.get( beanClass ).add( cascade ); - } - else { - List cascadeList = new ArrayList(); - cascadeList.add( cascade ); - cascadeConfig.put( beanClass, cascadeList ); - } + return new TypeConstraintMappingContextImpl( beanClass, context ); } - protected final void addDefaultGroupSequence(Class beanClass, List> defaultGroupSequence) { - configuredClasses.add( beanClass ); - defaultGroupSequences.put( beanClass, defaultGroupSequence ); - } - - protected final > void addDefaultGroupSequenceProvider(Class beanClass, Class defaultGroupSequenceProviderClass) { - configuredClasses.add( beanClass ); - defaultGroupSequenceProviders.put( beanClass, defaultGroupSequenceProviderClass ); - } - - protected final void addConstraintConfig(ConstraintDef definition) { - Class beanClass = definition.beanType; - configuredClasses.add( beanClass ); - if ( constraintConfig.containsKey( beanClass ) ) { - constraintConfig.get( beanClass ).add( definition ); - } - else { - List> definitionList = new ArrayList>(); - definitionList.add( definition ); - constraintConfig.put( beanClass, definitionList ); - } - } } - - diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/ConstraintsForType.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/ConstraintsForType.java deleted file mode 100644 index 73ebf76e98..0000000000 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/ConstraintsForType.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * JBoss, Home of Professional Open Source - * Copyright 2010, Red Hat, Inc. and/or its affiliates, and individual contributors - * by the @authors tag. See the copyright.txt in the distribution for a - * full listing of individual contributors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.hibernate.validator.cfg; - -import java.lang.annotation.Annotation; -import java.lang.annotation.ElementType; -import java.lang.reflect.Constructor; -import java.util.Arrays; - -import org.hibernate.validator.group.DefaultGroupSequenceProvider; -import org.hibernate.validator.util.ReflectionHelper; - -import static java.lang.annotation.ElementType.TYPE; - -/** - * Via instances of this class constraints and cascading properties can be configured for a single bean class. - * - * @author Hardy Ferentschik - * @author Gunnar Morling - * @author Kevin Pollet - SERLI - (kevin.pollet@serli.com) - */ -public final class ConstraintsForType { - private static final String EMPTY_PROPERTY = ""; - - private final ConstraintMapping mapping; - private final Class beanClass; - private String property; - private ElementType elementType; - - public ConstraintsForType(Class beanClass, ConstraintMapping mapping) { - this( beanClass, EMPTY_PROPERTY, TYPE, mapping ); - } - - public ConstraintsForType(Class beanClass, String property, ElementType type, ConstraintMapping mapping) { - this.beanClass = beanClass; - this.mapping = mapping; - this.property = property; - this.elementType = type; - } - - /** - * Adds a new constraint. - * - * @param definition The constraint definition class. - * - * @return A constraint definition class allowing to specify additional constraint parameters. - */ - public > T constraint(Class definition) { - final Constructor constructor = ReflectionHelper.getConstructor( - definition, Class.class, String.class, ElementType.class, ConstraintMapping.class - ); - - final T constraintDefinition = ReflectionHelper.newConstructorInstance( - constructor, beanClass, property, elementType, mapping - ); - mapping.addConstraintConfig( constraintDefinition ); - return constraintDefinition; - } - - /** - * Adds a new constraint in a generic way. - *

- * The attributes of the constraint can later on be set by invoking - * {@link GenericConstraintDef#addParameter(String, Object)}. - *

- * - * @param
The annotation type of the constraint to add. - * @param definition The constraint to add. - * - * @return A generic constraint definition class allowing to specify additional constraint parameters. - */ - public GenericConstraintDef genericConstraint(Class definition) { - final GenericConstraintDef constraintDefinition = new GenericConstraintDef( - beanClass, definition, property, elementType, mapping - ); - - mapping.addConstraintConfig( constraintDefinition ); - return constraintDefinition; - } - - /** - * Changes the property for which added constraints apply. - *

- * Until this method is called constraints apply on class level. After calling this method constraints - * apply on the specified property with the given access type. - *

- * - * @param property The property on which to apply the following constraints (Java Bean notation). - * @param type The access type (field/property). - * - * @return Returns itself for method chaining. - */ - public ConstraintsForType property(String property, ElementType type) { - return new ConstraintsForType( beanClass, property, type, mapping ); - } - - public ConstraintsForType valid(String property, ElementType type) { - mapping.addCascadeConfig( new CascadeDef( beanClass, property, type ) ); - return this; - } - - /** - * Defines the default groups sequence for the bean class of this instance. - * - * @param defaultGroupSequence the default group sequence. - * - * @return Returns itself for method chaining. - */ - public ConstraintsForType defaultGroupSequence(Class... defaultGroupSequence) { - mapping.addDefaultGroupSequence( beanClass, Arrays.asList( defaultGroupSequence ) ); - return this; - } - - /** - * Defines the default group sequence provider for the bean class of this instance. - * - * @param defaultGroupSequenceProviderClass The default group sequence provider class. - * - * @return Returns itself for method chaining. - */ - public > ConstraintsForType defaultGroupSequenceProvider(Class defaultGroupSequenceProviderClass) { - mapping.addDefaultGroupSequenceProvider( beanClass, defaultGroupSequenceProviderClass ); - return this; - } - - /** - * Creates a new {@code ConstraintsForType} in order to define constraints on a new bean type. - * - * @param type The bean type. - * - * @return Returns a new {@code ConstraintsForType} instance. - */ - public ConstraintsForType type(Class type) { - return new ConstraintsForType( type, mapping ); - } -} - - diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/GenericConstraintDef.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/GenericConstraintDef.java index f9dcff2549..d363c5dc33 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/GenericConstraintDef.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/GenericConstraintDef.java @@ -18,21 +18,20 @@ package org.hibernate.validator.cfg; import java.lang.annotation.Annotation; -import java.lang.annotation.ElementType; /** * A {@link ConstraintDef} class which can be used to configure any constraint * type. For this purpose the class defines a generic method * {@link GenericConstraintDef#param(String, Object)} which allows to add * arbitrary constraint parameters. - * + * * @author Hardy Ferentschik * @author Gunnar Morling */ public class GenericConstraintDef
extends ConstraintDef, A> { - public GenericConstraintDef(Class beanType, Class constraintType, String property, ElementType elementType, ConstraintMapping mapping) { - super( beanType, constraintType, property, elementType, mapping ); + public GenericConstraintDef(Class constraintType) { + super( constraintType ); } public GenericConstraintDef param(String key, Object value) { diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/Cascadable.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/Cascadable.java new file mode 100644 index 0000000000..d8f98bae2b --- /dev/null +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/Cascadable.java @@ -0,0 +1,35 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc. and/or its affiliates, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.hibernate.validator.cfg.context; + +/** + * Facet of a constraint mapping creational context which allows to mark the underlying + * element as to be validated in a cascaded way. + * + * @author Gunnar Morling + * @author Kevin Pollet - SERLI - (kevin.pollet@serli.com) + */ +public interface Cascadable> { + + /** + * Marks the current element (property, parameter etc.) as cascadable. + * + * @return The current creational context following the method chaining pattern. + */ + C valid(); + +} diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/Constrainable.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/Constrainable.java new file mode 100644 index 0000000000..2022ca41fd --- /dev/null +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/Constrainable.java @@ -0,0 +1,39 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc. and/or its affiliates, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.hibernate.validator.cfg.context; + +import org.hibernate.validator.cfg.ConstraintDef; + +/** + * Facet of a constraint mapping creational context which allows to place + * constraints on the underlying element. + * + * @author Gunnar Morling + * @author Kevin Pollet - SERLI - (kevin.pollet@serli.com) + */ +public interface Constrainable> { + + /** + * Adds a new constraint. + * + * @param definition The constraint to add. + * + * @return The current creational context following the method chaining pattern. + */ + C constraint(ConstraintDef definition); + +} diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/MethodConstraintMappingContext.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/MethodConstraintMappingContext.java new file mode 100644 index 0000000000..f446eb79a9 --- /dev/null +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/MethodConstraintMappingContext.java @@ -0,0 +1,27 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc. and/or its affiliates, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.hibernate.validator.cfg.context; + +/** + * Constraint mapping creational context representing a method. Allows to + * navigate to the method's parameters and return value. + * + * @author Gunnar Morling + */ +public interface MethodConstraintMappingContext extends ParameterTarget, ReturnValueTarget { + +} diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/ParameterConstraintMappingContext.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/ParameterConstraintMappingContext.java new file mode 100644 index 0000000000..e632236a8b --- /dev/null +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/ParameterConstraintMappingContext.java @@ -0,0 +1,29 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc. and/or its affiliates, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.hibernate.validator.cfg.context; + +/** + * Constraint mapping creational context representing a method parameter. Allows + * to place constraints on the parameter, mark the parameter as cascadable and to + * navigate to other constraint targets. + * + * @author Gunnar Morling + */ +public interface ParameterConstraintMappingContext + extends TypeTargets, ParameterTarget, ReturnValueTarget, Constrainable, Cascadable { + +} diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/ParameterTarget.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/ParameterTarget.java new file mode 100644 index 0000000000..ff94db363f --- /dev/null +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/ParameterTarget.java @@ -0,0 +1,37 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc. and/or its affiliates, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.hibernate.validator.cfg.context; + +/** + * Facet of a constraint mapping creational context which allows to the select a method + * parameter to which the next operations shall apply. + * + * @author Kevin Pollet - SERLI - (kevin.pollet@serli.com) + * @author Gunnar Morling + */ +public interface ParameterTarget { + + /** + * Changes the parameter for which added constraints apply. + * + * @param index The parameter index. + * + * @return A creational context representing the selected parameter. + */ + ParameterConstraintMappingContext parameter(int index); + +} diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/PropertyConstraintMappingContext.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/PropertyConstraintMappingContext.java new file mode 100644 index 0000000000..b21cf0ad04 --- /dev/null +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/PropertyConstraintMappingContext.java @@ -0,0 +1,29 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc. and/or its affiliates, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.hibernate.validator.cfg.context; + +/** + * Constraint mapping creational context representing a property of a bean. Allows + * to place constraints on the property, mark the property as cascadable and to + * navigate to other constraint targets. + * + * @author Gunnar Morling + */ +public interface PropertyConstraintMappingContext + extends Constrainable, TypeTargets, Cascadable { + +} diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/ReturnValueConstraintMappingContext.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/ReturnValueConstraintMappingContext.java new file mode 100644 index 0000000000..66a200673b --- /dev/null +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/ReturnValueConstraintMappingContext.java @@ -0,0 +1,29 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc. and/or its affiliates, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.hibernate.validator.cfg.context; + +/** + * Constraint mapping creational context representing a method return value. Allows + * to place constraints on the return value, mark it as cascadable and to + * navigate to other constraint targets. + * + * @author Gunnar Morling + */ +public interface ReturnValueConstraintMappingContext + extends TypeTargets, ParameterTarget, Constrainable, Cascadable { + +} diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/ReturnValueTarget.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/ReturnValueTarget.java new file mode 100644 index 0000000000..f7a4908554 --- /dev/null +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/ReturnValueTarget.java @@ -0,0 +1,35 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc. and/or its affiliates, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.hibernate.validator.cfg.context; + +/** + * Facet of a constraint mapping creational context which allows to the select the current method's + * return value as target for the next operations. + * + * @author Kevin Pollet - SERLI - (kevin.pollet@serli.com) + * @author Gunnar Morling + */ +public interface ReturnValueTarget { + + /** + * Selects the current method's return value as the target for the next operations. + * + * @return A creational context representing the current method's return value. + */ + ReturnValueConstraintMappingContext returnValue(); + +} diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/TypeConstraintMappingContext.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/TypeConstraintMappingContext.java new file mode 100644 index 0000000000..6cd38fc89c --- /dev/null +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/TypeConstraintMappingContext.java @@ -0,0 +1,54 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc. and/or its affiliates, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.hibernate.validator.cfg.context; + +import org.hibernate.validator.group.DefaultGroupSequenceProvider; + +/** + * Constraint mapping creational context representing a type. Allows place + * class-level constraints on that type, define its default group sequence (and provider) + * and to navigate to other constraint targets. + * + * @param The type represented by this creational context. + * + * @author Kevin Pollet - SERLI - (kevin.pollet@serli.com) + * @author Gunnar Morling + */ +public interface TypeConstraintMappingContext + extends Constrainable>, TypeTargets { + + /** + * Defines the default group sequence for current type. + * + * @param defaultGroupSequence the default group sequence. + * + * @return The current creational context following the method chaining pattern. + */ + TypeConstraintMappingContext defaultGroupSequence( + Class... defaultGroupSequence); + + /** + * Defines the default group sequence provider for the current type. + * + * @param defaultGroupSequenceProviderClass The default group sequence provider class. + * + * @return The current creational context following the method chaining pattern. + */ + > TypeConstraintMappingContext defaultGroupSequenceProvider( + Class defaultGroupSequenceProviderClass); + +} diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/TypeTargets.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/TypeTargets.java new file mode 100644 index 0000000000..7023389c71 --- /dev/null +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/TypeTargets.java @@ -0,0 +1,69 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc. and/or its affiliates, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.hibernate.validator.cfg.context; + +import java.lang.annotation.ElementType; + +/** + * Facet of a constraint mapping creational context which allows to the select the bean type, + * bean property or method of a type to which the next operations shall apply. + * + * @author Kevin Pollet - SERLI - (kevin.pollet@serli.com) + * @author Gunnar Morling + */ +public interface TypeTargets { + + /** + * Selects the type to which the next operations shall apply. + * + * @param The type to select. + * @param type The type to select. + * + * @return A creational context representing the selected type. + */ + TypeConstraintMappingContext type(Class type); + + /** + * Selects a property to which the next operations shall apply. + *

+ * Until this method is called constraints apply on class level. After calling this method constraints + * apply on the specified property with the given access type. + *

+ * + * @param property The property on which to apply the following constraints (Java Bean notation). + * @param type The access type (field/property). + * + * @return A creational context representing the selected property. + */ + PropertyConstraintMappingContext property(String property, + ElementType type); + + /** + * Selects a method to which the next operations shall apply. + *

+ * Until this method is called constraints apply on class level. After calling this method constraints + * apply to the specified method. + *

+ * + * @param name The method name. + * @param parameterTypes The method parameter types. + * + * @return A creational context representing the selected method. + */ + MethodConstraintMappingContext method(String name, Class... parameterTypes); + +} diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/ConfiguredConstraint.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/ConfiguredConstraint.java new file mode 100644 index 0000000000..25e563803d --- /dev/null +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/ConfiguredConstraint.java @@ -0,0 +1,106 @@ +/* +* JBoss, Home of Professional Open Source +* Copyright 2011, Red Hat, Inc. and/or its affiliates, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.hibernate.validator.cfg.context.impl; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.util.Map; + +import org.hibernate.validator.cfg.ConstraintDef; +import org.hibernate.validator.metadata.location.BeanConstraintLocation; +import org.hibernate.validator.metadata.location.ConstraintLocation; +import org.hibernate.validator.metadata.location.MethodConstraintLocation; + +/** + * Represents a programmatically configured constraint and meta-data + * related to its location (bean type etc.). + * + * @author Gunnar Morling + */ +public class ConfiguredConstraint
{ + + private final ConstraintDefAccessor constraint; + private final L location; + + private ConfiguredConstraint(ConstraintDef constraint, L location) { + + this.constraint = new ConstraintDefAccessor( constraint ); + this.location = location; + } + + public static ConfiguredConstraint forType(ConstraintDef constraint, Class beanType) { + return new ConfiguredConstraint( + constraint, new BeanConstraintLocation( beanType ) + ); + } + + public static ConfiguredConstraint forProperty(ConstraintDef constraint, Class beanType, Member member) { + + return new ConfiguredConstraint( + constraint, new BeanConstraintLocation( beanType, member ) + ); + } + + public static ConfiguredConstraint forParameter(ConstraintDef constraint, Method method, int parameterIndex) { + return new ConfiguredConstraint( + constraint, new MethodConstraintLocation( method, parameterIndex ) + ); + } + + public static ConfiguredConstraint forReturnValue(ConstraintDef constraint, Method method) { + return new ConfiguredConstraint( + constraint, new MethodConstraintLocation( method ) + ); + } + + public ConstraintDef getConstraint() { + return constraint; + } + + public L getLocation() { + return location; + } + + public Class getConstraintType() { + return constraint.getConstraintType(); + } + + public Map getParameters() { + return constraint.getParameters(); + } + + /** + * Provides access to the members of a {@link ConstraintDef}. + */ + private static class ConstraintDefAccessor + extends ConstraintDef, A> { + + private ConstraintDefAccessor(ConstraintDef original) { + super( original ); + } + + private Class getConstraintType() { + return constraintType; + } + + private Map getParameters() { + return parameters; + } + } + +} diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/ConstraintMappingContext.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/ConstraintMappingContext.java new file mode 100644 index 0000000000..303987d8ec --- /dev/null +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/ConstraintMappingContext.java @@ -0,0 +1,203 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc. and/or its affiliates, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.hibernate.validator.cfg.context.impl; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.hibernate.validator.cfg.ConstraintMapping; +import org.hibernate.validator.group.DefaultGroupSequenceProvider; +import org.hibernate.validator.metadata.location.BeanConstraintLocation; +import org.hibernate.validator.metadata.location.MethodConstraintLocation; + +import static org.hibernate.validator.util.CollectionHelper.newArrayList; +import static org.hibernate.validator.util.CollectionHelper.newHashMap; +import static org.hibernate.validator.util.CollectionHelper.newHashSet; + +/** + * Context which collects constraints, cascades etc. configured via the programmatic API. + * + * @author Hardy Ferentschik + * @author Gunnar Morling + * @author Kevin Pollet - SERLI - (kevin.pollet@serli.om) + */ +public class ConstraintMappingContext { + private final Map, List>> constraintConfig; + private final Map, List>> methodConstraintConfig; + private final Map, List> cascadeConfig; + private final Map, List> methodCascadeConfig; + private final Set> configuredClasses; + private final Map, List>> defaultGroupSequences; + private final Map, Class>> defaultGroupSequenceProviders; + + public ConstraintMappingContext() { + this.constraintConfig = newHashMap(); + this.methodConstraintConfig = newHashMap(); + this.cascadeConfig = newHashMap(); + this.methodCascadeConfig = newHashMap(); + this.configuredClasses = newHashSet(); + this.defaultGroupSequences = newHashMap(); + this.defaultGroupSequenceProviders = newHashMap(); + } + + /** + * Returns the constraint mapping context from the given constraint mapping. + */ + public static ConstraintMappingContext getFromMapping(ConstraintMapping mapping) { + return new ConstraintMappingContextAccessor( mapping ).getContext(); + } + + /** + * Returns all constraint definitions registered with this mapping. + * + * @return A map with this mapping's constraint definitions. Each key in + * this map represents a bean type, for which the constraint + * definitions in the associated map value are configured. + */ + public final Map, List>> getConstraintConfig() { + return constraintConfig; + } + + public Map, List>> getMethodConstraintConfig() { + return methodConstraintConfig; + } + + public final Map, List> getCascadeConfig() { + return cascadeConfig; + } + + public final Map, List> getMethodCascadeConfig() { + return methodCascadeConfig; + } + + public final Collection> getConfiguredClasses() { + return configuredClasses; + } + + public final List> getDefaultSequence(Class beanType) { + if ( defaultGroupSequences.containsKey( beanType ) ) { + return defaultGroupSequences.get( beanType ); + } + else { + return Collections.emptyList(); + } + } + + /** + * Returns the class of the default group sequence provider defined + * for the given bean type. + * + * @param beanType The bean type. + * + * @return The default group sequence provider defined class or {@code null} if none. + */ + public final Class> getDefaultGroupSequenceProvider(Class beanType) { + return defaultGroupSequenceProviders.get( beanType ); + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "ConstraintMapping" ); + sb.append( "{cascadeConfig=" ).append( cascadeConfig ); + sb.append( ", methodCascadeConfig=" ).append( methodCascadeConfig ); + sb.append( ", constraintConfig=" ).append( constraintConfig ); + sb.append( ", configuredClasses=" ).append( configuredClasses ); + sb.append( ", defaultGroupSequences=" ).append( defaultGroupSequences ); + sb.append( '}' ); + return sb.toString(); + } + + public final void addCascadeConfig(BeanConstraintLocation cascade) { + Class beanClass = cascade.getBeanClass(); + configuredClasses.add( beanClass ); + if ( cascadeConfig.containsKey( beanClass ) ) { + cascadeConfig.get( beanClass ).add( cascade ); + } + else { + List cascadeList = newArrayList(); + cascadeList.add( cascade ); + cascadeConfig.put( beanClass, cascadeList ); + } + } + + public final void addMethodCascadeConfig(MethodConstraintLocation cascade) { + Class beanClass = cascade.getBeanClass(); + configuredClasses.add( beanClass ); + if ( methodCascadeConfig.containsKey( beanClass ) ) { + methodCascadeConfig.get( beanClass ).add( cascade ); + } + else { + List cascadeList = newArrayList(); + cascadeList.add( cascade ); + methodCascadeConfig.put( beanClass, cascadeList ); + } + } + + public final void addDefaultGroupSequence(Class beanClass, List> defaultGroupSequence) { + configuredClasses.add( beanClass ); + defaultGroupSequences.put( beanClass, defaultGroupSequence ); + } + + public final > void addDefaultGroupSequenceProvider(Class beanClass, Class defaultGroupSequenceProviderClass) { + configuredClasses.add( beanClass ); + defaultGroupSequenceProviders.put( beanClass, defaultGroupSequenceProviderClass ); + } + + public final void addConstraintConfig(ConfiguredConstraint constraint) { + Class beanClass = constraint.getLocation().getBeanClass(); + configuredClasses.add( beanClass ); + if ( constraintConfig.containsKey( beanClass ) ) { + constraintConfig.get( beanClass ).add( constraint ); + } + else { + List> definitionList = newArrayList(); + definitionList.add( constraint ); + constraintConfig.put( beanClass, definitionList ); + } + } + + public final void addMethodConstraintConfig(ConfiguredConstraint constraint) { + Class beanClass = constraint.getLocation().getBeanClass(); + configuredClasses.add( beanClass ); + if ( methodConstraintConfig.containsKey( beanClass ) ) { + methodConstraintConfig.get( beanClass ).add( constraint ); + } + else { + List> definitionList = newArrayList(); + definitionList.add( constraint ); + methodConstraintConfig.put( beanClass, definitionList ); + } + } + + /** + * Provides access to the members of a {@link ConstraintMapping}. + */ + private static class ConstraintMappingContextAccessor extends ConstraintMapping { + + private ConstraintMappingContextAccessor(ConstraintMapping original) { + super( original ); + } + + private ConstraintMappingContext getContext() { + return context; + } + } +} diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/ConstraintMappingContextImplBase.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/ConstraintMappingContextImplBase.java new file mode 100644 index 0000000000..45b1a31e80 --- /dev/null +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/ConstraintMappingContextImplBase.java @@ -0,0 +1,99 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc. and/or its affiliates, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.hibernate.validator.cfg.context.impl; + +import java.lang.annotation.ElementType; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import javax.validation.ValidationException; + +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.util.Contracts; +import org.hibernate.validator.util.ReflectionHelper; + +/** + * Base class for implementations of constraint mapping creational context types. + * + * @author Gunnar Morling + */ +public abstract class ConstraintMappingContextImplBase { + + protected final Class beanClass; + + protected final ConstraintMappingContext mapping; + + public ConstraintMappingContextImplBase(Class beanClass, ConstraintMappingContext mapping) { + + this.beanClass = beanClass; + this.mapping = mapping; + } + + public TypeConstraintMappingContext type(Class type) { + + Contracts.assertNotNull( beanClass, "The bean type must not be null when creating a constraint mapping." ); + + return new TypeConstraintMappingContextImpl( type, mapping ); + } + + public PropertyConstraintMappingContext property(String property, ElementType elementType) { + + Contracts.assertNotNull( property, "The property name must not be null." ); + Contracts.assertNotNull( elementType, "The element type must not be null." ); + + if ( property.length() == 0 ) { + throw new IllegalArgumentException( "The property name must not be empty." ); + } + + Member member = ReflectionHelper.getMember( + beanClass, property, elementType + ); + + if ( member == null ) { + throw new ValidationException( + "The class " + beanClass + " does not have a property '" + + property + "' with access " + elementType + ); + } + + return new PropertyConstraintMappingContextImpl( beanClass, member, mapping ); + } + + public MethodConstraintMappingContext method(String name, Class... parameterTypes) { + + Contracts.assertNotNull( name, "The method name must not be null." ); + + Method method = ReflectionHelper.getDeclaredMethod( beanClass, name, parameterTypes ); + + if ( method == null ) { + StringBuilder sb = new StringBuilder(); + for ( Class oneParameterType : parameterTypes ) { + sb.append( oneParameterType.getName() + ", " ); + } + + String parameterTypesAsString = sb.length() > 2 ? sb.substring( 0, sb.length() - 2 ) : sb.toString(); + + throw new IllegalArgumentException( + String.format( "Type %s doesn't have a method %s(%s).", beanClass, name, parameterTypesAsString ) + ); + } + + return new MethodConstraintMappingContextImpl( beanClass, method, mapping ); + } + +} \ No newline at end of file diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/MethodConstraintMappingContextImpl.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/MethodConstraintMappingContextImpl.java new file mode 100644 index 0000000000..712161498e --- /dev/null +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/MethodConstraintMappingContextImpl.java @@ -0,0 +1,57 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc. and/or its affiliates, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.hibernate.validator.cfg.context.impl; + +import java.lang.reflect.Method; + +import org.hibernate.validator.cfg.context.MethodConstraintMappingContext; +import org.hibernate.validator.cfg.context.ParameterConstraintMappingContext; +import org.hibernate.validator.cfg.context.ReturnValueConstraintMappingContext; + +/** + * A constraint mapping creational context which allows to select the parameter or + * return value to which the next operations shall apply. + * + * @author Kevin Pollet - SERLI - (kevin.pollet@serli.com) + * @author Gunnar Morling + */ +public class MethodConstraintMappingContextImpl implements MethodConstraintMappingContext { + + private final Class beanClass; + private final Method method; + private final ConstraintMappingContext mapping; + + public MethodConstraintMappingContextImpl(Class beanClass, Method method, ConstraintMappingContext mapping) { + + this.beanClass = beanClass; + this.method = method; + this.mapping = mapping; + } + + public ParameterConstraintMappingContext parameter(int index) { + return new ParameterConstraintMappingContextImpl( + beanClass, method, index, mapping + ); + } + + public ReturnValueConstraintMappingContext returnValue() { + return new ReturnValueConstraintMappingContextImpl( + beanClass, method, mapping + ); + } + +} diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/ParameterConstraintMappingContextImpl.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/ParameterConstraintMappingContextImpl.java new file mode 100644 index 0000000000..6819e80582 --- /dev/null +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/ParameterConstraintMappingContextImpl.java @@ -0,0 +1,100 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2010, Red Hat, Inc. and/or its affiliates, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.hibernate.validator.cfg.context.impl; + +import java.lang.reflect.Method; + +import org.hibernate.validator.cfg.ConstraintDef; +import org.hibernate.validator.cfg.context.ParameterConstraintMappingContext; +import org.hibernate.validator.cfg.context.ReturnValueConstraintMappingContext; +import org.hibernate.validator.metadata.location.MethodConstraintLocation; + +/** + * Constraint mapping creational context which allows to configure the constraints for one method parameter. + * + * @author Hardy Ferentschik + * @author Gunnar Morling + * @author Kevin Pollet - SERLI - (kevin.pollet@serli.com) + */ +public final class ParameterConstraintMappingContextImpl + extends ConstraintMappingContextImplBase + implements ParameterConstraintMappingContext { + + private final Method method; + private final int parameterIndex; + + public ParameterConstraintMappingContextImpl(Class beanClass, Method method, int parameterIndex, ConstraintMappingContext mapping) { + + super( beanClass, mapping ); + + if ( parameterIndex < 0 || parameterIndex >= method.getParameterTypes().length ) { + throw new IllegalArgumentException( "A valid parameter index has to be specified for method '" + method.getName() + "'" ); + } + + this.method = method; + this.parameterIndex = parameterIndex; + } + + public ParameterConstraintMappingContext constraint(ConstraintDef definition) { + + mapping.addMethodConstraintConfig( + ConfiguredConstraint.forParameter( + definition, method, parameterIndex + ) + ); + return this; + } + + /** + * Marks the currently selected method parameter as cascadable. + * + * @return Returns itself for method chaining. + */ + public ParameterConstraintMappingContext valid() { + mapping.addMethodCascadeConfig( + new MethodConstraintLocation( + method, parameterIndex + ) + ); + return this; + } + + /** + * Changes the parameter for which added constraints apply. + * + * @param index The parameter index. + * + * @return Returns a new {@code ConstraintsForTypeMethodElement} instance allowing method chaining. + */ + public ParameterConstraintMappingContext parameter(int index) { + return new ParameterConstraintMappingContextImpl( + beanClass, method, index, mapping + ); + } + + /** + * Defines constraints on the return value of the current method. + * + * @return Returns a new {@code ConstraintsForTypeMethodElement} instance allowing method chaining. + */ + public ReturnValueConstraintMappingContext returnValue() { + return new ReturnValueConstraintMappingContextImpl( + beanClass, method, mapping + ); + } + +} diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/PropertyConstraintMappingContextImpl.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/PropertyConstraintMappingContextImpl.java new file mode 100644 index 0000000000..5b75efbf9c --- /dev/null +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/PropertyConstraintMappingContextImpl.java @@ -0,0 +1,59 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2010, Red Hat, Inc. and/or its affiliates, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.hibernate.validator.cfg.context.impl; + +import java.lang.reflect.Member; + +import org.hibernate.validator.cfg.ConstraintDef; +import org.hibernate.validator.cfg.context.PropertyConstraintMappingContext; +import org.hibernate.validator.metadata.location.BeanConstraintLocation; + +/** + * Constraint mapping creational context which allows to configure the constraints for one bean property. + * + * @author Hardy Ferentschik + * @author Gunnar Morling + * @author Kevin Pollet - SERLI - (kevin.pollet@serli.com) + */ +public final class PropertyConstraintMappingContextImpl extends ConstraintMappingContextImplBase + implements PropertyConstraintMappingContext { + + private final Member member; + + public PropertyConstraintMappingContextImpl(Class beanClass, Member member, ConstraintMappingContext mapping) { + + super( beanClass, mapping ); + + this.member = member; + } + + public PropertyConstraintMappingContext constraint(ConstraintDef definition) { + + mapping.addConstraintConfig( + ConfiguredConstraint.forProperty( + definition, beanClass, member + ) + ); + return this; + } + + public PropertyConstraintMappingContext valid() { + mapping.addCascadeConfig( new BeanConstraintLocation( beanClass, member ) ); + return this; + } +} + diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/ReturnValueConstraintMappingContextImpl.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/ReturnValueConstraintMappingContextImpl.java new file mode 100644 index 0000000000..2a9dd10bfc --- /dev/null +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/ReturnValueConstraintMappingContextImpl.java @@ -0,0 +1,78 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2010, Red Hat, Inc. and/or its affiliates, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.hibernate.validator.cfg.context.impl; + +import java.lang.reflect.Method; + +import org.hibernate.validator.cfg.ConstraintDef; +import org.hibernate.validator.cfg.context.ParameterConstraintMappingContext; +import org.hibernate.validator.cfg.context.ReturnValueConstraintMappingContext; +import org.hibernate.validator.metadata.location.MethodConstraintLocation; + +/** + * Constraint mapping creational context which allows to configure the constraints for one method return value. + * + * @author Hardy Ferentschik + * @author Gunnar Morling + * @author Kevin Pollet - SERLI - (kevin.pollet@serli.com) + */ +public final class ReturnValueConstraintMappingContextImpl + extends ConstraintMappingContextImplBase + implements ReturnValueConstraintMappingContext { + + private final Method method; + + public ReturnValueConstraintMappingContextImpl(Class beanClass, Method method, ConstraintMappingContext mapping) { + + super( beanClass, mapping ); + + this.method = method; + } + + public ReturnValueConstraintMappingContext constraint(ConstraintDef definition) { + mapping.addMethodConstraintConfig( + ConfiguredConstraint.forReturnValue( + definition, method + ) + ); + return this; + } + + /** + * Marks the current property as cascadable. + * + * @return Returns itself for method chaining. + */ + public ReturnValueConstraintMappingContext valid() { + mapping.addMethodCascadeConfig( new MethodConstraintLocation( method ) ); + return this; + } + + /** + * Changes the parameter for which added constraints apply. + * + * @param index The parameter index. + * + * @return Returns a new {@code ConstraintsForTypeMethodElement} instance allowing method chaining. + */ + public ParameterConstraintMappingContext parameter(int index) { + return new ParameterConstraintMappingContextImpl( + beanClass, method, index, mapping + ); + } + +} diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/TypeConstraintMappingContextImpl.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/TypeConstraintMappingContextImpl.java new file mode 100644 index 0000000000..589c494c81 --- /dev/null +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/TypeConstraintMappingContextImpl.java @@ -0,0 +1,70 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2010, Red Hat, Inc. and/or its affiliates, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.hibernate.validator.cfg.context.impl; + +import java.util.Arrays; + +import org.hibernate.validator.cfg.ConstraintDef; +import org.hibernate.validator.cfg.context.TypeConstraintMappingContext; +import org.hibernate.validator.group.DefaultGroupSequenceProvider; + +/** + * Constraint mapping creational context which allows to configure the class-level constraints for one bean. + * + * @param The type represented by this creational context. + * + * @author Hardy Ferentschik + * @author Gunnar Morling + * @author Kevin Pollet - SERLI - (kevin.pollet@serli.com) + */ +public final class TypeConstraintMappingContextImpl extends ConstraintMappingContextImplBase + implements TypeConstraintMappingContext { + + public TypeConstraintMappingContextImpl(Class beanClass, ConstraintMappingContext mapping) { + super( beanClass, mapping ); + } + + public TypeConstraintMappingContext constraint(ConstraintDef definition) { + + mapping.addConstraintConfig( ConfiguredConstraint.forType( definition, beanClass ) ); + return this; + } + + /** + * Defines the default groups sequence for the bean class of this instance. + * + * @param defaultGroupSequence the default group sequence. + * + * @return Returns itself for method chaining. + */ + public TypeConstraintMappingContext defaultGroupSequence(Class... defaultGroupSequence) { + mapping.addDefaultGroupSequence( beanClass, Arrays.asList( defaultGroupSequence ) ); + return this; + } + + /** + * Defines the default group sequence provider for the bean class of this instance. + * + * @param defaultGroupSequenceProviderClass The default group sequence provider class. + * + * @return Returns itself for method chaining. + */ + public > TypeConstraintMappingContext defaultGroupSequenceProvider(Class defaultGroupSequenceProviderClass) { + mapping.addDefaultGroupSequenceProvider( beanClass, defaultGroupSequenceProviderClass ); + return this; + } +} diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/package.html b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/package.html new file mode 100644 index 0000000000..96de8abbc0 --- /dev/null +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/impl/package.html @@ -0,0 +1,26 @@ + + + + + + +

Creational context implementations of the API for programmatic +constraint definition.

+ + diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/package.html b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/package.html new file mode 100644 index 0000000000..25e9056c61 --- /dev/null +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/context/package.html @@ -0,0 +1,27 @@ + + + + + + +

Contains facet and creational context interfaces forming the API +for programmatic constraint definition.

+

This package is part of the public Hibernate Validator API.

+ + diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/AssertFalseDef.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/AssertFalseDef.java index 966e4b473d..a2d5695837 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/AssertFalseDef.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/AssertFalseDef.java @@ -16,17 +16,16 @@ */ package org.hibernate.validator.cfg.defs; -import java.lang.annotation.ElementType; import javax.validation.constraints.AssertFalse; import org.hibernate.validator.cfg.ConstraintDef; -import org.hibernate.validator.cfg.ConstraintMapping; /** * @author Hardy Ferentschik */ public class AssertFalseDef extends ConstraintDef { - public AssertFalseDef(Class beanType, String property, ElementType elementType, ConstraintMapping mapping) { - super( beanType, AssertFalse.class, property, elementType, mapping ); + + public AssertFalseDef() { + super( AssertFalse.class ); } } diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/AssertTrueDef.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/AssertTrueDef.java index f77a26c6c0..089c44010b 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/AssertTrueDef.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/AssertTrueDef.java @@ -16,17 +16,16 @@ */ package org.hibernate.validator.cfg.defs; -import java.lang.annotation.ElementType; import javax.validation.constraints.AssertTrue; import org.hibernate.validator.cfg.ConstraintDef; -import org.hibernate.validator.cfg.ConstraintMapping; /** * @author Hardy Ferentschik */ public class AssertTrueDef extends ConstraintDef { - public AssertTrueDef(Class beanType, String property, ElementType elementType, ConstraintMapping mapping) { - super( beanType, AssertTrue.class, property, elementType, mapping ); + + public AssertTrueDef() { + super( AssertTrue.class ); } } diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/CreditCardNumberDef.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/CreditCardNumberDef.java index d285808354..c7dcf2df89 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/CreditCardNumberDef.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/CreditCardNumberDef.java @@ -17,17 +17,15 @@ package org.hibernate.validator.cfg.defs; -import java.lang.annotation.ElementType; - import org.hibernate.validator.cfg.ConstraintDef; -import org.hibernate.validator.cfg.ConstraintMapping; import org.hibernate.validator.constraints.CreditCardNumber; /** * @author Hardy Ferentschik */ public class CreditCardNumberDef extends ConstraintDef { - public CreditCardNumberDef(Class beanType, String property, ElementType elementType, ConstraintMapping mapping) { - super( beanType, CreditCardNumber.class, property, elementType, mapping ); + + public CreditCardNumberDef() { + super( CreditCardNumber.class ); } } diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/DecimalMaxDef.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/DecimalMaxDef.java index 1c60ce6411..7f6c722c8d 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/DecimalMaxDef.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/DecimalMaxDef.java @@ -17,19 +17,17 @@ package org.hibernate.validator.cfg.defs; -import java.lang.annotation.ElementType; import javax.validation.constraints.DecimalMax; import org.hibernate.validator.cfg.ConstraintDef; -import org.hibernate.validator.cfg.ConstraintMapping; /** * @author Hardy Ferentschik */ public class DecimalMaxDef extends ConstraintDef { - public DecimalMaxDef(Class beanType, String property, ElementType elementType, ConstraintMapping mapping) { - super( beanType, DecimalMax.class, property, elementType, mapping ); + public DecimalMaxDef() { + super( DecimalMax.class ); } public DecimalMaxDef value(String max) { diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/DecimalMinDef.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/DecimalMinDef.java index e6535db501..0a6219dacf 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/DecimalMinDef.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/DecimalMinDef.java @@ -16,19 +16,17 @@ */ package org.hibernate.validator.cfg.defs; -import java.lang.annotation.ElementType; import javax.validation.constraints.DecimalMin; import org.hibernate.validator.cfg.ConstraintDef; -import org.hibernate.validator.cfg.ConstraintMapping; /** * @author Hardy Ferentschik */ public class DecimalMinDef extends ConstraintDef { - public DecimalMinDef(Class beanType, String property, ElementType elementType, ConstraintMapping mapping) { - super( beanType, DecimalMin.class, property, elementType, mapping ); + public DecimalMinDef() { + super( DecimalMin.class ); } public DecimalMinDef value(String min) { diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/DigitsDef.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/DigitsDef.java index fe2c32545c..2b7345a972 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/DigitsDef.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/DigitsDef.java @@ -16,11 +16,9 @@ */ package org.hibernate.validator.cfg.defs; -import java.lang.annotation.ElementType; import javax.validation.constraints.Digits; import org.hibernate.validator.cfg.ConstraintDef; -import org.hibernate.validator.cfg.ConstraintMapping; /** @@ -28,8 +26,8 @@ */ public class DigitsDef extends ConstraintDef { - public DigitsDef(Class beanType, String property, ElementType elementType, ConstraintMapping mapping) { - super( beanType, Digits.class, property, elementType, mapping ); + public DigitsDef() { + super( Digits.class ); } public DigitsDef integer(int integer) { diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/EmailDef.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/EmailDef.java index f6834fdfa7..e3d9be8794 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/EmailDef.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/EmailDef.java @@ -17,17 +17,15 @@ package org.hibernate.validator.cfg.defs; -import java.lang.annotation.ElementType; - import org.hibernate.validator.cfg.ConstraintDef; -import org.hibernate.validator.cfg.ConstraintMapping; import org.hibernate.validator.constraints.Email; /** * @author Hardy Ferentschik */ public class EmailDef extends ConstraintDef { - public EmailDef(Class beanType, String property, ElementType elementType, ConstraintMapping mapping) { - super( beanType, Email.class, property, elementType, mapping ); + + public EmailDef() { + super( Email.class ); } } diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/FutureDef.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/FutureDef.java index cb8f7da537..53df19e9f9 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/FutureDef.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/FutureDef.java @@ -16,17 +16,16 @@ */ package org.hibernate.validator.cfg.defs; -import java.lang.annotation.ElementType; import javax.validation.constraints.Future; import org.hibernate.validator.cfg.ConstraintDef; -import org.hibernate.validator.cfg.ConstraintMapping; /** * @author Hardy Ferentschik */ public class FutureDef extends ConstraintDef { - public FutureDef(Class beanType, String property, ElementType elementType, ConstraintMapping mapping) { - super( beanType, Future.class, property, elementType, mapping ); + + public FutureDef() { + super( Future.class ); } } diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/LengthDef.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/LengthDef.java index 2dc6da7764..707ad19dd1 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/LengthDef.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/LengthDef.java @@ -17,10 +17,7 @@ package org.hibernate.validator.cfg.defs; -import java.lang.annotation.ElementType; - import org.hibernate.validator.cfg.ConstraintDef; -import org.hibernate.validator.cfg.ConstraintMapping; import org.hibernate.validator.constraints.Length; @@ -29,8 +26,8 @@ */ public class LengthDef extends ConstraintDef { - public LengthDef(Class beanType, String property, ElementType elementType, ConstraintMapping mapping) { - super( beanType, Length.class, property, elementType, mapping ); + public LengthDef() { + super( Length.class ); } public LengthDef min(int min) { diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/MaxDef.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/MaxDef.java index 7747a3e07c..1140a0b9ae 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/MaxDef.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/MaxDef.java @@ -16,20 +16,17 @@ */ package org.hibernate.validator.cfg.defs; -import java.lang.annotation.ElementType; - import javax.validation.constraints.Max; import org.hibernate.validator.cfg.ConstraintDef; -import org.hibernate.validator.cfg.ConstraintMapping; /** * @author Hardy Ferentschik */ public class MaxDef extends ConstraintDef { - public MaxDef(Class beanType, String property, ElementType elementType, ConstraintMapping mapping) { - super( beanType, Max.class, property, elementType, mapping ); + public MaxDef() { + super( Max.class ); } public MaxDef value(long max) { diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/MinDef.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/MinDef.java index f5d795a37f..fbe643b2a8 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/MinDef.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/MinDef.java @@ -16,20 +16,17 @@ */ package org.hibernate.validator.cfg.defs; -import java.lang.annotation.ElementType; - import javax.validation.constraints.Min; import org.hibernate.validator.cfg.ConstraintDef; -import org.hibernate.validator.cfg.ConstraintMapping; /** * @author Hardy Ferentschik */ public class MinDef extends ConstraintDef { - public MinDef(Class beanType, String property, ElementType elementType, ConstraintMapping mapping) { - super( beanType, Min.class, property, elementType, mapping ); + public MinDef() { + super( Min.class ); } public MinDef value(long min) { diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/NotBlankDef.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/NotBlankDef.java index a4d324eae4..3c06f10e7f 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/NotBlankDef.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/NotBlankDef.java @@ -16,17 +16,14 @@ */ package org.hibernate.validator.cfg.defs; -import java.lang.annotation.ElementType; - import org.hibernate.validator.cfg.ConstraintDef; -import org.hibernate.validator.cfg.ConstraintMapping; import org.hibernate.validator.constraints.NotBlank; /** * @author Hardy Ferentschik */ public class NotBlankDef extends ConstraintDef { - public NotBlankDef(Class beanType, String property, ElementType elementType, ConstraintMapping mapping) { - super( beanType, NotBlank.class, property, elementType, mapping ); + public NotBlankDef() { + super( NotBlank.class ); } } diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/NotEmptyDef.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/NotEmptyDef.java index 253084495e..1f0fe92888 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/NotEmptyDef.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/NotEmptyDef.java @@ -16,17 +16,15 @@ */ package org.hibernate.validator.cfg.defs; -import java.lang.annotation.ElementType; - import org.hibernate.validator.cfg.ConstraintDef; -import org.hibernate.validator.cfg.ConstraintMapping; import org.hibernate.validator.constraints.NotEmpty; /** * @author Hardy Ferentschik */ public class NotEmptyDef extends ConstraintDef { - public NotEmptyDef(Class beanType, String property, ElementType elementType, ConstraintMapping mapping) { - super( beanType, NotEmpty.class, property, elementType, mapping ); + + public NotEmptyDef() { + super( NotEmpty.class ); } } diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/NotNullDef.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/NotNullDef.java index c5f9c8d699..5090dd4763 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/NotNullDef.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/NotNullDef.java @@ -16,17 +16,17 @@ */ package org.hibernate.validator.cfg.defs; -import java.lang.annotation.ElementType; import javax.validation.constraints.NotNull; import org.hibernate.validator.cfg.ConstraintDef; -import org.hibernate.validator.cfg.ConstraintMapping; /** * @author Hardy Ferentschik */ public class NotNullDef extends ConstraintDef { - public NotNullDef(Class beanType, String property, ElementType elementType, ConstraintMapping mapping) { - super( beanType, NotNull.class, property, elementType, mapping ); + + public NotNullDef() { + super( NotNull.class ); } + } diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/NullDef.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/NullDef.java index 0bbfa70334..08e5289823 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/NullDef.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/NullDef.java @@ -16,17 +16,16 @@ */ package org.hibernate.validator.cfg.defs; -import java.lang.annotation.ElementType; import javax.validation.constraints.Null; import org.hibernate.validator.cfg.ConstraintDef; -import org.hibernate.validator.cfg.ConstraintMapping; /** * @author Hardy Ferentschik */ public class NullDef extends ConstraintDef { - public NullDef(Class beanType, String property, ElementType elementType, ConstraintMapping mapping) { - super( beanType, Null.class, property, elementType, mapping ); + + public NullDef() { + super( Null.class ); } } diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/PastDef.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/PastDef.java index a741f92403..38490c3191 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/PastDef.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/PastDef.java @@ -16,17 +16,16 @@ */ package org.hibernate.validator.cfg.defs; -import java.lang.annotation.ElementType; import javax.validation.constraints.Past; import org.hibernate.validator.cfg.ConstraintDef; -import org.hibernate.validator.cfg.ConstraintMapping; /** * @author Hardy Ferentschik */ public class PastDef extends ConstraintDef { - public PastDef(Class beanType, String property, ElementType elementType, ConstraintMapping mapping) { - super( beanType, Past.class, property, elementType, mapping ); + + public PastDef() { + super( Past.class ); } } diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/PatternDef.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/PatternDef.java index 7e9966ae00..e02e7c7d4a 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/PatternDef.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/PatternDef.java @@ -16,12 +16,9 @@ */ package org.hibernate.validator.cfg.defs; -import java.lang.annotation.ElementType; - import javax.validation.constraints.Pattern; import org.hibernate.validator.cfg.ConstraintDef; -import org.hibernate.validator.cfg.ConstraintMapping; /** @@ -29,8 +26,8 @@ */ public class PatternDef extends ConstraintDef { - public PatternDef(Class beanType, String property, ElementType elementType, ConstraintMapping mapping) { - super( beanType, Pattern.class, property, elementType, mapping ); + public PatternDef() { + super( Pattern.class ); } public PatternDef flags(Pattern.Flag[] flags) { diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/RangeDef.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/RangeDef.java index b1f2500337..d7d6ee8228 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/RangeDef.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/RangeDef.java @@ -16,10 +16,7 @@ */ package org.hibernate.validator.cfg.defs; -import java.lang.annotation.ElementType; - import org.hibernate.validator.cfg.ConstraintDef; -import org.hibernate.validator.cfg.ConstraintMapping; import org.hibernate.validator.constraints.Range; /** @@ -27,8 +24,8 @@ */ public class RangeDef extends ConstraintDef { - public RangeDef(Class beanType, String property, ElementType elementType, ConstraintMapping mapping) { - super( beanType, Range.class, property, elementType, mapping ); + public RangeDef() { + super( Range.class ); } public RangeDef min(long min) { diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/ScriptAssertDef.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/ScriptAssertDef.java index 21611071cb..4d6706bafd 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/ScriptAssertDef.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/ScriptAssertDef.java @@ -16,10 +16,7 @@ */ package org.hibernate.validator.cfg.defs; -import java.lang.annotation.ElementType; - import org.hibernate.validator.cfg.ConstraintDef; -import org.hibernate.validator.cfg.ConstraintMapping; import org.hibernate.validator.constraints.ScriptAssert; /** @@ -27,8 +24,8 @@ */ public class ScriptAssertDef extends ConstraintDef { - public ScriptAssertDef(Class beanType, String property, ElementType elementType, ConstraintMapping mapping) { - super( beanType, ScriptAssert.class, property, elementType, mapping ); + public ScriptAssertDef() { + super( ScriptAssert.class ); } public ScriptAssertDef lang(String lang) { diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/SizeDef.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/SizeDef.java index 5a82e16682..87d5d0018b 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/SizeDef.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/SizeDef.java @@ -17,20 +17,17 @@ package org.hibernate.validator.cfg.defs; -import java.lang.annotation.ElementType; - import javax.validation.constraints.Size; import org.hibernate.validator.cfg.ConstraintDef; -import org.hibernate.validator.cfg.ConstraintMapping; /** * @author Hardy Ferentschik */ public class SizeDef extends ConstraintDef { - public SizeDef(Class beanType, String property, ElementType elementType, ConstraintMapping mapping) { - super( beanType, Size.class, property, elementType, mapping ); + public SizeDef() { + super( Size.class ); } public SizeDef min(int min) { diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/URLDef.java b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/URLDef.java index 661ef8ead2..62ef4e4638 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/URLDef.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/URLDef.java @@ -15,11 +15,9 @@ */ package org.hibernate.validator.cfg.defs; -import java.lang.annotation.ElementType; import javax.validation.constraints.Pattern; import org.hibernate.validator.cfg.ConstraintDef; -import org.hibernate.validator.cfg.ConstraintMapping; import org.hibernate.validator.constraints.URL; /** @@ -27,8 +25,8 @@ */ public class URLDef extends ConstraintDef { - public URLDef(Class beanType, String property, ElementType elementType, ConstraintMapping mapping) { - super( beanType, URL.class, property, elementType, mapping ); + public URLDef() { + super( URL.class ); } public URLDef protocol(String protocol) { diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/package.html b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/package.html index 4b33510e88..d4ddb0e65f 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/package.html +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/defs/package.html @@ -19,6 +19,8 @@ -Helper classes for programmatic constraint definition API. +

Constraint definition classes for programmatic constraint +definition API.

+

This package is part of the public Hibernate Validator API.

diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/package.html b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/package.html index e92a4598d9..6f75e7694c 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/cfg/package.html +++ b/hibernate-validator/src/main/java/org/hibernate/validator/cfg/package.html @@ -20,6 +20,7 @@ -Programmatic constraint definition API. +

Entry point for the programmatic constraint definition API.

+

This package is part of the public Hibernate Validator API.

diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/SizeValidatorForCollection.java b/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/SizeValidatorForCollection.java index 4e1213c9b0..e2f70975e2 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/SizeValidatorForCollection.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/SizeValidatorForCollection.java @@ -26,7 +26,7 @@ * * @author Hardy Ferentschik */ -public class SizeValidatorForCollection implements ConstraintValidator { +public class SizeValidatorForCollection implements ConstraintValidator> { private int min; private int max; @@ -46,7 +46,7 @@ public void initialize(Size parameters) { * collection is between the specified min and max values (inclusive), * false otherwise. */ - public boolean isValid(Collection collection, ConstraintValidatorContext constraintValidatorContext) { + public boolean isValid(Collection collection, ConstraintValidatorContext constraintValidatorContext) { if ( collection == null ) { return true; } diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/SizeValidatorForMap.java b/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/SizeValidatorForMap.java index 03b5fe41af..b23b985762 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/SizeValidatorForMap.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/SizeValidatorForMap.java @@ -26,7 +26,7 @@ * * @author Hardy Ferentschik */ -public class SizeValidatorForMap implements ConstraintValidator { +public class SizeValidatorForMap implements ConstraintValidator> { private int min; private int max; @@ -46,7 +46,7 @@ public void initialize(Size parameters) { * is between the specified min and max values (inclusive), * false otherwise. */ - public boolean isValid(Map map, ConstraintValidatorContext constraintValidatorContext) { + public boolean isValid(Map map, ConstraintValidatorContext constraintValidatorContext) { if ( map == null ) { return true; } diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/package.html b/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/package.html index a1675bdca6..cfda056107 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/package.html +++ b/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/package.html @@ -20,6 +20,7 @@ -Implementations of the Bean Validation built-in as well as Hibernate Validator specific constraints. +

Implementations of the Bean Validation built-in as well as +Hibernate Validator specific constraints.

diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/constraints/package.html b/hibernate-validator/src/main/java/org/hibernate/validator/constraints/package.html index abb76ba1c4..9af564089e 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/constraints/package.html +++ b/hibernate-validator/src/main/java/org/hibernate/validator/constraints/package.html @@ -20,7 +20,7 @@ -Hibernate Validator specific constraints. Classes in this package are part of the public Hibernate -Validator API. +

Hibernate Validator specific constraints.

+

This package is part of the public Hibernate Validator API.

diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/engine/ValidatorFactoryImpl.java b/hibernate-validator/src/main/java/org/hibernate/validator/engine/ValidatorFactoryImpl.java index 805a1628cd..2c972f4ac3 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/engine/ValidatorFactoryImpl.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/engine/ValidatorFactoryImpl.java @@ -18,11 +18,13 @@ import java.io.InputStream; import java.lang.annotation.Annotation; +import java.lang.annotation.ElementType; import java.lang.reflect.Member; -import java.util.ArrayList; -import java.util.HashSet; +import java.lang.reflect.Method; +import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import javax.validation.ConstraintValidatorFactory; import javax.validation.MessageInterpolator; @@ -34,9 +36,10 @@ import org.hibernate.validator.HibernateValidatorConfiguration; import org.hibernate.validator.HibernateValidatorContext; import org.hibernate.validator.HibernateValidatorFactory; -import org.hibernate.validator.cfg.CascadeDef; -import org.hibernate.validator.cfg.ConstraintDefAccessor; import org.hibernate.validator.cfg.ConstraintMapping; +import org.hibernate.validator.cfg.context.impl.ConfiguredConstraint; +import org.hibernate.validator.cfg.context.impl.ConstraintMappingContext; +import org.hibernate.validator.metadata.AggregatedMethodMetaData; import org.hibernate.validator.metadata.AnnotationIgnores; import org.hibernate.validator.metadata.BeanMetaConstraint; import org.hibernate.validator.metadata.BeanMetaDataCache; @@ -45,12 +48,22 @@ import org.hibernate.validator.metadata.ConstraintHelper; import org.hibernate.validator.metadata.ConstraintOrigin; import org.hibernate.validator.metadata.MetaConstraint; +import org.hibernate.validator.metadata.MethodMetaConstraint; +import org.hibernate.validator.metadata.MethodMetaData; +import org.hibernate.validator.metadata.ParameterMetaData; +import org.hibernate.validator.metadata.location.BeanConstraintLocation; +import org.hibernate.validator.metadata.location.MethodConstraintLocation; +import org.hibernate.validator.util.CollectionHelper.Partitioner; import org.hibernate.validator.util.ReflectionHelper; import org.hibernate.validator.util.annotationfactory.AnnotationDescriptor; import org.hibernate.validator.util.annotationfactory.AnnotationFactory; import org.hibernate.validator.xml.XmlMappingParser; +import static org.hibernate.validator.metadata.BeanMetaDataImpl.DEFAULT_PARAMETER_NAME_PREFIX; +import static org.hibernate.validator.util.CollectionHelper.newArrayList; import static org.hibernate.validator.util.CollectionHelper.newHashMap; +import static org.hibernate.validator.util.CollectionHelper.newHashSet; +import static org.hibernate.validator.util.CollectionHelper.partition; /** * Factory returning initialized {@code Validator} instances. This is Hibernate Validator's default @@ -144,11 +157,16 @@ public HibernateValidatorContext usingContext() { * @param mapping The constraint configuration created via the programmatic API. */ private void initProgrammaticConfiguration(ConstraintMapping mapping) { - - final Map, List>> constraintsByType = mapping.getConstraintConfig(); - final Map, List> cascadeConfigByType = mapping.getCascadeConfig(); - - for ( Class clazz : mapping.getConfiguredClasses() ) { + + ConstraintMappingContext context = ConstraintMappingContext.getFromMapping(mapping); + + final Map, List>> constraintsByType = context.getConstraintConfig(); + final Map, List>> methodConstraintsByType = context + .getMethodConstraintConfig(); + final Map, List> cascadeConfigByType = context.getCascadeConfig(); + final Map, List> methodCascadeConfigByType = context.getMethodCascadeConfig(); + + for ( Class clazz : context.getConfiguredClasses() ) { @SuppressWarnings("unchecked") Class beanClass = (Class) clazz; @@ -157,12 +175,15 @@ private void initProgrammaticConfiguration(ConstraintMapping mapping) { List> classes = ReflectionHelper.computeClassHierarchy( beanClass, true ); Map, List>> constraints = newHashMap(); - Set cascadedMembers = new HashSet(); + Set builders = newHashSet(); + Set cascadedMembers = newHashSet(); for ( Class classInHierarchy : classes ) { // if the programmatic config contains constraints for the class in the hierarchy create equivalent meta constraints - List> constraintsOfType = constraintsByType.get( classInHierarchy ); + List> constraintsOfType = constraintsByType.get( + classInHierarchy + ); if ( constraintsOfType != null ) { addProgrammaticConfiguredConstraints( constraintsOfType, @@ -172,19 +193,42 @@ private void initProgrammaticConfiguration(ConstraintMapping mapping) { ); } + // retrieve the method constraints + List> methodConstraintsOfType = methodConstraintsByType + .get( classInHierarchy ); + if ( methodConstraintsOfType != null ) { + addProgrammaticConfiguredMethodConstraint( + methodConstraintsOfType, beanClass, classInHierarchy, builders + ); + } + // retrieve the cascading members of the current class if applicable - List cascadesOfType = cascadeConfigByType.get( classInHierarchy ); + List cascadesOfType = cascadeConfigByType.get( classInHierarchy ); if ( cascadesOfType != null ) { addProgrammaticConfiguredCascade( cascadesOfType, cascadedMembers ); } + + // retrieve the cascading method return value and method parameter + List methodCascadesOfType = methodCascadeConfigByType.get( classInHierarchy ); + if ( methodCascadesOfType != null ) { + addProgrammaticConfiguredMethodCascade( methodCascadesOfType, builders ); + } + } + + // build the programmatic configured method metaData + Set methodMetaDataMap = newHashSet(); + for ( AggregatedMethodMetaData.Builder oneBuilder : builders ) { + methodMetaDataMap.add( oneBuilder.build() ); } + // create the bean metadata with the programmatic configured constraints and cascade BeanMetaDataImpl metaData = new BeanMetaDataImpl( beanClass, constraintHelper, - mapping.getDefaultSequence( beanClass ), - mapping.getDefaultGroupSequenceProvider( beanClass ), + context.getDefaultSequence( beanClass ), + context.getDefaultGroupSequenceProvider( beanClass ), constraints, + methodMetaDataMap, cascadedMembers, new AnnotationIgnores(), beanMetaDataCache @@ -207,7 +251,7 @@ private void initXmlConfiguration(Set mappingStreams) { List> classes = ReflectionHelper.computeClassHierarchy( beanClass, true ); Map, List>> constraints = newHashMap(); - Set cascadedMembers = new HashSet(); + Set cascadedMembers = newHashSet(); // we need to collect all constraints which apply for a single class. Due to constraint inheritance // some constraints might be configured in super classes or interfaces. The xml configuration does not // imply any order so we have to check whether any of the super classes or interfaces of a given bean has @@ -225,6 +269,7 @@ private void initXmlConfiguration(Set mappingStreams) { mappingParser.getDefaultSequenceForClass( beanClass ), null, constraints, + Collections.emptySet(), cascadedMembers, annotationIgnores, beanMetaDataCache @@ -238,7 +283,7 @@ private void initXmlConfiguration(Set mappingStreams) { private void addXmlConfiguredConstraints(XmlMappingParser mappingParser, Class rootClass, Class hierarchyClass, Map, List>> constraints) { - for ( MetaConstraint constraint : mappingParser.getConstraintsForClass( hierarchyClass ) ) { + for ( BeanMetaConstraint constraint : mappingParser.getConstraintsForClass( hierarchyClass ) ) { ConstraintOrigin definedIn = definedIn( rootClass, hierarchyClass ); ConstraintDescriptorImpl
descriptor = new ConstraintDescriptorImpl( @@ -248,12 +293,10 @@ private void addXmlConfiguredConstraints(XmlMappingPar definedIn ); - //TODO GM: avoid this cast - BeanMetaConstraint asBeanMetaConstraint = (BeanMetaConstraint) constraint; BeanMetaConstraint newMetaConstraint = new BeanMetaConstraint( descriptor, - asBeanMetaConstraint.getLocation().getBeanClass(), - asBeanMetaConstraint.getLocation().getMember() + constraint.getLocation().getBeanClass(), + constraint.getLocation().getMember() ); addConstraintToMap( hierarchyClass, newMetaConstraint, constraints ); @@ -261,36 +304,31 @@ private void addXmlConfiguredConstraints(XmlMappingPar } @SuppressWarnings("unchecked") - private void addProgrammaticConfiguredConstraints(List> definitions, + private void addProgrammaticConfiguredConstraints(List> definitions, Class rootClass, Class hierarchyClass, Map, List>> constraints) { - for ( ConstraintDefAccessor config : definitions ) { + for ( ConfiguredConstraint config : definitions ) { A annotation = (A) createAnnotationProxy( config ); ConstraintOrigin definedIn = definedIn( rootClass, hierarchyClass ); ConstraintDescriptorImpl constraintDescriptor = new ConstraintDescriptorImpl( - annotation, constraintHelper, config.getElementType(), definedIn + annotation, constraintHelper, config.getLocation().getElementType(), definedIn ); - Member member = null; - if ( config.getProperty().length() != 0 ) { - member = ReflectionHelper.getMember( - config.getBeanType(), config.getProperty(), config.getElementType() - ); - } + Member member = config.getLocation().getMember(); BeanMetaConstraint metaConstraint = new BeanMetaConstraint( - constraintDescriptor, config.getBeanType(), member + constraintDescriptor, config.getLocation().getBeanClass(), member ); addConstraintToMap( hierarchyClass, metaConstraint, constraints ); } } - private > void addConstraintToMap(Class hierarchyClass, M constraint, Map, List> constraints) { + private > void addConstraintToMap(Class hierarchyClass, M constraint, Map, List> constraints) { List constraintList = constraints.get( hierarchyClass ); if ( constraintList == null ) { - constraintList = new ArrayList(); + constraintList = newArrayList(); constraints.put( hierarchyClass, constraintList ); } @@ -305,17 +343,139 @@ private void addXmlCascadedMember(XmlMappingParser mappingParser, } } - private void addProgrammaticConfiguredCascade(List cascades, + private void addProgrammaticConfiguredCascade(List cascades, Set cascadedMembers) { - for ( CascadeDef cascade : cascades ) { - Member m = ReflectionHelper.getMember( - cascade.getBeanType(), cascade.getProperty(), cascade.getElementType() + for ( BeanConstraintLocation cascade : cascades ) { + cascadedMembers.add( cascade.getMember() ); + } + } + + private void addProgrammaticConfiguredMethodConstraint(List> methodConstraints, Class rootClass, Class hierarchyClass, Set builders) { + + Map>> constraintsByMethod = partition( + methodConstraints, + byMethod() + ); + + for ( Entry>> oneMethod : constraintsByMethod.entrySet() ) { + + MethodMetaData methodMetaData = createMethodMetaData( + oneMethod.getKey(), oneMethod.getValue(), rootClass, hierarchyClass ); - cascadedMembers.add( m ); + addMetaDataToBuilder( methodMetaData, builders ); + } + } + + private void addProgrammaticConfiguredMethodCascade(List methodCascades, Set builders) { + for ( MethodConstraintLocation cascadeDef : methodCascades ) { + MethodMetaData methodMetaData = createMethodMetaData( cascadeDef ); + addMetaDataToBuilder( methodMetaData, builders ); } } + private MethodMetaData createMethodMetaData(MethodConstraintLocation cascadeDef) { + Method method = cascadeDef.getMethod(); + List parameterMetaDatas = newArrayList(); + List> parameterConstraints = Collections.emptyList(); + List> returnConstraints = Collections.emptyList(); + + int i = 0; + for ( Class parameterType : method.getParameterTypes() ) { + String parameterName = DEFAULT_PARAMETER_NAME_PREFIX + i; + boolean isCascading = Integer.valueOf( i ).equals( cascadeDef.getParameterIndex() ); + + parameterMetaDatas.add( + new ParameterMetaData( + i, + parameterType, + parameterName, + parameterConstraints, + isCascading + ) + ); + + i++; + } + + boolean isCascading = cascadeDef.getParameterIndex() == null; + return new MethodMetaData( method, parameterMetaDatas, returnConstraints, isCascading ); + } + + private MethodMetaData createMethodMetaData(Method method, List> constraints, Class rootClass, Class hierarchyClass) { + + Map>> constraintsByIndex = partition( + constraints, byParameterIndex() + ); + + List allParameterMetaData = newArrayList( method.getParameterTypes().length ); + + for ( int i = 0; i < method.getParameterTypes().length; i++ ) { + + allParameterMetaData.add( + new ParameterMetaData( + i, + method.getParameterTypes()[i], + DEFAULT_PARAMETER_NAME_PREFIX + i, + convertToMethodConstraints( + constraintsByIndex.get( i ), rootClass, hierarchyClass + ), + false + ) + ); + } + + List> returnValueConstraints = convertToMethodConstraints( + constraintsByIndex.get( null ), rootClass, hierarchyClass + ); + + return new MethodMetaData( + method, allParameterMetaData, returnValueConstraints, false + ); + } + + private List> convertToMethodConstraints( + List> configuredConstraints, + Class rootClass, + Class hierarchyClass) { + + if ( configuredConstraints == null ) { + configuredConstraints = Collections.emptyList(); + } + + List> theValue = newArrayList(); + + for ( ConfiguredConstraint oneConfiguredConstraint : configuredConstraints ) { + theValue.add( convertToMethodConstraint( oneConfiguredConstraint, rootClass, hierarchyClass ) ); + } + + return theValue; + } + + private MethodMetaConstraint convertToMethodConstraint(ConfiguredConstraint configuredConstraint, Class rootClass, Class hierarchyClass) { + + A annotation = createAnnotationProxy( configuredConstraint ); + ConstraintOrigin definedIn = definedIn( rootClass, hierarchyClass ); + ConstraintDescriptorImpl constraintDescriptor = new ConstraintDescriptorImpl( + annotation, constraintHelper, ElementType.PARAMETER, definedIn + ); + + return new MethodMetaConstraint( + constraintDescriptor, configuredConstraint.getLocation() + ); + } + + private void addMetaDataToBuilder(MethodMetaData methodMetaData, Set builders) { + for ( AggregatedMethodMetaData.Builder OneBuilder : builders ) { + if ( OneBuilder.accepts( methodMetaData ) ) { + OneBuilder.addMetaData( methodMetaData ); + return; + } + } + AggregatedMethodMetaData.Builder builder = new AggregatedMethodMetaData.Builder( methodMetaData ); + builders.add( builder ); + } + /** * @param rootClass The root class. That is the class for which we currently create a {@code BeanMetaData} * @param hierarchyClass The class on which the current constraint is defined on @@ -332,7 +492,7 @@ private ConstraintOrigin definedIn(Class rootClass, Class hierarchyClass) } } - private A createAnnotationProxy(ConstraintDefAccessor config) { + private A createAnnotationProxy(ConfiguredConstraint config) { Class constraintType = config.getConstraintType(); AnnotationDescriptor annotationDescriptor = new AnnotationDescriptor( constraintType ); for ( Map.Entry parameter : config.getParameters().entrySet() ) { @@ -366,4 +526,24 @@ private boolean checkPropertiesForFailFast(ConfigurationState configurationState } return failFast; } + + private Partitioner> byMethod() { + + return new Partitioner>() { + public Method getPartition(ConfiguredConstraint v) { + return v.getLocation().getMethod(); + } + }; + } + + private Partitioner> byParameterIndex() { + return new Partitioner>() { + + public Integer getPartition( + ConfiguredConstraint v) { + + return v.getLocation().getParameterIndex(); + } + }; + } } diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/engine/ValidatorImpl.java b/hibernate-validator/src/main/java/org/hibernate/validator/engine/ValidatorImpl.java index fb2a286f2d..0e75de90e7 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/engine/ValidatorImpl.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/engine/ValidatorImpl.java @@ -16,13 +16,11 @@ */ package org.hibernate.validator.engine; -import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Type; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; @@ -373,7 +371,7 @@ private > void validateConstraintsForD BeanMetaData hostingBeanMetaData = (BeanMetaData) getBeanMetaData( clazz ); boolean defaultGroupSequenceIsRedefined = hostingBeanMetaData.defaultGroupSequenceIsRedefined(); List> defaultGroupSequence = hostingBeanMetaData.getDefaultGroupSequence( valueContext.getCurrentBean() ); - Set> metaConstraints = hostingBeanMetaData.getDirectMetaConstraints(); + Set> metaConstraints = hostingBeanMetaData.getDirectMetaConstraints(); // if the current class redefined the default group sequence, this sequence has to be applied to all the class hierarchy. if ( defaultGroupSequenceIsRedefined ) { @@ -384,7 +382,7 @@ private > void validateConstraintsForD for ( Class defaultSequenceMember : defaultGroupSequence ) { valueContext.setCurrentGroup( defaultSequenceMember ); boolean validationSuccessful = true; - for ( BeanMetaConstraint metaConstraint : metaConstraints ) { + for ( BeanMetaConstraint 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().getBeanClass(); @@ -425,7 +423,7 @@ private > void validateConstraintsForD private void validateConstraintsForNonDefaultGroup(ValidationContext validationContext, ValueContext valueContext) { BeanMetaData beanMetaData = getBeanMetaData( valueContext.getCurrentBeanType() ); PathImpl currentPath = valueContext.getPropertyPath(); - for ( BeanMetaConstraint metaConstraint : beanMetaData.getMetaConstraints() ) { + for ( BeanMetaConstraint metaConstraint : beanMetaData.getMetaConstraints() ) { validateConstraint( validationContext, valueContext, metaConstraint ); if ( validationContext.shouldFailFast() ) { return; @@ -545,7 +543,7 @@ else if ( TypeUtils.isArray( type ) ) { valueContext.markCurrentPropertyAsIterable(); } else { - List list = new ArrayList(); + List list = newArrayList(); list.add( value ); iter = list.iterator(); } @@ -798,7 +796,7 @@ private int validatePropertyForDefaultGroup(ValueContext valueCo for ( Class clazz : beanMetaData.getClassHierarchy() ) { BeanMetaData hostingBeanMetaData = (BeanMetaData) getBeanMetaData( clazz ); boolean defaultGroupSequenceIsRedefined = hostingBeanMetaData.defaultGroupSequenceIsRedefined(); - Set> metaConstraints = hostingBeanMetaData.getDirectMetaConstraints(); + Set> metaConstraints = hostingBeanMetaData.getDirectMetaConstraints(); List> defaultGroupSequence = hostingBeanMetaData.getDefaultGroupSequence( valueContext.getCurrentBean() ); if ( defaultGroupSequenceIsRedefined ) { @@ -993,7 +991,7 @@ private int validateParameterForGroup(MethodValidationContext valid int numberOfViolationsBefore = validationContext.getFailingConstraints().size(); - for ( MetaConstraint metaConstraint : parameterMetaData ) { + for ( MetaConstraint metaConstraint : parameterMetaData ) { //ignore constraints not part of the evaluated group if ( !metaConstraint.getGroupList().contains( valueContext.getCurrentGroup() ) ) { @@ -1114,7 +1112,7 @@ private int validateReturnValueForGroup(MethodValidationContext valida int numberOfViolationsBefore = validationContext.getFailingConstraints().size(); - for ( MetaConstraint metaConstraint : methodMetaData ) { + for ( MetaConstraint metaConstraint : methodMetaData ) { if ( !metaConstraint.getGroupList().contains( valueContext.getCurrentGroup() ) ) { continue; @@ -1158,7 +1156,7 @@ private ValueContext collectMetaConstraintsForPath(Class claz if ( !propertyIter.hasNext() ) { for ( Class hierarchyClass : metaData.getClassHierarchy() ) { metaData = getBeanMetaData( hierarchyClass ); - for ( BeanMetaConstraint constraint : metaData.getDirectMetaConstraints() ) { + for ( BeanMetaConstraint constraint : metaData.getDirectMetaConstraints() ) { if ( elem.getName() != null && elem.getName() .equals( constraint.getLocation().getPropertyName() ) ) { metaConstraintsList.add( constraint ); diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/engine/groups/package.html b/hibernate-validator/src/main/java/org/hibernate/validator/engine/groups/package.html index d4c403bbbc..4956af34a4 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/engine/groups/package.html +++ b/hibernate-validator/src/main/java/org/hibernate/validator/engine/groups/package.html @@ -20,6 +20,6 @@ -Helper classes for the processing of groups. +

Helper classes for the processing of groups.

diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/engine/package.html b/hibernate-validator/src/main/java/org/hibernate/validator/engine/package.html index 83fdcd7786..4940d4eb99 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/engine/package.html +++ b/hibernate-validator/src/main/java/org/hibernate/validator/engine/package.html @@ -20,6 +20,6 @@ -Implementations for the core interfaces of JSR-303. +

Implementations for the core interfaces of JSR-303.

diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/engine/resolver/package.html b/hibernate-validator/src/main/java/org/hibernate/validator/engine/resolver/package.html index 13f1a882df..339917803f 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/engine/resolver/package.html +++ b/hibernate-validator/src/main/java/org/hibernate/validator/engine/resolver/package.html @@ -20,6 +20,6 @@ -Various implementations of the TraversableResolver interface. +

Various implementations of the TraversableResolver interface.

diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/group/package.html b/hibernate-validator/src/main/java/org/hibernate/validator/group/package.html index a6b682d47c..5d6cccfa31 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/group/package.html +++ b/hibernate-validator/src/main/java/org/hibernate/validator/group/package.html @@ -19,7 +19,7 @@ -This package provides support for dynamic default group sequence definition. -This package is part of the public Hibernate Validator API. +

This package provides support for dynamic default group sequence definition.

+

This package is part of the public Hibernate Validator API.

diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/messageinterpolation/package.html b/hibernate-validator/src/main/java/org/hibernate/validator/messageinterpolation/package.html index 8eef4fbb53..dd78628c7e 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/messageinterpolation/package.html +++ b/hibernate-validator/src/main/java/org/hibernate/validator/messageinterpolation/package.html @@ -20,7 +20,8 @@ -Implementations of the MessageInterpolator interface in particular ResourceBundleMessageInterpolator which can be used -by custom implementations of the interface for delegation. Classes in this package are part of the public Hibernate Validator API. +

Implementations of the MessageInterpolator interface in particular ResourceBundleMessageInterpolator which can be used +by custom implementations of the interface for delegation.

+

This package is part of the public Hibernate Validator API.

diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/AggregatedMethodMetaData.java b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/AggregatedMethodMetaData.java index 9b32440fe1..d546b557d6 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/AggregatedMethodMetaData.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/AggregatedMethodMetaData.java @@ -16,7 +16,6 @@ */ package org.hibernate.validator.metadata; -import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.Collection; import java.util.Collections; @@ -46,7 +45,7 @@ * * @author Gunnar Morling */ -public class AggregatedMethodMetaData implements Iterable> { +public class AggregatedMethodMetaData implements Iterable> { private final Method method; @@ -56,7 +55,7 @@ public class AggregatedMethodMetaData implements Iterable> returnValueConstraints; + private final List> returnValueConstraints; private final List parameterMetaData; @@ -72,7 +71,7 @@ public class AggregatedMethodMetaData implements Iterable> returnValueConstraints, + List> returnValueConstraints, List parameterMetaData, ConstraintDeclarationException parameterConstraintDeclarationException) { @@ -90,6 +89,7 @@ private AggregatedMethodMetaData( * Creates new {@link AggregatedMethodMetaData} instances. * * @author Gunnar Morling + * @author Kevin Pollet - SERLI - (kevin.pollet@serli.com) */ public static class Builder { @@ -139,8 +139,14 @@ public boolean accepts(MethodMetaData metaData) { */ public void addMetaData(MethodMetaData metaData) { - metaDataByDefiningType.put( metaData.getMethod().getDeclaringClass(), metaData ); + MethodMetaData existingMetaData = + metaDataByDefiningType.get( metaData.getMethod().getDeclaringClass() ); + + if ( existingMetaData != null ) { + metaData = existingMetaData.merge( metaData ); + } + metaDataByDefiningType.put( metaData.getMethod().getDeclaringClass(), metaData ); isCascading = isCascading || metaData.isCascading(); isConstrained = isConstrained || metaData.isConstrained(); } @@ -163,12 +169,12 @@ this, collectReturnValueConstraints(), findParameterMetaData(), checkParameterCo * * @return A list with all return value constraints. */ - private List> collectReturnValueConstraints() { + private List> collectReturnValueConstraints() { - List> theValue = newArrayList(); + List> theValue = newArrayList(); for ( MethodMetaData oneMethodMetaData : metaDataByDefiningType.values() ) { - for ( BeanMetaConstraint oneConstraint : oneMethodMetaData ) { + for ( MethodMetaConstraint oneConstraint : oneMethodMetaData ) { theValue.add( oneConstraint ); } } @@ -258,6 +264,7 @@ private Set getMethodsWithParameterConstraints(Iterable getAllMethodMetaData() { /** * An iterator with the return value constraints of the represented method. */ - public Iterator> iterator() { + public Iterator> iterator() { return returnValueConstraints.iterator(); } diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/BeanMetaData.java b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/BeanMetaData.java index ed12be83cb..32e78bedad 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/BeanMetaData.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/BeanMetaData.java @@ -16,7 +16,6 @@ */ package org.hibernate.validator.metadata; -import java.lang.annotation.Annotation; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.util.List; @@ -77,14 +76,14 @@ public interface BeanMetaData { * @return A set of {@code MetaConstraint} instances encapsulating the information of all the constraints * defined on the bean. This collection includes constraints from super classes as well */ - Set> getMetaConstraints(); + Set> getMetaConstraints(); /** * @return A set of {@code MetaConstraint} instances encapsulating the information of all the constraints * defined on the bean directly (including constraints defined on implemented interfaces). It does not * contain constraints from super classes or interfaces implemented by super classes */ - Set> getDirectMetaConstraints(); + Set> getDirectMetaConstraints(); /** * Returns the constraint-related meta data for the given method of the diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/BeanMetaDataImpl.java b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/BeanMetaDataImpl.java index cd0e44e770..0b30c94741 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/BeanMetaDataImpl.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/BeanMetaDataImpl.java @@ -70,7 +70,7 @@ public final class BeanMetaDataImpl implements BeanMetaData { /** * Used as prefix for parameter names, if no explicit names are given. */ - private static final String DEFAULT_PARAMETER_NAME_PREFIX = "arg"; + public static final String DEFAULT_PARAMETER_NAME_PREFIX = "arg"; /** * The root bean class for this meta data. @@ -81,17 +81,17 @@ public final class BeanMetaDataImpl implements BeanMetaData { * Map of all direct constraints which belong to the entity {@code beanClass}. The constraints are mapped to the class * (eg super class or interface) in which they are defined. */ - private final Map, List>> metaConstraints = newHashMap(); + private final Map, List>> metaConstraints = newHashMap(); /** * Set of all constraints for this bean type (defined on any implemented interfaces or super types) */ - private final Set> allMetaConstraints; + private final Set> allMetaConstraints; /** * Set of all constraints which are directly defined on the bean or any of the directly implemented interfaces */ - private final Set> directMetaConstraints; + private final Set> directMetaConstraints; /** * The main element descriptor for {@link #beanClass}. @@ -166,6 +166,7 @@ public BeanMetaDataImpl(Class beanClass, ConstraintHelper constraintHelper, B new ArrayList>(), null, new HashMap, List>>(), + new HashSet(), new HashSet(), new AnnotationIgnores(), beanMetaDataCache @@ -181,6 +182,7 @@ public BeanMetaDataImpl(Class beanClass, ConstraintHelper constraintHelper, B * @param defaultGroupSequence programmatic/xml configured default group sequence (overrides annotations) * @param defaultGroupSequenceProvider programmatic configured default group sequence provider class (overrides annotations) * @param constraints programmatic/xml configured constraints + * @param methodMetaDatas programmatic configured method constraints * @param cascadedMembers programmatic/xml configured cascaded members * @param annotationIgnores in xml configured ignores for annotations * @param beanMetaDataCache the cache of already configured meta data instances @@ -190,6 +192,7 @@ public BeanMetaDataImpl(Class beanClass, List> defaultGroupSequence, Class> defaultGroupSequenceProvider, Map, List>> constraints, + Set methodMetaDatas, Set cascadedMembers, AnnotationIgnores annotationIgnores, BeanMetaDataCache beanMetaDataCache) { @@ -228,13 +231,13 @@ public BeanMetaDataImpl(Class beanClass, Class clazz = entry.getKey(); // will hold the method constraints (getter and non-getter) of the given class keyed by method - Map>> constraintsByMethod = newHashMap(); + Map>> constraintsByMethod = newHashMap(); for ( BeanMetaConstraint constraint : entry.getValue() ) { if ( constraint.getDescriptor().getElementType() == ElementType.METHOD ) { - List> constraintsForMethod = constraintsByMethod.get( + List> constraintsForMethod = constraintsByMethod.get( constraint.getLocation().getMember() ); if ( constraintsForMethod == null ) { @@ -243,7 +246,8 @@ public BeanMetaDataImpl(Class beanClass, (Method) constraint.getLocation().getMember(), constraintsForMethod ); } - constraintsForMethod.add( constraint ); + + constraintsForMethod.add( getAsMethodMetaConstraint( constraint ) ); } //register non-method constraints else { @@ -252,7 +256,7 @@ public BeanMetaDataImpl(Class beanClass, } // register the constraints for each method in methodMetaConstraints. Constraints at getters will also registered in metaConstraints - for ( Entry>> methodAndConstraints : constraintsByMethod + for ( Entry>> methodAndConstraints : constraintsByMethod .entrySet() ) { MethodMetaData methodMetaData = new MethodMetaData( @@ -262,15 +266,27 @@ public BeanMetaDataImpl(Class beanClass, ); addMethodMetaConstraint( clazz, methodMetaData ); } + } allMetaConstraints = buildAllConstraintSets(); directMetaConstraints = buildDirectConstraintSets(); - methodMetaData = Collections.unmodifiableMap( buildMethodMetaData() ); + // add the explicitly configured method constraints, here we need to merge the programmatic and discovered + // metadata built with the "automatic" discovering. + if ( !methodMetaDatas.isEmpty() ) { + for ( AggregatedMethodMetaData aggregatedMethodMetaData : methodMetaDatas ) { + for ( MethodMetaData methodMetaData : aggregatedMethodMetaData.getAllMethodMetaData() ) { + Method method = methodMetaData.getMethod(); + addMethodMetaConstraint( method.getDeclaringClass(), methodMetaData ); + } + } + } + + this.methodMetaData = Collections.unmodifiableMap( buildMethodMetaData() ); // reset class members we don't need any longer - methodMetaDataBuilders = null; + this.methodMetaDataBuilders = null; this.constraintHelper = null; } @@ -290,15 +306,15 @@ public Set getCascadedMembers() { return Collections.unmodifiableSet( cascadedMembers ); } - public Map, List>> getMetaConstraintsAsMap() { + public Map, List>> getMetaConstraintsAsMap() { return Collections.unmodifiableMap( metaConstraints ); } - public Set> getMetaConstraints() { + public Set> getMetaConstraints() { return allMetaConstraints; } - public Set> getDirectMetaConstraints() { + public Set> getDirectMetaConstraints() { return directMetaConstraints; } @@ -339,16 +355,16 @@ public Set getConstrainedProperties() { return Collections.unmodifiableSet( new HashSet( propertyDescriptors.values() ) ); } - private Set> buildAllConstraintSets() { - Set> constraints = newHashSet(); - for ( List> list : metaConstraints.values() ) { + private Set> buildAllConstraintSets() { + Set> constraints = newHashSet(); + for ( List> list : metaConstraints.values() ) { constraints.addAll( list ); } return Collections.unmodifiableSet( constraints ); } - private Set> buildDirectConstraintSets() { - Set> constraints = newHashSet(); + private Set> buildDirectConstraintSets() { + Set> constraints = newHashSet(); // collect all constraints directly defined in this bean if ( metaConstraints.get( beanClass ) != null ) { constraints.addAll( metaConstraints.get( beanClass ) ); @@ -420,11 +436,11 @@ else if ( group.getName().equals( Default.class.getName() ) ) { return validDefaultGroupSequence; } - private void addMetaConstraint(Class clazz, BeanMetaConstraint metaConstraint) { + private void addMetaConstraint(Class clazz, BeanMetaConstraint metaConstraint) { // first we add the meta constraint to our meta constraint map - List> constraintList; + List> constraintList; if ( !metaConstraints.containsKey( clazz ) ) { - constraintList = new ArrayList>(); + constraintList = new ArrayList>(); metaConstraints.put( clazz, constraintList ); } else { @@ -457,8 +473,9 @@ private void addMethodMetaConstraint(Class clazz, MethodMetaData methodMetaDa addToPropertyNameList( methodMetaData.getMethod() ); ReflectionHelper.setAccessibility( methodMetaData.getMethod() ); - for ( BeanMetaConstraint metaConstraint : methodMetaData ) { - addMetaConstraint( clazz, metaConstraint ); + for ( MethodMetaConstraint metaConstraint : methodMetaData ) { + + addMetaConstraint( clazz, getAsBeanMetaConstraint( metaConstraint, methodMetaData.getMethod() ) ); } if ( methodMetaData.isCascading() ) { @@ -704,8 +721,12 @@ private BeanMetaConstraint createBeanMetaConstraint(Cl return new BeanMetaConstraint( descriptor, declaringClass, m ); } - private ParameterMetaConstraint createParameterMetaConstraint(Method method, int parameterIndex, ConstraintDescriptorImpl descriptor) { - return new ParameterMetaConstraint( descriptor, method, parameterIndex ); + private MethodMetaConstraint createParameterMetaConstraint(Method method, int parameterIndex, ConstraintDescriptorImpl descriptor) { + return new MethodMetaConstraint( descriptor, method, parameterIndex ); + } + + private MethodMetaConstraint createReturnValueMetaConstraint(Method method, ConstraintDescriptorImpl descriptor) { + return new MethodMetaConstraint( descriptor, method ); } /** @@ -802,18 +823,18 @@ private MethodMetaData findMethodMetaData(Method method) { List parameterConstraints = getParameterMetaData( method ); boolean isCascading = isValidAnnotationPresent( method ) || cascadedMembers.contains( method ); - List> constraints = + List> constraints = convertToMetaConstraints( findConstraints( method, ElementType.METHOD ), method ); return new MethodMetaData( method, parameterConstraints, constraints, isCascading ); } - private List> convertToMetaConstraints(List> constraintsDescriptors, Method method) { + private List> convertToMetaConstraints(List> constraintsDescriptors, Method method) { - List> constraints = new ArrayList>(); + List> constraints = newArrayList(); for ( ConstraintDescriptorImpl oneDescriptor : constraintsDescriptors ) { - constraints.add( createBeanMetaConstraint( method.getDeclaringClass(), method, oneDescriptor ) ); + constraints.add( createReturnValueMetaConstraint( method, oneDescriptor ) ); } return constraints; @@ -837,7 +858,7 @@ private List getParameterMetaData(Method method) { boolean parameterIsCascading = false; String parameterName = DEFAULT_PARAMETER_NAME_PREFIX + i; - List> constraintsOfOneParameter = newArrayList(); + List> constraintsOfOneParameter = newArrayList(); for ( Annotation oneAnnotation : annotationsOfOneParameter ) { @@ -870,6 +891,18 @@ private List getParameterMetaData(Method method) { return metaData; } + private MethodMetaConstraint getAsMethodMetaConstraint(BeanMetaConstraint beanMetaConstraint) { + return new MethodMetaConstraint( + beanMetaConstraint.getDescriptor(), (Method) beanMetaConstraint.getLocation().getMember() + ); + } + + private BeanMetaConstraint getAsBeanMetaConstraint(MethodMetaConstraint methodMetaConstraint, Method method) { + return new BeanMetaConstraint( + methodMetaConstraint.getDescriptor(), methodMetaConstraint.getLocation().getBeanClass(), method + ); + } + private ConstraintOrigin determineOrigin(Class clazz) { if ( clazz.equals( beanClass ) ) { return ConstraintOrigin.DEFINED_LOCALLY; diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/ConstraintDescriptorImpl.java b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/ConstraintDescriptorImpl.java index d76fd6ad82..bf9a085cb2 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/ConstraintDescriptorImpl.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/ConstraintDescriptorImpl.java @@ -46,14 +46,13 @@ import org.hibernate.validator.constraints.CompositionType; import org.hibernate.validator.constraints.ConstraintComposition; - -import static org.hibernate.validator.constraints.CompositionType.AND; - import org.hibernate.validator.util.LoggerFactory; import org.hibernate.validator.util.ReflectionHelper; import org.hibernate.validator.util.annotationfactory.AnnotationDescriptor; import org.hibernate.validator.util.annotationfactory.AnnotationFactory; +import static org.hibernate.validator.constraints.CompositionType.AND; + /** * Describe a single constraint (including it's composing constraints). * @@ -285,7 +284,7 @@ public boolean equals(Object o) { return false; } - ConstraintDescriptorImpl that = (ConstraintDescriptorImpl) o; + ConstraintDescriptorImpl that = (ConstraintDescriptorImpl) o; if ( annotation != null ? !annotation.equals( that.annotation ) : that.annotation != null ) { return false; diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/MetaConstraint.java b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/MetaConstraint.java index 73128684b1..e931e27601 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/MetaConstraint.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/MetaConstraint.java @@ -101,7 +101,7 @@ public boolean equals(Object o) { return false; } - MetaConstraint that = (MetaConstraint) o; + MetaConstraint that = (MetaConstraint) o; if ( constraintDescriptor != null ? !constraintDescriptor.equals( that.constraintDescriptor ) : that.constraintDescriptor != null ) { return false; @@ -123,7 +123,7 @@ public int hashCode() { @Override public String toString() { final StringBuilder sb = new StringBuilder(); - sb.append( "MetaConstraint"); + sb.append( "MetaConstraint" ); sb.append( "{constraintType=" ).append( constraintDescriptor.getAnnotation().annotationType().getName() ); sb.append( ", location=" ).append( location ); sb.append( "}" ); diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/MethodDescriptorImpl.java b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/MethodDescriptorImpl.java index bde0c81a13..4f0a0ab309 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/MethodDescriptorImpl.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/MethodDescriptorImpl.java @@ -16,7 +16,6 @@ */ package org.hibernate.validator.metadata; -import java.lang.annotation.Annotation; import java.util.List; import org.hibernate.validator.method.metadata.MethodDescriptor; @@ -37,7 +36,7 @@ public MethodDescriptorImpl(BeanMetaData metaDataBean, AggregatedMethodMetaDa this.methodMetaData = methodMetaData; //add the return value constraints of the represented method to the constraint descriptor list - for ( BeanMetaConstraint oneConstraint : methodMetaData ) { + for ( MethodMetaConstraint oneConstraint : methodMetaData ) { addConstraintDescriptor( oneConstraint.getDescriptor() ); } } diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/ParameterMetaConstraint.java b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/MethodMetaConstraint.java similarity index 53% rename from hibernate-validator/src/main/java/org/hibernate/validator/metadata/ParameterMetaConstraint.java rename to hibernate-validator/src/main/java/org/hibernate/validator/metadata/MethodMetaConstraint.java index f9f9325855..13e9818555 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/ParameterMetaConstraint.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/MethodMetaConstraint.java @@ -19,27 +19,53 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Method; -import org.hibernate.validator.metadata.location.MethodParameterConstraintLocation; +import org.hibernate.validator.metadata.location.MethodConstraintLocation; /** - * A {@link MetaConstraint} implementation that represents a method parameter constraint. + * A {@link MetaConstraint} implementation that represents a method parameter or return value constraint. * * @author Gunnar Morling */ -public class ParameterMetaConstraint extends MetaConstraint { +public class MethodMetaConstraint extends MetaConstraint { /** - * Creates a new {@link ParameterMetaConstraint} representing a method + * Creates a new {@link MethodMetaConstraint} representing a method * parameter constraint. * * @param constraintDescriptor The descriptor for this constraint. * @param method The method hosting this constraint. * @param parameterIndex The index of the parameter hosting this constraint. */ - public ParameterMetaConstraint( + public MethodMetaConstraint( ConstraintDescriptorImpl constraintDescriptor, Method method, int parameterIndex) { - super( constraintDescriptor, new MethodParameterConstraintLocation( method, parameterIndex ) ); + super( constraintDescriptor, new MethodConstraintLocation( method, parameterIndex ) ); + } + + /** + * Creates a new {@link MethodMetaConstraint} representing a method + * return value constraint. + * + * @param constraintDescriptor The descriptor for this constraint. + * @param method The method hosting this constraint. + */ + public MethodMetaConstraint( + ConstraintDescriptorImpl constraintDescriptor, Method method) { + + super( constraintDescriptor, new MethodConstraintLocation( method ) ); + } + + /** + * Creates a new {@link MethodMetaConstraint} representing a method + * parameter constraint. + * + * @param constraintDescriptor The descriptor for this constraint. + * @param location The location of this constraint. + */ + public MethodMetaConstraint( + ConstraintDescriptorImpl constraintDescriptor, MethodConstraintLocation location) { + + super( constraintDescriptor, location ); } } diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/MethodMetaData.java b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/MethodMetaData.java index 76899d26c7..1fc9b008db 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/MethodMetaData.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/MethodMetaData.java @@ -16,12 +16,13 @@ */ package org.hibernate.validator.metadata; -import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.Collections; import java.util.Iterator; import java.util.List; +import static org.hibernate.validator.util.CollectionHelper.newArrayList; + /** * Represents a method of a Java type and all its associated meta-data relevant * in the context of bean validation, for instance the constraints at it's @@ -29,7 +30,7 @@ * * @author Gunnar Morling */ -public class MethodMetaData implements Iterable> { +public class MethodMetaData implements Iterable> { private final Method method; @@ -38,7 +39,7 @@ public class MethodMetaData implements Iterable parameterMetaData; - private final List> constraints; + private final List> returnValueConstraints; private final boolean isCascading; @@ -46,21 +47,43 @@ public class MethodMetaData implements Iterable> constraints, + List> constraints, boolean isCascading) { this( method, Collections.emptyList(), constraints, isCascading ); } + /** + * Creates a new method meta data object. + * + * @param method The method to represent. + * @param parameterMetaData A list with parameter meta data. The length must correspond + * with the number of parameters of the represented method. So + * this list may be empty returned (in case of a parameterless + * method), but never null. + * @param returnValueConstraints The return value constraints of the represented method, if + * any. + * @param isCascading Whether a cascaded validation of the represented method's + * return value shall be performed or not. + */ public MethodMetaData( Method method, List parameterMetaData, - List> constraints, + List> returnValueConstraints, boolean isCascading) { + if ( parameterMetaData.size() != method.getParameterTypes().length ) { + throw new IllegalArgumentException( + String.format( + "Method %s has %s parameters, but the passed list of parameter meta data has a size of %s.", + method, method.getParameterTypes().length, parameterMetaData.size() + ) + ); + } + this.method = method; this.parameterMetaData = Collections.unmodifiableList( parameterMetaData ); - this.constraints = Collections.unmodifiableList( constraints ); + this.returnValueConstraints = Collections.unmodifiableList( returnValueConstraints ); this.isCascading = isCascading; this.hasParameterConstraints = hasParameterConstraints( parameterMetaData ); } @@ -121,8 +144,8 @@ public List getAllParameterMetaData() { /** * An iterator with the return value constraints of the represented method. */ - public Iterator> iterator() { - return constraints.iterator(); + public Iterator> iterator() { + return returnValueConstraints.iterator(); } /** @@ -148,7 +171,7 @@ public boolean isCascading() { */ public boolean isConstrained() { - return isCascading || !constraints.isEmpty() || hasParameterConstraints; + return isCascading || !returnValueConstraints.isEmpty() || hasParameterConstraints; } /** @@ -162,10 +185,32 @@ public boolean hasParameterConstraints() { return hasParameterConstraints; } + public MethodMetaData merge(MethodMetaData otherMetaData) { + + boolean isCascading = isCascading() || otherMetaData.isCascading(); + + // 1 - aggregate return value constraints + List> mergedReturnValueConstraints = newArrayList( + this, otherMetaData + ); + + // 2 - aggregate parameter metaData. The two method MetaData have the same signature, consequently they + // have the same number of parameters. + List mergedParameterMetaData = newArrayList(); + for ( ParameterMetaData oneParameterMetaData : getAllParameterMetaData() ) { + mergedParameterMetaData.add( + oneParameterMetaData.merge( + otherMetaData.getParameterMetaData( oneParameterMetaData.getIndex() ) + ) + ); + } + return new MethodMetaData( method, mergedParameterMetaData, mergedReturnValueConstraints, isCascading ); + } + @Override public String toString() { return "MethodMetaData [method=" + method + ", parameterMetaData=" - + parameterMetaData + ", constraints=" + constraints + + parameterMetaData + ", constraints=" + returnValueConstraints + ", isCascading=" + isCascading + ", hasParameterConstraints=" + hasParameterConstraints + "]"; } diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/ParameterDescriptorImpl.java b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/ParameterDescriptorImpl.java index 1ccd2031cc..2689c63920 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/ParameterDescriptorImpl.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/ParameterDescriptorImpl.java @@ -16,8 +16,6 @@ */ package org.hibernate.validator.metadata; -import java.lang.annotation.Annotation; - import org.hibernate.validator.method.metadata.ParameterDescriptor; /** @@ -33,7 +31,7 @@ public ParameterDescriptorImpl(BeanMetaData metaDataBean, ParameterMetaData p this.parameterMetaData = parameterMetaData; //add constraints of the represented parameter to the constraint descriptor list - for ( MetaConstraint oneConstraint : parameterMetaData ) { + for ( MetaConstraint oneConstraint : parameterMetaData ) { addConstraintDescriptor( oneConstraint.getDescriptor() ); } } diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/ParameterMetaData.java b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/ParameterMetaData.java index e2c9ef3671..fbe5be22d9 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/ParameterMetaData.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/ParameterMetaData.java @@ -16,17 +16,18 @@ */ package org.hibernate.validator.metadata; -import java.lang.annotation.Annotation; import java.util.Collections; import java.util.Iterator; import java.util.List; +import static org.hibernate.validator.util.CollectionHelper.newArrayList; + /** * Contains constraint-related meta-data for one method parameter. * * @author Gunnar Morling */ -public class ParameterMetaData implements Iterable> { +public class ParameterMetaData implements Iterable> { private final Class type; @@ -34,11 +35,11 @@ public class ParameterMetaData implements Iterable> constraints; + private final List> constraints; private final boolean isCascading; - public ParameterMetaData(int index, Class type, String name, List> constraints, boolean isCascading) { + public ParameterMetaData(int index, Class type, String name, List> constraints, boolean isCascading) { this.index = index; this.type = type; @@ -76,17 +77,28 @@ public boolean isConstrained() { return isCascading || !constraints.isEmpty(); } - public Iterator> iterator() { + public Iterator> iterator() { return constraints.iterator(); } + public ParameterMetaData merge(ParameterMetaData otherMetaData) { + + return new ParameterMetaData( + index, + type, + name, + newArrayList( this, otherMetaData ), + isCascading() || otherMetaData.isCascading() + ); + } + @Override public String toString() { //display short annotation type names StringBuilder sb = new StringBuilder(); - for ( MetaConstraint oneConstraint : constraints ) { + for ( MetaConstraint oneConstraint : constraints ) { sb.append( oneConstraint.getDescriptor().getAnnotation().annotationType().getSimpleName() ); sb.append( ", " ); } diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/location/BeanConstraintLocation.java b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/location/BeanConstraintLocation.java index ecb0400c71..e1fee9cbd5 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/location/BeanConstraintLocation.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/location/BeanConstraintLocation.java @@ -16,7 +16,9 @@ */ package org.hibernate.validator.metadata.location; +import java.lang.annotation.ElementType; import java.lang.reflect.Member; +import java.lang.reflect.Method; import java.lang.reflect.Type; import org.hibernate.validator.util.ReflectionHelper; @@ -46,6 +48,15 @@ public class BeanConstraintLocation implements ConstraintLocation { */ private final Class beanClass; + /** + * The type of element hosting this constraint. One of TYPE, FIELD or METHOD. + */ + private final ElementType elementType; + + public BeanConstraintLocation(Class beanClass) { + this( beanClass, null ); + } + /** * @param beanClass The class in which the constraint is defined on * @param member The member on which the constraint is defined on, {@code null} if it is a class constraint} @@ -56,9 +67,11 @@ public BeanConstraintLocation(Class beanClass, Member member) { if ( this.member != null ) { this.propertyName = ReflectionHelper.getPropertyName( member ); + this.elementType = ( member instanceof Method ) ? ElementType.METHOD : ElementType.FIELD; } else { this.propertyName = null; + this.elementType = ElementType.TYPE; } this.beanClass = beanClass; } @@ -95,6 +108,10 @@ public Type typeOfAnnotatedElement() { return t; } + public ElementType getElementType() { + return elementType; + } + @Override public boolean equals(Object o) { if ( this == o ) { diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/location/ConstraintLocation.java b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/location/ConstraintLocation.java index 5f5c1a64e9..520c1bf42e 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/location/ConstraintLocation.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/location/ConstraintLocation.java @@ -26,6 +26,8 @@ */ public interface ConstraintLocation { + public Class getBeanClass(); + /** * Returns the type of the element at this constraint location. Depending * on the concrete implementation this might be the type of an annotated bean, method parameter etc. diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/location/MethodParameterConstraintLocation.java b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/location/MethodConstraintLocation.java similarity index 58% rename from hibernate-validator/src/main/java/org/hibernate/validator/metadata/location/MethodParameterConstraintLocation.java rename to hibernate-validator/src/main/java/org/hibernate/validator/metadata/location/MethodConstraintLocation.java index a7fa97c3c4..ca8b4180ce 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/location/MethodParameterConstraintLocation.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/location/MethodConstraintLocation.java @@ -23,23 +23,32 @@ import org.hibernate.validator.util.ReflectionHelper; /** - * A {@link ConstraintLocation} implementation that represents a method parameter. + * A {@link ConstraintLocation} implementation that represents a method + * parameter or return value. * * @author Gunnar Morling */ -public class MethodParameterConstraintLocation implements ConstraintLocation { +public class MethodConstraintLocation implements ConstraintLocation { private final Method method; - private final int parameterIndex; + private final Integer parameterIndex; + + public MethodConstraintLocation(Method method) { + + Contracts.assertNotNull( method, "Method must not be null" ); + + this.method = method; + this.parameterIndex = null; + } /** - * Creates a new {@link MethodParameterConstraintLocation}. + * Creates a new {@link MethodConstraintLocation}. * * @param method The method of the location to be created. * @param parameterIndex The parameter index of the location to be created. */ - public MethodParameterConstraintLocation(Method method, int parameterIndex) { + public MethodConstraintLocation(Method method, int parameterIndex) { Contracts.assertNotNull( method, "Method must not be null" ); @@ -47,21 +56,43 @@ public MethodParameterConstraintLocation(Method method, int parameterIndex) { this.parameterIndex = parameterIndex; } + public Class getBeanClass() { + return method.getDeclaringClass(); + } + public Type typeOfAnnotatedElement() { Type t = null; - t = ReflectionHelper.typeOf( method, parameterIndex ); - if ( t instanceof Class && ( ( Class ) t ).isPrimitive() ) { + if ( parameterIndex == null ) { + t = ReflectionHelper.typeOf( method ); + } + else { + t = ReflectionHelper.typeOf( method, parameterIndex ); + } + + if ( t instanceof Class && ( (Class) t ).isPrimitive() ) { t = ReflectionHelper.boxedType( t ); } return t; } + public Method getMethod() { + return method; + } + + /** + * The parameter index of this constraint location or null if + * this location represents a method return value. + */ + public Integer getParameterIndex() { + return parameterIndex; + } + @Override public String toString() { - return "MethodConstraintLocation [method=" + method + ", parameterIndex=" - + parameterIndex + "]"; + return "MethodConstraintLocation [method=" + method + + ", parameterIndex=" + parameterIndex + "]"; } } diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/package.html b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/package.html index 0ee9ff79dc..299ab54089 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/metadata/package.html +++ b/hibernate-validator/src/main/java/org/hibernate/validator/metadata/package.html @@ -20,6 +20,6 @@ -Implementations of the Bean Validation metadata interfaces as well as Hibernate Validator specific meta data classes. +

Implementations of the Bean Validation metadata interfaces as well as Hibernate Validator specific meta data classes.

diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/method/metadata/package.html b/hibernate-validator/src/main/java/org/hibernate/validator/method/metadata/package.html index 575d443388..45e17ab816 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/method/metadata/package.html +++ b/hibernate-validator/src/main/java/org/hibernate/validator/method/metadata/package.html @@ -23,7 +23,7 @@

This package provides a meta model related to method-level constraints and as such is an addition to the package javax.validation.metadata provided by the Bean Validation API. This meta model is read-only, all -of its types are immutable. This package is part of the public Hibernate -Validator API.

+of its types are immutable.

+

This package is part of the public Hibernate Validator API.

diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/method/package.html b/hibernate-validator/src/main/java/org/hibernate/validator/method/package.html index de472ae468..010e9c2fd1 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/method/package.html +++ b/hibernate-validator/src/main/java/org/hibernate/validator/method/package.html @@ -20,11 +20,9 @@ -

-This package provides support for method-level constraints based on -JSR 303: Bean -Validation, Appendix C ("Proposal for method-level validation"). -This package is part of the public Hibernate Validator API. -

+

This package provides support for method-level constraints based +on JSR 303: Bean +Validation, Appendix C ("Proposal for method-level validation").

+

This package is part of the public Hibernate Validator API.

diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/package.html b/hibernate-validator/src/main/java/org/hibernate/validator/package.html index 8889b2d851..60fd702906 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/package.html +++ b/hibernate-validator/src/main/java/org/hibernate/validator/package.html @@ -20,7 +20,9 @@ -Bootstrap classes HibernateValidator and HibernateValidatorConfiguration which uniquely identify Hibernate Validator -and allow to configure it. These classes form part of the public Hibernate Validator API. +

Bootstrap classes HibernateValidator and +HibernateValidatorConfiguration which uniquely identify Hibernate +Validator and allow to configure it.

+

This package is part of the public Hibernate Validator API.

diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/resourceloading/package.html b/hibernate-validator/src/main/java/org/hibernate/validator/resourceloading/package.html index 63c5823ff9..fc2b5ab01d 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/resourceloading/package.html +++ b/hibernate-validator/src/main/java/org/hibernate/validator/resourceloading/package.html @@ -20,6 +20,7 @@ -ResourceBundleLocator interface and its various implementations. Part of the Hibernate Validator public API. +

ResourceBundleLocator interface and its various implementations.

+

This package is part of the public Hibernate Validator API.

diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/util/CollectionHelper.java b/hibernate-validator/src/main/java/org/hibernate/validator/util/CollectionHelper.java index 4cfb046a3a..950b19c086 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/util/CollectionHelper.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/util/CollectionHelper.java @@ -20,12 +20,15 @@ import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.List; +import java.util.Map; import java.util.Set; /** * Provides some methods for simplified collection instantiation. * * @author Gunnar Morling + * @author Kevin Pollet - SERLI - (kevin.pollet@serli.com) */ public class CollectionHelper { @@ -56,8 +59,53 @@ public static ArrayList newArrayList(int size) { return new ArrayList( size ); } - public static Set asSet(T... ts) { + public static ArrayList newArrayList(Iterable... iterables) { + ArrayList resultList = newArrayList(); + for ( Iterable oneIterable : iterables ) { + for ( T oneElement : oneIterable ) { + resultList.add( oneElement ); + } + } + return resultList; + } + public static Set asSet(T... ts) { return new HashSet( Arrays.asList( ts ) ); } + + /** + * Creates a map containing the given list's values partitioned by the given + * partitioner. + * + * @param The key type of the resulting map. + * @param The element type of the list to be partitioned. + * @param list The list to be partitioned. + * @param partitioner The partitioner to be used for determining the partitions. + * + * @return A map containing the given list's values partitioned by the given + * partitioner. + */ + public static Map> partition(List list, Partitioner partitioner) { + + Map> theValue = newHashMap(); + + for ( V v : list ) { + K key = partitioner.getPartition( v ); + + List partition = theValue.get( key ); + if ( partition == null ) { + partition = newArrayList(); + theValue.put( key, partition ); + } + + partition.add( v ); + } + + return theValue; + } + + public interface Partitioner { + + K getPartition(V v); + } } diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/util/ReflectionHelper.java b/hibernate-validator/src/main/java/org/hibernate/validator/util/ReflectionHelper.java index 34a9849dc8..41088d6e45 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/util/ReflectionHelper.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/util/ReflectionHelper.java @@ -46,6 +46,7 @@ import org.hibernate.validator.util.privilegedactions.GetConstructor; import org.hibernate.validator.util.privilegedactions.GetDeclaredField; import org.hibernate.validator.util.privilegedactions.GetDeclaredFields; +import org.hibernate.validator.util.privilegedactions.GetDeclaredMethod; import org.hibernate.validator.util.privilegedactions.GetDeclaredMethods; import org.hibernate.validator.util.privilegedactions.GetMethod; import org.hibernate.validator.util.privilegedactions.GetMethodFromPropertyName; @@ -141,7 +142,6 @@ public static T newConstructorInstance(Constructor constructor, Object... return instance; } - @SuppressWarnings("unchecked") public static T getAnnotationParameter(Annotation annotation, String parameterName, Class type) { T result; GetAnnotationParameter action = GetAnnotationParameter.action( annotation, parameterName, type ); @@ -385,7 +385,7 @@ else if ( TypeUtils.isArray( type ) ) { * @return Returns true if type is a iterable type, false otherwise. */ public static boolean isIterable(Type type) { - if ( type instanceof Class && Iterable.class.isAssignableFrom( (Class) type ) ) { + if ( type instanceof Class && Iterable.class.isAssignableFrom( (Class) type ) ) { return true; } if ( type instanceof ParameterizedType ) { @@ -404,7 +404,7 @@ public static boolean isIterable(Type type) { * @return Returns true if type is implementing Map, false otherwise. */ public static boolean isMap(Type type) { - if ( type instanceof Class && Map.class.isAssignableFrom( (Class) type ) ) { + if ( type instanceof Class && Map.class.isAssignableFrom( (Class) type ) ) { return true; } if ( type instanceof ParameterizedType ) { @@ -423,7 +423,7 @@ public static boolean isMap(Type type) { * @return Returns true if type is implementing List, false otherwise. */ public static boolean isList(Type type) { - if ( type instanceof Class && List.class.isAssignableFrom( (Class) type ) ) { + if ( type instanceof Class && List.class.isAssignableFrom( (Class) type ) ) { return true; } if ( type instanceof ParameterizedType ) { @@ -586,7 +586,7 @@ public static boolean containsMethodWithPropertyName(Class clazz, String prop * @param clazz The class to check. * @param methodName The method name. * - * @return Returns the method with the specified property or {@code null}if it does not exist. + * @return Returns the method with the specified property or {@code null} if it does not exist. */ public static Method getMethod(Class clazz, String methodName) { Method method; @@ -600,6 +600,28 @@ public static Method getMethod(Class clazz, String methodName) { return method; } + /** + * Returns the declared method with the specified name and parameter types or {@code null} if + * it does not exist. + * + * @param clazz The class to check. + * @param methodName The method name. + * @param parameterTypes The method parameter types. + * + * @return Returns the declared method with the specified name or {@code null} if it does not exist. + */ + public static Method getDeclaredMethod(Class clazz, String methodName, Class... parameterTypes) { + Method method; + GetDeclaredMethod action = GetDeclaredMethod.action( clazz, methodName, parameterTypes ); + if ( System.getSecurityManager() != null ) { + method = AccessController.doPrivileged( action ); + } + else { + method = action.run(); + } + return method; + } + /** * Returns the declared methods of the specified class. * @@ -668,7 +690,7 @@ public static boolean haveSameSignature(Method method1, Method method2) { * @throws IllegalArgumentException in case the parameter {@code primitiveType} does not represent a primitive type. */ public static Class boxedType(Type primitiveType) { - if ( !( primitiveType instanceof Class ) && !( (Class) primitiveType ).isPrimitive() ) { + if ( !( primitiveType instanceof Class ) && !( (Class) primitiveType ).isPrimitive() ) { throw new IllegalArgumentException( primitiveType.getClass() + "has to be a primitive type" ); } diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/util/ValidatorTypeHelper.java b/hibernate-validator/src/main/java/org/hibernate/validator/util/ValidatorTypeHelper.java index 90592ba74f..53763faaef 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/util/ValidatorTypeHelper.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/util/ValidatorTypeHelper.java @@ -84,7 +84,7 @@ private static Type resolveTypes(Map resolvedTypes, Type type) { return null; } else if ( type instanceof Class ) { - Class clazz = (Class) type; + Class clazz = (Class) type; final Type returnedType = resolveTypeForClassAndHierarchy( resolvedTypes, clazz ); if ( returnedType != null ) { return returnedType; diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/util/annotationfactory/package.html b/hibernate-validator/src/main/java/org/hibernate/validator/util/annotationfactory/package.html index 44129a1270..816f387222 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/util/annotationfactory/package.html +++ b/hibernate-validator/src/main/java/org/hibernate/validator/util/annotationfactory/package.html @@ -20,6 +20,6 @@ -Annotation proxy helper. +

Annotation proxy helper.

diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/util/package.html b/hibernate-validator/src/main/java/org/hibernate/validator/util/package.html index cd71903d8b..14bd9108ab 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/util/package.html +++ b/hibernate-validator/src/main/java/org/hibernate/validator/util/package.html @@ -20,6 +20,6 @@ -Independent helper classes. +

Independent helper classes.

diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/util/privilegedactions/GetDeclaredMethod.java b/hibernate-validator/src/main/java/org/hibernate/validator/util/privilegedactions/GetDeclaredMethod.java new file mode 100644 index 0000000000..fade03e602 --- /dev/null +++ b/hibernate-validator/src/main/java/org/hibernate/validator/util/privilegedactions/GetDeclaredMethod.java @@ -0,0 +1,48 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc. and/or its affiliates, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.hibernate.validator.util.privilegedactions; + +import java.lang.reflect.Method; +import java.security.PrivilegedAction; + +/** + * @author Kevin Pollet - SERLI - (kevin.pollet@serli.com) + */ +public final class GetDeclaredMethod implements PrivilegedAction { + private final Class clazz; + private final String methodName; + private final Class[] parameterTypes; + + public static GetDeclaredMethod action(Class clazz, String methodName, Class... parameterTypes) { + return new GetDeclaredMethod( clazz, methodName, parameterTypes ); + } + + private GetDeclaredMethod(Class clazz, String methodName, Class... parameterTypes) { + this.clazz = clazz; + this.methodName = methodName; + this.parameterTypes = parameterTypes; + } + + public Method run() { + try { + return clazz.getDeclaredMethod( methodName, parameterTypes ); + } + catch ( NoSuchMethodException e ) { + return null; + } + } +} diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/util/privilegedactions/package.html b/hibernate-validator/src/main/java/org/hibernate/validator/util/privilegedactions/package.html index d37dec175b..850c499ba8 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/util/privilegedactions/package.html +++ b/hibernate-validator/src/main/java/org/hibernate/validator/util/privilegedactions/package.html @@ -20,6 +20,6 @@ -Implementations of PrivilegedAction in order to execute reflection operations in a security manager. +

Implementations of PrivilegedAction in order to execute reflection operations in a security manager.

diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/util/scriptengine/package.html b/hibernate-validator/src/main/java/org/hibernate/validator/util/scriptengine/package.html index 454b4f36df..7ad191533e 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/util/scriptengine/package.html +++ b/hibernate-validator/src/main/java/org/hibernate/validator/util/scriptengine/package.html @@ -20,6 +20,6 @@ -Classes related to the evaluation of script with ScriptEngine (JSR-223). +

Classes related to the evaluation of script with ScriptEngine (JSR-223).

diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/xml/ValidationBootstrapParameters.java b/hibernate-validator/src/main/java/org/hibernate/validator/xml/ValidationBootstrapParameters.java index 2aa016a0e8..80720be473 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/xml/ValidationBootstrapParameters.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/xml/ValidationBootstrapParameters.java @@ -34,7 +34,7 @@ public class ValidationBootstrapParameters { private ConstraintValidatorFactory constraintValidatorFactory; private MessageInterpolator messageInterpolator; private TraversableResolver traversableResolver; - private ValidationProvider provider; + private ValidationProvider provider; private Class> providerClass = null; private final Map configProperties = new HashMap(); private final Set mappings = new HashSet(); @@ -55,11 +55,11 @@ public final void setMessageInterpolator(MessageInterpolator messageInterpolator this.messageInterpolator = messageInterpolator; } - public final ValidationProvider getProvider() { + public final ValidationProvider getProvider() { return provider; } - public final void setProvider(ValidationProvider provider) { + public final void setProvider(ValidationProvider provider) { this.provider = provider; } diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/xml/XmlMappingParser.java b/hibernate-validator/src/main/java/org/hibernate/validator/xml/XmlMappingParser.java index 5cd7486d86..0a5a9c2d50 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/xml/XmlMappingParser.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/xml/XmlMappingParser.java @@ -24,11 +24,8 @@ import java.lang.reflect.Member; import java.lang.reflect.Method; import java.net.URL; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -52,12 +49,15 @@ import org.hibernate.validator.metadata.ConstraintDescriptorImpl; import org.hibernate.validator.metadata.ConstraintHelper; import org.hibernate.validator.metadata.ConstraintOrigin; -import org.hibernate.validator.metadata.MetaConstraint; import org.hibernate.validator.util.LoggerFactory; import org.hibernate.validator.util.ReflectionHelper; import org.hibernate.validator.util.annotationfactory.AnnotationDescriptor; import org.hibernate.validator.util.annotationfactory.AnnotationFactory; +import static org.hibernate.validator.util.CollectionHelper.newArrayList; +import static org.hibernate.validator.util.CollectionHelper.newHashMap; +import static org.hibernate.validator.util.CollectionHelper.newHashSet; + /** * @author Hardy Ferentschik */ @@ -70,19 +70,19 @@ public class XmlMappingParser { private static final String PAYLOAD_PARAM = "payload"; private static final String PACKAGE_SEPARATOR = "."; - private final Set> processedClasses = new HashSet>(); + private final Set> processedClasses = newHashSet(); private final ConstraintHelper constraintHelper; private final AnnotationIgnores annotationIgnores; - private final Map, List>> constraintMap; + private final Map, List>> constraintMap; private final Map, List> cascadedMembers; private final Map, List>> defaultSequences; public XmlMappingParser(ConstraintHelper constraintHelper) { this.constraintHelper = constraintHelper; this.annotationIgnores = new AnnotationIgnores(); - this.constraintMap = new HashMap, List>>(); - this.cascadedMembers = new HashMap, List>(); - this.defaultSequences = new HashMap, List>>(); + this.constraintMap = newHashMap(); + this.cascadedMembers = newHashMap(); + this.defaultSequences = newHashMap(); } public final void parse(Set mappingStreams) { @@ -112,19 +112,11 @@ public final AnnotationIgnores getAnnotationIgnores() { return annotationIgnores; } - public final List> getConstraintsForClass(Class beanClass) { - List> list = new ArrayList>(); - if ( constraintMap.containsKey( beanClass ) ) { - for ( MetaConstraint metaConstraint : constraintMap.get( beanClass ) ) { - @SuppressWarnings("unchecked") // safe cast since the list of meta constraints is always specific to the bean type - MetaConstraint boundMetaConstraint = metaConstraint; - list.add( boundMetaConstraint ); - } - return list; - } - else { - return Collections.emptyList(); - } + public final List> getConstraintsForClass(Class beanClass) { + + List> theValue = constraintMap.get( beanClass ); + + return theValue != null ? theValue : Collections.>emptyList(); } public final List getCascadedMembersForClass(Class beanClass) { @@ -157,7 +149,7 @@ private void parseConstraintDefinitions(List constrain Class annotationClass = (Class) clazz; ValidatedByType validatedByType = constraintDefinition.getValidatedBy(); - List>> constraintValidatorClasses = new ArrayList>>(); + List>> constraintValidatorClasses = newArrayList(); if ( validatedByType.isIncludeExistingValidators() != null && validatedByType.isIncludeExistingValidators() ) { constraintValidatorClasses.addAll( findConstraintValidatorClasses( annotationClass ) ); } @@ -182,7 +174,7 @@ private void parseConstraintDefinitions(List constrain } private List>> findConstraintValidatorClasses(Class annotationType) { - List>> constraintValidatorDefinitionClasses = new ArrayList>>(); + List>> constraintValidatorDefinitionClasses = newArrayList(); if ( constraintHelper.isBuiltinConstraint( annotationType ) ) { constraintValidatorDefinitionClasses.addAll( constraintHelper.getBuiltInConstraints( annotationType ) ); } @@ -202,7 +194,7 @@ private void checkClassHasNotBeenProcessed(Set> processedClasses, Class } private void parseFieldLevelOverrides(List fields, Class beanClass, String defaultPackage) { - List fieldNames = new ArrayList(); + List fieldNames = newArrayList(); for ( FieldType fieldType : fields ) { String fieldName = fieldType.getName(); if ( fieldNames.contains( fieldName ) ) { @@ -230,7 +222,7 @@ private void parseFieldLevelOverrides(List fields, Class beanClass // constraints for ( ConstraintType constraint : fieldType.getConstraint() ) { - MetaConstraint metaConstraint = createMetaConstraint( + BeanMetaConstraint metaConstraint = createMetaConstraint( constraint, beanClass, field, defaultPackage ); addMetaConstraint( beanClass, metaConstraint ); @@ -239,7 +231,7 @@ private void parseFieldLevelOverrides(List fields, Class beanClass } private void parsePropertyLevelOverrides(List getters, Class beanClass, String defaultPackage) { - List getterNames = new ArrayList(); + List getterNames = newArrayList(); for ( GetterType getterType : getters ) { String getterName = getterType.getName(); if ( getterNames.contains( getterName ) ) { @@ -267,7 +259,7 @@ private void parsePropertyLevelOverrides(List getters, Class bean // constraints for ( ConstraintType constraint : getterType.getConstraint() ) { - MetaConstraint metaConstraint = createMetaConstraint( + BeanMetaConstraint metaConstraint = createMetaConstraint( constraint, beanClass, method, defaultPackage ); addMetaConstraint( beanClass, metaConstraint ); @@ -293,17 +285,17 @@ private void parseClassLevelOverrides(ClassType classType, Class beanClass, S // constraints for ( ConstraintType constraint : classType.getConstraint() ) { - MetaConstraint metaConstraint = createMetaConstraint( constraint, beanClass, null, defaultPackage ); + BeanMetaConstraint metaConstraint = createMetaConstraint( constraint, beanClass, null, defaultPackage ); addMetaConstraint( beanClass, metaConstraint ); } } - private void addMetaConstraint(Class beanClass, MetaConstraint metaConstraint) { + private void addMetaConstraint(Class beanClass, BeanMetaConstraint metaConstraint) { if ( constraintMap.containsKey( beanClass ) ) { constraintMap.get( beanClass ).add( metaConstraint ); } else { - List> constraintList = new ArrayList>(); + List> constraintList = newArrayList(); constraintList.add( metaConstraint ); constraintMap.put( beanClass, constraintList ); } @@ -314,14 +306,14 @@ private void addCascadedMember(Class beanClass, Member member) { cascadedMembers.get( beanClass ).add( member ); } else { - List tmpList = new ArrayList(); + List tmpList = newArrayList(); tmpList.add( member ); cascadedMembers.put( beanClass, tmpList ); } } private List> createGroupSequence(GroupSequenceType groupSequenceType, String defaultPackage) { - List> groupSequence = new ArrayList>(); + List> groupSequence = newArrayList(); if ( groupSequenceType != null ) { for ( String groupName : groupSequenceType.getValue() ) { Class group = getClass( groupName, defaultPackage ); @@ -331,7 +323,7 @@ private List> createGroupSequence(GroupSequenceType groupSequenceType, return groupSequence; } - private MetaConstraint createMetaConstraint(ConstraintType constraint, Class beanClass, Member member, String defaultPackage) { + private BeanMetaConstraint createMetaConstraint(ConstraintType constraint, Class beanClass, Member member, String defaultPackage) { @SuppressWarnings("unchecked") Class annotationClass = (Class) getClass( constraint.getAnnotation(), defaultPackage ); AnnotationDescriptor annotationDescriptor = new AnnotationDescriptor( annotationClass ); @@ -396,7 +388,7 @@ private Object getElementValue(ElementType elementType, Class returnType) { return getSingleValue( elementType.getContent().get( 0 ), returnType ); } else { - List values = new ArrayList(); + List values = newArrayList(); for ( Serializable s : elementType.getContent() ) { values.add( getSingleValue( s, returnType.getComponentType() ) ); } @@ -405,7 +397,7 @@ private Object getElementValue(ElementType elementType, Class returnType) { } private void removeEmptyContentElements(ElementType elementType) { - List contentToDelete = new ArrayList(); + List contentToDelete = newArrayList(); for ( Serializable content : elementType.getContent() ) { if ( content instanceof String && ( (String) content ).matches( "[\\n ].*" ) ) { contentToDelete.add( content ); @@ -421,13 +413,13 @@ private Object getSingleValue(Serializable serializable, Class returnType) { String value = (String) serializable; returnValue = convertStringToReturnType( returnType, value ); } - else if ( serializable instanceof JAXBElement && ( (JAXBElement) serializable ).getDeclaredType() + else if ( serializable instanceof JAXBElement && ( (JAXBElement) serializable ).getDeclaredType() .equals( String.class ) ) { JAXBElement elem = (JAXBElement) serializable; String value = (String) elem.getValue(); returnValue = convertStringToReturnType( returnType, value ); } - else if ( serializable instanceof JAXBElement && ( (JAXBElement) serializable ).getDeclaredType() + else if ( serializable instanceof JAXBElement && ( (JAXBElement) serializable ).getDeclaredType() .equals( AnnotationType.class ) ) { JAXBElement elem = (JAXBElement) serializable; AnnotationType annotationType = (AnnotationType) elem.getValue(); @@ -549,7 +541,7 @@ private Class[] getGroups(GroupsType groupsType, String defaultPackage) { return new Class[] { }; } - List> groupList = new ArrayList>(); + List> groupList = newArrayList(); for ( String groupClass : groupsType.getValue() ) { groupList.add( getClass( groupClass, defaultPackage ) ); } @@ -562,7 +554,7 @@ private Class[] getPayload(PayloadType payloadType, String de return new Class[] { }; } - List> payloadList = new ArrayList>(); + List> payloadList = newArrayList(); for ( String groupClass : payloadType.getValue() ) { Class payload = getClass( groupClass, defaultPackage ); if ( !Payload.class.isAssignableFrom( payload ) ) { diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/xml/package.html b/hibernate-validator/src/main/java/org/hibernate/validator/xml/package.html index 2c3aa9bd90..5390562490 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/xml/package.html +++ b/hibernate-validator/src/main/java/org/hibernate/validator/xml/package.html @@ -20,6 +20,6 @@ -Classes used to parse Bean Validation XML configuration files. +

Classes used to parse Bean Validation XML configuration files.

diff --git a/hibernate-validator/src/test/java/org/hibernate/validator/test/cfg/CascadingWithConstraintMappingTest.java b/hibernate-validator/src/test/java/org/hibernate/validator/test/cfg/CascadingWithConstraintMappingTest.java index 6f71d05c94..2e3decf0df 100644 --- a/hibernate-validator/src/test/java/org/hibernate/validator/test/cfg/CascadingWithConstraintMappingTest.java +++ b/hibernate-validator/src/test/java/org/hibernate/validator/test/cfg/CascadingWithConstraintMappingTest.java @@ -33,6 +33,7 @@ import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; +import static org.hibernate.validator.cfg.ConstraintDef.create; import static org.hibernate.validator.test.util.ConstraintViolationAssert.assertCorrectConstraintViolationMessages; import static org.hibernate.validator.test.util.ConstraintViolationAssert.assertNumberOfViolations; @@ -43,9 +44,10 @@ public void testProgrammaticCascadingValidationFieldAccess() { newMapping .type( C.class ) .property( "string", FIELD ) - .constraint( NotNullDef.class ) + .constraint( create( NotNullDef.class ) ) .type( A.class ) - .valid( "c", FIELD ); + .property( "c", FIELD ) + .valid(); Validator validator = ValidatorUtil.getValidatorForProgrammaticMapping( newMapping ); B b = new B(); @@ -63,9 +65,10 @@ public void testProgrammaticCascadingValidationMethodAccess() { newMapping .type( C.class ) .property( "string", METHOD ) - .constraint( NotNullDef.class ) + .constraint( create( NotNullDef.class ) ) .type( A.class ) - .valid( "c", METHOD ); + .property( "c", METHOD ) + .valid(); Validator validator = ValidatorUtil.getValidatorForProgrammaticMapping( newMapping ); B b = new B(); @@ -83,9 +86,10 @@ public void testProgrammaticCascadingMethodValidation() { newMapping .type( C.class ) .property( "string", METHOD ) - .constraint( NotNullDef.class ) + .constraint( create( NotNullDef.class ) ) .type( A.class ) - .valid( "c", METHOD ); + .property( "c", METHOD ) + .valid(); Validator validator = ValidatorUtil.getValidatorForProgrammaticMapping( newMapping ); MethodValidator methodValidator = validator.unwrap( MethodValidator.class ); diff --git a/hibernate-validator/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java b/hibernate-validator/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java index 5fdbe43cb4..ec0d9994ae 100644 --- a/hibernate-validator/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java +++ b/hibernate-validator/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java @@ -16,6 +16,7 @@ */ package org.hibernate.validator.test.cfg; +import java.lang.annotation.ElementType; import java.util.Arrays; import java.util.Calendar; import java.util.GregorianCalendar; @@ -29,12 +30,14 @@ import javax.validation.ValidatorFactory; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; import org.testng.annotations.Test; import org.hibernate.validator.HibernateValidator; import org.hibernate.validator.HibernateValidatorConfiguration; import org.hibernate.validator.cfg.ConstraintMapping; +import org.hibernate.validator.cfg.context.impl.ConstraintMappingContext; import org.hibernate.validator.cfg.defs.AssertTrueDef; import org.hibernate.validator.cfg.defs.FutureDef; import org.hibernate.validator.cfg.defs.MinDef; @@ -48,6 +51,8 @@ import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; +import static org.hibernate.validator.cfg.ConstraintDef.create; +import static org.hibernate.validator.cfg.ConstraintDef.createGeneric; import static org.hibernate.validator.test.util.ConstraintViolationAssert.assertConstraintViolation; import static org.hibernate.validator.test.util.ConstraintViolationAssert.assertCorrectConstraintViolationMessages; import static org.hibernate.validator.test.util.ConstraintViolationAssert.assertNumberOfViolations; @@ -76,12 +81,14 @@ public void testConstraintMappingWithConstraintDefs() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( Marathon.class ) .property( "name", METHOD ) - .constraint( NotNullDef.class ) + .constraint( create( NotNullDef.class ) ) .property( "numberOfHelpers", FIELD ) - .constraint( MinDef.class ).value( 1 ); + .constraint( create( MinDef.class ).value( 1 ) ); - assertTrue( mapping.getConstraintConfig().containsKey( Marathon.class ) ); - assertTrue( mapping.getConstraintConfig().get( Marathon.class ).size() == 2 ); + ConstraintMappingContext context = ConstraintMappingContext.getFromMapping( mapping ); + + assertTrue( context.getConstraintConfig().containsKey( Marathon.class ) ); + assertTrue( context.getConstraintConfig().get( Marathon.class ).size() == 2 ); } @Test @@ -89,12 +96,14 @@ public void testConstraintMappingWithGenericConstraints() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( Marathon.class ) .property( "name", METHOD ) - .genericConstraint( NotNull.class ) + .constraint( createGeneric( NotNull.class ) ) .property( "numberOfHelpers", FIELD ) - .genericConstraint( Min.class ).param( "value", 1 ); + .constraint( createGeneric( Min.class ).param( "value", 1 ) ); + + ConstraintMappingContext context = ConstraintMappingContext.getFromMapping( mapping ); - assertTrue( mapping.getConstraintConfig().containsKey( Marathon.class ) ); - assertTrue( mapping.getConstraintConfig().get( Marathon.class ).size() == 2 ); + assertTrue( context.getConstraintConfig().containsKey( Marathon.class ) ); + assertTrue( context.getConstraintConfig().get( Marathon.class ).size() == 2 ); } @Test @@ -102,11 +111,13 @@ public void testDefConstraintFollowedByGenericConstraint() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( Marathon.class ) .property( "numberOfHelpers", FIELD ) - .constraint( MinDef.class ).value( 1 ) - .genericConstraint( Min.class ).param( "value", 1 ); + .constraint( create( MinDef.class ).value( 1 ) ) + .constraint( createGeneric( Min.class ).param( "value", 1 ) ); + + ConstraintMappingContext context = ConstraintMappingContext.getFromMapping( mapping ); - assertTrue( mapping.getConstraintConfig().containsKey( Marathon.class ) ); - assertTrue( mapping.getConstraintConfig().get( Marathon.class ).size() == 2 ); + assertTrue( context.getConstraintConfig().containsKey( Marathon.class ) ); + assertTrue( context.getConstraintConfig().get( Marathon.class ).size() == 2 ); } @Test @@ -124,7 +135,7 @@ public void testSingleConstraint() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( Marathon.class ) .property( "name", METHOD ) - .constraint( NotNullDef.class ); + .constraint( create( NotNullDef.class ) ); Validator validator = ValidatorUtil.getValidatorForProgrammaticMapping( mapping ); Set> violations = validator.validate( new Marathon() ); @@ -137,9 +148,11 @@ public void testThatSpecificParameterCanBeSetAfterInvokingMethodFromBaseType() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( Marathon.class ) .property( "name", METHOD ) - .constraint( SizeDef.class ) - .message( "too short" ) - .min( 3 ); + .constraint( + create( SizeDef.class ) + .message( "too short" ) + .min( 3 ) + ); Validator validator = ValidatorUtil.getValidatorForProgrammaticMapping( mapping ); Marathon marathon = new Marathon(); @@ -153,12 +166,16 @@ public void testThatSpecificParameterCanBeSetAfterInvokingMethodFromBaseType() { public void testThatSpecificParameterCanBeSetAfterAddingGenericConstraintDef() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( Marathon.class ) - .genericConstraint( MarathonConstraint.class ) - .param( "minRunner", 1 ) + .constraint( + createGeneric( MarathonConstraint.class ) + .param( "minRunner", 1 ) + ) .property( "name", METHOD ) - .constraint( SizeDef.class ) - .message( "name too short" ) - .min( 3 ); + .constraint( + create( SizeDef.class ) + .message( "name too short" ) + .min( 3 ) + ); Validator validator = ValidatorUtil.getValidatorForProgrammaticMapping( mapping ); Marathon marathon = new Marathon(); @@ -174,10 +191,10 @@ public void testInheritedConstraint() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( Marathon.class ) .property( "name", METHOD ) - .constraint( NotNullDef.class ) + .constraint( create( NotNullDef.class ) ) .type( Tournament.class ) .property( "tournamentDate", METHOD ) - .constraint( FutureDef.class ); + .constraint( create( FutureDef.class ) ); Validator validator = ValidatorUtil.getValidatorForProgrammaticMapping( mapping ); Marathon marathon = new Marathon(); @@ -195,10 +212,11 @@ public void testInheritedConstraint() { public void testValid() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( Marathon.class ) - .valid( "runners", METHOD ) + .property( "runners", METHOD ) + .valid() .type( Runner.class ) .property( "paidEntryFee", FIELD ) - .constraint( AssertTrueDef.class ); + .constraint( create( AssertTrueDef.class ) ); Validator validator = ValidatorUtil.getValidatorForProgrammaticMapping( mapping ); Marathon marathon = new Marathon(); @@ -219,14 +237,9 @@ public void testValid() { ) public void testSingleConstraintWrongAccessType() throws Throwable { ConstraintMapping mapping = new ConstraintMapping(); - try { - mapping.type( Marathon.class ) - .property( "numberOfHelpers", METHOD ) - .constraint( NotNullDef.class ); - } - catch ( ValidationException e ) { - throw ( e.getCause().getCause() ); - } + mapping.type( Marathon.class ) + .property( "numberOfHelpers", METHOD ) + .constraint( create( NotNullDef.class ) ); } @Test @@ -235,9 +248,9 @@ public void testDefaultGroupSequence() { mapping.type( Marathon.class ) .defaultGroupSequence( Foo.class, Marathon.class ) .property( "name", METHOD ) - .constraint( NotNullDef.class ).groups( Foo.class ) + .constraint( create( NotNullDef.class ).groups( Foo.class ) ) .property( "runners", METHOD ) - .constraint( NotEmptyDef.class ); + .constraint( create( NotEmptyDef.class ) ); Validator validator = ValidatorUtil.getValidatorForProgrammaticMapping( mapping ); Marathon marathon = new Marathon(); @@ -258,9 +271,9 @@ public void testDefaultGroupSequenceProvider() { mapping.type( Marathon.class ) .defaultGroupSequenceProvider( MarathonDefaultGroupSequenceProvider.class ) .property( "name", METHOD ) - .constraint( NotNullDef.class ).groups( Foo.class ) + .constraint( create( NotNullDef.class ).groups( Foo.class ) ) .property( "runners", METHOD ) - .constraint( NotEmptyDef.class ); + .constraint( create( NotEmptyDef.class ) ); Validator validator = ValidatorUtil.getValidatorForProgrammaticMapping( mapping ); Marathon marathon = new Marathon(); @@ -275,18 +288,6 @@ public void testDefaultGroupSequenceProvider() { assertConstraintViolation( violations.iterator().next(), "may not be empty" ); } - @Test( - expectedExceptions = GroupDefinitionException.class, - expectedExceptionsMessageRegExp = "The default group sequence provider defined for .* has the wrong type" - ) - public void testDefaultGroupSequenceProviderDefinedWithWrongType() { - ConstraintMapping mapping = new ConstraintMapping(); - mapping.type( Marathon.class ) - .defaultGroupSequenceProvider( BDefaultGroupSequenceProvider.class ); - Validator validator = ValidatorUtil.getValidatorForProgrammaticMapping( mapping ); - validator.validate( new Marathon() ); - } - @Test( expectedExceptions = GroupDefinitionException.class, expectedExceptionsMessageRegExp = "Default group sequence and default group sequence provider cannot be defined at the same time" @@ -297,9 +298,9 @@ public void testProgrammaticDefaultGroupSequenceAndDefaultGroupSequenceProviderD .defaultGroupSequence( Foo.class, Marathon.class ) .defaultGroupSequenceProvider( MarathonDefaultGroupSequenceProvider.class ) .property( "name", METHOD ) - .constraint( NotNullDef.class ).groups( Foo.class ) + .constraint( create( NotNullDef.class ).groups( Foo.class ) ) .property( "runners", METHOD ) - .constraint( NotEmptyDef.class ); + .constraint( create( NotEmptyDef.class ) ); Validator validator = ValidatorUtil.getValidatorForProgrammaticMapping( mapping ); validator.validate( new Marathon() ); } @@ -313,7 +314,7 @@ public void testProgrammaticDefaultGroupSequenceDefinedOnClassWithGroupProviderA mapping.type( B.class ) .defaultGroupSequence( Foo.class, B.class ) .property( "b", FIELD ) - .constraint( NotNullDef.class ); + .constraint( create( NotNullDef.class ) ); Validator validator = ValidatorUtil.getValidatorForProgrammaticMapping( mapping ); validator.validate( new B() ); } @@ -327,7 +328,7 @@ public void testProgrammaticDefaultGroupSequenceProviderDefinedOnClassWithGroupS mapping.type( A.class ) .defaultGroupSequenceProvider( ADefaultGroupSequenceProvider.class ) .property( "a", FIELD ) - .constraint( NotNullDef.class ); + .constraint( create( NotNullDef.class ) ); Validator validator = ValidatorUtil.getValidatorForProgrammaticMapping( mapping ); validator.validate( new A() ); } @@ -337,8 +338,8 @@ public void testMultipleConstraintOfTheSameType() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( Marathon.class ) .property( "name", METHOD ) - .constraint( SizeDef.class ).min( 5 ) - .constraint( SizeDef.class ).min( 10 ); + .constraint( create( SizeDef.class ).min( 5 ) ) + .constraint( create( SizeDef.class ).min( 10 ) ); Validator validator = ValidatorUtil.getValidatorForProgrammaticMapping( mapping ); Marathon marathon = new Marathon(); @@ -363,7 +364,7 @@ public void testMultipleConstraintOfTheSameType() { public void testCustomConstraintTypeMissingParameter() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( Marathon.class ) - .genericConstraint( MarathonConstraint.class ); + .constraint( createGeneric( MarathonConstraint.class ) ); HibernateValidatorConfiguration config = ValidatorUtil.getConfiguration( HibernateValidator.class ); config.addMapping( mapping ); @@ -374,9 +375,11 @@ public void testCustomConstraintTypeMissingParameter() { public void testCustomConstraintType() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( Marathon.class ) - .genericConstraint( MarathonConstraint.class ) - .param( "minRunner", 100 ) - .message( "Needs more runners" ); + .constraint( + createGeneric( MarathonConstraint.class ) + .param( "minRunner", 100 ) + .message( "Needs more runners" ) + ); Validator validator = ValidatorUtil.getValidatorForProgrammaticMapping( mapping ); Marathon marathon = new Marathon(); @@ -394,13 +397,13 @@ public void testCustomConstraintType() { } @Test( - expectedExceptions = ValidationException.class, - expectedExceptionsMessageRegExp = "Null is not a valid bean type" + expectedExceptions = IllegalArgumentException.class, + expectedExceptionsMessageRegExp = "The bean type must not be null when creating a constraint mapping." ) public void testNullBean() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( null ) - .genericConstraint( MarathonConstraint.class ); + .constraint( createGeneric( MarathonConstraint.class ) ); HibernateValidatorConfiguration config = ValidatorUtil.getConfiguration( HibernateValidator.class ); config.addMapping( mapping ).buildValidatorFactory(); @@ -411,9 +414,11 @@ public void testRangeDef() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( Runner.class ) .property( "age", METHOD ) - .constraint( RangeDef.class ) - .min( 12 ) - .max( 99 ); + .constraint( + create( RangeDef.class ) + .min( 12 ) + .max( 99 ) + ); Validator validator = ValidatorUtil.getValidatorForProgrammaticMapping( mapping ); Set> violations = validator.validate( new Runner() ); assertNumberOfViolations( violations, 1 ); @@ -425,9 +430,9 @@ public void testDefaultGroupSequenceDefinedOnClassWithNoConstraints() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( Marathon.class ) .property( "name", METHOD ) - .constraint( NotNullDef.class ).groups( Foo.class ) + .constraint( create( NotNullDef.class ).groups( Foo.class ) ) .property( "runners", METHOD ) - .constraint( NotEmptyDef.class ) + .constraint( create( NotEmptyDef.class ) ) .type( ExtendedMarathon.class ) .defaultGroupSequence( Foo.class, ExtendedMarathon.class ); Validator validator = ValidatorUtil.getValidatorForProgrammaticMapping( mapping ); @@ -444,39 +449,93 @@ public void testDefaultGroupSequenceDefinedOnClassWithNoConstraints() { assertConstraintViolation( violations.iterator().next(), "may not be empty" ); } + @Test + public void testProgrammaticAndAnnotationFieldConstraintsAddUp() { + + ConstraintMapping mapping = new ConstraintMapping(); + mapping.type( User.class ) + .property( "firstName", ElementType.FIELD ) + .constraint( create( SizeDef.class ).min( 2 ).max( 10 ) ); + + Validator validator = ValidatorUtil.getValidatorForProgrammaticMapping( mapping ); + Set> violations = validator.validateProperty( new User( "", "" ), "firstName" ); + + assertCorrectConstraintViolationMessages( + violations, + "size must be between 1 and 10", "size must be between 2 and 10" + ); + } + + @Test + public void testProgrammaticAndAnnotationPropertyConstraintsAddUp() { + + ConstraintMapping mapping = new ConstraintMapping(); + mapping.type( User.class ) + .property( "lastName", ElementType.METHOD ) + .constraint( create( SizeDef.class ).min( 4 ).max( 10 ) ); + + Validator validator = ValidatorUtil.getValidatorForProgrammaticMapping( mapping ); + Set> violations = validator.validateProperty( new User( "", "" ), "lastName" ); + + assertCorrectConstraintViolationMessages( + violations, + "size must be between 3 and 10", "size must be between 4 and 10" + ); + } + private interface Foo { } @GroupSequence( { Foo.class, A.class }) private static class A { + @SuppressWarnings("unused") String a; } @GroupSequenceProvider(BDefaultGroupSequenceProvider.class) private static class B { + @SuppressWarnings("unused") String b; } private static class ExtendedMarathon extends Marathon { } + @SuppressWarnings("unused") + private static class User { + + @Size(min = 1, max = 10) + private String firstName; + + private String lastName; + + private User(String firstName, String lastName) { + this.firstName = firstName; + this.lastName = lastName; + } + + @Size(min = 3, max = 10) + public String getLastName() { + return lastName; + } + + } + public static class MarathonDefaultGroupSequenceProvider implements DefaultGroupSequenceProvider { public List> getValidationGroups(Marathon object) { - return Arrays.asList( Foo.class, Marathon.class ); + return Arrays.>asList( Foo.class, Marathon.class ); } } public static class BDefaultGroupSequenceProvider implements DefaultGroupSequenceProvider { public List> getValidationGroups(B object) { - return Arrays.asList( Foo.class, B.class ); + return Arrays.>asList( Foo.class, B.class ); } } public static class ADefaultGroupSequenceProvider implements DefaultGroupSequenceProvider { public List> getValidationGroups(A object) { - return Arrays.asList( Foo.class, A.class ); + return Arrays.>asList( Foo.class, A.class ); } } } - - diff --git a/hibernate-validator/src/test/java/org/hibernate/validator/test/cfg/MethodConstraintMappingTest.java b/hibernate-validator/src/test/java/org/hibernate/validator/test/cfg/MethodConstraintMappingTest.java new file mode 100644 index 0000000000..0f091ffdf1 --- /dev/null +++ b/hibernate-validator/src/test/java/org/hibernate/validator/test/cfg/MethodConstraintMappingTest.java @@ -0,0 +1,460 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc. and/or its affiliates, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.hibernate.validator.test.cfg; + +import javax.validation.ConstraintDeclarationException; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import org.hibernate.validator.cfg.ConstraintMapping; +import org.hibernate.validator.cfg.defs.NotNullDef; +import org.hibernate.validator.cfg.defs.SizeDef; +import org.hibernate.validator.method.MethodConstraintViolationException; + +import static org.hibernate.validator.cfg.ConstraintDef.create; +import static org.hibernate.validator.cfg.ConstraintDef.createGeneric; +import static org.hibernate.validator.test.util.ConstraintViolationAssert.assertCorrectConstraintViolationMessages; +import static org.hibernate.validator.test.util.ConstraintViolationAssert.assertCorrectPropertyPaths; +import static org.hibernate.validator.test.util.ValidatorUtil.getMethodValidatorForMapping; +import static org.hibernate.validator.test.util.ValidatorUtil.getValidatingProxy; +import static org.testng.Assert.fail; + +/** + * Tests the definition of method constraints with the programmatic API. + * + * @author Kevin Pollet - SERLI - (kevin.pollet@serli.com) + */ +public class MethodConstraintMappingTest { + + private GreetingService wrappedObject; + + @BeforeClass + public void setUp() { + wrappedObject = new GreetingServiceImpl(); + } + + @Test + public void testCascadingMethodReturnDefinition() { + ConstraintMapping mapping = new ConstraintMapping(); + mapping.type( GreetingService.class ) + .method( "greet", User.class ) + .returnValue() + .valid(); + + GreetingService service = getValidatingProxy( wrappedObject, mapping ); + + try { + service.greet( new User( "foo" ) ); + fail( "Expected exception wasn't thrown." ); + } + catch ( MethodConstraintViolationException e ) { + assertCorrectConstraintViolationMessages( e, "may not be null" ); + assertCorrectPropertyPaths( e, "GreetingService#greet().message" ); + } + } + + @Test + public void testCascadingMethodParameterDefinition() { + ConstraintMapping mapping = new ConstraintMapping(); + mapping.type( GreetingService.class ) + .method( "greet", User.class ) + .parameter( 0 ) + .valid(); + + GreetingService service = getValidatingProxy( wrappedObject, mapping ); + + try { + service.greet( new User( null ) ); + fail( "Expected exception wasn't thrown." ); + } + catch ( MethodConstraintViolationException e ) { + assertCorrectConstraintViolationMessages( e, "may not be null" ); + assertCorrectPropertyPaths( e, "GreetingService#greet(arg0).name" ); + } + } + + @Test( + expectedExceptions = IllegalArgumentException.class, + expectedExceptionsMessageRegExp = "Type .*GreetingService doesn't have a method greet().*" + ) + public void testCascadingDefinitionOnMissingMethod() { + ConstraintMapping mapping = new ConstraintMapping(); + mapping.type( GreetingService.class ) + .method( "greet" ) + .returnValue() + .valid(); + + getMethodValidatorForMapping( mapping ); + } + + @Test( + expectedExceptions = IllegalArgumentException.class, + expectedExceptionsMessageRegExp = "A valid parameter index has to be specified for method 'greet'" + ) + public void testCascadingDefinitionOnInvalidMethodParameter() { + ConstraintMapping mapping = new ConstraintMapping(); + mapping.type( GreetingService.class ) + .method( "greet", User.class ) + .parameter( 1 ) + .valid(); + + getMethodValidatorForMapping( mapping ); + } + + @Test( + expectedExceptions = ConstraintDeclarationException.class, + expectedExceptionsMessageRegExp = ".* there are parameter constraints defined at all of the following overridden methods: .*" + ) + public void testCascadingMethodParameterRedefinedInHierarchy() { + ConstraintMapping mapping = new ConstraintMapping(); + mapping.type( GreetingService.class ) + .method( "greet", User.class ) + .parameter( 0 ) + .valid() + .type( GreetingServiceImpl.class ) + .method( "greet", User.class ) + .parameter( 0 ) + .valid(); + + GreetingService service = getValidatingProxy( wrappedObject, mapping ); + + service.greet( new User( null ) ); + } + + @Test( + expectedExceptions = ConstraintDeclarationException.class, + expectedExceptionsMessageRegExp = ".* The following method itself has no parameter constraints but it is not defined on a sub-type of .*" + ) + public void testCascadingMethodParameterDefinedOnlyOnSubType() { + ConstraintMapping mapping = new ConstraintMapping(); + mapping.type( GreetingServiceImpl.class ) + .method( "greet", User.class ) + .parameter( 0 ) + .valid(); + + GreetingService service = getValidatingProxy( wrappedObject, mapping ); + + service.greet( new User( null ) ); + } + + @Test + public void testParameterConstraint() { + + ConstraintMapping mapping = new ConstraintMapping(); + mapping.type( GreetingService.class ) + .method( "greet", User.class ) + .parameter( 0 ) + .constraint( create( NotNullDef.class ) ); + + try { + GreetingService service = getValidatingProxy( wrappedObject, mapping ); + service.greet( (User) null ); + + fail( "Expected exception wasn't thrown." ); + } + catch ( MethodConstraintViolationException e ) { + + assertCorrectConstraintViolationMessages( e, "may not be null" ); + assertCorrectPropertyPaths( e, "GreetingService#greet(arg0)" ); + } + } + + @Test + public void testGenericParameterConstraint() { + + ConstraintMapping mapping = new ConstraintMapping(); + mapping.type( GreetingService.class ) + .method( "greet", String.class ) + .parameter( 0 ) + .constraint( createGeneric( Size.class ).param( "min", 1 ).param( "max", 10 ) ); + + try { + GreetingService service = getValidatingProxy( wrappedObject, mapping ); + service.greet( "" ); + + fail( "Expected exception wasn't thrown." ); + } + catch ( MethodConstraintViolationException e ) { + + assertCorrectConstraintViolationMessages( + e, "size must be between 1 and 10" + ); + assertCorrectPropertyPaths( e, "GreetingService#greet(arg0)" ); + } + } + + @Test + public void testMultipleParameterConstraintsAtSameParameter() { + + ConstraintMapping mapping = new ConstraintMapping(); + mapping.type( GreetingService.class ) + .method( "greet", String.class ) + .parameter( 0 ) + .constraint( create( SizeDef.class ).min( 1 ).max( 10 ) ) + .constraint( create( SizeDef.class ).min( 2 ).max( 10 ) ); + + try { + GreetingService service = getValidatingProxy( wrappedObject, mapping ); + service.greet( "" ); + + fail( "Expected exception wasn't thrown." ); + } + catch ( MethodConstraintViolationException e ) { + + assertCorrectConstraintViolationMessages( + e, "size must be between 1 and 10", "size must be between 2 and 10" + ); + assertCorrectPropertyPaths( e, "GreetingService#greet(arg0)", "GreetingService#greet(arg0)" ); + } + } + + @Test + public void testMultipleParameterConstraintsAtDifferentParameters() { + + ConstraintMapping mapping = new ConstraintMapping(); + mapping.type( GreetingService.class ) + .method( "greet", String.class, String.class ) + .parameter( 0 ) + .constraint( create( SizeDef.class ).min( 1 ).max( 10 ) ) + .parameter( 1 ) + .constraint( create( SizeDef.class ).min( 1 ).max( 10 ) ); + + try { + GreetingService service = getValidatingProxy( wrappedObject, mapping ); + service.greet( "", "" ); + + fail( "Expected exception wasn't thrown." ); + } + catch ( MethodConstraintViolationException e ) { + + assertCorrectConstraintViolationMessages( + e, "size must be between 1 and 10", "size must be between 1 and 10" + ); + assertCorrectPropertyPaths( e, "GreetingService#greet(arg0)", "GreetingService#greet(arg1)" ); + } + } + + @Test + public void testProgrammaticAndAnnotationParameterConstraintsAddUp() { + + ConstraintMapping mapping = new ConstraintMapping(); + mapping.type( GreetingService.class ) + .method( "sayHello", String.class ) + .parameter( 0 ) + .constraint( create( SizeDef.class ).min( 2 ).max( 10 ) ); + + try { + GreetingService service = getValidatingProxy( wrappedObject, mapping ); + service.sayHello( "" ); + + fail( "Expected exception wasn't thrown." ); + } + catch ( MethodConstraintViolationException e ) { + + assertCorrectConstraintViolationMessages( + e, "size must be between 1 and 10", "size must be between 2 and 10" + ); + assertCorrectPropertyPaths( e, "GreetingService#sayHello(arg0)", "GreetingService#sayHello(arg0)" ); + } + } + + @Test + public void testConstraintAtCascadedParameter() { + + ConstraintMapping mapping = new ConstraintMapping(); + mapping.type( GreetingService.class ) + .method( "greet", User.class ) + .parameter( 0 ) + .constraint( create( NotNullDef.class ) ) + .valid(); + + GreetingService service = getValidatingProxy( wrappedObject, mapping ); + + try { + service.greet( (User) null ); + + fail( "Expected exception wasn't thrown." ); + } + catch ( MethodConstraintViolationException e ) { + + assertCorrectConstraintViolationMessages( e, "may not be null" ); + assertCorrectPropertyPaths( e, "GreetingService#greet(arg0)" ); + } + + try { + service.greet( new User( null ) ); + + fail( "Expected exception wasn't thrown." ); + } + catch ( MethodConstraintViolationException e ) { + + assertCorrectConstraintViolationMessages( e, "may not be null" ); + assertCorrectPropertyPaths( e, "GreetingService#greet(arg0).name" ); + } + } + + @Test + public void testReturnValueConstraint() { + + ConstraintMapping mapping = new ConstraintMapping(); + mapping.type( GreetingService.class ) + .method( "greet", String.class ) + .returnValue() + .constraint( create( SizeDef.class ).min( 1 ).max( 10 ) ); + + try { + GreetingService service = getValidatingProxy( wrappedObject, mapping ); + service.greet( "Hello" ); + + fail( "Expected exception wasn't thrown." ); + } + catch ( MethodConstraintViolationException e ) { + + assertCorrectConstraintViolationMessages( e, "size must be between 1 and 10" ); + assertCorrectPropertyPaths( e, "GreetingService#greet()" ); + } + } + + @Test + public void testMultipleReturnValueConstraints() { + + ConstraintMapping mapping = new ConstraintMapping(); + mapping.type( GreetingService.class ) + .method( "greet", String.class ) + .returnValue() + .constraint( create( SizeDef.class ).min( 1 ).max( 10 ) ) + .constraint( create( SizeDef.class ).min( 2 ).max( 10 ) ); + + try { + GreetingService service = getValidatingProxy( wrappedObject, mapping ); + service.greet( "Hello" ); + + fail( "Expected exception wasn't thrown." ); + } + catch ( MethodConstraintViolationException e ) { + + assertCorrectConstraintViolationMessages( + e, "size must be between 1 and 10", "size must be between 2 and 10" + ); + assertCorrectPropertyPaths( e, "GreetingService#greet()", "GreetingService#greet()" ); + } + } + + @Test + public void testGenericReturnValueConstraint() { + + ConstraintMapping mapping = new ConstraintMapping(); + mapping.type( GreetingService.class ) + .method( "greet", String.class ) + .returnValue() + .constraint( createGeneric( Size.class ).param( "min", 1 ).param( "max", 10 ) ); + + try { + GreetingService service = getValidatingProxy( wrappedObject, mapping ); + service.greet( "" ); + + fail( "Expected exception wasn't thrown." ); + } + catch ( MethodConstraintViolationException e ) { + + assertCorrectConstraintViolationMessages( + e, "size must be between 1 and 10" + ); + assertCorrectPropertyPaths( e, "GreetingService#greet()" ); + } + } + + @Test + public void testProgrammaticAndAnnotationReturnValueConstraintsAddUp() { + + ConstraintMapping mapping = new ConstraintMapping(); + mapping.type( GreetingService.class ) + .method( "greet", String.class, String.class ) + .returnValue() + .constraint( create( SizeDef.class ).min( 2 ).max( 10 ) ); + + try { + GreetingService service = getValidatingProxy( wrappedObject, mapping ); + service.greet( "Hello", "World" ); + + fail( "Expected exception wasn't thrown." ); + } + catch ( MethodConstraintViolationException e ) { + + assertCorrectConstraintViolationMessages( + e, "size must be between 1 and 10", "size must be between 2 and 10" + ); + assertCorrectPropertyPaths( e, "GreetingService#greet()", "GreetingService#greet()" ); + } + } + + public class User { + + @SuppressWarnings("unused") + @NotNull + private String name; + + public User(String name) { + this.name = name; + } + } + + public class Message { + + @SuppressWarnings("unused") + @NotNull + private String message; + + public Message(String message) { + this.message = message; + } + } + + public interface GreetingService { + + Message greet(User user); + + String greet(String string); + + @Size(min = 1, max = 10) + String greet(String string1, String string2); + + Message sayHello(@Size(min = 1, max = 10) String name); + } + + public class GreetingServiceImpl implements GreetingService { + + public Message greet(User user) { + return new Message( null ); + } + + public String greet(String string) { + return ""; + } + + public String greet(String string1, String string2) { + return ""; + } + + public Message sayHello(String name) { + return null; + } + } +} diff --git a/hibernate-validator/src/test/java/org/hibernate/validator/test/constraints/ValidatorResolutionTest.java b/hibernate-validator/src/test/java/org/hibernate/validator/test/constraints/ValidatorResolutionTest.java index 6732a9b14a..d2569e8856 100644 --- a/hibernate-validator/src/test/java/org/hibernate/validator/test/constraints/ValidatorResolutionTest.java +++ b/hibernate-validator/src/test/java/org/hibernate/validator/test/constraints/ValidatorResolutionTest.java @@ -16,7 +16,6 @@ */ package org.hibernate.validator.test.constraints; -import java.lang.*; import java.util.ArrayList; import java.util.List; import java.util.Set; diff --git a/hibernate-validator/src/test/java/org/hibernate/validator/test/constraints/composition/CompositeConstraintTest.java b/hibernate-validator/src/test/java/org/hibernate/validator/test/constraints/composition/CompositeConstraintTest.java index 482bd0f2ab..9aa6da24ea 100644 --- a/hibernate-validator/src/test/java/org/hibernate/validator/test/constraints/composition/CompositeConstraintTest.java +++ b/hibernate-validator/src/test/java/org/hibernate/validator/test/constraints/composition/CompositeConstraintTest.java @@ -22,7 +22,6 @@ import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; -import static org.testng.Assert.assertEquals; import org.testng.annotations.Test; import org.hibernate.validator.test.util.ValidatorUtil; diff --git a/hibernate-validator/src/test/java/org/hibernate/validator/test/constraints/impl/DecimalMinMaxValidatorBoundaryTest.java b/hibernate-validator/src/test/java/org/hibernate/validator/test/constraints/impl/DecimalMinMaxValidatorBoundaryTest.java index ba7c9439f1..4e73a3cf8c 100644 --- a/hibernate-validator/src/test/java/org/hibernate/validator/test/constraints/impl/DecimalMinMaxValidatorBoundaryTest.java +++ b/hibernate-validator/src/test/java/org/hibernate/validator/test/constraints/impl/DecimalMinMaxValidatorBoundaryTest.java @@ -29,6 +29,7 @@ import org.hibernate.validator.test.util.ValidatorUtil; import static java.lang.annotation.ElementType.FIELD; +import static org.hibernate.validator.cfg.ConstraintDef.create; import static org.hibernate.validator.test.util.ConstraintViolationAssert.assertCorrectConstraintTypes; import static org.hibernate.validator.test.util.ConstraintViolationAssert.assertNumberOfViolations; @@ -44,8 +45,10 @@ public void testDecimalMinValue() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( DecimalMinMaxValidatorBoundaryTest.class ) .property( "d", FIELD ) - .constraint( DecimalMinDef.class ) - .value( "0.100000000000000005" ); + .constraint( + create( DecimalMinDef.class ) + .value( "0.100000000000000005" ) + ); Validator validator = ValidatorUtil.getValidatorForProgrammaticMapping( mapping ); this.d = 0.1; @@ -61,8 +64,10 @@ public void testDecimalMaxValue() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( DecimalMinMaxValidatorBoundaryTest.class ) .property( "d", FIELD ) - .constraint( DecimalMaxDef.class ) - .value( "0.1" ); + .constraint( + create( DecimalMaxDef.class ) + .value( "0.1" ) + ); Validator validator = ValidatorUtil.getValidatorForProgrammaticMapping( mapping ); diff --git a/hibernate-validator/src/test/java/org/hibernate/validator/test/constraints/impl/URLValidatorTest.java b/hibernate-validator/src/test/java/org/hibernate/validator/test/constraints/impl/URLValidatorTest.java index 1e55ca5b40..7cd89af4c7 100644 --- a/hibernate-validator/src/test/java/org/hibernate/validator/test/constraints/impl/URLValidatorTest.java +++ b/hibernate-validator/src/test/java/org/hibernate/validator/test/constraints/impl/URLValidatorTest.java @@ -32,6 +32,7 @@ import org.hibernate.validator.util.annotationfactory.AnnotationFactory; import static java.lang.annotation.ElementType.METHOD; +import static org.hibernate.validator.cfg.ConstraintDef.create; import static org.hibernate.validator.test.util.ConstraintViolationAssert.assertCorrectConstraintViolationMessages; import static org.hibernate.validator.test.util.ConstraintViolationAssert.assertNumberOfViolations; import static org.hibernate.validator.test.util.ValidatorUtil.getValidatorForProgrammaticMapping; @@ -140,8 +141,10 @@ public void testRegExp() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( URLContainerNoAnnotations.class ) .property( "url", METHOD ) - .constraint( URLDef.class ) - .regexp( "^http://\\S+[\\.htm|\\.html]{1}$" ); + .constraint( + create( URLDef.class ) + .regexp( "^http://\\S+[\\.htm|\\.html]{1}$" ) + ); validator = getValidatorForProgrammaticMapping( mapping ); container = new URLContainerNoAnnotations(); @@ -160,9 +163,11 @@ public void testRegExpCaseInsensitive() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( URLContainerNoAnnotations.class ) .property( "url", METHOD ) - .constraint( URLDef.class ) - .regexp( "^http://\\S+[\\.htm|\\.html]{1}$" ) - .flags( Flag.CASE_INSENSITIVE ); + .constraint( + create( URLDef.class ) + .regexp( "^http://\\S+[\\.htm|\\.html]{1}$" ) + .flags( Flag.CASE_INSENSITIVE ) + ); validator = getValidatorForProgrammaticMapping( mapping ); container = new URLContainerNoAnnotations(); diff --git a/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/failfast/FailFastTest.java b/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/failfast/FailFastTest.java index 02eebaa230..7201d81360 100644 --- a/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/failfast/FailFastTest.java +++ b/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/failfast/FailFastTest.java @@ -23,11 +23,10 @@ import org.hibernate.validator.method.MethodConstraintViolationException; import org.hibernate.validator.method.MethodValidator; import org.hibernate.validator.test.util.ValidatorUtil; -import org.hibernate.validator.test.util.ValidationInvocationHandler; import org.hibernate.validator.util.LoggerFactory; import static org.hibernate.validator.test.util.ConstraintViolationAssert.assertNumberOfViolations; -import static org.hibernate.validator.test.util.ValidatorUtil.getMethodValidationProxy; +import static org.hibernate.validator.test.util.ValidatorUtil.getValidatingProxy; import static org.testng.Assert.fail; /** @@ -54,14 +53,8 @@ public void testFailFastDefaultBehaviour() { @Test public void testFailFastMethodValidationDefaultBehaviour() { - final HibernateValidatorConfiguration configuration = ValidatorUtil.getConfiguration( HibernateValidator.class ); - final ValidatorFactory factory = configuration.buildValidatorFactory(); - final Validator validator = factory.getValidator(); - final MethodValidator methodvalidator = validator.unwrap( MethodValidator.class ); - - ValidationInvocationHandler handler = new ValidationInvocationHandler( new TestServiceImpl(), methodvalidator ); - TestService service = (TestService) getMethodValidationProxy( handler ); + TestService service = getValidatingProxy( new TestServiceImpl() ); try { service.testMethod( " ", null ); @@ -88,10 +81,9 @@ public void testFailFastMethodValidationOnConfiguration() { final ValidatorFactory factory = configuration.failFast( true ).buildValidatorFactory(); final Validator validator = factory.getValidator(); - final MethodValidator methodvalidator = validator.unwrap( MethodValidator.class ); + final MethodValidator methodValidator = validator.unwrap( MethodValidator.class ); - ValidationInvocationHandler handler = new ValidationInvocationHandler( new TestServiceImpl(), methodvalidator ); - TestService service = (TestService) getMethodValidationProxy( handler ); + TestService service = getValidatingProxy( new TestServiceImpl(), methodValidator ); try { service.testMethod( "a", null ); @@ -126,10 +118,9 @@ public void testFailFastMethodValidationSetOnValidatorFactory() { .usingContext() .failFast( true ) .getValidator(); - final MethodValidator methodvalidator = validator.unwrap( MethodValidator.class ); + final MethodValidator methodValidator = validator.unwrap( MethodValidator.class ); - ValidationInvocationHandler handler = new ValidationInvocationHandler( new TestServiceImpl(), methodvalidator ); - TestService service = (TestService) getMethodValidationProxy( handler ); + TestService service = getValidatingProxy( new TestServiceImpl(), methodValidator ); try { service.testMethod( " ", null ); @@ -169,10 +160,9 @@ public void testFailFastMethodValidationSetWithProperty() { .buildValidatorFactory(); final Validator validator = factory.getValidator(); - final MethodValidator methodvalidator = validator.unwrap( MethodValidator.class ); + final MethodValidator methodValidator = validator.unwrap( MethodValidator.class ); - ValidationInvocationHandler handler = new ValidationInvocationHandler( new TestServiceImpl(), methodvalidator ); - TestService service = (TestService) getMethodValidationProxy( handler ); + TestService service = getValidatingProxy( new TestServiceImpl(), methodValidator ); try { service.testMethod( " ", null ); @@ -207,7 +197,7 @@ public void testFailFastSetWithInconsistentConfiguration() { HibernateValidatorConfiguration.FAIL_FAST, "false" ).failFast( true ).buildValidatorFactory(); - final Validator validator = factory.getValidator(); + factory.getValidator(); } public void testFailSafePerf() { diff --git a/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/messageinterpolation/MessageInterpolatorContextTest.java b/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/messageinterpolation/MessageInterpolatorContextTest.java index 8311427618..bc14f6f7bd 100644 --- a/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/messageinterpolation/MessageInterpolatorContextTest.java +++ b/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/messageinterpolation/MessageInterpolatorContextTest.java @@ -39,6 +39,7 @@ import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; +import static org.hibernate.validator.cfg.ConstraintDef.create; import static org.hibernate.validator.test.util.ConstraintViolationAssert.assertNumberOfViolations; import static org.testng.Assert.assertTrue; @@ -55,9 +56,11 @@ public void testInterpolatorContext() throws Exception { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( Test.class ) .property( "test", FIELD ) - .constraint( MinDef.class ) - .value( 10 ) - .message( "{foo}" ); + .constraint( + create( MinDef.class ) + .value( 10 ) + .message( "{foo}" ) + ); // use a easy mock message interpolator to verify the right for verifying that the right MessageInterpolatorContext // will be passed diff --git a/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/messageinterpolation/ValueFormatterMessageInterpolatorTest.java b/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/messageinterpolation/ValueFormatterMessageInterpolatorTest.java index 75489b2c3b..48da2b673c 100644 --- a/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/messageinterpolation/ValueFormatterMessageInterpolatorTest.java +++ b/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/messageinterpolation/ValueFormatterMessageInterpolatorTest.java @@ -38,6 +38,7 @@ import org.hibernate.validator.test.util.ValidatorUtil; import static java.lang.annotation.ElementType.FIELD; +import static org.hibernate.validator.cfg.ConstraintDef.create; import static org.hibernate.validator.test.util.ConstraintViolationAssert.assertCorrectConstraintViolationMessages; import static org.hibernate.validator.test.util.ConstraintViolationAssert.assertNumberOfViolations; @@ -52,7 +53,7 @@ public void testSimpleValidatedValueInterpolation() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( TestClass.class ) .property( "date", FIELD ) - .constraint( FutureDef.class ).message( "${validatedValue}" ); + .constraint( create( FutureDef.class ).message( "${validatedValue}" ) ); Validator validator = getValidatorUsingConstraintMapping( mapping ); @@ -68,7 +69,7 @@ public void testMultipleValidatedValuesInMessageTemplate() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( TestClass.class ) .property( "date", FIELD ) - .constraint( FutureDef.class ).message( "${validatedValue} ${validatedValue}" ); + .constraint( create( FutureDef.class ).message( "${validatedValue} ${validatedValue}" ) ); Validator validator = getValidatorUsingConstraintMapping( mapping ); @@ -84,7 +85,7 @@ public void testEscapedCurlyBraces() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( TestClass.class ) .property( "date", FIELD ) - .constraint( FutureDef.class ).message( "\\{${validatedValue}\\}" ); + .constraint( create( FutureDef.class ).message( "\\{${validatedValue}\\}" ) ); Validator validator = getValidatorUsingConstraintMapping( mapping ); @@ -100,7 +101,7 @@ public void testFormattedDate() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( TestClass.class ) .property( "date", FIELD ) - .constraint( FutureDef.class ).message( "${validatedValue:%1$ty}" ); + .constraint( create( FutureDef.class ).message( "${validatedValue:%1$ty}" ) ); Validator validator = getValidatorUsingConstraintMapping( mapping ); @@ -116,7 +117,7 @@ public void testNullValueValidation() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( TestClass.class ) .property( "date", FIELD ) - .constraint( NotNullDef.class ).message( "${validatedValue}" ); + .constraint( create( NotNullDef.class ).message( "${validatedValue}" ) ); Validator validator = getValidatorUsingConstraintMapping( mapping ); @@ -131,7 +132,7 @@ public void testFormattedDouble() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( TestClass.class ) .property( "doubleValue", FIELD ) - .constraint( DecimalMinDef.class ).value( "1.0" ).message( "${validatedValue: '%1$5f' }" ); + .constraint( create( DecimalMinDef.class ).value( "1.0" ).message( "${validatedValue: '%1$5f' }" ) ); Validator validator = getValidatorUsingConstraintMapping( mapping ); @@ -146,7 +147,7 @@ public void testCurlyBraceInFormat() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( TestClass.class ) .property( "doubleValue", FIELD ) - .constraint( DecimalMinDef.class ).value( "1.0" ).message( "${validatedValue: {%1$5f} }" ); + .constraint( create( DecimalMinDef.class ).value( "1.0" ).message( "${validatedValue: {%1$5f} }" ) ); Validator validator = getValidatorUsingConstraintMapping( mapping ); @@ -161,7 +162,7 @@ public void testColonInFormat() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( TestClass.class ) .property( "doubleValue", FIELD ) - .constraint( DecimalMinDef.class ).value( "1.0" ).message( "${validatedValue::%1$5f:}" ); + .constraint( create( DecimalMinDef.class ).value( "1.0" ).message( "${validatedValue::%1$5f:}" ) ); Validator validator = getValidatorUsingConstraintMapping( mapping ); @@ -176,7 +177,9 @@ public void testValidatedValueAndAdditionalUnknownParameter() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( TestClass.class ) .property( "doubleValue", FIELD ) - .constraint( DecimalMinDef.class ).value( "1.0" ).message( "${validatedValue: '%1$5f' } ${foo}" ); + .constraint( + create( DecimalMinDef.class ).value( "1.0" ).message( "${validatedValue: '%1$5f' } ${foo}" ) + ); Validator validator = getValidatorUsingConstraintMapping( mapping ); @@ -191,7 +194,7 @@ public void testNoClosingBrace() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( TestClass.class ) .property( "doubleValue", FIELD ) - .constraint( DecimalMinDef.class ).value( "1.0" ).message( "${validatedValue{" ); + .constraint( create( DecimalMinDef.class ).value( "1.0" ).message( "${validatedValue{" ) ); Validator validator = getValidatorUsingConstraintMapping( mapping ); @@ -209,7 +212,7 @@ public void testMissingFormatString() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( TestClass.class ) .property( "doubleValue", FIELD ) - .constraint( DecimalMinDef.class ).value( "1.0" ).message( "${validatedValue:}" ); + .constraint( create( DecimalMinDef.class ).value( "1.0" ).message( "${validatedValue:}" ) ); Validator validator = getValidatorUsingConstraintMapping( mapping ); validator.validate( new TestClass( 0.1 ) ); @@ -220,7 +223,7 @@ public void testFormattable() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( TestClass.class ) .property( "greeter", FIELD ) - .constraint( NullDef.class ).message( "${validatedValue: '%1$s' }" ); + .constraint( create( NullDef.class ).message( "${validatedValue: '%1$s' }" ) ); Validator validator = getValidatorUsingConstraintMapping( mapping ); @@ -238,9 +241,11 @@ public void testIllegalFormat() { ConstraintMapping mapping = new ConstraintMapping(); mapping.type( TestClass.class ) .property( "doubleValue", FIELD ) - .constraint( DecimalMinDef.class ) - .value( "1.0" ) - .message( "${validatedValue:%1$z}" ); // z is an unknown format + .constraint( + create( DecimalMinDef.class ) + .value( "1.0" ) + .message( "${validatedValue:%1$z}" ) + ); // z is an unknown format Validator validator = getValidatorUsingConstraintMapping( mapping ); validator.validate( new TestClass( 0.1 ) ); diff --git a/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/methodlevel/MethodLevelValidationGroupSequenceTest.java b/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/methodlevel/MethodLevelValidationGroupSequenceTest.java index fe4b4388ff..2b9490b1a6 100644 --- a/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/methodlevel/MethodLevelValidationGroupSequenceTest.java +++ b/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/methodlevel/MethodLevelValidationGroupSequenceTest.java @@ -16,25 +16,20 @@ */ package org.hibernate.validator.test.engine.methodlevel; -import javax.validation.Validation; - import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; -import org.hibernate.validator.HibernateValidator; import org.hibernate.validator.method.MethodConstraintViolation; import org.hibernate.validator.method.MethodConstraintViolationException; -import org.hibernate.validator.method.MethodValidator; import org.hibernate.validator.test.engine.methodlevel.service.CustomerRepositoryWithRedefinedDefaultGroup; import org.hibernate.validator.test.engine.methodlevel.service.CustomerRepositoryWithRedefinedDefaultGroup.ValidationGroup1; import org.hibernate.validator.test.engine.methodlevel.service.CustomerRepositoryWithRedefinedDefaultGroup.ValidationGroup2; import org.hibernate.validator.test.engine.methodlevel.service.CustomerRepositoryWithRedefinedDefaultGroup.ValidationSequence; import org.hibernate.validator.test.engine.methodlevel.service.CustomerRepositoryWithRedefinedDefaultGroupImpl; -import org.hibernate.validator.test.util.ValidationInvocationHandler; import static org.hibernate.validator.test.util.ConstraintViolationAssert.assertConstraintViolation; import static org.hibernate.validator.test.util.ConstraintViolationAssert.assertCorrectConstraintViolationMessages; -import static org.hibernate.validator.test.util.ValidatorUtil.getMethodValidationProxy; +import static org.hibernate.validator.test.util.ValidatorUtil.getValidatingProxy; import static org.testng.Assert.assertEquals; import static org.testng.Assert.fail; @@ -53,18 +48,9 @@ public void setUpDefaultMethodValidator() { } private void setUpValidatorForGroups(Class... groups) { - - MethodValidator validator = Validation.byProvider( HibernateValidator.class ) - .configure() - .buildValidatorFactory() - .getValidator() - .unwrap( MethodValidator.class ); - - ValidationInvocationHandler handler = new ValidationInvocationHandler( - new CustomerRepositoryWithRedefinedDefaultGroupImpl(), validator, groups + customerRepository = getValidatingProxy( + new CustomerRepositoryWithRedefinedDefaultGroupImpl(), groups ); - - customerRepository = (CustomerRepositoryWithRedefinedDefaultGroup) getMethodValidationProxy( handler ); } @Test diff --git a/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/methodlevel/MethodLevelValidationTest.java b/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/methodlevel/MethodLevelValidationTest.java index a190cb319c..8c568f543c 100644 --- a/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/methodlevel/MethodLevelValidationTest.java +++ b/hibernate-validator/src/test/java/org/hibernate/validator/test/engine/methodlevel/MethodLevelValidationTest.java @@ -28,23 +28,20 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; -import org.hibernate.validator.HibernateValidator; import org.hibernate.validator.engine.ValidatorImpl; import org.hibernate.validator.method.MethodConstraintViolation; import org.hibernate.validator.method.MethodConstraintViolation.Kind; import org.hibernate.validator.method.MethodConstraintViolationException; -import org.hibernate.validator.method.MethodValidator; import org.hibernate.validator.test.engine.methodlevel.model.Address; import org.hibernate.validator.test.engine.methodlevel.model.Customer; import org.hibernate.validator.test.engine.methodlevel.service.CustomerRepository; import org.hibernate.validator.test.engine.methodlevel.service.CustomerRepositoryImpl; import org.hibernate.validator.test.engine.methodlevel.service.RepositoryBase; -import org.hibernate.validator.test.util.ValidationInvocationHandler; import static org.hibernate.validator.test.util.ConstraintViolationAssert.assertConstraintViolation; import static org.hibernate.validator.test.util.ConstraintViolationAssert.assertCorrectConstraintViolationMessages; import static org.hibernate.validator.test.util.ConstraintViolationAssert.assertNumberOfViolations; -import static org.hibernate.validator.test.util.ValidatorUtil.getMethodValidationProxy; +import static org.hibernate.validator.test.util.ValidatorUtil.getValidatingProxy; import static org.hibernate.validator.util.CollectionHelper.newHashMap; import static org.testng.Assert.assertEquals; import static org.testng.Assert.fail; @@ -66,18 +63,9 @@ public void setUpDefaultMethodValidator() { } private void setUpValidator(Integer parameterIndex, Class... groups) { - - MethodValidator validator = Validation.byProvider( HibernateValidator.class ) - .configure() - .buildValidatorFactory() - .getValidator() - .unwrap( MethodValidator.class ); - - ValidationInvocationHandler handler = new ValidationInvocationHandler( - new CustomerRepositoryImpl(), validator, parameterIndex, groups + repositoryBase = customerRepository = getValidatingProxy( + new CustomerRepositoryImpl(), parameterIndex, groups ); - - repositoryBase = customerRepository = (CustomerRepository) getMethodValidationProxy( handler ); } private void setUpValidator(Class... groups) { diff --git a/hibernate-validator/src/test/java/org/hibernate/validator/test/util/ConstraintViolationAssert.java b/hibernate-validator/src/test/java/org/hibernate/validator/test/util/ConstraintViolationAssert.java index d137b5b9d8..1250d61547 100644 --- a/hibernate-validator/src/test/java/org/hibernate/validator/test/util/ConstraintViolationAssert.java +++ b/hibernate-validator/src/test/java/org/hibernate/validator/test/util/ConstraintViolationAssert.java @@ -16,17 +16,20 @@ */ package org.hibernate.validator.test.util; -import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Path; +import org.hibernate.validator.method.MethodConstraintViolationException; + import static org.hibernate.validator.engine.PathImpl.createPathFromString; +import static org.hibernate.validator.util.CollectionHelper.newArrayList; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; -import static org.testng.FileAssert.fail; /** * This class provides useful functions to assert correctness of constraint violations raised @@ -50,19 +53,22 @@ private ConstraintViolationAssert() { * @param expectedMessages The expected constraint violation messages. */ public static void assertCorrectConstraintViolationMessages(Set> violations, String... expectedMessages) { - final List actualMessages = new ArrayList(); + + List expectedMessagesAsList = Arrays.asList( expectedMessages ); + + List actualMessages = newArrayList(); for ( ConstraintViolation violation : violations ) { actualMessages.add( violation.getMessage() ); } - assertEquals( actualMessages.size(), expectedMessages.length, "Wrong number of error messages" ); + Collections.sort( expectedMessagesAsList ); + Collections.sort( actualMessages ); - for ( String expectedMessage : expectedMessages ) { - assertTrue( - actualMessages.contains( expectedMessage ), - "The message '" + expectedMessage + "' should have been in the list of actual messages: " + actualMessages - ); - } + assertEquals( actualMessages, expectedMessagesAsList ); + } + + public static void assertCorrectConstraintViolationMessages(MethodConstraintViolationException e, String... expectedMessages) { + assertCorrectConstraintViolationMessages( e.getConstraintViolations(), expectedMessages ); } /** @@ -72,24 +78,24 @@ public static void assertCorrectConstraintViolationMessages(Set> violations, Class... expectedConstraintTypes) { - final List actualConstraintTypes = new ArrayList(); + public static void assertCorrectConstraintTypes(Set> violations, Class... expectedConstraintTypes) { + + List expectedConstraintTypeNames = newArrayList(); + for ( Class oneExpectedConstraintType : expectedConstraintTypes ) { + expectedConstraintTypeNames.add( oneExpectedConstraintType.getName() ); + } + + List actualConstraintTypeNames = newArrayList(); for ( ConstraintViolation violation : violations ) { - actualConstraintTypes.add( - ( violation.getConstraintDescriptor().getAnnotation() ).annotationType().getName() + actualConstraintTypeNames.add( + violation.getConstraintDescriptor().getAnnotation().annotationType().getName() ); } - assertEquals( - actualConstraintTypes.size(), expectedConstraintTypes.length, "Wrong number of constraint types" - ); + Collections.sort( expectedConstraintTypeNames ); + Collections.sort( actualConstraintTypeNames ); - for ( Class expectedConstraintType : expectedConstraintTypes ) { - assertTrue( - actualConstraintTypes.contains( expectedConstraintType.getName() ), - "The constraint type " + expectedConstraintType.getName() + " should have been violated" - ); - } + assertEquals( actualConstraintTypeNames, expectedConstraintTypeNames ); } /** @@ -99,28 +105,22 @@ public static void assertCorrectConstraintTypes(Set> violations, String... expectedPropertyPaths) { - final List propertyPathsOfViolations = new ArrayList(); + + List expectedPathsAsList = Arrays.asList( expectedPropertyPaths ); + + List actualPaths = newArrayList(); for ( ConstraintViolation violation : violations ) { - propertyPathsOfViolations.add( violation.getPropertyPath() ); + actualPaths.add( violation.getPropertyPath().toString() ); } - assertEquals( - propertyPathsOfViolations.size(), expectedPropertyPaths.length, "Wrong number of property paths" - ); + Collections.sort( expectedPathsAsList ); + Collections.sort( actualPaths ); - for ( String propertyPath : expectedPropertyPaths ) { - Path expectedPath = createPathFromString( propertyPath ); - boolean containsPath = false; - for ( Path actualPath : propertyPathsOfViolations ) { - if ( pathsAreEqual( expectedPath, actualPath ) ) { - containsPath = true; - break; - } - } - if ( !containsPath ) { - fail( expectedPath + " is not in the list of path instances contained in the actual constraint violations [" + propertyPathsOfViolations + "]" ); - } - } + assertEquals( actualPaths, expectedPathsAsList ); + } + + public static void assertCorrectPropertyPaths(MethodConstraintViolationException e, String... expectedPropertyPaths) { + assertCorrectPropertyPaths( e.getConstraintViolations(), expectedPropertyPaths ); } /** diff --git a/hibernate-validator/src/test/java/org/hibernate/validator/test/util/ValidatorUtil.java b/hibernate-validator/src/test/java/org/hibernate/validator/test/util/ValidatorUtil.java index 5eec6ac005..f8b6f5789e 100644 --- a/hibernate-validator/src/test/java/org/hibernate/validator/test/util/ValidatorUtil.java +++ b/hibernate-validator/src/test/java/org/hibernate/validator/test/util/ValidatorUtil.java @@ -16,6 +16,7 @@ */ package org.hibernate.validator.test.util; +import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.util.Locale; import javax.validation.Configuration; @@ -95,6 +96,10 @@ public static MethodValidator getMethodValidator() { return getValidator().unwrap( MethodValidator.class ); } + public static MethodValidator getMethodValidatorForMapping(ConstraintMapping... mappings) { + return getValidatorForProgrammaticMapping( mappings ).unwrap( MethodValidator.class ); + } + /** * Returns the {@code Configuration} object for Hibernate Validator. This method also sets the default locale to * english. @@ -203,20 +208,48 @@ public static ParameterDescriptor getParameterDescriptor(Class clazz, String return methodDescriptor.getParameterConstraints().get( parameterIndex ); } + public static T getValidatingProxy(I implementor) { + return getValidatingProxy( implementor, getMethodValidatorForMapping() ); + } + + public static T getValidatingProxy(I implementor, Class... validationGroups) { + return getValidatingProxy( implementor, getMethodValidatorForMapping(), validationGroups ); + } + + public static T getValidatingProxy(I implementor, Integer parameterIndex, Class... validationGroups) { + return getValidatingProxy( implementor, getMethodValidatorForMapping(), parameterIndex, validationGroups ); + } + + public static T getValidatingProxy(I implementor, ConstraintMapping... mappings) { + return getValidatingProxy( implementor, getMethodValidatorForMapping( mappings ) ); + } + + public static T getValidatingProxy(I implementor, MethodValidator methodValidator, Class... validationGroups) { + return getValidatingProxy( implementor, methodValidator, null, validationGroups ); + } + /** - * Returns an instance of proxy which dispatches method invocation to the given validation invocation handler. + * Creates a proxy for the given object which performs a validation of the given object's method constraints upon method invocation. * - * @param handler The validation invocation handler. + * @param The type to which the proxy shall be casted. Must be an interface. + * @param The type of the object to be proxied. + * @param implementor The object to be proxied. + * @param methodValidator The validator to use for method validation. + * @param parameterIndex Optionally the index of the parameter to which validation shall apply. + * @param validationGroups Optionally the groups which shall be evaluated. * - * @return a proxy instance configured with the given handler. - * - * @see ValidationInvocationHandler + * @return A proxy performing an automatic method validation. */ - public static Object getMethodValidationProxy(ValidationInvocationHandler handler) { - final Class wrappedObjectClass = handler.getWrapped().getClass(); - return Proxy.newProxyInstance( - wrappedObjectClass.getClassLoader(), - wrappedObjectClass.getInterfaces(), + @SuppressWarnings("unchecked") + private static T getValidatingProxy(I implementor, MethodValidator methodValidator, Integer parameterIndex, Class... validationGroups) { + + InvocationHandler handler = new ValidationInvocationHandler( + implementor, methodValidator, parameterIndex, validationGroups + ); + + return (T) Proxy.newProxyInstance( + implementor.getClass().getClassLoader(), + implementor.getClass().getInterfaces(), handler ); } diff --git a/pom.xml b/pom.xml index f6128debb9..668a96328d 100644 --- a/pom.xml +++ b/pom.xml @@ -36,6 +36,13 @@ Individual http://musingsofaprogrammingaddict.blogspot.com/ + + kevinpollet + Kevin Pollet + kevin.pollet@serli.com + Serli + http://www.serli.com +