KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > ui > TeamOperation


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 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.team.ui;
12
13 import java.lang.reflect.InvocationTargetException JavaDoc;
14 import java.net.URL JavaDoc;
15
16 import org.eclipse.core.runtime.IStatus;
17 import org.eclipse.core.runtime.Status;
18 import org.eclipse.core.runtime.jobs.*;
19 import org.eclipse.jface.action.IAction;
20 import org.eclipse.jface.operation.IRunnableContext;
21 import org.eclipse.jface.operation.IRunnableWithProgress;
22 import org.eclipse.swt.widgets.Display;
23 import org.eclipse.swt.widgets.Shell;
24 import org.eclipse.team.internal.ui.TeamUIPlugin;
25 import org.eclipse.team.internal.ui.Utils;
26 import org.eclipse.team.internal.ui.actions.*;
27 import org.eclipse.ui.IWorkbenchPart;
28 import org.eclipse.ui.IWorkbenchSite;
29 import org.eclipse.ui.progress.IProgressConstants;
30
31 /**
32  * An operation that can be configured to run in the foreground using
33  * the {@link org.eclipse.ui.progress.IProgressService} or the background
34  * as a {@link org.eclipse.core.runtime.jobs.Job}. The execution context is determined
35  * by what is returned by the {@link #canRunAsJob()} hint which may be overridden by subclasses.
36  * Subclass must override the <code>run(IProgressMonitor)</code> method to perform
37  * the behavior of the operation in the desired execution context.
38  * <p>
39  * If this operation is run as a job, it is registered with the job as a
40  * {@link org.eclipse.core.runtime.jobs.IJobChangeListener} and is scheduled with
41  * the part of this operation if it is not <code>null</code>.
42  * Subclasses can override the methods of this interface to receive job change notifications.
43  * </p>
44  * @see org.eclipse.ui.progress.IProgressService
45  * @see org.eclipse.core.runtime.jobs.Job
46  * @see org.eclipse.core.runtime.jobs.ISchedulingRule
47  * @see org.eclipse.core.runtime.jobs.IJobChangeListener
48  * @since 3.0
49  */

