PageRenderTime 45ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/resources/com/onresolve/jira/groovy/canned/workflow/postfunctions/AbstractCloneIssue.groovy

https://bitbucket.org/sorin/jira-plugin-intellij
Groovy | 206 lines | 163 code | 30 blank | 13 comment | 27 complexity | c7a9617a6951703ef232ee193328c5be MD5 | raw file
  1. package com.onresolve.jira.groovy.canned.workflow.postfunctions
  2. import com.atlassian.crowd.embedded.api.User
  3. import com.atlassian.jira.ComponentManager
  4. import com.atlassian.jira.bc.project.component.ProjectComponent
  5. import com.atlassian.jira.bc.project.component.ProjectComponentManager
  6. import com.atlassian.jira.issue.fields.CustomField
  7. import com.atlassian.jira.project.version.Version
  8. import com.atlassian.jira.user.util.UserUtil
  9. import com.atlassian.jira.util.ImportUtils
  10. import com.onresolve.jira.groovy.canned.utils.ConditionUtils
  11. import com.opensymphony.workflow.WorkflowContext
  12. import org.apache.log4j.Category
  13. import org.ofbiz.core.entity.GenericValue
  14. import com.atlassian.jira.issue.*
  15. import com.atlassian.jira.ManagerFactory
  16. import com.atlassian.jira.issue.label.LabelManager
  17. abstract class AbstractCloneIssue {
  18. public static final String FIELD_TARGET_PROJECT = "FIELD_TARGET_PROJECT"
  19. public static final String FIELD_TARGET_ISSUE_TYPE = "FIELD_TARGET_ISSUE_TYPE"
  20. public static final String FIELD_LINK_TYPE = 'FIELD_LINK_TYPE'
  21. public static final String FIELD_ADDITIONAL_SCRIPT = 'FIELD_ADDITIONAL_SCRIPT'
  22. ComponentManager componentManager = ComponentManager.getInstance()
  23. UserUtil userUtil = ComponentManager.getInstance().getUserUtil()
  24. ProjectComponentManager projectComponentManager = componentManager.getProjectComponentManager()
  25. Category log = Category.getInstance(CloneIssue.class)
  26. def projectManager = componentManager.getProjectManager()
  27. def versionManager = componentManager.getVersionManager()
  28. def indexManager = ComponentManager.getInstance().getIndexManager()
  29. def issueSecuritySchemeManager = ManagerFactory.getIssueSecuritySchemeManager()
  30. def labelManager = ComponentManager.getComponentInstanceOfType(LabelManager.class)
  31. Map doScript(Map params) {
  32. log.debug ("CloneIssue.doScript with params: ${params}");
  33. Issue issue = params['issue'] as Issue
  34. String targetProjKey = params[FIELD_TARGET_PROJECT] as String
  35. GenericValue targetProject = projectManager.getProjectByKey(targetProjKey)
  36. String targetIssueType = params[FIELD_TARGET_ISSUE_TYPE] as String
  37. Map transientVars = params['transientVars'] as Map
  38. IssueManager issueMgr = componentManager.getIssueManager()
  39. User currentUserObj = getUser(params)
  40. IssueFactory issueFactory = ComponentManager.getInstance().getIssueFactory()
  41. MutableIssue newIssue = issueFactory.getIssue()
  42. // needs to go before copying custom field values, otherwise we can't get the right target custom fields to copy them
  43. if (targetProject) {
  44. newIssue.setProject (targetProject)
  45. }
  46. if (targetIssueType) {
  47. newIssue.setIssueTypeId(targetIssueType)
  48. }
  49. copySystemFieldValues(issue, newIssue)
  50. copyCustomFieldValues(newIssue, issue)
  51. if (params[CreateSubTask.FIELD_SUBTASK_SUMMARY]) {
  52. newIssue.setSummary(params[CreateSubTask.FIELD_SUBTASK_SUMMARY] as String)
  53. }
  54. Map<String,Object> newIssueParams = ["issue":newIssue] as Map<String,Object>
  55. ConditionUtils.doAdditional(params[FIELD_ADDITIONAL_SCRIPT] as String, newIssue, [transientVars: transientVars])
  56. // todo: check the user has the Create Issue perm in the target project, or allow the setup to choose a user
  57. GenericValue newIssueGv = issueMgr.createIssue(currentUserObj, newIssueParams)
  58. reindexIssue(newIssueGv)
  59. params['newIssue'] = newIssue
  60. copyLabels(issue, newIssue, currentUserObj)
  61. return params
  62. }
  63. protected void reindexIssue(GenericValue gv) {
  64. def wasIndexing = ImportUtils.indexIssues
  65. ImportUtils.indexIssues = true
  66. indexManager.reIndex(gv);
  67. ImportUtils.indexIssues = wasIndexing
  68. }
  69. protected User getUser(Map params) {
  70. String currentUser
  71. Map transientVars = params['transientVars'] as Map
  72. if (transientVars) {
  73. currentUser = ((WorkflowContext) transientVars.get("context")).getCaller();
  74. }
  75. else {
  76. currentUser = componentManager.getJiraAuthenticationContext().getUser().getName()
  77. }
  78. User currentUserObj = userUtil.getUser(currentUser);
  79. return currentUserObj
  80. }
  81. protected def copyCustomFieldValues(MutableIssue newissue, Issue issue) {
  82. CustomFieldManager customFieldManager = componentManager.getCustomFieldManager()
  83. List newIssueCfs = customFieldManager.getCustomFieldObjects(newissue)
  84. newIssueCfs.intersect(customFieldManager.getCustomFieldObjects(issue)).each {CustomField cf ->
  85. // this format of setting a CF can be used before an issue is created
  86. // Something here may be causing GRV-40 - order is important
  87. newissue.setCustomFieldValue(cf, cf.getValue(issue))
  88. // If it's done like the following unit tests fail
  89. // newissue.setCustomFieldValue(cf, issue.getCustomFieldValue(cf))
  90. // this format must be used after it's created
  91. // if (cf.getValue(issue)) {
  92. // IssueChangeHolder changeHolder = new DefaultIssueChangeHolder();
  93. // cf.updateValue(null, newissue, new ModifiedValue(cf.getValue(newissue), cf.getValue(issue)), changeHolder)
  94. // }
  95. }
  96. }
  97. protected def copyLabels(Issue issue, MutableIssue newissue, User user) {
  98. issue.labels.each {label ->
  99. labelManager.addLabel(user, newissue.id, label.label, false)
  100. }
  101. }
  102. protected def copySystemFieldValues(Issue issue, MutableIssue newissue) {
  103. List systemFields = ["issueTypeId", "projectId", "summary", "assigneeId", "fixVersions", "affectedVersions",
  104. "reporterId", "environment", "description", "priorityId", "dueDate", "originalEstimate", "components",
  105. "securityLevel"
  106. ];
  107. Map allProps = issue.properties
  108. systemFields.each {String prop ->
  109. if (allProps.containsKey(prop)) {
  110. if (prop == "components") {
  111. def newComps = []
  112. issue.components.each {GenericValue gv ->
  113. ProjectComponent newComp = projectComponentManager.findByComponentName(newissue.project.id, gv.name)
  114. if (newComp)
  115. newComps.add(newComp.genericValue)
  116. }
  117. newissue.components = newComps
  118. }
  119. else if (prop == "affectedVersions") {
  120. def l = []
  121. issue.affectedVersions.each {Version v ->
  122. Version version = versionManager.getVersion(newissue.projectId, v.name)
  123. if (version) {
  124. l.add(version)
  125. }
  126. }
  127. newissue.affectedVersions = l
  128. }
  129. else if (prop == "fixVersions") {
  130. def l = []
  131. issue.fixVersions.each {Version v ->
  132. Version version = versionManager.getVersion(newissue.projectId, v.name)
  133. if (version) {
  134. l.add(version)
  135. }
  136. }
  137. newissue.fixVersions = l
  138. }
  139. // see https://studio.plugins.atlassian.com/browse/GRV-94
  140. else if (prop == "securityLevel") {
  141. def securityLevel = issue.getSecurityLevel()
  142. if (securityLevel) {
  143. if (issueSecuritySchemeManager.getSchemes(issue.project) == issueSecuritySchemeManager.getSchemes(newissue.project)) {
  144. newissue.setSecurityLevel(issue.securityLevel)
  145. }
  146. else {
  147. log.warn("Could not set security level, as the schemes between the two projects are different.")
  148. }
  149. }
  150. }
  151. // only copy issueTypeId and projectId if not already set through input parameters
  152. if (["issueTypeId", "projectId"]) {
  153. if (! newissue.@"$prop") {
  154. newissue.@"$prop" = issue.@"$prop"
  155. }
  156. }
  157. else {
  158. newissue.@"$prop" = issue.@"$prop"
  159. }
  160. }
  161. }
  162. }
  163. LinkedHashMap getOverridesParam() {
  164. [
  165. Name:FIELD_ADDITIONAL_SCRIPT,
  166. Label:'Additional issue actions',
  167. Description:"Enter any customisations to the target issue, e.g. hard-coding specific field values.",
  168. Type: "mediumtext",
  169. Examples: [
  170. "Set target issue summary": "issue.summary = \\'Cloned issue\\'",
  171. "Set custom field": "def cf = customFieldManager.getCustomFieldObjects(issue).find {it.name == \\'MyCustomFieldType\\'}\\n" +
  172. "issue.setCustomFieldValue(cf, \\'my value\\')"
  173. ]
  174. ]
  175. }
  176. }