From: Jean-Baptiste Lievremont Date: Tue, 13 Jan 2015 11:56:33 +0000 (+0100) Subject: SONAR-6019 Add statuses and severities facets X-Git-Tag: latest-silver-master-#65~231 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=fe82705588e450a34fb60897f1c733d8a55ba605;p=sonarqube.git SONAR-6019 Add statuses and severities facets --- diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java index 88dcf422eef..7b91182ccfc 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java @@ -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 { super.writeFacets(request, context, results, json); } - private void addMandatoryFacetValues(Result results, String facetName, @Nullable List mandatoryValues) { - Collection facetValues = results.getFacetValues(facetName); - if (facetValues != null) { - Map valuesByItem = Maps.newHashMap(); - for (FacetValue value : facetValues) { - valuesByItem.put(value.getKey(), value.getValue()); - } - List valuesToAdd = mandatoryValues == null ? Lists.newArrayList() : mandatoryValues; - for (String item : valuesToAdd) { - if (!valuesByItem.containsKey(item)) { - facetValues.add(new FacetValue(item, 0)); - } - } - } - } - private void collectFacetsData(Request request, Result result, Set projectUuids, Set componentUuids, List userLogins, Set actionPlanKeys) { collectFacetKeys(result, IssueFilterParameters.PROJECT_UUIDS, projectUuids); collectParameterValues(request, IssueFilterParameters.PROJECT_UUIDS, projectUuids); diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndex.java b/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndex.java index bdfca485496..dbf4dd85987 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndex.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndex.java @@ -19,7 +19,10 @@ */ 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 { 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 ALL_STATUSES = ImmutableList.copyOf(Collections2.transform(Arrays.asList(RuleStatus.values()), new Function() { + @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 { protected Map getFacets(RuleQuery query, QueryContext options, QueryBuilder queryBuilder, Map filters) { Map aggregations = new HashMap(); - 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 filters, + Map aggregations, StickyFacetBuilder stickyFacetBuilder) { + if (options.facets().contains(FACET_LANGUAGES) || options.facets().contains(FACET_OLD_DEFAULT)) { Collection 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 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 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 search(RuleQuery query, QueryContext options) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java index 6dd6f9890ac..fefdcab6fb5 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java @@ -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 { @CheckForNull protected Collection 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 { .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 { } 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); + } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/ws/SearchRequestHandler.java b/server/sonar-server/src/main/java/org/sonar/server/search/ws/SearchRequestHandler.java index e30bdcbc299..e5bec95f0e5 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/search/ws/SearchRequestHandler.java +++ b/server/sonar-server/src/main/java/org/sonar/server/search/ws/SearchRequestHandler.java @@ -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 implements RequestHandler { @@ -177,4 +181,20 @@ public abstract class SearchRequestHandler implements RequestHand } } + protected void addMandatoryFacetValues(Result results, String facetName, @Nullable List mandatoryValues) { + Collection facetValues = results.getFacetValues(facetName); + if (facetValues != null) { + Map valuesByItem = Maps.newHashMap(); + for (FacetValue value : facetValues) { + valuesByItem.put(value.getKey(), value.getValue()); + } + List valuesToAdd = mandatoryValues == null ? Lists.newArrayList() : mandatoryValues; + for (String item : valuesToAdd) { + if (!valuesByItem.containsKey(item)) { + facetValues.add(new FacetValue(item, 0)); + } + } + } + } + } diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWebServiceMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWebServiceMediumTest.java index 85ad9dd6488..bc4fab4772f 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWebServiceMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWebServiceMediumTest.java @@ -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 index 00000000000..f2d9754809b --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/severities_facet.json @@ -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 index 00000000000..dce6f519251 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/statuses_facet.json @@ -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 + } + ] + } +]}