]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5007 - Added getAllProfileStats for QProfileService class
authorStephane Gamard <stephane.gamard@searchbox.com>
Fri, 13 Jun 2014 11:09:34 +0000 (13:09 +0200)
committerStephane Gamard <stephane.gamard@searchbox.com>
Fri, 13 Jun 2014 11:09:44 +0000 (13:09 +0200)
sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileService.java
sonar-server/src/main/java/org/sonar/server/qualityprofile/index/ActiveRuleIndex.java
sonar-server/src/main/java/org/sonar/server/qualityprofile/index/ActiveRuleNormalizer.java
sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java
sonar-server/src/main/java/org/sonar/server/search/FacetValue.java
sonar-server/src/test/java/org/sonar/server/qualityprofile/ActiveRuleBackendMediumTest.java
sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileServiceMediumTest.java
sonar-server/src/test/java/org/sonar/server/qualityprofile/RegisterQualityProfilesMediumTest.java

index a07ac3892592e4cbbd07ea5b8605d7fb5c52087c..278f345089eeb5769b7ea1e49f99af16c6dc5ac3 100644 (file)
@@ -19,6 +19,9 @@
  */
 package org.sonar.server.qualityprofile;
 
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Multimap;
 import org.sonar.api.ServerComponent;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.core.permission.GlobalPermissions;
@@ -30,6 +33,7 @@ import org.sonar.server.db.DbClient;
 import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
 import org.sonar.server.qualityprofile.index.ActiveRuleNormalizer;
 import org.sonar.server.rule.index.RuleQuery;
+import org.sonar.server.search.FacetValue;
 import org.sonar.server.search.IndexClient;
 import org.sonar.server.user.UserSession;
 
@@ -215,4 +219,20 @@ public class QProfileService implements ServerComponent {
     }
     return counts;
   }
+
+  public Multimap<QualityProfileKey, FacetValue> getAllProfileStats() {
+
+    List<QualityProfileKey> keys = Lists.newArrayList();
+    for (QualityProfileDto profile : this.findAll()) {
+      keys.add(profile.getKey());
+    }
+
+    Multimap<QualityProfileKey, FacetValue> stats = ArrayListMultimap.create();
+
+    Collection<FacetValue> profilesStats = index.get(ActiveRuleIndex.class).getStatsByProfileKey(keys);
+    for (FacetValue profileStat : profilesStats) {
+      stats.put(QualityProfileKey.parse(profileStat.getKey()), profileStat);
+    }
+    return stats;
+  }
 }
index 933cd4a7b6777615ba41bdc18d908e8947b7ca73..52c7f5a7ac855d5ebea818974e6776320e1cbc61 100644 (file)
 */
 package org.sonar.server.qualityprofile.index;
 
+import com.google.common.collect.Multimap;
 import org.elasticsearch.action.count.CountRequestBuilder;
 import org.elasticsearch.action.search.SearchRequestBuilder;
 import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.common.settings.ImmutableSettings;
 import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.index.query.FilterBuilders;
 import org.elasticsearch.index.query.QueryBuilders;
 import org.elasticsearch.search.SearchHit;
+import org.elasticsearch.search.aggregations.AggregationBuilders;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.core.cluster.WorkQueue;
 import org.sonar.core.profiling.Profiling;
@@ -54,11 +57,13 @@ import org.sonar.core.qualityprofile.db.QualityProfileKey;
 import org.sonar.server.qualityprofile.ActiveRule;
 import org.sonar.server.search.BaseIndex;
 import org.sonar.server.search.ESNode;
+import org.sonar.server.search.FacetValue;
 import org.sonar.server.search.IndexDefinition;
 import org.sonar.server.search.IndexField;
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -77,8 +82,8 @@ public class ActiveRuleIndex extends BaseIndex<ActiveRule, ActiveRuleDto, Active
   @Override
   protected Settings getIndexSettings() throws IOException {
     return ImmutableSettings.builder()
-      .put("index.number_of_replicas",0)
-      .put("index.number_of_shards",1)
+      .put("index.number_of_replicas", 0)
+      .put("index.number_of_shards", 1)
       .build();
   }
 
@@ -99,12 +104,12 @@ public class ActiveRuleIndex extends BaseIndex<ActiveRule, ActiveRuleDto, Active
   }
 
   @Override
