Project

General

Profile

Download (31.7 KB) Statistics
| Branch: | Tag: | Revision:
1
// $Id$
2
/**
3
 * Copyright (C) 2007 EDIT
4
 * European Distributed Institute of Taxonomy
5
 * http://www.e-taxonomy.eu
6
 *
7
 * The contents of this file are subject to the Mozilla Public License Version 1.1
8
 * See LICENSE.TXT at the top of this package for the full license terms.
9
 */
10

    
11
package eu.etaxonomy.taxeditor.model;
12

    
13
import java.lang.reflect.InvocationTargetException;
14
import java.util.ArrayList;
15
import java.util.Collection;
16
import java.util.LinkedHashMap;
17
import java.util.List;
18
import java.util.TreeSet;
19
import java.util.UUID;
20

    
21
import org.apache.commons.lang.StringUtils;
22
import org.apache.log4j.Logger;
23
import org.eclipse.core.commands.ExecutionException;
24
import org.eclipse.core.commands.NotEnabledException;
25
import org.eclipse.core.commands.NotHandledException;
26
import org.eclipse.core.commands.common.NotDefinedException;
27
import org.eclipse.core.commands.operations.AbstractOperation;
28
import org.eclipse.core.commands.operations.IOperationHistory;
29
import org.eclipse.core.runtime.IAdaptable;
30
import org.eclipse.core.runtime.IProgressMonitor;
31
import org.eclipse.core.runtime.IStatus;
32
import org.eclipse.core.runtime.NullProgressMonitor;
33
import org.eclipse.core.runtime.OperationCanceledException;
34
import org.eclipse.core.runtime.Status;
35
import org.eclipse.core.runtime.SubProgressMonitor;
36
import org.eclipse.core.runtime.jobs.ISchedulingRule;
37
import org.eclipse.core.runtime.jobs.Job;
38
import org.eclipse.jface.action.IStatusLineManager;
39
import org.eclipse.jface.operation.IRunnableWithProgress;
40
import org.eclipse.jface.resource.ColorRegistry;
41
import org.eclipse.jface.resource.FontRegistry;
42
import org.eclipse.jface.window.ApplicationWindow;
43
import org.eclipse.swt.graphics.Color;
44
import org.eclipse.swt.graphics.Font;
45
import org.eclipse.swt.widgets.Display;
46
import org.eclipse.swt.widgets.Shell;
47
import org.eclipse.ui.IEditorPart;
48
import org.eclipse.ui.IViewPart;
49
import org.eclipse.ui.IViewReference;
50
import org.eclipse.ui.IWorkbench;
51
import org.eclipse.ui.IWorkbenchPage;
52
import org.eclipse.ui.IWorkbenchPart;
53
import org.eclipse.ui.IWorkbenchWindow;
54
import org.eclipse.ui.PartInitException;
55
import org.eclipse.ui.PlatformUI;
56
import org.eclipse.ui.handlers.IHandlerService;
57
import org.eclipse.ui.ide.undo.WorkspaceUndoUtil;
58
import org.eclipse.ui.part.EditorPart;
59
import org.eclipse.ui.progress.IProgressConstants;
60
import org.eclipse.ui.progress.IProgressService;
61
import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
62
import org.eclipse.ui.themes.ITheme;
63
import org.eclipse.ui.themes.IThemeManager;
64

    
65
import eu.etaxonomy.cdm.api.application.CdmApplicationState;
66
import eu.etaxonomy.cdm.api.service.IProgressMonitorService;
67
import eu.etaxonomy.cdm.common.monitor.IRemotingProgressMonitor;
68
import eu.etaxonomy.cdm.model.common.IEnumTerm;
69
import eu.etaxonomy.taxeditor.operation.AbstractPostOperation;
70
import eu.etaxonomy.taxeditor.operation.IFeedbackGenerator;
71
import eu.etaxonomy.taxeditor.operation.IPostMoniteredOperationEnabled;
72
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
73
import eu.etaxonomy.taxeditor.operation.RemotingCdmHandler;
74
import eu.etaxonomy.taxeditor.store.CdmStore;
75
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
76
import eu.etaxonomy.taxeditor.ui.dialog.ReportTextDialog;
77
import eu.etaxonomy.taxeditor.view.AbstractCdmDataViewer;
78
import eu.etaxonomy.taxeditor.view.detail.DetailsViewPart;
79
import eu.etaxonomy.taxeditor.view.supplementaldata.SupplementalDataViewPart;
80

    
81
/**
82
 * <p>
83
 * Abstract AbstractUtility class.
84
 * </p>
85
 *
86
 * @author n.hoffmann
87
 * @created 11.05.2009
88
 * @version 1.0
89
 */
