Project

General

Profile

Download (31.3 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.PartInitException;
54
import org.eclipse.ui.PlatformUI;
55
import org.eclipse.ui.handlers.IHandlerService;
56
import org.eclipse.ui.ide.undo.WorkspaceUndoUtil;
57
import org.eclipse.ui.part.EditorPart;
58
import org.eclipse.ui.progress.IProgressConstants;
59
import org.eclipse.ui.progress.IProgressService;
60
import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
61
import org.eclipse.ui.themes.ITheme;
62
import org.eclipse.ui.themes.IThemeManager;
63

    
64
import eu.etaxonomy.cdm.api.application.CdmApplicationState;
65
import eu.etaxonomy.cdm.api.service.IProgressMonitorService;
66
import eu.etaxonomy.cdm.common.monitor.IRemotingProgressMonitor;
67
import eu.etaxonomy.cdm.model.common.IEnumTerm;
68
import eu.etaxonomy.taxeditor.operation.AbstractPostOperation;
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
        return getActivePage().closeAllEditors(true);
105
    }
106

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

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

    
127
        return TaxeditorStorePlugin.getDefault().getWorkbench()
128
                .getActiveWorkbenchWindow().getShell();
129
    }
130

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

    
140
        return TaxeditorStorePlugin.getDefault().getWorkbench()
141
                .getActiveWorkbenchWindow().getActivePage();
142
    }
143

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

    
155
    public static IWorkbench getWorkbench() {
156
        return TaxeditorStorePlugin.getDefault().getWorkbench();
157
    }
158

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

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

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

    
206
    /**
207
     * <p>
208
     * getView
209
     * </p>
210
     *
211
     * @param id
212
     *            a {@link java.lang.String} object.
213
     * @param restore
214
     *            a boolean.
215
     * @return a {@link org.eclipse.ui.IViewPart} object.
216
     */
217
    public static IViewPart getView(String id, boolean restore) {
218
        IViewReference[] references = PlatformUI.getWorkbench()
219
                .getActiveWorkbenchWindow().getActivePage().getViewReferences();
220
        for (IViewReference reference : references) {
221
            if (reference.getId().equals(id)) {
222
                return reference.getView(restore);
223
            }
224
        }
225
        return null;
226
    }
227

    
228
    /**
229
     * <p>
230
     * getService
231
     * </p>
232
     *
233
     * @param api
234
     *            a {@link java.lang.Class} object.
235
     * @return a {@link java.lang.Object} object.
236
     */
237
    public static Object getService(Class api) {
238
        return TaxeditorStorePlugin.getDefault().getWorkbench().getService(api);
239
    }
240

    
241
    /**
242
     * <p>
243
     * getCurrentTheme
244
     * </p>
245
     *
246
     * @return a {@link org.eclipse.ui.themes.ITheme} object.
247
     */
248
    public static ITheme getCurrentTheme() {
249
        IThemeManager themeManager = TaxeditorStorePlugin.getDefault()
250
                .getWorkbench().getThemeManager();
251
        return themeManager.getCurrentTheme();
252
    }
253

    
254
    /**
255
     * Fonts registered to the plugin may be obtained with the Eclipse themeing
256
     * functionality. Thus fonts are chooseable by the user via
257
     * Preferences->General->Appearance->Colors and Fonts
258
     *
259
     * @return the FontRegistry for the current theme
260
     */
261
    public static FontRegistry getFontRegistry() {
262
        return getCurrentTheme().getFontRegistry();
263
    }
264

    
265
    /**
266
     * <p>
267
     * getFont
268
     * </p>
269
     *
270
     * @param symbolicName
271
     *            a {@link java.lang.String} object.
272
     * @return a {@link org.eclipse.swt.graphics.Font} object.
273
     */
274
    public static Font getFont(String symbolicName) {
275
        return getFontRegistry().get(symbolicName);
276
    }
277

    
278
    /**
279
     * Color registered to the plugin may be obtained with the Eclipse themeing
280
     * functionality. Thus colors are editable by the user via
281
     * Preferences->General->Appearance->Colors and Fonts
282
     *
283
     * @return the ColorRegistry for the current theme
284
     */
285
    public static ColorRegistry getColorRegistry() {
286
        return getCurrentTheme().getColorRegistry();
287
    }
288

    
289
    /**
290
     * <p>
291
     * getColor
292
     * </p>
293
     *
294
     * @param symbolicName
295
     *            a {@link java.lang.String} object.
296
     * @return a {@link org.eclipse.swt.graphics.Color} object.
297
     */
298
    public static Color getColor(String symbolicName) {
299
        return getColorRegistry().get(symbolicName);
300
    }
