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

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Mon Jun 22 17:05:29 EDT 2009


Author: hardy.ferentschik
Date: 2009-06-22 17:05:28 -0400 (Mon, 22 Jun 2009)
New Revision: 16865

Added:
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/NodeImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/PathImpl.java
Modified:
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintTree.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintValidatorContextImpl.java
   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/resolver/DefaultTraversableResolver.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/resolver/JPATraversableResolver.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/resolver/SingleThreadCachedTraversableResolver.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/traversableresolver/CachedTraversableResolverTest.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/TestUtil.java
Log:
started integrating the new path API

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintTree.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintTree.java	2009-06-22 21:05:07 UTC (rev 16864)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintTree.java	2009-06-22 21:05:28 UTC (rev 16865)
@@ -113,7 +113,7 @@
 		}
 
 		ConstraintValidatorContextImpl constraintValidatorContext = new ConstraintValidatorContextImpl(
-				executionContext.peekParentPath(), executionContext.peekProperty(), descriptor
+				executionContext.peekPropertyPath(), descriptor
 		);
 
 		// we could have a composing constraint which does not need its own validator.
@@ -133,9 +133,8 @@
 		if ( reportAsSingleViolation() && constraintViolations.size() > 0 ) {
 			constraintViolations.clear();
 			final String message = ( String ) getParent().getDescriptor().getAttributes().get( "message" );
-			final String property = executionContext.peekPropertyPath();
 			ConstraintValidatorContextImpl.ErrorMessage error = constraintValidatorContext.new ErrorMessage(
-					message, property
+					message, executionContext.peekPropertyPath()
 			);
 			constraintViolations.add( executionContext.createConstraintViolation( value, error, descriptor ) );
 		}

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintValidatorContextImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintValidatorContextImpl.java	2009-06-22 21:05:07 UTC (rev 16864)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintValidatorContextImpl.java	2009-06-22 21:05:28 UTC (rev 16865)
@@ -19,8 +19,9 @@
 
 import java.util.ArrayList;
 import java.util.List;
-import javax.validation.metadata.ConstraintDescriptor;
 import javax.validation.ConstraintValidatorContext;
