]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8120 api/measures/search now accepts only project keys
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Wed, 2 Nov 2016 11:00:05 +0000 (12:00 +0100)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Thu, 3 Nov 2016 14:35:15 +0000 (15:35 +0100)
server/sonar-server/src/main/java/org/sonar/server/measure/ws/SearchAction.java
server/sonar-server/src/main/resources/org/sonar/server/measure/ws/search-example.json
server/sonar-server/src/test/java/org/sonar/server/measure/ws/SearchActionTest.java
server/sonar-web/src/main/js/api/measures.js
server/sonar-web/src/main/js/apps/projects/store/actions.js
sonar-ws/src/main/java/org/sonarqube/ws/client/measure/MeasuresWsParameters.java
sonar-ws/src/main/java/org/sonarqube/ws/client/measure/SearchRequest.java
sonar-ws/src/test/java/org/sonarqube/ws/client/measure/SearchRequestTest.java

index 979ecd7f1d4017144c934c7e699a9280215569c3..5ec548b0722dfedcffad2d8c4e7488e91a3373a1 100644 (file)
 
 package org.sonar.server.measure.ws;
 
-import com.google.common.collect.ImmutableMultimap;
-import com.google.common.collect.ImmutableTable;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Table;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.stream.Collector;
-import java.util.stream.Stream;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
@@ -41,36 +34,27 @@ import org.sonar.core.util.stream.Collectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.SnapshotDto;
 import org.sonar.db.measure.MeasureDto;
 import org.sonar.db.measure.MeasureQuery;
 import org.sonar.db.metric.MetricDto;
 import org.sonar.server.user.UserSession;
-import org.sonarqube.ws.WsMeasures;
 import org.sonarqube.ws.WsMeasures.Measure;
 import org.sonarqube.ws.WsMeasures.SearchWsResponse;
 import org.sonarqube.ws.client.measure.SearchRequest;
 
 import static java.util.Comparator.comparing;
-import static java.util.Objects.requireNonNull;
 import static java.util.function.Function.identity;
 import static java.util.stream.Collectors.toMap;
 import static org.sonar.core.util.stream.Collectors.toList;
-import static org.sonar.core.util.stream.Collectors.toSet;
 import static org.sonar.core.util.stream.Collectors.uniqueIndex;
 import static org.sonar.server.measure.ws.MeasureDtoToWsMeasure.dbToWsMeasure;
 import static org.sonar.server.measure.ws.MeasuresWsParametersBuilder.createMetricKeysParameter;
-import static org.sonar.server.measure.ws.MetricDtoWithBestValue.buildBestMeasure;
-import static org.sonar.server.measure.ws.MetricDtoWithBestValue.isEligibleForBestValue;
-import static org.sonar.server.measure.ws.SnapshotDtoToWsPeriods.snapshotToWsPeriods;
-import static org.sonar.server.ws.KeyExamples.KEY_FILE_EXAMPLE_001;
-import static org.sonar.server.ws.KeyExamples.KEY_FILE_EXAMPLE_002;
 import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
 import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_002;
 import static org.sonar.server.ws.WsUtils.checkRequest;
 import static org.sonar.server.ws.WsUtils.writeProtobuf;
-import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_COMPONENT_KEYS;
 import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_METRIC_KEYS;
