View Javadoc

1   package com.atlassian.theplugin.idea.action.issues;
2   
3   import com.atlassian.theplugin.commons.remoteapi.ServerData;
4   import com.atlassian.theplugin.idea.Constants;
5   import com.atlassian.theplugin.idea.IdeaHelper;
6   import com.atlassian.theplugin.idea.jira.*;
7   import com.atlassian.theplugin.idea.ui.DialogWithDetails;
8   import com.atlassian.theplugin.jira.JIRAIssueProgressTimestampCache;
9   import com.atlassian.theplugin.jira.JIRAServerFacade;
10  import com.atlassian.theplugin.jira.JiraActionFieldType;
11  import com.atlassian.theplugin.jira.api.JIRAAction;
12  import com.atlassian.theplugin.jira.api.JIRAActionField;
13  import com.atlassian.theplugin.jira.api.JIRAException;
14  import com.atlassian.theplugin.jira.api.JIRAIssue;
15  import com.atlassian.theplugin.jira.model.JIRAIssueListModelBuilder;
16  import com.intellij.openapi.actionSystem.AnAction;
17  import com.intellij.openapi.actionSystem.AnActionEvent;
18  import com.intellij.openapi.progress.ProgressIndicator;
19  import com.intellij.openapi.progress.ProgressManager;
20  import com.intellij.openapi.progress.Task;
21  import com.intellij.openapi.project.Project;
22  import com.intellij.openapi.ui.DialogWrapper;
23  
24  import java.awt.*;
25  import java.util.List;
26  
27  public class RunIssueActionAction extends AnAction {
28  	private final JIRAIssue issue;
29  	private JIRAAction action;
30  	private JIRAServerFacade facade;
31  	private IssueActionProvider window;
32  	private JIRAIssueListModelBuilder jiraIssueListModelBuilder;
33  
34  	public RunIssueActionAction(IssueActionProvider toolWindow, JIRAServerFacade facade,
35  			JIRAIssue issue, JIRAAction jiraAction, final JIRAIssueListModelBuilder jiraIssueListModelBuilder) {
36  		super(jiraAction.getName());
37  		this.issue = issue;
38  		action = jiraAction;
39  		window = toolWindow;
40  		this.facade = facade;
41  		this.jiraIssueListModelBuilder = jiraIssueListModelBuilder;
42  	}
43  
44  	@Override
45  	public void actionPerformed(AnActionEvent event) {
46  		runIssueAction(IdeaHelper.getCurrentProject(event), null);
47  	}
48  
49  	public void runIssueAction(Project project, DeactivateIssueResultHandler resultHandler) {
50  		ProgressManager.getInstance().run(new IssueActionRunnable(project, resultHandler));
51  	}
52  
53  	private class IssueActionRunnable extends Task.Modal {
54  		private Project project;
55          private DeactivateIssueResultHandler resultHandler;
56  
57          IssueActionRunnable(Project project, DeactivateIssueResultHandler resultHandler) {
58  			super(project, "Running Issue Action", true);
59  			this.project = project;
60              this.resultHandler = resultHandler;
61          }
62  
63  		public void run(final ProgressIndicator indicator) {
64  
65  			if (indicator != null) {
66  				indicator.setFraction(0.0);
67  				indicator.setIndeterminate(true);
68  			}
69  
70  			showInfo("Retrieving fields for action \"" + action.getName() + "\" in issue " + issue.getKey() + "...");
71  
72  			final ServerData server = issue.getServer();
73  
74  			if (server != null) {
75  				final List<JIRAActionField> fields;
76  				try {
77  					fields = facade.getFieldsForAction(server, issue, action);
78  				} catch (JIRAException e) {
79  					showError(
80  							"Cannot retrieve fields for action [" + action.getName() + "] on issue [" + issue.getKey() + "]"
81  									+ e.getMessage(), e);
82  					showDialogDetailedInfo(project, e);
83                      notifyResultHandler(resultHandler, e);
84  					return;
85  				}
86  
87  				showInfo("Retrieving issue details");
88  				final JIRAIssue detailedIssue;
89  				try {
90  					JIRAIssue issueWithTime = facade.getIssue(issue.getServer(),
91  							issue.getKey());
92  					detailedIssue = facade.getIssueDetails(issue.getServer(), issueWithTime);
93  				} catch (JIRAException e) {
94  					showError("Cannot retrieve issue details for [" + issue.getKey() + "]: " + e.getMessage(), e);
95  					showDialogDetailedInfo(project, e);
96                      notifyResultHandler(resultHandler, e);
97  					return;
98  				}
99  
100 				showInfo("Running action [" + action.getName() + "] on issue [" + issue.getKey() + "]...");
101 
102 				showInfo("Retrieving values for action fields");
103 				final List<JIRAActionField> preFilleddfields = JiraActionFieldType.fillFieldValues(detailedIssue, fields);
104 
105 				if (preFilleddfields.isEmpty()) {
106 					try {
107 						facade.progressWorkflowAction(server, issue, action);
108 						performPostActionActivity(server);
109 					} catch (JIRAException e) {
110 						showError("Unable to run action [" + action.getName() + "] on issue [" + issue.getKey() + "]: "
111 								+ e.getMessage(), e);
112 						showDialogDetailedInfo(project, e);
113                         notifyResultHandler(resultHandler, e);
114 					}
115 				} else {
116 					EventQueue.invokeLater(new LocalDisplayActionDialogRunnable(project, detailedIssue,
117                             preFilleddfields, server, resultHandler));
118 				}
119 			}
120 		}
121 	}
122 
123 	private void showInfo(final String s) {
124 		window.setStatusInfoMessage(s);
125 	}
126 
127 	private void showError(final String error, final Throwable exception) {
128 		window.setStatusErrorMessage(error, exception);
129 	}
130 
131 	private void showDialogDetailedInfo(final Project project, final Throwable e) {
132 		EventQueue.invokeLater(new Runnable() {
133 			public void run() {
134 				DialogWithDetails.showExceptionDialog(project, e.getMessage(), e);
135 			}
136 		});
137 	}
138 
139 	/**
140 	 * Should be called in the background thread
141 	 *
142 	 * @param server
143 	 * @throws JIRAException
144 	 */
145 	private void performPostActionActivity(final ServerData server) throws JIRAException {
146 		if (action.getId() == Constants.JiraActionId.START_PROGRESS.getId()) {
147 			JIRAIssueProgressTimestampCache.getInstance().setTimestamp(server, issue);
148 		} else if (action.getId() == Constants.JiraActionId.STOP_PROGRESS.getId()) {
149 			JIRAIssueProgressTimestampCache.getInstance().removeTimestamp(server, issue);
150 		}
151 
152 		JiraIssueAdapter.get(issue).clearCachedActions();
153 
154 		if (jiraIssueListModelBuilder != null) {
155 			jiraIssueListModelBuilder.reloadIssue(issue.getKey(), server);
156 		}
157 		showInfo("Action [" + action.getName() + "] on issue " + issue.getKey() + " run succesfully");
158 	}
159 
160 	private class LocalDisplayActionDialogRunnable implements Runnable {
161 		private Project project;
162 		private JIRAIssue detailedIssue;
163 		private List<JIRAActionField> preFilleddfields;
164 		private ServerData server;
165         private DeactivateIssueResultHandler resultHandler;
166 
167         public LocalDisplayActionDialogRunnable(final Project project, final JIRAIssue detailedIssue,
168                                                 final List<JIRAActionField> preFilleddfields, final ServerData server,
169                                                 DeactivateIssueResultHandler resultHandler) {
170 			this.project = project;
171 			this.detailedIssue = detailedIssue;
172 			this.preFilleddfields = preFilleddfields;
173 			this.server = server;
174             this.resultHandler = resultHandler;
175         }
176 
177 		public void run() {
178 			// show action fields dialog
179 			final PerformIssueActionForm dialog =
180 					new PerformIssueActionForm(project, detailedIssue, preFilleddfields,
181 							action.getName() + " " + detailedIssue.getKey());
182 			dialog.show();
183 			if (dialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) {
184 				// perform workflow action in the background thread
185 				ProgressManager.getInstance().run(
186 						new Task.Backgroundable(project, "Running Workflow Action", false) {
187 							public void run(final ProgressIndicator indicator) {
188 								if (indicator != null) {
189 									indicator.setFraction(0.0);
190 									indicator.setIndeterminate(true);
191 								}
192 								try {
193 									facade.progressWorkflowAction(server, issue, action, dialog.getFields());
194 								} catch (JIRAException e) {
195 									showError("Unable to run action [" + action.getName() + "] on issue ["
196 											+ issue.getKey() + "]: " + e.getMessage(), e);
197 									showDialogDetailedInfo(project, e);
198                                     notifyResultHandler(resultHandler, e);
199                                     return;
200 								}
201 								try {
202 									if (dialog.getComment() != null && dialog.getComment().length() > 0) {
203 										facade.addComment(server, issue.getKey(), dialog.getComment());
204 									}
205 								} catch (JIRAException e) {
206 									showError("Unable to add comment to action [" + action.getName()
207 											+ "] on issue [" + issue.getKey() + "]: " + e.getMessage(), e);
208 									showDialogDetailedInfo(project, e);
209                                     notifyResultHandler(resultHandler, e);
210                                 }
211 								try {
212 									performPostActionActivity(server);
213                                     if (resultHandler != null) {
214                                         resultHandler.success();
215                                     }
216 								} catch (JIRAException e) {
217 									showError(e.getMessage(), e);
218 									showDialogDetailedInfo(project, e);
219                                     notifyResultHandler(resultHandler, e);
220                                 }
221 							}
222 						});
223 			} else {
224 				showInfo("Running workflow action [" + action.getName() + "] cancelled");
225 			}
226 		}
227     }
228 
229     private void notifyResultHandler(DeactivateIssueResultHandler resultHandler, JIRAException e) {
230         if (resultHandler != null) {
231             resultHandler.failure(e);
232         }
233     }
234 }