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;
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);
return files;
}
+ public Collection<String> viewUuids() {
+ return views;
+ }
+
public Collection<RuleKey> rules() {
return rules;
}
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;
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;
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;
}
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());
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) {
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;
return compositeFilter;
}
+ @CheckForNull
private FilterBuilder directoryFilter(Collection<String> moduleUuids, Collection<String> directoryPaths) {
BoolFilterBuilder directoryTop = null;
FilterBuilder moduleFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, moduleUuids);
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();
}
@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;
}
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)
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)
.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)
.setLanguage(null);
}
+ public static ComponentDto newModuleDto(ComponentDto subProjectOrProject) {
+ return newModuleDto(Uuids.create(), subProjectOrProject);
+ }
+
public static ComponentDto newProjectDto() {
return newProjectDto(Uuids.create());
}
.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())
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();
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;
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;
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;
assertThat(result.getFacets().get("directories")).containsOnly(new FacetValue("/src/main/xoo", 1), new FacetValue("/", 1));
}
+ @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();
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();
+ }
}