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

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Tue Apr 7 13:40:07 EDT 2009


Author: hardy.ferentschik
Date: 2009-04-07 13:40:07 -0400 (Tue, 07 Apr 2009)
New Revision: 16270

Added:
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataCache.java
Modified:
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaData.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/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/xml/ConsistentUserInformation.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/ConsistentUserValidator.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/XmlConfigurationTest.java
   validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml
   validator/trunk/hibernate-validator/src/test/suite/unit-tests.xml
Log:
HV-112 
Parsing successfully some xml class level constraints

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaData.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaData.java	2009-04-07 16:31:07 UTC (rev 16269)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaData.java	2009-04-07 17:40:07 UTC (rev 16270)
@@ -33,6 +33,12 @@
 public interface BeanMetaData<T> {
 
 	/**
+	 * Initalises the given meta data bean taken its current state into account. An instance of <code>BeanMetaData</code>
+	 * won't have any useful state information prior to calling this method.
+	 */
+	void init();
+
+	/**
 	 * @return the class of the bean.
 	 */
 	Class<T> getBeanClass();
@@ -43,16 +49,6 @@
 	BeanDescriptor getBeanDescriptor();
 
 	/**
-	 * @return A list of all cascaded fields (fields annotated with &#064;Valid).
-	 */
-	List<Field> getCascadedFields();
-
-	/**
-	 * @return A list of all cascaded methods (methods annotated with &#064;Valid).
-	 */
-	List<Method> getCascadedMethods();
-
-	/**
 	 * @return A list of all cascaded methods and fields (methods/fields annotated with &#064;Valid).
 	 */
 	List<Member> getCascadedMembers();

Added: 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	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataCache.java	2009-04-07 17:40:07 UTC (rev 16270)
@@ -0,0 +1,46 @@
+// $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;
+
+/**
+ * @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 static Map<Class<?>, BeanMetaDataImpl<?>> metadataProviders
+			= new ConcurrentHashMap<Class<?>, BeanMetaDataImpl<?>>( 10 );
+
+	public static <T> BeanMetaDataImpl<T> getBeanMetaData(Class<T> beanClass) {
+		if ( beanClass == null ) {
+			throw new IllegalArgumentException( "Class cannot be null" );
+		}
+		@SuppressWarnings("unchecked")
+		BeanMetaDataImpl<T> metadata = ( BeanMetaDataImpl<T> ) metadataProviders.get( beanClass );
+		return metadata;
+	}
+
+	static void addBeanMetaData(Class<?> beanClass, BeanMetaDataImpl<?> metaData) {
+		metadataProviders.put( beanClass, metaData );
+	}
+}

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java	2009-04-07 16:31:07 UTC (rev 16269)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java	2009-04-07 17:40:07 UTC (rev 16270)
@@ -26,10 +26,10 @@
 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 java.util.HashSet;
 import javax.validation.BeanDescriptor;
 import javax.validation.GroupSequence;
 import javax.validation.PropertyDescriptor;
@@ -48,6 +48,7 @@
  * instantiate an instance of this class and delegate the metadata extraction to it.
  *
  * @author Hardy Ferentschik
+ * @todo check the unchecked assignment warnings in this class
  */
 
 public class BeanMetaDataImpl<T> implements BeanMetaData<T> {
@@ -70,16 +71,11 @@
 	private List<MetaConstraint<T, ?>> metaConstraintList = new ArrayList<MetaConstraint<T, ?>>();
 
 	/**
-	 * List of cascaded fields.
+	 * List of cascaded members.
 	 */
-	private List<Field> cascadedFields = new ArrayList<Field>();
+	private List<Member> cascadedMembers = new ArrayList<Member>();
 
 	/**
-	 * List of cascaded methods.
-	 */
-	private List<Method> cascadedMethods = new ArrayList<Method>();
-
-	/**
 	 * Maps field and method names to their <code>ElementDescriptorImpl</code>.
 	 */
 	private Map<String, PropertyDescriptor> propertyDescriptors = new HashMap<String, PropertyDescriptor>();
@@ -97,9 +93,44 @@
 	public BeanMetaDataImpl(Class<T> beanClass, ConstraintHelper constraintHelper) {
 		this.beanClass = beanClass;
 		this.constraintHelper = constraintHelper;
+	}
+
+	public void init() {
 		createMetaData();
 	}
 
+	public Class<T> getBeanClass() {
+		return beanClass;
+	}
+
+	public BeanDescriptor getBeanDescriptor() {
+		return beanDescriptor;
+	}
+
+	public List<Member> getCascadedMembers() {
+		return cascadedMembers;
+	}
+
+	public List<MetaConstraint<T, ?>> geMetaConstraintList() {
+		return metaConstraintList;
+	}
+
+	public void addMetaConstraint(MetaConstraint<?, ?> metaConstraint) {
+		metaConstraintList.add( ( MetaConstraint<T, ?> ) metaConstraint );
+	}
+
+	public PropertyDescriptor getPropertyDescriptor(String property) {
+		return propertyDescriptors.get( property );
+	}
+
+	public List<Class<?>> getDefaultGroupSequence() {
+		return 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.
@@ -187,7 +218,7 @@
 			}
 			if ( field.isAnnotationPresent( Valid.class ) ) {
 				ReflectionHelper.setAccessibility( field );
-				cascadedFields.add( field );
+				cascadedMembers.add( field );
 				addPropertyDescriptorForMember( field );
 			}
 		}
@@ -205,7 +236,7 @@
 			}
 			if ( method.isAnnotationPresent( Valid.class ) ) {
 				ReflectionHelper.setAccessibility( method );
-				cascadedMethods.add( method );
+				cascadedMembers.add( method );
 				addPropertyDescriptorForMember( method );
 			}
 		}
