]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7961 Refactoring of add_project and remove_project actions
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 12 Sep 2016 07:46:43 +0000 (09:46 +0200)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Tue, 13 Sep 2016 09:42:18 +0000 (11:42 +0200)
33 files changed:
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/AddProjectAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ProjectAssociationActions.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ProjectAssociationFinder.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ProjectAssociationParameters.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfilesWs.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfilesWsModule.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/RemoveProjectAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SearchAction.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/AddProjectActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/BackupActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangelogActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CopyActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/DeleteActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ExportActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ExportersActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ImportersActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ProjectsActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsModuleTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RenameActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RestoreActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RestoreBuiltInActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SearchActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SetDefaultActionTest.java
sonar-db/src/test/java/org/sonar/db/qualityprofile/QualityProfileDbTester.java
sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/AddProjectRequest.java [new file with mode: 0644]
sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/QualityProfileWsParameters.java [new file with mode: 0644]
sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/QualityProfilesService.java
sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/RemoveProjectRequest.java [new file with mode: 0644]
sonar-ws/src/test/java/org/sonarqube/ws/client/qualityprofile/AddProjectRequestTest.java [new file with mode: 0644]
sonar-ws/src/test/java/org/sonarqube/ws/client/qualityprofile/QualityProfilesServiceTest.java [new file with mode: 0644]
sonar-ws/src/test/java/org/sonarqube/ws/client/qualityprofile/RemoveProjectRequestTest.java [new file with mode: 0644]

index 9e70631f3423e82f81c447ba3e906353a8514e02..003b90789c4b4bcfe64791f837fd7783fa37ce1f 100644 (file)
@@ -214,28 +214,10 @@ import org.sonar.server.qualityprofile.QProfiles;
 import org.sonar.server.qualityprofile.RuleActivator;
 import org.sonar.server.qualityprofile.RuleActivatorContextFactory;
 import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
-import org.sonar.server.qualityprofile.ws.BackupAction;
-import org.sonar.server.qualityprofile.ws.BulkRuleActivationActions;
-import org.sonar.server.qualityprofile.ws.ChangeParentAction;
-import org.sonar.server.qualityprofile.ws.ChangelogAction;
-import org.sonar.server.qualityprofile.ws.CompareAction;
-import org.sonar.server.qualityprofile.ws.CopyAction;
-import org.sonar.server.qualityprofile.ws.CreateAction;
-import org.sonar.server.qualityprofile.ws.ExportAction;
-import org.sonar.server.qualityprofile.ws.ExportersAction;
-import org.sonar.server.qualityprofile.ws.ImportersAction;
-import org.sonar.server.qualityprofile.ws.InheritanceAction;
 import org.sonar.server.qualityprofile.ws.OldRestoreAction;
 import org.sonar.server.qualityprofile.ws.ProfilesWs;
-import org.sonar.server.qualityprofile.ws.ProjectAssociationActions;
-import org.sonar.server.qualityprofile.ws.ProjectsAction;
-import org.sonar.server.qualityprofile.ws.QProfilesWs;
-import org.sonar.server.qualityprofile.ws.RenameAction;
-import org.sonar.server.qualityprofile.ws.RestoreAction;
-import org.sonar.server.qualityprofile.ws.RestoreBuiltInAction;
-import org.sonar.server.qualityprofile.ws.RuleActivationActions;
+import org.sonar.server.qualityprofile.ws.QProfilesWsModule;
 import org.sonar.server.qualityprofile.ws.SearchDataLoader;
-import org.sonar.server.qualityprofile.ws.SetDefaultAction;
 import org.sonar.server.rule.CommonRuleDefinitionsImpl;
 import org.sonar.server.rule.DefaultRuleFinder;
 import org.sonar.server.rule.DeprecatedRulesDefinitionLoader;
