Project

General

Profile

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

    
10
package eu.etaxonomy.taxeditor.model;
11

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

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

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

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

    
90
    private static final Logger logger = Logger.getLogger(AbstractUtility.class);
91

    
92
    /** Constant <code>statusLineManager</code> */
93
    protected static IStatusLineManager statusLineManager;
94

    
95

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
334
        IRunnableWithProgress runnable = new IRunnableWithProgress() {
335

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

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

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

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

    
358
            }
359
        };
360

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

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

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

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

    
384
        IRunnableWithProgress runnable = new IRunnableWithProgress() {
385

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

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

    
409
            }
410
        };
411

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

    
418
        return Status.OK_STATUS;
419
    }
420

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

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

    
447
            Job job = new Job(label) {
448

    
449

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

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

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

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

    
505
        return Status.OK_STATUS;
506
    }
507

    
508

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

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

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

    
537
        });
538

    
539
    }
540

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
775

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
943

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