[hibernate-commits] Hibernate SVN: r16022 - in validator/trunk/hibernate-validator/src: test/java/org/hibernate/validation/eg and 2 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Tue Feb 24 09:58:57 EST 2009


Author: hardy.ferentschik
Date: 2009-02-24 09:58:57 -0500 (Tue, 24 Feb 2009)
New Revision: 16022

Added:
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/AddressWithInvalidGroupSequence.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/ZipCodeCoherenceValidator.java
Removed:
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/ZipCode.java
Modified:
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaData.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintTree.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ExecutionContext.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaConstraint.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Dictonary.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolatorTest.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ValidatorImplTest.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/Address.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/GroupTest.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/ZipCodeCoherenceChecker.java
Log:
HV-113 Implemented redefining of default group for validate()
HV-123 Fixed typo

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaData.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaData.java	2009-02-23 10:17:40 UTC (rev 16021)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaData.java	2009-02-24 14:58:57 UTC (rev 16022)
@@ -61,7 +61,7 @@
 	/**
 	 * @return A map mapping defined group sequences to a list of groups.
 	 */
-	List<Class<?>> getDefaultGroupList();
+	List<Class<?>> getDefaultGroupSequence();
 
 	/**
 	 * @return A list of <code>MetaConstraint</code> instances encapsulating the information of all the constraints

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java	2009-02-23 10:17:40 UTC (rev 16021)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java	2009-02-24 14:58:57 UTC (rev 16022)
@@ -22,10 +22,10 @@
 import java.lang.reflect.Member;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Arrays;
 import javax.validation.BeanDescriptor;
 import javax.validation.GroupSequence;
 import javax.validation.PropertyDescriptor;
@@ -77,14 +77,13 @@
 
 	/**
 	 * Maps field and method names to their <code>ElementDescriptorImpl</code>.
-	 * FIXME This model is problematic as you can have conflicting names for fields and methods
 	 */
 	private Map<String, PropertyDescriptor> propertyDescriptors = new HashMap<String, PropertyDescriptor>();
 
 	/**
 	 * Maps group sequences to the list of group/sequences.
 	 */
-	private List<Class<?>> defaultGroupList = new ArrayList<Class<?>>();
+	private List<Class<?>> defaultGroupSequence = new ArrayList<Class<?>>();
 
 	private final BuiltinConstraints builtinConstraints;
 
@@ -135,13 +134,37 @@
 		initFieldConstraints( clazz );
 	}
 
+	/**
+	 * Checks whether there is a default group sequence defined for this class.
+	 * See HV-113.
+	 *
+	 * @param clazz The class to check for the <code>GroupSequence</code> annotation.
+	 */
 	private void initDefaultGroupSequence(Class<?> clazz) {
 		GroupSequence groupSequenceAnnotation = clazz.getAnnotation( GroupSequence.class );
 		if ( groupSequenceAnnotation == null ) {
-			defaultGroupList.add( Default.class );
+			defaultGroupSequence.add( Default.class );
 		}
 		else {
-			defaultGroupList.addAll( Arrays.asList( groupSequenceAnnotation.value() ) );
+			List<Class<?>> groupSequenceList = Arrays.asList( groupSequenceAnnotation.value() );
+			for ( Class<?> group : groupSequenceList ) {
+				if ( group.getName().equals( clazz.getName() ) ) {
+					defaultGroupSequence.add( Default.class );
+				}
+				else if ( group.getName().equals( Default.class.getName() ) ) {
+				   throw new ValidationException( "'Default.class' cannot appear in default group sequence list." );
+				}
+				else {
+					defaultGroupSequence.add( group );
+				}
+			}
+			if ( log.isDebugEnabled() ) {
+				log.debug(
+						"Bean {} redefines the Default group. Members of the default group sequence are: {}",
+						clazz.getName(),
+						defaultGroupSequence
+				);
+			}
 		}
 	}
 
