[hibernate-commits] Hibernate SVN: r16505 - in validator/trunk/hibernate-validator/src: test/java/org/hibernate/validation/engine/resolver and 1 other directory.
hibernate-commits at lists.jboss.org
hibernate-commits at lists.jboss.org
Mon May 4 08:42:25 EDT 2009
Author: epbernard
Date: 2009-05-04 08:42:25 -0400 (Mon, 04 May 2009)
New Revision: 16505
Added:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/resolver/SnifferTraversableResolver.java
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/resolver/TraversableResolverTest.java
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/ValidatorImpl.java
Log:
HV-157 cascading no longer executed if isTraversable returns false
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-05-03 21:41:37 UTC (rev 16504)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ExecutionContext.java 2009-05-04 12:42:25 UTC (rev 16505)
@@ -25,6 +25,9 @@
import java.util.Map;
import java.util.Set;
import java.util.Stack;
+import java.lang.reflect.Member;
+import java.lang.reflect.Field;
+import java.lang.annotation.ElementType;
import javax.validation.ConstraintDescriptor;
import javax.validation.ConstraintValidatorFactory;
import javax.validation.ConstraintViolation;
@@ -293,8 +296,18 @@
peekParentPath(),
metaConstraint.getElementType()
);
- }
+ }
+ public boolean isCascadeRequired(Member member) {
+ return traversableResolver.isTraversable(
+ peekCurrentBean(),
+ peekProperty(),
+ getRootBeanClass(),
+ peekParentPath(),
+ member instanceof Field ? ElementType.FIELD : ElementType.METHOD
+ );
+ }
+
public List<ConstraintViolationImpl<T>> createConstraintViolations(Object value, ConstraintValidatorContextImpl constraintValidatorContext) {
List<ConstraintViolationImpl<T>> constraintViolations = new ArrayList<ConstraintViolationImpl<T>>();
for ( ConstraintValidatorContextImpl.ErrorMessage error : constraintValidatorContext.getErrorMessages() ) {
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-05-03 21:41:37 UTC (rev 16504)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java 2009-05-04 12:42:25 UTC (rev 16505)
@@ -279,10 +279,12 @@
for ( Member member : cascadedMembers ) {
Type type = ReflectionHelper.typeOf( member );
context.pushProperty( ReflectionHelper.getPropertyName( member ) );
- Object value = ReflectionHelper.getValue( member, context.peekCurrentBean() );
- if ( value != null ) {
- Iterator<?> iter = createIteratorForCascadedValue( context, type, value );
- validateCascadedConstraint( context, iter );
+ if ( context.isCascadeRequired( member ) ) {
+ Object value = ReflectionHelper.getValue( member, context.peekCurrentBean() );
+ if ( value != null ) {
+ Iterator<?> iter = createIteratorForCascadedValue( context, type, value );
+ validateCascadedConstraint( context, iter );
+ }
}
context.popProperty();
}
Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/resolver/SnifferTraversableResolver.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/resolver/SnifferTraversableResolver.java (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/resolver/SnifferTraversableResolver.java 2009-05-04 12:42:25 UTC (rev 16505)
@@ -0,0 +1,108 @@
+package org.hibernate.validation.engine.resolver;
+
+import java.lang.annotation.ElementType;
+import java.util.Set;
+import java.util.HashSet;
+import javax.validation.TraversableResolver;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class SnifferTraversableResolver implements TraversableResolver {
+ Set<String> paths = new HashSet<String>();
+ Set<Call> calls = new HashSet<Call>();
+
+ public SnifferTraversableResolver(Suit suit) {
+ calls.add( new Call(suit, "size", Suit.class, "", ElementType.FIELD ) );
+ calls.add( new Call(suit, "trousers", Suit.class, "", ElementType.FIELD ) );
+ calls.add( new Call(suit.getTrousers(), "length", Suit.class, "trousers", ElementType.FIELD ) );
+ calls.add( new Call(suit, "jacket", Suit.class, "", ElementType.METHOD ) );
+ calls.add( new Call(suit.getJacket(), "width", Suit.class, "jacket", ElementType.METHOD ) );
+ }
+
+ public Set<String> getPaths() {
+ return paths;
+ }
+
+ //TODO add test with correct paths and types to make sure the impl does not mess it up
+ public boolean isTraversable(Object traversableObject, String traversableProperty, Class<?> rootBeanType, String pathToTraversableObject, ElementType elementType) {
+ String path = "";
+ if (! (pathToTraversableObject == null || pathToTraversableObject.length() == 0 ) ) {
+ path = pathToTraversableObject + ".";
+ }
+ paths.add( path + traversableProperty );
+ Call call = new Call(traversableObject, traversableProperty, rootBeanType, pathToTraversableObject, elementType);
+ if ( ! calls.contains( call ) ) {
+
+ throw new IllegalStateException( "Unexpected " + call.toString() );
+ }
+ return true;
+ }
+
+ private static final class Call {
+ private Object traversableObject;
+ private String traversableProperty;
+ private Class<?> rootBeanType;
+ private String pathToTraversableObject;
+ private ElementType elementType;
+
+ private Call(Object traversableObject, String traversableProperty, Class<?> rootBeanType, String pathToTraversableObject, ElementType elementType) {
+ this.traversableObject = traversableObject;
+ this.traversableProperty = traversableProperty;
+ this.rootBeanType = rootBeanType;
+ this.pathToTraversableObject = pathToTraversableObject;
+ this.elementType = elementType;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if ( this == o ) {
+ return true;
+ }
+ if ( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+
+ Call call = ( Call ) o;
+
+ if ( elementType != call.elementType ) {
+ return false;
+ }
+ if ( !pathToTraversableObject.equals( call.pathToTraversableObject ) ) {
+ return false;
+ }
+ if ( !rootBeanType.equals( call.rootBeanType ) ) {
+ return false;
+ }
+ if ( traversableObject != null ? !(traversableObject == call.traversableObject) : call.traversableObject != null ) {
+ return false;
+ }
+ if ( !traversableProperty.equals( call.traversableProperty ) ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = traversableObject != null ? traversableObject.hashCode() : 0;
+ result = 31 * result + traversableProperty.hashCode();
+ result = 31 * result + rootBeanType.hashCode();
+ result = 31 * result + pathToTraversableObject.hashCode();
+ result = 31 * result + elementType.hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "Call{" +
+ "traversableObject=" + traversableObject +
+ ", traversableProperty='" + traversableProperty + '\'' +
+ ", rootBeanType=" + rootBeanType +
+ ", pathToTraversableObject='" + pathToTraversableObject + '\'' +
+ ", elementType=" + elementType +
+ '}';
+ }
+ }
+}
Copied: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/resolver/TraversableResolverTest.java (from rev 16497, validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/resolver/CachedTraversableResolverTest.java)
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/resolver/TraversableResolverTest.java (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/resolver/TraversableResolverTest.java 2009-05-04 12:42:25 UTC (rev 16505)
@@ -0,0 +1,41 @@
+package org.hibernate.validation.engine.resolver;
+
+import java.lang.annotation.ElementType;
+import java.util.HashSet;
+import java.util.Set;
+import javax.validation.TraversableResolver;
+import javax.validation.Validation;
+import javax.validation.ValidatorFactory;
+import javax.validation.Validator;
+import javax.validation.groups.Default;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+import org.hibernate.validation.engine.HibernateValidatorConfiguration;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class TraversableResolverTest {
+ @Test
+ public void testCorrectPathsAreRequested() {
+ Suit suit = new Suit();
+ suit.setTrousers( new Trousers() );
+ suit.setJacket( new Jacket() );
+ suit.setSize( 3333 );
+ suit.getTrousers().setLength( 32321 );
+ suit.getJacket().setWidth( 432432 );
+
+ SnifferTraversableResolver resolver = new SnifferTraversableResolver(suit);
+ ValidatorFactory factory = Validation.byDefaultProvider()
+ .configure().traversableResolver( resolver )
+ .buildValidatorFactory();
+ Validator v = factory.getValidator();
+
+ //Raises an IllegalStateException if something goes wrong
+ v.validate( suit, Default.class, Cloth.class );
+
+ assertEquals( 5, resolver.getPaths().size() );
+ }
+}
\ No newline at end of file
More information about the hibernate-commits
mailing list