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 }