diff --git a/src/main/java/org/gitlab4j/api/EpicsApi.java b/src/main/java/org/gitlab4j/api/EpicsApi.java index 0366932e6855222b79239303462adaaf3809d8b7..42a5c3c221019d4b80a3b228eaa16cfa31a0f0b1 100644 --- a/src/main/java/org/gitlab4j/api/EpicsApi.java +++ b/src/main/java/org/gitlab4j/api/EpicsApi.java @@ -12,6 +12,7 @@ import javax.ws.rs.core.Response; import org.gitlab4j.api.models.ChildEpic; import org.gitlab4j.api.models.CreatedChildEpic; import org.gitlab4j.api.models.Epic; +import org.gitlab4j.api.models.EpicFilter; import org.gitlab4j.api.models.EpicIssue; import org.gitlab4j.api.models.EpicIssueLink; import org.gitlab4j.api.models.LinkType; @@ -54,7 +55,7 @@ public class EpicsApi extends AbstractApi { * * @param groupIdOrPath the group ID, path of the group, or a Group instance holding the group ID or path * @param page the page to get - * @param perPage the number of issues per page + * @param perPage the number of epics per page * @return a list of all epics of the requested group and its subgroups in the specified range * @throws GitLabApiException if any exception occurs */ @@ -69,7 +70,7 @@ public class EpicsApi extends AbstractApi { *
GitLab Endpoint: GET /groups/:id/epics
* * @param groupIdOrPath the group ID, path of the group, or a Group instance holding the group ID or path - * @param itemsPerPage the number of issues per page + * @param itemsPerPage the number of epics per page * @return the Pager of all epics of the requested group and its subgroups * @throws GitLabApiException if any exception occurs */ @@ -123,20 +124,28 @@ public class EpicsApi extends AbstractApi { * @param sortOrder return epics sorted in ASC or DESC order. Default is DESC * @param search search epics against their title and description * @param page the page to get - * @param perPage the number of issues per page + * @param perPage the number of epics per page * @return a list of matching epics of the requested group and its subgroups in the specified range * @throws GitLabApiException if any exception occurs */ public List getEpics(Object groupIdOrPath, Long authorId, String labels, EpicOrderBy orderBy, SortOrder sortOrder, String search, int page, int perPage) throws GitLabApiException { - GitLabApiForm formData = new GitLabApiForm(page, perPage) - .withParam("author_id", authorId) - .withParam("labels", labels) - .withParam("order_by", orderBy) - .withParam("sort", sortOrder) - .withParam("search", search); - Response response = get(Response.Status.OK, formData.asMap(), "groups", getGroupIdOrPath(groupIdOrPath), "epics"); - return (response.readEntity(new GenericType>() { })); + EpicFilter filter = createEpicFilter(authorId, labels, orderBy, sortOrder, search); + return getEpics(groupIdOrPath, filter); + } + + /** + * Gets all epics of the requested group and its subgroups using the specified page and per page setting. + * + *
GitLab Endpoint: GET /groups/:id/epics
+ * + * @param groupIdOrPath the group ID, path of the group, or a Group instance holding the group ID or path + * @param filter epic filter + * @return a list of matching epics of the requested group and its subgroups in the specified range + * @throws GitLabApiException if any exception occurs + */ + public List getEpics(Object groupIdOrPath, EpicFilter filter) throws GitLabApiException { + return getEpics(groupIdOrPath, getDefaultPerPage(), filter).all(); } /** @@ -148,7 +157,7 @@ public class EpicsApi extends AbstractApi { * @param authorId returns epics created by the given user id * @param labels return epics matching a comma separated list of labels names. * Label names from the epic group or a parent group can be used - * @param itemsPerPage the number of issues per page + * @param itemsPerPage the number of epics per page * @param orderBy return epics ordered by CREATED_AT or UPDATED_AT. Default is CREATED_AT * @param sortOrder return epics sorted in ASC or DESC order. Default is DESC * @param search search epics against their title and description @@ -157,13 +166,32 @@ public class EpicsApi extends AbstractApi { */ public Pager getEpics(Object groupIdOrPath, Long authorId, String labels, EpicOrderBy orderBy, SortOrder sortOrder, String search, int itemsPerPage) throws GitLabApiException { - GitLabApiForm formData = new GitLabApiForm() - .withParam("author_id", authorId) - .withParam("labels", labels) - .withParam("order_by", orderBy) - .withParam("sort", sortOrder) - .withParam("search", search); - return (new Pager(this, Epic.class, itemsPerPage, formData.asMap(), "groups", getGroupIdOrPath(groupIdOrPath), "epics")); + EpicFilter filter = createEpicFilter(authorId, labels, orderBy, sortOrder, search); + return getEpics(groupIdOrPath, itemsPerPage, filter); + } + + /** + * Gets all epics of the requested group and its subgroups using the specified page and per page setting. + * + *
GitLab Endpoint: GET /groups/:id/epics
+ * + * @param groupIdOrPath the group ID, path of the group, or a Group instance holding the group ID or path + * @param filter epic filter + * @param itemsPerPage the number of epics per page + * @return a list of matching epics of the requested group and its subgroups in the specified range + * @throws GitLabApiException if any exception occurs + */ + public Pager getEpics(Object groupIdOrPath, int itemsPerPage, EpicFilter filter) throws GitLabApiException { + return (new Pager(this, Epic.class, itemsPerPage, filter.getQueryParams().asMap(), "groups", getGroupIdOrPath(groupIdOrPath), "epics")); + } + + private EpicFilter createEpicFilter(Long authorId, String labels, EpicOrderBy orderBy, SortOrder sortOrder, String search) { + return new EpicFilter() + .withAuthorId(authorId) + .withLabels(labels) + .withOrderBy(orderBy) + .withSortOrder(sortOrder) + .withSearch(search); } /** @@ -369,7 +397,7 @@ public class EpicsApi extends AbstractApi { * @param groupIdOrPath the group ID, path of the group, or a Group instance holding the group ID or path * @param epicIid the IID of the epic to get issues for * @param page the page to get - * @param perPage the number of issues per page + * @param perPage the number of epics per page * @return a list of all issues belonging to the specified epic in the specified range * @throws GitLabApiException if any exception occurs */ @@ -385,7 +413,7 @@ public class EpicsApi extends AbstractApi { * * @param groupIdOrPath the group ID, path of the group, or a Group instance holding the group ID or path * @param epicIid the IID of the epic to get issues for - * @param itemsPerPage the number of issues per page + * @param itemsPerPage the number of epics per page * @return the Pager of all issues belonging to the specified epic * @throws GitLabApiException if any exception occurs */ diff --git a/src/main/java/org/gitlab4j/api/GitLabApiForm.java b/src/main/java/org/gitlab4j/api/GitLabApiForm.java index b9c09e608b410654f9c5fac8193307e06b490293..f58deeb198f57a8a2f2fe9169d10084ba93584fe 100644 --- a/src/main/java/org/gitlab4j/api/GitLabApiForm.java +++ b/src/main/java/org/gitlab4j/api/GitLabApiForm.java @@ -159,8 +159,7 @@ public class GitLabApiForm extends Form { for (Entry variable : variables.entrySet()) { Object value = variable.getValue(); if (value != null) { - this.param(name + "[][key]", variable.getKey()); - this.param(name + "[][value]", value.toString()); + this.param(name + "[" + variable.getKey() + "]", value.toString()); } } diff --git a/src/main/java/org/gitlab4j/api/models/EpicFilter.java b/src/main/java/org/gitlab4j/api/models/EpicFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..a30bf0bd0c87b38541f48dd6a6fb07f9aca447b3 --- /dev/null +++ b/src/main/java/org/gitlab4j/api/models/EpicFilter.java @@ -0,0 +1,293 @@ +package org.gitlab4j.api.models; + +import org.gitlab4j.api.Constants.EpicOrderBy; +import org.gitlab4j.api.Constants.SortOrder; + +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.gitlab4j.api.GitLabApiForm; +import org.gitlab4j.api.models.AbstractEpic.EpicState; +import org.gitlab4j.api.utils.ISO8601; +import org.gitlab4j.api.utils.JacksonJsonEnumHelper; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * This class is used to filter Groups when getting lists of epics. + */ +public class EpicFilter { + + private Long authorId; + private String authorUsername; + private String labels; + private EpicOrderBy orderBy; + private SortOrder sort; + private String search; + private EpicState state; + private Date createdAfter; + private Date updatedAfter; + private Date updatedBefore; + private Boolean includeAncestorGroups; + private Boolean includeDescendantGroups; + private String myReactionEmoji; + private Map not; + + public enum EpicField { + + AUTHOR_ID, AUTHOR_USERNAME, LABELS; + + private static JacksonJsonEnumHelper enumHelper = new JacksonJsonEnumHelper<>(EpicField.class); + + @JsonCreator + public static EpicField forValue(String value) { + return enumHelper.forValue(value); + } + + @JsonValue + public String toValue() { + return (enumHelper.toString(this)); + } + + @Override + public String toString() { + return (enumHelper.toString(this)); + } + } + + /** + * Add 'author id' filter. + * + * @param authorId the author id filter + * @return the reference to this EpicFilter instance + */ + public EpicFilter withAuthorId(Long authorId) { + this.authorId = authorId; + return (this); + } + + /** + * Add 'author username' filter. + * + * @param authorUsername the 'author username' filter + * @return the reference to this EpicFilter instance + */ + public EpicFilter withAuthorUsername(String authorUsername) { + this.authorUsername = authorUsername; + return (this); + } + + /** + * Add 'labels' filter. + * + * @param labels the labels filter + * @return the reference to this EpicFilter instance + */ + public EpicFilter withLabels(String labels) { + this.labels = labels; + return (this); + } + + /** + * Add 'order by' filter. + * + * @param orderBy the 'order by' filter + * @return the reference to this GroupFilter instance + */ + public EpicFilter withOrderBy(EpicOrderBy orderBy) { + this.orderBy = orderBy; + return (this); + } + + /** + * Add 'sort' filter. + * + * @param sort sort direction, ASC or DESC + * @return the reference to this GroupFilter instance + */ + public EpicFilter withSortOrder(SortOrder sort) { + this.sort = sort; + return (this); + } + + /** + * Add 'search' filter. + * + * @param search the 'search' filter + * @return the reference to this EpicFilter instance + */ + public EpicFilter withSearch(String search) { + this.search = search; + return (this); + } + + /** + * Add 'state' filter. + * + * @param state the 'state' filter + * @return the reference to this EpicFilter instance + */ + public EpicFilter withState(EpicState state) { + this.state = state; + return (this); + } + + /** + * Add 'created after' filter. + * + * @param createdAfter the 'created after' filter + * @return the reference to this EpicFilter instance + */ + public EpicFilter withCreatedAfter(Date createdAfter) { + this.createdAfter = createdAfter; + return (this); + } + + /** + * Add 'updated after' filter. + * + * @param updatedAfter the 'updated after' filter + * @return the reference to this EpicFilter instance + */ + public EpicFilter withUpdatedAfter(Date updatedAfter) { + this.updatedAfter = updatedAfter; + return (this); + } + + /** + * Add 'updated before' filter. + * + * @param updatedBefore the 'updated before' filter + * @return the reference to this EpicFilter instance + */ + public EpicFilter withUpdatedBefore(Date updatedBefore) { + this.updatedBefore = updatedBefore; + return (this); + } + + /** + * Add 'include ancestor groups' filter. + * + * @param includeAncestorGroups the 'include ancestor groups' filter + * @return the reference to this EpicFilter instance + */ + public EpicFilter withIncludeAncestorGroups(Boolean includeAncestorGroups) { + this.includeAncestorGroups = includeAncestorGroups; + return (this); + } + + /** + * Add 'include descendant groups' filter. + * + * @param includeDescendantGroups the 'include descendant groups' filter + * @return the reference to this EpicFilter instance + */ + public EpicFilter withIncludeDescendantGroups(Boolean includeDescendantGroups) { + this.includeDescendantGroups = includeDescendantGroups; + return (this); + } + + /** + * Add 'my reaction emoji' filter. + * + * @param myReactionEmoji the 'my reaction emoji' filter + * @return the reference to this EpicFilter instance + */ + public EpicFilter withMyReactionEmoji(String myReactionEmoji) { + this.myReactionEmoji = myReactionEmoji; + return (this); + } + + /** + * Add 'not' filter. + * + * @param not the 'not' filter + * @return the reference to this EpicFilter instance + */ + public EpicFilter withNot(Map not) { + this.not = not; + return (this); + } + + /** + * Add author_id to the 'not' filter entry. + * + * @param authorId the id of the author to add to the filter + * @return the reference to this EpicFilter instance + */ + public EpicFilter withoutAuthorId(Long authorId) { + return withNot(EpicField.AUTHOR_ID, authorId); + } + + /** + * Add author_username to the 'not' filter entry. + * + * @param authorUsername the username of the author to add to the filter + * @return the reference to this EpicFilter instance + */ + public EpicFilter withoutAuthorUsername(String authorUsername) { + return withNot(EpicField.AUTHOR_USERNAME, authorUsername); + } + + /** + * Add labels to the 'not' filter entry. + * + * @param labels the labels to add to the filter + * @return the reference to this EpicFilter instance + */ + public EpicFilter withoutLabels(String... labels) { + return withNot(EpicField.LABELS, String.join(",", labels)); + } + + /** + * Add 'not' filter entry. + * + * @param field the field to be added to the 'not' value + * @param value the value for the entry + * @return the reference to this EpicFilter instance + */ + public EpicFilter withNot(EpicField field, Object value) { + if(not == null) { + not = new LinkedHashMap<>(); + } + not.put(field, value); + return (this); + } + + /** + * Get the query params specified by this filter. + * + * @return a GitLabApiForm instance holding the query parameters for this GroupFilter instance + */ + public GitLabApiForm getQueryParams() { + return (new GitLabApiForm() + .withParam("author_id", authorId) + .withParam("author_username", authorUsername) + .withParam("labels", labels) + .withParam("order_by", orderBy) + .withParam("sort", sort) + .withParam("search", search) + .withParam("state", state) + .withParam("created_after", ISO8601.toString(createdAfter, false)) + .withParam("updated_after", ISO8601.toString(updatedAfter, false)) + .withParam("updated_before", ISO8601.toString(updatedBefore, false)) + .withParam("include_ancestor_groups", includeAncestorGroups) + .withParam("include_descendant_groups", includeDescendantGroups) + .withParam("my_reaction_emoji", myReactionEmoji) + .withParam("not", toStringMap(not), false) + ); + } + + private Map toStringMap(Map map) { + if(map == null) { + return null; + } + Map result = new LinkedHashMap<>(); + for (Map.Entry entry : map.entrySet()) { + result.put(entry.getKey().toString(), entry.getValue()); + } + return result; + } +}