From 639148ae110d402bc4b9566cd27698af0a843fbc Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Lievremont Date: Mon, 9 Mar 2015 14:28:36 +0100 Subject: [PATCH] SONAR-6247 Add createdInLast parameter to search issues by lifetime --- .../sonar/server/issue/IssueQueryService.java | 31 ++++++++++------ .../issue/filter/IssueFilterParameters.java | 5 +-- .../sonar/server/issue/ws/SearchAction.java | 7 +++- .../server/issue/IssueQueryServiceTest.java | 36 ++++++++++++++++--- .../issue/ws/SearchActionMediumTest.java | 2 +- 5 files changed, 61 insertions(+), 20 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java index 0f738d16220..576cc5a587f 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java @@ -21,20 +21,20 @@ package org.sonar.server.issue; 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.base.*; import com.google.common.collect.Collections2; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.ObjectUtils; +import org.joda.time.DateTime; +import org.joda.time.format.ISOPeriodFormat; 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.api.utils.System2; import org.sonar.api.web.UserRole; import org.sonar.core.component.ComponentDto; import org.sonar.core.persistence.DbSession; @@ -48,10 +48,7 @@ import org.sonar.server.util.RubyUtils; import javax.annotation.CheckForNull; import javax.annotation.Nullable; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import static com.google.common.collect.Lists.newArrayList; @@ -65,10 +62,12 @@ public class IssueQueryService implements ServerComponent { private static final String UNKNOWN = ""; private final DbClient dbClient; private final ComponentService componentService; + private final System2 system; - public IssueQueryService(DbClient dbClient, ComponentService componentService) { + public IssueQueryService(DbClient dbClient, ComponentService componentService, System2 system) { this.dbClient = dbClient; this.componentService = componentService; + this.system = system; } public IssueQuery createFromMap(Map params) { @@ -91,7 +90,7 @@ public class IssueQueryService implements ServerComponent { .planned(RubyUtils.toBoolean(params.get(IssueFilterParameters.PLANNED))) .hideRules(RubyUtils.toBoolean(params.get(IssueFilterParameters.HIDE_RULES))) .createdAt(RubyUtils.toDate(params.get(IssueFilterParameters.CREATED_AT))) - .createdAfter(RubyUtils.toDate(params.get(IssueFilterParameters.CREATED_AFTER))) + .createdAfter(buildCreatedAfter(RubyUtils.toDate(params.get(IssueFilterParameters.CREATED_AFTER)), (String) params.get(IssueFilterParameters.CREATED_IN_LAST))) .createdBefore(RubyUtils.toDate(params.get(IssueFilterParameters.CREATED_BEFORE))); Set allComponentUuids = Sets.newHashSet(); @@ -135,6 +134,16 @@ public class IssueQueryService implements ServerComponent { } } + private Date buildCreatedAfter(@Nullable Date createdAfter, @Nullable String createdSince) { + Preconditions.checkArgument(createdAfter == null || createdSince == null, "createdAfter and createdSince cannot be set simultaneously"); + + Date actualCreatedAfter = createdAfter; + if (createdSince != null) { + actualCreatedAfter = new DateTime(system.now()).minus(ISOPeriodFormat.standard().parsePeriod("P" + createdSince.toUpperCase())).toDate(); + } + return actualCreatedAfter; + } + public IssueQuery createFromRequest(Request request) { DbSession session = dbClient.openSession(false); try { @@ -153,7 +162,7 @@ public class IssueQueryService implements ServerComponent { .assigned(request.paramAsBoolean(IssueFilterParameters.ASSIGNED)) .planned(request.paramAsBoolean(IssueFilterParameters.PLANNED)) .createdAt(request.paramAsDateTime(IssueFilterParameters.CREATED_AT)) - .createdAfter(request.paramAsDateTime(IssueFilterParameters.CREATED_AFTER)) + .createdAfter(buildCreatedAfter(request.paramAsDateTime(IssueFilterParameters.CREATED_AFTER), request.param(IssueFilterParameters.CREATED_IN_LAST))) .createdBefore(request.paramAsDateTime(IssueFilterParameters.CREATED_BEFORE)) .ignorePaging(request.paramAsBoolean(IssueFilterParameters.IGNORE_PAGING)); diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/filter/IssueFilterParameters.java b/server/sonar-server/src/main/java/org/sonar/server/issue/filter/IssueFilterParameters.java index 24c4b2b7ab8..d8fb99c16dc 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/filter/IssueFilterParameters.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/filter/IssueFilterParameters.java @@ -64,6 +64,7 @@ public class IssueFilterParameters { public static final String CREATED_AFTER = "createdAfter"; public static final String CREATED_AT = "createdAt"; public static final String CREATED_BEFORE = "createdBefore"; + public static final String CREATED_IN_LAST = "createdInLast"; public static final String PAGE_SIZE = "pageSize"; public static final String PAGE_INDEX = "pageIndex"; public static final String SORT = "sort"; @@ -73,8 +74,8 @@ public class IssueFilterParameters { public static final String FACET_ASSIGNED_TO_ME = "assigned_to_me"; public static final List 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_UUIDS, DIRECTORIES, FILE_UUIDS, AUTHORS, HIDE_COMMENTS); + ASSIGNEES, LANGUAGES, ASSIGNED, PLANNED, HIDE_RULES, CREATED_AT, CREATED_AFTER, CREATED_BEFORE, CREATED_IN_LAST, COMPONENT_UUIDS, COMPONENT_ROOT_UUIDS, + PROJECTS, PROJECT_UUIDS, IGNORE_PAGING, PROJECT_KEYS, COMPONENT_KEYS, MODULE_UUIDS, DIRECTORIES, FILE_UUIDS, AUTHORS, HIDE_COMMENTS, PAGE_SIZE, PAGE_INDEX, SORT, ASC); public static final List ALL_WITHOUT_PAGINATION = newArrayList(Iterables.filter(ALL, new Predicate() { @Override diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java index 35c1574850a..90be2256aba 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java @@ -187,11 +187,16 @@ public class SearchAction implements BaseIssuesWsAction { .setDescription("To retrieve issues created at a given date. Format: date or datetime ISO formats") .setExampleValue("2013-05-01 (or 2013-05-01T13:00:00+0100)"); action.createParam(IssueFilterParameters.CREATED_AFTER) - .setDescription("To retrieve issues created after the given date (exclusive). Format: date or datetime ISO formats") + .setDescription("To retrieve issues created after the given date (exclusive). Format: date or datetime ISO formats. If this parameter is set, createdSince must not be set") .setExampleValue("2013-05-01 (or 2013-05-01T13:00:00+0100)"); action.createParam(IssueFilterParameters.CREATED_BEFORE) .setDescription("To retrieve issues created before the given date (exclusive). Format: date or datetime ISO formats") .setExampleValue("2013-05-01 (or 2013-05-01T13:00:00+0100)"); + action.createParam(IssueFilterParameters.CREATED_IN_LAST) + .setDescription("To retrieve issues created during a time span before the current time (exclusive). " + + "Accepted units are 'y' for year, 'm' for month, 'w' for week and 'd' for day. " + + "If this parameter is set, createdAfter must not be set") + .setExampleValue("1m2w (1 month 2 weeks)"); action.createParam(IssueFilterParameters.IGNORE_PAGING) .setDescription("Return the full list of issues, regardless of paging. For internal use only") .setBooleanPossibleValues() diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueQueryServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/IssueQueryServiceTest.java index 1a301b8cc66..4e0db201be0 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueQueryServiceTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/IssueQueryServiceTest.java @@ -35,6 +35,7 @@ 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.api.utils.System2; import org.sonar.api.web.UserRole; import org.sonar.core.component.ComponentDto; import org.sonar.core.persistence.DbSession; @@ -44,10 +45,7 @@ import org.sonar.server.component.db.ComponentDao; import org.sonar.server.db.DbClient; import org.sonar.server.user.MockUserSession; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Map; +import java.util.*; import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Maps.newHashMap; @@ -78,6 +76,9 @@ public class IssueQueryServiceTest { @Mock ComponentService componentService; + @Mock + System2 system; + IssueQueryService issueQueryService; @Before @@ -94,7 +95,7 @@ public class IssueQueryServiceTest { } }); - issueQueryService = new IssueQueryService(dbClient, componentService); + issueQueryService = new IssueQueryService(dbClient, componentService, system); } @After @@ -434,4 +435,29 @@ public class IssueQueryServiceTest { IssueQuery query = issueQueryService.createFromMap(map); assertThat(query.fileUuids()).containsExactly(fileUuid); } + + @Test + public void fail_if_created_after_and_created_since_are_both_set() { + Map map = newHashMap(); + map.put("createdAfter", "2013-07-25T07:35:00+0100"); + map.put("createdInLast", "palap"); + + try { + issueQueryService.createFromMap(map); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("createdAfter and createdSince cannot be set simultaneously"); + } + } + + @Test + public void set_created_after_from_created_since() { + Date now = DateUtils.parseDateTime("2013-07-25T07:35:00+0100"); + when(system.now()).thenReturn(now.getTime()); + Map map = newHashMap(); + + map.put("createdInLast", "1y2m3w4d"); + assertThat(issueQueryService.createFromMap(map).createdAfter()).isEqualTo(DateUtils.parseDateTime("2012-04-30T07:35:00+0100")); + + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java index 79a5f5c0085..2595a65d48e 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java @@ -88,7 +88,7 @@ public class SearchActionMediumTest { assertThat(show.isPost()).isFalse(); assertThat(show.isInternal()).isFalse(); assertThat(show.responseExampleAsString()).isNotEmpty(); - assertThat(show.params()).hasSize(39); + assertThat(show.params()).hasSize(40); } @Test -- 2.39.5