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