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 }