aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2017-02-17 17:33:07 +0100
committerJulien Lancelot <julien.lancelot@sonarsource.com>2017-02-22 08:15:35 +0100
commitda3f4238479d89173c3cbc9ebbd669c1990abb53 (patch)
tree41dc2619e9cd15bac44fb8a8e608cb34bc69f408
parenteb3a5e9ecb555ea838b28e2d0d27ae95922470e7 (diff)
downloadsonarqube-da3f4238479d89173c3cbc9ebbd669c1990abb53.tar.gz
sonarqube-da3f4238479d89173c3cbc9ebbd669c1990abb53.zip
SONAR-8231 Return language distribution facet
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndex.java59
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchProjectsActionTest.java35
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexTest.java2
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/project/ProjectsWsParameters.java2
4 files changed, 63 insertions, 35 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndex.java b/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndex.java
index 5ff762cf0f6..e687404d592 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndex.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndex.java
@@ -21,6 +21,7 @@ package org.sonar.server.measure.index;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Multimap;
import java.util.HashMap;
import java.util.List;
@@ -56,7 +57,6 @@ import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY;
import static org.sonar.api.measures.CoreMetrics.COVERAGE_KEY;
import static org.sonar.api.measures.CoreMetrics.DUPLICATED_LINES_DENSITY_KEY;
import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY;
-import static org.sonar.api.measures.CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION_KEY;
import static org.sonar.api.measures.CoreMetrics.RELIABILITY_RATING_KEY;
import static org.sonar.api.measures.CoreMetrics.SECURITY_RATING_KEY;
import static org.sonar.api.measures.CoreMetrics.SQALE_RATING_KEY;
@@ -69,6 +69,7 @@ import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIEL
import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES;
import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.TYPE_PROJECT_MEASURE;
import static org.sonar.server.measure.index.ProjectMeasuresQuery.SORT_BY_NAME;
+import static org.sonarqube.ws.client.project.ProjectsWsParameters.FILTER_LANGUAGE;
public class ProjectMeasuresIndex extends BaseIndex {
@@ -79,7 +80,8 @@ public class ProjectMeasuresIndex extends BaseIndex {
SQALE_RATING_KEY,
RELIABILITY_RATING_KEY,
SECURITY_RATING_KEY,
- ALERT_STATUS_KEY);
+ ALERT_STATUS_KEY,
+ FILTER_LANGUAGE);
private static final String FIELD_MEASURES_KEY = FIELD_MEASURES + "." + ProjectMeasuresIndexDefinition.FIELD_MEASURES_KEY;
private static final String FIELD_MEASURES_VALUE = FIELD_MEASURES + "." + ProjectMeasuresIndexDefinition.FIELD_MEASURES_VALUE;
@@ -87,6 +89,17 @@ public class ProjectMeasuresIndex extends BaseIndex {
private static final String FIELD_LANGUAGES_KEY = FIELD_LANGUAGES + "." + ProjectMeasuresIndexDefinition.FIELD_LANGUAGES_KEY;
private static final String FIELD_LANGUAGES_VALUE = FIELD_LANGUAGES + "." + ProjectMeasuresIndexDefinition.FIELD_LANGUAGES_VALUE;
+ private static final Map<String, FacetSetter> FACET_FACTORIES = ImmutableMap.<String, FacetSetter>builder()
+ .put(NCLOC_KEY, (esSearch, filters) -> addRangeFacet(esSearch, NCLOC_KEY, ImmutableList.of(1_000d, 10_000d, 100_000d, 500_000d), filters))
+ .put(DUPLICATED_LINES_DENSITY_KEY, (esSearch, filters) -> addRangeFacet(esSearch, DUPLICATED_LINES_DENSITY_KEY, ImmutableList.of(3d, 5d, 10d, 20d), filters))
+ .put(COVERAGE_KEY, (esSearch, filters) -> addRangeFacet(esSearch, COVERAGE_KEY, ImmutableList.of(30d, 50d, 70d, 80d), filters))
+ .put(SQALE_RATING_KEY, (esSearch, filters) -> addRatingFacet(esSearch, SQALE_RATING_KEY, filters))
+ .put(RELIABILITY_RATING_KEY, (esSearch, filters) -> addRatingFacet(esSearch, RELIABILITY_RATING_KEY, filters))
+ .put(SECURITY_RATING_KEY, (esSearch, filters) -> addRatingFacet(esSearch, SECURITY_RATING_KEY, filters))
+ .put(ALERT_STATUS_KEY, (esSearch, filters) -> esSearch.addAggregation(createStickyFacet(ALERT_STATUS_KEY, filters, createQualityGateFacet())))
+ .put(FILTER_LANGUAGE, (esSearch, filters) -> esSearch.addAggregation(createStickyFacet(FILTER_LANGUAGE, filters, createLanguagesFacet())))
+ .build();
+
private final AuthorizationTypeSupport authorizationTypeSupport;
public ProjectMeasuresIndex(EsClient client, AuthorizationTypeSupport authorizationTypeSupport) {
@@ -133,33 +146,10 @@ public class ProjectMeasuresIndex extends BaseIndex {
}
private static void addFacets(SearchRequestBuilder esSearch, SearchOptions options, Map<String, QueryBuilder> filters) {
- if (options.getFacets().isEmpty()) {
- return;
- }
- if (options.getFacets().contains(NCLOC_KEY)) {
- addRangeFacet(esSearch, NCLOC_KEY, ImmutableList.of(1_000d, 10_000d, 100_000d, 500_000d), filters);
- }
- if (options.getFacets().contains(DUPLICATED_LINES_DENSITY_KEY)) {
- addRangeFacet(esSearch, DUPLICATED_LINES_DENSITY_KEY, ImmutableList.of(3d, 5d, 10d, 20d), filters);
- }
- if (options.getFacets().contains(COVERAGE_KEY)) {
- addRangeFacet(esSearch, COVERAGE_KEY, ImmutableList.of(30d, 50d, 70d, 80d), filters);
- }
- if (options.getFacets().contains(SQALE_RATING_KEY)) {
- addRatingFacet(esSearch, SQALE_RATING_KEY, filters);
- }
- if (options.getFacets().contains(RELIABILITY_RATING_KEY)) {
- addRatingFacet(esSearch, RELIABILITY_RATING_KEY, filters);
- }
- if (options.getFacets().contains(SECURITY_RATING_KEY)) {
- addRatingFacet(esSearch, SECURITY_RATING_KEY, filters);
- }
- if (options.getFacets().contains(ALERT_STATUS_KEY)) {
- esSearch.addAggregation(createStickyFacet(ALERT_STATUS_KEY, filters, createQualityGateFacet()));
- }
- if (options.getFacets().contains(NCLOC_LANGUAGE_DISTRIBUTION_KEY)) {
- esSearch.addAggregation(createStickyFacet(NCLOC_LANGUAGE_DISTRIBUTION_KEY, filters, createLanguagesFacet()));
- }
+ options.getFacets().stream()
+ .filter(FACET_FACTORIES::containsKey)
+ .map(FACET_FACTORIES::get)
+ .forEach(factory -> factory.addFacet(esSearch, filters));
}
private static void addRangeFacet(SearchRequestBuilder esSearch, String metricKey, List<Double> thresholds, Map<String, QueryBuilder> filters) {
@@ -226,12 +216,12 @@ public class ProjectMeasuresIndex extends BaseIndex {
}
private static AbstractAggregationBuilder createLanguagesFacet() {
- return AggregationBuilders.nested("nested_" + NCLOC_LANGUAGE_DISTRIBUTION_KEY)
+ return AggregationBuilders.nested("nested_" + FILTER_LANGUAGE)
.path(FIELD_LANGUAGES)
.subAggregation(
- AggregationBuilders.terms(NCLOC_LANGUAGE_DISTRIBUTION_KEY)
+ AggregationBuilders.terms(FILTER_LANGUAGE)
.field(FIELD_LANGUAGES_KEY)
- .subAggregation(AggregationBuilders.sum("size_" + NCLOC_LANGUAGE_DISTRIBUTION_KEY)
+ .subAggregation(AggregationBuilders.sum("size_" + FILTER_LANGUAGE)
.field(FIELD_LANGUAGES_VALUE)));
}
@@ -282,4 +272,9 @@ public class ProjectMeasuresIndex extends BaseIndex {
}
}
+ @FunctionalInterface
+ private interface FacetSetter {
+ void addFacet(SearchRequestBuilder esSearch, Map<String, QueryBuilder> filters);
+ }
+
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchProjectsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchProjectsActionTest.java
index 0e3a9b87f40..1106791b797 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchProjectsActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchProjectsActionTest.java
@@ -61,10 +61,12 @@ import org.sonarqube.ws.client.component.SearchProjectsRequest;
import static com.google.common.collect.Lists.newArrayList;
import static java.util.Collections.emptyList;
+import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonList;
import static java.util.Optional.ofNullable;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
+import static org.sonar.api.measures.CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION_KEY;
import static org.sonar.api.measures.Metric.ValueType.INT;
import static org.sonar.api.server.ws.WebService.Param.ASCENDING;
import static org.sonar.api.server.ws.WebService.Param.FACETS;
@@ -84,6 +86,7 @@ import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.TYPE
import static org.sonar.test.JsonAssert.assertJson;
import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_FILTER;
import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_ORGANIZATION;
+import static org.sonarqube.ws.client.project.ProjectsWsParameters.FILTER_LANGUAGE;
public class SearchProjectsActionTest {
@@ -385,6 +388,29 @@ public class SearchProjectsActionTest {
}
@Test
+ public void return_languages_facet() {
+ OrganizationDto organization = db.getDefaultOrganization();
+ insertProjectInDbAndEs(newProjectDto(organization).setName("Sonar Java"), newArrayList(newMeasure(COVERAGE, 81d)), ImmutableMap.of("<null>", 2, "java", 6, "xoo", 18));
+ insertProjectInDbAndEs(newProjectDto(organization).setName("Sonar Groovy"), newArrayList(newMeasure(COVERAGE, 81)), ImmutableMap.of("java", 4, "xoo", 5));
+ insertProjectInDbAndEs(newProjectDto(organization).setName("Sonar Markdown"), newArrayList(newMeasure(COVERAGE, 80d)), ImmutableMap.of("xoo", 3));
+ insertProjectInDbAndEs(newProjectDto(organization).setName("Sonar Qube"), newArrayList(newMeasure(COVERAGE, 80d)), ImmutableMap.of("<null>", 5, "java", 16, "xoo", 9));
+ insertMetrics(COVERAGE, NCLOC_LANGUAGE_DISTRIBUTION_KEY);
+
+ SearchProjectsWsResponse result = call(request.setFacets(singletonList(FILTER_LANGUAGE)));
+
+ Common.Facet facet = result.getFacets().getFacetsList().stream()
+ .filter(oneFacet -> FILTER_LANGUAGE.equals(oneFacet.getProperty()))
+ .findFirst().orElseThrow(IllegalStateException::new);
+ assertThat(facet.getProperty()).isEqualTo(FILTER_LANGUAGE);
+ assertThat(facet.getValuesList())
+ .extracting(Common.FacetValue::getVal, Common.FacetValue::getCount)
+ .containsExactly(
+ tuple("xoo", 35L),
+ tuple("java", 26L),
+ tuple("<null>", 7L));
+ }
+
+ @Test
public void default_sort_is_by_ascending_name() throws Exception {
OrganizationDto organization = db.getDefaultOrganization();
insertProjectInDbAndEs(newProjectDto(organization).setName("Sonar Java"), newArrayList(newMeasure(COVERAGE, 81), newMeasure(NCLOC, 5d)));
@@ -466,6 +492,10 @@ public class SearchProjectsActionTest {
}
private ComponentDto insertProjectInDbAndEs(ComponentDto project, List<Map<String, Object>> measures) {
+ return insertProjectInDbAndEs(project, measures, emptyMap());
+ }
+
+ private ComponentDto insertProjectInDbAndEs(ComponentDto project, List<Map<String, Object>> measures, Map<String, Integer> languagesDistribution) {
ComponentDto res = componentDb.insertComponent(project);
try {
es.putDocuments(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURE,
@@ -474,7 +504,8 @@ public class SearchProjectsActionTest {
.setId(project.uuid())
.setKey(project.key())
.setName(project.name())
- .setMeasures(measures));
+ .setMeasures(measures)
+ .setLanguages(languagesDistribution));
authorizationIndexerTester.allowOnlyAnyone(project);
} catch (Exception e) {
Throwables.propagate(e);
@@ -490,7 +521,7 @@ public class SearchProjectsActionTest {
dbSession.commit();
}
- private static Map<String, Object> newMeasure(String key, double value) {
+ private static Map<String, Object> newMeasure(String key, Object value) {
return ImmutableMap.of("key", key, "value", value);
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexTest.java
index de317b41563..abbd8c49ac2 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexTest.java
@@ -69,7 +69,7 @@ public class ProjectMeasuresIndexTest {
private static final String COVERAGE = "coverage";
private static final String DUPLICATION = "duplicated_lines_density";
private static final String NCLOC = "ncloc";
- private static final String LANGUAGES = "ncloc_language_distribution";
+ private static final String LANGUAGES = "languages";
private static final OrganizationDto ORG = OrganizationTesting.newOrganizationDto();
private static final ComponentDto PROJECT1 = newProjectDto(ORG).setUuid("Project-1").setName("Project 1").setKey("key-1");
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/project/ProjectsWsParameters.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/project/ProjectsWsParameters.java
index b735334df8f..fe4371a341f 100644
--- a/sonar-ws/src/main/java/org/sonarqube/ws/client/project/ProjectsWsParameters.java
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/project/ProjectsWsParameters.java
@@ -36,6 +36,8 @@ public class ProjectsWsParameters {
public static final String PARAM_ORGANIZATION = "organization";
public static final String PARAM_QUALIFIERS = "qualifiers";
+ public static final String FILTER_LANGUAGE = "language";
+
private ProjectsWsParameters() {
// static utils only
}