diff options
3 files changed, 78 insertions, 10 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 1f7141e72e5..8b2d4c831fe 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 @@ -30,6 +30,7 @@ import java.util.Map; 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; @@ -45,7 +46,6 @@ import static org.sonar.api.measures.Metric.ValueType.DATA; 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; @@ -60,7 +60,7 @@ import static org.sonar.server.measure.ws.ComponentTreeAction.QUALIFIER_SORT; 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 @@ -129,6 +129,8 @@ class ComponentTreeSort { 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()); @@ -172,6 +174,18 @@ class ComponentTreeSort { 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; @@ -193,6 +207,27 @@ class ComponentTreeSort { } } + 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; 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 f57686501eb..af5da066369 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,7 +25,9 @@ import java.util.List; 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; @@ -72,7 +74,7 @@ public class ComponentTreeSortTest { 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) { @@ -136,6 +138,35 @@ public class ComponentTreeSortTest { } @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")); ComponentTreeWsRequest wsRequest = newRequest(singletonList(METRIC_PERIOD_SORT), true, NUM_METRIC_KEY).setMetricPeriodSort(1); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java index cf139075a5b..d27e62e34ae 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java @@ -105,6 +105,14 @@ public class Metric<G extends Serializable> implements Serializable, org.sonar.a public enum Level { OK("Green"), WARN("Orange"), ERROR("Red"); + private static final List<String> NAMES = Lists.transform(Arrays.asList(values()), new Function<Level, String>() { + @Nonnull + @Override + public String apply(@Nonnull Level level) { + return level.name(); + } + }); + private String colorName; Level(String colorName) { @@ -116,13 +124,7 @@ public class Metric<G extends Serializable> implements Serializable, org.sonar.a } public static List<String> names() { - return Lists.transform(Arrays.asList(values()), new Function<Level, String>() { - @Nonnull - @Override - public String apply(@Nonnull Level level) { - return level.name(); - } - }); + return NAMES; } } |