]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6019 Add statuses and severities facets
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Tue, 13 Jan 2015 11:56:33 +0000 (12:56 +0100)
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Tue, 13 Jan 2015 14:39:33 +0000 (15:39 +0100)
server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java
server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndex.java
server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java
server/sonar-server/src/main/java/org/sonar/server/search/ws/SearchRequestHandler.java
server/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWebServiceMediumTest.java
server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/severities_facet.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/statuses_facet.json [new file with mode: 0644]

index 88dcf422eef070c7dbec0059d40276479f7bee4d..7b91182ccfc5c2ba8b6cddd24bf69ccf4acfad0d 100644 (file)
@@ -21,7 +21,6 @@ package org.sonar.server.issue.ws;
 
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
 import com.google.common.collect.Multimap;
 import com.google.common.io.Resources;
 import org.apache.commons.lang.BooleanUtils;
@@ -422,22 +421,6 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> {
     super.writeFacets(request, context, results, json);
   }
 
-  private void addMandatoryFacetValues(Result<?> results, String facetName, @Nullable List<String> mandatoryValues) {
-    Collection<FacetValue> facetValues = results.getFacetValues(facetName);
-    if (facetValues != null) {
-      Map<String, Long> valuesByItem = Maps.newHashMap();
-      for (FacetValue value : facetValues) {
-        valuesByItem.put(value.getKey(), value.getValue());
-      }
-      List<String> valuesToAdd = mandatoryValues == null ? Lists.<String>newArrayList() : mandatoryValues;
-      for (String item : valuesToAdd) {
-        if (!valuesByItem.containsKey(item)) {
-          facetValues.add(new FacetValue(item, 0));
-        }
-      }
-    }
-  }
-
   private void collectFacetsData(Request request, Result<Issue> result, Set<String> projectUuids, Set<String> componentUuids, List<String> userLogins, Set<String> actionPlanKeys) {
     collectFacetKeys(result, IssueFilterParameters.PROJECT_UUIDS, projectUuids);
     collectParameterValues(request, IssueFilterParameters.PROJECT_UUIDS, projectUuids);
index bdfca485496cc93e12af9f964588434cf18dbf99..dbf4dd85987721873bfb364539d4eeba5fadddee 100644 (file)
  */
 package org.sonar.server.rule.index;
 
+import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
 import org.elasticsearch.action.search.SearchRequestBuilder;
@@ -44,6 +47,7 @@ import org.elasticsearch.search.sort.SortBuilders;
 import org.elasticsearch.search.sort.SortOrder;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.rule.Severity;
 import org.sonar.api.server.debt.DebtCharacteristic;
 import org.sonar.core.rule.RuleDto;
 import org.sonar.server.qualityprofile.index.ActiveRuleNormalizer;
@@ -59,6 +63,7 @@ import org.sonar.server.search.StickyFacetBuilder;
 import javax.annotation.CheckForNull;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -73,6 +78,17 @@ public class RuleIndex extends BaseIndex<Rule, RuleDto, RuleKey> {
   public static final String FACET_LANGUAGES = "languages";
   public static final String FACET_TAGS = "tags";
   public static final String FACET_REPOSITORIES = "repositories";
+  public static final String FACET_SEVERITIES = "severities";
+  public static final String FACET_STATUSES = "statuses";
+  public static final String FACET_DEBT_CHARACTERISTICS = "debt_characteristics";
+  public static final String FACET_OLD_DEFAULT = "true";
+
+  public static final List<String> ALL_STATUSES = ImmutableList.copyOf(Collections2.transform(Arrays.asList(RuleStatus.values()), new Function<RuleStatus, String>() {
+    @Override
+    public String apply(RuleStatus input) {
+      return input.toString();
+    }
+  }));
 
   public RuleIndex(RuleNormalizer normalizer, SearchClient client) {
     super(IndexDefinition.RULE, normalizer, client);
@@ -336,30 +352,44 @@ public class RuleIndex extends BaseIndex<Rule, RuleDto, RuleKey> {
 
   protected Map<String, AggregationBuilder> getFacets(RuleQuery query, QueryContext options, QueryBuilder queryBuilder, Map<String, FilterBuilder> filters) {
     Map<String, AggregationBuilder> aggregations = new HashMap<String, AggregationBuilder>();
-
     StickyFacetBuilder stickyFacetBuilder = stickyFacetBuilder(queryBuilder, filters);
-    if (options.facets().contains("languages") || options.facets().contains("true")) {
+
+    addDefaultFacets(query, options, queryBuilder, filters, aggregations, stickyFacetBuilder);
+
+    if (options.facets().contains(FACET_STATUSES)) {
+      aggregations.put(FACET_STATUSES,
+        stickyFacetBuilder.buildStickyFacet(RuleNormalizer.RuleField.STATUS.field(), FACET_STATUSES, ALL_STATUSES.toArray()));
+    }
+
+    if (options.facets().contains(FACET_SEVERITIES)) {
+      aggregations.put(FACET_SEVERITIES,
+        stickyFacetBuilder.buildStickyFacet(RuleNormalizer.RuleField.SEVERITY.field(), FACET_SEVERITIES, Severity.ALL.toArray()));
+    }
+
+    return aggregations;
+
+  }
+
+  protected void addDefaultFacets(RuleQuery query, QueryContext options, QueryBuilder queryBuilder, Map<String, FilterBuilder> filters,
+    Map<String, AggregationBuilder> aggregations, StickyFacetBuilder stickyFacetBuilder) {
+    if (options.facets().contains(FACET_LANGUAGES) || options.facets().contains(FACET_OLD_DEFAULT)) {
       Collection<String> languages = query.getLanguages();
       aggregations.put(FACET_LANGUAGES,
         stickyFacetBuilder.buildStickyFacet(RuleNormalizer.RuleField.LANGUAGE.field(), FACET_LANGUAGES,
           languages == null ? new String[0] : languages.toArray()));
     }
-    if (options.facets().contains("tags") || options.facets().contains("true")) {
+    if (options.facets().contains(FACET_TAGS) || options.facets().contains(FACET_OLD_DEFAULT)) {
       Collection<String> tags = query.getTags();
       aggregations.put(FACET_TAGS,
         stickyFacetBuilder.buildStickyFacet(RuleNormalizer.RuleField.ALL_TAGS.field(), FACET_TAGS,
           tags == null ? new String[0] : tags.toArray()));
     }
-    if (options.facets().contains("repositories") || options.facets().contains("true")) {
+    if (options.facets().contains("repositories") || options.facets().contains(FACET_OLD_DEFAULT)) {
       Collection<String> repositories = query.getRepositories();
       aggregations.put(FACET_REPOSITORIES,
         stickyFacetBuilder.buildStickyFacet(RuleNormalizer.RuleField.REPOSITORY.field(), FACET_REPOSITORIES,
           repositories == null ? new String[0] : repositories.toArray()));
     }
-
-
-    return aggregations;
-
   }
 
   public Result<Rule> search(RuleQuery query, QueryContext options) {
index 6dd6f9890ac8a1063f0a5a9bc94a480c9c9dbb35..fefdcab6fb5ae0b677950bbb29bb688ad3a5c62b 100644 (file)
@@ -31,6 +31,7 @@ import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.server.qualityprofile.ActiveRule;
 import org.sonar.server.rule.Rule;
 import org.sonar.server.rule.RuleService;
+import org.sonar.server.rule.index.RuleIndex;
 import org.sonar.server.rule.index.RuleNormalizer;
 import org.sonar.server.rule.index.RuleQuery;
 import org.sonar.server.search.QueryContext;
@@ -95,13 +96,13 @@ public class SearchAction extends SearchRequestHandler<RuleQuery, Rule> {
   @CheckForNull
   protected Collection<String> possibleFacets() {
     return Arrays.asList(new String[] {
-      PARAM_LANGUAGES,
-      PARAM_REPOSITORIES,
-      "tags",
-      "characteristics",
-      "severities",
-      "statuses",
-      "true"
+      RuleIndex.FACET_LANGUAGES,
+      RuleIndex.FACET_REPOSITORIES,
+      RuleIndex.FACET_TAGS,
+      RuleIndex.FACET_DEBT_CHARACTERISTICS,
+      RuleIndex.FACET_SEVERITIES,
+      RuleIndex.FACET_STATUSES,
+      RuleIndex.FACET_OLD_DEFAULT
     });
   }
 
@@ -257,7 +258,7 @@ public class SearchAction extends SearchRequestHandler<RuleQuery, Rule> {
       .setLimit(context.getLimit())
       .setOffset(context.getOffset())
       .setScroll(context.isScroll());
-    if (context.facets().contains("true")) {
+    if (context.facets().contains(RuleIndex.FACET_OLD_DEFAULT)) {
       searchQueryContext.addFacets(DEFAULT_FACETS);
     } else {
       searchQueryContext.addFacets(context.facets());
@@ -293,4 +294,11 @@ public class SearchAction extends SearchRequestHandler<RuleQuery, Rule> {
     }
     return builder.add("actives").build();
   }
+
+  @Override
+  protected void writeFacets(Request request, QueryContext context, Result<?> results, JsonWriter json) {
+    addMandatoryFacetValues(results, RuleIndex.FACET_STATUSES, RuleIndex.ALL_STATUSES);
+    addMandatoryFacetValues(results, RuleIndex.FACET_SEVERITIES, Severity.ALL);
+    super.writeFacets(request, context, results, json);
+  }
 }
index e30bdcbc299e9acb23a57b39274d2bf397ad5dac..e5bec95f0e5e7383f07fba5685792b921126e4cb 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.server.search.ws;
 
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.RequestHandler;
@@ -30,10 +32,12 @@ import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.Result;
 
 import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
 
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 public abstract class SearchRequestHandler<QUERY, DOMAIN> implements RequestHandler {
@@ -177,4 +181,20 @@ public abstract class SearchRequestHandler<QUERY, DOMAIN> implements RequestHand
     }
   }
 
+  protected void addMandatoryFacetValues(Result<?> results, String facetName, @Nullable List<String> mandatoryValues) {
+    Collection<FacetValue> facetValues = results.getFacetValues(facetName);
+    if (facetValues != null) {
+      Map<String, Long> valuesByItem = Maps.newHashMap();
+      for (FacetValue value : facetValues) {
+        valuesByItem.put(value.getKey(), value.getValue());
+      }
+      List<String> valuesToAdd = mandatoryValues == null ? Lists.<String>newArrayList() : mandatoryValues;
+      for (String item : valuesToAdd) {
+        if (!valuesByItem.containsKey(item)) {
+          facetValues.add(new FacetValue(item, 0));
+        }
+      }
+    }
+  }
+
 }
index 85ad9dd64885c3c2d371f2122cbfd8c06115684e..bc4fab4772f67a703285dee99a1f881344dde3eb 100644 (file)
@@ -454,6 +454,20 @@ public class RulesWebServiceMediumTest {
     result.assertJson(this.getClass(), "filter_by_tags.json");
   }
 
+  @Test
+  public void severities_facet_should_have_all_severities() throws Exception {
+    WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD);
+    request.setParam(SearchAction.PARAM_FACETS, "severities");
+    request.execute().assertJson(this.getClass(), "severities_facet.json", false);
+  }
+
+  @Test
+  public void statuses_facet_should_have_all_statuses() throws Exception {
+    WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD);
+    request.setParam(SearchAction.PARAM_FACETS, "statuses");
+    request.execute().assertJson(this.getClass(), "statuses_facet.json", false);
+  }
+
   @Test
   public void sort_by_name() throws Exception {
     ruleDao.insert(session, RuleTesting.newXooX1().setName("Dodgy - Consider returning a zero length array rather than null "));
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/severities_facet.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/severities_facet.json
new file mode 100644 (file)
index 0000000..f2d9754
--- /dev/null
@@ -0,0 +1,25 @@
+{"total": 0, "p": 1, "ps": 100, "rules": [],
+"facets": [
+  {
+    "property": "severities",
+    "values": [
+      {
+        "val": "BLOCKER",
+        "count": 0
+      },{
+        "val": "CRITICAL",
+        "count": 0
+      },{
+        "val": "MAJOR",
+        "count": 0
+      },{
+        "val": "MINOR",
+        "count": 0
+      },
+      {
+        "val": "INFO",
+        "count": 0
+      }
+    ]
+  }
+]}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/statuses_facet.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/statuses_facet.json
new file mode 100644 (file)
index 0000000..dce6f51
--- /dev/null
@@ -0,0 +1,21 @@
+{"total": 0, "p": 1, "ps": 100, "rules": [],
+"facets": [
+  {
+    "property": "statuses",
+    "values": [
+      {
+        "val": "BETA",
+        "count": 0
+      },{
+        "val": "DEPRECATED",
+        "count": 0
+      },{
+        "val": "READY",
+        "count": 0
+      },{
+        "val": "REMOVED",
+        "count": 0
+      }
+    ]
+  }
+]}