001: package org.acm.seguin.pmd.stat;
002:
003: import org.acm.seguin.pmd.AbstractRule;
004: import org.acm.seguin.pmd.RuleContext;
005:
006: import java.util.Iterator;
007: import java.util.List;
008: import java.util.Set;
009: import java.util.SortedSet;
010: import java.util.TreeSet;
011:
012: /**
013: * @author David Dixon-Peugh
014: * Aug 8, 2002 StatisticalRule.java
015: */
016: public abstract class StatisticalRule extends AbstractRule {
017: public static double DELTA = 0.000005; // Within this range. . .
018:
019: private SortedSet dataPoints = new TreeSet();
020:
021: private int count = 0;
022: private double total = 0.0;
023: private double totalSquared = 0.0;
024:
025: public void addDataPoint(DataPoint point) {
026: count++;
027: total += point.getScore();
028: totalSquared += point.getScore() * point.getScore();
029: dataPoints.add(point);
030: }
031:
032: public void apply(List acus, RuleContext ctx) {
033: visitAll(acus, ctx);
034:
035: double deviation;
036: double minimum = 0.0;
037:
038: if (hasProperty("sigma")) {
039: deviation = getStdDev();
040: double sigma = getDoubleProperty("sigma");
041:
042: minimum = getMean() + (sigma * deviation);
043: }
044:
045: if (hasProperty("minimum")) {
046: double mMin = getDoubleProperty("minimum");
047: if (mMin > minimum) {
048: minimum = mMin;
049: }
050: }
051:
052: SortedSet newPoints = applyMinimumValue(dataPoints, minimum);
053:
054: if (hasProperty("topscore")) {
055: int topScore = getIntProperty("topscore");
056: if (newPoints.size() >= topScore) {
057: newPoints = applyTopScore(newPoints, topScore);
058: }
059: }
060:
061: makeViolations(ctx, newPoints);
062:
063: double low = 0.0d;
064: double high = 0.0d;
065: if (!dataPoints.isEmpty()) {
066: low = ((DataPoint) dataPoints.first()).getScore();
067: high = ((DataPoint) dataPoints.last()).getScore();
068: }
069:
070: ctx.getReport().addMetric(
071: new Metric(this .getName(), count, total, low, high,
072: getMean(), getStdDev()));
073:
074: dataPoints.clear();
075: }
076:
077: protected double getMean() {
078: return total / count;
079: }
080:
081: protected double getStdDev() {
082: Iterator points = dataPoints.iterator();
083: double mean = getMean();
084: double deltaSq = 0.0;
085:
086: if (dataPoints.size() < 2) {
087: return Double.NaN;
088: }
089:
090: while (points.hasNext()) {
091: DataPoint point = (DataPoint) points.next();
092: deltaSq += ((point.getScore() - mean) * (point.getScore() - mean));
093: }
094:
095: return Math.sqrt(deltaSq / (dataPoints.size() - 1));
096: }
097:
098: protected SortedSet applyMinimumValue(SortedSet pointSet,
099: double minValue) {
100: Iterator points = pointSet.iterator();
101: SortedSet RC = new TreeSet();
102:
103: while (points.hasNext()) {
104: DataPoint point = (DataPoint) points.next();
105:
106: if (point.getScore() > (minValue - DELTA)) {
107: RC.add(point);
108: }
109: }
110: return RC;
111: }
112:
113: protected SortedSet applyTopScore(SortedSet points, int topScore) {
114: SortedSet RC = new TreeSet();
115: for (int i = 0; i < topScore; i++) {
116: DataPoint point = (DataPoint) points.last();
117: points.remove(point);
118:
119: RC.add(point);
120: }
121:
122: return RC;
123: }
124:
125: protected void makeViolations(RuleContext ctx, Set dataPoints) {
126: Iterator points = dataPoints.iterator();
127: while (points.hasNext()) {
128: DataPoint point = (DataPoint) points.next();
129: ctx.getReport().addRuleViolation(
130: this.createRuleViolation(ctx,
131: point.getLineNumber(), point.getMessage()));
132: }
133: }
134: }
|