package com.lesstif.jira.services;
import java.io.File;
import java.io.IOException;
import java.util.List;
import lombok.Data;
import org.apache.commons.configuration.ConfigurationException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.codehaus.jackson.type.TypeReference;
import org.slf4j.Logger;
import com.lesstif.jira.Constants;
import com.lesstif.jira.JIRAHTTPClient;
import com.lesstif.jira.issue.Attachment;
import com.lesstif.jira.issue.Issue;
import com.lesstif.jira.issue.IssueSearchResult;
import com.lesstif.jira.issue.IssueType;
import com.lesstif.jira.issue.Priority;
import com.lesstif.jira.issue.WorklogElement;
import com.sun.jersey.api.client.ClientHandlerException;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.multipart.FormDataMultiPart;
import com.sun.jersey.multipart.file.FileDataBodyPart;
import java.net.URLEncoder;
import org.apache.commons.lang.StringUtils;
/**
* @see
* <a href="https://docs.atlassian.com/software/jira/docs/api/REST/latest/#d2e86">/rest/api/2/project</a>
*
* @author lesstif
*
*/
@Data
public class IssueService {
private Logger logger = org.slf4j.LoggerFactory.getLogger(getClass());
private JIRAHTTPClient client = null;
private Issue issue;
public IssueService() throws ConfigurationException {
client = new JIRAHTTPClient();
}
public Issue getIssue(String issueKey) throws IOException {
if (client == null) {
throw new IllegalStateException("HTTP Client not Initailized");
}
client.setResourceName(Constants.JIRA_RESOURCE_ISSUE + "/" + issueKey);
ClientResponse response = client.get();
String content = response.getEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, true);
TypeReference<Issue> ref = new TypeReference<Issue>() {
};
issue = mapper.readValue(content, ref);
return issue;
}
public Issue createIssue(Issue issue) throws IOException {
ObjectMapper mapper = new ObjectMapper();
//to ignore a field if its value is null
mapper.getSerializationConfig().setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
String content = mapper.writeValueAsString(issue);
logger.debug("Content=" + content);
client.setResourceName(Constants.JIRA_RESOURCE_ISSUE);
ClientResponse response = client.post(content);
content = response.getEntity(String.class);
mapper = new ObjectMapper();
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, true);
TypeReference<Issue> ref = new TypeReference<Issue>() {
};
Issue resIssue = mapper.readValue(content, ref);
if (issue.hasAttachments()) {
issue.setId(resIssue.getId());
List<Attachment> attachment = postAttachment(issue);
resIssue.getFields().setAttachment(attachment);
}
return resIssue;
}
/**
* Returns a list of all issue types visible to the user
*
* @return List list of IssueType
*
* @throws IOException json decoding failed
*/
public List<IssueType> getAllIssueTypes() throws IOException {
client.setResourceName(Constants.JIRA_RESOURCE_ISSUETYPE);
ClientResponse response = client.get();
String content = response.getEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, true);
TypeReference<List<IssueType>> ref = new TypeReference<List<IssueType>>() {
};
List<IssueType> issueTypes = mapper.readValue(content, ref);
return issueTypes;
}
public List<Priority> getAllPriorities() throws IOException {
client.setResourceName(Constants.JIRA_RESOURCE_PRIORITY);
ClientResponse response = client.get();
String content = response.getEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, true);
TypeReference<List<Priority>> ref = new TypeReference<List<Priority>>() {
};
List<Priority> priorities = mapper.readValue(content, ref);
return priorities;
}
/**
* Add one or more attachments to an issue.
*
* @param issue Issue object
* @return List
* @throws JsonParseException json parsing failed
* @throws JsonMappingException json mapping failed
* @throws IOException general IO exception
*/
public List<Attachment> postAttachment(Issue issue) throws JsonParseException, JsonMappingException, IOException {
List<File> files = issue.getFields().getFileList();
if (files == null || files.size() == 0) {
throw new IllegalStateException("Oops! Attachment Not Found.");
}
if ((issue.getId() == null || issue.getId().isEmpty())
&& (issue.getKey() == null || issue.getKey().isEmpty())) {
throw new IllegalStateException("Oops! Issue id or Key not set.");
}
String idOrKey = issue.getId() == null ? issue.getKey() : issue.getId();
FormDataMultiPart form = new FormDataMultiPart();
for (int i = 0; i < files.size(); i++) {
// The name of the multipart/form-data parameter that contains attachments must be "file"
FileDataBodyPart fdp = new FileDataBodyPart("file", files.get(i));
form.bodyPart(fdp);
}
client.setResourceName(Constants.JIRA_RESOURCE_ISSUE + "/" + idOrKey + "/attachments");
ClientResponse response = client.postMultiPart(form);
String content = response.getEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, true);
TypeReference<List<Attachment>> ref = new TypeReference<List<Attachment>>() {
};
List<Attachment> res = mapper.readValue(content, ref);
return res;
}
/**
* Add one or more worklog to an issue.
*
* @param worklog Issue object
* @param issue
* @return List
* @throws JsonParseException json parsing failed
* @throws JsonMappingException json mapping failed
* @throws IOException general IO exception
*/
public WorklogElement postWorklog(final WorklogElement worklog, final Issue issue) throws JsonParseException, JsonMappingException, IOException {
String issueId = issue.getId();
if (StringUtils.isBlank(issueId)) {
final String key = issue.getKey();
final Issue issueByKey = getIssue(key);
issueId = issueByKey.getId();
}
ObjectMapper mapper = new ObjectMapper();
//to ignore a field if its value is null
mapper.getSerializationConfig().setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
String content = mapper.writeValueAsString(worklog);
final WorklogElement result = postWorklog(content, issueId);
return result;
}
public WorklogElement postWorklog(String content, final String issueId) throws UniformInterfaceException, ClientHandlerException, IOException {
ObjectMapper mapper;
//content = "{\"comment\":\"I did some work here.\",\"started\":\"2016-03-23T04:22:37.471+0000\",\"timeSpentSeconds\":12000}";
logger.debug("Content=" + content);
final String resource = Constants.JIRA_RESOURCE_ISSUE + "/" + issueId + "/worklog";
client.setResourceName(resource);
ClientResponse response = client.post(content);
content = response.getEntity(String.class);
mapper = new ObjectMapper();
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, true);
TypeReference<WorklogElement> ref = new TypeReference<WorklogElement>() {
};
WorklogElement resIssue = mapper.readValue(content, ref);
return resIssue;
}
public IssueSearchResult getIssuesFromQuery(final String query) throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.getSerializationConfig().setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
String content = URLEncoder.encode(query, "UTF-8");
logger.debug("Content=" + content);
final String resource = "search?jql=" + content;
logger.debug("resource=" + resource);
client.setResourceName(resource);
ClientResponse response = client.get();
content = response.getEntity(String.class);
TypeReference<IssueSearchResult> ref = new TypeReference<IssueSearchResult>() {
};
IssueSearchResult issues = mapper.readValue(content, ref);
return issues;
}
}