]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5899 Use tags in issues queries
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Tue, 9 Dec 2014 13:35:39 +0000 (14:35 +0100)
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Wed, 10 Dec 2014 08:21:16 +0000 (09:21 +0100)
server/sonar-server/src/main/java/org/sonar/server/issue/IssueQuery.java
server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java
server/sonar-server/src/main/java/org/sonar/server/issue/filter/IssueFilterParameters.java
server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java
server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueNormalizer.java
server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java
server/sonar-server/src/test/java/org/sonar/server/issue/IssueQueryServiceTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/IssueQueryTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java

index 16ec9fa653959c98f86f3a3d19357650520eeee7..4d831e6f9df783dbe70e273d30196bfa5b845de5 100644 (file)
@@ -65,6 +65,7 @@ public class IssueQuery {
   private final Collection<String> reporters;
   private final Collection<String> assignees;
   private final Collection<String> languages;
+  private final Collection<String> tags;
   private final Boolean assigned;
   private final Boolean planned;
   private final Boolean resolved;
@@ -89,6 +90,7 @@ public class IssueQuery {
     this.reporters = defaultCollection(builder.reporters);
     this.assignees = defaultCollection(builder.assignees);
     this.languages = defaultCollection(builder.languages);
+    this.tags = defaultCollection(builder.tags);
     this.assigned = builder.assigned;
     this.planned = builder.planned;
     this.resolved = builder.resolved;
@@ -149,6 +151,10 @@ public class IssueQuery {
     return languages;
   }
 
+  public Collection<String> tags() {
+    return tags;
+  }
+
   @CheckForNull
   public Boolean assigned() {
     return assigned;
@@ -224,6 +230,7 @@ public class IssueQuery {
     private Collection<String> reporters;
     private Collection<String> assignees;
     private Collection<String> languages;
+    private Collection<String> tags;
     private Boolean assigned = null;
     private Boolean planned = null;
     private Boolean resolved = null;
@@ -298,6 +305,11 @@ public class IssueQuery {
       return this;
     }
 
+    public Builder tags(@Nullable Collection<String> t) {
+      this.tags = t;
+      return this;
+    }
+
     /**
      * If true, it will return all issues assigned to someone
      * If false, it will return all issues not assigned to someone
index 88161e6ebc91ffd5242faece1aaebcd9f9b3fb66..f49a2798f3f8753378723809bd98e89fed6eacec 100644 (file)
@@ -69,6 +69,7 @@ public class IssueQueryService implements ServerComponent {
         .reporters(RubyUtils.toStrings(params.get(IssueFilterParameters.REPORTERS)))
         .assignees(RubyUtils.toStrings(params.get(IssueFilterParameters.ASSIGNEES)))
         .languages(RubyUtils.toStrings(params.get(IssueFilterParameters.LANGUAGES)))
+        .tags(RubyUtils.toStrings(params.get(IssueFilterParameters.TAGS)))
         .assigned(RubyUtils.toBoolean(params.get(IssueFilterParameters.ASSIGNED)))
         .planned(RubyUtils.toBoolean(params.get(IssueFilterParameters.PLANNED)))
         .hideRules(RubyUtils.toBoolean(params.get(IssueFilterParameters.HIDE_RULES)))
@@ -111,6 +112,7 @@ public class IssueQueryService implements ServerComponent {
         .reporters(request.paramAsStrings(IssueFilterParameters.REPORTERS))
         .assignees(request.paramAsStrings(IssueFilterParameters.ASSIGNEES))
         .languages(request.paramAsStrings(IssueFilterParameters.LANGUAGES))
+        .tags(request.paramAsStrings(IssueFilterParameters.TAGS))
         .assigned(request.paramAsBoolean(IssueFilterParameters.ASSIGNED))
         .planned(request.paramAsBoolean(IssueFilterParameters.PLANNED))
         .createdAt(request.paramAsDateTime(IssueFilterParameters.CREATED_AT))
index 4180c4fe537e8bfca5da817d4e7138c102bb33f3..8dbe5d1776cbe813a2b52885821886aaab18e391 100644 (file)
@@ -49,6 +49,7 @@ public class IssueFilterParameters {
   public static final String REPORTERS = "reporters";
   public static final String ASSIGNEES = "assignees";
   public static final String LANGUAGES = "languages";
+  public static final String TAGS = "tags";
   public static final String ASSIGNED = "assigned";
   public static final String PLANNED = "planned";
   public static final String HIDE_RULES = "hideRules";
@@ -61,7 +62,7 @@ public class IssueFilterParameters {
   public static final String ASC = "asc";
   public static final String IGNORE_PAGING = "ignorePaging";
 
-  public static final List<String> ALL = ImmutableList.of(ISSUES, SEVERITIES, STATUSES, RESOLUTIONS, RESOLVED, COMPONENTS, COMPONENT_ROOTS, RULES, ACTION_PLANS, REPORTERS,
+  public static final List<String> ALL = ImmutableList.of(ISSUES, SEVERITIES, STATUSES, RESOLUTIONS, RESOLVED, COMPONENTS, COMPONENT_ROOTS, RULES, ACTION_PLANS, REPORTERS, TAGS,
     ASSIGNEES, LANGUAGES, ASSIGNED, PLANNED, HIDE_RULES, CREATED_AT, CREATED_AFTER, CREATED_BEFORE, PAGE_SIZE, PAGE_INDEX, SORT, ASC, COMPONENT_UUIDS, COMPONENT_ROOT_UUIDS,
     PROJECTS, PROJECT_UUIDS, IGNORE_PAGING);
 
index f7e1c1c1900b7318c3c812134d46d75d2ea629b5..f951a4ee67c5e065f726368f66fb397ef79d3bed 100644 (file)
@@ -252,6 +252,7 @@ public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> {
     filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, matchFilter(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, query.componentUuids()));
     filters.put(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, matchFilter(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, query.projectUuids()));
     filters.put(IssueIndexDefinition.FIELD_ISSUE_LANGUAGE, matchFilter(IssueIndexDefinition.FIELD_ISSUE_LANGUAGE, query.languages()));
+    filters.put(IssueIndexDefinition.FIELD_ISSUE_TAGS, matchFilter(IssueIndexDefinition.FIELD_ISSUE_TAGS, query.tags()));
     filters.put(IssueIndexDefinition.FIELD_ISSUE_RESOLUTION, matchFilter(IssueIndexDefinition.FIELD_ISSUE_RESOLUTION, query.resolutions()));
     filters.put(IssueIndexDefinition.FIELD_ISSUE_REPORTER, matchFilter(IssueIndexDefinition.FIELD_ISSUE_REPORTER, query.reporters()));
     filters.put(IssueIndexDefinition.FIELD_ISSUE_RULE_KEY, matchFilter(IssueIndexDefinition.FIELD_ISSUE_RULE_KEY, query.rules()));
@@ -315,6 +316,8 @@ public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> {
         IssueFilterParameters.PROJECT_UUIDS, IssueNormalizer.IssueField.PROJECT.field(), query.projectUuids().toArray());
       addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch,
         IssueFilterParameters.LANGUAGES, IssueNormalizer.IssueField.LANGUAGE.field(), query.languages().toArray());
+      addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch,
+        IssueFilterParameters.TAGS, IssueNormalizer.IssueField.TAGS.field(), query.tags().toArray());
       addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch,
         IssueFilterParameters.RULES, IssueNormalizer.IssueField.RULE_KEY.field(), query.rules().toArray());
       addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch,
index 1a7e3dd6d0a42f4f3e3b59cecdd0d6c6ddf37981..e0d8e6d2ffd7c4b6ec5c3cab6ab9fb11db8aa837 100644 (file)
@@ -66,6 +66,7 @@ public class IssueNormalizer extends BaseNormalizer {
     public static final IndexField SEVERITY = add(IndexField.Type.STRING, "severity");
     public static final IndexField SEVERITY_VALUE = addSortable(IndexField.Type.INTEGER, "severityValue");
     public static final IndexField LANGUAGE = add(IndexField.Type.STRING, "language");
+    public static final IndexField TAGS = add(IndexField.Type.STRING, "tags");
     public static final IndexField RULE_KEY = add(IndexField.Type.STRING, "ruleKey");
     public static final IndexField FILE_PATH = addSortable(IndexField.Type.STRING, "filePath");
   }
index a637aadd4b6c3f730bbf54fc60ab6be1e52b8ffd..5be67c9b8d8d81a9d643d62719bfe357f4824c90 100644 (file)
@@ -64,7 +64,13 @@ import org.sonar.server.user.UserSession;
 import javax.annotation.CheckForNull;
 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.List;
+import java.util.Map;
+import java.util.Set;
 
 import static com.google.common.collect.Lists.newArrayList;
 import static com.google.common.collect.Maps.newHashMap;
@@ -167,6 +173,9 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> {
     action.createParam(IssueFilterParameters.RULES)
       .setDescription("Comma-separated list of coding rule keys. Format is <repository>:<rule>")
       .setExampleValue("squid:AvoidCycles");
+    action.createParam(IssueFilterParameters.TAGS)
+      .setDescription("Comma-separated list of tags.")
+      .setExampleValue("security,convention");
     action.createParam(IssueFilterParameters.HIDE_RULES)
       .setDescription("To not return rules")
       .setDefaultValue(false)
@@ -250,7 +259,8 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> {
       IssueFilterParameters.ASSIGNEES,
       IssueFilterParameters.REPORTERS,
       IssueFilterParameters.COMPONENT_UUIDS,
-      IssueFilterParameters.LANGUAGES
+      IssueFilterParameters.LANGUAGES,
+      IssueFilterParameters.TAGS,
     });
   }
 
@@ -373,6 +383,7 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> {
     addMandatoryFacetValues(results, IssueFilterParameters.REPORTERS, request.paramAsStrings(IssueFilterParameters.REPORTERS));
     addMandatoryFacetValues(results, IssueFilterParameters.RULES, request.paramAsStrings(IssueFilterParameters.RULES));
     addMandatoryFacetValues(results, IssueFilterParameters.LANGUAGES, request.paramAsStrings(IssueFilterParameters.LANGUAGES));
+    addMandatoryFacetValues(results, IssueFilterParameters.TAGS, request.paramAsStrings(IssueFilterParameters.TAGS));
     List<String> actionPlans = Lists.newArrayList("");
     List<String> actionPlansFromRequest = request.paramAsStrings(IssueFilterParameters.ACTION_PLANS);
     if (actionPlansFromRequest != null) {
@@ -512,6 +523,15 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> {
         .prop("fUpdateAge", formatAgeDate(updateDate))
         .prop("closeDate", isoDate(issue.closeDate()));
 
+      Collection<String> tags = ((IssueDoc) issue).tags();
+      if (tags != null && !tags.isEmpty()) {
+        json.name("tags").beginArray();
+        for (String tag: tags) {
+          json.value(tag);
+        }
+        json.endArray();
+      }
+
       writeIssueComments(commentsByIssues.get(issue.key()), usersByLogin, json);
       writeIssueAttributes(issue, json);
       writeIssueExtraFields(issue, project != null ? project.getKey() : null, usersByLogin, actionPlanByKeys, extraFields, json);
index 2a472eef843357c52fde8174f06bd16dd87cb2ea..5f13bb3ea6e06ff4722af1b2d3f63ea72e7e2ac6 100644 (file)
@@ -75,6 +75,7 @@ public class IssueQueryServiceTest {
     map.put("reporters", newArrayList("marilyn"));
     map.put("assignees", newArrayList("joanna"));
     map.put("languages", newArrayList("xoo"));
+    map.put("tags", newArrayList("tag1", "tag2"));
     map.put("assigned", true);
     map.put("planned", true);
     map.put("hideRules", true);
@@ -98,6 +99,7 @@ public class IssueQueryServiceTest {
     assertThat(query.reporters()).containsOnly("marilyn");
     assertThat(query.assignees()).containsOnly("joanna");
     assertThat(query.languages()).containsOnly("xoo");
+    assertThat(query.tags()).containsOnly("tag1", "tag2");
     assertThat(query.assigned()).isTrue();
     assertThat(query.planned()).isTrue();
     assertThat(query.hideRules()).isTrue();
index e06c6d3d4b77f9069baa75927bad1025532e6ccf..ff23362a5f726aa56da97420746ba290a9687438 100644 (file)
@@ -46,6 +46,7 @@ public class IssueQueryTest {
       .reporters(newArrayList("crunky"))
       .assignees(newArrayList("gargantua"))
       .languages(newArrayList("xoo"))
+      .tags(newArrayList("tag1", "tag2"))
       .assigned(true)
       .hideRules(true)
       .createdAfter(new Date())
@@ -65,6 +66,7 @@ public class IssueQueryTest {
     assertThat(query.reporters()).containsOnly("crunky");
     assertThat(query.assignees()).containsOnly("gargantua");
     assertThat(query.languages()).containsOnly("xoo");
+    assertThat(query.tags()).containsOnly("tag1", "tag2");
     assertThat(query.assigned()).isTrue();
     assertThat(query.hideRules()).isTrue();
     assertThat(query.rules()).containsOnly(RuleKey.of("squid", "AvoidCycle"));
@@ -118,6 +120,7 @@ public class IssueQueryTest {
       .rules(null)
       .severities(null)
       .languages(null)
+      .tags(null)
       .build();
     assertThat(query.issueKeys()).isEmpty();
     assertThat(query.componentUuids()).isEmpty();
@@ -130,6 +133,7 @@ public class IssueQueryTest {
     assertThat(query.rules()).isEmpty();
     assertThat(query.severities()).isEmpty();
     assertThat(query.languages()).isEmpty();
+    assertThat(query.tags()).isEmpty();
   }
 
   @Test
@@ -146,6 +150,7 @@ public class IssueQueryTest {
     assertThat(query.rules()).isEmpty();
     assertThat(query.severities()).isEmpty();
     assertThat(query.languages()).isEmpty();
+    assertThat(query.tags()).isEmpty();
     assertThat(query.assigned()).isNull();
     assertThat(query.createdAfter()).isNull();
     assertThat(query.createdBefore()).isNull();
index 5ea03bc325f1680265c2dd392f168d00e7ee6295..67efbf1325e12d8138de9f7ec4d055b097446fc6 100644 (file)
@@ -132,7 +132,7 @@ public class SearchActionMediumTest {
     assertThat(show.isPost()).isFalse();
     assertThat(show.isInternal()).isFalse();
     assertThat(show.responseExampleAsString()).isNotEmpty();
-    assertThat(show.params()).hasSize(31);
+    assertThat(show.params()).hasSize(32);
   }
 
   @Test