Skip to content

Commit

Permalink
[HV-1928] moves subPath check to PathImpl
Browse files Browse the repository at this point in the history
  • Loading branch information
Thomas T Strauss authored and thst71 committed Nov 11, 2023
1 parent 7a9f2f7 commit 998f7ce
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -453,4 +453,21 @@ private static boolean isValidJavaIdentifier(String identifier) {
}
return true;
}

public boolean isSubPathOrContains(PathImpl other) {

// prefetch contant return values
int oSize = other.nodeList.size();
// calling Math.min will reduce speed significantly
int mySize = nodeList.size() < oSize
? nodeList.size()
: oSize;

for ( int i = 0; i < mySize; i++ ) {
if ( !nodeList.get( i ).equals( other.nodeList.get( i ) ) ) {
return false;
}
}
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import java.util.Collections;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

Expand Down Expand Up @@ -344,44 +343,20 @@ private boolean isAlreadyValidatedForPath(Object value, PathImpl path) {
return false;
}

for ( PathImpl p : pathSet ) {
if ( pathsSharePrefix( p, path ) ) {
return true;
}
}

return false;
}

/**
* this method compares two PathImpl to decide if either one is a prefix of the other.
*
* @param p1 first Path
* @param p2 second Path
* @return true if p1 ⊃ p2 or p2 ⊃ p1
*/
private boolean pathsSharePrefix(PathImpl p1, PathImpl p2) {
// root path is a common prefix of any path != null
if ( p1.isRootPath() || p2.isRootPath() ) {
if ( path.isRootPath() ) {
return true;
}

// at this point, p1 and p2 will have at least one element in the iterator
Iterator<Path.Node> p1Iter = p1.iterator();
Iterator<Path.Node> p2Iter = p2.iterator();
while ( p1Iter.hasNext() ) {
Path.Node p1Node = p1Iter.next();
if ( !p2Iter.hasNext() ) {
// p1 ⊃ p2
// Since this isAlreadyValidatedForPath(..) is only applicable for an object that is about to be cascaded into,
// it means that the new path we are testing cannot be a root path; also since we are cascading into inner
// objects, i.e. going further from the object tree root, it means that the new path cannot be shorter than
// the ones we've already encountered.
for ( PathImpl p : pathSet ) {
if ( p.isSubPathOrContains( path ) ) {
return true;
}
Path.Node p2Node = p2Iter.next();
if ( !p1Node.equals( p2Node ) ) {
return false;
}
}
// p2 ⊃ p1
return true;
return false;
}

private boolean isAlreadyValidatedForCurrentGroup(Object value, Class<?> group) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
* @author Hardy Ferentschik
* @author Gunnar Morling
* @author Kevin Pollet &lt;kevin.pollet@serli.com&gt; (C) 2011 SERLI
* @author Thomas Strauß
*/
public class PathImplTest {

Expand Down Expand Up @@ -166,6 +167,28 @@ public void testEmptyString() {
assertTrue( path.iterator().hasNext() );
}

@Test
public void testIsSubPathOrContains() {
PathImpl rootPath = PathImpl.createPathFromString( "" );
PathImpl subPath = PathImpl.createPathFromString( "annotation" );
PathImpl middlePath = PathImpl.createPathFromString( "annotation.property" );
PathImpl middlePath2 = PathImpl.createPathFromString( "annotation.property[2]" );
PathImpl middlePath3 = PathImpl.createPathFromString( "annotation.property[3]" );
PathImpl fullPath3 = PathImpl.createPathFromString( "annotation.property[3].element" );
PathImpl fullPath4 = PathImpl.createPathFromString( "annotation.property[4].element" );

assertTrue( rootPath.isSubPathOrContains( middlePath ), "root path is in every path" );
assertTrue( middlePath.isSubPathOrContains( rootPath ), "every path contains the root path" );
assertTrue( subPath.isSubPathOrContains( middlePath ), "bean is subpath of its properties" );
assertTrue( middlePath.isSubPathOrContains( subPath ), "a property is an extension of its bean" );
assertTrue( subPath.isSubPathOrContains( fullPath3 ), "bean is subpath of its tree" );
assertTrue( subPath.isSubPathOrContains( fullPath4 ), "bean is subpath of its tree, for every array index" );
assertFalse( middlePath.isSubPathOrContains( fullPath3 ), "property is not a subpath of an array" );
assertFalse( middlePath3.isSubPathOrContains( fullPath3 ), "array property is not a subpath of a property of a bean in an array" );
assertFalse( middlePath2.isSubPathOrContains( fullPath3 ), "array element is not a subpath of another element's children" );
assertFalse( fullPath3.isSubPathOrContains( fullPath4 ), "different array elements are not subpaths of the other" );
}

@Test
public void testNonStringMapKey() {
Validator validator = ValidatorUtil.getValidator();
Expand Down

0 comments on commit 998f7ce

Please sign in to comment.