301

    
302
    /**
303
     * <p>
304
     * executeOperation
305
     * </p>
306
     *
307
     * @param operation
308
     *            a
309
     *            {@link eu.etaxonomy.taxeditor.operation.AbstractPostTaxonOperation}
310
     *            object.
311
     * @return a {@link org.eclipse.core.runtime.IStatus} object.
312
     */
313
    public static IStatus executeOperation(final AbstractPostOperation operation) {
314
        if (getOperationHistory() == null) {
315
            throw new IllegalArgumentException(
316
                    "There is no operation history for this context");
317
        }
318

    
319
        final IAdaptable uiInfoAdapter = WorkspaceUndoUtil
320
                .getUIInfoAdapter(getShell());
321

    
322
        IRunnableWithProgress runnable = new IRunnableWithProgress() {
323

    
324
            @Override
325
            public void run(IProgressMonitor monitor)
326
                    throws InvocationTargetException, InterruptedException {
327
                String operationlabel = operation.getLabel();
328
                monitor.beginTask(operationlabel, 100);
329
                IStatus status = Status.CANCEL_STATUS;
330
                try {
331
                    operation.addContext(IOperationHistory.GLOBAL_UNDO_CONTEXT);
332
                    status = getOperationHistory().execute(operation, monitor,
333
                            uiInfoAdapter);
334
                } catch (ExecutionException e) {
335

    
336
                    MessagingUtils.operationDialog(this, e, TaxeditorStorePlugin.PLUGIN_ID, operationlabel, null);
337

    
338
                } finally {
339
                    monitor.done();
340
                }
341

    
342
                String statusString = status.equals(Status.OK_STATUS) ? "completed"
343
                        : "cancelled";
344
                setStatusLine(operationlabel + " " + statusString + ".");
345

    
346
            }
347
        };
348

    
349
        try {
350
            runInUI(runnable, null);
351
        } catch (Exception e) {
352
            MessagingUtils.messageDialog("Error executing operation", AbstractUtility.class, "An error occured while executing " + operation.getLabel(), e);
353
        }
354

    
355
        IPostOperationEnabled postOperationEnabled = operation
356
                .getPostOperationEnabled();
357
        if (postOperationEnabled != null) {
358
            postOperationEnabled.onComplete();
359
        }
360
        return Status.OK_STATUS;
361
    }
362

    
363
    public static IStatus executeOperation(final AbstractOperation operation, final RemotingCdmHandler handler) {
364
        if (getOperationHistory() == null) {
365
            throw new IllegalArgumentException(
366
                    "There is no operation history for this context");
367
        }
368

    
369
        final IAdaptable uiInfoAdapter = WorkspaceUndoUtil
370
                .getUIInfoAdapter(getShell());
371

    
372
        IRunnableWithProgress runnable = new IRunnableWithProgress() {
373

    
374
            @Override
375
            public void run(IProgressMonitor monitor)
376
                    throws InvocationTargetException, InterruptedException {
377
                String operationlabel = operation.getLabel();
378
                monitor.beginTask(operationlabel, 100);
379
                IStatus status = Status.CANCEL_STATUS;
380
                try {
381
                    operation.addContext(IOperationHistory.GLOBAL_UNDO_CONTEXT);
382
                    status = getOperationHistory().execute(operation, monitor,
383
                            uiInfoAdapter);
384
                    if(handler != null) {
385
                        handler.postOperation(status);
386
                    }
387
                } catch (ExecutionException e) {
388
                    MessagingUtils.operationDialog(this, e, TaxeditorStorePlugin.PLUGIN_ID, operationlabel, null);
389
                } finally {
390
                    monitor.done();
391
                }
392

    
393
                String statusString = status.equals(Status.OK_STATUS) ? "completed"
394
                        : "cancelled";
395
                setStatusLine(operationlabel + " " + statusString + ".");
396

    
397
            }
398
        };
399

    
400
        try {
401
            runInUI(runnable, null);
402
        } catch (Exception e) {
403
            MessagingUtils.messageDialog("Error executing operation", AbstractUtility.class, "An error occured while executing " + operation.getLabel(), e);
404
        }
405

    
406
        return Status.OK_STATUS;
407
    }
408

    
409
    /**
410
     * Executes a remoting monitored operation
411
     *
412
     * @param label for the operation
413
     * @param uuid of the remoting monitor already started on the server
414
     * @param pollInterval in milliseconds
415
     * @param cancelable flag which determines whether the operation can be cancelled
416
     * @param postOp callback for running post operation logic
417
     * @return
418
     */
