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 if (l!=null && !l.isEmpty()) {
35 for (Iterator it = l.iterator() ; it.hasNext() ; ) {
36 ASTFieldDeclaration fd = (ASTFieldDeclaration) it.next();
37 ASTClassOrInterfaceDeclaration clazz = (ASTClassOrInterfaceDeclaration)fd.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class);
38 if (!clazz.isInterface()) {
39 bumpCounterFor(clazz);
40 }
41 }
42 }
43 for (Iterator it = stats.keySet().iterator() ; it.hasNext() ; ) {
44 String k = (String) it.next();
45 int val = ((Integer)stats.get(k)).intValue();
46 SimpleNode n = (SimpleNode) nodes.get(k);
47 if (val>maxFields) {
48 addViolation( data, n);
49 }
50 }
51 return data;
52 }
53
54 private void bumpCounterFor(ASTClassOrInterfaceDeclaration clazz) {
55 String key = clazz.getImage();
56 if (!stats.containsKey(key)) {
57 stats.put(key, new Integer(0));
58 nodes.put(key, clazz);
59 }
60 Integer i = new Integer(((Integer) stats.get(key)).intValue()+1);
61 stats.put(key,i);
62 }
63
64 }