Coverage report

  %line %branch
net.sf.infrared.base.util.TreeNode
85% 
96% 

 1  
 /* 
 2  
  * Copyright 2005 Tavant Technologies and Contributors
 3  
  * 
 4  
  * Licensed under the Apache License, Version 2.0 (the "License")
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *     http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  * 
 16  
  *
 17  
  *
 18  
  * Original Author:  kamal.govindraj (Tavant Technologies)
 19  
  * Contributor(s):   -;
 20  
  *
 21  
  */
 22  
 package net.sf.infrared.base.util;
 23  
 
 24  
 import net.sf.infrared.base.model.AggregateExecutionTime;
 25  
 
 26  
 import org.apache.log4j.Logger;
 27  
 
 28  
 import java.io.Serializable;
 29  
 import java.util.ArrayList;
 30  
 import java.util.Collections;
 31  
 import java.util.Iterator;
 32  
 import java.util.List;
 33  
 
 34  
 /**
 35  
  * Implementation of a TreeNode that represents a single node in a Tree.
 36  
  * 
 37  
  * @author kamal.govindraj
 38  
  */
 39  
 public class TreeNode implements Serializable, Cloneable {
 40  12
     private static final Logger log = LoggingFactory.getLogger(TreeNode.class);
 41  
     
 42  224
     private Object value = null;
 43  
 
 44  224
     private TreeNode parentNode = null;
 45  
 
 46  224
     private List childNodes = new ArrayList();
 47  
 
 48  
     // Indicates the depth/level at which the node appears in a
 49  
     // tree. Will only be set when the Node is part of a tree
 50  224
     private int depth = -1;
 51  
 
 52  
     // Indicates the postion the node occupies in the children
 53  
     // list of the parent node. Will only be set when the Node is part
 54  
     // of a tree.
 55  224
     private int position = -1;
 56  
 
 57  
     /**
 58  
      * Default constructor - required for handling mapping to XML
 59  
      */
 60  0
     public TreeNode() {
 61  
 
 62  0
     }
 63  
     
 64  
     /**
 65  
      * Contruct a new TreeNode.
 66  
      * 
 67  
      * @param value -
 68  
      *            value contained in this node
 69  
      */
 70  224
     private TreeNode(Object value) {
 71  224
         this.value = value;
 72  224
     }
 73  
 
 74  
     /**
 75  
      * Factory method to create tree nodes.
 76  
      * 
 77  
      * @param value
 78  
      * @return a new tree node object
 79  
      */
 80  
     public static TreeNode createTreeNode(Object value) {
 81  224
         return new TreeNode(value);
 82  
     }
 83  
 
 84  
     /**
 85  
      * Get the value associated with this TreeNode.
 86  
      * 
 87  
      * @return associated value
 88  
      */
 89  
     public Object getValue() {
 90  232
         return this.value;
 91  
     }
 92  
 
 93  
     /**
 94  
      * Return the list of child nodes. The returned list is a unmodifiyable copy
 95  
      * of the list of childnodes this TreeNode maintains.
 96  
      * 
 97  
      * @return returns list of TreeNodes
 98  
      */
 99  
     public List getChildren() {
 100  80
         return Collections.unmodifiableList(this.childNodes);
 101  
     }
 102  
 
 103  
     /**
 104  
      * Add a new child node to the end of the list.
 105  
      * 
 106  
      * @param child -
 107  
      *            child node shouldn't be null
 108  
      */
 109  
     public void addChild(TreeNode child) {
 110  155
         if (child == null) {
 111  1
             throw new IllegalArgumentException("Child node can't be null");
 112  
         }
 113  
 
 114  154
         if (child.getParent() != null) {
 115  1
             throw new IllegalArgumentException("Child node is already a part of some node");
 116  
         }
 117  
         // Set the parent node
 118  153
         this.childNodes.add(child);
 119  153
         child.setParent(this);
 120  153
         if (depth != -1) {
 121  99
             child.setDepth(depth + 1);
 122  
         }
 123  153
         child.setPostion(this.childNodes.size() - 1);
 124  153
     }
 125  
 
 126  
     public boolean removeChild(TreeNode child) {
 127  6
         if (child == null) {
 128  1
             throw new IllegalArgumentException("childnode can't be null");
 129  
         }
 130  5
         int index = this.childNodes.indexOf(child);
 131  5
         if (index != -1) {
 132  3
             childNodes.remove(index);
 133  3
             child.setParent(null);
 134  3
             child.setDepth(-1);
 135  3
             child.setPostion(-1);
 136  3
             adjustPosition(index);
 137  
         } else {
 138  2
             log.error("Child " + child + "not found in the list of children for node " + this);
 139  2
             return false;
 140  
         }
 141  3
         return true;
 142  
     }
 143  
 
 144  
     /**
 145  
      * This method is called when an child is removed to adjust the position
 146  
      * attribute of subsequent nodes
 147  
      * 
 148  
      * @param index
 149  
      */
 150  
     private void adjustPosition(int index) {
 151  3
         if (index < childNodes.size()) {
 152  1
             for (Iterator itr = childNodes.listIterator(); itr.hasNext();) {
 153  1
                 TreeNode node = (TreeNode) itr.next();
 154  1
                 node.setPostion(node.getPosition() - 1);
 155  
             }
 156  
         }
 157  3
     }
 158  
 
 159  
     /**
 160  
      * Set the parent for this node
 161  
      * 
 162  
      * @param parentNode
 163  
      */
 164  
     public void setParent(TreeNode parentNode) {
 165  156
         this.parentNode = parentNode;
 166  156
     }
 167  
 
 168  
     /**
 169  
      * Returns the parent node
 170  
      * 
 171  
      * @return parent node
 172  
      */
 173  
     public TreeNode getParent() {
 174  159
         return this.parentNode;
 175  
     }
 176  
 
 177  
     /**
 178  
      * traverse the tree (starting at this node) breadth first
 179  
      * 
 180  
      * @param visitor
 181  
      */
 182  
     public void traverseBreadthFirst(NodeVisitor visitor) {
 183  10
         for (Iterator itr = this.childNodes.iterator(); itr.hasNext();) {
 184  8
             visitor.visit((TreeNode) itr.next());
 185  
         }
 186  10
         if (this.childNodes.size() > 0) {
 187  4
             visitor.goingDown();
 188  4
             for (Iterator itr = this.childNodes.iterator(); itr.hasNext();) {
 189  8
                 ((TreeNode) itr.next()).traverseBreadthFirst(visitor);
 190  
             }
 191  4
             visitor.climbingUp();
 192  
         }
 193  10
     }
 194  
 
 195  
     public TreeNode find(Object value) {
 196  35
         for (Iterator itr = this.childNodes.iterator(); itr.hasNext();) {
 197  31
             TreeNode currNode = (TreeNode) itr.next();
 198  31
             if (currNode.getValue().equals(value)) {
 199  6
                 return currNode;
 200  
             }
 201  25
             TreeNode foundNode = currNode.find(value);
 202  25
             if (foundNode != null) {
 203  1
                 return foundNode;
 204  
             }
 205  
         }
 206  28
         return null;
 207  
     }
 208  
 
 209  
     /**
 210  
      * Returns the depth at which this node appears in a tree. Will return -1 if
 211  
      * the tree is not part of a tree
 212  
      * 
 213  
      * @return
 214  
      */
 215  
     public int getDepth() {
 216  32
         return this.depth;
 217  
     }
 218  
 
 219  
     /**
 220  
      * Returns the position the node occupies among the children of the parent
 221  
      * node. Will return -1 if the tree is not part of a tree
 222  
      * 
 223  
      * @return
 224  
      */
 225  
     public int getPosition() {
 226  13
         return this.position;
 227  
     }
 228  
 
 229  
     /**
 230  
      * Set the depth at which this node appears in a tree This is package scope
 231  
      * as it can be set only by the parent node and tree
 232  
      * 
 233  
      * @param depth
 234  
      */
 235  
     public void setDepth(int depth) {
 236  156
         this.depth = depth;
 237  
         // Adjust the depth of the children node
 238  156
         for (Iterator itr = childNodes.iterator(); itr.hasNext();) {
 239  3
             TreeNode childNode = (TreeNode) itr.next();
 240  3
             if (depth != -1) {
 241  2
                 childNode.setDepth(depth + 1);
 242  
             } else {
 243  1
                 childNode.setDepth(-1);
 244  
             }
 245  
         }
 246  156
     }
 247  
 
 248  
     /**
 249  
      * Set the position the node occupies among the children of the parent node.
 250  
      * Package scope as it can be set only by the parent node & Tree
 251  
      * 
 252  
      * @param position
 253  
      */
 254  
     void setPostion(int position) {
 255  207
         this.position = position;
 256  207
     }
 257  
 
 258  
     public void addChildren(List children) {
 259  0
         childNodes.addAll(children);
 260  0
     }
 261  
 
 262  
     public String toString() {
 263  11
         String str = "";
 264  
 
 265  19
         for (int i = 0; i < getDepth(); i++) {
 266  8
             str = str + "--";
 267  
         }
 268  
 
 269  11
         str = str + getValue().toString();
 270  
 
 271  11
         for (Iterator iterator = childNodes.iterator(); iterator.hasNext();) {
 272  6
             str = str + "\n";
 273  6
             TreeNode treeNode = (TreeNode) iterator.next();
 274  6
             str = str + treeNode.toString();
 275  
         }
 276  
 
 277  11
         return str;
 278  
     }
 279  
     
 280  
     /**
 281  
      * The method returns a clone of this tree node with the parent 
 282  
      * of the cloned node set to null.
 283  
      */
 284  
     public Object clone() {
 285  0
     	TreeNode clone = new TreeNode();
 286  0
     	clone.setDepth(this.depth);
 287  0
     	clone.setPostion(this.position);
 288  0
     	if(this.getValue() != null && class="keyword">this.getValue() instanceof AggregateExecutionTime)
 289  0
     		clone.setValue( ((AggregateExecutionTime) this.getValue()).clone());
 290  
     	else  //  The else clause is to accommodate for the dummy node which is a String.
 291  0
     		clone.setValue(this.getValue());
 292  
     	    	
 293  0
     	List children = this.getChildren();
 294  0
     	if(children != null && children.size() > 0) {
 295  0
     		for(Iterator itr = children.iterator();itr.hasNext();){
 296  0
     			TreeNode child = (TreeNode) itr.next();
 297  0
     			clone.addChild((TreeNode) child.clone());
 298  
     		}
 299  
     	}    
 300  0
     	return clone;
 301  
     }
 302  
     
 303  
 
 304  
     public void mergeAsChild(TreeNode node, Merger merger) {
 305  55
         TreeNode nodeToMergeOnto = null;        
 306  55
         for (Iterator i = this.childNodes.iterator(); i.hasNext();) {  
 307  39
             TreeNode childNode = (TreeNode) i.next();
 308  39
             if (merger.isMatching(childNode, node)) {
 309  13
                 nodeToMergeOnto = childNode;
 310  13
                 break;
 311  
             }
 312  
         }        
 313  55
         if (nodeToMergeOnto != null) {
 314  13
             merger.mergeValue(nodeToMergeOnto, node);
 315  
         } else {
 316  42
             nodeToMergeOnto = merger.createNewNode(node);
 317  42
             this.addChild(nodeToMergeOnto);
 318  
         }
 319  
         
 320  
         // @TODO: Clarity on what needs to be copied and what needs to be shared
 321  
         // Right now TreeNode instances are copied and the values are shared
 322  55
         for (Iterator i = node.childNodes.iterator(); i.hasNext(); ) {
 323  37
             TreeNode child = (TreeNode) i.next();
 324  37
             nodeToMergeOnto.mergeAsChild(child, merger);
 325  
         }
 326  55
     }
 327  
     
 328  
     // for the tests
 329  
     void setValue(Object value) {
 330  2
         this.value = value;
 331  2
     }
 332  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.