PageRenderTime 26ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/jira-automation-plugin/src/main/java/com/atlassian/plugin/automation/jira/action/SetAssigneeToLastCommentedAction.java

https://bitbucket.org/atlassianlabs/automation
Java | 285 lines | 246 code | 30 blank | 9 comment | 38 complexity | 9b5ea8b74af12123ac504321a09da160 MD5 | raw file
  1. package com.atlassian.plugin.automation.jira.action;
  2. import com.atlassian.crowd.embedded.api.Group;
  3. import com.atlassian.crowd.embedded.api.UserComparator;
  4. import com.atlassian.jira.bc.issue.IssueService;
  5. import com.atlassian.jira.issue.Issue;
  6. import com.atlassian.jira.issue.comments.Comment;
  7. import com.atlassian.jira.issue.comments.CommentManager;
  8. import com.atlassian.jira.plugin.userformat.UserFormats;
  9. import com.atlassian.jira.plugin.userformat.UserFormatter;
  10. import com.atlassian.jira.security.groups.GroupManager;
  11. import com.atlassian.jira.user.ApplicationUser;
  12. import com.atlassian.jira.user.util.UserUtil;
  13. import com.atlassian.plugin.automation.core.Action;
  14. import com.atlassian.plugin.automation.core.action.ActionConfiguration;
  15. import com.atlassian.plugin.automation.core.auditlog.AuditString;
  16. import com.atlassian.plugin.automation.core.auditlog.DefaultAuditString;
  17. import com.atlassian.plugin.automation.jira.util.ErrorCollectionUtil;
  18. import com.atlassian.plugin.automation.util.ErrorCollection;
  19. import com.atlassian.plugin.automation.util.ParameterUtil;
  20. import com.atlassian.plugin.spring.scanner.annotation.component.Scanned;
  21. import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;
  22. import com.atlassian.sal.api.message.I18nResolver;
  23. import com.atlassian.soy.renderer.SoyException;
  24. import com.atlassian.soy.renderer.SoyTemplateRenderer;
  25. import com.google.common.base.Function;
  26. import com.google.common.collect.Lists;
  27. import com.google.common.collect.Maps;
  28. import com.google.common.collect.Sets;
  29. import org.apache.commons.lang.StringUtils;
  30. import org.apache.log4j.Logger;
  31. import javax.annotation.Nullable;
  32. import javax.inject.Inject;
  33. import java.util.Collections;
  34. import java.util.List;
  35. import java.util.Map;
  36. import java.util.Set;
  37. import static com.atlassian.plugin.automation.jira.util.Constants.CONFIG_COMPLETE_KEY;
  38. import static com.atlassian.plugin.automation.util.ParameterUtil.singleValue;
  39. /**
  40. * Given a list of issues, this action will set the assignee for these issues to the person who last commented
  41. * (optionally from a particular group of users).
  42. * <p/>
  43. * This may be useful in a support style use case where we want to set the assignee to the supporter who last handled a
  44. * case when a customer adds a comment.
  45. *
  46. */
  47. @Scanned
  48. public class SetAssigneeToLastCommentedAction implements Action<Issue>
  49. {
  50. private static final Logger log = Logger.getLogger(SetAssigneeToLastCommentedAction.class);
  51. private static final String PROFILE_LINK_USER_FORMAT_TYPE = "profileLinkWithAvatar";
  52. private static final String GROUP_MEMBERSHIP_KEY = "groupMembership";
  53. private static final String EXCLUDED_USERS_KEY = "excludedUsers";
  54. private static final String UNRESTRICTED = "-1";
  55. private final CommentManager commentManager;
  56. private final GroupManager groupManager;
  57. private final IssueService issueService;
  58. private final UserUtil userUtil;
  59. private final SoyTemplateRenderer soyTemplateRenderer;
  60. private final UserFormats userFormats;
  61. private String groupMembership;
  62. private Set<ApplicationUser> excludedUsers;
  63. @Inject
  64. public SetAssigneeToLastCommentedAction(
  65. @ComponentImport final CommentManager commentManager,
  66. @ComponentImport final GroupManager groupManager,
  67. @ComponentImport final IssueService issueService,
  68. @ComponentImport final UserUtil userUtil,
  69. @ComponentImport final SoyTemplateRenderer soyTemplateRenderer,
  70. @ComponentImport final UserFormats userFormats)
  71. {
  72. this.commentManager = commentManager;
  73. this.groupManager = groupManager;
  74. this.issueService = issueService;
  75. this.userUtil = userUtil;
  76. this.soyTemplateRenderer = soyTemplateRenderer;
  77. this.userFormats = userFormats;
  78. }
  79. @Override
  80. public void init(final ActionConfiguration config)
  81. {
  82. groupMembership = singleValue(config, GROUP_MEMBERSHIP_KEY);
  83. excludedUsers = transformExcludedUsers(config);
  84. }
  85. @Override
  86. public void execute(final String actor, final Iterable<Issue> items, final ErrorCollection errorCollection)
  87. {
  88. log.debug("Processing issues");
  89. final Group restrictingGroup = StringUtils.isBlank(groupMembership) || StringUtils.equals(UNRESTRICTED, groupMembership) ? null : groupManager.getGroup(groupMembership);
  90. for (Issue issue : items)
  91. {
  92. log.debug("Processing issue: " + issue.getKey());
  93. final List<Comment> comments = commentManager.getComments(issue);
  94. Collections.reverse(comments);
  95. ApplicationUser lastCommented = null;
  96. for (Comment comment : comments)
  97. {
  98. final ApplicationUser commentAuthor = comment.getAuthorApplicationUser();
  99. if (excludedUsers != null && excludedUsers.contains(commentAuthor))
  100. {
  101. continue;
  102. }
  103. if (restrictingGroup != null)
  104. {
  105. if (groupManager.isUserInGroup(commentAuthor, restrictingGroup))
  106. {
  107. lastCommented = commentAuthor;
  108. break;
  109. }
  110. }
  111. else
  112. {
  113. lastCommented = commentAuthor;
  114. break;
  115. }
  116. }
  117. //if we found a user that last commented lets assign the issue to this person (if the issue isn't assigned to them already)!
  118. if (lastCommented != null && (issue.getAssignee() == null || !UserComparator.equal(lastCommented.getDirectoryUser(), issue.getAssignee().getDirectoryUser())))
  119. {
  120. log.debug(String.format("Last commented user found for issue '%s'. Setting assignee to user '%s'.", issue.getKey(), lastCommented.getName()));
  121. final ApplicationUser actorUser = userUtil.getUserByName(actor);
  122. final IssueService.AssignValidationResult result = issueService.validateAssign(actorUser, issue.getId(), lastCommented.getName());
  123. if (result.isValid())
  124. {
  125. issueService.assign(actorUser, result);
  126. }
  127. else
  128. {
  129. errorCollection.addErrorCollection(ErrorCollectionUtil.transform(result.getErrorCollection()));
  130. }
  131. }
  132. }
  133. }
  134. @Override
  135. public AuditString getAuditLog()
  136. {
  137. String logMessage = "Set Assignee to Last Commented for Issue.";
  138. if (!StringUtils.equals(groupMembership, UNRESTRICTED))
  139. {
  140. logMessage += " Last commented user had to be member of group '" + groupMembership + "'.";
  141. }
  142. return new DefaultAuditString(logMessage);
  143. }
  144. @Override
  145. public String getConfigurationTemplate(final ActionConfiguration actionConfiguration, final String actor)
  146. {
  147. try
  148. {
  149. final Map<String, Object> context = Maps.newHashMap();
  150. ParameterUtil.transformParams(context, actionConfiguration);
  151. context.put("groups", groupManager.getAllGroups());
  152. if (actionConfiguration != null && actionConfiguration.getParameters().containsKey(EXCLUDED_USERS_KEY))
  153. {
  154. List<ApplicationUser> excludedUsers = Lists.transform(actionConfiguration.getParameters().get(EXCLUDED_USERS_KEY), new Function<String, ApplicationUser>()
  155. {
  156. @Override
  157. public ApplicationUser apply(@Nullable final String userName)
  158. {
  159. return userUtil.getUserByName(userName);
  160. }
  161. });
  162. context.put("excludedUsers", excludedUsers);
  163. }
  164. return soyTemplateRenderer.render(CONFIG_COMPLETE_KEY, "Atlassian.Templates.Automation.JIRA.setLastCommented", context);
  165. }
  166. catch (SoyException e)
  167. {
  168. log.error("Error rendering template", e);
  169. return "Unable to render configuration form. Consult your server logs or administrator.";
  170. }
  171. }
  172. @Override
  173. public String getViewTemplate(final ActionConfiguration config, final String actor)
  174. {
  175. try
  176. {
  177. final Map<String, Object> context = Maps.newHashMap();
  178. ParameterUtil.transformParams(context, config);
  179. context.put("excludedUsersProfileLinks", transformExcludedUsersToProfileLinks(config));
  180. return soyTemplateRenderer.render(CONFIG_COMPLETE_KEY, "Atlassian.Templates.Automation.JIRA.setLastCommentedView", context);
  181. }
  182. catch (SoyException e)
  183. {
  184. log.error("Error rendering template", e);
  185. return "Unable to render configuration form. Consult your server logs or administrator.";
  186. }
  187. }
  188. @Override
  189. public ErrorCollection validateAddConfiguration(final I18nResolver i18n, final Map<String, List<String>> params,
  190. final String actor)
  191. {
  192. final ErrorCollection errors = new ErrorCollection();
  193. if (params.containsKey(GROUP_MEMBERSHIP_KEY))
  194. {
  195. final String groupMembership = singleValue(params, GROUP_MEMBERSHIP_KEY);
  196. if (!StringUtils.equals(UNRESTRICTED, groupMembership))
  197. {
  198. final Group group = groupManager.getGroup(groupMembership);
  199. if (group == null)
  200. {
  201. errors.addError(GROUP_MEMBERSHIP_KEY, i18n.getText("automation.jira.group.membership.invalid"));
  202. }
  203. }
  204. }
  205. if (params.containsKey(EXCLUDED_USERS_KEY))
  206. {
  207. final List<String> users = params.get(EXCLUDED_USERS_KEY);
  208. String usersNotFound = "";
  209. for (String userName : users)
  210. {
  211. ApplicationUser user = userUtil.getUserByName(userName);
  212. if (user == null)
  213. {
  214. usersNotFound += userName + " ";
  215. }
  216. }
  217. if (!usersNotFound.isEmpty())
  218. {
  219. errors.addError(EXCLUDED_USERS_KEY, i18n.getText("automation.jira.users.excluded.invalid") + " " + usersNotFound);
  220. }
  221. }
  222. return errors;
  223. }
  224. private Set<String> transformExcludedUsersToProfileLinks(final ActionConfiguration config)
  225. {
  226. final Set<String> ret = Sets.newLinkedHashSet();
  227. if (config != null && config.getParameters().containsKey(EXCLUDED_USERS_KEY))
  228. {
  229. final UserFormatter formatter = userFormats.formatter(PROFILE_LINK_USER_FORMAT_TYPE);
  230. for (String user : config.getParameters().get(EXCLUDED_USERS_KEY))
  231. {
  232. if (StringUtils.isNotBlank(user))
  233. {
  234. ret.add(formatter.formatUserkey(user, "excluded-user-" + config.getId()));
  235. }
  236. }
  237. }
  238. return ret;
  239. }
  240. private Set<ApplicationUser> transformExcludedUsers(final ActionConfiguration config)
  241. {
  242. final Set<ApplicationUser> ret = Sets.newHashSet();
  243. if (config != null && config.getParameters().containsKey(EXCLUDED_USERS_KEY))
  244. {
  245. for (String user : config.getParameters().get(EXCLUDED_USERS_KEY))
  246. {
  247. if (StringUtils.isNotBlank(user))
  248. {
  249. ret.add(userUtil.getUserByName(user));
  250. }
  251. }
  252. }
  253. return ret;
  254. }
  255. }