TooManyFieldsRule.java
01 /**
02  * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
03  */
04 package net.sourceforge.pmd.lang.java.rule.codesize;
05 
06 import java.util.HashMap;
07 import java.util.List;
08 import java.util.Map;
09 
10 import net.sourceforge.pmd.lang.ast.Node;
11 import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
12 import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
13 import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
14 import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
15 import net.sourceforge.pmd.lang.rule.properties.IntegerProperty;
16 import net.sourceforge.pmd.util.NumericConstants;
17 
18 
19 public class TooManyFieldsRule extends AbstractJavaRule {
20 
21     private static final int DEFAULT_MAXFIELDS = 15;
22 
23     private Map<String, Integer> stats;
24     private Map<String, ASTClassOrInterfaceDeclaration> nodes;
25 
26     private static final IntegerProperty MAX_FIELDS_DESCRIPTOR = new IntegerProperty(
27         "maxfields""Max allowable fields",
28         1300, DEFAULT_MAXFIELDS, 1.0f
29         );
30     
31     public TooManyFieldsRule() {
32   definePropertyDescriptor(MAX_FIELDS_DESCRIPTOR);
33     }
34 
35     @Override
36     public Object visit(ASTCompilationUnit node, Object data) {
37 
38         int maxFields = getProperty(MAX_FIELDS_DESCRIPTOR);
39 
40         stats = new HashMap<String, Integer>(5);
41         nodes = new HashMap<String, ASTClassOrInterfaceDeclaration>(5);
42 
43         List<ASTFieldDeclaration> l = node.findDescendantsOfType(ASTFieldDeclaration.class);
44 
45         for (ASTFieldDeclaration fd: l) {
46             if (fd.isFinal() && fd.isStatic()) {
47                 continue;
48             }
49             ASTClassOrInterfaceDeclaration clazz = fd.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class);
50             if (clazz != null && !clazz.isInterface()) {
51                 bumpCounterFor(clazz);
52             }
53         }
54         for (String k : stats.keySet()) {
55             int val = stats.get(k);
56             Node n = nodes.get(k);
57             if (val > maxFields) {
58                 addViolation(data, n);
59             }
60         }
61         return data;
62     }
63 
64     private void bumpCounterFor(ASTClassOrInterfaceDeclaration clazz) {
65         String key = clazz.getImage();
66         if (!stats.containsKey(key)) {
67             stats.put(key, NumericConstants.ZERO);
68             nodes.put(key, clazz);
69         }
70         Integer i = Integer.valueOf(stats.get(key1);
71         stats.put(key, i);
72     }
73 }