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 }