From aa868b02dbe13f89e0f52eaac67a5510b8697903 Mon Sep 17 00:00:00 2001 From: Daniel Schwarz Date: Mon, 10 Apr 2017 10:08:59 +0200 Subject: [PATCH] SONAR-9078 return project names for api/components/suggestions --- .../component/ws/SuggestionsAction.java | 30 ++++++++++++++--- .../component/ws/SuggestionsActionTest.java | 32 +++++++++++++++++-- .../src/main/protobuf/ws-components.proto | 7 ++++ 3 files changed, 61 insertions(+), 8 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/SuggestionsAction.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/SuggestionsAction.java index 09c94003b36..f256f0ad15b 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/ws/SuggestionsAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/ws/SuggestionsAction.java @@ -42,6 +42,7 @@ import org.sonar.server.es.textsearch.ComponentTextSearchFeature; import org.sonarqube.ws.WsComponents.Component; import org.sonarqube.ws.WsComponents.SuggestionsWsResponse; import org.sonarqube.ws.WsComponents.SuggestionsWsResponse.Category; +import org.sonarqube.ws.WsComponents.SuggestionsWsResponse.Project; import static com.google.common.base.Preconditions.checkState; import static java.util.Arrays.stream; @@ -138,6 +139,7 @@ public class SuggestionsAction implements ComponentsWsAction { if (!componentsPerQualifiers.isEmpty()) { Map organizationsByUuids; Map componentsByUuids; + Map projectsByUuids; try (DbSession dbSession = dbClient.openSession(false)) { Set componentUuids = componentsPerQualifiers.stream() .map(ComponentsPerQualifier::getComponentUuids) @@ -150,22 +152,29 @@ public class SuggestionsAction implements ComponentsWsAction { .collect(toSet()); organizationsByUuids = dbClient.organizationDao().selectByUuids(dbSession, organizationUuids).stream() .collect(MoreCollectors.uniqueIndex(OrganizationDto::getUuid)); + Set projectUuids = componentsByUuids.values().stream() + .filter(c -> !c.projectUuid().equals(c.uuid())) + .map(ComponentDto::projectUuid) + .collect(toSet()); + projectsByUuids = dbClient.componentDao().selectByUuids(dbSession, projectUuids).stream() + .collect(MoreCollectors.uniqueIndex(ComponentDto::uuid)); } builder - .addAllSuggestions(toCategoryResponses(componentsPerQualifiers, componentsByUuids, organizationsByUuids)) - .addAllOrganizations(toOrganizationResponses(organizationsByUuids)); + .addAllSuggestions(toCategoryResponses(componentsPerQualifiers, componentsByUuids, organizationsByUuids, projectsByUuids)) + .addAllOrganizations(toOrganizationResponses(organizationsByUuids)) + .addAllProjects(toProjectResponses(projectsByUuids)); } ofNullable(warning).ifPresent(builder::setWarning); return builder.build(); } private static List toCategoryResponses(List componentsPerQualifiers, Map componentsByUuids, - Map organizationByUuids) { + Map organizationByUuids, Map projectsByUuids) { return componentsPerQualifiers.stream().map(qualifier -> { List results = qualifier.getComponentUuids().stream() .map(componentsByUuids::get) - .map(dto -> dtoToComponent(dto, organizationByUuids)) + .map(dto -> dtoToComponent(dto, organizationByUuids, projectsByUuids)) .collect(toList()); return Category.newBuilder() @@ -176,11 +185,13 @@ public class SuggestionsAction implements ComponentsWsAction { }).collect(toList()); } - private static Component dtoToComponent(ComponentDto result, Map organizationByUuid) { + private static Component dtoToComponent(ComponentDto result, Map organizationByUuid, Map projectsByUuids) { String organizationKey = organizationByUuid.get(result.getOrganizationUuid()).getKey(); checkState(organizationKey != null, "Organization with uuid '%s' not found", result.getOrganizationUuid()); + String projectKey = ofNullable(result.projectUuid()).map(projectsByUuids::get).map(ComponentDto::getKey).orElse(""); return Component.newBuilder() .setOrganization(organizationKey) + .setProject(projectKey) .setKey(result.getKey()) .setName(result.longName()) .build(); @@ -194,4 +205,13 @@ public class SuggestionsAction implements ComponentsWsAction { .build()) .collect(Collectors.toList()); } + + private static List toProjectResponses(Map projectsByUuids) { + return projectsByUuids.values().stream() + .map(p -> Project.newBuilder() + .setKey(p.key()) + .setName(p.longName()) + .build()) + .collect(Collectors.toList()); + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/SuggestionsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/SuggestionsActionTest.java index 0ac15839dcb..533c94a4a41 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/ws/SuggestionsActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/ws/SuggestionsActionTest.java @@ -43,22 +43,24 @@ import org.sonar.server.permission.index.PermissionIndexerTester; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.TestRequest; import org.sonar.server.ws.WsActionTester; -import org.sonarqube.ws.WsComponents; +import org.sonarqube.ws.WsComponents.Component; import org.sonarqube.ws.WsComponents.SuggestionsWsResponse; +import org.sonarqube.ws.WsComponents.SuggestionsWsResponse.Project; import static java.util.Optional.ofNullable; import static java.util.stream.IntStream.range; import static java.util.stream.Stream.of; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.groups.Tuple.tuple; +import static org.sonar.db.component.ComponentTesting.newModuleDto; import static org.sonar.db.component.ComponentTesting.newProjectDto; import static org.sonar.server.component.ws.SuggestionsAction.DEFAULT_LIMIT; import static org.sonar.server.component.ws.SuggestionsAction.EXTENDED_LIMIT; import static org.sonar.server.component.ws.SuggestionsAction.SHORT_INPUT_WARNING; import static org.sonar.server.component.ws.SuggestionsAction.PARAM_MORE; import static org.sonar.server.component.ws.SuggestionsAction.PARAM_QUERY; -import static org.sonarqube.ws.WsComponents.SuggestionsWsResponse.Organization; import static org.sonarqube.ws.WsComponents.SuggestionsWsResponse.Category; +import static org.sonarqube.ws.WsComponents.SuggestionsWsResponse.Organization; import static org.sonarqube.ws.WsComponents.SuggestionsWsResponse.parseFrom; public class SuggestionsActionTest { @@ -116,7 +118,7 @@ public class SuggestionsActionTest { // assert correct id to be found assertThat(response.getSuggestionsList()) .flatExtracting(Category::getItemsList) - .extracting(WsComponents.Component::getKey, WsComponents.Component::getOrganization) + .extracting(Component::getKey, Component::getOrganization) .containsExactly(tuple(project.getKey(), organization.getKey())); } @@ -171,6 +173,30 @@ public class SuggestionsActionTest { .map(o -> tuple(o.getKey(), o.getName())).toArray(Tuple[]::new)); } + @Test + public void should_contain_project_names() throws Exception { + ComponentDto project = db.components().insertComponent(newProjectDto(organization)); + db.components().insertComponent(newModuleDto(project).setName("Module1")); + db.components().insertComponent(newModuleDto(project).setName("Module2")); + componentIndexer.indexProject(project.projectUuid(), ProjectIndexer.Cause.PROJECT_CREATION); + authorizationIndexerTester.allowOnlyAnyone(project); + + SuggestionsWsResponse response = actionTester.newRequest() + .setMethod("POST") + .setParam(PARAM_QUERY, "Module") + .executeProtobuf(SuggestionsWsResponse.class); + + assertThat(response.getSuggestionsList()) + .flatExtracting(Category::getItemsList) + .extracting(Component::getProject) + .containsOnly(project.key()); + + assertThat(response.getProjectsList()) + .extracting(Project::getKey, Project::getName) + .containsExactlyInAnyOrder( + tuple(project.key(), project.longName())); + } + @Test public void should_propose_to_show_more_results_if_7_projects_are_found() throws Exception { check_proposal_to_show_more_results(7, DEFAULT_LIMIT, 1L, null); diff --git a/sonar-ws/src/main/protobuf/ws-components.proto b/sonar-ws/src/main/protobuf/ws-components.proto index 76321305382..cd480edc5a0 100644 --- a/sonar-ws/src/main/protobuf/ws-components.proto +++ b/sonar-ws/src/main/protobuf/ws-components.proto @@ -51,6 +51,7 @@ message SuggestionsWsResponse { repeated Category suggestions = 1; optional string warning = 2; repeated Organization organizations = 3; + repeated Project projects = 4; message Category { optional string category = 1; @@ -62,6 +63,11 @@ message SuggestionsWsResponse { optional string key = 1; optional string name = 2; } + + message Project { + optional string key = 1; + optional string name = 2; + } } // WS api/components/search_projects @@ -77,6 +83,7 @@ message Component { optional string key = 2; optional string refId = 3; optional string refKey = 4; + optional string project = 15; optional string projectId = 5; optional string name = 6; optional string description = 7; -- 2.39.5