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.jface.window.ApplicationWindow;
42
import org.eclipse.swt.graphics.Color;
43
import org.eclipse.swt.graphics.Font;
44
import org.eclipse.swt.widgets.Display;
45
import org.eclipse.swt.widgets.Shell;
46
import org.eclipse.ui.IEditorPart;
47
import org.eclipse.ui.IViewPart;
48
import org.eclipse.ui.IViewReference;
49
import org.eclipse.ui.IWorkbench;
50
import org.eclipse.ui.IWorkbenchPage;
51
import org.eclipse.ui.IWorkbenchPart;
52
import org.eclipse.ui.IWorkbenchWindow;
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.IFeedbackGenerator;
70
import eu.etaxonomy.taxeditor.operation.IPostMoniteredOperationEnabled;
71
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
72
import eu.etaxonomy.taxeditor.operation.RemotingCdmHandler;
73
import eu.etaxonomy.taxeditor.store.CdmStore;
74
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
75
import eu.etaxonomy.taxeditor.ui.dialog.ReportTextDialog;
76
import eu.etaxonomy.taxeditor.view.AbstractCdmDataViewer;
77
import eu.etaxonomy.taxeditor.view.detail.DetailsViewPart;
78
import eu.etaxonomy.taxeditor.view.supplementaldata.SupplementalDataViewPart;
79

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

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

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

    
96

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
335
        IRunnableWithProgress runnable = new IRunnableWithProgress() {
336

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

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

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

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

    
359
            }
360
        };
361

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

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

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

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

    
385
        IRunnableWithProgress runnable = new IRunnableWithProgress() {
386

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

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

    
410
            }
411
        };
412

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

    
419
        return Status.OK_STATUS;
420
    }
421

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

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

    
448
            Job job = new Job(label) {
449

    
450

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

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

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

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

    
506
        return Status.OK_STATUS;
507
    }
508

    
509

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

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

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

    
538
        });
539

    
540
    }
541

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
776

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
944

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