aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2015-01-29 08:20:35 +0100
committerJulien Lancelot <julien.lancelot@sonarsource.com>2015-01-29 15:44:04 +0100
commit2f85f918b25f9fd3e3f3155095f3c994f745ed90 (patch)
treeb7c80689c83f9016b25fb04659697938e73048eb
parent13406b7db49fc22c8caea636b85b6143011bbd65 (diff)
downloadsonarqube-2f85f918b25f9fd3e3f3155095f3c994f745ed90.tar.gz
sonarqube-2f85f918b25f9fd3e3f3155095f3c994f745ed90.zip
SONAR-6089 Allow to search Issues by Views / Sub-Views
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/IssueQuery.java12
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java30
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/component/ComponentTesting.java18
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/step/PurgeRemovedViewsStepTest.java2
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java37
5 files changed, 84 insertions, 15 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQuery.java b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQuery.java
index dea020a2f41..5116a2054a5 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQuery.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQuery.java
@@ -63,6 +63,7 @@ public class IssueQuery {
private final Collection<String> projects;
private final Collection<String> directories;
private final Collection<String> files;
+ private final Collection<String> views;
private final Collection<RuleKey> rules;
private final Collection<String> actionPlans;
private final Collection<String> reporters;
@@ -93,6 +94,7 @@ public class IssueQuery {
this.projects = defaultCollection(builder.projects);
this.directories = defaultCollection(builder.directories);
this.files = defaultCollection(builder.files);
+ this.views = defaultCollection(builder.views);
this.rules = defaultCollection(builder.rules);
this.actionPlans = defaultCollection(builder.actionPlans);
this.reporters = defaultCollection(builder.reporters);
@@ -153,6 +155,10 @@ public class IssueQuery {
return files;
}
+ public Collection<String> viewUuids() {
+ return views;
+ }
+
public Collection<RuleKey> rules() {
return rules;
}
@@ -260,6 +266,7 @@ public class IssueQuery {
private Collection<String> projects;
private Collection<String> directories;
private Collection<String> files;
+ private Collection<String> views;
private Collection<RuleKey> rules;
private Collection<String> actionPlans;
private Collection<String> reporters;
@@ -332,6 +339,11 @@ public class IssueQuery {
return this;
}
+ public Builder viewUuids(@Nullable Collection<String> l) {
+ this.views = l;
+ return this;
+ }
+
public Builder rules(@Nullable Collection<RuleKey> rules) {
this.rules = rules;
return this;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java
index 11603bf01d6..42414efe6db 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java
@@ -45,6 +45,7 @@ import org.sonar.server.issue.IssueQuery;
import org.sonar.server.issue.filter.IssueFilterParameters;
import org.sonar.server.search.*;
import org.sonar.server.user.UserSession;
+import org.sonar.server.view.index.ViewIndexDefinition;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
@@ -258,7 +259,6 @@ public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> {
}
private void addComponentRelatedFilters(IssueQuery query, Map<String, FilterBuilder> filters) {
-
FilterBuilder projectFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, query.projectUuids());
FilterBuilder moduleRootFilter = moduleRootFilter(query.moduleRootUuids());
FilterBuilder moduleFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, query.moduleUuids());
@@ -266,6 +266,7 @@ public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> {
FilterBuilder directoryFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, query.directories());
FilterBuilder fileFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, query.fileUuids());
FilterBuilder componentFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, query.componentUuids());
+ FilterBuilder viewFilter = viewFilter(query.viewUuids());
if (BooleanUtils.isTrue(query.isContextualized())) {
if (projectFilter != null) {
@@ -292,14 +293,15 @@ public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> {
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);
}
}
+ @CheckForNull
private FilterBuilder moduleRootFilter(Collection<String> componentUuids) {
- if (componentUuids == null || componentUuids.isEmpty()) {
+ if (componentUuids.isEmpty()) {
return null;
}
-
FilterBuilder componentFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, componentUuids);
FilterBuilder modulePathFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_MODULE_PATH, componentUuids);
FilterBuilder compositeFilter = null;
@@ -315,6 +317,7 @@ public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> {
return compositeFilter;
}
+ @CheckForNull
private FilterBuilder directoryFilter(Collection<String> moduleUuids, Collection<String> directoryPaths) {
BoolFilterBuilder directoryTop = null;
FilterBuilder moduleFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, moduleUuids);
@@ -332,6 +335,23 @@ public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> {
return directoryTop;
}
+ @CheckForNull
+ private FilterBuilder viewFilter(Collection<String> viewUuids) {
+ if (viewUuids.isEmpty()) {
+ return null;
+ }
+
+ OrFilterBuilder viewsFilter = FilterBuilders.orFilter();
+ for (String viewUuid : viewUuids) {
+ viewsFilter.add(FilterBuilders.termsLookupFilter(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID)
+ .lookupIndex(ViewIndexDefinition.INDEX)
+ .lookupType(ViewIndexDefinition.TYPE_VIEW)
+ .lookupId(viewUuid)
+ .lookupPath(ViewIndexDefinition.FIELD_PROJECTS));
+ }
+ return viewsFilter;
+ }
+
private FilterBuilder getAuthorizationFilter(QueryContext options) {
String user = options.getUserLogin();
Set<String> groups = options.getUserGroups();
@@ -513,8 +533,8 @@ public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> {
}
@CheckForNull
- private FilterBuilder matchFilter(String field, @Nullable Collection<?> values) {
- if (values != null && !values.isEmpty()) {
+ private FilterBuilder matchFilter(String field, Collection<?> values) {
+ if (!values.isEmpty()) {
return FilterBuilders.termsFilter(field, values);
} else {
return null;
diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ComponentTesting.java b/server/sonar-server/src/test/java/org/sonar/server/component/ComponentTesting.java
index a5f007bee05..5d6091370cd 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/component/ComponentTesting.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/component/ComponentTesting.java
@@ -34,7 +34,7 @@ public class ComponentTesting {
}
public static ComponentDto newFileDto(ComponentDto module, String fileUuid) {
- return newComponent(module, fileUuid)
+ return newComponent(fileUuid, module)
.setKey("KEY_" + fileUuid)
.setName("NAME_" + fileUuid)
.setLongName("LONG_NAME_" + fileUuid)
@@ -46,7 +46,7 @@ public class ComponentTesting {
public static ComponentDto newDirectory(ComponentDto module, String path) {
String uuid = Uuids.create();
- return newComponent(module, uuid)
+ return newComponent(uuid, module)
.setKey(!path.equals("/") ? module.getKey() + ":" + path : module.getKey() + ":/")
.setName(path)
.setLongName(path)
@@ -55,12 +55,8 @@ public class ComponentTesting {
.setQualifier(Qualifiers.DIRECTORY);
}
- public static ComponentDto newModuleDto(ComponentDto subProjectOrProject) {
- return newModuleDto(subProjectOrProject, Uuids.create());
- }
-
- public static ComponentDto newModuleDto(ComponentDto subProjectOrProject, String uuid) {
- return newComponent(subProjectOrProject, uuid)
+ public static ComponentDto newModuleDto(String uuid, ComponentDto subProjectOrProject) {
+ return newComponent(uuid, subProjectOrProject)
.setKey("KEY_" + uuid)
.setName("NAME_" + uuid)
.setLongName("LONG_NAME_" + uuid)
@@ -70,6 +66,10 @@ public class ComponentTesting {
.setLanguage(null);
}
+ public static ComponentDto newModuleDto(ComponentDto subProjectOrProject) {
+ return newModuleDto(Uuids.create(), subProjectOrProject);
+ }
+
public static ComponentDto newProjectDto() {
return newProjectDto(Uuids.create());
}
@@ -90,7 +90,7 @@ public class ComponentTesting {
.setEnabled(true);
}
- private static ComponentDto newComponent(ComponentDto module, String uuid) {
+ private static ComponentDto newComponent(String uuid, ComponentDto module) {
return new ComponentDto()
.setUuid(uuid)
.setProjectUuid(module.projectUuid())
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PurgeRemovedViewsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PurgeRemovedViewsStepTest.java
index 0f1de03316e..ed96ecb547d 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PurgeRemovedViewsStepTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PurgeRemovedViewsStepTest.java
@@ -85,7 +85,7 @@ public class PurgeRemovedViewsStepTest {
new ViewDoc().setUuid("CDEF").getFields());
ComponentDto view = ComponentTesting.newProjectDto("ABCD").setQualifier(Qualifiers.VIEW);
- ComponentDto subView = ComponentTesting.newModuleDto(view, "BCDE").setQualifier(Qualifiers.SUBVIEW);
+ ComponentDto subView = ComponentTesting.newModuleDto("BCDE", view).setQualifier(Qualifiers.SUBVIEW);
dbClient.componentDao().insert(session, view, subView);
session.commit();
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java
index 0fc89a0186d..1f5f1b6eb00 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java
@@ -21,6 +21,8 @@ package org.sonar.server.issue.index;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterators;
+import org.elasticsearch.action.bulk.BulkRequestBuilder;
+import org.elasticsearch.action.index.IndexRequest;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
@@ -32,6 +34,7 @@ import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.KeyValueFormat;
import org.sonar.core.component.ComponentDto;
import org.sonar.server.component.ComponentTesting;
+import org.sonar.server.es.EsClient;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.issue.IssueQuery;
import org.sonar.server.issue.IssueTesting;
@@ -40,6 +43,8 @@ import org.sonar.server.search.QueryContext;
import org.sonar.server.search.Result;
import org.sonar.server.tester.ServerTester;
import org.sonar.server.user.MockUserSession;
+import org.sonar.server.view.index.ViewDoc;
+import org.sonar.server.view.index.ViewIndexDefinition;
import javax.annotation.Nullable;
@@ -291,6 +296,32 @@ public class IssueIndexMediumTest {
}
@Test
+ public void filter_by_views() throws Exception {
+ ComponentDto project1 = ComponentTesting.newProjectDto();
+ ComponentDto file1 = ComponentTesting.newFileDto(project1);
+ ComponentDto project2 = ComponentTesting.newProjectDto();
+ indexIssues(
+ // Project1 has 2 issues (one on a file and one on the project itself)
+ IssueTesting.newDoc("ISSUE1", project1),
+ IssueTesting.newDoc("ISSUE2", file1),
+ // Project2 has 1 issue
+ IssueTesting.newDoc("ISSUE3", project2));
+
+ // The view1 is containing 2 issues from project1
+ String view1 = "ABCD";
+ indexView(view1, newArrayList(project1.uuid()));
+
+ // The view2 is containing 1 issue from project2
+ String view2 = "CDEF";
+ indexView(view2, newArrayList(project2.uuid()));
+
+ assertThat(index.search(IssueQuery.builder().viewUuids(newArrayList(view1)).build(), new QueryContext()).getHits()).hasSize(2);
+ assertThat(index.search(IssueQuery.builder().viewUuids(newArrayList(view2)).build(), new QueryContext()).getHits()).hasSize(1);
+ assertThat(index.search(IssueQuery.builder().viewUuids(newArrayList(view1, view2)).build(), new QueryContext()).getHits()).hasSize(3);
+ assertThat(index.search(IssueQuery.builder().viewUuids(newArrayList("unknown")).build(), new QueryContext()).getHits()).isEmpty();
+ }
+
+ @Test
public void filter_by_severities() throws Exception {
ComponentDto project = ComponentTesting.newProjectDto();
ComponentDto file = ComponentTesting.newFileDto(project);
@@ -952,4 +983,10 @@ public class IssueIndexMediumTest {
tester.get(IssueAuthorizationIndexer.class).index(newArrayList(new IssueAuthorizationDao.Dto(projectUuid, 1).addGroup(group).addUser(user)));
}
+ private void indexView(String viewUuid, List<String> projects) {
+ EsClient client = tester.get(EsClient.class);
+ BulkRequestBuilder bulk = client.prepareBulk().setRefresh(true);
+ bulk.add(new IndexRequest(ViewIndexDefinition.INDEX, ViewIndexDefinition.TYPE_VIEW).source(new ViewDoc().setUuid(viewUuid).setProjects(projects).getFields()));
+ bulk.get();
+ }
}