@@ -381,30 +363,9 @@ public class PlatformLevel4 extends PlatformLevel {
       QProfileProjectLookup.class,
       QProfileComparison.class,
       BuiltInProfiles.class,
-      RestoreBuiltInAction.class,
-      org.sonar.server.qualityprofile.ws.SearchAction.class,
       SearchDataLoader.class,
-      SetDefaultAction.class,
-      ProjectsAction.class,
-      org.sonar.server.qualityprofile.ws.DeleteAction.class,
-      RenameAction.class,
-      CopyAction.class,
-      BackupAction.class,
-      RestoreAction.class,
-      CreateAction.class,
-      ImportersAction.class,
-      InheritanceAction.class,
-      ChangeParentAction.class,
-      ChangelogAction.class,
-      CompareAction.class,
-      ExportAction.class,
-      ExportersAction.class,
-      QProfilesWs.class,
       ProfilesWs.class,
       OldRestoreAction.class,
-      RuleActivationActions.class,
-      BulkRuleActivationActions.class,
-      ProjectAssociationActions.class,
       RuleActivator.class,
       QProfileLoader.class,
       QProfileExporters.class,
@@ -415,6 +376,7 @@ public class PlatformLevel4 extends PlatformLevel {
       QProfileBackuper.class,
       QProfileReset.class,
       RubyQProfileActivityService.class,
+      QProfilesWsModule.class,
 
       // rule
       RuleIndexDefinition.class,
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/AddProjectAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/AddProjectAction.java
new file mode 100644 (file)
index 0000000..acd8758
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.server.ws.WebService.NewAction;
+import org.sonar.server.qualityprofile.QProfileProjectOperations;
+import org.sonar.server.user.UserSession;
+import org.sonarqube.ws.client.qualityprofile.AddProjectRequest;
+
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_ADD_PROJECT;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROFILE_KEY;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROFILE_NAME;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROJECT_KEY;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROJECT_UUID;
+
+public class AddProjectAction implements QProfileWsAction {
+
+  private final ProjectAssociationParameters projectAssociationParameters;
+  private final ProjectAssociationFinder projectAssociationFinder;
+  private final QProfileProjectOperations profileProjectOperations;
+  private final UserSession userSession;
+
+  public AddProjectAction(ProjectAssociationParameters projectAssociationParameters, QProfileProjectOperations profileProjectOperations,
+    ProjectAssociationFinder projectAssociationFinder, UserSession userSession) {
+    this.projectAssociationParameters = projectAssociationParameters;
+    this.profileProjectOperations = profileProjectOperations;
+    this.projectAssociationFinder = projectAssociationFinder;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    NewAction action = controller.createAction(ACTION_ADD_PROJECT)
+      .setSince("5.2")
+      .setDescription("Associate a project with a quality profile.")
+      .setHandler(this);
+    projectAssociationParameters.addParameters(action);
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    AddProjectRequest addProjectRequest = toWsRequest(request);
+    String profileKey = projectAssociationFinder.getProfileKey(addProjectRequest.getLanguage(), addProjectRequest.getProfileName(), addProjectRequest.getProfileKey());
+    String projectUuid = projectAssociationFinder.getProjectUuid(addProjectRequest.getProjectKey(), addProjectRequest.getProjectUuid());
+    profileProjectOperations.addProject(profileKey, projectUuid, userSession);
+    response.noContent();
+  }
+
+  private static AddProjectRequest toWsRequest(Request request) {
+    return AddProjectRequest.builder()
+      .setLanguage(request.param(PARAM_LANGUAGE))
+      .setProfileName(request.param(PARAM_PROFILE_NAME))
+      .setProfileKey(request.param(PARAM_PROFILE_KEY))
+      .setProjectKey(request.param(PARAM_PROJECT_KEY))
+      .setProjectUuid(request.param(PARAM_PROJECT_UUID))
+      .build();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ProjectAssociationActions.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ProjectAssociationActions.java
deleted file mode 100644 (file)
index 896907e..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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 com.google.common.base.Preconditions;
-import org.sonar.api.server.ServerSide;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.RequestHandler;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.server.ws.WebService.NewAction;
-import org.sonar.server.component.ComponentService;
-import org.sonar.server.component.ws.LanguageParamUtils;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.qualityprofile.QProfile;
-import org.sonar.server.qualityprofile.QProfileLookup;
-import org.sonar.server.qualityprofile.QProfileProjectOperations;
-import org.sonar.server.user.UserSession;
-
-import static org.apache.commons.lang.StringUtils.isEmpty;
-import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
-
-@ServerSide
-public class ProjectAssociationActions {
-
-  private static final String PARAM_LANGUAGE = "language";
-  private static final String PARAM_PROFILE_NAME = "profileName";
-  private static final String PARAM_PROFILE_KEY = "profileKey";
-  private static final String PARAM_PROJECT_KEY = "projectKey";
-  private static final String PARAM_PROJECT_UUID = "projectUuid";
-
-  private final QProfileProjectOperations profileProjectOperations;
-  private final QProfileLookup profileLookup;
-  private final ComponentService componentService;
-  private final Languages languages;
-  private final UserSession userSession;
-
-  public ProjectAssociationActions(QProfileProjectOperations profileProjectOperations, QProfileLookup profileLookup,
-    ComponentService componentService, Languages languages, UserSession userSession) {
-    this.profileProjectOperations = profileProjectOperations;
-    this.profileLookup = profileLookup;
-    this.componentService = componentService;
-    this.languages = languages;
-    this.userSession = userSession;
-  }
-
-  void define(WebService.NewController controller) {
-    NewAction addProject = controller.createAction("add_project")
-      .setSince("5.2")
-      .setDescription("Associate a project with a quality profile.")
-      .setHandler(new AssociationHandler(profileLookup, componentService, userSession) {
-        @Override
-        protected void changeAssociation(String profileKey, String projectUuid, UserSession userSession) {
-          profileProjectOperations.addProject(profileKey, projectUuid, userSession);
-        }
-      });
-    setCommonAttributes(addProject);
-
-    NewAction removeProject = controller.createAction("remove_project")
-      .setSince("5.2")
-      .setDescription("Remove a project's association with a quality profile.")
-      .setHandler(new AssociationHandler(profileLookup, componentService, userSession) {
-        @Override
-        protected void changeAssociation(String profileKey, String projectUuid, UserSession userSession) {
-          profileProjectOperations.removeProject(profileKey, projectUuid, userSession);
-        }
-      });
-    setCommonAttributes(removeProject);
-  }
-
-  private void setCommonAttributes(NewAction action) {
-    action.setPost(true);
-    action.createParam(PARAM_PROJECT_UUID)
-      .setDescription("A project UUID. Either this parameter, or projectKey must be set.")
-      .setExampleValue("69e57151-be0d-4157-adff-c06741d88879");
-    action.createParam(PARAM_PROJECT_KEY)
-      .setDescription("A project key. Either this parameter, or projectUuid must be set.")
-      .setExampleValue(KEY_PROJECT_EXAMPLE_001);
-    action.createParam(PARAM_PROFILE_KEY)
-      .setDescription("A quality profile key. Either this parameter, or a combination of profileName + language must be set.")
-      .setExampleValue("sonar-way-java-12345");
-    action.createParam(PARAM_PROFILE_NAME)
-      .setDescription("A quality profile name. If this parameter is set, profileKey must not be set and language must be set to disambiguate.")
-      .setExampleValue("Soanr way");
-    action.createParam(PARAM_LANGUAGE)
-      .setDescription("A quality profile language. If this parameter is set, profileKey must not be set and profileName must be set to disambiguate.")
-      .setPossibleValues(LanguageParamUtils.getLanguageKeys(languages))
-      .setExampleValue("js");
-  }
-
-  private abstract static class AssociationHandler implements RequestHandler {
-
-    private final QProfileLookup profileLookup;
-    private final ComponentService componentService;
-    private final UserSession userSession;
-
-    public AssociationHandler(QProfileLookup profileLookup, ComponentService componentService, UserSession userSession) {
-      this.profileLookup = profileLookup;
-      this.componentService = componentService;
-      this.userSession = userSession;
-    }
-
-    protected abstract void changeAssociation(String profileKey, String projectUuid, UserSession userSession);
-
-    @Override
-    public void handle(Request request, Response response) throws Exception {
-      String language = request.param(PARAM_LANGUAGE);
-      String profileName = request.param(PARAM_PROFILE_NAME);
-      String profileKey = request.param(PARAM_PROFILE_KEY);
-      String projectKey = request.param(PARAM_PROJECT_KEY);
-      String projectUuid = request.param(PARAM_PROJECT_UUID);
-
-      Preconditions.checkArgument(
-        (!isEmpty(language) && !isEmpty(profileName)) ^ !isEmpty(profileKey), "Either profileKey or profileName + language must be set");
-      Preconditions.checkArgument(!isEmpty(projectKey) ^ !isEmpty(projectUuid), "Either projectKey or projectUuid must be set");
-
-      if (profileKey == null) {
-        profileKey = getProfileKeyFromLanguageAndName(language, profileName);
-      }
-
-      if (projectUuid == null) {
-        projectUuid = componentService.getByKey(projectKey).uuid();
-      }
-
-      changeAssociation(profileKey, projectUuid, userSession);
-      response.noContent();
-    }
-
-    private String getProfileKeyFromLanguageAndName(String language, String profileName) {
-      QProfile profile = profileLookup.profile(profileName, language);
-      if (profile == null) {
-        throw new NotFoundException(String.format("Unable to find a profile for language '%s' with name '%s'", language, profileName));
-      }
-      return profile.key();
-    }
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ProjectAssociationFinder.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ProjectAssociationFinder.java
new file mode 100644 (file)
index 0000000..9c640e3
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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 javax.annotation.Nullable;
+import org.sonar.server.component.ComponentService;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.qualityprofile.QProfile;
+import org.sonar.server.qualityprofile.QProfileLookup;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static org.apache.commons.lang.StringUtils.isEmpty;
+
+public class ProjectAssociationFinder {
+
+  private static final String BAD_PROFILE_PARAMETERS_ERROR = "Either profileKey or profileName + language must be set";
+  private static final String BAD_PROJECT_PARAMETERS_ERROR = "Either projectKey or projectUuid must be set";
+
+  private final QProfileLookup profileLookup;
+  private final ComponentService componentService;
+
+  public ProjectAssociationFinder(QProfileLookup profileLookup, ComponentService componentService) {
+    this.profileLookup = profileLookup;
+    this.componentService = componentService;
+  }
+
+  public String getProfileKey(@Nullable String language, @Nullable String profileName, @Nullable String profileKey) {
+    checkArgument((!isEmpty(language) && !isEmpty(profileName)) ^ !isEmpty(profileKey), BAD_PROFILE_PARAMETERS_ERROR);
+    return profileKey == null ? getProfileKeyFromLanguageAndName(language, profileName) : profileKey;
+  }
+
+  public String getProjectUuid(@Nullable String projectKey, @Nullable String projectUuid) {
+    checkArgument(!isEmpty(projectKey) ^ !isEmpty(projectUuid), BAD_PROJECT_PARAMETERS_ERROR);
+    return projectUuid == null ? componentService.getByKey(projectKey).uuid() : projectUuid;
+  }
+
+  private String getProfileKeyFromLanguageAndName(String language, String profileName) {
+    QProfile profile = profileLookup.profile(profileName, language);
+    if (profile == null) {
+      throw new NotFoundException(String.format("Unable to find a profile for language '%s' with name '%s'", language, profileName));
+    }
+    return profile.key();
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ProjectAssociationParameters.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ProjectAssociationParameters.java
new file mode 100644 (file)
index 0000000..e78d91c
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.WebService;
+import org.sonar.server.component.ws.LanguageParamUtils;
+
+import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROFILE_KEY;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROFILE_NAME;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROJECT_KEY;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROJECT_UUID;
+
+public class ProjectAssociationParameters {
+
+  private final Languages languages;
+
+  public ProjectAssociationParameters(Languages languages) {
+    this.languages = languages;
+  }
+
+  void addParameters(WebService.NewAction action) {
+    action.setPost(true);
+    action.createParam(PARAM_PROJECT_UUID)
+      .setDescription("A project UUID. Either this parameter, or projectKey must be set.")
+      .setExampleValue("69e57151-be0d-4157-adff-c06741d88879");
+    action.createParam(PARAM_PROJECT_KEY)
+      .setDescription("A project key. Either this parameter, or projectUuid must be set.")
+      .setExampleValue(KEY_PROJECT_EXAMPLE_001);
+    action.createParam(PARAM_PROFILE_KEY)
+      .setDescription("A quality profile key. Either this parameter, or a combination of profileName + language must be set.")
+      .setExampleValue("sonar-way-java-12345");
+    action.createParam(PARAM_PROFILE_NAME)
+      .setDescription("A quality profile name. If this parameter is set, profileKey must not be set and language must be set to disambiguate.")
+      .setExampleValue("Soanr way");
+    action.createParam(PARAM_LANGUAGE)
+      .setDescription("A quality profile language. If this parameter is set, profileKey must not be set and profileName must be set to disambiguate.")
+      .setPossibleValues(LanguageParamUtils.getLanguageKeys(languages))
+      .setExampleValue("js");
+  }
+
+}
index a9b87c520e3481685fe42a54c76c2d4551af3225..dac4233bb33382e37a204f1ce4518aa0bbb7ded7 100644 (file)
@@ -21,22 +21,21 @@ package org.sonar.server.qualityprofile.ws;
 
 import org.sonar.api.server.ws.WebService;
 
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.CONTROLLER_QUALITY_PROFILES;
+
 public class QProfilesWs implements WebService {
 
-  public static final String API_ENDPOINT = "api/qualityprofiles";
+  public static final String API_ENDPOINT = CONTROLLER_QUALITY_PROFILES;
 
   private final RuleActivationActions ruleActivationActions;
   private final BulkRuleActivationActions bulkRuleActivationActions;
-  private final ProjectAssociationActions projectAssociationActions;
   private final QProfileWsAction[] actions;
 
   public QProfilesWs(RuleActivationActions ruleActivationActions,
-                     BulkRuleActivationActions bulkRuleActivationActions,
-                     ProjectAssociationActions projectAssociationActions,
-                     QProfileWsAction... actions) {
+    BulkRuleActivationActions bulkRuleActivationActions,
+    QProfileWsAction... actions) {
     this.ruleActivationActions = ruleActivationActions;
     this.bulkRuleActivationActions = bulkRuleActivationActions;
-    this.projectAssociationActions = projectAssociationActions;
     this.actions = actions;
   }
 
@@ -48,8 +47,7 @@ public class QProfilesWs implements WebService {
 
     ruleActivationActions.define(controller);
     bulkRuleActivationActions.define(controller);
-    projectAssociationActions.define(controller);
-    for(QProfileWsAction action: actions) {
+    for (QProfileWsAction action : actions) {
       action.define(controller);
     }
 
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfilesWsModule.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfilesWsModule.java
new file mode 100644 (file)
index 0000000..0c85730
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.core.platform.Module;
+
+public class QProfilesWsModule extends Module {
+  @Override
+  protected void configureModule() {
+    add(
+      AddProjectAction.class,
+      BackupAction.class,
+      BulkRuleActivationActions.class,
+      CompareAction.class,
+      CopyAction.class,
+      ChangelogAction.class,
+      ChangeParentAction.class,
+      CreateAction.class,
+      DeleteAction.class,
+      ExportAction.class,
+      ExportersAction.class,
+      ImportersAction.class,
+      InheritanceAction.class,
+      QProfilesWs.class,
+      ProjectAssociationFinder.class,
+      ProjectAssociationParameters.class,
+      ProjectsAction.class,
+      RenameAction.class,
+      RemoveProjectAction.class,
+      RestoreAction.class,
+      RestoreBuiltInAction.class,
+      RuleActivationActions.class,
+      SearchAction.class,
+      SetDefaultAction.class
+      );
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/RemoveProjectAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/RemoveProjectAction.java
new file mode 100644 (file)
index 0000000..95b4313
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.server.ws.WebService.NewAction;
+import org.sonar.server.qualityprofile.QProfileProjectOperations;
+import org.sonar.server.user.UserSession;
+import org.sonarqube.ws.client.qualityprofile.RemoveProjectRequest;
+
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_REMOVE_PROJECT;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROFILE_KEY;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROFILE_NAME;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROJECT_KEY;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROJECT_UUID;
+
+public class RemoveProjectAction implements QProfileWsAction {
+
+  private final ProjectAssociationParameters projectAssociationParameters;
+  private final ProjectAssociationFinder projectAssociationFinder;
+  private final QProfileProjectOperations profileProjectOperations;
+  private final UserSession userSession;
+
+  public RemoveProjectAction(ProjectAssociationParameters projectAssociationParameters, ProjectAssociationFinder projectAssociationFinder,
+    QProfileProjectOperations profileProjectOperations, UserSession userSession) {
+    this.projectAssociationParameters = projectAssociationParameters;
+    this.projectAssociationFinder = projectAssociationFinder;
+    this.profileProjectOperations = profileProjectOperations;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    NewAction action = controller.createAction(ACTION_REMOVE_PROJECT)
+      .setSince("5.2")
+      .setDescription("Remove a project's association with a quality profile.")
+      .setHandler(this);
+    projectAssociationParameters.addParameters(action);
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    RemoveProjectRequest removeProjectRequest = toWsRequest(request);
+    String profileKey = projectAssociationFinder.getProfileKey(removeProjectRequest.getLanguage(), removeProjectRequest.getProfileName(), removeProjectRequest.getProfileKey());
+    String projectUuid = projectAssociationFinder.getProjectUuid(removeProjectRequest.getProjectKey(), removeProjectRequest.getProjectUuid());
+    profileProjectOperations.removeProject(profileKey, projectUuid, userSession);
+    response.noContent();
+  }
+
+  private static RemoveProjectRequest toWsRequest(Request request) {
+    return RemoveProjectRequest.builder()
+      .setLanguage(request.param(PARAM_LANGUAGE))
+      .setProfileName(request.param(PARAM_PROFILE_NAME))
+      .setProfileKey(request.param(PARAM_PROFILE_KEY))
+      .setProjectKey(request.param(PARAM_PROJECT_KEY))
+      .setProjectUuid(request.param(PARAM_PROJECT_UUID))
+      .build();
+  }
+
+}
index 6e447e3bc6ac6c28dd0911b6f1b290cdcc1e35da..4ce55995985039c058f37e753c6045e4592db509 100644 (file)
@@ -38,14 +38,14 @@ import org.sonarqube.ws.client.qualityprofile.SearchWsRequest;
 import static com.google.common.collect.Maps.uniqueIndex;
 import static java.lang.String.format;
 import static org.sonar.server.ws.WsUtils.writeProtobuf;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_SEARCH;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_DEFAULTS;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROFILE_NAME;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROJECT_KEY;
 
 public class SearchAction implements QProfileWsAction {
 
-  static final String PARAM_LANGUAGE = "language";
-  static final String PARAM_PROJECT_KEY = "projectKey";
-  static final String PARAM_DEFAULTS = "defaults";
-  static final String PARAM_PROFILE_NAME = "profileName";
-
   private final SearchDataLoader dataLoader;
   private final Languages languages;
 
@@ -56,7 +56,7 @@ public class SearchAction implements QProfileWsAction {
 
   @Override
   public void define(WebService.NewController controller) {
-    NewAction action = controller.createAction("search")
+    NewAction action = controller.createAction(ACTION_SEARCH)
       .setSince("5.2")
       .setDescription("List quality profiles.")
       .setHandler(this)
@@ -95,10 +95,10 @@ public class SearchAction implements QProfileWsAction {
 
   private static SearchWsRequest toSearchWsRequest(Request request) {
     return new SearchWsRequest()
-        .setProjectKey(request.param(PARAM_PROJECT_KEY))
-        .setProfileName(request.param(PARAM_PROFILE_NAME))
-        .setDefaults(request.paramAsBoolean(PARAM_DEFAULTS))
-        .setLanguage(request.param(PARAM_LANGUAGE));
+      .setProjectKey(request.param(PARAM_PROJECT_KEY))
+      .setProfileName(request.param(PARAM_PROFILE_NAME))
+      .setDefaults(request.paramAsBoolean(PARAM_DEFAULTS))
+      .setLanguage(request.param(PARAM_LANGUAGE));
   }
 
   private SearchWsResponse buildResponse(SearchWsRequest request) {
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/AddProjectActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/AddProjectActionTest.java
new file mode 100644 (file)
index 0000000..2586109
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.resources.Languages;
+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.ComponentDbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ComponentTesting;
+import org.sonar.db.qualityprofile.QualityProfileDbTester;
+import org.sonar.db.qualityprofile.QualityProfileDto;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.component.ComponentService;
+import org.sonar.server.language.LanguageTesting;
+import org.sonar.server.qualityprofile.QProfileLookup;
+import org.sonar.server.qualityprofile.QProfileName;
+import org.sonar.server.qualityprofile.QProfileProjectOperations;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.TestRequest;
+import org.sonar.server.ws.WsActionTester;
+
+import static org.assertj.core.api.Java6Assertions.assertThat;
+import static org.sonar.core.permission.GlobalPermissions.QUALITY_PROFILE_ADMIN;
+import static org.sonar.server.qualityprofile.QProfileTesting.newQProfileDto;
+
+public class AddProjectActionTest {
+
+  static final String LANGUAGE_1 = "xoo";
+  static final String LANGUAGE_2 = "foo";
+
+  @Rule
+  public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+  @Rule
+  public UserSessionRule userSession = UserSessionRule.standalone();
+
+  DbClient dbClient = dbTester.getDbClient();
+  DbSession session = dbTester.getSession();
+
+  ComponentDbTester componentDb = new ComponentDbTester(dbTester);
+  QualityProfileDbTester qualityProfileDbTester = new QualityProfileDbTester(dbTester);
+  QProfileProjectOperations qProfileProjectOperations = new QProfileProjectOperations(dbClient);
+  Languages languages = LanguageTesting.newLanguages(LANGUAGE_1, LANGUAGE_2);
+  ProjectAssociationParameters projectAssociationParameters = new ProjectAssociationParameters(languages);
+
+  ComponentDto project;
+
+  WsActionTester ws = new WsActionTester(new AddProjectAction(projectAssociationParameters,
+    qProfileProjectOperations, new ProjectAssociationFinder(new QProfileLookup(dbClient),
+      new ComponentService(dbClient, null, userSession, null, new ComponentFinder(dbClient))),
+    userSession));
+
+  @Before
+  public void setUp() throws Exception {
+    project = componentDb.insertComponent(ComponentTesting.newProjectDto());
+  }
+
+  @Test
+  public void add_project() throws Exception {
+    setUserAsQualityProfileAdmin();
+    QualityProfileDto profile = qualityProfileDbTester.insertQualityProfile(newQProfileDto(QProfileName.createFor(LANGUAGE_1, "profile1"), "Profile"));
+    session.commit();
+
+    executeRequest(project, profile);
+
+    assertProjectIsAssociatedToProfile(project.key(), LANGUAGE_1, profile.getKey());
+  }
+
+  @Test
+  public void change_project_association() throws Exception {
+    setUserAsQualityProfileAdmin();
+    QualityProfileDto profile1 = newQProfileDto(QProfileName.createFor(LANGUAGE_1, "profile1"), "Profile 1");
+    QualityProfileDto profile2 = newQProfileDto(QProfileName.createFor(LANGUAGE_1, "profile2"), "Profile 2");
+    qualityProfileDbTester.insertQualityProfiles(profile1, profile2);
+    qualityProfileDbTester.associateProjectWithQualityProfile(project, profile1);
+    session.commit();
+
+    executeRequest(project, profile2);
+
+    assertProjectIsAssociatedToProfile(project.key(), LANGUAGE_1, profile2.getKey());
+  }
+
+  private void assertProjectIsAssociatedToProfile(String projectKey, String language, String expectedProfileKey) {
+    assertThat(dbClient.qualityProfileDao().selectByProjectAndLanguage(session, projectKey, language).getKey()).isEqualTo(expectedProfileKey);
+  }
+
+  private void setUserAsQualityProfileAdmin() {
+    userSession.login("admin").setGlobalPermissions(QUALITY_PROFILE_ADMIN);
+  }
+
+  private void executeRequest(ComponentDto project, QualityProfileDto qualityProfile) {
+    TestRequest request = ws.newRequest()
+      .setParam("projectUuid", project.uuid())
+      .setParam("profileKey", qualityProfile.getKey());
+    request.execute();
+  }
+
+}
index a8cadafaa6e4be877c6ea5f6ceadf0b9b6514ed5..8b90e445abb366f53d6008ec8cf006b7c0eeced6 100644 (file)
@@ -63,7 +63,6 @@ public class BackupActionTest {
     tester = new WsTester(new QProfilesWs(
       mock(RuleActivationActions.class),
       mock(BulkRuleActivationActions.class),
-      mock(ProjectAssociationActions.class),
       new BackupAction(backuper, dbClient, new QProfileFactory(dbClient), LanguageTesting.newLanguages("xoo"))));
   }
 
index 57048a50f583565a88934cdc318286bb3d606a89..67acd3ed3cd1bd0eff548a7b058f4a92287f3f23 100644 (file)
@@ -90,7 +90,7 @@ public class ChangelogActionTest {
     dbSession.commit();
     dbSession.clearCache();
 
-    wsTester = new WsTester(new QProfilesWs(mock(RuleActivationActions.class), mock(BulkRuleActivationActions.class), mock(ProjectAssociationActions.class),
+    wsTester = new WsTester(new QProfilesWs(mock(RuleActivationActions.class), mock(BulkRuleActivationActions.class),
       new ChangelogAction(db, new ActivityIndex(esTester.client()), new QProfileFactory(db), LanguageTesting.newLanguages("xoo"))));
   }
 
index b3a86434b584fe7f79e05498680ca19e5c69c1e5..49c523d5234f26646eb17479ffae8f632f4f69ed 100644 (file)
@@ -54,7 +54,6 @@ public class CopyActionTest {
     tester = new WsTester(new QProfilesWs(
       mock(RuleActivationActions.class),
       mock(BulkRuleActivationActions.class),
-      mock(ProjectAssociationActions.class),
       new CopyAction(qProfileCopier, LanguageTesting.newLanguages("xoo"), userSessionRule)));
   }
 
index 8996e3bcd1e1c7439728274c3c5d0ad74b8bc455..5a692d7a998ebc4f942b85cbd928ea1fd66bbb27 100644 (file)
@@ -76,7 +76,6 @@ public class DeleteActionTest {
     tester = new WsTester(new QProfilesWs(
       mock(RuleActivationActions.class),
       mock(BulkRuleActivationActions.class),
-      mock(ProjectAssociationActions.class),
       new DeleteAction(new Languages(xoo1, xoo2), new QProfileFactory(dbClient), dbClient, userSessionRule)));
   }
 
index 7d02c4524b18585ca1b6bfaf151982a15ef0cb87..5db35ffd7a2389b520acc614aa3c3a097ca50f5d 100644 (file)
@@ -82,7 +82,6 @@ public class ExportActionTest {
       null);
     wsTester = new WsTester(new QProfilesWs(mock(RuleActivationActions.class),
       mock(BulkRuleActivationActions.class),
-      mock(ProjectAssociationActions.class),
       new ExportAction(dbClient, new QProfileFactory(dbClient), backuper, exporters, LanguageTesting.newLanguages("xoo"))));
   }
 
@@ -169,7 +168,6 @@ public class ExportActionTest {
     QProfileExporters myExporters = new QProfileExporters(dbClient, null, null, null, new ProfileExporter[0], null);
     WsTester myWsTester = new WsTester(new QProfilesWs(mock(RuleActivationActions.class),
       mock(BulkRuleActivationActions.class),
-      mock(ProjectAssociationActions.class),
       new ExportAction(dbClient, new QProfileFactory(dbClient), backuper, myExporters, LanguageTesting.newLanguages("xoo"))));
 
     Action export = myWsTester.controller("api/qualityprofiles").action("export");
index 6c4ce5dc108816ad177b8e50748daa2482539e39..67ffa1508c6d3c9cab9f50bdc66de0ab771cbb0a 100644 (file)
  */
 package org.sonar.server.qualityprofile.ws;
 
+import java.io.Writer;
 import org.junit.Test;
 import org.sonar.api.profiles.ProfileExporter;
 import org.sonar.api.profiles.RulesProfile;
 import org.sonar.server.ws.WsTester;
 
-import java.io.Writer;
-
 import static org.mockito.Mockito.mock;
 
 public class ExportersActionTest {
@@ -33,7 +32,7 @@ public class ExportersActionTest {
   @Test
   public void importers_nominal() throws Exception {
     WsTester wsTester = new WsTester(new QProfilesWs(
-      mock(RuleActivationActions.class), mock(BulkRuleActivationActions.class), mock(ProjectAssociationActions.class),
+      mock(RuleActivationActions.class), mock(BulkRuleActivationActions.class),
       new ExportersAction(createExporters())));
 
     wsTester.newGetRequest("api/qualityprofiles", "exporters").execute().assertJson(getClass(), "exporters.json");
index a400d1a350233f67544691f70a704bc778e81daa..29b139063e8a0ce85f8b024a2df8cd3913e18c9d 100644 (file)
  */
 package org.sonar.server.qualityprofile.ws;
 
+import java.io.Reader;
 import org.junit.Test;
 import org.sonar.api.profiles.ProfileImporter;
 import org.sonar.api.profiles.RulesProfile;
 import org.sonar.api.utils.ValidationMessages;
 import org.sonar.server.ws.WsTester;
 
-import java.io.Reader;
-
 import static org.mockito.Mockito.mock;
 
 public class ImportersActionTest {
@@ -34,7 +33,7 @@ public class ImportersActionTest {
   @Test
   public void importers_nominal() throws Exception {
     WsTester wsTester = new WsTester(new QProfilesWs(
-      mock(RuleActivationActions.class), mock(BulkRuleActivationActions.class), mock(ProjectAssociationActions.class),
+      mock(RuleActivationActions.class), mock(BulkRuleActivationActions.class),
       new ImportersAction(createImporters())));
 
     wsTester.newGetRequest("api/qualityprofiles", "importers").execute().assertJson(getClass(), "importers.json");
index 0a4f22781f4904cc242ec11a64a09b74a7e4b6ca..523ef703292d2025abae49e9c7e3c838b791c186 100644 (file)
@@ -68,7 +68,6 @@ public class ProjectsActionTest {
   private WsTester wsTester = new WsTester(new QProfilesWs(
     mock(RuleActivationActions.class),
     mock(BulkRuleActivationActions.class),
-    mock(ProjectAssociationActions.class),
     new ProjectsAction(dbClient, userSessionRule)));
 
   @Before
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsModuleTest.java
new file mode 100644 (file)
index 0000000..81f381e
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.Test;
+import org.sonar.core.platform.ComponentContainer;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class QProfilesWsModuleTest {
+  @Test
+  public void verify_count_of_added_components() {
+    ComponentContainer container = new ComponentContainer();
+    new QProfilesWsModule().configure(container);
+    assertThat(container.size()).isEqualTo(24 + 2);
+  }
+}
index 3ae6c3107312cabd66334ed483c9e13bcbe5750a..bba366584633871da5de01c71e4f69190b7abdd2 100644 (file)
@@ -54,13 +54,15 @@ public class QProfilesWsTest {
     I18n i18n = mock(I18n.class);
 
     Languages languages = LanguageTesting.newLanguages(xoo1Key, xoo2Key);
+    ProjectAssociationParameters projectAssociationParameters = new ProjectAssociationParameters(languages);
 
     ProfileImporter[] importers = createImporters(languages);
 
     controller = new WsTester(new QProfilesWs(
       new RuleActivationActions(profileService),
       new BulkRuleActivationActions(profileService, null, i18n, userSessionRule),
-      new ProjectAssociationActions(null, null, null, languages, userSessionRule),
+      new AddProjectAction(projectAssociationParameters, null, null, null),
+      new RemoveProjectAction(projectAssociationParameters, null, null, null),
       new CreateAction(null, null, null, languages, importers, userSessionRule),
       new ImportersAction(importers),
       new RestoreBuiltInAction(null),
index 63a763166f6f26a2bfc3069eba903380a1c8ec99..9421eb153035991c0bd5d377d862ebebae2c7a7f 100644 (file)
@@ -58,7 +58,6 @@ public class RenameActionTest {
 
   private DbSession session;
 
-
   @Before
   public void setUp() {
     dbTester.truncateTables();
@@ -71,7 +70,6 @@ public class RenameActionTest {
     tester = new WsTester(new QProfilesWs(
       mock(RuleActivationActions.class),
       mock(BulkRuleActivationActions.class),
-      mock(ProjectAssociationActions.class),
       new RenameAction(new QProfileFactory(dbClient), userSessionRule)));
   }
 
@@ -144,8 +142,7 @@ public class RenameActionTest {
     qualityProfileDao.insert(session,
       QualityProfileDto.createFor("sonar-way-xoo1-12345").setLanguage(xoo1Key).setName("Sonar way").setDefault(true),
       QualityProfileDto.createFor("sonar-way-xoo2-23456").setLanguage(xoo2Key).setName("Sonar way"),
-      QualityProfileDto.createFor("my-sonar-way-xoo2-34567").setLanguage(xoo2Key).setName("My Sonar way").setParentKee("sonar-way-xoo2-23456").setDefault(true)
-      );
+      QualityProfileDto.createFor("my-sonar-way-xoo2-34567").setLanguage(xoo2Key).setName("My Sonar way").setParentKee("sonar-way-xoo2-23456").setDefault(true));
     session.commit();
   }
 }
index 17c1ec2256dab19db534bdd276c3f3e4e6891492..3e5f0d1f005e1886e684cab0a6119ccb4d425311 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.server.qualityprofile.ws;
 
+import java.io.Reader;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -35,8 +36,6 @@ import org.sonar.server.qualityprofile.QProfileName;
 import org.sonar.server.tester.UserSessionRule;
 import org.sonar.server.ws.WsTester;
 
-import java.io.Reader;
-
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
@@ -59,7 +58,6 @@ public class RestoreActionTest {
     tester = new WsTester(new QProfilesWs(
       mock(RuleActivationActions.class),
       mock(BulkRuleActivationActions.class),
-      mock(ProjectAssociationActions.class),
       new RestoreAction(backuper, LanguageTesting.newLanguages("xoo"), userSessionRule)));
   }
 
index 93f19e29ca02aff2223e62ee8d205491ea79ee0c..8143a7079a2d124e1a686a8e1422ebfd3b19429e 100644 (file)
@@ -46,7 +46,6 @@ public class RestoreBuiltInActionTest {
     tester = new WsTester(new QProfilesWs(
       mock(RuleActivationActions.class),
       mock(BulkRuleActivationActions.class),
-      mock(ProjectAssociationActions.class),
       new RestoreBuiltInAction(profileService)));
   }
 
index 5791fe931b3cf1e68d90b32cbf906a1c47886da1..76a4488149618160dd04d8699257c286adaee443 100644 (file)
@@ -47,11 +47,10 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 import static org.sonar.db.component.ComponentTesting.newProjectDto;
-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;
 import static org.sonar.test.JsonAssert.assertJson;
-
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_DEFAULTS;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROFILE_NAME;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROJECT_KEY;
 
 public class SearchActionTest {
 
@@ -98,15 +97,13 @@ public class SearchActionTest {
   public void search_nominal() throws Exception {
     when(profileLoader.countAllActiveRules()).thenReturn(ImmutableMap.of(
       "sonar-way-xoo1-12345", 11L,
-      "my-sonar-way-xoo2-34567", 33L
-      ));
+      "my-sonar-way-xoo2-34567", 33L));
 
     qualityProfileDao.insert(dbSession,
       QualityProfileDto.createFor("sonar-way-xoo1-12345").setLanguage(xoo1.getKey()).setName("Sonar way").setDefault(true),
       QualityProfileDto.createFor("sonar-way-xoo2-23456").setLanguage(xoo2.getKey()).setName("Sonar way"),
       QualityProfileDto.createFor("my-sonar-way-xoo2-34567").setLanguage(xoo2.getKey()).setName("My Sonar way").setParentKee("sonar-way-xoo2-23456"),
-      QualityProfileDto.createFor("sonar-way-other-666").setLanguage("other").setName("Sonar way").setDefault(true)
-      );
+      QualityProfileDto.createFor("sonar-way-other-666").setLanguage("other").setName("Sonar way").setDefault(true));
     new ComponentDao().insert(dbSession,
       newProjectDto("project-uuid1"),
       newProjectDto("project-uuid2"));
@@ -122,8 +119,7 @@ public class SearchActionTest {
   @Test
   public void search_for_language() throws Exception {
     qualityProfileDao.insert(dbSession,
-      QualityProfileDto.createFor("sonar-way-xoo1-12345").setLanguage(xoo1.getKey()).setName("Sonar way")
-      );
+      QualityProfileDto.createFor("sonar-way-xoo1-12345").setLanguage(xoo1.getKey()).setName("Sonar way"));
     commit();
 
     String result = ws.newRequest().setParam("language", xoo1.getKey()).execute().getInput();
index 66dfaeb90d36197a92e12db95015645ac1c91eac..4acfacf70ad2c0ca8407b07f8aea80c083874985 100644 (file)
@@ -72,7 +72,6 @@ public class SetDefaultActionTest {
     tester = new WsTester(new QProfilesWs(
       mock(RuleActivationActions.class),
       mock(BulkRuleActivationActions.class),
-      mock(ProjectAssociationActions.class),
       new SetDefaultAction(LanguageTesting.newLanguages(xoo1Key, xoo2Key), new QProfileLookup(dbClient), new QProfileFactory(dbClient), userSessionRule)));
   }
 
@@ -156,8 +155,7 @@ public class SetDefaultActionTest {
     qualityProfileDao.insert(session,
       QualityProfileDto.createFor("sonar-way-xoo1-12345").setLanguage(xoo1Key).setName("Sonar way").setDefault(true),
       QualityProfileDto.createFor("sonar-way-xoo2-23456").setLanguage(xoo2Key).setName("Sonar way"),
-      QualityProfileDto.createFor("my-sonar-way-xoo2-34567").setLanguage(xoo2Key).setName("My Sonar way").setParentKee("sonar-way-xoo2-23456").setDefault(true)
-      );
+      QualityProfileDto.createFor("my-sonar-way-xoo2-34567").setLanguage(xoo2Key).setName("My Sonar way").setParentKee("sonar-way-xoo2-23456").setDefault(true));
     session.commit();
   }
 
index 0dd2ed189dd9bd63562ff3f9c929f6b9f5a38266..d6e0a12d31c913615bc009eb27babf84cfa553c0 100644 (file)
@@ -37,6 +37,11 @@ public class QualityProfileDbTester {
     dbClient.qualityProfileDao().insert(dbSession, qualityProfile, qualityProfiles);
   }
 
+  public QualityProfileDto insertQualityProfile(QualityProfileDto qualityProfile) {
+    dbClient.qualityProfileDao().insert(dbSession, qualityProfile);
+    return qualityProfile;
+  }
+
   public void insertProjectWithQualityProfileAssociations(ComponentDto project, QualityProfileDto... qualityProfiles) {
     dbClient.componentDao().insert(dbSession, project);
     for (QualityProfileDto qualityProfile : qualityProfiles) {
@@ -44,4 +49,12 @@ public class QualityProfileDbTester {
     }
   }
 
+  public void associateProjectWithQualityProfile(ComponentDto project, QualityProfileDto... qualityProfiles) {
+    for (QualityProfileDto qualityProfile : qualityProfiles) {
+      dbClient.qualityProfileDao().insertProjectProfileAssociation(project.uuid(), qualityProfile.getKey(), dbSession);
+    }
+
+    dbSession.commit();
+  }
+
 }
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/AddProjectRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/AddProjectRequest.java
new file mode 100644 (file)
index 0000000..8e6c7f8
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.sonarqube.ws.client.qualityprofile;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+public class AddProjectRequest {
+
+  private final String language;
+  private final String profileName;
+  private final String profileKey;
+  private final String projectKey;
+  private final String projectUuid;
+
+  public AddProjectRequest(Builder builder) {
+    this.language = builder.language;
+    this.profileName = builder.profileName;
+    this.profileKey = builder.profileKey;
+    this.projectKey = builder.projectKey;
+    this.projectUuid = builder.projectUuid;
+  }
+
+  @CheckForNull
+  public String getLanguage() {
+    return language;
+  }
+
+  @CheckForNull
+  public String getProfileName() {
+    return profileName;
+  }
+
+  @CheckForNull
+  public String getProfileKey() {
+    return profileKey;
+  }
+
+  @CheckForNull
+  public String getProjectKey() {
+    return projectKey;
+  }
+
+  @CheckForNull
+  public String getProjectUuid() {
+    return projectUuid;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private String language;
+    private String profileName;
+    private String profileKey;
+    private String projectKey;
+    private String projectUuid;
+
+    private Builder() {
+      // enforce factory method use
+    }
+
+    public Builder setLanguage(@Nullable String language) {
+      this.language = language;
+      return this;
+    }
+
+    public Builder setProfileName(@Nullable String profileName) {
+      this.profileName = profileName;
+      return this;
+    }
+
+    public Builder setProfileKey(@Nullable String profileKey) {
+      this.profileKey = profileKey;
+      return this;
+    }
+
+    public Builder setProjectKey(@Nullable String projectKey) {
+      this.projectKey = projectKey;
+      return this;
+    }
+
+    public Builder setProjectUuid(@Nullable String projectUuid) {
+      this.projectUuid = projectUuid;
+      return this;
+    }
+
+    public AddProjectRequest build() {
+      return new AddProjectRequest(this);
+    }
+  }
+}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/QualityProfileWsParameters.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/QualityProfileWsParameters.java
new file mode 100644 (file)
index 0000000..8d75d16
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.sonarqube.ws.client.qualityprofile;
+
+public class QualityProfileWsParameters {
+
+  public static final String CONTROLLER_QUALITY_PROFILES = "api/qualityprofiles";
+
+  public static final String ACTION_SEARCH = "search";
+  public static final String ACTION_ADD_PROJECT = "add_project";
+  public static final String ACTION_REMOVE_PROJECT = "remove_project";
+
+  public static final String PARAM_DEFAULTS = "defaults";
+  public static final String PARAM_LANGUAGE = "language";
+  public static final String PARAM_PROFILE_NAME = "profileName";
+  public static final String PARAM_PROFILE_KEY = "profileKey";
+  public static final String PARAM_PROJECT_KEY = "projectKey";
+  public static final String PARAM_PROJECT_UUID = "projectUuid";
+
+  private QualityProfileWsParameters() {
+    // Only static stuff
+  }
+
+}
index 0dd4a4beadaaaf24d1edc39628744470a0588247..f92565570115662ab539b9fd1b27ab1fa836f522 100644 (file)
@@ -22,22 +22,52 @@ package org.sonarqube.ws.client.qualityprofile;
 import org.sonarqube.ws.QualityProfiles.SearchWsResponse;
 import org.sonarqube.ws.client.BaseService;
 import org.sonarqube.ws.client.GetRequest;
+import org.sonarqube.ws.client.PostRequest;
 import org.sonarqube.ws.client.WsConnector;
 
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_ADD_PROJECT;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_REMOVE_PROJECT;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_SEARCH;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.CONTROLLER_QUALITY_PROFILES;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_DEFAULTS;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROFILE_KEY;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROFILE_NAME;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROJECT_KEY;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROJECT_UUID;
+
 public class QualityProfilesService extends BaseService {
 
   public QualityProfilesService(WsConnector wsConnector) {
-    super(wsConnector, "api/qualityprofiles");
+    super(wsConnector, CONTROLLER_QUALITY_PROFILES);
   }
 
   public SearchWsResponse search(SearchWsRequest request) {
     return call(
-      new GetRequest(path("search"))
-        .setParam("defaults", request.getDefaults())
-        .setParam("language", request.getLanguage())
-        .setParam("profileName", request.getProfileName())
-        .setParam("projectKey", request.getProjectKey()),
+      new GetRequest(path(ACTION_SEARCH))
+        .setParam(PARAM_DEFAULTS, request.getDefaults())
+        .setParam(PARAM_LANGUAGE, request.getLanguage())
+        .setParam(PARAM_PROFILE_NAME, request.getProfileName())
+        .setParam(PARAM_PROJECT_KEY, request.getProjectKey()),
       SearchWsResponse.parser());
   }
 
+  public void addProject(AddProjectRequest request) {
+    call(new PostRequest(path(ACTION_ADD_PROJECT))
+      .setParam(PARAM_LANGUAGE, request.getLanguage())
+      .setParam(PARAM_PROFILE_NAME, request.getProfileName())
+      .setParam(PARAM_PROFILE_KEY, request.getProfileKey())
+      .setParam(PARAM_PROJECT_KEY, request.getProjectKey())
+      .setParam(PARAM_PROJECT_UUID, request.getProjectUuid()));
+  }
+
+  public void removeProject(RemoveProjectRequest request) {
+    call(new PostRequest(path(ACTION_REMOVE_PROJECT))
+      .setParam(PARAM_LANGUAGE, request.getLanguage())
+      .setParam(PARAM_PROFILE_NAME, request.getProfileName())
+      .setParam(PARAM_PROFILE_KEY, request.getProfileKey())
+      .setParam(PARAM_PROJECT_KEY, request.getProjectKey())
+      .setParam(PARAM_PROJECT_UUID, request.getProjectUuid()));
+  }
+
 }
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/RemoveProjectRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/RemoveProjectRequest.java
new file mode 100644 (file)
index 0000000..2dd9360
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.sonarqube.ws.client.qualityprofile;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+public class RemoveProjectRequest {
+
+  private final String language;
+  private final String profileName;
+  private final String profileKey;
+  private final String projectKey;
+  private final String projectUuid;
+
+  public RemoveProjectRequest(Builder builder) {
+    this.language = builder.language;
+    this.profileName = builder.profileName;
+    this.profileKey = builder.profileKey;
+    this.projectKey = builder.projectKey;
+    this.projectUuid = builder.projectUuid;
+  }
+
+  @CheckForNull
+  public String getLanguage() {
+    return language;
+  }
+
+  @CheckForNull
+  public String getProfileName() {
+    return profileName;
+  }
+
+  @CheckForNull
+  public String getProfileKey() {
+    return profileKey;
+  }
+
+  @CheckForNull
+  public String getProjectKey() {
+    return projectKey;
+  }
+
+  @CheckForNull
+  public String getProjectUuid() {
+    return projectUuid;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private String language;
+    private String profileName;
+    private String profileKey;
+    private String projectKey;
+    private String projectUuid;
+
+    private Builder() {
+      // enforce factory method use
+    }
+
+    public Builder setLanguage(@Nullable String language) {
+      this.language = language;
+      return this;
+    }
+
+    public Builder setProfileName(@Nullable String profileName) {
+      this.profileName = profileName;
+      return this;
+    }
+
+    public Builder setProfileKey(@Nullable String profileKey) {
+      this.profileKey = profileKey;
+      return this;
+    }
+
+    public Builder setProjectKey(@Nullable String projectKey) {
+      this.projectKey = projectKey;
+      return this;
+    }
+
+    public Builder setProjectUuid(@Nullable String projectUuid) {
+      this.projectUuid = projectUuid;
+      return this;
+    }
+
+    public RemoveProjectRequest build() {
+      return new RemoveProjectRequest(this);
+    }
+  }
+}
diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/qualityprofile/AddProjectRequestTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/qualityprofile/AddProjectRequestTest.java
new file mode 100644 (file)
index 0000000..b8f38de
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.sonarqube.ws.client.qualityprofile;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class AddProjectRequestTest {
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  AddProjectRequest.Builder underTest = AddProjectRequest.builder();
+
+  @Test
+  public void create_request_from_profile_key_and_project_key() {
+    AddProjectRequest result = underTest.setProfileKey("SonarWay").setProjectKey("sample").build();
+
+    assertThat(result.getLanguage()).isNull();
+    assertThat(result.getProfileKey()).isEqualTo("SonarWay");
+    assertThat(result.getProfileName()).isNull();
+    assertThat(result.getProjectKey()).isEqualTo("sample");
+    assertThat(result.getProjectUuid()).isNull();
+  }
+
+  @Test
+  public void create_request_from_profile_name_and_language_and_project_key() {
+    AddProjectRequest result = underTest.setLanguage("xoo").setProfileName("Sonar Way").setProjectKey("sample").build();
+
+    assertThat(result.getLanguage()).isEqualTo("xoo");
+    assertThat(result.getProfileKey()).isNull();
+    assertThat(result.getProfileName()).isEqualTo("Sonar Way");
+    assertThat(result.getProjectKey()).isEqualTo("sample");
+    assertThat(result.getProjectUuid()).isNull();
+  }
+
+  @Test
+  public void create_request_from_profile_key_and_project_uuid() {
+    AddProjectRequest result = underTest.setProfileKey("SonarWay").setProjectUuid("123").build();
+
+    assertThat(result.getLanguage()).isNull();
+    assertThat(result.getProfileKey()).isEqualTo("SonarWay");
+    assertThat(result.getProfileName()).isNull();
+    assertThat(result.getProjectKey()).isNull();
+    assertThat(result.getProjectUuid()).isEqualTo("123");
+  }
+
+}
diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/qualityprofile/QualityProfilesServiceTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/qualityprofile/QualityProfilesServiceTest.java
new file mode 100644 (file)
index 0000000..91ddb86
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.sonarqube.ws.client.qualityprofile;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonarqube.ws.QualityProfiles;
+import org.sonarqube.ws.client.GetRequest;
+import org.sonarqube.ws.client.ServiceTester;
+import org.sonarqube.ws.client.WsConnector;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_DEFAULTS;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROFILE_NAME;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROJECT_KEY;
+
+public class QualityProfilesServiceTest {
+
+  @Rule
+  public ServiceTester<QualityProfilesService> serviceTester = new ServiceTester<>(new QualityProfilesService(mock(WsConnector.class)));
+
+  private QualityProfilesService underTest = serviceTester.getInstanceUnderTest();
+
+  @Test
+  public void search() {
+    underTest.search(new SearchWsRequest()
+      .setDefaults(true)
+      .setProjectKey("project")
+      .setLanguage("language")
+      .setProfileName("profile"));
+    GetRequest getRequest = serviceTester.getGetRequest();
+
+    assertThat(serviceTester.getGetParser()).isSameAs(QualityProfiles.SearchWsResponse.parser());
+    serviceTester.assertThat(getRequest)
+      .hasParam(PARAM_DEFAULTS, true)
+      .hasParam(PARAM_PROJECT_KEY, "project")
+      .hasParam(PARAM_LANGUAGE, "language")
+      .hasParam(PARAM_PROFILE_NAME, "profile")
+      .andNoOtherParam();
+  }
+
+  @Test
+  public void add_project() throws Exception {
+    underTest.addProject(AddProjectRequest.builder()
+      .setLanguage("xoo")
+      .setProfileName("Sonar Way")
+      .setProjectKey("sample")
+      .build());
+
+    serviceTester.assertThat(serviceTester.getPostRequest())
+      .hasParam(PARAM_LANGUAGE, "xoo")
+      .hasParam(PARAM_PROFILE_NAME, "Sonar Way")
+      .hasParam(PARAM_PROJECT_KEY, "sample")
+      .andNoOtherParam();
+  }
+
+  @Test
+  public void remove_project() throws Exception {
+    underTest.removeProject(RemoveProjectRequest.builder()
+      .setLanguage("xoo")
+      .setProfileName("Sonar Way")
+      .setProjectKey("sample")
+      .build());
+
+    serviceTester.assertThat(serviceTester.getPostRequest())
+      .hasParam(PARAM_LANGUAGE, "xoo")
+      .hasParam(PARAM_PROFILE_NAME, "Sonar Way")
+      .hasParam(PARAM_PROJECT_KEY, "sample")
+      .andNoOtherParam();
+  }
+}
diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/qualityprofile/RemoveProjectRequestTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/qualityprofile/RemoveProjectRequestTest.java
new file mode 100644 (file)
index 0000000..d09892b
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.sonarqube.ws.client.qualityprofile;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class RemoveProjectRequestTest {
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  RemoveProjectRequest.Builder underTest = RemoveProjectRequest.builder();
+
+  @Test
+  public void create_request_from_profile_key_and_project_key() {
+    RemoveProjectRequest result = underTest.setProfileKey("SonarWay").setProjectKey("sample").build();
+
+    assertThat(result.getLanguage()).isNull();
+    assertThat(result.getProfileKey()).isEqualTo("SonarWay");
+    assertThat(result.getProfileName()).isNull();
+    assertThat(result.getProjectKey()).isEqualTo("sample");
+    assertThat(result.getProjectUuid()).isNull();
+  }
+
+  @Test
+  public void create_request_from_profile_name_and_language_and_project_key() {
+    RemoveProjectRequest result = underTest.setLanguage("xoo").setProfileName("Sonar Way").setProjectKey("sample").build();
+
+    assertThat(result.getLanguage()).isEqualTo("xoo");
+    assertThat(result.getProfileKey()).isNull();
+    assertThat(result.getProfileName()).isEqualTo("Sonar Way");
+    assertThat(result.getProjectKey()).isEqualTo("sample");
+    assertThat(result.getProjectUuid()).isNull();
+  }
+
+  @Test
+  public void create_request_from_profile_key_and_project_uuid() {
+    RemoveProjectRequest result = underTest.setProfileKey("SonarWay").setProjectUuid("123").build();
+
+    assertThat(result.getLanguage()).isNull();
+    assertThat(result.getProfileKey()).isEqualTo("SonarWay");
+    assertThat(result.getProfileName()).isNull();
+    assertThat(result.getProjectKey()).isNull();
+    assertThat(result.getProjectUuid()).isEqualTo("123");
+  }
+
+}