From: Jean-Baptiste Lievremont Date: Thu, 16 Apr 2015 12:09:18 +0000 (+0200) Subject: SONAR-6406 Add active severity facet on rules WS X-Git-Tag: 5.2-RC1~2244 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=b4f20bd7aeb78fceac074f38a2f74db33e6ee6b9;p=sonarqube.git SONAR-6406 Add active severity facet on rules WS --- 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 483d6b2c55e..2eaa52be492 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 @@ -66,6 +66,7 @@ public class RuleIndex extends BaseIndex { 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_ACTIVE_SEVERITIES = "active_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"; @@ -361,6 +362,8 @@ public class RuleIndex extends BaseIndex { stickyFacetBuilder.buildStickyFacet(RuleNormalizer.RuleField.SEVERITY.field(), FACET_SEVERITIES, Severity.ALL.toArray())); } + addActiveSeverityFacetIfNeeded(query, options, aggregations, stickyFacetBuilder); + addCharacteristicsFacetIfNeeded(query, options, aggregations, stickyFacetBuilder); return aggregations; @@ -384,6 +387,41 @@ public class RuleIndex extends BaseIndex { } } + private void addActiveSeverityFacetIfNeeded(RuleQuery query, QueryContext options, Map aggregations, StickyFacetBuilder stickyFacetBuilder) { + if (options.facets().contains(FACET_ACTIVE_SEVERITIES)) { + // We are building a children aggregation on active rules + // so the rule filter has to be used as parent filter for active rules + // from which we remove filters that concern active rules ("activation") + HasParentFilterBuilder ruleFilter = FilterBuilders.hasParentFilter( + IndexDefinition.RULE.getIndexType(), + stickyFacetBuilder.getStickyFacetFilter("activation")); + + // Rebuilding the active rule filter without severities + BoolFilterBuilder childrenFilter = FilterBuilders.boolFilter(); + this.addTermFilter(childrenFilter, ActiveRuleNormalizer.ActiveRuleField.PROFILE_KEY.field(), query.getQProfileKey()); + this.addTermFilter(childrenFilter, ActiveRuleNormalizer.ActiveRuleField.INHERITANCE.field(), query.getInheritance()); + FilterBuilder activeRuleFilter; + if (childrenFilter.hasClauses()) { + activeRuleFilter = childrenFilter.must(ruleFilter); + } else { + activeRuleFilter = ruleFilter; + } + + AggregationBuilder activeSeverities = AggregationBuilders.children(FACET_ACTIVE_SEVERITIES + "_children") + .childType(IndexDefinition.ACTIVE_RULE.getIndexType()) + .subAggregation(AggregationBuilders.filter(FACET_ACTIVE_SEVERITIES + "_filter") + .filter(activeRuleFilter) + .subAggregation( + AggregationBuilders + .terms(FACET_ACTIVE_SEVERITIES) + .field(ActiveRuleNormalizer.ActiveRuleField.SEVERITY.field()) + .include(Joiner.on('|').join(Severity.ALL)) + .size(Severity.ALL.size()))); + + aggregations.put(FACET_ACTIVE_SEVERITIES, AggregationBuilders.global(FACET_ACTIVE_SEVERITIES).subAggregation(activeSeverities)); + } + } + private void addCharacteristicsFacetIfNeeded(RuleQuery query, QueryContext options, Map aggregations, StickyFacetBuilder stickyFacetBuilder) { if (options.facets().contains(FACET_DEBT_CHARACTERISTICS)) { 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 66bbea4f747..7fa9841aad6 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 @@ -105,6 +105,7 @@ public class SearchAction extends SearchRequestHandler implemen RuleIndex.FACET_TAGS, RuleIndex.FACET_DEBT_CHARACTERISTICS, RuleIndex.FACET_SEVERITIES, + RuleIndex.FACET_ACTIVE_SEVERITIES, RuleIndex.FACET_STATUSES, RuleIndex.FACET_OLD_DEFAULT }); @@ -311,11 +312,12 @@ public class SearchAction extends SearchRequestHandler implemen @Override protected void writeFacets(Request request, QueryContext context, Result results, JsonWriter json) { - addMandatoryFacetValues(results, RuleIndex.FACET_DEBT_CHARACTERISTICS, request.paramAsStrings(PARAM_SEVERITIES)); + addMandatoryFacetValues(results, RuleIndex.FACET_DEBT_CHARACTERISTICS, request.paramAsStrings(PARAM_DEBT_CHARACTERISTICS)); addMandatoryFacetValues(results, RuleIndex.FACET_LANGUAGES, request.paramAsStrings(PARAM_LANGUAGES)); addMandatoryFacetValues(results, RuleIndex.FACET_REPOSITORIES, request.paramAsStrings(PARAM_REPOSITORIES)); addMandatoryFacetValues(results, RuleIndex.FACET_STATUSES, RuleIndex.ALL_STATUSES_EXCEPT_REMOVED); addMandatoryFacetValues(results, RuleIndex.FACET_SEVERITIES, Severity.ALL); + addMandatoryFacetValues(results, RuleIndex.FACET_ACTIVE_SEVERITIES, Severity.ALL); addMandatoryFacetValues(results, RuleIndex.FACET_TAGS, request.paramAsStrings(PARAM_TAGS)); mergeNoneAndEmptyBucketOnCharacteristics(results); diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexMediumTest.java index 10f7dfba5da..75d3fed430f 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexMediumTest.java @@ -52,7 +52,15 @@ import org.sonar.server.tester.ServerTester; import javax.annotation.Nullable; -import java.util.*; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; import static com.google.common.collect.Lists.newArrayList; import static org.assertj.core.api.Assertions.assertThat; @@ -826,6 +834,45 @@ public class RuleIndexMediumTest { assertThat(result.getHits()).hasSize(3); } + @Test + public void search_by_profile_and_active_severity() throws InterruptedException { + QualityProfileDto qualityProfileDto1 = QProfileTesting.newXooP1(); + QualityProfileDto qualityProfileDto2 = QProfileTesting.newXooP2(); + db.qualityProfileDao().insert(dbSession, qualityProfileDto1, qualityProfileDto2); + + RuleDto rule1 = RuleTesting.newXooX1().setSeverity("MAJOR"); + RuleDto rule2 = RuleTesting.newXooX2().setSeverity("MINOR"); + RuleDto rule3 = RuleTesting.newXooX3().setSeverity("INFO"); + dao.insert(dbSession, rule1, rule2, rule3); + + db.activeRuleDao().insert( + dbSession, + ActiveRuleDto.createFor(qualityProfileDto1, rule1).setSeverity("BLOCKER"), + ActiveRuleDto.createFor(qualityProfileDto2, rule1).setSeverity("BLOCKER"), + ActiveRuleDto.createFor(qualityProfileDto1, rule2).setSeverity("CRITICAL")); + dbSession.commit(); + dbSession.clearCache(); + + // 1. get all active rules. + Result result = index.search(new RuleQuery().setActivation(true).setQProfileKey(qualityProfileDto1.getKey()), + new QueryContext()); + assertThat(result.getHits()).hasSize(2); + + // 2. get rules with active severity critical. + result = index.search(new RuleQuery().setActivation(true).setQProfileKey(qualityProfileDto1.getKey()).setActiveSeverities(Arrays.asList("CRITICAL")), + new QueryContext().addFacets(Arrays.asList(RuleIndex.FACET_ACTIVE_SEVERITIES))); + assertThat(result.getHits()).hasSize(1); + assertThat(result.getHits().get(0).name()).isEqualTo(rule2.getName()); + // check stickyness of active severity facet + assertThat(result.getFacetValues(RuleIndex.FACET_ACTIVE_SEVERITIES)).containsOnly(new FacetValue("BLOCKER", 1), new FacetValue("CRITICAL", 1)); + + // 3. count activation severities of all active rules + result = index.search(new RuleQuery(), + new QueryContext().addFacets(Arrays.asList(RuleIndex.FACET_ACTIVE_SEVERITIES))); + assertThat(result.getHits()).hasSize(3); + assertThat(result.getFacetValues(RuleIndex.FACET_ACTIVE_SEVERITIES)).containsOnly(new FacetValue("BLOCKER", 2), new FacetValue("CRITICAL", 1)); + } + @Test public void complex_param_value() throws InterruptedException { String value = "//expression[primary/qualifiedIdentifier[count(IDENTIFIER) = 2]/IDENTIFIER[2]/@tokenValue = 'firstOf' and primary/identifierSuffix/arguments/expression[not(primary) or primary[not(qualifiedIdentifier) or identifierSuffix]]]"; @@ -1074,7 +1121,6 @@ public class RuleIndexMediumTest { @Test public void sticky_facets() { - Integer numberOfSystemTags = 2; dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("xoo", "S001")).setLanguage("java").setTags(ImmutableSet.of()), RuleTesting.newDto(RuleKey.of("xoo", "S002")).setLanguage("java").setTags(ImmutableSet.of()),