]> source.dussan.org Git - sonarqube.git/blob
391c97d91c3e7970e437c2d7cb1565ebad2987cd
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2020 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.qualitygate.ws;
21
22 import com.google.gson.JsonArray;
23 import com.google.gson.JsonElement;
24 import com.google.gson.JsonObject;
25 import com.google.gson.JsonParser;
26 import java.util.Optional;
27 import java.util.function.Predicate;
28 import java.util.stream.StreamSupport;
29 import javax.annotation.Nullable;
30 import org.sonar.db.component.SnapshotDto;
31 import org.sonarqube.ws.Qualitygates.ProjectStatusResponse;
32
33 import static com.google.common.base.Strings.isNullOrEmpty;
34 import static org.sonar.api.utils.DateUtils.formatDateTime;
35
36 public class QualityGateDetailsFormatter {
37   private final Optional<String> optionalMeasureData;
38   private final Optional<SnapshotDto> optionalSnapshot;
39   private final ProjectStatusResponse.ProjectStatus.Builder projectStatusBuilder;
40
41   public QualityGateDetailsFormatter(Optional<String> measureData, Optional<SnapshotDto> snapshot) {
42     this.optionalMeasureData = measureData;
43     this.optionalSnapshot = snapshot;
44     this.projectStatusBuilder = ProjectStatusResponse.ProjectStatus.newBuilder();
45   }
46
47   public ProjectStatusResponse.ProjectStatus format() {
48     if (!optionalMeasureData.isPresent()) {
49       return newResponseWithoutQualityGateDetails();
50     }
51
52     JsonObject json = JsonParser.parseString(optionalMeasureData.get()).getAsJsonObject();
53
54     ProjectStatusResponse.Status qualityGateStatus = measureLevelToQualityGateStatus(json.get("level").getAsString());
55     projectStatusBuilder.setStatus(qualityGateStatus);
56
57     formatIgnoredConditions(json);
58     formatConditions(json.getAsJsonArray("conditions"));
59     formatPeriods();
60
61     return projectStatusBuilder.build();
62   }
63
64   private void formatIgnoredConditions(JsonObject json) {
65     JsonElement ignoredConditions = json.get("ignoredConditions");
66     if (ignoredConditions != null) {
67       projectStatusBuilder.setIgnoredConditions(ignoredConditions.getAsBoolean());
68     } else {
69       projectStatusBuilder.setIgnoredConditions(false);
70     }
71   }
72
73   private void formatPeriods() {
74     if (!optionalSnapshot.isPresent()) {
75       return;
76     }
77
78     ProjectStatusResponse.Period.Builder periodBuilder = ProjectStatusResponse.Period.newBuilder();
79     periodBuilder.clear();
80
81     SnapshotDto snapshot = this.optionalSnapshot.get();
82
83     if (isNullOrEmpty(snapshot.getPeriodMode())) {
84       return;
85     }
86     periodBuilder.setIndex(1);
87     periodBuilder.setMode(snapshot.getPeriodMode());
88     Long periodDate = snapshot.getPeriodDate();
89     if (periodDate != null) {
90       periodBuilder.setDate(formatDateTime(periodDate));
91     }
92     String periodModeParameter = snapshot.getPeriodModeParameter();
93     if (!isNullOrEmpty(periodModeParameter)) {
94       periodBuilder.setParameter(periodModeParameter);
95     }
96     projectStatusBuilder.addPeriods(periodBuilder);
97   }
98
99   private void formatConditions(@Nullable JsonArray jsonConditions) {
100     if (jsonConditions == null) {
101       return;
102     }
103
104     StreamSupport.stream(jsonConditions.spliterator(), false)
105       .map(JsonElement::getAsJsonObject)
106       .filter(isConditionOnValidPeriod())
107       .forEach(this::formatCondition);
108   }
109
110   private void formatCondition(JsonObject jsonCondition) {
111     ProjectStatusResponse.Condition.Builder conditionBuilder = ProjectStatusResponse.Condition.newBuilder();
112
113     formatConditionLevel(conditionBuilder, jsonCondition);
114     formatConditionMetric(conditionBuilder, jsonCondition);
115     formatConditionOperation(conditionBuilder, jsonCondition);
116     formatConditionPeriod(conditionBuilder, jsonCondition);
117     formatConditionWarningThreshold(conditionBuilder, jsonCondition);
118     formatConditionErrorThreshold(conditionBuilder, jsonCondition);
119     formatConditionActual(conditionBuilder, jsonCondition);
120
121     projectStatusBuilder.addConditions(conditionBuilder);
122   }
123
124   private static void formatConditionActual(ProjectStatusResponse.Condition.Builder conditionBuilder, JsonObject jsonCondition) {
125     JsonElement actual = jsonCondition.get("actual");
126     if (actual != null && !isNullOrEmpty(actual.getAsString())) {
127       conditionBuilder.setActualValue(actual.getAsString());
128     }
129   }
130
131   private static void formatConditionErrorThreshold(ProjectStatusResponse.Condition.Builder conditionBuilder, JsonObject jsonCondition) {
132     JsonElement error = jsonCondition.get("error");
133     if (error != null && !isNullOrEmpty(error.getAsString())) {
134       conditionBuilder.setErrorThreshold(error.getAsString());
135     }
136   }
137
138   private static void formatConditionWarningThreshold(ProjectStatusResponse.Condition.Builder conditionBuilder, JsonObject jsonCondition) {
139     JsonElement warning = jsonCondition.get("warning");
140     if (warning != null && !isNullOrEmpty(warning.getAsString())) {
141       conditionBuilder.setWarningThreshold(warning.getAsString());
142     }
143   }
144
145   private static void formatConditionPeriod(ProjectStatusResponse.Condition.Builder conditionBuilder, JsonObject jsonCondition) {
146     JsonElement periodIndex = jsonCondition.get("period");
147     if (periodIndex == null) {
148       return;
149     }
150     conditionBuilder.setPeriodIndex(periodIndex.getAsInt());
151   }
152
153   private static void formatConditionOperation(ProjectStatusResponse.Condition.Builder conditionBuilder, JsonObject jsonCondition) {
154     JsonElement op = jsonCondition.get("op");
155     if (op != null && !isNullOrEmpty(op.getAsString())) {
156       String stringOp = op.getAsString();
157       ProjectStatusResponse.Comparator comparator = measureOpToQualityGateComparator(stringOp);
158       conditionBuilder.setComparator(comparator);
159     }
160   }
161
162   private static void formatConditionMetric(ProjectStatusResponse.Condition.Builder conditionBuilder, JsonObject jsonCondition) {
163     JsonElement metric = jsonCondition.get("metric");
164     if (metric != null && !isNullOrEmpty(metric.getAsString())) {
165       conditionBuilder.setMetricKey(metric.getAsString());
166     }
167   }
168
169   private static void formatConditionLevel(ProjectStatusResponse.Condition.Builder conditionBuilder, JsonObject jsonCondition) {
170     JsonElement measureLevel = jsonCondition.get("level");
171     if (measureLevel != null && !isNullOrEmpty(measureLevel.getAsString())) {
172       conditionBuilder.setStatus(measureLevelToQualityGateStatus(measureLevel.getAsString()));
173     }
174   }
175
176   private static ProjectStatusResponse.Status measureLevelToQualityGateStatus(String measureLevel) {
177     for (ProjectStatusResponse.Status status : ProjectStatusResponse.Status.values()) {
178       if (status.name().equals(measureLevel)) {
179         return status;
180       }
181     }
182
183     throw new IllegalStateException(String.format("Unknown quality gate status '%s'", measureLevel));
184   }
185
186   private static ProjectStatusResponse.Comparator measureOpToQualityGateComparator(String measureOp) {
187     for (ProjectStatusResponse.Comparator comparator : ProjectStatusResponse.Comparator.values()) {
188       if (comparator.name().equals(measureOp)) {
189         return comparator;
190       }
191     }
192
193     throw new IllegalStateException(String.format("Unknown quality gate comparator '%s'", measureOp));
194   }
195
196   private static ProjectStatusResponse.ProjectStatus newResponseWithoutQualityGateDetails() {
197     return ProjectStatusResponse.ProjectStatus.newBuilder().setStatus(ProjectStatusResponse.Status.NONE).build();
198   }
199
200   private static Predicate<JsonObject> isConditionOnValidPeriod() {
201     return jsonCondition -> {
202       JsonElement periodIndex = jsonCondition.get("period");
203       if (periodIndex == null) {
204         return true;
205       }
206       int period = periodIndex.getAsInt();
207       // Ignore period that was set on non leak period (for retro compatibility with project that hasn't been analyzed since a while)
208       return period == 1;
209     };
210   }
211 }