-  protected Map mapDomain(){
+  protected Map mapDomain() {
     Map<String, Object> mapping = new HashMap<String, Object>();
     mapping.put("dynamic", false);
     mapping.put("_id", mapKey());
     mapping.put("_parent", mapParent());
-    mapping.put("_routing",mapRouting());
+    mapping.put("_routing", mapRouting());
     mapping.put("properties", mapProperties());
     return mapping;
   }
@@ -154,7 +159,7 @@ public class ActiveRuleIndex extends BaseIndex<ActiveRule, ActiveRuleDto, Active
     SearchRequestBuilder request = getClient().prepareSearch(getIndexName())
       .setQuery(QueryBuilders.termQuery(ActiveRuleNormalizer.ActiveRuleField.PROFILE_KEY.field(), key.toString()))
       .setRouting(key.toString())
-      // TODO replace by scrolling
+        // TODO replace by scrolling
       .setSize(Integer.MAX_VALUE);
     SearchResponse response = request.get();
 
@@ -177,21 +182,30 @@ public class ActiveRuleIndex extends BaseIndex<ActiveRule, ActiveRuleDto, Active
     return request.get().getCount();
   }
 
-  public Map getStatsByProfileKey(QualityProfileKey... keys) {
+
+  public Collection<FacetValue> getStatsByProfileKey(List<QualityProfileKey> keys) {
+
     // Get QProfiles keys as Strings
-    String[] stringKeys = new String[keys.length];
-    for(int i=0; i<keys.length; i++){
-      stringKeys[i]=keys[i].toString();
+    String[] stringKeys = new String[keys.size()];
+    for (int i = 0; i < keys.size(); i++) {
+      stringKeys[i] = keys.get(i).toString();
     }
 
-//    getClient().prepareSearch(this.getIndexName())
-//      .setQuery(QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(),
-//        FilterBuilders.termsFilter(ActiveRuleNormalizer.ActiveRuleField.PROFILE_KEY.field(), stringKeys)))
-//      .addAggregation(AggregationBuilders.terms("").)
-//      .setAggregations()
-//      .setRouting(key.toString());
-//    return request.get().getCount();
-
-    return null;
+    SearchResponse response = getClient().prepareSearch(this.getIndexName())
+      .setQuery(QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(),
+        FilterBuilders.termsFilter(ActiveRuleNormalizer.ActiveRuleField.PROFILE_KEY.field(), stringKeys)))
+      .addAggregation(AggregationBuilders.terms(ActiveRuleNormalizer.ActiveRuleField.PROFILE_KEY.field())
+        .field(ActiveRuleNormalizer.ActiveRuleField.PROFILE_KEY.field())
+        .subAggregation(AggregationBuilders.terms(ActiveRuleNormalizer.ActiveRuleField.INHERITANCE.field())
+          .field(ActiveRuleNormalizer.ActiveRuleField.INHERITANCE.field())
+          .subAggregation(AggregationBuilders.terms(ActiveRuleNormalizer.ActiveRuleField.SEVERITY.field())
+            .field(ActiveRuleNormalizer.ActiveRuleField.SEVERITY.field()))))
+      .setSize(0)
+      .setTypes(this.getIndexType())
+      .get();
+
+    Multimap<String, FacetValue> stats = this.processAggregations(response.getAggregations());
+
+    return stats.get(ActiveRuleNormalizer.ActiveRuleField.PROFILE_KEY.field());
   }
 }
index 58320729db2d9761a6b6a0441ba73d4a8a3c39c1..a5ddecd6ec6fd94c978785d650d224298223bd20 100644 (file)
@@ -29,6 +29,7 @@ import org.sonar.core.qualityprofile.db.ActiveRuleKey;
 import org.sonar.core.qualityprofile.db.ActiveRuleParamDto;
 import org.sonar.core.qualityprofile.db.QualityProfileDto;
 import org.sonar.server.db.DbClient;
+import org.sonar.server.qualityprofile.ActiveRule;
 import org.sonar.server.search.BaseNormalizer;
 import org.sonar.server.search.IndexDefinition;
 import org.sonar.server.search.IndexField;
@@ -123,7 +124,10 @@ public class ActiveRuleNormalizer extends BaseNormalizer<ActiveRuleDto, ActiveRu
     newRule.put("_parent", key.ruleKey().toString());
     newRule.put(ActiveRuleField.RULE_KEY.field(), key.ruleKey().toString());
     newRule.put(ActiveRuleField.KEY.field(), key.toString());
-    newRule.put(ActiveRuleField.INHERITANCE.field(), activeRuleDto.getInheritance());
+    newRule.put(ActiveRuleField.INHERITANCE.field(),
+      (activeRuleDto.getInheritance() != null) ?
+        activeRuleDto.getInheritance() :
+        ActiveRule.Inheritance.NONE.name());
     newRule.put(ActiveRuleField.SEVERITY.field(), activeRuleDto.getSeverityString());
 
     DbSession session = db.openSession(false);
