[hibernate-commits] Hibernate SVN: r16798 - in validator/trunk/hibernate-validator/src: main/java/org/hibernate/validation/engine and 4 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Tue Jun 16 12:16:48 EDT 2009


Author: hardy.ferentschik
Date: 2009-06-16 12:16:48 -0400 (Tue, 16 Jun 2009)
New Revision: 16798

Added:
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/AnnotationIgnores.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanDescriptorImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaData.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaDataCache.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaDataImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ConstraintDescriptorImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ConstraintHelper.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ElementDescriptorImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/MetaConstraint.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/PropertyDescriptorImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/ValidationBootstrapParameters.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/ValidationXmlParser.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/XmlMappingParser.java
Removed:
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanDescriptorImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaData.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataCache.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintDescriptorImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintHelper.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ElementDescriptorImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaConstraint.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/PropertyDescriptorImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/metadata/
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/xml/
Modified:
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConfigurationImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintTree.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ExecutionContext.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorContextImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ConstraintHelperTest.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolatorTest.java
   validator/trunk/hibernate-validator/src/test/suite/unit-tests.xml
Log:
Also introduced metadata package in validator implementation (mirrowring the api)

Deleted: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanDescriptorImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanDescriptorImpl.java	2009-06-16 15:29:59 UTC (rev 16797)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanDescriptorImpl.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -1,30 +0,0 @@
-package org.hibernate.validation.engine;
-
-import java.util.Set;
-import javax.validation.metadata.BeanDescriptor;
-import javax.validation.metadata.PropertyDescriptor;
-
-/**
- * @author Emmanuel Bernard
- * @author Hardy Ferentschik
- */
-public class BeanDescriptorImpl<T> extends ElementDescriptorImpl implements BeanDescriptor {
-	private final BeanMetaData<T> metadataBean;
-
-	public BeanDescriptorImpl(BeanMetaData<T> metadataBean) {
-		super( metadataBean.getBeanClass() );
-		this.metadataBean = metadataBean;
-	}
-
-	public boolean isBeanConstrained() {
-		return metadataBean.getConstrainedProperties().size() > 0;
-	}
-
-	public PropertyDescriptor getConstraintsForProperty(String propertyName) {
-		return metadataBean.getPropertyDescriptor( propertyName );
-	}
-
-	public Set<PropertyDescriptor> getConstrainedProperties() {
-		return metadataBean.getConstrainedProperties();
-	}
-}

Deleted: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaData.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaData.java	2009-06-16 15:29:59 UTC (rev 16797)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaData.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -1,75 +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.engine;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Member;
-import java.util.List;
-import java.util.Set;
-import javax.validation.metadata.BeanDescriptor;
-import javax.validation.metadata.PropertyDescriptor;
-
-/**
- * Interface defining the meta data about the constraints defined in a given bean.
- *
- * @author Hardy Ferentschik
- */
-public interface BeanMetaData<T> {
-
-	/**
-	 * @return the class of the bean.
-	 */
-	Class<T> getBeanClass();
-
-	/**
-	 * @return an instance of <code>ElementDescriptor</code> describing the bean this meta data applies for.
-	 */
-	BeanDescriptor getBeanDescriptor();
-
-	/**
-	 * @return A list of all cascaded methods and fields (methods/fields annotated with &#064;Valid).
-	 */
-	List<Member> getCascadedMembers();
-
-	/**
-	 * @return A map mapping defined group sequences to a list of groups.
-	 */
-	List<Class<?>> getDefaultGroupSequence();
-
-	/**
-	 * @return A list of <code>MetaConstraint</code> instances encapsulating the information of all the constraints
-	 *         defined on the bean.
-	 */
-	List<MetaConstraint<T, ? extends Annotation>> geMetaConstraintList();
-
-	/**
-	 * Return <code>PropertyDescriptor</code> for the given property.
-	 *
-	 * @param property the property for which to retrieve the descriptor.
-	 *
-	 * @return Returns the <code>PropertyDescriptor</code> for the given property or <code>null</code> in case the
-	 *         property does not have a descriptor.
-	 */
-	PropertyDescriptor getPropertyDescriptor(String property);
-
-	/**
-	 * @return the property descriptors having at least one constraint defined or which are marked
-	 *         as cascaded (@Valid).
-	 */
-	Set<PropertyDescriptor> getConstrainedProperties();
-}

Deleted: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataCache.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataCache.java	2009-06-16 15:29:59 UTC (rev 16797)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataCache.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -1,48 +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.engine;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * Cache for created instances of <code>BeanMetaData</code>.
- *
- * @author Hardy Ferentschik
- */
-public class BeanMetaDataCache {
-	/**
-	 * A map for the meta data for each entity. The key is the class and the value the bean meta data for this
-	 * entity.
-	 */
-	private Map<Class<?>, BeanMetaDataImpl<?>> metadataProviders = new ConcurrentHashMap<Class<?>, BeanMetaDataImpl<?>>(
-			10
-	);
-
-	@SuppressWarnings("unchecked")
-	public <T> BeanMetaDataImpl<T> getBeanMetaData(Class<T> beanClass) {
-		if ( beanClass == null ) {
-			throw new IllegalArgumentException( "Class cannot be null" );
-		}
-		return ( BeanMetaDataImpl<T> ) metadataProviders.get( beanClass );
-	}
-
-	public <T> void addBeanMetaData(Class<T> beanClass, BeanMetaDataImpl<T> metaData) {
-		metadataProviders.put( beanClass, metaData );
-	}
-}

Deleted: 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-06-16 15:29:59 UTC (rev 16797)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -1,389 +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.engine;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.Field;
-import java.lang.reflect.Member;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import javax.validation.GroupSequence;
-import javax.validation.Valid;
-import javax.validation.ValidationException;
-import javax.validation.groups.Default;
-import javax.validation.metadata.BeanDescriptor;
-import javax.validation.metadata.PropertyDescriptor;
-
-import org.slf4j.Logger;
-
-import org.hibernate.validation.engine.xml.AnnotationIgnores;
-import org.hibernate.validation.util.LoggerFactory;
-import org.hibernate.validation.util.ReflectionHelper;
-
-
-/**
- * This class encapsulates all meta data needed for validation. Implementations of {@code Validator} interface can
- * instantiate an instance of this class and delegate the metadata extraction to it.
- *
- * @author Hardy Ferentschik
- */
-
-public class BeanMetaDataImpl<T> implements BeanMetaData<T> {
-
-	private static final Logger log = LoggerFactory.make();
-
-	/**
-	 * The root bean class for this validator.
-	 */
-	private final Class<T> beanClass;
-
-	/**
-	 * The main element descriptor for <code>beanClass</code>.
-	 */
-	private BeanDescriptorImpl<T> beanDescriptor;
-
-	/**
-	 * List of constraints.
-	 */
-	private List<MetaConstraint<T, ? extends Annotation>> metaConstraintList = new ArrayList<MetaConstraint<T, ? extends Annotation>>();
-
-	/**
-	 * List of cascaded members.
-	 */
-	private List<Member> cascadedMembers = new ArrayList<Member>();
-
-	/**
-	 * Maps field and method names to their <code>ElementDescriptorImpl</code>.
-	 */
-	private Map<String, PropertyDescriptor> propertyDescriptors = new HashMap<String, PropertyDescriptor>();
-
-	/**
-	 * Maps group sequences to the list of group/sequences.
-	 */
-	private List<Class<?>> defaultGroupSequence = new ArrayList<Class<?>>();
-
-	/**
-	 * Object keeping track of all constraints.
-	 */
-	private final ConstraintHelper constraintHelper;
-
-
-	public BeanMetaDataImpl(Class<T> beanClass, ConstraintHelper constraintHelper) {
-		this(
-				beanClass,
-				constraintHelper,
-				new AnnotationIgnores()
-		);
-	}
-
-	public BeanMetaDataImpl(Class<T> beanClass, ConstraintHelper constraintHelper, AnnotationIgnores annotationIgnores) {
-		this.beanClass = beanClass;
-		this.constraintHelper = constraintHelper;
-		createMetaData( annotationIgnores );
-	}
-
-	public Class<T> getBeanClass() {
-		return beanClass;
-	}
-
-	public BeanDescriptor getBeanDescriptor() {
-		return beanDescriptor;
-	}
-
-	public List<Member> getCascadedMembers() {
-		return Collections.unmodifiableList( cascadedMembers );
-	}
-
-	public List<MetaConstraint<T, ? extends Annotation>> geMetaConstraintList() {
-		return Collections.unmodifiableList( metaConstraintList );
-	}
-
-	public void addMetaConstraint(MetaConstraint<T, ? extends Annotation> metaConstraint) {
-		metaConstraintList.add( metaConstraint );
-	}
-
-	public void addCascadedMember(Member member) {
-		cascadedMembers.add( member );
-	}
-
-	public PropertyDescriptor getPropertyDescriptor(String property) {
-		return propertyDescriptors.get( property );
-	}
-
-	public List<Class<?>> getDefaultGroupSequence() {
-		return Collections.unmodifiableList( defaultGroupSequence );
-	}
-
-	public void setDefaultGroupSequence(List<Class<?>> groupSequence) {
-		defaultGroupSequence = new ArrayList<Class<?>>();
-		for ( Class<?> group : groupSequence ) {
-			if ( group.getName().equals( beanClass.getName() ) ) {
-				defaultGroupSequence.add( Default.class );
-			}
-			else if ( group.getName().equals( Default.class.getName() ) ) {
-				throw new ValidationException( "'Default.class' cannot appear in default group sequence list." );
-			}
-			else {
-				defaultGroupSequence.add( group );
-			}
-		}
-		if ( log.isTraceEnabled() ) {
-			log.trace(
-					"Members of the default group sequence for bean {} are: {}",
-					beanClass.getName(),
-					defaultGroupSequence
-			);
-		}
-	}
-
-	public Set<PropertyDescriptor> getConstrainedProperties() {
-		return Collections.unmodifiableSet( new HashSet<PropertyDescriptor>( propertyDescriptors.values() ) );
-	}
-
-	/**
-	 * Create bean desciptor, find all classes/subclasses/interfaces which have to be taken in consideration
-	 * for this validator and create meta data.
-	 *
-	 * @param annotationIgnores Datastructure keeping track on which annotation should be ignored.
-	 */
-	private void createMetaData(AnnotationIgnores annotationIgnores) {
-		beanDescriptor = new BeanDescriptorImpl<T>( this );
-		initDefaultGroupSequence();
-		List<Class> classes = new ArrayList<Class>();
-		computeClassHierarchy( beanClass, classes );
-		for ( Class current : classes ) {
-			initClass( current, annotationIgnores );
-		}
-	}
-
-	/**
-	 * Get all superclasses and interfaces recursively.
-	 *
-	 * @param clazz The class to start the search with.
-	 * @param classes List of classes to which to add all found super classes and interfaces.
-	 */
-	private void computeClassHierarchy(Class clazz, List<Class> classes) {
-		if ( log.isTraceEnabled() ) {
-			log.trace( "Processing: {}", clazz );
-		}
-		for ( Class current = clazz; current != null; current = current.getSuperclass() ) {
-			if ( classes.contains( current ) ) {
-				return;
-			}
-			classes.add( current );
-			for ( Class currentInterface : current.getInterfaces() ) {
-				computeClassHierarchy( currentInterface, classes );
-			}
-		}
-	}
-
-	private void initClass(Class clazz, AnnotationIgnores annotationIgnores) {
-		initClassConstraints( clazz, annotationIgnores );
-		initMethodConstraints( clazz, annotationIgnores );
-		initFieldConstraints( clazz, annotationIgnores );
-	}
-
-	/**
-	 * Checks whether there is a default group sequence defined for this class.
-	 * See HV-113.
-	 */
-	private void initDefaultGroupSequence() {
-		List<Class<?>> groupSequence = new ArrayList<Class<?>>();
-		GroupSequence groupSequenceAnnotation = beanClass.getAnnotation( GroupSequence.class );
-		if ( groupSequenceAnnotation == null ) {
-			groupSequence.add( beanClass );
-		}
-		else {
-			groupSequence.addAll( Arrays.asList( groupSequenceAnnotation.value() ) );
-		}
-		setDefaultGroupSequence( groupSequence );
-	}
-
-	private void initFieldConstraints(Class clazz, AnnotationIgnores annotationIgnores) {
-		for ( Field field : clazz.getDeclaredFields() ) {
-			List<ConstraintDescriptorImpl<?>> fieldMetadata = findConstraints( field );
-			for ( ConstraintDescriptorImpl<?> constraintDescription : fieldMetadata ) {
-				if ( annotationIgnores.isIgnoreAnnotations( field ) ) {
-					break;
-				}
-				ReflectionHelper.setAccessibility( field );
-				MetaConstraint<T, ?> metaConstraint = createMetaConstraint( field, constraintDescription );
-				metaConstraintList.add( metaConstraint );
-			}
-			if ( field.isAnnotationPresent( Valid.class ) ) {
-				ReflectionHelper.setAccessibility( field );
-				cascadedMembers.add( field );
-				addPropertyDescriptorForMember( field );
-			}
-		}
-	}
-
-	private void initMethodConstraints(Class clazz, AnnotationIgnores annotationIgnores) {
-		for ( Method method : clazz.getDeclaredMethods() ) {
-			List<ConstraintDescriptorImpl<?>> methodMetadata = findConstraints( method );
-			for ( ConstraintDescriptorImpl<?> constraintDescription : methodMetadata ) {
-				if ( annotationIgnores.isIgnoreAnnotations( method ) ) {
-					break;
-				}
-				ReflectionHelper.setAccessibility( method );
-				MetaConstraint<T, ?> metaConstraint = createMetaConstraint( method, constraintDescription );
-				metaConstraintList.add( metaConstraint );
-			}
-			if ( method.isAnnotationPresent( Valid.class ) ) {
-				ReflectionHelper.setAccessibility( method );
-				cascadedMembers.add( method );
-				addPropertyDescriptorForMember( method );
-			}
-		}
-	}
-
-	private PropertyDescriptorImpl addPropertyDescriptorForMember(Member member) {
-		String name = ReflectionHelper.getPropertyName( member );
-		PropertyDescriptorImpl propertyDescriptor = ( PropertyDescriptorImpl ) propertyDescriptors.get(
-				name
-		);
-		if ( propertyDescriptor == null ) {
-			propertyDescriptor = new PropertyDescriptorImpl(
-					ReflectionHelper.getType( member ),
-					( ( AnnotatedElement ) member ).isAnnotationPresent( Valid.class ),
-					name
-			);
-			propertyDescriptors.put( name, propertyDescriptor );
-		}
-		return propertyDescriptor;
-	}
-
-	private void initClassConstraints(Class<?> clazz, AnnotationIgnores annotationIgnores) {
-		if ( annotationIgnores.isIgnoreAnnotations( clazz ) ) {
-			return;
-		}
-		List<ConstraintDescriptorImpl<?>> classMetadata = findClassLevelConstraints( clazz );
-		for ( ConstraintDescriptorImpl<?> constraintDescription : classMetadata ) {
-			MetaConstraint<T, ?> metaConstraint = createMetaConstraint( constraintDescription );
-			metaConstraintList.add( metaConstraint );
-		}
-	}
-
-	private <A extends Annotation> MetaConstraint<T, ?> createMetaConstraint(ConstraintDescriptorImpl<A> descriptor) {
-		return new MetaConstraint<T, A>( beanClass, descriptor );
-	}
-
-	private <A extends Annotation> MetaConstraint<T, ?> createMetaConstraint(Member m, ConstraintDescriptorImpl<A> descriptor) {
-		return new MetaConstraint<T, A>( m, beanClass, descriptor );
-	}
-
-	/**
-	 * Examines the given annotation to see whether it is a single or multi valued constraint annotation.
-	 *
-	 * @param clazz the class we are currently processing.
-	 * @param annotation The annotation to examine.
-	 *
-	 * @return A list of constraint descriptors or the empty list in case <code>annotation</code> is neither a
-	 *         single nor multi value annotation.
-	 */
-	private <A extends Annotation> List<ConstraintDescriptorImpl<?>> findConstraintAnnotations(Class<?> clazz, A annotation) {
-		List<ConstraintDescriptorImpl<?>> constraintDescriptors = new ArrayList<ConstraintDescriptorImpl<?>>();
-
-		List<Annotation> constraints = new ArrayList<Annotation>();
-		if ( constraintHelper.isConstraintAnnotation( annotation ) ||
-				constraintHelper.isBuiltinConstraint( annotation.annotationType() ) ) {
-			constraints.add( annotation );
-		}
-
-		// check if we have a multi value constraint
-		constraints.addAll( constraintHelper.getMultiValueConstraints( annotation ) );
-
-		for ( Annotation constraint : constraints ) {
-			final ConstraintDescriptorImpl constraintDescriptor = buildConstraintDescriptor( clazz, constraint );
-			constraintDescriptors.add( constraintDescriptor );
-		}
-		return constraintDescriptors;
-	}
-
-	@SuppressWarnings("unchecked")
-	private <A extends Annotation> ConstraintDescriptorImpl buildConstraintDescriptor(Class<?> clazz, A annotation) {
-		ConstraintDescriptorImpl constraintDescriptor;
-		if ( clazz.isInterface() ) {
-			constraintDescriptor = new ConstraintDescriptorImpl( annotation, constraintHelper, clazz );
-		}
-		else {
-			constraintDescriptor = new ConstraintDescriptorImpl( annotation, constraintHelper );
-		}
-		return constraintDescriptor;
-	}
-
-	/**
-	 * Finds all constraint annotations defined for the given class and returns them in a list of
-	 * constraint descriptors.
-	 *
-	 * @param beanClass The class to check for constraints annotations.
-	 *
-	 * @return A list of constraint descriptors for all constraint specified on the given class.
-	 */
-	private List<ConstraintDescriptorImpl<?>> findClassLevelConstraints(Class<?> beanClass) {
-		List<ConstraintDescriptorImpl<?>> metadata = new ArrayList<ConstraintDescriptorImpl<?>>();
-		for ( Annotation annotation : beanClass.getAnnotations() ) {
-			metadata.addAll( findConstraintAnnotations( beanClass, annotation ) );
-		}
-		for ( ConstraintDescriptorImpl constraintDescriptor : metadata ) {
-			beanDescriptor.addConstraintDescriptor( constraintDescriptor );
-		}
-		return metadata;
-	}
-
-
-	/**
-	 * Finds all constraint annotations defined for the given field/method and returns them in a list of
-	 * constraint descriptors.
-	 *
-	 * @param member The fiels or method to check for constraints annotations.
-	 *
-	 * @return A list of constraint descriptors for all constraint specified for the given field or method.
-	 */
-	private List<ConstraintDescriptorImpl<?>> findConstraints(Member member) {
-		assert member instanceof Field || member instanceof Method;
-
-		List<ConstraintDescriptorImpl<?>> metadata = new ArrayList<ConstraintDescriptorImpl<?>>();
-		for ( Annotation annotation : ( ( AnnotatedElement ) member ).getAnnotations() ) {
-			metadata.addAll( findConstraintAnnotations( member.getDeclaringClass(), annotation ) );
-		}
-
-		String name = ReflectionHelper.getPropertyName( member );
-		for ( ConstraintDescriptorImpl constraintDescriptor : metadata ) {
-			if ( member instanceof Method && name == null ) { // can happen if member is a Method which does not follow the bean convention
-				throw new ValidationException(
-						"Annotated methods must follow the JavaBeans naming convention. " + member.getName() + "() does not."
-				);
-			}
-			PropertyDescriptorImpl propertyDescriptor = ( PropertyDescriptorImpl ) propertyDescriptors.get( name );
-			if ( propertyDescriptor == null ) {
-				propertyDescriptor = addPropertyDescriptorForMember( member );
-			}
-			propertyDescriptor.addConstraintDescriptor( constraintDescriptor );
-		}
-		return metadata;
-	}
-}
\ No newline at end of file

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConfigurationImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConfigurationImpl.java	2009-06-16 15:29:59 UTC (rev 16797)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConfigurationImpl.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -34,8 +34,8 @@
 import org.slf4j.Logger;
 
 import org.hibernate.validation.engine.resolver.DefaultTraversableResolver;
