From dbfc8cfb5b9bba4683959e68743957b06db1e399 Mon Sep 17 00:00:00 2001 From: Teryk Bellahsene Date: Thu, 14 Jan 2016 16:29:31 +0100 Subject: [PATCH] SONAR-7135 WS api/measures/component_tree sort by textual metric value --- .../server/measure/ws/ComponentTreeSort.java | 76 +++++++++++++++---- .../measure/ws/ComponentTreeSortTest.java | 31 ++++++-- 2 files changed, 87 insertions(+), 20 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeSort.java b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeSort.java index f2ccb842042..710d2196feb 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeSort.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeSort.java @@ -27,6 +27,8 @@ import com.google.common.collect.Table; import java.util.List; import java.util.Map; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.sonar.api.measures.Metric.ValueType; import org.sonar.db.component.ComponentDtoWithSnapshotId; import org.sonar.db.measure.MeasureDto; import org.sonar.db.metric.MetricDto; @@ -73,18 +75,18 @@ class ComponentTreeSort { } private static Ordering componentNameOrdering(boolean isAscending) { - return genericComponentFieldOrdering(isAscending, ComponentDtoWithSnapshotIdToName.INSTANCE); + return stringOrdering(isAscending, ComponentDtoWithSnapshotIdToName.INSTANCE); } private static Ordering componentQualifierOrdering(boolean isAscending) { - return genericComponentFieldOrdering(isAscending, ComponentDtoWithSnapshotIdToQualifier.INSTANCE); + return stringOrdering(isAscending, ComponentDtoWithSnapshotIdToQualifier.INSTANCE); } private static Ordering componentPathOrdering(boolean isAscending) { - return genericComponentFieldOrdering(isAscending, ComponentDtoWithSnapshotIdToPath.INSTANCE); + return stringOrdering(isAscending, ComponentDtoWithSnapshotIdToPath.INSTANCE); } - private static Ordering genericComponentFieldOrdering(boolean isAscending, Function function) { + private static Ordering stringOrdering(boolean isAscending, Function function) { Ordering ordering = Ordering.from(CASE_INSENSITIVE_ORDER) .nullsLast(); if (!isAscending) { @@ -96,35 +98,60 @@ class ComponentTreeSort { /** * Order by measure value, taking the metric direction into account - * Metric direction is taken into account in {@link ComponentDtoWithSnapshotIdToMeasureValue} + * Metric direction is taken into account in {@link ComponentDtoWithSnapshotIdToNumericalMeasureValue} */ private static Ordering metricOrdering(ComponentTreeWsRequest wsRequest, List metrics, + Table measuresByComponentUuidAndMetric) { + if (wsRequest.getMetricSort()==null) { + return componentNameOrdering(wsRequest.getAsc()); + } + Map metricsByKey = Maps.uniqueIndex(metrics, MetricDtoFunctions.toKey()); + MetricDto metric = metricsByKey.get(wsRequest.getMetricSort()); + + boolean isAscending = wsRequest.getAsc(); + switch (ValueType.valueOf(metric.getValueType())) { + case BOOL: + case INT: + case MILLISEC: + case WORK_DUR: + case FLOAT: + case PERCENT: + case RATING: + return numericalMetricOrdering(isAscending, metric, measuresByComponentUuidAndMetric); + case DATA: + case DISTRIB: + case LEVEL: + case STRING: + return stringOrdering(isAscending, new ComponentDtoWithSnapshotIdToTextualMeasureValue(metric, measuresByComponentUuidAndMetric)); + default: + throw new IllegalStateException("Unrecognized metric value type: " + metric.getValueType()); + } + } + + private static Ordering numericalMetricOrdering(boolean isAscending, @Nullable MetricDto metric, Table measuresByComponentUuidAndMetric) { Ordering ordering = Ordering.natural() .nullsLast(); - if (!wsRequest.getAsc()) { + if (!isAscending) { ordering = ordering.reverse(); } - return ordering.onResultOf(new ComponentDtoWithSnapshotIdToMeasureValue(wsRequest, metrics, measuresByComponentUuidAndMetric)); + return ordering.onResultOf(new ComponentDtoWithSnapshotIdToNumericalMeasureValue(metric, measuresByComponentUuidAndMetric)); } - private static class ComponentDtoWithSnapshotIdToMeasureValue implements Function { - private final String metricKey; - private final Map metricsByKey; + private static class ComponentDtoWithSnapshotIdToNumericalMeasureValue implements Function { + private final MetricDto metric; private final Table measuresByComponentUuidAndMetric; - private ComponentDtoWithSnapshotIdToMeasureValue(ComponentTreeWsRequest wsRequest, List metrics, + private ComponentDtoWithSnapshotIdToNumericalMeasureValue(@Nullable MetricDto metric, Table measuresByComponentUuidAndMetric) { - this.metricKey = wsRequest.getMetricSort(); - this.metricsByKey = Maps.uniqueIndex(metrics, MetricDtoFunctions.toKey()); + this.metric = metric; this.measuresByComponentUuidAndMetric = measuresByComponentUuidAndMetric; } @Override public Double apply(@Nonnull ComponentDtoWithSnapshotId input) { - MetricDto metric = metricsByKey.get(metricKey); MeasureDto measure = measuresByComponentUuidAndMetric.get(input.uuid(), metric); if (measure == null || measure.getValue() == null) { return null; @@ -134,6 +161,27 @@ class ComponentTreeSort { } } + private static class ComponentDtoWithSnapshotIdToTextualMeasureValue implements Function { + private final MetricDto metric; + private final Table measuresByComponentUuidAndMetric; + + private ComponentDtoWithSnapshotIdToTextualMeasureValue(@Nullable MetricDto metric, + Table measuresByComponentUuidAndMetric) { + this.metric = metric; + this.measuresByComponentUuidAndMetric = measuresByComponentUuidAndMetric; + } + + @Override + public String apply(@Nonnull ComponentDtoWithSnapshotId input) { + MeasureDto measure = measuresByComponentUuidAndMetric.get(input.uuid(), metric); + if (measure == null || measure.getData() == null) { + return null; + } + + return measure.getData(); + } + } + private enum ComponentDtoWithSnapshotIdToName implements Function { INSTANCE; diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeSortTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeSortTest.java index 5341852e50b..eed4d78fc97 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeSortTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeSortTest.java @@ -25,6 +25,7 @@ import java.util.List; import javax.annotation.Nullable; import org.junit.Before; import org.junit.Test; +import org.sonar.api.measures.Metric.ValueType; import org.sonar.core.util.Uuids; import org.sonar.db.component.ComponentDtoWithSnapshotId; import org.sonar.db.measure.MeasureDto; @@ -41,7 +42,8 @@ import static org.sonar.server.measure.ws.ComponentTreeAction.PATH_SORT; import static org.sonar.server.measure.ws.ComponentTreeAction.QUALIFIER_SORT; public class ComponentTreeSortTest { - private static final String METRIC_KEY = "violations"; + private static final String NUM_METRIC_KEY = "violations"; + private static final String TEXT_METRIC_KEY = "sqale_index"; private List metrics; private Table measuresByComponentUuidAndMetric; @@ -60,14 +62,21 @@ public class ComponentTreeSortTest { newComponentWithoutSnapshotId("name-9", "qualifier-9", "path-2"), newComponentWithoutSnapshotId("name-8", "qualifier-1", "path-1")); - MetricDto metric = newMetricDto().setKey(METRIC_KEY).setDirection(1); - metrics = newArrayList(metric); + MetricDto violationsMetric = newMetricDto() + .setKey(NUM_METRIC_KEY) + .setValueType(ValueType.INT.name()); + MetricDto sqaleIndexMetric = newMetricDto() + .setKey(TEXT_METRIC_KEY) + .setValueType(ValueType.DATA.name()); + + metrics = newArrayList(violationsMetric, sqaleIndexMetric); measuresByComponentUuidAndMetric = HashBasedTable.create(components.size(), 1); // same number than path field double currentValue = 9; for (ComponentDtoWithSnapshotId component : components) { - measuresByComponentUuidAndMetric.put(component.uuid(), metric, new MeasureDto().setValue(currentValue)); + measuresByComponentUuidAndMetric.put(component.uuid(), violationsMetric, new MeasureDto().setValue(currentValue)); + measuresByComponentUuidAndMetric.put(component.uuid(), sqaleIndexMetric, new MeasureDto().setData(String.valueOf(currentValue))); currentValue--; } } @@ -102,8 +111,18 @@ public class ComponentTreeSortTest { } @Test - public void sort_by_metric_key() { - ComponentTreeWsRequest wsRequest = newRequest(singletonList(METRIC_SORT), true, METRIC_KEY); + public void sort_by_numerical_metric_key() { + ComponentTreeWsRequest wsRequest = newRequest(singletonList(METRIC_SORT), true, NUM_METRIC_KEY); + + List result = sortComponents(wsRequest); + + assertThat(result).extracting("path") + .containsExactly("path-1", "path-2", "path-3", "path-4", "path-5", "path-6", "path-7", "path-8", "path-9"); + } + + @Test + public void sort_by_textual_metric_key() { + ComponentTreeWsRequest wsRequest = newRequest(singletonList(METRIC_SORT), true, TEXT_METRIC_KEY); List result = sortComponents(wsRequest); -- 2.39.5