/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.rule.design;
import net.sourceforge.pmd.lang.java.ast.ASTStatement;
import net.sourceforge.pmd.lang.java.ast.ASTSwitchLabel;
import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement;
import net.sourceforge.pmd.lang.java.rule.AbstractStatisticalJavaRule;
import net.sourceforge.pmd.stat.DataPoint;
/**
* Switch Density - This is the number of statements over the number of
* cases within a switch. The higher the value, the more work each case
* is doing.
*
* <p>Its my theory, that when the Switch Density is high, you should start
* looking at Subclasses or State Pattern to alleviate the problem.</p>
*
* @author David Dixon-Peugh
*/
public class SwitchDensityRule extends AbstractStatisticalJavaRule {
private static class SwitchDensity {
private int labels = 0;
private int stmts = 0;
public void addSwitchLabel() {
labels++;
}
public void addStatement() {
stmts++;
}
public void addStatements(int stmtCount) {
stmts += stmtCount;
}
public int getStatementCount() {
return stmts;
}
public double getDensity() {
if (labels == 0) {
return 0;
}
return (double) stmts / (double) labels;
}
}
public SwitchDensityRule() {
super();
setProperty(MINIMUM_DESCRIPTOR, 10d);
}
public Object visit(ASTSwitchStatement node, Object data) {
SwitchDensity oldData = null;
if (data instanceof SwitchDensity) {
oldData = (SwitchDensity) data;
}
SwitchDensity density = new SwitchDensity();
node.childrenAccept(this, density);
DataPoint point = new DataPoint();
point.setNode(node);
point.setScore(density.getDensity());
point.setMessage(getMessage());
addDataPoint(point);
if (data instanceof SwitchDensity) {
((SwitchDensity) data).addStatements(density.getStatementCount());
}
return oldData;
}
public Object visit(ASTStatement statement, Object data) {
if (data instanceof SwitchDensity) {
((SwitchDensity) data).addStatement();
}
statement.childrenAccept(this, data);
return data;
}
public Object visit(ASTSwitchLabel switchLabel, Object data) {
if (data instanceof SwitchDensity) {
((SwitchDensity) data).addSwitchLabel();
}
switchLabel.childrenAccept(this, data);
return data;
}
}