-import org.hibernate.validation.engine.xml.ValidationBootstrapParameters;
-import org.hibernate.validation.engine.xml.ValidationXmlParser;
+import org.hibernate.validation.xml.ValidationBootstrapParameters;
+import org.hibernate.validation.xml.ValidationXmlParser;
 import org.hibernate.validation.util.LoggerFactory;
 import org.hibernate.validation.util.Version;
 

Deleted: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintDescriptorImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintDescriptorImpl.java	2009-06-16 15:29:59 UTC (rev 16797)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintDescriptorImpl.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -1,384 +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.engine;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import javax.validation.Constraint;
-import javax.validation.ConstraintDefinitionException;
-import javax.validation.metadata.ConstraintDescriptor;
-import javax.validation.ConstraintValidator;
-import javax.validation.OverridesAttribute;
-import javax.validation.ReportAsSingleViolation;
-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.AnnotationDescriptor;
-import org.hibernate.validation.util.annotationfactory.AnnotationFactory;
-
-/**
- * Describe a single constraint (including it's composing constraints).
- *
- * @author Emmanuel Bernard
- * @author Hardy Ferentschik
- */
-public class ConstraintDescriptorImpl<T extends Annotation> implements ConstraintDescriptor<T> {
-	private static final Logger log = LoggerFactory.make();
-	private static final int OVERRIDES_PARAMETER_DEFAULT_INDEX = -1;
-
-	/**
-	 * The actual constraint annotation.
-	 */
-	private final T annotation;
-
-	/**
-	 * The set of classes implementing the validation for this constraint. See also
-	 * <code>ConstraintValidator</code> resolution algorithm.
-	 */
-	private final List<Class<? extends ConstraintValidator<T, ?>>> constraintValidatorDefinitonClasses = new ArrayList<Class<? extends ConstraintValidator<T, ?>>>();
-
-	/**
-	 * The groups for which to apply this constraint.
-	 */
-	private final Set<Class<?>> groups = new HashSet<Class<?>>();
-
-	/**
-	 * The constraint parameters as map. The key is the paramter name and the value the
-	 * parameter value as specified in the constraint.
-	 */
-	private final Map<String, Object> attributes;
-
-	/**
-	 * The composing constraints for this constraints.
-	 */
-	private final Set<ConstraintDescriptor<?>> composingConstraints = new HashSet<ConstraintDescriptor<?>>();
-
-	/**
-	 * Flag indicating if in case of a composing constraint a single error or multiple errors should be raised.
-	 */
-	private final boolean isReportAsSingleInvalidConstraint;
-
-	/**
-	 * Handle to the builtin constraint implementations.
-	 */
-	private final ConstraintHelper constraintHelper;
-
-	public ConstraintDescriptorImpl(T annotation, ConstraintHelper constraintHelper, Class<?> implicitGroup) {
-		this( annotation, constraintHelper );
-		this.groups.add( implicitGroup );
-	}
-
-
-	public ConstraintDescriptorImpl(T annotation, ConstraintHelper constraintHelper) {
-		this.annotation = annotation;
-		this.attributes = getAnnotationParameters( annotation );
-		this.constraintHelper = constraintHelper;
-
-		this.isReportAsSingleInvalidConstraint = annotation.annotationType().isAnnotationPresent(
-				ReportAsSingleViolation.class
-		);
-
-		Class<?>[] groupsFromAnnotation = ReflectionHelper.getAnnotationParameter(
-				annotation, "groups", Class[].class
-		);
-		if ( groupsFromAnnotation.length == 0 ) {
-			groups.add( Default.class );
-		}
-		else {
-			this.groups.addAll( Arrays.asList( groupsFromAnnotation ) );
-		}
-
-		findConstraintValidatorClasses();
-		Map<ClassIndexWrapper, Map<String, Object>> overrideParameters = parseOverrideParameters();
-		parseComposingConstraints( overrideParameters );
-	}
-
-	private void findConstraintValidatorClasses() {
-		if ( constraintHelper.containsConstraintValidatorDefinition( annotation.annotationType() ) ) {
-			for ( Class<? extends ConstraintValidator<? extends Annotation, ?>> validator : constraintHelper
-					.getConstraintValidatorDefinition( annotation.annotationType() ) ) {
-				constraintValidatorDefinitonClasses.add( ( Class<? extends ConstraintValidator<T, ?>> ) validator );
-			}
-			return;
-		}
-
-		List<Class<? extends ConstraintValidator<? extends Annotation, ?>>> constraintDefinitonClasses = new ArrayList<Class<? extends ConstraintValidator<? extends Annotation, ?>>>();
-		if ( constraintHelper.isBuiltinConstraint( annotation.annotationType() ) ) {
-			constraintDefinitonClasses.addAll( constraintHelper.getBuiltInConstraints( annotation.annotationType() ) );
-		}
-		else {
-			final Class<? extends Annotation> annotationType = annotation.annotationType();
-			Class<? extends ConstraintValidator<?, ?>>[] validatedBy = annotationType
-					.getAnnotation( Constraint.class )
-					.validatedBy();
-			constraintDefinitonClasses.addAll( Arrays.asList( validatedBy ) );
-		}
-
-		constraintHelper.addConstraintValidatorDefinition(
-				annotation.annotationType(), constraintDefinitonClasses
-		);
-
-		for ( Class<? extends ConstraintValidator<? extends Annotation, ?>> validator : constraintDefinitonClasses ) {
-			@SuppressWarnings("unchecked")
-			Class<? extends ConstraintValidator<T, ?>> safeValidator = ( Class<? extends ConstraintValidator<T, ?>> ) validator;
-			constraintValidatorDefinitonClasses.add( safeValidator );
-		}
-	}
-
-	public T getAnnotation() {
-		return annotation;
-	}
-
-	public Set<Class<?>> getGroups() {
-		return Collections.unmodifiableSet( groups );
-	}
-
-	public List<Class<? extends ConstraintValidator<T, ?>>> getConstraintValidatorClasses() {
-		return Collections.unmodifiableList( constraintValidatorDefinitonClasses );
-	}
-
-	public Map<String, Object> getAttributes() {
-		return Collections.unmodifiableMap( attributes );
-	}
-
-	public Set<ConstraintDescriptor<?>> getComposingConstraints() {
-		return Collections.unmodifiableSet( composingConstraints );
-	}
-
-	public boolean isReportAsSingleViolation() {
-		return isReportAsSingleInvalidConstraint;
-	}
-
-	@Override
-	public String toString() {
-		return "ConstraintDescriptorImpl{" +
-				"annotation=" + annotation +
-				", constraintValidatorDefinitonClasses=" + constraintValidatorDefinitonClasses.toString() +
-				", groups=" + groups +
-				", attributes=" + attributes +
-				", 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 );
-		for ( Method m : declaredMethods ) {
-			try {
-				parameters.put( m.getName(), m.invoke( annotation ) );
-			}
-			catch ( IllegalAccessException e ) {
-				throw new ValidationException( "Unable to read annotation attributes: " + annotation.getClass(), e );
-			}
-			catch ( InvocationTargetException e ) {
-				throw new ValidationException( "Unable to read annotation attributes: " + annotation.getClass(), e );
-			}
-		}
-		return Collections.unmodifiableMap( parameters );
-	}
-
-	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 Map<ClassIndexWrapper, Map<String, Object>> parseOverrideParameters() {
-		Map<ClassIndexWrapper, Map<String, Object>> overrideParameters = new HashMap<ClassIndexWrapper, Map<String, Object>>();
-		for ( Method m : annotation.annotationType().getMethods() ) {
-			if ( m.getAnnotation( OverridesAttribute.class ) != null ) {
-				addOverrideAttributes(
-						overrideParameters, m, m.getAnnotation( OverridesAttribute.class )
-				);
-			}
-			else if ( m.getAnnotation( OverridesAttribute.List.class ) != null ) {
-				addOverrideAttributes(
-						overrideParameters,
-						m,
-						m.getAnnotation( OverridesAttribute.List.class ).value()
-				);
-			}
-		}
-		return overrideParameters;
-	}
-
-	private void addOverrideAttributes(Map<ClassIndexWrapper, Map<String, Object>> overrideParameters, Method m, OverridesAttribute... attributes) {
-
-		Object value = getMethodValue( annotation, m );
-		for ( OverridesAttribute overridesAttribute : attributes ) {
-			ensureAttributeIsOverridable( m, overridesAttribute );
-
-			ClassIndexWrapper wrapper = new ClassIndexWrapper(
-					overridesAttribute.constraint(), overridesAttribute.constraintIndex()
-			);
-			Map<String, Object> map = overrideParameters.get( wrapper );
-			if ( map == null ) {
-				map = new HashMap<String, Object>();
-				overrideParameters.put( wrapper, map );
-			}
-			map.put( overridesAttribute.name(), value );
-		}
-	}
-
-	private void ensureAttributeIsOverridable(Method m, OverridesAttribute overridesAttribute) {
-		try {
-			Class<?> returnTypeOfOverridenConstraint = overridesAttribute.constraint()
-					.getMethod( overridesAttribute.name() )
-					.getReturnType();
-			if ( !returnTypeOfOverridenConstraint.equals( m.getReturnType() ) ) {
-				String message = "The overiding type of a composite constraint must be identical to the overwridden one. Expected " + returnTypeOfOverridenConstraint
-						.getName() + " found " + m.getReturnType();
-				throw new ConstraintDefinitionException( message );
-			}
-		}
-		catch ( NoSuchMethodException nsme ) {
-			throw new ConstraintDefinitionException(
-					"Overriden constraint does not define an attribute with name " + overridesAttribute.name()
-			);
-		}
-	}
-
-	private void parseComposingConstraints(Map<ClassIndexWrapper, Map<String, Object>> overrideParameters) {
-		for ( Annotation declaredAnnotation : annotation.annotationType().getDeclaredAnnotations() ) {
-			if ( constraintHelper.isConstraintAnnotation( declaredAnnotation )
-					|| constraintHelper.isBuiltinConstraint( declaredAnnotation.annotationType() ) ) {
-				ConstraintDescriptorImpl<?> descriptor = createComposingConstraintDescriptor(
-						declaredAnnotation, overrideParameters, OVERRIDES_PARAMETER_DEFAULT_INDEX
-				);
-				composingConstraints.add( descriptor );
-				log.debug( "Adding composing constraint: " + descriptor );
-			}
-			else if ( constraintHelper.isMultiValueConstraint( declaredAnnotation ) ) {
-				List<Annotation> multiValueConstraints = constraintHelper.getMultiValueConstraints( declaredAnnotation );
-				int index = 1;
-				for ( Annotation constraintAnnotation : multiValueConstraints ) {
-					ConstraintDescriptorImpl<?> descriptor = createComposingConstraintDescriptor(
-							constraintAnnotation, overrideParameters, index
-					);
-					composingConstraints.add( descriptor );
-					log.debug( "Adding composing constraint: " + descriptor );
-					index++;
-				}
-			}
-		}
-	}
-
-	private <U extends Annotation> ConstraintDescriptorImpl<U> createComposingConstraintDescriptor(U declaredAnnotation, Map<ClassIndexWrapper, Map<String, Object>> overrideParameters, int index) {
-		//TODO don't quite understand this warning
-		//TODO assuming U.getClass() returns Class<U>
-		@SuppressWarnings("unchecked")
-		final Class<U> annotationType = ( Class<U> ) declaredAnnotation.annotationType();
-		return createComposingConstraintDescriptor(
-				overrideParameters,
-				index,
-				declaredAnnotation,
-				annotationType
-		);
-	}
-
-	private <U extends Annotation> ConstraintDescriptorImpl<U> createComposingConstraintDescriptor(Map<ClassIndexWrapper, Map<String, Object>> overrideParameters, int index, U constraintAnnotation, Class<U> annotationType) {
-		// use a annotation proxy
-		AnnotationDescriptor<U> annotationDescriptor = new AnnotationDescriptor<U>(
-				annotationType, getAnnotationParameters( constraintAnnotation )
-		);
-
-		// get the right override parameters
-		Map<String, Object> overrides = overrideParameters.get(
-				new ClassIndexWrapper(
-						annotationType, index
-				)
-		);
-		if ( overrides != null ) {
-			for ( Map.Entry<String, Object> entry : overrides.entrySet() ) {
-				annotationDescriptor.setValue( entry.getKey(), entry.getValue() );
-			}
-		}
-
-		// groups get inherited from the parent
-		annotationDescriptor.setValue( "groups", groups.toArray( new Class<?>[] { } ) );
-
-		U annotationProxy = AnnotationFactory.create( annotationDescriptor );
-		return new ConstraintDescriptorImpl<U>(
-				annotationProxy, constraintHelper
-		);
-	}
-
-	/**
-	 * A wrapper class to keep track for which compposing constraints (class and index) a given attribute override applies to.
-	 */
-	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;
-		}
-	}
-}

