Skip to main content
summaryrefslogtreecommitdiffstats
blob: 59463ba4b27e96fafa64ee25e9887abffc8376c0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
/*******************************************************************************
 * Copyright (c) 2002, 2008 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Initial Contributors:
 * The following IBM employees contributed to the Remote System Explorer
 * component that contains this file: David McKnight, Kushal Munir, 
 * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, 
 * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley.
 * 
 * Contributors:
 * Martin Oberhuber (Wind River) - [168975] Move RSE Events API to Core
 * Martin Oberhuber (Wind River) - [186128][refactoring] Move IProgressMonitor last in public base classes 
 * Martin Oberhuber (Wind River) - [186773] split ISystemRegistryUI from ISystemRegistry
 * David McKnight   (IBM)        - [223103] [cleanup] fix broken externalized strings
 * David McKnight   (IBM)        - [224313] [api] Create RSE Events for MOVE and COPY holding both source and destination fields
 *******************************************************************************/

package org.eclipse.rse.ui.actions;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.rse.core.RSECorePlugin;
import org.eclipse.rse.core.model.ISystemProfileManager;
import org.eclipse.rse.core.model.ISystemRegistry;
import org.eclipse.rse.internal.core.model.SystemProfileManager;
import org.eclipse.rse.internal.ui.SystemResources;
import org.eclipse.rse.services.clientserver.messages.SystemMessage;
import org.eclipse.rse.services.clientserver.messages.SystemMessageException;
import org.eclipse.rse.ui.ISystemContextMenuConstants;
import org.eclipse.rse.ui.ISystemIconConstants;
import org.eclipse.rse.ui.ISystemMessages;
import org.eclipse.rse.ui.RSEUIPlugin;
import org.eclipse.rse.ui.dialogs.SystemSimpleContentElement;
import org.eclipse.rse.ui.dialogs.SystemSimpleCopyDialog;
import org.eclipse.rse.ui.messages.SystemMessageDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;


/**
 * An abstract base class for all copy actions. Defers minimal requirements to 
 *  child classes.
 */
