[hibernate-commits] Hibernate SVN: r15600 - in validator/trunk: hibernate-validator/src/main/java/org/hibernate/validation/impl and 3 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Wed Nov 19 12:38:55 EST 2008


Author: epbernard
Date: 2008-11-19 12:38:55 -0500 (Wed, 19 Nov 2008)
New Revision: 15600

Added:
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImplementor.java
Modified:
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaDataProviderImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidationContext.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorFactoryImpl.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/bootstrap/ValidationTest.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ValidatorImplTest.java
   validator/trunk/validation-api/src/main/java/javax/validation/Validator.java
   validator/trunk/validation-api/src/main/java/javax/validation/ValidatorFactory.java
Log:
BVAL-77 Move from Validator<T> to Validator and <T> at the method level

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaDataProviderImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaDataProviderImpl.java	2008-11-19 17:34:11 UTC (rev 15599)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaDataProviderImpl.java	2008-11-19 17:38:55 UTC (rev 15600)
@@ -50,6 +50,7 @@
  * instantiate an instance of this class and delegate the metadata extraction to it.
  *
  * @author Hardy Ferentschik
+ * FIXME create an interface for MetadataProvider
  */
 
 public class MetaDataProviderImpl<T> implements MetaDataProvider<T> {

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidationContext.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidationContext.java	2008-11-19 17:34:11 UTC (rev 15599)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidationContext.java	2008-11-19 17:38:55 UTC (rev 15600)
@@ -70,7 +70,7 @@
 	/**
 	 * Stack for keep track of the currently validated object.
 	 */
-	private Stack<Object> validatedobjectStack = new Stack<Object>();
+	private Stack<ValidatedBean> validatedobjectStack = new Stack<ValidatedBean>();
 
 
 	public ValidationContext(T object) {
@@ -79,18 +79,22 @@
 
 	public ValidationContext(T rootBean, Object object) {
 		this.rootBean = rootBean;
-		validatedobjectStack.push( object );
+		validatedobjectStack.push( new ValidatedBean(object) );
 		processedObjects = new HashMap<String, IdentitySet>();
 		propertyPath = "";
 		failingConstraintViolations = new ArrayList<ConstraintViolationImpl<T>>();
 	}
 
 	public Object peekValidatedObject() {
-		return validatedobjectStack.peek();
+		return validatedobjectStack.peek().bean;
 	}
 
+	public Class<?> peekValidatedObjectType() {
+		return validatedobjectStack.peek().beanType;
+	}
+
 	public void pushValidatedObject(Object validatedObject) {
-		validatedobjectStack.push( validatedObject );
+		validatedobjectStack.push( new ValidatedBean(validatedObject) );
 	}
 
 	public void popValidatedObject() {
@@ -111,11 +115,11 @@
 
 	public void markProcessedForCurrentGroup() {
 		if ( processedObjects.containsKey( currentGroup ) ) {
-			processedObjects.get( currentGroup ).add( validatedobjectStack.peek() );
+			processedObjects.get( currentGroup ).add( validatedobjectStack.peek().bean );
 		}
 		else {
 			IdentitySet set = new IdentitySet();
-			set.add( validatedobjectStack.peek() );
+			set.add( validatedobjectStack.peek().bean );
 			processedObjects.put( currentGroup, set );
 		}
 	}
@@ -181,4 +185,21 @@
 	public boolean needsValidation(Set<String> groups) {
 		return groups.contains( currentGroup );
 	}
+
+	//TODO caching the object class is useful?
+	private static class ValidatedBean {
+
+		final Object bean;
+		final Class<?> beanType;
+
+		private ValidatedBean(Object bean) {
+			this.bean = bean;
+			if (bean == null) {
+				this.beanType = null;
+			}
+			else {
+				this.beanType = bean.getClass();
+			}
+		}
+	}
 }
\ No newline at end of file

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImplementor.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImplementor.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImplementor.java	2008-11-19 17:38:55 UTC (rev 15600)
@@ -0,0 +1,14 @@
+package org.hibernate.validation.engine;
+
+import javax.validation.ValidatorFactory;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public interface ValidatorFactoryImplementor extends ValidatorFactory {
+	/**
+	 * Gives access to the required parsed meta data.
+	 * This never returns an null object
+	 */
+	<T> MetaDataProviderImpl<T> getMetadataProvider(Class<T> clazz);
+}

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	2008-11-19 17:34:11 UTC (rev 15599)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java	2008-11-19 17:38:55 UTC (rev 15600)
@@ -27,23 +27,19 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
+import javax.validation.BeanDescriptor;
 import javax.validation.ConstraintDescriptor;
-import javax.validation.ConstraintFactory;
 import javax.validation.ConstraintViolation;
 import javax.validation.MessageResolver;
-import javax.validation.Validator;
 import javax.validation.PropertyDescriptor;
-import javax.validation.BeanDescriptor;
+import javax.validation.Validator;
 
-import org.hibernate.validation.Version;
 import org.hibernate.validation.ValidatorConstants;
+import org.hibernate.validation.Version;
 import org.hibernate.validation.impl.ConstraintDescriptorImpl;
-import org.hibernate.validation.impl.ConstraintFactoryImpl;
 import org.hibernate.validation.impl.ConstraintViolationImpl;
-import org.hibernate.validation.impl.ResourceBundleMessageResolver;
-import org.hibernate.validation.util.ReflectionHelper;
 import org.hibernate.validation.util.PropertyIterator;
+import org.hibernate.validation.util.ReflectionHelper;
 
 /**
  * The main Bean Validation class.
@@ -52,9 +48,9 @@
  * @author Hardy Ferentschik
  * @todo Make all properties transient for serializability.
  */
-public class ValidatorImpl<T> implements Validator<T> {
+public class ValidatorImpl implements Validator {
 
-    private static final Set<Class> INDEXABLE_CLASS = new HashSet<Class>();
+    private static final Set<Class<?>> INDEXABLE_CLASS = new HashSet<Class<?>>();
 
 	static {
 		INDEXABLE_CLASS.add( Integer.class );
@@ -62,46 +58,36 @@
 		INDEXABLE_CLASS.add( String.class );
 	}
 
+
+	//TODO move to Factory at least
 	static {
 		Version.touch();
 	}
 
-	@SuppressWarnings("unchecked")
-	private final List<ConstraintViolationImpl<T>> EMPTY_CONSTRAINTS_LIST = Collections.EMPTY_LIST;
-
+	//TODO remove
 	/**
 	 * A map for caching validators for cascaded entities.
 	 */
-	private final Map<Class<?>, ValidatorImpl> subValidators = new ConcurrentHashMap<Class<?>, ValidatorImpl>();
+	//private final Map<Class<?>, ValidatorImpl> subValidators = new ConcurrentHashMap<Class<?>, ValidatorImpl>();
 
+	
 	/**
-	 * Gives access to the required parsed meta data.
-	 */
-	private final MetaDataProvider<T> metaDataProvider;
-
-	/**
 	 * Message resolver used  for interpolating error messages.
 	 */
 	private final MessageResolver messageResolver;
+	
+	private final ValidatorFactoryImplementor factory;
 
-	public ValidatorImpl(Class<T> beanClass, ConstraintFactory constraintFactory, MessageResolver messageResolver) {
-		if ( beanClass == null ) {
-			throw new IllegalArgumentException( "Bean class paramter cannot be null" );
-		}
-
-		metaDataProvider = new MetaDataProviderImpl<T>( beanClass, constraintFactory );
+	public ValidatorImpl(ValidatorFactoryImplementor factory, MessageResolver messageResolver) {
+		this.factory = factory;
 		this.messageResolver = messageResolver;
 	}
 
-	public ValidatorImpl(Class<T> beanClass) {
-		this( beanClass, new ConstraintFactoryImpl(), new ResourceBundleMessageResolver() );
-	}
 
-
 	/**
 	 * {@inheritDoc}
 	 */
-	public Set<ConstraintViolation<T>> validate(T object, String... groups) {
+	public <T> Set<ConstraintViolation<T>> validate(T object, String... groups) {
 		if ( object == null ) {
 			throw new IllegalArgumentException( "Validation of a null object" );
 		}
@@ -123,9 +109,9 @@
 	 * @todo Currently we iterate the cascaded fields multiple times. Maybe we should change to an approach where we iterate the object graph only once.
 	 * @todo Context root bean can be a different object than the current Validator<T> hence two different generics variables
 	 */
-	private List<ConstraintViolationImpl<T>> validate(ValidationContext<T> context, List<String> groups) {
+	private <T> List<ConstraintViolationImpl<T>> validate(ValidationContext<T> context, List<String> groups) {
 		if ( context.peekValidatedObject() == null ) {
-			return EMPTY_CONSTRAINTS_LIST;
+			return Collections.emptyList();
 		}
 
 		// if no group is specified use the default
@@ -137,7 +123,7 @@
 		boolean isGroupSequence;
 		for ( String group : groups ) {
 			expandedGroups = new ArrayList<String>();
-			isGroupSequence = expandGroupName( group, expandedGroups );
+			isGroupSequence = expandGroupName( context.peekValidatedObjectType(), group, expandedGroups );
 
 			for ( String expandedGroupName : expandedGroups ) {
 				context.setCurrentGroup( expandedGroupName );
@@ -158,7 +144,11 @@
 	 *
 	 * @param context The current validation context.
 	 */
-	private void validateConstraints(ValidationContext<T> context) {
+	private <T> void validateConstraints(ValidationContext<T> context) {
+		//casting rely on the fact that root object is at the top of the stack
+		@SuppressWarnings( "unchecked" )
+		MetaDataProviderImpl<T> metaDataProvider =
+				( MetaDataProviderImpl<T> ) factory.getMetadataProvider( context.peekValidatedObjectType() );
 		for ( MetaConstraint metaConstraint : metaDataProvider.getConstraintMetaDataList() ) {
 			ConstraintDescriptorImpl constraintDescriptor = metaConstraint.getDescriptor();
 			context.pushProperty( metaConstraint.getPropertyName() );
@@ -197,7 +187,7 @@
 		context.markProcessedForCurrentGroup();
 	}
 
-	private void validateCascadedConstraint(ValidationContext<T> context, Type type, Object value) {
+	private <T> void validateCascadedConstraint(ValidationContext<T> context, Type type, Object value) {
 		if ( value == null ) {
 			return;
 		}
@@ -226,8 +216,8 @@
 		validateCascadedConstraint( context, iter );
 	}
 
-	private void validateCascadedConstraints(ValidationContext<T> context) {
-		List<Member> cascadedMembers = getMetaDataProvider().getCascadedMembers();
+	private <T> void validateCascadedConstraints(ValidationContext<T> context) {
+		List<Member> cascadedMembers = factory.getMetadataProvider( context.peekValidatedObjectType() ).getCascadedMembers();
 		for ( Member member : cascadedMembers ) {
 			Type type = ReflectionHelper.typeOf( member );
 			context.pushProperty( ReflectionHelper.getPropertyName( member ) );
@@ -238,7 +228,7 @@
 		}
 	}
 
-	private void validateCascadedConstraint(ValidationContext<T> context, Iterator<?> iter) {
+	private <T> void validateCascadedConstraint(ValidationContext<T> context, Iterator<?> iter) {
 		Object actualValue;
 		String propertyIndex;
 		int i = 0;
@@ -260,10 +250,8 @@
 
 			context.replacePropertyIndex( propertyIndex );
 
-			Class cascadedClass = actualValue.getClass();
-			ValidatorImpl validatorImpl = getValidatorForClass( cascadedClass );
 			context.pushValidatedObject( actualValue );
-			validatorImpl.validate( context, Arrays.asList( context.getCurrentGroup() ) );
+			validate( context, Arrays.asList( context.getCurrentGroup() ) );
 			context.popValidatedObject();
 			i++;
 		}
@@ -273,16 +261,19 @@
 	/**
 	 * {@inheritDoc}
 	 */
-	public Set<ConstraintViolation<T>> validateProperty(T object, String propertyName, String... groups) {
+	public <T> Set<ConstraintViolation<T>> validateProperty(T object, String propertyName, String... groups) {
 		List<ConstraintViolationImpl<T>> failingConstraintViolations = new ArrayList<ConstraintViolationImpl<T>>();
 		validateProperty( object, new PropertyIterator( propertyName ), failingConstraintViolations, groups );
 		return new HashSet<ConstraintViolation<T>>( failingConstraintViolations );
 	}
 
 
-	private void validateProperty(T object, PropertyIterator propertyIter, List<ConstraintViolationImpl<T>> failingConstraintViolations, String... groups) {
-		DesrciptorValueWrapper wrapper = getConstraintDescriptorAndValueForPath( this, propertyIter, object );
+	private <T> void validateProperty(T object, PropertyIterator propertyIter, List<ConstraintViolationImpl<T>> failingConstraintViolations, String... groups) {
+		@SuppressWarnings( "unchecked" )
+		final Class<T> beanType = (Class<T>) object.getClass();
 
+		DesrciptorValueWrapper wrapper = getConstraintDescriptorAndValueForPath( beanType, propertyIter, object );
+
 		if ( wrapper == null ) {
 			return;
 		}
@@ -296,7 +287,7 @@
 		boolean isGroupSequence;
 		for ( String group : groups ) {
 			expandedGroups = new ArrayList<String>();
-			isGroupSequence = expandGroupName( group, expandedGroups );
+			isGroupSequence = expandGroupName( beanType, group, expandedGroups );
 
 			for ( String expandedGroupName : expandedGroups ) {
 
@@ -316,7 +307,7 @@
 						ConstraintViolationImpl<T> failingConstraintViolation = new ConstraintViolationImpl<T>(
 								message,
 								object,
-								( Class<T> ) object.getClass(),
+								beanType,
 								object,
 								wrapper.value,
 								propertyIter.getOriginalProperty(), //FIXME use error.getProperty()
@@ -337,15 +328,15 @@
 	/**
 	 * {@inheritDoc}
 	 */
-	public Set<ConstraintViolation<T>> validateValue(String propertyName, Object value, String... groups) {
+	public <T> Set<ConstraintViolation<T>> validateValue(Class<T> beanType, String propertyName, Object value, String... groups) {
 		List<ConstraintViolationImpl<T>> failingConstraintViolations = new ArrayList<ConstraintViolationImpl<T>>();
-		validateValue( value, new PropertyIterator( propertyName ), failingConstraintViolations, groups );
+		validateValue( beanType, value, new PropertyIterator( propertyName ), failingConstraintViolations, groups );
 		return new HashSet<ConstraintViolation<T>>( failingConstraintViolations );
 	}
 
 
-	private void validateValue(Object object, PropertyIterator propertyIter, List<ConstraintViolationImpl<T>> failingConstraintViolations, String... groups) {
-		ConstraintDescriptorImpl constraintDescriptor = getConstraintDescriptorForPath( this, propertyIter );
+	private <T> void validateValue(Class<T> beanType, Object object, PropertyIterator propertyIter, List<ConstraintViolationImpl<T>> failingConstraintViolations, String... groups) {
+		ConstraintDescriptorImpl constraintDescriptor = getConstraintDescriptorForPath( beanType, propertyIter );
 
 		if ( constraintDescriptor == null ) {
 			return;
@@ -360,7 +351,7 @@
 		boolean isGroupSequence;
 		for ( String group : groups ) {
 			expandedGroups = new ArrayList<String>();
-			isGroupSequence = expandGroupName( group, expandedGroups );
+			isGroupSequence = expandGroupName( beanType, group, expandedGroups );
 
 			for ( String expandedGroupName : expandedGroups ) {
 
@@ -407,18 +398,18 @@
 	 * a constraint descriptor will be returned.
 	 * </p>
 	 *
-	 * @param validator the validator to check for constraints.
+	 * @param clazz the class type to check for constraints.
 	 * @param propertyIter an instance of <code>PropertyIterator</code>
 	 *
 	 * @return The constraint descriptor matching the given path.
 	 */
-	private ConstraintDescriptorImpl getConstraintDescriptorForPath(ValidatorImpl<?> validator, PropertyIterator propertyIter) {
+	private ConstraintDescriptorImpl getConstraintDescriptorForPath(Class<?> clazz, PropertyIterator propertyIter) {
 
 		ConstraintDescriptorImpl matchingConstraintDescriptor = null;
 		propertyIter.split();
 
 		if ( !propertyIter.hasNext() ) {
-			List<MetaConstraint> metaConstraintList = validator.getMetaDataProvider().getConstraintMetaDataList();
+			List<MetaConstraint> metaConstraintList = factory.getMetadataProvider(clazz).getConstraintMetaDataList();
 			for ( MetaConstraint metaConstraint : metaConstraintList ) {
 				ConstraintDescriptor constraintDescriptor = metaConstraint.getDescriptor();
 				if ( metaConstraint.getPropertyName().equals( propertyIter.getHead() ) ) {
@@ -427,7 +418,7 @@
 			}
 		}
 		else {
-			List<Member> cascadedMembers = validator.getMetaDataProvider().getCascadedMembers();
+			List<Member> cascadedMembers = factory.getMetadataProvider(clazz).getCascadedMembers();
 			for ( Member m : cascadedMembers ) {
 				if ( ReflectionHelper.getPropertyName( m ).equals( propertyIter.getHead() ) ) {
 					Type type = ReflectionHelper.typeOf( m );
@@ -439,8 +430,7 @@
 						}
 					}
 
-					ValidatorImpl v = getValidatorForClass( ( Class ) type );
-					matchingConstraintDescriptor = v.getConstraintDescriptorForPath( v, propertyIter );
+					matchingConstraintDescriptor = getConstraintDescriptorForPath( (Class<?>) type, propertyIter );
 				}
 			}
 		}
@@ -449,7 +439,7 @@
 	}
 
 
-	private DesrciptorValueWrapper getConstraintDescriptorAndValueForPath(ValidatorImpl<?> validator, PropertyIterator propertyIter, Object value) {
+	private DesrciptorValueWrapper getConstraintDescriptorAndValueForPath(Class<?> clazz, PropertyIterator propertyIter, Object value) {
 
 		DesrciptorValueWrapper wrapper = null;
 		propertyIter.split();
@@ -457,7 +447,7 @@
 
 		// bottom out - there is only one token left
 		if ( !propertyIter.hasNext() ) {
-			List<MetaConstraint> metaConstraintList = validator.getMetaDataProvider().getConstraintMetaDataList();
+			List<MetaConstraint> metaConstraintList = factory.getMetadataProvider(clazz).getConstraintMetaDataList();
 			for ( MetaConstraint metaConstraint : metaConstraintList ) {
 				ConstraintDescriptor constraintDescriptor = metaConstraint.getDescriptor();
 				if ( metaConstraint.getPropertyName().equals( propertyIter.getHead() ) ) {
@@ -468,20 +458,19 @@
 			}
 		}
 		else {
-			List<Member> cascadedMembers = validator.getMetaDataProvider().getCascadedMembers();
+			List<Member> cascadedMembers = factory.getMetadataProvider(clazz).getCascadedMembers();
 			for ( Member m : cascadedMembers ) {
 				if ( ReflectionHelper.getPropertyName( m ).equals( propertyIter.getHead() ) ) {
 					ReflectionHelper.setAccessibility( m );
-					Object newValue = null;
+					Object newValue;
 					if ( propertyIter.isIndexed() ) {
 						newValue = ReflectionHelper.getValue( m, value );
 					}
 					else {
 						newValue = ReflectionHelper.getIndexedValue( value, propertyIter.getIndex() );
 					}
-					ValidatorImpl cascadedValidator = getValidatorForClass( newValue.getClass() );
-					wrapper = cascadedValidator.getConstraintDescriptorAndValueForPath(
-							cascadedValidator, propertyIter, newValue
+					wrapper = getConstraintDescriptorAndValueForPath(
+							newValue.getClass(), propertyIter, newValue
 					);
 				}
 			}
@@ -491,7 +480,7 @@
 	}
 
 
-	private void addFailingConstraint(List<ConstraintViolationImpl<T>> failingConstraintViolations, ConstraintViolationImpl<T> failingConstraintViolation) {
+	private <T> void addFailingConstraint(List<ConstraintViolationImpl<T>> failingConstraintViolations, ConstraintViolationImpl<T> failingConstraintViolation) {
 		int i = failingConstraintViolations.indexOf( failingConstraintViolation );
 		if ( i == -1 ) {
 			failingConstraintViolations.add( failingConstraintViolation );
@@ -505,26 +494,23 @@
 	/**
 	 * @todo add child validation
 	 */
-	public boolean hasConstraints() {
-		return metaDataProvider.getConstraintMetaDataList().size() > 0;
+	public boolean hasConstraints(Class<?> clazz) {
+		return factory.getMetadataProvider( clazz ).getConstraintMetaDataList().size() > 0;
 	}
 
-	public BeanDescriptor getConstraintsForClass() {
-		return metaDataProvider.getBeanDescriptor();
+	public BeanDescriptor getConstraintsForClass(Class<?> clazz) {
+		return factory.getMetadataProvider( clazz ).getBeanDescriptor();
 	}
 
-	public PropertyDescriptor getConstraintsForProperty(String propertyName) {
-		return metaDataProvider.getPropertyDescriptors().get( propertyName );
+	public PropertyDescriptor getConstraintsForProperty(Class<?> clazz, String propertyName) {
+		return factory.getMetadataProvider( clazz ).getPropertyDescriptors().get( propertyName );
 	}
 
-	public Set<String> getPropertiesWithConstraints() {
-		return Collections.unmodifiableSet( metaDataProvider.getPropertyDescriptors()
-				.keySet() );
+	public Set<String> getPropertiesWithConstraints(Class<?> clazz) {
+		final MetaDataProviderImpl<?> dataProvider = factory.getMetadataProvider( clazz );
+		return Collections.unmodifiableSet( dataProvider.getPropertyDescriptors().keySet() );
 	}
 
-	public MetaDataProvider<T> getMetaDataProvider() {
-		return metaDataProvider;
-	}
 
 	/**
 	 * Checks whether the provided group name is a group sequence and if so expands the group name and add the expanded
@@ -536,13 +522,13 @@
 	 *
 	 * @return <code>true</code> if an expansion took place, <code>false</code> otherwise.
 	 */
-	private boolean expandGroupName(String groupName, List<String> expandedGroupNames) {
+	private <T> boolean expandGroupName(Class<T> beanType, String groupName, List<String> expandedGroupNames) {
 		if ( expandedGroupNames == null ) {
 			throw new IllegalArgumentException( "List cannot be empty" );
 		}
 
 		boolean isGroupSequence;
-
+		MetaDataProviderImpl<T> metaDataProvider = factory.getMetadataProvider( beanType );
 		if ( metaDataProvider.getGroupSequences().containsKey( groupName ) ) {
 			expandedGroupNames.addAll( metaDataProvider.getGroupSequences().get( groupName ) );
 			isGroupSequence = true;
@@ -554,16 +540,6 @@
 		return isGroupSequence;
 	}
 
-	@SuppressWarnings("unchecked")
-	private <V> ValidatorImpl<V> getValidatorForClass(Class<V> cascadedClass) {
-		ValidatorImpl<V> validatorImpl = subValidators.get( cascadedClass );
-		if ( validatorImpl == null ) {
-			validatorImpl = new ValidatorImpl<V>( cascadedClass );
-			subValidators.put( cascadedClass, validatorImpl );
-		}
-		return validatorImpl;
-	}
-
 	private class DesrciptorValueWrapper {
 		final ConstraintDescriptorImpl descriptor;
 		final Object value;

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorFactoryImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorFactoryImpl.java	2008-11-19 17:34:11 UTC (rev 15599)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorFactoryImpl.java	2008-11-19 17:38:55 UTC (rev 15600)
@@ -17,6 +17,8 @@
 */
 package org.hibernate.validation.impl;
 
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 import javax.validation.ConstraintFactory;
 import javax.validation.MessageResolver;
 import javax.validation.Validator;
@@ -24,17 +26,23 @@
 import javax.validation.spi.ValidatorFactoryConfiguration;
 
 import org.hibernate.validation.engine.ValidatorImpl;
+import org.hibernate.validation.engine.ValidatorFactoryImplementor;
+import org.hibernate.validation.engine.MetaDataProviderImpl;
 
 /**
  * @author Emmanuel Bernard
  * @author Hardy Ferentschik
  */
-public class ValidatorFactoryImpl implements ValidatorFactory {
+public class ValidatorFactoryImpl implements ValidatorFactoryImplementor {
 
 	private final MessageResolver messageResolver;
 	private final ConstraintFactory constraintFactory;
 
+	//TODO is there a way to replace ? by so kind of <T> to express the correlation?
+	private Map<Class<?>, MetaDataProviderImpl<?>> metadataProviders
+			= new ConcurrentHashMap<Class<?>, MetaDataProviderImpl<?>>(10);
 
+
 	public ValidatorFactoryImpl(ValidatorFactoryConfiguration configuration) {
 		this.messageResolver = configuration.getMessageResolver();
 		this.constraintFactory = configuration.getConstraintFactory();
@@ -44,15 +52,27 @@
 	/**
 	 * {@inheritDoc}
 	 */
-	public <T> Validator<T> getValidator(Class<T> clazz) {
-		return new ValidatorImpl<T>( clazz, constraintFactory, messageResolver );
+	public Validator getValidator() {
+		return new ValidatorImpl( this, messageResolver );
 	}
 
-	public <T> Validator<T> getValidator(Class<T> clazz, MessageResolver messageResolver) {
-		return new ValidatorImpl<T>( clazz, constraintFactory, messageResolver );
+	public Validator getValidator(MessageResolver messageResolver) {
+		return new ValidatorImpl( this, messageResolver );
 	}
 
 	public MessageResolver getMessageResolver() {
 		return messageResolver;
 	}
+
+	public <T> MetaDataProviderImpl<T> getMetadataProvider(Class<T> beanClass) {
+		//FIXME make sure a optimized mock is provided when no constraints are present.
+		if (beanClass == null) throw new IllegalArgumentException( "Class cannot be null" );
+		@SuppressWarnings( "unchecked")
+		MetaDataProviderImpl<T> metadata = ( MetaDataProviderImpl<T> ) metadataProviders.get(beanClass);
+		if (metadata == null) {
+			metadata = new MetaDataProviderImpl<T>(beanClass, constraintFactory);
+			metadataProviders.put( beanClass, metadata );
+		}
+		return metadata;
+	}
 }

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/bootstrap/ValidationTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/bootstrap/ValidationTest.java	2008-11-19 17:34:11 UTC (rev 15599)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/bootstrap/ValidationTest.java	2008-11-19 17:38:55 UTC (rev 15600)
@@ -77,7 +77,7 @@
 		assertDefaultBuilderAndFactory( builder );
 
 		ValidatorFactory factory = builder.build();
-		Validator<Customer> validator = factory.getValidator( Customer.class );
+		Validator validator = factory.getValidator();
 
 		Customer customer = new Customer();
 		customer.setFirstName( "John" );
@@ -100,7 +100,7 @@
 		assertDefaultBuilderAndFactory( builder );
 
 		ValidatorFactory factory = builder.build();
-		Validator<Customer> validator = factory.getValidator( Customer.class );
+		Validator validator = factory.getValidator( );
 
 		Customer customer = new Customer();
 		customer.setFirstName( "John" );
@@ -124,7 +124,7 @@
 				}
 		);
 		factory = builder.build();
-		validator = factory.getValidator( Customer.class );
+		validator = factory.getValidator( );
 		constraintViolations = validator.validate( customer );
 		assertEquals( "Wrong number of constraints", 1, constraintViolations.size() );
 		constraintViolation = constraintViolations.iterator().next();
@@ -138,7 +138,7 @@
 		assertDefaultBuilderAndFactory( builder );
 
 		ValidatorFactory factory = builder.build();
-		Validator<Customer> validator = factory.getValidator( Customer.class );
+		Validator validator = factory.getValidator(  );
 
 		Customer customer = new Customer();
 		customer.setFirstName( "John" );
@@ -161,7 +161,7 @@
 				}
 		);
 		factory = builder.build();
-		validator = factory.getValidator( Customer.class );
+		validator = factory.getValidator( );
 		constraintViolations = validator.validate( customer );
 		assertEquals( "Wrong number of constraints", 0, constraintViolations.size() );
 	}

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ValidatorImplTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ValidatorImplTest.java	2008-11-19 17:34:11 UTC (rev 15599)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ValidatorImplTest.java	2008-11-19 17:38:55 UTC (rev 15600)
@@ -22,6 +22,7 @@
 import javax.validation.ConstraintViolation;
 import javax.validation.ValidationException;
 import javax.validation.Validator;
+import javax.validation.Validation;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -40,6 +41,7 @@
 import org.hibernate.validation.eg.EnglishDictonary;
 import org.hibernate.validation.eg.Order;
 import org.hibernate.validation.eg.Unconstraint;
+import org.hibernate.validation.HibernateValidatorFactoryBuilder;
 
 /**
  * Tests for the implementation of <code>Validator</code>.
@@ -48,14 +50,27 @@
  */
 public class ValidatorImplTest {
 
+	private Validator hibernateValidator;
 
+	//TODO should not be Hibernate specific in most case
+	private Validator getHibernateValidator() {
+		if (hibernateValidator == null) {
+			HibernateValidatorFactoryBuilder builder = Validation
+					.builderType( HibernateValidatorFactoryBuilder.class )
+					.getBuilder();
+			hibernateValidator = builder.build().getValidator();
+		}
+		return hibernateValidator;
+	}
+
+
 	/**
 	 * JSR 303: Requirements on classes to be validates (3.1)
 	 */
 	@Test
 	public void testWrongMethodName() {
 		try {
-			new ValidatorImpl<Boy>( Boy.class );
+			getHibernateValidator().hasConstraints( Boy.class );
 			fail();
 		}
 		catch ( ValidationException e ) {
@@ -70,36 +85,36 @@
 
 	@Test(expected = IllegalArgumentException.class)
 	public void testNullParamterToValidatorImplConstructor() {
-		new ValidatorImpl<Unconstraint>( null );
+		getHibernateValidator().hasConstraints( null );
 	}
 
 	@Test
 	public void testUnconstraintClass() {
-		Validator<Unconstraint> validator = new ValidatorImpl<Unconstraint>( Unconstraint.class );
-		assertTrue( "There should be no constraints", !validator.hasConstraints() );
+		Validator validator = getHibernateValidator();
+		assertTrue( "There should be no constraints", !validator.hasConstraints( Unconstraint.class ) );
 	}
 
 	@Test
 	public void testHasConstraints() {
-		Validator<Customer> validatorCustomer = new ValidatorImpl<Customer>( Customer.class );
-		assertTrue( "There should be constraints", validatorCustomer.hasConstraints() );
+		Validator validator = getHibernateValidator();
+		assertTrue( "There should be constraints", validator.hasConstraints( Customer.class ) );
 	}
 
 	@Test(expected = IllegalArgumentException.class)
 	public void testValidateWithNull() {
-		Validator<Customer> validatorCustomer = new ValidatorImpl<Customer>( Customer.class );
-		validatorCustomer.validate( null );
+		Validator validator = getHibernateValidator();
+		validator.validate( null );
 	}
 
 	@Test(expected = IllegalArgumentException.class)
 	public void testValidateWithNullProperty() {
-		Validator<Customer> validatorCustomer = new ValidatorImpl<Customer>( Customer.class );
-		validatorCustomer.validate( null, "firstName" );
+		Validator validator = getHibernateValidator();
+		validator.validate( null, "firstName" );
 	}
 
 	@Test
 	public void testGroups() {
-		Validator<Book> validator = new ValidatorImpl<Book>( Book.class );
+		Validator validator = getHibernateValidator();
 
 		Author author = new Author();
 		author.setLastName( "" );
@@ -155,7 +170,7 @@
 
 	@Test
 	public void testDefaultGroupSequence() {
-		Validator<Book> validator = new ValidatorImpl<Book>( Book.class );
+		Validator validator = getHibernateValidator();
 
 		Author author = new Author();
 		author.setLastName( "" );
@@ -198,7 +213,7 @@
 
 	@Test
 	public void testBasicValidation() {
-		Validator<Customer> validator = new ValidatorImpl<Customer>( Customer.class );
+		Validator validator = getHibernateValidator();
 
 		Customer customer = new Customer();
 		customer.setFirstName( "John" );
@@ -214,7 +229,7 @@
 
 	@Test
 	public void testGroupSequences() {
-		Validator<Dictonary> validator = new ValidatorImpl<Dictonary>( Dictonary.class );
+		Validator validator = getHibernateValidator();
 
 		Dictonary dictonary = new Dictonary();
 		dictonary.setTitle( "English - German" );
@@ -230,7 +245,7 @@
 
 	@Test
 	public void testValidationFailureInMultipleGroups() {
-		Validator<Animal> validator = new ValidatorImpl<Animal>( Animal.class );
+		Validator validator = getHibernateValidator();
 		Animal elepfant = new Animal();
 		elepfant.setName( "" );
 		elepfant.setDomain( Animal.Domain.EUKARYOTA );
@@ -255,12 +270,13 @@
 
 	@Test(expected = ValidationException.class)
 	public void testInvalidSequenceName() {
-		new ValidatorImpl<EnglishDictonary>( EnglishDictonary.class );
+		Validator validator = getHibernateValidator();
+		validator.hasConstraints( EnglishDictonary.class );
 	}
 
 	@Test
 	public void testValidationMethod() {
-		Validator<Address> validator = new ValidatorImpl<Address>( Address.class );
+		Validator validator = getHibernateValidator();
 
 		Address address = new Address();
 		address.setAddressline1( null );
@@ -288,7 +304,7 @@
 				constraintViolations.size()
 		);
 
-		constraintViolations = validator.validateValue( "city", "Paris" );
+		constraintViolations = validator.validateValue( Address.class, "city", "Paris" );
 		assertEquals(
 				"Paris should be a valid city name.",
 				0,
@@ -298,7 +314,7 @@
 
 	@Test
 	public void testValidateList() {
-		Validator<Customer> validator = new ValidatorImpl<Customer>( Customer.class );
+		Validator validator = getHibernateValidator();
 
 		Customer customer = new Customer();
 		customer.setFirstName( "John" );
@@ -326,7 +342,7 @@
 	 */
 	@Test
 	public void testMultiValueConstraint() {
-		Validator<Engine> validator = new ValidatorImpl<Engine>( Engine.class );
+		Validator validator = getHibernateValidator();
 
 		Engine engine = new Engine();
 		engine.setSerialNumber( "mail at foobar.com" );
@@ -348,6 +364,8 @@
 	 */
 	@Test
 	public void testGraphValidation() {
+		Validator validator = getHibernateValidator();
+
 		Actor clint = new Actor( "Clint", "Eastwood" );
 		Actor morgan = new Actor( "Morgan", "" );
 		Actor charlie = new Actor( "Charlie", "Sheen" );
@@ -359,7 +377,7 @@
 		morgan.addPlayedWith( clint );
 		clint.addPlayedWith( morgan );
 
-		Validator<Actor> validator = new ValidatorImpl<Actor>( Actor.class );
+
 		Set<ConstraintViolation<Actor>> constraintViolations = validator.validate( clint );
 		ConstraintViolation constraintViolation = constraintViolations.iterator().next();
 		assertEquals( "Wrong number of constraints", 1, constraintViolations.size() );
@@ -372,12 +390,12 @@
 
 	@Test
 	public void testValidateValue() {
-		Validator<Customer> validator = new ValidatorImpl<Customer>( Customer.class );
+		Validator validator = getHibernateValidator();
 
 		Order order = new Order();
 
 		Set<ConstraintViolation<Customer>> constraintViolations = validator.validateValue(
-				"orderList[0].orderNumber", null
+				Customer.class, "orderList[0].orderNumber", null
 		);
 		assertEquals( "Wrong number of constraints", 1, constraintViolations.size() );
 
@@ -389,7 +407,7 @@
 		assertEquals( "Wrong value", order.getOrderNumber(), constraintViolation.getInvalidValue() );
 		assertEquals( "Wrong propertyName", "orderList[0].orderNumber", constraintViolation.getPropertyPath() );
 
-		constraintViolations = validator.validateValue( "orderList[0].orderNumber", "1234" );
+		constraintViolations = validator.validateValue( Customer.class, "orderList[0].orderNumber", "1234" );
 		assertEquals( "Wrong number of constraints", 0, constraintViolations.size() );
 	}
 }

Modified: validator/trunk/validation-api/src/main/java/javax/validation/Validator.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/Validator.java	2008-11-19 17:34:11 UTC (rev 15599)
+++ validator/trunk/validation-api/src/main/java/javax/validation/Validator.java	2008-11-19 17:38:55 UTC (rev 15600)
@@ -21,14 +21,14 @@
 import java.util.Set;
 
 /**
- * Validate a given object type.
+ * Validate objects
  * Implementations of this interface must be thread-safe
  *
  * @author Emmanuel Bernard
  * @author Hardy Ferentschik
  * @todo Should Serializable be part of the definition?
  */
-public interface Validator<T> extends Serializable {
+public interface Validator extends Serializable {
 	/**
 	 * validate all constraints on object
 	 *
@@ -40,7 +40,7 @@
 	 *
 	 * @throws IllegalArgumentException e if object is null
 	 */
-	Set<ConstraintViolation<T>> validate(T object, String... groups);
+	<T> Set<ConstraintViolation<T>> validate(T object, String... groups);
 
 	/**
 	 * validate all constraints on &lt;code&gt;propertyName&lt;/code&gt; property of object
@@ -54,7 +54,7 @@
 	 *
 	 * @throws IllegalArgumentException e if object is null
 	 */
-	Set<ConstraintViolation<T>> validateProperty(T object, String propertyName, String... groups);
+	<T> Set<ConstraintViolation<T>> validateProperty(T object, String propertyName, String... groups);
 
 	/**
 	 * validate all constraints on <code>propertyName</code> property
@@ -69,32 +69,41 @@
 	 *
 	 * @return constraint violations or an empty Set if none
 	 */
-	Set<ConstraintViolation<T>> validateValue(String propertyName, Object value, String... groups);
+	<T> Set<ConstraintViolation<T>> validateValue(Class<T> beanType, String propertyName, Object value, String... groups);
 
 	/**
 	 * return true if at least one constraint declaration is present for the given bean
 	 * or if one property is marked for validation cascade
+	 *
+	 * @param clazz class type evaluated
 	 */
-	boolean hasConstraints();
+	boolean hasConstraints(Class<?> clazz);
 
 	/**
 	 * Return the class level constraints
 	 * The returned object (and associated objects including ConstraintDescriptors)
      * are immutable.
+	 *
+	 * @param clazz class type evaluated
 	 */
-	BeanDescriptor getConstraintsForClass();
+	BeanDescriptor getConstraintsForClass(Class<?> clazz);
 
 	/**
 	 * Return the property level constraints for a given propertyName
 	 * or null if either the property does not exist or has no constraint
 	 * The returned object (and associated objects including ConstraintDescriptors)
      * are immutable.
+	 *
+	 * @param clazz class type evaluated
+	 * @param propertyName property evaludated
 	 */
-	PropertyDescriptor getConstraintsForProperty(String propertyName);
+	PropertyDescriptor getConstraintsForProperty(Class<?> clazz, String propertyName);
 
 	/**
 	 * return the property names having at least a constraint defined
+	 *
+	 * @param clazz class type evaluated
 	 */
-	Set<String> getPropertiesWithConstraints();
+	Set<String> getPropertiesWithConstraints(Class<?> clazz);
 
 }

Modified: validator/trunk/validation-api/src/main/java/javax/validation/ValidatorFactory.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/ValidatorFactory.java	2008-11-19 17:34:11 UTC (rev 15599)
+++ validator/trunk/validation-api/src/main/java/javax/validation/ValidatorFactory.java	2008-11-19 17:38:55 UTC (rev 15600)
@@ -26,23 +26,21 @@
  */
 public interface ValidatorFactory {
 	/**
-	 * return an initialized Validator instance for the specific class.
+	 * return an initialized Validator instance.
 	 * Validator instances can be pooled and shared by the implementation
 	 *
-	 * @param clazz the object class the validator validates
 	 */
-	<T> Validator<T> getValidator(Class<T> clazz);
+	Validator getValidator();
 
 	/**
-	 * return an initialized Validator instance for the specific class.
+	 * return an initialized Validator instance.
 	 * Validator instances can be pooled and shared by the implementation
 	 *
 	 * The returned Validator instance must use the MessageResolver instance
 	 * passed as a parameter to resolve error messages. 
 	 *
-	 * @param clazz the object class the validator validates
 	 */
-	<T> Validator<T> getValidator(Class<T> clazz, MessageResolver messageResolver);
+	Validator getValidator(MessageResolver messageResolver);
 
 	/**
 	 * Returns the MessageResolver instance configured at initialization time




More information about the hibernate-commits mailing list