index 40e420b52376145d4efe5f15b375c222ba4ced4f..112cef4dfa17323a5a564c12aed90cde3bce36be 100644 (file)
@@ -19,7 +19,9 @@
  */
 package org.sonar.server.search;
 
+import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Multimap;
 import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
 import org.elasticsearch.action.bulk.BulkRequestBuilder;
 import org.elasticsearch.action.get.GetResponse;
@@ -35,7 +37,9 @@ import org.elasticsearch.index.query.FilterBuilder;
 import org.elasticsearch.index.query.FilterBuilders;
 import org.elasticsearch.index.query.QueryBuilders;
 import org.elasticsearch.search.SearchHit;
+import org.elasticsearch.search.aggregations.Aggregation;
 import org.elasticsearch.search.aggregations.AggregationBuilders;
+import org.elasticsearch.search.aggregations.Aggregations;
 import org.elasticsearch.search.aggregations.bucket.terms.Terms;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -596,4 +600,19 @@ public abstract class BaseIndex<DOMAIN, DTO extends Dto<KEY>, KEY extends Serial
     }
     return counts;
   }
+
+  // Response helpers
+  protected Multimap<String, FacetValue> processAggregations(Aggregations aggregations) {
+    Multimap<String, FacetValue> stats = ArrayListMultimap.create();
+    if (aggregations != null) {
+      for (Aggregation aggregation : aggregations.asList()) {
+        for (Terms.Bucket value : ((Terms) aggregation).getBuckets()) {
+          FacetValue facetValue = new FacetValue(value.getKey(), (int) value.getDocCount());
+          facetValue.setSubFacets(processAggregations(value.getAggregations()));
+          stats.put(aggregation.getName(), facetValue);
+        }
+      }
+    }
+    return stats;
+  }
 }
index 8c39dbdba76ef36d21afd4426186b0a420ca8845..cffc5dc9fedec68d613b2957467f807d796b5ff3 100644 (file)
  */
 package org.sonar.server.search;
 
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
 import org.apache.commons.lang.builder.ReflectionToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
 
