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 java.util.ArrayList;
    7   import java.util.Arrays;
    8   import java.util.Iterator;
    9   import java.util.List;
    10  import java.util.Map;
    11
    12  import net.sourceforge.pmd.AbstractRule;
    13  import net.sourceforge.pmd.PropertyDescriptor;
    14  import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
    15  import net.sourceforge.pmd.ast.ASTCompilationUnit;
    16  import net.sourceforge.pmd.ast.ASTMethodDeclarator;
    17  import net.sourceforge.pmd.ast.ASTPrimitiveType;
    18  import net.sourceforge.pmd.ast.ASTResultType;
    19  import net.sourceforge.pmd.ast.SimpleNode;
    20  import net.sourceforge.pmd.properties.StringProperty;
    21  import net.sourceforge.pmd.symboltable.MethodNameDeclaration;
    22  import net.sourceforge.pmd.symboltable.VariableNameDeclaration;
    23
    24  public class BeanMembersShouldSerializeRule extends AbstractRule {
    25
    26  	private String prefixProperty;
    27
    28      private static final PropertyDescriptor prefixDescriptor = new StringProperty(
    29      	"prefix", "Prefix somethingorother?", "", 1.0f
    30      	);
    31
    32      private static final Map propertyDescriptorsByName = asFixedMap(prefixDescriptor);
    33
    34
    35  	public Object visit(ASTCompilationUnit node, Object data) {
    36  		prefixProperty = getStringProperty(prefixDescriptor);
    37  		super.visit(node, data);
    38  		return data;
    39  	}
    40
    41  	private static String[] imagesOf(List simpleNodes) {
    42
    43          String[] imageArray = new String[simpleNodes.size()];
    44
    45          for (int i = 0; i < simpleNodes.size(); i++) {
    46          	imageArray[i] = ((SimpleNode) simpleNodes.get(i)).getImage();
    47          }
    48          return imageArray;
    49  	}
    50
    51      public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
    52          if (node.isInterface()) {
    53              return data;
    54          }
    55
    56          Map methods = node.getScope().getEnclosingClassScope().getMethodDeclarations();
    57          List getSetMethList = new ArrayList(methods.size());
    58          for (Iterator i = methods.keySet().iterator(); i.hasNext();) {
    59              ASTMethodDeclarator mnd = ((MethodNameDeclaration) i.next()).getMethodNameDeclaratorNode();
    60              if (isBeanAccessor(mnd)) {
    61                  getSetMethList.add(mnd);
    62              }
    63          }
    64
    65          String[] methNameArray = imagesOf(getSetMethList);
    66
    67          Arrays.sort(methNameArray);
    68
    69          Map vars = node.getScope().getVariableDeclarations();
    70          for (Iterator i = vars.keySet().iterator(); i.hasNext();) {
    71              VariableNameDeclaration decl = (VariableNameDeclaration) i.next();
    72              if (((List) vars.get(decl)).isEmpty() || decl.getAccessNodeParent().isTransient() || decl.getAccessNodeParent().isStatic()) {
    73                  continue;
    74              }
    75              String varName = trimIfPrefix(decl.getImage());
    76              varName = varName.substring(0, 1).toUpperCase() + varName.substring(1, varName.length());
    77              boolean hasGetMethod = Arrays.binarySearch(methNameArray, "get" + varName) >= 0 || Arrays.binarySearch(methNameArray, "is" + varName) >= 0;
    78              boolean hasSetMethod = Arrays.binarySearch(methNameArray, "set" + varName) >= 0;
    79              if (!hasGetMethod || !hasSetMethod) {
    80                  addViolation(data, decl.getNode(), decl.getImage());
    81              }
    82          }
    83          return super.visit(node, data);
    84      }
    85
    86      private String trimIfPrefix(String img) {
    87          if (prefixProperty != null && img.startsWith(prefixProperty)) {
    88              return img.substring(prefixProperty.length());
    89          }
    90          return img;
    91      }
    92
    93      private boolean isBeanAccessor(ASTMethodDeclarator meth) {
    94
    95      	String methodName = meth.getImage();
    96
    97          if (methodName.startsWith("get") || methodName.startsWith("set")) {
    98              return true;
    99          }
    100         if (methodName.startsWith("is")) {
    101             ASTResultType ret = (ASTResultType) meth.jjtGetParent().jjtGetChild(0);
    102             List primitives = ret.findChildrenOfType(ASTPrimitiveType.class);
    103             if (!primitives.isEmpty() && ((ASTPrimitiveType) primitives.get(0)).isBoolean()) {
    104                 return true;
    105             }
    106         }
    107         return false;
    108     }
    109
    110     /***
    111      * @return Map
    112      */
    113     protected Map propertiesByName() {
    114     	return propertyDescriptorsByName;
    115     }
    116 }