Coverage Report - th.co.edge.jseq.ActivationList
 
Classes in this File Line Coverage Branch Coverage Complexity
ActivationList
94%
51/54
95%
19/20
0
ActivationList$Filter
N/A
N/A
0
 
 1  
 /*
 2  
  * Copyright (c) 2003-2008, by Henrik Arro and Contributors
 3  
  *
 4  
  * This file is part of JSeq, a tool to automatically create
 5  
  * sequence diagrams by tracing program execution.
 6  
  *
 7  
  * See <http://jseq.sourceforge.net> for more information.
 8  
  *
 9  
  * JSeq is free software: you can redistribute it and/or modify
 10  
  * it under the terms of the GNU Lesser General Public License as
 11  
  * published by the Free Software Foundation, either version 3 of
 12  
  * the License, or (at your option) any later version.
 13  
  *
 14  
  * JSeq is distributed in the hope that it will be useful,
 15  
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16  
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 17  
  * GNU Lesser General Public License for more details.
 18  
  *
 19  
  * You should have received a copy of the GNU Lesser General Public License
 20  
  * along with JSeq. If not, see <http://www.gnu.org/licenses/>.
 21  
  */
 22  
 
 23  
 package th.co.edge.jseq;
 24  
 
 25  
 import java.util.Iterator;
 26  
 import java.util.LinkedList;
 27  
 import java.util.List;
 28  
 
 29  
 /**
 30  
  * An <code>ActivationList</code> holds a number of <code>Activation</code>
 31  
  * instances, representing a number of method calls. This can be used to hold
 32  
  * nested method call made by a method, or all root activation, i.e., methods
 33  
  * that are not called by one of the traced methods but "magically" from outside
 34  
  * the sequence diagram.
 35  
  */
 36  146
 public class ActivationList implements java.io.Serializable,
 37  
         Iterable<Activation> {
 38  
     private static final long serialVersionUID = 5359418912455509769L;
 39  
 
 40  146
     private List<Activation> activations = new LinkedList<Activation>();
 41  
 
 42  
     /**
 43  
      * Adds an <code>Activation</code> to this list.
 44  
      *
 45  
      * @param activation
 46  
      *            the <code>Activation</code> to add
 47  
      */
 48  
     public void add(Activation activation) {
 49  107
         activations.add(activation);
 50  107
     }
 51  
 
 52  
     /**
 53  
      * Adds all <code>Activation</code>s from another
 54  
      * <code>ActivationList</code> to this list.
 55  
      *
 56  
      * @param activationList
 57  
      *            the <code>ActivationList</code> whose
 58  
      *            <code>Activation</code>s will be added to this list
 59  
      */
 60  
     public void addAll(ActivationList activationList) {
 61  3
         activations.addAll(activationList.activations);
 62  3
     }
 63  
 
 64  
     /**
 65  
      * Removes an <code>Activation</code> at a certain position in this list.
 66  
      *
 67  
      * @param index
 68  
      *            the position in this list to remove
 69  
      *
 70  
      * @return the removed <code>Activation</code>
 71  
      */
 72  
     public Activation remove(int index) {
 73  4
         return activations.remove(index);
 74  
     }
 75  
 
 76  
     /**
 77  
      * Returns the <code>Activation</code> at a certain position in this list.
 78  
      *
 79  
      * @param index
 80  
      *            the position in this list to return
 81  
      *
 82  
      * @return the <code>Activation</code> at position <code>index</code> in
 83  
      *         this list
 84  
      */
 85  
     public Activation get(int index) {
 86  22
         return activations.get(index);
 87  
     }
 88  
 
 89  
     /**
 90  
      * Returns the size of this <code>ActivationList</code>.
 91  
      *
 92  
      * @return the size of this list
 93  
      */
 94  
     public int size() {
 95  33
         return activations.size();
 96  
     }
 97  
 
 98  
     /**
 99  
      * Returns an iterator that iterates over the <code>Activation</code>s in
 100  
      * this list, in the order they were added.
 101  
      *
 102  
      * @return an iterator that iterates over the <code>Activation</code>s in
 103  
      *         this list
 104  
      */
 105  
     public Iterator<Activation> iterator() {
 106  85
         return activations.iterator();
 107  
     }
 108  
 
 109  
     /**
 110  
      * Returns a new <code>ActivationList</code> containing only the
 111  
      * <code>Activation</code>s for which the given filter returns
 112  
      * <code>true</code>. The filtering is also done recursively on nested
 113  
      * <code>Activation</code>s.
 114  
      *
 115  
      * @param filter
 116  
      *            the <code>Filter</code> instance used to determine which
 117  
      *            <code>Activation</code>s should be included
 118  
      *
 119  
      * @return a new <code>ActivationList</code> containing only the
 120  
      *         <code>Activation</code>s that <code>filter</code> accepts
 121  
      */
 122  
     public ActivationList filter(Filter filter) {
 123  5
         ActivationList filteredList = new ActivationList();
 124  5
         for (Activation activation : activations) {
 125  10
             if (filter.accept(activation)) {
 126  4
                 Activation newActivation = new Activation(null, activation
 127  
                         .getClassName(), activation.getMethod(), -1);
 128  4
                 ActivationList nestedActivations = activation
 129  
                         .getNestedActivations().filter(filter);
 130  4
                 newActivation.setNestedActivations(nestedActivations);
 131  4
                 nestedActivations.setParent(newActivation);
 132  4
                 filteredList.add(newActivation);
 133  10
             }
 134  
         }
 135  5
         return filteredList;
 136  
     }
 137  
 
 138  
     /**
 139  
      * Returns a new <code>ActivationList</code> where the activations and
 140  
      * nested activations have been pruned, so as to start with an activation
 141  
      * that is accepted by the given filter. In other words, this method "lifts"
 142  
      * activations accepted by the filter to be root activations.
 143  
      *
 144  
      * <p>
 145  
      * For example, given the following activations:
 146  
      *
 147  
      * <pre>
 148  
      *   m
 149  
      *     m1
 150  
      *       q1
 151  
      *       q2
 152  
      *     m2
 153  
      *   p
 154  
      *     m1
 155  
      *       q3
 156  
      *     p2
 157  
      * </pre>
 158  
      *
 159  
      * and a filter that only accepts methods named "m1", the following list
 160  
      * would be returned:
 161  
      *
 162  
      * <pre>
 163  
      *   m1
 164  
      *     q1
 165  
      *     q2
 166  
      *   m1
 167  
      *     q3
 168  
      * </pre>
 169  
      *
 170  
      * @param filter
 171  
      *            the <code>Filter</code> instance used to determine which
 172  
      *            <code>Activation</code>s should be used as root activations
 173  
      *
 174  
      * @return a new <code>ActivationList</code> with <code>Activation</code>s
 175  
      *         accepted by <code>filter</code> as root activations
 176  
      */
 177  
     public ActivationList find(Filter filter) {
 178  4
         ActivationList foundActivations = new ActivationList();
 179  4
         for (Activation activation : activations) {
 180  4
             if (filter.accept(activation)) {
 181  1
                 foundActivations.add(activation.copy(null));
 182  
             } else {
 183  3
                 foundActivations.addAll(activation.getNestedActivations().find(
 184  
                         filter));
 185  
             }
 186  
         }
 187  4
         return foundActivations;
 188  
     }
 189  
 
 190  
     /**
 191  
      * Sets the parent <code>Activation</code> of all <code>Activation</code>s
 192  
      * in this list to the given value.
 193  
      *
 194  
      * @param parent
 195  
      *            the new parent activation
 196  
      */
 197  
     public void setParent(Activation parent) {
 198  10
         for (Activation activation : activations) {
 199  8
             activation.setParent(parent);
 200  
         }
 201  10
     }
 202  
 
 203  
     /**
 204  
      * Returns an <code>ActivationList</code> where all consecutive identical
 205  
      * <code>Activation</code>s but the first have been removed, and its
 206  
      * <code>numRepetitions</code> property increased accordingly.
 207  
      *
 208  
      * @return an <code>ActivationList</code> with no repeated identical
 209  
      *         <code>Activation</code>s
 210  
      */
 211  
     public ActivationList collapseRepetitions() {
 212  7
         ActivationList newList = copy();
 213  13
         for (int i = 0; i < newList.size(); i++) {
 214  6
             Activation activation = newList.get(i);
 215  10
             while (newList.size() > i + 1) {
 216  7
                 Activation nextActivation = newList.get(i + 1);
 217  7
                 if (activation.equals(nextActivation)) {
 218  4
                     newList.remove(i + 1);
 219  4
                     activation.increaseNumRepetitions();
 220  
                 } else {
 221  
                     break;
 222  
                 }
 223  4
             }
 224  6
             ActivationList nestedActivations = activation
 225  
                     .getNestedActivations().collapseRepetitions();
 226  6
             nestedActivations.setParent(activation);
 227  6
             activation.setNestedActivations(nestedActivations);
 228  
         }
 229  7
         return newList;
 230  
     }
 231  
 
 232  
     /**
 233  
      * Performs a deep copy of this <code>ActivationList</code>, copying all
 234  
      * <code>Activation</code>s and recursively the nested
 235  
      * <code>Activation</code>s.
 236  
      *
 237  
      * @return a new <code>ActivationList</code> containing a deep copy of all
 238  
      *         <code>Activation</code>s in this list
 239  
      */
 240  
     public ActivationList copy() {
 241  8
         ActivationList newList = new ActivationList();
 242  8
         for (Activation activation : activations) {
 243  11
             newList.add(activation.copy(null));
 244  
         }
 245  8
         return newList;
 246  
     }
 247  
 
 248  
     /**
 249  
      * Returns a string representation of this <code>ActivationList</code>.
 250  
      *
 251  
      * @return a string representation of this <code>ActivationList</code>
 252  
      */
 253  
     @Override
 254  
     public String toString() {
 255  0
         return activations.toString();
 256  
     }
 257  
 
 258  
     /**
 259  
      * Compares this <code>ActivationList</code> to another object, and
 260  
      * returns <code>true</code> if and only if the other object is an
 261  
      * <code>ActivationList</code> with equal <code>Activation</code>s.
 262  
      *
 263  
      * @param o
 264  
      *            the object to compare this <code>ActivationList</code> to
 265  
      *
 266  
      * @return <code>true</code> if <code>o</code> is an
 267  
      *         <code>ActivationList</code> with equal activations,
 268  
      *         <code>false</code> otherwise
 269  
      */
 270  
     @Override
 271  
     public boolean equals(Object o) {
 272  17
         boolean equal = false;
 273  17
         if (o instanceof ActivationList) {
 274  17
             ActivationList otherActivationList = (ActivationList) o;
 275  17
             return activations.equals(otherActivationList.activations);
 276  
         }
 277  0
         return equal;
 278  
     }
 279  
 
 280  
     /**
 281  
      * Returns a hash code for this <code>ActivationList</code>.
 282  
      *
 283  
      * @return a hash code for this <code>ActivationList</code>
 284  
      */
 285  
     @Override
 286  
     public int hashCode() {
 287  0
         return activations.hashCode();
 288  
     }
 289  
 
 290  
     //
 291  
     // Nested top-level classes
 292  
     //
 293  
 
 294  
     /**
 295  
      * An interface used by the <code>filter</code> and <code>find</code>
 296  
      * methods to determine if an <code>Activation</code> is acceptable or
 297  
      * not.
 298  
      *
 299  
      * @see #filter(Filter)
 300  
      * @see #find(Filter)
 301  
      */
 302  146
     public interface Filter {
 303  
 
 304  
         /**
 305  
          * This method determines if an <code>Activation</code> is accepted by
 306  
          * a <code>Filter</code> instance or not. It should return
 307  
          * <code>true</code> if the given <code>Activation</code> should be
 308  
          * accepted, <code>false</code> otherwise.
 309  
          *
 310  
          * @param activation
 311  
          *            the <code>Activation</code> to check for acceptance
 312  
          *
 313  
          * @return <code>true</code> if <code>activation</code> is accepted,
 314  
          *         <code>false</code> otherwise
 315  
          */
 316  
         boolean accept(Activation activation);
 317  
     }
 318  
 }