77import java .io .Serializable ;
88import java .lang .invoke .MethodHandles ;
99import java .util .Arrays ;
10+ import java .util .Iterator ;
11+ import java .util .LinkedList ;
1012import java .util .List ;
1113import java .util .Map ;
1214
3537 */
3638public class NodeImpl
3739 implements Path .PropertyNode , Path .MethodNode , Path .ConstructorNode , Path .BeanNode , Path .ParameterNode , Path .ReturnValueNode , Path .CrossParameterNode , Path .ContainerElementNode ,
38- org .hibernate .validator .path .PropertyNode , org .hibernate .validator .path .ContainerElementNode , Serializable {
40+ org .hibernate .validator .path .PropertyNode , org .hibernate .validator .path .ContainerElementNode , Serializable , Iterable < Path . Node > {
3941 private static final long serialVersionUID = 2075466571633860499L ;
4042 private static final Class <?>[] EMPTY_CLASS_ARRAY = new Class <?>[] { };
4143
@@ -55,6 +57,8 @@ public class NodeImpl
5557
5658 private final String name ;
5759 private final NodeImpl parent ;
60+ private final NodeImpl root ;
61+ private final int size ;
5862 private final boolean isIterable ;
5963 private final Integer index ;
6064 private final Object key ;
@@ -70,10 +74,14 @@ public class NodeImpl
7074 private int hashCode = -1 ;
7175 private String asString ;
7276
73- private NodeImpl (String name , NodeImpl parent , boolean isIterable , Integer index , Object key , ElementKind kind , Class <?>[] parameterTypes ,
74- Integer parameterIndex , Object value , Class <?> containerClass , Integer typeArgumentIndex ) {
77+ private NodeImpl (
78+ String name , NodeImpl parent , boolean isIterable , Integer index , Object key , ElementKind kind , Class <?>[] parameterTypes ,
79+ Integer parameterIndex , Object value , Class <?> containerClass , Integer typeArgumentIndex
80+ ) {
7581 this .name = name ;
7682 this .parent = parent ;
83+ this .root = parent == null ? this : parent .root ;
84+ this .size = ( parent == null ? 0 : parent .size ) + 1 ;
7785 this .index = index ;
7886 this .key = key ;
7987 this .value = value ;
@@ -525,4 +533,92 @@ else if ( !Arrays.equals( parameterTypes, other.parameterTypes ) ) {
525533 }
526534 return true ;
527535 }
536+
537+ boolean isRootPath () {
538+ // .size() == 1 && nodeList.get( 0 ).getName() == null
539+ return parent == null && name == null ;
540+ }
541+
542+ @ Override
543+ public Iterator <Path .Node > iterator () {
544+ if ( parent == null ) {
545+ return List .of ( (Path .Node ) this ).iterator ();
546+ }
547+ List <Path .Node > result = new LinkedList <>();
548+ NodeImpl curr = this ;
549+ while ( !curr .isRootPath () ) {
550+ result .add ( 0 , curr );
551+ curr = curr .parent ;
552+ }
553+ return result .iterator ();
554+ }
555+
556+ boolean isSubPathOf (NodeImpl other ) {
557+ if ( this .size > other .size ) {
558+ return false ;
559+ }
560+ NodeImpl curr = this ;
561+ NodeImpl otherCurr = other ;
562+ while ( otherCurr != null && !otherCurr .equals ( this ) ) {
563+ otherCurr = otherCurr .parent ;
564+ }
565+ if ( otherCurr == null ) {
566+ return false ;
567+ }
568+ while ( !curr .isRootPath () && !otherCurr .isRootPath () ) {
569+ if ( !curr .equals ( otherCurr ) ) {
570+ return false ;
571+ }
572+ curr = curr .parent ;
573+ otherCurr = otherCurr .parent ;
574+ }
575+
576+ return curr .isRootPath ();
577+ }
578+
579+ boolean isSubPathOrContains (NodeImpl other ) {
580+ NodeImpl curr ;
581+ NodeImpl otherCurr ;
582+ if ( this .size > other .size ) {
583+ curr = other ;
584+ otherCurr = this ;
585+ }
586+ else {
587+ curr = this ;
588+ otherCurr = other ;
589+ }
590+
591+ while ( otherCurr != null && !otherCurr .equals ( curr ) ) {
592+ otherCurr = otherCurr .parent ;
593+ }
594+ if ( otherCurr == null ) {
595+ return false ;
596+ }
597+ while ( !curr .isRootPath () && !otherCurr .isRootPath () ) {
598+ if ( !curr .equals ( otherCurr ) ) {
599+ return false ;
600+ }
601+ curr = curr .parent ;
602+ otherCurr = otherCurr .parent ;
603+ }
604+
605+ return curr .isRootPath () && otherCurr .isRootPath ();
606+ }
607+
608+ boolean samePath (NodeImpl other ) {
609+ if ( this .size != other .size ) {
610+ return false ;
611+ }
612+ NodeImpl curr = this ;
613+ NodeImpl otherCurr = other ;
614+ while ( curr != null && otherCurr != null ) {
615+ if ( !curr .equals ( otherCurr ) ) {
616+ return false ;
617+ }
618+ otherCurr = otherCurr .parent ;
619+ curr = curr .parent ;
620+ }
621+
622+ return curr == null && otherCurr == null ;
623+ }
528624}
0 commit comments