[hibernate-commits] Hibernate SVN: r16902 - validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Tue Jun 23 08:59:27 EDT 2009


Author: hardy.ferentschik
Date: 2009-06-23 08:59:27 -0400 (Tue, 23 Jun 2009)
New Revision: 16902

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/ExecutionContext.java
   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
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java
Log:
HV-177

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-23 12:57:02 UTC (rev 16901)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintValidatorContextImpl.java	2009-06-23 12:59:27 UTC (rev 16902)
@@ -48,7 +48,7 @@
 	}
 
 	public ErrorBuilder buildErrorWithMessageTemplate(String messageTemplate) {
-		return null;  //To change body of implemented methods use File | Settings | File Templates.
+		return new ErrorBuilderImpl( messageTemplate, propertyPath );
 	}
 
 	public ConstraintDescriptor<?> getConstraintDescriptor() {
@@ -86,4 +86,103 @@
 			return propertyPath;
 		}
 	}
+
+	class ErrorBuilderImpl implements ErrorBuilder {
+		String messageTemplate;
+		Path propertyPath;
+
+		ErrorBuilderImpl(String template, Path path) {
+			messageTemplate = template;
+			propertyPath = path;
+		}
+
+		public NodeBuilder inSubNode(String name) {
+			PathImpl path = new PathImpl();
+			path.addNode( new NodeImpl( name ) );
+			return new NodeBuilderImpl( messageTemplate, path );
+		}
+
+		public ConstraintValidatorContext addError() {
+			errorMessages.add( new ErrorMessage( messageTemplate, propertyPath ) );
+			return ConstraintValidatorContextImpl.this;
+		}
+	}
+
+	class NodeBuilderImpl implements ErrorBuilder.NodeBuilder {
+		String messageTemplate;
+		PathImpl propertyPath;
+
+		NodeBuilderImpl(String template, PathImpl path) {
+			messageTemplate = template;
+			propertyPath = path;
+		}
+
+		public ErrorBuilder.InIterableNodeBuilder inSubNode(String name) {
+			NodeImpl node = new NodeImpl( name );
+			propertyPath.addNode( node );
+			return new InIterableNodeBuilderImpl( messageTemplate, propertyPath );
+		}
+
+		public ConstraintValidatorContext addError() {
+			errorMessages.add( new ErrorMessage( messageTemplate, propertyPath ) );
+			return ConstraintValidatorContextImpl.this;
+		}
+	}
+
+	class InIterableNodeBuilderImpl implements ErrorBuilder.InIterableNodeBuilder {
+		String messageTemplate;
+		PathImpl propertyPath;
+
+		InIterableNodeBuilderImpl(String template, PathImpl path) {
+			messageTemplate = template;
+			propertyPath = path;
+		}
+
+		public ErrorBuilder.InIterablePropertiesBuilder inIterable() {
+			return new InIterablePropertiesBuilderImpl(messageTemplate, propertyPath);
+		}
+
+		public ErrorBuilder.InIterableNodeBuilder inSubNode(String name) {
+			Path.Node node = new NodeImpl( name );
+			propertyPath.addNode( node );
+			return this;
+		}
+
+		public ConstraintValidatorContext addError() {
+			errorMessages.add( new ErrorMessage( messageTemplate, propertyPath ) );
+			return ConstraintValidatorContextImpl.this;
+		}
+	}
+
+	class InIterablePropertiesBuilderImpl implements ErrorBuilder.InIterablePropertiesBuilder {
+		String messageTemplate;
+		PathImpl propertyPath;
+
+		InIterablePropertiesBuilderImpl(String template, PathImpl path) {
+			messageTemplate = template;
+			propertyPath = path;
+			propertyPath.getLeafNode().setInIterable( true );
+		}
+
+		public ErrorBuilder.NodeBuilder atKey(Object key) {
+			propertyPath.getLeafNode().setKey( key );
+			return new NodeBuilderImpl( messageTemplate, propertyPath );
+		}
+
+		public ErrorBuilder.NodeBuilder atIndex(Integer index) {
+			propertyPath.getLeafNode().setIndex( index );
+			return new NodeBuilderImpl( messageTemplate, propertyPath );
+		}
+
+		public ErrorBuilder.InIterableNodeBuilder inSubNode(String name) {
+			Path.Node node = new NodeImpl( name );
+			propertyPath.addNode( node );
+			return new InIterableNodeBuilderImpl( messageTemplate, propertyPath );
+		}
+
+		public ConstraintValidatorContext addError() {
+			errorMessages.add( new ErrorMessage( messageTemplate, propertyPath ) );
+			return ConstraintValidatorContextImpl.this;
+		}
+	}
 }

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-23 12:57:02 UTC (rev 16901)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ExecutionContext.java	2009-06-23 12:59:27 UTC (rev 16902)
@@ -22,16 +22,15 @@
 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.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;
 