90
public abstract class AbstractUtility {
91

    
92
    private static final Logger logger = Logger.getLogger(AbstractUtility.class);
93

    
94
    /** Constant <code>statusLineManager</code> */
95
    protected static IStatusLineManager statusLineManager;
96

    
97

    
98
    /**
99
     * <p>
100
     * closeAll
101
     * </p>
102
     *
103
     * @return a boolean.
104
     */
105
    public static boolean closeAll() {
106
        return getActivePage().closeAllEditors(true);
107
    }
108

    
109
    /**
110
     * Close the given editor.
111
     *
112
     * @param editor
113
     *            The <tt>MultipageTaxonEditor</tt> to close.
114
     * @return <tt>true</tt> on success
115
     */
116
    public static boolean close(EditorPart editor) {
117
        return getActivePage().closeEditor(editor, true);
118
    }
119

    
120
    /**
121
     * <p>
122
     * getShell
123
     * </p>
124
     *
125
     * @return a {@link org.eclipse.swt.widgets.Shell} object.
126
     */
127
    public static Shell getShell() {
128

    
129
        return TaxeditorStorePlugin.getDefault().getWorkbench()
130
                .getActiveWorkbenchWindow().getShell();
131
    }
132

    
133
    /**
134
     * <p>
135
     * getActivePage
136
     * </p>
137
     *
138
     * @return a {@link org.eclipse.ui.IWorkbenchPage} object.
139
     */
140
    public static IWorkbenchPage getActivePage() {
141

    
142
        return TaxeditorStorePlugin.getDefault().getWorkbench()
143
                .getActiveWorkbenchWindow().getActivePage();
144
    }
145

    
146
    /**
147
     * <p>
148
     * getActivePart
149
     * </p>
150
     *
151
     * @return a {@link org.eclipse.ui.IWorkbenchPart} object.
152
     */
153
    public static IWorkbenchPart getActivePart() {
154
        return getActivePage() != null ? getActivePage().getActivePart() : null;
155
    }
156

    
157
    public static IWorkbench getWorkbench() {
158
        return TaxeditorStorePlugin.getDefault().getWorkbench();
159
    }
160

    
161
    /**
162
     * <p>
163
     * getWorkbenchWindow
164
     * </p>
165
     *
166
     * @return a {@link org.eclipse.jface.window.ApplicationWindow} object.
167
     */
168
    public static ApplicationWindow getWorkbenchWindow() {
169
        if (getWorkbench().getWorkbenchWindowCount() > 1) {
170
            throw new IllegalStateException("More than one workbench window");
171
        }
172
        return (ApplicationWindow) getWorkbench().getWorkbenchWindows()[0];
173
    }
174

    
175
    /**
176
     * <p>
177
     * showView
178
     * </p>
179
     *
180
     * @param id
181
     *            a {@link java.lang.String} object.
182
     * @return a {@link org.eclipse.ui.IViewPart} object.
183
     */
184
    public static IViewPart showView(String id) {
185
        try {
186
            return PlatformUI.getWorkbench().getActiveWorkbenchWindow()
187
                    .getActivePage()
188
                    .showView(id, null, IWorkbenchPage.VIEW_VISIBLE);
189
        } catch (PartInitException e) {
190
            MessagingUtils.messageDialog("Error opening view", AbstractUtility.class, "Could not open view: " + id, e);
191
            return null;
192
        }
193
    }
194

    
195
    /**
196
     * <p>
197
     * hideView
198
     * </p>
199
     *
200
     * @param view
201
     *            a {@link org.eclipse.ui.IViewPart} object.
202
     */
203
    public static void hideView(IViewPart view) {
204
        PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
205
        .hideView(view);
206
    }
207

    
208
    /**
209
     * <p>
210
     * getView
211
     * </p>
212
     *
213
     * @param id
214
     *            a {@link java.lang.String} object.
215
     * @param restore
216
     *            a boolean.
217
     * @return a {@link org.eclipse.ui.IViewPart} object.
218
     */
219
    public static IViewPart getView(String id, boolean restore) {
220
    	IWorkbenchWindow activeWorkbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
221
    	IViewReference[] references = null;
222
    	if(activeWorkbenchWindow!=null){
223
    		references = PlatformUI.getWorkbench()
224
    				.getActiveWorkbenchWindow().getActivePage().getViewReferences();
225
    	}
226
    	else if(PlatformUI.getWorkbench().getWorkbenchWindows().length>0){
227
    		references = PlatformUI.getWorkbench().getWorkbenchWindows()[0].getActivePage().getViewReferences();
228
    	}
229
    	if(references!=null){
230
    		for (IViewReference reference : references) {
231
    			if (reference.getId().equals(id)) {
232
    				return reference.getView(restore);
233
    			}
234
    		}
235
    	}
236
        return null;
237
    }
238

    
239
    /**
240
     * <p>
241
     * getService
242
     * </p>
243
     *
244
     * @param api
245
     *            a {@link java.lang.Class} object.
246
     * @return a {@link java.lang.Object} object.
247
     */
248
    public static Object getService(Class api) {
249
        return TaxeditorStorePlugin.getDefault().getWorkbench().getService(api);
250
    }
251

    
252
    /**
253
     * <p>
254
     * getCurrentTheme
255
     * </p>
256
     *
257
     * @return a {@link org.eclipse.ui.themes.ITheme} object.
258
     */
259
    public static ITheme getCurrentTheme() {
260
        IThemeManager themeManager = TaxeditorStorePlugin.getDefault()
261
                .getWorkbench().getThemeManager();
262
        return themeManager.getCurrentTheme();
263
    }
264

    
265
    /**
266
     * Fonts registered to the plugin may be obtained with the Eclipse themeing
267
     * functionality. Thus fonts are chooseable by the user via
268
     * Preferences->General->Appearance->Colors and Fonts
269
     *
270
     * @return the FontRegistry for the current theme
271
     */
272
    public static FontRegistry getFontRegistry() {
273
        return getCurrentTheme().getFontRegistry();
274
    }
275

    
276
    /**
277
     * <p>
278
     * getFont
279
     * </p>
280
     *
281
     * @param symbolicName
282
     *            a {@link java.lang.String} object.
283
     * @return a {@link org.eclipse.swt.graphics.Font} object.
284
     */
285
    public static Font getFont(String symbolicName) {
286
        return getFontRegistry().get(symbolicName);
287
    }
288

    
289
    /**
290
     * Color registered to the plugin may be obtained with the Eclipse themeing
291
     * functionality. Thus colors are editable by the user via
292
     * Preferences->General->Appearance->Colors and Fonts
293
     *
294
     * @return the ColorRegistry for the current theme
295
     */
296
    public static ColorRegistry getColorRegistry() {
297
        return getCurrentTheme().getColorRegistry();
298
    }
299

    
300
    /**
301
     * <p>
302
     * getColor
303
     * </p>
304
     *
305
     * @param symbolicName
306
     *            a {@link java.lang.String} object.
307
     * @return a {@link org.eclipse.swt.graphics.Color} object.
308
     */
309
    public static Color getColor(String symbolicName) {
310
        return getColorRegistry().get(symbolicName);
311
    }
312

    
313
    /**
314
     * <p>
315
     * executeOperation
316
     * </p>
317
     *
318
     * @param operation
319
     *            a
320
     *            {@link eu.etaxonomy.taxeditor.operation.AbstractPostTaxonOperation}
321
     *            object.
322
     * @return a {@link org.eclipse.core.runtime.IStatus} object.
323
     */
324
    public static IStatus executeOperation(final AbstractPostOperation operation) {
325
        if (getOperationHistory() == null) {
326
            throw new IllegalArgumentException(
327
                    "There is no operation history for this context");
328
        }
329

    
330
        final IAdaptable uiInfoAdapter = WorkspaceUndoUtil
331
                .getUIInfoAdapter(getShell());
332

    
333
        IRunnableWithProgress runnable = new IRunnableWithProgress() {
334

    
335
            @Override
336
            public void run(IProgressMonitor monitor)
337
                    throws InvocationTargetException, InterruptedException {
338
                String operationlabel = operation.getLabel();
339
                monitor.beginTask(operationlabel, 100);
340
                IStatus status = Status.CANCEL_STATUS;
341
                try {
342
                    operation.addContext(IOperationHistory.GLOBAL_UNDO_CONTEXT);
343
                    status = getOperationHistory().execute(operation, monitor,
344
                            uiInfoAdapter);
345
                } catch (ExecutionException e) {
346

    
347
                    MessagingUtils.operationDialog(this, e, TaxeditorStorePlugin.PLUGIN_ID, operationlabel, null);
348

    
349
                } finally {
350
                    monitor.done();
351
                }
352

    
353
                String statusString = status.equals(Status.OK_STATUS) ? "completed"
354
                        : "cancelled";
355
                setStatusLine(operationlabel + " " + statusString + ".");
356

    
357
            }
358
        };
359

    
360
        try {
361
            runInUI(runnable, null);
362
        } catch (Exception e) {
363
            MessagingUtils.messageDialog("Error executing operation", AbstractUtility.class, "An error occured while executing " + operation.getLabel(), e);
364
        }
365

    
366
        IPostOperationEnabled postOperationEnabled = operation
367
                .getPostOperationEnabled();
368
        if (postOperationEnabled != null) {
369
            postOperationEnabled.onComplete();
370
        }
371
        return Status.OK_STATUS;
372
    }
373

    
374
    public static IStatus executeOperation(final AbstractOperation operation, final RemotingCdmHandler handler) {
375
        if (getOperationHistory() == null) {
376
            throw new IllegalArgumentException(
377
                    "There is no operation history for this context");
378
        }
379

    
380
        final IAdaptable uiInfoAdapter = WorkspaceUndoUtil
381
                .getUIInfoAdapter(getShell());
382

    
383
        IRunnableWithProgress runnable = new IRunnableWithProgress() {
384

    
385
            @Override
386
            public void run(IProgressMonitor monitor)
387
                    throws InvocationTargetException, InterruptedException {
388
                String operationlabel = operation.getLabel();
389
                monitor.beginTask(operationlabel, 100);
390
                IStatus status = Status.CANCEL_STATUS;
391
                try {
392
                    operation.addContext(IOperationHistory.GLOBAL_UNDO_CONTEXT);
393
                    status = getOperationHistory().execute(operation, monitor,
394
                            uiInfoAdapter);
395
                    if(handler != null) {
396
                        handler.postOperation(status);
397
                    }
398
                } catch (ExecutionException e) {
399
                    MessagingUtils.operationDialog(this, e, TaxeditorStorePlugin.PLUGIN_ID, operationlabel, null);
400
                } finally {
401
                    monitor.done();
402
                }
403

    
404
                String statusString = status.equals(Status.OK_STATUS) ? "completed"
405
                        : "cancelled";
406
                setStatusLine(operationlabel + " " + statusString + ".");
407

    
408
            }
409
        };
410

    
411
        try {
412
            runInUI(runnable, null);
413
        } catch (Exception e) {
414
            MessagingUtils.messageDialog("Error executing operation", AbstractUtility.class, "An error occured while executing " + operation.getLabel(), e);
415
        }
416

    
417
        return Status.OK_STATUS;
418
    }
419

    
420
    /**
421
     * Executes a remoting monitored operation
422
     *
423
     * @param label for the operation
424
     * @param uuid of the remoting monitor already started on the server
425
     * @param pollInterval in milliseconds
426
     * @param cancelable flag which determines whether the operation can be cancelled
427
     * @param postOp callback for running post operation logic
428
     * @return
429
     */
430
    public static IStatus executeMoniteredOperation(final String label,
431
            final UUID uuid,
432
            final int pollInterval,
433
            final boolean cancelable,
434
            final IPostMoniteredOperationEnabled postOp,
435
            final IFeedbackGenerator feedbackGenerator) {
436

    
437
        try {
438
            // get the remoting monitor the first time to make sure that the
439
            // operation is valid
440
            final IProgressMonitorService progressMonitorService = CdmApplicationState.getCurrentAppConfig().getProgressMonitorService();
441
            final IRemotingProgressMonitor firstRemotingMonitor = progressMonitorService.getRemotingMonitor(uuid);
442
            if(firstRemotingMonitor == null) {
443
                throw new IllegalStateException("Remoting progress monitor is null");
444
            }
445

    
446
            Job job = new Job(label) {
447

    
448

    
449
                @Override
450
                public IStatus run(IProgressMonitor monitor) {
451
                    // run the monitor until the operation is finished
452
                    IRemotingProgressMonitor remotingMonitor;
453
                    try {
454
                        remotingMonitor = CdmStore.getProgressMonitorClientManager().pollMonitor(label,
455
                                uuid,
456
                                pollInterval,
457
                                postOp,
458
                                feedbackGenerator,
459
                                monitor);
460
                    } catch (Exception ex) {
461
                        return new Status(Status.ERROR, TaxeditorStorePlugin.PLUGIN_ID, "Operation Interrupted", ex);
462
                    }
463
                    final StringBuilder reportSb = new StringBuilder();
464
                    // collect reports
465
                    for(String report : remotingMonitor.getReports()) {
466
                        reportSb.append(report);
467
                    }
468
                    if(!StringUtils.isBlank(reportSb.toString())) {
469
                        Display.getDefault().asyncExec(new Runnable() {
470
                            @Override
471
                            public void run() {
472
                                // display reports with possibility to save
473
                                ReportTextDialog dialog = new ReportTextDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
474
                                dialog.setTitle(label + " Report");
475
                                dialog.setReportText(reportSb.toString());
476
                                dialog.open();
477
                            }
478
                        });
479
                    }
480
                    return Status.OK_STATUS;
481
                }
482

    
483
                @Override
484
                protected void canceling() {
485
                    CdmStore.getCurrentApplicationConfiguration().getProgressMonitorService().cancel(uuid);
486
                }
487
            };
488

    
489
            // configure the job
490
            job.setProperty(IProgressConstants.KEEP_PROPERTY, true);
491
            job.setUser(true);
492
            // schedule job
493
            job.schedule();
494

    
495
        } catch (Exception e) {
496
            MessagingUtils.errorDialog("Error executing operation",
497
                    AbstractUtility.class,
498
                    "An error occured while executing " + label,
499
                    TaxeditorStorePlugin.PLUGIN_ID,
500
                    e,
501
                    true);
502
        }
503

    
504
        return Status.OK_STATUS;
505
    }
506

    
507

    
508
    /**
509
     * <p>
510
     * getOperationHistory
511
     * </p>
512
     *
513
     * @return a {@link org.eclipse.core.commands.operations.IOperationHistory}
514
     *         object.
515
     */
516
    public static IOperationHistory getOperationHistory() {
517
        return getWorkbench().getOperationSupport().getOperationHistory();
518
    }
519

    
520
    /**
521
     * <p>
522
     * setStatusLine
523
     * </p>
524
     *
525
     * @param message
526
     *            a {@link java.lang.String} object.
527
     */
528
    public static void setStatusLine(final String message) {
529
        Display.getDefault().asyncExec(new Runnable() {
530

    
531
            @Override
532
            public void run() {
533
                statusLineManager.setMessage(message);
534
            }
535

    
536
        });
537

    
538
    }
539

    
540
    /**
541
     * <p>
542
     * getMonitor
543
     * </p>
544
     *
545
     * @return a {@link org.eclipse.core.runtime.IProgressMonitor} object.
546
     */
547
    public static IProgressMonitor getMonitor() {
548
        statusLineManager.setCancelEnabled(false);
549
        return statusLineManager.getProgressMonitor();
550
    }
551

    
552
    /**
553
     * Starts either the given {@link IProgressMonitor} if it's not
554
     * <code>null</code> or a new {@link NullProgressMonitor}.
555
     *
556
     * @param progressMonitor
557
     *            The {@link IProgressMonitor} or <code>null</code> if no
558
     *            progress should be reported.
559
     * @param taskName
560
     *            The name of the main task.
561
     * @param steps
562
     *            The number of steps this task is subdivided into.
563
     * @return The {@link IProgressMonitor}.
564
     */
565
    public static IProgressMonitor startMainMonitor(
566
            IProgressMonitor progressMonitor, String taskName, int steps) {
567
        IProgressMonitor newMonitor = progressMonitor;
568
        if (newMonitor == null) {
569
            newMonitor = new NullProgressMonitor();
570
        }
571
        newMonitor.beginTask(taskName == null ? "" : taskName, steps);
572
        newMonitor.subTask(" ");
573
        return newMonitor;
574
    }
575

    
576
    /**
577
     * Creates a {@link SubProgressMonitor} if the given
578
     * {@link IProgressMonitor} is not <code>null</code> and not a
579
     * {@link NullProgressMonitor}.
580
     *
581
     * @param progressMonitor
582
     *            The parent {@link IProgressMonitor} of the
583
     *            {@link SubProgressMonitor} to be created.
584
     * @param ticks
585
     *            The number of steps this subtask is subdivided into. Must be a
586
     *            positive number and must not be
587
     *            {@link IProgressMonitor#UNKNOWN}.
588
     * @return The {@link IProgressMonitor}.
589
     */
590
    public static IProgressMonitor getSubProgressMonitor(
591
            IProgressMonitor progressMonitor, int ticks) {
592
        if (progressMonitor == null) {
593
            return new NullProgressMonitor();
594
        }
595
        if (progressMonitor instanceof NullProgressMonitor) {
596
            return progressMonitor;
597
        }
598

    
599
        return new SubProgressMonitor(progressMonitor, ticks);
600
    }
601

    
602
    /**
603
     * Checks whether the user canceled this operation. If not canceled, the
604
     * given number of steps are declared as done.
605
     *
606
     * @param newMonitor
607
     *            a {@link org.eclipse.core.runtime.IProgressMonitor} object.
608
     * @param steps
609
     *            a int.
610
     */
611
    public static void workedChecked(IProgressMonitor newMonitor, int steps) {
612
        // In case the progress monitor was canceled throw an exception.
613
        if (newMonitor.isCanceled()) {
614
            throw new OperationCanceledException();
615
        }
616
        // Otherwise declare this step as done.
617
        newMonitor.worked(steps);
618
    }
619

    
620
    /**
621
     * Present a progress dialog to the user. This dialog will block the UI
622
     *
623
     * @param runnable
624
     *            an implementation of {@link IRunnableWithProgress}
625
     * @throws java.lang.InterruptedException
626
     *             if any.
627
     * @throws java.lang.reflect.InvocationTargetException
628
     *             if any.
629
     */
630
    public static void busyCursorWhile(IRunnableWithProgress runnable)
631
            throws InvocationTargetException, InterruptedException {
632
        getProgressService().busyCursorWhile(runnable);
633
    }
634

    
635
    /**
636
     * <p>
637
     * runInUI
638
     * </p>
639
     *
640
     * @see {@link IProgressService#runInUI(org.eclipse.jface.operation.IRunnableContext, IRunnableWithProgress, ISchedulingRule)}
641
     * @param runnable
642
     *            a {@link org.eclipse.jface.operation.IRunnableWithProgress}
643
     *            object.
644
     * @param rule
645
     *            a {@link org.eclipse.core.runtime.jobs.ISchedulingRule}
646
     *            object.
647
     * @throws java.lang.reflect.InvocationTargetException
648
     *             if any.
649
     * @throws java.lang.InterruptedException
650
     *             if any.
651
     */
652
    public static void runInUI(IRunnableWithProgress runnable,
653
            ISchedulingRule rule) throws InvocationTargetException,
654
            InterruptedException {
655
        getProgressService().runInUI(getWorkbenchWindow(), runnable, rule);
656
    }
657

    
658
    /**
659
     * <p>
660
     * run
661
     * </p>
662
     *
663
     * @param fork
664
     *            a boolean.
665
     * @param cancelable
666
     *            a boolean.
667
     * @param runnable
668
     *            a {@link org.eclipse.jface.operation.IRunnableWithProgress}
669
     *            object.
670
     * @throws java.lang.reflect.InvocationTargetException
671
     *             if any.
672
     * @throws java.lang.InterruptedException
673
     *             if any.
674
     */
675
    public static void run(boolean fork, boolean cancelable,
676
            IRunnableWithProgress runnable) throws InvocationTargetException,
677
            InterruptedException {
678
        getProgressService().run(fork, cancelable, runnable);
679
    }
680

    
681
    /**
682
     * <p>
683
     * getProgressService
684
     * </p>
685
     *
686
     * @return a {@link org.eclipse.ui.progress.IProgressService} object.
687
     */
688
    public static IProgressService getProgressService() {
689
        IWorkbench workbench = PlatformUI.getWorkbench();
690
        return workbench.getProgressService();
691
    }
692

    
693
    /**
694
     * <p>
695
     * getProgressService2
696
     * </p>
697
     *
698
     * @return a {@link org.eclipse.ui.progress.IWorkbenchSiteProgressService}
699
     *         object.
700
     */
701
    public static IWorkbenchSiteProgressService getProgressService2() {
702
        return (IWorkbenchSiteProgressService) getService(IWorkbenchSiteProgressService.class);
703
    }
704

    
705
    /**
706
     * <p>
707
     * getPluginId
708
     * </p>
709
     *
710
     * @return a {@link java.lang.String} object.
711
     */
712
    public static String getPluginId() {
713
        return "eu.taxeditor";
714
    }
715

    
716
    /**
717
     * <p>
718
     * getActiveEditor
719
     * </p>
720
     *
721
     * @return a {@link org.eclipse.ui.IEditorPart} object.
722
     */
723
    public static IEditorPart getActiveEditor() {
724
        return getActivePage() != null ? getActivePage().getActiveEditor()
725
                : null;
726
    }
727

    
728
    /**
729
     * <p>
730
     * getDetailsView
731
     * </p>
732
     *
733
     * @return a {@link eu.etaxonomy.taxeditor.view.detail.DetailsViewPart}
734
     *         object.
735
     */
736
    public static DetailsViewPart getDetailsView() {
737
        return (DetailsViewPart) getView(DetailsViewPart.ID, false);
738
    }
739

    
740
    /**
741
     * <p>
742
     * refreshDetailsViewer
743
     * </p>
744
     */
745
    public static void refreshDetailsViewer() {
746
        if (getDetailsView() != null) {
747
            ((AbstractCdmDataViewer) getDetailsView().getViewer()).refresh();
748
        }
749
    }
750

    
751
    /**
752
     * <p>
753
     * reflowDetailsViewer
754
     * </p>
755
     */
756
    public static void reflowDetailsViewer() {
757
        if (getDetailsView() != null) {
758
            ((AbstractCdmDataViewer) getDetailsView().getViewer()).reflow();
759
        }
760
    }
761

    
762
    public static SupplementalDataViewPart getSupplementalDataView() {
763
        return (SupplementalDataViewPart) getView(SupplementalDataViewPart.ID,
764
                false);
765
    }
766

    
767
    public static void reflowSupplementalViewer() {
768
        if (getSupplementalDataView() != null) {
769
            ((AbstractCdmDataViewer) getSupplementalDataView().getViewer())
770
            .reflow();
771
        }
772
    }
773

    
774

    
775
    /**
776
     * Orders a Collection of {@link IEnumTerm}s according to the term
777
     * hierarchy. <br>
778
     * <br>
779
     * The returned map will be be ordered primarily by root elements,
780
     * secondarily by the child elements and their children resp., both ascending alphabetically. <br>
781
     * @param terms
782
     *            A {@link Collection} of {@link IEnumTerm}s for which the term
783
     *            hierarchy should be created
784
     * @return a map which holds the terms as keys and their string
785
     *         representation via {@link IEnumTerm#getMessage()} as values
786
     */
787
    public static <T extends IEnumTerm<T>> LinkedHashMap<T, String> orderTerms(Collection<T> terms) {
788
        TreeSet<TermNode<T>> parentElements = new TreeSet<TermNode<T>>();
789
        parentElements.addAll(getTermHierarchy(terms));
790

    
791
        // create list according to the type hierarchy (root elements alphabetically with recursive children also alphabetically)
792
        LinkedHashMap<T, String> result = new LinkedHashMap<T, String>();
793
        parseTermTree(parentElements, result, -1);
794
        return result;
795
    }
796

    
797
    private static<T extends IEnumTerm<T>> void parseTermTree(Collection<TermNode<T>> children, LinkedHashMap<T, String> result, int depth){
798
        depth++;
799
        for(TermNode<T> node:children){
800
            String indentString = "";
801
            for(int i=0;i<depth;i++){
802
                indentString += "  ";
803
            }
804
            if(depth>0){
805
                indentString += "- ";
806
            }
807
            result.put(node.term, indentString + node.term.getMessage());
808
            parseTermTree(node.children, result, depth);
809
        }
810
    }
811

    
812
    private static<T extends IEnumTerm<T>> void addToParents(List<TermNode<T>> parents, Collection<T> terms){
813
        List<TermNode<T>> hasChildrenList = new ArrayList<TermNode<T>>();
814
        for(T term:terms){
815
            // only terms with parents
816
            if(term.getKindOf()!=null){
817
                TermNode<T> parentNode = new TermNode<T>(term.getKindOf());
818
                TermNode<T> childNode = new TermNode<T>(term);
819
                if(parents.contains(parentNode)){
820
                    // parent found in parent list -> add this term to parent's child list
821
                    parents.get(parents.indexOf(parentNode)).addChild(childNode);
822
                    if(!term.getGeneralizationOf().isEmpty()){
823
                        // has more children -> add to list which will be the parent for the next recursion
824
                        hasChildrenList.add(childNode);
825
                    }
826
                }
827
            }
828
        }
829
        if(!hasChildrenList.isEmpty()){
830
            addToParents(hasChildrenList, terms);
831
        }
832
    }
833

    
834
    private static<T extends IEnumTerm<T>> List<TermNode<T>> getTermHierarchy(Collection<T> terms){
835
        List<TermNode<T>> parents = new ArrayList<TermNode<T>>();
836
        // get root elements
837
        for(T term:terms){
838
            T parentTerm = term.getKindOf();
839
            if(parentTerm==null){
840
                // root element
841
                parents.add(new TermNode<T>(term));
842
            }
843
        }
844
        addToParents(parents, terms);
845
        return parents;
846
    }
847

    
848
    @SuppressWarnings("unchecked")
849
    /**
850
     * Recursively iterates over all term parents until no more parent is found i.e. the root node
851
     * @param term The term for which the parent should be found
852
     * @return the root terms of the term hierarchy
853
     */
854
    private static<T extends IEnumTerm<T>> T getParentFor(T term){
855
        // PP: cast should be safe. Why is Eclipse complaining??
856
        T parent = term.getKindOf();
857
        if(parent==null){
858
            return term;
859
        }
860
        else{
861
            return getParentFor(term.getKindOf());
862
        }
863
    }
864

    
865
    private static class TermNode<T extends IEnumTerm<T>> implements Comparable<TermNode<T>>{
866
        private final T term;
867
        private final TreeSet<TermNode<T>> children;
868

    
869
        /**
870
         * @param term
871
         * @param children
872
         */
873
        public TermNode(T term) {
874
            super();
875
            this.term = term;
876
            this.children = new TreeSet<TermNode<T>>();
877
        }
878

    
879
        public void addChild(TermNode<T> child){
880
            this.children.add(child);
881
        }
882

    
883
        /**
884
         * @return the children
885
         */
886
        public TreeSet<TermNode<T>> getChildren() {
887
            return children;
888
        }
889

    
890
        /**
891
         * @return the term
892
         */
893
        public T getTerm() {
894
            return term;
895
        }
896

    
897
        /* (non-Javadoc)
898
         * @see java.lang.Object#hashCode()
899
         */
900
        @Override
901
        public int hashCode() {
902
            final int prime = 31;
903
            int result = 1;
904
            result = prime * result + ((term == null) ? 0 : term.hashCode());
905
            return result;
906
        }
907

    
908
        /* (non-Javadoc)
909
         * @see java.lang.Object#equals(java.lang.Object)
910
         */
911
        @Override
912
        public boolean equals(Object obj) {
913
            if (this == obj) {
914
                return true;
915
            }
916
            if (obj == null) {
917
                return false;
918
            }
919
            if (getClass() != obj.getClass()) {
920
                return false;
921
            }
922
            TermNode other = (TermNode) obj;
923
            if (term == null) {
924
                if (other.term != null) {
925
                    return false;
926
                }
927
            } else if (!term.equals(other.term)) {
928
                return false;
929
            }
930
            return true;
931
        }
932

    
933
        /* (non-Javadoc)
934
         * @see java.lang.Comparable#compareTo(java.lang.Object)
935
         */
936
        @Override
937
        public int compareTo(TermNode<T> that) {
938
            return this.term.getMessage().compareTo(that.term.getMessage());
939
        }
940
    }
941

    
942

    
943
    public static void executeCommand(String commandId, Object source, String pluginId) {
944
        IHandlerService handlerService = (IHandlerService) AbstractUtility.getService(IHandlerService.class);
945
        Exception exception = null;
946
        try {
947
            handlerService.executeCommand(commandId, null);
948
        } catch (ExecutionException e) {
949
            exception = e;
950
        } catch (NotDefinedException e) {
951
            exception = e;
952
        } catch (NotEnabledException e) {
953
            exception = e;
954
        } catch (NotHandledException e) {
955
            exception = e;
956
        } finally {
957
            if(exception != null) {
958
                MessagingUtils.errorDialog("Error executing command",
959
                        source,
960
                        "Could not execute command with id " + commandId ,
961
                        pluginId,
962
                        exception,
963
                        true);
964
            }
965
        }
966
    }
967
}
(2-2/38)