+import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_PROJECT_KEYS;
 
 public class SearchAction implements MeasuresWsAction {
 
@@ -86,24 +70,19 @@ public class SearchAction implements MeasuresWsAction {
   public void define(WebService.NewController context) {
     WebService.NewAction action = context.createAction("search")
       .setInternal(true)
-      .setDescription("Search for component measures ordered by component names.<br>" +
-        "At most %d components can be provided.<br>" +
-        "Requires one of the following permissions:" +
-        "<ul>" +
-        " <li>'Administer System'</li>" +
-        " <li>'Administer' rights on the provided components</li>" +
-        " <li>'Browse' on the provided components</li>" +
-        "</ul>",
-        SearchRequest.MAX_NB_COMPONENTS)
+      .setDescription("Search for project measures ordered by project names.<br>" +
+        "At most %d projects can be provided.<br>" +
+        "Requires 'Browse' on the provided projects",
+        SearchRequest.MAX_NB_PROJECTS)
       .setSince("6.2")
       .setResponseExample(getClass().getResource("search-example.json"))
       .setHandler(this);
 
     createMetricKeysParameter(action);
 
-    action.createParam(PARAM_COMPONENT_KEYS)
-      .setDescription("Comma-separated list of component keys")
-      .setExampleValue(String.join(",", KEY_PROJECT_EXAMPLE_001, KEY_FILE_EXAMPLE_001, KEY_PROJECT_EXAMPLE_002, KEY_FILE_EXAMPLE_002))
+    action.createParam(PARAM_PROJECT_KEYS)
+      .setDescription("Comma-separated list of project keys")
+      .setExampleValue(String.join(",", KEY_PROJECT_EXAMPLE_001, KEY_PROJECT_EXAMPLE_002))
       .setRequired(true);
   }
 
@@ -120,10 +99,9 @@ public class SearchAction implements MeasuresWsAction {
     private final DbSession dbSession;
     private final Request httpRequest;
     private SearchRequest request;
-    private List<ComponentDto> components;
+    private List<ComponentDto> projects;
     private List<MetricDto> metrics;
     private List<MeasureDto> measures;
-    private List<SnapshotDto> snapshots;
 
     ResponseBuilder(Request httpRequest, DbSession dbSession) {
       this.dbSession = dbSession;
@@ -132,32 +110,22 @@ public class SearchAction implements MeasuresWsAction {
 
     SearchWsResponse build() {
       this.request = createRequest();
-      this.components = searchComponents();
+      this.projects = searchProjects();
       this.metrics = searchMetrics();
       this.measures = searchMeasures();
-      this.snapshots = searchSnapshots();
-
       return buildResponse();
     }
 
-    private List<SnapshotDto> searchSnapshots() {
-      requireNonNull(components);
-
-      Set<String> projectUuids = components.stream().map(ComponentDto::projectUuid).collect(toSet());
-      return dbClient.snapshotDao().selectLastAnalysesByRootComponentUuids(dbSession, projectUuids);
-    }
-
     private SearchRequest createRequest() {
       request = SearchRequest.builder()
         .setMetricKeys(httpRequest.mandatoryParamAsStrings(PARAM_METRIC_KEYS))
-        .setComponentKeys(httpRequest.paramAsStrings(PARAM_COMPONENT_KEYS))
+        .setProjectKeys(httpRequest.paramAsStrings(PARAM_PROJECT_KEYS))
         .build();
 
       return request;
     }
 
     private List<MetricDto> searchMetrics() {
-      requireNonNull(request);
       List<MetricDto> dbMetrics = dbClient.metricDao().selectByKeys(dbSession, request.getMetricKeys());
       List<String> metricKeys = dbMetrics.stream().map(MetricDto::getKey).collect(toList());
       checkRequest(request.getMetricKeys().size() == dbMetrics.size(), "The following metrics are not found: %s",
@@ -165,33 +133,27 @@ public class SearchAction implements MeasuresWsAction {
       return dbMetrics;
     }
 
-    private List<ComponentDto> searchComponents() {
-      requireNonNull(request);
-      return getAuthorizedComponents(searchByComponentKeys(dbSession, request.getComponentKeys()));
+    private List<ComponentDto> searchProjects() {
+      return getAuthorizedProjects(searchByProjectKeys(dbSession, request.getProjectKeys()));
     }
 
-    private List<ComponentDto> getAuthorizedComponents(List<ComponentDto> componentDtos) {
-      List<String> projectUuids = componentDtos.stream().map(ComponentDto::getRootUuid).collect(Collectors.toList());
-      List<ComponentDto> projects = dbClient.componentDao().selectByUuids(dbSession, projectUuids);
-      Map<String, Long> projectIdsByUuids = projects.stream().collect(uniqueIndex(ComponentDto::uuid, ComponentDto::getId));
+    private List<ComponentDto> getAuthorizedProjects(List<ComponentDto> projectDtos) {
+      Map<String, Long> projectIdsByUuids = projectDtos.stream().collect(uniqueIndex(ComponentDto::uuid, ComponentDto::getId));
       Collection<Long> authorizedProjectIds = dbClient.authorizationDao().keepAuthorizedProjectIds(dbSession,
-        projects.stream().map(ComponentDto::getId).collect(toList()),
+        projectDtos.stream().map(ComponentDto::getId).collect(toList()),
         userSession.getUserId(), UserRole.USER);
-      return componentDtos.stream()
+      return projectDtos.stream()
         .filter(c -> authorizedProjectIds.contains(projectIdsByUuids.get(c.projectUuid())))
         .collect(Collectors.toList());
     }
 
-    private List<ComponentDto> searchByComponentKeys(DbSession dbSession, List<String> componentKeys) {
-      return dbClient.componentDao().selectByKeys(dbSession, componentKeys);
+    private List<ComponentDto> searchByProjectKeys(DbSession dbSession, List<String> projectKeys) {
+      return dbClient.componentDao().selectByKeys(dbSession, projectKeys);
     }
 
     private List<MeasureDto> searchMeasures() {
-      requireNonNull(components);
-      requireNonNull(metrics);
-
       return dbClient.measureDao().selectByQuery(dbSession, MeasureQuery.builder()
-        .setComponentUuids(components.stream().map(ComponentDto::uuid).collect(toList()))
+        .setComponentUuids(projects.stream().map(ComponentDto::uuid).collect(toList()))
         .setMetricIds(metrics.stream().map(MetricDto::getId).collect(toList()))
         .build());
     }
@@ -206,11 +168,6 @@ public class SearchAction implements MeasuresWsAction {
     }
 
     private SearchWsResponse buildResponse() {
-      requireNonNull(metrics);
-      requireNonNull(measures);
-      requireNonNull(components);
-      requireNonNull(snapshots);
-
       List<Measure> wsMeasures = buildWsMeasures();
       return SearchWsResponse.newBuilder()
         .addAllMeasures(wsMeasures)
@@ -218,49 +175,18 @@ public class SearchAction implements MeasuresWsAction {
     }
 
     private List<Measure> buildWsMeasures() {
-      Map<String, ComponentDto> componentsByUuid = components.stream().collect(toMap(ComponentDto::uuid, Function.identity()));
-      Map<String, String> componentNamesByKey = components.stream().collect(toMap(ComponentDto::key, ComponentDto::name));
+      Map<String, ComponentDto> componentsByUuid = projects.stream().collect(toMap(ComponentDto::uuid, Function.identity()));
+      Map<String, String> componentNamesByKey = projects.stream().collect(toMap(ComponentDto::key, ComponentDto::name));
       Map<Integer, MetricDto> metricsById = metrics.stream().collect(toMap(MetricDto::getId, identity()));
 
       Function<MeasureDto, MetricDto> dbMeasureToDbMetric = dbMeasure -> metricsById.get(dbMeasure.getMetricId());
       Function<Measure, String> byMetricKey = Measure::getMetric;
       Function<Measure, String> byComponentName = wsMeasure -> componentNamesByKey.get(wsMeasure.getComponent());
 
-      return Stream
-        .concat(measures.stream(), buildBestMeasures().stream())
+      return measures.stream()
         .map(dbMeasure -> dbToWsMeasure(dbMeasure, dbMeasureToDbMetric.apply(dbMeasure), componentsByUuid.get(dbMeasure.getComponentUuid())))
         .sorted(comparing(byMetricKey).thenComparing(byComponentName))
         .collect(toList());
     }
-
-    private List<MeasureDto> buildBestMeasures() {
-      Set<MetricDto> metricsWithBestValue = metrics.stream()
-        .filter(metric -> metric.isOptimizedBestValue() && metric.getBestValue() != null)
-        .collect(toSet());
-
-      Multimap<String, WsMeasures.Period> wsPeriodsByProjectUuid = snapshots.stream().collect(Collector.of(
-        ImmutableMultimap::<String, WsMeasures.Period>builder,
-        (result, snapshot) -> result.putAll(snapshot.getComponentUuid(), snapshotToWsPeriods(snapshot)),
-        (result1, result2) -> {
-          throw new IllegalStateException("Parallel execution forbidden");
-        },
-        ImmutableMultimap.Builder::build));
-
-      Table<String, Integer, MeasureDto> measuresByComponentUuidAndMetricId = measures.stream().collect(Collector.of(
-        ImmutableTable::<String, Integer, MeasureDto>builder,
-        (result, measure) -> result.put(measure.getComponentUuid(), measure.getMetricId(), measure),
-        (result1, result2) -> {
-          throw new IllegalStateException("Parallel execution forbidden");
-        },
-        ImmutableTable.Builder::build));
-
-      Function<ComponentDto, Predicate<MetricDto>> doesNotHaveAMeasureInDb = component -> metric -> !measuresByComponentUuidAndMetricId.contains(component.uuid(), metric.getId());
-      return components.stream()
-        .filter(isEligibleForBestValue())
-        .flatMap(component -> metricsWithBestValue.stream()
-          .filter(doesNotHaveAMeasureInDb.apply(component))
-          .map(buildBestMeasure(component, wsPeriodsByProjectUuid.get(component.projectUuid()))))
-        .collect(toList());
-    }
   }
 }
index 1e1d801ff89a4930a8796d0e8178b479c2f82b64..4c7d34ef4df89da6b389a30136b077ee715210a6 100644 (file)
@@ -3,12 +3,7 @@
     {
       "metric": "complexity",
       "value": "12",
-      "component": "com.sonarsource:java-markdown:src/main/java/com/sonarsource/markdown/impl/ElementImpl.java"
-    },
-    {
-      "metric": "complexity",
-      "value": "42",
-      "component": "MY_PROJECT"
+      "component": "MY_PROJECT_1"
     },
     {
       "metric": "complexity",
           "value": "0"
         }
       ],
-      "component": "com.sonarsource:java-markdown:src/main/java/com/sonarsource/markdown/impl"
+      "component": "MY_PROJECT_2"
     },
     {
       "metric": "ncloc",
       "value": "114",
-      "component": "com.sonarsource:java-markdown:src/main/java/com/sonarsource/markdown/impl/ElementImpl.java"
-    },
-    {
-      "metric": "ncloc",
-      "value": "1984",
-      "component": "MY_PROJECT"
+      "component": "MY_PROJECT_1"
     },
     {
       "metric": "ncloc",
           "value": "0"
         }
       ],
-      "component": "com.sonarsource:java-markdown:src/main/java/com/sonarsource/markdown/impl"
+      "component": "MY_PROJECT_2"
+    },
+    {
+      "metric": "ncloc",
+      "value": "1984",
+      "component": "MY_PROJECT_3"
     },
     {
       "metric": "new_violations",
           "value": "25"
         }
       ],
-      "component": "com.sonarsource:java-markdown:src/main/java/com/sonarsource/markdown/impl/ElementImpl.java"
+      "component": "MY_PROJECT_1"
     },
     {
       "metric": "new_violations",
       "periods": [
         {
           "index": 1,
-          "value": "0"
+          "value": "25"
         },
         {
           "index": 2,
         },
         {
           "index": 3,
-          "value": "0"
+          "value": "25"
         }
       ],
-      "component": "com.sonarsource:java-markdown:src/test/java/com/sonarsource/markdown/impl/ElementImplTest.java"
+      "component": "MY_PROJECT_2"
     },
     {
       "metric": "new_violations",
           "value": "255"
         }
       ],
-      "component": "MY_PROJECT"
-    },
-    {
-      "metric": "new_violations",
-      "periods": [
-        {
-          "index": 1,
-          "value": "25"
-        },
-        {
-          "index": 2,
-          "value": "0"
-        },
-        {
-          "index": 3,
-          "value": "25"
-        }
-      ],
-      "component": "com.sonarsource:java-markdown:src/main/java/com/sonarsource/markdown/impl"
+      "component": "MY_PROJECT_3"
     }
   ]
 }