@@ -68,7 +67,7 @@
 	/**
 	 * Maps an object to a list of paths in which it has been invalidated.
 	 */
-	private final Map<Object, Set<Path>> processedPaths;
+	private final Map<Object, Set<PathImpl>> processedPaths;
 
 	/**
 	 * A list of all failing constraints so far.
@@ -95,7 +94,7 @@
 	 *
 	 * @todo Make this boolean a configurable item.
 	 */
-	private boolean allowOneValidationPerPath = false;
+	private boolean allowOneValidationPerPath = true;
 
 	/**
 	 * The message resolver which should be used in this context.
@@ -148,7 +147,7 @@
 
 		beanStack.push( object );
 		processedObjects = new HashMap<Class<?>, IdentitySet>();
-		processedPaths = new IdentityHashMap<Object, Set<Path>>();
+		processedPaths = new IdentityHashMap<Object, Set<PathImpl>>();
 		propertyPath = new PathImpl();
 		failingConstraintViolations = new ArrayList<ConstraintViolation<T>>();
 	}
@@ -232,29 +231,21 @@
 	 * Drops the last level of the current property path of this context.
 	 */
 	public void popProperty() {
-		propertyPath.removeLast();
+		propertyPath.removeLeafNode();
 	}
 
 	public void markCurrentPropertyAsIterable() {
-		((NodeImpl)propertyPath.getLast()).setInIterable( true );
+		( ( NodeImpl ) propertyPath.getLeafNode() ).setInIterable( true );
 	}
 
 	public void setPropertyIndex(String index) {
-		((NodeImpl)propertyPath.getLast()).setIndex( Integer.getInteger( index ) );
+		( ( NodeImpl ) propertyPath.getLeafNode() ).setIndex( new Integer( index ) );
 	}
 
