View Javadoc

    1   package net.sourceforge.pmd.dfa.report;
    2
    3   import net.sourceforge.pmd.IRuleViolation;
    4
    5   import java.util.Iterator;
    6
    7   public class ReportTree {
    8
    9       private PackageNode rootNode = new PackageNode("");
    10      private AbstractReportNode level;
    11
    12      private class TreeIterator implements Iterator<IRuleViolation> {
    13
    14          private AbstractReportNode iterNode = rootNode;
    15          private boolean hasNextFlag;
    16
    17          public void remove() {
    18              throw new UnsupportedOperationException();
    19          }
    20
    21          public boolean hasNext() {
    22              this.hasNextFlag = true;
    23              return this.getNext() != null;
    24          }
    25
    26          public IRuleViolation next() {
    27
    28              if (!this.hasNextFlag) {
    29                  this.getNext();
    30              } else {
    31                  this.hasNextFlag = false;
    32              }
    33
    34              if (this.iterNode instanceof ViolationNode) {
    35                  return ((ViolationNode) this.iterNode).getRuleViolation();
    36              }
    37              return null;
    38          }
    39
    40          /**
    41           * It's some kind of left-right-middle search (postorder).
    42           * It always returns only
    43           * leafs. The first node he returns is the most left handed leaf he can
    44           * found. Now he's looking for siblings and if there are any, he starts
    45           * searching for the next most left handed leaf. If there are no
    46           * siblings he goes up to his parent and starts looking for siblings.
    47           * If there are any he starts searching for the next most left handed
    48           * leaf again. And so on ... until he wants to get the parent of the
    49           * root node. Because there is no one, the search stops.
    50           */
    51
    52          private AbstractReportNode getNext() {
    53              AbstractReportNode node;
    54
    55              while (true) {
    56                  if (this.iterNode.isLeaf()) {
    57
    58                      while ((node = (this.iterNode).getNextSibling()) == null) {
    59
    60                          node = this.iterNode.getParent();
    61                          if (node == null) {
    62                              return null;
    63                          } else {
    64                              this.iterNode = node;
    65                          }
    66                      }
    67
    68                      this.iterNode = node;
    69                      if (this.iterNode.isLeaf()) {
    70                          return this.iterNode;
    71                      } else {
    72                          continue;
    73                      }
    74                  } else {
    75                      this.iterNode = this.iterNode.getFirstChild();
    76                      if (this.iterNode.isLeaf()) {
    77                          return this.iterNode;
    78                      } else {
    79                          continue;
    80                      }
    81                  }
    82              }
    83          }
    84      }
    85
    86
    87      public Iterator<IRuleViolation> iterator() {
    88          return new TreeIterator();
    89      }
    90
    91      public int size() {
    92          int count = 0;
    93          for (Iterator<IRuleViolation> i = iterator(); i.hasNext();) {
    94              i.next();
    95              count++;
    96          }
    97          return count;
    98      }
    99
    100     public AbstractReportNode getRootNode() {
    101         return rootNode;
    102     }
    103
    104     /**
    105      * Adds the RuleViolation to the tree. Splits the package name. Each
    106      * package, class and violation gets there own tree node.
    107      */
    108     public void addRuleViolation(IRuleViolation violation) {
    109         String pack = violation.getPackageName();
    110         String[] a = {};
    111         if (pack == null) {
    112             a = new String[]{""};
    113         } else if (pack.indexOf('.') != -1) {
    114             String[] tmp = pack.split("\\.");
    115             a = new String[tmp.length];
    116             System.arraycopy(tmp, 0, a, 0, tmp.length);
    117         } else {
    118             a = new String[]{pack};
    119         }
    120
    121         this.level = this.rootNode;
    122         String plugedPackageName = "";
    123
    124         for (int i = 0; i < a.length; i++) {
    125             String packageName = a[i];
    126             plugedPackageName += packageName + '.';
    127
    128             if (!this.isStringInLevel(plugedPackageName)) {
    129                 PackageNode node = new PackageNode(plugedPackageName);
    130                 this.level.addFirst(node);
    131                 // gotoLevel
    132                 this.level = node;
    133             }
    134         }
    135
    136         String cl = violation.getClassName();
    137
    138         if (!this.isStringInLevel(cl)) {
    139             ClassNode node = new ClassNode(cl);
    140             this.level.addFirst(node);
    141             // gotoLevel
    142             this.level = node;
    143         }
    144
    145         /*
    146          * Filters dublicated rule violations. Like the comparator in
    147          * RuleViolation if he already exists.
    148          */
    149         ViolationNode tmp = new ViolationNode(violation);
    150         if (!this.equalsNodeInLevel(this.level, tmp)) {
    151             this.level.add(tmp);
    152         }
    153     }
    154
    155     /**
    156      * Checks if node is a child of the level node.
    157      */
    158     private boolean equalsNodeInLevel(AbstractReportNode level, AbstractReportNode node) {
    159         for (int i = 0; i < level.getChildCount(); i++) {
    160             if ((level.getChildAt(i)).equalsNode(node)) {
    161                 return true;
    162             }
    163         }
    164         return false;
    165     }
    166
    167     /**
    168      * Checks if the packageName or the className is a child of the current
    169      * (this.level) node. If it's true, the current node changes to the
    170      * child node.
    171      */
    172     private boolean isStringInLevel(String str) {
    173
    174         for (int i = 0; i < this.level.getChildCount(); i++) {
    175             AbstractReportNode child = this.level.getChildAt(i);
    176             String tmp = null;
    177
    178             if (child instanceof PackageNode) {
    179                 tmp = ((PackageNode) child).getPackageName();
    180             }
    181             if (child instanceof ClassNode) {
    182                 tmp = ((ClassNode) child).getClassName();
    183             }
    184
    185             if (tmp == null) {
    186                 return false;
    187             }
    188
    189             if (tmp.equals(str)) {
    190                 // goto level
    191                 this.level = child;
    192                 return true;
    193             }
    194         }
    195         return false;
    196     }
    197
    198 }