[hibernate-commits] Hibernate SVN: r15763 - in validator/trunk: hibernate-validator/src/main/java/org/hibernate/validation/constraints and 6 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Fri Jan 9 08:45:30 EST 2009


Author: hardy.ferentschik
Date: 2009-01-09 08:45:30 -0500 (Fri, 09 Jan 2009)
New Revision: 15763

Added:
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/TestUtil.java
Modified:
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/Patterns.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidationContext.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ConstraintDescriptorImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/HibernateValidationProvider.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorFactoryBuilderImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorFactoryImpl.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/FrenchZipcode.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ConstraintCompositionTest.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ValidatorImplTest.java
   validator/trunk/pom.xml
   validator/trunk/validation-api/src/main/java/javax/validation/TraversableResolver.java
Log:
BVAL-31 added support for @OverridesParameters; refactoring

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/Patterns.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/Patterns.java	2009-01-09 11:32:38 UTC (rev 15762)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/Patterns.java	2009-01-09 13:45:30 UTC (rev 15763)
@@ -20,6 +20,7 @@
 import java.lang.annotation.Documented;
 import static java.lang.annotation.ElementType.FIELD;
 import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
 import java.lang.annotation.Retention;
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
 import java.lang.annotation.Target;
@@ -28,7 +29,7 @@
  * @author Hardy Ferentschik
  */
 @Documented