-	public Path peekPropertyPath() {
-		return new PathImpl(propertyPath);
+	public PathImpl peekPropertyPath() {
+		return new PathImpl( propertyPath );
 	}
 
-	public Path.Node peekProperty() {
-		return propertyPath.getLast();
-	}
-
-	public Path peekParentPath() {
-		return propertyPath.getParentPath();
-	}
-
 	@SuppressWarnings("SimplifiableIfStatement")
 	public boolean isValidationRequired(MetaConstraint metaConstraint) {
 		if ( !metaConstraint.getGroupList().contains( currentGroup ) ) {
@@ -263,9 +254,9 @@
 
 		return traversableResolver.isReachable(
 				peekCurrentBean(),
-				peekProperty(),
+				propertyPath.getLeafNode(),
 				getRootBeanClass(),
-				peekParentPath(),
+				propertyPath.getPathWithoutLeafNode(),
 				metaConstraint.getElementType()
 		);
 	}
@@ -276,16 +267,16 @@
 		final Object traversableobject = peekCurrentBean();
 		return traversableResolver.isReachable(
 				traversableobject,
-				peekProperty(),
+				propertyPath.getLeafNode(),
 				rootBeanType,
-				peekParentPath(),
+				propertyPath.getPathWithoutLeafNode(),
 				type
 		)
 				&& traversableResolver.isCascadable(
 				traversableobject,
-				peekProperty(),
+				propertyPath.getLeafNode(),
 				rootBeanType,
-				peekParentPath(),
+				propertyPath.getPathWithoutLeafNode(),
 				type
 		);
 	}
@@ -320,10 +311,17 @@
 	}
 
 	private boolean isAlreadyValidatedForPath(Object value) {
-		Set<Path> pathSet = processedPaths.get( value );
-		if(pathSet != null && pathSet.contains( peekPropertyPath() )) {
-			return true;
+		Set<PathImpl> pathSet = processedPaths.get( value );
+		if ( pathSet == null ) {
+			return false;
 		}
+
+		for (PathImpl p : pathSet) {
+			if (p.isSubPathOf(peekPropertyPath()) || peekPropertyPath().isSubPathOf(p)) {
+				return true;
+			}
+		}
+
 		return false;
 	}
 
@@ -344,7 +342,7 @@
 			processedPaths.get( peekCurrentBean() ).add( peekPropertyPath() );
 		}
 		else {
-			Set<Path> set = new HashSet<Path>();
+			Set<PathImpl> set = new HashSet<PathImpl>();
 			set.add( peekPropertyPath() );
 			processedPaths.put( peekCurrentBean(), set );
 		}

Modified: 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	2009-06-23 12:57:02 UTC (rev 16901)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/NodeImpl.java	2009-06-23 12:59:27 UTC (rev 16902)
@@ -23,6 +23,10 @@
  * @author Hardy Ferentschik
  */
 public class NodeImpl implements Path.Node {
+
+	private static final String INDEX_OPEN = "[";
+	private static final String INDEX_CLOSE = "]";
+
 	private final String name;
 	private boolean isInIterable;
 	private Integer index;
@@ -33,6 +37,13 @@
 		this.name = name;
 	}
 
+	NodeImpl(Path.Node node) {
+		this.name = node.getName();
+		this.isInIterable = node.isInIterable();
+		this.index = node.getIndex();
+		this.key = node.getKey();
+	}
+
 	public String getName() {
 		return name;
 	}
@@ -50,6 +61,7 @@
 	}
 
 	public void setIndex(Integer index) {
+		isInIterable = true;
 		this.index = index;
 	}
 
@@ -57,14 +69,25 @@
 		return key;
 	}
 
+	public void setKey(Object key) {
+		isInIterable = true;
+		this.key = key;
+	}
+
 	@Override
 	public String toString() {
-		return "NodeImpl{" +
-				"name='" + name + '\'' +
-				", isInIterable=" + isInIterable +
-				", index=" + index +
-				", key=" + key +
-				'}';
+		StringBuilder builder = new StringBuilder( name );
+		if ( isInIterable ) {
+			builder.append( INDEX_OPEN );
+			if ( getIndex() != null ) {
+				builder.append( getIndex() );
+			}
+			else if ( getKey() != null ) {
+				builder.append( getKey() );
+			}
+			builder.append( INDEX_CLOSE );
+		}
+		return builder.toString();
 	}
 
 	@Override

