/** * Bean Validation TCK * * License: Apache License, Version 2.0 * See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>. */ package org.hibernate.beanvalidation.tck.util; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.ElementKind; import javax.validation.Path; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.fail; /** * Provides assertion methods for property paths. * * @author Gunnar Morling */ public class PathUtil { /** * Creates a path expectation which can be configured using the offered * fluent API methods. * * @return An empty path expection. */ public static PathExpectation pathWith() { return new PathExpectation(); } /** * Asserts that the given violations only contain the given expected * property paths. * * @param actualViolations A set of constraint violations. * @param paths One or more expected property paths. */ public static void assertViolationsContainOnlyPaths(Set<? extends ConstraintViolation<?>> actualViolations, PathExpectation... paths) { assertNotNull( actualViolations ); assertNotNull( paths ); List<PathExpectation> expectedPaths = Arrays.asList( paths ); List<PathExpectation> actualPaths = new ArrayList<PathExpectation>(); for ( ConstraintViolation<?> violation : actualViolations ) { actualPaths.add( new PathExpectation( violation.getPropertyPath() ) ); } List<PathExpectation> actualPathsTmp = new ArrayList<PathExpectation>( actualPaths ); actualPathsTmp.removeAll( expectedPaths ); if ( !actualPathsTmp.isEmpty() ) { fail( String.format( "Found unexpected path(s): %s. Expected: %s", actualPathsTmp, expectedPaths ) ); } List<PathExpectation> expectedPathsTmp = new ArrayList<PathExpectation>( expectedPaths ); expectedPathsTmp.removeAll( actualPaths ); if ( !expectedPathsTmp.isEmpty() ) { fail( String.format( "Missing expected path(s) %s. Actual paths: %s", expectedPathsTmp, actualPaths ) ); } } public static class PathExpectation { private final List<NodeExpectation> nodes = new ArrayList<NodeExpectation>(); private PathExpectation() { } private PathExpectation(Path propertyPath) { for ( Path.Node node : propertyPath ) { Integer parameterIndex = null; if ( node.getKind() == ElementKind.PARAMETER ) { parameterIndex = node.as( Path.ParameterNode.class ).getParameterIndex(); } nodes.add( new NodeExpectation( node.getName(), node.getKind(), node.isInIterable(), node.getKey(), node.getIndex(), parameterIndex ) ); } } public PathExpectation property(String name) { nodes.add( new NodeExpectation( name, ElementKind.PROPERTY, false, null, null, null ) ); return this; } public PathExpectation property(String name, boolean inIterable, Object key, Integer index) { nodes.add( new NodeExpectation( name, ElementKind.PROPERTY, inIterable, key, index, null ) ); return this; } public PathExpectation bean() { nodes.add( new NodeExpectation( null, ElementKind.BEAN, false, null, null, null ) ); return this; } public PathExpectation bean(boolean inIterable, Object key, Integer index) { nodes.add( new NodeExpectation( null, ElementKind.BEAN, inIterable, key, index, null ) ); return this; } public PathExpectation method(String name) { nodes.add( new NodeExpectation( name, ElementKind.METHOD, false, null, null, null ) ); return this; } public PathExpectation parameter(String name, int index) { nodes.add( new NodeExpectation( name, ElementKind.PARAMETER, false, null, null, index ) ); return this; } public PathExpectation crossParameter() { nodes.add( new NodeExpectation( TestUtil.CROSS_PARAMETER_NODE_NAME, ElementKind.CROSS_PARAMETER, false, null, null, null ) ); return this; } @Override public String toString() { String lineBreak = System.getProperty( "line.separator" ); StringBuilder asString = new StringBuilder( lineBreak + "PathExpectation(" + lineBreak ); for ( NodeExpectation node : nodes ) { asString.append( " " ).append( node ).append( lineBreak ); } return asString.append( ")" ).toString(); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ( ( nodes == null ) ? 0 : nodes.hashCode() ); return result; } @Override public boolean equals(Object obj) { if ( this == obj ) { return true; } if ( obj == null ) { return false; } if ( getClass() != obj.getClass() ) { return false; } PathExpectation other = (PathExpectation) obj; if ( nodes == null ) { if ( other.nodes != null ) { return false; } } else if ( !nodes.equals( other.nodes ) ) { return false; } return true; } } private static class NodeExpectation { private final String name; private final ElementKind kind; private final boolean inIterable; private final Object key; private final Integer index; private final Integer parameterIndex; private NodeExpectation(String name, ElementKind kind, boolean inIterable, Object key, Integer index, Integer parameterIndex) { this.name = name; this.kind = kind; this.inIterable = inIterable; this.key = key; this.index = index; this.parameterIndex = parameterIndex; } @Override public String toString() { return "NodeExpectation(" + name + ", " + kind + ", " + inIterable + ", " + key + ", " + index + ", " + parameterIndex + ")"; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ( inIterable ? 1231 : 1237 ); result = prime * result + ( ( index == null ) ? 0 : index.hashCode() ); result = prime * result + ( ( key == null ) ? 0 : key.hashCode() ); result = prime * result + ( ( kind == null ) ? 0 : kind.hashCode() ); result = prime * result + ( ( name == null ) ? 0 : name.hashCode() ); result = prime * result + ( ( parameterIndex == null ) ? 0 : parameterIndex.hashCode() ); return result; } @Override public boolean equals(Object obj) { if ( this == obj ) { return true; } if ( obj == null ) { return false; } if ( getClass() != obj.getClass() ) { return false; } NodeExpectation other = (NodeExpectation) obj; if ( inIterable != other.inIterable ) { return false; } if ( index == null ) { if ( other.index != null ) { return false; } } else if ( !index.equals( other.index ) ) { return false; } if ( key == null ) { if ( other.key != null ) { return false; } } else if ( !key.equals( other.key ) ) { return false; } if ( kind != other.kind ) { return false; } if ( name == null ) { if ( other.name != null ) { return false; } } else if ( !name.equals( other.name ) ) { return false; } if ( parameterIndex == null ) { if ( other.parameterIndex != null ) { return false; } } else if ( !parameterIndex.equals( other.parameterIndex ) ) { return false; } return true; } } }