2 * Sonar, open source software quality management tool.
3 * Copyright (C) 2009 SonarSource SA
4 * mailto:contact AT sonarsource DOT com
6 * Sonar is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * Sonar is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Sonar; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
20 package org.sonar.plugins.core.timemachine;
22 import com.google.common.collect.ArrayListMultimap;
23 import com.google.common.collect.Maps;
24 import com.google.common.collect.Multimap;
25 import com.google.common.collect.Sets;
26 import org.sonar.api.batch.Decorator;
27 import org.sonar.api.batch.DecoratorContext;
28 import org.sonar.api.batch.DependedUpon;
29 import org.sonar.api.batch.DependsUpon;
30 import org.sonar.api.measures.*;
31 import org.sonar.api.resources.Project;
32 import org.sonar.api.resources.Resource;
33 import org.sonar.api.rules.Rule;
34 import org.sonar.api.rules.RulePriority;
35 import org.sonar.api.rules.Violation;
39 @DependsUpon(classes = ViolationPersisterDecorator.class)
40 public class NewViolationsDecorator implements Decorator {
42 private TimeMachineConfiguration timeMachineConfiguration;
44 // temporary data for current resource
45 private Map<Rule, RulePriority> ruleToLevel = Maps.newHashMap();
46 private Multimap<RulePriority, Violation> violationsByPriority = ArrayListMultimap.create();
47 private Multimap<Rule, Violation> violationsByRule = ArrayListMultimap.create();
49 public NewViolationsDecorator(TimeMachineConfiguration timeMachineConfiguration) {
50 this.timeMachineConfiguration = timeMachineConfiguration;
53 public boolean shouldExecuteOnProject(Project project) {
54 return project.isLatestAnalysis();
58 public List<Metric> generatesMetric() {
59 return Arrays.asList(CoreMetrics.NEW_VIOLATIONS,
60 CoreMetrics.NEW_BLOCKER_VIOLATIONS, CoreMetrics.NEW_CRITICAL_VIOLATIONS, CoreMetrics.NEW_MAJOR_VIOLATIONS, CoreMetrics.NEW_MINOR_VIOLATIONS, CoreMetrics.NEW_INFO_VIOLATIONS);
63 public void decorate(Resource resource, DecoratorContext context) {
64 prepareCurrentResourceViolations(context);
65 saveNewViolations(context);
66 saveNewViolationsByPriority(context);
67 saveNewViolationsByRule(context);
71 private void clearCache() {
73 violationsByPriority.clear();
74 violationsByRule.clear();
77 private void prepareCurrentResourceViolations(DecoratorContext context) {
78 for (Violation violation : context.getViolations()) {
79 violationsByPriority.put(violation.getPriority(), violation);
80 violationsByRule.put(violation.getRule(), violation);
81 ruleToLevel.put(violation.getRule(), violation.getPriority());
85 private void saveNewViolations(DecoratorContext context) {
86 Measure measure = new Measure(CoreMetrics.NEW_VIOLATIONS);
87 for (PastSnapshot variationSnapshot : timeMachineConfiguration.getProjectPastSnapshots()) {
88 int variationIndex = variationSnapshot.getIndex();
89 Collection<Measure> children = context.getChildrenMeasures(CoreMetrics.NEW_VIOLATIONS);
90 int count = countViolations(context.getViolations(), variationSnapshot.getDate());
91 double sum = sumChildren(variationIndex, children) + count;
92 measure.setVariation(variationIndex, sum);
94 context.saveMeasure(measure);
97 private void saveNewViolationsByPriority(DecoratorContext context) {
98 for (RulePriority priority : RulePriority.values()) {
99 Measure measure1 = new Measure(getMetricForPriority(priority));
100 Measure measure2 = RuleMeasure.createForPriority(CoreMetrics.NEW_VIOLATIONS, priority, null);
101 for (PastSnapshot variationSnapshot : timeMachineConfiguration.getProjectPastSnapshots()) {
102 int variationIndex = variationSnapshot.getIndex();
103 Collection<Measure> children = context.getChildrenMeasures(MeasuresFilters.rulePriority(CoreMetrics.NEW_VIOLATIONS, priority));
104 int count = countViolations(violationsByPriority.get(priority), variationSnapshot.getDate());
105 double sum = sumChildren(variationIndex, children) + count;
106 measure1.setVariation(variationIndex, sum);
107 measure2.setVariation(variationIndex, sum);
109 context.saveMeasure(measure1);
110 context.saveMeasure(measure2);
114 private void saveNewViolationsByRule(DecoratorContext context) {
115 ArrayListMultimap<Rule, Measure> childrenByRule = ArrayListMultimap.create();
116 Collection<Measure> children = context.getChildrenMeasures(MeasuresFilters.rules(CoreMetrics.NEW_VIOLATIONS));
117 for (Measure childMeasure : children) {
118 RuleMeasure childRuleMeasure = (RuleMeasure) childMeasure;
119 Rule rule = childRuleMeasure.getRule();
120 if (rule != null && MeasureUtils.hasValue(childRuleMeasure)) {
121 childrenByRule.put(rule, childMeasure);
122 ruleToLevel.put(childRuleMeasure.getRule(), childRuleMeasure.getRulePriority());
126 Set<Rule> rules = Sets.newHashSet(violationsByRule.keys());
127 rules.addAll(childrenByRule.keys());
129 for (Rule rule : rules) {
130 RuleMeasure measure = RuleMeasure.createForRule(CoreMetrics.NEW_VIOLATIONS, rule, null);
131 measure.setRulePriority(ruleToLevel.get(rule));
132 for (PastSnapshot variationSnapshot : timeMachineConfiguration.getProjectPastSnapshots()) {
133 int variationIndex = variationSnapshot.getIndex();
134 int count = countViolations(violationsByRule.get(rule), variationSnapshot.getDate());
135 double sum = sumChildren(variationIndex, childrenByRule.get(rule)) + count;
136 measure.setVariation(variationIndex, sum);
138 context.saveMeasure(measure);
142 int sumChildren(int variationIndex, Collection<Measure> measures) {
144 for (Measure measure : measures) {
145 Double var = measure.getVariation(variationIndex);
147 sum += var.intValue();
153 int countViolations(Collection<Violation> violations, Date targetDate) {
154 if (violations == null) {
158 for (Violation violation : violations) {
159 if (isAfter(violation, targetDate)) {
166 private boolean isAfter(Violation violation, Date date) {
167 return !violation.getCreatedAt().before(date);
170 private Metric getMetricForPriority(RulePriority priority) {
171 Metric metric = null;
172 if (priority.equals(RulePriority.BLOCKER)) {
173 metric = CoreMetrics.NEW_BLOCKER_VIOLATIONS;
174 } else if (priority.equals(RulePriority.CRITICAL)) {
175 metric = CoreMetrics.NEW_CRITICAL_VIOLATIONS;
176 } else if (priority.equals(RulePriority.MAJOR)) {
177 metric = CoreMetrics.NEW_MAJOR_VIOLATIONS;
178 } else if (priority.equals(RulePriority.MINOR)) {
179 metric = CoreMetrics.NEW_MINOR_VIOLATIONS;
180 } else if (priority.equals(RulePriority.INFO)) {
181 metric = CoreMetrics.NEW_INFO_VIOLATIONS;
187 public String toString() {
188 return getClass().getSimpleName();