import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import org.sonar.api.measures.Metric;
import org.sonar.api.measures.Metric.ValueType;
import org.sonar.db.component.ComponentDtoWithSnapshotId;
import org.sonar.db.measure.MeasureDto;
import static org.sonar.api.measures.Metric.ValueType.DISTRIB;
import static org.sonar.api.measures.Metric.ValueType.FLOAT;
import static org.sonar.api.measures.Metric.ValueType.INT;
-import static org.sonar.api.measures.Metric.ValueType.LEVEL;
import static org.sonar.api.measures.Metric.ValueType.MILLISEC;
import static org.sonar.api.measures.Metric.ValueType.PERCENT;
import static org.sonar.api.measures.Metric.ValueType.RATING;
class ComponentTreeSort {
private static final Set<ValueType> NUMERIC_VALUE_TYPES = EnumSet.of(BOOL, FLOAT, INT, MILLISEC, WORK_DUR, PERCENT, RATING);
- private static final Set<ValueType> TEXTUAL_VALUE_TYPES = EnumSet.of(DATA, DISTRIB, LEVEL, STRING);
+ private static final Set<ValueType> TEXTUAL_VALUE_TYPES = EnumSet.of(DATA, DISTRIB, STRING);
private ComponentTreeSort() {
// static method only
return numericalMetricOrdering(isAscending, metric, measuresByComponentUuidAndMetric);
} else if (TEXTUAL_VALUE_TYPES.contains(metricValueType)) {
return stringOrdering(isAscending, new ComponentDtoWithSnapshotIdToTextualMeasureValue(metric, measuresByComponentUuidAndMetric));
+ } else if (ValueType.LEVEL.equals(ValueType.valueOf(metric.getValueType()))) {
+ return levelMetricOrdering(isAscending, metric, measuresByComponentUuidAndMetric);
}
throw new IllegalStateException("Unrecognized metric value type: " + metric.getValueType());
return ordering.nullsLast().onResultOf(new ComponentDtoWithSnapshotIdToMeasureVariationValue(metric, measuresByComponentUuidAndMetric, request.getMetricPeriodSort()));
}
+ private static Ordering<ComponentDtoWithSnapshotId> levelMetricOrdering(boolean isAscending, @Nullable MetricDto metric,
+ Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric) {
+ Ordering<Integer> ordering = Ordering.natural();
+
+ // inverse the order of org.sonar.api.measures.Metric.Level
+ if (isAscending) {
+ ordering = ordering.reverse();
+ }
+
+ return ordering.nullsLast().onResultOf(new ComponentDtoWithSnapshotIdToLevelIndex(metric, measuresByComponentUuidAndMetric));
+ }
+
private static class ComponentDtoWithSnapshotIdToNumericalMeasureValue implements Function<ComponentDtoWithSnapshotId, Double> {
private final MetricDto metric;
private final Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric;
}
}
+ private static class ComponentDtoWithSnapshotIdToLevelIndex implements Function<ComponentDtoWithSnapshotId, Integer> {
+ private final MetricDto metric;
+ private final Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric;
+
+ private ComponentDtoWithSnapshotIdToLevelIndex(@Nullable MetricDto metric,
+ Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric) {
+ this.metric = metric;
+ this.measuresByComponentUuidAndMetric = measuresByComponentUuidAndMetric;
+ }
+
+ @Override
+ public Integer apply(@Nonnull ComponentDtoWithSnapshotId input) {
+ MeasureDto measure = measuresByComponentUuidAndMetric.get(input.uuid(), metric);
+ if (measure == null || measure.getData() == null) {
+ return null;
+ }
+
+ return Metric.Level.names().indexOf(measure.getData());
+ }
+ }
+
private static class ComponentDtoWithSnapshotIdToMeasureVariationValue implements Function<ComponentDtoWithSnapshotId, Double> {
private final MetricDto metric;
private final Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric;
import javax.annotation.Nullable;
import org.junit.Before;
import org.junit.Test;
+import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Metric.ValueType;
+import org.sonar.api.resources.Qualifiers;
import org.sonar.core.util.Uuids;
import org.sonar.db.component.ComponentDtoWithSnapshotId;
import org.sonar.db.measure.MeasureDto;
metrics = newArrayList(violationsMetric, sqaleIndexMetric);
- measuresByComponentUuidAndMetric = HashBasedTable.create(components.size(), 1);
+ measuresByComponentUuidAndMetric = HashBasedTable.create(components.size(), 2);
// same number than path field
double currentValue = 9;
for (ComponentDtoWithSnapshotId component : components) {
.containsExactly("path-9", "path-8", "path-7", "path-6", "path-5", "path-4", "path-3", "path-2", "path-1", "path-without-measure");
}
+ @Test
+ public void sort_by_alert_status_ascending() {
+ components = newArrayList(
+ newComponentWithoutSnapshotId("PROJECT OK 1", Qualifiers.PROJECT, "PROJECT_OK_PATH_1"),
+ newComponentWithoutSnapshotId("PROJECT WARN 1", Qualifiers.PROJECT, "PROJECT_WARN_PATH_1"),
+ newComponentWithoutSnapshotId("PROJECT ERROR 1", Qualifiers.PROJECT, "PROJECT_ERROR_PATH_1"),
+ newComponentWithoutSnapshotId("PROJECT OK 2", Qualifiers.PROJECT, "PROJECT_OK_PATH_2"),
+ newComponentWithoutSnapshotId("PROJECT WARN 2", Qualifiers.PROJECT, "PROJECT_WARN_PATH_2"),
+ newComponentWithoutSnapshotId("PROJECT ERROR 2", Qualifiers.PROJECT, "PROJECT_ERROR_PATH_2"));
+ metrics = singletonList(newMetricDto()
+ .setKey(CoreMetrics.ALERT_STATUS_KEY)
+ .setValueType(ValueType.LEVEL.name()));
+ measuresByComponentUuidAndMetric = HashBasedTable.create();
+ List<String> statuses = newArrayList("OK", "WARN", "ERROR");
+ for (int i = 0; i < components.size(); i++) {
+ ComponentDtoWithSnapshotId component = components.get(i);
+ String alertStatus = statuses.get(i % 3);
+ measuresByComponentUuidAndMetric.put(component.uuid(), metrics.get(0), new MeasureDto().setData(alertStatus));
+ }
+ ComponentTreeWsRequest wsRequest = newRequest(newArrayList(METRIC_SORT, NAME_SORT), true, CoreMetrics.ALERT_STATUS_KEY);
+
+ List<ComponentDtoWithSnapshotId> result = sortComponents(wsRequest);
+
+ assertThat(result).extracting("name").containsExactly(
+ "PROJECT ERROR 1", "PROJECT ERROR 2",
+ "PROJECT WARN 1", "PROJECT WARN 2",
+ "PROJECT OK 1", "PROJECT OK 2");
+ }
+
@Test
public void sort_by_numerical_metric_period_1_key_ascending() {
components.add(newComponentWithoutSnapshotId("name-without-measure", "qualifier-without-measure", "path-without-measure"));