index e19b853b65c39b9cde03ed7c18b662aad12c2afd..ec2321edd539b55145eb79292ecdb26c212e03c6 100644 (file)
@@ -33,7 +33,6 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.measures.Metric;
-import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.System2;
 import org.sonar.api.web.UserRole;
@@ -60,16 +59,14 @@ import static java.util.Collections.singletonList;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.tuple;
 import static org.sonar.api.utils.DateUtils.parseDateTime;
-import static org.sonar.db.component.ComponentTesting.newDirectory;
-import static org.sonar.db.component.ComponentTesting.newFileDto;
 import static org.sonar.db.component.ComponentTesting.newProjectDto;
 import static org.sonar.db.component.SnapshotTesting.newAnalysis;
 import static org.sonar.db.measure.MeasureTesting.newMeasureDto;
 import static org.sonar.db.metric.MetricTesting.newMetricDto;
 import static org.sonar.test.JsonAssert.assertJson;
 import static org.sonarqube.ws.MediaTypes.PROTOBUF;
-import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_COMPONENT_KEYS;
 import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_METRIC_KEYS;
+import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_PROJECT_KEYS;
 
 public class SearchActionTest {
 
@@ -98,10 +95,10 @@ public class SearchActionTest {
 
   @Test
   public void json_example() {
-    List<String> componentKeys = insertJsonExampleData();
+    List<String> projectKeys = insertJsonExampleData();
 
     String result = ws.newRequest()
-      .setParam(PARAM_COMPONENT_KEYS, Joiner.on(",").join(componentKeys))
+      .setParam(PARAM_PROJECT_KEYS, Joiner.on(",").join(projectKeys))
       .setParam(PARAM_METRIC_KEYS, "ncloc, complexity, new_violations")
       .execute()
       .getInput();
@@ -153,88 +150,48 @@ public class SearchActionTest {
   }
 
   @Test
-  public void add_best_values_when_no_value() {
-    ComponentDto projectDto = newProjectDto("project-uuid");
-    SnapshotDto projectSnapshot = componentDb.insertProjectAndSnapshot(projectDto);
-    ComponentDto directoryDto = newDirectory(projectDto, "directory-uuid", "path/to/directory").setName("directory-1");
-    componentDb.insertComponent(directoryDto);
-    ComponentDto file = newFileDto(directoryDto, null, "file-uuid").setName("file-1");
-    componentDb.insertComponent(file);
-    MetricDto coverage = insertCoverageMetric();
-    dbClient.metricDao().insert(dbSession, newMetricDto()
-      .setKey("ncloc")
-      .setValueType(Metric.ValueType.INT.name())
-      .setOptimizedBestValue(true)
-      .setBestValue(100d)
-      .setWorstValue(1000d));
-    dbClient.metricDao().insert(dbSession, newMetricDtoWithoutOptimization()
-      .setKey("new_violations")
-      .setOptimizedBestValue(true)
-      .setBestValue(1984.0d)
-      .setValueType(Metric.ValueType.INT.name()));
-    dbClient.measureDao().insert(dbSession,
-      newMeasureDto(coverage, file, projectSnapshot).setValue(15.5d),
-      newMeasureDto(coverage, directoryDto, projectSnapshot).setValue(42.0d));
-    db.commit();
-    setBrowsePermissionOnUser(projectDto);
-
-    SearchWsResponse result = call(newArrayList(directoryDto.key(), file.key()), newArrayList("ncloc", "coverage", "new_violations"));
-
-    // directory is not eligible for best value
-    assertThat(result.getMeasuresList().stream()
-      .filter(measure -> directoryDto.key().equals(measure.getComponent()))
-      .map(Measure::getMetric))
-        .containsOnly("coverage");
-    // file measures
-    List<Measure> fileMeasures = result.getMeasuresList().stream().filter(measure -> file.key().equals(measure.getComponent())).collect(Collectors.toList());
-    assertThat(fileMeasures).extracting(Measure::getMetric).containsOnly("ncloc", "coverage", "new_violations");
-    assertThat(fileMeasures).extracting(Measure::getValue).containsOnly("100", "15.5", "");
-  }
-
-  @Test
-  public void sort_by_metric_key_then_component_name() throws Exception {
+  public void sort_by_metric_key_then_project_name() throws Exception {
     MetricDto coverage = insertCoverageMetric();
     MetricDto complexity = insertComplexityMetric();
-    ComponentDto project = newProjectDto();
-    SnapshotDto projectSnapshot = componentDb.insertProjectAndSnapshot(project);
-    setBrowsePermissionOnUser(project);
-    ComponentDto file1 = componentDb.insertComponent(newFileDto(project).setName("C"));
-    ComponentDto file2 = componentDb.insertComponent(newFileDto(project).setName("A"));
-    ComponentDto file3 = componentDb.insertComponent(newFileDto(project).setName("B"));
-    dbClient.measureDao().insert(dbSession, newMeasureDto(coverage, file1, projectSnapshot).setValue(5.5d));
-    dbClient.measureDao().insert(dbSession, newMeasureDto(coverage, file2, projectSnapshot).setValue(6.5d));
-    dbClient.measureDao().insert(dbSession, newMeasureDto(coverage, file3, projectSnapshot).setValue(7.5d));
-    dbClient.measureDao().insert(dbSession, newMeasureDto(complexity, file1, projectSnapshot).setValue(10d));
-    dbClient.measureDao().insert(dbSession, newMeasureDto(complexity, file2, projectSnapshot).setValue(15d));
-    dbClient.measureDao().insert(dbSession, newMeasureDto(complexity, file3, projectSnapshot).setValue(20d));
+    ComponentDto project1 = newProjectDto().setName("C");
+    SnapshotDto projectSnapshot1 = componentDb.insertProjectAndSnapshot(project1);
+    ComponentDto project2 = newProjectDto().setName("A");
+    SnapshotDto projectSnapshot2 = componentDb.insertProjectAndSnapshot(project2);
+    ComponentDto project3 = newProjectDto().setName("B");
+    SnapshotDto projectSnapshot3 = componentDb.insertProjectAndSnapshot(project3);
+    setBrowsePermissionOnUser(project1, project2, project3);
+    dbClient.measureDao().insert(dbSession, newMeasureDto(coverage, project1, projectSnapshot1).setValue(5.5d));
+    dbClient.measureDao().insert(dbSession, newMeasureDto(coverage, project2, projectSnapshot2).setValue(6.5d));
+    dbClient.measureDao().insert(dbSession, newMeasureDto(coverage, project3, projectSnapshot3).setValue(7.5d));
+    dbClient.measureDao().insert(dbSession, newMeasureDto(complexity, project1, projectSnapshot1).setValue(10d));
+    dbClient.measureDao().insert(dbSession, newMeasureDto(complexity, project2, projectSnapshot2).setValue(15d));
+    dbClient.measureDao().insert(dbSession, newMeasureDto(complexity, project3, projectSnapshot3).setValue(20d));
     db.commit();
 
-    SearchWsResponse result = call(asList(file1.key(), file2.key(), file3.key()), asList("coverage", "complexity"));
+    SearchWsResponse result = call(asList(project1.key(), project2.key(), project3.key()), asList("coverage", "complexity"));
 
     assertThat(result.getMeasuresList()).extracting(Measure::getMetric, Measure::getComponent)
       .containsExactly(
-        tuple("complexity", file2.key()), tuple("complexity", file3.key()), tuple("complexity", file1.key()),
-        tuple("coverage", file2.key()), tuple("coverage", file3.key()), tuple("coverage", file1.key()));
+        tuple("complexity", project2.key()), tuple("complexity", project3.key()), tuple("complexity", project1.key()),
+        tuple("coverage", project2.key()), tuple("coverage", project3.key()), tuple("coverage", project1.key()));
   }
 
   @Test
-  public void only_returns_authorized_components() {
+  public void only_returns_authorized_projects() {
     MetricDto metricDto = insertComplexityMetric();
     ComponentDto project1 = newProjectDto();
     SnapshotDto projectSnapshot1 = componentDb.insertProjectAndSnapshot(project1);
-    ComponentDto file1 = componentDb.insertComponent(newFileDto(project1));
     ComponentDto project2 = newProjectDto();
     SnapshotDto projectSnapshot2 = componentDb.insertProjectAndSnapshot(project2);
-    ComponentDto file2 = componentDb.insertComponent(newFileDto(project2));
     dbClient.measureDao().insert(dbSession,
-      newMeasureDto(metricDto, file1, projectSnapshot1).setValue(15.5d),
-      newMeasureDto(metricDto, file2, projectSnapshot2).setValue(42.0d));
+      newMeasureDto(metricDto, project1, projectSnapshot1).setValue(15.5d),
+      newMeasureDto(metricDto, project2, projectSnapshot2).setValue(42.0d));
     db.commit();
     setBrowsePermissionOnUser(project1);
 
-    SearchWsResponse result = call(asList(file1.key(), file2.key()), singletonList("complexity"));
+    SearchWsResponse result = call(asList(project1.key(), project2.key()), singletonList("complexity"));
 
-    assertThat(result.getMeasuresList()).extracting(Measure::getComponent).containsOnly(file1.key());
+    assertThat(result.getMeasuresList()).extracting(Measure::getComponent).containsOnly(project1.key());
   }
 
   @Test
@@ -272,27 +229,27 @@ public class SearchActionTest {
   }
 
   @Test
-  public void fail_if_no_component() {
+  public void fail_if_no_project() {
     insertComplexityMetric();
 
     expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("Component keys must be provided");
+    expectedException.expectMessage("Project keys must be provided");
 
     call(null, singletonList("complexity"));
   }
 
   @Test
-  public void fail_if_empty_component_key() {
+  public void fail_if_empty_project_key() {
     insertComplexityMetric();
 
     expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("Component keys must be provided");
+    expectedException.expectMessage("Project keys must be provided");
 
     call(emptyList(), singletonList("complexity"));
   }
 
   @Test
-  public void fail_if_more_than_100_component_key() {
+  public void fail_if_more_than_100_project_keys() {
     List<String> keys = IntStream.rangeClosed(1, 101)
       .mapToObj(i -> componentDb.insertProject())
       .map(ComponentDto::key)
@@ -300,7 +257,7 @@ public class SearchActionTest {
     insertComplexityMetric();
 
     expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("101 components provided, more than maximum authorized (100)");
+    expectedException.expectMessage("101 projects provided, more than maximum authorized (100)");
 
     call(keys, singletonList("complexity"));
   }
@@ -316,14 +273,9 @@ public class SearchActionTest {
     assertThat(result.params()).hasSize(2);
     assertThat(result.responseExampleAsString()).isNotEmpty();
     assertThat(result.description()).isEqualToIgnoringWhitespace("" +
-      "Search for component measures ordered by component names.<br>" +
-      "At most 100 components can be provided.<br>" +
-      "Requires one of the following permissions:" +
-      "<ul>" +
-      " <li>'Administer System'</li>" +
-      " <li>'Administer' rights on the provided components</li>" +
-      " <li>'Browse' on the provided components</li>" +
-      "</ul>");
+      "Search for project measures ordered by project names.<br>" +
+      "At most 100 projects can be provided.<br>" +
+      "Requires 'Browse' on the provided projects");
   }
 
   private SearchWsResponse call(@Nullable List<String> keys, @Nullable List<String> metrics) {
@@ -331,7 +283,7 @@ public class SearchActionTest {
       .setMediaType(PROTOBUF);
 
     if (keys != null) {
-      request.setParam(PARAM_COMPONENT_KEYS, String.join(",", keys));
+      request.setParam(PARAM_PROJECT_KEYS, String.join(",", keys));
     }
     if (metrics != null) {
       request.setParam(PARAM_METRIC_KEYS, String.join(",", metrics));
@@ -415,15 +367,33 @@ public class SearchActionTest {
   }
 
   private List<String> insertJsonExampleData() {
-    List<String> componentKeys = new ArrayList<>();
-    ComponentDto project = newProjectDto("project-id")
-      .setKey("MY_PROJECT")
-      .setName("My Project")
-      .setDescription("My Project Description")
-      .setQualifier(Qualifiers.PROJECT);
-    componentKeys.add(project.key());
-    componentDb.insertComponent(project);
-    SnapshotDto projectSnapshot = dbClient.snapshotDao().insert(dbSession, newAnalysis(project)
+    List<String> projectKeys = new ArrayList<>();
+    ComponentDto project1 = newProjectDto().setKey("MY_PROJECT_1");
+    ComponentDto project2 = newProjectDto().setKey("MY_PROJECT_2");
+    ComponentDto project3 = newProjectDto().setKey("MY_PROJECT_3");
+    projectKeys.addAll(asList(project1.key(), project2.key(), project3.key()));
+    componentDb.insertComponents(project1, project2, project3);
+    SnapshotDto projectSnapshot1 = dbClient.snapshotDao().insert(dbSession, newAnalysis(project1)
+      .setPeriodDate(1, parseDateTime("2016-01-11T10:49:50+0100").getTime())
+      .setPeriodMode(1, "previous_version")
+      .setPeriodParam(1, "1.0-SNAPSHOT")
+      .setPeriodDate(2, parseDateTime("2016-01-11T10:50:06+0100").getTime())
+      .setPeriodMode(2, "previous_analysis")
+      .setPeriodParam(2, "2016-01-11")
+      .setPeriodDate(3, parseDateTime("2016-01-11T10:38:45+0100").getTime())
+      .setPeriodMode(3, "days")
+      .setPeriodParam(3, "30"));
+    SnapshotDto projectSnapshot2 = dbClient.snapshotDao().insert(dbSession, newAnalysis(project2)
+      .setPeriodDate(1, parseDateTime("2016-01-11T10:49:50+0100").getTime())
+      .setPeriodMode(1, "previous_version")
+      .setPeriodParam(1, "1.0-SNAPSHOT")
+      .setPeriodDate(2, parseDateTime("2016-01-11T10:50:06+0100").getTime())
+      .setPeriodMode(2, "previous_analysis")
+      .setPeriodParam(2, "2016-01-11")
+      .setPeriodDate(3, parseDateTime("2016-01-11T10:38:45+0100").getTime())
+      .setPeriodMode(3, "days")
+      .setPeriodParam(3, "30"));
+    SnapshotDto projectSnapshot3 = dbClient.snapshotDao().insert(dbSession, newAnalysis(project3)
       .setPeriodDate(1, parseDateTime("2016-01-11T10:49:50+0100").getTime())
       .setPeriodMode(1, "previous_version")
       .setPeriodParam(1, "1.0-SNAPSHOT")
@@ -433,71 +403,50 @@ public class SearchActionTest {
       .setPeriodDate(3, parseDateTime("2016-01-11T10:38:45+0100").getTime())
       .setPeriodMode(3, "days")
       .setPeriodParam(3, "30"));
-
-    ComponentDto file1 = componentDb.insertComponent(newFileDto(project, null)
-      .setUuid("AVIwDXE-bJbJqrw6wFv5")
-      .setKey("com.sonarsource:java-markdown:src/main/java/com/sonarsource/markdown/impl/ElementImpl.java")
-      .setName("ElementImpl.java")
-      .setLanguage("java")
-      .setQualifier(Qualifiers.FILE)
-      .setPath("src/main/java/com/sonarsource/markdown/impl/ElementImpl.java"));
-    componentKeys.add(file1.key());
-    ComponentDto file = newFileDto(project, null)
-      .setUuid("AVIwDXE_bJbJqrw6wFwJ")
-      .setKey("com.sonarsource:java-markdown:src/test/java/com/sonarsource/markdown/impl/ElementImplTest.java")
-      .setName("ElementImplTest.java")
-      .setLanguage("java")
-      .setQualifier(Qualifiers.UNIT_TEST_FILE)
-      .setPath("src/test/java/com/sonarsource/markdown/impl/ElementImplTest.java");
-    componentKeys.add(file.key());
-    componentDb.insertComponent(file);
-    ComponentDto dir = componentDb.insertComponent(newDirectory(project, "src/main/java/com/sonarsource/markdown/impl")
-      .setUuid("AVIwDXE-bJbJqrw6wFv8")
-      .setKey("com.sonarsource:java-markdown:src/main/java/com/sonarsource/markdown/impl")
-      .setQualifier(Qualifiers.DIRECTORY));
-    componentKeys.add(dir.key());
 
     MetricDto complexity = insertComplexityMetric();
     dbClient.measureDao().insert(dbSession,
-      newMeasureDto(complexity, file1, projectSnapshot)
+      newMeasureDto(complexity, project1, projectSnapshot1)
         .setValue(12.0d),
-      newMeasureDto(complexity, dir, projectSnapshot)
+      newMeasureDto(complexity, project2, projectSnapshot2)
         .setValue(35.0d)
         .setVariation(2, 0.0d),
-      newMeasureDto(complexity, project, projectSnapshot)
+      newMeasureDto(complexity, project1, projectSnapshot3)
         .setValue(42.0d));
 
     MetricDto ncloc = insertNclocMetric();
     dbClient.measureDao().insert(dbSession,
-      newMeasureDto(ncloc, file1, projectSnapshot)
+      newMeasureDto(ncloc, project1, projectSnapshot1)
         .setValue(114.0d),
-      newMeasureDto(ncloc, dir, projectSnapshot)
+      newMeasureDto(ncloc, project2, projectSnapshot2)
         .setValue(217.0d)
         .setVariation(2, 0.0d),
-      newMeasureDto(ncloc, project, projectSnapshot)
+      newMeasureDto(ncloc, project3, projectSnapshot3)
         .setValue(1984.0d));
 
     MetricDto newViolations = insertNewViolationsMetric();
     dbClient.measureDao().insert(dbSession,
-      newMeasureDto(newViolations, file1, projectSnapshot)
+      newMeasureDto(newViolations, project1, projectSnapshot1)
         .setVariation(1, 25.0d)
         .setVariation(2, 0.0d)
         .setVariation(3, 25.0d),
-      newMeasureDto(newViolations, dir, projectSnapshot)
+      newMeasureDto(newViolations, project2, projectSnapshot2)
         .setVariation(1, 25.0d)
         .setVariation(2, 0.0d)
         .setVariation(3, 25.0d),
-      newMeasureDto(newViolations, project, projectSnapshot)
+      newMeasureDto(newViolations, project3, projectSnapshot3)
         .setVariation(1, 255.0d)
         .setVariation(2, 0.0d)
         .setVariation(3, 255.0d));
     db.commit();
-    setBrowsePermissionOnUser(project);
-    return componentKeys;
+    setBrowsePermissionOnUser(project1, project2, project3);
+    return projectKeys;
   }
 
-  private void setBrowsePermissionOnUser(ComponentDto project) {
-    db.users().insertProjectPermissionOnUser(user, UserRole.USER, project);
+  private void setBrowsePermissionOnUser(ComponentDto... projects) {
+    for (ComponentDto project : projects) {
+      db.users().insertProjectPermissionOnUser(user, UserRole.USER, project);
+    }
     dbSession.commit();
   }
 }
index f04d579bf087db34f78de4ec5feb9b742b0b8002..b9ccc591132f1e42cae94542b73acd53a905814a 100644 (file)
@@ -34,9 +34,9 @@ export function getMeasuresAndMeta (componentKey, metrics, additional = {}) {
   return getJSON(url, data);
 }
 
-export const getMeasuresForComponents = (componentKeys, metricKeys) => (
+export const getMeasuresForProjects = (projectKeys, metricKeys) => (
     getJSON('/api/measures/search', {
-      componentKeys: componentKeys.join(),
+      projectKeys: projectKeys.join(),
       metricKeys: metricKeys.join()
     })
 );
index e811bd6327903ff89e1842201b832d9e26f08ea9..003cdceba64e7f9f6e4bbb6670eb5fd9e3aa599f 100644 (file)
@@ -25,7 +25,7 @@ import { receiveComponents } from '../../../app/store/components/actions';
 import { receiveProjects, receiveMoreProjects } from './projects/actions';
 import { updateState } from './state/actions';
 import { getProjectsAppState } from '../../../app/store/rootReducer';
-import { getMeasuresForComponents } from '../../../api/measures';
+import { getMeasuresForProjects } from '../../../api/measures';
 import { receiveComponentsMeasures } from '../../../app/store/measures/actions';
 import { convertToFilter } from './utils';
 import { getFavorites } from '../../../api/favorites';
@@ -81,7 +81,7 @@ const fetchProjectMeasures = projects => dispatch => {
   }
 
   const projectKeys = projects.map(project => project.key);
-  return getMeasuresForComponents(projectKeys, METRICS).then(onReceiveMeasures(dispatch), onFail(dispatch));
+  return getMeasuresForProjects(projectKeys, METRICS).then(onReceiveMeasures(dispatch), onFail(dispatch));
 };
 
 const onReceiveProjects = dispatch => response => {
index 49ce3efb27e56a796710c2ddf3810af1cafad112..f83b5427f6593131d95966482783cb40834cb715 100644 (file)
@@ -43,7 +43,7 @@ public class MeasuresWsParameters {
   public static final String PARAM_ADDITIONAL_FIELDS = "additionalFields";
   public static final String PARAM_COMPONENT_ID = "componentId";
   public static final String PARAM_COMPONENT_KEY = "componentKey";
-  public static final String PARAM_COMPONENT_KEYS = "componentKeys";
+  public static final String PARAM_PROJECT_KEYS = "projectKeys";
   public static final String PARAM_DEVELOPER_ID = "developerId";
   public static final String PARAM_DEVELOPER_KEY = "developerKey";
   public static final String ADDITIONAL_METRICS = "metrics";
index a9e767729703527f1adfcb56729611bc303eec77..41821338e31bf22938f5e80c4dc9d1363f5c534c 100644 (file)
@@ -25,22 +25,22 @@ import java.util.List;
 import static com.google.common.base.Preconditions.checkArgument;
 
 public class SearchRequest {
-  public static final int MAX_NB_COMPONENTS = 100;
+  public static final int MAX_NB_PROJECTS = 100;
 
   private final List<String> metricKeys;
-  private final List<String> componentKeys;
+  private final List<String> projectKeys;
 
   public SearchRequest(Builder builder) {
     metricKeys = builder.metricKeys;
-    componentKeys = builder.componentKeys;
+    projectKeys = builder.projectKeys;
   }
 
   public List<String> getMetricKeys() {
     return metricKeys;
   }
 
-  public List<String> getComponentKeys() {
-    return componentKeys;
+  public List<String> getProjectKeys() {
+    return projectKeys;
   }
 
   public static Builder builder() {
@@ -49,7 +49,7 @@ public class SearchRequest {
 
   public static class Builder {
     private List<String> metricKeys;
-    private List<String> componentKeys;
+    private List<String> projectKeys;
 
     private Builder() {
       // enforce method constructor
@@ -60,17 +60,17 @@ public class SearchRequest {
       return this;
     }
 
-    public Builder setComponentKeys(List<String> componentKeys) {
-      this.componentKeys = componentKeys;
+    public Builder setProjectKeys(List<String> projectKeys) {
+      this.projectKeys = projectKeys;
       return this;
     }
 
     public SearchRequest build() {
       checkArgument(metricKeys != null && !metricKeys.isEmpty(), "Metric keys must be provided");
-      checkArgument(componentKeys != null && !componentKeys.isEmpty(), "Component keys must be provided");
-      int nbComponents = componentKeys.size();
-      checkArgument(nbComponents < MAX_NB_COMPONENTS,
-        "%s components provided, more than maximum authorized (%s)", nbComponents, MAX_NB_COMPONENTS);
+      checkArgument(projectKeys != null && !projectKeys.isEmpty(), "Project keys must be provided");
+      int nbComponents = projectKeys.size();
+      checkArgument(nbComponents < MAX_NB_PROJECTS,
+        "%s projects provided, more than maximum authorized (%s)", nbComponents, MAX_NB_PROJECTS);
       return new SearchRequest(this);
     }
   }
index 6e174d78ed5a3d7e057fe8b92817daff27672d68..878f314a5872797ab6d117cebdd4829feea9c672 100644 (file)
@@ -39,11 +39,11 @@ public class SearchRequestTest {
   public void with_component_keys() {
     SearchRequest result = underTest
       .setMetricKeys(singletonList("metric"))
-      .setComponentKeys(singletonList("key"))
+      .setProjectKeys(singletonList("key"))
       .build();
 
     assertThat(result.getMetricKeys()).containsExactly("metric");
-    assertThat(result.getComponentKeys()).containsExactly("key");
+    assertThat(result.getProjectKeys()).containsExactly("key");
   }
 
   @Test
@@ -73,7 +73,7 @@ public class SearchRequestTest {
 
     underTest
       .setMetricKeys(singletonList("metric"))
-      .setComponentKeys(emptyList())
+      .setProjectKeys(emptyList())
       .build();
   }
 
@@ -84,6 +84,6 @@ public class SearchRequestTest {
 
   private void expectExceptionOnComponents() {
     expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("Component keys must be provided");
+    expectedException.expectMessage("Project keys must be provided");
   }
 }