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

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Thu Jan 8 12:04:03 EST 2009


Author: hardy.ferentschik
Date: 2009-01-08 12:04:02 -0500 (Thu, 08 Jan 2009)
New Revision: 15756

Added:
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/LengthConstraint.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/SizeContraint.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/FrenchAddress.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/UKZipcode.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/UKZipcodeConstraint.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ConstraintCompositionTest.java
   validator/trunk/validation-api/src/main/java/javax/validation/OverridesParameters.java
Removed:
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/LengthConstraint.java
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/ConstraintContextImpl.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/ValidatorBuilderImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorFactoryImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/ReflectionHelper.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/annotationfactory/AnnotationDescriptor.java
   validator/trunk/hibernate-validator/src/main/resources/org/hibernate/validation/ValidationMessages.properties
   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/FrenchZipcodeConstraint.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/impl/ResourceBundleMessageResolverTest.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/annotationfactory/AnnotationFactoryTest.java
   validator/trunk/hibernate-validator/src/test/resources/log4j.properties
   validator/trunk/pom.xml
   validator/trunk/validation-api/src/main/java/javax/validation/OverridesParameter.java
   validator/trunk/validation-api/src/main/java/javax/validation/ValidatorBuilder.java
   validator/trunk/validation-api/src/main/java/javax/validation/constraints/Size.java
Log:
BVAL-31 first support for basic composition

Deleted: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/LengthConstraint.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/LengthConstraint.java	2009-01-08 09:36:38 UTC (rev 15755)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/LengthConstraint.java	2009-01-08 17:04:02 UTC (rev 15756)
@@ -1,50 +0,0 @@
-// $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.constraints;
-
-import javax.validation.Constraint;
-import javax.validation.ConstraintContext;
-
-/**
- * Check that a string's length is between min and max.
- *
- * @author Emmanuel Bernard
- * @author Gavin King
- */
-public class LengthConstraint implements Constraint<Length> {
-	private int min;
-	private int max;
-
-	public void initialize(Length parameters) {
-		min = parameters.min();
-		max = parameters.max();
-	}
-
-	public boolean isValid(Object value, ConstraintContext constraintContext) {
-		if ( value == null ) {
-			return true;
-		}
-		if ( !( value instanceof String ) ) {
-			throw new IllegalArgumentException( "Expected String type." );
-		}
-		String string = ( String ) value;
-		int length = string.length();
-		return length >= min && length <= max;
-	}
-
-}

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/LengthConstraint.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/LengthConstraint.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/LengthConstraint.java	2009-01-08 17:04:02 UTC (rev 15756)
@@ -0,0 +1,51 @@
+// $Id: SizeContraint.java 15494 2008-11-04 03:12:55Z epbernard $
+/*
+* 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.constraints;
+
+import javax.validation.Constraint;
+import javax.validation.ConstraintContext;
+import javax.validation.constraints.Size;
+
+/**
+ * Check that a string's length is between min and max.
+ *
+ * @author Emmanuel Bernard
+ * @author Gavin King
+ */
+public class LengthConstraint implements Constraint<Length> {
+	private int min;
+	private int max;
+
+	public void initialize(Length parameters) {
+		min = parameters.min();
+		max = parameters.max();
+	}
+
+	public boolean isValid(Object value, ConstraintContext constraintContext) {
+		if ( value == null ) {
+			return true;
+		}
+		if ( !( value instanceof String ) ) {
+			throw new IllegalArgumentException( "Expected String type." );
+		}
+		String string = ( String ) value;
+		int length = string.length();
+		return length >= min && length <= max;
+	}
+
+}
\ No newline at end of file