+import javax.validation.Path;
+import javax.validation.metadata.ConstraintDescriptor;
 
 /**
  * @author Hardy Ferentschik
@@ -28,15 +29,13 @@
 public class ConstraintValidatorContextImpl implements ConstraintValidatorContext {
 
 	private final List<ErrorMessage> errorMessages = new ArrayList<ErrorMessage>( 3 );
-	private final String property;
-	private final String propertyParent;
+	private final Path propertyPath;
 	private final ConstraintDescriptor<?> constraintDescriptor;
 	private boolean defaultDisabled;
 
 
-	public ConstraintValidatorContextImpl(String propertyParent, String property, ConstraintDescriptor<?> constraintDescriptor) {
-		this.property = property;
-		this.propertyParent = propertyParent;
+	public ConstraintValidatorContextImpl(Path propertyPath, ConstraintDescriptor<?> constraintDescriptor) {
+		this.propertyPath = propertyPath;
 		this.constraintDescriptor = constraintDescriptor;
 	}
 
@@ -44,18 +43,14 @@
 		defaultDisabled = true;
 	}
 
-	public String getDefaultErrorMessage() {
+	public String getDefaultErrorMessageTemplate() {
 		return ( String ) constraintDescriptor.getAttributes().get( "message" );
 	}
 
-	public void addError(String message) {
-		errorMessages.add( new ErrorMessage( message, buildPropertyPath( propertyParent, property ) ) );
+	public ErrorBuilder buildErrorWithMessageTemplate(String messageTemplate) {
+		return null;  //To change body of implemented methods use File | Settings | File Templates.
 	}
 
-	public void addError(String message, String property) {
-		errorMessages.add( new ErrorMessage( message, buildPropertyPath( propertyParent, property ) ) );
-	}
-
 	public ConstraintDescriptor<?> getConstraintDescriptor() {
 		return constraintDescriptor;
 	}
@@ -68,39 +63,27 @@
 		List<ErrorMessage> returnedErrorMessages = new ArrayList<ErrorMessage>( errorMessages );
 		if ( !defaultDisabled ) {
 			returnedErrorMessages.add(
-					new ErrorMessage( getDefaultErrorMessage(), buildPropertyPath( propertyParent, property ) )
+					new ErrorMessage( getDefaultErrorMessageTemplate(), propertyPath )
 			);
 		}
 		return returnedErrorMessages;
 	}
 
-	private String buildPropertyPath(String parent, String leaf) {
-		if ( ExecutionContext.PROPERTY_ROOT.equals( parent ) ) {
-			return leaf;
-		}
-		else {
-			return new StringBuilder().append( parent )
-					.append( ExecutionContext.PROPERTY_PATH_SEPERATOR )
-					.append( leaf )
-					.toString();
-		}
-	}
-
 	public class ErrorMessage {
 		private final String message;
-		private final String property;
+		private final Path propertyPath;
 
-		public ErrorMessage(String message, String property) {
+		public ErrorMessage(String message, Path property) {
 			this.message = message;
-			this.property = property;
+			this.propertyPath = property;
 		}
 
 		public String getMessage() {
 			return message;
 		}
 
-		public String getProperty() {
-			return property;
+		public Path getPath() {
+			return propertyPath;
 		}
 	}
 }

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-22 21:05:07 UTC (rev 16864)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintViolationImpl.java	2009-06-22 21:05:28 UTC (rev 16865)
@@ -18,6 +18,7 @@
 package org.hibernate.validation.engine;
 
 import javax.validation.ConstraintViolation;
+import javax.validation.Path;
 import javax.validation.metadata.ConstraintDescriptor;
 
 /**
@@ -28,7 +29,7 @@
 	private final String interpolatedMessage;
 	private final T rootBean;
 	private final Object value;
-	private final String propertyPath;
+	private final Path propertyPath;
 	private final Object leafBeanInstance;
 	private final ConstraintDescriptor constraintDescriptor;
 	private final String rawMessage;
@@ -37,7 +38,7 @@
 
 	public ConstraintViolationImpl(String messageTemplate, String interpolatedMessage, Class<T> rootBeanClass,
 								   T rootBean, Object leafBeanInstance, Object value,
-								   String propertyPath, ConstraintDescriptor constraintDescriptor) {
+								   Path propertyPath, ConstraintDescriptor constraintDescriptor) {
 		this.rawMessage = messageTemplate;
 		this.interpolatedMessage = interpolatedMessage;
 		this.rootBean = rootBean;
@@ -48,9 +49,6 @@
 		this.rootBeanClass = rootBeanClass;
 	}
 
-	/**
-	 * {@inheritDoc}
-	 */
 	public String getMessage() {
 		return interpolatedMessage;
 	}
@@ -59,9 +57,6 @@
 		return rawMessage;
 	}
 
-	/**
-	 * {@inheritDoc}
-	 */
 	public T getRootBean() {
 		return rootBean;
 	}
@@ -74,17 +69,11 @@
 		return leafBeanInstance;
 	}
 
-	/**
-	 * {@inheritDoc}
-	 */
 	public Object getInvalidValue() {
 		return value;
 	}
 
