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             addViolationWithMessage(ctx, point.getNode(), point.getMessage());
    125         }
    126     }
    127 }