public abstract class SystemBaseCopyAction extends SystemBaseDialogAction 
                implements IRunnableWithProgress, ISystemCopyTargetSelectionCallback
{	
	protected ISystemProfileManager mgr;
	protected ISystemRegistry sr;
	protected String[] oldNames;
	protected String[] newNames;
	protected Object[] oldObjects;
	protected Object targetContainer;
	protected boolean copiedOk = true;
	//private boolean makeActive;
    protected Exception runException = null;
    protected int mode = SystemSimpleCopyDialog.MODE_COPY;
    protected int runCount = 0;
	public static final int MODE_COPY = SystemSimpleCopyDialog.MODE_COPY;
	public static final int MODE_MOVE = SystemSimpleCopyDialog.MODE_MOVE;
    
    	
	/**
	 * Constructor when using default action ID
	 * @param parent Owning shell
	 * @param mode Either MODE_COPY or MODE_MOVE from this class
	 */
	public SystemBaseCopyAction(Shell parent, int mode) 
	{
		this(parent, mode==MODE_COPY ? SystemResources.ACTION_COPY_LABEL : SystemResources.ACTION_MOVE_LABEL, mode);
		setToolTipText(mode==MODE_COPY ? SystemResources.ACTION_COPY_TOOLTIP : SystemResources.ACTION_MOVE_TOOLTIP);
	}

	/**
	 * Constructor
	 * @param parent Owning shell
	 * @param label
	 * @param mode Either MODE_COPY or MODE_MOVE from this class
	 */
	public SystemBaseCopyAction(Shell parent, String label, int mode) 
	{
		super(label, 
		      (mode==MODE_COPY ? 
		            PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_COPY)
		      		//RSEUIPlugin.getDefault().getImageDescriptor(ISystemConstants.ICON_SYSTEM_COPY_ID) 
		            : RSEUIPlugin.getDefault().getImageDescriptor(ISystemIconConstants.ICON_SYSTEM_MOVE_ID)), 
		      parent);
		this.mode = mode;
		mgr = SystemProfileManager.getDefault();
		sr = RSECorePlugin.getTheSystemRegistry();
		allowOnMultipleSelection(true);
        setProcessAllSelections(true);
		setContextMenuGroup(ISystemContextMenuConstants.GROUP_REORGANIZE);
	}
	
	/**
	 * Reset. This is a re-run of this action
	 */
	protected void reset()
	{
		oldNames = null;
		newNames = null;
		oldObjects = null;
		targetContainer = null;
		copiedOk = true;
		runException = null;
		//System.out.println("inside base reset()");
	}

	/**
	 * Override of parent.
	 * Return the dialog that will be used to prompt for the copy/move target location
	 * @see #run()
	 */
	protected Dialog createDialog(Shell parent)
	{
		++runCount;
		if (runCount > 1)		
		  reset();
		SystemSimpleCopyDialog copyDlg = new SystemSimpleCopyDialog(parent, getPromptString(), mode, this, getTreeModel(), getTreeInitialSelection());

		// our title now reflects multiple selection. If single change it.
		IStructuredSelection sel = getSelection();
		//System.out.println("size = "+sel.size());
		if (sel.size() == 1)
		{		
			String singleTitle = null;
			if (mode == MODE_COPY)
				singleTitle = SystemResources.RESID_COPY_SINGLE_TITLE;
			else
				singleTitle = SystemResources.RESID_MOVE_SINGLE_TITLE;
			//System.out.println("..."+singleTitle);
			if (!singleTitle.startsWith("Missing")) // TODO: remove test after next mri rev         	 //$NON-NLS-1$
				copyDlg.setTitle(singleTitle);
		}									
		
		return copyDlg; 
	}

	protected abstract String[] getOldNames();
	protected abstract Object[] getOldObjects();	
	/**
	 * Get the verbiage prompt to show on line one of the copy dialog
	 */	
	protected String getPromptString()
	{
		if (mode == MODE_COPY)		
		  return SystemResources.RESID_COPY_PROMPT;		
		else
		  return SystemResources.RESID_MOVE_PROMPT;		
	}
	
	protected abstract SystemSimpleContentElement getTreeModel();
	protected abstract SystemSimpleContentElement getTreeInitialSelection();
	
	/**
	 * This method is a callback from the select-target-parent dialog, allowing us to decide whether the current selected
	 * object is a valid parent object. This affects the enabling of the OK button on that dialog.
	 * <p>
	 * The default is to return true if the selected element has no children. This is sufficient for most cases. However, 
	 * in some cases it is not, such as for filter strings where we want to only enable OK if a filter is selected. It is 
	 * possible that filter pools have no filters, so the default algorithm is not sufficient. In these cases the child class
	 * can override this method.
	 */
	public boolean isValidTargetParent(SystemSimpleContentElement selectedElement)
	{
		return !selectedElement.hasChildren();
	}
	
		
	/**
	 * Required by parent. We use it to actually do the work.
	 */
	protected Object getDialogValue(Dialog dlg)
	{		
		targetContainer = getTargetContainer(dlg);
		if (targetContainer != null)
	    {	    	
	       boolean okToProceed = preCheckForCollision();    	
	       if (!okToProceed)
	         return null;
    	   IRunnableContext runnableContext = getRunnableContext();
    	   try
    	   {
    	     runnableContext.run(false,false,this); // inthread, cancellable, IRunnableWithProgress
    	     if (copiedOk)
    	     {
    	     	SystemMessage completeMsg = getCompletionMessage(targetContainer, oldNames, newNames);
    	     	if (completeMsg != null)
    	     	{
    	     	  SystemMessageDialog msgDlg = new SystemMessageDialog(getShell(),completeMsg);
    	     	  msgDlg.open();
    	     	}  
    	     }   
    	   }
    	   catch (java.lang.reflect.InvocationTargetException exc) // unexpected error
    	   {
    	  	 showOperationMessage((Exception)exc.getTargetException(), getShell());
    	     //throw (Exception) exc.getTargetException();    	    	
    	   }
    	   catch (Exception exc)
    	   {
    	  	 showOperationMessage(exc, getShell());
             //throw exc;
    	   }    	
		}
		return null;	
	}
	/**
	 * Get an IRunnable context to show progress in. If there is currently a dialog or wizard up with
	 * a progress monitor in it, we will use this, else we will create a progress monitor dialog.
	 */
	protected IRunnableContext getRunnableContext()
	{
		IRunnableContext irc = RSEUIPlugin.getTheSystemRegistryUI().getRunnableContext();
		if (irc == null)
		  irc = new ProgressMonitorDialog(getShell());
		return irc;
	}
	/**
	 * Override this method if you supply your own copy/move target dialog. 
	 * Return the user-selected target or null if cancelled
	 */
	protected Object getTargetContainer(Dialog dlg)
	{
		SystemSimpleCopyDialog cpyDlg = (SystemSimpleCopyDialog)dlg;		
		Object targetContainer = null;
		if (!cpyDlg.wasCancelled())
		   targetContainer = cpyDlg.getTargetContainer();
	    return targetContainer;
	}
	
	/**
	 * Do a pre-check for a collision situation.
	 * This really is only a problem for filter strings, when a name collision is fatal verus
	 *  recoverable via a new-name prompt.
	 */
	protected boolean preCheckForCollision()
	{
		boolean ok = true;
        oldNames = getOldNames();
        oldObjects = getOldObjects();
        int steps = oldObjects.length;
        
	    String oldName = null;
	    Object oldObject = null;
	    for (int idx=0; ok && (idx<steps); idx++)
	    {
	       oldName = oldNames[idx];
	       oldObject = oldObjects[idx];
	       ok = preCheckForCollision(getShell(), targetContainer, oldObject, oldName);
	    }		
		return ok;
	}
	/**
	 * Overridable entry point when you want to prevent any copies/moves if any of the
	 * selected objects have a name collision.
	 * <p>
	 * If you decide to override this, it is your responsibility to issue the error 
	 * message to the user and return false here.
	 * <p>
	 * @return true if there is no problem, false if there is a fatal collision
	 */
	protected boolean preCheckForCollision(Shell shell, Object targetContainer, 
	                                       Object oldObject, String oldName)
	{
		return true;
	}	
	
	/**
	 * Called after all the copy/move operations end, be it successfully or not.
	 * Your opportunity to display completion or do post-copy selections/refreshes
	 * @since 3.0 taking String argument
	 */
	public void copyComplete(String operation) {}
	
    // ----------------------------------
    // INTERNAL METHODS...
    // ----------------------------------
	/**
	 * Method required by IRunnableWithProgress interface.
	 * Allows execution of a long-running operation modally by via a thread.
	 * In our case, it runs the copy operation with a visible progress monitor
	 */
    public void run(IProgressMonitor monitor)
         throws java.lang.reflect.InvocationTargetException,
                java.lang.InterruptedException
	{		
		SystemMessage msg = getCopyingMessage();
		runException = null;
		
        try
        {
           //oldNames = getOldNames();
           //oldObjects = getOldObjects();
           int steps = oldObjects.length;
	       monitor.beginTask(msg.getLevelOneText(), steps);
	       copiedOk = true;
	       String oldName = null;
	       String newName = null;
	       Object oldObject = null;
	       newNames = new String[oldNames.length];
	       for (int idx=0; copiedOk && (idx<steps); idx++)
	       {
	       	  oldName = oldNames[idx];
	       	  oldObject = oldObjects[idx];
	       	  monitor.subTask(getCopyingMessage(oldName).getLevelOneText());
	       	  newName = checkForCollision(getShell(), monitor, targetContainer, oldObject, oldName);
	       	  if (newName == null)
	       	    copiedOk = false;
	       	  else
		        copiedOk = doCopy(targetContainer, oldObject, newName, monitor);
		      newNames[idx] = newName;
		      monitor.worked(1);
	       }
           monitor.done();
        }
        catch(java.lang.InterruptedException exc)
        {
           monitor.done();
           runException = exc;
           throw (java.lang.InterruptedException)runException;
        }						
        catch(Exception exc)
        {
           monitor.done();
           runException = new java.lang.reflect.InvocationTargetException(exc);
           throw (java.lang.reflect.InvocationTargetException)runException;
        }
        if (copiedOk)
        	copyComplete(null);
	}
	
	protected abstract String checkForCollision(Shell shell, IProgressMonitor monitor, Object targetContainer, Object oldObject, String oldName);
	/**
	 * Get the generic "Copying..." or "Moving..." message
	 */
    protected SystemMessage getCopyingMessage()
    {
		if (mode == MODE_COPY)		
		  return RSEUIPlugin.getPluginMessage(ISystemMessages.MSG_COPYGENERIC_PROGRESS); 
		else
		  return RSEUIPlugin.getPluginMessage(ISystemMessages.MSG_MOVEGENERIC_PROGRESS); 
    }
	/**
	 * Get the specific "Copying %1..." or "Moving %1..." message
	 */
    protected SystemMessage getCopyingMessage(String oldName)
    {
    	SystemMessage msg = null;
		if (mode == MODE_COPY)		
		  msg = RSEUIPlugin.getPluginMessage(ISystemMessages.MSG_COPYTHINGGENERIC_PROGRESS); 
		else
		  msg = RSEUIPlugin.getPluginMessage(ISystemMessages.MSG_MOVETHINGGENERIC_PROGRESS); 
		msg.makeSubstitution(oldName);
		return msg;
    }
    
    /**
     * DO THE ACTUAL COPY OR MOVE. THIS MUST BE IMPLEMENTED BY CHILD CLASSES
     */
	protected abstract boolean doCopy(Object targetContainer, Object oldObject, String newName, IProgressMonitor monitor)
	 throws Exception;
	 
	/**
	 * Return complete message.
	 * Override if you want to popup a completion message after a successful copy/move
	 */
	public SystemMessage getCompletionMessage(Object targetContainer, String[] oldNames, String[] newNames)
	{
		return null;
	}

    /**
     * Helper method to show an error message resulting from the attempted operation.
     */
	protected void showOperationMessage(Exception exc, Shell shell)
	{
		if (exc instanceof java.lang.InterruptedException)
		  showOperationCancelledMessage(shell);
		else if (exc instanceof java.lang.reflect.InvocationTargetException)
		  showOperationErrorMessage(shell, ((java.lang.reflect.InvocationTargetException)exc).getTargetException());
		else
		  showOperationErrorMessage(shell, exc);
	}

    /**
     * Show an error message when the operation fails.
     * Shows a common message by default.
     * Overridable.
     */
    protected void showOperationErrorMessage(Shell shell, Throwable exc)
    {
    	if (exc instanceof SystemMessageException)
    	  showOperationErrorMessage(shell, (SystemMessageException)exc);
    	else
        {
    	  String msg = exc.getMessage();
    	  if ((msg == null) || (exc instanceof ClassCastException))
    	    msg = exc.getClass().getName();
    	  SystemMessageDialog msgDlg = 
    	    new SystemMessageDialog(shell, 
    	      RSEUIPlugin.getPluginMessage(ISystemMessages.MSG_OPERATION_FAILED).makeSubstitution(msg));
    	  msgDlg.setException(exc);
    	  msgDlg.open();
          //RSEUIPlugin.logError("Copy/Move operation failed",exc);
        }
    }	
    /**
     * Show an error message when the operation fails.
     * Shows a SystemMessage that was encapsulated in a SystemMessage exception
     * Overridable.
     */
    protected void showOperationErrorMessage(Shell shell, SystemMessageException exc)
    {
    	SystemMessage msg = exc.getSystemMessage();
    	SystemMessageDialog msgDlg = 
    	  new SystemMessageDialog(shell, msg);
    	msgDlg.open();
        //RSEUIPlugin.logError("Copy/Move operation failed",exc);
    }	

    /**
     * Show an error message when the user cancels the operation.
     * Shows a common message by default.
     * Overridable.
     */
    protected void showOperationCancelledMessage(Shell shell)
    {
    	SystemMessageDialog msgDlg = new SystemMessageDialog(shell, RSEUIPlugin.getPluginMessage(ISystemMessages.MSG_OPERATION_CANCELLED));
    	msgDlg.open();
    }	


}

Back to the top