]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5953 Fall back to backwards compatible API for issues search WS (components... latest-silver-master-#65
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Fri, 30 Jan 2015 10:12:28 +0000 (11:12 +0100)
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Fri, 30 Jan 2015 15:58:35 +0000 (16:58 +0100)
server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java
server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.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

index a1881f884489add6004a3cb72a0ba02ff144dff3..1472b728a55ff63b62f7393f9c302a272c1d1ef1 100644 (file)
@@ -28,6 +28,7 @@ import com.google.common.base.Strings;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
+import org.apache.commons.lang.BooleanUtils;
 import org.apache.commons.lang.ObjectUtils;
 import org.sonar.api.ServerComponent;
 import org.sonar.api.resources.Qualifiers;
@@ -81,7 +82,6 @@ public class IssueQueryService implements ServerComponent {
         .assignees(RubyUtils.toStrings(params.get(IssueFilterParameters.ASSIGNEES)))
         .languages(RubyUtils.toStrings(params.get(IssueFilterParameters.LANGUAGES)))
         .tags(RubyUtils.toStrings(params.get(IssueFilterParameters.TAGS)))
-        .onComponentOnly(RubyUtils.toBoolean(params.get(IssueFilterParameters.ON_COMPONENT_ONLY)))
         .assigned(RubyUtils.toBoolean(params.get(IssueFilterParameters.ASSIGNED)))
         .planned(RubyUtils.toBoolean(params.get(IssueFilterParameters.PLANNED)))
         .hideRules(RubyUtils.toBoolean(params.get(IssueFilterParameters.HIDE_RULES)))
@@ -89,14 +89,11 @@ public class IssueQueryService implements ServerComponent {
         .createdAfter(RubyUtils.toDate(params.get(IssueFilterParameters.CREATED_AFTER)))
         .createdBefore(RubyUtils.toDate(params.get(IssueFilterParameters.CREATED_BEFORE)));
 
-      addComponentUuids(builder, session,
+      addComponentParameters(builder, session,
+        RubyUtils.toBoolean(params.get(IssueFilterParameters.ON_COMPONENT_ONLY)),
+        RubyUtils.toStrings(params.get(IssueFilterParameters.COMPONENTS)),
         RubyUtils.toStrings(params.get(IssueFilterParameters.COMPONENT_UUIDS)),
-        RubyUtils.toStrings(
-          ObjectUtils.defaultIfNull(
-            params.get(IssueFilterParameters.COMPONENT_KEYS),
-            params.get(IssueFilterParameters.COMPONENTS)
-            )
-          ),
+        RubyUtils.toStrings(params.get(IssueFilterParameters.COMPONENT_KEYS)),
         RubyUtils.toStrings(params.get(IssueFilterParameters.COMPONENT_ROOT_UUIDS)),
         RubyUtils.toStrings(params.get(IssueFilterParameters.COMPONENT_ROOTS)),
         RubyUtils.toStrings(params.get(IssueFilterParameters.PROJECT_UUIDS)),
@@ -141,7 +138,6 @@ public class IssueQueryService implements ServerComponent {
         .assignees(request.paramAsStrings(IssueFilterParameters.ASSIGNEES))
         .languages(request.paramAsStrings(IssueFilterParameters.LANGUAGES))
         .tags(request.paramAsStrings(IssueFilterParameters.TAGS))
-        .onComponentOnly(request.paramAsBoolean(IssueFilterParameters.ON_COMPONENT_ONLY))
         .assigned(request.paramAsBoolean(IssueFilterParameters.ASSIGNED))
         .planned(request.paramAsBoolean(IssueFilterParameters.PLANNED))
         .createdAt(request.paramAsDateTime(IssueFilterParameters.CREATED_AT))
@@ -149,9 +145,13 @@ public class IssueQueryService implements ServerComponent {
         .createdBefore(request.paramAsDateTime(IssueFilterParameters.CREATED_BEFORE))
         .ignorePaging(request.paramAsBoolean(IssueFilterParameters.IGNORE_PAGING));
 
-      addComponentUuids(builder, session,
-        request.paramAsStrings(IssueFilterParameters.COMPONENT_UUIDS), request.paramAsStrings(IssueFilterParameters.COMPONENT_KEYS),
-        request.paramAsStrings(IssueFilterParameters.COMPONENT_ROOT_UUIDS), request.paramAsStrings(IssueFilterParameters.COMPONENT_ROOTS),
+      addComponentParameters(builder, session,
+        request.paramAsBoolean(IssueFilterParameters.ON_COMPONENT_ONLY),
+        request.paramAsStrings(IssueFilterParameters.COMPONENTS),
+        request.paramAsStrings(IssueFilterParameters.COMPONENT_UUIDS),
+        request.paramAsStrings(IssueFilterParameters.COMPONENT_KEYS),
+        request.paramAsStrings(IssueFilterParameters.COMPONENT_ROOT_UUIDS),
+        request.paramAsStrings(IssueFilterParameters.COMPONENT_ROOTS),
         request.paramAsStrings(IssueFilterParameters.PROJECT_UUIDS), request.paramAsStrings(IssueFilterParameters.PROJECT_KEYS),
         request.paramAsStrings(IssueFilterParameters.MODULE_UUIDS),
         request.paramAsStrings(IssueFilterParameters.DIRECTORIES),
@@ -169,38 +169,44 @@ public class IssueQueryService implements ServerComponent {
     }
   }
 
-  private void addComponentUuids(IssueQuery.Builder builder, DbSession session,
-    @Nullable Collection<String> componentUuids, @Nullable Collection<String> components,
+  private void addComponentParameters(IssueQuery.Builder builder, DbSession session,
+    @Nullable Boolean onComponentOnly,
+    @Nullable Collection<String> components,
+    @Nullable Collection<String> componentUuids,
+    @Nullable Collection<String> componentKeys,
     /*
      * Since 5.1, search of issues is recursive by default (module + submodules),
      * but "componentKeys" parameter already deprecates "components" parameter,
      * so queries specifying "componentRoots" must be handled manually
      */
-    @Nullable Collection<String> componentRootUuids, @Nullable Collection<String> componentRoots,
+    @Nullable Collection<String> componentRootUuids,
+    @Nullable Collection<String> componentRoots,
     @Nullable Collection<String> projectUuids, @Nullable Collection<String> projects,
     @Nullable Collection<String> moduleUuids,
     @Nullable Collection<String> directories,
     @Nullable Collection<String> fileUuids) {
 
     Set<String> allComponentUuids = Sets.newHashSet();
+    boolean effectiveOnComponentOnly = mergeComponentParameters(session, onComponentOnly,
+      components,
+      componentUuids,
+      componentKeys,
+      componentRootUuids,
+      componentRoots,
+      allComponentUuids);
 
-    if (componentUuids != null || componentRootUuids != null) {
-      if (components != null || componentRoots != null) {
-        throw new IllegalArgumentException("components and componentUuids cannot be set simultaneously");
-      }
-      allComponentUuids.addAll((Collection<String>) ObjectUtils.defaultIfNull(componentUuids, Sets.newHashSet()));
-      allComponentUuids.addAll((Collection<String>) ObjectUtils.defaultIfNull(componentRootUuids, Sets.newHashSet()));
-    } else {
-      Set<String> allComponents = Sets.newHashSet();
-      allComponents.addAll((Collection<String>) ObjectUtils.defaultIfNull(components, Sets.newHashSet()));
-      allComponents.addAll((Collection<String>) ObjectUtils.defaultIfNull(componentRoots, Sets.newHashSet()));
-      allComponentUuids.addAll(componentUuids(session, allComponents));
-    }
+    builder.onComponentOnly(effectiveOnComponentOnly);
 
     if (allComponentUuids.isEmpty()) {
       builder.setContextualized(false);
       addComponentsBelowView(builder, session, projects, projectUuids, moduleUuids, directories, fileUuids);
     } else {
+      if (effectiveOnComponentOnly) {
+        builder.setContextualized(false);
+        builder.componentUuids(allComponentUuids);
+        return;
+      }
+
       builder.setContextualized(true);
 
       Set<String> qualifiers = componentService.getDistinctQualifiers(session, allComponentUuids);
@@ -244,6 +250,43 @@ public class IssueQueryService implements ServerComponent {
     }
   }
 
+  private boolean mergeComponentParameters(DbSession session, Boolean onComponentOnly,
+    Collection<String> components,
+    Collection<String> componentUuids,
+    Collection<String> componentKeys,
+    Collection<String> componentRootUuids,
+    Collection<String> componentRoots,
+    Set<String> allComponentUuids) {
+    boolean effectiveOnComponentOnly = false;
+
+    if (componentRootUuids != null) {
+      if (componentRoots != null) {
+        throw new IllegalArgumentException("componentRoots and componentRootUuids cannot be set simultaneously");
+      }
+      allComponentUuids.addAll(componentRootUuids);
+      effectiveOnComponentOnly = false;
+    } else if (componentRoots != null) {
+      allComponentUuids.addAll(componentUuids(session, componentRoots));
+      effectiveOnComponentOnly = false;
+    } else if (components != null) {
+      if (componentUuids != null) {
+        throw new IllegalArgumentException("components and componentUuids cannot be set simultaneously");
+      }
+      allComponentUuids.addAll(componentUuids(session, components));
+      effectiveOnComponentOnly = true;
+    } else if (componentUuids != null) {
+      if (componentKeys != null) {
+        throw new IllegalArgumentException("componentUuids and componentKeys cannot be set simultaneously");
+      }
+      allComponentUuids.addAll(componentUuids);
+      effectiveOnComponentOnly = BooleanUtils.isTrue(onComponentOnly);
+    } else if (componentKeys != null) {
+      allComponentUuids.addAll(componentUuids(session, componentKeys));
+      effectiveOnComponentOnly = BooleanUtils.isTrue(onComponentOnly);
+    }
+    return effectiveOnComponentOnly;
+  }
+
   private void addComponentsBelowView(Builder builder, DbSession session,
     @Nullable Collection<String> projects, @Nullable Collection<String> projectUuids,
     @Nullable Collection<String> moduleUuids, Collection<String> directories, Collection<String> fileUuids) {
index 42414efe6dbe669773b1e363b7a385ca6a2b41e3..688cc6b5ebbc4199fc04eb217994928ab1e884b8 100644 (file)
@@ -289,10 +289,14 @@ public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> {
         filters.put(FILTER_COMPONENT_ROOT, componentFilter);
       }
     } else {
+      if (query.onComponentOnly()) {
+        filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, componentFilter);
+      } else {
+        filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, fileFilter);
+      }
       filters.put(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, projectFilter);
       filters.put(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, moduleFilter);
       filters.put(IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, directoryFilter);
-      filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, fileFilter);
       filters.put("view", viewFilter);
     }
   }
index 16331c7d8a23599a3914197fec83ac263ffb38cb..dbf72d30a718773fe15a4e0321a15224845023e7 100644 (file)
@@ -196,21 +196,34 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> {
   }
 
   private void addComponentRelatedParams(WebService.NewAction action) {
+
+    action.createParam(IssueFilterParameters.ON_COMPONENT_ONLY)
+      .setDescription("Return only issues at a component's level, not on its descendants (modules, directories, files, etc). " +
+        "This parameter is only considered when componentKeys or componentUuids is set. " +
+        "Using the deprecated componentRoots or componentRootUuids parameters will set this parameter to false. " +
+        "Using the deprecated components parameter will set this parameter to true.")
+      .setBooleanPossibleValues()
+      .setDefaultValue("false");
+
     action.createParam(IssueFilterParameters.COMPONENT_KEYS)
-      .setDescription("To retrieve issues associated to a specific list of components and their sub-components (comma-separated list of component keys). " +
-        "A component can be a project, module, directory or file. " +
+      .setDescription("To retrieve issues associated to a specific list of components sub-components (comma-separated list of component keys). " +
+        "A component can be a view, developer, project, module, directory or file. " +
         "If this parameter is set, componentUuids must not be set.")
-      .setDeprecatedKey(IssueFilterParameters.COMPONENTS)
       .setExampleValue("org.apache.struts:struts:org.apache.struts.Action");
     action.createParam(IssueFilterParameters.COMPONENTS)
-      .setDescription("Deprecated since 5.1. See componentKeys.");
+      .setDescription("Deprecated since 5.1. If used, will have the same meaning as componentKeys AND onComponentOnly=true.");
     action.createParam(IssueFilterParameters.COMPONENT_UUIDS)
-      .setDescription("To retrieve issues associated to a specific list of components and their sub-components (comma-separated list of component UUIDs). " +
+      .setDescription("To retrieve issues associated to a specific list of components their sub-components (comma-separated list of component UUIDs). " +
         INTERNAL_PARAMETER_DISCLAIMER +
         "A component can be a project, module, directory or file. " +
         "If this parameter is set, componentKeys must not be set.")
       .setExampleValue("584a89f2-8037-4f7b-b82c-8b45d2d63fb2");
 
+    action.createParam(IssueFilterParameters.COMPONENT_ROOTS)
+      .setDescription("Deprecated since 5.1. If used, will have the same meaning as componentKeys AND onComponentOnly=false.");
+    action.createParam(IssueFilterParameters.COMPONENT_ROOT_UUIDS)
+      .setDescription("Deprecated since 5.1. If used, will have the same meaning as componentUuids AND onComponentOnly=false.");
+
     action.createParam(IssueFilterParameters.PROJECTS)
       .setDescription("Deprecated since 5.1. See projectKeys");
     action.createParam(IssueFilterParameters.PROJECT_KEYS)
@@ -225,10 +238,6 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> {
         "Views are not supported. If this parameter is set, projectKeys must not be set.")
       .setExampleValue("7d8749e8-3070-4903-9188-bdd82933bb92");
 
-    action.createParam(IssueFilterParameters.COMPONENT_ROOTS)
-      .setDescription("Deprecated since 5.1. Use componentKeys instead, with onComponentOnly=false.");
-    action.createParam(IssueFilterParameters.COMPONENT_ROOT_UUIDS)
-      .setDescription("Deprecated since 5.1. Use componentUuids instead, with onComponentOnly=false.");
     action.createParam(IssueFilterParameters.MODULE_UUIDS)
       .setDescription("To retrieve issues associated to a specific list of modules (comma-separated list of module UUIDs). " +
         INTERNAL_PARAMETER_DISCLAIMER +
@@ -245,11 +254,6 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> {
       .setDescription("To retrieve issues associated to a specific list of files (comma-separated list of file UUIDs). " +
         INTERNAL_PARAMETER_DISCLAIMER)
       .setExampleValue("bdd82933-3070-4903-9188-7d8749e8bb92");
-
-    action.createParam(IssueFilterParameters.ON_COMPONENT_ONLY)
-      .setDescription("Return only issues at the component's level, not on its descendants (modules, directories, files, etc.)")
-      .setBooleanPossibleValues()
-      .setDefaultValue("false");
   }
 
   @Override
@@ -259,7 +263,7 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> {
 
   @Override
   protected Result<Issue> doSearch(IssueQuery query, QueryContext context) {
-    Collection<String> components = query.fileUuids();
+    Collection<String> components = query.componentUuids();
     if (components != null && components.size() == 1 && BooleanUtils.isTrue(query.ignorePaging())) {
       context.setShowFullResult(true);
     }
index b2b811575c2ebb59f1554e1ac9e240a4787e057f..379e15a484f68b65117a829c1c167361173d1ce7 100644 (file)
@@ -92,8 +92,8 @@ public class IssueQueryServiceTest {
     map.put("statuses", newArrayList("CLOSED"));
     map.put("resolutions", newArrayList("FALSE-POSITIVE"));
     map.put("resolved", true);
-    ArrayList<String> componentKeys = newArrayList("org.apache");
-    map.put("components", componentKeys);
+    ArrayList<String> projectKeys = newArrayList("org.apache");
+    map.put("projectKeys", projectKeys);
     ArrayList<String> moduleUuids = newArrayList("BCDE");
     map.put("moduleUuids", moduleUuids);
     map.put("directories", newArrayList("/src/main/java/example"));
@@ -103,7 +103,6 @@ public class IssueQueryServiceTest {
     map.put("assignees", newArrayList("joanna"));
     map.put("languages", newArrayList("xoo"));
     map.put("tags", newArrayList("tag1", "tag2"));
-    map.put("onComponentOnly", true);
     map.put("assigned", true);
     map.put("planned", true);
     map.put("hideRules", true);
@@ -142,7 +141,7 @@ public class IssueQueryServiceTest {
     assertThat(query.assignees()).containsOnly("joanna");
     assertThat(query.languages()).containsOnly("xoo");
     assertThat(query.tags()).containsOnly("tag1", "tag2");
-    assertThat(query.onComponentOnly()).isTrue();
+    assertThat(query.onComponentOnly()).isFalse();
     assertThat(query.assigned()).isTrue();
     assertThat(query.planned()).isTrue();
     assertThat(query.hideRules()).isTrue();
@@ -219,7 +218,7 @@ public class IssueQueryServiceTest {
       issueQueryService.createFromMap(map);
       fail();
     } catch (Exception e) {
-      assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("components and componentUuids cannot be set simultaneously");
+      assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("componentRoots and componentRootUuids cannot be set simultaneously");
     }
   }