001    /*
002     * Sonar, open source software quality management tool.
003     * Copyright (C) 2008-2012 SonarSource
004     * mailto:contact AT sonarsource DOT com
005     *
006     * Sonar is free software; you can redistribute it and/or
007     * modify it under the terms of the GNU Lesser General Public
008     * License as published by the Free Software Foundation; either
009     * version 3 of the License, or (at your option) any later version.
010     *
011     * Sonar is distributed in the hope that it will be useful,
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014     * Lesser General Public License for more details.
015     *
016     * You should have received a copy of the GNU Lesser General Public
017     * License along with Sonar; if not, write to the Free Software
018     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
019     */
020    package org.sonar.plugins.core.sensors;
021    
022    import com.google.common.collect.HashMultiset;
023    import com.google.common.collect.Maps;
024    import com.google.common.collect.Multiset;
025    import org.sonar.api.batch.*;
026    import org.sonar.api.measures.*;
027    import org.sonar.api.resources.Project;
028    import org.sonar.api.resources.Resource;
029    import org.sonar.api.resources.ResourceUtils;
030    import org.sonar.api.rules.Rule;
031    import org.sonar.api.rules.RulePriority;
032    import org.sonar.api.rules.Violation;
033    
034    import java.util.Arrays;
035    import java.util.Collection;
036    import java.util.List;
037    import java.util.Map;
038    
039    @DependsUpon(DecoratorBarriers.END_OF_VIOLATION_TRACKING)
040    public class ViolationsDecorator implements Decorator {
041    
042      public boolean shouldExecuteOnProject(Project project) {
043        return true;
044      }
045    
046      private boolean shouldDecorateResource(Resource resource) {
047        return !ResourceUtils.isUnitTestClass(resource);
048      }
049    
050      @DependedUpon
051      public List<Metric> generatesViolationsMetrics() {
052        return Arrays.asList(CoreMetrics.VIOLATIONS,
053          CoreMetrics.BLOCKER_VIOLATIONS,
054          CoreMetrics.CRITICAL_VIOLATIONS,
055          CoreMetrics.MAJOR_VIOLATIONS,
056          CoreMetrics.MINOR_VIOLATIONS,
057          CoreMetrics.INFO_VIOLATIONS);
058      }
059    
060      public void decorate(Resource resource, DecoratorContext context) {
061        if (shouldDecorateResource(resource)) {
062          computeTotalViolations(context);
063          computeViolationsPerSeverities(context);
064          computeViolationsPerRules(context);
065        }
066      }
067    
068      private void computeTotalViolations(DecoratorContext context) {
069        if (context.getMeasure(CoreMetrics.VIOLATIONS) == null) {
070          Collection<Measure> childrenViolations = context.getChildrenMeasures(CoreMetrics.VIOLATIONS);
071          Double sum = MeasureUtils.sum(true, childrenViolations);
072          context.saveMeasure(CoreMetrics.VIOLATIONS, sum + context.getViolations().size());
073        }
074      }
075    
076      private void computeViolationsPerSeverities(DecoratorContext context) {
077        Multiset<RulePriority> severitiesBag = HashMultiset.create();
078        for (Violation violation : context.getViolations()) {
079          severitiesBag.add(violation.getSeverity());
080        }
081    
082        for (RulePriority severity : RulePriority.values()) {
083          Metric metric = SeverityUtils.severityToViolationMetric(severity);
084          if (context.getMeasure(metric) == null) {
085            Collection<Measure> children = context.getChildrenMeasures(MeasuresFilters.metric(metric));
086            int sum = MeasureUtils.sum(true, children).intValue() + severitiesBag.count(severity);
087            context.saveMeasure(metric, (double) sum);
088          }
089        }
090      }
091    
092      private void computeViolationsPerRules(DecoratorContext context) {
093        Map<RulePriority, Multiset<Rule>> rulesPerSeverity = Maps.newHashMap();
094        for (Violation violation : context.getViolations()) {
095          Multiset<Rule> rulesBag = initRules(rulesPerSeverity, violation.getSeverity());
096          rulesBag.add(violation.getRule());
097        }
098    
099        for (RulePriority severity : RulePriority.values()) {
100          Metric metric = SeverityUtils.severityToViolationMetric(severity);
101    
102          Collection<Measure> children = context.getChildrenMeasures(MeasuresFilters.rules(metric));
103          for (Measure child : children) {
104            RuleMeasure childRuleMeasure = (RuleMeasure) child;
105            Rule rule = childRuleMeasure.getRule();
106            if (rule != null && MeasureUtils.hasValue(childRuleMeasure)) {
107              Multiset<Rule> rulesBag = initRules(rulesPerSeverity, severity);
108              rulesBag.add(rule, childRuleMeasure.getIntValue());
109            }
110          }
111    
112          Multiset<Rule> rulesBag = rulesPerSeverity.get(severity);
113          if (rulesBag != null) {
114            for (Multiset.Entry<Rule> entry : rulesBag.entrySet()) {
115              RuleMeasure measure = RuleMeasure.createForRule(metric, entry.getElement(), (double) entry.getCount());
116              measure.setSeverity(severity);
117              context.saveMeasure(measure);
118            }
119          }
120        }
121      }
122    
123      private Multiset<Rule> initRules(Map<RulePriority, Multiset<Rule>> rulesPerSeverity, RulePriority severity) {
124        Multiset<Rule> rulesBag = rulesPerSeverity.get(severity);
125        if (rulesBag == null) {
126          rulesBag = HashMultiset.create();
127          rulesPerSeverity.put(severity, rulesBag);
128        }
129        return rulesBag;
130      }
131    
132      @Override
133      public String toString() {
134        return getClass().getSimpleName();
135      }
136    }