SwitchDensityRule.java
001 /**
002  * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
003  */
004 package net.sourceforge.pmd.lang.java.rule.design;
005 
006 import net.sourceforge.pmd.lang.java.ast.ASTStatement;
007 import net.sourceforge.pmd.lang.java.ast.ASTSwitchLabel;
008 import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement;
009 import net.sourceforge.pmd.lang.java.rule.AbstractStatisticalJavaRule;
010 import net.sourceforge.pmd.stat.DataPoint;
011 
012 /**
013  @author David Dixon-Peugh
014  *
015  *         <p/>
016  *         Switch Density - This is the number of statements over the
017  *         number of cases within a switch.  The higher the value, the
018  *         more work each case is doing.
019  *         <p/>
020  *         Its my theory, that when the Switch Density is high, you should
021  *         start looking at Subclasses or State Pattern to alleviate the
022  *         problem.
023  */
024 public class SwitchDensityRule extends AbstractStatisticalJavaRule {
025 
026     private static class SwitchDensity {
027         private int labels = 0;
028         private int stmts = 0;
029 
030         public void addSwitchLabel() {
031             labels++;
032         }
033 
034         public void addStatement() {
035             stmts++;
036         }
037 
038         public void addStatements(int stmtCount) {
039             stmts += stmtCount;
040         }
041 
042         public int getStatementCount() {
043             return stmts;
044         }
045 
046         public double getDensity() {
047             if (labels == 0) {
048                 return 0;
049             }
050             return (doublestmts / (doublelabels;
051         }
052     }
053     
054     public SwitchDensityRule() {
055   super();
056   setProperty(MINIMUM_DESCRIPTOR, 10d);
057     }
058 
059     public Object visit(ASTSwitchStatement node, Object data) {
060         SwitchDensity oldData = null;
061 
062         if (data instanceof SwitchDensity) {
063             oldData = (SwitchDensitydata;
064         }
065 
066         SwitchDensity density = new SwitchDensity();
067 
068         node.childrenAccept(this, density);
069 
070         DataPoint point = new DataPoint();
071         point.setNode(node);
072         point.setScore(density.getDensity());
073         point.setMessage(getMessage());
074 
075         addDataPoint(point);
076 
077         if (data instanceof SwitchDensity) {
078             ((SwitchDensitydata).addStatements(density.getStatementCount());
079         }
080         return oldData;
081     }
082 
083     public Object visit(ASTStatement statement, Object data) {
084         if (data instanceof SwitchDensity) {
085             ((SwitchDensitydata).addStatement();
086         }
087 
088         statement.childrenAccept(this, data);
089 
090         return data;
091     }
092 
093     public Object visit(ASTSwitchLabel switchLabel, Object data) {
094         if (data instanceof SwitchDensity) {
095             ((SwitchDensitydata).addSwitchLabel();
096         }
097 
098         switchLabel.childrenAccept(this, data);
099         return data;
100     }
101 }