From cb7648877ea9834348deab134b921af7d9a9268d Mon Sep 17 00:00:00 2001 From: Greg Messner Date: Tue, 1 Oct 2019 17:35:35 -0700 Subject: [PATCH] Mods to prepare TodosApi for release (#441). --- src/main/java/org/gitlab4j/api/Constants.java | 10 +- src/main/java/org/gitlab4j/api/IssuesApi.java | 23 ++ src/main/java/org/gitlab4j/api/TodosApi.java | 185 ++++----- .../java/org/gitlab4j/api/models/Todo.java | 372 ++++-------------- 4 files changed, 181 insertions(+), 409 deletions(-) diff --git a/src/main/java/org/gitlab4j/api/Constants.java b/src/main/java/org/gitlab4j/api/Constants.java index 2192ddfd..126d545e 100644 --- a/src/main/java/org/gitlab4j/api/Constants.java +++ b/src/main/java/org/gitlab4j/api/Constants.java @@ -691,7 +691,7 @@ public interface Constants { } } - /** Enum to use for specifying the action when doing a getTodos() with the TodoApi. */ + /** Enum to use for specifying the action when doing a getTodos() with the TodosApi. */ public enum TodoAction { ASSIGNED, MENTIONED, BUILD_FAILED, MARKED, APPROVAL_REQUIRED, UNMERGEABLE, DIRECTLY_ADDRESSED; @@ -714,7 +714,7 @@ public interface Constants { } } - /** Enum to use for specifying the state when doing a getTodos() with the TodoApi. */ + /** Enum to use for specifying the state when doing a getTodos() with the TodosApi. */ public enum TodoState { PENDING, DONE; @@ -737,12 +737,12 @@ public interface Constants { } } - /** Enum to use for specifying the type when doing a getTodos() with the TodoApi. */ + /** Enum to use for specifying the type when doing a getTodos() with the TodosApi. */ public enum TodoType { - ISSUE, MERGEREQUEST; + ISSUE, MERGE_REQUEST; - private static JacksonJsonEnumHelper enumHelper = new JacksonJsonEnumHelper<>(TodoType.class); + private static JacksonJsonEnumHelper enumHelper = new JacksonJsonEnumHelper<>(TodoType.class, true, true); @JsonCreator public static TodoType forValue(String value) { diff --git a/src/main/java/org/gitlab4j/api/IssuesApi.java b/src/main/java/org/gitlab4j/api/IssuesApi.java index 49b6453a..d56e14fc 100644 --- a/src/main/java/org/gitlab4j/api/IssuesApi.java +++ b/src/main/java/org/gitlab4j/api/IssuesApi.java @@ -1,5 +1,6 @@ package org.gitlab4j.api; +import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Optional; @@ -412,6 +413,28 @@ public class IssuesApi extends AbstractApi implements Constants { return (response.readEntity(Issue.class)); } + /** + * Updates an existing project issue. This call can also be used to mark an issue as closed. + * + *
GitLab Endpoint: PUT /projects/:id/issues/:issue_iid
+ * + * @param projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance, required + * @param issueIid the issue IID to update, required + * @param assigneeId the ID of the user to assign issue to, required + * @return an instance of the updated Issue + * @throws GitLabApiException if any exception occurs + */ + public Issue assignIssue(Object projectIdOrPath, Integer issueIid, Integer assigneeId) throws GitLabApiException { + + if (issueIid == null) { + throw new RuntimeException("issue IID cannot be null"); + } + + GitLabApiForm formData = new GitLabApiForm().withParam("assignee_ids", Collections.singletonList(assigneeId)); + Response response = put(Response.Status.OK, formData.asMap(), "projects", getProjectIdOrPath(projectIdOrPath), "issues", issueIid); + return (response.readEntity(Issue.class)); + } + /** * Delete an issue. * diff --git a/src/main/java/org/gitlab4j/api/TodosApi.java b/src/main/java/org/gitlab4j/api/TodosApi.java index f4f15e52..2e715b3b 100644 --- a/src/main/java/org/gitlab4j/api/TodosApi.java +++ b/src/main/java/org/gitlab4j/api/TodosApi.java @@ -1,35 +1,12 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2017 Greg Messner - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - package org.gitlab4j.api; -import org.gitlab4j.api.models.Todo; - -import javax.ws.rs.core.GenericType; -import javax.ws.rs.core.Response; import java.util.List; import java.util.stream.Stream; +import javax.ws.rs.core.Response; + +import org.gitlab4j.api.models.Todo; + /** * This class implements the client side API for the GitLab Todos API. */ @@ -40,140 +17,150 @@ public class TodosApi extends AbstractApi { } /** - * Get a list of all pending todos for the current user. + * Get a List of pending todos for the current user. * *
GitLab Endpoint: GET /todos
* - * @return a list of pages in todo + * @return a List of pending Todos for the current user * @throws GitLabApiException if any exception occurs */ - public List getTodos() throws GitLabApiException { - return (getTodos(null, null, null, null, null, null, getDefaultPerPage()).all()); + public List getPendingTodos() throws GitLabApiException { + return (getTodos(null, null, null, null, TodoState.PENDING, null, getDefaultPerPage()).all()); } /** - * Get a list of pages in all pending todos for the current user. + * Get a Pager of pending todos for the current user. * *
GitLab Endpoint: GET /todos
* - * @param page the page to get - * @param perPage the number of todo-pages per page - * @return a list of pages in todo for the specified range + * @param itemsPerPage the number of todo that will be fetched per page + * @return a Pager containing the pending Todos for the current user * @throws GitLabApiException if any exception occurs */ - public List getTodos(int page, int perPage) throws GitLabApiException { - return (getTodos(null, null, null, null, null, null, page, perPage)); + public Pager getPendingTodos(int itemsPerPage) throws GitLabApiException { + return (getTodos(null, null, null, null, TodoState.PENDING, null, itemsPerPage)); } /** - * Get a list of all todos for the current user. + * Get a Stream of pending todos for the current user. * *
GitLab Endpoint: GET /todos
* - * @param itemsPerPage the number of todo that will be fetched per page - * @return a Pager containing the Todos for the user + * @return a Stream containing the pending Todos for the user + * @throws GitLabApiException if any exception occurs + */ + public Stream getPendingTodosStream() throws GitLabApiException { + return (getTodos(null, null, null, null, TodoState.PENDING, null, getDefaultPerPage()).stream()); + } + + /** + * Get a List of done todos for the current user. + * + *
GitLab Endpoint: GET /todos
+ * + * @return a List of done Todos for the current user * @throws GitLabApiException if any exception occurs */ - public Pager getTodos(int itemsPerPage) throws GitLabApiException { - return (getTodos(null, null, null, null, null, null, itemsPerPage)); + public List getDoneTodos() throws GitLabApiException { + return (getTodos(null, null, null, null, TodoState.DONE, null, getDefaultPerPage()).all()); } /** - * Returns a list of todos. When no filter is applied, - * it returns all pending todos for the current user. - * Different filters allow the user to precise the request. + * Get a Pager of done todos for the current user. * *
GitLab Endpoint: GET /todos
* - * @param action the action to be filtered. Can be assigned, mentioned, build_failed, marked, approval_required, unmergeable or directly_addressed. - * @param authorId the ID of an author - * @param projectId the ID of a project - * @param groupId the ID of a group - * @param state the state of the todo. Can be either pending or done - * @param type the type of a todo. Can be either Issue or MergeRequest * @param itemsPerPage the number of todo that will be fetched per page - * @return a list of pages in todo for the specified range + * @return a Pager containing the done Todos for the current user * @throws GitLabApiException if any exception occurs */ - public Pager getTodos(TodoAction action, Integer authorId, Integer projectId, Integer groupId, TodoState state, TodoType type, int itemsPerPage) throws GitLabApiException { - GitLabApiForm formData = new GitLabApiForm() - .withParam("action", action, false) - .withParam("author_id", authorId, false) - .withParam("project_id", projectId, false) - .withParam("group_id", groupId, false) - .withParam("state", state, false) - .withParam("type", type, false); - return (new Pager(this, Todo.class, itemsPerPage, formData.asMap(), "todos")); + public Pager getDoneTodos(int itemsPerPage) throws GitLabApiException { + return (getTodos(null, null, null, null, TodoState.DONE, null, itemsPerPage)); } /** - * Returns a list of todos. When no filter is applied, - * it returns all pending todos for the current user. - * Different filters allow the user to precise the request. + * Get a Stream of done todos for the current user. * *
GitLab Endpoint: GET /todos
* - * @param action the action to be filtered. Can be assigned, mentioned, build_failed, marked, approval_required, unmergeable or directly_addressed. - * @param authorId the ID of an author - * @param projectId the ID of a project - * @param groupId the ID of a group - * @param state the state of the todo. Can be either pending or done - * @param type the type of a todo. Can be either Issue or MergeRequest - * @param page the page to get - * @param perPage the number of todo-pages per page - * @return a list of pages in todo for the specified range + * @return a Stream containing the done Todos for the current user * @throws GitLabApiException if any exception occurs */ - public List getTodos(TodoAction action, Integer authorId, Integer projectId, Integer groupId, TodoState state, TodoType type, int page, int perPage) throws GitLabApiException { - GitLabApiForm formData = new GitLabApiForm(page, perPage) - .withParam("action", action, false) - .withParam("author_id", authorId, false) - .withParam("project_id", projectId, false) - .withParam("group_id", groupId, false) - .withParam("state", state, false) - .withParam("type", type, false); - Response response = get(Response.Status.OK, formData.asMap(), "todos"); - return (response.readEntity(new GenericType>() { - })); + public Stream getDoneTodosStream() throws GitLabApiException { + return (getTodos(null, null, null, null, TodoState.DONE, null, getDefaultPerPage()).stream()); } /** - * Get a Stream of all todos for the current user. + * Get a List of all todos that match the provided filter params. * *
GitLab Endpoint: GET /todos
* - * @return Stream of Todos + * @param action the action to be filtered. Can be assigned, mentioned, build_failed, marked, approval_required, unmergeable or directly_addressed. + * @param authorId the ID of an author + * @param projectId the ID of a project + * @param groupId the ID of a group + * @param state the state of the todo. Can be either pending or done + * @param type the type of a todo. Can be either Issue or MergeRequest + * @return Stream of Todo instances * @throws GitLabApiException if any exception occurs */ - public Stream getTodoStream() throws GitLabApiException { - return (getTodos(null, null, null, null, null, null, getDefaultPerPage()).stream()); + public List getTodos(TodoAction action, Integer authorId, Integer projectId, Integer groupId, TodoState state, TodoType type) throws GitLabApiException { + return (getTodos(action, authorId, projectId, groupId, state, type, getDefaultPerPage()).all()); } /** - * Get a Stream of all todos for the current user with pagination support. + * Get a List of all todos that match the provided filter params. * *
GitLab Endpoint: GET /todos
* - * @param action the action to be filtered. Can be assigned, mentioned, build_failed, marked, approval_required, unmergeable or directly_addressed. - * @param authorId the ID of an author + * @param action the action to be filtered. Can be assigned, mentioned, build_failed, marked, approval_required, unmergeable or directly_addressed. + * @param authorId the ID of an author * @param projectId the ID of a project - * @param groupId the ID of a group - * @param state the state of the todo. Can be either pending or done - * @param type the type of a todo. Can be either Issue or MergeRequest - * @return Stream of Todos + * @param groupId the ID of a group + * @param state the state of the todo. Can be either pending or done + * @param type the type of a todo. Can be either Issue or MergeRequest + * @return Stream of Todo instances * @throws GitLabApiException if any exception occurs */ - public Stream getTodoStream(TodoAction action, Integer authorId, Integer projectId, Integer groupId, TodoState state, TodoType type) throws GitLabApiException { + public Stream getTodosStream(TodoAction action, Integer authorId, Integer projectId, Integer groupId, TodoState state, TodoType type) throws GitLabApiException { return (getTodos(action, authorId, projectId, groupId, state, type, getDefaultPerPage()).stream()); } + /** + * Returns a Pager of todos that match the provided filter params. When no filter params are provided, + * will returns all pending todos for the current user. + * + *
GitLab Endpoint: GET /todos
+ * + * @param action the action to be filtered. Can be assigned, mentioned, build_failed, marked, approval_required, + * unmergeable or directly_addressed. + * @param authorId the ID of an author + * @param projectId the ID of a project + * @param groupId the ID of a group + * @param state the state of the todo. Can be either pending or done + * @param type the type of a todo. Can be either Issue or MergeRequest + * @param itemsPerPage the number of todo that will be fetched per page + * @return a list of pages in todo for the specified range + * @throws GitLabApiException if any exception occurs + */ + public Pager getTodos(TodoAction action, Integer authorId, Integer projectId, Integer groupId, TodoState state, TodoType type, int itemsPerPage) throws GitLabApiException { + GitLabApiForm formData = new GitLabApiForm() + .withParam("action", action, false) + .withParam("author_id", authorId, false) + .withParam("project_id", projectId, false) + .withParam("group_id", groupId, false) + .withParam("state", state, false) + .withParam("type", type, false); + return (new Pager(this, Todo.class, itemsPerPage, formData.asMap(), "todos")); + } + /** * Marks a single pending todo given by its ID for the current user as done. * The todo marked as done is returned in the response. * *
GitLab Endpoint: POST /todos/:id/mark_as_done
* - * @param todoId the ID of a todi + * @param todoId the ID of a todo * @return todo instance with info on the created page * @throws GitLabApiException if any exception occurs */ @@ -190,8 +177,8 @@ public class TodosApi extends AbstractApi { * * @throws GitLabApiException if any exception occurs */ - public void markAsDone() throws GitLabApiException { + public void markAllAsDone() throws GitLabApiException { GitLabApiForm formData = new GitLabApiForm(); - Response response = post(Response.Status.NO_CONTENT, formData, "todos", "mark_as_done"); + post(Response.Status.NO_CONTENT, formData, "todos", "mark_as_done"); } } diff --git a/src/main/java/org/gitlab4j/api/models/Todo.java b/src/main/java/org/gitlab4j/api/models/Todo.java index 13f9bc7e..35c879bb 100644 --- a/src/main/java/org/gitlab4j/api/models/Todo.java +++ b/src/main/java/org/gitlab4j/api/models/Todo.java @@ -1,312 +1,36 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2018 Greg Messner - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - package org.gitlab4j.api.models; -import org.gitlab4j.api.utils.JacksonJson; - +import java.io.IOException; import java.util.Date; -public class Todo { - - public static class Project { - - private Integer id; - private String name; - private String nameWithNamespace; - private String path; - private String pathWithNamespace; - - public Integer getId() { - return id; - } - - public void setId(Integer id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getNameWithNamespace() { - return nameWithNamespace; - } - - public void setNameWithNamespace(String nameWithNamespace) { - this.nameWithNamespace = nameWithNamespace; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public String getPathWithNamespace() { - return pathWithNamespace; - } - - public void setPathWithNamespace(String pathWithNamespace) { - this.pathWithNamespace = pathWithNamespace; - } - - @Override - public String toString() { - return (JacksonJson.toJsonString(this)); - } - } - - public class Target { - private Integer id; - private Integer iid; - private Integer projectId; - private String title; - private String description; - private String state; - private Date createdAt; - private Date updatedAt; - private String targetBranch; - private String sourceBranch; - private Integer upvotes; - private Integer downvotes; - private Author author; - private Author assignee; - private Integer sourceProjectId; - private Integer targetProjectId; - private String[] labels; - private Boolean workInProgress; - private Milestone milestone; - private Boolean mergeWhenPipelineSucceeds; - private String mergeStatus; - private Boolean subscribed; - private Integer userNotesCount; - - public Integer getId() { - return id; - } - - public void setId(Integer id) { - this.id = id; - } - - public Integer getIid() { - return iid; - } - - public void setIid(Integer iid) { - this.iid = iid; - } - - public Integer getProjectId() { - return projectId; - } - - public void setProjectId(Integer projectId) { - this.projectId = projectId; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getState() { - return state; - } - - public void setState(String state) { - this.state = state; - } - - public Date getCreatedAt() { - return createdAt; - } - - public void setCreatedAt(Date createdAt) { - this.createdAt = createdAt; - } - - public Date getUpdatedAt() { - return updatedAt; - } - - public void setUpdatedAt(Date updatedAt) { - this.updatedAt = updatedAt; - } - - public String getTargetBranch() { - return targetBranch; - } - - public void setTargetBranch(String targetBranch) { - this.targetBranch = targetBranch; - } - - public String getSourceBranch() { - return sourceBranch; - } - - public void setSourceBranch(String sourceBranch) { - this.sourceBranch = sourceBranch; - } - - public Integer getUpvotes() { - return upvotes; - } - - public void setUpvotes(Integer upvotes) { - this.upvotes = upvotes; - } - - public Integer getDownvotes() { - return downvotes; - } - - public void setDownvotes(Integer downvotes) { - this.downvotes = downvotes; - } - - public Author getAuthor() { - return author; - } - - public void setAuthor(Author author) { - this.author = author; - } - - public Author getAssignee() { - return assignee; - } - - public void setAssignee(Author assignee) { - this.assignee = assignee; - } - - public Integer getSourceProjectId() { - return sourceProjectId; - } - - public void setSourceProjectId(Integer sourceProjectId) { - this.sourceProjectId = sourceProjectId; - } - - public Integer getTargetProjectId() { - return targetProjectId; - } - - public void setTargetProjectId(Integer targetProjectId) { - this.targetProjectId = targetProjectId; - } - - public String[] getLabels() { - return labels; - } - - public void setLabels(String[] labels) { - this.labels = labels; - } - - public Boolean getWorkInProgress() { - return workInProgress; - } - - public void setWorkInProgress(Boolean workInProgress) { - this.workInProgress = workInProgress; - } - - public Milestone getMilestone() { - return milestone; - } - - public void setMilestone(Milestone milestone) { - this.milestone = milestone; - } - - public Boolean getMergeWhenPipelineSucceeds() { - return mergeWhenPipelineSucceeds; - } - - public void setMergeWhenPipelineSucceeds(Boolean mergeWhenPipelineSucceeds) { - this.mergeWhenPipelineSucceeds = mergeWhenPipelineSucceeds; - } - - public String getMergeStatus() { - return mergeStatus; - } - - public void setMergeStatus(String mergeStatus) { - this.mergeStatus = mergeStatus; - } - - public Boolean getSubscribed() { - return subscribed; - } - - public void setSubscribed(Boolean subscribed) { - this.subscribed = subscribed; - } - - public Integer getUserNotesCount() { - return userNotesCount; - } +import org.gitlab4j.api.Constants.TodoAction; +import org.gitlab4j.api.Constants.TodoState; +import org.gitlab4j.api.Constants.TodoType; +import org.gitlab4j.api.utils.JacksonJson; - public void setUserNotesCount(Integer userNotesCount) { - this.userNotesCount = userNotesCount; - } +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.node.ObjectNode; - @Override - public String toString() { - return (JacksonJson.toJsonString(this)); - } - } +public class Todo { private Integer id; private Project project; private Author author; - private String actionName; - private String targetType; + private TodoAction actionName; + private TodoType targetType; + + @JsonDeserialize(using = TargetDeserializer.class) + private Object target; + private String targetUrl; - private Target target; private String body; - private String state; + private TodoState state; private Date createdAt; public Integer getId() { @@ -333,19 +57,19 @@ public class Todo { this.author = author; } - public String getActionName() { + public TodoAction getActionName() { return actionName; } - public void setActionName(String actionName) { + public void setActionName(TodoAction actionName) { this.actionName = actionName; } - public String getTargetType() { + public TodoType getTargetType() { return targetType; } - public void setTargetType(String targetType) { + public void setTargetType(TodoType targetType) { this.targetType = targetType; } @@ -357,11 +81,11 @@ public class Todo { this.targetUrl = targetUrl; } - public Target getTarget() { + public Object getTarget() { return target; } - public void setTarget(Target target) { + public void setTarget(Object target) { this.target = target; } @@ -373,11 +97,11 @@ public class Todo { this.body = body; } - public String getState() { + public TodoState getState() { return state; } - public void setState(String state) { + public void setState(TodoState state) { this.state = state; } @@ -389,8 +113,46 @@ public class Todo { this.createdAt = createdAt; } + @JsonIgnore + public Issue getIssueTarget() { + return (targetType == TodoType.ISSUE ? (Issue) target : null); + } + + @JsonIgnore + public MergeRequest getMergeRequestTarget() { + return (targetType == TodoType.MERGE_REQUEST ? (MergeRequest) target : null); + } + + @JsonIgnore + public boolean isIssueTodo() { + return (targetType == TodoType.ISSUE); + } + + @JsonIgnore + public boolean isMergeRequestTodo() { + return (targetType == TodoType.MERGE_REQUEST); + } + @Override public String toString() { return (JacksonJson.toJsonString(this)); } + + // This deserializer will determine the target type and deserialize to the correct class (either MergeRequest or Issue). + private static class TargetDeserializer extends JsonDeserializer { + + @Override + public Object deserialize(JsonParser jp, DeserializationContext context) + throws IOException, JsonProcessingException { + + ObjectMapper mapper = (ObjectMapper) jp.getCodec(); + ObjectNode root = (ObjectNode) mapper.readTree(jp); + boolean isMergeRequestTarget = root.has("source_branch"); + if (isMergeRequestTarget) { + return mapper.treeToValue(root, MergeRequest.class); + } else { + return mapper.treeToValue(root, Issue.class); + } + } + } } -- GitLab