]> source.dussan.org Git - sonarqube.git/blob
43057b08f93ae286c1fe9370a7e0a32241f89e2f
[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.base.Optional;
24 import com.google.common.collect.ImmutableMap;
25 import java.util.Map;
26 import org.sonar.api.ce.measure.Issue;
27 import org.sonar.api.measures.CoreMetrics;
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.RatingVariationValue;
31 import org.sonar.server.computation.task.projectanalysis.issue.ComponentIssuesRepository;
32 import org.sonar.server.computation.task.projectanalysis.measure.Measure;
33 import org.sonar.server.computation.task.projectanalysis.measure.MeasureRepository;
34 import org.sonar.server.computation.task.projectanalysis.metric.Metric;
35 import org.sonar.server.computation.task.projectanalysis.metric.MetricRepository;
36
37 import static org.sonar.api.measures.CoreMetrics.RELIABILITY_RATING_KEY;
38 import static org.sonar.api.measures.CoreMetrics.SECURITY_RATING_KEY;
39 import static org.sonar.api.rule.Severity.BLOCKER;
40 import static org.sonar.api.rule.Severity.CRITICAL;
41 import static org.sonar.api.rule.Severity.INFO;
42 import static org.sonar.api.rule.Severity.MAJOR;
43 import static org.sonar.api.rule.Severity.MINOR;
44 import static org.sonar.api.rules.RuleType.BUG;
45 import static org.sonar.api.rules.RuleType.VULNERABILITY;
46 import static org.sonar.server.computation.task.projectanalysis.component.ComponentVisitor.Order.POST_ORDER;
47 import static org.sonar.server.computation.task.projectanalysis.component.CrawlerDepthLimit.LEAVES;
48 import static org.sonar.server.computation.task.projectanalysis.measure.Measure.newMeasureBuilder;
49 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating;
50 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.A;
51 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.B;
52 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.C;
53 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.D;
54 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.E;
55 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.RatingGrid.Rating.valueOf;
56
57 /**
58  * Compute following measures :
59  * {@link CoreMetrics#RELIABILITY_RATING_KEY}
60  * {@link CoreMetrics#SECURITY_RATING_KEY}
61  */
62 public class ReliabilityAndSecurityRatingMeasuresVisitor extends PathAwareVisitorAdapter<ReliabilityAndSecurityRatingMeasuresVisitor.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
74   // Output metrics
75   private final Metric reliabilityRatingMetric;
76   private final Metric securityRatingMetric;
77
78   private final Map<String, Metric> metricsByKey;
79
80   public ReliabilityAndSecurityRatingMeasuresVisitor(MetricRepository metricRepository, MeasureRepository measureRepository, ComponentIssuesRepository componentIssuesRepository) {
81     super(LEAVES, POST_ORDER, CounterFactory.INSTANCE);
82     this.measureRepository = measureRepository;
83     this.componentIssuesRepository = componentIssuesRepository;
84
85     // Output metrics
86     this.reliabilityRatingMetric = metricRepository.getByKey(RELIABILITY_RATING_KEY);
87     this.securityRatingMetric = metricRepository.getByKey(SECURITY_RATING_KEY);
88
89     this.metricsByKey = ImmutableMap.of(
90       RELIABILITY_RATING_KEY, reliabilityRatingMetric,
91       SECURITY_RATING_KEY, securityRatingMetric);
92   }
93
94   @Override
95   public void visitProject(Component project, Path<Counter> path) {
96     computeAndSaveMeasures(project, path);
97   }
98
99   @Override
100   public void visitDirectory(Component directory, Path<Counter> path) {
101     computeAndSaveMeasures(directory, path);
102   }
103
104   @Override
105   public void visitModule(Component module, Path<Counter> path) {
106     computeAndSaveMeasures(module, path);
107   }
108
109   @Override
110   public void visitFile(Component file, Path<Counter> path) {
111     computeAndSaveMeasures(file, path);
112   }
113
114   @Override
115   public void visitView(Component view, Path<Counter> path) {
116     computeAndSaveMeasures(view, path);
117   }
118
119   @Override
120   public void visitSubView(Component subView, Path<Counter> path) {
121     computeAndSaveMeasures(subView, path);
122   }
123
124   @Override
125   public void visitProjectView(Component projectView, Path<Counter> path) {
126     path.parent().ratingValueByMetric.entrySet().forEach(entry -> {
127       Optional<Measure> ratingMeasure = measureRepository.getRawMeasure(projectView, metricsByKey.get(entry.getKey()));
128       if (ratingMeasure.isPresent()) {
129         entry.getValue().increment(valueOf(ratingMeasure.get().getData()));
130       }
131     });
132   }
133
134   private void computeAndSaveMeasures(Component component, Path<Counter> path) {
135     processIssues(component, path);
136     path.current().ratingValueByMetric.entrySet().forEach(
137       entry -> measureRepository.add(component, metricsByKey.get(entry.getKey()), createRatingMeasure(entry.getValue().getValue())));
138     addToParent(path);
139   }
140
141   private void processIssues(Component component, Path<Counter> path) {
142     componentIssuesRepository.getIssues(component)
143       .stream()
144       .filter(issue -> issue.resolution() == null)
145       .filter(issue -> issue.type().equals(BUG) || issue.type().equals(VULNERABILITY))
146       .forEach(path.current()::processIssue);
147   }
148
149   private static void addToParent(Path<Counter> path) {
150     if (!path.isRoot()) {
151       path.parent().add(path.current());
152     }
153   }
154
155   private static Measure createRatingMeasure(Rating rating) {
156     return newMeasureBuilder().create(rating.getIndex(), rating.name());
157   }
158
159   static final class Counter {
160     private Map<String, RatingVariationValue> ratingValueByMetric = ImmutableMap.of(
161       RELIABILITY_RATING_KEY, new RatingVariationValue(),
162       SECURITY_RATING_KEY, new RatingVariationValue());
163
164     private Counter() {
165       // prevents instantiation
166     }
167
168     void add(Counter otherCounter) {
169       ratingValueByMetric.entrySet().forEach(e -> e.getValue().increment(otherCounter.ratingValueByMetric.get(e.getKey())));
170     }
171
172     void processIssue(Issue issue) {
173       Rating rating = RATING_BY_SEVERITY.get(issue.severity());
174       if (issue.type().equals(BUG)) {
175         ratingValueByMetric.get(RELIABILITY_RATING_KEY).increment(rating);
176       } else if (issue.type().equals(VULNERABILITY)) {
177         ratingValueByMetric.get(SECURITY_RATING_KEY).increment(rating);
178       }
179     }
180   }
181
182   private static final class CounterFactory extends PathAwareVisitorAdapter.SimpleStackElementFactory<ReliabilityAndSecurityRatingMeasuresVisitor.Counter> {
183     public static final CounterFactory INSTANCE = new CounterFactory();
184
185     private CounterFactory() {
186       // prevents instantiation
187     }
188
189     @Override
190     public Counter createForAny(Component component) {
191       return new Counter();
192     }
193
194     /**
195      * Counter is not used at ProjectView level, saves on instantiating useless objects
196      */
197     @Override
198     public Counter createForProjectView(Component projectView) {
199       return null;
200     }
201   }
202 }