[hibernate-commits] Hibernate SVN: r16182 - in validator/trunk/hibernate-validator/src: test/java/org/hibernate/validation/engine/graphnavigation and 1 other directory.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Wed Mar 18 09:45:24 EDT 2009


Author: hardy.ferentschik
Date: 2009-03-18 09:45:24 -0400 (Wed, 18 Mar 2009)
New Revision: 16182

Added:
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintValidatorContextImpl.java
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/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/engine/graphnavigation/GraphNavigationTest.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/graphnavigation/User.java
Log:
HV-126 Code refactoring and some more tests.

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-03-18 11:16:04 UTC (rev 16181)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintTree.java	2009-03-18 13:45:24 UTC (rev 16182)
@@ -29,6 +29,7 @@
 import javax.validation.ConstraintValidatorFactory;
 import javax.validation.UnexpectedTypeException;
 import javax.validation.ValidationException;
+import javax.validation.ConstraintViolation;
 
 import com.googlecode.jtype.TypeUtils;
 import org.slf4j.Logger;
@@ -101,7 +102,7 @@
 	 * @param <T> Type of the root bean for the current validation.
 	 * @param <V> Type of the value to be validated.
 	 */
-	public <T, V> void validateConstraints(V value, Type type, ExecutionContext<T> executionContext, List<ConstraintViolationImpl<T>> constraintViolations) {
+	public <T, V> void validateConstraints(V value, Type type, ExecutionContext<T> executionContext, List<ConstraintViolation<T>> constraintViolations) {
 		for ( ConstraintTree<?> tree : getChildren() ) {
 			tree.validateConstraints( value, type, executionContext, constraintViolations );
 		}
@@ -112,16 +113,18 @@
 		ConstraintValidator<A, V> validator = getInitalizedValidator(
 				value, type, executionContext.getConstraintValidatorFactory()
 		);
-		executionContext.setCurrentConstraintDescriptor( descriptor );
-		if ( !validator.isValid( value, executionContext ) ) {
-			constraintViolations.addAll( executionContext.createConstraintViolations( value ) );
+		ConstraintValidatorContextImpl constraintValidatorContext = new ConstraintValidatorContextImpl(
+				executionContext.peekParentPath(), executionContext.peekProperty(), descriptor
+		);
+		if ( !validator.isValid( value, constraintValidatorContext ) ) {
+			constraintViolations.addAll( executionContext.createConstraintViolations( value, constraintValidatorContext ) );
 		}
 		if ( reportAsSingleViolation() && constraintViolations.size() > 0 ) {
 			constraintViolations.clear();
 			final String message = ( String ) getParent().getDescriptor().getAttributes().get( "message" );
 			final String property = executionContext.peekPropertyPath();
-			ExecutionContext<T>.ErrorMessage error = executionContext.new ErrorMessage( message, property );
-			constraintViolations.add( executionContext.createConstraintViolation( value, error ) );
+			ConstraintValidatorContextImpl.ErrorMessage error = constraintValidatorContext.new ErrorMessage( message, property );
+			constraintViolations.add( executionContext.createConstraintViolation( value, error, descriptor ) );
 		}
 	}
 

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintValidatorContextImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintValidatorContextImpl.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintValidatorContextImpl.java	2009-03-18 13:45:24 UTC (rev 16182)
@@ -0,0 +1,106 @@
+// $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;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.validation.ConstraintDescriptor;
+import javax.validation.ConstraintValidatorContext;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class ConstraintValidatorContextImpl implements ConstraintValidatorContext {
+
+	private final List<ErrorMessage> errorMessages = new ArrayList<ErrorMessage>( 3 );
+	private final String property;
+	private final String propertyParent;
+	private final ConstraintDescriptor<?> constraintDescriptor;
+	private boolean defaultDisabled;
+
+
+	public ConstraintValidatorContextImpl(String propertyParent, String property, ConstraintDescriptor<?> constraintDescriptor) {
+		this.property = property;
+		this.propertyParent = propertyParent;
+		this.constraintDescriptor = constraintDescriptor;
+	}
+
+	public void disableDefaultError() {
+		defaultDisabled = true;
+	}
+
+	public String getDefaultErrorMessage() {
+		return ( String ) constraintDescriptor.getAttributes().get( "message" );
+	}
+
+	public void addError(String message) {
+		errorMessages.add( new ErrorMessage( message, buildPropertyPath( propertyParent, property ) ) );
+	}
+
+	public void addError(String message, String property) {
+		errorMessages.add( new ErrorMessage( message, buildPropertyPath( propertyParent, property ) ) );
+	}
+
+	public ConstraintDescriptor<?> getConstraintDescriptor() {
+		return constraintDescriptor;
+	}
+
+	public boolean isDefaultErrorDisabled() {
+		return defaultDisabled;
+	}
+
+	public List<ErrorMessage> getErrorMessages() {
+		List<ErrorMessage> returnedErrorMessages = new ArrayList<ErrorMessage>( errorMessages );
+		if ( !defaultDisabled ) {
+			returnedErrorMessages.add(
+					new ErrorMessage( getDefaultErrorMessage(), buildPropertyPath( propertyParent, property ) )
+			);
+		}
+		return returnedErrorMessages;
+	}
+
+	private String buildPropertyPath(String parent, String leaf) {
+		if ( ExecutionContext.PROPERTY_ROOT.equals( parent ) ) {
+			return leaf;
+		}
+		else {
+			return new StringBuilder().append( parent )
+					.append( ExecutionContext.PROPERTY_PATH_SEPERATOR )
+					.append( leaf )
+					.toString();
+		}
+	}
+
+	public class ErrorMessage {
+		private final String message;
+		private final String property;
+
+		public ErrorMessage(String message, String property) {
+			this.message = message;
+			this.property = property;
+		}
+
+		public String getMessage() {
+			return message;
+		}
+
+		public String getProperty() {
+			return property;
+		}
+	}
+}


Property changes on: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintValidatorContextImpl.java
___________________________________________________________________
Name: svn:keywords
   + Id

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-03-18 11:16:04 UTC (rev 16181)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ExecutionContext.java	2009-03-18 13:45:24 UTC (rev 16182)
@@ -26,10 +26,10 @@
 import java.util.Set;
 import java.util.Stack;
 import javax.validation.ConstraintDescriptor;
-import javax.validation.ConstraintValidatorContext;
 import javax.validation.ConstraintValidatorFactory;
 import javax.validation.MessageInterpolator;
 import javax.validation.TraversableResolver;
+import javax.validation.ConstraintViolation;
 
 import org.hibernate.validation.util.IdentitySet;
 
@@ -42,11 +42,11 @@
  * @todo Look for ways to improve this data structure. It is quite fragile and depends on the right oder of calls
  * in order to work.
  */
-public class ExecutionContext<T> implements ConstraintValidatorContext {
+public class ExecutionContext<T> {
 
-	private static final String PROPERTY_ROOT = "";
+	public static final String PROPERTY_ROOT = "";
 
-	private static final String PROPERTY_PATH_SEPERATOR = ".";
+	public static final String PROPERTY_PATH_SEPERATOR = ".";
 
 	/**
 	 * The root bean of the validation.
@@ -67,7 +67,7 @@
 	/**
 	 * A list of all failing constraints so far.
 	 */
-	private final List<ConstraintViolationImpl<T>> failingConstraintViolations;
+	private final List<ConstraintViolation<T>> failingConstraintViolations;
 
 	/**
 	 * The current property based based from the root bean.
@@ -80,12 +80,6 @@
 	private Class<?> currentGroup;
 
 	/**
-	 * Reference to a <code>ValidatedProperty</code> keeping track of the property we are currently validating,
-	 * together with required meta data.
-	 */
-	private ValidatedProperty currentValidatedProperty;
-
-	/**
 	 * Stack for keeping track of the currently validated bean.
 	 */
 	private Stack<Object> beanStack = new Stack<Object>();
@@ -126,38 +120,13 @@
 		processedObjects = new HashMap<Class<?>, IdentitySet>();
 		processedPaths = new IdentityHashMap<Object, Set<String>>();
 		propertyPath = new ArrayList<String>();
-		failingConstraintViolations = new ArrayList<ConstraintViolationImpl<T>>();
+		failingConstraintViolations = new ArrayList<ConstraintViolation<T>>();
 	}
 
 	public ConstraintValidatorFactory getConstraintValidatorFactory() {
 		return constraintValidatorFactory;
 	}
 
-	public void disableDefaultError() {
-		assert currentValidatedProperty != null;
-		currentValidatedProperty.disableDefaultError();
-	}
-
-	public String getDefaultErrorMessage() {
-		assert currentValidatedProperty != null;
-		return currentValidatedProperty.getDefaultErrorMessage();
-	}
-
-	public void addError(String message) {
-		assert currentValidatedProperty != null;
-		currentValidatedProperty.addError( message );
-	}
-
-	public void addError(String message, String property) {
-		assert currentValidatedProperty != null;
-		currentValidatedProperty.addError( message, property );
-	}
-
-	public void setCurrentConstraintDescriptor(ConstraintDescriptor constraintDescriptor) {
-		assert currentValidatedProperty != null;
-		currentValidatedProperty.setConstraintDescriptor( constraintDescriptor );
-	}
-
 	public Object peekCurrentBean() {
 		return beanStack.peek();
 	}
@@ -220,13 +189,13 @@
 		return objectsProcessedInCurrentGroups != null && objectsProcessedInCurrentGroups.contains( value );
 	}
 
-	public void addConstraintFailures(List<ConstraintViolationImpl<T>> failingConstraintViolations) {
-		for ( ConstraintViolationImpl<T> violation : failingConstraintViolations ) {
+	public void addConstraintFailures(List<ConstraintViolation<T>> failingConstraintViolations) {
+		for ( ConstraintViolation<T> violation : failingConstraintViolations ) {
 			addConstraintFailure( violation );
 		}
 	}
 
-	public List<ConstraintViolationImpl<T>> getFailingConstraints() {
+	public List<ConstraintViolation<T>> getFailingConstraints() {
 		return failingConstraintViolations;
 	}
 
@@ -236,7 +205,6 @@
 	 * @param property the new property to add to the current path.
 	 */
 	public void pushProperty(String property) {
-		currentValidatedProperty = new ValidatedProperty( peekPropertyPath(), property );
 		propertyPath.add( property );
 	}
 
@@ -246,7 +214,6 @@
 	public void popProperty() {
 		if ( propertyPath.size() > 0 ) {
 			propertyPath.remove( propertyPath.size() - 1 );
-			currentValidatedProperty = null;
 		}
 	}
 
@@ -267,14 +234,7 @@
 	}
 
 	public String peekPropertyPath() {
-		StringBuilder builder = new StringBuilder();
-		for ( int i = 0; i <= propertyPath.size() - 1; i++ ) {
-			builder.append( propertyPath.get( i ) );
-			if ( i < propertyPath.size() - 1 ) {
-				builder.append( PROPERTY_PATH_SEPERATOR );
-			}
-		}
-		return builder.toString();
+		return buildPath( propertyPath.size() - 1 );
 	}
 
 	public String peekProperty() {
@@ -284,6 +244,10 @@
 		return propertyPath.get( propertyPath.size() - 1 );
 	}
 
+	public String peekParentPath() {
+		return buildPath( propertyPath.size() - 2 );
+	}
+
 	public boolean isValidationRequired(MetaConstraint metaConstraint) {
 		if ( !metaConstraint.getGroupList().contains( currentGroup ) ) {
 			return false;
@@ -299,16 +263,18 @@
 		);
 	}
 
-	public List<ConstraintViolationImpl<T>> createConstraintViolations(Object value) {
+	public List<ConstraintViolationImpl<T>> createConstraintViolations(Object value, ConstraintValidatorContextImpl constraintValidatorContext) {
 		List<ConstraintViolationImpl<T>> constraintViolations = new ArrayList<ConstraintViolationImpl<T>>();
-		for ( ErrorMessage error : currentValidatedProperty.getErrorMessages() ) {
-			constraintViolations.add( createConstraintViolation( value, error ) );
+		for ( ConstraintValidatorContextImpl.ErrorMessage error : constraintValidatorContext.getErrorMessages() ) {
+			ConstraintViolationImpl<T> violation = createConstraintViolation(
+					value, error, constraintValidatorContext.getConstraintDescriptor()
+			);
+			constraintViolations.add( violation );
 		}
 		return constraintViolations;
 	}
 
-	public ConstraintViolationImpl<T> createConstraintViolation(Object value, ErrorMessage error) {
-		ConstraintDescriptor descriptor = currentValidatedProperty.getConstraintDescriptor();
+	public ConstraintViolationImpl<T> createConstraintViolation(Object value, ConstraintValidatorContextImpl.ErrorMessage error, ConstraintDescriptor<?> descriptor) {
 		String messageTemplate = error.getMessage();
 		String interpolatedMessage = messageInterpolator.interpolate(
 				messageTemplate,
@@ -325,6 +291,17 @@
 		);
 	}
 
+	private String buildPath(int index) {
+		StringBuilder builder = new StringBuilder();
+		for ( int i = 0; i <= index; i++ ) {
+			builder.append( propertyPath.get( i ) );
+			if ( i < index ) {
+				builder.append( PROPERTY_PATH_SEPERATOR );
+			}
+		}
+		return builder.toString();
+	}
+
 	private void markProcessed() {
 		markProcessForCurrentGroup();
 		if ( allowOneValidationPerPath ) {
@@ -354,90 +331,10 @@
 		}
 	}
 
-	private void addConstraintFailure(ConstraintViolationImpl<T> failingConstraintViolation) {
+	private void addConstraintFailure(ConstraintViolation<T> failingConstraintViolation) {
 		int i = failingConstraintViolations.indexOf( failingConstraintViolation );
 		if ( i == -1 ) {
 			failingConstraintViolations.add( failingConstraintViolation );
 		}
 	}
-
-	class ValidatedProperty {
-
-		private final List<ErrorMessage> errorMessages = new ArrayList<ErrorMessage>( 3 );
-		private final String property;
-		private final String propertyParent;
-		private ConstraintDescriptor<?> constraintDescriptor;
-		private boolean defaultDisabled;
-
-
-		private ValidatedProperty(String propertyParent, String property) {
-			this.property = property;
-			this.propertyParent = propertyParent;
-		}
-
-		public void setConstraintDescriptor(ConstraintDescriptor<?> constraintDescriptor) {
-			this.constraintDescriptor = constraintDescriptor;
-		}
-
-		public ConstraintDescriptor<?> getConstraintDescriptor() {
-			return constraintDescriptor;
-		}
-
-		void disableDefaultError() {
-			defaultDisabled = true;
-		}
-
-		public boolean isDefaultErrorDisabled() {
-			return defaultDisabled;
-		}
-
-		public String getDefaultErrorMessage() {
-			return ( String ) constraintDescriptor.getAttributes().get( "message" );
-		}
-
-		public void addError(String message) {
-			errorMessages.add( new ErrorMessage( message, buildPropertyPath( propertyParent, property ) ) );
-		}
-
-		public void addError(String message, String property) {
-			errorMessages.add( new ErrorMessage( message, buildPropertyPath( propertyParent, property ) ) );
-		}
-
-		public List<ErrorMessage> getErrorMessages() {
-			List<ErrorMessage> returnedErrorMessages = new ArrayList<ErrorMessage>( errorMessages );
-			if ( !defaultDisabled ) {
-				returnedErrorMessages.add(
-						new ErrorMessage( getDefaultErrorMessage(), buildPropertyPath( propertyParent, property ) )
-				);
-			}
-			return returnedErrorMessages;
-		}
-
-		private String buildPropertyPath(String parent, String leaf) {
-			if ( PROPERTY_ROOT.equals( parent ) ) {
-				return leaf;
-			}
-			else {
-				return new StringBuilder().append( parent ).append( PROPERTY_PATH_SEPERATOR ).append( leaf ).toString();
-			}
-		}
-	}
-
-	public class ErrorMessage {
-		private final String message;
-		private final String property;
-
-		public ErrorMessage(String message, String property) {
-			this.message = message;
-			this.property = property;
-		}
-
-		public String getMessage() {
-			return message;
-		}
-
-		public String getProperty() {
-			return property;
-		}
-	}
 }
\ 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-03-18 11:16:04 UTC (rev 16181)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaConstraint.java	2009-03-18 13:45:24 UTC (rev 16182)
@@ -28,6 +28,7 @@
 import java.util.List;
 import java.util.Set;
 import javax.validation.ConstraintDescriptor;
+import javax.validation.ConstraintViolation;
 
 import org.hibernate.validation.util.ReflectionHelper;
 
@@ -139,7 +140,7 @@
 	public <T> boolean validateConstraint(ExecutionContext<T> executionContext) {
 		final Object leafBeanInstance = executionContext.peekCurrentBean();
 		Object value = getValue( leafBeanInstance );
-		List<ConstraintViolationImpl<T>> constraintViolations = new ArrayList<ConstraintViolationImpl<T>>();
+		List<ConstraintViolation<T>> constraintViolations = new ArrayList<ConstraintViolation<T>>();
 		constraintTree.validateConstraints( value, typeOfAnnoatedElement(), executionContext, constraintViolations );
 		if ( constraintViolations.size() > 0 ) {
 			executionContext.addConstraintFailures( constraintViolations );
@@ -149,7 +150,7 @@
 	}
 
 	public <T> boolean validateConstraint(Object value, ExecutionContext<T> executionContext) {
-		List<ConstraintViolationImpl<T>> constraintViolations = new ArrayList<ConstraintViolationImpl<T>>();
+		List<ConstraintViolation<T>> constraintViolations = new ArrayList<ConstraintViolation<T>>();
 		constraintTree.validateConstraints( value, typeOfAnnoatedElement(), executionContext, constraintViolations );
 		if ( constraintViolations.size() > 0 ) {
 			executionContext.addConstraintFailures( constraintViolations );

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-03-18 11:16:04 UTC (rev 16181)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java	2009-03-18 13:45:24 UTC (rev 16182)
@@ -113,7 +113,7 @@
 				object, messageInterpolator, constraintValidatorFactory, traversableResolver
 		);
 
-		List<ConstraintViolationImpl<T>> list = validateInContext( context, groupChain );
+		List<ConstraintViolation<T>> list = validateInContext( context, groupChain );
 		return new HashSet<ConstraintViolation<T>>( list );
 	}
 
@@ -127,7 +127,7 @@
 		sanityCheckPropertyPath( propertyName );
 		GroupChain groupChain = determineGroupExecutionOrder( groups );
 
-		List<ConstraintViolationImpl<T>> failingConstraintViolations = new ArrayList<ConstraintViolationImpl<T>>();
+		List<ConstraintViolation<T>> failingConstraintViolations = new ArrayList<ConstraintViolation<T>>();
 		validateProperty( object, new PropertyIterator( propertyName ), failingConstraintViolations, groupChain );
 		return new HashSet<ConstraintViolation<T>>( failingConstraintViolations );
 	}
@@ -142,7 +142,7 @@
 		sanityCheckPropertyPath( propertyName );
 		GroupChain groupChain = determineGroupExecutionOrder( groups );
 
-		List<ConstraintViolationImpl<T>> failingConstraintViolations = new ArrayList<ConstraintViolationImpl<T>>();
+		List<ConstraintViolation<T>> failingConstraintViolations = new ArrayList<ConstraintViolation<T>>();
 		validateValue( beanType, value, new PropertyIterator( propertyName ), failingConstraintViolations, groupChain );
 		return new HashSet<ConstraintViolation<T>>( failingConstraintViolations );
 	}
@@ -182,7 +182,7 @@
 	 *
 	 * @return List of invalid constraints.
 	 */
-	private <T> List<ConstraintViolationImpl<T>> validateInContext(ExecutionContext<T> context, GroupChain groupChain) {
+	private <T> List<ConstraintViolation<T>> validateInContext(ExecutionContext<T> context, GroupChain groupChain) {
 		if ( context.peekCurrentBean() == null ) {
 			return Collections.emptyList();
 		}
@@ -349,7 +349,7 @@
 		}
 	}
 
-	private <T> void validateProperty(T object, PropertyIterator propertyIter, List<ConstraintViolationImpl<T>> failingConstraintViolations, GroupChain groupChain) {
+	private <T> void validateProperty(T object, PropertyIterator propertyIter, List<ConstraintViolation<T>> failingConstraintViolations, GroupChain groupChain) {
 
 		@SuppressWarnings("unchecked")
 		final Class<T> beanType = ( Class<T> ) object.getClass();
@@ -390,7 +390,7 @@
 		}
 	}
 
-	private <T> void validatePropertyForGroup(T object, PropertyIterator propertyIter, List<ConstraintViolationImpl<T>> failingConstraintViolations, Set<MetaConstraint<T, ?>> metaConstraints, Object hostingBeanInstance, Group group) {
+	private <T> void validatePropertyForGroup(T object, PropertyIterator propertyIter, List<ConstraintViolation<T>> failingConstraintViolations, Set<MetaConstraint<T, ?>> metaConstraints, Object hostingBeanInstance, Group group) {
 		int numberOfConstraintViolationsBefore = failingConstraintViolations.size();
 		BeanMetaData<T> beanMetaData = getBeanMetaData( metaConstraints.iterator().next().getBeanClass() );
 
@@ -427,7 +427,7 @@
 	}
 
 	@SuppressWarnings("unchecked")
-	private <T> void validateValue(Class<T> beanType, Object value, PropertyIterator propertyIter, List<ConstraintViolationImpl<T>> failingConstraintViolations, GroupChain groupChain) {
+	private <T> void validateValue(Class<T> beanType, Object value, PropertyIterator propertyIter, List<ConstraintViolation<T>> failingConstraintViolations, GroupChain groupChain) {
 		Set<MetaConstraint<T, ?>> metaConstraints = new HashSet<MetaConstraint<T, ?>>();
 		collectMetaConstraintsForPath( beanType, null, propertyIter, metaConstraints );
 
@@ -469,7 +469,7 @@
 		}
 	}
 
-	private <T> void validateValueForGroup(Object value, PropertyIterator propertyIter, List<ConstraintViolationImpl<T>> failingConstraintViolations, Set<MetaConstraint<T, ?>> metaConstraints, Group group) {
+	private <T> void validateValueForGroup(Object value, PropertyIterator propertyIter, List<ConstraintViolation<T>> failingConstraintViolations, Set<MetaConstraint<T, ?>> metaConstraints, Group group) {
 		int numberOfConstraintViolations = failingConstraintViolations.size();
 		BeanMetaData<T> beanMetaData = getBeanMetaData( metaConstraints.iterator().next().getBeanClass() );
 

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/graphnavigation/GraphNavigationTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/graphnavigation/GraphNavigationTest.java	2009-03-18 11:16:04 UTC (rev 16181)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/graphnavigation/GraphNavigationTest.java	2009-03-18 13:45:24 UTC (rev 16182)
@@ -17,11 +17,14 @@
 */
 package org.hibernate.validation.engine.graphnavigation;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Set;
 import javax.validation.ConstraintViolation;
 import javax.validation.Validator;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import org.junit.Test;
 
 import org.hibernate.validation.util.TestUtil;
@@ -59,5 +62,55 @@
 
 		Set<ConstraintViolation<Order>> constraintViolations = validator.validate( order );
 		assertEquals( "Wrong number of constraints", 3, constraintViolations.size() );
+
+		List<String> expectedErrorMessages = new ArrayList<String>();
+		expectedErrorMessages.add( "shippingAddress.addressline1" );
+		expectedErrorMessages.add( "customer.addresses[0].addressline1" );
+		expectedErrorMessages.add( "billingAddress.inhabitant.addresses[0].addressline1" );
+
+		for ( ConstraintViolation<Order> violation : constraintViolations ) {
+			if ( expectedErrorMessages.contains( violation.getPropertyPath() ) ) {
+				expectedErrorMessages.remove( violation.getPropertyPath() );
+			}
+		}
+
+		assertTrue( "All error messages should have occured once", expectedErrorMessages.size() == 0 );
 	}
+
+	@Test
+	public void testNoEndlessLoop() {
+		User john = new User( "John", null );
+		john.knows( john );
+
+		Validator validator = TestUtil.getValidator();
+
+		Set<ConstraintViolation<User>> constraintViolations = validator.validate( john );
+		assertEquals( "Wrong number of constraints", 1, constraintViolations.size() );
+		TestUtil.assertConstraintViolation(
+				constraintViolations.iterator().next(), "may not be null", User.class, null, "lastName"
+		);
+
+
+		User jane = new User( "Jane", "Doe" );
+		jane.knows( john );
+		john.knows( jane );
+
+		constraintViolations = validator.validate( john );
+		assertEquals( "Wrong number of constraints", 1, constraintViolations.size() );
+		TestUtil.assertConstraintViolation(
+				constraintViolations.iterator().next(), "may not be null", User.class, null, "lastName"
+		);
+
+		constraintViolations = validator.validate( jane );
+		assertEquals( "Wrong number of constraints", 1, constraintViolations.size() );
+		TestUtil.assertConstraintViolation(
+				constraintViolations.iterator().next(), "may not be null", User.class, null, "knowsUser[0].lastName"
+		);
+
+		john.setLastName( "Doe" );
+		constraintViolations = validator.validate( john );
+		assertEquals( "Wrong number of constraints", 0, constraintViolations.size() );
+
+
+	}
 }

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/graphnavigation/User.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/graphnavigation/User.java	2009-03-18 11:16:04 UTC (rev 16181)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/graphnavigation/User.java	2009-03-18 13:45:24 UTC (rev 16182)
@@ -1,4 +1,4 @@
-// $Id:$
+// $Id$
 /*
 * JBoss, Home of Professional Open Source
 * Copyright 2008, Red Hat Middleware LLC, and individual contributors
@@ -17,11 +17,11 @@
 */
 package org.hibernate.validation.engine.graphnavigation;
 
-import java.util.HashSet;
-import java.util.Set;
+import java.util.ArrayList;
+import java.util.List;
+import javax.validation.Valid;
 import javax.validation.constraints.NotNull;
 import javax.validation.groups.Default;
-import javax.validation.Valid;
 
 /**
  * @author Hardy Ferentschik
@@ -35,8 +35,11 @@
 	private String lastName;
 
 	@Valid
-	private Set<Address> addresses = new HashSet<Address>();
+	private List<Address> addresses = new ArrayList<Address>();
 
+	@Valid
+	private List<User> knowsUser = new ArrayList<User>();
+
 	public User() {
 	}
 
@@ -45,7 +48,7 @@
 		this.lastName = lastName;
 	}
 
-	public Set<Address> getAddresses() {
+	public List<Address> getAddresses() {
 		return addresses;
 	}
 
@@ -53,6 +56,14 @@
 		addresses.add( address );
 	}
 
+	public void knows(User user) {
+		knowsUser.add( user );
+	}
+
+	public List<User> getKnowsUser() {
+		return knowsUser;
+	}
+
 	public String getFirstName() {
 		return firstName;
 	}




More information about the hibernate-commits mailing list