using System.Collections; using System.Collections.Generic; namespace Rokojori { public abstract class TreeWalker where N:class { public abstract N Parent( N node ); public abstract N ChildAt( N node, int index ); public abstract int NumChildren( N node ); public bool HasChildren( N node ) { return NumChildren( node ) > 0; } public bool HasParent( N node ) { return Parent( node ) != null; } public int ChildIndexOf( N node ) { var p = Parent( node ); if ( p == null ) { return -1; } var numKids = NumChildren( p ); for ( var i = 0; i= NumChildren( p ) ) { return null; } return ChildAt( p, index ); } public N NextSibling( N node ) { var index = ChildIndexOf( node ); return SiblingAt( node, index+1 ); } public N PreviousSibling( N node ) { var index = ChildIndexOf( node ); return SiblingAt( node, index-1 ); } public bool HasSiblingAt( N node, int index ) { var p = Parent( node ); if ( p == null || index<0 || index >= NumChildren( p ) ) { return false; } return true; } public N FirstChild( N node ) { return NumChildren( node )<=0?null:ChildAt( node, 0 ); } public N LastChild( N node ) { var num = NumChildren( node ); return num <= 0 ? null : ChildAt( node, num - 1 ); } public N NextNode( N node ) { if ( HasChildren( node ) ) { return FirstChild( node ); } var next = NextSibling( node ); if ( next != null ) { return next; } var parent = Parent( node ); while ( parent != null ) { var n = NextSibling( parent ); if ( n != null ) { return n; } parent = Parent( parent ); } return null; } public N PreviousNode( N node ) { var prev = PreviousSibling( node ); if ( prev != null ) { while ( HasChildren( prev ) ) { prev = LastChild( prev ); } return prev; } return Parent( node ); } public N RootParent( N node ) { node = Parent( node ); if ( node == null ) { return null; } while ( HasParent( node ) ) { node = Parent( node ); } return node; } public N LastGrandChild( N node ) { if ( HasChildren( node ) ) { node = LastChild( node ); while ( HasChildren( node ) ) { node = LastChild( node ); } return node; } return null; } public bool IsChildOf( N child, N parent ) { var p = Parent( child ); while ( p != null ) { if ( p == parent ) { return true; } p = Parent( p ); } return false; } public int NumParents( N node ) { var num = 0; var p = Parent( node ); while ( p != null ) { num++; p = Parent( p ); } return num; } public N LastOuterNode( N node ) { var its = 0; var max = 10000; while ( HasChildren( node ) ) { its++; if ( its > max ) { throw new System.Exception(); } node = LastChild( node ); } return node; } public N NextNonChild( N node ) { return NextNode( LastOuterNode( node ) ); } public N IterationEndOf( N node ) { return NextNonChild( node ); } public void Iterate( N node, System.Action callback, bool childrenOnly = false ) { var end = IterationEndOf( node ); var it = node; if ( childrenOnly ) { it = NextNode( it ); } while ( it != end ) { callback( it ); it = NextNode( it ); } } public N Find( N node, System.Predicate predicate, bool childrenOnly ) { var end = IterationEndOf( node ); var it = node; if ( childrenOnly ) { it = NextNode( it ); } while ( it != end ) { if ( predicate( it ) ) { return it; } it = NextNode( it ); } return null; } public void Filter( List list, N node, System.Predicate predicate, bool childrenOnly ) { System.Action addToList = ( N n ) => { if ( predicate( n ) ) { list.Add( n ); } }; Iterate( node, addToList, childrenOnly ); } public void FilterAndMap( List list, N node, System.Predicate predicate, System.Func mapper, bool childrenOnly ) { System.Action addToList = ( N n ) => { if ( predicate( n ) ) { list.Add( mapper( n ) ); } }; Iterate( node, addToList, childrenOnly ); } public void Map( List list, N node, System.Predicate predicate, System.Func mapper, bool childrenOnly ) { System.Action addToList = ( N n ) => { list.Add( mapper( n ) ); }; Iterate( node, addToList, childrenOnly ); } } }