[hibernate-commits] Hibernate SVN: r16792 - in validator/trunk/hibernate-validator/src: main/java/org/hibernate/validation/util and 2 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Tue Jun 16 09:21:53 EDT 2009


Author: hardy.ferentschik
Date: 2009-06-16 09:21:53 -0400 (Tue, 16 Jun 2009)
New Revision: 16792

Added:
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/PropertyPath.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/PropertyPathTest.java
Removed:
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/PropertyIterator.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/PropertyIteratorTest.java
Modified:
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintViolationImpl.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/ValidatorImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/ReflectionHelper.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/package.html
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/Customer.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ValidatorImplTest.java
Log:
HV-163

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintViolationImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintViolationImpl.java	2009-06-16 10:50:53 UTC (rev 16791)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintViolationImpl.java	2009-06-16 13:21:53 UTC (rev 16792)
@@ -17,8 +17,8 @@
 */
 package org.hibernate.validation.engine;
 
+import javax.validation.ConstraintViolation;
 import javax.validation.metadata.ConstraintDescriptor;
-import javax.validation.ConstraintViolation;
 
 /**
  * @author Emmanuel Bernard
@@ -35,7 +35,7 @@
 	private final Class<T> rootBeanClass;
 
 
-	public ConstraintViolationImpl(String messageTemplate, String interpolatedMessage, Class<T> rootBeanClass, 
+	public ConstraintViolationImpl(String messageTemplate, String interpolatedMessage, Class<T> rootBeanClass,
 								   T rootBean, Object leafBeanInstance, Object value,
 								   String propertyPath, ConstraintDescriptor constraintDescriptor) {
 		this.rawMessage = messageTemplate;
@@ -93,6 +93,7 @@
 	}
 
 	@Override
+	@SuppressWarnings("SimplifiableIfStatement")
 	public boolean equals(Object o) {
 		if ( this == o ) {
 			return true;
@@ -112,6 +113,9 @@
 		if ( rootBean != null ? !rootBean.equals( that.rootBean ) : that.rootBean != null ) {
 			return false;
 		}
+		if ( leafBeanInstance != null ? !leafBeanInstance.equals( that.leafBeanInstance ) : that.leafBeanInstance != null ) {
+			return false;
+		}
 		if ( value != null ? !value.equals( that.value ) : that.value != null ) {
 			return false;
 		}
@@ -122,9 +126,10 @@
 	@Override
 	public int hashCode() {
 		int result = interpolatedMessage != null ? interpolatedMessage.hashCode() : 0;
+		result = 31 * result + ( propertyPath != null ? propertyPath.hashCode() : 0 );
 		result = 31 * result + ( rootBean != null ? rootBean.hashCode() : 0 );
+		result = 31 * result + ( leafBeanInstance != null ? leafBeanInstance.hashCode() : 0 );
 		result = 31 * result + ( value != null ? value.hashCode() : 0 );
-		result = 31 * result + ( propertyPath != null ? propertyPath.hashCode() : 0 );
 		return result;
 	}
 }

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 10:50:53 UTC (rev 16791)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ExecutionContext.java	2009-06-16 13:21:53 UTC (rev 16792)
@@ -253,7 +253,7 @@
 		}
 	}
 
-	public void markCurrentPropertyAsIndexed() {
+	public void markCurrentPropertyAsIterable() {
 		String property = peekProperty();
 		property += "[]";
 		propertyPath.remove( propertyPath.size() - 1 );
@@ -284,6 +284,7 @@
 		return buildPath( propertyPath.size() - 2 );
 	}
 
+	@SuppressWarnings("SimplifiableIfStatement")
 	public boolean isValidationRequired(MetaConstraint metaConstraint) {
 		if ( !metaConstraint.getGroupList().contains( currentGroup ) ) {
 			return false;

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 10:50:53 UTC (rev 16791)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java	2009-06-16 13:21:53 UTC (rev 16792)
@@ -28,14 +28,14 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import javax.validation.metadata.BeanDescriptor;
 import javax.validation.ConstraintValidatorFactory;
 import javax.validation.ConstraintViolation;
 import javax.validation.MessageInterpolator;
 import javax.validation.TraversableResolver;
+import javax.validation.ValidationException;
 import javax.validation.Validator;
-import javax.validation.ValidationException;
 import javax.validation.groups.Default;
+import javax.validation.metadata.BeanDescriptor;
 
 import com.googlecode.jtype.TypeUtils;
 import org.slf4j.Logger;
@@ -45,7 +45,7 @@
 import org.hibernate.validation.engine.groups.GroupChainGenerator;
 import org.hibernate.validation.engine.resolver.SingleThreadCachedTraversableResolver;
 import org.hibernate.validation.util.LoggerFactory;
-import org.hibernate.validation.util.PropertyIterator;
+import org.hibernate.validation.util.PropertyPath;
 import org.hibernate.validation.util.ReflectionHelper;
 
 /**
@@ -125,7 +125,7 @@
 		GroupChain groupChain = determineGroupExecutionOrder( groups );
 
 		List<ConstraintViolation<T>> failingConstraintViolations = new ArrayList<ConstraintViolation<T>>();
-		validateProperty( object, new PropertyIterator( propertyName ), failingConstraintViolations, groupChain );
+		validateProperty( object, new PropertyPath( propertyName ), failingConstraintViolations, groupChain );
 		return new HashSet<ConstraintViolation<T>>( failingConstraintViolations );
 	}
 
@@ -140,7 +140,7 @@
 		GroupChain groupChain = determineGroupExecutionOrder( groups );
 
 		List<ConstraintViolation<T>> failingConstraintViolations = new ArrayList<ConstraintViolation<T>>();
-		validateValue( beanType, value, new PropertyIterator( propertyName ), failingConstraintViolations, groupChain );
+		validateValue( beanType, value, new PropertyPath( propertyName ), failingConstraintViolations, groupChain );
 		return new HashSet<ConstraintViolation<T>>( failingConstraintViolations );
 	}
 
@@ -152,7 +152,7 @@
 	}
 
 	public <T> T unwrap(Class<T> type) {
-		throw new ValidationException( "Type " + type + " not supported");
+		throw new ValidationException( "Type " + type + " not supported" );
 	}
 
 	private void sanityCheckPropertyPath(String propertyName) {
@@ -288,7 +288,8 @@
 				Object value = ReflectionHelper.getValue( member, context.peekCurrentBean() );
 				if ( value != null ) {
 					Iterator<?> iter = createIteratorForCascadedValue( context, type, value );
-					validateCascadedConstraint( context, iter );
+					boolean isIndexable = isIndexable( type );
+					validateCascadedConstraint( context, iter, isIndexable );
 				}
 			}
 			context.popProperty();
@@ -309,17 +310,17 @@
 		Iterator<?> iter;
 		if ( ReflectionHelper.isIterable( type ) ) {
 			iter = ( ( Iterable<?> ) value ).iterator();
-			context.markCurrentPropertyAsIndexed();
+			context.markCurrentPropertyAsIterable();
 		}
 		else if ( ReflectionHelper.isMap( type ) ) {
 			Map<?, ?> map = ( Map<?, ?> ) value;
 			iter = map.values().iterator();
-			context.markCurrentPropertyAsIndexed();
+			context.markCurrentPropertyAsIterable();
 		}
 		else if ( TypeUtils.isArray( type ) ) {
 			List<?> arrayList = Arrays.asList( value );
 			iter = arrayList.iterator();
-			context.markCurrentPropertyAsIndexed();
+			context.markCurrentPropertyAsIterable();
 		}
 		else {
 			List<Object> list = new ArrayList<Object>();
@@ -329,8 +330,30 @@
 		return iter;
 	}
 
+	/**
+	 * Called when processing cascaded constraints. This methods inspects the type of the cascaded constraints and in case
+	 * of a list or array creates an iterator in order to validate each element.
+	 *
+	 * @param type the type of the cascaded field or property.
+	 *
+	 * @return An iterator over the value of a cascaded property.
+	 */
+	private boolean isIndexable(Type type) {
+		boolean isIndexable = false;
+		if ( ReflectionHelper.isList( type ) ) {
+			isIndexable = true;
+		}
+		else if ( ReflectionHelper.isMap( type ) ) {
+			isIndexable = true;
+		}
+		else if ( TypeUtils.isArray( type ) ) {
+			isIndexable = true;
+		}
+		return isIndexable;
+	}
+
 	@SuppressWarnings("RedundantArrayCreation")
