Skip to content

Commit

Permalink
SONAR-6153 Show rule tags in issue tag suggestions
Browse files Browse the repository at this point in the history
  • Loading branch information
jblievremont committed Feb 19, 2015
1 parent f84e084 commit 9dac52b
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 5 deletions.
Expand Up @@ -24,6 +24,7 @@
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.BooleanUtils;
import org.elasticsearch.action.search.SearchRequestBuilder; import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchResponse;
Expand All @@ -32,6 +33,8 @@
import org.elasticsearch.search.aggregations.AggregationBuilder; import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders; import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.filter.FilterAggregationBuilder; import org.elasticsearch.search.aggregations.bucket.filter.FilterAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.global.Global;
import org.elasticsearch.search.aggregations.bucket.global.GlobalBuilder;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogram; import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogram;
import org.elasticsearch.search.aggregations.bucket.missing.InternalMissing; import org.elasticsearch.search.aggregations.bucket.missing.InternalMissing;
import org.elasticsearch.search.aggregations.bucket.terms.Terms; import org.elasticsearch.search.aggregations.bucket.terms.Terms;
Expand All @@ -46,6 +49,8 @@
import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.issue.IssueQuery; import org.sonar.server.issue.IssueQuery;
import org.sonar.server.issue.filter.IssueFilterParameters; import org.sonar.server.issue.filter.IssueFilterParameters;
import org.sonar.server.rule.index.RuleNormalizer;
import org.sonar.server.search.IndexDefinition;
import org.sonar.server.search.StickyFacetBuilder; import org.sonar.server.search.StickyFacetBuilder;
import org.sonar.server.user.UserSession; import org.sonar.server.user.UserSession;
import org.sonar.server.view.index.ViewIndexDefinition; import org.sonar.server.view.index.ViewIndexDefinition;
Expand All @@ -64,6 +69,8 @@
*/ */
public class IssueIndex extends BaseIndex { public class IssueIndex extends BaseIndex {


private static final String SUBSTRING_MATCH_REGEXP = ".*%s.*";

public static final List<String> SUPPORTED_FACETS = ImmutableList.of( public static final List<String> SUPPORTED_FACETS = ImmutableList.of(
IssueFilterParameters.SEVERITIES, IssueFilterParameters.SEVERITIES,
IssueFilterParameters.STATUSES, IssueFilterParameters.STATUSES,
Expand Down Expand Up @@ -542,8 +549,39 @@ private FilterBuilder createTermsFilter(String field, Collection<?> values) {
} }


public List<String> listTags(IssueQuery query, @Nullable String textQuery, int maxNumberOfTags) { public List<String> listTags(IssueQuery query, @Nullable String textQuery, int maxNumberOfTags) {
Terms terms = listTermsMatching(IssueIndexDefinition.FIELD_ISSUE_TAGS, query, textQuery, Terms.Order.term(true), maxNumberOfTags); SearchRequestBuilder requestBuilder = getClient()
return EsUtils.termsKeys(terms); .prepareSearch(IssueIndexDefinition.INDEX, IndexDefinition.RULE.getIndexName())
.setTypes(IssueIndexDefinition.TYPE_ISSUE, IndexDefinition.RULE.getIndexType());

requestBuilder.setQuery(QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(),
createBoolFilter(query)));
GlobalBuilder topAggreg = AggregationBuilders.global("tags");
TermsBuilder issueTags = AggregationBuilders.terms("tags__issues")
.field(IssueIndexDefinition.FIELD_ISSUE_TAGS)
.size(maxNumberOfTags)
.order(Terms.Order.term(true))
.minDocCount(1L);
if (textQuery != null) {
issueTags.include(String.format(SUBSTRING_MATCH_REGEXP, textQuery));
}
TermsBuilder ruleTags = AggregationBuilders.terms("tags__rules")
.field(RuleNormalizer.RuleField.ALL_TAGS.field())
.size(maxNumberOfTags)
.order(Terms.Order.term(true))
.minDocCount(1L);
if (textQuery != null) {
ruleTags.include(String.format(SUBSTRING_MATCH_REGEXP, textQuery));
}

SearchResponse searchResponse = requestBuilder.addAggregation(topAggreg.subAggregation(issueTags).subAggregation(ruleTags)).get();
Global allTags = searchResponse.getAggregations().get("tags");
SortedSet<String> result = Sets.newTreeSet();
Terms issuesResult = allTags.getAggregations().get("tags__issues");
Terms rulesResult = allTags.getAggregations().get("tags__rules");
result.addAll(EsUtils.termsKeys(issuesResult));
result.addAll(EsUtils.termsKeys(rulesResult));
List<String> resultAsList = Lists.newArrayList(result);
return resultAsList.size() > maxNumberOfTags ? resultAsList.subList(0, maxNumberOfTags) : resultAsList;
} }


public Map<String, Long> countTags(IssueQuery query, int maxNumberOfTags) { public Map<String, Long> countTags(IssueQuery query, int maxNumberOfTags) {
Expand Down Expand Up @@ -572,7 +610,7 @@ private Terms listTermsMatching(String fieldName, IssueQuery query, @Nullable St
.order(termsOrder) .order(termsOrder)
.minDocCount(1L); .minDocCount(1L);
if (textQuery != null) { if (textQuery != null) {
aggreg.include(String.format(".*%s.*", textQuery)); aggreg.include(String.format(SUBSTRING_MATCH_REGEXP, textQuery));
} }


SearchResponse searchResponse = requestBuilder.addAggregation(aggreg).get(); SearchResponse searchResponse = requestBuilder.addAggregation(aggreg).get();
Expand Down
Expand Up @@ -532,11 +532,12 @@ public void list_tags() {
saveIssue(IssueTesting.newDto(rule, file, project)); saveIssue(IssueTesting.newDto(rule, file, project));
saveIssue(IssueTesting.newDto(rule, file, project).setTags(ImmutableSet.of("convention"))); saveIssue(IssueTesting.newDto(rule, file, project).setTags(ImmutableSet.of("convention")));


assertThat(service.listTags(null, 5)).containsOnly("convention", "java8", "bug"); assertThat(service.listTags(null, 5)).containsOnly("convention", "java8", "bug" /* from issues */, "systag1", "systag2" /* from rules */);
assertThat(service.listTags(null, 2)).containsOnly("bug", "convention"); assertThat(service.listTags(null, 2)).containsOnly("bug", "convention");
assertThat(service.listTags("vent", 5)).containsOnly("convention"); assertThat(service.listTags("vent", 5)).containsOnly("convention");
assertThat(service.listTags("sys", 5)).containsOnly("systag1", "systag2");
assertThat(service.listTags(null, 1)).containsOnly("bug"); assertThat(service.listTags(null, 1)).containsOnly("bug");
assertThat(service.listTags(null, Integer.MAX_VALUE)).containsOnly("convention", "java8", "bug"); assertThat(service.listTags(null, Integer.MAX_VALUE)).containsOnly("convention", "java8", "bug", "systag1", "systag2", "tag1", "tag2");
} }


@Test @Test
Expand Down

0 comments on commit 9dac52b

Please sign in to comment.