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  }