package org.sonar.db.measure;
import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
}
Measures setLanguageDistribution(String languageDistributionValue) {
- this.languageDistribution = parseStringInt(languageDistributionValue);
+ this.languageDistribution = ImmutableMap.copyOf(parseStringInt(languageDistributionValue));
return this;
}
import java.util.function.Function;
import java.util.stream.Collector;
import java.util.stream.Stream;
-import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.server.ws.Change;
import org.sonarqube.ws.WsComponents.Component;
import org.sonarqube.ws.WsComponents.SearchProjectsWsResponse;
import org.sonarqube.ws.client.component.SearchProjectsRequest;
-import org.sonarqube.ws.client.project.ProjectsWsParameters;
import static com.google.common.base.MoreObjects.firstNonNull;
import static java.lang.String.format;
+import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY;
import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY;
import static org.sonar.core.util.stream.Collectors.toSet;
import static org.sonar.server.component.ws.ProjectMeasuresQueryFactory.IS_FAVORITE_CRITERION;
import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_ORGANIZATION;
import static org.sonarqube.ws.client.component.SearchProjectsRequest.DEFAULT_PAGE_SIZE;
import static org.sonarqube.ws.client.component.SearchProjectsRequest.MAX_PAGE_SIZE;
+import static org.sonarqube.ws.client.project.ProjectsWsParameters.FILTER_LANGUAGE;
public class SearchProjectsAction implements ComponentsWsAction {
.setInternal(true)
.setResponseExample(getClass().getResource("search_projects-example.json"))
.setChangelog(
- new Change("6.4", format("The '%s' parameter accepts '%s' to filter by language", ProjectsWsParameters.FILTER_LANGUAGE, PARAM_FILTER)))
+ new Change("6.4", format("The '%s' parameter accepts '%s' to filter by language", FILTER_LANGUAGE, PARAM_FILTER)))
.setHandler(this);
action.createParam(PARAM_ORGANIZATION)
"Use the WS api/languages/list to find the key of a language.");
action.createParam(Param.SORT)
- .setDescription("Sort projects by numeric metric key or by name.<br/>" +
- "See '%s' parameter description for the possible metric values", PARAM_FILTER)
+ .setDescription("Sort projects by numeric metric key, quality gate status (using '%s'), or by project name.<br/>" +
+ "See '%s' parameter description for the possible metric values", ALERT_STATUS_KEY, PARAM_FILTER)
.setDefaultValue(SORT_BY_NAME)
.setExampleValue(NCLOC_KEY)
.setSince("6.4");
private SearchResults searchData(DbSession dbSession, SearchProjectsRequest request, @Nullable OrganizationDto organization) {
Set<String> favoriteProjectUuids = loadFavoriteProjectUuids(dbSession);
-
List<Criterion> criteria = FilterParser.parse(firstNonNull(request.getFilter(), ""));
- Set<String> projectUuids = buildFilterOnFavoriteProjectUuids(criteria, favoriteProjectUuids);
-
- ProjectMeasuresQuery query = newProjectMeasuresQuery(criteria, projectUuids)
+ ProjectMeasuresQuery query = newProjectMeasuresQuery(criteria, hasFavoriteFilter(criteria) ? favoriteProjectUuids : null)
.setSort(request.getSort())
.setAsc(request.getAsc());
Optional.ofNullable(organization)
return new SearchResults(projects, favoriteProjectUuids, esResults);
}
- @CheckForNull
- private Set<String> buildFilterOnFavoriteProjectUuids(List<Criterion> criteria, Set<String> favoriteProjectUuids) {
- if (criteria.stream()
+ private static boolean hasFavoriteFilter(List<Criterion> criteria) {
+ return criteria.stream()
.map(Criterion::getKey)
- .anyMatch(IS_FAVORITE_CRITERION::equalsIgnoreCase)) {
- return favoriteProjectUuids;
- }
- return null;
+ .anyMatch(IS_FAVORITE_CRITERION::equalsIgnoreCase);
}
private Set<String> loadFavoriteProjectUuids(DbSession dbSession) {
private static void addSort(ProjectMeasuresQuery query, SearchRequestBuilder requestBuilder) {
String sort = query.getSort();
- if (sort == null || SORT_BY_NAME.equals(sort)) {
+ if (SORT_BY_NAME.equals(sort)) {
requestBuilder.addSort(DefaultIndexSettingsElement.SORTABLE_ANALYZER.subField(FIELD_NAME), query.isAsc() ? ASC : DESC);
+ } else if (ALERT_STATUS_KEY.equals(sort)) {
+ requestBuilder.addSort(FIELD_QUALITY_GATE_STATUS, query.isAsc() ? ASC : DESC);
+ requestBuilder.addSort(DefaultIndexSettingsElement.SORTABLE_ANALYZER.subField(FIELD_NAME), ASC);
} else {
- addNameSort(query, requestBuilder, sort);
+ addMetricSort(query, requestBuilder, sort);
requestBuilder.addSort(DefaultIndexSettingsElement.SORTABLE_ANALYZER.subField(FIELD_NAME), ASC);
}
// last sort is by key in order to be deterministic when same value
requestBuilder.addSort(FIELD_KEY, ASC);
}
- private static void addNameSort(ProjectMeasuresQuery query, SearchRequestBuilder requestBuilder, String sort) {
+ private static void addMetricSort(ProjectMeasuresQuery query, SearchRequestBuilder requestBuilder, String sort) {
requestBuilder.addSort(
new FieldSortBuilder(FIELD_MEASURES_VALUE)
.setNestedPath(FIELD_MEASURES)
import java.util.List;
import java.util.Optional;
import java.util.Set;
-import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.api.measures.Metric;
private String organizationUuid;
private Set<String> projectUuids;
private Set<String> languages;
- private String sort;
+ private String sort = SORT_BY_NAME;
private boolean asc = true;
public ProjectMeasuresQuery addMetricCriterion(MetricCriterion metricCriterion) {
return Optional.ofNullable(languages);
}
- @CheckForNull
public String getSort() {
return sort;
}
- public ProjectMeasuresQuery setSort(@Nullable String sort) {
- this.sort = sort;
+ public ProjectMeasuresQuery setSort(String sort) {
+ this.sort = requireNonNull(sort, "Sort cannot be null");
return this;
}
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.measures.Metric.ValueType.LEVEL;
import static org.sonar.api.server.ws.WebService.Param.ASCENDING;
import static org.sonar.api.server.ws.WebService.Param.FACETS;
import static org.sonar.api.server.ws.WebService.Param.PAGE;
private static final String NCLOC = "ncloc";
private static final String COVERAGE = "coverage";
+ private static final String QUALITY_GATE_STATUS = "alert_status";
private static final String IS_FAVOURITE_CRITERION = "isFavorite";
@Rule
.containsExactly("Sonar Groovy", "Sonar Java", "Sonar Markdown", "Sonar Qube");
}
+ @Test
+ public void sort_by_quality_gate() throws Exception {
+ OrganizationDto organization = db.getDefaultOrganization();
+ insertProjectInDbAndEs(newProjectDto(organization).setName("Sonar Java"), "ERROR");
+ insertProjectInDbAndEs(newProjectDto(organization).setName("Sonar Groovy"), "WARN");
+ insertProjectInDbAndEs(newProjectDto(organization).setName("Sonar Markdown"), "OK");
+ insertProjectInDbAndEs(newProjectDto(organization).setName("Sonar Qube"), "OK");
+ dbClient.metricDao().insert(dbSession, newMetricDto().setKey(QUALITY_GATE_STATUS).setValueType(LEVEL.name()).setEnabled(true).setHidden(false));
+ db.commit();
+
+ assertThat(call(request.setSort(QUALITY_GATE_STATUS).setAsc(true)).getComponentsList()).extracting(Component::getName)
+ .containsExactly("Sonar Markdown", "Sonar Qube", "Sonar Groovy", "Sonar Java");
+ assertThat(call(request.setSort(QUALITY_GATE_STATUS).setAsc(false)).getComponentsList()).extracting(Component::getName)
+ .containsExactly("Sonar Java", "Sonar Groovy", "Sonar Markdown", "Sonar Qube");
+ }
+
@Test
public void fail_when_metrics_are_unknown() {
expectedException.expect(IllegalArgumentException.class);
assertResults(new ProjectMeasuresQuery().setSort("ncloc").setAsc(false), windows, apache1, apache2, apachee);
}
+ @Test
+ public void sort_by_quality_gate_status() {
+ ComponentDto project4 = newProjectDto(ORG).setUuid("Project-4").setName("Project 4").setKey("key-4");
+ index(
+ newDoc(PROJECT1).setQualityGateStatus(OK.name()),
+ newDoc(PROJECT2).setQualityGateStatus(ERROR.name()),
+ newDoc(PROJECT3).setQualityGateStatus(WARN.name()),
+ newDoc(project4).setQualityGateStatus(OK.name()));
+
+ assertResults(new ProjectMeasuresQuery().setSort("alert_status").setAsc(true), PROJECT1, project4, PROJECT3, PROJECT2);
+ assertResults(new ProjectMeasuresQuery().setSort("alert_status").setAsc(false), PROJECT2, PROJECT3, PROJECT1, project4);
+ }
+
+ @Test
+ public void sort_by_quality_gate_status_then_by_name_then_by_key() {
+ ComponentDto windows = newProjectDto(ORG).setUuid("windows").setName("Windows").setKey("project1");
+ ComponentDto apachee = newProjectDto(ORG).setUuid("apachee").setName("apachee").setKey("project2");
+ ComponentDto apache1 = newProjectDto(ORG).setUuid("apache-1").setName("Apache").setKey("project3");
+ ComponentDto apache2 = newProjectDto(ORG).setUuid("apache-2").setName("Apache").setKey("project4");
+ index(
+ newDoc(windows).setQualityGateStatus(WARN.name()),
+ newDoc(apachee).setQualityGateStatus(OK.name()),
+ newDoc(apache1).setQualityGateStatus(OK.name()),
+ newDoc(apache2).setQualityGateStatus(OK.name()));
+
+ assertResults(new ProjectMeasuresQuery().setSort("alert_status").setAsc(true), apache1, apache2, apachee, windows);
+ assertResults(new ProjectMeasuresQuery().setSort("alert_status").setAsc(false), windows, apache1, apache2, apachee);
+ }
+
@Test
public void paginate_results() {
IntStream.rangeClosed(1, 9)
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.groups.Tuple.tuple;
import static org.sonar.api.measures.Metric.Level.OK;
-import static org.sonar.server.component.ws.FilterParser.Operator;
import static org.sonar.server.component.ws.FilterParser.Operator.EQ;
public class ProjectMeasuresQueryTest {
assertThat(underTest.getQualityGateStatus().get()).isEqualTo(Level.OK);
}
- @Test
- public void fail_to_create_operator_from_unknown_value() throws Exception {
- expectedException.expect(IllegalArgumentException.class);
-
- Operator.valueOf("UNKNOWN");
- }
-
@Test
public void default_sort_is_by_name() throws Exception {
assertThat(underTest.getSort()).isEqualTo("name");