-public class FacetValue {
+public class FacetValue implements Comparable<FacetValue> {
 
-  String key;
-  Integer value;
+  public static enum Sort {
+    BY_KEY, BY_VALUE
+  }
+
+  private String key;
+  private Integer value;
+  private Sort sort;
+  private Multimap<String, FacetValue> subFacets;
 
   public FacetValue(String key, Integer value){
     this.key = key;
     this.value = value;
+    this.subFacets = ArrayListMultimap.create();
+    this.sort = Sort.BY_VALUE;
   }
 
   public String getKey() {
@@ -47,8 +58,25 @@ public class FacetValue {
     this.value = value;
   }
 
+  public Multimap<String, FacetValue> getSubFacets() {
+    return subFacets;
+  }
+
+  public void setSubFacets(Multimap<String, FacetValue> subFacets) {
+    this.subFacets = subFacets;
+  }
+
   @Override
   public String toString() {
-    return ReflectionToStringBuilder.toString(this);
+    return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE);
+  }
+
+  @Override
+  public int compareTo(FacetValue other) {
+    if (this.sort.equals(Sort.BY_KEY)) {
+      return this.getKey().compareTo(other.getKey());
+    } else {
+      return this.getValue().compareTo(other.getValue());
+    }
   }
 }
index 743cc2c3553d16a345814d3f2bd7d095cd9ae7b5..d50cd4443cb94f85def2a4887eed5708749717f5 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.server.qualityprofile;
 
+import com.google.common.collect.ImmutableList;
 import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Ignore;
@@ -38,6 +39,7 @@ import org.sonar.server.db.DbClient;
 import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
 import org.sonar.server.qualityprofile.index.ActiveRuleNormalizer;
 import org.sonar.server.rule.RuleTesting;
+import org.sonar.server.search.FacetValue;
 import org.sonar.server.tester.ServerTester;
 
 import java.util.Collection;
@@ -297,20 +299,30 @@ public class ActiveRuleBackendMediumTest {
     db.ruleDao().insert(dbSession, ruleDto1, ruleDto2);
 
     db.activeRuleDao().insert(dbSession,
-      ActiveRuleDto.createFor(profileDto1, ruleDto1).setSeverity(Severity.BLOCKER),
-      ActiveRuleDto.createFor(profileDto2, ruleDto1).setSeverity(Severity.MINOR),
-      ActiveRuleDto.createFor(profileDto1, ruleDto2).setSeverity(Severity.MAJOR),
-      ActiveRuleDto.createFor(profileDto2, ruleDto2).setSeverity(Severity.BLOCKER)
+      ActiveRuleDto.createFor(profileDto1, ruleDto1)
+        .setInheritance(ActiveRule.Inheritance.INHERITED.name())
+        .setSeverity(Severity.BLOCKER),
+      ActiveRuleDto.createFor(profileDto2, ruleDto1)
+        .setInheritance(ActiveRule.Inheritance.INHERITED.name())
+        .setSeverity(Severity.MINOR),
+      ActiveRuleDto.createFor(profileDto1, ruleDto2)
+        .setInheritance(ActiveRule.Inheritance.OVERRIDES.name())
+        .setSeverity(Severity.MAJOR),
+      ActiveRuleDto.createFor(profileDto2, ruleDto2)
+        .setInheritance(ActiveRule.Inheritance.INHERITED.name())
+        .setSeverity(Severity.BLOCKER)
       );
     dbSession.commit();
 
     // 0. Test base case
-    assertThat(index.countAll()).isEqualTo(2);
+    assertThat(index.countAll()).isEqualTo(4);
 
     // 1. Assert by term aggregation;
-    Map stats = index.getStatsByProfileKey(
-      profileDto1.getKey(),
-      profileDto2.getKey());
+    Collection<FacetValue> stats = index.getStatsByProfileKey(
+      ImmutableList.of(profileDto1.getKey(),
+        profileDto2.getKey()));
+
+    assertThat(stats).hasSize(2);
   }
 
 
index 0c80a7b6b90f71f39e31aae00b60a03af6a47e5f..b8003506c46eef859740d4a98489ef8e74bf1328 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.server.qualityprofile;
 
+import com.google.common.collect.Multimap;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.ClassRule;
@@ -33,6 +34,7 @@ import org.sonar.core.rule.RuleDto;
 import org.sonar.server.db.DbClient;
 import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
 import org.sonar.server.rule.RuleTesting;
+import org.sonar.server.search.FacetValue;
 import org.sonar.server.tester.ServerTester;
 import org.sonar.server.user.MockUserSession;
 
@@ -101,4 +103,21 @@ public class QProfileServiceMediumTest {
     assertThat(counts.values()).containsOnly(1L, 1L);
 
   }
+
+  @Test
+  public void stat_for_all_profiles() {
+    MockUserSession.set().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN).setLogin("me");
+
+    service.activate(new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_1, XOO_RULE_1))
+      .setSeverity("MINOR"));
+
+    service.activate(new RuleActivation(ActiveRuleKey.of(XOO_PROFILE_2, XOO_RULE_1))
+      .setSeverity("BLOCKER"));
+
+    dbSession.commit();
+
+    Multimap<QualityProfileKey, FacetValue> stats = service.getAllProfileStats();
+    assertThat(stats.size()).isEqualTo(2);
+    assertThat(stats.get(XOO_PROFILE_1).size()).isEqualTo(1);
+  }
 }
index 19a6bf124af82fcb46389a9dc8debfcf0f43fba3..b12da7722de9b25761d1a18579fd3edb665caeab 100644 (file)
@@ -43,8 +43,8 @@ import org.sonar.core.qualityprofile.db.QualityProfileKey;
 import org.sonar.core.template.LoadedTemplateDto;
 import org.sonar.server.db.DbClient;
 import org.sonar.server.platform.Platform;
-import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
 import org.sonar.server.qualityprofile.db.ActiveRuleDao;
+import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
 import org.sonar.server.tester.ServerTester;
 
 import java.util.Map;
@@ -109,6 +109,7 @@ public class RegisterQualityProfilesMediumTest {
     assertThat(params.get("acceptWhitespace").getValue()).isEqualTo("true");
     // default value
     assertThat(params.get("max").getValue()).isEqualTo("10");
+
   }
 
   @Test
@@ -138,7 +139,7 @@ public class RegisterQualityProfilesMediumTest {
 
     // Check ActiveRuleParameters in DB
     Map<String, ActiveRuleParamDto> params =
-      ActiveRuleParamDto.groupByKey(activeRuleDao.findParamsByActiveRuleKey(dbSession, activeRule.getKey()   ));
+      ActiveRuleParamDto.groupByKey(activeRuleDao.findParamsByActiveRuleKey(dbSession, activeRule.getKey()));
     assertThat(params).hasSize(2);
     // set by profile
     assertThat(params.get("acceptWhitespace").getValue()).isEqualTo("true");