]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7135 WS api/measures/component_tree sort by textual metric value
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Thu, 14 Jan 2016 15:29:31 +0000 (16:29 +0100)
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Thu, 14 Jan 2016 17:53:45 +0000 (18:53 +0100)
server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeSort.java
server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeSortTest.java

index f2ccb842042b0d9779825e58cfd52a2e7eecd087..710d2196feb7615923f4d2c457bdd0b7b891aefd 100644 (file)
@@ -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<ComponentDtoWithSnapshotId> componentNameOrdering(boolean isAscending) {
-    return genericComponentFieldOrdering(isAscending, ComponentDtoWithSnapshotIdToName.INSTANCE);
+    return stringOrdering(isAscending, ComponentDtoWithSnapshotIdToName.INSTANCE);
   }
 
   private static Ordering<ComponentDtoWithSnapshotId> componentQualifierOrdering(boolean isAscending) {
-    return genericComponentFieldOrdering(isAscending, ComponentDtoWithSnapshotIdToQualifier.INSTANCE);
+    return stringOrdering(isAscending, ComponentDtoWithSnapshotIdToQualifier.INSTANCE);
   }
 
   private static Ordering<ComponentDtoWithSnapshotId> componentPathOrdering(boolean isAscending) {
-    return genericComponentFieldOrdering(isAscending, ComponentDtoWithSnapshotIdToPath.INSTANCE);
+    return stringOrdering(isAscending, ComponentDtoWithSnapshotIdToPath.INSTANCE);
   }
 
-  private static Ordering<ComponentDtoWithSnapshotId> genericComponentFieldOrdering(boolean isAscending, Function<ComponentDtoWithSnapshotId, String> function) {
+  private static Ordering<ComponentDtoWithSnapshotId> stringOrdering(boolean isAscending, Function<ComponentDtoWithSnapshotId, String> function) {
     Ordering<String> 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<ComponentDtoWithSnapshotId> metricOrdering(ComponentTreeWsRequest wsRequest, List<MetricDto> metrics,
+    Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric) {
+    if (wsRequest.getMetricSort()==null) {
+      return componentNameOrdering(wsRequest.getAsc());
+    }
+    Map<String, MetricDto> 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<ComponentDtoWithSnapshotId> numericalMetricOrdering(boolean isAscending, @Nullable MetricDto metric,
     Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric) {
     Ordering<Double> 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<ComponentDtoWithSnapshotId, Double> {
-    private final String metricKey;
-    private final Map<String, MetricDto> metricsByKey;
+  private static class ComponentDtoWithSnapshotIdToNumericalMeasureValue implements Function<ComponentDtoWithSnapshotId, Double> {
+    private final MetricDto metric;
     private final Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric;
 
-    private ComponentDtoWithSnapshotIdToMeasureValue(ComponentTreeWsRequest wsRequest, List<MetricDto> metrics,
+    private ComponentDtoWithSnapshotIdToNumericalMeasureValue(@Nullable MetricDto metric,
       Table<String, MetricDto, MeasureDto> 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<ComponentDtoWithSnapshotId, String> {
+    private final MetricDto metric;
+    private final Table<String, MetricDto, MeasureDto> measuresByComponentUuidAndMetric;
+
+    private ComponentDtoWithSnapshotIdToTextualMeasureValue(@Nullable MetricDto metric,
+      Table<String, MetricDto, MeasureDto> 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<ComponentDtoWithSnapshotId, String> {
     INSTANCE;
 
index 5341852e50b9040b92d9a44a1490a047d71fc683..eed4d78fc97632dd0b91e82c0e5dfa7d54edfbe2 100644 (file)
@@ -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<MetricDto> metrics;
   private Table<String, MetricDto, MeasureDto> 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<ComponentDtoWithSnapshotId> 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<ComponentDtoWithSnapshotId> result = sortComponents(wsRequest);