Deleted: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintHelper.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintHelper.java	2009-06-16 15:29:59 UTC (rev 16797)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintHelper.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -1,335 +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.engine;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import javax.validation.Constraint;
-import javax.validation.ConstraintDefinitionException;
-import javax.validation.ConstraintValidator;
-import javax.validation.ValidationException;
-import javax.validation.constraints.AssertFalse;
-import javax.validation.constraints.AssertTrue;
-import javax.validation.constraints.DecimalMax;
-import javax.validation.constraints.DecimalMin;
-import javax.validation.constraints.Digits;
-import javax.validation.constraints.Future;
-import javax.validation.constraints.Max;
-import javax.validation.constraints.Min;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Null;
-import javax.validation.constraints.Past;
-import javax.validation.constraints.Pattern;
-import javax.validation.constraints.Size;
-
-import org.hibernate.validation.constraints.impl.AssertFalseValidator;
-import org.hibernate.validation.constraints.impl.AssertTrueValidator;
-import org.hibernate.validation.constraints.impl.DecimalMaxValidatorForNumber;
-import org.hibernate.validation.constraints.impl.DecimalMaxValidatorForString;
-import org.hibernate.validation.constraints.impl.DecimalMinValidatorForNumber;
-import org.hibernate.validation.constraints.impl.DecimalMinValidatorForString;
-import org.hibernate.validation.constraints.impl.DigitsValidatorForNumber;
-import org.hibernate.validation.constraints.impl.DigitsValidatorForString;
-import org.hibernate.validation.constraints.impl.FutureValidatorForCalendar;
-import org.hibernate.validation.constraints.impl.FutureValidatorForDate;
-import org.hibernate.validation.constraints.impl.MaxValidatorForNumber;
-import org.hibernate.validation.constraints.impl.MaxValidatorForString;
-import org.hibernate.validation.constraints.impl.MinValidatorForNumber;
-import org.hibernate.validation.constraints.impl.MinValidatorForString;
-import org.hibernate.validation.constraints.impl.NotNullValidator;
-import org.hibernate.validation.constraints.impl.NullValidator;
-import org.hibernate.validation.constraints.impl.PastValidatorForCalendar;
-import org.hibernate.validation.constraints.impl.PastValidatorForDate;
-import org.hibernate.validation.constraints.impl.PatternValidator;
-import org.hibernate.validation.constraints.impl.SizeValidatorForArray;
-import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfBoolean;
-import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfByte;
-import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfChar;
-import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfDouble;
-import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfFloat;
-import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfInt;
-import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfLong;
-import org.hibernate.validation.constraints.impl.SizeValidatorForCollection;
-import org.hibernate.validation.constraints.impl.SizeValidatorForMap;
-import org.hibernate.validation.constraints.impl.SizeValidatorForString;
-import org.hibernate.validation.util.ReflectionHelper;
-
-/**
- * Keeps track of builtin constraints and their validator implementations, as well as already resolved validator definitions.
- *
- * @author Hardy Ferentschik
- * @author Alaa Nassef
- */
-public class ConstraintHelper {
-
-	private final static Map<Class<? extends Annotation>, List<Class<? extends ConstraintValidator<?, ?>>>> builtinConstraints =
-			new ConcurrentHashMap<Class<? extends Annotation>, List<Class<? extends ConstraintValidator<?, ?>>>>();
-
-	static {
-		List<Class<? extends ConstraintValidator<?, ?>>> constraintList =
-				new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
-		constraintList.add( AssertFalseValidator.class );
-		builtinConstraints.put( AssertFalse.class, constraintList );
-
-		constraintList = new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
-		constraintList.add( AssertTrueValidator.class );
-		builtinConstraints.put( AssertTrue.class, constraintList );
-
-		constraintList = new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
-		constraintList.add( DecimalMaxValidatorForNumber.class );
-		constraintList.add( DecimalMaxValidatorForString.class );
-		builtinConstraints.put( DecimalMax.class, constraintList );
-
-		constraintList = new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
-		constraintList.add( DecimalMinValidatorForNumber.class );
-		constraintList.add( DecimalMinValidatorForString.class );
-		builtinConstraints.put( DecimalMin.class, constraintList );
-
-		constraintList = new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
-		constraintList.add( DigitsValidatorForString.class );
-		constraintList.add( DigitsValidatorForNumber.class );
-		builtinConstraints.put( Digits.class, constraintList );
-
-		constraintList = new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
-		constraintList.add( FutureValidatorForCalendar.class );
-		constraintList.add( FutureValidatorForDate.class );
-		builtinConstraints.put( Future.class, constraintList );
-
-		constraintList = new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
-		constraintList.add( MaxValidatorForNumber.class );
-		constraintList.add( MaxValidatorForString.class );
-		builtinConstraints.put( Max.class, constraintList );
-
-		constraintList = new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
-		constraintList.add( MinValidatorForNumber.class );
-		constraintList.add( MinValidatorForString.class );
-		builtinConstraints.put( Min.class, constraintList );
-
-		constraintList = new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
-		constraintList.add( NotNullValidator.class );
-		builtinConstraints.put( NotNull.class, constraintList );
-
-		constraintList = new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
-		constraintList.add( NullValidator.class );
-		builtinConstraints.put( Null.class, constraintList );
-
-		constraintList = new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
-		constraintList.add( PastValidatorForCalendar.class );
-		constraintList.add( PastValidatorForDate.class );
-		builtinConstraints.put( Past.class, constraintList );
-
-		constraintList = new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
-		constraintList.add( PatternValidator.class );
-		builtinConstraints.put( Pattern.class, constraintList );
-
-		constraintList = new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
-		constraintList.add( SizeValidatorForString.class );
-		constraintList.add( SizeValidatorForCollection.class );
-		constraintList.add( SizeValidatorForArray.class );
-		constraintList.add( SizeValidatorForMap.class );
-		constraintList.add( SizeValidatorForArraysOfBoolean.class );
-		constraintList.add( SizeValidatorForArraysOfByte.class );
-		constraintList.add( SizeValidatorForArraysOfChar.class );
-		constraintList.add( SizeValidatorForArraysOfDouble.class );
-		constraintList.add( SizeValidatorForArraysOfFloat.class );
-		constraintList.add( SizeValidatorForArraysOfInt.class );
-		constraintList.add( SizeValidatorForArraysOfLong.class );
-		builtinConstraints.put( Size.class, constraintList );
-	}
-
-	private final Map<Class<? extends Annotation>, List<Class<? extends ConstraintValidator<? extends Annotation, ?>>>> constraintValidatorDefinitons =
-			new ConcurrentHashMap<Class<? extends Annotation>, List<Class<? extends ConstraintValidator<? extends Annotation, ?>>>>();
-
-	public List<Class<? extends ConstraintValidator<? extends Annotation, ?>>> getBuiltInConstraints(Class<? extends Annotation> annotationType) {
-		final List<Class<? extends ConstraintValidator<?, ?>>> builtInList = getBuiltInFromAnnotationType(
-				annotationType
-		);
-
-		if ( builtInList == null || builtInList.size() == 0 ) {
-			throw new ValidationException( "Unable to find constraints for  " + annotationType );
-		}
-		List<Class<? extends ConstraintValidator<? extends Annotation, ?>>> constraints =
-				new ArrayList<Class<? extends ConstraintValidator<? extends Annotation, ?>>>( builtInList.size() );
-		for ( Class<? extends ConstraintValidator<?, ?>> validatorClass : builtInList ) {
-			//safe cause all CV for a given annotation A are CV<A, ?>
-			@SuppressWarnings("unchecked")
-			Class<ConstraintValidator<? extends Annotation, ?>> safeValdiatorClass = ( Class<ConstraintValidator<? extends Annotation, ?>> ) validatorClass;
-			constraints.add( safeValdiatorClass );
-		}
-
-		return constraints;
-	}
-
-	private List<Class<? extends ConstraintValidator<?, ?>>> getBuiltInFromAnnotationType(Class<? extends Annotation> annotationType) {
-		return builtinConstraints.get( annotationType );
-	}
-
-	public boolean isBuiltinConstraint(Class<? extends Annotation> annotationType) {
-		return builtinConstraints.containsKey( annotationType );
-	}
-
-	/**
-	 * 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 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 ) || isBuiltinConstraint( a.annotationType() ) ) {
-						isMultiValueConstraint = true;
-					}
-					else {
-						isMultiValueConstraint = false;
-						break;
-					}
-				}
-			}
-		}
-		catch ( NoSuchMethodException nsme ) {
-			// ignore
-		}
-		catch ( IllegalAccessException iae ) {
-			// ignore
-		}
-		catch ( InvocationTargetException ite ) {
-			// 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.
-	 *
-	 * @return A list of constraint annotations or the empty list if <code>annotation</code> is not a multi constraint
-	 *         annotation.
-	 */
-	public <A extends Annotation> List<Annotation> getMultiValueConstraints(A annotation) {
-		List<Annotation> annotationList = new ArrayList<Annotation>();
-		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 ) || isBuiltinConstraint( a.annotationType() ) ) {
-						annotationList.add( a );
-					}
-				}
-			}
-		}
-		catch ( NoSuchMethodException nsme ) {
-			// ignore
-		}
-		catch ( IllegalAccessException iae ) {
-			// ignore
-		}
-		catch ( InvocationTargetException ite ) {
-			// ignore
-		}
-		return annotationList;
-	}
-
-	/**
-	 * Checks whether the specified annotation is a valid constraint annotation. A constraint annotations has to
-	 * fulfill the following conditions:
-	 * <ul>
-	 * <li>Has to contain a <code>ConstraintValidator</code> implementation.</li>
-	 * <li>Defines a message parameter.</li>
-	 * <li>Defines a group parameter.</li>
-	 * </ul>
-	 *
-	 * @param annotation The annotation to test.
-	 *
-	 * @return <code>true</code> if the annotation fulfills the above condtions, <code>false</code> otherwise.
-	 */
-	public boolean isConstraintAnnotation(Annotation annotation) {
-
-		Constraint constraint = annotation.annotationType()
-				.getAnnotation( Constraint.class );
-		if ( constraint == null ) {
-			return false;
-		}
-
-		try {
-			ReflectionHelper.getAnnotationParameter( annotation, "message", String.class );
-		}
-		catch ( Exception e ) {
-			String msg = annotation.annotationType().getName() + " contains Constraint annotation, but does " +
-					"not contain a message parameter.";
-			throw new ConstraintDefinitionException( msg );
-		}
-
-		try {
-			Class<?>[] defaultGroups = ( Class<?>[] ) annotation.annotationType()
-					.getMethod( "groups" )
-					.getDefaultValue();
-			if ( defaultGroups.length != 0 ) {
-				String msg = annotation.annotationType()
-						.getName() + " contains Constraint annotation, but the groups " +
-						"paramter default value is not empty.";
-				throw new ConstraintDefinitionException( msg );
-			}
-		}
-		catch ( NoSuchMethodException nsme ) {
-			String msg = annotation.annotationType().getName() + " contains Constraint annotation, but does " +
-					"not contain a groups parameter.";
-			throw new ConstraintDefinitionException( msg );
-		}
-
-		Method[] methods = annotation.getClass().getMethods();
-		for ( Method m : methods ) {
-			if ( m.getName().startsWith( "valid" ) ) {
-				String msg = "Parameters starting with 'valid' are not allowed in a constraint.";
-				throw new ConstraintDefinitionException( msg );
-			}
-		}
-		return true;
-	}
-
-	public List<Class<? extends ConstraintValidator<? extends Annotation, ?>>> getConstraintValidatorDefinition(Class<? extends Annotation> annotationClass) {
-		if ( annotationClass == null ) {
-			throw new IllegalArgumentException( "Class cannot be null" );
-		}
-		return constraintValidatorDefinitons.get( annotationClass );
-	}
-
-	public <A extends Annotation> void addConstraintValidatorDefinition(Class<A> annotationClass, List<Class<? extends ConstraintValidator<? extends Annotation, ?>>> definitionClasses) {
-		constraintValidatorDefinitons.put( annotationClass, definitionClasses );
-	}
-
-	public boolean containsConstraintValidatorDefinition(Class<? extends Annotation> annotationClass) {
-		return constraintValidatorDefinitons.containsKey( annotationClass );
-	}
-}

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintTree.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintTree.java	2009-06-16 15:29:59 UTC (rev 16797)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintTree.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -36,6 +36,8 @@
 
 import org.hibernate.validation.util.LoggerFactory;
 import org.hibernate.validation.util.ValidatorTypeHelper;
