From c467e84eed1a60bbe8c0fe800e2cada2bb26bb4c Mon Sep 17 00:00:00 2001 From: Teryk Bellahsene Date: Mon, 27 Jun 2016 11:33:35 +0200 Subject: [PATCH] SONAR-7789 WS api/qualityprofiles/search return lastUsed field --- .../sonar/server/qualityprofile/QProfile.java | 14 +++- .../qualityprofile/ws/SearchAction.java | 27 +++----- .../qualityprofile/ws/search-example.json | 14 ++-- .../server/qualityprofile/QProfileTest.java | 2 +- .../qualityprofile/ws/SearchActionTest.java | 67 ++++++++++++------- .../main/protobuf/ws-qualityprofiles.proto | 1 + 6 files changed, 77 insertions(+), 48 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfile.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfile.java index a011ef0b1a5..b66740fe52f 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfile.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfile.java @@ -34,6 +34,7 @@ public class QProfile { private String parent; private boolean isDefault; private String rulesUpdatedAt; + private Long lastUsed; /** * @deprecated in 4.4 @@ -111,6 +112,16 @@ public class QProfile { return this; } + @CheckForNull + public Long getLastUsed() { + return lastUsed; + } + + public QProfile setLastUsed(@Nullable Long lastUsed) { + this.lastUsed = lastUsed; + return this; + } + public static QProfile from(QualityProfileDto dto) { return new QProfile() .setId(dto.getId()) @@ -119,7 +130,8 @@ public class QProfile { .setLanguage(dto.getLanguage()) .setParent(dto.getParentKee()) .setDefault(dto.isDefault()) - .setRulesUpdatedAt(dto.getRulesUpdatedAt()); + .setRulesUpdatedAt(dto.getRulesUpdatedAt()) + .setLastUsed(dto.getLastUsed()); } @Override diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SearchAction.java index a77ac9a13af..0a74e250924 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SearchAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SearchAction.java @@ -19,10 +19,9 @@ */ package org.sonar.server.qualityprofile.ws; -import com.google.common.base.Function; import java.util.List; import java.util.Map; -import javax.annotation.Nonnull; +import java.util.stream.Collectors; import org.sonar.api.resources.Languages; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; @@ -30,13 +29,13 @@ import org.sonar.api.server.ws.WebService; import org.sonar.api.server.ws.WebService.NewAction; import org.sonar.server.component.ws.LanguageParamUtils; import org.sonar.server.qualityprofile.QProfile; -import org.sonarqube.ws.QualityProfiles; import org.sonarqube.ws.QualityProfiles.SearchWsResponse; import org.sonarqube.ws.QualityProfiles.SearchWsResponse.QualityProfile; import org.sonarqube.ws.client.qualityprofile.SearchWsRequest; -import static com.google.common.collect.Maps.uniqueIndex; import static java.lang.String.format; +import static java.util.function.Function.identity; +import static org.sonar.api.utils.DateUtils.formatDateTime; import static org.sonar.server.ws.WsUtils.writeProtobuf; public class SearchAction implements QProfileWsAction { @@ -108,13 +107,12 @@ public class SearchAction implements QProfileWsAction { private SearchWsResponse buildResponse(SearchData data) { List profiles = data.getProfiles(); - Map profilesByKey = uniqueIndex(profiles, QProfileToKey.INSTANCE); + Map profilesByKey = profiles.stream().collect(Collectors.toMap(QProfile::key, identity())); - QualityProfiles.SearchWsResponse.Builder response = QualityProfiles.SearchWsResponse.newBuilder(); - QualityProfile.Builder profileBuilder = QualityProfile.newBuilder(); + SearchWsResponse.Builder response = SearchWsResponse.newBuilder(); for (QProfile profile : profiles) { - profileBuilder.clear(); + QualityProfile.Builder profileBuilder = response.addProfilesBuilder(); String profileKey = profile.key(); profileBuilder.setKey(profileKey); @@ -124,6 +122,9 @@ public class SearchAction implements QProfileWsAction { if (profile.getRulesUpdatedAt() != null) { profileBuilder.setRulesUpdatedAt(profile.getRulesUpdatedAt()); } + if (profile.getLastUsed() != null) { + profileBuilder.setLastUsed(formatDateTime(profile.getLastUsed())); + } profileBuilder.setActiveRuleCount(data.getActiveRuleCount(profileKey)); profileBuilder.setActiveDeprecatedRuleCount(data.getActiveDeprecatedRuleCount(profileKey)); if (!profile.isDefault()) { @@ -134,7 +135,6 @@ public class SearchAction implements QProfileWsAction { writeParentFields(profileBuilder, profile, profilesByKey); profileBuilder.setIsInherited(profile.isInherited()); profileBuilder.setIsDefault(profile.isDefault()); - response.addProfiles(profileBuilder); } return response.build(); @@ -165,13 +165,4 @@ public class SearchAction implements QProfileWsAction { profileBuilder.setParentName(parent.name()); } } - - private enum QProfileToKey implements Function { - INSTANCE; - - @Override - public String apply(@Nonnull QProfile input) { - return input.key(); - } - } } diff --git a/server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/search-example.json b/server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/search-example.json index 2570046ee76..e87df333946 100644 --- a/server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/search-example.json +++ b/server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/search-example.json @@ -8,7 +8,9 @@ "isInherited": false, "activeRuleCount": 37, "activeDeprecatedRuleCount": 0, - "isDefault": true + "isDefault": true, + "ruleUpdatedAt": "2016-12-22T19:10:03+0100", + "lastUsed": "2016-12-01T19:10:03+0100" }, { "key": "my-bu-profile-java-34567", @@ -21,7 +23,9 @@ "activeRuleCount": 72, "activeDeprecatedRuleCount": 5, "isDefault": false, - "projectCount": 13 + "projectCount": 13, + "ruleUpdatedAt": "2016-12-20T19:10:03+0100", + "lastUsed": "2016-12-21T16:10:03+0100" }, { "key": "my-company-profile-java-23456", @@ -31,7 +35,8 @@ "isInherited": false, "isDefault": true, "activeRuleCount": 42, - "activeDeprecatedRuleCount": 3 + "activeDeprecatedRuleCount": 3, + "ruleUpdatedAt": "2016-12-22T19:10:03+0100" }, { "key": "sonar-way-python-01234", @@ -41,7 +46,8 @@ "isInherited": false, "activeRuleCount": 125, "activeDeprecatedRuleCount": 0, - "isDefault": true + "isDefault": true, + "ruleUpdatedAt": "2014-12-22T19:10:03+0100" } ] } diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileTest.java index 6e0de55177c..fce69e72f20 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileTest.java @@ -38,7 +38,7 @@ public class QProfileTest { @Test public void to_string() { assertThat(new QProfile().setId(1).setName("Default").setLanguage("java").setParent("Parent").toString()) - .contains("[id=1,key=,name=Default,language=java,parent=Parent,isDefault=false,rulesUpdatedAt=]"); + .contains("[id=1,key=,name=Default,language=java,parent=Parent,isDefault=false,rulesUpdatedAt=,lastUsed=]"); } @Test diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SearchActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SearchActionTest.java index e541884328f..dcf5081e29a 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SearchActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SearchActionTest.java @@ -20,6 +20,7 @@ package org.sonar.server.qualityprofile.ws; import com.google.common.collect.ImmutableMap; +import java.io.IOException; import java.util.Date; import org.junit.Before; import org.junit.Rule; @@ -27,11 +28,13 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import org.sonar.api.resources.Language; import org.sonar.api.resources.Languages; +import org.sonar.api.utils.DateUtils; import org.sonar.api.utils.System2; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDao; +import org.sonar.db.component.ComponentDbTester; import org.sonar.db.component.ComponentDto; import org.sonar.db.qualityprofile.QualityProfileDao; import org.sonar.db.qualityprofile.QualityProfileDbTester; @@ -41,12 +44,18 @@ import org.sonar.server.language.LanguageTesting; import org.sonar.server.qualityprofile.QProfileFactory; import org.sonar.server.qualityprofile.QProfileLookup; import org.sonar.server.qualityprofile.index.ActiveRuleIndex; +import org.sonar.server.ws.TestRequest; import org.sonar.server.ws.WsActionTester; +import org.sonarqube.ws.MediaTypes; +import org.sonarqube.ws.QualityProfiles.SearchWsResponse; +import static com.google.common.base.Throwables.propagate; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import static org.sonar.api.utils.DateUtils.parseDateTime; import static org.sonar.db.component.ComponentTesting.newProjectDto; +import static org.sonar.db.qualityprofile.QualityProfileTesting.newQualityProfileDto; import static org.sonar.server.qualityprofile.ws.SearchAction.PARAM_DEFAULTS; import static org.sonar.server.qualityprofile.ws.SearchAction.PARAM_PROFILE_NAME; import static org.sonar.server.qualityprofile.ws.SearchAction.PARAM_PROJECT_KEY; @@ -54,29 +63,25 @@ import static org.sonar.test.JsonAssert.assertJson; public class SearchActionTest { - @Rule - public DbTester db = DbTester.create(System2.INSTANCE); - @Rule public ExpectedException expectedException = ExpectedException.none(); + @Rule + public DbTester db = DbTester.create(System2.INSTANCE); + QualityProfileDbTester qualityProfileDb = new QualityProfileDbTester(db); + ComponentDbTester componentDb = new ComponentDbTester(db); + DbClient dbClient = db.getDbClient(); + DbSession dbSession = db.getSession(); + QualityProfileDao qualityProfileDao = dbClient.qualityProfileDao(); private ActiveRuleIndex activeRuleIndex = mock(ActiveRuleIndex.class); - final DbClient dbClient = db.getDbClient(); - final DbSession dbSession = db.getSession(); - - private QualityProfileDao qualityProfileDao = dbClient.qualityProfileDao(); - private Language xoo1; private Language xoo2; - private WsActionTester ws; - private QualityProfileDbTester qualityProfileDb; + private WsActionTester ws; @Before public void setUp() { - qualityProfileDb = new QualityProfileDbTester(db); - xoo1 = LanguageTesting.newLanguage("xoo1"); xoo2 = LanguageTesting.newLanguage("xoo2"); @@ -110,18 +115,31 @@ public class SearchActionTest { newProjectDto("project-uuid2")); qualityProfileDao.insertProjectProfileAssociation("project-uuid1", "sonar-way-xoo2-23456", dbSession); qualityProfileDao.insertProjectProfileAssociation("project-uuid2", "sonar-way-xoo2-23456", dbSession); - commit(); + db.commit(); String result = ws.newRequest().execute().getInput(); assertJson(result).isSimilarTo(getClass().getResource("SearchActionTest/search.json")); } + @Test + public void search_map_dates() { + long time = DateUtils.parseDateTime("2016-12-22T19:10:03+0100").getTime(); + qualityProfileDb.insertQualityProfiles(newQualityProfileDto() + .setLanguage(xoo1.getKey()) + .setRulesUpdatedAt("2016-12-21T19:10:03+0100") + .setLastUsed(time)); + + SearchWsResponse result = call(ws.newRequest()); + + assertThat(result.getProfilesCount()).isEqualTo(1); + assertThat(result.getProfiles(0).getRulesUpdatedAt()).isEqualTo("2016-12-21T19:10:03+0100"); + assertThat(parseDateTime(result.getProfiles(0).getLastUsed()).getTime()).isEqualTo(time); + } + @Test public void search_for_language() throws Exception { - qualityProfileDao.insert(dbSession, - QualityProfileDto.createFor("sonar-way-xoo1-12345").setLanguage(xoo1.getKey()).setName("Sonar way")); - commit(); + qualityProfileDb.insertQualityProfiles(QualityProfileDto.createFor("sonar-way-xoo1-12345").setLanguage(xoo1.getKey()).setName("Sonar way")); String result = ws.newRequest().setParam("language", xoo1.getKey()).execute().getInput(); @@ -145,7 +163,6 @@ public class SearchActionTest { ComponentDto project = newProjectDto("project-uuid"); qualityProfileDb.insertQualityProfiles(qualityProfileOnXoo1, qualityProfileOnXoo2, anotherQualityProfileOnXoo1); qualityProfileDb.insertProjectWithQualityProfileAssociations(project, qualityProfileOnXoo1, qualityProfileOnXoo2); - commit(); String result = ws.newRequest() .setParam(PARAM_PROJECT_KEY, project.key()) @@ -171,7 +188,6 @@ public class SearchActionTest { .setName("Another way") .setDefault(true); qualityProfileDb.insertQualityProfiles(qualityProfileOnXoo1, qualityProfileOnXoo2, anotherQualityProfileOnXoo1); - commit(); String result = ws.newRequest() .setParam(PARAM_DEFAULTS, Boolean.TRUE.toString()) @@ -197,10 +213,8 @@ public class SearchActionTest { .setLanguage(xoo1.getKey()) .setRulesUpdatedAtAsDate(new Date()) .setName("Another way"); - ComponentDto project = newProjectDto("project-uuid"); qualityProfileDb.insertQualityProfiles(qualityProfileOnXoo1, qualityProfileOnXoo2, anotherQualityProfileOnXoo1); - dbClient.componentDao().insert(dbSession, project); - commit(); + ComponentDto project = componentDb.insertComponent(newProjectDto("project-uuid")); String result = ws.newRequest() .setParam(PARAM_PROJECT_KEY, project.key()) @@ -210,10 +224,15 @@ public class SearchActionTest { assertThat(result) .contains("sonar-way-xoo1-12345", "sonar-way-xoo2-12345") .doesNotContain("sonar-way-xoo1-45678"); - } - private void commit() { - dbSession.commit(); + private SearchWsResponse call(TestRequest request) { + try { + return SearchWsResponse.parseFrom(request + .setMediaType(MediaTypes.PROTOBUF) + .execute().getInputStream()); + } catch (IOException e) { + throw propagate(e); + } } } diff --git a/sonar-ws/src/main/protobuf/ws-qualityprofiles.proto b/sonar-ws/src/main/protobuf/ws-qualityprofiles.proto index 9b4e871cb51..534b46c64a6 100644 --- a/sonar-ws/src/main/protobuf/ws-qualityprofiles.proto +++ b/sonar-ws/src/main/protobuf/ws-qualityprofiles.proto @@ -41,5 +41,6 @@ message SearchWsResponse { optional int64 activeDeprecatedRuleCount = 12; optional int64 projectCount = 10; optional string rulesUpdatedAt = 11; + optional string lastUsed = 13; } } -- 2.39.5