]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6306 WS to show ancestors and children of a quality profile
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Wed, 8 Apr 2015 08:46:05 +0000 (10:46 +0200)
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Fri, 10 Apr 2015 09:19:25 +0000 (11:19 +0200)
server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileLookup.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceAction.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionTest/inheritance-buWide.json [new file with mode: 0644]

index eb874b84664c358ab68c726fe94b49833c76d5d8..23a95ec3bd2f82e2c13d211d93796ddeffc50f43 100644 (file)
@@ -389,6 +389,7 @@ class ServerComponents {
     pico.addSingleton(QProfileRestoreAction.class);
     pico.addSingleton(QProfileCreateAction.class);
     pico.addSingleton(QProfileImportersAction.class);
+    pico.addSingleton(QProfileInheritanceAction.class);
     pico.addSingleton(QProfilesWs.class);
     pico.addSingleton(ProfilesWs.class);
     pico.addSingleton(RuleActivationActions.class);
index 4830b4e3d57894aa16c44366c7c2cd98d6b6cb3f..bd6c88cda30e210adb030b5bbb70e68be73d8eb0 100644 (file)
@@ -116,6 +116,12 @@ public class QProfileLookup implements ServerComponent {
     return toQProfiles(db.qualityProfileDao().findChildren(session, profile.key()));
   }
 
+  public List<QProfile> ancestors(QualityProfileDto profile, DbSession session) {
+    List<QProfile> ancestors = newArrayList();
+    incrementAncestors(QProfile.from(profile), ancestors, session);
+    return ancestors;
+  }
+
   public List<QProfile> ancestors(QProfile profile) {
     List<QProfile> ancestors = newArrayList();
     DbSession session = db.openSession(false);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceAction.java
new file mode 100644 (file)
index 0000000..1312157
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import org.sonar.api.resources.Languages;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService.NewAction;
+import org.sonar.api.server.ws.WebService.NewController;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.qualityprofile.QProfile;
+import org.sonar.server.qualityprofile.QProfileFactory;
+import org.sonar.server.qualityprofile.QProfileLookup;
+
+import java.util.List;
+
+public class QProfileInheritanceAction implements BaseQProfileWsAction {
+
+  private final DbClient dbClient;
+
+  private final QProfileLookup profileLookup;
+
+  private final QProfileFactory profileFactory;
+
+  private final Languages languages;
+
+  public QProfileInheritanceAction(DbClient dbClient, QProfileLookup profileLookup, QProfileFactory profileFactory, Languages languages) {
+    this.dbClient = dbClient;
+    this.profileLookup = profileLookup;
+    this.profileFactory = profileFactory;
+    this.languages = languages;
+  }
+
+  @Override
+  public void define(NewController context) {
+    NewAction inheritance = context.createAction("inheritance")
+      .setSince("5.2")
+      .setDescription("Show a quality profile's ancestors and children.")
+      .setHandler(this)
+      .setResponseExample(getClass().getResource("example-inheritance.json"));
+
+    QProfileIdentificationParamUtils.defineProfileParams(inheritance, languages);
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    DbSession session = dbClient.openSession(false);
+    try {
+      String profileKey = QProfileIdentificationParamUtils.getProfileKeyFromParameters(request, profileFactory, session);
+      QualityProfileDto profile = dbClient.qualityProfileDao().getByKey(session, profileKey);
+      if (profile == null) {
+        throw new NotFoundException(String.format("Could not find a quality profile with key %s", profileKey));
+      }
+
+      List<QProfile> ancestors = profileLookup.ancestors(profile, session);
+      List<QualityProfileDto> children = dbClient.qualityProfileDao().findChildren(session, profileKey);
+
+      writeResponse(response.newJsonWriter(), ancestors, children);
+    } finally {
+      session.close();
+    }
+  }
+
+  private void writeResponse(JsonWriter json, List<QProfile> ancestors, List<QualityProfileDto> children) {
+    json.beginObject();
+    writeAncestors(json, ancestors);
+    writeChildren(json, children);
+    json.endObject().close();
+  }
+
+  private void writeAncestors(JsonWriter json, List<QProfile> ancestors) {
+    json.name("ancestors").beginArray();
+    for (QProfile ancestor : ancestors) {
+      json.beginObject()
+        .prop("key", ancestor.key())
+        .prop("name", ancestor.name())
+        .prop("parent", ancestor.parent())
+        .endObject();
+    }
+    json.endArray();
+  }
+
+  private void writeChildren(JsonWriter json, List<QualityProfileDto> children) {
+    json.name("children").beginArray();
+    for (QualityProfileDto child : children) {
+      json.beginObject()
+        .prop("key", child.getKey())
+        .prop("name", child.getName())
+        .endObject();
+    }
+    json.endArray();
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionTest.java
new file mode 100644 (file)
index 0000000..4231d26
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile.ws;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.api.utils.System2;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.core.qualityprofile.db.QualityProfileDao;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.language.LanguageTesting;
+import org.sonar.server.qualityprofile.QProfileFactory;
+import org.sonar.server.qualityprofile.QProfileLookup;
+import org.sonar.server.qualityprofile.QProfileName;
+import org.sonar.server.qualityprofile.QProfileTesting;
+import org.sonar.server.ws.WsTester;
+import org.sonar.test.DbTests;
+
+import static org.mockito.Mockito.mock;
+
+@Category(DbTests.class)
+public class QProfileInheritanceActionTest {
+
+  @ClassRule
+  public static final DbTester dbTester = new DbTester();
+
+  private WsTester wsTester;
+
+  private DbClient dbClient;
+
+  private DbSession session;
+
+  @Before
+  public void setUp() throws Exception {
+    dbTester.truncateTables();
+    dbClient = new DbClient(dbTester.database(), dbTester.myBatis(),
+      new QualityProfileDao(dbTester.myBatis(), mock(System2.class)));
+    session = dbClient.openSession(false);
+
+    wsTester = new WsTester(new QProfilesWs(
+      mock(RuleActivationActions.class),
+      mock(BulkRuleActivationActions.class),
+      mock(ProjectAssociationActions.class),
+      new QProfileInheritanceAction(dbClient, new QProfileLookup(dbClient), new QProfileFactory(dbClient), LanguageTesting.newLanguages("xoo"))));
+  }
+
+  @After
+  public void tearDown() {
+    session.close();
+  }
+
+  @Test
+  public void inheritance_nominal() throws Exception {
+    /*
+     * groupWide <- companyWide <- buWide <- (forProject1, forProject2)
+     */
+    QualityProfileDto groupWide = QProfileTesting.newDto(QProfileName.createFor("xoo", "My Group Profile"), "xoo-my-group-profile-01234");
+    QualityProfileDto companyWide = QProfileTesting.newDto(QProfileName.createFor("xoo", "My Company Profile"), "xoo-my-company-profile-12345").setParentKee(groupWide.getKee());
+    QualityProfileDto buWide = QProfileTesting.newDto(QProfileName.createFor("xoo", "My BU Profile"), "xoo-my-by-profile-23456").setParentKee(companyWide.getKee());
+    QualityProfileDto forProject1 = QProfileTesting.newDto(QProfileName.createFor("xoo", "For Project One"), "xoo-for-project-one-34567").setParentKee(buWide.getKee());
+    QualityProfileDto forProject2 = QProfileTesting.newDto(QProfileName.createFor("xoo", "For Project Two"), "xoo-for-project-two-45678").setParentKee(buWide.getKee());
+
+    dbClient.qualityProfileDao().insert(session, groupWide, companyWide, buWide, forProject1, forProject2);
+    session.commit();
+
+    wsTester.newGetRequest("api/qualityprofiles", "inheritance").setParam("profileKey", buWide.getKee()).execute().assertJson(getClass(), "inheritance-buWide.json");
+  }
+
+  @Test(expected = NotFoundException.class)
+  public void fail_if_not_found() throws Exception {
+    wsTester.newGetRequest("api/qualityprofiles", "inheritance").setParam("profileKey", "polop").execute();
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionTest/inheritance-buWide.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionTest/inheritance-buWide.json
new file mode 100644 (file)
index 0000000..154c25e
--- /dev/null
@@ -0,0 +1,10 @@
+{
+  "ancestors": [
+    {"key": "xoo-my-company-profile-12345", "name": "My Company Profile", "parent": "xoo-my-group-profile-01234"},
+    {"key": "xoo-my-group-profile-01234", "name": "My Group Profile"}
+  ],
+  "children": [
+    {"key": "xoo-for-project-one-34567", "name": "For Project One"},
+    {"key": "xoo-for-project-two-45678", "name": "For Project Two"}
+  ]
+}
\ No newline at end of file