Selaa lähdekoodia

SONAR-9206 Enhance /api/components/search_projects response with organizations

tags/7.5
Guillaume Jambet 6 vuotta sitten
vanhempi
commit
d651bd4c8f

+ 31
- 5
server/sonar-server/src/main/java/org/sonar/server/component/ws/SearchProjectsAction.java Näytä tiedosto

@@ -23,6 +23,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Ordering;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -58,16 +59,19 @@ import org.sonar.server.measure.index.ProjectMeasuresQuery;
import org.sonar.server.project.Visibility;
import org.sonar.server.user.UserSession;
import org.sonarqube.ws.Common;
import org.sonarqube.ws.Components;
import org.sonarqube.ws.Components.Component;
import org.sonarqube.ws.Components.SearchProjectsWsResponse;

import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableList.of;
import static com.google.common.collect.Sets.newHashSet;
import static java.lang.String.format;
import static java.util.Collections.emptyMap;
import static java.util.Objects.requireNonNull;
import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY;
import static org.sonar.api.server.ws.WebService.Param.FACETS;
import static org.sonar.api.server.ws.WebService.Param.FIELDS;
import static org.sonar.api.utils.DateUtils.formatDateTime;
import static org.sonar.core.util.Protobuf.setNullable;
@@ -92,9 +96,11 @@ public class SearchProjectsAction implements ComponentsWsAction {

public static final int MAX_PAGE_SIZE = 500;
public static final int DEFAULT_PAGE_SIZE = 100;
private static final String ALL = "_all";
private static final String ORGANIZATIONS = "organizations";
private static final String ANALYSIS_DATE = "analysisDate";
private static final String LEAK_PERIOD_DATE = "leakPeriodDate";
private static final Set<String> POSSIBLE_FIELDS = newHashSet(ANALYSIS_DATE, LEAK_PERIOD_DATE);
private static final Set<String> POSSIBLE_FIELDS = newHashSet(ALL, ORGANIZATIONS, ANALYSIS_DATE, LEAK_PERIOD_DATE);

private final DbClient dbClient;
private final ProjectMeasuresIndex index;
@@ -130,7 +136,7 @@ public class SearchProjectsAction implements ComponentsWsAction {
.setRequired(false)
.setInternal(true)
.setSince("6.3");
action.createParam(Param.FACETS)
action.createParam(FACETS)
.setDescription("Comma-separated list of the facets to be computed. No facet is computed by default.")
.setPossibleValues(SUPPORTED_FACETS.stream().sorted().collect(MoreCollectors.toList(SUPPORTED_FACETS.size())));
action
@@ -299,11 +305,16 @@ public class SearchProjectsAction implements ComponentsWsAction {
.setAsc(httpRequest.mandatoryParamAsBoolean(Param.ASCENDING))
.setPage(httpRequest.mandatoryParamAsInt(Param.PAGE))
.setPageSize(httpRequest.mandatoryParamAsInt(Param.PAGE_SIZE));
if (httpRequest.hasParam(Param.FACETS)) {
request.setFacets(httpRequest.paramAsStrings(Param.FACETS));
if (httpRequest.hasParam(FACETS)) {
request.setFacets(httpRequest.mandatoryParamAsStrings(FACETS));
}
if (httpRequest.hasParam(FIELDS)) {
request.setAdditionalFields(httpRequest.paramAsStrings(FIELDS));
List<String> paramsAsString = httpRequest.mandatoryParamAsStrings(FIELDS);
if (paramsAsString.contains(ALL)) {
request.setAdditionalFields(of(ORGANIZATIONS, ANALYSIS_DATE, LEAK_PERIOD_DATE));
} else {
request.setAdditionalFields(paramsAsString);
}
}
return request.build();
}
@@ -312,6 +323,11 @@ public class SearchProjectsAction implements ComponentsWsAction {
Function<ComponentDto, Component> dbToWsComponent = new DbToWsComponent(request, organizationsByUuid, searchResults.favoriteProjectUuids, searchResults.analysisByProjectUuid,
userSession.isLoggedIn());

Map<String, OrganizationDto> organizationsByUuidForAdditionalInfo = new HashMap<>();
if (request.additionalFields.contains(ORGANIZATIONS)) {
organizationsByUuidForAdditionalInfo.putAll(organizationsByUuid);
}

return Stream.of(SearchProjectsWsResponse.newBuilder())
.map(response -> response.setPaging(Common.Paging.newBuilder()
.setPageIndex(request.getPage())
@@ -323,6 +339,15 @@ public class SearchProjectsAction implements ComponentsWsAction {
.forEach(response::addComponents);
return response;
})
.map(response -> {
organizationsByUuidForAdditionalInfo.values().stream().forEach(
dto -> response.addOrganizations(
Components.Organization.newBuilder()
.setKey(dto.getKey())
.setName(dto.getName())
.build()));
return response;
})
.map(response -> addFacets(searchResults, response))
.map(SearchProjectsWsResponse.Builder::build)
.findFirst()
@@ -532,6 +557,7 @@ public class SearchProjectsAction implements ComponentsWsAction {
public static RequestBuilder builder() {
return new RequestBuilder();
}

}

static class RequestBuilder {

+ 1
- 1
server/sonar-server/src/main/java/org/sonar/server/component/ws/SuggestionsAction.java Näytä tiedosto

@@ -72,7 +72,7 @@ import static org.sonar.core.util.stream.MoreCollectors.toSet;
import static org.sonar.server.component.index.SuggestionQuery.DEFAULT_LIMIT;
import static org.sonar.server.es.DefaultIndexSettings.MINIMUM_NGRAM_LENGTH;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
import static org.sonarqube.ws.Components.SuggestionsWsResponse.Organization;
import static org.sonarqube.ws.Components.Organization;
import static org.sonarqube.ws.Components.SuggestionsWsResponse.newBuilder;
import static org.sonarqube.ws.client.component.ComponentsWsParameters.ACTION_SUGGESTIONS;


+ 10
- 0
server/sonar-server/src/main/resources/org/sonar/server/component/ws/search_projects-example.json Näytä tiedosto

@@ -4,6 +4,16 @@
"pageSize": 100,
"total": 3
},
"organizations": [
{
"key": "my-org-key-1",
"name": "Foo"
},
{
"key": "my-org-key-2",
"name": "Bar"
}
],
"components": [
{
"organization": "my-org-key-1",

+ 23
- 12
server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchProjectsActionTest.java Näytä tiedosto

@@ -54,7 +54,6 @@ import org.sonar.server.measure.index.ProjectMeasuresIndexer;
import org.sonar.server.permission.index.AuthorizationTypeSupport;
import org.sonar.server.permission.index.PermissionIndexerTester;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.KeyExamples;
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.WsActionTester;
import org.sonarqube.ws.Common;
@@ -89,6 +88,9 @@ import static org.sonar.core.util.stream.MoreCollectors.toList;
import static org.sonar.server.computation.task.projectanalysis.metric.Metric.MetricType.DATA;
import static org.sonar.server.computation.task.projectanalysis.metric.Metric.MetricType.PERCENT;
import static org.sonar.server.computation.task.projectanalysis.metric.Metric.MetricType.RATING;
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.KeyExamples.KEY_PROJECT_EXAMPLE_003;
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;
@@ -183,9 +185,9 @@ public class SearchProjectsActionTest {
assertThat(asc.defaultValue()).isEqualTo("true");
assertThat(asc.possibleValues()).containsOnly("true", "false", "yes", "no");

Param additionalFields = def.param("f");
assertThat(additionalFields.defaultValue()).isNull();
assertThat(additionalFields.possibleValues()).containsOnly("analysisDate", "leakPeriodDate");
Param f = def.param("f");
assertThat(f.defaultValue()).isNull();
assertThat(f.possibleValues()).containsOnly("_all", "organizations", "analysisDate", "leakPeriodDate");

Param facets = def.param("facets");
assertThat(facets.defaultValue()).isNull();
@@ -196,31 +198,40 @@ public class SearchProjectsActionTest {
@Test
public void json_example() {
userSession.logIn();
OrganizationDto organization1Dto = db.organizations().insertForKey("my-org-key-1");
OrganizationDto organization2Dto = db.organizations().insertForKey("my-org-key-2");
OrganizationDto organization2Dto = db.organizations().insert(dto-> dto.setKey("my-org-key-2").setName("Bar"));
OrganizationDto organization1Dto = db.organizations().insert(dto-> dto.setKey("my-org-key-1").setName("Foo"));

MetricDto coverage = db.measures().insertMetric(c -> c.setKey(COVERAGE).setValueType(PERCENT.name()));
ComponentDto project1 = insertProject(organization1Dto, c -> c
.setDbKey(KeyExamples.KEY_PROJECT_EXAMPLE_001)
.setDbKey(KEY_PROJECT_EXAMPLE_001)
.setName("My Project 1")
.setTagsString("finance, java"),
new Measure(coverage, c -> c.setValue(80d)));
ComponentDto project2 = insertProject(organization1Dto, c -> c
.setDbKey(KeyExamples.KEY_PROJECT_EXAMPLE_002)
.setDbKey(KEY_PROJECT_EXAMPLE_002)
.setName("My Project 2"),
new Measure(coverage, c -> c.setValue(90d)));
ComponentDto project3 = insertProject(organization2Dto, c -> c
.setDbKey(KeyExamples.KEY_PROJECT_EXAMPLE_003)
.setDbKey(KEY_PROJECT_EXAMPLE_003)
.setName("My Project 3")
.setTagsString("sales, offshore, java"),
new Measure(coverage, c -> c.setValue(20d)));
addFavourite(project1);

String jsonResult = ws.newRequest().setParam(Param.FACETS, COVERAGE).execute().getInput();
SearchProjectsWsResponse protobufResult = ws.newRequest().setParam(Param.FACETS, COVERAGE).executeProtobuf(SearchProjectsWsResponse.class);
String jsonResult = ws.newRequest()
.setParam(FACETS, COVERAGE)
.setParam(FIELDS, "_all")
.execute().getInput();

assertJson(jsonResult).withStrictArrayOrder().ignoreFields("id").isSimilarTo(ws.getDef().responseExampleAsString());
assertJson(ws.getDef().responseExampleAsString()).ignoreFields("id").withStrictArrayOrder().isSimilarTo(jsonResult);
assertThat(protobufResult.getComponentsList()).extracting(Component::getId).containsExactly(project1.uuid(), project2.uuid(), project3.uuid());

SearchProjectsWsResponse protobufResult = ws.newRequest()
.setParam(FACETS, COVERAGE)
.executeProtobuf(SearchProjectsWsResponse.class);

assertThat(protobufResult.getComponentsList()).extracting(Component::getId)
.containsExactly(project1.uuid(), project2.uuid(), project3.uuid());
}

@Test

+ 2
- 2
server/sonar-server/src/test/java/org/sonar/server/component/ws/SuggestionsActionTest.java Näytä tiedosto

@@ -49,12 +49,12 @@ import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.TestResponse;
import org.sonar.server.ws.WsActionTester;
import org.sonarqube.ws.MediaTypes;
import org.sonarqube.ws.Components.Organization;
import org.sonarqube.ws.Components.SuggestionsWsResponse;
import org.sonarqube.ws.Components.SuggestionsWsResponse.Category;
import org.sonarqube.ws.Components.SuggestionsWsResponse.Organization;
import org.sonarqube.ws.Components.SuggestionsWsResponse.Project;
import org.sonarqube.ws.Components.SuggestionsWsResponse.Suggestion;
import org.sonarqube.ws.MediaTypes;

import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;

+ 10
- 7
sonar-ws/src/main/protobuf/ws-components.proto Näytä tiedosto

@@ -69,11 +69,6 @@ message SuggestionsWsResponse {
optional bool isFavorite = 7;
}

message Organization {
optional string key = 1;
optional string name = 2;
}

message Project {
optional string key = 1;
optional string name = 2;
@@ -83,8 +78,9 @@ message SuggestionsWsResponse {
// WS api/components/search_projects
message SearchProjectsWsResponse {
optional sonarqube.ws.commons.Paging paging = 1;
repeated Component components = 2;
optional sonarqube.ws.commons.Facets facets = 3;
repeated Organization organizations = 2;
repeated Component components = 3;
optional sonarqube.ws.commons.Facets facets = 4;
}

// WS api/components/provisioned
@@ -129,3 +125,10 @@ message Component {
}
}

message Organization {
optional string key = 1;
optional string name = 2;
}




Loading…
Peruuta
Tallenna