aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java2
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/IssueDao.java13
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/issue/IssueMapper.xml29
-rw-r--r--sonar-core/src/test/java/org/sonar/core/issue/IssueDaoTest.java15
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/issue/IssueDaoTest/should_select_by_date_creation.xml23
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/issue/IssueDaoTest/should_select_returned_sorted_result.xml74
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQuery.java34
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/issue/IssueQueryTest.java51
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueQuery.java10
-rw-r--r--sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueQueryTest.java6
10 files changed, 252 insertions, 5 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java
index e4ae221f2eb..0d66c96f94d 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java
@@ -36,6 +36,7 @@ import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.issue.IssueDto;
import javax.annotation.Nullable;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
@@ -75,7 +76,6 @@ public class IssueTrackingDecorator implements Decorator {
// not in newIssues
addManualIssuesAndCloseResolvedOnes(openIssue);
-
closeResolvedStandardIssues(openIssue, issueKeys);
keepFalsePositiveIssues(openIssue);
reopenUnresolvedIssues(openIssue);
diff --git a/sonar-core/src/main/java/org/sonar/core/issue/IssueDao.java b/sonar-core/src/main/java/org/sonar/core/issue/IssueDao.java
index 4a190ba3449..faa60590ef8 100644
--- a/sonar-core/src/main/java/org/sonar/core/issue/IssueDao.java
+++ b/sonar-core/src/main/java/org/sonar/core/issue/IssueDao.java
@@ -35,6 +35,7 @@ import java.util.List;
import java.util.Map;
import static com.google.common.collect.Lists.newArrayList;
+import static com.google.common.collect.Maps.newHashMap;
/**
* @since 3.6
@@ -43,8 +44,11 @@ public class IssueDao implements BatchComponent, ServerComponent {
private final MyBatis mybatis;
+ private Map<String, String> avalailableSorts;
+
public IssueDao(MyBatis mybatis) {
this.mybatis = mybatis;
+ this.avalailableSorts = getAvalailableSorts();
}
public void insert(IssueDto issueDto) {
@@ -145,4 +149,13 @@ public class IssueDao implements BatchComponent, ServerComponent {
return session.selectList("org.sonar.core.issue.IssueMapper.selectByIds", params);
}
+ private Map<String, String> getAvalailableSorts() {
+ Map<String, String> availableSorts = newHashMap();
+ availableSorts.put("created", "i.created_at");
+ availableSorts.put("updated", "i.updated_at");
+ availableSorts.put("closed", "i.closed_at");
+ availableSorts.put("assignee", "i.assignee");
+ return availableSorts;
+ }
+
}
diff --git a/sonar-core/src/main/resources/org/sonar/core/issue/IssueMapper.xml b/sonar-core/src/main/resources/org/sonar/core/issue/IssueMapper.xml
index bad09e26d69..15e299742a3 100644
--- a/sonar-core/src/main/resources/org/sonar/core/issue/IssueMapper.xml
+++ b/sonar-core/src/main/resources/org/sonar/core/issue/IssueMapper.xml
@@ -196,13 +196,38 @@
<if test="rules != null and rules.size() > 0">
and (<foreach item="rule" index="index" collection="rules" open="(" separator=" or " close=")">r.plugin_name=#{rule.repository} and r.plugin_rule_key=#{rule.rule}</foreach>)
</if>
- <if test="createdAfter">
+ <if test="createdAfter != null">
and i.created_at &gt; #{createdAfter}
</if>
- <if test="createdBefore">
+ <if test="createdBefore != null">
and i.created_at &lt; #{createdBefore}
</if>
</where>
+ <if test="sort != null">
+ order by
+ <choose>
+ <when test="'created'.equals(sort)">
+ i.created_at
+ </when>
+ <when test="'updated'.equals(sort)">
+ i.updated_at
+ </when>
+ <when test="'closed'.equals(sort)">
+ i.closed_at
+ </when>
+ <when test="'assignee'.equals(sort)">
+ i.assignee_login
+ </when>
+ </choose>
+ <choose>
+ <when test="true.equals(asc)">
+ asc
+ </when>
+ <otherwise>
+ desc
+ </otherwise>
+ </choose>
+ </if>
</sql>
</mapper>
diff --git a/sonar-core/src/test/java/org/sonar/core/issue/IssueDaoTest.java b/sonar-core/src/test/java/org/sonar/core/issue/IssueDaoTest.java
index 3880b69cf9e..37dfa625f45 100644
--- a/sonar-core/src/test/java/org/sonar/core/issue/IssueDaoTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/issue/IssueDaoTest.java
@@ -178,7 +178,7 @@ public class IssueDaoTest extends AbstractDaoTestCase {
assertThat(dao.select(query)).hasSize(1);
query = IssueQuery.builder().createdBefore(DateUtils.parseDate("2013-04-17")).build();
- assertThat(dao.select(query)).hasSize(1);
+ assertThat(dao.select(query)).hasSize(2);
}
@Test
@@ -201,6 +201,18 @@ public class IssueDaoTest extends AbstractDaoTestCase {
}
@Test
+ public void should_select_sort_by_assignee() {
+ setupData("shared", "should_select_returned_sorted_result");
+
+ IssueQuery query = IssueQuery.builder().sort("assignee").asc(true).build();
+ List<IssueDto> results = newArrayList(dao.select(query));
+ assertThat(results).hasSize(3);
+ assertThat(results.get(0).getAssignee()).isEqualTo("arthur");
+ assertThat(results.get(1).getAssignee()).isEqualTo("henry");
+ assertThat(results.get(2).getAssignee()).isEqualTo("perceval");
+ }
+
+ @Test
public void should_select_issue_ids_and_components_ids() {
setupData("shared", "should_select_issue_ids_and_components_ids");
@@ -230,4 +242,5 @@ public class IssueDaoTest extends AbstractDaoTestCase {
assertThat(results).hasSize(3);
}
+
}
diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/IssueDaoTest/should_select_by_date_creation.xml b/sonar-core/src/test/resources/org/sonar/core/issue/IssueDaoTest/should_select_by_date_creation.xml
index 11fe9b857b8..e4d6cac1cd6 100644
--- a/sonar-core/src/test/resources/org/sonar/core/issue/IssueDaoTest/should_select_by_date_creation.xml
+++ b/sonar-core/src/test/resources/org/sonar/core/issue/IssueDaoTest/should_select_by_date_creation.xml
@@ -23,4 +23,27 @@
closed_at="2013-04-16"
/>
+ <issues
+ id="101"
+ kee="ABCDE"
+ resource_id="400"
+ rule_id="500"
+ severity="BLOCKER"
+ manual_severity="[false]"
+ manual_issue="[false]"
+ description="[null]"
+ line="200"
+ cost="4.2"
+ status="OPEN"
+ resolution="FIXED"
+ checksum="XXX"
+ user_login="arthur"
+ assignee_login="perceval"
+ author_login="[null]"
+ attributes="JIRA=FOO-1234"
+ created_at="2013-04-13"
+ updated_at="2013-04-13"
+ closed_at="2013-04-13"
+ />
+
</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/IssueDaoTest/should_select_returned_sorted_result.xml b/sonar-core/src/test/resources/org/sonar/core/issue/IssueDaoTest/should_select_returned_sorted_result.xml
new file mode 100644
index 00000000000..e77de4125c9
--- /dev/null
+++ b/sonar-core/src/test/resources/org/sonar/core/issue/IssueDaoTest/should_select_returned_sorted_result.xml
@@ -0,0 +1,74 @@
+<dataset>
+
+ <!-- rule 500 -->
+ <issues
+ id="100"
+ kee="ABCDE"
+ resource_id="400"
+ rule_id="500"
+ severity="BLOCKER"
+ manual_severity="[false]"
+ manual_issue="[false]"
+ description="[null]"
+ line="200"
+ cost="4.2"
+ status="OPEN"
+ resolution="FIXED"
+ checksum="XXX"
+ user_login="arthur"
+ assignee_login="arthur"
+ author_login="[null]"
+ attributes="JIRA=FOO-1234"
+ created_at="2013-04-16"
+ updated_at="2013-04-16"
+ closed_at="2013-04-16"
+ />
+
+ <issues
+ id="101"
+ kee="ABCDE"
+ resource_id="400"
+ rule_id="500"
+ severity="BLOCKER"
+ manual_severity="[false]"
+ manual_issue="[false]"
+ description="[null]"
+ line="200"
+ cost="4.2"
+ status="OPEN"
+ resolution="FIXED"
+ checksum="XXX"
+ user_login="arthur"
+ assignee_login="perceval"
+ author_login="[null]"
+ attributes="JIRA=FOO-1234"
+ created_at="2013-04-16"
+ updated_at="2013-04-16"
+ closed_at="2013-04-16"
+ />
+
+
+ <!-- rule 501 -->
+ <issues
+ id="102"
+ kee="ABCDE"
+ resource_id="400"
+ rule_id="501"
+ severity="BLOCKER"
+ manual_severity="[false]"
+ manual_issue="[false]"
+ description="[null]"
+ line="200"
+ cost="4.2"
+ status="OPEN"
+ resolution="FIXED"
+ checksum="XXX"
+ user_login="arthur"
+ assignee_login="henry"
+ author_login="[null]"
+ attributes="JIRA=FOO-1234"
+ created_at="2013-04-16"
+ updated_at="2013-04-16"
+ closed_at="2013-04-16"
+ />
+</dataset>
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQuery.java b/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQuery.java
index bde2cab4488..7ca75e4e14a 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQuery.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQuery.java
@@ -24,6 +24,7 @@ import com.google.common.base.Preconditions;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.sonar.api.rule.RuleKey;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
@@ -45,6 +46,8 @@ public class IssueQuery {
private final Collection<String> assignees;
private final Date createdAfter;
private final Date createdBefore;
+ private final String sort;
+ private final boolean asc;
// max results per page
private final int pageSize;
@@ -64,6 +67,8 @@ public class IssueQuery {
this.assignees = builder.assignees;
this.createdAfter = builder.createdAfter;
this.createdBefore = builder.createdBefore;
+ this.sort = builder.sort;
+ this.asc = builder.asc;
this.pageSize = builder.pageSize;
this.pageIndex = builder.pageIndex;
}
@@ -112,6 +117,14 @@ public class IssueQuery {
return createdBefore;
}
+ public String sort() {
+ return sort;
+ }
+
+ public boolean asc() {
+ return asc;
+ }
+
public int pageSize() {
return pageSize;
}
@@ -134,6 +147,11 @@ public class IssueQuery {
* @since 3.6
*/
public static class Builder {
+
+ private enum Sort {
+ created, updated, closed, assignee;
+ }
+
private static final int DEFAULT_PAGE_SIZE = 100;
private static final int MAX_PAGE_SIZE = 1000;
private static final int DEFAULT_PAGE_INDEX = 1;
@@ -149,6 +167,8 @@ public class IssueQuery {
private Collection<String> assignees;
private Date createdAfter;
private Date createdBefore;
+ private String sort;
+ private boolean asc = false;
private int pageSize = DEFAULT_PAGE_SIZE;
private int pageIndex = DEFAULT_PAGE_INDEX;
@@ -210,6 +230,20 @@ public class IssueQuery {
return this;
}
+ public Builder sort(String sort) {
+ try {
+ this.sort = Sort.valueOf(sort).name();
+ } catch (IllegalArgumentException e){
+ throw new IllegalArgumentException("Sort should contain only : " + Arrays.toString(Sort.values()), e);
+ }
+ return this;
+ }
+
+ public Builder asc(boolean asc) {
+ this.asc = asc;
+ return this;
+ }
+
public Builder pageSize(Integer i) {
Preconditions.checkArgument(i == null || i.intValue() > 0, "Page size must be greater than 0 (got " + i + ")");
Preconditions.checkArgument(i == null || i.intValue() < MAX_PAGE_SIZE, "Page size must be less than " + MAX_PAGE_SIZE + " (got " + i + ")");
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/issue/IssueQueryTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/issue/IssueQueryTest.java
index cb47aec4e18..9d8a9adbdcc 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/issue/IssueQueryTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/issue/IssueQueryTest.java
@@ -27,6 +27,7 @@ import org.sonar.api.rule.Severity;
import java.util.Date;
import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
public class IssueQueryTest {
@@ -44,6 +45,7 @@ public class IssueQueryTest {
.assignees(Lists.newArrayList("gargantua"))
.createdAfter(new Date())
.createdBefore(new Date())
+ .sort("assignee")
.pageSize(10)
.pageIndex(2)
.build();
@@ -58,7 +60,56 @@ public class IssueQueryTest {
assertThat(query.rules()).containsOnly(RuleKey.of("squid", "AvoidCycle"));
assertThat(query.createdAfter()).isNotNull();
assertThat(query.createdBefore()).isNotNull();
+ assertThat(query.sort()).isEqualTo("assignee");
assertThat(query.pageSize()).isEqualTo(10);
assertThat(query.pageIndex()).isEqualTo(2);
}
+
+ @Test
+ public void should_validate_page_size() throws Exception {
+ try {
+ IssueQuery.builder()
+ .pageSize(0)
+ .build();
+ fail();
+ } catch (Exception e) {
+ assertThat(e).hasMessage("Page size must be greater than 0 (got 0)").isInstanceOf(IllegalArgumentException.class);
+ }
+ }
+
+ @Test
+ public void should_validate_page_size_too_high() throws Exception {
+ try {
+ IssueQuery.builder()
+ .pageSize(10000)
+ .build();
+ fail();
+ } catch (Exception e) {
+ assertThat(e).hasMessage("Page size must be less than 1000 (got 10000)").isInstanceOf(IllegalArgumentException.class);
+ }
+ }
+
+ @Test
+ public void should_validate_page_index() throws Exception {
+ try {
+ IssueQuery.builder()
+ .pageIndex(0)
+ .build();
+ fail();
+ } catch (Exception e) {
+ assertThat(e).hasMessage("Page index must be greater than 0 (got 0)").isInstanceOf(IllegalArgumentException.class);
+ }
+ }
+
+ @Test
+ public void should_validate_sort() throws Exception {
+ try {
+ IssueQuery.builder()
+ .sort("INVALID SORT")
+ .build();
+ fail();
+ } catch (Exception e) {
+ assertThat(e).hasMessage("Sort should contain only : [created, updated, closed, assignee]").isInstanceOf(IllegalArgumentException.class);
+ }
+ }
}
diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueQuery.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueQuery.java
index 34b822230f5..e4d38dc3bef 100644
--- a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueQuery.java
+++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueQuery.java
@@ -90,6 +90,16 @@ public class IssueQuery {
return this;
}
+ public IssueQuery sort(String sort) {
+ params.put("sort", sort);
+ return this;
+ }
+
+ public IssueQuery asc(boolean asc) {
+ params.put("asc", asc);
+ return this;
+ }
+
public IssueQuery pageSize(int pageSize) {
params.put("pageSize", pageSize);
return this;
diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueQueryTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueQueryTest.java
index a82a6658f1b..4a37fed1e80 100644
--- a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueQueryTest.java
+++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueQueryTest.java
@@ -43,10 +43,12 @@ public class IssueQueryTest {
.statuses("OPEN", "CLOSED")
.severities("BLOCKER", "INFO")
.userLogins("login1", "login2")
+ .sort("assignee")
+ .asc(false)
.pageSize(5)
.pageIndex(4);
- assertThat(query.urlParams()).hasSize(11);
+ assertThat(query.urlParams()).hasSize(13);
assertThat(query.urlParams()).includes(entry("keys", "ABCDE,FGHIJ"));
assertThat(query.urlParams()).includes(entry("assignees", "arthur,perceval"));
assertThat(query.urlParams()).includes(entry("components", "Action.java,Filter.java"));
@@ -55,6 +57,8 @@ public class IssueQueryTest {
assertThat(query.urlParams()).includes(entry("statuses", "OPEN,CLOSED"));
assertThat(query.urlParams()).includes(entry("severities", "BLOCKER,INFO"));
assertThat(query.urlParams()).includes(entry("userLogins", "login1,login2"));
+ assertThat(query.urlParams()).includes(entry("sort", "assignee"));
+ assertThat(query.urlParams()).includes(entry("asc", false));
assertThat(query.urlParams()).includes(entry("pageSize", 5));
assertThat(query.urlParams()).includes(entry("pageIndex", 4));
}