View Javadoc

    1   /***
    2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
    3    */
    4   package net.sourceforge.pmd.rules;
    5
    6   import net.sourceforge.pmd.AbstractRule;
    7   import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
    8   import net.sourceforge.pmd.ast.ASTMethodDeclarator;
    9   import net.sourceforge.pmd.ast.ASTPrimitiveType;
    10  import net.sourceforge.pmd.ast.ASTResultType;
    11  import net.sourceforge.pmd.symboltable.MethodNameDeclaration;
    12  import net.sourceforge.pmd.symboltable.VariableNameDeclaration;
    13
    14  import java.util.ArrayList;
    15  import java.util.Arrays;
    16  import java.util.Iterator;
    17  import java.util.List;
    18  import java.util.Map;
    19
    20  public class BeanMembersShouldSerializeRule extends AbstractRule {
    21
    22      public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
    23          if (node.isInterface()) {
    24              return data;
    25          }
    26
    27          Map methods = node.getScope().getEnclosingClassScope().getMethodDeclarations();
    28          List getSetMethList = new ArrayList();
    29          for (Iterator i = methods.keySet().iterator(); i.hasNext();) {
    30              ASTMethodDeclarator mnd = ((MethodNameDeclaration) i.next()).getMethodNameDeclaratorNode();
    31              if (isBeanAccessor(mnd)) {
    32                  getSetMethList.add(mnd);
    33              }
    34          }
    35
    36          String[] methNameArray = new String[getSetMethList.size()];
    37          for (int i = 0; i < getSetMethList.size(); i++) {
    38              methNameArray[i] = ((ASTMethodDeclarator) getSetMethList.get(i)).getImage();
    39          }
    40
    41          Arrays.sort(methNameArray);
    42
    43          Map vars = node.getScope().getVariableDeclarations();
    44          for (Iterator i = vars.keySet().iterator(); i.hasNext();) {
    45              VariableNameDeclaration decl = (VariableNameDeclaration) i.next();
    46              if (((List) vars.get(decl)).isEmpty() || decl.getAccessNodeParent().isTransient() || decl.getAccessNodeParent().isStatic()) {
    47                  continue;
    48              }
    49              String varName = trimIfPrefix(decl.getImage());
    50              varName = varName.substring(0, 1).toUpperCase() + varName.substring(1, varName.length());
    51              boolean hasGetMethod = Arrays.binarySearch(methNameArray, "get" + varName) >= 0 || Arrays.binarySearch(methNameArray, "is" + varName) >= 0;
    52              boolean hasSetMethod = Arrays.binarySearch(methNameArray, "set" + varName) >= 0;
    53              if (!hasGetMethod || !hasSetMethod) {
    54                  addViolation(data, decl.getNode(), decl.getImage());
    55              }
    56          }
    57          return super.visit(node, data);
    58      }
    59
    60      private String trimIfPrefix(String img) {
    61          if (getStringProperty("prefix") != null && img.startsWith(getStringProperty("prefix"))) {
    62              return img.substring(getStringProperty("prefix").length());
    63          }
    64          return img;
    65      }
    66
    67      private boolean isBeanAccessor(ASTMethodDeclarator meth) {
    68          if (meth.getImage().startsWith("get") || meth.getImage().startsWith("set")) {
    69              return true;
    70          }
    71          if (meth.getImage().startsWith("is")) {
    72              ASTResultType ret = (ASTResultType) meth.jjtGetParent().jjtGetChild(0);
    73              List primitives = ret.findChildrenOfType(ASTPrimitiveType.class);
    74              if (!primitives.isEmpty() && ((ASTPrimitiveType) primitives.get(0)).isBoolean()) {
    75                  return true;
    76              }
    77          }
    78          return false;
    79      }
    80  }