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 */
020package org.sonar.plugins.core.sensors;
021
022import com.google.common.collect.HashMultiset;
023import com.google.common.collect.Maps;
024import com.google.common.collect.Multiset;
025import org.sonar.api.batch.*;
026import org.sonar.api.measures.*;
027import org.sonar.api.resources.Project;
028import org.sonar.api.resources.Resource;
029import org.sonar.api.rules.Rule;
030import org.sonar.api.rules.RulePriority;
031import org.sonar.api.rules.Violation;
032
033import java.util.Arrays;
034import java.util.Collection;
035import java.util.List;
036import java.util.Map;
037
038@DependsUpon(DecoratorBarriers.END_OF_VIOLATION_TRACKING)
039public class ViolationsDecorator implements Decorator {
040
041  public boolean shouldExecuteOnProject(Project project) {
042    return true;
043  }
044
045  @DependedUpon
046  public List<Metric> generatesViolationsMetrics() {
047    return Arrays.asList(CoreMetrics.VIOLATIONS,
048      CoreMetrics.BLOCKER_VIOLATIONS,
049      CoreMetrics.CRITICAL_VIOLATIONS,
050      CoreMetrics.MAJOR_VIOLATIONS,
051      CoreMetrics.MINOR_VIOLATIONS,
052      CoreMetrics.INFO_VIOLATIONS);
053  }
054
055  public void decorate(Resource resource, DecoratorContext context) {
056    computeTotalViolations(context);
057    computeViolationsPerSeverities(context);
058    computeViolationsPerRules(context);
059  }
060
061  private void computeTotalViolations(DecoratorContext context) {
062    if (context.getMeasure(CoreMetrics.VIOLATIONS) == null) {
063      Collection<Measure> childrenViolations = context.getChildrenMeasures(CoreMetrics.VIOLATIONS);
064      Double sum = MeasureUtils.sum(true, childrenViolations);
065      context.saveMeasure(CoreMetrics.VIOLATIONS, sum + context.getViolations().size());
066    }
067  }
068
069  private void computeViolationsPerSeverities(DecoratorContext context) {
070    Multiset<RulePriority> severitiesBag = HashMultiset.create();
071    for (Violation violation : context.getViolations()) {
072      severitiesBag.add(violation.getSeverity());
073    }
074
075    for (RulePriority severity : RulePriority.values()) {
076      Metric metric = SeverityUtils.severityToViolationMetric(severity);
077      if (context.getMeasure(metric) == null) {
078        Collection<Measure> children = context.getChildrenMeasures(MeasuresFilters.metric(metric));
079        int sum = MeasureUtils.sum(true, children).intValue() + severitiesBag.count(severity);
080        context.saveMeasure(metric, (double) sum);
081      }
082    }
083  }
084
085  private void computeViolationsPerRules(DecoratorContext context) {
086    Map<RulePriority, Multiset<Rule>> rulesPerSeverity = Maps.newHashMap();
087    for (Violation violation : context.getViolations()) {
088      Multiset<Rule> rulesBag = initRules(rulesPerSeverity, violation.getSeverity());
089      rulesBag.add(violation.getRule());
090    }
091
092    for (RulePriority severity : RulePriority.values()) {
093      Metric metric = SeverityUtils.severityToViolationMetric(severity);
094
095      Collection<Measure> children = context.getChildrenMeasures(MeasuresFilters.rules(metric));
096      for (Measure child : children) {
097        RuleMeasure childRuleMeasure = (RuleMeasure) child;
098        Rule rule = childRuleMeasure.getRule();
099        if (rule != null && MeasureUtils.hasValue(childRuleMeasure)) {
100          Multiset<Rule> rulesBag = initRules(rulesPerSeverity, severity);
101          rulesBag.add(rule, childRuleMeasure.getIntValue());
102        }
103      }
104
105      Multiset<Rule> rulesBag = rulesPerSeverity.get(severity);
106      if (rulesBag != null) {
107        for (Multiset.Entry<Rule> entry : rulesBag.entrySet()) {
108          RuleMeasure measure = RuleMeasure.createForRule(metric, entry.getElement(), (double) entry.getCount());
109          measure.setSeverity(severity);
110          context.saveMeasure(measure);
111        }
112      }
113    }
114  }
115
116  private Multiset<Rule> initRules(Map<RulePriority, Multiset<Rule>> rulesPerSeverity, RulePriority severity) {
117    Multiset<Rule> rulesBag = rulesPerSeverity.get(severity);
118    if (rulesBag == null) {
119      rulesBag = HashMultiset.create();
120      rulesPerSeverity.put(severity, rulesBag);
121    }
122    return rulesBag;
123  }
124
125  @Override
126  public String toString() {
127    return getClass().getSimpleName();
128  }
129}