View Javadoc

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 java.util.HashMap;
7   import java.util.Iterator;
8   import java.util.List;
9   import java.util.Map;
10  
11  import net.sourceforge.pmd.AbstractRule;
12  import net.sourceforge.pmd.PropertyDescriptor;
13  import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
14  import net.sourceforge.pmd.ast.ASTCompilationUnit;
15  import net.sourceforge.pmd.ast.ASTFieldDeclaration;
16  import net.sourceforge.pmd.ast.SimpleNode;
17  import net.sourceforge.pmd.properties.IntegerProperty;
18  import net.sourceforge.pmd.util.NumericConstants;
19  
20  
21  public class TooManyFields extends AbstractRule {
22  
23      private static final int DEFAULT_MAXFIELDS = 15;
24  
25      private Map stats;
26      private Map nodes;
27      private int maxFields;
28  
29      private static final PropertyDescriptor maxFieldsDescriptor = new IntegerProperty(
30      		"maxfields", 
31      		"Maximum allowable fields per class",
32      		DEFAULT_MAXFIELDS,
33      		1.0f
34      		);
35      
36      private static final Map propertyDescriptorsByName = asFixedMap(maxFieldsDescriptor);
37      
38      public Object visit(ASTCompilationUnit node, Object data) {
39      	
40          maxFields = getIntProperty(maxFieldsDescriptor);
41  
42          stats = new HashMap(5);
43          nodes = new HashMap(5);
44  
45          List l = node.findChildrenOfType(ASTFieldDeclaration.class);
46  
47          for (Iterator it = l.iterator(); it.hasNext();) {
48              ASTFieldDeclaration fd = (ASTFieldDeclaration) it.next();
49              if (fd.isFinal() && fd.isStatic()) {
50                  continue;
51              }
52              ASTClassOrInterfaceDeclaration clazz = (ASTClassOrInterfaceDeclaration) fd.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class);
53              if (clazz != null && !clazz.isInterface()) {
54                  bumpCounterFor(clazz);
55              }
56          }
57          for (Iterator it = stats.keySet().iterator(); it.hasNext();) {
58              String k = (String) it.next();
59              int val = ((Integer) stats.get(k)).intValue();
60              SimpleNode n = (SimpleNode) nodes.get(k);
61              if (val > maxFields) {
62                  addViolation(data, n);
63              }
64          }
65          return data;
66      }
67  
68      private void bumpCounterFor(ASTClassOrInterfaceDeclaration clazz) {
69          String key = clazz.getImage();
70          if (!stats.containsKey(key)) {
71              stats.put(key, NumericConstants.ZERO);
72              nodes.put(key, clazz);
73          }
74          Integer i = new Integer(((Integer) stats.get(key)).intValue() + 1);
75          stats.put(key, i);
76      }
77  
78      /***
79       * @return Map
80       */
81      protected Map propertiesByName() {
82      	return propertyDescriptorsByName;
83      }
84  }