]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6406 Add active severity facet on rules WS
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Thu, 16 Apr 2015 12:09:18 +0000 (14:09 +0200)
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Thu, 16 Apr 2015 15:59:50 +0000 (17:59 +0200)
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/test/java/org/sonar/server/rule/index/RuleIndexMediumTest.java

index 483d6b2c55eb5d002559a004eb6b737bd88c6739..2eaa52be4927fe22ef14dd73125255a2c657627f 100644 (file)
@@ -66,6 +66,7 @@ public class RuleIndex extends BaseIndex<Rule, RuleDto, RuleKey> {
   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<Rule, RuleDto, RuleKey> {
         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<Rule, RuleDto, RuleKey> {
     }
   }
 
+  private void addActiveSeverityFacetIfNeeded(RuleQuery query, QueryContext options, Map<String, AggregationBuilder> 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<String, AggregationBuilder> aggregations, StickyFacetBuilder stickyFacetBuilder) {
 
     if (options.facets().contains(FACET_DEBT_CHARACTERISTICS)) {
index 66bbea4f7478fc58854b19fc5dd4c4bab70b3290..7fa9841aad6c63cb520d58d50c63ccd676339cc5 100644 (file)
@@ -105,6 +105,7 @@ public class SearchAction extends SearchRequestHandler<RuleQuery, Rule> 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<RuleQuery, Rule> 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);
index 10f7dfba5da794a04b0ad2b79db74957c4e60cec..75d3fed430fd29b56bc62a00576dcc7f8ee81bd8 100644 (file)
@@ -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<Rule> 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.<String>of()),
       RuleTesting.newDto(RuleKey.of("xoo", "S002")).setLanguage("java").setTags(ImmutableSet.<String>of()),