+import org.hibernate.validation.engine.ExecutionContext;
+import org.hibernate.validation.engine.ConstraintValidatorContextImpl;
 
 /**
  * Due to constraint conposition a single constraint annotation can lead to a whole constraint tree beeing validated.

Deleted: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ElementDescriptorImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ElementDescriptorImpl.java	2009-06-16 15:29:59 UTC (rev 16797)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ElementDescriptorImpl.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -1,64 +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.engine;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-import javax.validation.metadata.ConstraintDescriptor;
-import javax.validation.metadata.ElementDescriptor;
-
-/**
- * Describe a validated element (class, field or property).
- *
- * @author Emmanuel Bernard
- * @author Hardy Ferentschik
- */
-public class ElementDescriptorImpl implements ElementDescriptor {
-	private final Class<?> type;
-	private final Set<ConstraintDescriptor<?>> constraintDescriptors = new HashSet<ConstraintDescriptor<?>>();
-
-	public ElementDescriptorImpl(Class<?> type) {
-		this.type = type;
-	}
-
-	public void addConstraintDescriptor(ConstraintDescriptorImpl constraintDescriptor) {
-		constraintDescriptors.add( constraintDescriptor );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public boolean hasConstraints() {
-		return constraintDescriptors.size() != 0;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public Class<?> getType() {
-		return type;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public Set<ConstraintDescriptor<?>> getConstraintDescriptors() {
-		return Collections.unmodifiableSet( constraintDescriptors );
-	}
-}

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ExecutionContext.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ExecutionContext.java	2009-06-16 15:29:59 UTC (rev 16797)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ExecutionContext.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -35,6 +35,7 @@
 import javax.validation.TraversableResolver;
 
 import org.hibernate.validation.util.IdentitySet;
+import org.hibernate.validation.metadata.MetaConstraint;
 
 /**
  * Context object keeping track of all processed objects and failing constraints.

Deleted: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaConstraint.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaConstraint.java	2009-06-16 15:29:59 UTC (rev 16797)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaConstraint.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -1,176 +0,0 @@
-// $Id$// $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.lang.annotation.Annotation;
-import java.lang.annotation.ElementType;
-import java.lang.reflect.Field;
-import java.lang.reflect.Member;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-import javax.validation.metadata.ConstraintDescriptor;
-import javax.validation.ConstraintViolation;
-
-import org.hibernate.validation.util.ReflectionHelper;
-
-/**
- * Instances of this class abstract the constraint type  (class, method or field constraint) and gives access to
- * meta data about the constraint. This allows a unified handling of constraints in the validator imlpementation.
- *
- * @author Hardy Ferentschik
- */
-public class MetaConstraint<T, A extends Annotation> {
-
-	/**
-	 * The constraint tree created from the constraint annotation.
-	 */
-	private final ConstraintTree<A> constraintTree;
-
-	/**
-	 * The member the constraint was defined on.
-	 */
-	private final Member member;
-
-	/**
-	 * The JavaBeans name for this constraint.
-	 */
-	private final String propertyName;
-
-	/**
-	 * Describes on which level (<code>TYPE</code>, <code>METHOD</code>, <code>FIELD</code>) the constraint was
-	 * defined on.
-	 */
-	private final ElementType elementType;
-
-	/**
-	 * The class of the bean hosting this constraint.
-	 */
-	private final Class<T> beanClass;
-
-	public MetaConstraint(Class<T> beanClass, ConstraintDescriptor<A> constraintDescriptor) {
-		this.elementType = ElementType.TYPE;
-		this.member = null;
-		this.propertyName = "";
-		this.beanClass = beanClass;
-		constraintTree = new ConstraintTree<A>( constraintDescriptor );
-	}
-
-	public MetaConstraint(Member member, Class<T> beanClass, ConstraintDescriptor<A> constraintDescriptor) {
-		if ( member instanceof Method ) {
-			this.elementType = ElementType.METHOD;
-		}
-		else if ( member instanceof Field ) {
-			this.elementType = ElementType.FIELD;
-		}
-		else {
-			throw new IllegalArgumentException( "Non allowed member type: " + member );
-		}
-		this.member = member;
-		this.propertyName = ReflectionHelper.getPropertyName( member );
-		this.beanClass = beanClass;
-		constraintTree = new ConstraintTree<A>( constraintDescriptor );
-	}
-
-
-	/**
-	 * @return Returns the list of groups this constraint is part of. This might include the default group even when
-	 *         it is not explicitly specified, but part of the redefined default group list of the hosting bean.
-	 */
-	public Set<Class<?>> getGroupList() {
-		return constraintTree.getDescriptor().getGroups();
-	}
-
-	public ConstraintDescriptor getDescriptor() {
-		return constraintTree.getDescriptor();
-	}
-
-	public Class<T> getBeanClass() {
-		return beanClass;
-	}
-
-	public String getPropertyName() {
-		return propertyName;
-	}
-
-	public ElementType getElementType() {
-		return elementType;
-	}
-
-	public ConstraintTree getConstraintTree() {
-		return constraintTree;
-	}
-
-	public <T> boolean validateConstraint(ExecutionContext<T> executionContext) {
-		final Object leafBeanInstance = executionContext.peekCurrentBean();
-		Object value = getValue( leafBeanInstance );
-		List<ConstraintViolation<T>> constraintViolations = new ArrayList<ConstraintViolation<T>>();
-		constraintTree.validateConstraints( value, typeOfAnnoatedElement(), executionContext, constraintViolations );
-		if ( constraintViolations.size() > 0 ) {
-			executionContext.addConstraintFailures( constraintViolations );
-			return false;
-		}
-		return true;
-	}
-
-	public <T> boolean validateConstraint(Object value, ExecutionContext<T> executionContext) {
-		List<ConstraintViolation<T>> constraintViolations = new ArrayList<ConstraintViolation<T>>();
-		constraintTree.validateConstraints( value, typeOfAnnoatedElement(), executionContext, constraintViolations );
-		if ( constraintViolations.size() > 0 ) {
-			executionContext.addConstraintFailures( constraintViolations );
-			return false;
-		}
-		return true;
-	}
-
-	private Type typeOfAnnoatedElement() {
-		Type t;
-		switch ( elementType ) {
-			case TYPE: {
-				t = beanClass;
-				break;
-			}
-			default: {
-				t = ReflectionHelper.typeOf( member );
-				if ( t instanceof Class && ((Class) t).isPrimitive()) {
-					t = ReflectionHelper.boxedTyp( t );
-				}
-			}
-		}
-		return t;
-	}
-
-	/**
-	 * @param o the object from which to retrieve the value.
-	 *
-	 * @return Returns the value for this constraint from the specified object. Depending on the type either the value itself
-	 *         is returned of method or field access is used to access the value.
-	 */
-	private Object getValue(Object o) {
-		switch ( elementType ) {
-			case TYPE: {
-				return o;
-			}
-			default: {
-				return ReflectionHelper.getValue( member, o );
-			}
-		}
-	}
-}

Deleted: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/PropertyDescriptorImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/PropertyDescriptorImpl.java	2009-06-16 15:29:59 UTC (rev 16797)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/PropertyDescriptorImpl.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -1,52 +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.engine;
-
-import javax.validation.metadata.PropertyDescriptor;
-
-/**
- * Describe a validated element (class, field or property).
- *
- * @author Emmanuel Bernard
- * @author Hardy Ferentschik
- */
-public class PropertyDescriptorImpl extends ElementDescriptorImpl implements PropertyDescriptor {
-	private final boolean cascaded;
-	private final String property;
-
-
-	public PropertyDescriptorImpl(Class<?> returnType, boolean cascaded, String property) {
-		super( returnType );
-		this.cascaded = cascaded;
-		this.property = property;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public boolean isCascaded() {
-		return cascaded;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public String getPropertyName() {
-		return property;
-	}
-}
\ No newline at end of file

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorContextImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorContextImpl.java	2009-06-16 15:29:59 UTC (rev 16797)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorContextImpl.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -6,6 +6,9 @@
 import javax.validation.Validator;
 import javax.validation.ValidatorContext;
 
+import org.hibernate.validation.metadata.BeanMetaDataCache;
+import org.hibernate.validation.metadata.ConstraintHelper;
+
 /**
  * @author Emmanuel Bernard
  * @author Hardy Ferentschik

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java	2009-06-16 15:29:59 UTC (rev 16797)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -30,8 +30,12 @@
 import javax.validation.ValidationException;
 import javax.validation.spi.ConfigurationState;
 
-import org.hibernate.validation.engine.xml.AnnotationIgnores;
-import org.hibernate.validation.engine.xml.XmlMappingParser;
+import org.hibernate.validation.metadata.AnnotationIgnores;
+import org.hibernate.validation.xml.XmlMappingParser;
+import org.hibernate.validation.metadata.BeanMetaDataImpl;
+import org.hibernate.validation.metadata.BeanMetaDataCache;
+import org.hibernate.validation.metadata.MetaConstraint;
+import org.hibernate.validation.metadata.ConstraintHelper;
 
 /**
  * Factory returning initialized <code>Validator</code> instances.

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-06-16 15:29:59 UTC (rev 16797)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -47,6 +47,11 @@
 import org.hibernate.validation.util.LoggerFactory;
 import org.hibernate.validation.util.PropertyPath;
 import org.hibernate.validation.util.ReflectionHelper;
+import org.hibernate.validation.metadata.BeanMetaData;
+import org.hibernate.validation.metadata.BeanMetaDataImpl;
+import org.hibernate.validation.metadata.BeanMetaDataCache;
+import org.hibernate.validation.metadata.MetaConstraint;
+import org.hibernate.validation.metadata.ConstraintHelper;
 
 /**
  * The main Bean Validation class. This is the core processing class of Hibernate Validator.

Copied: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/AnnotationIgnores.java (from rev 16797, validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/xml/AnnotationIgnores.java)
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/AnnotationIgnores.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/AnnotationIgnores.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -0,0 +1,119 @@
+// $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.metadata;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.slf4j.Logger;
+
+import org.hibernate.validation.util.LoggerFactory;
+
+/**
+ * This class instantiated during the parsing of the XML configuration data and keeps
+ * track of the annotations which should be ignored.
+ *
+ * @author Hardy Ferentschik
+ */
+public class AnnotationIgnores {
+
+	private static final Logger log = LoggerFactory.make();
+
+	/**
+	 * Keeps track whether the 'ignore-annotations' flag is set on bean level in the xml configuration. If 'ignore-annotations'
+	 * is not specified <code>false</code> is the default.
+	 */
+	private final Map<Class<?>, Boolean> ignoreAnnotationDefaults = new HashMap<Class<?>, Boolean>();
+
+	/**
+	 * Keeps track of explicitly excluded members (fields and properties) for a given class. If a member appears in
+	 * the list mapped to a given class 'ignore-annotations' was explicitly set to <code>true</code> in the configuration
+	 * for this class.
+	 */
+	private final Map<Class<?>, List<Member>> ignoreAnnotationOnMember = new HashMap<Class<?>, List<Member>>();
+
+	private final List<Class<?>> ignoreAnnotationOnClass = new ArrayList<Class<?>>();
+
+	public void setDefaultIgnoreAnnotation(Class<?> clazz, Boolean b) {
+		if ( b == null ) {
+			ignoreAnnotationDefaults.put( clazz, Boolean.FALSE );
+		}
+		else {
+			ignoreAnnotationDefaults.put( clazz, b );
+		}
+	}
+
+	public boolean getDefaultIgnoreAnnotation(Class<?> clazz) {
+		return ignoreAnnotationDefaults.containsKey( clazz ) && ignoreAnnotationDefaults.get( clazz );
+	}
+
+	public void setIgnoreAnnotationsOnMember(Member member) {
+		Class<?> beanClass = member.getDeclaringClass();
+		if ( ignoreAnnotationOnMember.get( beanClass ) == null ) {
+			List<Member> tmpList = new ArrayList<Member>();
+			tmpList.add( member );
+			ignoreAnnotationOnMember.put( beanClass, tmpList );
+		}
+		else {
+			ignoreAnnotationOnMember.get( beanClass ).add( member );
+		}
+	}
+
+	public boolean isIgnoreAnnotations(Member member) {
+		boolean ignoreAnnotation;
+		Class<?> clazz = member.getDeclaringClass();
+		List<Member> ignoreAnnotationForMembers = ignoreAnnotationOnMember.get( clazz );
+		if ( ignoreAnnotationForMembers == null || !ignoreAnnotationForMembers.contains( member ) ) {
+			ignoreAnnotation = getDefaultIgnoreAnnotation( clazz );
+		}
+		else {
+			ignoreAnnotation = ignoreAnnotationForMembers.contains( member );
+		}
+		if ( ignoreAnnotation ) {
+			logMessage( member, clazz );
+		}
+		return ignoreAnnotation;
+	}
+
+	private void logMessage(Member member, Class<?> clazz) {
+		String type;
+		if ( member instanceof Field ) {
+			type = "Field";
+		}
+		else {
+			type = "Property";
+		}
+		log.debug( type + " level annotations are getting ignored for " + clazz.getName() + "." + member.getName() );
+	}
+
+	public void setIgnoreAnnotationsOnClass(Class<?> clazz) {
+		ignoreAnnotationOnClass.add( clazz );
+	}
+
+	public boolean isIgnoreAnnotations(Class<?> clazz) {
+		boolean ignoreAnnotation = ignoreAnnotationOnClass.contains( clazz ) || getDefaultIgnoreAnnotation( clazz );
+		if ( log.isDebugEnabled() && ignoreAnnotation ) {
+			log.debug( "Class level annotation are getting ignored for " + clazz.getName() );
+		}
+		return ignoreAnnotation;
+	}
+}

Copied: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanDescriptorImpl.java (from rev 16797, validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanDescriptorImpl.java)
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanDescriptorImpl.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanDescriptorImpl.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -0,0 +1,30 @@
+package org.hibernate.validation.metadata;
+
+import java.util.Set;
+import javax.validation.metadata.BeanDescriptor;
+import javax.validation.metadata.PropertyDescriptor;
+
+/**
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ */
+public class BeanDescriptorImpl<T> extends ElementDescriptorImpl implements BeanDescriptor {
+	private final BeanMetaData<T> metadataBean;
+
+	public BeanDescriptorImpl(BeanMetaData<T> metadataBean) {
+		super( metadataBean.getBeanClass() );
+		this.metadataBean = metadataBean;
+	}
+
+	public boolean isBeanConstrained() {
+		return metadataBean.getConstrainedProperties().size() > 0;
+	}
+
+	public PropertyDescriptor getConstraintsForProperty(String propertyName) {
+		return metadataBean.getPropertyDescriptor( propertyName );
+	}
+
+	public Set<PropertyDescriptor> getConstrainedProperties() {
+		return metadataBean.getConstrainedProperties();
+	}
+}

Copied: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaData.java (from rev 16797, validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaData.java)
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaData.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaData.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -0,0 +1,77 @@
+// $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.metadata;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Member;
+import java.util.List;
+import java.util.Set;
+import javax.validation.metadata.BeanDescriptor;
+import javax.validation.metadata.PropertyDescriptor;
+
+import org.hibernate.validation.metadata.MetaConstraint;
+
+/**
+ * Interface defining the meta data about the constraints defined in a given bean.
+ *
+ * @author Hardy Ferentschik
+ */
+public interface BeanMetaData<T> {
+
+	/**
+	 * @return the class of the bean.
+	 */
+	Class<T> getBeanClass();
+
+	/**
+	 * @return an instance of <code>ElementDescriptor</code> describing the bean this meta data applies for.
+	 */
+	BeanDescriptor getBeanDescriptor();
+
+	/**
+	 * @return A list of all cascaded methods and fields (methods/fields annotated with &#064;Valid).
+	 */
+	List<Member> getCascadedMembers();
+
+	/**
+	 * @return A map mapping defined group sequences to a list of groups.
+	 */
+	List<Class<?>> getDefaultGroupSequence();
+
+	/**
+	 * @return A list of <code>MetaConstraint</code> instances encapsulating the information of all the constraints
+	 *         defined on the bean.
+	 */
+	List<MetaConstraint<T, ? extends Annotation>> geMetaConstraintList();
+
+	/**
+	 * Return <code>PropertyDescriptor</code> for the given property.
+	 *
+	 * @param property the property for which to retrieve the descriptor.
+	 *
+	 * @return Returns the <code>PropertyDescriptor</code> for the given property or <code>null</code> in case the
+	 *         property does not have a descriptor.
+	 */
+	PropertyDescriptor getPropertyDescriptor(String property);
+
+	/**
+	 * @return the property descriptors having at least one constraint defined or which are marked
+	 *         as cascaded (@Valid).
+	 */
+	Set<PropertyDescriptor> getConstrainedProperties();
+}

Copied: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaDataCache.java (from rev 16797, validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataCache.java)
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaDataCache.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaDataCache.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -0,0 +1,48 @@
+// $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.metadata;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Cache for created instances of <code>BeanMetaData</code>.
+ *
+ * @author Hardy Ferentschik
+ */
+public class BeanMetaDataCache {
+	/**
+	 * A map for the meta data for each entity. The key is the class and the value the bean meta data for this
+	 * entity.
+	 */
+	private Map<Class<?>, BeanMetaDataImpl<?>> metadataProviders = new ConcurrentHashMap<Class<?>, BeanMetaDataImpl<?>>(
+			10
+	);
+
+	@SuppressWarnings("unchecked")
+	public <T> BeanMetaDataImpl<T> getBeanMetaData(Class<T> beanClass) {
+		if ( beanClass == null ) {
+			throw new IllegalArgumentException( "Class cannot be null" );
+		}
+		return ( BeanMetaDataImpl<T> ) metadataProviders.get( beanClass );
+	}
+
+	public <T> void addBeanMetaData(Class<T> beanClass, BeanMetaDataImpl<T> metaData) {
+		metadataProviders.put( beanClass, metaData );
+	}
+}

Copied: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaDataImpl.java (from rev 16797, validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java)
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaDataImpl.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaDataImpl.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -0,0 +1,390 @@
+// $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.metadata;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.validation.GroupSequence;
+import javax.validation.Valid;
+import javax.validation.ValidationException;
+import javax.validation.groups.Default;
+import javax.validation.metadata.BeanDescriptor;
+import javax.validation.metadata.PropertyDescriptor;
+
+import org.slf4j.Logger;
+
+import org.hibernate.validation.metadata.AnnotationIgnores;
+import org.hibernate.validation.util.LoggerFactory;
+import org.hibernate.validation.util.ReflectionHelper;
+import org.hibernate.validation.metadata.MetaConstraint;
+
+
+/**
+ * This class encapsulates all meta data needed for validation. Implementations of {@code Validator} interface can
+ * instantiate an instance of this class and delegate the metadata extraction to it.
+ *
+ * @author Hardy Ferentschik
+ */
+
+public class BeanMetaDataImpl<T> implements BeanMetaData<T> {
+
+	private static final Logger log = LoggerFactory.make();
+
+	/**
+	 * The root bean class for this validator.
+	 */
+	private final Class<T> beanClass;
+
+	/**
+	 * The main element descriptor for <code>beanClass</code>.
+	 */
+	private BeanDescriptorImpl<T> beanDescriptor;
+
+	/**
+	 * List of constraints.
+	 */
+	private List<MetaConstraint<T, ? extends Annotation>> metaConstraintList = new ArrayList<MetaConstraint<T, ? extends Annotation>>();
+
+	/**
+	 * List of cascaded members.
+	 */
+	private List<Member> cascadedMembers = new ArrayList<Member>();
+
+	/**
+	 * Maps field and method names to their <code>ElementDescriptorImpl</code>.
+	 */
+	private Map<String, PropertyDescriptor> propertyDescriptors = new HashMap<String, PropertyDescriptor>();
+
+	/**
+	 * Maps group sequences to the list of group/sequences.
+	 */
+	private List<Class<?>> defaultGroupSequence = new ArrayList<Class<?>>();
+
+	/**
+	 * Object keeping track of all constraints.
+	 */
+	private final ConstraintHelper constraintHelper;
+
+
+	public BeanMetaDataImpl(Class<T> beanClass, ConstraintHelper constraintHelper) {
+		this(
+				beanClass,
+				constraintHelper,
+				new AnnotationIgnores()
+		);
+	}
+
+	public BeanMetaDataImpl(Class<T> beanClass, ConstraintHelper constraintHelper, AnnotationIgnores annotationIgnores) {
+		this.beanClass = beanClass;
+		this.constraintHelper = constraintHelper;
+		createMetaData( annotationIgnores );
+	}
+
+	public Class<T> getBeanClass() {
+		return beanClass;
+	}
+
+	public BeanDescriptor getBeanDescriptor() {
+		return beanDescriptor;
+	}
+
+	public List<Member> getCascadedMembers() {
+		return Collections.unmodifiableList( cascadedMembers );
+	}
+
+	public List<MetaConstraint<T, ? extends Annotation>> geMetaConstraintList() {
+		return Collections.unmodifiableList( metaConstraintList );
+	}
+
+	public void addMetaConstraint(MetaConstraint<T, ? extends Annotation> metaConstraint) {
+		metaConstraintList.add( metaConstraint );
+	}
+
+	public void addCascadedMember(Member member) {
+		cascadedMembers.add( member );
+	}
+
+	public PropertyDescriptor getPropertyDescriptor(String property) {
+		return propertyDescriptors.get( property );
+	}
+
+	public List<Class<?>> getDefaultGroupSequence() {
+		return Collections.unmodifiableList( defaultGroupSequence );
+	}
+
+	public void setDefaultGroupSequence(List<Class<?>> groupSequence) {
+		defaultGroupSequence = new ArrayList<Class<?>>();
+		for ( Class<?> group : groupSequence ) {
+			if ( group.getName().equals( beanClass.getName() ) ) {
+				defaultGroupSequence.add( Default.class );
+			}
+			else if ( group.getName().equals( Default.class.getName() ) ) {
+				throw new ValidationException( "'Default.class' cannot appear in default group sequence list." );
+			}
+			else {
+				defaultGroupSequence.add( group );
+			}
+		}
+		if ( log.isTraceEnabled() ) {
+			log.trace(
+					"Members of the default group sequence for bean {} are: {}",
+					beanClass.getName(),
+					defaultGroupSequence
+			);
+		}
+	}
+
+	public Set<PropertyDescriptor> getConstrainedProperties() {
+		return Collections.unmodifiableSet( new HashSet<PropertyDescriptor>( propertyDescriptors.values() ) );
+	}
+
+	/**
+	 * Create bean desciptor, find all classes/subclasses/interfaces which have to be taken in consideration
+	 * for this validator and create meta data.
+	 *
+	 * @param annotationIgnores Datastructure keeping track on which annotation should be ignored.
+	 */
+	private void createMetaData(AnnotationIgnores annotationIgnores) {
+		beanDescriptor = new BeanDescriptorImpl<T>( this );
+		initDefaultGroupSequence();
+		List<Class> classes = new ArrayList<Class>();
+		computeClassHierarchy( beanClass, classes );
+		for ( Class current : classes ) {
+			initClass( current, annotationIgnores );
+		}
+	}
+
+	/**
+	 * Get all superclasses and interfaces recursively.
+	 *
+	 * @param clazz The class to start the search with.
+	 * @param classes List of classes to which to add all found super classes and interfaces.
+	 */
+	private void computeClassHierarchy(Class clazz, List<Class> classes) {
+		if ( log.isTraceEnabled() ) {
+			log.trace( "Processing: {}", clazz );
+		}
+		for ( Class current = clazz; current != null; current = current.getSuperclass() ) {
+			if ( classes.contains( current ) ) {
+				return;
+			}
+			classes.add( current );
+			for ( Class currentInterface : current.getInterfaces() ) {
+				computeClassHierarchy( currentInterface, classes );
+			}
+		}
+	}
+
+	private void initClass(Class clazz, AnnotationIgnores annotationIgnores) {
+		initClassConstraints( clazz, annotationIgnores );
+		initMethodConstraints( clazz, annotationIgnores );
+		initFieldConstraints( clazz, annotationIgnores );
+	}
+
+	/**
+	 * Checks whether there is a default group sequence defined for this class.
+	 * See HV-113.
+	 */
+	private void initDefaultGroupSequence() {
+		List<Class<?>> groupSequence = new ArrayList<Class<?>>();
+		GroupSequence groupSequenceAnnotation = beanClass.getAnnotation( GroupSequence.class );
+		if ( groupSequenceAnnotation == null ) {
+			groupSequence.add( beanClass );
+		}
+		else {
+			groupSequence.addAll( Arrays.asList( groupSequenceAnnotation.value() ) );
+		}
+		setDefaultGroupSequence( groupSequence );
+	}
+
+	private void initFieldConstraints(Class clazz, AnnotationIgnores annotationIgnores) {
+		for ( Field field : clazz.getDeclaredFields() ) {
+			List<ConstraintDescriptorImpl<?>> fieldMetadata = findConstraints( field );
+			for ( ConstraintDescriptorImpl<?> constraintDescription : fieldMetadata ) {
+				if ( annotationIgnores.isIgnoreAnnotations( field ) ) {
+					break;
+				}
+				ReflectionHelper.setAccessibility( field );
+				MetaConstraint<T, ?> metaConstraint = createMetaConstraint( field, constraintDescription );
+				metaConstraintList.add( metaConstraint );
+			}
+			if ( field.isAnnotationPresent( Valid.class ) ) {
+				ReflectionHelper.setAccessibility( field );
+				cascadedMembers.add( field );
+				addPropertyDescriptorForMember( field );
+			}
+		}
+	}
+
+	private void initMethodConstraints(Class clazz, AnnotationIgnores annotationIgnores) {
+		for ( Method method : clazz.getDeclaredMethods() ) {
+			List<ConstraintDescriptorImpl<?>> methodMetadata = findConstraints( method );
+			for ( ConstraintDescriptorImpl<?> constraintDescription : methodMetadata ) {
+				if ( annotationIgnores.isIgnoreAnnotations( method ) ) {
+					break;
+				}
+				ReflectionHelper.setAccessibility( method );
+				MetaConstraint<T, ?> metaConstraint = createMetaConstraint( method, constraintDescription );
+				metaConstraintList.add( metaConstraint );
+			}
+			if ( method.isAnnotationPresent( Valid.class ) ) {
+				ReflectionHelper.setAccessibility( method );
+				cascadedMembers.add( method );
+				addPropertyDescriptorForMember( method );
+			}
+		}
+	}
+
+	private PropertyDescriptorImpl addPropertyDescriptorForMember(Member member) {
+		String name = ReflectionHelper.getPropertyName( member );
+		PropertyDescriptorImpl propertyDescriptor = ( PropertyDescriptorImpl ) propertyDescriptors.get(
+				name
+		);
+		if ( propertyDescriptor == null ) {
+			propertyDescriptor = new PropertyDescriptorImpl(
+					ReflectionHelper.getType( member ),
+					( ( AnnotatedElement ) member ).isAnnotationPresent( Valid.class ),
+					name
+			);
+			propertyDescriptors.put( name, propertyDescriptor );
+		}
+		return propertyDescriptor;
+	}
+
+	private void initClassConstraints(Class<?> clazz, AnnotationIgnores annotationIgnores) {
+		if ( annotationIgnores.isIgnoreAnnotations( clazz ) ) {
+			return;
+		}
+		List<ConstraintDescriptorImpl<?>> classMetadata = findClassLevelConstraints( clazz );
+		for ( ConstraintDescriptorImpl<?> constraintDescription : classMetadata ) {
+			MetaConstraint<T, ?> metaConstraint = createMetaConstraint( constraintDescription );
+			metaConstraintList.add( metaConstraint );
+		}
+	}
+
+	private <A extends Annotation> MetaConstraint<T, ?> createMetaConstraint(ConstraintDescriptorImpl<A> descriptor) {
+		return new MetaConstraint<T, A>( beanClass, descriptor );
+	}
+
+	private <A extends Annotation> MetaConstraint<T, ?> createMetaConstraint(Member m, ConstraintDescriptorImpl<A> descriptor) {
+		return new MetaConstraint<T, A>( m, beanClass, descriptor );
+	}
+
+	/**
+	 * Examines the given annotation to see whether it is a single or multi valued constraint annotation.
+	 *
+	 * @param clazz the class we are currently processing.
+	 * @param annotation The annotation to examine.
+	 *
+	 * @return A list of constraint descriptors or the empty list in case <code>annotation</code> is neither a
+	 *         single nor multi value annotation.
+	 */
+	private <A extends Annotation> List<ConstraintDescriptorImpl<?>> findConstraintAnnotations(Class<?> clazz, A annotation) {
+		List<ConstraintDescriptorImpl<?>> constraintDescriptors = new ArrayList<ConstraintDescriptorImpl<?>>();
+
+		List<Annotation> constraints = new ArrayList<Annotation>();
+		if ( constraintHelper.isConstraintAnnotation( annotation ) ||
+				constraintHelper.isBuiltinConstraint( annotation.annotationType() ) ) {
+			constraints.add( annotation );
+		}
+
+		// check if we have a multi value constraint
+		constraints.addAll( constraintHelper.getMultiValueConstraints( annotation ) );
+
+		for ( Annotation constraint : constraints ) {
+			final ConstraintDescriptorImpl constraintDescriptor = buildConstraintDescriptor( clazz, constraint );
+			constraintDescriptors.add( constraintDescriptor );
+		}
+		return constraintDescriptors;
+	}
+
+	@SuppressWarnings("unchecked")
+	private <A extends Annotation> ConstraintDescriptorImpl buildConstraintDescriptor(Class<?> clazz, A annotation) {
+		ConstraintDescriptorImpl constraintDescriptor;
+		if ( clazz.isInterface() ) {
+			constraintDescriptor = new ConstraintDescriptorImpl( annotation, constraintHelper, clazz );
+		}
+		else {
+			constraintDescriptor = new ConstraintDescriptorImpl( annotation, constraintHelper );
+		}
+		return constraintDescriptor;
+	}
+
+	/**
+	 * Finds all constraint annotations defined for the given class and returns them in a list of
+	 * constraint descriptors.
+	 *
+	 * @param beanClass The class to check for constraints annotations.
+	 *
+	 * @return A list of constraint descriptors for all constraint specified on the given class.
+	 */
+	private List<ConstraintDescriptorImpl<?>> findClassLevelConstraints(Class<?> beanClass) {
+		List<ConstraintDescriptorImpl<?>> metadata = new ArrayList<ConstraintDescriptorImpl<?>>();
+		for ( Annotation annotation : beanClass.getAnnotations() ) {
+			metadata.addAll( findConstraintAnnotations( beanClass, annotation ) );
+		}
+		for ( ConstraintDescriptorImpl constraintDescriptor : metadata ) {
+			beanDescriptor.addConstraintDescriptor( constraintDescriptor );
+		}
+		return metadata;
+	}
+
+
+	/**
+	 * Finds all constraint annotations defined for the given field/method and returns them in a list of
+	 * constraint descriptors.
+	 *
+	 * @param member The fiels or method to check for constraints annotations.
+	 *
+	 * @return A list of constraint descriptors for all constraint specified for the given field or method.
+	 */
+	private List<ConstraintDescriptorImpl<?>> findConstraints(Member member) {
+		assert member instanceof Field || member instanceof Method;
+
+		List<ConstraintDescriptorImpl<?>> metadata = new ArrayList<ConstraintDescriptorImpl<?>>();
+		for ( Annotation annotation : ( ( AnnotatedElement ) member ).getAnnotations() ) {
+			metadata.addAll( findConstraintAnnotations( member.getDeclaringClass(), annotation ) );
+		}
+
+		String name = ReflectionHelper.getPropertyName( member );
+		for ( ConstraintDescriptorImpl constraintDescriptor : metadata ) {
+			if ( member instanceof Method && name == null ) { // can happen if member is a Method which does not follow the bean convention
+				throw new ValidationException(
+						"Annotated methods must follow the JavaBeans naming convention. " + member.getName() + "() does not."
+				);
+			}
+			PropertyDescriptorImpl propertyDescriptor = ( PropertyDescriptorImpl ) propertyDescriptors.get( name );
+			if ( propertyDescriptor == null ) {
+				propertyDescriptor = addPropertyDescriptorForMember( member );
+			}
+			propertyDescriptor.addConstraintDescriptor( constraintDescriptor );
+		}
+		return metadata;
+	}
+}
\ No newline at end of file

Copied: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ConstraintDescriptorImpl.java (from rev 16797, validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintDescriptorImpl.java)
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ConstraintDescriptorImpl.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ConstraintDescriptorImpl.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -0,0 +1,384 @@
+// $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.metadata;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.validation.Constraint;
+import javax.validation.ConstraintDefinitionException;
+import javax.validation.ConstraintValidator;
+import javax.validation.OverridesAttribute;
+import javax.validation.ReportAsSingleViolation;
+import javax.validation.ValidationException;
+import javax.validation.groups.Default;
+import javax.validation.metadata.ConstraintDescriptor;
+
+import org.slf4j.Logger;
+
+import org.hibernate.validation.util.LoggerFactory;
+import org.hibernate.validation.util.ReflectionHelper;
+import org.hibernate.validation.util.annotationfactory.AnnotationDescriptor;
+import org.hibernate.validation.util.annotationfactory.AnnotationFactory;
+
+/**
+ * Describe a single constraint (including it's composing constraints).
+ *
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ */
+public class ConstraintDescriptorImpl<T extends Annotation> implements ConstraintDescriptor<T> {
+	private static final Logger log = LoggerFactory.make();
+	private static final int OVERRIDES_PARAMETER_DEFAULT_INDEX = -1;
+
+	/**
+	 * The actual constraint annotation.
+	 */
+	private final T annotation;
+
+	/**
+	 * The set of classes implementing the validation for this constraint. See also
+	 * <code>ConstraintValidator</code> resolution algorithm.
+	 */
+	private final List<Class<? extends ConstraintValidator<T, ?>>> constraintValidatorDefinitonClasses = new ArrayList<Class<? extends ConstraintValidator<T, ?>>>();
+
+	/**
+	 * The groups for which to apply this constraint.
+	 */
+	private final Set<Class<?>> groups = new HashSet<Class<?>>();
+
+	/**
+	 * The constraint parameters as map. The key is the paramter name and the value the
+	 * parameter value as specified in the constraint.
+	 */
+	private final Map<String, Object> attributes;
+
+	/**
+	 * The composing constraints for this constraints.
+	 */
+	private final Set<ConstraintDescriptor<?>> composingConstraints = new HashSet<ConstraintDescriptor<?>>();
+
+	/**
+	 * Flag indicating if in case of a composing constraint a single error or multiple errors should be raised.
+	 */
+	private final boolean isReportAsSingleInvalidConstraint;
+
+	/**
+	 * Handle to the builtin constraint implementations.
+	 */
+	private final ConstraintHelper constraintHelper;
+
+	public ConstraintDescriptorImpl(T annotation, ConstraintHelper constraintHelper, Class<?> implicitGroup) {
+		this( annotation, constraintHelper );
+		this.groups.add( implicitGroup );
+	}
+
+
+	public ConstraintDescriptorImpl(T annotation, ConstraintHelper constraintHelper) {
+		this.annotation = annotation;
+		this.attributes = getAnnotationParameters( annotation );
+		this.constraintHelper = constraintHelper;
+
+		this.isReportAsSingleInvalidConstraint = annotation.annotationType().isAnnotationPresent(
+				ReportAsSingleViolation.class
+		);
+
+		Class<?>[] groupsFromAnnotation = ReflectionHelper.getAnnotationParameter(
+				annotation, "groups", Class[].class
+		);
+		if ( groupsFromAnnotation.length == 0 ) {
+			groups.add( Default.class );
+		}
+		else {
+			this.groups.addAll( Arrays.asList( groupsFromAnnotation ) );
+		}
+
+		findConstraintValidatorClasses();
+		Map<ClassIndexWrapper, Map<String, Object>> overrideParameters = parseOverrideParameters();
+		parseComposingConstraints( overrideParameters );
+	}
+
+	private void findConstraintValidatorClasses() {
+		if ( constraintHelper.containsConstraintValidatorDefinition( annotation.annotationType() ) ) {
+			for ( Class<? extends ConstraintValidator<? extends Annotation, ?>> validator : constraintHelper
+					.getConstraintValidatorDefinition( annotation.annotationType() ) ) {
+				constraintValidatorDefinitonClasses.add( ( Class<? extends ConstraintValidator<T, ?>> ) validator );
+			}
+			return;
+		}
+
+		List<Class<? extends ConstraintValidator<? extends Annotation, ?>>> constraintDefinitonClasses = new ArrayList<Class<? extends ConstraintValidator<? extends Annotation, ?>>>();
+		if ( constraintHelper.isBuiltinConstraint( annotation.annotationType() ) ) {
+			constraintDefinitonClasses.addAll( constraintHelper.getBuiltInConstraints( annotation.annotationType() ) );
+		}
+		else {
+			final Class<? extends Annotation> annotationType = annotation.annotationType();
+			Class<? extends ConstraintValidator<?, ?>>[] validatedBy = annotationType
+					.getAnnotation( Constraint.class )
+					.validatedBy();
+			constraintDefinitonClasses.addAll( Arrays.asList( validatedBy ) );
+		}
+
+		constraintHelper.addConstraintValidatorDefinition(
+				annotation.annotationType(), constraintDefinitonClasses
+		);
+
+		for ( Class<? extends ConstraintValidator<? extends Annotation, ?>> validator : constraintDefinitonClasses ) {
+			@SuppressWarnings("unchecked")
+			Class<? extends ConstraintValidator<T, ?>> safeValidator = ( Class<? extends ConstraintValidator<T, ?>> ) validator;
+			constraintValidatorDefinitonClasses.add( safeValidator );
+		}
+	}
+
+	public T getAnnotation() {
+		return annotation;
+	}
+
+	public Set<Class<?>> getGroups() {
+		return Collections.unmodifiableSet( groups );
+	}
+
+	public List<Class<? extends ConstraintValidator<T, ?>>> getConstraintValidatorClasses() {
+		return Collections.unmodifiableList( constraintValidatorDefinitonClasses );
+	}
+
+	public Map<String, Object> getAttributes() {
+		return Collections.unmodifiableMap( attributes );
+	}
+
+	public Set<ConstraintDescriptor<?>> getComposingConstraints() {
+		return Collections.unmodifiableSet( composingConstraints );
+	}
+
+	public boolean isReportAsSingleViolation() {
+		return isReportAsSingleInvalidConstraint;
+	}
+
+	@Override
+	public String toString() {
+		return "ConstraintDescriptorImpl{" +
+				"annotation=" + annotation +
+				", constraintValidatorDefinitonClasses=" + constraintValidatorDefinitonClasses.toString() +
+				", groups=" + groups +
+				", attributes=" + attributes +
+				", 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 );
+		for ( Method m : declaredMethods ) {
+			try {
+				parameters.put( m.getName(), m.invoke( annotation ) );
+			}
+			catch ( IllegalAccessException e ) {
+				throw new ValidationException( "Unable to read annotation attributes: " + annotation.getClass(), e );
+			}
+			catch ( InvocationTargetException e ) {
+				throw new ValidationException( "Unable to read annotation attributes: " + annotation.getClass(), e );
+			}
+		}
+		return Collections.unmodifiableMap( parameters );
+	}
+
+	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 Map<ClassIndexWrapper, Map<String, Object>> parseOverrideParameters() {
+		Map<ClassIndexWrapper, Map<String, Object>> overrideParameters = new HashMap<ClassIndexWrapper, Map<String, Object>>();
+		for ( Method m : annotation.annotationType().getMethods() ) {
+			if ( m.getAnnotation( OverridesAttribute.class ) != null ) {
+				addOverrideAttributes(
+						overrideParameters, m, m.getAnnotation( OverridesAttribute.class )
+				);
+			}
+			else if ( m.getAnnotation( OverridesAttribute.List.class ) != null ) {
+				addOverrideAttributes(
+						overrideParameters,
+						m,
+						m.getAnnotation( OverridesAttribute.List.class ).value()
+				);
+			}
+		}
+		return overrideParameters;
+	}
+
+	private void addOverrideAttributes(Map<ClassIndexWrapper, Map<String, Object>> overrideParameters, Method m, OverridesAttribute... attributes) {
+
+		Object value = getMethodValue( annotation, m );
+		for ( OverridesAttribute overridesAttribute : attributes ) {
+			ensureAttributeIsOverridable( m, overridesAttribute );
+
+			ClassIndexWrapper wrapper = new ClassIndexWrapper(
+					overridesAttribute.constraint(), overridesAttribute.constraintIndex()
+			);
+			Map<String, Object> map = overrideParameters.get( wrapper );
+			if ( map == null ) {
+				map = new HashMap<String, Object>();
+				overrideParameters.put( wrapper, map );
+			}
+			map.put( overridesAttribute.name(), value );
+		}
+	}
+
+	private void ensureAttributeIsOverridable(Method m, OverridesAttribute overridesAttribute) {
+		try {
+			Class<?> returnTypeOfOverridenConstraint = overridesAttribute.constraint()
+					.getMethod( overridesAttribute.name() )
+					.getReturnType();
+			if ( !returnTypeOfOverridenConstraint.equals( m.getReturnType() ) ) {
+				String message = "The overiding type of a composite constraint must be identical to the overwridden one. Expected " + returnTypeOfOverridenConstraint
+						.getName() + " found " + m.getReturnType();
+				throw new ConstraintDefinitionException( message );
+			}
+		}
+		catch ( NoSuchMethodException nsme ) {
+			throw new ConstraintDefinitionException(
+					"Overriden constraint does not define an attribute with name " + overridesAttribute.name()
+			);
+		}
+	}
+
+	private void parseComposingConstraints(Map<ClassIndexWrapper, Map<String, Object>> overrideParameters) {
+		for ( Annotation declaredAnnotation : annotation.annotationType().getDeclaredAnnotations() ) {
+			if ( constraintHelper.isConstraintAnnotation( declaredAnnotation )
+					|| constraintHelper.isBuiltinConstraint( declaredAnnotation.annotationType() ) ) {
+				ConstraintDescriptorImpl<?> descriptor = createComposingConstraintDescriptor(
+						declaredAnnotation, overrideParameters, OVERRIDES_PARAMETER_DEFAULT_INDEX
+				);
+				composingConstraints.add( descriptor );
+				log.debug( "Adding composing constraint: " + descriptor );
+			}
+			else if ( constraintHelper.isMultiValueConstraint( declaredAnnotation ) ) {
+				List<Annotation> multiValueConstraints = constraintHelper.getMultiValueConstraints( declaredAnnotation );
+				int index = 1;
+				for ( Annotation constraintAnnotation : multiValueConstraints ) {
+					ConstraintDescriptorImpl<?> descriptor = createComposingConstraintDescriptor(
+							constraintAnnotation, overrideParameters, index
+					);
+					composingConstraints.add( descriptor );
+					log.debug( "Adding composing constraint: " + descriptor );
+					index++;
+				}
+			}
+		}
+	}
+
+	private <U extends Annotation> ConstraintDescriptorImpl<U> createComposingConstraintDescriptor(U declaredAnnotation, Map<ClassIndexWrapper, Map<String, Object>> overrideParameters, int index) {
+		//TODO don't quite understand this warning
+		//TODO assuming U.getClass() returns Class<U>
+		@SuppressWarnings("unchecked")
+		final Class<U> annotationType = ( Class<U> ) declaredAnnotation.annotationType();
+		return createComposingConstraintDescriptor(
+				overrideParameters,
+				index,
+				declaredAnnotation,
+				annotationType
+		);
+	}
+
+	private <U extends Annotation> ConstraintDescriptorImpl<U> createComposingConstraintDescriptor(Map<ClassIndexWrapper, Map<String, Object>> overrideParameters, int index, U constraintAnnotation, Class<U> annotationType) {
+		// use a annotation proxy
+		AnnotationDescriptor<U> annotationDescriptor = new AnnotationDescriptor<U>(
+				annotationType, getAnnotationParameters( constraintAnnotation )
+		);
+
+		// get the right override parameters
+		Map<String, Object> overrides = overrideParameters.get(
+				new ClassIndexWrapper(
+						annotationType, index
+				)
+		);
+		if ( overrides != null ) {
+			for ( Map.Entry<String, Object> entry : overrides.entrySet() ) {
+				annotationDescriptor.setValue( entry.getKey(), entry.getValue() );
+			}
+		}
+
+		// groups get inherited from the parent
+		annotationDescriptor.setValue( "groups", groups.toArray( new Class<?>[] { } ) );
+
+		U annotationProxy = AnnotationFactory.create( annotationDescriptor );
+		return new ConstraintDescriptorImpl<U>(
+				annotationProxy, constraintHelper
+		);
+	}
+
+	/**
+	 * A wrapper class to keep track for which compposing constraints (class and index) a given attribute override applies to.
+	 */
+	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;
+		}
+	}
+}

Copied: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ConstraintHelper.java (from rev 16797, validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintHelper.java)
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ConstraintHelper.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ConstraintHelper.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -0,0 +1,335 @@
+// $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.metadata;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import javax.validation.Constraint;
+import javax.validation.ConstraintDefinitionException;
+import javax.validation.ConstraintValidator;
+import javax.validation.ValidationException;
+import javax.validation.constraints.AssertFalse;
+import javax.validation.constraints.AssertTrue;
+import javax.validation.constraints.DecimalMax;
+import javax.validation.constraints.DecimalMin;
+import javax.validation.constraints.Digits;
+import javax.validation.constraints.Future;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Null;
+import javax.validation.constraints.Past;
+import javax.validation.constraints.Pattern;
+import javax.validation.constraints.Size;
+
+import org.hibernate.validation.constraints.impl.AssertFalseValidator;
+import org.hibernate.validation.constraints.impl.AssertTrueValidator;
+import org.hibernate.validation.constraints.impl.DecimalMaxValidatorForNumber;
+import org.hibernate.validation.constraints.impl.DecimalMaxValidatorForString;
+import org.hibernate.validation.constraints.impl.DecimalMinValidatorForNumber;
+import org.hibernate.validation.constraints.impl.DecimalMinValidatorForString;
+import org.hibernate.validation.constraints.impl.DigitsValidatorForNumber;
+import org.hibernate.validation.constraints.impl.DigitsValidatorForString;
+import org.hibernate.validation.constraints.impl.FutureValidatorForCalendar;
+import org.hibernate.validation.constraints.impl.FutureValidatorForDate;
+import org.hibernate.validation.constraints.impl.MaxValidatorForNumber;
+import org.hibernate.validation.constraints.impl.MaxValidatorForString;
+import org.hibernate.validation.constraints.impl.MinValidatorForNumber;
+import org.hibernate.validation.constraints.impl.MinValidatorForString;
+import org.hibernate.validation.constraints.impl.NotNullValidator;
+import org.hibernate.validation.constraints.impl.NullValidator;
+import org.hibernate.validation.constraints.impl.PastValidatorForCalendar;
+import org.hibernate.validation.constraints.impl.PastValidatorForDate;
+import org.hibernate.validation.constraints.impl.PatternValidator;
+import org.hibernate.validation.constraints.impl.SizeValidatorForArray;
+import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfBoolean;
+import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfByte;
+import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfChar;
+import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfDouble;
+import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfFloat;
+import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfInt;
+import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfLong;
+import org.hibernate.validation.constraints.impl.SizeValidatorForCollection;
+import org.hibernate.validation.constraints.impl.SizeValidatorForMap;
+import org.hibernate.validation.constraints.impl.SizeValidatorForString;
+import org.hibernate.validation.util.ReflectionHelper;
+
+/**
+ * Keeps track of builtin constraints and their validator implementations, as well as already resolved validator definitions.
+ *
+ * @author Hardy Ferentschik
+ * @author Alaa Nassef
+ */
+public class ConstraintHelper {
+
+	private final static Map<Class<? extends Annotation>, List<Class<? extends ConstraintValidator<?, ?>>>> builtinConstraints =
+			new ConcurrentHashMap<Class<? extends Annotation>, List<Class<? extends ConstraintValidator<?, ?>>>>();
+
+	static {
+		List<Class<? extends ConstraintValidator<?, ?>>> constraintList =
+				new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
+		constraintList.add( AssertFalseValidator.class );
+		builtinConstraints.put( AssertFalse.class, constraintList );
+
+		constraintList = new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
+		constraintList.add( AssertTrueValidator.class );
+		builtinConstraints.put( AssertTrue.class, constraintList );
+
+		constraintList = new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
+		constraintList.add( DecimalMaxValidatorForNumber.class );
+		constraintList.add( DecimalMaxValidatorForString.class );
+		builtinConstraints.put( DecimalMax.class, constraintList );
+
+		constraintList = new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
+		constraintList.add( DecimalMinValidatorForNumber.class );
+		constraintList.add( DecimalMinValidatorForString.class );
+		builtinConstraints.put( DecimalMin.class, constraintList );
+
+		constraintList = new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
+		constraintList.add( DigitsValidatorForString.class );
+		constraintList.add( DigitsValidatorForNumber.class );
+		builtinConstraints.put( Digits.class, constraintList );
+
+		constraintList = new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
+		constraintList.add( FutureValidatorForCalendar.class );
+		constraintList.add( FutureValidatorForDate.class );
+		builtinConstraints.put( Future.class, constraintList );
+
+		constraintList = new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
+		constraintList.add( MaxValidatorForNumber.class );
+		constraintList.add( MaxValidatorForString.class );
+		builtinConstraints.put( Max.class, constraintList );
+
+		constraintList = new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
+		constraintList.add( MinValidatorForNumber.class );
+		constraintList.add( MinValidatorForString.class );
+		builtinConstraints.put( Min.class, constraintList );
+
+		constraintList = new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
+		constraintList.add( NotNullValidator.class );
+		builtinConstraints.put( NotNull.class, constraintList );
+
+		constraintList = new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
+		constraintList.add( NullValidator.class );
+		builtinConstraints.put( Null.class, constraintList );
+
+		constraintList = new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
+		constraintList.add( PastValidatorForCalendar.class );
+		constraintList.add( PastValidatorForDate.class );
+		builtinConstraints.put( Past.class, constraintList );
+
+		constraintList = new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
+		constraintList.add( PatternValidator.class );
+		builtinConstraints.put( Pattern.class, constraintList );
+
+		constraintList = new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
+		constraintList.add( SizeValidatorForString.class );
+		constraintList.add( SizeValidatorForCollection.class );
+		constraintList.add( SizeValidatorForArray.class );
+		constraintList.add( SizeValidatorForMap.class );
+		constraintList.add( SizeValidatorForArraysOfBoolean.class );
+		constraintList.add( SizeValidatorForArraysOfByte.class );
+		constraintList.add( SizeValidatorForArraysOfChar.class );
+		constraintList.add( SizeValidatorForArraysOfDouble.class );
+		constraintList.add( SizeValidatorForArraysOfFloat.class );
+		constraintList.add( SizeValidatorForArraysOfInt.class );
+		constraintList.add( SizeValidatorForArraysOfLong.class );
+		builtinConstraints.put( Size.class, constraintList );
+	}
+
+	private final Map<Class<? extends Annotation>, List<Class<? extends ConstraintValidator<? extends Annotation, ?>>>> constraintValidatorDefinitons =
+			new ConcurrentHashMap<Class<? extends Annotation>, List<Class<? extends ConstraintValidator<? extends Annotation, ?>>>>();
+
+	public List<Class<? extends ConstraintValidator<? extends Annotation, ?>>> getBuiltInConstraints(Class<? extends Annotation> annotationType) {
+		final List<Class<? extends ConstraintValidator<?, ?>>> builtInList = getBuiltInFromAnnotationType(
+				annotationType
+		);
+
+		if ( builtInList == null || builtInList.size() == 0 ) {
+			throw new ValidationException( "Unable to find constraints for  " + annotationType );
+		}
+		List<Class<? extends ConstraintValidator<? extends Annotation, ?>>> constraints =
+				new ArrayList<Class<? extends ConstraintValidator<? extends Annotation, ?>>>( builtInList.size() );
+		for ( Class<? extends ConstraintValidator<?, ?>> validatorClass : builtInList ) {
+			//safe cause all CV for a given annotation A are CV<A, ?>
+			@SuppressWarnings("unchecked")
+			Class<ConstraintValidator<? extends Annotation, ?>> safeValdiatorClass = ( Class<ConstraintValidator<? extends Annotation, ?>> ) validatorClass;
+			constraints.add( safeValdiatorClass );
+		}
+
+		return constraints;
+	}
+
+	private List<Class<? extends ConstraintValidator<?, ?>>> getBuiltInFromAnnotationType(Class<? extends Annotation> annotationType) {
+		return builtinConstraints.get( annotationType );
+	}
+
+	public boolean isBuiltinConstraint(Class<? extends Annotation> annotationType) {
+		return builtinConstraints.containsKey( annotationType );
+	}
+
+	/**
+	 * 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 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 ) || isBuiltinConstraint( a.annotationType() ) ) {
+						isMultiValueConstraint = true;
+					}
+					else {
+						isMultiValueConstraint = false;
+						break;
+					}
+				}
+			}
+		}
+		catch ( NoSuchMethodException nsme ) {
+			// ignore
+		}
+		catch ( IllegalAccessException iae ) {
+			// ignore
+		}
+		catch ( InvocationTargetException ite ) {
+			// 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.
+	 *
+	 * @return A list of constraint annotations or the empty list if <code>annotation</code> is not a multi constraint
+	 *         annotation.
+	 */
+	public <A extends Annotation> List<Annotation> getMultiValueConstraints(A annotation) {
+		List<Annotation> annotationList = new ArrayList<Annotation>();
+		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 ) || isBuiltinConstraint( a.annotationType() ) ) {
+						annotationList.add( a );
+					}
+				}
+			}
+		}
+		catch ( NoSuchMethodException nsme ) {
+			// ignore
+		}
+		catch ( IllegalAccessException iae ) {
+			// ignore
+		}
+		catch ( InvocationTargetException ite ) {
+			// ignore
+		}
+		return annotationList;
+	}
+
+	/**
+	 * Checks whether the specified annotation is a valid constraint annotation. A constraint annotations has to
+	 * fulfill the following conditions:
+	 * <ul>
+	 * <li>Has to contain a <code>ConstraintValidator</code> implementation.</li>
+	 * <li>Defines a message parameter.</li>
+	 * <li>Defines a group parameter.</li>
+	 * </ul>
+	 *
+	 * @param annotation The annotation to test.
+	 *
+	 * @return <code>true</code> if the annotation fulfills the above condtions, <code>false</code> otherwise.
+	 */
+	public boolean isConstraintAnnotation(Annotation annotation) {
+
+		Constraint constraint = annotation.annotationType()
+				.getAnnotation( Constraint.class );
+		if ( constraint == null ) {
+			return false;
+		}
+
+		try {
+			ReflectionHelper.getAnnotationParameter( annotation, "message", String.class );
+		}
+		catch ( Exception e ) {
+			String msg = annotation.annotationType().getName() + " contains Constraint annotation, but does " +
+					"not contain a message parameter.";
+			throw new ConstraintDefinitionException( msg );
+		}
+
+		try {
+			Class<?>[] defaultGroups = ( Class<?>[] ) annotation.annotationType()
+					.getMethod( "groups" )
+					.getDefaultValue();
+			if ( defaultGroups.length != 0 ) {
+				String msg = annotation.annotationType()
+						.getName() + " contains Constraint annotation, but the groups " +
+						"paramter default value is not empty.";
+				throw new ConstraintDefinitionException( msg );
+			}
+		}
+		catch ( NoSuchMethodException nsme ) {
+			String msg = annotation.annotationType().getName() + " contains Constraint annotation, but does " +
+					"not contain a groups parameter.";
+			throw new ConstraintDefinitionException( msg );
+		}
+
+		Method[] methods = annotation.getClass().getMethods();
+		for ( Method m : methods ) {
+			if ( m.getName().startsWith( "valid" ) ) {
+				String msg = "Parameters starting with 'valid' are not allowed in a constraint.";
+				throw new ConstraintDefinitionException( msg );
+			}
+		}
+		return true;
+	}
+
+	public List<Class<? extends ConstraintValidator<? extends Annotation, ?>>> getConstraintValidatorDefinition(Class<? extends Annotation> annotationClass) {
+		if ( annotationClass == null ) {
+			throw new IllegalArgumentException( "Class cannot be null" );
+		}
+		return constraintValidatorDefinitons.get( annotationClass );
+	}
+
+	public <A extends Annotation> void addConstraintValidatorDefinition(Class<A> annotationClass, List<Class<? extends ConstraintValidator<? extends Annotation, ?>>> definitionClasses) {
+		constraintValidatorDefinitons.put( annotationClass, definitionClasses );
+	}
+
+	public boolean containsConstraintValidatorDefinition(Class<? extends Annotation> annotationClass) {
+		return constraintValidatorDefinitons.containsKey( annotationClass );
+	}
+}