@@ -150,7 +173,7 @@
 			List<ConstraintDescriptorImpl> fieldMetadata = findFieldLevelConstraints( field );
 			for ( ConstraintDescriptorImpl constraintDescription : fieldMetadata ) {
 				ReflectionHelper.setAccessibility( field );
-				MetaConstraint metaConstraint = new MetaConstraint( field, constraintDescription, new ArrayList<Class<?>>(defaultGroupList) );
+				MetaConstraint metaConstraint = new MetaConstraint( field, constraintDescription );
 				metaConstraintList.add( metaConstraint );
 			}
 			if ( field.isAnnotationPresent( Valid.class ) ) {
@@ -165,7 +188,7 @@
 			List<ConstraintDescriptorImpl> methodMetadata = findMethodLevelConstraints( method );
 			for ( ConstraintDescriptorImpl constraintDescription : methodMetadata ) {
 				ReflectionHelper.setAccessibility( method );
-				MetaConstraint metaConstraint = new MetaConstraint( method, constraintDescription, new ArrayList<Class<?>>(defaultGroupList) );
+				MetaConstraint metaConstraint = new MetaConstraint( method, constraintDescription );
 				metaConstraintList.add( metaConstraint );
 			}
 			if ( method.isAnnotationPresent( Valid.class ) ) {
@@ -178,7 +201,7 @@
 	private void initClassConstraints(Class clazz) {
 		List<ConstraintDescriptorImpl> classMetadata = findClassLevelConstraints( clazz );
 		for ( ConstraintDescriptorImpl constraintDescription : classMetadata ) {
-			MetaConstraint metaConstraint = new MetaConstraint( clazz, constraintDescription, new ArrayList<Class<?>>(defaultGroupList) );
+			MetaConstraint metaConstraint = new MetaConstraint( clazz, constraintDescription );
 			metaConstraintList.add( metaConstraint );
 		}
 	}
@@ -323,10 +346,6 @@
 		return cascadedMembers;
 	}
 
-	public List<Class<?>> getDefaultGroupList() {
-		return defaultGroupList;
-	}
-
 	public List<MetaConstraint> geMetaConstraintList() {
 		return metaConstraintList;
 	}
@@ -338,4 +357,8 @@
 	public PropertyDescriptor getPropertyDescriptors(String property) {
 		return propertyDescriptors.get( property );
 	}
+
+	public List<Class<?>> getDefaultGroupSequence() {
+		return defaultGroupSequence;
+	}
 }
\ No newline at end of file

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintTree.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintTree.java	2009-02-23 10:17:40 UTC (rev 16021)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintTree.java	2009-02-24 14:58:57 UTC (rev 16022)
@@ -83,9 +83,9 @@
 		return descriptor;
 	}
 
