1 4 package net.sourceforge.pmd.stat; 5 6 import java.util.Iterator ; 7 import java.util.List ; 8 import java.util.Map ; 9 import java.util.Set ; 10 import java.util.SortedSet ; 11 import java.util.TreeSet ; 12 13 import net.sourceforge.pmd.AbstractRule; 14 import net.sourceforge.pmd.PropertyDescriptor; 15 import net.sourceforge.pmd.RuleContext; 16 import net.sourceforge.pmd.properties.DoubleProperty; 17 import net.sourceforge.pmd.properties.IntegerProperty; 18 19 23 public abstract class StatisticalRule extends AbstractRule { 24 25 public static double DELTA = 0.000005; 27 private SortedSet dataPoints = new TreeSet (); 28 29 private int count = 0; 30 private double total = 0.0; 31 32 private static final PropertyDescriptor sigmaDescriptor = new DoubleProperty( 33 "sigma", "Sigma value", 0, 1.0f 34 ); 35 36 private static final PropertyDescriptor minimumDescriptor = new DoubleProperty( 37 "minimum", "Minimum value", 0, 1.0f 38 ); 39 40 private static final PropertyDescriptor topScoreDescriptor = new IntegerProperty( 41 "topscore", "Top score value", 0, 1.0f 42 ); 43 44 private static final Map propertyDescriptorsByName = asFixedMap( new PropertyDescriptor[] { 45 sigmaDescriptor, minimumDescriptor, topScoreDescriptor 46 }); 47 48 49 public void addDataPoint(DataPoint point) { 50 count++; 51 total += point.getScore(); 52 dataPoints.add(point); 53 } 54 55 public void apply(List acus, RuleContext ctx) { 56 visitAll(acus, ctx); 57 58 double deviation; 59 double minimum = 0.0; 60 61 if (hasProperty("sigma")) { deviation = getStdDev(); 63 double sigma = getDoubleProperty(sigmaDescriptor); 64 minimum = getMean() + (sigma * deviation); 65 } 66 67 if (hasProperty("minimum")) { double mMin = getDoubleProperty(minimumDescriptor); 69 if (mMin > minimum) { 70 minimum = mMin; 71 } 72 } 73 74 SortedSet newPoints = applyMinimumValue(dataPoints, minimum); 75 76 if (hasProperty("topscore")) { int topScore = getIntProperty(topScoreDescriptor); 78 if (newPoints.size() >= topScore) { 79 newPoints = applyTopScore(newPoints, topScore); 80 } 81 } 82 83 makeViolations(ctx, newPoints); 84 85 double low = 0.0d; 86 double high = 0.0d; 87 if (!dataPoints.isEmpty()) { 88 low = ((DataPoint) dataPoints.first()).getScore(); 89 high = ((DataPoint) dataPoints.last()).getScore(); 90 } 91 92 ctx.getReport().addMetric(new Metric(this.getName(), count, total, low, high, getMean(), getStdDev())); 93 94 dataPoints.clear(); 95 } 96 97 protected double getMean() { 98 return total / count; 99 } 100 101 protected double getStdDev() { 102 if (dataPoints.size() < 2) { 103 return Double.NaN; 104 } 105 106 Iterator points = dataPoints.iterator(); 107 double mean = getMean(); 108 double deltaSq = 0.0; 109 double scoreMinusMean; 110 111 while (points.hasNext()) { 112 scoreMinusMean = ((DataPoint) points.next()).getScore() - mean; 113 deltaSq += (scoreMinusMean * scoreMinusMean); 114 } 115 116 return Math.sqrt(deltaSq / (dataPoints.size() - 1)); 117 } 118 119 protected SortedSet applyMinimumValue(SortedSet pointSet, double minValue) { 120 Iterator points = pointSet.iterator(); 121 SortedSet RC = new TreeSet (); 122 double threshold = minValue - DELTA; 123 124 while (points.hasNext()) { 125 DataPoint point = (DataPoint) points.next(); 126 127 if (point.getScore() > threshold) { 128 RC.add(point); 129 } 130 } 131 return RC; 132 } 133 134 protected SortedSet applyTopScore(SortedSet points, int topScore) { 135 SortedSet s = new TreeSet (); 136 Object [] arr = points.toArray(); 137 for (int i = arr.length - 1; i >= (arr.length - topScore); i--) { 138 s.add(arr[i]); 139 } 140 return s; 141 } 142 143 protected void makeViolations(RuleContext ctx, Set p) { 144 Iterator points = p.iterator(); 145 while (points.hasNext()) { 146 DataPoint point = (DataPoint) points.next(); 147 addViolationWithMessage(ctx, point.getNode(), point.getMessage()); 148 } 149 } 150 151 protected Map propertiesByName() { 152 return propertyDescriptorsByName; 153 } 154 } 155 | Popular Tags |