/src/main/java/com/verhas/jira/plugin/merger/MergeIssuesFunction.java
Java | 271 lines | 236 code | 29 blank | 6 comment | 41 complexity | 5e05203e1b553491126d069436570830 MD5 | raw file
Possible License(s): LGPL-3.0
- package com.verhas.jira.plugin.merger;
- import com.atlassian.extras.common.log.Logger;
- import com.atlassian.jira.bc.JiraServiceContext;
- import com.atlassian.jira.bc.JiraServiceContextImpl;
- import com.atlassian.jira.bc.issue.IssueService;
- import com.atlassian.jira.bc.issue.attachment.AttachmentService;
- import com.atlassian.jira.bc.issue.comment.CommentService;
- import com.atlassian.jira.bc.issue.visibility.Visibilities;
- import com.atlassian.jira.bc.user.UserService;
- import com.atlassian.jira.exception.CreateException;
- import com.atlassian.jira.exception.RemoveException;
- import com.atlassian.jira.issue.*;
- import com.atlassian.jira.issue.attachment.Attachment;
- import com.atlassian.jira.issue.comments.Comment;
- import com.atlassian.jira.issue.comments.MutableComment;
- import com.atlassian.jira.issue.fields.CustomField;
- import com.atlassian.jira.issue.fields.FieldManager;
- import com.atlassian.jira.issue.link.IssueLink;
- import com.atlassian.jira.issue.link.IssueLinkManager;
- import com.atlassian.jira.security.JiraAuthenticationContext;
- import com.atlassian.jira.user.ApplicationUser;
- import com.atlassian.jira.user.util.UserManager;
- import com.atlassian.jira.util.ErrorCollection;
- import com.atlassian.jira.util.SimpleErrorCollection;
- import com.atlassian.jira.web.util.AttachmentException;
- import com.atlassian.jira.workflow.function.issue.AbstractJiraFunctionProvider;
- import com.opensymphony.module.propertyset.PropertySet;
- import com.opensymphony.workflow.WorkflowException;
- import java.util.*;
- import org.ofbiz.core.entity.GenericEntityException;
- import java.io.IOException;
- import java.util.List;
- /**
- * Created by IntelliJ IDEA. User: verhasi Date: 12/29/11 Time: 7:12 PM To
- * change this template use File | Settings | File Templates.
- */
- public class MergeIssuesFunction extends AbstractJiraFunctionProvider {
- private static final Logger.Log log = Logger.getInstance(MergeIssuesFunction.class);
- private static final boolean DONTDISPATCHEVENT = false;
- private static final String PREFIX = "JIRAMERGE";
- private static final String POSTFIX = ".attachment";
- public static final String MERGE_INTO_ISSUE = "Merge into issue";
- private final UserManager userManager;
- private final IssueService issueService;
- private final CustomFieldManager customFieldManager;
- private final FieldManager fieldManager;
- private final AttachmentManager attachmentManager;
- private final AttachmentService attachmentService;
- private final CommentService commentService;
- private final IssueLinkManager issueLinkManager;
- private final ApplicationUser loggedInUser;
- public MergeIssuesFunction(JiraAuthenticationContext authContext,
- IssueService issueService,
- CustomFieldManager customFieldManager,
- FieldManager fieldManager,
- AttachmentManager attachmentManager,
- CommentService commentService,
- AttachmentService attachmentService,
- UserService userService,
- UserManager userManager,
- IssueLinkManager issueLinkManager) {
- this.issueService = issueService;
- this.customFieldManager = customFieldManager;
- this.fieldManager = fieldManager;
- this.attachmentManager = attachmentManager;
- this.commentService = commentService;
- this.attachmentService = attachmentService;
- this.userManager = userManager;
- this.loggedInUser = authContext.getLoggedInUser();
- this.issueLinkManager = issueLinkManager;
- }
- //args delete or not;customfield name;multiple target merge enabled
- @Override
- public void execute(Map transientVars, Map args, PropertySet ps) throws WorkflowException {
- log.debug("start of com.verhas.jira.plugin.merger.MergeIssuesFunction.execute");
- MutableIssue sourceIssue = getIssue(transientVars);
- //TODO make customfield's name parameter from transient configuration
- Collection<CustomField> customFields = customFieldManager.getCustomFieldObjectsByName(MERGE_INTO_ISSUE);
- if (null == customFields || customFields.isEmpty()) {
- throw new WorkflowException("Custom field 'Merge into issue' not found");
- }
- CustomField customField = customFields.iterator().next();
- if (null == sourceIssue.getCustomFieldValue(customField)) {
- throw new WorkflowException("Merge into issue is mandatory!");
- }
- Object mergeInto = sourceIssue.getCustomFieldValue(customField);
- if (mergeInto instanceof List) {
- List targetIssues = (List) mergeInto;
- if (targetIssues.isEmpty()) {
- throw new WorkflowException("Merge into issue is mandatory!");
- }
- mergeInto = targetIssues.get(targetIssues.size() - 1);
- }
- MutableIssue targetIssue = issueService.getIssue(loggedInUser, mergeInto.toString()).getIssue();
- if (!sourceIssue.isEditable() || !targetIssue.isEditable()) {
- throw new WorkflowException("Both the source and the target issues must be editable!");
- }
- try {
- mergeAttachments(sourceIssue, targetIssue);
- mergeComments(sourceIssue, targetIssue);
- mergeDescription(sourceIssue, targetIssue);
- mergeLinks(sourceIssue, targetIssue);
- log.debug("normal finish of com.verhas.jira.plugin.merger.MergeIssuesFunction.execute");
- } catch (AttachmentException e) {
- throw new WorkflowException(e);
- } catch (IOException e) {
- throw new WorkflowException(e);
- } catch (GenericEntityException e) {
- throw new WorkflowException(e);
- } catch (RemoveException e) {
- throw new WorkflowException(e);
- } finally {
- log.debug("finish of com.verhas.jira.plugin.merger.MergeIssuesFunction.execute");
- }
- }
- private void mergeComments(MutableIssue sourceIssue, MutableIssue targetIssue) throws WorkflowException {
- ErrorCollection errorCollection = new SimpleErrorCollection();
- for (Comment comment : commentService.getCommentsForUser(null, sourceIssue)) {
- Comment newComment = commentService.create(
- comment.getAuthorApplicationUser(),
- commentService.validateCommentCreate(comment.getAuthorApplicationUser(),
- new CommentService.CommentParameters.CommentParametersBuilder()
- .issue(targetIssue)
- .body(comment.getBody())
- .visibility(Visibilities.fromGroupAndRoleId(comment.getGroupLevel(), comment.getRoleLevelId()))
- .created(comment.getCreated())
- .build()),
- DONTDISPATCHEVENT);
- MutableComment mutableComment = commentService.getMutableComment(newComment.getAuthorApplicationUser(), newComment.getId(),errorCollection);
- if (!errorCollection.hasAnyErrors()) {
- mutableComment.setUpdated(comment.getUpdated());
- mutableComment.setUpdateAuthor(comment.getUpdateAuthorApplicationUser());
- ApplicationUser commentAuthor = (comment.getAuthorApplicationUser());
- JiraServiceContext jiraServiceContext = null;
- for (ApplicationUser user : Arrays.asList(commentAuthor, loggedInUser)) {
- if (commentService.hasPermissionToDelete(new JiraServiceContextImpl(user), comment.getId())) {
- jiraServiceContext = new JiraServiceContextImpl(user, errorCollection);
- break;
- }
- }
- if (null != jiraServiceContext) {
- commentService.delete(jiraServiceContext, comment, false);
- for (String errorMessage : errorCollection.getErrorMessages()) {
- log.error("Tried to delete comment but " + errorMessage);
- }
- } else {
- log.debug("Neither the comment author (" + commentAuthor + ") nor the logged in user (" + loggedInUser + ") has permission to delete the comment.");
- }
- }
- }
- if (errorCollection.hasAnyErrors()) {
- throw new WorkflowException(errorCollection.toString());
- }
- }
- private void mergeAttachments(MutableIssue sourceIssue, MutableIssue targetIssue) throws AttachmentException, IOException, GenericEntityException, RemoveException {
- if (attachmentManager.attachmentsEnabled()) {
- Map<Long,com.atlassian.fugue.Either<AttachmentError,Attachment>> copyResult = attachmentManager.copyAttachments(sourceIssue,null,targetIssue.getKey());
- for (Attachment attachment : sourceIssue.getAttachments()) {
- if(copyResult.get(attachment.getId())!=null) {
- if (copyResult.get(attachment.getId()).isRight()) {
- deleteAttachment(attachment);
- } else {
- log.error(copyResult.get(attachment.getId()).left().get().getLogMessage());
- }
- } else {
- log.error("Attachment was not copied!? id="+attachment.getId());
- }
- }
- }
- }
- private void deleteAttachment(Attachment attachment) throws RemoveException {
- ErrorCollection errorCollection = new SimpleErrorCollection();
- ApplicationUser attachmentAuthor = attachment.getAuthorObject();
- JiraServiceContext jiraServiceContext = null;
- for (ApplicationUser user : Arrays.asList(attachmentAuthor, loggedInUser)) {
- if (attachmentService.canDeleteAttachment(new JiraServiceContextImpl(user), attachment.getId())) {
- jiraServiceContext = new JiraServiceContextImpl(user, errorCollection);
- break;
- }
- }
- if (null != jiraServiceContext) {
- attachmentService.delete(jiraServiceContext, attachment.getId());
- for (String errorMessage : errorCollection.getErrorMessages()) {
- log.error("Tried to delete attachment but " + errorMessage);
- }
- } else {
- log.debug("Neither the attachment author (" + attachmentAuthor + ") nor the logged in user (" + loggedInUser + ") has permission to delete the attachment.");
- }
- }
- private void mergeDescription(MutableIssue sourceIssue, MutableIssue targetIssue) {
- IssueInputParameters targetIssueInputParameters = issueService.newIssueInputParameters();
- String targetDescriptionExtension = "{panel:borderStyle=solid|bgColor=#FFFFCE}Merged from " + sourceIssue.getKey()
- + " - " + sourceIssue.getSummary() + "{panel}" + sourceIssue.getDescription();
- targetIssueInputParameters.setDescription(targetIssue.getDescription() + "\n" + targetDescriptionExtension);
- IssueService.UpdateValidationResult updateValidationResult = issueService.validateUpdate(loggedInUser, targetIssue.getId(), targetIssueInputParameters);
- IssueService.IssueResult updateResult = null;
- if (updateValidationResult.isValid()) {
- updateResult = issueService.update(loggedInUser, updateValidationResult);
- if (updateResult != null && updateResult.isValid()) {
- sourceIssue.setDescription("{panel:borderStyle=solid|bgColor=#FFFFCE}h1. Merged to " + targetIssue.getKey() + "{panel}");
- }
- } else {
- StringBuilder errors = new StringBuilder();
- for (String error : updateValidationResult.getErrorCollection().getErrorMessages()) {
- errors.append("#").append(error);
- }
- log.debug("failed target issue update as " + errors);
- }
- }
- private void mergeLinks(MutableIssue sourceIssue, MutableIssue targetIssue) {
- if (issueLinkManager.isLinkingEnabled()) {
- for (IssueLink inwardLink : issueLinkManager.getInwardLinks(sourceIssue.getId())) {
- try {
- if (!inwardLink.getSourceObject().equals(sourceIssue)) {
- cloneLink(inwardLink, inwardLink.getSourceObject(), targetIssue);
- issueLinkManager.removeIssueLink(inwardLink, loggedInUser);
- }
- } catch (CreateException ex) {
- log.error("Unable to create new issueLink", ex);
- }
- }
- for (IssueLink outwardLink : issueLinkManager.getOutwardLinks(sourceIssue.getId())) {
- try {
- if (!outwardLink.getDestinationObject().equals(targetIssue)) {
- cloneLink(outwardLink, targetIssue, outwardLink.getDestinationObject());
- issueLinkManager.removeIssueLink(outwardLink, loggedInUser);
- }
- } catch (CreateException ex) {
- log.error("Unable to create new issueLink", ex);
- }
- }
- }
- }
- private void cloneLink(IssueLink oldLink, Issue newSourceIssue, Issue newTargetIssue) throws CreateException {
- issueLinkManager.createIssueLink(
- newSourceIssue.getId(),
- newTargetIssue.getId(),
- oldLink.getLinkTypeId(),
- oldLink.getSequence(),
- loggedInUser);
- }
- }