3 * Copyright (C) 2009-2019 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.qualitygate;
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;
28 import static com.google.common.base.Preconditions.checkArgument;
29 import static java.util.Optional.of;
31 public final class ConditionEvaluator {
34 * Evaluates the condition for the specified measure
36 public EvaluationResult evaluate(Condition condition, Measure measure) {
37 checkArgument(condition.getMetric().getType() != Metric.MetricType.DATA, "Conditions on MetricType DATA are not supported");
39 Comparable measureComparable = parseMeasure(condition, measure);
40 if (measureComparable == null) {
41 return new EvaluationResult(Measure.Level.OK, null);
44 return evaluateCondition(condition, measureComparable, Measure.Level.ERROR)
45 .orElseGet(() -> evaluateCondition(condition, measureComparable, Measure.Level.WARN)
46 .orElseGet(() -> new EvaluationResult(Measure.Level.OK, measureComparable)));
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();
56 Comparable conditionComparable = parseConditionValue(condition.getMetric(), conditionValue);
57 if (doesReachThresholds(measureComparable, conditionComparable, condition)) {
58 return of(new EvaluationResult(alertLevel, measureComparable));
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()));
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();
74 throw new IllegalStateException(alertLevel.toString());
78 private static boolean doesReachThresholds(Comparable measureValue, Comparable criteriaValue, Condition condition) {
79 int comparison = measureValue.compareTo(criteriaValue);
80 switch (condition.getOperator()) {
82 return comparison == 0;
84 return comparison != 0;
86 return comparison > 0;
88 return comparison < 0;
90 throw new IllegalArgumentException(String.format("Unsupported operator '%s'", condition.getOperator()));
94 private static Comparable parseConditionValue(Metric metric, String value) {
95 switch (metric.getType().getValueType()) {
97 return Integer.parseInt(value) == 1;
99 return parseInteger(value);
101 return Long.parseLong(value);
103 return Double.parseDouble(value);
108 throw new IllegalArgumentException(String.format("Unsupported value type %s. Can not convert condition value", metric.getType().getValueType()));
112 private static Comparable<Integer> parseInteger(String value) {
113 return value.contains(".") ? Integer.parseInt(value.substring(0, value.indexOf('.'))) : Integer.parseInt(value);
117 private static Comparable parseMeasure(Condition condition, Measure measure) {
118 if (condition.useVariation()) {
119 return parseMeasureFromVariation(condition, measure);
121 switch (measure.getValueType()) {
123 return measure.getBooleanValue();
125 return measure.getIntValue();
127 return measure.getLongValue();
129 return measure.getDoubleValue();
131 return measure.getStringValue();
133 return measure.getLevelValue().name();
137 throw new IllegalArgumentException(
138 String.format("Unsupported measure ValueType %s. Can not parse measure to a Comparable", measure.getValueType()));
143 private static Comparable parseMeasureFromVariation(Condition condition, Measure measure) {
144 if (!measure.hasVariation()) {
148 Double variation = measure.getVariation();
149 Metric.MetricType metricType = condition.getMetric().getType();
150 switch (metricType.getValueType()) {
152 return variation.intValue() == 1;
154 return variation.intValue();
156 return variation.longValue();
163 throw new IllegalArgumentException("Unsupported metric type " + metricType);