aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-server
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@gmail.com>2013-05-27 16:44:07 +0200
committerJulien Lancelot <julien.lancelot@gmail.com>2013-05-27 16:44:07 +0200
commit97090aad19a494b36f7fc514f7eb60405bc6156f (patch)
tree79612e1dd982dd7a02d48071e29e98cbed649acf /sonar-server
parent3e4d1ad986e546bf6699ce12555218ac09f546ee (diff)
downloadsonarqube-97090aad19a494b36f7fc514f7eb60405bc6156f.tar.gz
sonarqube-97090aad19a494b36f7fc514f7eb60405bc6156f.zip
SONAR-4292 Create a IssueStatsFinder to be used by UnresolvedIssuesPerAssigneeWidget
Diffstat (limited to 'sonar-server')
-rw-r--r--sonar-server/src/main/java/org/sonar/server/issue/DefaultIssueFinder.java9
-rw-r--r--sonar-server/src/main/java/org/sonar/server/issue/DefaultIssueQueryResult.java166
-rw-r--r--sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java8
-rw-r--r--sonar-server/src/main/java/org/sonar/server/issue/IssueStatsFinder.java92
-rw-r--r--sonar-server/src/main/java/org/sonar/server/issue/PublicRubyIssueService.java2
-rw-r--r--sonar-server/src/main/java/org/sonar/server/platform/Platform.java1
-rw-r--r--sonar-server/src/test/java/org/sonar/server/issue/DefaultIssueFinderTest.java30
-rw-r--r--sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java3
-rw-r--r--sonar-server/src/test/java/org/sonar/server/issue/IssueStatsFinderTest.java54
9 files changed, 356 insertions, 9 deletions
diff --git a/sonar-server/src/main/java/org/sonar/server/issue/DefaultIssueFinder.java b/sonar-server/src/main/java/org/sonar/server/issue/DefaultIssueFinder.java
index f7682b6693c..fcdf4e5dbd6 100644
--- a/sonar-server/src/main/java/org/sonar/server/issue/DefaultIssueFinder.java
+++ b/sonar-server/src/main/java/org/sonar/server/issue/DefaultIssueFinder.java
@@ -32,7 +32,6 @@ import org.sonar.api.user.UserFinder;
import org.sonar.api.utils.Paging;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.issue.DefaultIssueComment;
-import org.sonar.core.issue.DefaultIssueQueryResult;
import org.sonar.core.issue.db.IssueChangeDao;
import org.sonar.core.issue.db.IssueDao;
import org.sonar.core.issue.db.IssueDto;
@@ -93,6 +92,7 @@ public class DefaultIssueFinder implements IssueFinder {
return dto.toDefaultIssue();
}
+ @Override
public IssueQueryResult find(IssueQuery query) {
LOG.debug("IssueQuery : {}", query);
SqlSession sqlSession = myBatis.openSession();
@@ -142,17 +142,14 @@ public class DefaultIssueFinder implements IssueFinder {
}
}
- DefaultIssueQueryResult defaultIssueQueryResult = new DefaultIssueQueryResult();
- defaultIssueQueryResult.setMaxResultsReached(authorizedIssues.size() == query.maxResults());
- defaultIssueQueryResult.setIssues(issues)
+ return new DefaultIssueQueryResult(issues)
+ .setMaxResultsReached(authorizedIssues.size() == query.maxResults())
.addRules(findRules(ruleIds))
.addComponents(findComponents(componentIds))
.addProjects(findProjects(projectIds))
.addActionPlans(findActionPlans(actionPlanKeys))
.addUsers(findUsers(users))
.setPaging(paging);
-
- return defaultIssueQueryResult;
} finally {
MyBatis.closeQuietly(sqlSession);
}
diff --git a/sonar-server/src/main/java/org/sonar/server/issue/DefaultIssueQueryResult.java b/sonar-server/src/main/java/org/sonar/server/issue/DefaultIssueQueryResult.java
new file mode 100644
index 00000000000..4a404362024
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/issue/DefaultIssueQueryResult.java
@@ -0,0 +1,166 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.Maps;
+import org.sonar.api.component.Component;
+import org.sonar.api.issue.ActionPlan;
+import org.sonar.api.issue.Issue;
+import org.sonar.api.issue.IssueQueryResult;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.user.User;
+import org.sonar.api.utils.Paging;
+
+import javax.annotation.CheckForNull;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+public class DefaultIssueQueryResult implements IssueQueryResult {
+
+ private List<Issue> issues;
+ private final Map<RuleKey, Rule> rulesByKey = Maps.newHashMap();
+ private final Map<String, Component> componentsByKey = Maps.newHashMap();
+ private final Map<String, Component> projectsByKey = Maps.newHashMap();
+ private final Map<String, ActionPlan> actionPlansByKey = Maps.newHashMap();
+ private final Map<String, User> usersByLogin = Maps.newHashMap();
+ private boolean maxResultsReached;
+ private Paging paging;
+
+ public DefaultIssueQueryResult(List<Issue> issues){
+ this.issues = issues;
+ }
+
+ public DefaultIssueQueryResult addRules(Collection<Rule> rules){
+ for (Rule rule : rules) {
+ rulesByKey.put(rule.ruleKey(), rule);
+ }
+ return this;
+ }
+
+ public DefaultIssueQueryResult addComponents(Collection<Component> components){
+ for (Component component : components) {
+ componentsByKey.put(component.key(), component);
+ }
+ return this;
+ }
+
+ public DefaultIssueQueryResult addProjects(Collection<Component> projects){
+ for (Component project : projects) {
+ projectsByKey.put(project.key(), project);
+ }
+ return this;
+ }
+
+ public DefaultIssueQueryResult addActionPlans(Collection<ActionPlan> actionPlans){
+ for (ActionPlan actionPlan : actionPlans) {
+ actionPlansByKey.put(actionPlan.key(), actionPlan);
+ }
+ return this;
+ }
+
+ public DefaultIssueQueryResult addUsers(Collection<User> users){
+ for (User user : users) {
+ usersByLogin.put(user.login(), user);
+ }
+ return this;
+ }
+
+ public DefaultIssueQueryResult setMaxResultsReached(boolean maxResultsReached){
+ this.maxResultsReached = maxResultsReached;
+ return this;
+ }
+
+ public DefaultIssueQueryResult setPaging(Paging paging){
+ this.paging = paging;
+ return this;
+ }
+
+ @Override
+ public List<Issue> issues() {
+ return issues;
+ }
+
+ @Override
+ public Rule rule(Issue issue) {
+ return rulesByKey.get(issue.ruleKey());
+ }
+
+ @Override
+ public Collection<Rule> rules() {
+ return rulesByKey.values();
+ }
+
+ @Override
+ public Component component(Issue issue) {
+ return componentsByKey.get(issue.componentKey());
+ }
+
+ @Override
+ public Collection<Component> components() {
+ return componentsByKey.values();
+ }
+
+ @Override
+ public Component project(Issue issue) {
+ return projectsByKey.get(issue.projectKey());
+ }
+
+ @Override
+ public Collection<Component> projects() {
+ return projectsByKey.values();
+ }
+
+ @Override
+ public ActionPlan actionPlan(Issue issue) {
+ return actionPlansByKey.get(issue.actionPlanKey());
+ }
+
+ @Override
+ public Collection<ActionPlan> actionPlans() {
+ return actionPlansByKey.values();
+ }
+
+ @Override
+ public Collection<User> users() {
+ return usersByLogin.values();
+ }
+
+ @Override
+ @CheckForNull
+ public User user(String login) {
+ return usersByLogin.get(login);
+ }
+
+ @Override
+ public boolean maxResultsReached() {
+ return maxResultsReached;
+ }
+
+ @Override
+ public Paging paging() {
+ return paging;
+ }
+
+
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java b/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java
index c81de2d16df..b6ee9e55fdc 100644
--- a/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java
+++ b/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java
@@ -55,18 +55,24 @@ public class InternalRubyIssueService implements ServerComponent {
private final IssueService issueService;
private final IssueCommentService commentService;
private final ActionPlanService actionPlanService;
+ private final IssueStatsFinder issueStatsFinder;
private final ResourceDao resourceDao;
public InternalRubyIssueService(IssueService issueService,
IssueCommentService commentService,
ActionPlanService actionPlanService,
- ResourceDao resourceDao) {
+ IssueStatsFinder issueStatsFinder, ResourceDao resourceDao) {
this.issueService = issueService;
this.commentService = commentService;
this.actionPlanService = actionPlanService;
+ this.issueStatsFinder = issueStatsFinder;
this.resourceDao = resourceDao;
}
+ public IssueStatsFinder.IssueStatsResult findIssueAssignees(Map<String, Object> params){
+ return issueStatsFinder.findIssueAssignees(PublicRubyIssueService.toQuery(params));
+ }
+
public List<Transition> listTransitions(String issueKey) {
return issueService.listTransitions(issueKey);
}
diff --git a/sonar-server/src/main/java/org/sonar/server/issue/IssueStatsFinder.java b/sonar-server/src/main/java/org/sonar/server/issue/IssueStatsFinder.java
new file mode 100644
index 00000000000..a19829113f0
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/issue/IssueStatsFinder.java
@@ -0,0 +1,92 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.issue.IssueQuery;
+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.platform.UserSession;
+
+import javax.annotation.CheckForNull;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+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);
+ }
+ }
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/issue/PublicRubyIssueService.java b/sonar-server/src/main/java/org/sonar/server/issue/PublicRubyIssueService.java
index 0b8909dd1d0..1832775006f 100644
--- a/sonar-server/src/main/java/org/sonar/server/issue/PublicRubyIssueService.java
+++ b/sonar-server/src/main/java/org/sonar/server/issue/PublicRubyIssueService.java
@@ -63,7 +63,7 @@ public class PublicRubyIssueService implements RubyIssueService {
return finder.find(toQuery(params));
}
- IssueQuery toQuery(Map<String, Object> props) {
+ static IssueQuery toQuery(Map<String, Object> props) {
IssueQuery.Builder builder = IssueQuery.builder();
builder.requiredRole(UserRole.CODEVIEWER);
builder.issueKeys(RubyUtils.toStrings(props.get("issues")));
diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
index a1605e29579..0691c29d5f2 100644
--- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
+++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
@@ -263,6 +263,7 @@ public final class Platform {
servicesContainer.addSingleton(IssueService.class);
servicesContainer.addSingleton(IssueCommentService.class);
servicesContainer.addSingleton(DefaultIssueFinder.class);
+ servicesContainer.addSingleton(IssueStatsFinder.class);
servicesContainer.addSingleton(PublicRubyIssueService.class);
servicesContainer.addSingleton(InternalRubyIssueService.class);
servicesContainer.addSingleton(ActionPlanService.class);
diff --git a/sonar-server/src/test/java/org/sonar/server/issue/DefaultIssueFinderTest.java b/sonar-server/src/test/java/org/sonar/server/issue/DefaultIssueFinderTest.java
index d3419a8082e..0123c9f1083 100644
--- a/sonar-server/src/test/java/org/sonar/server/issue/DefaultIssueFinderTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/issue/DefaultIssueFinderTest.java
@@ -19,6 +19,7 @@
*/
package org.sonar.server.issue;
+import com.google.common.collect.Lists;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import org.sonar.api.component.Component;
@@ -27,6 +28,7 @@ import org.sonar.api.issue.Issue;
import org.sonar.api.issue.IssueQuery;
import org.sonar.api.issue.IssueQueryResult;
import org.sonar.api.rules.Rule;
+import org.sonar.api.user.User;
import org.sonar.api.user.UserFinder;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.issue.DefaultActionPlan;
@@ -37,6 +39,7 @@ import org.sonar.core.persistence.MyBatis;
import org.sonar.core.resource.ResourceDao;
import org.sonar.core.rule.DefaultRuleFinder;
import org.sonar.core.user.AuthorizationDao;
+import org.sonar.core.user.DefaultUser;
import java.util.Collections;
import java.util.List;
@@ -48,6 +51,7 @@ import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyCollection;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.anyListOf;
import static org.mockito.Mockito.*;
public class DefaultIssueFinderTest {
@@ -242,6 +246,32 @@ public class DefaultIssueFinderTest {
}
@Test
+ public void should_get_user_from_result() {
+ when(userFinder.findByLogins(anyListOf(String.class))).thenReturn(Lists.<User>newArrayList(
+ new DefaultUser().setLogin("perceval").setName("Perceval"),
+ new DefaultUser().setLogin("arthur").setName("Roi Arthur")
+ ));
+
+ IssueQuery query = IssueQuery.builder().build();
+
+ IssueDto issue1 = new IssueDto().setId(1L).setRuleId(50).setComponentId(123).setRootComponentId(100).setKee("ABC").setAssignee("perceval")
+ .setRuleKey_unit_test_only("squid", "AvoidCycle")
+ .setStatus("OPEN").setResolution("OPEN");
+ IssueDto issue2 = new IssueDto().setId(2L).setRuleId(50).setComponentId(123).setRootComponentId(100).setKee("DEF").setReporter("arthur")
+ .setRuleKey_unit_test_only("squid", "AvoidCycle")
+ .setStatus("OPEN").setResolution("OPEN");
+ List<IssueDto> dtoList = newArrayList(issue1, issue2);
+ when(issueDao.selectByIds(anyCollection(), any(SqlSession.class))).thenReturn(dtoList);
+
+ IssueQueryResult results = finder.find(query);
+ assertThat(results.issues()).hasSize(2);
+
+ assertThat(results.users()).hasSize(2);
+ assertThat(results.user("perceval").name()).isEqualTo("Perceval");
+ assertThat(results.user("arthur").name()).isEqualTo("Roi Arthur");
+ }
+
+ @Test
public void should_get_empty_result_when_no_issue() {
IssueQuery query = IssueQuery.builder().build();
when(issueDao.selectIssues(eq(query), anyInt(), any(SqlSession.class))).thenReturn(Collections.<IssueDto>emptyList());
diff --git a/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java b/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java
index 24e5ebabe0c..f49177d8989 100644
--- a/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java
@@ -43,12 +43,13 @@ public class InternalRubyIssueServiceTest {
private IssueCommentService commentService = mock(IssueCommentService.class);
private ActionPlanService actionPlanService = mock(ActionPlanService.class);
private ResourceDao resourceDao = mock(ResourceDao.class);
+ private IssueStatsFinder issueStatsFinder = mock(IssueStatsFinder.class);
@Before
public void before() {
ResourceDto project = new ResourceDto().setKey("org.sonar.Sample");
when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(project);
- internalRubyIssueService = new InternalRubyIssueService(issueService, commentService, actionPlanService, resourceDao);
+ internalRubyIssueService = new InternalRubyIssueService(issueService, commentService, actionPlanService, issueStatsFinder, resourceDao);
}
@Test
diff --git a/sonar-server/src/test/java/org/sonar/server/issue/IssueStatsFinderTest.java b/sonar-server/src/test/java/org/sonar/server/issue/IssueStatsFinderTest.java
new file mode 100644
index 00000000000..15497ff2c2a
--- /dev/null
+++ b/sonar-server/src/test/java/org/sonar/server/issue/IssueStatsFinderTest.java
@@ -0,0 +1,54 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.issue.IssueQuery;
+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");
+ }
+}