@@ -327,43 +358,4 @@
 		}
 		return metadata;
 	}
-
-	public Class<T> getBeanClass() {
-		return beanClass;
-	}
-
-	public BeanDescriptor getBeanDescriptor() {
-		return beanDescriptor;
-	}
-
-	public List<Field> getCascadedFields() {
-		return cascadedFields;
-	}
-
-	public List<Method> getCascadedMethods() {
-		return cascadedMethods;
-	}
-
-	public List<Member> getCascadedMembers() {
-		List<Member> cascadedMembers = new ArrayList<Member>();
-		cascadedMembers.addAll( getCascadedFields() );
-		cascadedMembers.addAll( getCascadedMethods() );
-		return cascadedMembers;
-	}
-
-	public List<MetaConstraint<T, ?>> geMetaConstraintList() {
-		return metaConstraintList;
-	}
-
-	public PropertyDescriptor getPropertyDescriptor(String property) {
-		return propertyDescriptors.get( property );
-	}
-
-	public List<Class<?>> getDefaultGroupSequence() {
-		return defaultGroupSequence;
-	}
-
-	public Set<PropertyDescriptor> getConstrainedProperties() {
-		return Collections.unmodifiableSet( new HashSet<PropertyDescriptor>(propertyDescriptors.values() ) );
-	}
 }
\ No newline at end of file

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-04-07 16:31:07 UTC (rev 16269)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java	2009-04-07 17:40:07 UTC (rev 16270)
@@ -19,9 +19,17 @@
 
 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.Member;
+import java.lang.reflect.Method;
 import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import javax.validation.ConstraintValidatorFactory;
 import javax.validation.MessageInterpolator;