Copied: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/SizeContraint.java (from rev 15750, validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/LengthConstraint.java)
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/SizeContraint.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/SizeContraint.java	2009-01-08 17:04:02 UTC (rev 15756)
@@ -0,0 +1,55 @@
+// $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.constraints;
+
+import javax.validation.Constraint;
+import javax.validation.ConstraintContext;
+import javax.validation.constraints.Size;
+
+/**
+ * Check that a string's length is between min and max.
+ *
+ * @author Emmanuel Bernard
+ * @author Gavin King
+ */
+public class SizeContraint implements Constraint<Size> {
+	private int min;
+	private int max;
+
+	public void initialize(Size parameters) {
+		min = parameters.min();
+		max = parameters.max();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * @todo Implement collection support
+	 */
+	public boolean isValid(Object value, ConstraintContext constraintContext) {
+		if ( value == null ) {
+			return true;
+		}
+		if ( !( value instanceof String ) ) {
+			throw new IllegalArgumentException( "Expected String type." );
+		}
+		String string = ( String ) value;
+		int length = string.length();
+		return length >= min && length <= max;
+	}
+
+}


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

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-01-08 09:36:38 UTC (rev 15755)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java	2009-01-08 17:04:02 UTC (rev 15756)
@@ -27,9 +27,6 @@
 import java.util.List;
 import java.util.Map;
 import javax.validation.BeanDescriptor;
-import javax.validation.Constraint;
-import javax.validation.ConstraintFactory;
-import javax.validation.ConstraintValidator;
 import javax.validation.GroupSequence;
 import javax.validation.GroupSequences;
 import javax.validation.PropertyDescriptor;
@@ -38,10 +35,9 @@
 
 import org.slf4j.Logger;
 
+import org.hibernate.validation.impl.BeanDescriptorImpl;
 import org.hibernate.validation.impl.ConstraintDescriptorImpl;
-import org.hibernate.validation.impl.ConstraintFactoryImpl;
 import org.hibernate.validation.impl.ElementDescriptorImpl;
-import org.hibernate.validation.impl.BeanDescriptorImpl;
 import org.hibernate.validation.util.LoggerFactory;
 import org.hibernate.validation.util.ReflectionHelper;
 
@@ -51,7 +47,7 @@
  * instantiate an instance of this class and delegate the metadata extraction to it.
  *
  * @author Hardy Ferentschik
- * FIXME create an interface for MetadataProvider
+ *         FIXME create an interface for MetadataProvider
  */
 
 public class BeanMetaDataImpl<T> implements BeanMetaData<T> {
@@ -90,18 +86,12 @@
 	private Map<String, PropertyDescriptor> propertyDescriptors = new HashMap<String, PropertyDescriptor>();
 
 	/**
-	 * Factory to create acutal constraint instances from the annotated fields/method/class.
-	 */
-	private ConstraintFactory constraintFactory = new ConstraintFactoryImpl();
-
-	/**
 	 * Maps group sequences to the list of group/sequences.
 	 */
 	private Map<Class<?>, List<Class<?>>> groupSequences = new HashMap<Class<?>, List<Class<?>>>();
 
-	public BeanMetaDataImpl(Class<T> beanClass, ConstraintFactory constraintFactory) {
+	public BeanMetaDataImpl(Class<T> beanClass) {
 		this.beanClass = beanClass;
-		this.constraintFactory = constraintFactory;
 		createMetaData();
 	}
 
@@ -244,7 +234,7 @@
 
 		List<Annotation> constraints = new ArrayList<Annotation>();
 		if ( ReflectionHelper.isConstraintAnnotation( annotation ) ||
-				ReflectionHelper.isBuiltInConstraintAnnotation( annotation) ) {
+				ReflectionHelper.isBuiltInConstraintAnnotation( annotation ) ) {
 			constraints.add( annotation );
 		}
 
@@ -252,29 +242,14 @@
 		constraints.addAll( ReflectionHelper.getMultiValueConstraints( annotation ) );
 
 		for ( Annotation constraint : constraints ) {
-			if ( ReflectionHelper.isBuiltInConstraintAnnotation( constraint ) ) {
-				Class constraintClass = ReflectionHelper.getBuiltInConstraint( constraint );
-				final ConstraintDescriptorImpl constraintDescriptor = buildConstraintDescriptor(
-						constraint, constraintClass
-				);
-				constraintDescriptors.add( constraintDescriptor );
-				continue;
-			}
-
-			if ( ReflectionHelper.isConstraintAnnotation( constraint ) ) {
-				ConstraintValidator constraintValidator = constraint.annotationType()
-						.getAnnotation( ConstraintValidator.class );
-				final ConstraintDescriptorImpl constraintDescriptor = buildConstraintDescriptor(
-						constraint, constraintValidator.value()
-				);
-				constraintDescriptors.add( constraintDescriptor );
-			}
+			final ConstraintDescriptorImpl constraintDescriptor = buildConstraintDescriptor( constraint );
+			constraintDescriptors.add( constraintDescriptor );
 		}
 		return constraintDescriptors;
 	}
 
 	@SuppressWarnings("unchecked")
-	private <A extends Annotation> ConstraintDescriptorImpl buildConstraintDescriptor(A annotation, Class constraintClass) {
+	private <A extends Annotation> ConstraintDescriptorImpl buildConstraintDescriptor(A annotation) {
 		Class<?>[] groups = ReflectionHelper.getAnnotationParameter( annotation, "groups", Class[].class );
 		for ( Class<?> groupName : groups ) {
 			if ( groupSequences.containsKey( groupName ) ) {
@@ -282,23 +257,7 @@
 			}
 		}
 
-		Constraint<A> constraint;
-		try {
-			//unchecked
-			constraint = constraintFactory.getInstance( constraintClass );
-		}
-		catch ( RuntimeException e ) {
-			throw new ValidationException( "Unable to instantiate " + constraintClass, e );
-		}
-
-		try {
-			constraint.initialize( annotation );
-		}
-		catch ( RuntimeException e ) {
-			throw new ValidationException( "Unable to intialize " + constraint.getClass().getName(), e );
-		}
-
-		return new ConstraintDescriptorImpl( annotation, groups, constraint, constraintClass );
+		return new ConstraintDescriptorImpl(annotation, groups);
 	}
 
 	/**

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintContextImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintContextImpl.java	2009-01-08 09:36:38 UTC (rev 15755)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintContextImpl.java	2009-01-08 17:04:02 UTC (rev 15756)
@@ -17,14 +17,12 @@
 */
 package org.hibernate.validation.engine;
 
-import java.util.List;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.List;
 import javax.validation.ConstraintContext;
 import javax.validation.ConstraintDescriptor;
 
-import org.hibernate.validation.impl.ConstraintDescriptorImpl;
-
 /**
  * @author Emmanuel Bernard
  */
@@ -33,7 +31,7 @@
 	private final List<ErrorMessage> errorMessages;
 	private boolean defaultDisabled;
 
-	public ConstraintContextImpl(ConstraintDescriptorImpl constraintDescriptor) {
+	public ConstraintContextImpl(ConstraintDescriptor constraintDescriptor) {
 		this.constraintDescriptor = constraintDescriptor;
 		this.errorMessages = new ArrayList<ErrorMessage>(3);
 	}

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-08 09:36:38 UTC (rev 15755)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java	2009-01-08 17:04:02 UTC (rev 15756)
@@ -28,15 +28,17 @@
 import java.util.Map;
 import java.util.Set;
 import javax.validation.BeanDescriptor;
+import javax.validation.Constraint;
 import javax.validation.ConstraintDescriptor;
 import javax.validation.ConstraintViolation;
 import javax.validation.MessageResolver;
+import javax.validation.TraversableResolver;
+import javax.validation.ValidationException;
 import javax.validation.Validator;
-import javax.validation.TraversableResolver;
+import javax.validation.ConstraintFactory;
 import javax.validation.groups.Default;
 
 import org.hibernate.validation.Version;
-import org.hibernate.validation.impl.ConstraintDescriptorImpl;
 import org.hibernate.validation.impl.ConstraintViolationImpl;
 import org.hibernate.validation.util.PropertyIterator;
 import org.hibernate.validation.util.ReflectionHelper;
@@ -50,7 +52,7 @@
  */
 public class ValidatorImpl implements Validator {
 
-    private static final Set<Class<?>> INDEXABLE_CLASS = new HashSet<Class<?>>();
+	private static final Set<Class<?>> INDEXABLE_CLASS = new HashSet<Class<?>>();
 
 	static {
 		INDEXABLE_CLASS.add( Integer.class );
@@ -68,16 +70,18 @@
 	 * Message resolver used  for interpolating error messages.
 	 */
 	private final MessageResolver messageResolver;
-	
+
 	private final ValidatorFactoryImplementor factory;
 	private static final Class<?>[] DEFAULT_GROUP = new Class<?>[] { Default.class };
+	private final ConstraintFactory constraintFactory;
 	private final TraversableResolver traversableResolver;
 
 	public ValidatorImpl(ValidatorFactoryImplementor factory, MessageResolver messageResolver,
-						 TraversableResolver traversableResolver) {
+						 TraversableResolver traversableResolver, ConstraintFactory constraintFactory) {
 		this.factory = factory;
 		this.messageResolver = messageResolver;
 		this.traversableResolver = traversableResolver;
+		this.constraintFactory = constraintFactory;
 	}
 
 
@@ -143,11 +147,11 @@
 	 */
 	private <T> void validateConstraints(ValidationContext<T> context) {
 		//casting rely on the fact that root object is at the top of the stack
-		@SuppressWarnings( "unchecked" )
+		@SuppressWarnings("unchecked")
 		BeanMetaData<T> beanMetaData =
 				( BeanMetaData<T> ) factory.getBeanMetaData( context.peekValidatedObjectType() );
 		for ( MetaConstraint metaConstraint : beanMetaData.getConstraintMetaDataList() ) {
-			ConstraintDescriptorImpl constraintDescriptor = (ConstraintDescriptorImpl) metaConstraint.getDescriptor();
+			ConstraintDescriptor constraintDescriptor = metaConstraint.getDescriptor();
 			context.pushProperty( metaConstraint.getPropertyName() );
 
 			if ( !context.needsValidation( constraintDescriptor.getGroups() ) ) {
@@ -157,28 +161,33 @@
 
 			final Object leafBeanInstance = context.peekValidatedObject();
 			Object value = metaConstraint.getValue( leafBeanInstance );
-			ConstraintContextImpl contextImpl = new ConstraintContextImpl(constraintDescriptor);
 
-			if ( !constraintDescriptor.getConstraintImplementation().isValid( value, contextImpl ) ) {
-				for ( ConstraintContextImpl.ErrorMessage error : contextImpl.getErrorMessages() ) {
-					final String message = error.getMessage();
-					String interpolatedMessage = messageResolver.interpolate(
-							message,
-							constraintDescriptor,
-							leafBeanInstance
-					);
-					ConstraintViolationImpl<T> failingConstraintViolation = new ConstraintViolationImpl<T>(
-							message,
-							interpolatedMessage,
-							context.getRootBean(),
-							beanMetaData.getBeanClass(),
-							leafBeanInstance,
-							value,
-							context.peekPropertyPath(), //FIXME use error.getProperty()
-							context.getCurrentGroup(),
-							constraintDescriptor
-					);
-					context.addConstraintFailure( failingConstraintViolation );
+			Set<ConstraintDescriptor> descriptors = new HashSet<ConstraintDescriptor>();
+			descriptors.addAll( constraintDescriptor.getComposingConstraints() );
+			descriptors.add(constraintDescriptor);
+			for (ConstraintDescriptor descriptor : descriptors) {
+				ConstraintContextImpl contextImpl = new ConstraintContextImpl( descriptor );
+				if ( !getConstraint( descriptor ).isValid( value, contextImpl ) ) {
+					for ( ConstraintContextImpl.ErrorMessage error : contextImpl.getErrorMessages() ) {
+						final String message = error.getMessage();
+						String interpolatedMessage = messageResolver.interpolate(
+								message,
+								descriptor,
+								leafBeanInstance
+						);
+						ConstraintViolationImpl<T> failingConstraintViolation = new ConstraintViolationImpl<T>(
+								message,
+								interpolatedMessage,
+								context.getRootBean(),
+								beanMetaData.getBeanClass(),
+								leafBeanInstance,
+								value,
+								context.peekPropertyPath(), //FIXME use error.getProperty()
+								context.getCurrentGroup(),
+								descriptor
+						);
+						context.addConstraintFailure( failingConstraintViolation );
+					}
 				}
 			}
 			context.popProperty();
@@ -216,7 +225,8 @@
 	}
 
 	private <T> void validateCascadedConstraints(ValidationContext<T> context) {
-		List<Member> cascadedMembers = factory.getBeanMetaData( context.peekValidatedObjectType() ).getCascadedMembers();
+		List<Member> cascadedMembers = factory.getBeanMetaData( context.peekValidatedObjectType() )
+				.getCascadedMembers();
 		for ( Member member : cascadedMembers ) {
 			Type type = ReflectionHelper.typeOf( member );
 			context.pushProperty( ReflectionHelper.getPropertyName( member ) );
@@ -269,9 +279,11 @@
 
 
 	private <T> void validateProperty(T object, PropertyIterator propertyIter, List<ConstraintViolationImpl<T>> failingConstraintViolations, Class<?>... groups) {
-		if ( object == null ) throw new IllegalArgumentException("Validated object cannot be null");
-		@SuppressWarnings( "unchecked" )
-		final Class<T> beanType = (Class<T>) object.getClass();
+		if ( object == null ) {
+			throw new IllegalArgumentException( "Validated object cannot be null" );
+		}
+		@SuppressWarnings("unchecked")
+		final Class<T> beanType = ( Class<T> ) object.getClass();
 
 		DesrciptorValueWrapper wrapper = getConstraintDescriptorAndValueForPath( beanType, propertyIter, object );
 
@@ -292,12 +304,12 @@
 
 			for ( Class<?> expandedGroup : expandedGroups ) {
 
-				if ( !wrapper.descriptor.isInGroups( expandedGroup ) ) {
+				if ( !wrapper.descriptor.getGroups().contains( expandedGroup ) ) {
 					continue;
 				}
 
-				ConstraintContextImpl contextImpl = new ConstraintContextImpl(wrapper.descriptor);
-				if ( !wrapper.descriptor.getConstraintImplementation().isValid( wrapper.value, contextImpl ) ) {
+				ConstraintContextImpl contextImpl = new ConstraintContextImpl( wrapper.descriptor );
+				if ( !getConstraint( wrapper.descriptor ).isValid( wrapper.value, contextImpl ) ) {
 
 					for ( ConstraintContextImpl.ErrorMessage error : contextImpl.getErrorMessages() ) {
 						final String message = error.getMessage();
@@ -341,9 +353,8 @@
 		return factory.getBeanMetaData( clazz ).getBeanDescriptor();
 	}
 
-
 	private <T> void validateValue(Class<T> beanType, Object object, PropertyIterator propertyIter, List<ConstraintViolationImpl<T>> failingConstraintViolations, Class<?>... groups) {
-		ConstraintDescriptorImpl constraintDescriptor = getConstraintDescriptorForPath( beanType, propertyIter );
+		ConstraintDescriptor constraintDescriptor = getConstraintDescriptorForPath( beanType, propertyIter );
 
 		if ( constraintDescriptor == null ) {
 			return;
@@ -362,12 +373,12 @@
 
 			for ( Class<?> expandedGroup : expandedGroups ) {
 
-				if ( !constraintDescriptor.isInGroups( expandedGroup ) ) {
+				if ( !constraintDescriptor.getGroups().contains( expandedGroup ) ) {
 					continue;
 				}
 
-				ConstraintContextImpl contextImpl = new ConstraintContextImpl(constraintDescriptor);
-				if ( !constraintDescriptor.getConstraintImplementation().isValid( object, contextImpl ) ) {
+				ConstraintContextImpl contextImpl = new ConstraintContextImpl( constraintDescriptor );
+				if ( !getConstraint( constraintDescriptor ).isValid( object, contextImpl ) ) {
 					for ( ConstraintContextImpl.ErrorMessage error : contextImpl.getErrorMessages() ) {
 						final String message = error.getMessage();
 						String interpolatedMessage = messageResolver.interpolate(
@@ -383,7 +394,8 @@
 								null,
 								object,
 								propertyIter.getOriginalProperty(),  //FIXME use error.getProperty()
-								null, //FIXME why is this a null group!! Used to be "" string should it be Default. Looks weird
+								null,
+								//FIXME why is this a null group!! Used to be "" string should it be Default. Looks weird
 								constraintDescriptor
 						);
 						addFailingConstraint( failingConstraintViolations, failingConstraintViolation );
@@ -412,22 +424,22 @@
 	 *
 	 * @return The constraint descriptor matching the given path.
 	 */
-	private ConstraintDescriptorImpl getConstraintDescriptorForPath(Class<?> clazz, PropertyIterator propertyIter) {
+	private ConstraintDescriptor getConstraintDescriptorForPath(Class<?> clazz, PropertyIterator propertyIter) {
 
-		ConstraintDescriptorImpl matchingConstraintDescriptor = null;
+		ConstraintDescriptor matchingConstraintDescriptor = null;
 		propertyIter.split();
 
 		if ( !propertyIter.hasNext() ) {
-			List<MetaConstraint> metaConstraintList = factory.getBeanMetaData(clazz).getConstraintMetaDataList();
+			List<MetaConstraint> metaConstraintList = factory.getBeanMetaData( clazz ).getConstraintMetaDataList();
 			for ( MetaConstraint metaConstraint : metaConstraintList ) {
 				ConstraintDescriptor constraintDescriptor = metaConstraint.getDescriptor();
 				if ( metaConstraint.getPropertyName().equals( propertyIter.getHead() ) ) {
-					matchingConstraintDescriptor = ( ConstraintDescriptorImpl ) constraintDescriptor;
+					matchingConstraintDescriptor = ( ConstraintDescriptor ) constraintDescriptor;
 				}
 			}
 		}
 		else {
-			List<Member> cascadedMembers = factory.getBeanMetaData(clazz).getCascadedMembers();
+			List<Member> cascadedMembers = factory.getBeanMetaData( clazz ).getCascadedMembers();
 			for ( Member m : cascadedMembers ) {
 				if ( ReflectionHelper.getPropertyName( m ).equals( propertyIter.getHead() ) ) {
 					Type type = ReflectionHelper.typeOf( m );
@@ -439,7 +451,7 @@
 						}
 					}
 
-					matchingConstraintDescriptor = getConstraintDescriptorForPath( (Class<?>) type, propertyIter );
+					matchingConstraintDescriptor = getConstraintDescriptorForPath( ( Class<?> ) type, propertyIter );
 				}
 			}
 		}
@@ -456,18 +468,18 @@
 
 		// bottom out - there is only one token left
 		if ( !propertyIter.hasNext() ) {
-			List<MetaConstraint> metaConstraintList = factory.getBeanMetaData(clazz).getConstraintMetaDataList();
+			List<MetaConstraint> metaConstraintList = factory.getBeanMetaData( clazz ).getConstraintMetaDataList();
 			for ( MetaConstraint metaConstraint : metaConstraintList ) {
 				ConstraintDescriptor constraintDescriptor = metaConstraint.getDescriptor();
 				if ( metaConstraint.getPropertyName().equals( propertyIter.getHead() ) ) {
 					return new DesrciptorValueWrapper(
-							( ConstraintDescriptorImpl ) constraintDescriptor, metaConstraint.getValue( value )
+							constraintDescriptor, metaConstraint.getValue( value )
 					);
 				}
 			}
 		}
 		else {
-			List<Member> cascadedMembers = factory.getBeanMetaData(clazz).getCascadedMembers();
+			List<Member> cascadedMembers = factory.getBeanMetaData( clazz ).getCascadedMembers();
 			for ( Member m : cascadedMembers ) {
 				if ( ReflectionHelper.getPropertyName( m ).equals( propertyIter.getHead() ) ) {
 					ReflectionHelper.setAccessibility( m );
@@ -529,11 +541,30 @@
 		return isGroupSequence;
 	}
 
+	private Constraint getConstraint(ConstraintDescriptor descriptor) {
+		Constraint constraint;
+		try {
+			//unchecked
+			constraint = constraintFactory.getInstance( descriptor.getConstraintClass() );
+		}
+		catch ( RuntimeException e ) {
+			throw new ValidationException( "Unable to instantiate " + descriptor.getConstraintClass(), e );
+		}
+
+		try {
+			constraint.initialize( descriptor.getAnnotation() );
+		}
+		catch ( RuntimeException e ) {
+			throw new ValidationException( "Unable to intialize " + constraint.getClass().getName(), e );
+		}
+		return constraint;
+	}
+
 	private class DesrciptorValueWrapper {
-		final ConstraintDescriptorImpl descriptor;
+		final ConstraintDescriptor descriptor;
 		final Object value;
 
-		DesrciptorValueWrapper(ConstraintDescriptorImpl descriptor, Object value) {
+		DesrciptorValueWrapper(ConstraintDescriptor descriptor, Object value) {
 			this.descriptor = descriptor;
 			this.value = value;
 		}

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-08 09:36:38 UTC (rev 15755)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ConstraintDescriptorImpl.java	2009-01-08 17:04:02 UTC (rev 15756)
@@ -28,10 +28,20 @@
 import java.util.Set;
 import javax.validation.Constraint;
 import javax.validation.ConstraintDescriptor;
+import javax.validation.ConstraintValidator;
+import javax.validation.OverridesParameter;
+import javax.validation.OverridesParameters;
 import javax.validation.ReportAsViolationFromCompositeConstraint;
 import javax.validation.ValidationException;
 import javax.validation.groups.Default;
 
+import org.slf4j.Logger;
+
+import org.hibernate.validation.util.LoggerFactory;
+import org.hibernate.validation.util.ReflectionHelper;
+import org.hibernate.validation.util.annotationfactory.AnnotationFactory;
+import org.hibernate.validation.util.annotationfactory.AnnotationDescriptor;
+
 /**
  * Describe a single constraint.
  *
@@ -39,30 +49,84 @@
  * @author Hardy Ferentschik
  */
 public class ConstraintDescriptorImpl implements ConstraintDescriptor {
+	private static final Logger log = LoggerFactory.make();
+	private static final Class<?>[] DEFAULT_GROUP = new Class<?>[] { Default.class };
+
 	private final Annotation annotation;
-	private final Constraint constraintImplementation;
 	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 boolean isReportAsSingleInvalidConstraint;
-	private static final Class<?>[] DEFAULT_GROUP = new Class<?>[] { Default.class };
 
-	public ConstraintDescriptorImpl(Annotation annotation, Class<?>[] groups, Constraint validator, Class<? extends Constraint> constraintClass) {
+	public ConstraintDescriptorImpl(Annotation annotation, Class<?>[] groups) {
 		this.annotation = annotation;
 		if ( groups.length == 0 ) {
 			groups = DEFAULT_GROUP;
 		}
 		this.groups = new HashSet<Class<?>>();
 		this.groups.addAll( Arrays.asList( groups ) );
-		this.constraintImplementation = validator;
 		this.parameters = getAnnotationParameters( annotation );
+
 		this.isReportAsSingleInvalidConstraint = annotation.annotationType().isAnnotationPresent(
 				ReportAsViolationFromCompositeConstraint.class
 		);
-		this.constraintClass = constraintClass;
+
+
+		if ( ReflectionHelper.isBuiltInConstraintAnnotation( annotation ) ) {
+			this.constraintClass = ReflectionHelper.getBuiltInConstraint( annotation );
+		}
+		else {
+			ConstraintValidator constraintValidator = annotation.annotationType()
+					.getAnnotation( ConstraintValidator.class );
+			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
+			}
+		}
 	}
 
-
 	/**
 	 * {@inheritDoc}
 	 */
@@ -84,20 +148,7 @@
 		return constraintClass;
 	}
 
-	public boolean isInGroups(Class<?> group) {
-		return groups.contains( group );
-	}
-
 	/**
-	 * @return the constraint's implementation.
-	 *
-	 * @todo should we get rid of that and call the ConstraintFactory each time??
-	 */
-	public Constraint getConstraintImplementation() {
-		return constraintImplementation;
-	}
-
-	/**
 	 * {@inheritDoc}
 	 */
 	public Map<String, Object> getParameters() {
@@ -106,11 +157,9 @@
 
 	/**
 	 * {@inheritDoc}
-	 *
-	 * @todo Implement
 	 */
 	public Set<ConstraintDescriptor> getComposingConstraints() {
-		return Collections.emptySet();
+		return composingConstraints;
 	}
 
 	/**
@@ -120,6 +169,18 @@
 		return isReportAsSingleInvalidConstraint;
 	}
 
+	@Override
+	public String toString() {
+		return "ConstraintDescriptorImpl{" +
+				"annotation=" + annotation +
+				", constraintClass=" + constraintClass +
+				", groups=" + groups +
+				", parameters=" + parameters +
+				", composingConstraints=" + composingConstraints +
+				", isReportAsSingleInvalidConstraint=" + isReportAsSingleInvalidConstraint +
+				'}';
+	}
+
 	private Map<String, Object> getAnnotationParameters(Annotation annotation) {
 		Method[] declaredMethods = annotation.annotationType().getDeclaredMethods();
 		Map<String, Object> parameters = new HashMap<String, Object>( declaredMethods.length );
@@ -136,4 +197,70 @@
 		}
 		return Collections.unmodifiableMap( parameters );
 	}
+
+	private void addOverrideParameter(Map<ClassIndexWrapper, Map<String, Object>> overrideParameters, Object value, OverridesParameter... parameters) {
+
+		for ( OverridesParameter parameter : parameters ) {
+			ClassIndexWrapper wrapper = new ClassIndexWrapper( parameter.constraint(), parameter.index() );
+			Map<String, Object> map = overrideParameters.get( wrapper );
+			if ( map == null ) {
+				map = new HashMap<String, Object>();
+				overrideParameters.put( wrapper, map );
+			}
+			map.put( parameter.parameter(), value );
+		}
+	}
+
+	private Object getMethodValue(Annotation annotation, Method m) {
+		Object value;
+		try {
+			value = m.invoke( annotation );
+		}
+		// should never happen
+		catch ( IllegalAccessException e ) {
+			throw new ValidationException( "Unable to retrieve annotation parameter value." );
+		}
+		catch ( InvocationTargetException e ) {
+			throw new ValidationException( "Unable to retrieve annotation parameter value." );
+		}
+		return value;
+	}
+
+	private class ClassIndexWrapper {
+		final Class<?> clazz;
+		final int index;
+
+		ClassIndexWrapper(Class<?> clazz, int index) {
+			this.clazz = clazz;
+			this.index = index;
+		}
+
+		@Override
+		public boolean equals(Object o) {
+			if ( this == o ) {
+				return true;
+			}
+			if ( o == null || getClass() != o.getClass() ) {
+				return false;
+			}
+
+			ClassIndexWrapper that = ( ClassIndexWrapper ) o;
+
+			if ( index != that.index ) {
+				return false;
+			}
+			if ( clazz != null ? !clazz.equals( that.clazz ) : that.clazz != null ) {
+				return false;
+			}
+
+			return true;
+		}
+
+		@Override
+		public int hashCode() {
+			int result = clazz != null ? clazz.hashCode() : 0;
+			result = 31 * result + index;
+			return result;
+		}
+	}
 }

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorBuilderImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorBuilderImpl.java	2009-01-08 09:36:38 UTC (rev 15755)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorBuilderImpl.java	2009-01-08 17:04:02 UTC (rev 15756)
@@ -4,6 +4,7 @@
 import javax.validation.MessageResolver;
 import javax.validation.TraversableResolver;
 import javax.validation.Validator;
+import javax.validation.ConstraintFactory;
 
 import org.hibernate.validation.engine.ValidatorImpl;
 
@@ -16,13 +17,16 @@
 	private final MessageResolver factoryMessageResolver;
 	private final TraversableResolver factoryTraversableResolver;
 	private final ValidatorFactoryImpl validatorFactory;
+	private final ConstraintFactory constraintFactory;
 
 	public ValidatorBuilderImpl(ValidatorFactoryImpl validatorFactory,
 								MessageResolver factoryMessageResolver,
-								TraversableResolver factoryTraversableResolver) {
+								TraversableResolver factoryTraversableResolver,
+								ConstraintFactory constraintFactory) {
 		this.validatorFactory = validatorFactory;
 		this.factoryMessageResolver = factoryMessageResolver;
 		this.factoryTraversableResolver = factoryTraversableResolver;
+		this.constraintFactory = constraintFactory;
 		messageResolver(factoryMessageResolver);
 		traversableResolver(factoryTraversableResolver);
 	}
@@ -48,6 +52,6 @@
 	}
 
 	public Validator getValidator() {
-		return new ValidatorImpl( validatorFactory, messageResolver, traversableResolver );
+		return new ValidatorImpl( validatorFactory, messageResolver, traversableResolver, constraintFactory );
 	}
 }

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-08 09:36:38 UTC (rev 15755)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorFactoryImpl.java	2009-01-08 17:04:02 UTC (rev 15756)
@@ -63,7 +63,7 @@
 	}
 
 	public ValidatorBuilder defineValidatorState() {
-		return new ValidatorBuilderImpl(this, messageResolver, traversableResolver);
+		return new ValidatorBuilderImpl(this, messageResolver, traversableResolver, constraintFactory);
 	}
 
 	public <T> BeanMetaDataImpl<T> getBeanMetaData(Class<T> beanClass) {
@@ -72,7 +72,7 @@
 		@SuppressWarnings( "unchecked")
 		BeanMetaDataImpl<T> metadata = ( BeanMetaDataImpl<T> ) metadataProviders.get(beanClass);
 		if (metadata == null) {
-			metadata = new BeanMetaDataImpl<T>(beanClass, constraintFactory);
+			metadata = new BeanMetaDataImpl<T>(beanClass);
 			metadataProviders.put( beanClass, metadata );
 		}
 		return metadata;

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/ReflectionHelper.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/ReflectionHelper.java	2009-01-08 09:36:38 UTC (rev 15755)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/ReflectionHelper.java	2009-01-08 17:04:02 UTC (rev 15756)
@@ -37,11 +37,14 @@
 import java.util.ArrayList;
 import javax.validation.ConstraintValidator;
 import javax.validation.ValidationException;
+import javax.validation.Constraint;
 import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
 
 import org.slf4j.Logger;
 
 import org.hibernate.validation.constraints.NotNullConstraint;
+import org.hibernate.validation.constraints.SizeContraint;
 
 /**
  * Some reflection utility methods.
@@ -63,10 +66,13 @@
 	 * @todo Maybe move into another class
 	 * @todo Read mappings for example from a resource file
 	 */
-	public static Class getBuiltInConstraint(Annotation annotation) {
+	public static Class<? extends Constraint> getBuiltInConstraint(Annotation annotation) {
 		if ( annotation instanceof NotNull ) {
 			return NotNullConstraint.class;
 		}
+		if ( annotation instanceof Size ) {
+			return SizeContraint.class;
+		}
 		else {
 			return null;
 		}
@@ -143,6 +149,38 @@
 	}
 
 	/**
+	 * Checks whether a given annotation is a multi value constraint or not.
+	 *
+	 * @param annotation the annotation to check.
+	 *
+	 * @return <code>true</code> if the specified annotation is a multi value constraints, <code>false</code>
+	 * otherwise.
+	 */
+	public static boolean  isMultiValueConstraint(Annotation annotation) {
+		boolean isMultiValueConstraint = false;
+		try {
+			Method m = annotation.getClass().getMethod( "value" );
+			Class returnType = m.getReturnType();
+			if ( returnType.isArray() && returnType.getComponentType().isAnnotation() ) {
+				Annotation[] annotations = ( Annotation[] ) m.invoke( annotation );
+				for ( Annotation a : annotations ) {
+					if ( isConstraintAnnotation( a ) || isBuiltInConstraintAnnotation( a ) ) {
+						isMultiValueConstraint = true;
+					} else {
+						isMultiValueConstraint = false;
+						break;
+					}
+				}
+			}
+		}
+		catch ( Exception e ) {
+			// ignore
+		}
+		return isMultiValueConstraint;
+	}
+
+
+	/**
 	 * Checks whether a given annotation is a multi value constraint and returns the contained constraints if so.
 	 *
 	 * @param annotation the annotation to check.

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/annotationfactory/AnnotationDescriptor.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/annotationfactory/AnnotationDescriptor.java	2009-01-08 09:36:38 UTC (rev 15755)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/annotationfactory/AnnotationDescriptor.java	2009-01-08 17:04:02 UTC (rev 15756)
@@ -31,6 +31,7 @@
  *
  * @author Paolo Perrotta
  * @author Davide Marchignoli
+ * @author Hardy Ferentschik
  */
 public class AnnotationDescriptor {
 
@@ -39,9 +40,16 @@
 	private final Map<String, Object> elements = new HashMap<String, Object>();
 
 	public AnnotationDescriptor(Class<? extends Annotation> annotationType) {
-		type = annotationType;
+		this.type = annotationType;
 	}
 
+    public AnnotationDescriptor(Class<? extends Annotation> annotationType, Map<String, Object> elements) {
+		this.type = annotationType;
+		for (Map.Entry<String, Object> entry : elements.entrySet()) {
+			this.elements.put( entry.getKey(), entry.getValue() );
+		}
+	}
+
 	public void setValue(String elementName, Object value) {
 		elements.put( elementName, value );
 	}

Modified: validator/trunk/hibernate-validator/src/main/resources/org/hibernate/validation/ValidationMessages.properties
===================================================================
--- validator/trunk/hibernate-validator/src/main/resources/org/hibernate/validation/ValidationMessages.properties	2009-01-08 09:36:38 UTC (rev 15755)
+++ validator/trunk/hibernate-validator/src/main/resources/org/hibernate/validation/ValidationMessages.properties	2009-01-08 17:04:02 UTC (rev 15756)
@@ -1,4 +1,5 @@
 validator.notNull=may not be null
+validator.size=size must be between {min} and {max}
 validator.length=length must be between {min} and {max}
 validator.notEmpty=may not be empty
 validator.pattern=must match "{regex}"
\ No newline at end of file

Copied: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/FrenchAddress.java (from rev 15750, validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Address.java)
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/FrenchAddress.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/FrenchAddress.java	2009-01-08 17:04:02 UTC (rev 15756)
@@ -0,0 +1,35 @@
+// $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.eg;
+
+import javax.validation.constraints.NotNull;
+
+import org.hibernate.validation.constraints.Length;
+import org.hibernate.validation.eg.constraint.FrenchZipcode;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class FrenchAddress extends Address {
+
+	@FrenchZipcode
+	public String getZipCode() {
+		return super.getZipCode();
+	}
+
+}
\ No newline at end of file


Property changes on: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/FrenchAddress.java
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:mergeinfo
   + 

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-08 09:36:38 UTC (rev 15755)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/FrenchZipcode.java	2009-01-08 17:04:02 UTC (rev 15756)
@@ -25,6 +25,7 @@
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
 import java.lang.annotation.Target;
 import javax.validation.ConstraintValidator;
+import javax.validation.OverridesParameter;
 import javax.validation.constraints.NotNull;
 import javax.validation.constraints.Size;
 
@@ -32,7 +33,7 @@
  * @author Hardy Ferentschik
  */
 @NotNull
- at Size(min = 5, max = 5)
+ at Size(max = 5)
 @ConstraintValidator(FrenchZipcodeConstraint.class)
 @Documented
 @Target({ METHOD, FIELD, TYPE })
@@ -41,4 +42,7 @@
 	String message() default "Wrong zipcode";
 
 	Class<?>[] groups() default { };
+
+	@OverridesParameter(constraint = Size.class, parameter = "min")
+	int size() default 5;
 }

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/FrenchZipcodeConstraint.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/FrenchZipcodeConstraint.java	2009-01-08 09:36:38 UTC (rev 15755)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/FrenchZipcodeConstraint.java	2009-01-08 17:04:02 UTC (rev 15756)
@@ -29,6 +29,6 @@
 	}
 
 	public boolean isValid(Object object, ConstraintContext constraintContext) {
-		return false;
+		return true;
 	}
 }

Copied: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/UKZipcode.java (from rev 15751, 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/UKZipcode.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/UKZipcode.java	2009-01-08 17:04:02 UTC (rev 15756)
@@ -0,0 +1,44 @@
+// $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.eg.constraint;
+
+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;
+import javax.validation.ConstraintValidator;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+
+/**
+ * @author Hardy Ferentschik
+ */
+ at NotNull
+ at Size(min = 5, max = 5)
+ at ConstraintValidator(UKZipcodeConstraint.class)
+ at Documented
+ at Target({ METHOD, FIELD, TYPE })
+ at Retention(RUNTIME)
+public @interface UKZipcode {
+	public abstract String message() default "Wrong zipcode";
+
+	public abstract Class<?>[] groups() default { };
+}
\ No newline at end of file


Property changes on: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/UKZipcode.java
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:mergeinfo
   + 

Copied: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/UKZipcodeConstraint.java (from rev 15751, validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/FrenchZipcodeConstraint.java)
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/UKZipcodeConstraint.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/UKZipcodeConstraint.java	2009-01-08 17:04:02 UTC (rev 15756)
@@ -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.eg.constraint;
+
+import javax.validation.Constraint;
+import javax.validation.ConstraintContext;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class UKZipcodeConstraint implements Constraint<UKZipcode> {
+
+	public void initialize(UKZipcode parameters) {
+	}
+
+	public boolean isValid(Object object, ConstraintContext constraintContext) {
+		return false;
+	}
+}
\ No newline at end of file


Property changes on: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/UKZipcodeConstraint.java
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:mergeinfo
   + 

Copied: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ConstraintCompositionTest.java (from rev 15750, validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ValidatorImplTest.java)
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ConstraintCompositionTest.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ConstraintCompositionTest.java	2009-01-08 17:04:02 UTC (rev 15756)
@@ -0,0 +1,108 @@
+// $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.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 org.hibernate.validation.constraints.NotNullConstraint;
+import org.hibernate.validation.constraints.SizeContraint;
+import org.hibernate.tck.annotations.SpecAssertion;
+
+/**
+ * Tests for the implementation of <code>Validator</code>.
+ *
+ * @author Hardy Ferentschik
+ */
+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();
+
+		FrenchAddress address = new FrenchAddress();
+		address.setAddressline1( "10 rue des Treuils" );
+		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",
+				NotNullConstraint.class,
+				violation.getConstraintDescriptor().getConstraintClass()
+		);
+		assertEquals( "Wrong message", "may not be null", violation.getInterpolatedMessage() );
+
+		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()
+		);
+
+		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() );
+	}
+}
\ No newline at end of file


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

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/impl/ResourceBundleMessageResolverTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/impl/ResourceBundleMessageResolverTest.java	2009-01-08 09:36:38 UTC (rev 15755)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/impl/ResourceBundleMessageResolverTest.java	2009-01-08 17:04:02 UTC (rev 15756)
@@ -17,7 +17,6 @@
 */
 package org.hibernate.validation.impl;
 
-import java.lang.annotation.Annotation;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -25,13 +24,14 @@
 import java.util.NoSuchElementException;
 import java.util.ResourceBundle;
 import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
 
 import static org.junit.Assert.assertEquals;
 import org.junit.Before;
 import org.junit.Test;
 
-import org.hibernate.validation.constraints.Length;
-import org.hibernate.validation.constraints.NotNullConstraint;
+import org.hibernate.validation.util.annotationfactory.AnnotationDescriptor;
+import org.hibernate.validation.util.annotationfactory.AnnotationFactory;
 
 /**
  * Tests for message resolution.
@@ -42,53 +42,22 @@
 
 	private ResourceBundleMessageResolver resolver;
 	private NotNull notNull;
-	private Length length;
+	private Size size;
 
 	@Before
 	public void setUp() {
 		resolver = new ResourceBundleMessageResolver( new TestResources() );
-		notNull = new NotNull() {
-			public String message() {
-				return "{validator.notNull}";
-			}
 
-			public Class<?>[] groups() {
-				return new Class<?>[] { };
-			}
+		AnnotationDescriptor descriptor = new AnnotationDescriptor( NotNull.class );
+		notNull = AnnotationFactory.create( descriptor );
 
-			public Class<? extends Annotation> annotationType() {
-				return this.getClass();
-			}
-		};
-
-		length = new Length() {
-			public int min() {
-				return 0;
-			}
-
-			public int max() {
-				return Integer.MAX_VALUE;
-			}
-
-			public String message() {
-				return "{validator.length}";
-			}
-
-			public Class<?>[] groups() {
-				return new Class<?>[] { };
-			}
-
-			public Class<? extends Annotation> annotationType() {
-				return this.getClass();
-			}
-		};
+		descriptor = new AnnotationDescriptor( Size.class );
+		size = AnnotationFactory.create( descriptor );
 	}
 
 	@Test
 	public void testSuccessfulInterpolation() {
-		ConstraintDescriptorImpl desciptor = new ConstraintDescriptorImpl(
-				notNull, new Class<?>[] { }, new NotNullConstraint(), NotNullConstraint.class
-		);
+		ConstraintDescriptorImpl desciptor = new ConstraintDescriptorImpl( notNull, new Class<?>[] { } );
 
 		String expected = "replacement worked";
 		String actual = resolver.interpolate( "{foo}", desciptor, null );
@@ -109,9 +78,7 @@
 
 	@Test
 	public void testUnSuccessfulInterpolation() {
-		ConstraintDescriptorImpl desciptor = new ConstraintDescriptorImpl(
-				notNull, new Class<?>[] { }, new NotNullConstraint(), NotNullConstraint.class
-		);
+		ConstraintDescriptorImpl desciptor = new ConstraintDescriptorImpl( notNull, new Class<?>[] { } );
 		String expected = "foo";  // missing {}
 		String actual = resolver.interpolate( "foo", desciptor, null );
 		assertEquals( "Wrong substitution", expected, actual );
@@ -123,9 +90,7 @@
 
 	@Test
 	public void testUnkownTokenInterpolation() {
-		ConstraintDescriptorImpl desciptor = new ConstraintDescriptorImpl(
-				notNull, new Class<?>[] { }, new NotNullConstraint(), NotNullConstraint.class
-		);
+		ConstraintDescriptorImpl desciptor = new ConstraintDescriptorImpl( notNull, new Class<?>[] { } );
 		String expected = "{bar}";  // unkown token {}
 		String actual = resolver.interpolate( "{bar}", desciptor, null );
 		assertEquals( "Wrong substitution", expected, actual );
@@ -133,16 +98,14 @@
 
 	@Test
 	public void testDefaultInterpolation() {
-		ConstraintDescriptorImpl desciptor = new ConstraintDescriptorImpl(
-				notNull, new Class<?>[] { }, new NotNullConstraint(), NotNullConstraint.class
-		);
+		ConstraintDescriptorImpl desciptor = new ConstraintDescriptorImpl( notNull, new Class<?>[] { } );
 		String expected = "may not be null";
 		String actual = resolver.interpolate( notNull.message(), desciptor, null );
 		assertEquals( "Wrong substitution", expected, actual );
 
-		desciptor = new ConstraintDescriptorImpl( length, new Class<?>[] { }, new NotNullConstraint(), NotNullConstraint.class );
-		expected = "length must be between 0 and 2147483647";  // unkown token {}
-		actual = resolver.interpolate( length.message(), desciptor, null );
+		desciptor = new ConstraintDescriptorImpl( size, new Class<?>[] { } );
+		expected = "size must be between -2147483648 and 2147483647";  // unkown token {}
+		actual = resolver.interpolate( size.message(), desciptor, null );
 		assertEquals( "Wrong substitution", expected, actual );
 	}
 

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/annotationfactory/AnnotationFactoryTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/annotationfactory/AnnotationFactoryTest.java	2009-01-08 09:36:38 UTC (rev 15755)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/annotationfactory/AnnotationFactoryTest.java	2009-01-08 17:04:02 UTC (rev 15756)
@@ -17,10 +17,11 @@
 */
 package org.hibernate.validation.util.annotationfactory;
 
+import javax.validation.constraints.Size;
+
 import static org.junit.Assert.assertEquals;
 import org.junit.Test;
 
-import org.hibernate.validation.constraints.Length;
 import org.hibernate.validation.constraints.Pattern;
 
 /**
@@ -30,14 +31,14 @@
 
 	@Test
 	public void createAnnotationProxy() {
-		AnnotationDescriptor descriptor = new AnnotationDescriptor( Length.class );
+		AnnotationDescriptor descriptor = new AnnotationDescriptor( Size.class );
 		descriptor.setValue( "min", 5 );
 		descriptor.setValue( "max", 10 );
 
-		Length l = AnnotationFactory.create( descriptor );
+		Size size = AnnotationFactory.create( descriptor );
 
-		assertEquals( "Wrong parameter value", 5, l.min() );
-		assertEquals( "Wrong parameter value", 10, l.max() );
+		assertEquals( "Wrong parameter value", 5, size.min() );
+		assertEquals( "Wrong parameter value", 10, size.max() );
 	}
 
 	@Test(expected = IllegalArgumentException.class)

Modified: validator/trunk/hibernate-validator/src/test/resources/log4j.properties
===================================================================
--- validator/trunk/hibernate-validator/src/test/resources/log4j.properties	2009-01-08 09:36:38 UTC (rev 15755)
+++ validator/trunk/hibernate-validator/src/test/resources/log4j.properties	2009-01-08 17:04:02 UTC (rev 15756)
@@ -18,7 +18,7 @@
 
 
 ### set log levels - for more verbose logging change 'info' to 'debug' ###
-log4j.rootLogger=info, stdout
+log4j.rootLogger=debug, stdout
 
 log4j.logger.org.hibernate.validation.engine.ValidatorImpl=trace
 org.hibernate.validation.impl.ResourceBundleMessageResolver=info

Modified: validator/trunk/pom.xml
===================================================================
--- validator/trunk/pom.xml	2009-01-08 09:36:38 UTC (rev 15755)
+++ validator/trunk/pom.xml	2009-01-08 17:04:02 UTC (rev 15756)
@@ -70,11 +70,6 @@
                 <version>1.4.2</version>
             </dependency>
             <dependency>
-                <groupId>commons-collections</groupId>
-                <artifactId>commons-collections</artifactId>
-                <version>3.2</version>
-            </dependency>
-            <dependency>
                 <groupId>junit</groupId>
                 <artifactId>junit</artifactId>
                 <version>4.4</version>

Modified: validator/trunk/validation-api/src/main/java/javax/validation/OverridesParameter.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/OverridesParameter.java	2009-01-08 09:36:38 UTC (rev 15755)
+++ validator/trunk/validation-api/src/main/java/javax/validation/OverridesParameter.java	2009-01-08 17:04:02 UTC (rev 15756)
@@ -18,11 +18,10 @@
 package javax.validation;
 
 import java.lang.annotation.Annotation;
-import java.lang.annotation.Target;
+import static java.lang.annotation.ElementType.METHOD;
 import java.lang.annotation.Retention;
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.FIELD;
+import java.lang.annotation.Target;
 
 /**
  * Mark a parameter as overriding the parameter of a composing constraint.
@@ -31,6 +30,7 @@
  * @author Emmanuel Bernard
  */
 @Retention(RUNTIME)
+ at Target({ METHOD })
 public @interface OverridesParameter {
 	/**
 	 * @return Constraint type the parameter is overriding

Copied: validator/trunk/validation-api/src/main/java/javax/validation/OverridesParameters.java (from rev 15751, validator/trunk/validation-api/src/main/java/javax/validation/OverridesParameter.java)
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/OverridesParameters.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/OverridesParameters.java	2009-01-08 17:04:02 UTC (rev 15756)
@@ -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 javax.validation;
+
+import java.lang.annotation.Documented;
+import static java.lang.annotation.ElementType.METHOD;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+
+/**
+ * @author Hardy Ferentschik
+ */
+ at Documented
+ at Target({ METHOD })
+ at Retention(RUNTIME)
+public @interface OverridesParameters {
+	OverridesParameter[] value();
+}
\ No newline at end of file


Property changes on: validator/trunk/validation-api/src/main/java/javax/validation/OverridesParameters.java
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:mergeinfo
   + 

Modified: validator/trunk/validation-api/src/main/java/javax/validation/ValidatorBuilder.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/ValidatorBuilder.java	2009-01-08 09:36:38 UTC (rev 15755)
+++ validator/trunk/validation-api/src/main/java/javax/validation/ValidatorBuilder.java	2009-01-08 17:04:02 UTC (rev 15756)
@@ -23,8 +23,8 @@
 	ValidatorBuilder traversableResolver(TraversableResolver traversableResolver);
 
 	/**
-	 * return an initialized Validator instance respecting the defined state
-	 * Validator instances can be pooled and shared by the implementation
+	 * @return an initialized <code>Validator</code> instance respecting the defined state.
+	 * Validator instances can be pooled and shared by the implementation.
 	 */
 	Validator getValidator();
 

Modified: validator/trunk/validation-api/src/main/java/javax/validation/constraints/Size.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/constraints/Size.java	2009-01-08 09:36:38 UTC (rev 15755)
+++ validator/trunk/validation-api/src/main/java/javax/validation/constraints/Size.java	2009-01-08 17:04:02 UTC (rev 15756)
@@ -42,7 +42,7 @@
 @Retention(RUNTIME)
 @Documented
 public @interface Size {
-	String message() default "{validator.min}";
+	String message() default "{validator.size}";
 	Class<?>[] groups() default {};
 
 	/**




More information about the hibernate-commits mailing list