]> source.dussan.org Git - sonarqube.git/blob
c9aa477a7bab4a210d3dff68794000323017202c
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2016 SonarSource SA
4  * mailto:contact AT sonarsource DOT com
5  *
6  * This program 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.
10  *
11  * This program 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.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20
21 package org.sonar.server.computation.task.projectanalysis.qualitymodel;
22
23 import com.google.common.collect.ImmutableMap;
24 import java.util.Map;
25 import org.sonar.api.ce.measure.Issue;
26 import org.sonar.api.measures.CoreMetrics;
27 import org.sonar.core.issue.DefaultIssue;
28 import org.sonar.server.computation.task.projectanalysis.component.Component;
29 import org.sonar.server.computation.task.projectanalysis.component.PathAwareVisitorAdapter;
30 import org.sonar.server.computation.task.projectanalysis.formula.counter.RatingValue;
31 import org.sonar.server.computation.task.projectanalysis.issue.ComponentIssuesRepository;
32 import org.sonar.server.computation.task.projectanalysis.measure.MeasureRepository;
33 import org.sonar.server.computation.task.projectanalysis.metric.Metric;
34 import org.sonar.server.computation.task.projectanalysis.metric.MetricRepository;
35 import org.sonar.server.computation.task.projectanalysis.period.Period;
36 import org.sonar.server.computation.task.projectanalysis.period.PeriodsHolder;
37
38 import static org.sonar.api.measures.CoreMetrics.NEW_RELIABILITY_RATING_KEY;
39 import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_RATING_KEY;
40 import static org.sonar.api.rule.Severity.BLOCKER;
41 import static org.sonar.api.rule.Severity.CRITICAL;
42 import static org.sonar.api.rule.Severity.INFO;
43 import static org.sonar.api.rule.Severity.MAJOR;
44 import static org.sonar.api.rule.Severity.MINOR;
45 import static org.sonar.api.rules.RuleType.BUG;
46 import static org.sonar.api.rules.RuleType.VULNERABILITY;
47 import static org.sonar.server.computation.task.projectanalysis.component.ComponentVisitor.Order.POST_ORDER;
48 import static org.sonar.server.computation.task.projectanalysis.component.CrawlerDepthLimit.LEAVES;
49 import static org.sonar.server.computation.task.projectanalysis.measure.Measure.newMeasureBuilder;
50 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating;
51 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.A;
52 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.B;
53 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.C;
54 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.D;
55 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.E;
56
57 /**
58  * Compute following measures :
59  * {@link CoreMetrics#NEW_RELIABILITY_RATING_KEY}
60  * {@link CoreMetrics#NEW_SECURITY_RATING_KEY}
61  */
62 public class NewReliabilityAndSecurityRatingMeasuresVisitor extends PathAwareVisitorAdapter<NewReliabilityAndSecurityRatingMeasuresVisitor.Counter> {
63
64   private static final Map<String, Rating> RATING_BY_SEVERITY = ImmutableMap.of(
65     BLOCKER, E,
66     CRITICAL, D,
67     MAJOR, C,
68     MINOR, B,
69     INFO, A);
70
71   private final MeasureRepository measureRepository;
72   private final ComponentIssuesRepository componentIssuesRepository;
73   private final PeriodsHolder periodsHolder;
74
75   private final Map<String, Metric> metricsByKey;
76
77   public NewReliabilityAndSecurityRatingMeasuresVisitor(MetricRepository metricRepository, MeasureRepository measureRepository, ComponentIssuesRepository componentIssuesRepository,
78     PeriodsHolder periodsHolder) {
79     super(LEAVES, POST_ORDER, CounterFactory.INSTANCE);
80     this.measureRepository = measureRepository;
81     this.componentIssuesRepository = componentIssuesRepository;
82     this.periodsHolder = periodsHolder;
83
84     // Output metrics
85     this.metricsByKey = ImmutableMap.of(
86       NEW_RELIABILITY_RATING_KEY, metricRepository.getByKey(NEW_RELIABILITY_RATING_KEY),
87       NEW_SECURITY_RATING_KEY, metricRepository.getByKey(NEW_SECURITY_RATING_KEY));
88   }
89
90   @Override
91   public void visitProject(Component project, Path<Counter> path) {
92     computeAndSaveMeasures(project, path);
93   }
94
95   @Override
96   public void visitDirectory(Component directory, Path<Counter> path) {
97     computeAndSaveMeasures(directory, path);
98   }
99
100   @Override
101   public void visitModule(Component module, Path<Counter> path) {
102     computeAndSaveMeasures(module, path);
103   }
104
105   @Override
106   public void visitFile(Component file, Path<Counter> path) {
107     computeAndSaveMeasures(file, path);
108   }
109
110   private void computeAndSaveMeasures(Component component, Path<Counter> path) {
111     if (!periodsHolder.hasPeriod()) {
112       return;
113     }
114     initRatingsToA(path);
115     processIssues(component, path);
116     path.current().newRatingValueByMetric.entrySet()
117       .stream()
118       .filter(entry -> entry.getValue().isSet())
119       .forEach(
120         entry -> measureRepository.add(
121           component,
122           metricsByKey.get(entry.getKey()),
123           newMeasureBuilder().setVariation(entry.getValue().getValue().getIndex()).createNoValue()));
124     addToParent(path);
125   }
126
127   private static void initRatingsToA(Path<Counter> path) {
128     path.current().newRatingValueByMetric.values().forEach(entry -> entry.increment(A));
129   }
130
131   private void processIssues(Component component, Path<Counter> path) {
132     componentIssuesRepository.getIssues(component)
133       .stream()
134       .filter(issue -> issue.resolution() == null)
135       .filter(issue -> issue.type().equals(BUG) || issue.type().equals(VULNERABILITY))
136       .forEach(issue -> path.current().processIssue(issue, periodsHolder.getPeriod()));
137   }
138
139   private static void addToParent(Path<Counter> path) {
140     if (!path.isRoot()) {
141       path.parent().add(path.current());
142     }
143   }
144
145   static final class Counter {
146     private Map<String, RatingValue> newRatingValueByMetric = ImmutableMap.of(
147       NEW_RELIABILITY_RATING_KEY, new RatingValue(),
148       NEW_SECURITY_RATING_KEY, new RatingValue());
149
150     private Counter() {
151       // prevents instantiation
152     }
153
154     void add(Counter otherCounter) {
155       newRatingValueByMetric.entrySet().forEach(e -> e.getValue().increment(otherCounter.newRatingValueByMetric.get(e.getKey())));
156     }
157
158     void processIssue(Issue issue, Period period) {
159       if (isOnPeriod((DefaultIssue) issue, period)) {
160         Rating rating = RATING_BY_SEVERITY.get(issue.severity());
161         if (issue.type().equals(BUG)) {
162           newRatingValueByMetric.get(NEW_RELIABILITY_RATING_KEY).increment(rating);
163         } else if (issue.type().equals(VULNERABILITY)) {
164           newRatingValueByMetric.get(NEW_SECURITY_RATING_KEY).increment(rating);
165         }
166       }
167     }
168
169     private static boolean isOnPeriod(DefaultIssue issue, Period period) {
170       // Add one second to not take into account issues created during current analysis
171       return issue.creationDate().getTime() >= period.getSnapshotDate() + 1000L;
172     }
173   }
174
175   private static final class CounterFactory extends SimpleStackElementFactory<NewReliabilityAndSecurityRatingMeasuresVisitor.Counter> {
176     public static final CounterFactory INSTANCE = new CounterFactory();
177
178     private CounterFactory() {
179       // prevents instantiation
180     }
181
182     @Override
183     public Counter createForAny(Component component) {
184       return new Counter();
185     }
186   }
187 }