@@ -44,21 +52,27 @@
 
 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.BeanType;
 import org.hibernate.validation.xml.ClassType;
 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.GroupsType;
 
 /**
  * @author Emmanuel Bernard
  * @author Hardy Ferentschik
- * @todo Is this the right place to parse the mapping files?
  */
 public class ValidatorFactoryImpl implements ValidatorFactory {
 
 	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 final MessageInterpolator messageInterpolator;
 	private final TraversableResolver traversableResolver;
@@ -66,13 +80,18 @@
 	private final ConstraintHelper constraintHelper = new ConstraintHelper();
 	private static final String PACKAGE_SEPERATOR = ".";
 
+	private final Map<Class<?>, Boolean> ignoreAnnotationDefaults = new HashMap<Class<?>, Boolean>();
+	private final Map<Class<?>, List<Member>> ignoreAnnotationOnMember = new HashMap<Class<?>, List<Member>>();
+	private final List<Class<?>> ignoreAnnotationOnClass = new ArrayList<Class<?>>();
+	private final Map<Class<?>, List<MetaConstraint<?, ?>>> constraintMap = new HashMap<Class<?>, List<MetaConstraint<?, ?>>>();
+
 	public ValidatorFactoryImpl(ConfigurationState configurationState) {
 		this.messageInterpolator = configurationState.getMessageInterpolator();
 		this.constraintValidatorFactory = configurationState.getConstraintValidatorFactory();
 		this.traversableResolver = configurationState.getTraversableResolver();
 
 		parseMappingFiles( configurationState.getMappingStreams() );
-
+		initBeanMetaData();
 	}
 
 	/**
@@ -99,7 +118,7 @@
 		);
 	}
 
-	public Schema getMappingSchema() {
+	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;
@@ -119,16 +138,13 @@
 				ConstraintMappingsType mappings = getValidationConfig( in );
 				String defaultPackage = mappings.getDefaultPackage();
 				for ( BeanType bean : mappings.getBean() ) {
-					Class<?> beanClass = getBeanClass( bean.getClazz(), defaultPackage );
-					if ( processedClasses.contains( beanClass ) ) {
-						throw new ValidationException( beanClass.getName() + " has already be configured in xml." );
-					}
-					boolean ignoreAnnotations = bean.isIgnoreAnnotations();
-					@SuppressWarnings("unchecked")
-					BeanMetaDataImpl<?> metaData = new BeanMetaDataImpl( beanClass, constraintHelper );
-					parseClassLevelOverrides( metaData, bean.getClassType() );
-					parseFieldLevelOverrides( metaData, bean.getField() );
-					parsePropertyLevelOverrides( metaData, bean.getGetter() );
+					Class<?> beanClass = getClass( bean.getClazz(), defaultPackage );
+					checkClassHasNotBeenProcessed( processedClasses, beanClass );
+					Boolean ignoreAnnotations = bean.isIgnoreAnnotations() == null ? false : bean.isIgnoreAnnotations();
+					ignoreAnnotationDefaults.put( beanClass, ignoreAnnotations );
+					parseClassLevelOverrides( bean.getClassType(), beanClass, defaultPackage );
+					parseFieldLevelOverrides( bean.getField() );
+					parsePropertyLevelOverrides( bean.getGetter() );
 					processedClasses.add( beanClass );
 				}
 			}
@@ -143,19 +159,226 @@
 		}
 	}
 
-	private void parseFieldLevelOverrides(BeanMetaDataImpl<?> metaData, List<FieldType> field) {
-		//To change body of created methods use File | Settings | File Templates.
+	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 parsePropertyLevelOverrides(BeanMetaDataImpl<?> metaData, List<GetterType> getter) {
-		//To change body of created methods use File | Settings | File Templates.
+	private void parseFieldLevelOverrides(List<FieldType> fields) {
+		for ( FieldType field : fields ) {
+			boolean ignoreFieldAnnotation = field.isIgnoreAnnotations() == null ? false : field.isIgnoreAnnotations();
+		}
 	}
 
-	private void parseClassLevelOverrides(BeanMetaDataImpl<?> metaData, ClassType classType) {
-		//To change body of created methods use File | Settings | File Templates.
+	private void parsePropertyLevelOverrides(List<GetterType> getters) {
+		for ( GetterType getter : getters ) {
+			boolean ignoreGetterAnnotation = getter.isIgnoreAnnotations() == null ? false : getter.isIgnoreAnnotations();
+		}
 	}
 
-	private Class getBeanClass(String clazz, String defaultPackage) {
+	private void parseClassLevelOverrides(ClassType classType, Class<?> beanClass, String defaultPackage) {
+		if ( classType == null ) {
+			return;
+		}
+		boolean ignoreClassAnnotation = classType.isIgnoreAnnotations() == null ? false : classType.isIgnoreAnnotations();
+		if ( ignoreClassAnnotation ) {
+			ignoreAnnotationOnClass.add( beanClass );
+		}
+		for ( ConstraintType constraint : classType.getConstraint() ) {
+			MetaConstraint<?, ?> metaConstraint = createMetaConstraint( constraint, beanClass, defaultPackage );
+			addMetaConstraint( beanClass, metaConstraint );
+		}
+	}
+
+	private void addMetaConstraint(Class<?> beanClass, MetaConstraint<?, ?> metaConstraint) {
+		if ( constraintMap.containsKey( beanClass ) ) {
+			constraintMap.get( beanClass ).add( metaConstraint );
+		}
+		else {
+			List<MetaConstraint<?, ?>> constraintList = new ArrayList<MetaConstraint<?, ?>>();
+			constraintList.add( metaConstraint );
+			constraintMap.put( beanClass, constraintList );
+		}
+	}
+
+	private <A extends Annotation, T> MetaConstraint<?, ?> createMetaConstraint(ConstraintType constraint, Class<T> beanClass, 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, new Class[] { }, constraintHelper
+		);
+		return new MetaConstraint<T, A>( beanClass, constraintDescriptor );
+	}
+
+	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 <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) {
+		String value;
+		if ( serializable instanceof String ) {
+			value = ( String ) serializable;
+		}
+		else if ( serializable instanceof JAXBElement ) {
+			JAXBElement<?> elem = ( JAXBElement<?> ) serializable;
+			// this is safe due to the underlying schema
+			value = ( String ) elem.getValue();
+		}
+		else {
+			throw new ValidationException( "Unexpected paramter value" );
+		}
+
+		return convertStringToReturnType( returnType, value );
+	}
+
+	private Object convertStringToReturnType(Class<?> returnType, String value) {
+		Object returnValue;
+		if ( returnType.isPrimitive() && returnType.getName().equals( byte.class.getName() ) ) {
+			try {
+				returnValue = Byte.parseByte( value );
+			}
+			catch ( NumberFormatException e ) {
+				throw new ValidationException( "Invalid byte format", e );
+			}
+		}
+		else if ( returnType.isPrimitive() && returnType.getName().equals( short.class.getName() ) ) {
+			try {
+				returnValue = Short.parseShort( value );
+			}
+			catch ( NumberFormatException e ) {
+				throw new ValidationException( "Invalid short format", e );
+			}
+		}
+		else if ( returnType.isPrimitive() && returnType.getName().equals( int.class.getName() ) ) {
+			try {
+				returnValue = Integer.parseInt( value );
+			}
+			catch ( NumberFormatException e ) {
+				throw new ValidationException( "Invalid int format", e );
+			}
+		}
+		else if ( returnType.isPrimitive() && returnType.getName().equals( long.class.getName() ) ) {
+			try {
+				returnValue = Long.parseLong( value );
+			}
+			catch ( NumberFormatException e ) {
+				throw new ValidationException( "Invalid long format", e );
+			}
+		}
+		else if ( returnType.isPrimitive() && returnType.getName().equals( float.class.getName() ) ) {
+			try {
+				returnValue = Float.parseFloat( value );
+			}
+			catch ( NumberFormatException e ) {
+				throw new ValidationException( "Invalid float format", e );
+			}
+		}
+		else if ( returnType.isPrimitive() && returnType.getName().equals( double.class.getName() ) ) {
+			try {
+				returnValue = Double.parseDouble( value );
+			}
+			catch ( NumberFormatException e ) {
+				throw new ValidationException( "Invalid double format", e );
+			}
+		}
+		else if ( returnType.isPrimitive() && returnType.getName().equals( boolean.class.getName() ) ) {
+			returnValue = Boolean.parseBoolean( value );
+		}
+		else if ( returnType.isPrimitive() && 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 {
+			throw new ValidationException( "Invalid return type: " + returnType );
+		}
+		return returnValue;
+	}
+
+	private Class<?>[] getGroups(GroupsType groupsType, String defaultPackage) {
+		if ( groupsType == null ) {
+			return new Class[] { };
+		}
+
+		List<Class<?>> groupList = new ArrayList<Class<?>>();
+		for ( String groupClass : groupsType.getValue() ) {
+			groupList.add( getClass( groupClass, defaultPackage ) );
+		}
+		return groupList.toArray( new Class[groupList.size()] );
+	}
+
+	private Class<?> getClass(String clazz, String defaultPackage) {
 		String fullyQualifiedClass;
 		if ( isQualifiedClass( clazz ) ) {
 			fullyQualifiedClass = clazz;
@@ -193,4 +416,15 @@
 		}
 		return constraintMappings;
 	}
+
+	private void initBeanMetaData() {
+		for ( Map.Entry<Class<?>, List<MetaConstraint<?, ?>>> entry : constraintMap.entrySet() ) {
+			BeanMetaDataImpl<?> metaData = new BeanMetaDataImpl( entry.getKey(), constraintHelper );
+			for ( MetaConstraint<?, ?> metaConstraint : entry.getValue() ) {
+				metaData.addMetaConstraint( metaConstraint );
+			}
+			metaData.init();
+			BeanMetaDataCache.addBeanMetaData( entry.getKey(), metaData );
+		}
+	}
 }

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-04-07 16:31:07 UTC (rev 16269)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java	2009-04-07 17:40:07 UTC (rev 16270)
@@ -27,7 +27,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
 import javax.validation.BeanDescriptor;
 import javax.validation.ConstraintValidatorFactory;
 import javax.validation.ConstraintViolation;
@@ -73,13 +72,6 @@
 	private static final Class<?>[] DEFAULT_GROUP_ARRAY = new Class<?>[] { Default.class };
 
 	/**
-	 * 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 static Map<Class<?>, BeanMetaDataImpl<?>> metadataProviders
-			= new ConcurrentHashMap<Class<?>, BeanMetaDataImpl<?>>( 10 );
-
-	/**
 	 * Used to resolve the group execution order for a validate call.
 	 */
 	private GroupChainGenerator groupChainGenerator;
@@ -559,14 +551,11 @@
 	 * {@inheritDoc}
 	 */
 	private <T> BeanMetaData<T> getBeanMetaData(Class<T> beanClass) {
-		if ( beanClass == null ) {
-			throw new IllegalArgumentException( "Class cannot be null" );
-		}
-		@SuppressWarnings("unchecked")
-		BeanMetaDataImpl<T> metadata = ( BeanMetaDataImpl<T> ) metadataProviders.get( beanClass );
+		BeanMetaDataImpl<T> metadata = BeanMetaDataCache.getBeanMetaData( beanClass );
 		if ( metadata == null ) {
 			metadata = new BeanMetaDataImpl<T>( beanClass, constraintHelper );
-			metadataProviders.put( beanClass, metadata );
+			metadata.init();
+			BeanMetaDataCache.addBeanMetaData( beanClass, metadata );
 		}
 		return metadata;
 	}

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/ConsistentUserInformation.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/ConsistentUserInformation.java	2009-04-07 16:31:07 UTC (rev 16269)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/ConsistentUserInformation.java	2009-04-07 17:40:07 UTC (rev 16270)
@@ -1,4 +1,4 @@
-// $Id:$
+// $Id$
 /*
 * JBoss, Home of Professional Open Source
 * Copyright 2008, Red Hat Middleware LLC, and individual contributors
@@ -38,4 +38,10 @@
 	public abstract String message() default "User information is not consistent.";
 
 	public abstract Class<?>[] groups() default { };
+
+	public abstract String stringParam() default "";
+
+	public abstract String[] stringArrayParam() default { };
+
+	public abstract int intParam() default 0;
 }

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/ConsistentUserValidator.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/ConsistentUserValidator.java	2009-04-07 16:31:07 UTC (rev 16269)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/ConsistentUserValidator.java	2009-04-07 17:40:07 UTC (rev 16270)
@@ -1,4 +1,4 @@
-// $Id:$
+// $Id$
 /*
 * JBoss, Home of Professional Open Source
 * Copyright 2008, Red Hat Middleware LLC, and individual contributors
@@ -29,6 +29,6 @@
 	}
 
 	public boolean isValid(User user, ConstraintValidatorContext constraintValidatorContext) {
-		return true;
+		return user.isConsistent();
 	}
 }

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java	2009-04-07 16:31:07 UTC (rev 16269)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java	2009-04-07 17:40:07 UTC (rev 16270)
@@ -5,6 +5,8 @@
  */
 public class User {
 
+	private boolean isConsistent;
+
 	private String firstname;
 
 	//@NotNull(groups = Default.class)
@@ -37,4 +39,12 @@
 	public void setPhoneNumber(String phoneNumber) {
 		this.phoneNumber = phoneNumber;
 	}
+
+	public void setConsistent(boolean consistent) {
+		isConsistent = consistent;
+	}
+
+	public boolean isConsistent() {
+		return isConsistent;
+	}
 }
\ No newline at end of file

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/XmlConfigurationTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/XmlConfigurationTest.java	2009-04-07 16:31:07 UTC (rev 16269)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/XmlConfigurationTest.java	2009-04-07 17:40:07 UTC (rev 16270)
@@ -25,6 +25,7 @@
 
 import static org.hibernate.validation.util.TestUtil.assertNumberOfViolations;
 import static org.hibernate.validation.util.TestUtil.getValidator;
+import org.hibernate.validation.util.TestUtil;
 
 /**
  * @author Hardy Ferentschik
@@ -38,5 +39,10 @@
 		User user = new User();
 		Set<ConstraintViolation<User>> constraintViolations = validator.validate( user );
 		assertNumberOfViolations( constraintViolations, 1 );
+		TestUtil.assertConstraintViolation( constraintViolations.iterator().next(), "Message from xml" );
+
+		user.setConsistent( true );
+		constraintViolations = validator.validate( user );
+		assertNumberOfViolations( constraintViolations, 0 );
 	}
 }


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

Modified: validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml
===================================================================
--- validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml	2009-04-07 16:31:07 UTC (rev 16269)
+++ validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml	2009-04-07 17:40:07 UTC (rev 16270)
@@ -8,13 +8,17 @@
                 <value>value0</value>
             </group-sequence>
             <constraint annotation="org.hibernate.validation.engine.xml.ConsistentUserInformation">
-                <message>message0</message>
+                <message>Message from xml</message>
                 <groups>
+                    <value>javax.validation.groups.Default</value>
+                </groups>
+                <element name="stringParam">foobar</element>
+                <element name="stringArrayParam">
                     <value>foo</value>
-                </groups>
-                <element name="name1">
+                    <value>bar</value>
                 </element>
-                <element name="name3">
+                <element name="intParam">
+                    <value>42</value>
                 </element>
             </constraint>
         </class>

Modified: validator/trunk/hibernate-validator/src/test/suite/unit-tests.xml
===================================================================
--- validator/trunk/hibernate-validator/src/test/suite/unit-tests.xml	2009-04-07 16:31:07 UTC (rev 16269)
+++ validator/trunk/hibernate-validator/src/test/suite/unit-tests.xml	2009-04-07 17:40:07 UTC (rev 16270)
@@ -12,6 +12,7 @@
             <package name="org.hibernate.validation.engine.groups"/>
             <package name="org.hibernate.validation.engine.metadata"/>
             <package name="org.hibernate.validation.engine.validatorresolution"/>
+            <package name="org.hibernate.validation.engine.xml"/>
             <package name="org.hibernate.validation.util"/>
             <package name="org.hibernate.validation.util.annotationfactory"/>
         </packages>




More information about the hibernate-commits mailing list