From aee1bfc4506dbdc39a31c704a359d4edb6365a16 Mon Sep 17 00:00:00 2001 From: Teryk Bellahsene Date: Tue, 8 Nov 2016 17:22:46 +0100 Subject: [PATCH] SONAR-8361 WS api/components/search_projects return isFavorite --- .../component/es/ProjectMeasuresQuery.java | 7 ++- .../component/ws/ComponentsWsModule.java | 1 - .../ws/ProjectMeasuresQueryFactory.java | 44 +++----------- .../component/ws/SearchProjectsAction.java | 58 ++++++++++++++----- .../component/ws/search_projects-example.json | 9 ++- .../es/ProjectMeasuresIndexTest.java | 3 +- .../component/ws/ComponentsWsModuleTest.java | 2 +- .../ws/ProjectMeasuresQueryFactoryTest.java | 53 +++++++---------- .../ws/ProjectMeasuresQueryValidatorTest.java | 15 ++--- .../ws/SearchProjectsActionTest.java | 12 ++-- .../src/main/protobuf/ws-components.proto | 1 + 11 files changed, 103 insertions(+), 102 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/es/ProjectMeasuresQuery.java b/server/sonar-server/src/main/java/org/sonar/server/component/es/ProjectMeasuresQuery.java index ed673b2d74b..64da007ff4c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/es/ProjectMeasuresQuery.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/es/ProjectMeasuresQuery.java @@ -22,6 +22,7 @@ package org.sonar.server.component.es; import java.util.ArrayList; import java.util.List; +import java.util.Set; import org.sonar.api.measures.Metric; import static com.google.common.base.Preconditions.checkState; @@ -32,7 +33,7 @@ import static java.util.Objects.requireNonNull; public class ProjectMeasuresQuery { private List metricCriteria = new ArrayList<>(); private Metric.Level qualityGateStatus; - private List projectUuids = null; + private Set projectUuids = null; public ProjectMeasuresQuery addMetricCriterion(MetricCriterion metricCriterion) { this.metricCriteria.add(metricCriterion); @@ -57,7 +58,7 @@ public class ProjectMeasuresQuery { return qualityGateStatus; } - public ProjectMeasuresQuery setProjectUuids(List projectUuids) { + public ProjectMeasuresQuery setProjectUuids(Set projectUuids) { this.projectUuids = requireNonNull(projectUuids); return this; } @@ -66,7 +67,7 @@ public class ProjectMeasuresQuery { return projectUuids != null; } - public List getProjectUuids() { + public Set getProjectUuids() { return requireNonNull(projectUuids); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentsWsModule.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentsWsModule.java index 9e8f7b35a0f..76933a91e20 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentsWsModule.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentsWsModule.java @@ -37,7 +37,6 @@ public class ComponentsWsModule extends Module { UpdateKeyAction.class, BulkUpdateKeyAction.class, SearchProjectsAction.class, - ProjectMeasuresQueryFactory.class, ProjectMeasuresQueryValidator.class); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectMeasuresQueryFactory.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectMeasuresQueryFactory.java index 0698c0fcd7d..da1b8dd6fd1 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectMeasuresQueryFactory.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectMeasuresQueryFactory.java @@ -21,20 +21,12 @@ package org.sonar.server.component.ws; import com.google.common.base.Splitter; -import java.util.List; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.lang.StringUtils; import org.sonar.api.measures.Metric.Level; -import org.sonar.api.resources.Qualifiers; -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.property.PropertyDto; -import org.sonar.db.property.PropertyQuery; import org.sonar.server.component.es.ProjectMeasuresQuery; -import org.sonar.server.user.UserSession; import static com.google.common.base.Preconditions.checkArgument; import static java.util.Locale.ENGLISH; @@ -42,20 +34,16 @@ import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY; import static org.sonar.server.component.es.ProjectMeasuresQuery.MetricCriterion; import static org.sonar.server.component.es.ProjectMeasuresQuery.Operator; -public class ProjectMeasuresQueryFactory { +class ProjectMeasuresQueryFactory { private static final Splitter CRITERIA_SPLITTER = Splitter.on(Pattern.compile("and", Pattern.CASE_INSENSITIVE)); private static final Pattern CRITERIA_PATTERN = Pattern.compile("(\\w+)\\s*([<>]?[=]?)\\s*(\\w+)"); private static final String IS_FAVORITE_CRITERION = "isFavorite"; - private final DbClient dbClient; - private final UserSession userSession; - - public ProjectMeasuresQueryFactory(DbClient dbClient, UserSession userSession) { - this.dbClient = dbClient; - this.userSession = userSession; + private ProjectMeasuresQueryFactory() { + // prevent instantiation } - ProjectMeasuresQuery newProjectMeasuresQuery(DbSession dbSession, String filter) { + static ProjectMeasuresQuery newProjectMeasuresQuery(String filter, Set favoriteProjectUuids) { if (StringUtils.isBlank(filter)) { return new ProjectMeasuresQuery(); } @@ -63,16 +51,16 @@ public class ProjectMeasuresQueryFactory { ProjectMeasuresQuery query = new ProjectMeasuresQuery(); CRITERIA_SPLITTER.split(filter) - .forEach(criteria -> processCriterion(dbSession, criteria, query)); + .forEach(criteria -> processCriterion(criteria, query, favoriteProjectUuids)); return query; } - private void processCriterion(DbSession dbSession, String rawCriterion, ProjectMeasuresQuery query) { + private static void processCriterion(String rawCriterion, ProjectMeasuresQuery query, Set favoriteProjectUuids) { String criterion = rawCriterion.trim(); try { if (IS_FAVORITE_CRITERION.equalsIgnoreCase(criterion)) { - query.setProjectUuids(searchFavoriteUuids(dbSession)); + query.setProjectUuids(favoriteProjectUuids); return; } @@ -93,20 +81,4 @@ public class ProjectMeasuresQueryFactory { } } - private List searchFavoriteUuids(DbSession dbSession) { - List favoriteDbIds = dbClient.propertiesDao().selectByQuery(PropertyQuery.builder() - .setUserId(userSession.getUserId()) - .setKey("favourite") - .build(), dbSession) - .stream() - .map(PropertyDto::getResourceId) - .collect(Collectors.toList()); - - return dbClient.componentDao().selectByIds(dbSession, favoriteDbIds) - .stream() - .filter(dbComponent -> Qualifiers.PROJECT.equals(dbComponent.qualifier())) - .map(ComponentDto::uuid) - .collect(Collectors.toList()); - } - } diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/SearchProjectsAction.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/SearchProjectsAction.java index 0a6e28220a4..0c6142362b7 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/ws/SearchProjectsAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/ws/SearchProjectsAction.java @@ -25,21 +25,27 @@ import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map.Entry; +import java.util.Set; import java.util.function.Function; import java.util.stream.Collector; import java.util.stream.Stream; +import org.sonar.api.resources.Qualifiers; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; import org.sonar.api.server.ws.WebService.Param; +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.property.PropertyDto; +import org.sonar.db.property.PropertyQuery; import org.sonar.server.component.es.ProjectMeasuresIndex; import org.sonar.server.component.es.ProjectMeasuresQuery; import org.sonar.server.es.Facets; import org.sonar.server.es.SearchIdResult; import org.sonar.server.es.SearchOptions; +import org.sonar.server.user.UserSession; import org.sonarqube.ws.Common; import org.sonarqube.ws.WsComponents.Component; import org.sonarqube.ws.WsComponents.SearchProjectsWsResponse; @@ -47,6 +53,7 @@ import org.sonarqube.ws.client.component.SearchProjectsRequest; import static com.google.common.base.MoreObjects.firstNonNull; import static org.sonar.server.component.es.ProjectMeasuresIndex.SUPPORTED_FACETS; +import static org.sonar.server.component.ws.ProjectMeasuresQueryFactory.newProjectMeasuresQuery; import static org.sonar.server.ws.WsUtils.writeProtobuf; import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_FILTER; import static org.sonarqube.ws.client.component.SearchProjectsRequest.DEFAULT_PAGE_SIZE; @@ -56,14 +63,13 @@ public class SearchProjectsAction implements ComponentsWsAction { private final DbClient dbClient; private final ProjectMeasuresIndex index; private final ProjectMeasuresQueryValidator queryValidator; - private final ProjectMeasuresQueryFactory queryFactory; + private final UserSession userSession; - public SearchProjectsAction(DbClient dbClient, ProjectMeasuresIndex index, ProjectMeasuresQueryFactory queryFactory, - ProjectMeasuresQueryValidator queryValidator) { + public SearchProjectsAction(DbClient dbClient, ProjectMeasuresIndex index, ProjectMeasuresQueryValidator queryValidator, UserSession userSession) { this.dbClient = dbClient; this.index = index; - this.queryFactory = queryFactory; this.queryValidator = queryValidator; + this.userSession = userSession; } @Override @@ -93,25 +99,44 @@ public class SearchProjectsAction implements ComponentsWsAction { private SearchProjectsWsResponse doHandle(SearchProjectsRequest request) { try (DbSession dbSession = dbClient.openSession(false)) { - SearchResults searchResults = searchProjects(dbSession, request); + SearchResults searchResults = searchData(dbSession, request); return buildResponse(request, searchResults); } } - private SearchResults searchProjects(DbSession dbSession, SearchProjectsRequest request) { + private SearchResults searchData(DbSession dbSession, SearchProjectsRequest request) { String filter = firstNonNull(request.getFilter(), ""); - ProjectMeasuresQuery query = queryFactory.newProjectMeasuresQuery(dbSession, filter); + + Set favoriteProjectUuids = searchFavoriteProjects(dbSession); + + ProjectMeasuresQuery query = newProjectMeasuresQuery(filter, favoriteProjectUuids); queryValidator.validate(dbSession, query); - SearchIdResult searchResults = index.search(query, new SearchOptions() + SearchIdResult esResults = index.search(query, new SearchOptions() .addFacets(request.getFacets()) .setPage(request.getPage(), request.getPageSize())); - Ordering ordering = Ordering.explicit(searchResults.getIds()).onResultOf(ComponentDto::uuid); - List projects = ordering.immutableSortedCopy(dbClient.componentDao().selectByUuids(dbSession, searchResults.getIds())); + Ordering ordering = Ordering.explicit(esResults.getIds()).onResultOf(ComponentDto::uuid); + List projects = ordering.immutableSortedCopy(dbClient.componentDao().selectByUuids(dbSession, esResults.getIds())); + + return new SearchResults(projects, favoriteProjectUuids, esResults); + } - return new SearchResults(projects, searchResults); + private Set searchFavoriteProjects(DbSession dbSession) { + List favoriteDbIds = dbClient.propertiesDao().selectByQuery(PropertyQuery.builder() + .setUserId(userSession.getUserId()) + .setKey("favourite") + .build(), dbSession) + .stream() + .map(PropertyDto::getResourceId) + .collect(Collectors.toList()); + + return dbClient.componentDao().selectByIds(dbSession, favoriteDbIds) + .stream() + .filter(dbComponent -> Qualifiers.PROJECT.equals(dbComponent.qualifier())) + .map(ComponentDto::uuid) + .collect(Collectors.toSet()); } private static SearchProjectsRequest toRequest(Request httpRequest) { @@ -126,7 +151,7 @@ public class SearchProjectsAction implements ComponentsWsAction { } private static SearchProjectsWsResponse buildResponse(SearchProjectsRequest request, SearchResults searchResults) { - Function dbToWsComponent = new DbToWsComponent(); + Function dbToWsComponent = new DbToWsComponent(searchResults.favoriteProjectUuids); return Stream.of(SearchProjectsWsResponse.newBuilder()) .map(response -> response.setPaging(Common.Paging.newBuilder() @@ -205,9 +230,11 @@ public class SearchProjectsAction implements ComponentsWsAction { private static class DbToWsComponent implements Function { private final Component.Builder wsComponent; + private final Set favoriteProjectUuids; - private DbToWsComponent() { + private DbToWsComponent(Set favoriteProjectUuids) { this.wsComponent = Component.newBuilder(); + this.favoriteProjectUuids = favoriteProjectUuids; } @Override @@ -217,17 +244,20 @@ public class SearchProjectsAction implements ComponentsWsAction { .setId(dbComponent.uuid()) .setKey(dbComponent.key()) .setName(dbComponent.name()) + .setIsFavorite(favoriteProjectUuids.contains(dbComponent.uuid())) .build(); } } private static class SearchResults { private final List projects; + private final Set favoriteProjectUuids; private final Facets facets; private final int total; - private SearchResults(List projects, SearchIdResult searchResults) { + private SearchResults(List projects, Set favoriteProjectUuids, SearchIdResult searchResults) { this.projects = projects; + this.favoriteProjectUuids = favoriteProjectUuids; this.total = (int) searchResults.getTotal(); this.facets = searchResults.getFacets(); } diff --git a/server/sonar-server/src/main/resources/org/sonar/server/component/ws/search_projects-example.json b/server/sonar-server/src/main/resources/org/sonar/server/component/ws/search_projects-example.json index 14dc2fc75ed..4dead04eec0 100644 --- a/server/sonar-server/src/main/resources/org/sonar/server/component/ws/search_projects-example.json +++ b/server/sonar-server/src/main/resources/org/sonar/server/component/ws/search_projects-example.json @@ -8,17 +8,20 @@ { "id": "AU-Tpxb--iU5OvuD2FLy", "key": "my_project", - "name": "My Project 1" + "name": "My Project 1", + "isFavorite": true }, { "id": "AU-TpxcA-iU5OvuD2FLz", "key": "another_project", - "name": "My Project 2" + "name": "My Project 2", + "isFavorite": false }, { "id": "AU-TpxcA-iU5OvuD2FL0", "key": "third_project", - "name": "My Project 3" + "name": "My Project 3", + "isFavorite": false } ] } diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/es/ProjectMeasuresIndexTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/es/ProjectMeasuresIndexTest.java index ac31148d9ea..341a8d420ee 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/es/ProjectMeasuresIndexTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/es/ProjectMeasuresIndexTest.java @@ -39,6 +39,7 @@ import org.sonar.server.permission.index.PermissionIndexerTester; import org.sonar.server.tester.UserSessionRule; import static com.google.common.collect.Lists.newArrayList; +import static com.google.common.collect.Sets.newHashSet; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; @@ -203,7 +204,7 @@ public class ProjectMeasuresIndexTest { newDoc("P1", "K1", "N1"), newDoc("P2", "K2", "N2"), newDoc("P3", "K3", "N3")); - ProjectMeasuresQuery esQuery = new ProjectMeasuresQuery().setProjectUuids(newArrayList("P1", "P3")); + ProjectMeasuresQuery esQuery = new ProjectMeasuresQuery().setProjectUuids(newHashSet("P1", "P3")); List result = underTest.search(esQuery, new SearchOptions()).getIds(); diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentsWsModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentsWsModuleTest.java index 01c09012ce9..f8dee7ef5f4 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentsWsModuleTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentsWsModuleTest.java @@ -29,6 +29,6 @@ public class ComponentsWsModuleTest { public void verify_count_of_added_components() { ComponentContainer container = new ComponentContainer(); new ComponentsWsModule().configure(container); - assertThat(container.size()).isEqualTo(13 + 2); + assertThat(container.size()).isEqualTo(12 + 2); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/ProjectMeasuresQueryFactoryTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/ProjectMeasuresQueryFactoryTest.java index 96bddea1dcc..22230e9175f 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/ws/ProjectMeasuresQueryFactoryTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/ws/ProjectMeasuresQueryFactoryTest.java @@ -23,17 +23,15 @@ package org.sonar.server.component.ws; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.api.utils.System2; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; -import org.sonar.db.DbTester; import org.sonar.server.component.es.ProjectMeasuresQuery; import org.sonar.server.tester.UserSessionRule; +import static java.util.Collections.emptySet; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; import static org.sonar.server.component.es.ProjectMeasuresQuery.MetricCriterion; import static org.sonar.server.component.es.ProjectMeasuresQuery.Operator; +import static org.sonar.server.component.ws.ProjectMeasuresQueryFactory.newProjectMeasuresQuery; import static org.sonar.server.computation.task.projectanalysis.measure.Measure.Level.OK; public class ProjectMeasuresQueryFactoryTest { @@ -42,17 +40,10 @@ public class ProjectMeasuresQueryFactoryTest { public ExpectedException expectedException = ExpectedException.none(); @Rule public UserSessionRule userSession = UserSessionRule.standalone(); - @Rule - public DbTester db = DbTester.create(System2.INSTANCE); - - private DbClient dbClient = db.getDbClient(); - private DbSession dbSession = db.getSession(); - - private ProjectMeasuresQueryFactory underTest = new ProjectMeasuresQueryFactory(dbClient, userSession); @Test public void create_query() throws Exception { - ProjectMeasuresQuery query = underTest.newProjectMeasuresQuery(dbSession, "ncloc > 10 and coverage <= 80"); + ProjectMeasuresQuery query = newProjectMeasuresQuery("ncloc > 10 and coverage <= 80", emptySet()); assertThat(query.getMetricCriteria()) .extracting(MetricCriterion::getMetricKey, MetricCriterion::getOperator, MetricCriterion::getValue) @@ -63,7 +54,7 @@ public class ProjectMeasuresQueryFactoryTest { @Test public void create_query_having_lesser_than_operation() throws Exception { - ProjectMeasuresQuery query = underTest.newProjectMeasuresQuery(dbSession, "ncloc < 10"); + ProjectMeasuresQuery query = newProjectMeasuresQuery("ncloc < 10", emptySet()); assertThat(query.getMetricCriteria()) .extracting(MetricCriterion::getMetricKey, MetricCriterion::getOperator, MetricCriterion::getValue) @@ -72,7 +63,7 @@ public class ProjectMeasuresQueryFactoryTest { @Test public void create_query_having_lesser_than_or_equals_operation() throws Exception { - ProjectMeasuresQuery query = underTest.newProjectMeasuresQuery(dbSession, "ncloc <= 10"); + ProjectMeasuresQuery query = newProjectMeasuresQuery("ncloc <= 10", emptySet()); assertThat(query.getMetricCriteria()) .extracting(MetricCriterion::getMetricKey, MetricCriterion::getOperator, MetricCriterion::getValue) @@ -81,7 +72,7 @@ public class ProjectMeasuresQueryFactoryTest { @Test public void create_query_having_greater_than_operation() throws Exception { - ProjectMeasuresQuery query = underTest.newProjectMeasuresQuery(dbSession, "ncloc > 10"); + ProjectMeasuresQuery query = newProjectMeasuresQuery("ncloc > 10", emptySet()); assertThat(query.getMetricCriteria()) .extracting(MetricCriterion::getMetricKey, MetricCriterion::getOperator, MetricCriterion::getValue) @@ -90,7 +81,7 @@ public class ProjectMeasuresQueryFactoryTest { @Test public void create_query_having_greater_than_or_equals_operation() throws Exception { - ProjectMeasuresQuery query = underTest.newProjectMeasuresQuery(dbSession, "ncloc >= 10"); + ProjectMeasuresQuery query = newProjectMeasuresQuery("ncloc >= 10", emptySet()); assertThat(query.getMetricCriteria()) .extracting(MetricCriterion::getMetricKey, MetricCriterion::getOperator, MetricCriterion::getValue) @@ -99,7 +90,7 @@ public class ProjectMeasuresQueryFactoryTest { @Test public void create_query_having_equal_operation() throws Exception { - ProjectMeasuresQuery query = underTest.newProjectMeasuresQuery(dbSession, "ncloc = 10"); + ProjectMeasuresQuery query = newProjectMeasuresQuery("ncloc = 10", emptySet()); assertThat(query.getMetricCriteria()) .extracting(MetricCriterion::getMetricKey, MetricCriterion::getOperator, MetricCriterion::getValue) @@ -108,21 +99,21 @@ public class ProjectMeasuresQueryFactoryTest { @Test public void create_query_on_quality_gate() throws Exception { - ProjectMeasuresQuery query = underTest.newProjectMeasuresQuery(dbSession, "alert_status = OK"); + ProjectMeasuresQuery query = newProjectMeasuresQuery("alert_status = OK", emptySet()); assertThat(query.getQualityGateStatus().name()).isEqualTo(OK.name()); } @Test public void query_without_favorites_by_default() { - ProjectMeasuresQuery query = underTest.newProjectMeasuresQuery(dbSession, "ncloc = 10"); + ProjectMeasuresQuery query = newProjectMeasuresQuery("ncloc = 10", emptySet()); assertThat(query.doesFilterOnProjectUuids()).isFalse(); } @Test public void create_query_with_favorites() throws Exception { - ProjectMeasuresQuery query = underTest.newProjectMeasuresQuery(dbSession, "isFavorite"); + ProjectMeasuresQuery query = newProjectMeasuresQuery("isFavorite", emptySet()); assertThat(query.doesFilterOnProjectUuids()).isTrue(); } @@ -130,17 +121,17 @@ public class ProjectMeasuresQueryFactoryTest { @Test public void fail_to_create_query_on_quality_gate_when_operator_is_not_equal() throws Exception { expectedException.expect(IllegalArgumentException.class); - underTest.newProjectMeasuresQuery(dbSession, "alert_status > OK"); + newProjectMeasuresQuery("alert_status > OK", emptySet()); } @Test public void search_is_case_insensitive() throws Exception { - assertThat(underTest.newProjectMeasuresQuery(dbSession, "ncloc > 10 AnD coverage <= 80 AND debt = 10 AND issues = 20").getMetricCriteria()).hasSize(4); + assertThat(newProjectMeasuresQuery("ncloc > 10 AnD coverage <= 80 AND debt = 10 AND issues = 20", emptySet()).getMetricCriteria()).hasSize(4); } @Test public void convert_metric_to_lower_case() throws Exception { - assertThat(underTest.newProjectMeasuresQuery(dbSession, "NCLOC > 10 AND coVERage <= 80").getMetricCriteria()) + assertThat(newProjectMeasuresQuery("NCLOC > 10 AND coVERage <= 80", emptySet()).getMetricCriteria()) .extracting(MetricCriterion::getMetricKey, MetricCriterion::getOperator, MetricCriterion::getValue) .containsOnly( tuple("ncloc", Operator.GT, 10d), @@ -149,14 +140,14 @@ public class ProjectMeasuresQueryFactoryTest { @Test public void ignore_white_spaces() throws Exception { - assertThat(underTest.newProjectMeasuresQuery(dbSession, " ncloc > 10 ").getMetricCriteria()) + assertThat(newProjectMeasuresQuery(" ncloc > 10 ", emptySet()).getMetricCriteria()) .extracting(MetricCriterion::getMetricKey, MetricCriterion::getOperator, MetricCriterion::getValue) .containsOnly(tuple("ncloc", Operator.GT, 10d)); } @Test public void accept_empty_query() throws Exception { - ProjectMeasuresQuery result = underTest.newProjectMeasuresQuery(dbSession, ""); + ProjectMeasuresQuery result = newProjectMeasuresQuery("", emptySet()); assertThat(result.getMetricCriteria()).isEmpty(); } @@ -165,7 +156,7 @@ public class ProjectMeasuresQueryFactoryTest { public void fail_on_invalid_criteria() throws Exception { expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Invalid criterion 'ncloc ? 10'"); - underTest.newProjectMeasuresQuery(dbSession, "ncloc ? 10"); + newProjectMeasuresQuery("ncloc ? 10", emptySet()); } @Test @@ -173,34 +164,34 @@ public class ProjectMeasuresQueryFactoryTest { expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Invalid criterion 'ncloc ? 10'"); - underTest.newProjectMeasuresQuery(dbSession, " ncloc ? 10 "); + newProjectMeasuresQuery(" ncloc ? 10 ", emptySet()); } @Test public void fail_when_not_double() throws Exception { expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Invalid criterion 'ncloc > ten'"); - underTest.newProjectMeasuresQuery(dbSession, "ncloc > ten"); + newProjectMeasuresQuery("ncloc > ten", emptySet()); } @Test public void fail_when_no_operator() throws Exception { expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Invalid criterion 'ncloc 10'"); - underTest.newProjectMeasuresQuery(dbSession, "ncloc 10"); + newProjectMeasuresQuery("ncloc 10", emptySet()); } @Test public void fail_when_no_key() throws Exception { expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Invalid criterion '>= 10'"); - underTest.newProjectMeasuresQuery(dbSession, ">= 10"); + newProjectMeasuresQuery(">= 10", emptySet()); } @Test public void fail_when_no_value() throws Exception { expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Invalid criterion 'ncloc >='"); - underTest.newProjectMeasuresQuery(dbSession, "ncloc >="); + newProjectMeasuresQuery("ncloc >=", emptySet()); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/ProjectMeasuresQueryValidatorTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/ProjectMeasuresQueryValidatorTest.java index 33de8438bce..7aa322f0108 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/ws/ProjectMeasuresQueryValidatorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/ws/ProjectMeasuresQueryValidatorTest.java @@ -30,12 +30,14 @@ import org.sonar.db.DbTester; import org.sonar.db.metric.MetricDto; import org.sonar.server.tester.UserSessionRule; +import static java.util.Collections.emptySet; 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.INT; import static org.sonar.api.measures.Metric.ValueType.STRING; import static org.sonar.api.measures.Metric.ValueType.WORK_DUR; import static org.sonar.db.metric.MetricTesting.newMetricDto; +import static org.sonar.server.component.ws.ProjectMeasuresQueryFactory.newProjectMeasuresQuery; public class ProjectMeasuresQueryValidatorTest { @@ -50,20 +52,19 @@ public class ProjectMeasuresQueryValidatorTest { private DbClient dbClient = db.getDbClient(); private DbSession dbSession = db.getSession(); - private ProjectMeasuresQueryFactory queryFactory = new ProjectMeasuresQueryFactory(dbClient, userSession); private ProjectMeasuresQueryValidator underTest = new ProjectMeasuresQueryValidator(dbClient); @Test public void query_with_empty_metrics_is_valid() throws Exception { - underTest.validate(dbSession, queryFactory.newProjectMeasuresQuery(dbSession, "")); + underTest.validate(dbSession, newProjectMeasuresQuery("", emptySet())); } @Test public void does_not_fail_when_metric_criteria_contains_an_existing_metric() throws Exception { insertValidMetric("ncloc"); - underTest.validate(dbSession, queryFactory.newProjectMeasuresQuery(dbSession, "ncloc > 10")); + underTest.validate(dbSession, newProjectMeasuresQuery("ncloc > 10", emptySet())); } @Test @@ -76,7 +77,7 @@ public class ProjectMeasuresQueryValidatorTest { expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Following metrics are not numeric : [data, distrib, string]"); - underTest.validate(dbSession, queryFactory.newProjectMeasuresQuery(dbSession, "data > 10 and distrib = 11 and ncloc <= 20 and debt < 30 and string = 40")); + underTest.validate(dbSession, newProjectMeasuresQuery("data > 10 and distrib = 11 and ncloc <= 20 and debt < 30 and string = 40", emptySet())); } @Test @@ -85,7 +86,7 @@ public class ProjectMeasuresQueryValidatorTest { expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Following metrics are disabled : [ncloc]"); - underTest.validate(dbSession, queryFactory.newProjectMeasuresQuery(dbSession, "ncloc > 10")); + underTest.validate(dbSession, newProjectMeasuresQuery("ncloc > 10", emptySet())); } @Test @@ -94,7 +95,7 @@ public class ProjectMeasuresQueryValidatorTest { expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Unknown metric(s) [unknown]"); - underTest.validate(dbSession, queryFactory.newProjectMeasuresQuery(dbSession, "unknown > 10")); + underTest.validate(dbSession, newProjectMeasuresQuery("unknown > 10", emptySet())); } @Test @@ -103,7 +104,7 @@ public class ProjectMeasuresQueryValidatorTest { expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Unknown metric(s) [coverage, debt]"); - underTest.validate(dbSession, queryFactory.newProjectMeasuresQuery(dbSession, "debt > 10 AND ncloc <= 20 AND coverage > 30")); + underTest.validate(dbSession, newProjectMeasuresQuery("debt > 10 AND ncloc <= 20 AND coverage > 30", emptySet())); } private void insertValidMetric(String metricKey) { 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 a826c026480..d5c1285d532 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 @@ -97,17 +97,16 @@ public class SearchProjectsActionTest { private PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(es); private final ProjectMeasuresIndex index = new ProjectMeasuresIndex(es.client(), userSession); - private ProjectMeasuresQueryFactory queryFactory = new ProjectMeasuresQueryFactory(dbClient, userSession); private final ProjectMeasuresQueryValidator queryValidator = new ProjectMeasuresQueryValidator(dbClient); private WsActionTester ws = new WsActionTester( - new SearchProjectsAction(dbClient, index, queryFactory, queryValidator)); + new SearchProjectsAction(dbClient, index, queryValidator, userSession)); private SearchProjectsRequest.Builder request = SearchProjectsRequest.builder(); @Test public void json_example() { - insertProjectInDbAndEs(newProjectDto() + long project1Id = insertProjectInDbAndEs(newProjectDto() .setUuid(Uuids.UUID_EXAMPLE_01) .setKey(KeyExamples.KEY_PROJECT_EXAMPLE_001) .setName("My Project 1")); @@ -119,6 +118,9 @@ public class SearchProjectsActionTest { .setUuid(Uuids.UUID_EXAMPLE_03) .setKey(KeyExamples.KEY_PROJECT_EXAMPLE_003) .setName("My Project 3")); + userSession.login().setUserId(23); + dbClient.propertiesDao().saveProperty(dbSession, new PropertyDto().setKey("favourite").setResourceId(project1Id).setUserId(23L)); + dbSession.commit(); String result = ws.newRequest().execute().getInput(); @@ -278,8 +280,8 @@ public class SearchProjectsActionTest { assertThat(def.responseExampleAsString()).isNotEmpty(); } - private void insertProjectInDbAndEs(ComponentDto project) { - insertProjectInDbAndEs(project, emptyList()); + private long insertProjectInDbAndEs(ComponentDto project) { + return insertProjectInDbAndEs(project, emptyList()); } private long insertProjectInDbAndEs(ComponentDto project, List> measures) { diff --git a/sonar-ws/src/main/protobuf/ws-components.proto b/sonar-ws/src/main/protobuf/ws-components.proto index 004df58988c..6d70af9c280 100644 --- a/sonar-ws/src/main/protobuf/ws-components.proto +++ b/sonar-ws/src/main/protobuf/ws-components.proto @@ -75,4 +75,5 @@ message Component { optional string qualifier = 8; optional string path = 9; optional string language = 10; + optional bool isFavorite = 11; } -- 2.39.5