-	public void validateConstraints(Object value, Class beanClass, ExecutionContext executionContext) {
+	public <T> void validateConstraints(Object value, Class beanClass, ExecutionContext executionContext, List<ConstraintViolationImpl<T>> constraintViolations) {
 		for ( ConstraintTree tree : getChildren() ) {
-			tree.validateConstraints( value, beanClass, executionContext );
+			tree.validateConstraints( value, beanClass, executionContext, constraintViolations );
 		}
 
 		final Object leafBeanInstance = executionContext.peekValidatedObject();
@@ -99,15 +99,22 @@
 		if ( !validator.isValid( value, constraintContext ) ) {
 			for ( ConstraintValidatorContextImpl.ErrorMessage error : constraintContext.getErrorMessages() ) {
 				final String message = error.getMessage();
-				createConstraintViolation( value, beanClass, executionContext, leafBeanInstance, message, descriptor );
+				createConstraintViolation(
+						value, beanClass, executionContext, leafBeanInstance, message, descriptor, constraintViolations
+				);
 			}
 		}
-		if ( reportAsSingleViolation()
-				&& executionContext.getFailingConstraints().size() > 0 ) {
-			executionContext.clearFailingConstraints();
+		if ( reportAsSingleViolation() && constraintViolations.size() > 0 ) {
+			constraintViolations.clear();
 			final String message = ( String ) getParent().getDescriptor().getParameters().get( "message" );
 			createConstraintViolation(
-					value, beanClass, executionContext, leafBeanInstance, message, getParent().descriptor
+					value,
+					beanClass,
+					executionContext,
+					leafBeanInstance,
+					message,
+					getParent().descriptor,
+					constraintViolations
 			);
 		}
 	}
@@ -117,7 +124,7 @@
 				&& getParent().getDescriptor().isReportAsSingleViolation();
 	}
 
-	private <T> void createConstraintViolation(Object value, Class<T> beanClass, ExecutionContext<T> executionContext, Object leafBeanInstance, String messageTemplate, ConstraintDescriptor descriptor) {
+	private <T> void createConstraintViolation(Object value, Class<T> beanClass, ExecutionContext<T> executionContext, Object leafBeanInstance, String messageTemplate, ConstraintDescriptor descriptor, List<ConstraintViolationImpl<T>> constraintViolations) {
 		String interpolatedMessage = executionContext.getMessageResolver().interpolate(
 				messageTemplate,
 				descriptor,
@@ -134,7 +141,7 @@
 				executionContext.getCurrentGroup(),
 				descriptor
 		);
-		executionContext.addConstraintFailure( failingConstraintViolation );
+		constraintViolations.add( failingConstraintViolation );
 	}
 
 	/**

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ExecutionContext.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ExecutionContext.java	2009-02-23 10:17:40 UTC (rev 16021)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ExecutionContext.java	2009-02-24 14:58:57 UTC (rev 16022)
@@ -71,8 +71,8 @@
 	/**
 	 * Stack for keeping track of the currently validated object.
 	 */
-	private Stack<ValidatedBean> validatedObjectStack = new Stack<ValidatedBean>();
-
+	private Stack<Object> validatedObjectStack = new Stack<Object>();
+	
 	/**
 	 * The message resolver which should be used in this context.
 	 */
@@ -92,7 +92,7 @@
 		this.rootBean = rootBean;
 		this.messageResolver = messageResolver;
 		this.constraintValidatorFactory = constraintValidatorFactory;
-		validatedObjectStack.push( new ValidatedBean( object ) );
+		validatedObjectStack.push( object );
 		processedObjects = new HashMap<Class<?>, IdentitySet>();
 		propertyPath = "";
 		failingConstraintViolations = new ArrayList<ConstraintViolationImpl<T>>();
@@ -107,15 +107,15 @@
 	}
 
 	public Object peekValidatedObject() {
-		return validatedObjectStack.peek().bean;
+		return validatedObjectStack.peek();
 	}
 
 	public Class<?> peekValidatedObjectType() {
-		return validatedObjectStack.peek().beanType;
+		return validatedObjectStack.peek().getClass();
 	}
 
 	public void pushValidatedObject(Object validatedObject) {
-		validatedObjectStack.push( new ValidatedBean( validatedObject ) );
+		validatedObjectStack.push( validatedObject );
 	}
 
 	public void popValidatedObject() {
@@ -136,11 +136,11 @@
 
 	public void markProcessedForCurrentGroup() {
 		if ( processedObjects.containsKey( currentGroup ) ) {
-			processedObjects.get( currentGroup ).add( validatedObjectStack.peek().bean );
+			processedObjects.get( currentGroup ).add( validatedObjectStack.peek() );
 		}
 		else {
 			IdentitySet set = new IdentitySet();
-			set.add( validatedObjectStack.peek().bean );
+			set.add( validatedObjectStack.peek() );
 			processedObjects.put( currentGroup, set );
 		}
 	}
@@ -160,6 +160,12 @@
 		}
 	}
 
+	public void addConstraintFailures(List<ConstraintViolationImpl<T>> failingConstraintViolations) {
+		for(ConstraintViolationImpl<T> violation : failingConstraintViolations) {
+			addConstraintFailure( violation );
+		}
+	}
+
 	public List<ConstraintViolationImpl<T>> getFailingConstraints() {
 		return failingConstraintViolations;
 	}
@@ -207,26 +213,7 @@
 		return propertyPath;
 	}
 
