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