Project

General

Profile

Download (31.8 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
        if(getActivePage()!=null){
107
            return getActivePage().closeAllEditors(true);
108
        }
109
        return false;
110
    }
111

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

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

    
132
        return TaxeditorStorePlugin.getDefault().getWorkbench()
133
                .getActiveWorkbenchWindow().getShell();
134
    }
135

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

    
145
        return TaxeditorStorePlugin.getDefault().getWorkbench()
146
                .getActiveWorkbenchWindow().getActivePage();
147
    }
148

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

    
160
    public static IWorkbench getWorkbench() {
161
        return TaxeditorStorePlugin.getDefault().getWorkbench();
162
    }
163

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

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

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

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

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

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

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

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

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

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

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

    
333
        final IAdaptable uiInfoAdapter = WorkspaceUndoUtil
334
                .getUIInfoAdapter(getShell());
335

    
336
        IRunnableWithProgress runnable = new IRunnableWithProgress() {
337

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

    
350
                    MessagingUtils.operationDialog(this, e, TaxeditorStorePlugin.PLUGIN_ID, operationlabel, null);
351

    
352
                } finally {
353
                    monitor.done();
354
                }
355

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

    
360
            }
361
        };
362

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

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

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

    
383
        final IAdaptable uiInfoAdapter = WorkspaceUndoUtil
384
                .getUIInfoAdapter(getShell());
385

    
386
        IRunnableWithProgress runnable = new IRunnableWithProgress() {
387

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

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

    
411
            }
412
        };
413

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

    
420
        return Status.OK_STATUS;
421
    }
422

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

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

    
449
            Job job = new Job(label) {
450

    
451

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

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

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

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

    
507
        return Status.OK_STATUS;
508
    }
509

    
510

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

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

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

    
539
        });
540

    
541
    }
542

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

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

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

    
602
        return new SubProgressMonitor(progressMonitor, ticks);
603
    }
604

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

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

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

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

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

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

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

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

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

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

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

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

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

    
777

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
945

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