3 * Copyright (C) 2009-2024 SonarSource SA
4 * mailto:info AT sonarsource DOT com
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.
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.
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.
20 package org.sonar.ce.task.projectanalysis.qualitymodel;
23 import org.sonar.api.issue.impact.Severity;
24 import org.sonar.api.issue.impact.SoftwareQuality;
25 import org.sonar.api.measures.CoreMetrics;
26 import org.sonar.ce.task.projectanalysis.component.Component;
27 import org.sonar.ce.task.projectanalysis.component.PathAwareVisitorAdapter;
28 import org.sonar.ce.task.projectanalysis.formula.counter.RatingValue;
29 import org.sonar.ce.task.projectanalysis.issue.ComponentIssuesRepository;
30 import org.sonar.ce.task.projectanalysis.measure.MeasureRepository;
31 import org.sonar.ce.task.projectanalysis.measure.RatingMeasures;
32 import org.sonar.ce.task.projectanalysis.metric.Metric;
33 import org.sonar.ce.task.projectanalysis.metric.MetricRepository;
34 import org.sonar.core.issue.DefaultIssue;
35 import org.sonar.server.measure.Rating;
36 import org.sonar.core.metric.SoftwareQualitiesMetrics;
38 import static org.sonar.api.measures.CoreMetrics.RELIABILITY_RATING_KEY;
39 import static org.sonar.api.measures.CoreMetrics.SECURITY_RATING_KEY;
40 import static org.sonar.api.rules.RuleType.BUG;
41 import static org.sonar.api.rules.RuleType.VULNERABILITY;
42 import static org.sonar.ce.task.projectanalysis.component.CrawlerDepthLimit.FILE;
43 import static org.sonar.server.measure.Rating.RATING_BY_SEVERITY;
44 import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_RATING_KEY;
45 import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_RATING_KEY;
48 * Compute following measures for projects and descendants:
49 * {@link CoreMetrics#RELIABILITY_RATING_KEY}
50 * {@link CoreMetrics#SECURITY_RATING_KEY}
51 * {@link SoftwareQualitiesMetrics#SOFTWARE_QUALITY_RELIABILITY_RATING_KEY}
52 * {@link SoftwareQualitiesMetrics#SOFTWARE_QUALITY_SECURITY_RATING_KEY}
54 public class ReliabilityAndSecurityRatingMeasuresVisitor extends PathAwareVisitorAdapter<ReliabilityAndSecurityRatingMeasuresVisitor.Counter> {
56 private final MeasureRepository measureRepository;
57 private final ComponentIssuesRepository componentIssuesRepository;
58 private final Map<String, Metric> metricsByKey;
60 public ReliabilityAndSecurityRatingMeasuresVisitor(MetricRepository metricRepository, MeasureRepository measureRepository, ComponentIssuesRepository componentIssuesRepository) {
61 super(FILE, Order.POST_ORDER, CounterFactory.INSTANCE);
62 this.measureRepository = measureRepository;
63 this.componentIssuesRepository = componentIssuesRepository;
66 Metric reliabilityRatingMetric = metricRepository.getByKey(RELIABILITY_RATING_KEY);
67 Metric securityRatingMetric = metricRepository.getByKey(SECURITY_RATING_KEY);
68 Metric softwareQualityReliabilityRatingMetric = metricRepository.getByKey(SOFTWARE_QUALITY_RELIABILITY_RATING_KEY);
69 Metric softwareQualitySecurityRatingMetric = metricRepository.getByKey(SOFTWARE_QUALITY_SECURITY_RATING_KEY);
71 this.metricsByKey = Map.of(
72 RELIABILITY_RATING_KEY, reliabilityRatingMetric,
73 SECURITY_RATING_KEY, securityRatingMetric,
74 SOFTWARE_QUALITY_RELIABILITY_RATING_KEY, softwareQualityReliabilityRatingMetric,
75 SOFTWARE_QUALITY_SECURITY_RATING_KEY, softwareQualitySecurityRatingMetric)
80 public void visitProject(Component project, Path<Counter> path) {
81 computeAndSaveMeasures(project, path);
85 public void visitDirectory(Component directory, Path<Counter> path) {
86 computeAndSaveMeasures(directory, path);
90 public void visitFile(Component file, Path<Counter> path) {
91 computeAndSaveMeasures(file, path);
94 private void computeAndSaveMeasures(Component component, Path<Counter> path) {
95 processIssues(component, path);
96 path.current().ratingValueByMetric.forEach((key, value) -> {
97 Rating rating = value.getValue();
98 measureRepository.add(component, metricsByKey.get(key), RatingMeasures.get(rating));
100 if (!path.isRoot()) {
101 path.parent().add(path.current());
105 private void processIssues(Component component, Path<Counter> path) {
106 componentIssuesRepository.getIssues(component)
108 .filter(issue -> issue.resolution() == null)
110 processIssue(path, issue);
114 private static void processIssue(Path<Counter> path, DefaultIssue issue) {
115 Rating rating = RATING_BY_SEVERITY.get(issue.severity());
116 if (issue.type().equals(BUG)) {
117 path.current().ratingValueByMetric.get(RELIABILITY_RATING_KEY).increment(rating);
118 } else if (issue.type().equals(VULNERABILITY)) {
119 path.current().ratingValueByMetric.get(SECURITY_RATING_KEY).increment(rating);
122 processSoftwareQualityRating(path, issue, SoftwareQuality.RELIABILITY, SOFTWARE_QUALITY_RELIABILITY_RATING_KEY);
123 processSoftwareQualityRating(path, issue, SoftwareQuality.SECURITY, SOFTWARE_QUALITY_SECURITY_RATING_KEY);
126 private static void processSoftwareQualityRating(Path<Counter> path, DefaultIssue issue, SoftwareQuality softwareQuality, String metricKey) {
127 Severity severity = issue.impacts().get(softwareQuality);
128 if (severity != null) {
129 Rating rating = Rating.RATING_BY_SOFTWARE_QUALITY_SEVERITY.get(severity);
131 if (rating != null) {
132 path.current().ratingValueByMetric.get(metricKey).increment(rating);
137 static final class Counter {
138 private final Map<String, RatingValue> ratingValueByMetric = Map.of(
139 RELIABILITY_RATING_KEY, new RatingValue(),
140 SECURITY_RATING_KEY, new RatingValue(),
141 SOFTWARE_QUALITY_RELIABILITY_RATING_KEY, new RatingValue(),
142 SOFTWARE_QUALITY_SECURITY_RATING_KEY, new RatingValue());
145 // prevents instantiation
148 void add(Counter otherCounter) {
149 ratingValueByMetric.forEach((key, value) -> value.increment(otherCounter.ratingValueByMetric.get(key)));
154 private static final class CounterFactory extends PathAwareVisitorAdapter.SimpleStackElementFactory<ReliabilityAndSecurityRatingMeasuresVisitor.Counter> {
155 public static final CounterFactory INSTANCE = new CounterFactory();
157 private CounterFactory() {
158 // prevents instantiation
162 public Counter createForAny(Component component) {
163 return new Counter();