419
    public static IStatus executeMoniteredOperation(final String label,
420
            final UUID uuid,
421
            final int pollInterval,
422
            final boolean cancelable,
423
            final IPostMoniteredOperationEnabled postOp) {
424

    
425
        try {
426
            // get the remoting monitor the first time to make sure that the
427
            // operation is valid
428
            final IProgressMonitorService progressMonitorService = CdmApplicationState.getCurrentAppConfig().getProgressMonitorService();
429
            final IRemotingProgressMonitor firstRemotingMonitor = progressMonitorService.getRemotingMonitor(uuid);
430
            if(firstRemotingMonitor == null) {
431
                throw new IllegalStateException("Remoting progress monitor is null");
432
            }
433

    
434
            Job job = new Job(label) {
435

    
436

    
437
                @Override
438
                public IStatus run(IProgressMonitor monitor) {
439
                    // run the monitor until the operation is finished
440
                    IRemotingProgressMonitor remotingMonitor;
441
                    try {
442
                        remotingMonitor = CdmStore.getProgressMonitorClientManager().pollMonitor(label, uuid, pollInterval, postOp, monitor);
443
                    } catch (InterruptedException ie) {
444
                        return new Status(Status.ERROR, TaxeditorStorePlugin.PLUGIN_ID, "Operation Interrupted", ie);
445
                    }
446
                    final StringBuilder reportSb = new StringBuilder();
447
                    // collect reports
448
                    for(String report : remotingMonitor.getReports()) {
449
                        reportSb.append(report);
450
                    }
451
                    if(!StringUtils.isBlank(reportSb.toString())) {
452
                        Display.getDefault().asyncExec(new Runnable() {
453
                            @Override
454
                            public void run() {
455
                                // display reports with possibility to save
456
                                ReportTextDialog dialog = new ReportTextDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
457
                                dialog.setTitle(label + " Report");
458
                                dialog.setReportText(reportSb.toString());
459
                                dialog.open();
460
                            }
461
                        });
462
                    }
463
                    return Status.OK_STATUS;
464
                }
465

    
466
                @Override
467
                protected void canceling() {
468
                    CdmStore.getCurrentApplicationConfiguration().getProgressMonitorService().cancel(uuid);
469
                }
470
            };
471

    
472
//            job.addJobChangeListener(new JobChangeAdapter() {
473
//                @Override
474
//                public void done(IJobChangeEvent event) {
475
//                    if(event.getJob().) {
476
//                        logger.warn("in jobc change listener");
477
//                    }
478
//                }
479
//            });
480

    
481
            // configure the job
482
            job.setProperty(IProgressConstants.KEEP_PROPERTY, true);
483
            job.setUser(true);
484
            // schedule job
485
            job.schedule();
486

    
487
        } catch (Exception e) {
488
            MessagingUtils.errorDialog("Error executing operation",
489
                    AbstractUtility.class,
490
                    "An error occured while executing " + label,
491
                    TaxeditorStorePlugin.PLUGIN_ID,
492
                    e,
493
                    true);
494
        }
495

    
496
        return Status.OK_STATUS;
497
    }
498

    
499

    
500
    /**
501
     * <p>
502
     * getOperationHistory
503
     * </p>
504
     *
505
     * @return a {@link org.eclipse.core.commands.operations.IOperationHistory}
506
     *         object.
507
     */
508
    public static IOperationHistory getOperationHistory() {
509
        return getWorkbench().getOperationSupport().getOperationHistory();
510
    }
511

    
512
    /**
513
     * <p>
514
     * setStatusLine
515
     * </p>
516
     *
517
     * @param message
518
     *            a {@link java.lang.String} object.
519
     */
520
    public static void setStatusLine(final String message) {
521
        Display.getDefault().asyncExec(new Runnable() {
522

    
523
            @Override
524
            public void run() {
525
                statusLineManager.setMessage(message);
526
            }
527

    
528
        });
529

    
530
    }
531

    
532
    /**
533
     * <p>
534
     * getMonitor
535
     * </p>
536
     *
537
     * @return a {@link org.eclipse.core.runtime.IProgressMonitor} object.
538
     */
539
    public static IProgressMonitor getMonitor() {
540
        statusLineManager.setCancelEnabled(false);
541
        return statusLineManager.getProgressMonitor();
542
    }
543

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

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

    
591
        return new SubProgressMonitor(progressMonitor, ticks);
592
    }
593

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

    
612
    /**
613
     * Present a progress dialog to the user. This dialog will block the UI
614
     *
615
     * @param runnable
616
     *            an implementation of {@link IRunnableWithProgress}
617
     * @throws java.lang.InterruptedException
618
     *             if any.
619
     * @throws java.lang.reflect.InvocationTargetException
620
     *             if any.
621
     */
