import org.sonar.core.issue.IssueDto;
import javax.annotation.Nullable;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
// not in newIssues
addManualIssuesAndCloseResolvedOnes(openIssue);
-
closeResolvedStandardIssues(openIssue, issueKeys);
keepFalsePositiveIssues(openIssue);
reopenUnresolvedIssues(openIssue);
import java.util.Map;
import static com.google.common.collect.Lists.newArrayList;
+import static com.google.common.collect.Maps.newHashMap;
/**
* @since 3.6
private final MyBatis mybatis;
+ private Map<String, String> avalailableSorts;
+
public IssueDao(MyBatis mybatis) {
this.mybatis = mybatis;
+ this.avalailableSorts = getAvalailableSorts();
}
public void insert(IssueDto issueDto) {
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;
+ }
+
}
<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 > #{createdAfter}
</if>
- <if test="createdBefore">
+ <if test="createdBefore != null">
and i.created_at < #{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>
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
assertThat(dao.select(query)).hasSize(3);
}
+ @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");
assertThat(results).hasSize(3);
}
+
}
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>
--- /dev/null
+<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>
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;
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;
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;
}
return createdBefore;
}
+ public String sort() {
+ return sort;
+ }
+
+ public boolean asc() {
+ return asc;
+ }
+
public int pageSize() {
return pageSize;
}
* @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;
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;
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 + ")");
import java.util.Date;
import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
public class IssueQueryTest {
.assignees(Lists.newArrayList("gargantua"))
.createdAfter(new Date())
.createdBefore(new Date())
+ .sort("assignee")
.pageSize(10)
.pageIndex(2)
.build();
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);
+ }
+ }
}
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;
.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"));
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));
}