50 public abstract class TeamOperation extends JobChangeAdapter implements IRunnableWithProgress {
51     
52     private IWorkbenchPart part;
53     private IRunnableContext context;
54     
55     /*
56      * Job context that configures how the team operation will
57      * interact with the progress service
58      */

59     private static class TeamOperationJobContext extends JobRunnableContext {
60
61         private final TeamOperation operation;
62         private IAction gotoAction;
63
64         public TeamOperationJobContext(TeamOperation operation) {
65             super(operation.getJobName(), operation, operation.getSite());
66             this.operation = operation;
67         }
68         
69         protected void configureJob(Job job) {
70             super.configureJob(job);
71             if (operation.isKeepOneProgressServiceEntry())
72                 job.setProperty(IProgressConstants.KEEPONE_PROPERTY, Boolean.TRUE);
73             else if(operation.getKeepOperation())
74                 job.setProperty(IProgressConstants.KEEP_PROPERTY, Boolean.TRUE);
75             gotoAction = operation.getGotoAction();
76             if(gotoAction != null)
77                 job.setProperty(IProgressConstants.ACTION_PROPERTY, gotoAction);
78             URL JavaDoc icon = operation.getOperationIcon();
79             if(icon != null)
80                 job.setProperty(IProgressConstants.ICON_PROPERTY, icon);
81         }
82
83         /* (non-Javadoc)
84          * @see org.eclipse.team.internal.ui.actions.JobRunnableContext#belongsTo(org.eclipse.team.internal.ui.actions.JobRunnableContext.IContextJob, java.lang.Object)
85          */

86         protected boolean belongsTo(IContextJob job, Object JavaDoc family) {
87             if (family instanceof IContextJob) {
88                 IContextJob otherJob = (IContextJob)family;
89                 IRunnableWithProgress runnable = otherJob.getRunnable();
90                 if (runnable instanceof TeamOperation) {
91                     return operation.isSameFamilyAs((TeamOperation)runnable);
92                 }
93             }
94             return operation.belongsTo(family);
95         }
96         
97         /* (non-Javadoc)
98          * @see org.eclipse.team.internal.ui.actions.JobRunnableContext#getCompletionStatus()
99          */

100         protected IStatus getCompletionStatus() {
101             if (gotoAction != null) {
102                 return new Status(IStatus.OK, TeamUIPlugin.ID, IStatus.OK, gotoAction.getText(), null);
103             }
104             return super.getCompletionStatus();
105         }
106         
107         /* (non-Javadoc)
108          * @see org.eclipse.team.internal.ui.actions.JobRunnableContext#isUser()
109          */

110         protected boolean isUser() {
111             return operation.isUserInitiated();
112         }
113     }
114     
115     /**
116      * Create an team operation associated with the given part.
117      * @param part the part the operation is associated with or <code>null</code> if the
118      * operation is to be run without a part.
119      */

120     protected TeamOperation(IWorkbenchPart part) {
121         this(part, null);
122     }
123
124     /**
125      * Create an team operation that will run in the given context.
126      * @param context a runnable context
127      */

128     protected TeamOperation(IRunnableContext context) {
129         this(null, context);
130     }
131     
132     /**
133      * Create an team operation associated with the given part
134      * that will run in the given context.
135      * @param part the part the operation is associated with or <code>null</code>
136      * @param context a runnable context
137      */

138     protected TeamOperation(IWorkbenchPart part, IRunnableContext context) {
139         this.part = part;
140         this.context = context;
141     }
142
143     /**
144      * Return the part that is associated with this operation.
145      *
146      * @return Returns the part or <code>null</code>
147      */

148     public IWorkbenchPart getPart() {
149         return part;
150     }
151     
152     /**
153      * Run the operation in a context that is determined by the {@link #canRunAsJob()}
154      * hint. If this operation can run as a job then it will be run in a background thread.
155      * Otherwise it will run in the foreground and block the caller.
156      */

157     public final void run() throws InvocationTargetException JavaDoc, InterruptedException JavaDoc {
158         if (shouldRun()) {
159             getRunnableContext().run(this);
160         }
161     }
162
163     /**
164      * This method is invoked from the <code>run()</code> method before
165      * the operation is run in the operation's context. Subclasses may
166      * override in order to perform pre-checks to determine if the operation
167      * should run. This may include prompting the user for information, etc.
168      *
169      * @return whether the operation should be run.
170      */

171     protected boolean shouldRun() {
172         return true;
173     }
174
175     /**
176      * Returns the scheduling rule that is to be obtained before this
177      * operation is executed by its context or <code>null</code> if
178      * no scheduling rule is to be obtained. If the operation is run
179      * as a job, the scheduling rule is used as the scheduling rule of the
180      * job. Otherwise, it is obtained before execution of the operation
181      * occurs.
182      * <p>
183      * By default, no scheduling
184      * rule is obtained. Subclasses can override in order to obtain a
185      * scheduling rule or can obtain scheduling rules within their operation
186      * if finer grained scheduling is desired.
187      *
188      * @return the scheduling rule to be obtained by this operation
189      * or <code>null</code>.
190      */

191     protected ISchedulingRule getSchedulingRule() {
192         return null;
193     }
194     
195     /**
196      * Return whether the auto-build should be postponed until after
197      * the operation is complete. The default is to postpone the auto-build.
198      * subclasses can override.
199      *
200      * @return whether to postpone the auto-build while the operation is executing.
201      */

202     protected boolean isPostponeAutobuild() {
203         return true;
204     }
205     
206     /**
207      * If this operation can safely be run in the background, then subclasses can
208      * override this method and return <code>true</code>. This will make their
209      * action run in a {@link org.eclipse.core.runtime.jobs.Job}.
210      * Subclass that override this method should
211      * also override the <code>getJobName()</code> method.
212      *
213      * @return <code>true</code> if this action can be run in the background and
214      * <code>false</code> otherwise.
215      */

216     protected boolean canRunAsJob() {
217         return false;
218     }
219     
220     /**
221      * Return the job name to be used if the action can run as a job. (i.e.
222      * if <code>canRunAsJob()</code> returns <code>true</code>).
223      *
224      * @return the string to be used as the job name
225      */

226     protected String JavaDoc getJobName() {
227         return ""; //$NON-NLS-1$
228
}
229     
230     /**
231      * This method is called to allow subclasses to configure an action that could be run to show
232      * the results of the action to the user. Default is to return null.
233      *
234      * @return an action that could be run to see the results of this operation
235      */

236     protected IAction getGotoAction() {
237         return null;
238     }
239     
240     /**
241      * This method is called to allow subclasses to configure an icon to show when running this
242      * operation.
243      *
244      * @return an URL to an icon
245      */

246     protected URL JavaDoc getOperationIcon() {
247         return null;
248     }
249     
250     /**
251      * This method is called to allow subclasses to have the results of the
252      * operation remain available to the user in the progress service even after
253      * the job is done. This method is only relevant if the operation is run as
254      * a job (i.e., <code>canRunAsJob</code> returns <code>true</code>).
255      *
256      * @return <code>true</code> to keep the operation and <code>false</code>
257      * otherwise.
258      */

259     protected boolean getKeepOperation() {
260         return false;
261     }
262     
263     /**
264      * This method is similar to <code>getKeepOperation</code> but will
265      * only keep one entry of a particular type available.
266      * This method is only relevant if the operation is run as
267      * a job (i.e., <code>canRunAsJob</code> returns <code>true</code>).
268      * Subclasses that override this method should also override
269      * <code>isSameFamilyAs</code> in order to match operations of the same type.
270      *
271      * @return <code>true</code> to keep the operation and <code>false</code>
272      * otherwise.
273      * @since 3.1
274      */

275     public boolean isKeepOneProgressServiceEntry() {
276         return false;
277     }
278     
279     /**
280      * Return whether this Team operation belongs to the same family
281      * as the given operation for the purpose of showing only one
282      * operation of the same type in the progress service when
283      * <code>isKeepOneProgressServiceEntry</code> is overridden to
284      * return <code>true</code>. By default,
285      * <code>false</code> is returned. Subclasses may override.
286      * @param operation a team operation
287      * @since 3.1
288      */

289     protected boolean isSameFamilyAs(TeamOperation operation) {
290         return false;
291     }
292     
293     /**
294      * Return whether the job that is running this operation should be considered
295      * a member member of the given family. Subclasses can override this method in
296      * order to support the family based functionality provided by the {@link IJobManager}.
297      * By default, <code>false</code> is always returned. Subclasses that override the
298      * <code>isKeepOneProgressServiceEntry</code> method do not need to override
299      * this method, but instead should override <code>isSameFamilyAs</code>.
300      *
301      * @param family the family being tested.
302      * @return whether the job that is running this operation should be considered
303      * a member member of the given family.
304      * @since 3.1
305      */

306     public boolean belongsTo(Object JavaDoc family) {
307         return false;
308     }
309     
310     /**
311      * Indicates whether the operation was user initiated. The
312      * progress for user initiated jobs may be presented differently
313      * than non-user initiated operations if they are run as jobs.
314      * @return whether the operation is user initiated
315      * @since 3.1
316      */

317     public boolean isUserInitiated() {
318         return true;
319     }
320     
321     /**
322      * Return a shell that can be used by the operation to display dialogs, etc.
323      *
324      * @return a shell
325      */

326     protected Shell getShell() {
327         final Shell[] shell = new Shell[] { null };
328         if (Display.getCurrent() == null) {
329             Display.getDefault().syncExec(new Runnable JavaDoc() {
330                 public void run() {
331                     shell[0] = Utils.getShell(getSite());
332                 }
333             });
334         } else {
335             shell[0] = Utils.getShell(getSite());
336         }
337         return shell[0];
338     }
339     
340     /*
341      * Uses the {@link #canRunAsJob()} hint to return a {@link ITeamRunnableContext}
342      * that is used to execute the <code>run(SyncInfoSet, IProgressMonitor)</code>
343      * method of this action.
344      *
345      * @param syncSet the sync info set containing the selected elements for which this
346      * action is enabled.
347      * @return the runnable context in which to run this action.
348      */

349     private ITeamRunnableContext getRunnableContext() {
350         if (context == null && canRunAsJob()) {
351             JobRunnableContext context = new TeamOperationJobContext(this);
352             context.setPostponeBuild(isPostponeAutobuild());
353             context.setSchedulingRule(getSchedulingRule());
354             return context;
355         } else {
356             ProgressDialogRunnableContext context = new ProgressDialogRunnableContext();
357             context.setPostponeBuild(isPostponeAutobuild());
358             context.setSchedulingRule(getSchedulingRule());
359             if (this.context != null) {
360                 context.setRunnableContext(this.context);
361             }
362             return context;
363         }
364     }
365     
366     private IWorkbenchSite getSite() {
367         IWorkbenchSite site = null;
368         if(part != null) {
369             site = part.getSite();
370         }
371         return site;
372     }
373 }
374
Popular Tags