622
    public static void busyCursorWhile(IRunnableWithProgress runnable)
623
            throws InvocationTargetException, InterruptedException {
624
        getProgressService().busyCursorWhile(runnable);
625
    }
626

    
627
    /**
628
     * <p>
629
     * runInUI
630
     * </p>
631
     *
632
     * @see {@link IProgressService#runInUI(org.eclipse.jface.operation.IRunnableContext, IRunnableWithProgress, ISchedulingRule)}
633
     * @param runnable
634
     *            a {@link org.eclipse.jface.operation.IRunnableWithProgress}
635
     *            object.
636
     * @param rule
637
     *            a {@link org.eclipse.core.runtime.jobs.ISchedulingRule}
638
     *            object.
639
     * @throws java.lang.reflect.InvocationTargetException
640
     *             if any.
641
     * @throws java.lang.InterruptedException
642
     *             if any.
643
     */
644
    public static void runInUI(IRunnableWithProgress runnable,
645
            ISchedulingRule rule) throws InvocationTargetException,
646
            InterruptedException {
647
        getProgressService().runInUI(getWorkbenchWindow(), runnable, rule);
648
    }
649

    
650
    /**
651
     * <p>
652
     * run
653
     * </p>
654
     *
655
     * @param fork
656
     *            a boolean.
657
     * @param cancelable
658
     *            a boolean.
659
     * @param runnable
660
     *            a {@link org.eclipse.jface.operation.IRunnableWithProgress}
661
     *            object.
662
     * @throws java.lang.reflect.InvocationTargetException
663
     *             if any.
664
     * @throws java.lang.InterruptedException
665
     *             if any.
666
     */
667
    public static void run(boolean fork, boolean cancelable,
668
            IRunnableWithProgress runnable) throws InvocationTargetException,
669
            InterruptedException {
670
        getProgressService().run(fork, cancelable, runnable);
671
    }
672

    
673
    /**
674
     * <p>
675
     * getProgressService
676
     * </p>
677
     *
678
     * @return a {@link org.eclipse.ui.progress.IProgressService} object.
679
     */
680
    public static IProgressService getProgressService() {
681
        IWorkbench workbench = PlatformUI.getWorkbench();
682
        return workbench.getProgressService();
683
    }
684

    
685
    /**
686
     * <p>
687
     * getProgressService2
688
     * </p>
689
     *
690
     * @return a {@link org.eclipse.ui.progress.IWorkbenchSiteProgressService}
691
     *         object.
692
     */
693
    public static IWorkbenchSiteProgressService getProgressService2() {
694
        return (IWorkbenchSiteProgressService) getService(IWorkbenchSiteProgressService.class);
695
    }
696

    
697
    /**
698
     * <p>
699
     * getPluginId
700
     * </p>
701
     *
702
     * @return a {@link java.lang.String} object.
703
     */
704
    public static String getPluginId() {
705
        return "eu.taxeditor";
706
    }
707

    
708
    /**
709
     * <p>
710
     * getActiveEditor
711
     * </p>
712
     *
713
     * @return a {@link org.eclipse.ui.IEditorPart} object.
714
     */
715
    public static IEditorPart getActiveEditor() {
716
        return getActivePage() != null ? getActivePage().getActiveEditor()
717
                : null;
718
    }
719

    
720
    /**
721
     * <p>
722
     * getDetailsView
723
     * </p>
724
     *
725
     * @return a {@link eu.etaxonomy.taxeditor.view.detail.DetailsViewPart}
726
     *         object.
727
     */
728
    public static DetailsViewPart getDetailsView() {
729
        return (DetailsViewPart) getView(DetailsViewPart.ID, false);
730
    }
731

    
732
    /**
733
     * <p>
734
     * refreshDetailsViewer
735
     * </p>
736
     */
737
    public static void refreshDetailsViewer() {
738
        if (getDetailsView() != null) {
739
            ((AbstractCdmDataViewer) getDetailsView().getViewer()).refresh();
740
        }
741
    }
742

    
743
    /**
744
     * <p>
745
     * reflowDetailsViewer
746
     * </p>
747
     */
748
    public static void reflowDetailsViewer() {
749
        if (getDetailsView() != null) {
750
            ((AbstractCdmDataViewer) getDetailsView().getViewer()).reflow();
751
        }
752
    }
753

    
754
    public static SupplementalDataViewPart getSupplementalDataView() {
755
        return (SupplementalDataViewPart) getView(SupplementalDataViewPart.ID,
756
                false);
757
    }
