1 /***
2 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3 */
4 package net.sourceforge.pmd.rules.design;
5
6 import net.sourceforge.pmd.AbstractRule;
7 import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
8 import net.sourceforge.pmd.ast.ASTCompilationUnit;
9 import net.sourceforge.pmd.ast.ASTFieldDeclaration;
10 import net.sourceforge.pmd.ast.SimpleNode;
11
12 import java.util.HashMap;
13 import java.util.Iterator;
14 import java.util.List;
15 import java.util.Map;
16
17
18 public class TooManyFields extends AbstractRule {
19
20 private static final int DEFAULT_MAXFIELDS = 15;
21
22 private Map stats;
23 private Map nodes;
24 private int maxFields;
25
26 public Object visit(ASTCompilationUnit node, Object data) {
27 maxFields = hasProperty("maxfields") ? getIntProperty("maxfields") : DEFAULT_MAXFIELDS;
28
29 stats = new HashMap(5);
30 nodes = new HashMap(5);
31
32 List l = node.findChildrenOfType(ASTFieldDeclaration.class);
33
34 for (Iterator it = l.iterator(); it.hasNext();) {
35 ASTFieldDeclaration fd = (ASTFieldDeclaration) it.next();
36 if (fd.isFinal() && fd.isStatic()) {
37 continue;
38 }
39 ASTClassOrInterfaceDeclaration clazz = (ASTClassOrInterfaceDeclaration) fd.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class);
40 if (clazz != null && !clazz.isInterface()) {
41 bumpCounterFor(clazz);
42 }
43 }
44 for (Iterator it = stats.keySet().iterator(); it.hasNext();) {
45 String k = (String) it.next();
46 int val = ((Integer) stats.get(k)).intValue();
47 SimpleNode n = (SimpleNode) nodes.get(k);
48 if (val > maxFields) {
49 addViolation(data, n);
50 }
51 }
52 return data;
53 }
54
55 private void bumpCounterFor(ASTClassOrInterfaceDeclaration clazz) {
56 String key = clazz.getImage();
57 if (!stats.containsKey(key)) {
58 stats.put(key, new Integer(0));
59 nodes.put(key, clazz);
60 }
61 Integer i = new Integer(((Integer) stats.get(key)).intValue() + 1);
62 stats.put(key, i);
63 }
64
65 }