import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.Collections2;
+import com.google.common.collect.Sets;
import org.apache.commons.collections.CollectionUtils;
import org.sonar.api.ServerComponent;
import org.sonar.api.i18n.I18n;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
+import java.util.*;
import static com.google.common.collect.Lists.newArrayList;
return componentUuids;
}
+ public Set<String> getDistinctQualifiers(DbSession session, @Nullable Collection<String> componentUuids) {
+ Set<String> componentQualifiers = Sets.newHashSet();
+ if (componentUuids != null && !componentUuids.isEmpty()) {
+ List<ComponentDto> components = dbClient.componentDao().getByUuids(session, componentUuids);
+
+ for (ComponentDto component : components) {
+ componentQualifiers.add(component.qualifier());
+ }
+ }
+ return componentQualifiers;
+ }
+
+ public Collection<ComponentDto> getByUuids(DbSession session, Collection<String> componentUuids) {
+ Set<ComponentDto> directoryPaths = Sets.newHashSet();
+ if (componentUuids != null && !componentUuids.isEmpty()) {
+ List<ComponentDto> components = dbClient.componentDao().getByUuids(session, componentUuids);
+
+ for (ComponentDto component : components) {
+ directoryPaths.add(component);
+ }
+ }
+ return directoryPaths;
+ }
+
private void checkKeyFormat(String qualifier, String kee) {
if (!ComponentKeys.isValidModuleKey(kee)) {
throw new BadRequestException(formatMessage("Malformed key for %s: %s. Allowed characters are alphanumeric, '-', '_', '.' and ':', with at least one non-digit.",
private ComponentDto getByKey(DbSession session, String key) {
return dbClient.componentDao().getByKey(session, key);
}
-
}
private final Collection<String> resolutions;
private final Collection<String> components;
private final Collection<String> modules;
+ private final Collection<String> moduleRoots;
private final Collection<String> projects;
private final Collection<String> directories;
+ private final Collection<String> files;
private final Collection<RuleKey> rules;
private final Collection<String> actionPlans;
private final Collection<String> reporters;
this.resolutions = defaultCollection(builder.resolutions);
this.components = defaultCollection(builder.components);
this.modules = defaultCollection(builder.modules);
+ this.moduleRoots = defaultCollection(builder.moduleRoots);
this.projects = defaultCollection(builder.projects);
this.directories = defaultCollection(builder.directories);
+ this.files = defaultCollection(builder.files);
this.rules = defaultCollection(builder.rules);
this.actionPlans = defaultCollection(builder.actionPlans);
this.reporters = defaultCollection(builder.reporters);
return modules;
}
+ public Collection<String> moduleRootUuids() {
+ return moduleRoots;
+ }
+
public Collection<String> projectUuids() {
return projects;
}
return directories;
}
+ public Collection<String> fileUuids() {
+ return files;
+ }
+
public Collection<RuleKey> rules() {
return rules;
}
private Collection<String> resolutions;
private Collection<String> components;
private Collection<String> modules;
+ private Collection<String> moduleRoots;
private Collection<String> projects;
private Collection<String> directories;
+ private Collection<String> files;
private Collection<RuleKey> rules;
private Collection<String> actionPlans;
private Collection<String> reporters;
return this;
}
+ public Builder moduleRootUuids(@Nullable Collection<String> l) {
+ this.moduleRoots = l;
+ return this;
+ }
+
public Builder projectUuids(@Nullable Collection<String> l) {
this.projects = l;
return this;
return this;
}
+ public Builder fileUuids(@Nullable Collection<String> l) {
+ this.files = l;
+ return this;
+ }
+
public Builder rules(@Nullable Collection<RuleKey> rules) {
this.rules = rules;
return this;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
+import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import org.apache.commons.lang.ObjectUtils;
import org.sonar.api.ServerComponent;
+import org.sonar.api.resources.Qualifiers;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.server.ws.Request;
+import org.sonar.core.component.ComponentDto;
import org.sonar.core.persistence.DbSession;
import org.sonar.server.component.ComponentService;
import org.sonar.server.db.DbClient;
+import org.sonar.server.issue.IssueQuery.Builder;
import org.sonar.server.issue.filter.IssueFilterParameters;
import org.sonar.server.search.ws.SearchRequestHandler;
import org.sonar.server.util.RubyUtils;
public IssueQuery createFromMap(Map<String, Object> params) {
DbSession session = dbClient.openSession(false);
try {
+
IssueQuery.Builder builder = IssueQuery.builder()
.issueKeys(RubyUtils.toStrings(params.get(IssueFilterParameters.ISSUES)))
.severities(RubyUtils.toStrings(params.get(IssueFilterParameters.SEVERITIES)))
.onComponentOnly(RubyUtils.toBoolean(params.get(IssueFilterParameters.ON_COMPONENT_ONLY)))
.assigned(RubyUtils.toBoolean(params.get(IssueFilterParameters.ASSIGNED)))
.planned(RubyUtils.toBoolean(params.get(IssueFilterParameters.PLANNED)))
- .directories(RubyUtils.toStrings(params.get(IssueFilterParameters.DIRECTORIES)))
.hideRules(RubyUtils.toBoolean(params.get(IssueFilterParameters.HIDE_RULES)))
.createdAt(RubyUtils.toDate(params.get(IssueFilterParameters.CREATED_AT)))
.createdAfter(RubyUtils.toDate(params.get(IssueFilterParameters.CREATED_AFTER)))
.createdBefore(RubyUtils.toDate(params.get(IssueFilterParameters.CREATED_BEFORE)));
- addProjectUuids(builder, session,
- RubyUtils.toStrings(params.get(IssueFilterParameters.PROJECT_UUIDS)),
- RubyUtils.toStrings(
- ObjectUtils.defaultIfNull(
- params.get(IssueFilterParameters.PROJECT_KEYS),
- params.get(IssueFilterParameters.PROJECTS)
- )
- ));
+
addComponentUuids(builder, session,
RubyUtils.toStrings(params.get(IssueFilterParameters.COMPONENT_UUIDS)),
RubyUtils.toStrings(
)
),
RubyUtils.toStrings(params.get(IssueFilterParameters.COMPONENT_ROOT_UUIDS)),
- RubyUtils.toStrings(params.get(IssueFilterParameters.COMPONENT_ROOTS)));
- addModuleUuids(builder, session,
+ RubyUtils.toStrings(params.get(IssueFilterParameters.COMPONENT_ROOTS)),
+ RubyUtils.toStrings(params.get(IssueFilterParameters.PROJECT_UUIDS)),
+ RubyUtils.toStrings(
+ ObjectUtils.defaultIfNull(
+ params.get(IssueFilterParameters.PROJECT_KEYS),
+ params.get(IssueFilterParameters.PROJECTS)
+ )
+ ),
RubyUtils.toStrings(params.get(IssueFilterParameters.MODULE_UUIDS)),
- RubyUtils.toStrings(params.get(IssueFilterParameters.MODULE_KEYS)));
+ RubyUtils.toStrings(params.get(IssueFilterParameters.DIRECTORIES)),
+ RubyUtils.toStrings(params.get(IssueFilterParameters.FILE_UUIDS)));
+
String sort = (String) params.get(IssueFilterParameters.SORT);
if (!Strings.isNullOrEmpty(sort)) {
builder.sort(sort);
.onComponentOnly(request.paramAsBoolean(IssueFilterParameters.ON_COMPONENT_ONLY))
.assigned(request.paramAsBoolean(IssueFilterParameters.ASSIGNED))
.planned(request.paramAsBoolean(IssueFilterParameters.PLANNED))
- .directories(request.paramAsStrings(IssueFilterParameters.DIRECTORIES))
.createdAt(request.paramAsDateTime(IssueFilterParameters.CREATED_AT))
.createdAfter(request.paramAsDateTime(IssueFilterParameters.CREATED_AFTER))
.createdBefore(request.paramAsDateTime(IssueFilterParameters.CREATED_BEFORE))
.ignorePaging(request.paramAsBoolean(IssueFilterParameters.IGNORE_PAGING));
- addProjectUuids(builder, session,
- request.paramAsStrings(IssueFilterParameters.PROJECT_UUIDS), request.paramAsStrings(IssueFilterParameters.PROJECT_KEYS));
+
addComponentUuids(builder, session,
request.paramAsStrings(IssueFilterParameters.COMPONENT_UUIDS), request.paramAsStrings(IssueFilterParameters.COMPONENT_KEYS),
- request.paramAsStrings(IssueFilterParameters.COMPONENT_ROOT_UUIDS), request.paramAsStrings(IssueFilterParameters.COMPONENT_ROOTS));
- addModuleUuids(builder, session,
- request.paramAsStrings(IssueFilterParameters.MODULE_UUIDS), request.paramAsStrings(IssueFilterParameters.MODULE_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),
+ request.paramAsStrings(IssueFilterParameters.FILE_UUIDS));
+
String sort = request.param(SearchRequestHandler.PARAM_SORT);
if (!Strings.isNullOrEmpty(sort)) {
builder.sort(sort);
}
}
- private void addProjectUuids(IssueQuery.Builder builder, DbSession session, @Nullable Collection<String> projectUuids, @Nullable Collection<String> projects) {
- if (projectUuids != null) {
- if (projects != null) {
- throw new IllegalArgumentException("projects and projectUuids cannot be set simultaneously");
- }
- builder.projectUuids(projectUuids);
- } else {
- builder.projectUuids(componentUuids(session, projects));
- }
- }
-
private void addComponentUuids(IssueQuery.Builder builder, DbSession session,
@Nullable Collection<String> componentUuids, @Nullable Collection<String> components,
/*
* 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();
+
if (componentUuids != null || componentRootUuids != null) {
if (components != null || componentRoots != null) {
throw new IllegalArgumentException("components and componentUuids cannot be set simultaneously");
}
- Set<String> allComponentUuids = Sets.newHashSet();
allComponentUuids.addAll((Collection<String>) ObjectUtils.defaultIfNull(componentUuids, Sets.newHashSet()));
allComponentUuids.addAll((Collection<String>) ObjectUtils.defaultIfNull(componentRootUuids, Sets.newHashSet()));
- builder.componentUuids(allComponentUuids);
} else {
Set<String> allComponents = Sets.newHashSet();
allComponents.addAll((Collection<String>) ObjectUtils.defaultIfNull(components, Sets.newHashSet()));
allComponents.addAll((Collection<String>) ObjectUtils.defaultIfNull(componentRoots, Sets.newHashSet()));
- builder.componentUuids(componentUuids(session, allComponents));
+ allComponentUuids.addAll(componentUuids(session, allComponents));
+ }
+
+ if (allComponentUuids.isEmpty()) {
+ addComponentsBelowView(builder, session, projects, projectUuids, moduleUuids, directories, fileUuids);
+ } else {
+
+ Set<String> qualifiers = componentService.getDistinctQualifiers(session, allComponentUuids);
+ if (qualifiers.isEmpty()) {
+ // Qualifier not found, defaulting to componentUuids (e.g <UNKNOWN>)
+ builder.componentUuids(allComponentUuids);
+ return;
+ }
+ if (qualifiers.size() > 1) {
+ throw new IllegalArgumentException("All components must have the same qualifier, found " + Joiner.on(',').join(qualifiers));
+ }
+
+ String uniqueQualifier = qualifiers.iterator().next();
+ if (Qualifiers.VIEW.equals(uniqueQualifier)) {
+ // TODO Handle views
+ addComponentsBelowView(builder, session, projects, projectUuids, moduleUuids, directories, fileUuids);
+ } else if ("DEV".equals(uniqueQualifier)) { // XXX No constant !!!
+ // TODO Get SCM accounts from dev, then search by author
+ // TODO addComponentsBelowView(projects, projectUuids, moduleUuids, directories, fileUuids);
+ } else if (Qualifiers.PROJECT.equals(uniqueQualifier)) {
+ builder.projectUuids(allComponentUuids);
+ addComponentsBelowModule(builder, moduleUuids, directories, fileUuids);
+ } else if (Qualifiers.MODULE.equals(uniqueQualifier)) {
+ builder.moduleRootUuids(allComponentUuids);
+ addComponentsBelowModule(builder, moduleUuids, directories, fileUuids);
+ } else if (Qualifiers.DIRECTORY.equals(uniqueQualifier)) {
+ Collection<String> directoryModuleUuids = Sets.newHashSet();
+ Collection<String> directoryPaths = Sets.newHashSet();
+ for (ComponentDto directory : componentService.getByUuids(session, allComponentUuids)) {
+ directoryModuleUuids.add(directory.moduleUuid());
+ directoryPaths.add(directory.path());
+ }
+ builder.moduleUuids(directoryModuleUuids);
+ builder.directories(directoryPaths);
+ addComponentsBelowDirectory(builder, fileUuids);
+ } else if (Qualifiers.FILE.equals(uniqueQualifier)) {
+ builder.fileUuids(allComponentUuids);
+ } else {
+ throw new IllegalArgumentException("Unable to set search root context for components " + Joiner.on(',').join(allComponentUuids));
+ }
}
}
- private void addModuleUuids(IssueQuery.Builder builder, DbSession session, @Nullable Collection<String> componentRootUuids, @Nullable Collection<String> componentRoots) {
- if (componentRootUuids != null) {
- if (componentRoots != null) {
- throw new IllegalArgumentException("componentRoots and componentRootUuids cannot be set simultaneously");
+ 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) {
+ if (projectUuids != null) {
+ if (projects != null) {
+ throw new IllegalArgumentException("projects and projectUuids cannot be set simultaneously");
}
- builder.moduleUuids(componentRootUuids);
+ builder.projectUuids(projectUuids);
} else {
- builder.moduleUuids(componentUuids(session, componentRoots));
+ builder.projectUuids(componentUuids(session, projects));
}
+ addComponentsBelowModule(builder, moduleUuids, directories, fileUuids);
+ }
+
+ private void addComponentsBelowModule(Builder builder,
+ @Nullable Collection<String> moduleUuids, @Nullable Collection<String> directories, @Nullable Collection<String> fileUuids) {
+ builder.moduleUuids(moduleUuids);
+ addComponentsBelowModule(builder, directories, fileUuids);
+ }
+
+ private void addComponentsBelowModule(Builder builder,
+ @Nullable Collection<String> directories, @Nullable Collection<String> fileUuids) {
+ builder.directories(directories);
+ addComponentsBelowDirectory(builder, fileUuids);
+ }
+
+ private void addComponentsBelowDirectory(Builder builder,
+ @Nullable Collection<String> fileUuids) {
+ builder.fileUuids(fileUuids);
}
private Collection<String> componentUuids(DbSession session, @Nullable Collection<String> componentKeys) {
public static final String COMPONENT_UUIDS = "componentUuids";
public static final String COMPONENT_ROOTS = "componentRoots";
public static final String COMPONENT_ROOT_UUIDS = "componentRootUuids";
- public static final String MODULE_KEYS = "moduleKeys";
public static final String MODULE_UUIDS = "moduleUuids";
public static final String PROJECTS = "projects";
public static final String PROJECT_KEYS = "projectKeys";
public static final String PROJECT_UUIDS = "projectUuids";
public static final String DIRECTORIES = "directories";
+ public static final String FILE_UUIDS = "fileUuids";
public static final String ON_COMPONENT_ONLY = "onComponentOnly";
public static final String RULES = "rules";
public static final String ACTION_PLANS = "actionPlans";
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, PROJECT_KEYS, COMPONENT_KEYS, MODULE_KEYS, MODULE_UUIDS, DIRECTORIES);
+ PROJECTS, PROJECT_UUIDS, IGNORE_PAGING, PROJECT_KEYS, COMPONENT_KEYS, MODULE_UUIDS, DIRECTORIES, FILE_UUIDS);
public static final List<String> ALL_WITHOUT_PAGINATION = newArrayList(Iterables.filter(ALL, new Predicate<String>() {
@Override
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
import org.apache.commons.lang.BooleanUtils;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
}
private void addComponentRelatedFilters(IssueQuery query, Map<String, FilterBuilder> filters) {
- Collection<String> componentUuids = query.componentUuids();
- if (BooleanUtils.isTrue(query.onComponentOnly())) {
- Set<String> allComponents = Sets.newHashSet();
- allComponents.addAll(query.projectUuids());
- allComponents.addAll(query.moduleUuids());
- allComponents.addAll(componentUuids);
- filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, matchFilter(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, allComponents));
- } else {
- filters.put(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, matchFilter(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, query.projectUuids()));
- filters.put(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, matchFilter(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, query.moduleUuids()));
-
- FilterBuilder compositeFilter = componentFilter(componentUuids);
- filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, compositeFilter);
- filters.put(IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, matchFilter(IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, query.directories()));
+ 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 directoryRootFilter = directoryFilter(query.moduleUuids(), query.directories());
+ 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());
+
+ if (projectFilter != null) {
+ filters.put("__componentRoot", 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);
+ } else if (moduleRootFilter != null) {
+ filters.put("__componentRoot", moduleRootFilter);
+ filters.put(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, moduleFilter);
+ filters.put(IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, directoryFilter);
+ filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, fileFilter);
+ } else if (directoryRootFilter != null) {
+ filters.put("__componentRoot", directoryRootFilter);
+ filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, fileFilter);
+ } else if (fileFilter != null) {
+ filters.put("__componentRoot", fileFilter);
+ } else if (componentFilter != null) {
+ // Last resort, when component type is unknown
+ filters.put("__componentRoot", componentFilter);
}
}
- private FilterBuilder componentFilter(Collection<String> componentUuids) {
+ private FilterBuilder moduleRootFilter(Collection<String> componentUuids) {
+ if (componentUuids == null || 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;
}
+ private FilterBuilder directoryFilter(Collection<String> moduleUuids, Collection<String> directoryPaths) {
+ BoolFilterBuilder directoryTop = null;
+ FilterBuilder moduleFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, moduleUuids);
+ FilterBuilder directoryFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, directoryPaths);
+ if (moduleFilter != null) {
+ directoryTop = FilterBuilders.boolFilter();
+ directoryTop.must(moduleFilter);
+ }
+ if (directoryFilter != null) {
+ if (directoryTop == null) {
+ directoryTop = FilterBuilders.boolFilter();
+ }
+ directoryTop.must(directoryFilter);
+ }
+ return directoryTop;
+ }
+
private FilterBuilder getAuthorizationFilter(QueryContext options) {
String user = options.getUserLogin();
Set<String> groups = options.getUserGroups();
IssueFilterParameters.SEVERITIES, IssueIndexDefinition.FIELD_ISSUE_SEVERITY, Severity.ALL.toArray());
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch,
IssueFilterParameters.STATUSES, IssueIndexDefinition.FIELD_ISSUE_STATUS, Issue.STATUSES.toArray());
- addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch,
- IssueFilterParameters.COMPONENT_UUIDS, IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, query.componentUuids().toArray());
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch,
IssueFilterParameters.PROJECT_UUIDS, IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, query.projectUuids().toArray());
+ addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch,
+ IssueFilterParameters.MODULE_UUIDS, IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, query.moduleUuids().toArray());
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch,
IssueFilterParameters.DIRECTORIES, IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, query.directories().toArray());
+ addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch,
+ IssueFilterParameters.FILE_UUIDS, IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, query.fileUuids().toArray());
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch,
IssueFilterParameters.LANGUAGES, IssueIndexDefinition.FIELD_ISSUE_LANGUAGE, query.languages().toArray());
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch,
FilterBuilders.boolFilter()
.must(getAuthorizationFilter(new QueryContext()))
.must(FilterBuilders.missingFilter(IssueIndexDefinition.FIELD_ISSUE_RESOLUTION))
- .must(componentFilter(Arrays.asList(componentUuid)))));
+ .must(moduleRootFilter(Arrays.asList(componentUuid)))));
TermsBuilder aggreg = AggregationBuilders.terms("_ref")
.field(IssueIndexDefinition.FIELD_ISSUE_TAGS)
.size(pageSize)
.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_KEYS)
- .setDescription("To retrieve issues associated to a specific list of modules (comma-separated list of module keys). " +
- INTERNAL_PARAMETER_DISCLAIMER +
- "Views are not supported. If this parameter is set, moduleUuids must not be set.")
- .setExampleValue("org.apache.struts:struts");
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 +
.setExampleValue("7d8749e8-3070-4903-9188-bdd82933bb92");
action.createParam(IssueFilterParameters.DIRECTORIES)
- .setDescription("Since 5.1. To retrieve issues associated to a specific list of directories (comma-separated list of directory paths). ")
- .setExampleValue("7d8749e8-3070-4903-9188-bdd82933bb92");
+ .setDescription("Since 5.1. To retrieve issues associated to a specific list of directories (comma-separated list of directory paths). " +
+ "This parameter is only meaningful when a module is selected. " +
+ INTERNAL_PARAMETER_DISCLAIMER)
+ .setExampleValue("src/main/java/org/sonar/server/");
+
+ action.createParam(IssueFilterParameters.FILE_UUIDS)
+ .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.)")
@Override
protected Result<Issue> doSearch(IssueQuery query, QueryContext context) {
- Collection<String> components = query.componentUuids();
+ Collection<String> components = query.fileUuids();
if (components != null && components.size() == 1 && BooleanUtils.isTrue(query.ignorePaging())) {
context.setShowFullResult(true);
}
IssueFilterParameters.RULES,
IssueFilterParameters.ASSIGNEES,
IssueFilterParameters.REPORTERS,
- IssueFilterParameters.COMPONENT_UUIDS,
+ IssueFilterParameters.MODULE_UUIDS,
+ IssueFilterParameters.FILE_UUIDS,
IssueFilterParameters.DIRECTORIES,
IssueFilterParameters.LANGUAGES,
IssueFilterParameters.TAGS,
package org.sonar.server.issue;
+import com.google.common.collect.Sets;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
+import org.sonar.api.resources.Qualifiers;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.DateUtils;
import org.sonar.core.persistence.DbSession;
map.put("resolved", true);
ArrayList<String> componentKeys = newArrayList("org.apache");
map.put("components", componentKeys);
- ArrayList<String> moduleKeys = newArrayList("org.sonar");
- map.put("moduleKeys", moduleKeys);
+ ArrayList<String> moduleUuids = newArrayList("BCDE");
+ map.put("moduleUuids", moduleUuids);
map.put("directories", newArrayList("/src/main/java/example"));
+ ArrayList<String> fileUuids = newArrayList("CDEF");
+ map.put("fileUuids", fileUuids);
map.put("reporters", newArrayList("marilyn"));
map.put("assignees", newArrayList("joanna"));
map.put("languages", newArrayList("xoo"));
}
if (components.contains("org.apache")) {
return newArrayList("ABCD");
- } else if (components.contains("org.sonar")) {
- return newArrayList("BCDE");
}
return newArrayList();
}
});
+ when(componentService.getDistinctQualifiers(eq(session), Matchers.anyCollection())).thenReturn(Sets.newHashSet(Qualifiers.PROJECT));
+
IssueQuery query = issueQueryService.createFromMap(map);
assertThat(query.issueKeys()).containsOnly("ABCDE1234");
assertThat(query.severities()).containsOnly("MAJOR", "MINOR");
assertThat(query.statuses()).containsOnly("CLOSED");
assertThat(query.resolutions()).containsOnly("FALSE-POSITIVE");
assertThat(query.resolved()).isTrue();
- assertThat(query.componentUuids()).containsOnly("ABCD");
+ assertThat(query.projectUuids()).containsOnly("ABCD");
assertThat(query.moduleUuids()).containsOnly("BCDE");
+ assertThat(query.fileUuids()).containsOnly("CDEF");
assertThat(query.reporters()).containsOnly("marilyn");
assertThat(query.assignees()).containsOnly("joanna");
assertThat(query.languages()).containsOnly("xoo");
IssueTesting.newDoc("ISSUE6", ComponentTesting.newFileDto(subModule)));
assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid())).build(), new QueryContext()).getHits()).hasSize(6);
- assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid())).onComponentOnly(true).build(), new QueryContext()).getHits()).hasSize(1);
assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList("unknown")).build(), new QueryContext()).getHits()).isEmpty();
}
IssueTesting.newDoc("ISSUE5", subModule),
IssueTesting.newDoc("ISSUE2", file));
- assertThat(index.search(IssueQuery.builder().moduleUuids(newArrayList(file.uuid())).build(), new QueryContext()).getHits()).isEmpty();
- assertThat(index.search(IssueQuery.builder().moduleUuids(newArrayList(module.uuid())).build(), new QueryContext()).getHits()).hasSize(1);
- assertThat(index.search(IssueQuery.builder().moduleUuids(newArrayList(subModule.uuid())).build(), new QueryContext()).getHits()).hasSize(1);
- assertThat(index.search(IssueQuery.builder().moduleUuids(newArrayList(project.uuid())).build(), new QueryContext()).getHits()).hasSize(1);
- assertThat(index.search(IssueQuery.builder().moduleUuids(newArrayList("unknown")).build(), new QueryContext()).getHits()).isEmpty();
+ assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid()))
+ .moduleUuids(newArrayList(file.uuid())).build(), new QueryContext()).getHits()).isEmpty();
+ assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid()))
+ .moduleUuids(newArrayList(module.uuid())).build(), new QueryContext()).getHits()).hasSize(1);
+ assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid()))
+ .moduleUuids(newArrayList(subModule.uuid())).build(), new QueryContext()).getHits()).hasSize(1);
+ assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid()))
+ .moduleUuids(newArrayList(project.uuid())).build(), new QueryContext()).getHits()).hasSize(1);
+ assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid()))
+ .moduleUuids(newArrayList("unknown")).build(), new QueryContext()).getHits()).isEmpty();
}
@Test
IssueTesting.newDoc("ISSUE5", subModule),
IssueTesting.newDoc("ISSUE6", file3));
- assertThat(index.search(IssueQuery.builder().componentUuids(newArrayList(file1.uuid(), file2.uuid(), file3.uuid())).build(), new QueryContext()).getHits()).hasSize(3);
- assertThat(index.search(IssueQuery.builder().componentUuids(newArrayList(file1.uuid())).build(), new QueryContext()).getHits()).hasSize(1);
- assertThat(index.search(IssueQuery.builder().componentUuids(newArrayList(subModule.uuid())).build(), new QueryContext()).getHits()).hasSize(2);
- assertThat(index.search(IssueQuery.builder().componentUuids(newArrayList(subModule.uuid())).onComponentOnly(true).build(), new QueryContext()).getHits()).hasSize(1);
- assertThat(index.search(IssueQuery.builder().componentUuids(newArrayList(module.uuid())).build(), new QueryContext()).getHits()).hasSize(4);
- assertThat(index.search(IssueQuery.builder().componentUuids(newArrayList(module.uuid())).onComponentOnly(true).build(), new QueryContext()).getHits()).hasSize(1);
- assertThat(index.search(IssueQuery.builder().componentUuids(newArrayList(project.uuid())).build(), new QueryContext()).getHits()).hasSize(6);
- assertThat(index.search(IssueQuery.builder().componentUuids(newArrayList(project.uuid())).onComponentOnly(true).build(), new QueryContext()).getHits()).hasSize(1);
- assertThat(index.search(IssueQuery.builder().componentUuids(newArrayList("unknown")).build(), new QueryContext()).getHits()).isEmpty();
+ assertThat(index.search(IssueQuery.builder().fileUuids(newArrayList(file1.uuid(), file2.uuid(), file3.uuid())).build(), new QueryContext()).getHits()).hasSize(3);
+ assertThat(index.search(IssueQuery.builder().fileUuids(newArrayList(file1.uuid())).build(), new QueryContext()).getHits()).hasSize(1);
+ assertThat(index.search(IssueQuery.builder().moduleRootUuids(newArrayList(subModule.uuid())).build(), new QueryContext()).getHits()).hasSize(2);
+ assertThat(index.search(IssueQuery.builder().moduleRootUuids(newArrayList(module.uuid())).build(), new QueryContext()).getHits()).hasSize(4);
+ assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid())).build(), new QueryContext()).getHits()).hasSize(6);
+ assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList("unknown")).build(), new QueryContext()).getHits()).isEmpty();
}
@Test
IssueTesting.newDoc("ISSUE4", file2),
IssueTesting.newDoc("ISSUE5", file3));
- Result<Issue> result = index.search(IssueQuery.builder().build(), new QueryContext().addFacets(newArrayList("componentUuids")));
- assertThat(result.getFacets()).containsOnlyKeys("componentUuids");
- assertThat(result.getFacets().get("componentUuids")).containsOnly(new FacetValue("A", 1), new FacetValue("ABCD", 1), new FacetValue("BCDE", 2), new FacetValue("CDEF", 1));
+ Result<Issue> result = index.search(IssueQuery.builder().build(), new QueryContext().addFacets(newArrayList("fileUuids")));
+ assertThat(result.getFacets()).containsOnlyKeys("fileUuids");
+ assertThat(result.getFacets().get("fileUuids")).containsOnly(new FacetValue("A", 1), new FacetValue("ABCD", 1), new FacetValue("BCDE", 2), new FacetValue("CDEF", 1));
}
@Test
indexIssue(IssueTesting.newDoc("ISSUE1", file1), "sonar-users", null);
// project2 can be seen by sonar-admins
indexIssue(IssueTesting.newDoc("ISSUE2", file2), "sonar-admins", null);
- // project3 cannot be seen by anyone
+ // project3 can be seen by nobody
indexIssue(IssueTesting.newDoc("ISSUE3", file3), null, null);
IssueQuery.Builder query = IssueQuery.builder();
assertThat(index.search(query.build(), new QueryContext()).getHits()).hasSize(2);
MockUserSession.set().setUserGroups("another group");
- assertThat(index.search(query.build(), new QueryContext()).getHits()).hasSize(0);
+ assertThat(index.search(query.build(), new QueryContext()).getHits()).isEmpty();
MockUserSession.set().setUserGroups("sonar-users", "sonar-admins");
- assertThat(index.search(query.moduleUuids(newArrayList(project3.key())).build(), new QueryContext()).getHits()).hasSize(0);
+ assertThat(index.search(query.projectUuids(newArrayList(project3.uuid())).build(), new QueryContext()).getHits()).isEmpty();
}
@Test
assertThat(index.search(query.build(), new QueryContext()).getHits()).hasSize(0);
MockUserSession.set().setLogin("john");
- assertThat(index.search(query.moduleUuids(newArrayList(project3.key())).build(), new QueryContext()).getHits()).hasSize(0);
+ assertThat(index.search(query.projectUuids(newArrayList(project3.key())).build(), new QueryContext()).getHits()).hasSize(0);
}
@Test
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.issue.ws;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.security.DefaultGroups;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.issue.db.IssueDto;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.server.component.ComponentTesting;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.issue.IssueTesting;
+import org.sonar.server.issue.filter.IssueFilterParameters;
+import org.sonar.server.issue.index.IssueIndexer;
+import org.sonar.server.permission.InternalPermissionService;
+import org.sonar.server.permission.PermissionChange;
+import org.sonar.server.rule.RuleTesting;
+import org.sonar.server.rule.db.RuleDao;
+import org.sonar.server.tester.ServerTester;
+import org.sonar.server.user.MockUserSession;
+import org.sonar.server.ws.WsTester;
+
+public class SearchActionComponentsMediumTest {
+
+ @ClassRule
+ public static ServerTester tester = new ServerTester();
+
+ DbClient db;
+ DbSession session;
+ WsTester wsTester;
+
+ @Before
+ public void setUp() throws Exception {
+ tester.clearDbAndIndexes();
+ db = tester.get(DbClient.class);
+ wsTester = tester.get(WsTester.class);
+ session = db.openSession(false);
+ }
+
+ @After
+ public void after() {
+ session.close();
+ }
+
+ @Test
+ public void issues_on_different_projects() throws Exception {
+ RuleDto rule = newRule();
+ ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject"));
+ setDefaultProjectPermission(project);
+ ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent"));
+ IssueDto issue = IssueTesting.newDto(rule, file, project)
+ .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
+ .setStatus("OPEN").setResolution("OPEN")
+ .setSeverity("MAJOR")
+ .setIssueCreationDate(DateUtils.parseDate("2014-09-04"))
+ .setIssueUpdateDate(DateUtils.parseDate("2017-12-04"));
+ db.issueDao().insert(session, issue);
+
+ ComponentDto project2 = insertComponent(ComponentTesting.newProjectDto("DBCA").setKey("MyProject2"));
+ setDefaultProjectPermission(project2);
+ ComponentDto file2 = insertComponent(ComponentTesting.newFileDto(project2, "EDCB").setKey("MyComponent2"));
+ IssueDto issue2 = IssueTesting.newDto(rule, file2, project2)
+ .setKee("92fd47d4-b650-4037-80bc-7b112bd4eac2")
+ .setStatus("OPEN").setResolution("OPEN")
+ .setSeverity("MAJOR")
+ .setIssueCreationDate(DateUtils.parseDate("2014-09-04"))
+ .setIssueUpdateDate(DateUtils.parseDate("2017-12-04"));
+ db.issueDao().insert(session, issue2);
+ session.commit();
+ tester.get(IssueIndexer.class).indexAll();
+
+ WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION).execute();
+ result.assertJson(this.getClass(), "issues_on_different_projects.json", false);
+ }
+
+ @Test
+ public void search_by_project_uuid() throws Exception {
+ ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject"));
+ setDefaultProjectPermission(project);
+ ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent"));
+ IssueDto issue = IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2");
+ db.issueDao().insert(session, issue);
+ session.commit();
+ tester.get(IssueIndexer.class).indexAll();
+
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
+ .setParam(IssueFilterParameters.PROJECT_UUIDS, project.uuid())
+ .execute()
+ .assertJson(this.getClass(), "search_by_project_uuid.json", false);
+
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
+ .setParam(IssueFilterParameters.PROJECT_UUIDS, "unknown")
+ .execute()
+ .assertJson(this.getClass(), "no_issue.json", false);
+
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
+ .setParam(IssueFilterParameters.COMPONENT_UUIDS, project.uuid())
+ .execute()
+ .assertJson(this.getClass(), "search_by_project_uuid.json", false);
+
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
+ .setParam(IssueFilterParameters.COMPONENT_UUIDS, "unknown")
+ .execute()
+ .assertJson(this.getClass(), "no_issue.json", false);
+ }
+
+ @Test
+ public void search_by_file_uuid() throws Exception {
+ ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject"));
+ setDefaultProjectPermission(project);
+ ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent"));
+ IssueDto issue = IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2");
+ db.issueDao().insert(session, issue);
+ session.commit();
+ tester.get(IssueIndexer.class).indexAll();
+
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
+ .setParam(IssueFilterParameters.FILE_UUIDS, file.uuid())
+ .execute()
+ .assertJson(this.getClass(), "search_by_file_uuid.json", false);
+
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
+ .setParam(IssueFilterParameters.FILE_UUIDS, "unknown")
+ .execute()
+ .assertJson(this.getClass(), "no_issue.json", false);
+
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
+ .setParam(IssueFilterParameters.COMPONENT_UUIDS, file.uuid())
+ .execute()
+ .assertJson(this.getClass(), "search_by_file_uuid.json", false);
+
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
+ .setParam(IssueFilterParameters.COMPONENT_UUIDS, "unknown")
+ .execute()
+ .assertJson(this.getClass(), "no_issue.json", false);
+ }
+
+ @Test
+ public void search_by_directory_path() throws Exception {
+ ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject"));
+ setDefaultProjectPermission(project);
+ ComponentDto directory = insertComponent(ComponentTesting.newDirectory(project, "src/main/java/dir"));
+ ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent").setPath(directory.path() + "/MyComponent.java"));
+ IssueDto issue = IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2");
+ db.issueDao().insert(session, issue);
+ session.commit();
+ tester.get(IssueIndexer.class).indexAll();
+
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
+ .setParam(IssueFilterParameters.COMPONENT_UUIDS, directory.uuid())
+ .execute()
+ .assertJson(this.getClass(), "search_by_file_uuid.json", false);
+
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
+ .setParam(IssueFilterParameters.COMPONENT_UUIDS, "unknown")
+ .execute()
+ .assertJson(this.getClass(), "no_issue.json", false);
+
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
+ .setParam(IssueFilterParameters.DIRECTORIES, "src/main/java/dir")
+ .execute()
+ .assertJson(this.getClass(), "search_by_file_uuid.json", false);
+
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
+ .setParam(IssueFilterParameters.DIRECTORIES, "src/main/java")
+ .execute()
+ .assertJson(this.getClass(), "no_issue.json", false);
+ }
+
+ @Test
+ public void search_by_directory_path_in_different_modules() throws Exception {
+ ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject"));
+ setDefaultProjectPermission(project);
+ ComponentDto module1 = insertComponent(ComponentTesting.newModuleDto(project).setKey("module1"));
+ ComponentDto module2 = insertComponent(ComponentTesting.newModuleDto(project).setKey("module2"));
+ ComponentDto directory1 = insertComponent(ComponentTesting.newDirectory(module1, "src/main/java/dir"));
+ ComponentDto directory2 = insertComponent(ComponentTesting.newDirectory(module2, "src/main/java/dir"));
+ ComponentDto file1 = insertComponent(ComponentTesting.newFileDto(module1, "BCDE").setKey("module1:MyComponent").setPath(directory1.path() + "/MyComponent.java"));
+ insertComponent(ComponentTesting.newFileDto(module2, "CDEF").setKey("module2:MyComponent").setPath(directory2.path() + "/MyComponent.java"));
+ RuleDto rule = newRule();
+ IssueDto issue1 = IssueTesting.newDto(rule, file1, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2");
+ db.issueDao().insert(session, issue1);
+ session.commit();
+
+ tester.get(IssueIndexer.class).indexAll();
+
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
+ .setParam(IssueFilterParameters.COMPONENT_UUIDS, directory1.uuid())
+ .execute()
+ .assertJson(this.getClass(), "search_by_directory_uuid.json", false);
+
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
+ .setParam(IssueFilterParameters.COMPONENT_UUIDS, directory2.uuid())
+ .execute()
+ .assertJson(this.getClass(), "no_issue.json", false);
+
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
+ .setParam(IssueFilterParameters.MODULE_UUIDS, module1.uuid())
+ .setParam(IssueFilterParameters.DIRECTORIES, "src/main/java/dir")
+ .execute()
+ .assertJson(this.getClass(), "search_by_directory_uuid.json", false);
+
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
+ .setParam(IssueFilterParameters.MODULE_UUIDS, module2.uuid())
+ .setParam(IssueFilterParameters.DIRECTORIES, "src/main/java/dir")
+ .execute()
+ .assertJson(this.getClass(), "no_issue.json", false);
+
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
+ .setParam(IssueFilterParameters.DIRECTORIES, "src/main/java/dir")
+ .execute()
+ .assertJson(this.getClass(), "search_by_directory_uuid.json", false);
+
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
+ .setParam(IssueFilterParameters.DIRECTORIES, "src/main/java")
+ .execute()
+ .assertJson(this.getClass(), "no_issue.json", false);
+ }
+
+ @Test
+ public void display_directory_facet() throws Exception {
+ ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject"));
+ setDefaultProjectPermission(project);
+ ComponentDto directory = insertComponent(ComponentTesting.newDirectory(project, "src/main/java/dir"));
+ ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent").setPath(directory.path() + "/MyComponent.java"));
+ IssueDto issue = IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2");
+ db.issueDao().insert(session, issue);
+ session.commit();
+ tester.get(IssueIndexer.class).indexAll();
+
+ MockUserSession.set().setLogin("john");
+ WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
+ .setParam("resolved", "false")
+ .setParam(SearchAction.PARAM_FACETS, "directories")
+ .execute();
+ result.assertJson(this.getClass(), "display_directory_facet.json", false);
+ }
+
+ private RuleDto newRule() {
+ RuleDto rule = RuleTesting.newXooX1()
+ .setName("Rule name")
+ .setDescription("Rule desc")
+ .setStatus(RuleStatus.READY);
+ tester.get(RuleDao.class).insert(session, rule);
+ session.commit();
+ return rule;
+ }
+
+ private void setDefaultProjectPermission(ComponentDto project) {
+ // project can be seen by anyone and by code viewer
+ MockUserSession.set().setLogin("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+ tester.get(InternalPermissionService.class).addPermission(new PermissionChange().setComponentKey(project.getKey()).setGroup(DefaultGroups.ANYONE).setPermission(UserRole.USER));
+ MockUserSession.set();
+ }
+
+ private ComponentDto insertComponent(ComponentDto component) {
+ db.componentDao().insert(session, component);
+ session.commit();
+ return component;
+ }
+
+}
result.assertJson(this.getClass(), "issue.json", false);
}
- @Test
- public void issues_on_different_projects() throws Exception {
- RuleDto rule = newRule();
- ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject"));
- setDefaultProjectPermission(project);
- ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent"));
- IssueDto issue = IssueTesting.newDto(rule, file, project)
- .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
- .setStatus("OPEN").setResolution("OPEN")
- .setSeverity("MAJOR")
- .setIssueCreationDate(DateUtils.parseDate("2014-09-04"))
- .setIssueUpdateDate(DateUtils.parseDate("2017-12-04"));
- db.issueDao().insert(session, issue);
-
- ComponentDto project2 = insertComponent(ComponentTesting.newProjectDto("DBCA").setKey("MyProject2"));
- setDefaultProjectPermission(project2);
- ComponentDto file2 = insertComponent(ComponentTesting.newFileDto(project2, "EDCB").setKey("MyComponent2"));
- IssueDto issue2 = IssueTesting.newDto(rule, file2, project2)
- .setKee("92fd47d4-b650-4037-80bc-7b112bd4eac2")
- .setStatus("OPEN").setResolution("OPEN")
- .setSeverity("MAJOR")
- .setIssueCreationDate(DateUtils.parseDate("2014-09-04"))
- .setIssueUpdateDate(DateUtils.parseDate("2017-12-04"));
- db.issueDao().insert(session, issue2);
- session.commit();
- tester.get(IssueIndexer.class).indexAll();
-
- WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION).execute();
- result.assertJson(this.getClass(), "issues_on_different_projects.json", false);
- }
-
@Test
public void issue_with_comment() throws Exception {
db.userDao().insert(session, new UserDto().setLogin("john").setName("John").setEmail("john@email.com"));
assertThat(result.outputAsString()).contains("\"componentId\":" + file.getId() + ",");
}
- @Test
- public void search_by_project_uuid() throws Exception {
- ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject"));
- setDefaultProjectPermission(project);
- ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent"));
- IssueDto issue = IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2");
- db.issueDao().insert(session, issue);
- session.commit();
- tester.get(IssueIndexer.class).indexAll();
-
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
- .setParam(IssueFilterParameters.PROJECT_UUIDS, project.uuid())
- .execute()
- .assertJson(this.getClass(), "search_by_project_uuid.json", false);
-
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
- .setParam(IssueFilterParameters.PROJECT_UUIDS, "unknown")
- .execute()
- .assertJson(this.getClass(), "no_issue.json", false);
- }
-
- @Test
- public void search_by_component_uuid() throws Exception {
- ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject"));
- setDefaultProjectPermission(project);
- ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent"));
- IssueDto issue = IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2");
- db.issueDao().insert(session, issue);
- session.commit();
- tester.get(IssueIndexer.class).indexAll();
-
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
- .setParam(IssueFilterParameters.COMPONENT_UUIDS, file.uuid())
- .execute()
- .assertJson(this.getClass(), "search_by_file_uuid.json", false);
-
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
- .setParam(IssueFilterParameters.COMPONENT_UUIDS, "unknown")
- .execute()
- .assertJson(this.getClass(), "no_issue.json", false);
- }
-
- @Test
- public void search_by_directory_path() throws Exception {
- ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject"));
- setDefaultProjectPermission(project);
- ComponentDto directory = insertComponent(ComponentTesting.newDirectory(project, "src/main/java/dir"));
- ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent").setPath(directory.path() + "/MyComponent.java"));
- IssueDto issue = IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2");
- db.issueDao().insert(session, issue);
- session.commit();
- tester.get(IssueIndexer.class).indexAll();
-
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
- .setParam(IssueFilterParameters.DIRECTORIES, "src/main/java/dir")
- .execute()
- .assertJson(this.getClass(), "search_by_file_uuid.json", false);
-
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
- .setParam(IssueFilterParameters.DIRECTORIES, "src/main/java")
- .execute()
- .assertJson(this.getClass(), "no_issue.json", false);
- }
-
@Test
public void ignore_paging_with_one_component() throws Exception {
RuleDto rule = newRule();
MockUserSession.set().setLogin("john");
WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam("resolved", "false")
- .setParam(SearchAction.PARAM_FACETS, "statuses,severities,resolutions,projectUuids,rules,componentUuids,assignees,languages,actionPlans")
+ .setParam(SearchAction.PARAM_FACETS, "statuses,severities,resolutions,projectUuids,rules,fileUuids,assignees,languages,actionPlans")
.execute();
result.assertJson(this.getClass(), "display_facets.json", false);
}
.setParam("resolved", "false")
.setParam("severities", "MAJOR,MINOR")
.setParam("languages", "xoo,polop,palap")
- .setParam(SearchAction.PARAM_FACETS, "statuses,severities,resolutions,projectUuids,rules,componentUuids,assignees,languages,actionPlans")
+ .setParam(SearchAction.PARAM_FACETS, "statuses,severities,resolutions,projectUuids,rules,fileUuids,assignees,languages,actionPlans")
.execute();
result.assertJson(this.getClass(), "display_zero_facets.json", false);
}
- @Test
- public void display_directory_facet() throws Exception {
- ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject"));
- setDefaultProjectPermission(project);
- ComponentDto directory = insertComponent(ComponentTesting.newDirectory(project, "src/main/java/dir"));
- ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent").setPath(directory.path() + "/MyComponent.java"));
- IssueDto issue = IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2");
- db.issueDao().insert(session, issue);
- session.commit();
- tester.get(IssueIndexer.class).indexAll();
-
- MockUserSession.set().setLogin("john");
- WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
- .setParam("resolved", "false")
- .setParam(SearchAction.PARAM_FACETS, "directories")
- .execute();
- result.assertJson(this.getClass(), "display_directory_facet.json", false);
- }
-
@Test
public void hide_rules() throws Exception {
ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject"));
--- /dev/null
+{
+ "facets": [
+ {
+ "property": "directories",
+ "values": [
+ {
+ "val": "src/main/java/dir",
+ "count": 1
+ }
+ ]
+ }
+ ]
+}
--- /dev/null
+{
+ "issues": [
+ {
+ "key": "82fd47d4-b650-4037-80bc-7b112bd4eac2",
+ "component": "MyComponent",
+ "project": "MyProject",
+ "rule": "xoo:x1",
+ "status": "OPEN",
+ "resolution": "OPEN",
+ "severity": "MAJOR",
+ "updateDate": "2017-12-04T00:00:00+0100",
+ "fUpdateAge": "less than a minute"
+ },
+ {
+ "key": "92fd47d4-b650-4037-80bc-7b112bd4eac2",
+ "component": "MyComponent2",
+ "project": "MyProject2",
+ "rule": "xoo:x1",
+ "status": "OPEN",
+ "resolution": "OPEN",
+ "severity": "MAJOR",
+ "updateDate": "2017-12-04T00:00:00+0100",
+ "fUpdateAge": "less than a minute"
+ }
+ ],
+ "components": [
+ {
+ "uuid": "BCDE",
+ "key": "MyComponent",
+ "enabled" : true
+ },
+ {
+ "uuid": "ABCD",
+ "key": "MyProject",
+ "enabled" : true
+ },
+ {
+ "uuid": "EDCB",
+ "key": "MyComponent2",
+ "enabled" : true
+ },
+ {
+ "uuid": "DBCA",
+ "key": "MyProject2",
+ "enabled" : true
+ }
+ ],
+ "projects": [
+ {
+ "uuid": "ABCD",
+ "key": "MyProject"
+ },
+ {
+ "uuid": "DBCA",
+ "key": "MyProject2"
+ }
+ ]
+}
--- /dev/null
+{
+ "total": 0,
+ "issues": []
+}
--- /dev/null
+{
+ "total": 1,
+ "p": 1,
+ "issues": [
+ {
+ "key": "82fd47d4-b650-4037-80bc-7b112bd4eac2",
+ "component": "module1:MyComponent",
+ "project": "MyProject",
+ "rule": "xoo:x1"
+ }
+ ]
+}
--- /dev/null
+{
+ "total": 1,
+ "p": 1,
+ "issues": [
+ {
+ "key": "82fd47d4-b650-4037-80bc-7b112bd4eac2",
+ "component": "MyComponent",
+ "project": "MyProject",
+ "rule": "xoo:x1"
+ }
+ ]
+}
--- /dev/null
+{
+ "total": 1,
+ "p": 1,
+ "ps": 100,
+ "issues": [
+ {
+ "key": "82fd47d4-b650-4037-80bc-7b112bd4eac2",
+ "component": "MyComponent",
+ "project": "MyProject",
+ "rule": "xoo:x1"
+ }
+ ]
+}
+++ /dev/null
-{
- "facets": [
- {
- "property": "directories",
- "values": [
- {
- "val": "src/main/java/dir",
- "count": 1
- }
- ]
- }
- ]
-}
]
},
{
- "property": "componentUuids",
+ "property": "fileUuids",
"values": [
{
"val": "BCDE",
]
},
{
- "property": "componentUuids",
+ "property": "fileUuids",
"values": [
{
"val": "BCDE",
+++ /dev/null
-{
- "issues": [
- {
- "key": "82fd47d4-b650-4037-80bc-7b112bd4eac2",
- "component": "MyComponent",
- "project": "MyProject",
- "rule": "xoo:x1",
- "status": "OPEN",
- "resolution": "OPEN",
- "severity": "MAJOR",
- "updateDate": "2017-12-04T00:00:00+0100",
- "fUpdateAge": "less than a minute"
- },
- {
- "key": "92fd47d4-b650-4037-80bc-7b112bd4eac2",
- "component": "MyComponent2",
- "project": "MyProject2",
- "rule": "xoo:x1",
- "status": "OPEN",
- "resolution": "OPEN",
- "severity": "MAJOR",
- "updateDate": "2017-12-04T00:00:00+0100",
- "fUpdateAge": "less than a minute"
- }
- ],
- "components": [
- {
- "uuid": "BCDE",
- "key": "MyComponent",
- "enabled" : true
- },
- {
- "uuid": "ABCD",
- "key": "MyProject",
- "enabled" : true
- },
- {
- "uuid": "EDCB",
- "key": "MyComponent2",
- "enabled" : true
- },
- {
- "uuid": "DBCA",
- "key": "MyProject2",
- "enabled" : true
- }
- ],
- "projects": [
- {
- "uuid": "ABCD",
- "key": "MyProject"
- },
- {
- "uuid": "DBCA",
- "key": "MyProject2"
- }
- ]
-}
+++ /dev/null
-{
- "total": 1,
- "p": 1,
- "issues": [
- {
- "key": "82fd47d4-b650-4037-80bc-7b112bd4eac2",
- "component": "MyComponent",
- "project": "MyProject",
- "rule": "xoo:x1"
- }
- ]
-}
+++ /dev/null
-{
- "total": 1,
- "p": 1,
- "ps": 100,
- "issues": [
- {
- "key": "82fd47d4-b650-4037-80bc-7b112bd4eac2",
- "component": "MyComponent",
- "project": "MyProject",
- "rule": "xoo:x1"
- }
- ]
-}