-	/**
-	 * {@inheritDoc}
-	 */
-	public String getPropertyPath() {
+	public Path getPropertyPath() {
 		return propertyPath;
 	}
 

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-22 21:05:07 UTC (rev 16864)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ExecutionContext.java	2009-06-22 21:05:28 UTC (rev 16865)
@@ -17,25 +17,26 @@
 */
 package org.hibernate.validation.engine;
 
+import java.lang.annotation.ElementType;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.IdentityHashMap;
 import java.util.List;
 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.metadata.ConstraintDescriptor;
+import java.util.HashSet;
 import javax.validation.ConstraintValidatorFactory;
 import javax.validation.ConstraintViolation;
 import javax.validation.MessageInterpolator;
+import javax.validation.Path;
 import javax.validation.TraversableResolver;
+import javax.validation.metadata.ConstraintDescriptor;
 
-import org.hibernate.validation.util.IdentitySet;
 import org.hibernate.validation.metadata.MetaConstraint;
+import org.hibernate.validation.util.IdentitySet;
 
 /**
  * Context object keeping track of all processed objects and failing constraints.
@@ -48,10 +49,6 @@
  */
 public class ExecutionContext<T> {
 
-	public static final String PROPERTY_ROOT = "";
-
-	public static final String PROPERTY_PATH_SEPERATOR = ".";
-
 	/**
 	 * The root bean of the validation.
 	 */
@@ -71,7 +68,7 @@
 	/**
 	 * Maps an object to a list of paths in which it has been invalidated.
 	 */
-	private final Map<Object, Set<String>> processedPaths;
+	private final Map<Object, Set<Path>> processedPaths;
 
 	/**
 	 * A list of all failing constraints so far.
@@ -79,9 +76,9 @@
 	private final List<ConstraintViolation<T>> failingConstraintViolations;
 
 	/**
-	 * The current property based based from the root bean.
+	 * The current property path we are validating.
 	 */
-	private List<String> propertyPath;
+	private PathImpl propertyPath;
 
 	/**
 	 * The current group we are validating.
@@ -98,7 +95,7 @@
 	 *
 	 * @todo Make this boolean a configurable item.
 	 */
-	private boolean allowOneValidationPerPath = true;
+	private boolean allowOneValidationPerPath = false;
 
 	/**
 	 * The message resolver which should be used in this context.
@@ -151,8 +148,8 @@
 
 		beanStack.push( object );
 		processedObjects = new HashMap<Class<?>, IdentitySet>();
-		processedPaths = new IdentityHashMap<Object, Set<String>>();
-		propertyPath = new ArrayList<String>();
+		processedPaths = new IdentityHashMap<Object, Set<Path>>();
+		propertyPath = new PathImpl();
 		failingConstraintViolations = new ArrayList<ConstraintViolation<T>>();
 	}
 
@@ -212,20 +209,6 @@
 		return alreadyValidated;
 	}
 
-	private boolean isAlreadyValidatedForPath(Object value) {
-		for ( String path : processedPaths.get( value ) ) {
-			if ( path.contains( peekPropertyPath() ) || peekPropertyPath().contains( path ) ) {
-				return true;
-			}
-		}
-		return false;
-	}
-
-	private boolean isAlreadyValidatedForCurrentGroup(Object value) {
-		final IdentitySet objectsProcessedInCurrentGroups = processedObjects.get( currentGroup );
-		return objectsProcessedInCurrentGroups != null && objectsProcessedInCurrentGroups.contains( value );
-	}
-
 	public void addConstraintFailures(List<ConstraintViolation<T>> failingConstraintViolations) {
 		for ( ConstraintViolation<T> violation : failingConstraintViolations ) {
 			addConstraintFailure( violation );
@@ -242,47 +225,34 @@
 	 * @param property the new property to add to the current path.
 	 */
 	public void pushProperty(String property) {
-		propertyPath.add( property );
+		propertyPath.addNode( new NodeImpl( property ) );
 	}
 
 	/**
 	 * Drops the last level of the current property path of this context.
 	 */
 	public void popProperty() {
-		if ( propertyPath.size() > 0 ) {
-			propertyPath.remove( propertyPath.size() - 1 );
-		}
+		propertyPath.removeLast();
 	}
 
 	public void markCurrentPropertyAsIterable() {
-		String property = peekProperty();
-		property += "[]";
-		propertyPath.remove( propertyPath.size() - 1 );
-		pushProperty( property );
+		((NodeImpl)propertyPath.getLast()).setInIterable( true );
 	}
 
 	public void setPropertyIndex(String index) {
-		String property = peekProperty();
-
-		// replace the last occurance of [<oldIndex>] with [<index>]
-		property = property.replaceAll( "\\[[0-9]*\\]$", "[" + index + "]" );
-		propertyPath.remove( propertyPath.size() - 1 );
-		pushProperty( property );
+		((NodeImpl)propertyPath.getLast()).setIndex( Integer.getInteger( index ) );
 	}
 
-	public String peekPropertyPath() {
-		return buildPath( propertyPath.size() - 1 );
+	public Path peekPropertyPath() {
+		return new PathImpl(propertyPath);
 	}
 
-	public String peekProperty() {
-		if ( propertyPath.size() == 0 ) {
-			return PROPERTY_ROOT;
-		}
-		return propertyPath.get( propertyPath.size() - 1 );
+	public Path.Node peekProperty() {
+		return propertyPath.getLast();
 	}
 
-	public String peekParentPath() {
-		return buildPath( propertyPath.size() - 2 );
+	public Path peekParentPath() {
+		return propertyPath.getParentPath();
 	}
 
 	@SuppressWarnings("SimplifiableIfStatement")
@@ -302,22 +272,20 @@
 
 	public boolean isCascadeRequired(Member member) {
 		final ElementType type = member instanceof Field ? ElementType.FIELD : ElementType.METHOD;
-		final String parentPath = peekParentPath();
 		final Class<T> rootBeanType = getRootBeanClass();
-		final String traversableProperty = peekProperty();
 		final Object traversableobject = peekCurrentBean();
 		return traversableResolver.isReachable(
 				traversableobject,
-				traversableProperty,
+				peekProperty(),
 				rootBeanType,
-				parentPath,
+				peekParentPath(),
 				type
 		)
 				&& traversableResolver.isCascadable(
 				traversableobject,
-				traversableProperty,
+				peekProperty(),
 				rootBeanType,
-				parentPath,
+				peekParentPath(),
 				type
 		);
 	}
@@ -346,23 +314,24 @@
 				getRootBean(),
 				peekCurrentBean(),
 				value,
-				error.getProperty(),
+				error.getPath(),
 				descriptor
 		);
 	}
 
-	private String buildPath(int index) {
-		if (index < 0) return PROPERTY_ROOT;
-		StringBuilder builder = new StringBuilder();
-		for ( int i = 0; i <= index; i++ ) {
-			builder.append( propertyPath.get( i ) );
-			if ( i < index ) {
-				builder.append( PROPERTY_PATH_SEPERATOR );
-			}
+	private boolean isAlreadyValidatedForPath(Object value) {
+		Set<Path> pathSet = processedPaths.get( value );
+		if(pathSet != null && pathSet.contains( peekPropertyPath() )) {
+			return true;
 		}
-		return builder.toString();
+		return false;
 	}
 
+	private boolean isAlreadyValidatedForCurrentGroup(Object value) {
+		final IdentitySet objectsProcessedInCurrentGroups = processedObjects.get( currentGroup );
+		return objectsProcessedInCurrentGroups != null && objectsProcessedInCurrentGroups.contains( value );
+	}
+
 	private void markProcessed() {
 		markProcessForCurrentGroup();
 		if ( allowOneValidationPerPath ) {
@@ -375,12 +344,13 @@
 			processedPaths.get( peekCurrentBean() ).add( peekPropertyPath() );
 		}
 		else {
-			Set<String> set = new HashSet<String>();
+			Set<Path> set = new HashSet<Path>();
 			set.add( peekPropertyPath() );
 			processedPaths.put( peekCurrentBean(), set );
 		}
 	}
 
+
 	private void markProcessForCurrentGroup() {
 		if ( processedObjects.containsKey( currentGroup ) ) {
 			processedObjects.get( currentGroup ).add( peekCurrentBean() );

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/NodeImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/NodeImpl.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/NodeImpl.java	2009-06-22 21:05:28 UTC (rev 16865)
@@ -0,0 +1,105 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+* http://www.apache.org/licenses/LICENSE-2.0
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.hibernate.validation.engine;
+
+import javax.validation.Path;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class NodeImpl implements Path.Node {
+	private final String name;
+	private boolean isInIterable;
+	private Integer index;
+	private Object key;
+
+
+	public NodeImpl(String name) {
+		this.name = name;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public boolean isInIterable() {
+		return isInIterable;
+	}
+
+	public void setInIterable(boolean inIterable) {
+		isInIterable = inIterable;
+	}
+
+	public Integer getIndex() {
+		return index;
+	}
+
+	public void setIndex(Integer index) {
+		this.index = index;
+	}
+
+	public Object getKey() {
+		return key;
+	}
+
+	@Override
+	public String toString() {
+		return "NodeImpl{" +
+				"name='" + name + '\'' +
+				", isInIterable=" + isInIterable +
+				", index=" + index +
+				", key=" + key +
+				'}';
+	}
+
+	@Override
+	public boolean equals(Object o) {
+		if ( this == o ) {
+			return true;
+		}
+		if ( o == null || getClass() != o.getClass() ) {
+			return false;
+		}
+
+		NodeImpl node = ( NodeImpl ) o;
+
+		if ( isInIterable != node.isInIterable ) {
+			return false;
+		}
+		if ( index != null ? !index.equals( node.index ) : node.index != null ) {
+			return false;
+		}
+		if ( key != null ? !key.equals( node.key ) : node.key != null ) {
+			return false;
+		}
+		if ( name != null ? !name.equals( node.name ) : node.name != null ) {
+			return false;
+		}
+
+		return true;
+	}
+
+	@Override
+	public int hashCode() {
+		int result = name != null ? name.hashCode() : 0;
+		result = 31 * result + ( isInIterable ? 1 : 0 );
+		result = 31 * result + ( index != null ? index.hashCode() : 0 );
+		result = 31 * result + ( key != null ? key.hashCode() : 0 );
+		return result;
+	}
+}

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/PathImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/PathImpl.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/PathImpl.java	2009-06-22 21:05:28 UTC (rev 16865)
@@ -0,0 +1,133 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+* http://www.apache.org/licenses/LICENSE-2.0
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.hibernate.validation.engine;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import javax.validation.Path;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class PathImpl implements Path {
+
+	public static final String PROPERTY_PATH_SEPERATOR = ".";
+
+	private final List<Node> nodeList;
+
+	public PathImpl() {
+		nodeList = new ArrayList<Node>();
+		Node root = new NodeImpl( null );
+		nodeList.add( root );
+	}
+
+	public PathImpl(PathImpl path) {
+		this();
+		Iterator<Node> iter = path.iterator();
+		while(iter.hasNext()) {
+			Node node = iter.next();
+			nodeList.add(node);
+		}
+	}
+
+	public PathImpl(List<Node> nodeList) {
+		this.nodeList = nodeList;
+	}
+
+	public Path getParentPath() {
+		List<Node> nodes = new ArrayList<Node>( nodeList );
+		if ( nodes.size() > 1 ) {
+			nodes.remove( nodes.size() - 1 );
+		}
+		return new PathImpl( nodes );
+	}
+
+	public void addNode(Node node) {
+		nodeList.add( node );
+	}
+
+	public Node removeLast() {
+		if ( nodeList.size() < 1 ) {
+			throw new IllegalStateException();
+		}
+		return nodeList.remove( nodeList.size() - 1 );
+	}
+
+	public Node getLast() {
+		if ( nodeList.size() < 1 ) {
+			throw new IllegalStateException();
+		}
+		return nodeList.get( nodeList.size() - 1 );
+	}
+
+	public Iterator<Path.Node> iterator() {
+		return nodeList.iterator();
+	}
+
+	@Override
+	public String toString() {
+		StringBuilder builder = new StringBuilder();
+		Iterator<Path.Node> iter = iterator();
+		while ( iter.hasNext() ) {
+			Node node = iter.next();
+			if ( node.getName() != null ) {
+				builder.append( node.getName() );
+
+				if ( node.isInIterable() ) {
+					builder.append( "[" );
+					if ( node.getIndex() != null ) {
+						builder.append( node.getIndex() );
+					}
+					else if ( node.getKey() != null ) {
+						builder.append( node.getKey() );
+					}
+					builder.append( "]" );
+				}
+				if ( iter.hasNext() ) {
+					builder.append( PROPERTY_PATH_SEPERATOR );
+
+				}
+			}
+		}
+		return builder.toString();
+	}
+
+	@Override
+	public boolean equals(Object o) {
+		if ( this == o ) {
+			return true;
+		}
+		if ( o == null || getClass() != o.getClass() ) {
+			return false;
+		}
+
+		PathImpl path = ( PathImpl ) o;
+
+		if ( nodeList != null ? !nodeList.equals( path.nodeList ) : path.nodeList != null ) {
+			return false;
+		}
+
+		return true;
+	}
+
+	@Override
+	public int hashCode() {
+		return nodeList != null ? nodeList.hashCode() : 0;
+	}
+}

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/resolver/DefaultTraversableResolver.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/resolver/DefaultTraversableResolver.java	2009-06-22 21:05:07 UTC (rev 16864)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/resolver/DefaultTraversableResolver.java	2009-06-22 21:05:28 UTC (rev 16865)
@@ -1,6 +1,7 @@
 package org.hibernate.validation.engine.resolver;
 
 import java.lang.annotation.ElementType;
+import javax.validation.Path;
 import javax.validation.TraversableResolver;
 
 import org.slf4j.Logger;
@@ -83,13 +84,13 @@
 		}
 	}
 
-	public boolean isReachable(Object traversableObject, String traversableProperty, Class<?> rootBeanType, String pathToTraversableObject, ElementType elementType) {
+	public boolean isReachable(Object traversableObject, Path.Node traversableProperty, Class<?> rootBeanType, Path pathToTraversableObject, ElementType elementType) {
 		return jpaTraversableResolver == null || jpaTraversableResolver.isReachable(
 				traversableObject, traversableProperty, rootBeanType, pathToTraversableObject, elementType
 		);
 	}
 
-	public boolean isCascadable(Object traversableObject, String traversableProperty, Class<?> rootBeanType, String pathToTraversableObject, ElementType elementType) {
+	public boolean isCascadable(Object traversableObject, Path.Node traversableProperty, Class<?> rootBeanType, Path pathToTraversableObject, ElementType elementType) {
 		return jpaTraversableResolver == null || jpaTraversableResolver.isCascadable(
 				traversableObject, traversableProperty, rootBeanType, pathToTraversableObject, elementType
 		);

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/resolver/JPATraversableResolver.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/resolver/JPATraversableResolver.java	2009-06-22 21:05:07 UTC (rev 16864)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/resolver/JPATraversableResolver.java	2009-06-22 21:05:28 UTC (rev 16865)
@@ -20,6 +20,7 @@
 import java.lang.annotation.ElementType;
 import javax.persistence.Persistence;
 import javax.validation.TraversableResolver;
+import javax.validation.Path;
 
 /**
  * @author Hardy Ferentschik
@@ -27,12 +28,13 @@
  */
 public class JPATraversableResolver implements TraversableResolver {
 
-	public boolean isReachable(Object traversableObject, String traversableProperty, Class<?> rootBeanType, String pathToTraversableObject, ElementType elementType) {
+	// TODO Check the call to PeristenceUtil. traversableProperty.getName() is this correct?
+	public boolean isReachable(Object traversableObject, Path.Node traversableProperty, Class<?> rootBeanType, Path pathToTraversableObject, ElementType elementType) {
 		return traversableObject == null ||
-				Persistence.getPersistenceUtil().isLoaded( traversableObject, traversableProperty );
+				Persistence.getPersistenceUtil().isLoaded( traversableObject, traversableProperty.getName() );
 	}
 
-	public boolean isCascadable(Object traversableObject, String traversableProperty, Class<?> rootBeanType, String pathToTraversableObject, ElementType elementType) {
+	public boolean isCascadable(Object traversableObject, Path.Node traversableProperty, Class<?> rootBeanType, Path pathToTraversableObject, ElementType elementType) {
 		return true;
 	}
 }

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/resolver/SingleThreadCachedTraversableResolver.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/resolver/SingleThreadCachedTraversableResolver.java	2009-06-22 21:05:07 UTC (rev 16864)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/resolver/SingleThreadCachedTraversableResolver.java	2009-06-22 21:05:28 UTC (rev 16865)
@@ -20,6 +20,7 @@
 import java.lang.annotation.ElementType;
 import java.util.HashMap;
 import java.util.Map;
+import javax.validation.Path;
 import javax.validation.TraversableResolver;
 
 /**
@@ -37,16 +38,19 @@
 		this.delegate = delegate;
 	}
 
-	public boolean isReachable(Object traversableObject, String traversableProperty, Class<?> rootBeanType, String pathToTraversableObject, ElementType elementType) {
-		TraversableHolder currentLH = new TraversableHolder( traversableObject, traversableProperty, rootBeanType, pathToTraversableObject, elementType );
+	public boolean isReachable(Object traversableObject, Path.Node traversableProperty, Class<?> rootBeanType, Path pathToTraversableObject, ElementType elementType) {
+		TraversableHolder currentLH = new TraversableHolder(
+				traversableObject, traversableProperty, rootBeanType, pathToTraversableObject, elementType
+		);
 		TraversableHolder cachedLH = traversables.get( currentLH );
-		if (cachedLH == null) {
+		if ( cachedLH == null ) {
 			currentLH.isReachable = delegate.isReachable(
 					traversableObject,
 					traversableProperty,
 					rootBeanType,
 					pathToTraversableObject,
-					elementType );
+					elementType
+			);
 			traversables.put( currentLH, currentLH );
 			cachedLH = currentLH;
 		}
@@ -56,21 +60,25 @@
 					traversableProperty,
 					rootBeanType,
 					pathToTraversableObject,
-					elementType );
+					elementType
+			);
 		}
 		return cachedLH.isReachable;
 	}
 
-	public boolean isCascadable(Object traversableObject, String traversableProperty, Class<?> rootBeanType, String pathToTraversableObject, ElementType elementType) {
-		TraversableHolder currentLH = new TraversableHolder( traversableObject, traversableProperty, rootBeanType, pathToTraversableObject, elementType );
+	public boolean isCascadable(Object traversableObject, Path.Node traversableProperty, Class<?> rootBeanType, Path pathToTraversableObject, ElementType elementType) {
+		TraversableHolder currentLH = new TraversableHolder(
+				traversableObject, traversableProperty, rootBeanType, pathToTraversableObject, elementType
+		);
 		TraversableHolder cachedLH = traversables.get( currentLH );
-		if (cachedLH == null) {
+		if ( cachedLH == null ) {
 			currentLH.isCascadable = delegate.isCascadable(
 					traversableObject,
 					traversableProperty,
 					rootBeanType,
 					pathToTraversableObject,
-					elementType );
+					elementType
+			);
 			traversables.put( currentLH, currentLH );
 			cachedLH = currentLH;
 		}
@@ -80,28 +88,29 @@
 					traversableProperty,
 					rootBeanType,
 					pathToTraversableObject,
-					elementType );
+					elementType
+			);
 		}
 		return cachedLH.isCascadable;
 	}
-	
+
 	private static class TraversableHolder {
 		private final Object traversableObject;
-		private final String traversableProperty;
+		private final Path.Node traversableProperty;
 		private final Class<?> rootBeanType;
-		private final String pathToTraversableObject;
+		private final Path pathToTraversableObject;
 		private final ElementType elementType;
 		private final int hashCode;
-		
+
 		private Boolean isReachable;
 		private Boolean isCascadable;
 
 
-		private TraversableHolder(Object traversableObject, String traversableProperty, Class<?> rootBeanType, String pathToTraversableObject, ElementType elementType) {
+		private TraversableHolder(Object traversableObject, Path.Node traversableProperty, Class<?> rootBeanType, Path pathToTraversableObject, ElementType elementType) {
 			this.traversableObject = traversableObject;
 			this.traversableProperty = traversableProperty;
 			this.rootBeanType = rootBeanType;
-			this.pathToTraversableObject = pathToTraversableObject == null ? "" : pathToTraversableObject;
+			this.pathToTraversableObject = pathToTraversableObject;
 			this.elementType = elementType;
 			this.hashCode = buildHashCode();
 		}

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/traversableresolver/CachedTraversableResolverTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/traversableresolver/CachedTraversableResolverTest.java	2009-06-22 21:05:07 UTC (rev 16864)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/traversableresolver/CachedTraversableResolverTest.java	2009-06-22 21:05:28 UTC (rev 16865)
@@ -25,6 +25,7 @@
 import javax.validation.Validation;
 import javax.validation.Validator;
 import javax.validation.ValidatorFactory;
+import javax.validation.Path;
 import javax.validation.groups.Default;
 
 import static org.testng.Assert.fail;
@@ -77,7 +78,7 @@
 		private Set<Holder> askedReach = new HashSet<Holder>();
 		private Set<Holder> askedCascade = new HashSet<Holder>();
 
-		private boolean isTraversable(Set<Holder> asked, Object traversableObject, String traversableProperty, Class<?> rootBeanType, String pathToTraversableObject, ElementType elementType) {
+		private boolean isTraversable(Set<Holder> asked, Object traversableObject, Path.Node traversableProperty, Class<?> rootBeanType, Path pathToTraversableObject, ElementType elementType) {
 			Holder h = new Holder( traversableObject, traversableProperty );
 			if ( asked.contains( h ) ) {
 				throw new IllegalStateException( "Called twice" );
@@ -86,7 +87,7 @@
 			return true;
 		}
 
-		public boolean isReachable(Object traversableObject, String traversableProperty, Class<?> rootBeanType, String pathToTraversableObject, ElementType elementType) {
+		public boolean isReachable(Object traversableObject, Path.Node traversableProperty, Class<?> rootBeanType, Path pathToTraversableObject, ElementType elementType) {
 			return isTraversable(
 					askedReach,
 					traversableObject,
@@ -97,7 +98,7 @@
 			);
 		}
 
-		public boolean isCascadable(Object traversableObject, String traversableProperty, Class<?> rootBeanType, String pathToTraversableObject, ElementType elementType) {
+		public boolean isCascadable(Object traversableObject, Path.Node traversableProperty, Class<?> rootBeanType, Path pathToTraversableObject, ElementType elementType) {
 			return isTraversable(
 					askedCascade,
 					traversableObject,
@@ -111,9 +112,9 @@
 		public static class Holder {
 			Object NULL = new Object();
 			Object to;
-			String tp;
+			Path.Node tp;
 
-			public Holder(Object traversableObject, String traversableProperty) {
+			public Holder(Object traversableObject, Path.Node traversableProperty) {
 				to = traversableObject == null ? NULL : traversableObject;
 				tp = traversableProperty;
 			}

Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/TestUtil.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/TestUtil.java	2009-06-22 21:05:07 UTC (rev 16864)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/TestUtil.java	2009-06-22 21:05:28 UTC (rev 16865)
@@ -114,7 +114,7 @@
 
 	public static void assertConstraintViolation(ConstraintViolation violation, String errorMessage, Class rootBean, Object invalidValue, String propertyPath) {
 		assertEquals(
-				violation.getPropertyPath(),
+				violation.getPropertyPath().toString(),
 				propertyPath,
 				"Wrong propertyPath"
 		);




More information about the hibernate-commits mailing list