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.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
        return getActivePage().closeAllEditors(true);
106
    }
107

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
323
        IRunnableWithProgress runnable = new IRunnableWithProgress() {
324

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

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

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

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

    
347
            }
348
        };
349

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

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

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

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

    
373
        IRunnableWithProgress runnable = new IRunnableWithProgress() {
374

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

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

    
398
            }
399
        };
400

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

    
407
        return Status.OK_STATUS;
408
    }
409

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

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

    
436
            Job job = new Job(label) {
437

    
438

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

    
473
                @Override
474
                protected void canceling() {
475
                    CdmStore.getCurrentApplicationConfiguration().getProgressMonitorService().cancel(uuid);
476
                }
477
            };
478

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

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

    
494
        return Status.OK_STATUS;
495
    }
496

    
497

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

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

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

    
526
        });
527

    
528
    }
529

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

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

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

    
589
        return new SubProgressMonitor(progressMonitor, ticks);
590
    }
591

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

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

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

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

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

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

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

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

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

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

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

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

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

    
764

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
932

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