From f316983bec908646d8b120e7d169c3fb76028a02 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Thu, 5 Jun 2014 12:32:19 +0200 Subject: [PATCH] SONAR-5360 Create a new /api/rules/create WS --- .../java/org/sonar/server/rule/NewRule.java | 27 +++---- .../org/sonar/server/rule/NewRuleParam.java | 45 ----------- .../org/sonar/server/rule/RuleCreator.java | 8 +- .../sonar/server/rule/ws/CreateAction.java | 16 ++-- .../sonar/server/rule/ws/RulesWebService.java | 5 +- .../server/rule/RuleCreatorMediumTest.java | 16 ++-- .../server/rule/RuleServiceMediumTest.java | 4 +- .../sonar/server/rule/ws/AppActionTest.java | 2 +- .../server/rule/ws/CreateActionTest.java | 79 +++++++++++++++++++ .../server/rule/ws/RulesWebServiceTest.java | 3 +- 10 files changed, 123 insertions(+), 82 deletions(-) delete mode 100644 sonar-server/src/main/java/org/sonar/server/rule/NewRuleParam.java create mode 100644 sonar-server/src/test/java/org/sonar/server/rule/ws/CreateActionTest.java diff --git a/sonar-server/src/main/java/org/sonar/server/rule/NewRule.java b/sonar-server/src/main/java/org/sonar/server/rule/NewRule.java index 63376a163fd..86be3dcdc55 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/NewRule.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/NewRule.java @@ -19,16 +19,14 @@ */ package org.sonar.server.rule; -import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; +import com.google.common.collect.Maps; import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.RuleStatus; import javax.annotation.CheckForNull; import javax.annotation.Nullable; -import java.util.List; -import static com.google.common.collect.Lists.newArrayList; +import java.util.Map; public class NewRule { @@ -36,7 +34,7 @@ public class NewRule { private RuleKey templateKey; private String name, htmlDescription, severity; private RuleStatus status; - private List params = newArrayList(); + private final Map params = Maps.newHashMap(); public boolean isTemplate() { return isTemplate; @@ -51,6 +49,9 @@ public class NewRule { return templateKey; } + /** + * For the creation a custom rule + */ public NewRule setTemplateKey(@Nullable RuleKey templateKey) { this.templateKey = templateKey; return this; @@ -96,22 +97,18 @@ public class NewRule { return this; } - public List params() { + public Map params() { return params; } @CheckForNull - public NewRuleParam param(final String paramKey) { - return Iterables.find(params, new Predicate() { - @Override - public boolean apply(@Nullable NewRuleParam input) { - return input != null && input.key().equals(paramKey); - } - }, null); + public String param(final String paramKey) { + return params.get(paramKey); } - public NewRule setParams(List params) { - this.params = params; + public NewRule setParams(Map params) { + this.params.clear(); + this.params.putAll(params); return this; } } diff --git a/sonar-server/src/main/java/org/sonar/server/rule/NewRuleParam.java b/sonar-server/src/main/java/org/sonar/server/rule/NewRuleParam.java deleted file mode 100644 index cd0d10f1f02..00000000000 --- a/sonar-server/src/main/java/org/sonar/server/rule/NewRuleParam.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.rule; - -public class NewRuleParam { - - String key, defaultValue; - - public NewRuleParam(String key) { - this.key = key; - } - - public String key() { - return key; - } - - - public String defaultValue() { - return defaultValue; - } - - public NewRuleParam setDefaultValue(String defaultValue) { - this.defaultValue = defaultValue; - return this; - } - -} diff --git a/sonar-server/src/main/java/org/sonar/server/rule/RuleCreator.java b/sonar-server/src/main/java/org/sonar/server/rule/RuleCreator.java index ecd08c4fc87..f497c54a2ce 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/RuleCreator.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/RuleCreator.java @@ -99,7 +99,7 @@ public class RuleCreator implements ServerComponent { dbClient.ruleDao().insert(dbSession, ruleDto); for (RuleParamDto templateRuleParamDto : dbClient.ruleDao().findRuleParamsByRuleKey(dbSession, templateRuleDto.getKey())) { - NewRuleParam newRuleParam = newRule.param(templateRuleParamDto.getName()); + String newRuleParam = newRule.param(templateRuleParamDto.getName()); if (newRuleParam == null) { throw new IllegalArgumentException(String.format("The parameter '%s' has not been set", templateRuleParamDto.getName())); } @@ -108,12 +108,12 @@ public class RuleCreator implements ServerComponent { return ruleKey; } - private void createCustomRuleParams(NewRuleParam param, RuleDto ruleDto, RuleParamDto templateRuleParam, DbSession dbSession){ + private void createCustomRuleParams(String param, RuleDto ruleDto, RuleParamDto templateRuleParam, DbSession dbSession){ RuleParamDto ruleParamDto = RuleParamDto.createFor(ruleDto) - .setName(param.key()) + .setName(templateRuleParam.getName()) .setType(templateRuleParam.getType()) .setDescription(templateRuleParam.getDescription()) - .setDefaultValue(param.defaultValue()); + .setDefaultValue(param); dbClient.ruleDao().addRuleParam(dbSession, ruleDto, ruleParamDto); } diff --git a/sonar-server/src/main/java/org/sonar/server/rule/ws/CreateAction.java b/sonar-server/src/main/java/org/sonar/server/rule/ws/CreateAction.java index 77f87753866..4041f136190 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/ws/CreateAction.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/ws/CreateAction.java @@ -26,6 +26,7 @@ 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.utils.KeyValueFormat; import org.sonar.server.rule.NewRule; import org.sonar.server.rule.RuleService; @@ -35,17 +36,16 @@ import org.sonar.server.rule.RuleService; public class CreateAction implements RequestHandler { public static final String PARAM_NAME = "name"; - public static final String PARAM_DESCRIPTION = "description"; + public static final String PARAM_DESCRIPTION = "html_description"; public static final String PARAM_SEVERITY = "severity"; public static final String PARAM_STATUS = "status"; public static final String PARAM_TEMPLATE_KEY = "template_key"; + public static final String PARAMS = "params"; private final RuleService service; - private final RuleMapping mapping; - public CreateAction(RuleService service, RuleMapping mapping) { + public CreateAction(RuleService service) { this.service = service; - this.mapping = mapping; } void define(WebService.NewController controller) { @@ -85,6 +85,9 @@ public class CreateAction implements RequestHandler { .setRequired(true) .setDefaultValue(RuleStatus.READY) .setPossibleValues(RuleStatus.values()); + + action.createParam(PARAMS) + .setDescription("Parameters as semi-colon list of =, for example 'params=key1=v1;key2=v2'."); } @Override @@ -96,7 +99,10 @@ public class CreateAction implements RequestHandler { .setHtmlDescription(request.mandatoryParam(PARAM_DESCRIPTION)) .setSeverity(request.mandatoryParam(PARAM_SEVERITY)) .setStatus(RuleStatus.valueOf(request.mandatoryParam(PARAM_STATUS))); - + String params = request.param(PARAMS); + if (params != null) { + newRule.setParams(KeyValueFormat.parse(params)); + } service.create(newRule); } } diff --git a/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesWebService.java b/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesWebService.java index be8469f3c50..3bb48bd4ed0 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesWebService.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesWebService.java @@ -26,14 +26,16 @@ public class RulesWebService implements WebService { private final SearchAction search; private final ShowAction show; private final TagsAction tags; + private final CreateAction create; private final AppAction app; private final UpdateAction update; - public RulesWebService(SearchAction search, ShowAction show, TagsAction tags, + public RulesWebService(SearchAction search, ShowAction show, TagsAction tags, CreateAction create, AppAction app, UpdateAction update) { this.search = search; this.show = show; this.tags = tags; + this.create = create; this.app = app; this.update = update; } @@ -49,6 +51,7 @@ public class RulesWebService implements WebService { tags.define(controller); app.define(controller); update.define(controller); + create.define(controller); controller.done(); } diff --git a/sonar-server/src/test/java/org/sonar/server/rule/RuleCreatorMediumTest.java b/sonar-server/src/test/java/org/sonar/server/rule/RuleCreatorMediumTest.java index 407827091cc..ef23891cbdd 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule/RuleCreatorMediumTest.java +++ b/sonar-server/src/test/java/org/sonar/server/rule/RuleCreatorMediumTest.java @@ -20,6 +20,7 @@ package org.sonar.server.rule; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Sets; import org.junit.After; import org.junit.Before; @@ -39,7 +40,6 @@ import org.sonar.server.tester.ServerTester; import java.util.List; -import static com.google.common.collect.Lists.newArrayList; import static org.fest.assertions.Assertions.assertThat; import static org.fest.assertions.Fail.fail; @@ -76,7 +76,7 @@ public class RuleCreatorMediumTest { .setHtmlDescription("Some description") .setSeverity(Severity.MAJOR) .setStatus(RuleStatus.READY) - .setParams(newArrayList(new NewRuleParam("regex").setDefaultValue("a.*"))); + .setParams(ImmutableMap.of("regex", "a.*")); RuleKey customRuleKey = creator.create(newRule); dbSession.clearCache(); @@ -112,7 +112,7 @@ public class RuleCreatorMediumTest { .setHtmlDescription("Some description") .setSeverity(Severity.MAJOR) .setStatus(RuleStatus.READY) - .setParams(newArrayList(new NewRuleParam("regex").setDefaultValue("a.*"))); + .setParams(ImmutableMap.of("regex", "a.*")); try { creator.create(newRule); @@ -133,7 +133,7 @@ public class RuleCreatorMediumTest { .setName("My custom") .setSeverity(Severity.MAJOR) .setStatus(RuleStatus.READY) - .setParams(newArrayList(new NewRuleParam("regex").setDefaultValue("a.*"))); + .setParams(ImmutableMap.of("regex", "a.*")); try { creator.create(newRule); @@ -154,7 +154,7 @@ public class RuleCreatorMediumTest { .setName("My custom") .setHtmlDescription("Some description") .setStatus(RuleStatus.READY) - .setParams(newArrayList(new NewRuleParam("regex").setDefaultValue("a.*"))); + .setParams(ImmutableMap.of("regex", "a.*")); try { creator.create(newRule); @@ -176,7 +176,7 @@ public class RuleCreatorMediumTest { .setHtmlDescription("Some description") .setSeverity("INVALID") .setStatus(RuleStatus.READY) - .setParams(newArrayList(new NewRuleParam("regex").setDefaultValue("a.*"))); + .setParams(ImmutableMap.of("regex", "a.*")); try { creator.create(newRule); @@ -197,7 +197,7 @@ public class RuleCreatorMediumTest { .setName("My custom") .setHtmlDescription("Some description") .setSeverity(Severity.MAJOR) - .setParams(newArrayList(new NewRuleParam("regex").setDefaultValue("a.*"))); + .setParams(ImmutableMap.of("regex", "a.*")); try { creator.create(newRule); @@ -222,7 +222,7 @@ public class RuleCreatorMediumTest { .setHtmlDescription("Some description") .setSeverity(Severity.MAJOR) .setStatus(RuleStatus.READY) - .setParams(newArrayList(new NewRuleParam("regex").setDefaultValue("a.*"))); + .setParams(ImmutableMap.of("regex", "a.*")); try { creator.create(newRule); diff --git a/sonar-server/src/test/java/org/sonar/server/rule/RuleServiceMediumTest.java b/sonar-server/src/test/java/org/sonar/server/rule/RuleServiceMediumTest.java index dd44c8824fa..260e60d20f2 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule/RuleServiceMediumTest.java +++ b/sonar-server/src/test/java/org/sonar/server/rule/RuleServiceMediumTest.java @@ -19,6 +19,7 @@ */ package org.sonar.server.rule; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Sets; import org.junit.After; import org.junit.Before; @@ -42,7 +43,6 @@ import org.sonar.server.user.MockUserSession; import java.util.Collections; import java.util.Set; -import static com.google.common.collect.Lists.newArrayList; import static org.fest.assertions.Assertions.assertThat; import static org.fest.assertions.Fail.fail; @@ -150,7 +150,7 @@ public class RuleServiceMediumTest { .setHtmlDescription("Some description") .setSeverity(Severity.MAJOR) .setStatus(RuleStatus.READY) - .setParams(newArrayList(new NewRuleParam("regex").setDefaultValue("a.*"))); + .setParams(ImmutableMap.of("regex", "a.*")); RuleKey customRuleKey = service.create(newRule); dbSession.clearCache(); diff --git a/sonar-server/src/test/java/org/sonar/server/rule/ws/AppActionTest.java b/sonar-server/src/test/java/org/sonar/server/rule/ws/AppActionTest.java index 7eb003a1865..58e7c280e5e 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule/ws/AppActionTest.java +++ b/sonar-server/src/test/java/org/sonar/server/rule/ws/AppActionTest.java @@ -68,7 +68,7 @@ public class AppActionTest { public void should_generate_app_init_info() throws Exception { AppAction app = new AppAction(languages, ruleRepositories, i18n, debtModel, qualityProfileService); WsTester tester = new WsTester(new RulesWebService( - mock(SearchAction.class), mock(ShowAction.class), mock(TagsAction.class), + mock(SearchAction.class), mock(ShowAction.class), mock(TagsAction.class), mock(CreateAction.class), app, mock(UpdateAction.class))); MockUserSession.set().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN); diff --git a/sonar-server/src/test/java/org/sonar/server/rule/ws/CreateActionTest.java b/sonar-server/src/test/java/org/sonar/server/rule/ws/CreateActionTest.java new file mode 100644 index 00000000000..ff3ecf74392 --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/rule/ws/CreateActionTest.java @@ -0,0 +1,79 @@ +/* + * 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.rule.ws; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rule.RuleStatus; +import org.sonar.server.rule.NewRule; +import org.sonar.server.rule.RuleService; +import org.sonar.server.ws.WsTester; + +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +@RunWith(MockitoJUnitRunner.class) +public class CreateActionTest { + + @Mock + RuleService ruleService; + + @Captor + ArgumentCaptor newRuleCaptor; + + WsTester tester; + + @Before + public void setUp() throws Exception { + tester = new WsTester(new RulesWebService(mock(SearchAction.class), mock(ShowAction.class), mock(TagsAction.class), new CreateAction(ruleService), + mock(AppAction.class), mock(UpdateAction.class))); + } + + @Test + public void create_custom_rule() throws Exception { + WsTester.TestRequest request = tester.newGetRequest("api/rules", "create") + .setParam("template_key", "java:S001") + .setParam("name", "My custom rule") + .setParam("html_description", "Description") + .setParam("severity", "MAJOR") + .setParam("status", "BETA") + .setParam("params", "key=value"); + request.execute(); + + verify(ruleService).create(newRuleCaptor.capture()); + + NewRule newRule = newRuleCaptor.getValue(); + assertThat(newRule.templateKey()).isEqualTo(RuleKey.of("java", "S001")); + assertThat(newRule.name()).isEqualTo("My custom rule"); + assertThat(newRule.htmlDescription()).isEqualTo("Description"); + assertThat(newRule.severity()).isEqualTo("MAJOR"); + assertThat(newRule.status()).isEqualTo(RuleStatus.BETA); + assertThat(newRule.params()).hasSize(1); + assertThat(newRule.params().get("key")).isEqualTo("value"); + } +} diff --git a/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWebServiceTest.java b/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWebServiceTest.java index cd7f36756d6..2631ad29192 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWebServiceTest.java +++ b/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWebServiceTest.java @@ -87,11 +87,12 @@ public class RulesWebServiceTest { WebService.Controller controller = context.controller(API_ENDPOINT); assertThat(controller).isNotNull(); - assertThat(controller.actions()).hasSize(5); + assertThat(controller.actions()).hasSize(6); assertThat(controller.action(API_SEARCH_METHOD)).isNotNull(); assertThat(controller.action(API_SHOW_METHOD)).isNotNull(); assertThat(controller.action(API_TAGS_METHOD)).isNotNull(); assertThat(controller.action("update")).isNotNull(); + assertThat(controller.action("create")).isNotNull(); assertThat(controller.action("app")).isNotNull(); } -- 2.39.5