758

    
759
    public static void reflowSupplementalViewer() {
760
        if (getSupplementalDataView() != null) {
761
            ((AbstractCdmDataViewer) getSupplementalDataView().getViewer())
762
            .reflow();
763
        }
764
    }
765

    
766

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

    
783
        // create list according to the type hierarchy (root elements alphabetically with recursive children also alphabetically)
784
        LinkedHashMap<T, String> result = new LinkedHashMap<T, String>();
785
        parseTermTree(parentElements, result, -1);
786
        return result;
787
    }
788

    
789
    private static<T extends IEnumTerm<T>> void parseTermTree(Collection<TermNode<T>> children, LinkedHashMap<T, String> result, int depth){
790
        depth++;
791
        for(TermNode<T> node:children){
792
            String indentString = "";
793
            for(int i=0;i<depth;i++){
794
                indentString += "  ";
795
            }
796
            if(depth>0){
797
                indentString += "- ";
798
            }
799
            result.put(node.term, indentString + node.term.getMessage());
800
            parseTermTree(node.children, result, depth);
801
        }
802
    }
803

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

    
826
    private static<T extends IEnumTerm<T>> List<TermNode<T>> getTermHierarchy(Collection<T> terms){
827
        List<TermNode<T>> parents = new ArrayList<TermNode<T>>();
828
        // get root elements
829
        for(T term:terms){
830
            T parentTerm = term.getKindOf();
831
            if(parentTerm==null){
832
                // root element
833
                parents.add(new TermNode<T>(term));
834
            }
835
        }
836
        addToParents(parents, terms);
837
        return parents;
838
    }
839

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

    
857
    private static class TermNode<T extends IEnumTerm<T>> implements Comparable<TermNode<T>>{
858
        private final T term;
859
        private final TreeSet<TermNode<T>> children;
860

    
861
        /**
862
         * @param term
863
         * @param children
864
         */
865
        public TermNode(T term) {
866
            super();
867
            this.term = term;
868
            this.children = new TreeSet<TermNode<T>>();
869
        }
870

    
871
        public void addChild(TermNode<T> child){
872
            this.children.add(child);
873
        }
874

    
875
        /**
876
         * @return the children
877
         */
878
        public TreeSet<TermNode<T>> getChildren() {
879
            return children;
880
        }
881

    
882
        /**
883
         * @return the term
884
         */
885
        public T getTerm() {
886
            return term;
887
        }
888

    
889
        /* (non-Javadoc)
890
         * @see java.lang.Object#hashCode()
891
         */
892
        @Override
893
        public int hashCode() {
894
            final int prime = 31;
895
            int result = 1;
896
            result = prime * result + ((term == null) ? 0 : term.hashCode());
897
            return result;
898
        }
899

    
900
        /* (non-Javadoc)
901
         * @see java.lang.Object#equals(java.lang.Object)
902
         */
903
        @Override
904
        public boolean equals(Object obj) {
905
            if (this == obj) {
906
                return true;
907
            }
908
            if (obj == null) {
909
                return false;
910
            }
911
            if (getClass() != obj.getClass()) {
912
                return false;
913
            }
914
            TermNode other = (TermNode) obj;
915
            if (term == null) {
916
                if (other.term != null) {
917
                    return false;
918
                }
919
            } else if (!term.equals(other.term)) {
920
                return false;
921
            }
922
            return true;
923
        }
924

    
925
        /* (non-Javadoc)
926
         * @see java.lang.Comparable#compareTo(java.lang.Object)
927
         */
928
        @Override
929
        public int compareTo(TermNode<T> that) {
930
            return this.term.getMessage().compareTo(that.term.getMessage());
931
        }
932
    }
933

    
934

    
935
    public static void executeCommand(String commandId, Object source, String pluginId) {
936
        IHandlerService handlerService = (IHandlerService) AbstractUtility.getService(IHandlerService.class);
937
        Exception exception = null;
938
        try {
939
            handlerService.executeCommand(commandId, null);
940
        } catch (ExecutionException e) {
941
            exception = e;
942
        } catch (NotDefinedException e) {
943
            exception = e;
944
        } catch (NotEnabledException e) {
945
            exception = e;
946
        } catch (NotHandledException e) {
947
            exception = e;
948
        } finally {
949
            if(exception != null) {
950
                MessagingUtils.errorDialog("Error executing command",
951
                        source,
952
                        "Could not execute command with id " + commandId ,
953
                        pluginId,
954
                        exception,
955
                        true);
956
            }
957
        }
958
    }
959
}
(2-2/39)