KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ltk > core > refactoring > PerformChangeOperation


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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.ltk.core.refactoring;
12
13 import org.eclipse.core.runtime.Assert;
14 import org.eclipse.core.runtime.CoreException;
15 import org.eclipse.core.runtime.IProgressMonitor;
16 import org.eclipse.core.runtime.NullProgressMonitor;
17 import org.eclipse.core.runtime.OperationCanceledException;
18 import org.eclipse.core.runtime.SubProgressMonitor;
19 import org.eclipse.core.runtime.jobs.ISchedulingRule;
20
21 import org.eclipse.core.resources.IWorkspace;
22 import org.eclipse.core.resources.IWorkspaceRunnable;
23 import org.eclipse.core.resources.ResourcesPlugin;
24
25 import org.eclipse.ltk.internal.core.refactoring.NotCancelableProgressMonitor;
26
27 /**
28  * Operation that, when run, performs a {@link Change} object. The operation
29  * can be created in two different ways: with a given change or with a
30  * {@link CreateChangeOperation}. If created the second way the given create
31  * change operation will be used to create the actual change to perform.
32  * <p>
33  * If the change has been performed successfully (e.g. {@link #changeExecuted()} returns
34  * <code>true</code>) then the operation has called {@link Change#dispose()} as well
35  * to clear-up internal state in the change object. If it hasn't been executed the
36  * change, the change is still intact and the client is responsible to dispose the
37  * change object.
38  * </p>
39  * <p>
40  * If an undo change has been provided by the change to execute then the operation
41  * calls {@link Change#initializeValidationData(IProgressMonitor)} to initialize the
42  * undo change's validation data.
43  * </p>
44  * <p>
45  * If an undo manager has been set via the method {@link #setUndoManager(IUndoManager, String)}
46  * then the undo object, if any has been provided, will be pushed onto the manager's
47  * undo stack.
48  * </p>
49  * <p>
50  * The operation should be executed via the run method offered by
51  * <code>IWorkspace</code> to achieve proper delta batching.
52  * </p>
53  * <p>
54  * Note: this class is not intended to be extended outside of the refactoring framework.
55  * </p>
56  *
57  * @since 3.0
58  */

