]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7789 WS api/qualityprofiles/search return lastUsed field
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Mon, 27 Jun 2016 09:33:35 +0000 (11:33 +0200)
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Mon, 27 Jun 2016 09:43:32 +0000 (11:43 +0200)
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfile.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SearchAction.java
server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/search-example.json
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SearchActionTest.java
sonar-ws/src/main/protobuf/ws-qualityprofiles.proto

index a011ef0b1a554898608df4bc713ea071f3e7b67f..b66740fe52f8eadbca7f66a0878f8cfb1800b997 100644 (file)
@@ -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
index a77ac9a13afc0bcae242f6e920b0b9f6c7e04c76..0a74e2509241dd953c08a38fc95fcf31ff3d17ad 100644 (file)
  */
 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<QProfile> profiles = data.getProfiles();
-    Map<String, QProfile> profilesByKey = uniqueIndex(profiles, QProfileToKey.INSTANCE);
+    Map<String, QProfile> 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<QProfile, String> {
-    INSTANCE;
-
-    @Override
-    public String apply(@Nonnull QProfile input) {
-      return input.key();
-    }
-  }
 }
index 2570046ee7677a51636228d31a5f76bb4795a590..e87df3339468f6f5d5db684da94bd865bd698613 100644 (file)
@@ -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"
     }
   ]
 }
index 6e0de55177cd870d0e87dc1c9774dd41a464f302..fce69e72f2056f649b424fce2c82319afe6dbad1 100644 (file)
@@ -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=<null>,name=Default,language=java,parent=Parent,isDefault=false,rulesUpdatedAt=<null>]");
+      .contains("[id=1,key=<null>,name=Default,language=java,parent=Parent,isDefault=false,rulesUpdatedAt=<null>,lastUsed=<null>]");
   }
 
   @Test
index e541884328f8576f617c9fbda3a845045087d5d5..dcf5081e29a915285e21403c1f931edd6218f573 100644 (file)
@@ -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);
+    }
   }
 }
index 9b4e871cb5195c6fd00b2a830ebccc76243d7b42..534b46c64a6a6eb3585ac7ed6dae77a65ec3ec54 100644 (file)
@@ -41,5 +41,6 @@ message SearchWsResponse {
     optional int64 activeDeprecatedRuleCount = 12;
     optional int64 projectCount = 10;
     optional string rulesUpdatedAt = 11;
+    optional string lastUsed = 13;
   }
 }