Copied: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ElementDescriptorImpl.java (from rev 16797, validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ElementDescriptorImpl.java)
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ElementDescriptorImpl.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ElementDescriptorImpl.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -0,0 +1,64 @@
+// $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.metadata;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import javax.validation.metadata.ConstraintDescriptor;
+import javax.validation.metadata.ElementDescriptor;
+
+/**
+ * Describe a validated element (class, field or property).
+ *
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ */
+public class ElementDescriptorImpl implements ElementDescriptor {
+	private final Class<?> type;
+	private final Set<ConstraintDescriptor<?>> constraintDescriptors = new HashSet<ConstraintDescriptor<?>>();
+
+	public ElementDescriptorImpl(Class<?> type) {
+		this.type = type;
+	}
+
+	public void addConstraintDescriptor(ConstraintDescriptorImpl constraintDescriptor) {
+		constraintDescriptors.add( constraintDescriptor );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean hasConstraints() {
+		return constraintDescriptors.size() != 0;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Class<?> getType() {
+		return type;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Set<ConstraintDescriptor<?>> getConstraintDescriptors() {
+		return Collections.unmodifiableSet( constraintDescriptors );
+	}
+}

Copied: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/MetaConstraint.java (from rev 16797, validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaConstraint.java)
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/MetaConstraint.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/MetaConstraint.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -0,0 +1,178 @@
+// $Id$// $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.metadata;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import javax.validation.metadata.ConstraintDescriptor;
+import javax.validation.ConstraintViolation;
+
+import org.hibernate.validation.util.ReflectionHelper;
+import org.hibernate.validation.engine.ConstraintTree;
+import org.hibernate.validation.engine.ExecutionContext;
+
+/**
+ * Instances of this class abstract the constraint type  (class, method or field constraint) and gives access to
+ * meta data about the constraint. This allows a unified handling of constraints in the validator imlpementation.
+ *
+ * @author Hardy Ferentschik
+ */
+public class MetaConstraint<T, A extends Annotation> {
+
+	/**
+	 * The constraint tree created from the constraint annotation.
+	 */
+	private final ConstraintTree<A> constraintTree;
+
+	/**
+	 * The member the constraint was defined on.
+	 */
+	private final Member member;
+
+	/**
+	 * The JavaBeans name for this constraint.
+	 */
+	private final String propertyName;
+
+	/**
+	 * Describes on which level (<code>TYPE</code>, <code>METHOD</code>, <code>FIELD</code>) the constraint was
+	 * defined on.
+	 */
+	private final ElementType elementType;
+
+	/**
+	 * The class of the bean hosting this constraint.
+	 */
+	private final Class<T> beanClass;
+
+	public MetaConstraint(Class<T> beanClass, ConstraintDescriptor<A> constraintDescriptor) {
+		this.elementType = ElementType.TYPE;
+		this.member = null;
+		this.propertyName = "";
+		this.beanClass = beanClass;
+		constraintTree = new ConstraintTree<A>( constraintDescriptor );
+	}
+
+	public MetaConstraint(Member member, Class<T> beanClass, ConstraintDescriptor<A> constraintDescriptor) {
+		if ( member instanceof Method ) {
+			this.elementType = ElementType.METHOD;
+		}
+		else if ( member instanceof Field ) {
+			this.elementType = ElementType.FIELD;
+		}
+		else {
+			throw new IllegalArgumentException( "Non allowed member type: " + member );
+		}
+		this.member = member;
+		this.propertyName = ReflectionHelper.getPropertyName( member );
+		this.beanClass = beanClass;
+		constraintTree = new ConstraintTree<A>( constraintDescriptor );
+	}
+
+
+	/**
+	 * @return Returns the list of groups this constraint is part of. This might include the default group even when
+	 *         it is not explicitly specified, but part of the redefined default group list of the hosting bean.
+	 */
+	public Set<Class<?>> getGroupList() {
+		return constraintTree.getDescriptor().getGroups();
+	}
+
+	public ConstraintDescriptor getDescriptor() {
+		return constraintTree.getDescriptor();
+	}
+
+	public Class<T> getBeanClass() {
+		return beanClass;
+	}
+
+	public String getPropertyName() {
+		return propertyName;
+	}
+
+	public ElementType getElementType() {
+		return elementType;
+	}
+
+	public ConstraintTree getConstraintTree() {
+		return constraintTree;
+	}
+
+	public <T> boolean validateConstraint(ExecutionContext<T> executionContext) {
+		final Object leafBeanInstance = executionContext.peekCurrentBean();
+		Object value = getValue( leafBeanInstance );
+		List<ConstraintViolation<T>> constraintViolations = new ArrayList<ConstraintViolation<T>>();
+		constraintTree.validateConstraints( value, typeOfAnnoatedElement(), executionContext, constraintViolations );
+		if ( constraintViolations.size() > 0 ) {
+			executionContext.addConstraintFailures( constraintViolations );
+			return false;
+		}
+		return true;
+	}
+
+	public <T> boolean validateConstraint(Object value, ExecutionContext<T> executionContext) {
+		List<ConstraintViolation<T>> constraintViolations = new ArrayList<ConstraintViolation<T>>();
+		constraintTree.validateConstraints( value, typeOfAnnoatedElement(), executionContext, constraintViolations );
+		if ( constraintViolations.size() > 0 ) {
+			executionContext.addConstraintFailures( constraintViolations );
+			return false;
+		}
+		return true;
+	}
+
+	private Type typeOfAnnoatedElement() {
+		Type t;
+		switch ( elementType ) {
+			case TYPE: {
+				t = beanClass;
+				break;
+			}
+			default: {
+				t = ReflectionHelper.typeOf( member );
+				if ( t instanceof Class && ((Class) t).isPrimitive()) {
+					t = ReflectionHelper.boxedTyp( t );
+				}
+			}
+		}
+		return t;
+	}
+
+	/**
+	 * @param o the object from which to retrieve the value.
+	 *
+	 * @return Returns the value for this constraint from the specified object. Depending on the type either the value itself
+	 *         is returned of method or field access is used to access the value.
+	 */
+	private Object getValue(Object o) {
+		switch ( elementType ) {
+			case TYPE: {
+				return o;
+			}
+			default: {
+				return ReflectionHelper.getValue( member, o );
+			}
+		}
+	}
+}

Copied: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/PropertyDescriptorImpl.java (from rev 16797, validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/PropertyDescriptorImpl.java)
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/PropertyDescriptorImpl.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/PropertyDescriptorImpl.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -0,0 +1,52 @@
+// $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.metadata;
+
+import javax.validation.metadata.PropertyDescriptor;
+
+/**
+ * Describe a validated element (class, field or property).
+ *
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ */
+public class PropertyDescriptorImpl extends ElementDescriptorImpl implements PropertyDescriptor {
+	private final boolean cascaded;
+	private final String property;
+
+
+	public PropertyDescriptorImpl(Class<?> returnType, boolean cascaded, String property) {
+		super( returnType );
+		this.cascaded = cascaded;
+		this.property = property;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean isCascaded() {
+		return cascaded;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public String getPropertyName() {
+		return property;
+	}
+}
\ No newline at end of file

Copied: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/ValidationBootstrapParameters.java (from rev 16797, validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/xml/ValidationBootstrapParameters.java)
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/ValidationBootstrapParameters.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/ValidationBootstrapParameters.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -0,0 +1,41 @@
+// $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.xml;
+
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import javax.validation.ConstraintValidatorFactory;
+import javax.validation.MessageInterpolator;
+import javax.validation.TraversableResolver;
+import javax.validation.spi.ValidationProvider;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class ValidationBootstrapParameters {
+	public ConstraintValidatorFactory constraintValidatorFactory;
+	public MessageInterpolator messageInterpolator;
+	public TraversableResolver traversableResolver;
+	public ValidationProvider provider;
+	public Class<? extends ValidationProvider<?>> providerClass = null;
+	public final Map<String, String> configProperties = new HashMap<String, String>();
+	public final Set<InputStream> mappings = new HashSet<InputStream>();
+}

Copied: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/ValidationXmlParser.java (from rev 16797, validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/xml/ValidationXmlParser.java)
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/ValidationXmlParser.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/ValidationXmlParser.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -0,0 +1,255 @@
+// $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.xml;
+
+import java.io.InputStream;
+import java.net.URL;
+import javax.validation.ConstraintValidatorFactory;
+import javax.validation.MessageInterpolator;
+import javax.validation.TraversableResolver;
+import javax.validation.ValidationException;
+import javax.validation.spi.ValidationProvider;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+
+import org.slf4j.Logger;
+import org.xml.sax.SAXException;
+
+import org.hibernate.validation.util.LoggerFactory;
+import org.hibernate.validation.util.ReflectionHelper;
+import org.hibernate.validation.xml.PropertyType;
+import org.hibernate.validation.xml.ValidationConfigType;
+
+/**
+ * Parser for <i>validation.xml</i> using JAXB.
+ *
+ * @author Hardy Ferentschik
+ */
+public class ValidationXmlParser {
+
+	private static final Logger log = LoggerFactory.make();
+	private static final String VALIDATION_XML_FILE = "META-INF/validation.xml";
+	private static final String VALIDATION_CONFIGURATION_XSD = "META-INF/validation-configuration-1.0.xsd";
+
+
+	/**
+	 * Tries to check whether a validation.xml file exists and parses it using JAXB.
+	 *
+	 * @return The parameters parsed out of <i>validation.xml</i> wrapped in an instance of <code>ConfigurationImpl.ValidationBootstrapParameters</code>.
+	 */
+	public ValidationBootstrapParameters parseValidationXml() {
+		ValidationConfigType config = getValidationConfig();
+		ValidationBootstrapParameters xmlParameters = new ValidationBootstrapParameters();
+		if ( config != null ) {
+			// collect the paramters from the xml file
+			setProviderClassFromXml( config, xmlParameters );
+			setMessageInterpolatorFromXml( config, xmlParameters );
+			setTraversableResolverFromXml( config, xmlParameters );
+			setConstraintFactoryFromXml( config, xmlParameters );
+			setMappingStreamsFromXml( config, xmlParameters );
+			setPropertiesFromXml( config, xmlParameters );
+		}
+		return xmlParameters;
+	}
+
+	private void setConstraintFactoryFromXml(ValidationConfigType config, ValidationBootstrapParameters xmlParameters) {
+		String constraintFactoryClass = config.getConstraintValidatorFactory();
+		if ( constraintFactoryClass != null ) {
+			try {
+				@SuppressWarnings("unchecked")
+				Class<ConstraintValidatorFactory> clazz = ( Class<ConstraintValidatorFactory> ) ReflectionHelper.classForName(
+						constraintFactoryClass, this.getClass()
+				);
+				xmlParameters.constraintValidatorFactory = clazz.newInstance();
+				log.info( "Using {} as constraint factory.", constraintFactoryClass );
+			}
+			catch ( ClassNotFoundException e ) {
+				throw new ValidationException(
+						"Unable to instantiate constraint factory class " + constraintFactoryClass + ".", e
+				);
+			}
+			catch ( InstantiationException e ) {
+				throw new ValidationException(
+						"Unable to instantiate constraint factory class " + constraintFactoryClass + ".", e
+				);
+			}
+			catch ( IllegalAccessException e ) {
+				throw new ValidationException(
+						"Unable to instantiate constraint factory class " + constraintFactoryClass + ".", e
+				);
+			}
+		}
+	}
+
+	private void setPropertiesFromXml(ValidationConfigType config, ValidationBootstrapParameters xmlParameters) {
+		for ( PropertyType property : config.getProperty() ) {
+			if ( log.isDebugEnabled() ) {
+				log.debug(
+						"Found property '{}' with value '{}' in validation.xml.",
+						property.getName(),
+						property.getValue()
+				);
+			}
+			xmlParameters.configProperties.put( property.getName(), property.getValue() );
+		}
+	}
+
+	private void setMappingStreamsFromXml(ValidationConfigType config, ValidationBootstrapParameters xmlParameters) {
+		for ( JAXBElement<String> mappingFileName : config.getConstraintMapping() ) {
+			if ( log.isDebugEnabled() ) {
+				log.debug(
+						"Trying to open input stream for {}.", mappingFileName.getValue()
+				);
+			}
+			InputStream in = getInputStreamForPath( mappingFileName.getValue() );
+			if ( in == null ) {
+				throw new ValidationException( "Unable to open input stream for mapping file " + mappingFileName.getValue() + "." );
+			}
+			xmlParameters.mappings.add( in );
+		}
+	}
+
+	private void setMessageInterpolatorFromXml(ValidationConfigType config, ValidationBootstrapParameters xmlParameters) {
+		String messageInterpolatorClass = config.getMessageInterpolator();
+		if ( messageInterpolatorClass != null ) {
+			try {
+				@SuppressWarnings("unchecked")
+				Class<MessageInterpolator> clazz = ( Class<MessageInterpolator> ) ReflectionHelper.classForName(
+						messageInterpolatorClass, this.getClass()
+				);
+				xmlParameters.messageInterpolator = clazz.newInstance();
+				log.info( "Using {} as message interpolator.", messageInterpolatorClass );
+			}
+			catch ( ClassNotFoundException e ) {
+				throw new ValidationException(
+						"Unable to instantiate message interpolator class " + messageInterpolatorClass + ".", e
+				);
+			}
+			catch ( InstantiationException e ) {
+				throw new ValidationException(
+						"Unable to instantiate message interpolator class " + messageInterpolatorClass + ".", e
+				);
+			}
+			catch ( IllegalAccessException e ) {
+				throw new ValidationException(
+						"Unable to instantiate message interpolator class " + messageInterpolatorClass + ".", e
+				);
+			}
+		}
+	}
+
+	private void setTraversableResolverFromXml(ValidationConfigType config, ValidationBootstrapParameters xmlParameters) {
+		String traversableResolverClass = config.getTraversableResolver();
+		if ( traversableResolverClass != null ) {
+			try {
+				@SuppressWarnings("unchecked")
+				Class<TraversableResolver> clazz = ( Class<TraversableResolver> ) ReflectionHelper.classForName(
+						traversableResolverClass, this.getClass()
+				);
+				xmlParameters.traversableResolver = clazz.newInstance();
+				log.info( "Using {} as traversable resolver.", traversableResolverClass );
+			}
+			catch ( ClassNotFoundException e ) {
+				throw new ValidationException(
+						"Unable to instantiate traversable resolver class " + traversableResolverClass + ".", e
+				);
+			}
+			catch ( InstantiationException e ) {
+				throw new ValidationException(
+						"Unable to instantiate traversable resolver class " + traversableResolverClass + ".", e
+				);
+			}
+			catch ( IllegalAccessException e ) {
+				throw new ValidationException(
+						"Unable to instantiate traversable resolver class " + traversableResolverClass + ".", e
+				);
+			}
+		}
+	}
+
+	@SuppressWarnings("unchecked")
+	private void setProviderClassFromXml(ValidationConfigType config, ValidationBootstrapParameters xmlParamters) {
+		String providerClassName = config.getDefaultProvider();
+		if ( providerClassName != null ) {
+			try {
+				xmlParamters.providerClass = ( Class<? extends ValidationProvider<?>> ) ReflectionHelper.classForName(
+						providerClassName, this.getClass()
+				);
+				log.info( "Using {} as validation provider.", providerClassName );
+			}
+			catch ( Exception e ) {
+				throw new ValidationException( "Unable to instantiate validation provider class " + providerClassName + "." );
+			}
+		}
+	}
+
+	private ValidationConfigType getValidationConfig() {
+		InputStream inputStream = getInputStreamForPath( VALIDATION_XML_FILE );
+		if ( inputStream == null ) {
+			log.info( "No {} found. Using annotation based configuration only!", VALIDATION_XML_FILE );
+			return null;
+		}
+
+		log.info( "{} found.", VALIDATION_XML_FILE );
+
+		ValidationConfigType validationConfig;
+		Schema schema = getValidationConfigurationSchema();
+		try {
+			JAXBContext jc = JAXBContext.newInstance( ValidationConfigType.class );
+			Unmarshaller unmarshaller = jc.createUnmarshaller();
+			unmarshaller.setSchema( schema );
+			StreamSource stream = new StreamSource( inputStream );
+			JAXBElement<ValidationConfigType> root = unmarshaller.unmarshal( stream, ValidationConfigType.class );
+			validationConfig = root.getValue();
+		}
+		catch ( JAXBException e ) {
+			log.error( "Error parsing validation.xml: {}", e.getMessage() );
+			throw new ValidationException( "Unable to parse " + VALIDATION_XML_FILE );
+		}
+		return validationConfig;
+	}
+
+	private InputStream getInputStreamForPath(String path) {
+		// try the context class loader first
+		InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream( path );
+
+		// try the current class loader
+		if ( inputStream == null ) {
+			inputStream = this.getClass().getResourceAsStream( path );
+		}
+		return inputStream;
+	}
+
+	private Schema getValidationConfigurationSchema() {
+		URL schemaUrl = this.getClass().getClassLoader().getResource( VALIDATION_CONFIGURATION_XSD );
+		SchemaFactory sf = SchemaFactory.newInstance( javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI );
+		Schema schema = null;
+		try {
+			schema = sf.newSchema( schemaUrl );
+		}
+		catch ( SAXException e ) {
+			log.warn( "Unable to create schema for {}: {}", VALIDATION_CONFIGURATION_XSD, e.getMessage() );
+		}
+		return schema;
+	}
+}

Copied: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/XmlMappingParser.java (from rev 16797, validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/xml/XmlMappingParser.java)
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/XmlMappingParser.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/XmlMappingParser.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -0,0 +1,620 @@
+// $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.xml;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.validation.Constraint;
+import javax.validation.ConstraintValidator;
+import javax.validation.ValidationException;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+
+import org.slf4j.Logger;
+import org.xml.sax.SAXException;
+
+import org.hibernate.validation.metadata.ConstraintDescriptorImpl;
+import org.hibernate.validation.metadata.MetaConstraint;
+import org.hibernate.validation.metadata.ConstraintHelper;
+import org.hibernate.validation.metadata.AnnotationIgnores;
+import org.hibernate.validation.util.LoggerFactory;
+import org.hibernate.validation.util.ReflectionHelper;
+import org.hibernate.validation.util.annotationfactory.AnnotationDescriptor;
+import org.hibernate.validation.util.annotationfactory.AnnotationFactory;
+import org.hibernate.validation.xml.AnnotationType;
+import org.hibernate.validation.xml.BeanType;
+import org.hibernate.validation.xml.ClassType;
+import org.hibernate.validation.xml.ConstraintDefinitionType;
+import org.hibernate.validation.xml.ConstraintMappingsType;
+import org.hibernate.validation.xml.ConstraintType;
+import org.hibernate.validation.xml.ElementType;
+import org.hibernate.validation.xml.FieldType;
+import org.hibernate.validation.xml.GetterType;
+import org.hibernate.validation.xml.GroupSequenceType;
+import org.hibernate.validation.xml.GroupsType;
+import org.hibernate.validation.xml.ValidatedByType;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class XmlMappingParser {
+
+	private static final Logger log = LoggerFactory.make();
+	private static final String VALIDATION_MAPPING_XSD = "META-INF/validation-mapping-1.0.xsd";
+	private static final String MESSAGE_PARAM = "message";
+	private static final String GROUPS_PARAM = "groups";
+	private static final String PACKAGE_SEPERATOR = ".";
+
+	private final Set<Class<?>> processedClasses = new HashSet<Class<?>>();
+	private final ConstraintHelper constraintHelper;
+	private final AnnotationIgnores annotationIgnores;
+	private final Map<Class<?>, List<MetaConstraint<?, ? extends Annotation>>> constraintMap;
+	private final Map<Class<?>, List<Member>> cascadedMembers;
+	private final Map<Class<?>, List<Class<?>>> defaultSequences;
+
+	public XmlMappingParser(ConstraintHelper constraintHelper) {
+		this.constraintHelper = constraintHelper;
+		this.annotationIgnores = new AnnotationIgnores();
+		this.constraintMap = new HashMap<Class<?>, List<MetaConstraint<?, ? extends Annotation>>>();
+		this.cascadedMembers = new HashMap<Class<?>, List<Member>>();
+		this.defaultSequences = new HashMap<Class<?>, List<Class<?>>>();
+	}
+
+	public void parse(Set<InputStream> mappingStreams) {
+		for ( InputStream in : mappingStreams ) {
+			try {
+				ConstraintMappingsType mapping = getValidationConfig( in );
+				parseConstraintDefinitions( mapping.getConstraintDefinition() );
+				String defaultPackage = mapping.getDefaultPackage();
+				for ( BeanType bean : mapping.getBean() ) {
+					Class<?> beanClass = getClass( bean.getClazz(), defaultPackage );
+					checkClassHasNotBeenProcessed( processedClasses, beanClass );
+					annotationIgnores.setDefaultIgnoreAnnotation( beanClass, bean.isIgnoreAnnotations() );
+					parseClassLevelOverrides( bean.getClassType(), beanClass, defaultPackage );
+					parseFieldLevelOverrides( bean.getField(), beanClass, defaultPackage );
+					parsePropertyLevelOverrides( bean.getGetter(), beanClass, defaultPackage );
+					processedClasses.add( beanClass );
+				}
+			}
+			finally {
+				try {
+					in.close();
+				}
+				catch ( IOException e ) {
+					log.warn( "Error closing input stream: {}", e.getMessage() );
+				}
+			}
+		}
+	}
+
+	public Set<Class<?>> getProcessedClasses() {
+		return processedClasses;
+	}
+
+	public AnnotationIgnores getAnnotationIgnores() {
+		return annotationIgnores;
+	}
+
+	public <T> List<MetaConstraint<T, ? extends Annotation>> getConstraintsForClass(Class<T> beanClass) {
+		List<MetaConstraint<T, ? extends Annotation>> list = new ArrayList<MetaConstraint<T, ? extends Annotation>>();
+		if ( constraintMap.containsKey( beanClass ) ) {
+			for ( MetaConstraint<?, ? extends Annotation> metaConstraint : constraintMap.get( beanClass ) ) {
+				@SuppressWarnings( "unchecked") // safe cast since the list of meta constraints is always specific to the bean type
+				MetaConstraint<T, ? extends Annotation> boundMetaConstraint = ( MetaConstraint<T, ? extends Annotation> ) metaConstraint;
+				list.add( boundMetaConstraint );
+			}
+			return list;
+		}
+		else {
+			return Collections.emptyList();
+		}
+	}
+
+	public List<Member> getCascadedMembersForClass(Class<?> beanClass) {
+		if ( cascadedMembers.containsKey( beanClass ) ) {
+			return cascadedMembers.get( beanClass );
+		}
+		else {
+			return Collections.emptyList();
+		}
+	}
+
+	public List<Class<?>> getDefaultSequenceForClass(Class<?> beanClass) {
+		if ( defaultSequences.containsKey( beanClass ) ) {
+			return defaultSequences.get( beanClass );
+		}
+		else {
+			return Collections.emptyList();
+		}
+	}
+
+	@SuppressWarnings("unchecked")
+	private void parseConstraintDefinitions(List<ConstraintDefinitionType> constraintDefinitionList) {
+		for ( ConstraintDefinitionType constraintDefinition : constraintDefinitionList ) {
+			String annotationClassName = constraintDefinition.getAnnotation();
+			Class<? extends Annotation> annotationClass;
+			try {
+				annotationClass = ( Class<? extends Annotation> ) ReflectionHelper.classForName(
+						annotationClassName, this.getClass()
+				);
+			}
+			catch ( ClassNotFoundException e ) {
+				throw new ValidationException( "Unable to load class " + annotationClassName );
+			}
+
+			if ( !annotationClass.isAnnotation() ) {
+				throw new ValidationException( annotationClassName + " is not an annotation" );
+			}
+
+			ValidatedByType validatedByType = constraintDefinition.getValidatedBy();
+			List<Class<? extends ConstraintValidator<? extends Annotation, ?>>> constraintValidatorClasses = new ArrayList<Class<? extends ConstraintValidator<? extends Annotation, ?>>>();
+			if ( validatedByType.isIncludeExistingValidators() != null && validatedByType.isIncludeExistingValidators() ) {
+				constraintValidatorClasses.addAll( findConstraintValidatorClasses( annotationClass ) );
+			}
+			for ( JAXBElement<String> validatorClassName : validatedByType.getValue() ) {
+				Class<? extends ConstraintValidator<?, ?>> validatorClass;
+				try {
+					validatorClass = ( Class<? extends ConstraintValidator<?, ?>> ) ReflectionHelper.classForName(
+							validatorClassName.getValue(),
+							this.getClass()
+					);
+				}
+				catch ( ClassNotFoundException e ) {
+					throw new ValidationException( "Unable to load class " + validatorClassName );
+				}
+
+				if ( !ConstraintValidator.class.isAssignableFrom( validatorClass ) ) {
+					throw new ValidationException( validatorClass + " is not a constraint validator class" );
+				}
+
+				constraintValidatorClasses.add( validatorClass );
+			}
+			constraintHelper.addConstraintValidatorDefinition(
+					annotationClass, constraintValidatorClasses
+			);
+		}
+	}
+
+	private List<Class<? extends ConstraintValidator<? extends Annotation, ?>>> findConstraintValidatorClasses(Class<? extends Annotation> annotationType) {
+		List<Class<? extends ConstraintValidator<? extends Annotation, ?>>> constraintValidatorDefinitonClasses = new ArrayList<Class<? extends ConstraintValidator<? extends Annotation, ?>>>();
+		if ( constraintHelper.isBuiltinConstraint( annotationType ) ) {
+			constraintValidatorDefinitonClasses.addAll( constraintHelper.getBuiltInConstraints( annotationType ) );
+		}
+		else {
+			Class<? extends ConstraintValidator<?, ?>>[] validatedBy = annotationType
+					.getAnnotation( Constraint.class )
+					.validatedBy();
+			for ( Class<? extends ConstraintValidator<?, ?>> validator : validatedBy ) {
+				//FIXME does this create a CCE at runtime?
+				//FIXME if yes wrap into VE, if no we need to test the type here
+				//Once resolved,we can @SuppressWarning("unchecked") on the cast
+				Class<? extends ConstraintValidator<? extends Annotation, ?>> safeValidator = validator;
+				constraintValidatorDefinitonClasses.add( safeValidator );
+			}
+		}
+		return constraintValidatorDefinitonClasses;
+	}
+
+	private void checkClassHasNotBeenProcessed(Set<Class<?>> processedClasses, Class<?> beanClass) {
+		if ( processedClasses.contains( beanClass ) ) {
+			throw new ValidationException( beanClass.getName() + " has already be configured in xml." );
+		}
+	}
+
+	private void parseFieldLevelOverrides(List<FieldType> fields, Class<?> beanClass, String defaultPackage) {
+		for ( FieldType fieldType : fields ) {
+			String fieldName = fieldType.getName();
+			if ( !ReflectionHelper.containsField( beanClass, fieldName ) ) {
+				throw new ValidationException( beanClass.getName() + " does not contain the fieldType  " + fieldName );
+			}
+			Field field = ReflectionHelper.getField( beanClass, fieldName );
+
+			// ignore annotations
+			boolean ignoreFieldAnnotation = fieldType.isIgnoreAnnotations() == null ? false : fieldType.isIgnoreAnnotations();
+			if ( ignoreFieldAnnotation ) {
+				annotationIgnores.setIgnoreAnnotationsOnMember( field );
+			}
+
+			// valid
+			if ( fieldType.getValid() != null ) {
+				addCascadedMember( beanClass, field );
+			}
+
+			// constraints
+			for ( ConstraintType constraint : fieldType.getConstraint() ) {
+				MetaConstraint<?, ?> metaConstraint = createMetaConstraint(
+						constraint, beanClass, field, defaultPackage
+				);
+				addMetaConstraint( beanClass, metaConstraint );
+			}
+		}
+	}
+
+	private void parsePropertyLevelOverrides(List<GetterType> getters, Class<?> beanClass, String defaultPackage) {
+		for ( GetterType getterType : getters ) {
+			String getterName = getterType.getName();
+			if ( !ReflectionHelper.containsMethod( beanClass, getterName ) ) {
+				throw new ValidationException( beanClass.getName() + " does not contain the property  " + getterName );
+			}
+			Method method = ReflectionHelper.getMethod( beanClass, getterName );
+
+			// ignore annotations
+			boolean ignoreGetterAnnotation = getterType.isIgnoreAnnotations() == null ? false : getterType.isIgnoreAnnotations();
+			if ( ignoreGetterAnnotation ) {
+				annotationIgnores.setIgnoreAnnotationsOnMember( method );
+			}
+
+			// valid
+			if ( getterType.getValid() != null ) {
+				addCascadedMember( beanClass, method );
+			}
+
+			// constraints
+			for ( ConstraintType constraint : getterType.getConstraint() ) {
+				MetaConstraint<?, ?> metaConstraint = createMetaConstraint(
+						constraint, beanClass, method, defaultPackage
+				);
+				addMetaConstraint( beanClass, metaConstraint );
+			}
+		}
+	}
+
+	private void parseClassLevelOverrides(ClassType classType, Class<?> beanClass, String defaultPackage) {
+		if ( classType == null ) {
+			return;
+		}
+
+		// ignore annotation
+		boolean ignoreClassAnnotation = classType.isIgnoreAnnotations() == null ? false : classType.isIgnoreAnnotations();
+		if ( ignoreClassAnnotation ) {
+			annotationIgnores.setIgnoreAnnotationsOnClass( beanClass );
+		}
+
+		// group sequence
+		List<Class<?>> groupSequence = createGroupSequence( classType.getGroupSequence(), defaultPackage );
+		if ( !groupSequence.isEmpty() ) {
+			defaultSequences.put( beanClass, groupSequence );
+		}
+
+		// constraints
+		for ( ConstraintType constraint : classType.getConstraint() ) {
+			MetaConstraint<?, ?> metaConstraint = createMetaConstraint( constraint, beanClass, null, defaultPackage );
+			addMetaConstraint( beanClass, metaConstraint );
+		}
+	}
+
+	private void addMetaConstraint(Class<?> beanClass, MetaConstraint<?, ?> metaConstraint) {
+		if ( constraintMap.containsKey( beanClass ) ) {
+			constraintMap.get( beanClass ).add( metaConstraint );
+		}
+		else {
+			List<MetaConstraint<?, ? extends Annotation>> constraintList = new ArrayList<MetaConstraint<?, ? extends Annotation>>();
+			constraintList.add( metaConstraint );
+			constraintMap.put( beanClass, constraintList );
+		}
+	}
+
+	private void addCascadedMember(Class<?> beanClass, Member member) {
+		if ( cascadedMembers.containsKey( beanClass ) ) {
+			cascadedMembers.get( beanClass ).add( member );
+		}
+		else {
+			List<Member> tmpList = new ArrayList<Member>();
+			tmpList.add( member );
+			cascadedMembers.put( beanClass, tmpList );
+		}
+	}
+
+	private List<Class<?>> createGroupSequence(GroupSequenceType groupSequenceType, String defaultPackage) {
+		List<Class<?>> groupSequence = new ArrayList<Class<?>>();
+		for ( JAXBElement<String> groupName : groupSequenceType.getValue() ) {
+			Class<?> group = getClass( groupName.getValue(), defaultPackage );
+			groupSequence.add( group );
+		}
+		return groupSequence;
+	}
+
+	private <A extends Annotation, T> MetaConstraint<?, ?> createMetaConstraint(ConstraintType constraint, Class<T> beanClass, Member member, String defaultPackage) {
+		@SuppressWarnings("unchecked")
+		Class<A> annotationClass = ( Class<A> ) getClass( constraint.getAnnotation(), defaultPackage );
+		AnnotationDescriptor<A> annotationDescriptor = new AnnotationDescriptor<A>( annotationClass );
+
+		if ( constraint.getMessage() != null ) {
+			annotationDescriptor.setValue( MESSAGE_PARAM, constraint.getMessage() );
+		}
+		annotationDescriptor.setValue( GROUPS_PARAM, getGroups( constraint.getGroups(), defaultPackage ) );
+
+		for ( ElementType elementType : constraint.getElement() ) {
+			String name = elementType.getName();
+			checkNameIsValid( name );
+			Class<?> returnType = getAnnotationParamterType( annotationClass, name );
+			Object elementValue = getElementValue( elementType, returnType );
+			annotationDescriptor.setValue( name, elementValue );
+		}
+
+		A annotation = AnnotationFactory.create( annotationDescriptor );
+		ConstraintDescriptorImpl<A> constraintDescriptor = new ConstraintDescriptorImpl<A>(
+				annotation, constraintHelper
+		);
+
+		MetaConstraint<T, A> metaConstraint;
+		if ( member == null ) {
+			metaConstraint = new MetaConstraint<T, A>( beanClass, constraintDescriptor );
+		}
+		else {
+			metaConstraint = new MetaConstraint<T, A>( member, beanClass, constraintDescriptor );
+		}
+		return metaConstraint;
+	}
+
+	private <A extends Annotation> Class<?> getAnnotationParamterType(Class<A> annotationClass, String name) {
+		Method m;
+		try {
+			m = annotationClass.getMethod( name );
+		}
+		catch ( NoSuchMethodException e ) {
+			throw new ValidationException( "Annotation of type " + annotationClass.getName() + " does not contain a paramter " + name + "." );
+		}
+		return m.getReturnType();
+	}
+
+	private Object getElementValue(ElementType elementType, Class<?> returnType) {
+		removeEmptyContentElements( elementType );
+
+		boolean isArray = returnType.isArray();
+		if ( !isArray ) {
+			if ( elementType.getContent().size() != 1 ) {
+				throw new ValidationException( "Attempt to specify an array where single value is expected." );
+			}
+			return getSingleValue( elementType.getContent().get( 0 ), returnType );
+		}
+		else {
+			List<Object> values = new ArrayList<Object>();
+			for ( Serializable s : elementType.getContent() ) {
+				values.add( getSingleValue( s, returnType.getComponentType() ) );
+			}
+			return values.toArray( ( Object[] ) Array.newInstance( returnType.getComponentType(), values.size() ) );
+		}
+	}
+
+	private void removeEmptyContentElements(ElementType elementType) {
+		List<Serializable> contentToDelete = new ArrayList<Serializable>();
+		for ( Serializable content : elementType.getContent() ) {
+			if ( content instanceof String && ( ( String ) content ).matches( "[\\n ].*" ) ) {
+				contentToDelete.add( content );
+			}
+		}
+		elementType.getContent().removeAll( contentToDelete );
+	}
+
+	private Object getSingleValue(Serializable serializable, Class<?> returnType) {
+
+		Object returnValue;
+		if ( serializable instanceof String ) {
+			String value = ( String ) serializable;
+			returnValue = convertStringToReturnType( returnType, value );
+		}
+		else if ( serializable instanceof JAXBElement && ( ( JAXBElement ) serializable ).getDeclaredType()
+				.equals( String.class ) ) {
+			JAXBElement<?> elem = ( JAXBElement<?> ) serializable;
+			String value = ( String ) elem.getValue();
+			returnValue = convertStringToReturnType( returnType, value );
+		}
+		else if ( serializable instanceof JAXBElement && ( ( JAXBElement ) serializable ).getDeclaredType()
+				.equals( AnnotationType.class ) ) {
+			JAXBElement<?> elem = ( JAXBElement<?> ) serializable;
+			AnnotationType annotationType = ( AnnotationType ) elem.getValue();
+			try {
+				@SuppressWarnings("unchecked")
+				Class<Annotation> annotationClass = ( Class<Annotation> ) returnType;
+				returnValue = createAnnotation( annotationType, annotationClass );
+			}
+			catch ( ClassCastException e ) {
+				throw new ValidationException( "Unexpected paramter value" );
+			}
+		}
+		else {
+			throw new ValidationException( "Unexpected paramter value" );
+		}
+		return returnValue;
+
+	}
+
+	private <A extends Annotation> Annotation createAnnotation(AnnotationType annotationType, Class<A> returnType) {
+		AnnotationDescriptor<A> annotationDescriptor = new AnnotationDescriptor<A>( returnType );
+		for ( ElementType elementType : annotationType.getElement() ) {
+			String name = elementType.getName();
+			Class<?> paramterType = getAnnotationParamterType( returnType, name );
+			Object elementValue = getElementValue( elementType, paramterType );
+			annotationDescriptor.setValue( name, elementValue );
+		}
+		return AnnotationFactory.create( annotationDescriptor );
+	}
+
+	private Object convertStringToReturnType(Class<?> returnType, String value) {
+		Object returnValue;
+		if ( returnType.getName().equals( byte.class.getName() ) ) {
+			try {
+				returnValue = Byte.parseByte( value );
+			}
+			catch ( NumberFormatException e ) {
+				throw new ValidationException( "Invalid byte format", e );
+			}
+		}
+		else if ( returnType.getName().equals( short.class.getName() ) ) {
+			try {
+				returnValue = Short.parseShort( value );
+			}
+			catch ( NumberFormatException e ) {
+				throw new ValidationException( "Invalid short format", e );
+			}
+		}
+		else if ( returnType.getName().equals( int.class.getName() ) ) {
+			try {
+				returnValue = Integer.parseInt( value );
+			}
+			catch ( NumberFormatException e ) {
+				throw new ValidationException( "Invalid int format", e );
+			}
+		}
+		else if ( returnType.getName().equals( long.class.getName() ) ) {
+			try {
+				returnValue = Long.parseLong( value );
+			}
+			catch ( NumberFormatException e ) {
+				throw new ValidationException( "Invalid long format", e );
+			}
+		}
+		else if ( returnType.getName().equals( float.class.getName() ) ) {
+			try {
+				returnValue = Float.parseFloat( value );
+			}
+			catch ( NumberFormatException e ) {
+				throw new ValidationException( "Invalid float format", e );
+			}
+		}
+		else if ( returnType.getName().equals( double.class.getName() ) ) {
+			try {
+				returnValue = Double.parseDouble( value );
+			}
+			catch ( NumberFormatException e ) {
+				throw new ValidationException( "Invalid double format", e );
+			}
+		}
+		else if ( returnType.getName().equals( boolean.class.getName() ) ) {
+			returnValue = Boolean.parseBoolean( value );
+		}
+		else if ( returnType.getName().equals( char.class.getName() ) ) {
+			if ( value.length() != 1 ) {
+				throw new ValidationException( "Invalid char value: " + value );
+			}
+			returnValue = value.charAt( 0 );
+		}
+		else if ( returnType.getName().equals( String.class.getName() ) ) {
+			returnValue = value;
+		}
+		else if ( returnType.getName().equals( Class.class.getName() ) ) {
+			try {
+				returnValue = ReflectionHelper.classForName( value, this.getClass() );
+			}
+			catch ( ClassNotFoundException e ) {
+				throw new ValidationException( "Unable to instantiate class: " + value );
+			}
+		}
+		else {
+			try {
+				@SuppressWarnings("unchecked")
+				Class<Enum> enumClass = ( Class<Enum> ) returnType;
+				returnValue = Enum.valueOf( enumClass, value );
+			}
+			catch ( ClassCastException e ) {
+				throw new ValidationException( "Invalid return type: " + returnType + ". Should be a enumeration type." );
+			}
+		}
+		return returnValue;
+	}
+
+	private void checkNameIsValid(String name) {
+		if ( MESSAGE_PARAM.equals( name ) || GROUPS_PARAM.equals( name ) ) {
+			throw new ValidationException( MESSAGE_PARAM + " and " + GROUPS_PARAM + " are reserved paramter names." );
+		}
+	}
+
+	private Class<?>[] getGroups(GroupsType groupsType, String defaultPackage) {
+		if ( groupsType == null ) {
+			return new Class[] { };
+		}
+
+		List<Class<?>> groupList = new ArrayList<Class<?>>();
+		for ( JAXBElement<String> groupClass : groupsType.getValue() ) {
+			groupList.add( getClass( groupClass.getValue(), defaultPackage ) );
+		}
+		return groupList.toArray( new Class[groupList.size()] );
+	}
+
+	private Class<?> getClass(String clazz, String defaultPackage) {
+		String fullyQualifiedClass;
+		if ( isQualifiedClass( clazz ) ) {
+			fullyQualifiedClass = clazz;
+		}
+		else {
+			fullyQualifiedClass = defaultPackage + PACKAGE_SEPERATOR + clazz;
+		}
+		try {
+			return ReflectionHelper.classForName( fullyQualifiedClass, this.getClass() );
+		}
+		catch ( Exception e ) {
+			throw new ValidationException( "Unable to instantiate class " + fullyQualifiedClass );
+		}
+	}
+
+	private boolean isQualifiedClass(String clazz) {
+		return clazz.contains( PACKAGE_SEPERATOR );
+	}
+
+	private ConstraintMappingsType getValidationConfig(InputStream in) {
+		ConstraintMappingsType constraintMappings;
+		Schema schema = getMappingSchema();
+		try {
+			JAXBContext jc = JAXBContext.newInstance( ConstraintMappingsType.class );
+			Unmarshaller unmarshaller = jc.createUnmarshaller();
+			unmarshaller.setSchema( schema );
+			StreamSource stream = new StreamSource( in );
+			JAXBElement<ConstraintMappingsType> root = unmarshaller.unmarshal( stream, ConstraintMappingsType.class );
+			constraintMappings = root.getValue();
+		}
+		catch ( JAXBException e ) {
+			String msg = "Error parsing mapping file.";
+			log.error( msg );
+			throw new ValidationException( msg, e );
+		}
+		return constraintMappings;
+	}
+
+	private Schema getMappingSchema() {
+		URL schemaUrl = this.getClass().getClassLoader().getResource( VALIDATION_MAPPING_XSD );
+		SchemaFactory sf = SchemaFactory.newInstance( javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI );
+		Schema schema = null;
+		try {
+			schema = sf.newSchema( schemaUrl );
+		}
+		catch ( SAXException e ) {
+			log.warn( "Unable to create schema for {}: {}", VALIDATION_MAPPING_XSD, e.getMessage() );
+		}
+		return schema;
+	}
+}

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ConstraintHelperTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ConstraintHelperTest.java	2009-06-16 15:29:59 UTC (rev 16797)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ConstraintHelperTest.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -29,6 +29,7 @@
 import org.testng.annotations.Test;
 
 import org.hibernate.validation.util.ReflectionHelper;
+import org.hibernate.validation.metadata.ConstraintHelper;
 
 /**
  * @author Hardy Ferentschik

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolatorTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolatorTest.java	2009-06-16 15:29:59 UTC (rev 16797)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolatorTest.java	2009-06-16 16:16:48 UTC (rev 16798)
@@ -35,6 +35,8 @@
 
 import org.hibernate.validation.util.annotationfactory.AnnotationDescriptor;
 import org.hibernate.validation.util.annotationfactory.AnnotationFactory;
+import org.hibernate.validation.metadata.ConstraintDescriptorImpl;
+import org.hibernate.validation.metadata.ConstraintHelper;
 
 /**
  * Tests for message resolution.

Modified: validator/trunk/hibernate-validator/src/test/suite/unit-tests.xml
===================================================================
--- validator/trunk/hibernate-validator/src/test/suite/unit-tests.xml	2009-06-16 15:29:59 UTC (rev 16797)
+++ validator/trunk/hibernate-validator/src/test/suite/unit-tests.xml	2009-06-16 16:16:48 UTC (rev 16798)
@@ -10,10 +10,10 @@
             <package name="org.hibernate.validation.engine.constraintcomposition"/>
             <package name="org.hibernate.validation.engine.graphnavigation"/>
             <package name="org.hibernate.validation.engine.groups"/>
-            <package name="org.hibernate.validation.engine.metadata"/>
+            <package name="org.hibernate.validation.metadata"/>
             <package name="org.hibernate.validation.engine.inheritance"/>
             <package name="org.hibernate.validation.engine.resolver"/>
-            <package name="org.hibernate.validation.engine.xml"/>
+            <package name="org.hibernate.validation.xml"/>
             <package name="org.hibernate.validation.util"/>
             <package name="org.hibernate.validation.util.annotationfactory"/>
         </packages>




More information about the hibernate-commits mailing list