59 public class PerformChangeOperation implements IWorkspaceRunnable {
60
61     private Change fChange;
62     private CreateChangeOperation fCreateChangeOperation;
63     private RefactoringStatus fValidationStatus;
64     
65     private Change fUndoChange;
66     private String JavaDoc fUndoName;
67     private IUndoManager fUndoManager;
68     
69     private boolean fChangeExecuted;
70     private boolean fChangeExecutionFailed;
71     private ISchedulingRule fSchedulingRule;
72     
73     /**
74      * Creates a new perform change operation instance for the given change.
75      *
76      * @param change the change to be applied to the workbench
77      */

78     public PerformChangeOperation(Change change) {
79         Assert.isNotNull(change);
80         fChange= change;
81         fSchedulingRule= ResourcesPlugin.getWorkspace().getRoot();
82     }
83
84     /**
85      * Creates a new <code>PerformChangeOperation</code> for the given {@link
86      * CreateChangeOperation}. The create change operation is used to create
87      * the actual change to execute.
88      *
89      * @param op the <code>CreateChangeOperation</code> used to create the
90      * actual change object
91      */

92     public PerformChangeOperation(CreateChangeOperation op) {
93         Assert.isNotNull(op);
94         fCreateChangeOperation= op;
95         fSchedulingRule= ResourcesPlugin.getWorkspace().getRoot();
96     }
97     
98     /**
99      * Returns <code>true</code> if the change execution failed.
100      *
101      * @return <code>true</code> if the change execution failed;
102      * <code>false</code> otherwise
103      *
104      */

105     public boolean changeExecutionFailed() {
106         return fChangeExecutionFailed;
107     }
108
109     /**
110      * Returns <code>true</code> if the change has been executed. Otherwise <code>
111      * false</code> is returned.
112      *
113      * @return <code>true</code> if the change has been executed, otherwise
114      * <code>false</code>
115      */

116     public boolean changeExecuted() {
117         return fChangeExecuted;
118     }
119     
120     /**
121      * Returns the status of the condition checking. Returns <code>null</code> if
122      * no condition checking has been requested.
123      *
124      * @return the status of the condition checking
125      */

126     public RefactoringStatus getConditionCheckingStatus() {
127         if (fCreateChangeOperation != null)
128             return fCreateChangeOperation.getConditionCheckingStatus();
129         return null;
130     }
131     
132     /**
133      * Returns the change used by this operation. This is either the change passed to
134      * the constructor or the one create by the <code>CreateChangeOperation</code>.
135      * Method returns <code>null</code> if the create operation did not create
136      * a corresponding change or hasn't been executed yet.
137      *
138      * @return the change used by this operation or <code>null</code> if no change
139      * has been created
140      */

141     public Change getChange() {
142         return fChange;
143     }
144     
145     /**
146      * Returns the undo change of the change performed by this operation. Returns
147      * <code>null</code> if the change hasn't been performed yet or if the change
148      * doesn't provide a undo.
149      *
150      * @return the undo change of the performed change or <code>null</code>
151      */

152     public Change getUndoChange() {
153         return fUndoChange;
154     }
155     
156     /**
157      * Returns the refactoring status returned from the call <code>IChange#isValid()</code>.
158      * Returns <code>null</code> if the change has not been executed.
159      *
160      * @return the change's validation status
161      */

162     public RefactoringStatus getValidationStatus() {
163         return fValidationStatus;
164     }
165     
166     /**
167      * Sets the undo manager. If the executed change provides an undo change,
168      * then the undo change is pushed onto this manager.
169      *
170      * @param manager the undo manager to use or <code>null</code> if no
171      * undo recording is desired
172      * @param undoName the name used to present the undo change on the undo
173      * stack. Must be a human-readable string. Must not be <code>null</code>
174      * if manager is unequal <code>null</code>
175      */

176     public void setUndoManager(IUndoManager manager, String JavaDoc undoName) {
177         if (manager != null) {
178             Assert.isNotNull(undoName);
179         }
180         fUndoManager= manager;
181         fUndoName= undoName;
182     }
183     
184     /**
185      * Sets the scheduling rule used to execute this operation. If
186      * not set then the workspace root is used. The Change operation
187      * must be able to be performed in the provided scheduling rule.
188      *
189      * @param rule the Rule to use, not null
190      * @since 3.3
191      */

192     public void setSchedulingRule(ISchedulingRule rule) {
193         Assert.isNotNull(rule);
194         
195         fSchedulingRule= rule;
196     }
197
198     /**
199      * {@inheritDoc}
200      */

201     public void run(IProgressMonitor pm) throws CoreException {
202         if (pm == null)
203             pm= new NullProgressMonitor();
204         try {
205             fChangeExecuted= false;
206             if (createChange()) {
207                 pm.beginTask("", 4); //$NON-NLS-1$
208
pm.subTask(""); //$NON-NLS-1$
209
fCreateChangeOperation.run(new SubProgressMonitor(pm, 3));
210                 // Check for cancellation before executing the change, since canceling
211
// during change execution is not supported
212
// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=187265 ):
213
if (pm.isCanceled())
214                     throw new OperationCanceledException();
215                 
216                 fChange= fCreateChangeOperation.getChange();
217                 if (fChange != null) {
218                     executeChange(new SubProgressMonitor(pm, 1));
219                 } else {
220                     pm.worked(1);
221                 }
222             } else {
223                 executeChange(pm);
224             }
225         } finally {
226             pm.done();
227         }
228     }
229     
230     /**
231      * Actually executes the change.
232      *
233      * @param pm a progress monitor to report progress
234      *
235      * @throws CoreException if an unexpected error occurs during
236      * change execution
237      */

238     protected void executeChange(IProgressMonitor pm) throws CoreException {
239         fChangeExecuted= false;
240         if (!fChange.isEnabled())
241             return;
242         IWorkspaceRunnable runnable= new IWorkspaceRunnable() {
243             public void run(IProgressMonitor monitor) throws CoreException {
244                 boolean undoInitialized= false;
245                 try {
246                     monitor.beginTask("", 10); //$NON-NLS-1$
247
fValidationStatus= fChange.isValid(new SubProgressMonitor(monitor, 1));
248                     if (fValidationStatus.hasFatalError())
249                         return;
250                     boolean aboutToPerformChangeCalled= false;
251                     try {
252                         if (fUndoManager != null) {
253                             ResourcesPlugin.getWorkspace().checkpoint(false);
254                             fUndoManager.aboutToPerformChange(fChange);
255                             aboutToPerformChangeCalled= true;
256                         }
257                         fChangeExecutionFailed= true;
258                         fUndoChange= fChange.perform(new SubProgressMonitor(monitor, 9));
259                         fChangeExecutionFailed= false;
260                         fChangeExecuted= true;
261                     } finally {
262                         if (fUndoManager != null) {
263                             ResourcesPlugin.getWorkspace().checkpoint(false);
264                             if (aboutToPerformChangeCalled)
265                                 fUndoManager.changePerformed(fChange, !fChangeExecutionFailed);
266                         }
267                     }
268                     fChange.dispose();
269                     if (fUndoChange != null) {
270                         fUndoChange.initializeValidationData(new NotCancelableProgressMonitor(
271                             new SubProgressMonitor(monitor, 1)));
272                         undoInitialized= true;
273                     }
274                     if (fUndoManager != null) {
275                         if (fUndoChange != null) {
276                             fUndoManager.addUndo(fUndoName, fUndoChange);
277                         } else {
278                             fUndoManager.flush();
279                         }
280                     }
281                 } catch (CoreException e) {
282                     if (fUndoManager != null)
283                         fUndoManager.flush();
284                     if (fUndoChange != null && undoInitialized) {
285                         Change ch= fUndoChange;
286                         fUndoChange= null;
287                         ch.dispose();
288                     }
289                     fUndoChange= null;
290                     throw e;
291                 } catch (RuntimeException JavaDoc e) {
292                     if (fUndoManager != null)
293                         fUndoManager.flush();
294                     if (fUndoChange != null && undoInitialized) {
295                         Change ch= fUndoChange;
296                         fUndoChange= null;
297                         ch.dispose();
298                     }
299                     fUndoChange= null;
300                     throw e;
301                 } finally {
302                     monitor.done();
303                 }
304             }
305         };
306         ResourcesPlugin.getWorkspace().run(runnable, fSchedulingRule, IWorkspace.AVOID_UPDATE, pm);
307     }
308     
309     private boolean createChange() {
310         return fCreateChangeOperation != null;
311     }
312 }
313
Popular Tags