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
109
110
111
112 private ReportTree violationTree = new ReportTree();
113
114
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
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 }