Unverified Commit 999b6fb7 authored by Jérémie Bresson's avatar Jérémie Bresson Committed by GitHub
Browse files

Add support for link type between issues (#964)

* Add support for link type between issues

Fixes #847

* Create AbstractIssue
parent 6e248bcc
...@@ -16,6 +16,7 @@ import org.gitlab4j.api.models.IssueFilter; ...@@ -16,6 +16,7 @@ import org.gitlab4j.api.models.IssueFilter;
import org.gitlab4j.api.models.IssueLink; import org.gitlab4j.api.models.IssueLink;
import org.gitlab4j.api.models.IssuesStatistics; import org.gitlab4j.api.models.IssuesStatistics;
import org.gitlab4j.api.models.IssuesStatisticsFilter; import org.gitlab4j.api.models.IssuesStatisticsFilter;
import org.gitlab4j.api.models.LinkType;
import org.gitlab4j.api.models.MergeRequest; import org.gitlab4j.api.models.MergeRequest;
import org.gitlab4j.api.models.Participant; import org.gitlab4j.api.models.Participant;
import org.gitlab4j.api.models.TimeStats; import org.gitlab4j.api.models.TimeStats;
...@@ -889,10 +890,31 @@ public class IssuesApi extends AbstractApi implements Constants { ...@@ -889,10 +890,31 @@ public class IssuesApi extends AbstractApi implements Constants {
*/ */
public IssueLink createIssueLink(Object projectIdOrPath, Long issueIid, public IssueLink createIssueLink(Object projectIdOrPath, Long issueIid,
Object targetProjectIdOrPath, Long targetIssueIid) throws GitLabApiException { Object targetProjectIdOrPath, Long targetIssueIid) throws GitLabApiException {
return createIssueLink(projectIdOrPath, issueIid, targetProjectIdOrPath, targetIssueIid, null);
}
/**
* Creates a two-way relation between two issues. User must be allowed to update both issues in order to succeed.
*
* <p>NOTE: Only available in GitLab Starter, GitLab Bronze, and higher tiers.</p>
*
* <pre><code>GitLab Endpoint: POST /projects/:id/issues/:issue_iid/links</code></pre>
*
* @param projectIdOrPath the project in the form of an Long(ID), String(path), or Project instance
* @param issueIid the internal ID of a project's issue
* @param targetProjectIdOrPath the project in the form of an Long(ID), String(path), or Project instance of the target project
* @param targetIssueIid the internal ID of a target project’s issue
* @param linkType the type of the relation (optional), defaults to {@link LinkType#RELATES_TO}.
* @return an instance of IssueLink holding the link relationship
* @throws GitLabApiException if any exception occurs
*/
public IssueLink createIssueLink(Object projectIdOrPath, Long issueIid,
Object targetProjectIdOrPath, Long targetIssueIid, LinkType linkType) throws GitLabApiException {
GitLabApiForm formData = new GitLabApiForm() GitLabApiForm formData = new GitLabApiForm()
.withParam("target_project_id", getProjectIdOrPath(targetProjectIdOrPath), true) .withParam("target_project_id", getProjectIdOrPath(targetProjectIdOrPath), true)
.withParam("target_issue_iid", targetIssueIid, true); .withParam("target_issue_iid", targetIssueIid, true)
.withParam("link_type", linkType, false);
Response response = post(Response.Status.OK, formData.asMap(), Response response = post(Response.Status.OK, formData.asMap(),
"projects", getProjectIdOrPath(projectIdOrPath), "issues", issueIid, "links"); "projects", getProjectIdOrPath(projectIdOrPath), "issues", issueIid, "links");
......
package org.gitlab4j.api.models;
import java.util.Date;
import java.util.List;
import org.gitlab4j.api.Constants.IssueState;
import org.gitlab4j.api.utils.JacksonJson;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.node.IntNode;
import com.fasterxml.jackson.databind.node.LongNode;
import com.fasterxml.jackson.databind.node.TextNode;
import com.fasterxml.jackson.databind.node.ValueNode;
public abstract class AbstractIssue {
public static class TaskCompletionStatus {
private Integer count;
private Integer completedCount;
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
public Integer getCompletedCount() {
return completedCount;
}
public void setCompletedCount(Integer completedCount) {
this.completedCount = completedCount;
}
@Override
public String toString() {
return (JacksonJson.toJsonString(this));
}
}
private Assignee assignee;
private List<Assignee> assignees;
private Author author;
private Boolean confidential;
private Date createdAt;
private Date updatedAt;
private Date closedAt;
private User closedBy;
private String description;
private Date dueDate;
@JsonProperty("id")
private ValueNode actualId;
@JsonIgnore
private String externalId;
@JsonIgnore
private Long id;
private Long iid;
private List<String> labels;
private Milestone milestone;
private Long projectId;
private IssueState state;
private String title;
private Integer userNotesCount;
private String webUrl;
private Integer weight;
private Boolean discussionLocked;
private TimeStats timeStats;
private Integer upvotes;
private Integer downvotes;
private Integer mergeRequestsCount;
private Boolean hasTasks;
private String taskStatus;
private TaskCompletionStatus taskCompletionStatus;
public Assignee getAssignee() {
return assignee;
}
public void setAssignee(Assignee assignee) {
this.assignee = assignee;
}
public List<Assignee> getAssignees() {
return assignees;
}
public void setAssignees(List<Assignee> assignees) {
this.assignees = assignees;
}
public Author getAuthor() {
return author;
}
public void setAuthor(Author author) {
this.author = author;
}
public Boolean getConfidential() {
return confidential;
}
public void setConfidential(Boolean confidential) {
this.confidential = confidential;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getDueDate() {
return dueDate;
}
public void setDueDate(Date dueDate) {
this.dueDate = dueDate;
}
public ValueNode getActualId() {
return actualId;
}
public void setActualId(ValueNode id) {
actualId = id;
if (actualId instanceof TextNode) {
externalId = actualId.asText();
} else if (actualId instanceof IntNode || actualId instanceof LongNode) {
this.id = actualId.asLong();
}
}
public Long getId() {
return (id);
}
public void setId(Long id) {
this.id = id;
if (id != null) {
actualId = new LongNode(id);
externalId = null;
}
}
public String getExternalId() {
return (externalId);
}
public void setExternalId(String externalId) {
this.externalId = externalId;
if (externalId != null) {
actualId = new TextNode(externalId);
id = null;
}
}
public Long getIid() {
return iid;
}
public void setIid(Long iid) {
this.iid = iid;
}
public List<String> getLabels() {
return labels;
}
public void setLabels(List<String> labels) {
this.labels = labels;
}
public Milestone getMilestone() {
return milestone;
}
public void setMilestone(Milestone milestone) {
this.milestone = milestone;
}
public Long getProjectId() {
return projectId;
}
public void setProjectId(Long projectId) {
this.projectId = projectId;
}
public IssueState getState() {
return state;
}
public void setState(IssueState state) {
this.state = state;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public Date getClosedAt() {
return closedAt;
}
public void setClosedAt(Date closedAt) {
this.closedAt = closedAt;
}
public User getClosedBy() {
return closedBy;
}
public void setClosedBy(User closedBy) {
this.closedBy = closedBy;
}
public Integer getUserNotesCount() {
return userNotesCount;
}
public void setUserNotesCount(Integer userNotesCount) {
this.userNotesCount = userNotesCount;
}
public String getWebUrl() {
return webUrl;
}
public void setWebUrl(String webUrl) {
this.webUrl = webUrl;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight;
}
public Boolean getDiscussionLocked() {
return discussionLocked;
}
public void setDiscussionLocked(Boolean discussionLocked) {
this.discussionLocked = discussionLocked;
}
public TimeStats getTimeStats() {
return timeStats;
}
public void setTimeStats(TimeStats timeStats) {
this.timeStats = timeStats;
}
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 Integer getMergeRequestsCount() {
return mergeRequestsCount;
}
public void setMergeRequestsCount(Integer mergeRequestsCount) {
this.mergeRequestsCount = mergeRequestsCount;
}
public Boolean getHasTasks() {
return hasTasks;
}
public void setHasTasks(Boolean hasTasks) {
this.hasTasks = hasTasks;
}
public String getTaskStatus() {
return taskStatus;
}
public void setTaskStatus(String taskStatus) {
this.taskStatus = taskStatus;
}
public TaskCompletionStatus getTaskCompletionStatus() {
return taskCompletionStatus;
}
public void setTaskCompletionStatus(TaskCompletionStatus taskCompletionStatus) {
this.taskCompletionStatus = taskCompletionStatus;
}
@Override
public String toString() {
return (JacksonJson.toJsonString(this));
}
}
...@@ -2,226 +2,17 @@ ...@@ -2,226 +2,17 @@
package org.gitlab4j.api.models; package org.gitlab4j.api.models;
import java.util.Date; import java.util.Date;
import java.util.List;
import org.gitlab4j.api.Constants.IssueState;
import org.gitlab4j.api.utils.JacksonJson; import org.gitlab4j.api.utils.JacksonJson;
import com.fasterxml.jackson.annotation.JsonIgnore; public class Issue extends AbstractIssue {
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.node.IntNode;
import com.fasterxml.jackson.databind.node.LongNode;
import com.fasterxml.jackson.databind.node.TextNode;
import com.fasterxml.jackson.databind.node.ValueNode;
public class Issue {
public static class TaskCompletionStatus {
private Integer count;
private Integer completedCount;
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
public Integer getCompletedCount() {
return completedCount;
}
public void setCompletedCount(Integer completedCount) {
this.completedCount = completedCount;
}
@Override
public String toString() {
return (JacksonJson.toJsonString(this));
}
}
private Assignee assignee;
private List<Assignee> assignees;
private Author author;
private Boolean confidential;
private Date createdAt;
private Date updatedAt;
private Date closedAt;
private User closedBy;
private String description;
private Date dueDate;
@JsonProperty("id")
private ValueNode actualId;
@JsonIgnore
private String externalId;
@JsonIgnore
private Long id;
private Long iid;
private Long issueLinkId;
private List<String> labels;
private Milestone milestone;
private Long projectId;
private IssueState state;
private Boolean subscribed; private Boolean subscribed;
private String title;
private Integer userNotesCount;
private String webUrl;
private Integer weight;
private Boolean discussionLocked;
private TimeStats timeStats;
private Integer upvotes;
private Integer downvotes;
private Integer mergeRequestsCount;
private Boolean hasTasks;
private String taskStatus;
private TaskCompletionStatus taskCompletionStatus;
public Assignee getAssignee() {
return assignee;
}
public void setAssignee(Assignee assignee) {
this.assignee = assignee;
}
public List<Assignee> getAssignees() {
return assignees;
}
public void setAssignees(List<Assignee> assignees) {
this.assignees = assignees;
}
public Author getAuthor() {
return author;
}
public void setAuthor(Author author) {
this.author = author;
}
public Boolean getConfidential() {
return confidential;
}
public void setConfidential(Boolean confidential) {
this.confidential = confidential;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getDueDate() {
return dueDate;
}
public void setDueDate(Date dueDate) {
this.dueDate = dueDate;
}
public ValueNode getActualId() {
return actualId;
}
public void setActualId(ValueNode id) {
actualId = id;
if (actualId instanceof TextNode) {
externalId = actualId.asText();
} else if (actualId instanceof IntNode || actualId instanceof LongNode) {
this.id = actualId.asLong();
}
}
public Long getId() {
return (id);
}
public void setId(Long id) {
this.id = id;
if (id != null) {
actualId = new LongNode(id);
externalId = null;
}
}
public String getExternalId() {
return (externalId);
}
public void setExternalId(String externalId) {
this.externalId = externalId;
if (externalId != null) {
actualId = new TextNode(externalId);
id = null;
}
}
public Long getIid() {
return iid;
}
public void setIid(Long iid) {
this.iid = iid;
}
public Long getIssueLinkId() {
return issueLinkId;
}
public void setIssueLinkId(Long issueLinkId) {
this.issueLinkId = issueLinkId;
}
public List<String> getLabels() { private Long issueLinkId;
return labels; private LinkType linkType;
} private Date linkCreatedAt;
private Date linkUpdatedAt;
public void setLabels(List<String> labels) {
this.labels = labels;
}
public Milestone getMilestone() {
return milestone;
}
public void setMilestone(Milestone milestone) {
this.milestone = milestone;
}
public Long getProjectId() {
return projectId;
}
public void setProjectId(Long projectId) {
this.projectId = projectId;
}
public IssueState getState() {
return state;
}
public void setState(IssueState state) {
this.state = state;
}
public Boolean getSubscribed() { public Boolean getSubscribed() {
return subscribed; return subscribed;
...@@ -231,124 +22,36 @@ public class Issue { ...@@ -231,124 +22,36 @@ public class Issue {
this.subscribed = subscribed; this.subscribed = subscribed;
} }
public String getTitle() { public Long getIssueLinkId() {
return title; return issueLinkId;
}
public void setTitle(String title) {
this.title = title;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public Date getClosedAt() {
return closedAt;
}
public void setClosedAt(Date closedAt) {
this.closedAt = closedAt;
}
public User getClosedBy() {
return closedBy;
}
public void setClosedBy(User closedBy) {
this.closedBy = closedBy;
}
public Integer getUserNotesCount() {
return userNotesCount;
}
public void setUserNotesCount(Integer userNotesCount) {
this.userNotesCount = userNotesCount;
}
public String getWebUrl() {
return webUrl;
}
public void setWebUrl(String webUrl) {
this.webUrl = webUrl;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight;
}
public Boolean getDiscussionLocked() {
return discussionLocked;
}
public void setDiscussionLocked(Boolean discussionLocked) {
this.discussionLocked = discussionLocked;
}
public TimeStats getTimeStats() {
return timeStats;
}
public void setTimeStats(TimeStats timeStats) {
this.timeStats = timeStats;
}
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 Integer getMergeRequestsCount() {
return mergeRequestsCount;
} }
public void setMergeRequestsCount(Integer mergeRequestsCount) { public void setIssueLinkId(Long issueLinkId) {
this.mergeRequestsCount = mergeRequestsCount; this.issueLinkId = issueLinkId;
} }
public Boolean getHasTasks() { public LinkType getLinkType() {
return hasTasks; return linkType;
} }
public void setHasTasks(Boolean hasTasks) { public void setLinkType(LinkType linkType) {
this.hasTasks = hasTasks; this.linkType = linkType;
} }
public String getTaskStatus() { public Date getLinkCreatedAt() {
return taskStatus; return linkCreatedAt;
} }
public void setTaskStatus(String taskStatus) { public void setLinkCreatedAt(Date linkCreatedAt) {
this.taskStatus = taskStatus; this.linkCreatedAt = linkCreatedAt;
} }
public TaskCompletionStatus getTaskCompletionStatus() { public Date getLinkUpdatedAt() {
return taskCompletionStatus; return linkUpdatedAt;
} }
public void setTaskCompletionStatus(TaskCompletionStatus taskCompletionStatus) { public void setLinkUpdatedAt(Date linkUpdatedAt) {
this.taskCompletionStatus = taskCompletionStatus; this.linkUpdatedAt = linkUpdatedAt;
} }
@Override @Override
......
...@@ -6,6 +6,7 @@ public class IssueLink { ...@@ -6,6 +6,7 @@ public class IssueLink {
private Issue sourceIssue; private Issue sourceIssue;
private Issue targetIssue; private Issue targetIssue;
private LinkType linkType;
public Issue getSourceIssue() { public Issue getSourceIssue() {
return sourceIssue; return sourceIssue;
...@@ -23,6 +24,14 @@ public class IssueLink { ...@@ -23,6 +24,14 @@ public class IssueLink {
this.targetIssue = targetIssue; this.targetIssue = targetIssue;
} }
public LinkType getLinkType() {
return linkType;
}
public void setLinkType(LinkType linkType) {
this.linkType = linkType;
}
@Override @Override
public String toString() { public String toString() {
return (JacksonJson.toJsonString(this)); return (JacksonJson.toJsonString(this));
......
package org.gitlab4j.api.models;
import org.gitlab4j.api.utils.JacksonJsonEnumHelper;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
/**
* Enum to model the type of link between issues or epics
*/
public enum LinkType {
RELATES_TO,
BLOCKS,
IS_BLOCKED_BY;
private static JacksonJsonEnumHelper<LinkType> enumHelper = new JacksonJsonEnumHelper<>(LinkType.class);
@JsonCreator
public static LinkType forValue(String value) {
return enumHelper.forValue(value);
}
@JsonValue
public String toValue() {
return (enumHelper.toString(this));
}
@Override
public String toString() {
return (enumHelper.toString(this));
}
}
...@@ -46,5 +46,6 @@ ...@@ -46,5 +46,6 @@
"user_notes_count": 0, "user_notes_count": 0,
"web_url": "http://example.com/example/example/issues/14", "web_url": "http://example.com/example/example/issues/14",
"confidential": false "confidential": false
} },
"link_type": "is_blocked_by"
} }
\ No newline at end of file
...@@ -22,6 +22,9 @@ ...@@ -22,6 +22,9 @@
"subscribed" : true, "subscribed" : true,
"user_notes_count": 0, "user_notes_count": 0,
"web_url": "http://example.com/example/example/issues/14", "web_url": "http://example.com/example/example/issues/14",
"confidential": false "confidential": false,
"link_type": "relates_to",
"link_created_at": "2016-01-07T12:44:33.959Z",
"link_updated_at": "2016-01-07T12:44:33.959Z"
} }
] ]
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment