Clover coverage report - PMD - 3.9 Coverage timestamp: Tue Dec 19 2006 09:38:44 EST FRAMES NO FRAMES |
file stats: | LOC: | 467 |  | Methods: | 61
| NCLOC: | 276 |  | Classes: | 1
Source file | Conditionals | Statements | Methods | TOTAL
AbstractRule.java | 66.7% | 76.1% | 82% | 75.9% |

1 |  | /**
2 |  | * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3 |  | */
4 |  | package net.sourceforge.pmd;
5 |  |
6 |  | import java.text.MessageFormat;
7 |  | import java.util.Collections;
8 |  | import java.util.HashMap;
9 |  | import java.util.Iterator;
10 |  | import java.util.List;
11 |  | import java.util.Map;
12 |  | import java.util.Properties;
13 |  |
14 |  | import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
15 |  | import net.sourceforge.pmd.ast.ASTCompilationUnit;
16 |  | import net.sourceforge.pmd.ast.ASTImportDeclaration;
17 |  | import net.sourceforge.pmd.ast.JavaParserVisitorAdapter;
18 |  | import net.sourceforge.pmd.ast.Node;
19 |  | import net.sourceforge.pmd.ast.SimpleNode;
20 |  |
21 |  | public abstract class AbstractRule extends JavaParserVisitorAdapter implements Rule {
22 |  |
23 |  | protected String name = getClass().getName();
24 |  | protected Properties properties = new Properties(); // TODO - remove when ready
25 |  | protected String message;
26 |  | protected String description;
27 |  | protected String example;
28 |  | protected String ruleSetName;
29 |  | protected boolean include;
30 |  | protected boolean usesDFA;
31 |  | protected boolean usesTypeResolution;
32 |  | protected int priority = LOWEST_PRIORITY;
33 |  | protected String externalInfoUrl;
34 |  |
35 |  | private static final boolean inOldPropertyMode = true; // temporary flag during conversion
36 |  |
37 | 251 | protected static Map asFixedMap(PropertyDescriptor[] descriptors) {
38 |  |
39 | 251 | Map descsById = new HashMap(descriptors.length);
40 |  |
41 | 251 | for (int i=0; i<descriptors.length; i++) {
42 | 533 | descsById.put(descriptors[i].name(), descriptors[i]);
43 |  | }
44 | 251 | return Collections.unmodifiableMap(descsById);
45 |  | }
46 |  |
47 | 72 | protected static Map asFixedMap(PropertyDescriptor descriptor) {
48 | 72 | return asFixedMap(new PropertyDescriptor[] {descriptor});
49 |  | }
50 |  |
51 | 12 | public String getRuleSetName() {
52 | 12 | return ruleSetName;
53 |  | }
54 |  |
55 | 4599 | public void setRuleSetName(String ruleSetName) {
56 | 4599 | this.ruleSetName = ruleSetName;
57 |  | }
58 |  |
59 | 2 | public String getDescription() {
60 | 2 | return description;
61 |  | }
62 |  |
63 | 4346 | public void setDescription(String description) {
64 | 4346 | this.description = description;
65 |  | }
66 |  |
67 | 1 | public String getExample() {
68 | 1 | return example;
69 |  | }
70 |  |
71 | 4434 | public void setExample(String example) {
72 | 4434 | this.example = example;
73 |  | }
74 |  |
75 |  | /**
76 |  | * @deprecated - property values will be guaranteed available via default values
77 |  | */
78 | 603 | public boolean hasProperty(String name) {
79 |  |
80 | 603 | return inOldPropertyMode ? // TODO -remove
81 |  | properties.containsKey(name) :
82 |  | propertiesByName().containsKey(name);
83 |  | }
84 |  |
85 |  | /**
86 |  | * @deprecated
87 |  | */
88 | 3455 | public void addProperty(String name, String value) {
89 | 3455 | properties.setProperty(name, value);
90 |  | }
91 |  |
92 |  | /**
93 |  | * @deprecated
94 |  | */
95 | 2 | public void addProperties(Properties properties) {
96 | 2 | this.properties.putAll(properties);
97 |  | }
98 |  |
99 | 0 | public double[] getDoubleProperties(PropertyDescriptor descriptor) {
100 |  |
101 | 0 | Number[] values = (Number[])getProperties(descriptor);
102 |  |
103 | 0 | double[] doubles = new double[values.length];
104 | 0 | for (int i=0; i<doubles.length; i++) doubles[i] = values[i].doubleValue();
105 | 0 | return doubles;
106 |  | }
107 |  |
108 |  | /**
109 |  | * @deprecated - use getDoubleProperty(PropertyDescriptor) instead
110 |  | */
111 | 1 | public double getDoubleProperty(String name) {
112 |  |
113 | 1 | return Double.parseDouble(properties.getProperty(name));
114 |  | }
115 |  |
116 | 253 | public double getDoubleProperty(PropertyDescriptor descriptor) {
117 |  |
118 | 253 | return ((Number)getProperty(descriptor)).doubleValue();
119 |  | }
120 |  |
121 | 1 | public int[] getIntProperties(PropertyDescriptor descriptor) {
122 |  |
123 | 1 | Number[] values = (Number[])getProperties(descriptor);
124 |  |
125 | 1 | int[] ints = new int[values.length];
126 | 2 | for (int i=0; i<ints.length; i++) ints[i] = values[i].intValue();
127 | 1 | return ints;
128 |  | }
129 |  |
130 |  | /**
131 |  | * @deprecated - use getIntProperty(PropertyDescriptor) instead
132 |  | */
133 | 8 | public int getIntProperty(String name) {
134 |  |
135 | 8 | return Integer.parseInt(properties.getProperty(name));
136 |  | }
137 |  |
138 | 176 | public int getIntProperty(PropertyDescriptor descriptor) {
139 |  |
140 | 176 | return ((Number)getProperty(descriptor)).intValue();
141 |  | }
142 |  |
143 | 0 | public Class[] getTypeProperties(PropertyDescriptor descriptor) {
144 |  |
145 | 0 | return (Class[])getProperties(descriptor);
146 |  | }
147 |  |
148 | 0 | public Class getTypeProperty(PropertyDescriptor descriptor) {
149 |  |
150 | 0 | return (Class)getProperty(descriptor);
151 |  | }
152 |  |
153 | 1 | public boolean[] getBooleanProperties(PropertyDescriptor descriptor) {
154 |  |
155 | 1 | Boolean[] values = (Boolean[])getProperties(descriptor);
156 |  |
157 | 1 | boolean[] bools = new boolean[values.length];
158 | 2 | for (int i=0; i<bools.length; i++) bools[i] = values[i].booleanValue();
159 | 1 | return bools;
160 |  | }
161 |  |
162 | 25 | public boolean getBooleanProperty(PropertyDescriptor descriptor) {
163 |  |
164 | 25 | return ((Boolean)getProperty(descriptor)).booleanValue();
165 |  | }
166 |  |
167 |  | /**
168 |  | * @deprecated - use getBooleanProperty(PropertyDescriptor) instead
169 |  | */
170 | 16 | public boolean getBooleanProperty(String name) {
171 |  |
172 | 16 | return Boolean.valueOf(properties.getProperty(name)).booleanValue();
173 |  | }
174 |  |
175 |  | /**
176 |  | * @deprecated - use setProperty(PropertyDescriptor, Object) instead
177 |  | *
178 |  | * @param name
179 |  | * @param flag
180 |  | */
181 | 0 | public void setBooleanProperty(String name, boolean flag) {
182 |  |
183 | 0 | properties.setProperty(name, Boolean.toString(flag));
184 |  | }
185 |  |
186 | 41 | public String[] getStringProperties(PropertyDescriptor descriptor) {
187 |  |
188 | 41 | return (String[])getProperties(descriptor);
189 |  | }
190 |  |
191 |  |
192 |  | /**
193 |  | * @deprecated - use getStringProperty(PropertyDescriptor) instead
194 |  | *
195 |  | */
196 | 109 | public String getStringProperty(String name) {
197 | 109 | return properties.getProperty(name);
198 |  | }
199 |  |
200 | 37 | public String getStringProperty(PropertyDescriptor descriptor) {
201 | 37 | return (String)getProperty(descriptor);
202 |  | }
203 |  |
204 | 491 | private Object getProperty(PropertyDescriptor descriptor) {
205 |  |
206 | 0 | if (descriptor.maxValueCount() > 1) propertyGetError(descriptor, true);
207 |  |
208 | 491 | String rawValue = properties.getProperty(descriptor.name());
209 |  |
210 | 491 | return rawValue == null || rawValue.length() == 0 ?
211 |  | descriptor.defaultValue() :
212 |  | descriptor.valueFrom(rawValue);
213 |  | }
214 |  |
215 | 29 | public void setProperty(PropertyDescriptor descriptor, Object value) {
216 |  |
217 | 3 | if (descriptor.maxValueCount() > 1) propertySetError(descriptor, true);
218 |  |
219 | 26 | properties.setProperty(descriptor.name(), descriptor.asDelimitedString(value));
220 |  | }
221 |  |
222 | 43 | private Object[] getProperties(PropertyDescriptor descriptor) {
223 |  |
224 | 0 | if (descriptor.maxValueCount() == 1) propertyGetError(descriptor, false);
225 |  |
226 | 43 | String rawValue = properties.getProperty(descriptor.name());
227 |  |
228 | 43 | return rawValue == null || rawValue.length() == 0 ?
229 |  | (Object[])descriptor.defaultValue() :
230 |  | (Object[])descriptor.valueFrom(rawValue);
231 |  | }
232 |  |
233 | 6 | public void setProperties(PropertyDescriptor descriptor, Object[] values) {
234 |  |
235 | 3 | if (descriptor.maxValueCount() == 1) propertySetError(descriptor, false);
236 |  |
237 | 3 | properties.setProperty(descriptor.name(), descriptor.asDelimitedString(values));
238 |  | }
239 |  |
240 | 0 | private void propertyGetError(PropertyDescriptor descriptor, boolean requestedSingleValue) {
241 |  |
242 | 0 | if (requestedSingleValue) {
243 | 0 | throw new RuntimeException("Cannot retrieve a single value from a multi-value property field");
244 |  | }
245 | 0 | throw new RuntimeException("Cannot retrieve multiple values from a single-value property field");
246 |  | }
247 |  |
248 | 6 | private void propertySetError(PropertyDescriptor descriptor, boolean setSingleValue) {
249 |  |
250 | 6 | if (setSingleValue) {
251 | 3 | throw new RuntimeException("Cannot set a single value within a multi-value property field");
252 |  | }
253 | 3 | throw new RuntimeException("Cannot set multiple values within a single-value property field");
254 |  | }
255 |  |
256 | 2846 | public String getName() {
257 | 2846 | return name;
258 |  | }
259 |  |
260 | 4413 | public void setName(String name) {
261 | 4413 | this.name = name;
262 |  | }
263 |  |
264 | 849 | public String getMessage() {
265 | 849 | return message;
266 |  | }
267 |  |
268 | 4417 | public void setMessage(String message) {
269 | 4417 | this.message = message;
270 |  | }
271 |  |
272 | 15 | public String getExternalInfoUrl() {
273 | 15 | return externalInfoUrl;
274 |  | }
275 |  |
276 | 4391 | public void setExternalInfoUrl(String url) {
277 | 4391 | this.externalInfoUrl = url;
278 |  | }
279 |  |
280 |  | /**
281 |  | * Test if rules are equals. Rules are equals if
282 |  | * 1. they have the same implementation class
283 |  | * 2. they have the same name
284 |  | * 3. they have the same priority
285 |  | * 4. they share the same properties/values
286 |  | */
287 | 16 | public boolean equals(Object o) {
288 | 16 | if (o == null) {
289 | 1 | return false; // trivial
290 |  | }
291 |  |
292 | 15 | if (this == o) {
293 | 5 | return true; // trivial
294 |  | }
295 |  |
296 | 10 | Rule rule = null;
297 | 10 | boolean equality = this.getClass().getName().equals(o.getClass().getName());
298 |  |
299 | 10 | if (equality) {
300 | 8 | rule = (Rule) o;
301 | 8 | equality = this.getName().equals(rule.getName())
302 |  | && this.getPriority() == rule.getPriority()
303 |  | && this.getProperties().equals(rule.getProperties());
304 |  | }
305 |  |
306 | 10 | return equality;
307 |  | }
308 |  |
309 |  | /**
310 |  | * Return a hash code to conform to equality. Try with a string.
311 |  | */
312 | 20 | public int hashCode() {
313 | 20 | String s = getClass().getName() + getName() + getPriority() + getProperties().toString();
314 | 20 | return s.hashCode();
315 |  | }
316 |  |
317 | 1189 | public void apply(List acus, RuleContext ctx) {
318 | 1189 | visitAll(acus, ctx);
319 |  | }
320 |  |
321 |  | /**
322 |  | * @deprecated - retrieve by name using get<type>Property or get<type>Properties
323 |  | */
324 | 1200 | public Properties getProperties() {
325 | 1200 | return properties;
326 |  | }
327 |  |
328 | 0 | public boolean include() {
329 | 0 | return include;
330 |  | }
331 |  |
332 | 0 | public void setInclude(boolean include) {
333 | 0 | this.include = include;
334 |  | }
335 |  |
336 | 4483 | public int getPriority() {
337 | 4483 | return priority;
338 |  | }
339 |  |
340 | 0 | public String getPriorityName() {
341 | 0 | return PRIORITIES[getPriority() - 1];
342 |  | }
343 |  |
344 | 4356 | public void setPriority(int priority) {
345 | 4356 | this.priority = priority;
346 |  | }
347 |  |
348 | 19 | public void setUsesDFA() {
349 | 19 | this.usesDFA = true;
350 |  | }
351 |  |
352 | 1229 | public boolean usesDFA() {
353 | 1229 | return this.usesDFA;
354 |  | }
355 |  |
356 | 4 | public void setUsesTypeResolution() {
357 | 4 | this.usesTypeResolution = true;
358 |  | }
359 |  |
360 | 1225 | public boolean usesTypeResolution() {
361 | 1225 | return this.usesTypeResolution;
362 |  | }
363 |  |
364 | 1383 | protected void visitAll(List acus, RuleContext ctx) {
365 | 1383 | for (Iterator i = acus.iterator(); i.hasNext();) {
366 | 1225 | ASTCompilationUnit node = (ASTCompilationUnit) i.next();
367 | 1225 | visit(node, ctx);
368 |  | }
369 |  | }
370 |  |
371 |  | /**
372 |  | * Adds a violation to the report.
373 |  | *
374 |  | * @param ctx the RuleContext
375 |  | * @param node the node that produces the violation
376 |  | */
377 | 224 | protected final void addViolation(Object data, SimpleNode node) {
378 | 224 | RuleContext ctx = (RuleContext) data;
379 | 224 | ctx.getReport().addRuleViolation(new RuleViolation(this, ctx, node));
380 |  | }
381 |  |
382 |  | /**
383 |  | * Adds a violation to the report.
384 |  | *
385 |  | * @param ctx the RuleContext
386 |  | * @param node the node that produces the violation
387 |  | * @param msg specific message to put in the report
388 |  | */
389 | 2239 | protected final void addViolationWithMessage(Object data, SimpleNode node, String msg) {
390 | 2239 | RuleContext ctx = (RuleContext) data;
391 | 2239 | ctx.getReport().addRuleViolation(new RuleViolation(this, ctx, node, msg));
392 |  | }
393 |  |
394 |  | /**
395 |  | * Adds a violation to the report.
396 |  | *
397 |  | * @param ctx the RuleContext
398 |  | * @param node the node that produces the violation
399 |  | * @param embed a variable to embed in the rule violation message
400 |  | */
401 | 326 | protected final void addViolation(Object data, SimpleNode node, String embed) {
402 | 326 | RuleContext ctx = (RuleContext) data;
403 | 326 | ctx.getReport().addRuleViolation(new RuleViolation(this, ctx, node, MessageFormat.format(getMessage(), new Object[]{embed})));
404 |  | }
405 |  |
406 |  | /**
407 |  | * Adds a violation to the report.
408 |  | *
409 |  | * @param ctx the RuleContext
410 |  | * @param node the node that produces the violation, may be null, in which case all line and column info will be set to zero
411 |  | * @param args objects to embed in the rule violation message
412 |  | */
413 | 62 | protected final void addViolation(Object data, Node node, Object[] args) {
414 | 62 | RuleContext ctx = (RuleContext) data;
415 | 62 | ctx.getReport().addRuleViolation(new RuleViolation(this, ctx, (SimpleNode) node, MessageFormat.format(getMessage(), args)));
416 |  | }
417 |  |
418 |  | /**
419 |  | * Gets the Image of the first parent node of type ASTClassOrInterfaceDeclaration or <code>null</code>
420 |  | *
421 |  | * @param node the node which will be searched
422 |  | */
423 | 12 | protected final String getDeclaringType(SimpleNode node) {
424 | 12 | ASTClassOrInterfaceDeclaration c = (ASTClassOrInterfaceDeclaration) node.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class);
425 | 12 | if (c != null)
426 | 12 | return c.getImage();
427 | 0 | return null;
428 |  | }
429 |  |
430 | 46 | public static boolean isQualifiedName(SimpleNode node) {
431 | 46 | return node.getImage().indexOf('.') != -1;
432 |  | }
433 |  |
434 | 0 | public static boolean importsPackage(ASTCompilationUnit node, String packageName) {
435 |  |
436 | 0 | List nodes = node.findChildrenOfType(ASTImportDeclaration.class);
437 | 0 | for (Iterator i = nodes.iterator(); i.hasNext();) {
438 | 0 | ASTImportDeclaration n = (ASTImportDeclaration) i.next();
439 | 0 | if (n.getPackageName().startsWith(packageName)) {
440 | 0 | return true;
441 |  | }
442 |  | }
443 | 0 | return false;
444 |  | }
445 |  |
446 |  | /**
447 |  | * Return all the relevant properties for the receiver by
448 |  | * overriding in subclasses as necessary.
449 |  | *
450 |  | * @return Map
451 |  | */
452 | 0 | protected Map propertiesByName() {
453 | 0 | return Collections.EMPTY_MAP;
454 |  | }
455 |  |
456 |  | /**
457 |  | * Return the indicated property descriptor or null if not found.
458 |  | *
459 |  | * @param propertyName String
460 |  | * @return PropertyDescriptor
461 |  | */
462 | 0 | public PropertyDescriptor propertyDescriptorFor(String propertyName) {
463 | 0 | PropertyDescriptor desc = (PropertyDescriptor)propertiesByName().get(propertyName);
464 | 0 | if (desc == null) throw new IllegalArgumentException("unknown property: " + propertyName);
465 | 0 | return desc;
466 |  | }
467 |  | }