]> source.dussan.org Git - sonarqube.git/blob
99633200d9fe0fa79b6595966fdf08c5fa8f6a64
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2019 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.ce.task.projectanalysis.qualitygate;
21
22 import java.util.Optional;
23 import javax.annotation.CheckForNull;
24 import org.apache.commons.lang.StringUtils;
25 import org.sonar.ce.task.projectanalysis.metric.Metric;
26 import org.sonar.ce.task.projectanalysis.measure.Measure;
27
28 import static com.google.common.base.Preconditions.checkArgument;
29 import static java.util.Optional.of;
30
31 public final class ConditionEvaluator {
32
33   /**
34    * Evaluates the condition for the specified measure
35    */
36   public EvaluationResult evaluate(Condition condition, Measure measure) {
37     checkArgument(condition.getMetric().getType() != Metric.MetricType.DATA, "Conditions on MetricType DATA are not supported");
38
39     Comparable measureComparable = parseMeasure(condition, measure);
40     if (measureComparable == null) {
41       return new EvaluationResult(Measure.Level.OK, null);
42     }
43
44     return evaluateCondition(condition, measureComparable, Measure.Level.ERROR)
45       .orElseGet(() -> evaluateCondition(condition, measureComparable, Measure.Level.WARN)
46         .orElseGet(() -> new EvaluationResult(Measure.Level.OK, measureComparable)));
47   }
48
49   private static Optional<EvaluationResult> evaluateCondition(Condition condition, Comparable<?> measureComparable, Measure.Level alertLevel) {
50     String conditionValue = getValueToEval(condition, alertLevel);
51     if (StringUtils.isEmpty(conditionValue)) {
52       return Optional.empty();
53     }
54
55     try {
56       Comparable conditionComparable = parseConditionValue(condition.getMetric(), conditionValue);
57       if (doesReachThresholds(measureComparable, conditionComparable, condition)) {
58         return of(new EvaluationResult(alertLevel, measureComparable));
59       }
60       return Optional.empty();
61     } catch (NumberFormatException badValueFormat) {
62       throw new IllegalArgumentException(String.format(
63         "Quality Gate: Unable to parse value '%s' to compare against %s",
64         conditionValue, condition.getMetric().getName()));
65     }
66   }
67
68   private static String getValueToEval(Condition condition, Measure.Level alertLevel) {
69     if (Measure.Level.ERROR.equals(alertLevel)) {
70       return condition.getErrorThreshold();
71     } else if (Measure.Level.WARN.equals(alertLevel)) {
72       return condition.getWarningThreshold();
73     } else {
74       throw new IllegalStateException(alertLevel.toString());
75     }
76   }
77
78   private static boolean doesReachThresholds(Comparable measureValue, Comparable criteriaValue, Condition condition) {
79     int comparison = measureValue.compareTo(criteriaValue);
80     switch (condition.getOperator()) {
81       case EQUALS:
82         return comparison == 0;
83       case NOT_EQUALS:
84         return comparison != 0;
85       case GREATER_THAN:
86         return comparison > 0;
87       case LESS_THAN:
88         return comparison < 0;
89       default:
90         throw new IllegalArgumentException(String.format("Unsupported operator '%s'", condition.getOperator()));
91     }
92   }
93
94   private static Comparable parseConditionValue(Metric metric, String value) {
95     switch (metric.getType().getValueType()) {
96       case BOOLEAN:
97         return Integer.parseInt(value) == 1;
98       case INT:
99         return parseInteger(value);
100       case LONG:
101         return Long.parseLong(value);
102       case DOUBLE:
103         return Double.parseDouble(value);
104       case STRING:
105       case LEVEL:
106         return value;
107       default:
108         throw new IllegalArgumentException(String.format("Unsupported value type %s. Can not convert condition value", metric.getType().getValueType()));
109     }
110   }
111
112   private static Comparable<Integer> parseInteger(String value) {
113     return value.contains(".") ? Integer.parseInt(value.substring(0, value.indexOf('.'))) : Integer.parseInt(value);
114   }
115
116   @CheckForNull
117   private static Comparable parseMeasure(Condition condition, Measure measure) {
118     if (condition.useVariation()) {
119       return parseMeasureFromVariation(condition, measure);
120     }
121     switch (measure.getValueType()) {
122       case BOOLEAN:
123         return measure.getBooleanValue();
124       case INT:
125         return measure.getIntValue();
126       case LONG:
127         return measure.getLongValue();
128       case DOUBLE:
129         return measure.getDoubleValue();
130       case STRING:
131         return measure.getStringValue();
132       case LEVEL:
133         return measure.getLevelValue().name();
134       case NO_VALUE:
135         return null;
136       default:
137         throw new IllegalArgumentException(
138           String.format("Unsupported measure ValueType %s. Can not parse measure to a Comparable", measure.getValueType()));
139     }
140   }
141
142   @CheckForNull
143   private static Comparable parseMeasureFromVariation(Condition condition, Measure measure) {
144     if (!measure.hasVariation()) {
145       return null;
146     }
147
148     Double variation = measure.getVariation();
149     Metric.MetricType metricType = condition.getMetric().getType();
150     switch (metricType.getValueType()) {
151       case BOOLEAN:
152         return variation.intValue() == 1;
153       case INT:
154         return variation.intValue();
155       case LONG:
156         return variation.longValue();
157       case DOUBLE:
158         return variation;
159       case NO_VALUE:
160       case STRING:
161       case LEVEL:
162       default:
163         throw new IllegalArgumentException("Unsupported metric type " + metricType);
164     }
165   }
166 }