-	public boolean needsValidation(Collection<Class<?>> groups) {
+	public boolean checkValidationRequired(Collection<Class<?>> groups) {
 		return groups.contains( currentGroup );
 	}
-
-	/**
-	 * @todo Is it useful to cache the object class?
-	 */
-	private static class ValidatedBean {
-
-		final Object bean;
-		final Class<?> beanType;
-
-		private ValidatedBean(Object bean) {
-			this.bean = bean;
-			if ( bean == null ) {
-				this.beanType = null;
-			}
-			else {
-				this.beanType = bean.getClass();
-			}
-		}
-	}
 }
\ No newline at end of file

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaConstraint.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaConstraint.java	2009-02-23 10:17:40 UTC (rev 16021)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaConstraint.java	2009-02-24 14:58:57 UTC (rev 16022)
@@ -23,9 +23,9 @@
 import java.lang.reflect.Type;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 import javax.validation.ConstraintDescriptor;
 import javax.validation.ValidationException;
-import javax.validation.groups.Default;
 
 import org.hibernate.validation.util.ReflectionHelper;
 
@@ -71,54 +71,41 @@
 	 */
 	private final ElementType elementType;
 
-	private final List<Class<?>> groupList;
-
-	public MetaConstraint(Type t, ConstraintDescriptor constraintDescriptor, List<Class<?>> defaultGroupList) {
-		this( t, null, null, ElementType.FIELD, constraintDescriptor, "", defaultGroupList );
+	public MetaConstraint(Type t, ConstraintDescriptor constraintDescriptor) {
+		this( t, null, null, ElementType.TYPE, constraintDescriptor, "" );
 	}
 
-	public MetaConstraint(Method m, ConstraintDescriptor constraintDescriptor, List<Class<?>> defaultGroupList) {
+	public MetaConstraint(Method m, ConstraintDescriptor constraintDescriptor) {
 		this(
 				null,
 				m,
 				null,
 				ElementType.METHOD,
 				constraintDescriptor,
-				ReflectionHelper.getPropertyName( m ),
-				defaultGroupList
+				ReflectionHelper.getPropertyName( m )
 		);
 	}
 
-	public MetaConstraint(Field f, ConstraintDescriptor constraintDescriptor, List<Class<?>> defaultGroupList) {
-		this( null, null, f, ElementType.FIELD, constraintDescriptor, f.getName(), defaultGroupList );
+	public MetaConstraint(Field f, ConstraintDescriptor constraintDescriptor) {
+		this( null, null, f, ElementType.FIELD, constraintDescriptor, f.getName());
 	}
 
-	private MetaConstraint(Type t, Method m, Field f, ElementType elementType, ConstraintDescriptor constraintDescriptor, String property, List<Class<?>> defaultGroupList) {
+	private MetaConstraint(Type t, Method m, Field f, ElementType elementType, ConstraintDescriptor constraintDescriptor, String property) {
 		this.type = t;
 		this.method = m;
 		this.field = f;
 		this.elementType = elementType;
 		this.propertyName = property;
 		constraintTree = new ConstraintTree( constraintDescriptor );
-		this.groupList = new ArrayList<Class<?>>( constraintDescriptor.getGroups() );
-		checkIfPartOfDefaultGroup( defaultGroupList );
 	}
 
-	private void checkIfPartOfDefaultGroup(List<Class<?>> defaultGroupList) {
-		for ( Class<?> clazz : defaultGroupList ) {
-			if ( groupList.contains( clazz ) ) {
-				groupList.add( Default.class );
-				break;
-			}
-		}
-	}
 
 	/**
 	 * @return Returns the list of groups this constraint is part of. This might include the default group even when
-	 * it is not explicitly specified, but part of the redefined default group list of the hosting bean.
+	 *         it is not explicitly specified, but part of the redefined default group list of the hosting bean.
 	 */
-	public List<Class<?>> getGroupList() {
-		return groupList;
+	public Set<Class<?>> getGroupList() {
+		return constraintTree.getDescriptor().getGroups();
 	}
 
 	/**
@@ -192,14 +179,26 @@
 		return constraintTree;
 	}
 
-	public <T> void validateConstraint(Class beanClass, ExecutionContext<T> executionContext) {
+	public <T> boolean validateConstraint(Class beanClass, ExecutionContext<T> executionContext) {
 		final Object leafBeanInstance = executionContext.peekValidatedObject();
 		Object value = getValue( leafBeanInstance );
-		constraintTree.validateConstraints( value, beanClass, executionContext );
+		List<ConstraintViolationImpl<T>> constraintViolations = new ArrayList<ConstraintViolationImpl<T>>();
+		constraintTree.validateConstraints( value, beanClass, executionContext, constraintViolations );
+		if ( constraintViolations.size() > 0 ) {
+			executionContext.addConstraintFailures( constraintViolations );
+			return false;
+		}
+		return true;
 	}
 
-	public <T> void validateConstraint(Class beanClass, Object value, ExecutionContext<T> executionContext) {
-		constraintTree.validateConstraints( value, beanClass, executionContext );
+	public <T> boolean validateConstraint(Class beanClass, Object value, ExecutionContext<T> executionContext) {
+		List<ConstraintViolationImpl<T>> constraintViolations = new ArrayList<ConstraintViolationImpl<T>>();
+		constraintTree.validateConstraints( value, beanClass, executionContext, constraintViolations );
+		if ( constraintViolations.size() > 0 ) {
+			executionContext.addConstraintFailures( constraintViolations );
+			return false;
+		}
+		return true;
 	}
 
 	private Type typeOfAnnoatedElement() {

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java	2009-02-23 10:17:40 UTC (rev 16021)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java	2009-02-24 14:58:57 UTC (rev 16022)
@@ -35,9 +35,12 @@
 import javax.validation.Validator;
 import javax.validation.groups.Default;
 
+import org.slf4j.Logger;
+
 import org.hibernate.validation.engine.groups.Group;
 import org.hibernate.validation.engine.groups.GroupChain;
 import org.hibernate.validation.engine.groups.GroupChainGenerator;
+import org.hibernate.validation.util.LoggerFactory;
 import org.hibernate.validation.util.PropertyIterator;
 import org.hibernate.validation.util.ReflectionHelper;
 
@@ -49,6 +52,8 @@
  * @todo Make all properties transient for serializability.
  */
 public class ValidatorImpl implements Validator {
+	private static final Logger log = LoggerFactory.make();
+
 	/**
 	 * Set of classes which can be used as index in a map.
 	 */
@@ -163,13 +168,14 @@
 
 		GroupChain groupChain = groupChainGenerator.getGroupChainFor( groups );
 		while ( groupChain.hasNext() ) {
+			int numberOfViolations = context.getFailingConstraints().size();
 			Group group = groupChain.next();
 			context.setCurrentGroup( group.getGroup() );
 
 			validateConstraints( context );
 			validateCascadedConstraints( context );
 
-			if ( groupChain.inSequence() && context.getFailingConstraints().size() > 0 ) {
+			if ( groupChain.inSequence() && context.getFailingConstraints().size() > numberOfViolations ) {
 				groupChain.moveToLastInCurrentSequence();
 			}
 		}
@@ -186,19 +192,46 @@
 		@SuppressWarnings("unchecked")
 		BeanMetaData<T> beanMetaData =
 				( BeanMetaData<T> ) getBeanMetaData( executionContext.peekValidatedObjectType() );
+		if ( executionContext.getCurrentGroup().getName().equals( Default.class.getName() ) ) {
+			List<Class<?>> defaultGroupSequence = beanMetaData.getDefaultGroupSequence();
+			if ( log.isDebugEnabled() && defaultGroupSequence.size() > 0 ) {
+				log.debug(
+						"Executing redefined Default group for bean {} as sequence {}",
+						beanMetaData.getBeanClass().getName(),
+						defaultGroupSequence
+				);
+			}
+			for ( Class<?> defaultSequenceMember : defaultGroupSequence ) {
+				executionContext.setCurrentGroup( defaultSequenceMember );
+				boolean validationSuccessful = validateConstraintsForBean( executionContext, beanMetaData );
+				if ( !validationSuccessful ) {
+					if ( log.isDebugEnabled() ) {
+						log.debug(
+								"Aborting validation of Default group sequence for {} due to constraint violation.",
+								beanMetaData.getBeanClass().getName()
+						);
+					}
+					break;
+				}
+			}
+		}
+		else {
+			validateConstraintsForBean( executionContext, beanMetaData );
+		}
+	}
+
+	private <T> boolean validateConstraintsForBean(ExecutionContext<T> executionContext, BeanMetaData<T> beanMetaData) {
+		boolean validationSuccessful = true;
 		for ( MetaConstraint metaConstraint : beanMetaData.geMetaConstraintList() ) {
-
 			executionContext.pushProperty( metaConstraint.getPropertyName() );
-
-			if ( !executionContext.needsValidation( metaConstraint.getGroupList() ) ) {
-				executionContext.popProperty();
-				continue;
+			if ( executionContext.checkValidationRequired( metaConstraint.getGroupList() ) ) {
+				boolean tmp = metaConstraint.validateConstraint( beanMetaData.getBeanClass(), executionContext );
+				validationSuccessful = validationSuccessful && tmp;
 			}
-
-			metaConstraint.validateConstraint( beanMetaData.getBeanClass(), executionContext );
 			executionContext.popProperty();
 		}
 		executionContext.markProcessedForCurrentGroup();
+		return validationSuccessful;
 	}
 
 	private <T> void validateCascadedConstraints(ExecutionContext<T> context) {
@@ -306,6 +339,7 @@
 				ExecutionContext<T> context = new ExecutionContext<T>(
 						object, messageInterpolator, constraintValidatorFactory
 				);
+				context.pushProperty( propertyIter.getOriginalProperty() );
 				metaConstraint.validateConstraint( object.getClass(), context );
 				failingConstraintViolations.addAll( context.getFailingConstraints() );
 			}

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Dictonary.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Dictonary.java	2009-02-23 10:17:40 UTC (rev 16021)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Dictonary.java	2009-02-24 14:58:57 UTC (rev 16022)
@@ -26,7 +26,6 @@
 /**
  * @author Hardy Ferentschik
  */
- at GroupSequence(value = { Default.class })
 public class Dictonary extends Book {
 	@NotNull(groups = Translate.class)
 	@NotEmpty(groups = Translate.class)

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolatorTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolatorTest.java	2009-02-23 10:17:40 UTC (rev 16021)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolatorTest.java	2009-02-24 14:58:57 UTC (rev 16022)
@@ -115,7 +115,7 @@
 		ConstraintDescriptorImpl<Size> sizeDescriptor = new ConstraintDescriptorImpl<Size>(
 				size, new Class<?>[] { }, new BuiltinConstraints()
 		);
-		expected = "size must be between -2147483648 and 2147483647";  // unkown token {}
+		expected = "size must be between 0 and 2147483647";  // unkown token {}
 		actual = interpolator.interpolate( size.message(), sizeDescriptor, null );
 		assertEquals( "Wrong substitution", expected, actual );
 	}

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ValidatorImplTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ValidatorImplTest.java	2009-02-23 10:17:40 UTC (rev 16021)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ValidatorImplTest.java	2009-02-24 14:58:57 UTC (rev 16022)
@@ -102,6 +102,7 @@
 	}
 
 	@Test
+	@SuppressWarnings( "NullArgumentToVariableArgMethod")
 	public void testPassingNullAsGroup() {
 		Validator validator = TestUtil.getValidator();
 		Customer customer = new Customer();

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/Address.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/Address.java	2009-02-23 10:17:40 UTC (rev 16021)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/Address.java	2009-02-24 14:58:57 UTC (rev 16022)
@@ -1,35 +1,64 @@
 package org.hibernate.validation.engine.groups;
 
+import javax.validation.GroupSequence;
 import javax.validation.constraints.NotNull;
 import javax.validation.constraints.Size;
-import javax.validation.GroupSequence;
 import javax.validation.groups.Default;
 
 /**
  * @author Emmanuel Bernard
  */
+ at GroupSequence({ Address.class, Address.HighLevelCoherence.class })
 @ZipCodeCoherenceChecker(groups = Address.HighLevelCoherence.class)
 public class Address {
-	@NotNull @Size(max = 50)
-	private String street1;
+	@NotNull
+	@Size(max = 50)
+	private String street;
 
-	@ZipCode
+	@NotNull
+	@Size(max = 5)
 	private String zipcode;
 
 	@NotNull
 	@Size(max = 30)
 	private String city;
 
+	public String getStreet() {
+		return street;
+	}
+
+	public void setStreet(String street) {
+		this.street = street;
+	}
+
+	public String getZipcode() {
+		return zipcode;
+	}
+
+	public void setZipcode(String zipcode) {
+		this.zipcode = zipcode;
+	}
+
+	public String getCity() {
+		return city;
+	}
+
+	public void setCity(String city) {
+		this.city = city;
+	}
+
 	/**
 	 * Check conherence on the overall object
 	 * Needs basic checking to be green first
 	 */
-	public interface HighLevelCoherence {}
+	public interface HighLevelCoherence {
+	}
 
 	/**
 	 * Check both basic constraints and high level ones.
 	 * High level constraints are not checked if basic constraints fail.
 	 */
-	@GroupSequence(value = {Default.class, HighLevelCoherence.class})
-	public interface Complete {}
+	@GroupSequence(value = { Default.class, HighLevelCoherence.class })
+	public interface Complete {
+	}
 }
\ No newline at end of file

Copied: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/AddressWithInvalidGroupSequence.java (from rev 16021, validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/Address.java)
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/AddressWithInvalidGroupSequence.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/AddressWithInvalidGroupSequence.java	2009-02-24 14:58:57 UTC (rev 16022)
@@ -0,0 +1,12 @@
+package org.hibernate.validation.engine.groups;
+
+import javax.validation.GroupSequence;
+import javax.validation.groups.Default;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at GroupSequence({ Default.class, AddressWithInvalidGroupSequence.HighLevelCoherence.class })
+public class AddressWithInvalidGroupSequence extends Address {
+
+}
\ No newline at end of file

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/GroupTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/GroupTest.java	2009-02-23 10:17:40 UTC (rev 16021)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/GroupTest.java	2009-02-24 14:58:57 UTC (rev 16022)
@@ -18,12 +18,13 @@
 package org.hibernate.validation.engine.groups;
 
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.Set;
 import javax.validation.ConstraintViolation;
+import javax.validation.ValidationException;
 import javax.validation.Validator;
 import javax.validation.groups.Default;
 
+import static junit.framework.Assert.fail;
 import static org.junit.Assert.assertEquals;
 import org.junit.Test;
 
@@ -38,8 +39,6 @@
 import org.hibernate.validation.util.TestUtil;
 import static org.hibernate.validation.util.TestUtil.assertConstraintViolation;
 
-import static junit.framework.Assert.fail;
-
 /**
  * Tests for the group and group sequence feature.
  *
@@ -78,8 +77,8 @@
 		book.setSubtitle( "Revised Edition of Hibernate in Action" );
 
 		constraintViolations = validator.validate( book, First.class, Second.class, Last.class );
+		assertEquals( "Wrong number of constraints", 1, constraintViolations.size() );
 		constraintViolation = constraintViolations.iterator().next();
-		assertEquals( "Wrong number of constraints", 1, constraintViolations.size() );
 		assertEquals( "Wrong message", "length must be between 0 and 30", constraintViolation.getMessage() );
 		assertEquals( "Wrong root entity", book, constraintViolation.getRootBean() );
 		assertEquals( "Wrong value", book.getSubtitle(), constraintViolation.getInvalidValue() );
@@ -280,21 +279,19 @@
 				constraintViolations.size()
 		);
 
-		Iterator<ConstraintViolation<User>> iter = constraintViolations.iterator();
-		while ( iter.hasNext() ) {
-			ConstraintViolation<User> violation = iter.next();
-			if ( violation.getPropertyPath().equals( "defaultCreditCard" ) ) {
+		for ( ConstraintViolation<User> constraintViolation : constraintViolations ) {
+			if ( constraintViolation.getPropertyPath().equals( "defaultCreditCard" ) ) {
 				assertConstraintViolation(
-						violation,
+						constraintViolation,
 						"may not be null",
 						User.class,
 						null,
 						"defaultCreditCard"
 				);
 			}
-			else if ( violation.getPropertyPath().equals( "phoneNumber" ) ) {
+			else if ( constraintViolation.getPropertyPath().equals( "phoneNumber" ) ) {
 				assertConstraintViolation(
-						violation,
+						constraintViolation,
 						"must match \"[0-9 -]?\"",
 						User.class,
 						"+46 123-456",
@@ -306,4 +303,57 @@
 			}
 		}
 	}
+
+	/**
+	 * HV-113
+	 */
+	@Test
+	public void testRedefiningDefaultGroup() {
+		Address address = new Address();
+		address.setStreet( "Guldmyntgatan" );
+		address.setCity( "Gothenborg" );
+
+		Validator validator = TestUtil.getValidator();
+
+		Set<ConstraintViolation<Address>> constraintViolations = validator.validate( address );
+		assertEquals(
+				"There should only be one violation for zipcode",
+				1,
+				constraintViolations.size()
+		);
+
+		ConstraintViolation<Address> violation = constraintViolations.iterator().next();
+		assertConstraintViolation( violation, "may not be null", address.getClass(), null, "zipcode" );
+
+		address.setZipcode( "41841" );
+
+		// now the second group in the re-defined default group causes an error
+		constraintViolations = validator.validate( address );
+		assertEquals(
+				"There should only be one violation for zipcode",
+				1,
+				constraintViolations.size()
+		);
+
+		violation = constraintViolations.iterator().next();
+		assertConstraintViolation( violation, "{validator.zipCodeCoherenceChecker}", address.getClass(), address, "" );
+	}
+
+	/**
+	 * HV-113
+	 */
+	@Test
+	public void testInvalidRedefinitionOfDefaultGroup() {
+		Address address = new AddressWithInvalidGroupSequence();
+		Validator validator = TestUtil.getValidator();
+		try {
+			validator.validate( address );
+			fail( "It shoud not be allowed to have Default.class in the group sequence of a class." );
+		}
+		catch ( ValidationException e ) {
+			assertEquals(
+					"Wrong message", "'Default.class' cannot appear in default group sequence list.", e.getMessage()
+			);
+		}
+	}
 }
\ No newline at end of file

Deleted: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/ZipCode.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/ZipCode.java	2009-02-23 10:17:40 UTC (rev 16021)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/ZipCode.java	2009-02-24 14:58:57 UTC (rev 16022)
@@ -1,7 +0,0 @@
-package org.hibernate.validation.engine.groups;
-
-/**
- * @author Emmanuel Bernard
- */
-public @interface ZipCode {
-}
\ No newline at end of file

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/ZipCodeCoherenceChecker.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/ZipCodeCoherenceChecker.java	2009-02-23 10:17:40 UTC (rev 16021)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/ZipCodeCoherenceChecker.java	2009-02-24 14:58:57 UTC (rev 16022)
@@ -6,13 +6,17 @@
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
 import static java.lang.annotation.ElementType.TYPE;
 import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import javax.validation.Constraint;
 
+import org.hibernate.validation.constraints.PatternValidator;
+
 /**
  * @author Emmanuel Bernard
  */
 @Target({ TYPE, ANNOTATION_TYPE })
 @Retention(RUNTIME)
 @Documented
+ at Constraint(validatedBy = ZipCodeCoherenceValidator.class)
 public @interface ZipCodeCoherenceChecker {
 	public abstract String message() default "{validator.zipCodeCoherenceChecker}";
 	public abstract Class<?>[] groups() default {};

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/ZipCodeCoherenceValidator.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/ZipCodeCoherenceValidator.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/ZipCodeCoherenceValidator.java	2009-02-24 14:58:57 UTC (rev 16022)
@@ -0,0 +1,34 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.validation.engine.groups;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class ZipCodeCoherenceValidator implements ConstraintValidator<ZipCodeCoherenceChecker, Address> {
+
+	public void initialize(ZipCodeCoherenceChecker parameters) {
+	}
+
+	public boolean isValid(Address value, ConstraintValidatorContext constraintValidatorContext) {
+		return false;
+	}
+}




More information about the hibernate-commits mailing list