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 }