Coverage Report - org.apache.onami.configuration.variables.Tree
 
Classes in this File Line Coverage Branch Coverage Complexity
Tree
66%
39/59
59%
19/32
2
 
 1  
 package org.apache.onami.configuration.variables;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *   http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import java.util.ArrayList;
 23  
 import java.util.List;
 24  
 
 25  
 /**
 26  
  * Basic implementation of a tree.
 27  
  *
 28  
  * @param <T>
 29  
  */
 30  
 final class Tree<T>
 31  
 {
 32  
 
 33  
     /** Current tree node data */
 34  
     private T data;
 35  
 
 36  
     /** Parent node */
 37  89372
     private Tree<T> parent = null;
 38  
 
 39  
     /** Children */
 40  89372
     private List<Tree<T>> children = new ArrayList<Tree<T>>();
 41  
 
 42  
     /**
 43  
      * Default constructor
 44  
      *
 45  
      * @param data
 46  
      */
 47  
     public Tree( T data )
 48  89372
     {
 49  89372
         this.data = data;
 50  89372
     }
 51  
 
 52  
     /**
 53  
      * @return True if parent is not null
 54  
      */
 55  
     public boolean isRoot()
 56  
     {
 57  313382
         return parent == null;
 58  
     }
 59  
 
 60  
     /**
 61  
      * @return True if no children
 62  
      */
 63  
     public boolean isLeaf()
 64  
     {
 65  0
         return children.isEmpty();
 66  
     }
 67  
 
 68  
     /**
 69  
      * Add a new leaf to this tree
 70  
      *
 71  
      * @param child
 72  
      * @return Tree node of the newly added leaf
 73  
      */
 74  
     public Tree<T> addLeaf( T child )
 75  
     {
 76  73566
         Tree<T> leaf = new Tree<T>( child );
 77  73566
         leaf.parent = this;
 78  73566
         children.add( leaf );
 79  73566
         return leaf;
 80  
     }
 81  
 
 82  
     /**
 83  
      * @return Parent node, or null if this node is root
 84  
      */
 85  
     public Tree<T> getParent()
 86  
     {
 87  269238
         return parent;
 88  
     }
 89  
 
 90  
     /**
 91  
      * Remove this tree from its parent, if any.
 92  
      */
 93  
     public void removeFromParent()
 94  
     {
 95  0
         if ( !isRoot() )
 96  
         {
 97  0
             getParent().removeSubtree( this );
 98  
         }
 99  0
     }
 100  
 
 101  
     /**
 102  
      * Remove given subtree
 103  
      *
 104  
      * @param subtree
 105  
      */
 106  
     public void removeSubtree( Tree<T> subtree )
 107  
     {
 108  0
         if ( children.remove( subtree ) )
 109  
         {
 110  0
             subtree.parent = null;
 111  
         }
 112  0
     }
 113  
 
 114  
     /**
 115  
      * @return Node data
 116  
      */
 117  
     public T getData()
 118  
     {
 119  126
         return data;
 120  
     }
 121  
 
 122  
     /**
 123  
      *
 124  
      * @return Node depth
 125  
      */
 126  
     public int getDepth()
 127  
     {
 128  0
         int depth = 0;
 129  0
         Tree<T> curr = parent;
 130  0
         while ( curr != null )
 131  
         {
 132  0
             curr = curr.parent;
 133  0
             depth++;
 134  
         }
 135  0
         return depth;
 136  
     }
 137  
 
 138  
     /**
 139  
      * @return Subtrees
 140  
      */
 141  
     public List<Tree<T>> getChildren()
 142  
     {
 143  126
         return children;
 144  
     }
 145  
 
 146  
     /**
 147  
      * Add a subtree, provided tree is not modified.
 148  
      *
 149  
      * @param subtree
 150  
      * @return subtree copy added
 151  
      */
 152  
     public Tree<T> addSubtree( Tree<T> subtree )
 153  
     {
 154  0
         Tree<T> copy = addLeaf( subtree.data );
 155  0
         copy.children = new ArrayList<Tree<T>>( subtree.children );
 156  0
         return copy;
 157  
     }
 158  
 
 159  
     /**
 160  
      * @param element
 161  
      * @return true if element is contained in this node subtrees.
 162  
      */
 163  
     public boolean inSubtrees( T element )
 164  
     {
 165  0
         for ( Tree<T> child : getChildren() )
 166  
         {
 167  0
             if ( child.isElement( element ) || child.inSubtrees( element ) )
 168  
             {
 169  0
                 return true;
 170  
             }
 171  
         }
 172  0
         return false;
 173  
     }
 174  
 
 175  
     /**
 176  
      * @param element
 177  
      * @return True if element is equal to this node data.
 178  
      */
 179  
     public boolean isElement( T element )
 180  
     {
 181  134600
         return ( data.equals( element ) );
 182  
     }
 183  
 
 184  
     /**
 185  
      *
 186  
      * @param element
 187  
      * @return true if element is is in the ancestors of this node
 188  
      */
 189  
     public boolean inAncestors( T element )
 190  
     {
 191  223954
         if ( !isRoot() )
 192  
         {
 193  134600
             return getParent().isElement( element ) || getParent().inAncestors( element );
 194  
         }
 195  89354
         return false;
 196  
     }
 197  
 
 198  
     /**
 199  
      * @return Root node, this if current node is root
 200  
      */
 201  
     public Tree<T> getRoot()
 202  
     {
 203  74
         if ( isRoot() )
 204  
         {
 205  18
             return this;
 206  
         }
 207  56
         return getParent().getRoot();
 208  
     }
 209  
 
 210  
     @Override
 211  
     public String toString()
 212  
     {
 213  18
         StringBuilder buffer = new StringBuilder();
 214  18
         toString( buffer, 0 );
 215  18
         return buffer.toString();
 216  
     }
 217  
 
 218  
     private void toString( StringBuilder buffer, int level )
 219  
     {
 220  
         // Create proper indent
 221  
         // Search for next cousins in each level
 222  126
         StringBuilder indent = new StringBuilder();
 223  
         Tree<T> prev;
 224  126
         Tree<T> curr = this;
 225  378
         for ( int i = level - 1; i >= 0; i-- )
 226  
         {
 227  252
             prev = curr;
 228  252
             curr = prev.parent;
 229  252
             if ( i == level - 1 )
 230  
             {
 231  108
                 indent.append( " _|" );
 232  
             }
 233  
             else
 234  
             {
 235  144
                 indent.append( "  " );
 236  
 
 237  144
                 if ( i < level && curr.children.indexOf( prev ) < curr.children.size() - 1 )
 238  
                 {
 239  4
                     indent.append( "|" );
 240  
                 }
 241  
                 else
 242  
                 {
 243  140
                     indent.append( " " );
 244  
                 }
 245  
             }
 246  
         }
 247  126
         buffer.append( indent.reverse() );
 248  
 
 249  
         // Print data
 250  126
         buffer.append( getData() ).append( "\n" );
 251  
 
 252  
         // Print subtrees
 253  126
         for ( Tree<T> child : getChildren() )
 254  
         {
 255  108
             child.toString( buffer, level + 1 );
 256  
         }
 257  126
     }
 258  
 
 259  
 }