- at Target({ METHOD, FIELD })
+ at Target({ METHOD, FIELD, TYPE })
 @Retention(RUNTIME)
 public @interface Patterns {
 	Pattern[] value();

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidationContext.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidationContext.java	2009-01-09 11:32:38 UTC (rev 15762)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidationContext.java	2009-01-09 13:45:30 UTC (rev 15763)
@@ -68,7 +68,7 @@
 	private Class<?> currentGroup;
 
 	/**
-	 * Stack for keep track of the currently validated object.
+	 * Stack for keeping track of the currently validated object.
 	 */
 	private Stack<ValidatedBean> validatedObjectStack = new Stack<ValidatedBean>();
 
@@ -79,7 +79,7 @@
 
 	public ValidationContext(T rootBean, Object object) {
 		this.rootBean = rootBean;
-		validatedObjectStack.push( new ValidatedBean(object) );
+		validatedObjectStack.push( new ValidatedBean( object ) );
 		processedObjects = new HashMap<Class<?>, IdentitySet>();
 		propertyPath = "";
 		failingConstraintViolations = new ArrayList<ConstraintViolationImpl<T>>();
@@ -94,7 +94,7 @@
 	}
 
 	public void pushValidatedObject(Object validatedObject) {
-		validatedObjectStack.push( new ValidatedBean(validatedObject) );
+		validatedObjectStack.push( new ValidatedBean( validatedObject ) );
 	}
 
 	public void popValidatedObject() {
@@ -186,7 +186,9 @@
 		return groups.contains( currentGroup );
 	}
 
-	//TODO caching the object class is useful?
+	/**
+	 * @todo Is it useful to cache the object class?
+	 */
 	private static class ValidatedBean {
 
 		final Object bean;
@@ -194,7 +196,7 @@
 
 		private ValidatedBean(Object bean) {
 			this.bean = bean;
-			if (bean == null) {
+			if ( bean == null ) {
 				this.beanType = null;
 			}
 			else {

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-01-09 11:32:38 UTC (rev 15762)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java	2009-01-09 13:45:30 UTC (rev 15763)
@@ -30,15 +30,14 @@
 import javax.validation.BeanDescriptor;
 import javax.validation.Constraint;
 import javax.validation.ConstraintDescriptor;
+import javax.validation.ConstraintFactory;
 import javax.validation.ConstraintViolation;
 import javax.validation.MessageResolver;
 import javax.validation.TraversableResolver;
 import javax.validation.ValidationException;
 import javax.validation.Validator;
-import javax.validation.ConstraintFactory;
 import javax.validation.groups.Default;
 
-import org.hibernate.validation.Version;
 import org.hibernate.validation.impl.ConstraintViolationImpl;
 import org.hibernate.validation.util.PropertyIterator;
 import org.hibernate.validation.util.ReflectionHelper;
@@ -60,12 +59,6 @@
 		INDEXABLE_CLASS.add( String.class );
 	}
 
-
-	//TODO move to Factory at least
-	static {
-		Version.touch();
-	}
-
 	/**
 	 * Message resolver used  for interpolating error messages.
 	 */
@@ -151,10 +144,10 @@
 		BeanMetaData<T> beanMetaData =
 				( BeanMetaData<T> ) factory.getBeanMetaData( context.peekValidatedObjectType() );
 		for ( MetaConstraint metaConstraint : beanMetaData.getConstraintMetaDataList() ) {
-			ConstraintDescriptor constraintDescriptor = metaConstraint.getDescriptor();
+			ConstraintDescriptor mainConstraintDescriptor = metaConstraint.getDescriptor();
 			context.pushProperty( metaConstraint.getPropertyName() );
 
-			if ( !context.needsValidation( constraintDescriptor.getGroups() ) ) {
+			if ( !context.needsValidation( mainConstraintDescriptor.getGroups() ) ) {
 				context.popProperty();
 				continue;
 			}
@@ -162,9 +155,10 @@
 			final Object leafBeanInstance = context.peekValidatedObject();
 			Object value = metaConstraint.getValue( leafBeanInstance );
 
+			// we have to check the main constraint and all composing constraints
 			Set<ConstraintDescriptor> descriptors = new HashSet<ConstraintDescriptor>();
-			descriptors.addAll( constraintDescriptor.getComposingConstraints() );
-			descriptors.add(constraintDescriptor);
+			descriptors.addAll( mainConstraintDescriptor.getComposingConstraints() );
+			descriptors.add(mainConstraintDescriptor);
 			for (ConstraintDescriptor descriptor : descriptors) {
 				ConstraintContextImpl contextImpl = new ConstraintContextImpl( descriptor );
 				if ( !getConstraint( descriptor ).isValid( value, contextImpl ) ) {
@@ -353,6 +347,9 @@
 		return factory.getBeanMetaData( clazz ).getBeanDescriptor();
 	}
 
+	/**
+	 * @todo Implement composing constraints.
+	 */
 	private <T> void validateValue(Class<T> beanType, Object object, PropertyIterator propertyIter, List<ConstraintViolationImpl<T>> failingConstraintViolations, Class<?>... groups) {
 		ConstraintDescriptor constraintDescriptor = getConstraintDescriptorForPath( beanType, propertyIter );
 
@@ -434,7 +431,7 @@
 			for ( MetaConstraint metaConstraint : metaConstraintList ) {
 				ConstraintDescriptor constraintDescriptor = metaConstraint.getDescriptor();
 				if ( metaConstraint.getPropertyName().equals( propertyIter.getHead() ) ) {
-					matchingConstraintDescriptor = ( ConstraintDescriptor ) constraintDescriptor;
+					matchingConstraintDescriptor = constraintDescriptor;
 				}
 			}
 		}

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ConstraintDescriptorImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ConstraintDescriptorImpl.java	2009-01-09 11:32:38 UTC (rev 15762)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ConstraintDescriptorImpl.java	2009-01-09 13:45:30 UTC (rev 15763)
@@ -26,6 +26,7 @@
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.List;
 import javax.validation.Constraint;
 import javax.validation.ConstraintDescriptor;
 import javax.validation.ConstraintValidator;
@@ -51,21 +52,27 @@
 public class ConstraintDescriptorImpl implements ConstraintDescriptor {
 	private static final Logger log = LoggerFactory.make();
 	private static final Class<?>[] DEFAULT_GROUP = new Class<?>[] { Default.class };
+	private static final int OVERRIDES_PARAMETER_DEFAULT_INDEX = -1;
 
 	private final Annotation annotation;
 	private final Class<? extends Constraint> constraintClass;
 	private final Set<Class<?>> groups;
 	private final Map<String, Object> parameters;
 	private final Set<ConstraintDescriptor> composingConstraints = new HashSet<ConstraintDescriptor>();
+	private final Map<ClassIndexWrapper, Map<String, Object>> overrideParameters = new HashMap<ClassIndexWrapper, Map<String, Object>>();
 	private final boolean isReportAsSingleInvalidConstraint;
 
 	public ConstraintDescriptorImpl(Annotation annotation, Class<?>[] groups) {
-		this.annotation = annotation;
+		this( annotation, new HashSet<Class<?>>() );
 		if ( groups.length == 0 ) {
 			groups = DEFAULT_GROUP;
 		}
-		this.groups = new HashSet<Class<?>>();
 		this.groups.addAll( Arrays.asList( groups ) );
+	}
+
+	public ConstraintDescriptorImpl(Annotation annotation, Set<Class<?>> groups) {
+		this.annotation = annotation;
+		this.groups = groups;
 		this.parameters = getAnnotationParameters( annotation );
 
 		this.isReportAsSingleInvalidConstraint = annotation.annotationType().isAnnotationPresent(
@@ -82,49 +89,8 @@
 			this.constraintClass = constraintValidator.value();
 		}
 
-
-		// check for overrides
-		Map<ClassIndexWrapper, Map<String, Object>> overrideParameters = new HashMap<ClassIndexWrapper, Map<String, Object>>();
-		for ( Method m : annotation.annotationType().getMethods() ) {
-			if ( m.getAnnotation( OverridesParameter.class ) != null ) {
-				addOverrideParameter(
-						overrideParameters, getMethodValue( annotation, m ), m.getAnnotation( OverridesParameter.class )
-				);
-			}
-			else if ( m.getAnnotation( OverridesParameters.class ) != null ) {
-				addOverrideParameter(
-						overrideParameters,
-						getMethodValue( annotation, m ),
-						m.getAnnotation( OverridesParameters.class ).value()
-				);
-			}
-		}
-
-		// check for composing constraints
-		for ( Annotation a : annotation.annotationType().getDeclaredAnnotations() ) {
-			if ( ReflectionHelper.isConstraintAnnotation( a ) || ReflectionHelper.isBuiltInConstraintAnnotation( a ) ) {
-				AnnotationDescriptor annotationDescriptor = new AnnotationDescriptor(
-						a.annotationType(), getAnnotationParameters( a )
-				);
-				Map<String, Object> overrides = overrideParameters.get(
-						new ClassIndexWrapper(
-								a.annotationType(), -1
-						)
-				);
-				if ( overrides != null ) {
-					for ( Map.Entry<String, Object> entry : overrides.entrySet() ) {
-						annotationDescriptor.setValue( entry.getKey(), entry.getValue() );
-					}
-				}
-				Annotation annotationProxy = AnnotationFactory.create( annotationDescriptor );
-				ConstraintDescriptorImpl descriptor = new ConstraintDescriptorImpl( annotationProxy, groups );
-				composingConstraints.add( descriptor );
-				log.debug( "Adding composing constraint: " + descriptor );
-			}
-			else if ( ReflectionHelper.isMultiValueConstraint( a ) ) {
-				// todo - implement
-			}
-		}
+		parseOverrideParameters();
+		parseComposingConstraints();
 	}
 
 	/**
@@ -226,6 +192,69 @@
 		return value;
 	}
 
+	private void parseOverrideParameters() {
+		// check for overrides
+		for ( Method m : annotation.annotationType().getMethods() ) {
+			if ( m.getAnnotation( OverridesParameter.class ) != null ) {
+				addOverrideParameter(
+						overrideParameters, getMethodValue( annotation, m ), m.getAnnotation( OverridesParameter.class )
+				);
+			}
+			else if ( m.getAnnotation( OverridesParameters.class ) != null ) {
+				addOverrideParameter(
+						overrideParameters,
+						getMethodValue( annotation, m ),
+						m.getAnnotation( OverridesParameters.class ).value()
+				);
+			}
+		}
+	}
+
+	private void parseComposingConstraints() {
+		for ( Annotation declaredAnnotation : annotation.annotationType().getDeclaredAnnotations() ) {
+			if ( ReflectionHelper.isConstraintAnnotation( declaredAnnotation ) || ReflectionHelper.isBuiltInConstraintAnnotation(
+					declaredAnnotation
+			) ) {
+				ConstraintDescriptorImpl descriptor = createComposingConstraintDescriptor(
+						OVERRIDES_PARAMETER_DEFAULT_INDEX,
+						declaredAnnotation
+				);
+				composingConstraints.add( descriptor );
+				log.debug( "Adding composing constraint: " + descriptor );
+			}
+			else if ( ReflectionHelper.isMultiValueConstraint( declaredAnnotation ) ) {
+				List<Annotation> multiValueConstraints = ReflectionHelper.getMultiValueConstraints( declaredAnnotation );
+				int index = 1;
+				for ( Annotation constraintAnnotation : multiValueConstraints ) {
+					ConstraintDescriptorImpl descriptor = createComposingConstraintDescriptor(
+							index, constraintAnnotation
+					);
+					composingConstraints.add( descriptor );
+					log.debug( "Adding composing constraint: " + descriptor );
+					index++;
+				}
+			}
+		}
+	}
+
+	private ConstraintDescriptorImpl createComposingConstraintDescriptor(int index, Annotation constraintAnnotation) {
+		AnnotationDescriptor annotationDescriptor = new AnnotationDescriptor(
+				constraintAnnotation.annotationType(), getAnnotationParameters( constraintAnnotation )
+		);
+		Map<String, Object> overrides = overrideParameters.get(
+				new ClassIndexWrapper(
+						constraintAnnotation.annotationType(), index
+				)
+		);
+		if ( overrides != null ) {
+			for ( Map.Entry<String, Object> entry : overrides.entrySet() ) {
+				annotationDescriptor.setValue( entry.getKey(), entry.getValue() );
+			}
+		}
+		Annotation annotationProxy = AnnotationFactory.create( annotationDescriptor );
+		return new ConstraintDescriptorImpl( annotationProxy, groups );
+	}
+
 	private class ClassIndexWrapper {
 		final Class<?> clazz;
 		final int index;

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/HibernateValidationProvider.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/HibernateValidationProvider.java	2009-01-09 11:32:38 UTC (rev 15762)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/HibernateValidationProvider.java	2009-01-09 13:45:30 UTC (rev 15763)
@@ -25,6 +25,7 @@
 import javax.validation.spi.BootstrapState;
 
 import org.hibernate.validation.HibernateValidatorFactoryBuilder;
+import org.hibernate.validation.Version;
 
 /**
  * Default implementation of <code>ValidationProvider</code> within Hibernate validator.
@@ -42,8 +43,10 @@
 	}
 
 	public <T extends ValidatorFactoryBuilder<T>> T createSpecializedValidatorFactoryBuilder(BootstrapState state, Class<T> builderClass) {
-		if ( ! isSuitable( builderClass ) ) {
-			throw new ValidationException("Illegal call to createSpecializedValidatorFactoryBuilder() for a non suitable provider");
+		if ( !isSuitable( builderClass ) ) {
+			throw new ValidationException(
+					"Illegal call to createSpecializedValidatorFactoryBuilder() for a non suitable provider"
+			);
 		}
 		//cast protected  by isSuitable call
 		return builderClass.cast( new ValidatorFactoryBuilderImpl( this ) );

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorFactoryBuilderImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorFactoryBuilderImpl.java	2009-01-09 11:32:38 UTC (rev 15762)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorFactoryBuilderImpl.java	2009-01-09 13:45:30 UTC (rev 15763)
@@ -32,11 +32,17 @@
 import javax.validation.spi.ValidatorFactoryConfiguration;
 
 import org.hibernate.validation.HibernateValidatorFactoryBuilder;
+import org.hibernate.validation.Version;
 
 /**
  * @author Emmanuel Bernard
  */
 public class ValidatorFactoryBuilderImpl implements HibernateValidatorFactoryBuilder, ValidatorFactoryConfiguration {
+
+	static {
+		Version.touch();
+	}
+
 	//FIXME not sure why it is like that. We should cache these instances somehow. Static?
 	private final MessageResolver defaultMessageResolver = new ResourceBundleMessageResolver();
 	private final TraversableResolver defaultTraversableResolver = new DefaultTraversableResolver();
@@ -49,7 +55,7 @@
 	private TraversableResolver traversableResolver;
 
 	public ValidatorFactoryBuilderImpl(BootstrapState state) {
-		if (state.getValidationProviderResolver() == null) {
+		if ( state.getValidationProviderResolver() == null ) {
 			this.providerResolver = new DefaultValidationProviderResolver();
 		}
 		else {
@@ -62,7 +68,7 @@
 
 	public ValidatorFactoryBuilderImpl(ValidationProvider provider) {
 		if ( provider == null ) {
-			throw new ValidationException( "Assertion error: inconsistent ValidatorFactoryBuilderImpl construction");
+			throw new ValidationException( "Assertion error: inconsistent ValidatorFactoryBuilderImpl construction" );
 		}
 		this.provider = provider;
 		this.providerResolver = null;

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorFactoryImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorFactoryImpl.java	2009-01-09 11:32:38 UTC (rev 15762)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorFactoryImpl.java	2009-01-09 13:45:30 UTC (rev 15763)
@@ -34,7 +34,7 @@
  * @author Hardy Ferentschik
  */
 public class ValidatorFactoryImpl implements ValidatorFactoryImplementor {
-
+	
 	private final MessageResolver messageResolver;
 	private final TraversableResolver traversableResolver;
 	private final ConstraintFactory constraintFactory;

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/FrenchZipcode.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/FrenchZipcode.java	2009-01-09 11:32:38 UTC (rev 15762)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/FrenchZipcode.java	2009-01-09 13:45:30 UTC (rev 15763)
@@ -26,14 +26,19 @@
 import java.lang.annotation.Target;
 import javax.validation.ConstraintValidator;
 import javax.validation.OverridesParameter;
+import javax.validation.OverridesParameters;
 import javax.validation.constraints.NotNull;
 import javax.validation.constraints.Size;
 
+import org.hibernate.validation.constraints.Pattern;
+import org.hibernate.validation.constraints.Patterns;
+
 /**
  * @author Hardy Ferentschik
  */
 @NotNull
- at Size(max = 5)
+ at Size
+ at Patterns({ @Pattern(regex = "....."), @Pattern(regex = "bar") })
 @ConstraintValidator(FrenchZipcodeConstraint.class)
 @Documented
 @Target({ METHOD, FIELD, TYPE })
@@ -43,6 +48,16 @@
 
 	Class<?>[] groups() default { };
 
-	@OverridesParameter(constraint = Size.class, parameter = "min")
+	@OverridesParameters({
+			@OverridesParameter(constraint = Size.class, parameter = "min"),
+			@OverridesParameter(constraint = Size.class, parameter = "max")
+	})
 	int size() default 5;
+
+	@OverridesParameter(constraint = Size.class, parameter = "message")
+    String sizeMessage() default "A french zip code has a length of 5";
+
+
+	@OverridesParameter(constraint = Pattern.class, parameter = "regex", index=2)
+	String regex() default "\\d*";
 }

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ConstraintCompositionTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ConstraintCompositionTest.java	2009-01-09 11:32:38 UTC (rev 15762)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ConstraintCompositionTest.java	2009-01-09 13:45:30 UTC (rev 15763)
@@ -17,40 +17,21 @@
 */
 package org.hibernate.validation.engine;
 
-import java.util.HashSet;
 import java.util.Set;
 import javax.validation.ConstraintViolation;
-import javax.validation.ValidationException;
 import javax.validation.Validator;
-import javax.validation.Validation;
-import javax.validation.groups.Default;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import org.junit.Test;
 
-import org.hibernate.validation.eg.Actor;
-import org.hibernate.validation.eg.Address;
-import org.hibernate.validation.eg.Animal;
-import org.hibernate.validation.eg.Author;
-import org.hibernate.validation.eg.Book;
-import org.hibernate.validation.eg.Boy;
-import org.hibernate.validation.eg.Customer;
-import org.hibernate.validation.eg.Dictonary;
-import org.hibernate.validation.eg.Engine;
-import org.hibernate.validation.eg.EnglishDictonary;
-import org.hibernate.validation.eg.Order;
-import org.hibernate.validation.eg.Unconstraint;
-import org.hibernate.validation.eg.First;
-import org.hibernate.validation.eg.Second;
-import org.hibernate.validation.eg.Last;
-import org.hibernate.validation.eg.DefaultAlias;
-import org.hibernate.validation.eg.FrenchAddress;
-import org.hibernate.validation.HibernateValidatorFactoryBuilder;
+import static org.hibernate.validation.util.TestUtil.getHibernateValidator;
+import static org.hibernate.validation.util.TestUtil.assertNumberOfViolations;
+import static org.hibernate.validation.util.TestUtil.assertConstraintViolation;
+
 import org.hibernate.validation.constraints.NotNullConstraint;
 import org.hibernate.validation.constraints.SizeContraint;
-import org.hibernate.tck.annotations.SpecAssertion;
+import org.hibernate.validation.constraints.PatternConstraint;
+import org.hibernate.validation.eg.FrenchAddress;
 
 /**
  * Tests for the implementation of <code>Validator</code>.
@@ -59,19 +40,6 @@
  */
 public class ConstraintCompositionTest {
 
-	private Validator hibernateValidator;
-
-	//TODO should not be Hibernate specific in most case
-	private Validator getHibernateValidator() {
-		if ( hibernateValidator == null ) {
-			HibernateValidatorFactoryBuilder builder = Validation
-					.builderType( HibernateValidatorFactoryBuilder.class )
-					.getBuilder();
-			hibernateValidator = builder.build().getValidator();
-		}
-		return hibernateValidator;
-	}
-
 	@Test
 	public void testComposition() {
 		Validator validator = getHibernateValidator();
@@ -81,28 +49,88 @@
 		address.setAddressline2( "BP 12 " );
 		address.setCity( "Bordeaux" );
 		Set<ConstraintViolation<FrenchAddress>> constraintViolations = validator.validate( address );
-		assertEquals( "Wrong number of constraints", 1, constraintViolations.size() );
-		ConstraintViolation<FrenchAddress> violation = constraintViolations.iterator().next();
-		assertEquals(
-				"Wrong error type",
+		assertNumberOfViolations( constraintViolations, 1 );
+		assertConstraintViolation(
+				constraintViolations.iterator().next(),
+				"may not be null",
 				NotNullConstraint.class,
-				violation.getConstraintDescriptor().getConstraintClass()
+				FrenchAddress.class,
+				null,
+				"zipCode"
 		);
-		assertEquals( "Wrong message", "may not be null", violation.getInterpolatedMessage() );
 
+
+		address.setZipCode( "abc" );
+		constraintViolations = validator.validate( address );
+		assertNumberOfViolations( constraintViolations, 3 );
+		for ( ConstraintViolation violation : constraintViolations ) {
+			if ( violation.getInterpolatedMessage().equals( "A french zip code has a length of 5" ) ) {
+				assertConstraintViolation(
+						violation,
+						"A french zip code has a length of 5",
+						SizeContraint.class,
+						FrenchAddress.class,
+						"abc",
+						"zipCode"
+				);
+			}
+			else if ( violation.getInterpolatedMessage().equals( "must match \"d*\"" ) ) {
+				assertConstraintViolation(
+						violation,
+						"must match \"d*\"",
+						PatternConstraint.class,
+						FrenchAddress.class,
+						"abc",
+						"zipCode"
+				);
+			}
+			else if ( violation.getInterpolatedMessage().equals( "must match \".....\"" ) ) {
+				assertConstraintViolation(
+						violation,
+						"must match \".....\"" ,
+						PatternConstraint.class,
+						FrenchAddress.class,
+						"abc",
+						"zipCode"
+				);
+			}
+			else {
+				fail( "Wrong violation found." );
+			}
+		}
+
+
 		address.setZipCode( "123" );
 		constraintViolations = validator.validate( address );
-		assertEquals( "Wrong number of constraints", 1, constraintViolations.size() );
-		violation = constraintViolations.iterator().next();
-		assertEquals(
-				"Wrong error type",
-				SizeContraint.class,
-				violation.getConstraintDescriptor().getConstraintClass()
-		);
+		assertNumberOfViolations( constraintViolations, 2 );
+		for ( ConstraintViolation violation : constraintViolations ) {
+			if ( violation.getInterpolatedMessage().equals( "A french zip code has a length of 5" ) ) {
+				assertConstraintViolation(
+						violation,
+						"A french zip code has a length of 5",
+						SizeContraint.class,
+						FrenchAddress.class,
+						"123",
+						"zipCode"
+				);
+			}
+			else if ( violation.getInterpolatedMessage().equals( "must match \".....\"" ) ) {
+				assertConstraintViolation(
+						violation,
+						"must match \".....\"" ,
+						PatternConstraint.class,
+						FrenchAddress.class,
+						"123",
+						"zipCode"
+				);
+			}
+			else {
+				fail( "Wrong violation found." );
+			}
+		}
 
 		address.setZipCode( "33023" );
 		constraintViolations = validator.validate( address );
-		assertEquals( "Wrong number of constraints", 0, constraintViolations.size() );
-		assertEquals( "Wrong message", "size must be between 5 and 5", violation.getInterpolatedMessage() );
+		assertNumberOfViolations( constraintViolations, 0 );
 	}
 }
\ No newline at end of file

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-01-09 11:32:38 UTC (rev 15762)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ValidatorImplTest.java	2009-01-09 13:45:30 UTC (rev 15763)
@@ -22,7 +22,6 @@
 import javax.validation.ConstraintViolation;
 import javax.validation.ValidationException;
 import javax.validation.Validator;
-import javax.validation.Validation;
 import javax.validation.groups.Default;
 
 import static org.junit.Assert.assertEquals;
@@ -30,6 +29,7 @@
 import static org.junit.Assert.fail;
 import org.junit.Test;
 
+import org.hibernate.tck.annotations.SpecAssertion;
 import org.hibernate.validation.eg.Actor;
 import org.hibernate.validation.eg.Address;
 import org.hibernate.validation.eg.Animal;
@@ -37,17 +37,16 @@
 import org.hibernate.validation.eg.Book;
 import org.hibernate.validation.eg.Boy;
 import org.hibernate.validation.eg.Customer;
+import org.hibernate.validation.eg.DefaultAlias;
 import org.hibernate.validation.eg.Dictonary;
 import org.hibernate.validation.eg.Engine;
 import org.hibernate.validation.eg.EnglishDictonary;
-import org.hibernate.validation.eg.Order;
-import org.hibernate.validation.eg.Unconstraint;
 import org.hibernate.validation.eg.First;
-import org.hibernate.validation.eg.Second;
 import org.hibernate.validation.eg.Last;
-import org.hibernate.validation.eg.DefaultAlias;
-import org.hibernate.validation.HibernateValidatorFactoryBuilder;
-import org.hibernate.tck.annotations.SpecAssertion;
+import org.hibernate.validation.eg.Order;
+import org.hibernate.validation.eg.Second;
+import org.hibernate.validation.eg.Unconstraint;
+import org.hibernate.validation.util.TestUtil;
 
 /**
  * Tests for the implementation of <code>Validator</code>.
@@ -56,29 +55,11 @@
  */
 public class ValidatorImplTest {
 
-	private Validator hibernateValidator;
-
-	//TODO should not be Hibernate specific in most case
-	private Validator getHibernateValidator() {
-		if (hibernateValidator == null) {
-			HibernateValidatorFactoryBuilder builder = Validation
-					.builderType( HibernateValidatorFactoryBuilder.class )
-					.getBuilder();
-			hibernateValidator = builder.build().getValidator();
-		}
-		return hibernateValidator;
-	}
-
-
-	/**
-	 * JSR 303: Requirements on classes to be validates (3.1)
-	 * @jsr 3.1
-	 */
 	@SpecAssertion( section = {"3.1"} )
 	@Test
 	public void testWrongMethodName() {
 		try {
-			getHibernateValidator().getConstraintsForClass( Boy.class ).hasConstraints();
+			TestUtil.getHibernateValidator().getConstraintsForClass( Boy.class ).hasConstraints();
 			fail();
 		}
 		catch ( ValidationException e ) {
@@ -93,36 +74,36 @@
 
 	@Test(expected = IllegalArgumentException.class)
 	public void testNullParamterToValidatorImplConstructor() {
-		getHibernateValidator().getConstraintsForClass( null );
+		TestUtil.getHibernateValidator().getConstraintsForClass( null );
 	}
 
 	@Test
 	public void testUnconstraintClass() {
-		Validator validator = getHibernateValidator();
+		Validator validator = TestUtil.getHibernateValidator();
 		assertTrue( "There should be no constraints", !validator.getConstraintsForClass( Unconstraint.class ).hasConstraints() );
 	}
 
 	@Test
 	public void testHasConstraints() {
-		Validator validator = getHibernateValidator();
+		Validator validator = TestUtil.getHibernateValidator();
 		assertTrue( "There should be constraints", validator.getConstraintsForClass( Customer.class ).hasConstraints() );
 	}
 
 	@Test(expected = IllegalArgumentException.class)
 	public void testValidateWithNull() {
-		Validator validator = getHibernateValidator();
+		Validator validator = TestUtil.getHibernateValidator();
 		validator.validate( null );
 	}
 
 	@Test(expected = IllegalArgumentException.class)
 	public void testValidateWithNullProperty() {
-		Validator validator = getHibernateValidator();
+		Validator validator = TestUtil.getHibernateValidator();
 		validator.validateProperty( null, "firstName" );
 	}
 
 	@Test
 	public void testGroups() {
-		Validator validator = getHibernateValidator();
+		Validator validator = TestUtil.getHibernateValidator();
 
 		Author author = new Author();
 		author.setLastName( "" );
@@ -175,7 +156,7 @@
 
 	@Test
 	public void testDefaultGroupSequence() {
-		Validator validator = getHibernateValidator();
+		Validator validator = TestUtil.getHibernateValidator();
 
 		Author author = new Author();
 		author.setLastName( "" );
@@ -217,7 +198,7 @@
 
 	@Test
 	public void testBasicValidation() {
-		Validator validator = getHibernateValidator();
+		Validator validator = TestUtil.getHibernateValidator();
 
 		Customer customer = new Customer();
 		customer.setFirstName( "John" );
@@ -233,7 +214,7 @@
 
 	@Test
 	public void testGroupSequences() {
-		Validator validator = getHibernateValidator();
+		Validator validator = TestUtil.getHibernateValidator();
 
 		Dictonary dictonary = new Dictonary();
 		dictonary.setTitle( "English - German" );
@@ -249,7 +230,7 @@
 
 	@Test
 	public void testValidationFailureInMultipleGroups() {
-		Validator validator = getHibernateValidator();
+		Validator validator = TestUtil.getHibernateValidator();
 		Animal elepfant = new Animal();
 		elepfant.setName( "" );
 		elepfant.setDomain( Animal.Domain.EUKARYOTA );
@@ -274,13 +255,13 @@
 
 	@Test(expected = ValidationException.class)
 	public void testInvalidSequenceName() {
-		Validator validator = getHibernateValidator();
+		Validator validator = TestUtil.getHibernateValidator();
 		validator.getConstraintsForClass( EnglishDictonary.class ).hasConstraints();
 	}
 
 	@Test
 	public void testValidationMethod() {
-		Validator validator = getHibernateValidator();
+		Validator validator = TestUtil.getHibernateValidator();
 
 		Address address = new Address();
 		address.setAddressline1( null );
@@ -318,7 +299,7 @@
 
 	@Test
 	public void testValidateList() {
-		Validator validator = getHibernateValidator();
+		Validator validator = TestUtil.getHibernateValidator();
 
 		Customer customer = new Customer();
 		customer.setFirstName( "John" );
@@ -340,13 +321,10 @@
 
 	}
 
-	/**
-	 * JSR 303: Multi-valued constraints (2.2)
-	 * @jsr 2.2
-	 */
 	@Test
+	@SpecAssertion( section = {"2.2"} )
 	public void testMultiValueConstraint() {
-		Validator validator = getHibernateValidator();
+		Validator validator = TestUtil.getHibernateValidator();
 
 		Engine engine = new Engine();
 		engine.setSerialNumber( "mail at foobar.com" );
@@ -362,14 +340,10 @@
 		assertEquals( "Wrong number of constraints", 0, constraintViolations.size() );
 	}
 
-
-	/**
-	 * JSR 303: Object graph validation (3.5.1)
-	 * @jsr 3.5.1
-	 */
 	@Test
+	@SpecAssertion( section = {"3.5.1"} )
 	public void testGraphValidation() {
-		Validator validator = getHibernateValidator();
+		Validator validator = TestUtil.getHibernateValidator();
 
 		Actor clint = new Actor( "Clint", "Eastwood" );
 		Actor morgan = new Actor( "Morgan", "" );
@@ -394,7 +368,7 @@
 
 	@Test
 	public void testValidateValue() {
-		Validator validator = getHibernateValidator();
+		Validator validator = TestUtil.getHibernateValidator();
 
 		Order order = new Order();
 

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/TestUtil.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/TestUtil.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/TestUtil.java	2009-01-09 13:45:30 UTC (rev 15763)
@@ -0,0 +1,103 @@
+// $Id: ReflectionHelperTest.java 15751 2009-01-07 15:32:23Z hardy.ferentschik $
+/*
+* 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.util;
+
+import java.util.Set;
+import javax.validation.ConstraintViolation;
+import javax.validation.Validation;
+import javax.validation.Validator;
+
+import static org.junit.Assert.assertEquals;
+
+import org.hibernate.validation.HibernateValidatorFactoryBuilder;
+
+/**
+ * Tests for the <code>ReflectionHelper</code>.
+ *
+ * @author Hardy Ferentschik
+ */
+public class TestUtil {
+
+	private static Validator hibernateValidator;
+
+	private TestUtil() {
+	}
+
+	public static Validator getHibernateValidator() {
+		if ( hibernateValidator == null ) {
+			HibernateValidatorFactoryBuilder builder = Validation
+					.builderType( HibernateValidatorFactoryBuilder.class )
+					.getBuilder();
+			hibernateValidator = builder.build().getValidator();
+		}
+		return hibernateValidator;
+	}
+
+	public static void assertConstraintViolation(ConstraintViolation violation, String errorMessage, Class constraintType, Class rootBean, Object invalidValue, String propertyPath, Class leafBean) {
+		assertEquals(
+				"Wrong leaf bean type",
+				leafBean,
+				violation.getLeafBean().getClass()
+		);
+		assertConstraintViolation( violation, errorMessage, constraintType, rootBean, invalidValue, propertyPath );
+	}
+
+	public static void assertConstraintViolation(ConstraintViolation violation, String errorMessage, Class constraintType, Class rootBean, Object invalidValue, String propertyPath) {
+		assertEquals(
+				"Wrong propertyPath",
+				propertyPath,
+				violation.getPropertyPath()
+		);
+		assertConstraintViolation( violation, errorMessage, constraintType, rootBean, invalidValue );
+	}
+
+	public static void assertConstraintViolation(ConstraintViolation violation, String errorMessage, Class constraintType, Class rootBean, Object invalidValue) {
+		assertEquals(
+				"Wrong invalid value",
+				invalidValue,
+				violation.getInvalidValue()
+		);
+		assertConstraintViolation( violation, errorMessage, constraintType, rootBean );
+	}
+
+	public static void assertConstraintViolation(ConstraintViolation violation, String errorMessage, Class constraintType, Class rootBean) {
+		assertEquals(
+				"Wrong root bean type",
+				rootBean,
+				violation.getRootBean().getClass()
+		);
+		assertConstraintViolation( violation, errorMessage, constraintType );
+	}
+
+	public static void assertConstraintViolation(ConstraintViolation violation, String errorMessage, Class constraintType) {
+		assertEquals(
+				"Wrong constraint error Type",
+				constraintType,
+				violation.getConstraintDescriptor().getConstraintClass()
+		);
+		assertConstraintViolation( violation, errorMessage );
+	}
+
+	public static void assertConstraintViolation(ConstraintViolation violation, String message) {
+		assertEquals( "Wrong message", message, violation.getInterpolatedMessage() );
+	}
+
+	public static void assertNumberOfViolations(Set violations, int expectedViolations) {
+		assertEquals( "Wrong number of constraint violations", expectedViolations, violations.size() );
+	}
+}

Modified: validator/trunk/pom.xml
===================================================================
--- validator/trunk/pom.xml	2009-01-09 11:32:38 UTC (rev 15762)
+++ validator/trunk/pom.xml	2009-01-09 13:45:30 UTC (rev 15763)
@@ -124,6 +124,9 @@
                     <configuration>
                         <forkMode>always</forkMode>
                         <redirectTestOutputToFile>true</redirectTestOutputToFile>
+                        <includes>
+                            <include>**/*Test.java</include>
+                        </includes>
                     </configuration>
                 </plugin>
                 <plugin>

Modified: validator/trunk/validation-api/src/main/java/javax/validation/TraversableResolver.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/TraversableResolver.java	2009-01-09 11:32:38 UTC (rev 15762)
+++ validator/trunk/validation-api/src/main/java/javax/validation/TraversableResolver.java	2009-01-09 13:45:30 UTC (rev 15763)
@@ -6,7 +6,7 @@
  * Contract determining if a property can be accessed by the Bean Validation provider
  * This contract is called for each property either validated or traversed
  *
- * A traversable resolver implementation must me thread-safe
+ * A traversable resolver implementation must me thread-safe.
  *
  * @author Emmanuel Bernard
  */
@@ -14,14 +14,14 @@
 	/**
 	 * Determine if a property can be traversed by Bean Validation.
 	 *
-	 * @param traversableObject object hosting traversableProperty
-	 * @param traversableProperty name of the traqversable property
+	 * @param traversableObject object hosting <code>traversableProperty</code>.
+	 * @param traversableProperty name of the traqversable property.
 	 * @param rootBeanType type of the root object passed to the Validator.
-	 * @param pathToTraversableObject path from the root object to the traversableObject
-	 *        (using the path specification defined by Bean Validator)	 
-	 * @param elementType either FIELD or METHOD
+	 * @param pathToTraversableObject path from the root object to the <code>traversableProperty</code>
+	 *        (using the path specification defined by Bean Validator).
+	 * @param elementType either <code>FIELD</code> or <code>METHOD</code>.
 	 *
-	 * @return true if the property is traversable by Bean Validation
+	 * @return <code>true</code> if the property is traversable by Bean Validation, <code>false</code> otherwise.
 	 */
 	boolean isTraversable(Object traversableObject,
 						  String traversableProperty,




More information about the hibernate-commits mailing list