From b45714bb50d0160edc3c791c05224cdf7f23db7e Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Lievremont Date: Mon, 19 Jan 2015 16:50:21 +0100 Subject: [PATCH] SONAR-6019 Apply feedback on stickyness of "characteristics" facet, hide "REMOVED" in status facet --- .../sonar/server/rule/index/RuleIndex.java | 60 ++++++++++++++----- .../sonar/server/rule/ws/SearchAction.java | 2 +- .../rule/ws/RulesWebServiceMediumTest.java | 39 +++++++++++- .../search_debt_rules_sticky.json | 37 ++++++++++++ .../statuses_facet.json | 3 - 5 files changed, 121 insertions(+), 20 deletions(-) create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/search_debt_rules_sticky.json 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 e623303fb8a..71a806c197f 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 @@ -22,6 +22,7 @@ package org.sonar.server.rule.index; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import org.apache.commons.collections.CollectionUtils; @@ -85,12 +86,22 @@ public class RuleIndex extends BaseIndex { 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 static final List ALL_STATUSES_EXCEPT_REMOVED = ImmutableList.copyOf( + Collections2.filter( + Collections2.transform( + Arrays.asList(RuleStatus.values()), + new Function() { + @Override + public String apply(RuleStatus input) { + return input.toString(); + } + }), + new Predicate() { + @Override + public boolean apply(String input) { + return !RuleStatus.REMOVED.toString().equals(input); + } + })); public RuleIndex(RuleNormalizer normalizer, SearchClient client) { super(IndexDefinition.RULE, normalizer, client); @@ -348,23 +359,45 @@ public class RuleIndex extends BaseIndex { 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())); - } + addStatusFacetIfNeeded(query, options, aggregations, stickyFacetBuilder); if (options.facets().contains(FACET_SEVERITIES)) { aggregations.put(FACET_SEVERITIES, stickyFacetBuilder.buildStickyFacet(RuleNormalizer.RuleField.SEVERITY.field(), FACET_SEVERITIES, Severity.ALL.toArray())); } + addCharacteristicsFacetIfNeeded(query, options, aggregations, stickyFacetBuilder); + + return aggregations; + + } + + private void addStatusFacetIfNeeded(RuleQuery query, QueryContext options, Map aggregations, StickyFacetBuilder stickyFacetBuilder) { + if (options.facets().contains(FACET_STATUSES)) { + Collection statusesFromQuery = query.getStatuses(); + Object[] selectedStatuses = statusesFromQuery == null ? new Object[0] : statusesFromQuery.toArray(); + + AggregationBuilder statuses = AggregationBuilders.filter(FACET_STATUSES + "__top") + .filter(stickyFacetBuilder.getStickyFacetFilter(RuleNormalizer.RuleField.STATUS.field()) + .mustNot(FilterBuilders.termFilter(RuleNormalizer.RuleField.STATUS.field(), RuleStatus.REMOVED.toString()))) + .subAggregation( + AggregationBuilders.terms(FACET_STATUSES + "__values").field(RuleNormalizer.RuleField.STATUS.field())) + .subAggregation( + AggregationBuilders.terms(FACET_STATUSES + "__selected").field(RuleNormalizer.RuleField.STATUS.field()) + .include(Joiner.on('|').join(selectedStatuses))); + + aggregations.put(FACET_STATUSES, statuses); + } + } + + private void addCharacteristicsFacetIfNeeded(RuleQuery query, QueryContext options, Map aggregations, StickyFacetBuilder stickyFacetBuilder) { if (options.facets().contains(FACET_DEBT_CHARACTERISTICS)) { int characsSize = 10; int subCharacsSize = 300; Collection characsFromQuery = query.getDebtCharacteristics(); Object[] selectedChars = characsFromQuery == null ? new Object[0] : characsFromQuery.toArray(); AggregationBuilder debtChar = AggregationBuilders.filter(FACET_DEBT_CHARACTERISTICS + "__chars") - .filter(stickyFacetBuilder.getStickyFacetFilter(RuleNormalizer.RuleField.CHARACTERISTIC.field())) + .filter(stickyFacetBuilder.getStickyFacetFilter("debtCharacteristics")) .subAggregation( AggregationBuilders.terms(FACET_DEBT_CHARACTERISTICS + "__chars_top").field(RuleNormalizer.RuleField.CHARACTERISTIC.field()) .size(characsSize)) @@ -373,7 +406,7 @@ public class RuleIndex extends BaseIndex { .include(Joiner.on('|').join(selectedChars)) .size(characsSize)); AggregationBuilder debtSubChar = AggregationBuilders.filter(FACET_DEBT_CHARACTERISTICS + "__subchars") - .filter(stickyFacetBuilder.getStickyFacetFilter(RuleNormalizer.RuleField.CHARACTERISTIC.field())) + .filter(stickyFacetBuilder.getStickyFacetFilter("debtCharacteristics")) .subAggregation( AggregationBuilders.terms(FACET_DEBT_CHARACTERISTICS + "__subchars_top").field(RuleNormalizer.RuleField.SUB_CHARACTERISTIC.field()) .size(subCharacsSize)) @@ -386,9 +419,6 @@ public class RuleIndex extends BaseIndex { .subAggregation(debtSubChar); aggregations.put(FACET_DEBT_CHARACTERISTICS, debtCharTopLevel); } - - return aggregations; - } protected void addDefaultFacets(RuleQuery query, QueryContext options, QueryBuilder queryBuilder, Map filters, 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 fefdcab6fb5..3adbc00b4b4 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 @@ -297,7 +297,7 @@ public class SearchAction extends SearchRequestHandler { @Override protected void writeFacets(Request request, QueryContext context, Result results, JsonWriter json) { - addMandatoryFacetValues(results, RuleIndex.FACET_STATUSES, RuleIndex.ALL_STATUSES); + addMandatoryFacetValues(results, RuleIndex.FACET_STATUSES, RuleIndex.ALL_STATUSES_EXCEPT_REMOVED); addMandatoryFacetValues(results, RuleIndex.FACET_SEVERITIES, Severity.ALL); super.writeFacets(request, context, results, json); } 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 4e6b9cbfde7..ba5a067b414 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 @@ -272,6 +272,43 @@ public class RulesWebServiceMediumTest { result.assertJson(this.getClass(), "search_debt_rules_with_default_linear_offset_and_overridden_linear_debt.json"); } + @Test + public void debt_characteristics_is_sticky_facet() throws Exception { + insertDebtCharacteristics(session); + + ruleDao.insert(session, RuleTesting.newXooX1() + .setDefaultSubCharacteristicId(hardReliabilityId) + .setDefaultRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) + .setDefaultRemediationCoefficient("1h") + .setDefaultRemediationOffset("15min") + + .setSubCharacteristicId(null) + .setRemediationFunction(null) + .setRemediationCoefficient(null) + .setRemediationOffset(null) + ); + ruleDao.insert(session, RuleTesting.newXooX2() + .setDefaultSubCharacteristicId(hardReliabilityId) + .setDefaultRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) + .setDefaultRemediationCoefficient("1h") + .setDefaultRemediationOffset("15min") + + .setSubCharacteristicId(softReliabilityId) + .setRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) + .setRemediationCoefficient("30min") + .setRemediationOffset("5min") + ); + session.commit(); + + MockUserSession.set(); + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); + request.setParam(SearchOptions.PARAM_FIELDS, "debtChar,debtCharName,debtSubChar,debtSubCharName,debtRemFn,debtOverloaded,defaultDebtChar,defaultDebtSubChar,defaultDebtRemFn"); + request.setParam("debt_characteristics", "SOFT_RELIABILITY"); + request.setParam(SearchAction.PARAM_FACETS, "debt_characteristics"); + WsTester.Result result = request.execute(); + result.assertJson(this.getClass(), "search_debt_rules_sticky.json"); + } + @Test public void search_template_rules() throws Exception { RuleDto templateRule = RuleTesting.newXooX1().setIsTemplate(true); @@ -463,7 +500,7 @@ public class RulesWebServiceMediumTest { } @Test - public void statuses_facet_should_have_all_statuses() throws Exception { + public void statuses_facet_should_have_all_statuses_except_removed() 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); diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/search_debt_rules_sticky.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/search_debt_rules_sticky.json new file mode 100644 index 00000000000..fdd626cfb0e --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/search_debt_rules_sticky.json @@ -0,0 +1,37 @@ +{"total": 1, "p": 1, "ps": 100, "rules": [ + { + "key": "xoo:x2", + "debtChar": "RELIABILITY", + "debtCharName": "Reliability", + "debtSubChar": "SOFT_RELIABILITY", + "debtSubCharName": "Soft Reliability", + "debtRemFnType": "LINEAR_OFFSET", + "debtRemFnCoeff": "30min", + "debtRemFnOffset": "5min", + "debtOverloaded": true, + "defaultDebtChar": "RELIABILITY", + "defaultDebtSubChar": "HARD_RELIABILITY", + "defaultDebtRemFnType": "LINEAR_OFFSET", + "defaultDebtRemFnCoeff": "1h", + "defaultDebtRemFnOffset": "15min" + } +], +"facets": [ + { + "property": "debt_characteristics", + "values": [ + { + "val": "RELIABILITY", + "count": 2 + }, + { + "val": "SOFT_RELIABILITY", + "count": 1 + }, + { + "val": "HARD_RELIABILITY", + "count": 1 + } + ] + } +]} 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 index dce6f519251..4692be87efe 100644 --- 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 @@ -12,9 +12,6 @@ },{ "val": "READY", "count": 0 - },{ - "val": "REMOVED", - "count": 0 } ] } -- 2.39.5