Modified: 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	2009-06-23 12:57:02 UTC (rev 16901)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/PathImpl.java	2009-06-23 12:59:27 UTC (rev 16902)
@@ -27,30 +27,35 @@
  */
 public class PathImpl implements Path {
 
-	public static final String PROPERTY_PATH_SEPERATOR = ".";
+	private static final String PROPERTY_PATH_SEPERATOR = ".";
+	private static final String INDEX_OPEN = "[";
+	private static final String INDEX_CLOSE = "]";
 
+	private static final Node ROOT_NODE = new NodeImpl( ( String ) null );
+
 	private final List<Node> nodeList;
 
 	public PathImpl() {
 		nodeList = new ArrayList<Node>();
-		Node root = new NodeImpl( null );
-		nodeList.add( root );
+		nodeList.add( ROOT_NODE );
 	}
 
 	public PathImpl(PathImpl path) {
-		this();
+		this.nodeList = new ArrayList<Node>();
 		Iterator<Node> iter = path.iterator();
-		while(iter.hasNext()) {
-			Node node = iter.next();
-			nodeList.add(node);
+		while ( iter.hasNext() ) {
+			nodeList.add( new NodeImpl( iter.next() ) );
 		}
 	}
 
-	public PathImpl(List<Node> nodeList) {
-		this.nodeList = nodeList;
+	private PathImpl(List<Node> nodeList) {
+		this.nodeList = new ArrayList<Node>();
+		for ( Node node : nodeList ) {
+			this.nodeList.add( new NodeImpl( node ) );
+		}
 	}
 
-	public Path getParentPath() {
+	public Path getPathWithoutLeafNode() {
 		List<Node> nodes = new ArrayList<Node>( nodeList );
 		if ( nodes.size() > 1 ) {
 			nodes.remove( nodes.size() - 1 );
@@ -62,48 +67,56 @@
 		nodeList.add( node );
 	}
 
-	public Node removeLast() {
-		if ( nodeList.size() < 1 ) {
-			throw new IllegalStateException();
+	public Node removeLeafNode() {
+		if ( nodeList.size() == 0 ) {
+			throw new IllegalStateException( "No nodes in path!" );
 		}
+		if ( nodeList.size() == 1 ) {
+			throw new IllegalStateException( "Root node cannot be removed!" );
+		}
 		return nodeList.remove( nodeList.size() - 1 );
 	}
 
-	public Node getLast() {
-		if ( nodeList.size() < 1 ) {
-			throw new IllegalStateException();
+	public NodeImpl getLeafNode() {
+		if ( nodeList.size() == 0 ) {
+			throw new IllegalStateException( "No nodes in path!" );
 		}
-		return nodeList.get( nodeList.size() - 1 );
+		return ( NodeImpl ) nodeList.get( nodeList.size() - 1 );
 	}
 
 	public Iterator<Path.Node> iterator() {
 		return nodeList.iterator();
 	}
 
+	public boolean isSubPathOf(Path path) {
+		Iterator<Node> pathIter = path.iterator();
+		Iterator<Node> thisIter = iterator();
+		while ( pathIter.hasNext() ) {
+			Node pathNode = pathIter.next();
+			if ( !thisIter.hasNext() ) {
+				return false;
+			}
+			Node thisNode = thisIter.next();
+			if ( !thisNode.equals( pathNode ) ) {
+				return false;
+			}
+		}
+		return true;
+	}
+
 	@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 );
-
-				}
+			if ( ROOT_NODE.equals( node ) ) {
+				continue;
 			}
+			builder.append( node.toString() );
+			if ( iter.hasNext() ) {
+				builder.append( PROPERTY_PATH_SEPERATOR );
+			}
 		}
 		return builder.toString();
 	}

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-23 12:57:02 UTC (rev 16901)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java	2009-06-23 12:59:27 UTC (rev 16902)
@@ -234,7 +234,7 @@
 	 */
 	private <T> void validateConstraints(ExecutionContext<T> executionContext) {
 		//casting rely on the fact that root object is at the top of the stack
-		@SuppressWarnings(" unchecked")
+		@SuppressWarnings("unchecked")
 		BeanMetaData<T> beanMetaData = getBeanMetaData( ( Class<T> ) executionContext.peekCurrentBeanType() );
 		if ( executionContext.getCurrentGroup().getName().equals( Default.class.getName() ) ) {
 			List<Class<?>> defaultGroupSequence = beanMetaData.getDefaultGroupSequence();




More information about the hibernate-commits mailing list