]> git.uio.no Git - ifi-stolz-refaktor.git/blob - case-study/jdt-before/ui refactoring/org/eclipse/jdt/internal/ui/refactoring/RefactoringExecutionHelper.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-before / ui refactoring / org / eclipse / jdt / internal / ui / refactoring / RefactoringExecutionHelper.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2009 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package org.eclipse.jdt.internal.ui.refactoring;
12
13 import java.lang.reflect.InvocationTargetException;
14
15 import org.eclipse.swt.custom.BusyIndicator;
16 import org.eclipse.swt.widgets.Display;
17 import org.eclipse.swt.widgets.Shell;
18
19 import org.eclipse.core.runtime.Assert;
20 import org.eclipse.core.runtime.CoreException;
21 import org.eclipse.core.runtime.IProgressMonitor;
22 import org.eclipse.core.runtime.OperationCanceledException;
23 import org.eclipse.core.runtime.SubProgressMonitor;
24 import org.eclipse.core.runtime.jobs.IJobManager;
25 import org.eclipse.core.runtime.jobs.ISchedulingRule;
26 import org.eclipse.core.runtime.jobs.Job;
27
28 import org.eclipse.core.resources.IWorkspaceRunnable;
29 import org.eclipse.core.resources.ResourcesPlugin;
30
31 import org.eclipse.jface.dialogs.Dialog;
32 import org.eclipse.jface.dialogs.IDialogConstants;
33 import org.eclipse.jface.dialogs.MessageDialog;
34 import org.eclipse.jface.operation.IRunnableContext;
35
36 import org.eclipse.ltk.core.refactoring.Change;
37 import org.eclipse.ltk.core.refactoring.PerformChangeOperation;
38 import org.eclipse.ltk.core.refactoring.Refactoring;
39 import org.eclipse.ltk.core.refactoring.RefactoringCore;
40 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
41 import org.eclipse.ltk.ui.refactoring.RefactoringUI;
42
43 import org.eclipse.jdt.internal.corext.util.Messages;
44
45 import org.eclipse.jdt.ui.refactoring.RefactoringSaveHelper;
46
47 import org.eclipse.jdt.internal.ui.actions.WorkbenchRunnableAdapter;
48
49
50
51 /**
52  * A helper class to execute a refactoring. The class takes care of pushing the
53  * undo change onto the undo stack and folding editor edits into one editor
54  * undo object.
55  */
56 public class RefactoringExecutionHelper {
57
58         private final Refactoring fRefactoring;
59         private final Shell fParent;
60         private final IRunnableContext fExecContext;
61         private final int fStopSeverity;
62         private final int fSaveMode;
63
64         private class Operation implements IWorkspaceRunnable {
65                 public Change fChange;
66                 public PerformChangeOperation fPerformChangeOperation;
67                 private final boolean fForked;
68                 private final boolean fForkChangeExecution;
69
70                 public Operation(boolean forked, boolean forkChangeExecution) {
71                         fForked= forked;
72                         fForkChangeExecution= forkChangeExecution;
73         }
74
75                 public void run(IProgressMonitor pm) throws CoreException {
76                         try {
77                                 pm.beginTask("", fForked && !fForkChangeExecution ? 7 : 11); //$NON-NLS-1$
78                                 pm.subTask(""); //$NON-NLS-1$
79
80                                 final RefactoringStatus status= fRefactoring.checkAllConditions(new SubProgressMonitor(pm, 4, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
81                                 if (status.getSeverity() >= fStopSeverity) {
82                                         final boolean[] canceled= { false };
83                                         if (fForked) {
84                                                 fParent.getDisplay().syncExec(new Runnable() {
85                                                         public void run() {
86                                                                 canceled[0]= showStatusDialog(status);
87                                                         }
88                                                 });
89                                         } else {
90                                                 canceled[0]= showStatusDialog(status);
91                                         }
92                                         if (canceled[0]) {
93                                                 throw new OperationCanceledException();
94                                         }
95                                 }
96
97                                 fChange= fRefactoring.createChange(new SubProgressMonitor(pm, 2, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
98                                 fChange.initializeValidationData(new SubProgressMonitor(pm, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
99
100                                 fPerformChangeOperation= new PerformChangeOperation(fChange);//RefactoringUI.createUIAwareChangeOperation(fChange);
101                                 fPerformChangeOperation.setUndoManager(RefactoringCore.getUndoManager(), fRefactoring.getName());
102                                 if (fRefactoring instanceof IScheduledRefactoring)
103                                         fPerformChangeOperation.setSchedulingRule(((IScheduledRefactoring)fRefactoring).getSchedulingRule());
104
105                                 if (!fForked || fForkChangeExecution)
106                                         fPerformChangeOperation.run(new SubProgressMonitor(pm, 4, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
107                         } finally {
108                                 pm.done();
109                         }
110                 }
111
112                 /**
113                  * @param status the status to show
114                  * @return <code>true</code> iff the operation should be cancelled
115                  */
116                 private boolean showStatusDialog(RefactoringStatus status) {
117                         Dialog dialog= RefactoringUI.createRefactoringStatusDialog(status, fParent, fRefactoring.getName(), false);
118                         return dialog.open() == IDialogConstants.CANCEL_ID;
119                 }
120         }
121
122         /**
123          * Creates a new refactoring execution helper.
124          *
125          * @param refactoring the refactoring
126          * @param stopSeverity a refactoring status constant from {@link RefactoringStatus}
127          * @param saveMode a save mode from {@link RefactoringSaveHelper}
128          * @param parent the parent shell
129          * @param context the runnable context
130          */
131         public RefactoringExecutionHelper(Refactoring refactoring, int stopSeverity, int saveMode, Shell parent, IRunnableContext context) {
132                 super();
133                 Assert.isNotNull(refactoring);
134                 Assert.isNotNull(parent);
135                 Assert.isNotNull(context);
136                 fRefactoring= refactoring;
137                 fStopSeverity= stopSeverity;
138                 fParent= parent;
139                 fExecContext= context;
140                 fSaveMode= saveMode;
141         }
142
143         /**
144          * Must be called in the UI thread.
145          * @param fork if set, the operation will be forked
146          * @param cancelable  if set, the operation will be cancelable
147          * @throws InterruptedException thrown when the operation is cancelled
148          * @throws InvocationTargetException thrown when the operation failed to execute
149          */
150         public void perform(boolean fork, boolean cancelable) throws InterruptedException, InvocationTargetException {
151                 perform(fork, false, cancelable);
152         }
153
154         /**
155          * Must be called in the UI thread.<br>
156          * <strong>Use {@link #perform(boolean, boolean)} unless you know exactly what you are doing!</strong>
157          *
158          * @param fork if set, the operation will be forked
159          * @param forkChangeExecution if the change should not be executed in the UI thread: This may not work in any case
160          * @param cancelable  if set, the operation will be cancelable
161          * @throws InterruptedException thrown when the operation is cancelled
162          * @throws InvocationTargetException thrown when the operation failed to execute
163          */
164         public void perform(boolean fork, boolean forkChangeExecution, boolean cancelable) throws InterruptedException, InvocationTargetException {
165                 Assert.isTrue(Display.getCurrent() != null);
166                 final IJobManager manager=  Job.getJobManager();
167                 final ISchedulingRule rule;
168                 if (fRefactoring instanceof IScheduledRefactoring) {
169                         rule= ((IScheduledRefactoring)fRefactoring).getSchedulingRule();
170                 } else {
171                         rule= ResourcesPlugin.getWorkspace().getRoot();
172                 }
173                 try {
174                         try {
175                                 Runnable r= new Runnable() {
176                                         public void run() {
177                                                 manager.beginRule(rule, null);
178                                         }
179                                 };
180                                 BusyIndicator.showWhile(fParent.getDisplay(), r);
181                         } catch (OperationCanceledException e) {
182                                 throw new InterruptedException(e.getMessage());
183                         }
184
185                         RefactoringSaveHelper saveHelper= new RefactoringSaveHelper(fSaveMode);
186                         if (!saveHelper.saveEditors(fParent))
187                                 throw new InterruptedException();
188                         final Operation op= new Operation(fork, forkChangeExecution);
189                         fRefactoring.setValidationContext(fParent);
190                         try{
191                                 fExecContext.run(fork, cancelable, new WorkbenchRunnableAdapter(op, rule, true));
192                                 if (fork && !forkChangeExecution && op.fPerformChangeOperation != null)
193                                         fExecContext.run(false, false, new WorkbenchRunnableAdapter(op.fPerformChangeOperation, rule, true));
194
195                                 if (op.fPerformChangeOperation != null) {
196                                         RefactoringStatus validationStatus= op.fPerformChangeOperation.getValidationStatus();
197                                         if (validationStatus != null && validationStatus.hasFatalError()) {
198                                                 MessageDialog.openError(fParent, fRefactoring.getName(),
199                                                                 Messages.format(
200                                                                                 RefactoringMessages.RefactoringExecutionHelper_cannot_execute,
201                                                                                 validationStatus.getMessageMatchingSeverity(RefactoringStatus.FATAL)));
202                                                 throw new InterruptedException();
203                                         }
204                                 }
205                         } catch (InvocationTargetException e) {
206                                 PerformChangeOperation pco= op.fPerformChangeOperation;
207                                 if (pco != null && pco.changeExecutionFailed()) {
208                                         ChangeExceptionHandler handler= new ChangeExceptionHandler(fParent, fRefactoring);
209                                         Throwable inner= e.getTargetException();
210                                         if (inner instanceof RuntimeException) {
211                                                 handler.handle(pco.getChange(), (RuntimeException)inner);
212                                         } else if (inner instanceof CoreException) {
213                                                 handler.handle(pco.getChange(), (CoreException)inner);
214                                         } else {
215                                                 throw e;
216                                         }
217                                 } else {
218                                         throw e;
219                                 }
220                         } catch (OperationCanceledException e) {
221                                 throw new InterruptedException(e.getMessage());
222                         } finally {
223                                 saveHelper.triggerIncrementalBuild();
224                         }
225                 } finally {
226                         manager.endRule(rule);
227                         fRefactoring.setValidationContext(null);
228                 }
229         }
230 }