Clover coverage report - PMD - 3.7
Coverage timestamp: Wed May 31 2006 09:25:59 EDT
file stats: LOC: 149   Methods: 10
NCLOC: 94   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
CouplingBetweenObjects.java 45.8% 60.5% 60% 55.8%
coverage coverage
 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.symboltable.ClassScope;
 8    import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
 9    import net.sourceforge.pmd.ast.ASTClassOrInterfaceType;
 10    import net.sourceforge.pmd.ast.ASTCompilationUnit;
 11    import net.sourceforge.pmd.ast.ASTFieldDeclaration;
 12    import net.sourceforge.pmd.ast.ASTFormalParameter;
 13    import net.sourceforge.pmd.ast.ASTLocalVariableDeclaration;
 14    import net.sourceforge.pmd.ast.ASTReferenceType;
 15    import net.sourceforge.pmd.ast.ASTResultType;
 16    import net.sourceforge.pmd.ast.ASTType;
 17    import net.sourceforge.pmd.ast.SimpleNode;
 18   
 19    import java.util.HashSet;
 20    import java.util.Set;
 21   
 22   
 23    /**
 24    * CouplingBetweenObjects attempts to capture all unique Class attributes,
 25    * local variables, and return types to determine how many objects a class is
 26    * coupled to. This is only a guage and isn't a hard and fast rule. The threshold
 27    * value is configurable and should be determined accordingly
 28    *
 29    * @author aglover
 30    * @since Feb 20, 2003
 31    */
 32    public class CouplingBetweenObjects extends AbstractRule {
 33   
 34    private int couplingCount;
 35    private Set typesFoundSoFar;
 36   
 37  3 public Object visit(ASTCompilationUnit cu, Object data) {
 38  3 this.typesFoundSoFar = new HashSet();
 39  3 this.couplingCount = 0;
 40   
 41  3 Object returnObj = cu.childrenAccept(this, data);
 42   
 43  3 if (this.couplingCount > getIntProperty("threshold")) {
 44  1 addViolation(data, cu, "A value of " + this.couplingCount + " may denote a high amount of coupling within the class");
 45    }
 46   
 47  3 return returnObj;
 48    }
 49   
 50  3 public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
 51  3 if (node.isInterface()) {
 52  1 return data;
 53    }
 54  2 return super.visit(node, data);
 55    }
 56   
 57  3 public Object visit(ASTResultType node, Object data) {
 58  3 for (int x = 0; x < node.jjtGetNumChildren(); x++) {
 59  3 SimpleNode tNode = (SimpleNode) node.jjtGetChild(x);
 60  3 if (tNode instanceof ASTType) {
 61  3 SimpleNode reftypeNode = (SimpleNode) tNode.jjtGetChild(0);
 62  3 if (reftypeNode instanceof ASTReferenceType) {
 63  3 SimpleNode classOrIntType = (SimpleNode) reftypeNode.jjtGetChild(0);
 64  3 if (classOrIntType instanceof ASTClassOrInterfaceType) {
 65  3 SimpleNode nameNode = (ASTClassOrInterfaceType) classOrIntType;
 66  3 this.checkVariableType(nameNode, nameNode.getImage());
 67    }
 68    }
 69    }
 70    }
 71  3 return super.visit(node, data);
 72    }
 73   
 74  0 public Object visit(ASTLocalVariableDeclaration node, Object data) {
 75  0 this.handleASTTypeChildren(node);
 76  0 return super.visit(node, data);
 77    }
 78   
 79  0 public Object visit(ASTFormalParameter node, Object data) {
 80  0 this.handleASTTypeChildren(node);
 81  0 return super.visit(node, data);
 82    }
 83   
 84  0 public Object visit(ASTFieldDeclaration node, Object data) {
 85  0 for (int x = 0; x < node.jjtGetNumChildren(); ++x) {
 86  0 SimpleNode firstStmt = (SimpleNode) node.jjtGetChild(x);
 87  0 if (firstStmt instanceof ASTType) {
 88  0 ASTType tp = (ASTType) firstStmt;
 89  0 SimpleNode nd = (SimpleNode) tp.jjtGetChild(0);
 90  0 this.checkVariableType(nd, nd.getImage());
 91    }
 92    }
 93   
 94  0 return super.visit(node, data);
 95    }
 96   
 97    /**
 98    * convience method to handle hierarchy. This is probably too much
 99    * work and will go away once I figure out the framework
 100    */
 101  0 private void handleASTTypeChildren(SimpleNode node) {
 102  0 for (int x = 0; x < node.jjtGetNumChildren(); x++) {
 103  0 SimpleNode sNode = (SimpleNode) node.jjtGetChild(x);
 104  0 if (sNode instanceof ASTType) {
 105  0 SimpleNode nameNode = (SimpleNode) sNode.jjtGetChild(0);
 106  0 this.checkVariableType(nameNode, nameNode.getImage());
 107    }
 108    }
 109    }
 110   
 111    /**
 112    * performs a check on the variable and updates the counter. Counter is
 113    * instance for a class and is reset upon new class scan.
 114    *
 115    * @param String variableType
 116    */
 117  3 private void checkVariableType(SimpleNode nameNode, String variableType) {
 118    // TODO - move this into the symbol table somehow?
 119  3 if (nameNode.getParentsOfType(ASTClassOrInterfaceDeclaration.class).isEmpty()) {
 120  0 return;
 121    }
 122    //if the field is of any type other than the class type
 123    //increment the count
 124  3 ClassScope clzScope = nameNode.getScope().getEnclosingClassScope();
 125  3 if (!clzScope.getClassName().equals(variableType) && (!this.filterTypes(variableType)) && !this.typesFoundSoFar.contains(variableType)) {
 126  3 this.couplingCount++;
 127  3 this.typesFoundSoFar.add(variableType);
 128    }
 129    }
 130   
 131    /**
 132    * Filters variable type - we don't want primatives, wrappers, strings, etc.
 133    * This needs more work. I'd like to filter out super types and perhaps interfaces
 134    *
 135    * @param String variableType
 136    * @return boolean true if variableType is not what we care about
 137    */
 138  3 private boolean filterTypes(String variableType) {
 139  3 return variableType != null && (variableType.startsWith("java.lang.") || (variableType.equals("String")) || filterPrimitivesAndWrappers(variableType));
 140    }
 141   
 142    /**
 143    * @param String variableType
 144    * @return boolean true if variableType is a primative or wrapper
 145    */
 146  3 private boolean filterPrimitivesAndWrappers(String variableType) {
 147  3 return (variableType.equals("int") || variableType.equals("Integer") || variableType.equals("char") || variableType.equals("Character") || variableType.equalsIgnoreCase("double") || variableType.equalsIgnoreCase("long") || variableType.equalsIgnoreCase("short") || variableType.equalsIgnoreCase("float") || variableType.equalsIgnoreCase("byte") || variableType.equalsIgnoreCase("boolean"));
 148    }
 149    }