View Javadoc

1   /***
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd;
5   
6   import net.sourceforge.pmd.dfa.report.ReportTree;
7   import net.sourceforge.pmd.stat.Metric;
8   import net.sourceforge.pmd.util.NumericConstants;
9   
10  import java.util.ArrayList;
11  import java.util.HashMap;
12  import java.util.HashSet;
13  import java.util.Iterator;
14  import java.util.List;
15  import java.util.Map;
16  import java.util.Set;
17  import java.util.TreeSet;
18  
19  public class Report {
20  
21      public static class ReadableDuration {
22          private long duration;
23  
24          public ReadableDuration(long duration) {
25              this.duration = duration;
26          }
27  
28          public String getTime() {
29              long seconds = 0;
30              long minutes = 0;
31              long hours = 0;
32  
33              if (duration > 1000) {
34                  seconds = duration / 1000;
35              }
36  
37              if (seconds > 60) {
38                  minutes = seconds / 60;
39                  seconds = seconds % 60;
40              }
41  
42              if (minutes > 60) {
43                  hours = minutes / 60;
44                  minutes = minutes % 60;
45              }
46  
47              StringBuffer res = new StringBuffer();
48              if (hours > 0) {
49                  res.append(hours).append("h ");
50              }
51              if (hours > 0 || minutes > 0) {
52                  res.append(minutes).append("m ");
53              }
54              res.append(seconds).append('s');
55              return res.toString();
56          }
57      }
58  
59      public static class ProcessingError {
60          private String msg;
61          private String file;
62  
63          public ProcessingError(String msg, String file) {
64              this.msg = msg;
65              this.file = file;
66          }
67  
68          public String getMsg() {
69              return msg;
70          }
71  
72          public String getFile() {
73              return file;
74          }
75      }
76  
77      public static class SuppressedViolation {
78          private IRuleViolation rv;
79          private boolean isNOPMD;
80          private String userMessage;
81  
82          public SuppressedViolation(IRuleViolation rv, boolean isNOPMD, String userMessage) {
83              this.isNOPMD = isNOPMD;
84              this.rv = rv;
85              this.userMessage = userMessage;
86          }
87  
88          public boolean suppressedByNOPMD() {
89              return this.isNOPMD;
90          }
91  
92          public boolean suppressedByAnnotation() {
93              return !this.isNOPMD;
94          }
95  
96          public IRuleViolation getRuleViolation() {
97              return this.rv;
98          }
99  
100         public String getUserMessage() {
101             return userMessage;
102         }
103     }
104 
105     private static final RuleViolation.RuleViolationComparator COMPARATOR = new RuleViolation.RuleViolationComparator();
106 
107     /*
108      * The idea is to store the violations in a tree instead of a list, to do
109      * better and faster sort and filter mechanism and to visualize the result
110      * als tree. (ide plugins).
111      * */
112     private ReportTree violationTree = new ReportTree();
113 
114     // Note that this and the above data structure are both being maintained for a bit
115     private Set violations = new TreeSet(COMPARATOR);
116     private Set metrics = new HashSet();
117     private List listeners = new ArrayList();
118     private List errors = new ArrayList();
119     private Map linesToExclude = new HashMap();
120     private long start;
121     private long end;
122 
123     private List suppressedRuleViolations = new ArrayList();
124 
125     public void exclude(Map lines) {
126         linesToExclude = lines;
127     }
128 
129     public Map getCountSummary() {
130         Map summary = new HashMap();
131         for (Iterator iter = violationTree.iterator(); iter.hasNext();) {
132             IRuleViolation rv = (IRuleViolation) iter.next();
133             String key = "";
134             if (rv.getPackageName() != null && rv.getPackageName().length() != 0) {
135                 key = rv.getPackageName() + '.' + rv.getClassName();
136             }
137             Object o = summary.get(key);
138             if (o == null) {
139                 summary.put(key, NumericConstants.ONE);
140             } else {
141                 Integer value = (Integer) o;
142                 summary.put(key, new Integer(value.intValue() + 1));
143             }
144         }
145         return summary;
146     }
147 
148     public ReportTree getViolationTree() {
149         return this.violationTree;
150     }
151 
152 
153     /***
154      * @return a Map summarizing the Report: String (rule name) ->Integer (count of violations)
155      */
156     public Map getSummary() {
157         Map summary = new HashMap();
158         for (Iterator i = violations.iterator(); i.hasNext();) {
159             IRuleViolation rv = (IRuleViolation) i.next();
160             String name = rv.getRule().getName();
161             if (!summary.containsKey(name)) {
162                 summary.put(name, NumericConstants.ZERO);
163             }
164             Integer count = (Integer) summary.get(name);
165             summary.put(name, new Integer(count.intValue() + 1));
166         }
167         return summary;
168     }
169 
170     public void addListener(ReportListener listener) {
171         listeners.add(listener);
172     }
173 
174     public List getSuppressedRuleViolations() {
175         return suppressedRuleViolations;
176     }
177 
178     public void addRuleViolation(IRuleViolation violation) {
179 
180         // NOPMD excluder
181         Integer line = new Integer(violation.getBeginLine());
182         if (linesToExclude.keySet().contains(line)) {
183             suppressedRuleViolations.add(new SuppressedViolation(violation, true, (String)linesToExclude.get(line)));
184             return;
185         }
186 
187         if (violation.isSuppressed()) {
188             suppressedRuleViolations.add(new SuppressedViolation(violation, false, null));
189             return;
190         }
191 
192 
193         violations.add(violation);
194         violationTree.addRuleViolation(violation);
195         for (Iterator i = listeners.iterator(); i.hasNext();) {
196             ReportListener listener = (ReportListener) i.next();
197             listener.ruleViolationAdded(violation);
198         }
199     }
200 
201     public void addMetric(Metric metric) {
202         metrics.add(metric);
203         for (Iterator i = listeners.iterator(); i.hasNext();) {
204             ReportListener listener = (ReportListener) i.next();
205             listener.metricAdded(metric);
206         }
207     }
208 
209     public void addError(ProcessingError error) {
210         errors.add(error);
211     }
212 
213     public void merge(Report r) {
214         Iterator i = r.errors();
215         while (i.hasNext()) {
216             addError((ProcessingError)i.next());
217         }
218         i = r.metrics();
219         while (i.hasNext()) {
220             addMetric((Metric)i.next());
221         }
222         i = r.iterator();
223         while (i.hasNext()) {
224             addRuleViolation((IRuleViolation)i.next());
225         }
226     }
227 
228     public boolean hasMetrics() {
229         return !metrics.isEmpty();
230     }
231 
232     public Iterator metrics() {
233         return metrics.iterator();
234     }
235 
236     public boolean isEmpty() {
237         return !violations.iterator().hasNext() && errors.isEmpty();
238     }
239 
240     public boolean treeIsEmpty() {
241         return !violationTree.iterator().hasNext();
242     }
243 
244     public Iterator treeIterator() {
245         return violationTree.iterator();
246     }
247 
248     public Iterator iterator() {
249         return violations.iterator();
250     }
251 
252     public Iterator errors() {
253         return errors.iterator();
254     }
255 
256     public int treeSize() {
257         return violationTree.size();
258     }
259 
260     public int size() {
261         return violations.size();
262     }
263 
264     public void start() {
265         start = System.currentTimeMillis();
266     }
267 
268     public void end() {
269         end = System.currentTimeMillis();
270     }
271 
272     public long getElapsedTimeInMillis() {
273         return end - start;
274     }
275 }