View Javadoc

1   /***
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.stat;
5   
6   import net.sourceforge.pmd.AbstractRule;
7   import net.sourceforge.pmd.RuleContext;
8   
9   import java.util.Iterator;
10  import java.util.List;
11  import java.util.Set;
12  import java.util.SortedSet;
13  import java.util.TreeSet;
14  
15  /***
16   * @author David Dixon-Peugh
17   *         Aug 8, 2002 StatisticalRule.java
18   */
19  public abstract class StatisticalRule extends AbstractRule {
20  
21      public static double DELTA = 0.000005; // Within this range. . .
22  
23      private SortedSet dataPoints = new TreeSet();
24  
25      private int count = 0;
26      private double total = 0.0;
27  
28      public void addDataPoint(DataPoint point) {
29          count++;
30          total += point.getScore();
31          dataPoints.add(point);
32      }
33  
34      public void apply(List acus, RuleContext ctx) {
35          visitAll(acus, ctx);
36  
37          double deviation;
38          double minimum = 0.0;
39  
40          if (hasProperty("sigma")) {
41              deviation = getStdDev();
42              double sigma = getDoubleProperty("sigma");
43              minimum = getMean() + (sigma * deviation);
44          }
45  
46          if (hasProperty("minimum")) {
47              double mMin = getDoubleProperty("minimum");
48              if (mMin > minimum) {
49                  minimum = mMin;
50              }
51          }
52  
53          SortedSet newPoints = applyMinimumValue(dataPoints, minimum);
54  
55          if (hasProperty("topscore")) {
56              int topScore = getIntProperty("topscore");
57              if (newPoints.size() >= topScore) {
58                  newPoints = applyTopScore(newPoints, topScore);
59              }
60          }
61  
62          makeViolations(ctx, newPoints);
63  
64          double low = 0.0d;
65          double high = 0.0d;
66          if (!dataPoints.isEmpty()) {
67              low = ((DataPoint) dataPoints.first()).getScore();
68              high = ((DataPoint) dataPoints.last()).getScore();
69          }
70  
71          ctx.getReport().addMetric(new Metric(this.getName(), count, total, low, high, getMean(), getStdDev()));
72  
73          dataPoints.clear();
74      }
75  
76      protected double getMean() {
77          return total / count;
78      }
79  
80      protected double getStdDev() {
81          Iterator points = dataPoints.iterator();
82          double mean = getMean();
83          double deltaSq = 0.0;
84  
85          if (dataPoints.size() < 2) {
86              return Double.NaN;
87          }
88  
89          while (points.hasNext()) {
90              DataPoint point = (DataPoint) points.next();
91              deltaSq += ((point.getScore() - mean) * (point.getScore() - mean));
92          }
93  
94          return Math.sqrt(deltaSq / (dataPoints.size() - 1));
95      }
96  
97      protected SortedSet applyMinimumValue(SortedSet pointSet, double minValue) {
98          Iterator points = pointSet.iterator();
99          SortedSet RC = new TreeSet();
100 
101         while (points.hasNext()) {
102             DataPoint point = (DataPoint) points.next();
103 
104             if (point.getScore() > (minValue - DELTA)) {
105                 RC.add(point);
106             }
107         }
108         return RC;
109     }
110 
111     protected SortedSet applyTopScore(SortedSet points, int topScore) {
112         SortedSet s = new TreeSet();
113         Object[] arr = points.toArray();
114         for (int i=arr.length-1; i>=(arr.length - topScore); i--) {
115             s.add(arr[i]);
116         }
117         return s;
118     }
119 
120     protected void makeViolations(RuleContext ctx, Set p) {
121         Iterator points = p.iterator();
122         while (points.hasNext()) {
123             DataPoint point = (DataPoint) points.next();
124             ctx.getReport().addRuleViolation(createRuleViolation(ctx, point.getLineNumber(), point.getMessage()));
125         }
126     }
127 }