-	private <T> void validateCascadedConstraint(ExecutionContext<T> context, Iterator<?> iter) {
+	private <T> void validateCascadedConstraint(ExecutionContext<T> context, Iterator<?> iter, boolean isIndexable) {
 		Object actualValue;
 		String propertyIndex;
 		int i = 0;
@@ -346,7 +369,9 @@
 			}
 
 			if ( !context.isAlreadyValidated( actualValue ) ) {
-				context.setPropertyIndex( propertyIndex );
+				if ( isIndexable ) {
+					context.setPropertyIndex( propertyIndex );
+				}
 				context.pushCurrentBean( actualValue );
 				GroupChain groupChain = groupChainGenerator.getGroupChainFor( Arrays.asList( new Class<?>[] { context.getCurrentGroup() } ) );
 				validateInContext( context, groupChain );
@@ -356,13 +381,15 @@
 		}
 	}
 
-	private <T> void validateProperty(T object, PropertyIterator propertyIter, List<ConstraintViolation<T>> failingConstraintViolations, GroupChain groupChain) {
+	private <T> void validateProperty(T object, PropertyPath propertyPath, List<ConstraintViolation<T>> failingConstraintViolations, GroupChain groupChain) {
 
 		@SuppressWarnings("unchecked")
 		final Class<T> beanType = ( Class<T> ) object.getClass();
 
 		Set<MetaConstraint<T, ?>> metaConstraints = new HashSet<MetaConstraint<T, ?>>();
-		Object hostingBeanInstance = collectMetaConstraintsForPath( beanType, object, propertyIter, metaConstraints );
+		Object hostingBeanInstance = collectMetaConstraintsForPath(
+				beanType, object, propertyPath.iterator(), metaConstraints
+		);
 
 		if ( hostingBeanInstance == null ) {
 			throw new IllegalArgumentException( "Invalid property path." );
@@ -379,7 +406,13 @@
 		while ( groupIterator.hasNext() ) {
 			Group group = groupIterator.next();
 			validatePropertyForGroup(
-					object, propertyIter, failingConstraintViolations, metaConstraints, hostingBeanInstance, group, cachedResolver
+					object,
+					propertyPath,
+					failingConstraintViolations,
+					metaConstraints,
+					hostingBeanInstance,
+					group,
+					cachedResolver
 			);
 		}
 
@@ -389,7 +422,13 @@
 			int numberOfConstraintViolationsBefore = failingConstraintViolations.size();
 			for ( Group group : sequence ) {
 				validatePropertyForGroup(
-						object, propertyIter, failingConstraintViolations, metaConstraints, hostingBeanInstance, group, cachedResolver
+						object,
+						propertyPath,
+						failingConstraintViolations,
+						metaConstraints,
+						hostingBeanInstance,
+						group,
+						cachedResolver
 				);
 
 				if ( failingConstraintViolations.size() > numberOfConstraintViolationsBefore ) {
@@ -401,7 +440,7 @@
 
 	private <T> void validatePropertyForGroup(
 			T object,
-			PropertyIterator propertyIter,
+			PropertyPath propertyIter,
 			List<ConstraintViolation<T>> failingConstraintViolations,
 			Set<MetaConstraint<T, ?>> metaConstraints,
 			Object hostingBeanInstance,
@@ -443,9 +482,9 @@
 	}
 
 	@SuppressWarnings("unchecked")
-	private <T> void validateValue(Class<T> beanType, Object value, PropertyIterator propertyIter, List<ConstraintViolation<T>> failingConstraintViolations, GroupChain groupChain) {
+	private <T> void validateValue(Class<T> beanType, Object value, PropertyPath propertyPath, List<ConstraintViolation<T>> failingConstraintViolations, GroupChain groupChain) {
 		Set<MetaConstraint<T, ?>> metaConstraints = new HashSet<MetaConstraint<T, ?>>();
-		collectMetaConstraintsForPath( beanType, null, propertyIter, metaConstraints );
+		collectMetaConstraintsForPath( beanType, null, propertyPath.iterator(), metaConstraints );
 
 		if ( metaConstraints.size() == 0 ) {
 			return;
@@ -461,7 +500,7 @@
 			validateValueForGroup(
 					beanType,
 					value,
-					propertyIter,
+					propertyPath,
 					failingConstraintViolations,
 					metaConstraints,
 					group,
@@ -478,7 +517,7 @@
 				validateValueForGroup(
 						beanType,
 						value,
-						propertyIter,
+						propertyPath,
 						failingConstraintViolations,
 						metaConstraints,
 						group,
@@ -495,7 +534,7 @@
 	private <T> void validateValueForGroup(
 			Class<T> beanType,
 			Object value,
-			PropertyIterator propertyIter,
+			PropertyPath propertyIter,
 			List<ConstraintViolation<T>> failingConstraintViolations,
 			Set<MetaConstraint<T, ?>> metaConstraints,
 			Group group,
@@ -546,22 +585,23 @@
 	 * @return Returns the bean hosting the constraints which match the specified property path.
 	 */
 	@SuppressWarnings("unchecked")
-	private <T> Object collectMetaConstraintsForPath(Class<T> clazz, Object value, PropertyIterator propertyIter, Set<MetaConstraint<T, ?>> metaConstraints) {
-		propertyIter.split();
+	private <T> Object collectMetaConstraintsForPath(Class<T> clazz, Object value, Iterator<PropertyPath.PathElement> propertyIter, Set<MetaConstraint<T, ?>> metaConstraints) {
 
+		PropertyPath.PathElement elem = propertyIter.next();
 		final BeanMetaData<T> metaData = getBeanMetaData( clazz );
 		if ( !propertyIter.hasNext() ) {
+
 			//use metadata first as ReflectionHelper#containsMember is slow
 			//TODO store some metadata here?
-			if ( metaData.getPropertyDescriptor( propertyIter.getHead() ) == null
-					&& !ReflectionHelper.containsMember( clazz, propertyIter.getHead() ) ) {
+			if ( metaData.getPropertyDescriptor( elem.value() ) == null
+					&& !ReflectionHelper.containsMember( clazz, elem.value() ) ) {
 				//TODO better error report
 				throw new IllegalArgumentException( "Invalid property path." );
 			}
 
 			List<MetaConstraint<T, ? extends Annotation>> metaConstraintList = metaData.geMetaConstraintList();
 			for ( MetaConstraint<T, ?> metaConstraint : metaConstraintList ) {
-				if ( metaConstraint.getPropertyName().equals( propertyIter.getHead() ) ) {
+				if ( metaConstraint.getPropertyName().equals( elem.value() ) ) {
 					metaConstraints.add( metaConstraint );
 				}
 			}
@@ -569,13 +609,13 @@
 		else {
 			List<Member> cascadedMembers = metaData.getCascadedMembers();
 			for ( Member m : cascadedMembers ) {
-				if ( ReflectionHelper.getPropertyName( m ).equals( propertyIter.getHead() ) ) {
+				if ( ReflectionHelper.getPropertyName( m ).equals( elem.value() ) ) {
 					Type type = ReflectionHelper.typeOf( m );
 					value = value == null ? null : ReflectionHelper.getValue( m, value );
-					if ( propertyIter.isIndexed() ) {
+					if ( elem.isIndexed() ) {
 						type = ReflectionHelper.getIndexedType( type );
 						value = value == null ? null : ReflectionHelper.getIndexedValue(
-								value, propertyIter.getIndex()
+								value, elem.getIndex()
 						);
 						if ( type == null ) {
 							continue;

Deleted: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/PropertyIterator.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/PropertyIterator.java	2009-06-16 10:50:53 UTC (rev 16791)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/PropertyIterator.java	2009-06-16 13:21:53 UTC (rev 16792)
@@ -1,102 +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.util;
-
-/**
- * @author Hardy Ferentschik
- */
-
-/**
- * Helper class to iterate over a property. After constructing an instance of this class one can with
- * successive calls to <code>split()</code> split the property into a head and tail section. The head will contain the
- * property up to the first '.' and tail the rest. If head is an indexed value it is further seperated into its actual
- * value and index. For example, <code>new PropertyNavigator("order[2].orderNumer").split()</code> will result into:
- * <ul>
- * <li> <code>getHead() == "order"</code> </li>
- * <li> <code>getIndex() == "2"</code> </li>
- * <li> <code>getTail() == "orderNumber"</code> </li>
- * </ul>.
- */
-public class PropertyIterator {
-	final String originalProperty;
-	String head;
-	String index;
-	String tail;
-
-	public PropertyIterator(String property) {
-		this.originalProperty = property;
-		if ("".equals( property ) ) {
-			this.tail = null;
-		} else {
-			this.tail = property;
-		}
-	}
-
-	public boolean hasNext() {
-		return tail != null;
-	}
-
-	/**
-	 * Splits the property at the next '.'
-	 *
-	 * @todo Add error handling in case the property uses wrong characters or has unbalanced []
-	 */
-	public void split() {
-
-		if ( tail == null ) {
-			return;
-		}
-
-		String[] tokens = tail.split( "\\.", 2 ); // split the property at the first .
-
-		head = tokens[0];
-		index = null;
-
-		if ( head.contains( "[" ) ) {
-			head = tokens[0].substring( 0, tokens[0].indexOf( "[" ) );
-			index = tokens[0].substring( tokens[0].indexOf( "[" ) + 1, tokens[0].indexOf( "]" ) );
-		}
-
-		if ( tokens.length > 1 ) {
-			tail = tokens[1];
-		}
-		else {
-			tail = null;
-		}
-	}
-
-	public String getOriginalProperty() {
-		return originalProperty;
-	}
-
-	public String getHead() {
-		return head;
-	}
-
-	public String getTail() {
-		return tail;
-	}
-
-	public String getIndex() {
-		return index;
-	}
-
-	public boolean isIndexed() {
-		return index != null;
-	}
-}

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/PropertyPath.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/PropertyPath.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/PropertyPath.java	2009-06-16 13:21:53 UTC (rev 16792)
@@ -0,0 +1,109 @@
+// $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.util;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+/**
+ * Helper class to iterate over a property path.
+ *
+ * @author Hardy Ferentschik
+ */
+public class PropertyPath implements Iterable<PropertyPath.PathElement> {
+
+	/**
+	 * Regular expression used to split the path into its elements.
+	 *
+	 * @see <a href="http://www.regexplanet.com/simple/index.jsp">Regular expression tester</a>
+	 */
+	private static final Pattern pathPattern = Pattern.compile( "(\\w+)(\\[(\\w+)\\])?(\\.(.*))*" );
+
+	final String originalProperty;
+
+	final List<PathElement> pathList = new ArrayList<PathElement>();
+
+	/**
+	 * Constructs a new {@code PropertyPath}.
+	 *
+	 * @param property The string representation of the property path.
+	 *
+	 * @throws IllegalArgumentException in case {@code property == null} or {@code property} cannot be parsed.
+	 */
+	public PropertyPath(String property) {
+		if ( property == null ) {
+			throw new IllegalArgumentException( "null is not allowed as property path." );
+		}
+
+		this.originalProperty = property;
+		if ( property.length() > 0 ) {
+			parseProperty( property );
+		}
+	}
+
+	private void parseProperty(String property) {
+		String tmp = property;
+		do {
+			Matcher matcher = pathPattern.matcher( tmp );
+			if ( matcher.matches() ) {
+				String value = matcher.group( 1 );
+				String index = matcher.group( 3 );
+				PathElement elem = new PathElement( value, index );
+				pathList.add( elem );
+				tmp = matcher.group( 5 );
+			}
+			else {
+				throw new IllegalArgumentException( "Unable to parse property path " + property );
+			}
+		} while ( tmp != null );
+	}
+
+	public String getOriginalProperty() {
+		return originalProperty;
+	}
+
+	public Iterator<PathElement> iterator() {
+		return pathList.iterator();
+	}
+
+	public static class PathElement {
+		private final String value;
+		private final String index;
+
+		private PathElement(String value, String index) {
+			this.value = value;
+			this.index = index;
+		}
+
+		public String value() {
+			return value;
+		}
+
+		public String getIndex() {
+			return index;
+		}
+
+		public boolean isIndexed() {
+			return index != null;
+		}
+	}
+}
\ No newline at end of file


Property changes on: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/PropertyPath.java
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/ReflectionHelper.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/ReflectionHelper.java	2009-06-16 10:50:53 UTC (rev 16791)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/ReflectionHelper.java	2009-06-16 13:21:53 UTC (rev 16792)
@@ -243,7 +243,7 @@
 	 * @return Returns <code>true</code> if <code>type</code> is a iterable type, <code>false</code> otherwise.
 	 */
 	public static boolean isIterable(Type type) {
-		if ( type instanceof Class && isIterableClass( ( Class ) type ) ) {
+		if ( type instanceof Class && extendsOrImplements( ( Class ) type, Iterable.class ) ) {
 			return true;
 		}
 		if ( type instanceof ParameterizedType ) {
@@ -262,7 +262,7 @@
 	 * @return Returns <code>true</code> if <code>type</code> is implementing <code>Map</code>, <code>false</code> otherwise.
 	 */
 	public static boolean isMap(Type type) {
-		if ( type instanceof Class && isMapClass( ( Class ) type ) ) {
+		if ( type instanceof Class && extendsOrImplements( ( Class ) type, Map.class ) ) {
 			return true;
 		}
 		if ( type instanceof ParameterizedType ) {
@@ -276,6 +276,25 @@
 	}
 
 	/**
+	 * @param type the type to check.
+	 *
+	 * @return Returns <code>true</code> if <code>type</code> is implementing <code>List</code>, <code>false</code> otherwise.
+	 */
+	public static boolean isList(Type type) {
+		if ( type instanceof Class && extendsOrImplements( ( Class ) type, List.class ) ) {
+			return true;
+		}
+		if ( type instanceof ParameterizedType ) {
+			return isList( ( ( ParameterizedType ) type ).getRawType() );
+		}
+		if ( type instanceof WildcardType ) {
+			Type[] upperBounds = ( ( WildcardType ) type ).getUpperBounds();
+			return upperBounds.length != 0 && isList( upperBounds[0] );
+		}
+		return false;
+	}
+
+	/**
 	 * Tries to retrieve the indexed value from the specified object.
 	 *
 	 * @param value The object from which to retrieve the indexed value. The object has to be non <code>null</null> and
@@ -438,7 +457,9 @@
 	 * Returns the autoboxed type of a primitive type.
 	 *
 	 * @param primitiveType the primitive type
-	 * @return  the autoboxed type of a primitive type.
+	 *
+	 * @return the autoboxed type of a primitive type.
+	 *
 	 * @throws IllegalArgumentException in case the parameter {@code primitiveType} does not represent a primitive type.
 	 */
 	public static Class<?> boxedTyp(Type primitiveType) {
@@ -494,28 +515,16 @@
 	}
 
 	/**
-	 * Checks whether the specified class parameter is an instance of a collection class.
+	 * Checks whether the specified {@code clazz} extends or inherits the specified super class or interface.
 	 *
-	 * @param clazz <code>Class</code> to check.
+	 * @param clazz @{code Class} to check.
+	 * @param superClassOrInterface The super class/interface {@code clazz}.
 	 *
-	 * @return <code>true</code> is <code>clazz</code> is instance of a collection class, <code>false</code> otherwise.
+	 * @return {@code true} if {@code clazz} extends or implements {@code superClassOrInterface}, {@code false} otherwise. 
 	 */
-	private static boolean isIterableClass(Class<?> clazz) {
+	private static boolean extendsOrImplements(Class<?> clazz, Class<?> superClassOrInterface) {
 		List<Class<?>> classes = new ArrayList<Class<?>>();
 		computeClassHierarchy( clazz, classes );
-		return classes.contains( Iterable.class );
+		return classes.contains( superClassOrInterface );
 	}
-
-	/**
-	 * Checks whether the specified class parameter is an instance of a collection class.
-	 *
-	 * @param clazz <code>Class</code> to check.
-	 *
-	 * @return <code>true</code> is <code>clazz</code> is instance of a collection class, <code>false</code> otherwise.
-	 */
-	private static boolean isMapClass(Class<?> clazz) {
-		List<Class<?>> classes = new ArrayList<Class<?>>();
-		computeClassHierarchy( clazz, classes );
-		return classes.contains( Map.class );
-	}
 }

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/package.html
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/package.html	2009-06-16 10:50:53 UTC (rev 16791)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/package.html	2009-06-16 13:21:53 UTC (rev 16792)
@@ -21,6 +21,6 @@
 -->
 </head>
 <body>
-This package contains helper independend helper classes.
+This package contains independend helper classes.
 </body>
 </html>

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/Customer.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/Customer.java	2009-06-16 10:50:53 UTC (rev 16791)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/Customer.java	2009-06-16 13:21:53 UTC (rev 16792)
@@ -17,13 +17,10 @@
 */
 package org.hibernate.validation.engine;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.util.HashSet;
+import java.util.Set;
 import javax.validation.Valid;
 
-import org.hibernate.validation.engine.Order;
-import org.hibernate.validation.engine.Person;
-
 /**
  * @author Hardy Ferentschik
  */
@@ -34,14 +31,14 @@
 	private String lastName;
 
 	@Valid
-	private List<Order> orderList = new ArrayList<Order>();
+	private Set<Order> orders = new HashSet<Order>();
 
 	public void addOrder(Order order) {
-		orderList.add( order );
+		orders.add( order );
 	}
 
-	public List<Order> getOrderList() {
-		return orderList;
+	public Set<Order> getOrders() {
+		return orders;
 	}
 
 	public String getFirstName() {

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ValidatorImplTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ValidatorImplTest.java	2009-06-16 10:50:53 UTC (rev 16791)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ValidatorImplTest.java	2009-06-16 13:21:53 UTC (rev 16792)
@@ -159,7 +159,7 @@
 		assertEquals(
 				constraintViolations.size(),
 				3,
-				"we should have been 2 not null violation for addresslines and one lenth violation for city"
+				"we should have been 2 not null violation for addresslines and one length violation for city"
 		);
 
 		constraintViolations = validator.validateProperty( address, "city" );
@@ -185,7 +185,7 @@
 	}
 
 	@Test
-	public void testValidateList() {
+	public void testValidateSet() {
 		Validator validator = TestUtil.getValidator();
 
 		Customer customer = new Customer();
@@ -204,7 +204,7 @@
 		assertEquals( "may not be null", constraintViolation.getMessage(), "Wrong message" );
 		assertEquals( constraintViolation.getRootBean(), customer, "Wrong root entity" );
 		assertEquals( constraintViolation.getInvalidValue(), order.getOrderNumber(), "Wrong value" );
-		assertEquals( "orderList[0].orderNumber", constraintViolation.getPropertyPath(), "Wrong propertyName" );
+		assertEquals( "orders[].orderNumber", constraintViolation.getPropertyPath(), "Wrong propertyName" );
 	}
 
 	@Test
@@ -248,7 +248,7 @@
 		assertEquals( constraintViolation.getRootBean(), clint, "Wrong root entity" );
 		assertEquals( constraintViolation.getInvalidValue(), morgan.getLastName(), "Wrong value" );
 		assertEquals(
-				"playedWith[0].playedWith[1].lastName", constraintViolation.getPropertyPath(), "Wrong propertyName"
+				constraintViolation.getPropertyPath(), "playedWith[0].playedWith[1].lastName", "Wrong propertyName"
 		);
 	}
 
@@ -257,7 +257,7 @@
 		Validator validator = TestUtil.getValidator();
 
 		Set<ConstraintViolation<Customer>> constraintViolations = validator.validateValue(
-				Customer.class, "orderList[0].orderNumber", null
+				Customer.class, "orders[0].orderNumber", null
 		);
 		assertEquals( constraintViolations.size(), 1, "Wrong number of constraints" );
 
@@ -267,9 +267,9 @@
 		assertEquals( constraintViolation.getRootBean(), null, "Wrong root entity" );
 		assertEquals( constraintViolation.getRootBeanClass(), Customer.class, "Wrong root bean class" );
 		assertEquals( constraintViolation.getInvalidValue(), null, "Wrong value" );
-		assertEquals( "orderList[0].orderNumber", constraintViolation.getPropertyPath(), "Wrong propertyName" );
+		assertEquals( "orders[0].orderNumber", constraintViolation.getPropertyPath(), "Wrong propertyName" );
 
-		constraintViolations = validator.validateValue( Customer.class, "orderList[0].orderNumber", 1234 );
+		constraintViolations = validator.validateValue( Customer.class, "orders[0].orderNumber", 1234 );
 		assertEquals( constraintViolations.size(), 0, "Wrong number of constraints" );
 	}
 
@@ -294,7 +294,7 @@
 		}
 
 		try {
-			validator.validateValue( Customer.class, "orderList[0].foobar", null );
+			validator.validateValue( Customer.class, "orders[0].foobar", null );
 			fail();
 		}
 		catch ( IllegalArgumentException e ) {
@@ -311,7 +311,7 @@
 		customer.addOrder( order );
 
 		Set<ConstraintViolation<Customer>> constraintViolations = validator.validateProperty(
-				customer, "orderList[0].orderNumber"
+				customer, "orders[0].orderNumber"
 		);
 		assertEquals( constraintViolations.size(), 1, "Wrong number of constraints" );
 
@@ -320,7 +320,7 @@
 		assertEquals( "may not be null", constraintViolation.getMessage(), "Wrong message" );
 		assertEquals( constraintViolation.getRootBean(), customer, "Wrong root entity" );
 		assertEquals( constraintViolation.getInvalidValue(), order.getOrderNumber(), "Wrong value" );
-		assertEquals( "orderList[0].orderNumber", constraintViolation.getPropertyPath(), "Wrong propertyName" );
+		assertEquals( "orders[0].orderNumber", constraintViolation.getPropertyPath(), "Wrong propertyName" );
 
 		order.setOrderNumber( 1234 );
 		constraintViolations = validator.validateProperty( customer, "orderList[0].orderNumber" );
@@ -336,11 +336,11 @@
 		customer.addOrder( order );
 
 		try {
-			validator.validateProperty( customer, "orderList[1].orderNumber" );
+			validator.validateProperty( customer, "orders[].orderNumber" );
 			fail();
 		}
 		catch ( IllegalArgumentException e ) {
-			assertEquals( "Invalid property path.", e.getMessage() );
+			// success
 		}
 
 		try {
@@ -348,7 +348,7 @@
 			fail();
 		}
 		catch ( IllegalArgumentException e ) {
-			assertEquals( "Invalid property path.", e.getMessage() );
+			// success
 		}
 
 		try {
@@ -356,15 +356,15 @@
 			fail();
 		}
 		catch ( IllegalArgumentException e ) {
-			assertEquals( "Invalid property path.", e.getMessage() );
+			// success
 		}
 
 		try {
-			validator.validateProperty( customer, "orderList[0].foobar" );
+			validator.validateProperty( customer, "orders[].foobar" );
 			fail();
 		}
 		catch ( IllegalArgumentException e ) {
-			assertEquals( "Invalid property path.", e.getMessage() );
+			// success
 		}
 	}
 
@@ -392,7 +392,7 @@
 				"may not be null",
 				Customer.class,
 				null,
-				"orderList[0].orderNumber"
+				"orders[].orderNumber"
 		);
 
 		order.setOrderNumber( 123 );

Deleted: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/PropertyIteratorTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/PropertyIteratorTest.java	2009-06-16 10:50:53 UTC (rev 16791)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/PropertyIteratorTest.java	2009-06-16 13:21:53 UTC (rev 16792)
@@ -1,89 +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.util;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
-import org.testng.annotations.Test;
-
-/**
- * @author Hardy Ferentschik
- */
-public class PropertyIteratorTest {
-
-	@Test
-	public void testSplit() {
-		String property = "order[3].deliveryAddress.addressline[1]";
-		PropertyIterator propIter = new PropertyIterator( property );
-
-		assertTrue( propIter.hasNext() );
-
-		propIter.split();
-		assertTrue( propIter.hasNext() );
-		assertEquals( "order", propIter.getHead() );
-		assertTrue( propIter.isIndexed() );
-		assertEquals( "3", propIter.getIndex() );
-		assertEquals( "deliveryAddress.addressline[1]", propIter.getTail() );
-		assertEquals( property, propIter.getOriginalProperty() );
-
-		propIter.split();
-		assertTrue( propIter.hasNext() );
-		assertEquals( "deliveryAddress", propIter.getHead() );
-		assertFalse( propIter.isIndexed() );
-		assertEquals( null, propIter.getIndex() );
-		assertEquals( "addressline[1]", propIter.getTail() );
-		assertEquals( property, propIter.getOriginalProperty() );
-
-		propIter.split();
-		assertFalse( propIter.hasNext() );
-		assertEquals( "addressline", propIter.getHead() );
-		assertTrue( propIter.isIndexed() );
-		assertEquals( "1", propIter.getIndex() );
-		assertEquals( null, propIter.getTail() );
-		assertEquals( property, propIter.getOriginalProperty() );
-	}
-
-	@Test
-	public void testNull() {
-		PropertyIterator propIter = new PropertyIterator( null );
-		assertFalse( propIter.hasNext() );
-
-		propIter.split();
-		assertFalse( propIter.hasNext() );
-		assertEquals( null, propIter.getHead() );
-		assertFalse( propIter.isIndexed() );
-		assertEquals( null, propIter.getIndex() );
-		assertEquals( null, propIter.getTail() );
-		assertEquals( null, propIter.getOriginalProperty() );
-	}
-
-	@Test
-	public void testEmptyString() {
-		PropertyIterator propIter = new PropertyIterator( "" );
-		assertFalse( propIter.hasNext() );
-
-		propIter.split();
-		assertFalse( propIter.hasNext() );
-		assertEquals( null, propIter.getHead() );
-		assertFalse( propIter.isIndexed() );
-		assertEquals( null, propIter.getIndex() );
-		assertEquals( null, propIter.getTail() );
-		assertEquals( "", propIter.getOriginalProperty() );
-	}
-}

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/PropertyPathTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/PropertyPathTest.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/PropertyPathTest.java	2009-06-16 13:21:53 UTC (rev 16792)
@@ -0,0 +1,92 @@
+// $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.util;
+
+import java.util.Iterator;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import org.testng.annotations.Test;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class PropertyPathTest {
+
+	@Test
+	public void testParsing() {
+		String property = "order[3].deliveryAddress.addressline[1]";
+		PropertyPath path = new PropertyPath( property );
+		Iterator<PropertyPath.PathElement> propIter = path.iterator();
+
+		assertTrue( propIter.hasNext() );
+
+		PropertyPath.PathElement elem = propIter.next();
+		assertTrue( propIter.hasNext() );
+		assertEquals( "order", elem.value() );
+		assertTrue( elem.isIndexed() );
+		assertEquals( "3", elem.getIndex() );
+		assertEquals( property, path.getOriginalProperty() );
+
+		assertTrue( propIter.hasNext() );
+		elem = propIter.next();
+		assertEquals( "deliveryAddress", elem.value() );
+		assertFalse( elem.isIndexed() );
+		assertEquals( null, elem.getIndex() );
+
+		assertTrue( propIter.hasNext() );
+		elem = propIter.next();
+		assertEquals( "addressline", elem.value() );
+		assertTrue( elem.isIndexed() );
+		assertEquals( "1", elem.getIndex() );
+
+		assertFalse( propIter.hasNext() );
+	}
+
+	@Test(expectedExceptions = IllegalArgumentException.class)
+	public void testNull() {
+		new PropertyPath( null );
+	}
+
+	@Test(expectedExceptions = IllegalArgumentException.class)
+	public void testUnbalancedBraces() {
+		new PropertyPath( "foo[.bar" );
+	}
+
+	@Test(expectedExceptions = IllegalArgumentException.class)
+	public void testIndexInMiddleOfProperty() {
+		new PropertyPath( "f[1]oo.bar" );
+	}
+
+	@Test(expectedExceptions = IllegalArgumentException.class)
+	public void testTrailingPathSeperator() {
+		new PropertyPath( "foo.bar." );
+	}
+
+	@Test(expectedExceptions = IllegalArgumentException.class)
+	public void testLeadingPathSeperator() {
+		new PropertyPath( ".foo.bar" );
+	}
+
+	@Test
+	public void testEmptyString() {
+		PropertyPath path = new PropertyPath( "" );
+		assertFalse( path.iterator().hasNext() );
+	}
+}


Property changes on: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/PropertyPathTest.java
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native




More information about the hibernate-commits mailing list