]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5360 Create a new /api/rules/create WS
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Thu, 5 Jun 2014 10:32:19 +0000 (12:32 +0200)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Thu, 5 Jun 2014 10:32:28 +0000 (12:32 +0200)
sonar-server/src/main/java/org/sonar/server/rule/NewRule.java
sonar-server/src/main/java/org/sonar/server/rule/NewRuleParam.java [deleted file]
sonar-server/src/main/java/org/sonar/server/rule/RuleCreator.java
sonar-server/src/main/java/org/sonar/server/rule/ws/CreateAction.java
sonar-server/src/main/java/org/sonar/server/rule/ws/RulesWebService.java
sonar-server/src/test/java/org/sonar/server/rule/RuleCreatorMediumTest.java
sonar-server/src/test/java/org/sonar/server/rule/RuleServiceMediumTest.java
sonar-server/src/test/java/org/sonar/server/rule/ws/AppActionTest.java
sonar-server/src/test/java/org/sonar/server/rule/ws/CreateActionTest.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWebServiceTest.java

index 63376a163fd6c658d258f7b39ca3db371d0118e2..86be3dcdc555ab9ec1172d3ab8552eee4021dc2f 100644 (file)
  */
 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<NewRuleParam> params = newArrayList();
+  private final Map<String, String> 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<NewRuleParam> params() {
+  public Map<String, String> params() {
     return params;
   }
 
   @CheckForNull
-  public NewRuleParam param(final String paramKey) {
-    return Iterables.find(params, new Predicate<NewRuleParam>() {
-      @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<NewRuleParam> params) {
-    this.params = params;
+  public NewRule setParams(Map<String, String> 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 (file)
index cd0d10f..0000000
+++ /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;
-  }
-
-}
index ecd08c4fc8757216a48b9406b70161ea4bc5aa41..f497c54a2ce505ce57f8294179df23848cf1e65f 100644 (file)
@@ -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);
   }
 
index 77f87753866ea80f4976866fc24e70bbaa30bfe4..4041f13619010ede2924efe0d3c7ae4cc7f37f56 100644 (file)
@@ -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 <key>=<value>, 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);
   }
 }
index be8469f3c50b34f54a3e51ed62ceb5afbfbf1832..3bb48bd4ed09994fe42e7b3bb6214394b641c080 100644 (file)
@@ -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();
   }
index 407827091cc4108ff9ea4f74f0bb486867b6382f..ef23891cbdd4a29173474b9eb723e732eef6fe20 100644 (file)
@@ -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);
index dd44c8824fa052803b8826dd601454ffa62acbc5..260e60d20f2e0b15afff24e348e08e32589b1d9f 100644 (file)
@@ -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();
index 7eb003a18652f9346d55876cbc1b177dc7d42979..58e7c280e5e6cc70ce7a2c6c435dc1b571801700 100644 (file)
@@ -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 (file)
index 0000000..ff3ecf7
--- /dev/null
@@ -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<NewRule> 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");
+  }
+}
index cd7f36756d643ef604077bf5b37834232c8506f5..2631ad291929a265166416d33188a8c9e1bb9595 100644 (file)
@@ -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();
   }