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.RuleContext;
8   import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
9   import net.sourceforge.pmd.ast.ASTMethodDeclarator;
10  import net.sourceforge.pmd.ast.ASTPrimitiveType;
11  import net.sourceforge.pmd.ast.ASTResultType;
12  import net.sourceforge.pmd.symboltable.VariableNameDeclaration;
13  
14  import java.text.MessageFormat;
15  import java.util.ArrayList;
16  import java.util.Arrays;
17  import java.util.Iterator;
18  import java.util.List;
19  import java.util.Map;
20  
21  public class BeanMembersShouldSerializeRule extends AbstractRule {
22  
23      public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
24          if (node.isInterface()) {
25              return data;
26          }
27  
28          List methList = new ArrayList();
29          node.findChildrenOfType(ASTMethodDeclarator.class, methList);
30  
31          List getSetMethList = new ArrayList();
32          for (Iterator i = methList.iterator(); i.hasNext();) {
33              ASTMethodDeclarator meth = (ASTMethodDeclarator) i.next();
34              if (isBeanAccessor(meth)) {
35                  getSetMethList.add(meth);
36              }
37          }
38          String[] methNameArray = new String[getSetMethList.size()];
39          for (int i = 0; i < getSetMethList.size(); i++) {
40              String methName = ((ASTMethodDeclarator) getSetMethList.get(i)).getImage();
41              methNameArray[i] = methName;
42          }
43  
44          Arrays.sort(methNameArray);
45  
46          Map vars = node.getScope().getVariableDeclarations();
47          for (Iterator i = vars.keySet().iterator(); i.hasNext();) {
48              VariableNameDeclaration decl = (VariableNameDeclaration) i.next();
49              if (((List) vars.get(decl)).isEmpty() || decl.getAccessNodeParent().isTransient() || decl.getAccessNodeParent().isStatic()) {
50                  continue;
51              }
52              String varName = decl.getImage();
53              varName = varName.substring(0, 1).toUpperCase() + varName.substring(1, varName.length());
54              boolean hasGetMethod = Arrays.binarySearch(methNameArray, "get" + varName) >= 0 || Arrays.binarySearch(methNameArray, "is" + varName) >= 0;
55              boolean hasSetMethod = Arrays.binarySearch(methNameArray, "set" + varName) >= 0;
56              if (!hasGetMethod || !hasSetMethod) {
57                  RuleContext ctx = (RuleContext) data;
58                  ctx.getReport().addRuleViolation(createRuleViolation(ctx, decl, MessageFormat.format(getMessage(), new Object[]{decl.getImage()})));
59              }
60          }
61          return super.visit(node, data);
62      }
63  
64      private boolean isBeanAccessor(ASTMethodDeclarator meth) {
65          if (meth.getImage().startsWith("get") || meth.getImage().startsWith("set")) {
66              return true;
67          }
68          if (meth.getImage().startsWith("is")) {
69              ASTResultType ret = (ASTResultType) meth.jjtGetParent().jjtGetChild(0);
70              List primitives = ret.findChildrenOfType(ASTPrimitiveType.class);
71              if (!primitives.isEmpty() && ((ASTPrimitiveType) primitives.get(0)).isBoolean()) {
72                  return true;
73              }
74          }
75          return false;
76      }
77  }