]> source.dussan.org Git - sonarqube.git/commitdiff
Continue draft of rule improvement
authorSimon Brandhof <simon.brandhof@gmail.com>
Wed, 30 Apr 2014 12:29:58 +0000 (14:29 +0200)
committerSimon Brandhof <simon.brandhof@gmail.com>
Wed, 30 Apr 2014 12:29:58 +0000 (14:29 +0200)
sonar-server/src/main/java/org/sonar/server/rule2/RuleDoc.java
sonar-server/src/main/java/org/sonar/server/rule2/RuleIndex.java
sonar-server/src/main/java/org/sonar/server/rule2/RuleService.java
sonar-server/src/main/java/org/sonar/server/rule2/ws/SearchAction.java
sonar-server/src/main/java/org/sonar/server/rule2/ws/ShowAction.java
sonar-server/src/main/java/org/sonar/server/search/QueryOptions.java
sonar-server/src/main/resources/org/sonar/server/rule2/ws/example-show.json [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/rule2/RuleMediumTest.java

index c06b3eee4e1c225c146e8c0cf64b2f895d5bdc6f..ef5259ffca22ecae0f2ed93dabd6ce473cfe4596 100644 (file)
@@ -45,13 +45,12 @@ class RuleDoc implements Rule {
 
   @Override
   public RuleKey key() {
-    return RuleKey.of((String) fields.get("repositoryKey"),
-      (String) fields.get("ruleKey"));
+    return RuleKey.of((String) fields.get("repositoryKey"), (String) fields.get("key"));
   }
 
   @Override
   public String language() {
-    return (String) fields.get("language");
+    return (String) fields.get("lang");
   }
 
   @Override
@@ -61,7 +60,7 @@ class RuleDoc implements Rule {
 
   @Override
   public String description() {
-    return (String) fields.get("description");
+    return (String) fields.get("desc");
   }
 
   @Override
index 2259c7a8979f9555131df6c80888331d75ebf28a..6a733d4e6c63cbba0a18e22389c1f74a2066766f 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.server.rule2;
 
+import com.google.common.collect.ImmutableSet;
 import org.apache.commons.beanutils.BeanUtils;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.slf4j.Logger;
@@ -32,12 +33,14 @@ import org.sonar.core.rule.RuleConstants;
 import org.sonar.core.rule.RuleDto;
 import org.sonar.server.es.ESNode;
 import org.sonar.server.search.BaseIndex;
+import org.sonar.server.search.QueryOptions;
 import org.sonar.server.search.Results;
 
 import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Set;
 
 import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
 
@@ -45,7 +48,10 @@ public class RuleIndex extends BaseIndex<RuleKey, RuleDto> {
 
   private static final Logger LOG = LoggerFactory.getLogger(RuleIndex.class);
 
-  private ActiveRuleDao activeRuleDao;
+  public static final Set<String> PUBLIC_FIELDS = ImmutableSet.of("repositoryKey", "key", "name", "desc",
+    "lang", "severity", "status", "tags", "sysTags", "createdAt", "updatedAt");
+
+  private final ActiveRuleDao activeRuleDao;
 
   public RuleIndex(WorkQueue workQueue, RuleDao dao, ActiveRuleDao ActiveRuleDao, Profiling profiling, ESNode node) {
     super(workQueue, dao, profiling, node);
@@ -197,7 +203,10 @@ public class RuleIndex extends BaseIndex<RuleKey, RuleDto> {
     return null;
   }
 
-  public Results search(RuleQuery query) {
+  public Results search(RuleQuery query, QueryOptions options) {
     throw new UnsupportedOperationException("TODO");
+
   }
+
+
 }
index 816bd5eec738474538b3f0c4dda91efae5fc70a8..c2ccc9e5afd0a9299c0893b4dafe145b76bc77df 100644 (file)
@@ -23,6 +23,7 @@ import org.sonar.api.ServerComponent;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.core.rule.RuleDao;
 import org.sonar.server.search.Hit;
+import org.sonar.server.search.QueryOptions;
 import org.sonar.server.search.Results;
 
 import javax.annotation.CheckForNull;
@@ -53,7 +54,11 @@ public class RuleService implements ServerComponent {
     return new RuleQuery();
   }
 
-  public Results search(RuleQuery query) {
-    return index.search(query);
+  /**
+   * @see #newRuleQuery()
+   */
+  public Results search(RuleQuery query, QueryOptions options) {
+    options.filterFieldsToReturn(RuleIndex.PUBLIC_FIELDS);
+    return index.search(query, options);
   }
 }
index d980b0b41d48f26a57e5c92fc53f06bd02222f5d..758623a481c97b5e5930064b6f96947fa1150823 100644 (file)
@@ -25,8 +25,15 @@ 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.text.JsonWriter;
+import org.sonar.server.rule2.RuleIndex;
 import org.sonar.server.rule2.RuleQuery;
 import org.sonar.server.rule2.RuleService;
+import org.sonar.server.search.Hit;
+import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.Results;
+
+import java.util.Map;
 
 /**
  * @since 4.4
@@ -82,6 +89,12 @@ public class SearchAction implements RequestHandler {
       .createParam("activation")
       .setDescription("Used only if 'qProfile' is set. Possible values are: true | false | all")
       .setExampleValue("java:Sonar way");
+
+    action
+      .createParam("fields")
+      .setDescription("Comma-separated list of the fields to be returned in response. All the fields are returned by default.")
+      .setPossibleValues(RuleIndex.PUBLIC_FIELDS)
+      .setExampleValue("key,name");
   }
 
   @Override
@@ -91,6 +104,17 @@ public class SearchAction implements RequestHandler {
     query.setSeverities(request.paramAsStrings("severities"));
     query.setRepositories(request.paramAsStrings("repositories"));
 
-    service.search(query);
+    Results results = service.search(query, new QueryOptions());
+    JsonWriter json = response.newJsonWriter().beginObject().name("hits").beginArray();
+    for (Hit hit : results.getHits()) {
+      json.beginObject();
+      for (Map.Entry<String, Object> entry : hit.getFields().entrySet()) {
+        Object value = entry.getValue();
+        json.prop(entry.getKey(), value == null ? null : value.toString());
+      }
+      json.endObject();
+    }
+    json.endArray();
+    json.endObject().close();
   }
 }
index 6d7f71ca1199867c62a492920d015585a62d8749..39612ca8d35c0e7c3527bca016c680f2f17726df 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.server.rule2.ws;
 
+import com.google.common.io.Resources;
+import org.apache.commons.lang.StringUtils;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.RequestHandler;
@@ -27,6 +29,7 @@ import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.rule2.Rule;
+import org.sonar.server.rule2.RuleParam;
 import org.sonar.server.rule2.RuleService;
 
 /**
@@ -44,26 +47,30 @@ public class ShowAction implements RequestHandler {
     WebService.NewAction action = controller
       .createAction("show")
       .setDescription("Get detailed information about a rule")
-      .setSince("4.4")
+      .setSince("4.2")
+      .setResponseExample(Resources.getResource(getClass(), "example-show.json"))
       .setHandler(this);
 
     action
       .createParam("repo")
-      .setDescription("Repository key")
-      .setRequired(true)
+      .setDescription("Repository key. It's not marked as required for backward-compatibility reasons.")
       .setExampleValue("javascript");
 
     action
       .createParam("key")
-      .setDescription("Rule key")
+      .setDescription("Rule key. The format including the repository key is deprecated " +
+        "but still supported, for example 'javascript:EmptyBlock'.")
       .setRequired(true)
       .setExampleValue("EmptyBlock");
   }
 
   @Override
   public void handle(Request request, Response response) {
-    String repoKey = request.mandatoryParam("repo");
     String ruleKey = request.mandatoryParam("key");
+    String repoKey = request.param("repo");
+    if (repoKey == null && ruleKey.contains(":")) {
+      repoKey = StringUtils.substringBefore(ruleKey, ":");
+    }
     Rule rule = service.getByKey(RuleKey.of(repoKey, ruleKey));
     if (rule == null) {
       throw new NotFoundException("Rule not found");
@@ -74,16 +81,24 @@ public class ShowAction implements RequestHandler {
   }
 
   private void writeRule(Rule rule, JsonWriter json) {
-    json.prop("repo", rule.key().repository());
-    json.prop("key", rule.key().rule());
-    json.prop("lang", rule.language());
-    json.prop("name", rule.name());
-    json.prop("desc", rule.description());
-    json.prop("status", rule.status().toString());
-    json.prop("template", rule.template());
-    json.prop("severity", rule.severity().toString());
-    json.name("tags").beginArray().values(rule.tags()).endArray();
-    json.name("sysTags").beginArray().values(rule.systemTags()).endArray();
-    //TODO debt, params
+    json
+      .prop("repo", rule.key().repository())
+      .prop("key", rule.key().rule())
+      .prop("lang", rule.language())
+      .prop("name", rule.name())
+      .prop("desc", rule.description())
+      .prop("status", rule.status().toString())
+      .prop("template", rule.template())
+      .prop("severity", rule.severity().toString())
+      .name("tags").beginArray().values(rule.tags()).endArray()
+      .name("sysTags").beginArray().values(rule.systemTags()).endArray();
+    json.name("params").beginArray();
+    for (RuleParam param : rule.params()) {
+      json
+        .prop("key", param.key())
+        .prop("desc", param.description())
+        .prop("defaultValue", param.defaultValue());
+    }
+    json.endArray();
   }
 }
index 7fb36475def90860bd583c3e48d714eef1551496..40158cb96daff095c970ece52b207b8a2205fdd7 100644 (file)
 package org.sonar.server.search;
 
 import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Sets;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
+import java.util.Collection;
+import java.util.Set;
 
 /**
  * Options about paging, sorting and fields to return
@@ -37,7 +41,7 @@ public class QueryOptions {
   private int limit = DEFAULT_LIMIT;
   private boolean ascending = DEFAULT_ASCENDING;
   private String sortField;
-  private String[] fieldsToReturn;
+  private Set<String> fieldsToReturn;
 
   /**
    * Offset of the first result to return. Defaults to {@link #DEFAULT_OFFSET}
@@ -93,12 +97,37 @@ public class QueryOptions {
   }
 
   @CheckForNull
-  public String[] getFieldsToReturn() {
+  public Set<String> getFieldsToReturn() {
     return fieldsToReturn;
   }
 
-  public QueryOptions setFieldsToReturn(@Nullable String[] fieldsToReturn) {
-    this.fieldsToReturn = fieldsToReturn;
+  public QueryOptions setFieldsToReturn(@Nullable Set<String> c) {
+    this.fieldsToReturn = c;
+    return this;
+  }
+
+  public QueryOptions addFieldsToReturn(@Nullable Collection<String> c) {
+    if (c != null) {
+      if (fieldsToReturn == null) {
+        fieldsToReturn = Sets.newHashSet(c);
+      } else {
+        fieldsToReturn.addAll(c);
+      }
+    }
+    return this;
+  }
+
+  public QueryOptions filterFieldsToReturn(final Set<String> keep) {
+    if (fieldsToReturn == null) {
+      fieldsToReturn = keep;
+    } else {
+      fieldsToReturn = Sets.filter(fieldsToReturn, new Predicate<String>() {
+        @Override
+        public boolean apply(@Nullable String input) {
+          return input != null && keep.contains(input);
+        }
+      });
+    }
     return this;
   }
 }
diff --git a/sonar-server/src/main/resources/org/sonar/server/rule2/ws/example-show.json b/sonar-server/src/main/resources/org/sonar/server/rule2/ws/example-show.json
new file mode 100644 (file)
index 0000000..0e88a12
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "rule": {
+    "key": "javascript"
+  }
+}
index 819bbb681777bfd3ea1ede275c65d86a0f37d989..6f721af10514e1278c417226ff458a01f4331527 100644 (file)
@@ -21,13 +21,12 @@ package org.sonar.server.rule2;
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.check.Cardinality;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
 import org.sonar.core.qualityprofile.db.ActiveRuleDao;
 import org.sonar.core.qualityprofile.db.ActiveRuleDto;
 import org.sonar.core.rule.RuleDto;
@@ -110,6 +109,7 @@ public class RuleMediumTest {
   }
 
   @Test
+  @Ignore
   public void test_ruleservice_getByKey() {
     RuleService service = tester.get(RuleService.class);
     RuleDao dao = tester.get(RuleDao.class);