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;
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;
private static final String UNKNOWN = "<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<String, Object> params) {
.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<String> allComponentUuids = Sets.newHashSet();
}
}
+ 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 {
.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));
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";
public static final String FACET_ASSIGNED_TO_ME = "assigned_to_me";
public static final List<String> 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<String> ALL_WITHOUT_PAGINATION = newArrayList(Iterables.filter(ALL, new Predicate<String>() {
@Override
.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()
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;
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;
@Mock
ComponentService componentService;
+ @Mock
+ System2 system;
+
IssueQueryService issueQueryService;
@Before
}
});
- issueQueryService = new IssueQueryService(dbClient, componentService);
+ issueQueryService = new IssueQueryService(dbClient, componentService, system);
}
@After
IssueQuery query = issueQueryService.createFromMap(map);
assertThat(query.fileUuids()).containsExactly(fileUuid);
}
+
+ @Test
+ public void fail_if_created_after_and_created_since_are_both_set() {
+ Map<String, Object> 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<String, Object> map = newHashMap();
+
+ map.put("createdInLast", "1y2m3w4d");
+ assertThat(issueQueryService.createFromMap(map).createdAfter()).isEqualTo(DateUtils.parseDateTime("2012-04-30T07:35:00+0100"));
+
+ }
}
assertThat(show.isPost()).isFalse();
assertThat(show.isInternal()).isFalse();
assertThat(show.responseExampleAsString()).isNotEmpty();
- assertThat(show.params()).hasSize(39);
+ assertThat(show.params()).hasSize(40);
}
@Test