@WidgetCategory({"Issues"})
public class UnresolvedIssuesPerAssigneeWidget extends CoreWidget {
public UnresolvedIssuesPerAssigneeWidget() {
- super("reviews_per_developer", "Unresolved issues per assignee", "/org/sonar/plugins/core/widgets/issues/unresolved_issues_per_assignee.html.erb");
+ super("reviews_per_developer", "Unresolved issues per assignee", "/Users/julienlancelot/Dev/Sources/sonarqube/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/issues/unresolved_issues_per_assignee.html.erb");
}
}
-<%
+<%
options = {}
options['resolved'] = 'false'
options['componentRoots'] = @project.key
options['createdAfter'] = Api::Utils.format_datetime(@dashboard_configuration.from_datetime)
options['createdBefore'] = Api::Utils.format_datetime(DateTime.now)
end
- results = Internal.issues.findIssueAssignees(options)
- assignees = results.results
+ issues_by_assignee = Internal.issues.findIssueAssignees(options)
- unless assignees.empty?
- issues_by_assignee = {}
- counter_no_assignee = 0
- assignees.each do |assignee|
- if assignee
- counter = issues_by_assignee[assignee]
- if counter
- issues_by_assignee[assignee] = counter+1
- else
- issues_by_assignee[assignee] = 1
- end
- else
- counter_no_assignee += 1
- end
+ unless issues_by_assignee.empty?
+ users = Internal.users_api.find({'logins', issues_by_assignee.keySet()})
+ users_by_login = {}
+ users.each do |u|
+ users_by_login[u.login()] = u
end
+
+ # puts "### " + users_by_login.inspect
+
+ counter_no_assignee = issues_by_assignee.get(nil)
counter_max = 0
- counter_max = issues_by_assignee.values.max unless issues_by_assignee.empty?
+ counter_max = issues_by_assignee.values().max unless issues_by_assignee.empty?
counter_max = counter_no_assignee if counter_no_assignee > counter_max
-
+
div_id = "unresolved-issues-per-assignee-widget-#{widget.id.to_s}"
end
%>
<h3><%= message('widget.reviews_per_developer.name') -%></h3>
-<% if assignees.size ==0 %>
+<% if issues_by_assignee.size ==0 %>
<span class="empty_widget"><%= message('issue_filter.no_issues') -%></span>
<% else %>
</thead>
<tbody>
<%
- issues_by_assignee.sort{|h1,h2| h2[1] <=> h1[1]}.each do |assignee, count|
+ issues_by_assignee.each do |assignee, count|
+ if assignee
%>
<tr class="<%= cycle 'even', 'odd', :name => (div_id) -%>">
<td class="max-width">
- <%= link_to results.user(assignee).name, url_for_issues(options.merge(:assignees => assignee)) -%>
+ <%= link_to users_by_login[assignee].name(), url_for_issues(options.merge(:assignees => assignee)) -%>
</td>
<td class="nowrap">
<%= '+' if @dashboard_configuration.selected_period? -%><%= count.to_s -%>
<% end %>
</tr>
<%
- end
- # And now show the unassigned issues counter
- unless counter_no_assignee==0
+ # And now show the unassigned issues counter
+ else
%>
<tr class="<%= cycle 'even', 'odd', :name => (div_id) -%>">
<td class="max-width">
</td>
<% end %>
</tr>
- <% end %>
+ <% end
+ end %>
</tbody>
</table>
private final IssueCommentService commentService;
private final IssueChangelogService changelogService;
private final ActionPlanService actionPlanService;
- private final IssueStatsFinder issueStatsFinder;
private final ResourceDao resourceDao;
private final ActionService actionService;
private final IssueFilterService issueFilterService;
IssueService issueService,
IssueCommentService commentService,
IssueChangelogService changelogService, ActionPlanService actionPlanService,
- IssueStatsFinder issueStatsFinder, ResourceDao resourceDao, ActionService actionService,
+ ResourceDao resourceDao, ActionService actionService,
IssueFilterService issueFilterService, IssueBulkChangeService issueBulkChangeService) {
this.issueService = issueService;
this.commentService = commentService;
this.changelogService = changelogService;
this.actionPlanService = actionPlanService;
- this.issueStatsFinder = issueStatsFinder;
this.resourceDao = resourceDao;
this.actionService = actionService;
this.issueFilterService = issueFilterService;
return issueService.getByKey(issueKey);
}
- public IssueStatsFinder.IssueStatsResult findIssueAssignees(Map<String, Object> params) {
- return issueStatsFinder.findIssueAssignees(toQuery(params));
+ public Map<String, Integer> findIssueAssignees(Map<String, Object> params) {
+ return issueService.findIssueAssignees(toQuery(params));
}
public List<Transition> listTransitions(String issueKey) {
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.issue.actionplan.ActionPlanService;
import org.sonar.server.issue.index.IssueIndex;
+import org.sonar.server.search.FacetValue;
import org.sonar.server.search.IndexClient;
import org.sonar.server.search.QueryContext;
import org.sonar.server.user.UserSession;
import javax.annotation.Nullable;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
+import java.util.*;
+
+import static com.google.common.collect.Maps.newLinkedHashMap;
public class IssueService implements ServerComponent {
private final IssueNotifications issueNotifications;
private final ActionPlanService actionPlanService;
private final RuleFinder ruleFinder;
- private final IssueDao issueDao;
+ private final IssueDao deprecatedIssueDao;
private final UserFinder userFinder;
private final PreviewCache dryRunCache;
IssueNotifications issueNotifications,
ActionPlanService actionPlanService,
RuleFinder ruleFinder,
- IssueDao issueDao,
+ IssueDao deprecatedIssueDao,
UserFinder userFinder,
PreviewCache dryRunCache) {
this.dbClient = dbClient;
this.actionPlanService = actionPlanService;
this.ruleFinder = ruleFinder;
this.issueNotifications = issueNotifications;
- this.issueDao = issueDao;
+ this.deprecatedIssueDao = deprecatedIssueDao;
this.userFinder = userFinder;
this.dryRunCache = dryRunCache;
}
// TODO result should be replaced by an aggregation object in IssueIndex
public RulesAggregation findRulesByComponent(String componentKey, @Nullable Date periodDate, DbSession session) {
RulesAggregation rulesAggregation = new RulesAggregation();
- for (RuleDto ruleDto : issueDao.findRulesByComponent(componentKey, periodDate, session)) {
+ for (RuleDto ruleDto : deprecatedIssueDao.findRulesByComponent(componentKey, periodDate, session)) {
rulesAggregation.add(ruleDto);
}
return rulesAggregation;
// TODO result should be replaced by an aggregation object in IssueIndex
public Multiset<String> findSeveritiesByComponent(String componentKey, @Nullable Date periodDate, DbSession session) {
Multiset<String> aggregation = HashMultiset.create();
- for (String severity : issueDao.findSeveritiesByComponent(componentKey, periodDate, session)) {
+ for (String severity : deprecatedIssueDao.findSeveritiesByComponent(componentKey, periodDate, session)) {
aggregation.add(severity);
}
return aggregation;
}
+ public Map<String, Integer> findIssueAssignees(IssueQuery query) {
+ Map<String, Integer> result = newLinkedHashMap();
+ List<FacetValue> facetValues = indexClient.get(IssueIndex.class).listAssignees(query);
+ for (FacetValue facetValue : facetValues) {
+ if (facetValue.getKey().equals("_notAssigned_")) {
+ result.put(null, facetValue.getValue());
+ } else {
+ result.put(facetValue.getKey(), facetValue.getValue());
+ }
+ }
+ return result;
+ }
+
public Issue getByKey(String key) {
return indexClient.get(IssueIndex.class).getByKey(key);
}
+++ /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;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import org.sonar.api.ServerComponent;
-import org.sonar.api.user.User;
-import org.sonar.api.user.UserFinder;
-import org.sonar.core.issue.db.IssueStatsColumn;
-import org.sonar.core.issue.db.IssueStatsDao;
-import org.sonar.server.user.UserSession;
-
-import javax.annotation.CheckForNull;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @since 3.6
- */
-public class IssueStatsFinder implements ServerComponent {
-
- private final IssueStatsDao issuestatsDao;
- private final UserFinder userFinder;
-
- public IssueStatsFinder(IssueStatsDao issuestatsDao, UserFinder userFinder) {
- this.issuestatsDao = issuestatsDao;
- this.userFinder = userFinder;
- }
-
- public IssueStatsResult findIssueAssignees(IssueQuery query) {
- List<Object> results = issuestatsDao.selectIssuesColumn(query, IssueStatsColumn.ASSIGNEE, UserSession.get().userId());
-
- Set<String> users = Sets.newHashSet();
- for (Object result : results) {
- if (result != null) {
- users.add((String) result);
- }
- }
-
- return new IssueStatsResult(results).addUsers(findUsers(users));
- }
-
- private Collection<User> findUsers(Set<String> logins) {
- return userFinder.findByLogins(Lists.newArrayList(logins));
- }
-
- public static class IssueStatsResult {
- private final Map<String, User> usersByLogin = Maps.newHashMap();
- private List<Object> results;
-
- public IssueStatsResult(List<Object> results) {
- this.results = results;
- }
-
- public IssueStatsResult addUsers(Collection<User> users) {
- for (User user : users) {
- usersByLogin.put(user.login(), user);
- }
- return this;
- }
-
- public List<Object> results() {
- return results;
- }
-
- @CheckForNull
- public User user(String login) {
- return usersByLogin.get(login);
- }
- }
-}
private void unplanIssues(DefaultActionPlan actionPlan, UserSession userSession) {
// Get all issues linked to this plan (need to disable pagination and authorization check)
IssueQuery query = IssueQuery.builder().actionPlans(Arrays.asList(actionPlan.key())).requiredRole(null).build();
+ // TODO use IssueService
List<IssueDto> dtos = issueDao.selectIssues(query);
IssueChangeContext context = IssueChangeContext.createUser(new Date(), userSession.login());
List<DefaultIssue> issues = newArrayList();
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.aggregations.AggregationBuilders;
+import org.elasticsearch.search.aggregations.bucket.missing.InternalMissing;
+import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
return null;
}
+ public List<FacetValue> listAssignees(IssueQuery query) {
+ QueryContext queryContext = new QueryContext().setPage(1, 0);
+
+ SearchRequestBuilder esSearch = getClient()
+ .prepareSearch(this.getIndexName())
+ .setTypes(this.getIndexType())
+ .setIndices(this.getIndexName());
+
+ QueryBuilder esQuery = QueryBuilders.matchAllQuery();
+ BoolFilterBuilder esFilter = getFilter(query, queryContext);
+ if (esFilter.hasClauses()) {
+ esSearch.setQuery(QueryBuilders.filteredQuery(esQuery, esFilter));
+ } else {
+ esSearch.setQuery(esQuery);
+ }
+ esSearch.addAggregation(AggregationBuilders.terms(IssueNormalizer.IssueField.ASSIGNEE.field())
+ .size(Integer.MAX_VALUE)
+ .field(IssueNormalizer.IssueField.ASSIGNEE.field()));
+ esSearch.addAggregation(AggregationBuilders.missing("notAssigned")
+ .field(IssueNormalizer.IssueField.ASSIGNEE.field()));
+
+ SearchResponse response = getClient().execute(esSearch);
+ Terms aggregation = (Terms) response.getAggregations().getAsMap().get(IssueNormalizer.IssueField.ASSIGNEE.field());
+ List<FacetValue> facetValues = newArrayList();
+ for (Terms.Bucket value : aggregation.getBuckets()) {
+ facetValues.add(new FacetValue(value.getKey(), (int) value.getDocCount()).setSort(FacetValue.Sort.BY_VALUE));
+ }
+ facetValues.add(new FacetValue("_notAssigned_", (int) ((InternalMissing) response.getAggregations().get("notAssigned")).getDocCount()));
+
+ return facetValues;
+ }
+
public Result<Issue> search(IssueQuery query, QueryContext options) {
SearchRequestBuilder esSearch = getClient()
.prepareSearch(this.getIndexName())
pico.addSingleton(FunctionExecutor.class);
pico.addSingleton(IssueWorkflow.class);
pico.addSingleton(IssueCommentService.class);
- pico.addSingleton(IssueStatsFinder.class);
pico.addSingleton(InternalRubyIssueService.class);
pico.addSingleton(IssueChangelogService.class);
pico.addSingleton(IssueNotifications.class);
@Mock
ResourceDao resourceDao;
- @Mock
- IssueStatsFinder issueStatsFinder;
-
@Mock
ActionService actionService;
public void setUp() {
ResourceDto project = new ResourceDto().setKey("org.sonar.Sample");
when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(project);
- service = new InternalRubyIssueService(issueService, commentService, changelogService, actionPlanService, issueStatsFinder, resourceDao, actionService,
+ service = new InternalRubyIssueService(issueService, commentService, changelogService, actionPlanService, resourceDao, actionService,
issueFilterService, issueBulkChangeService);
}
@Test
public void find_issue_assignees() throws Exception {
service.findIssueAssignees(ImmutableMap.<String, Object>of("issues", "ABCD"));
- verify(issueStatsFinder).findIssueAssignees(any(IssueQuery.class));
+ verify(issueService).findIssueAssignees(any(IssueQuery.class));
}
@Test
import java.util.Date;
import java.util.List;
+import java.util.Map;
import java.util.UUID;
import static org.fest.assertions.Assertions.assertThat;
assertThat(result).hasSize(1);
}
+ @Test
+ public void find_issue_assignees() throws Exception {
+ db.issueDao().insert(session,
+ IssueTesting.newDto(rule, file, project).setAssignee("steph"),
+ IssueTesting.newDto(rule, file, project).setAssignee("simon"),
+ IssueTesting.newDto(rule, file, project),
+ IssueTesting.newDto(rule, file, project).setAssignee("steph"));
+ session.commit();
+
+ Map<String, Integer> results = service.findIssueAssignees(IssueQuery.builder().build());
+
+ assertThat(results).hasSize(3);
+ assertThat(results.get("steph")).isEqualTo(2);
+ assertThat(results.get("simon")).isEqualTo(1);
+ assertThat(results.get(null)).isEqualTo(1);
+
+ assertThat(results.keySet().toArray()[0]).isEqualTo("steph");
+ assertThat(results.keySet().toArray()[1]).isEqualTo("simon");
+ assertThat(results.keySet().toArray()[2]).isNull();
+ }
+
private IssueDto newIssue() {
return new IssueDto()
.setIssueCreationDate(DateUtils.parseDate("2014-09-04"))
+++ /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;
-
-import com.google.common.collect.Lists;
-import org.junit.Test;
-import org.sonar.api.user.User;
-import org.sonar.api.user.UserFinder;
-import org.sonar.core.issue.db.IssueStatsDao;
-import org.sonar.core.user.DefaultUser;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Matchers.*;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class IssueStatsFinderTest {
-
- private IssueStatsDao issuestatsDao = mock(IssueStatsDao.class);
- private UserFinder userFinder = mock(UserFinder.class);
-
- @Test
- public void should_find_assignees(){
- when(issuestatsDao.selectIssuesColumn(any(IssueQuery.class), anyString(), anyInt())).thenReturn(Lists.<Object>newArrayList("perceval", "perceval", "arthur", null));
- when(userFinder.findByLogins(anyListOf(String.class))).thenReturn(Lists.<User>newArrayList(
- new DefaultUser().setLogin("perceval").setName("Perceval"),
- new DefaultUser().setLogin("arthur").setName("Roi Arthur")
- ));
-
- IssueStatsFinder issueStatsFinder = new IssueStatsFinder(issuestatsDao, userFinder);
- IssueStatsFinder.IssueStatsResult issueStatsResult = issueStatsFinder.findIssueAssignees(IssueQuery.builder().build());
- assertThat(issueStatsResult.results()).hasSize(4);
- assertThat(issueStatsResult.user("arthur").name()).isEqualTo("Roi Arthur");
- }
-}
import org.sonar.server.platform.BackendCleanup;
import org.sonar.server.rule.RuleTesting;
import org.sonar.server.rule.db.RuleDao;
+import org.sonar.server.search.FacetValue;
import org.sonar.server.search.IndexDefinition;
import org.sonar.server.search.QueryContext;
import org.sonar.server.search.Result;
-import org.sonar.server.search.SearchClient;
import org.sonar.server.tester.ServerTester;
import org.sonar.server.user.MockUserSession;
List<String> issueKeys = newArrayList();
for (int i = 0; i < numberOfIssues; i++) {
IssueDto issue = IssueTesting.newDto(rule, resource, project);
- issue.setIssueAttributes("attr" + i);
tester.get(IssueDao.class).insert(session, issue);
issueKeys.add(issue.getKey());
}
}
assertThat(index.countAll()).isEqualTo(numberOfIssues);
+ }
+
+ @Test
+ public void list_assignees() throws Exception {
+ db.issueDao().insert(session,
+ IssueTesting.newDto(rule, file, project).setAssignee("steph").setStatus(Issue.STATUS_OPEN),
+ IssueTesting.newDto(rule, file, project).setAssignee("simon").setStatus(Issue.STATUS_OPEN),
+ IssueTesting.newDto(rule, file, project).setStatus(Issue.STATUS_OPEN),
+ IssueTesting.newDto(rule, file, project).setAssignee("steph").setStatus(Issue.STATUS_OPEN),
+ // julien should not be returned as the issue is closed
+ IssueTesting.newDto(rule, file, project).setAssignee("julien").setStatus(Issue.STATUS_CLOSED)
+ );
+ session.commit();
+
+ List<FacetValue> results = index.listAssignees(IssueQuery.builder().statuses(newArrayList(Issue.STATUS_OPEN)).build());
+
+ assertThat(results).hasSize(3);
+ assertThat(results.get(0).getKey()).isEqualTo("steph");
+ assertThat(results.get(0).getValue()).isEqualTo(2);
+
+ assertThat(results.get(1).getKey()).isEqualTo("simon");
+ assertThat(results.get(1).getValue()).isEqualTo(1);
- SearchClient elastic = tester.get(SearchClient.class);
- IndicesStatsResponse stats = elastic.admin().indices().prepareStats(IndexDefinition.ISSUES.getIndexName()).get();
- System.out.println("stats = " + stats);
+ assertThat(results.get(2).getKey()).isEqualTo("_notAssigned_");
+ assertThat(results.get(2).getValue()).isEqualTo(1);
}
}
+++ /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.core.issue.db;
-
-import com.google.common.collect.ImmutableList;
-
-import java.util.List;
-
-public class IssueStatsColumn {
-
- private IssueStatsColumn() {
- // utility
- }
-
- public static final String ASSIGNEE = "ASSIGNEE";
-
- public static final List<String> ALL = ImmutableList.of(ASSIGNEE);
-
-}
+++ /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.core.issue.db;
-
-import org.apache.ibatis.session.SqlSession;
-import org.sonar.api.ServerComponent;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.server.issue.IssueQuery;
-
-import javax.annotation.Nullable;
-
-import java.util.List;
-
-/**
- * @since 3.6
- */
-public class IssueStatsDao implements ServerComponent {
-
- private final MyBatis mybatis;
-
- public IssueStatsDao(MyBatis mybatis) {
- this.mybatis = mybatis;
- }
-
- public List<Object> selectIssuesColumn(IssueQuery query, String column, @Nullable Integer userId) {
- SqlSession session = mybatis.openSession(false);
- try {
- IssueStatsMapper mapper = session.getMapper(IssueStatsMapper.class);
- return mapper.selectIssuesColumn(query, column, query.componentRoots(), userId, query.requiredRole());
- } finally {
- MyBatis.closeQuietly(session);
- }
- }
-}
+++ /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.core.issue.db;
-
-import org.apache.ibatis.annotations.Param;
-import org.sonar.server.issue.IssueQuery;
-
-import javax.annotation.Nullable;
-
-import java.util.Collection;
-import java.util.List;
-
-public interface IssueStatsMapper {
-
- List<Object> selectIssuesColumn(@Param("query") IssueQuery query, @Param("column") String column, @Param("componentRootKeys") Collection<String> componentRootKeys,
- @Nullable @Param("userId") Integer userId, @Param("role") String role);
-
-}
import org.sonar.core.dashboard.DashboardDao;
import org.sonar.core.duplication.DuplicationDao;
import org.sonar.core.graph.jdbc.GraphDao;
-import org.sonar.core.issue.db.ActionPlanDao;
-import org.sonar.core.issue.db.ActionPlanStatsDao;
-import org.sonar.core.issue.db.IssueChangeDao;
-import org.sonar.core.issue.db.IssueDao;
-import org.sonar.core.issue.db.IssueFilterDao;
-import org.sonar.core.issue.db.IssueFilterFavouriteDao;
-import org.sonar.core.issue.db.IssueStatsDao;
+import org.sonar.core.issue.db.*;
import org.sonar.core.notification.db.NotificationQueueDao;
import org.sonar.core.permission.PermissionDao;
import org.sonar.core.permission.PermissionTemplateDao;
import org.sonar.core.source.db.SnapshotSourceDao;
import org.sonar.core.technicaldebt.db.CharacteristicDao;
import org.sonar.core.template.LoadedTemplateDao;
-import org.sonar.core.user.AuthorDao;
-import org.sonar.core.user.AuthorizationDao;
-import org.sonar.core.user.GroupMembershipDao;
-import org.sonar.core.user.RoleDao;
-import org.sonar.core.user.UserDao;
+import org.sonar.core.user.*;
import java.util.List;
GraphDao.class,
GroupMembershipDao.class,
IssueDao.class,
- IssueStatsDao.class,
IssueChangeDao.class,
IssueFilterDao.class,
IssueFilterFavouriteDao.class,
loadMapper(conf, "org.sonar.core.permission.PermissionMapper");
Class<?>[] mappers = {ActivityMapper.class, ActiveDashboardMapper.class, AuthorMapper.class, DashboardMapper.class,
DependencyMapper.class, DuplicationMapper.class, GraphDtoMapper.class,
- IssueMapper.class, IssueAuthorizationMapper.class, IssueStatsMapper.class, IssueChangeMapper.class, IssueFilterMapper.class, IssueFilterFavouriteMapper.class,
+ IssueMapper.class, IssueAuthorizationMapper.class, IssueChangeMapper.class, IssueFilterMapper.class, IssueFilterFavouriteMapper.class,
LoadedTemplateMapper.class, MeasureFilterMapper.class, Migration44Mapper.class, PermissionTemplateMapper.class, PropertiesMapper.class, PurgeMapper.class,
ResourceKeyUpdaterMapper.class, ResourceIndexerMapper.class, ResourceSnapshotMapper.class, RoleMapper.class, RuleMapper.class,
SchemaMigrationMapper.class, SemaphoreMapper.class, UserMapper.class, GroupMapper.class, WidgetMapper.class, WidgetPropertyMapper.class,
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mappei.dtd">
-
-<mapper namespace="org.sonar.core.issue.db.IssueStatsMapper">
-
- <select id="selectIssuesColumn" parameterType="map" resultType="Object">
- SELECT
- <if test="'ASSIGNEE'.equals(column)">
- i.assignee
- </if>
- FROM issues i
- <include refid="org.sonar.core.issue.db.IssueMapper.selectQueryConditions"/>
- </select>
-
-</mapper>
+++ /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.core.issue.db;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.core.persistence.AbstractDaoTestCase;
-import org.sonar.server.issue.IssueQuery;
-
-import java.util.List;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class IssueStatsDaoTest extends AbstractDaoTestCase {
-
- IssueStatsDao dao;
-
- @Before
- public void createDao() {
- dao = new IssueStatsDao(getMyBatis());
- }
-
- @Test
- public void should_select_assignees(){
- setupData("should_select_assignees");
-
- IssueQuery query = IssueQuery.builder().requiredRole("user").build();
- List<Object> results = dao.selectIssuesColumn(query, IssueStatsColumn.ASSIGNEE, null);
- assertThat(results).hasSize(3);
- // 2 perceval, and one null
- assertThat(results).containsOnly("perceval", null);
- }
-}