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.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.ASTMethodDeclaration;
    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.NameOccurrence;
    23  import net.sourceforge.pmd.symboltable.VariableNameDeclaration;
    24
    25  public class BeanMembersShouldSerializeRule extends AbstractRule {
    26
    27  	private String prefixProperty;
    28
    29      private static final PropertyDescriptor prefixDescriptor = new StringProperty(
    30      	"prefix", "Prefix somethingorother?", "", 1.0f
    31      	);
    32
    33      private static final Map<String, PropertyDescriptor> propertyDescriptorsByName = asFixedMap(prefixDescriptor);
    34
    35
    36  	public Object visit(ASTCompilationUnit node, Object data) {
    37  		prefixProperty = getStringProperty(prefixDescriptor);
    38  		super.visit(node, data);
    39  		return data;
    40  	}
    41
    42  	private static String[] imagesOf(List<? extends SimpleNode> simpleNodes) {
    43
    44          String[] imageArray = new String[simpleNodes.size()];
    45
    46          for (int i = 0; i < simpleNodes.size(); i++) {
    47          	imageArray[i] = simpleNodes.get(i).getImage();
    48          }
    49          return imageArray;
    50  	}
    51
    52      public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
    53          if (node.isInterface()) {
    54              return data;
    55          }
    56
    57          Map<MethodNameDeclaration, List<NameOccurrence>> methods = node.getScope().getEnclosingClassScope().getMethodDeclarations();
    58          List<ASTMethodDeclarator> getSetMethList = new ArrayList<ASTMethodDeclarator>(methods.size());
    59          for (MethodNameDeclaration d: methods.keySet()) {
    60              ASTMethodDeclarator mnd = d.getMethodNameDeclaratorNode();
    61              if (isBeanAccessor(mnd)) {
    62                  getSetMethList.add(mnd);
    63              }
    64          }
    65
    66          String[] methNameArray = imagesOf(getSetMethList);
    67
    68          Arrays.sort(methNameArray);
    69
    70          Map<VariableNameDeclaration, List<NameOccurrence>> vars = node.getScope().getVariableDeclarations();
    71          for (VariableNameDeclaration decl: vars.keySet()) {
    72              if (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 = ((ASTMethodDeclaration) meth.jjtGetParent()).getResultType();
    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<String, PropertyDescriptor> propertiesByName() {
    114     	return propertyDescriptorsByName;
    115     }
    116 }