]> source.dussan.org Git - sonarqube.git/blob
dd40744a261d28448a96f90205905a5a5cd11a12
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2022 SonarSource SA
4  * mailto:info 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 package org.sonar.server.measure.live;
21
22 import java.util.Collection;
23 import java.util.HashSet;
24 import java.util.Map;
25 import java.util.Optional;
26 import java.util.OptionalDouble;
27 import java.util.Set;
28 import java.util.stream.Stream;
29 import org.sonar.api.config.Configuration;
30 import org.sonar.api.measures.CoreMetrics;
31 import org.sonar.api.measures.Metric;
32 import org.sonar.db.DbClient;
33 import org.sonar.db.DbSession;
34 import org.sonar.db.component.BranchDto;
35 import org.sonar.db.component.BranchType;
36 import org.sonar.db.component.ComponentDto;
37 import org.sonar.db.measure.LiveMeasureDto;
38 import org.sonar.db.metric.MetricDto;
39 import org.sonar.db.project.ProjectDto;
40 import org.sonar.db.qualitygate.QualityGateConditionDto;
41 import org.sonar.server.qualitygate.Condition;
42 import org.sonar.server.qualitygate.EvaluatedQualityGate;
43 import org.sonar.server.qualitygate.QualityGate;
44 import org.sonar.server.qualitygate.QualityGateConverter;
45 import org.sonar.server.qualitygate.QualityGateEvaluator;
46 import org.sonar.server.qualitygate.QualityGateFinder;
47 import org.sonar.server.qualitygate.QualityGateFinder.QualityGateData;
48
49 import static org.sonar.core.util.stream.MoreCollectors.toHashSet;
50 import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
51
52 public class LiveQualityGateComputerImpl implements LiveQualityGateComputer {
53
54   private final DbClient dbClient;
55   private final QualityGateFinder qGateFinder;
56   private final QualityGateEvaluator evaluator;
57
58   public LiveQualityGateComputerImpl(DbClient dbClient, QualityGateFinder qGateFinder, QualityGateEvaluator evaluator) {
59     this.dbClient = dbClient;
60     this.qGateFinder = qGateFinder;
61     this.evaluator = evaluator;
62   }
63
64   @Override
65   public QualityGate loadQualityGate(DbSession dbSession, ProjectDto project, BranchDto branch) {
66     QualityGateData qg = qGateFinder.getEffectiveQualityGate(dbSession, project);
67     Collection<QualityGateConditionDto> conditionDtos = dbClient.gateConditionDao().selectForQualityGate(dbSession, qg.getUuid());
68     Set<String> metricUuids = conditionDtos.stream().map(QualityGateConditionDto::getMetricUuid)
69       .collect(toHashSet(conditionDtos.size()));
70     Map<String, MetricDto> metricsByUuid = dbClient.metricDao().selectByUuids(dbSession, metricUuids).stream()
71       .collect(uniqueIndex(MetricDto::getUuid));
72
73     Stream<Condition> conditions = conditionDtos.stream().map(conditionDto -> {
74       String metricKey = metricsByUuid.get(conditionDto.getMetricUuid()).getKey();
75       Condition.Operator operator = Condition.Operator.fromDbValue(conditionDto.getOperator());
76       return new Condition(metricKey, operator, conditionDto.getErrorThreshold());
77     });
78
79     if (branch.getBranchType() == BranchType.PULL_REQUEST) {
80       conditions = conditions.filter(Condition::isOnLeakPeriod);
81     }
82
83     return new QualityGate(String.valueOf(qg.getUuid()), qg.getName(), conditions.collect(toHashSet(conditionDtos.size())));
84   }
85
86   @Override
87   public EvaluatedQualityGate refreshGateStatus(ComponentDto project, QualityGate gate, MeasureMatrix measureMatrix, Configuration configuration) {
88     QualityGateEvaluator.Measures measures = metricKey -> {
89       Optional<LiveMeasureDto> liveMeasureDto = measureMatrix.getMeasure(project, metricKey);
90       if (!liveMeasureDto.isPresent()) {
91         return Optional.empty();
92       }
93       MetricDto metric = measureMatrix.getMetricByUuid(liveMeasureDto.get().getMetricUuid());
94       return Optional.of(new LiveMeasure(liveMeasureDto.get(), metric));
95     };
96
97     EvaluatedQualityGate evaluatedGate = evaluator.evaluate(gate, measures, configuration);
98
99     measureMatrix.setValue(project, CoreMetrics.ALERT_STATUS_KEY, evaluatedGate.getStatus().name());
100     measureMatrix.setValue(project, CoreMetrics.QUALITY_GATE_DETAILS_KEY, QualityGateConverter.toJson(evaluatedGate));
101
102     return evaluatedGate;
103   }
104
105   @Override
106   public Set<String> getMetricsRelatedTo(QualityGate gate) {
107     Set<String> metricKeys = new HashSet<>();
108     metricKeys.add(CoreMetrics.ALERT_STATUS_KEY);
109     metricKeys.add(CoreMetrics.QUALITY_GATE_DETAILS_KEY);
110     metricKeys.addAll(evaluator.getMetricKeys(gate));
111     return metricKeys;
112   }
113
114   private static class LiveMeasure implements QualityGateEvaluator.Measure {
115     private final LiveMeasureDto dto;
116     private final MetricDto metric;
117
118     LiveMeasure(LiveMeasureDto dto, MetricDto metric) {
119       this.dto = dto;
120       this.metric = metric;
121     }
122
123     @Override
124     public Metric.ValueType getType() {
125       return Metric.ValueType.valueOf(metric.getValueType());
126     }
127
128     @Override
129     public OptionalDouble getValue() {
130       if (dto.getValue() == null) {
131         return OptionalDouble.empty();
132       }
133       return OptionalDouble.of(dto.getValue());
134     }
135
136     @Override
137     public Optional<String> getStringValue() {
138       return Optional.ofNullable(dto.getTextValue());
139     }
140
141     @Override
142     public OptionalDouble getNewMetricValue() {
143       if (dto.getVariation() == null) {
144         return OptionalDouble.empty();
145       }
146       return OptionalDouble.of(dto.getVariation());
147     }
148   }
149 }