Project

General

Profile

Download (29.4 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.e4.ui.workbench.modeling.EPartService;
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.viewers.IStructuredSelection;
43
import org.eclipse.jface.viewers.SelectionChangedEvent;
44
import org.eclipse.swt.graphics.Color;
45
import org.eclipse.swt.graphics.Font;
46
import org.eclipse.swt.widgets.Display;
47
import org.eclipse.swt.widgets.Shell;
48
import org.eclipse.ui.IEditorPart;
49
import org.eclipse.ui.IViewPart;
50
import org.eclipse.ui.IViewReference;
51
import org.eclipse.ui.IWorkbench;
52
import org.eclipse.ui.IWorkbenchPage;
53
import org.eclipse.ui.IWorkbenchPart;
54
import org.eclipse.ui.IWorkbenchWindow;
55
import org.eclipse.ui.PartInitException;
56
import org.eclipse.ui.PlatformUI;
57
import org.eclipse.ui.handlers.IHandlerService;
58
import org.eclipse.ui.ide.undo.WorkspaceUndoUtil;
59
import org.eclipse.ui.part.EditorPart;
60
import org.eclipse.ui.progress.IProgressConstants;
61
import org.eclipse.ui.progress.IProgressService;
62
import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
63
import org.eclipse.ui.themes.ITheme;
64
import org.eclipse.ui.themes.IThemeManager;
65

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

    
84
/**
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
    public static boolean closeAll() {
99
        if(getActivePage()!=null){
100
            return getActivePage().closeAllEditors(true);
101
        }
102
        return false;
103
    }
104

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

    
116
    public static Shell getShell() {
117

    
118
        return TaxeditorStorePlugin.getDefault().getWorkbench()
119
                .getActiveWorkbenchWindow().getShell();
120
    }
121

    
122
    public static IWorkbenchPage getActivePage() {
123
        try{
124
            return TaxeditorStorePlugin.getDefault().getWorkbench()
125
                    .getActiveWorkbenchWindow().getActivePage();
126
        } catch(NullPointerException npe){
127
            return null;
128
        }
129
    }
130

    
131
    public static IWorkbenchPart getActiveWorkbenchPart() {
132
        IWorkbenchPage activePage = getActivePage();
133
        if(activePage!=null){
134
            IWorkbenchPart activePart = activePage.getActivePart();
135
            if(activePart!=null){
136
                return activePart;
137
            }
138
        }
139
        return null;
140
    }
141

    
142
    public static Object getActiveE4Part() {
143
        IWorkbenchPage activePage = getActivePage();
144
        if(activePage!=null){
145
            IWorkbenchPart activePart = activePage.getActivePart();
146
            Object e4WrappedPart = WorkbenchUtility.getE4WrappedPart(activePart);
147
            return e4WrappedPart!=null?e4WrappedPart:activePart;
148
        }
149
        return null;
150
    }
151

    
152
    public static IWorkbench getWorkbench() {
153
        return TaxeditorStorePlugin.getDefault().getWorkbench();
154
    }
155

    
156
    public static IWorkbenchWindow getWorkbenchWindow() {
157
        if (getWorkbench().getWorkbenchWindowCount() > 1) {
158
            throw new IllegalStateException("More than one workbench window");
159
        }
160
        return getWorkbench().getWorkbenchWindows()[0];
161
    }
162

    
163
    public static IViewPart showView(String id) {
164
        try {
165
            return PlatformUI.getWorkbench().getActiveWorkbenchWindow()
166
                    .getActivePage()
167
                    .showView(id, null, IWorkbenchPage.VIEW_VISIBLE);
168
        } catch (PartInitException e) {
169
            MessagingUtils.messageDialog("Error opening view", AbstractUtility.class, "Could not open view: " + id, e);
170
            return null;
171
        }
172
    }
173

    
174
    public static void hideView(IViewPart view) {
175
        PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
176
        .hideView(view);
177
    }
178

    
179
    public static IViewPart getView(String id, boolean restore) {
180
    	IWorkbench workbench = PlatformUI.getWorkbench();
181
        IWorkbenchWindow activeWorkbenchWindow = workbench.getActiveWorkbenchWindow();
182
    	IViewReference[] references = null;
183
    	if(activeWorkbenchWindow!=null && activeWorkbenchWindow.getActivePage()!=null){
184
    	    references = activeWorkbenchWindow.getActivePage().getViewReferences();
185
    	}
186
    	else if(workbench.getWorkbenchWindows().length>0 && workbench.getWorkbenchWindows()[0].getActivePage()!=null){
187
    		references = workbench.getWorkbenchWindows()[0].getActivePage().getViewReferences();
188
    	}
189
    	if(references!=null){
190
    		for (IViewReference reference : references) {
191
    			if (reference.getId().equals(id)) {
192
    				return reference.getView(restore);
193
    			}
194
    		}
195
    	}
196
        return null;
197
    }
198

    
199
    public static Object getService(Class api) {
200
        return TaxeditorStorePlugin.getDefault().getWorkbench().getService(api);
201
    }
202

    
203
    public static ITheme getCurrentTheme() {
204
        IThemeManager themeManager = TaxeditorStorePlugin.getDefault()
205
                .getWorkbench().getThemeManager();
206
        return themeManager.getCurrentTheme();
207
    }
208

    
209
    /**
210
     * Fonts registered to the plugin may be obtained with the Eclipse themeing
211
     * functionality. Thus fonts are chooseable by the user via
212
     * Preferences->General->Appearance->Colors and Fonts
213
     *
214
     * @return the FontRegistry for the current theme
215
     */
216
    public static FontRegistry getFontRegistry() {
217
        return getCurrentTheme().getFontRegistry();
218
    }
219

    
220
    public static Font getFont(String symbolicName) {
221
        return getFontRegistry().get(symbolicName);
222
    }
223

    
224
    /**
225
     * Color registered to the plugin may be obtained with the Eclipse themeing
226
     * functionality. Thus colors are editable by the user via
227
     * Preferences->General->Appearance->Colors and Fonts
228
     *
229
     * @return the ColorRegistry for the current theme
230
     */
231
    public static ColorRegistry getColorRegistry() {
232
        return getCurrentTheme().getColorRegistry();
233
    }
234

    
235
    public static Color getColor(String symbolicName) {
236
        return getColorRegistry().get(symbolicName);
237
    }
238

    
239
    public static IStatus executeOperation(final AbstractPostOperation operation) {
240
        if (getOperationHistory() == null) {
241
            throw new IllegalArgumentException(
242
                    "There is no operation history for this context");
243
        }
244

    
245
        final IAdaptable uiInfoAdapter = WorkspaceUndoUtil
246
                .getUIInfoAdapter(getShell());
247

    
248
        IRunnableWithProgress runnable = new IRunnableWithProgress() {
249

    
250
            @Override
251
            public void run(IProgressMonitor monitor)
252
                    throws InvocationTargetException, InterruptedException {
253
                String operationlabel = operation.getLabel();
254
                monitor.beginTask(operationlabel, 100);
255
                IStatus status = Status.CANCEL_STATUS;
256
                try {
257
                    operation.addContext(IOperationHistory.GLOBAL_UNDO_CONTEXT);
258
                    status = getOperationHistory().execute(operation, monitor,
259
                            uiInfoAdapter);
260
                } catch (ExecutionException e) {
261

    
262
                    MessagingUtils.operationDialog(this, e, TaxeditorStorePlugin.PLUGIN_ID, operationlabel, null);
263

    
264
                } finally {
265
                    monitor.done();
266
                }
267

    
268
                String statusString = status.equals(Status.OK_STATUS) ? "completed"
269
                        : "cancelled";
270
                setStatusLine(operationlabel + " " + statusString + ".");
271

    
272
            }
273
        };
274

    
275
        try {
276
            runInUI(runnable, null);
277
        } catch (Exception e) {
278
            MessagingUtils.messageDialog("Error executing operation", AbstractUtility.class, "An error occured while executing " + operation.getLabel(), e);
279
        }
280

    
281
        IPostOperationEnabled postOperationEnabled = operation
282
                .getPostOperationEnabled();
283
        if (postOperationEnabled != null) {
284
            postOperationEnabled.onComplete();
285
        }
286
        return Status.OK_STATUS;
287
    }
288

    
289
    public static IStatus executeOperation(final AbstractOperation operation, final RemotingCdmHandlerE4 handler) {
290
        return executeOperation_internal(operation, handler);
291
    }
292

    
293
    public static IStatus executeOperation(final AbstractOperation operation, final RemotingCdmHandler handler) {
294
        return executeOperation_internal(operation, handler);
295
    }
296

    
297
    private static IStatus executeOperation_internal(final AbstractOperation operation, final Object handler) {
298
        if (getOperationHistory() == null) {
299
            throw new IllegalArgumentException(
300
                    "There is no operation history for this context");
301
        }
302

    
303
        final IAdaptable uiInfoAdapter = WorkspaceUndoUtil
304
                .getUIInfoAdapter(getShell());
305

    
306
        IRunnableWithProgress runnable = new IRunnableWithProgress() {
307

    
308
            @Override
309
            public void run(IProgressMonitor monitor)
310
                    throws InvocationTargetException, InterruptedException {
311
                String operationlabel = operation.getLabel();
312
                monitor.beginTask(operationlabel, 100);
313
                IStatus status = Status.CANCEL_STATUS;
314
                try {
315
                    operation.addContext(IOperationHistory.GLOBAL_UNDO_CONTEXT);
316
                    status = getOperationHistory().execute(operation, monitor,
317
                            uiInfoAdapter);
318
                    if(handler instanceof RemotingCdmHandler) {
319
                        ((RemotingCdmHandler) handler).postOperation(status);
320
                    }
321
                    else if(handler instanceof RemotingCdmHandlerE4) {
322
                        ((RemotingCdmHandlerE4) handler).postOperation(status);
323
                    }
324
                } catch (ExecutionException e) {
325
                    MessagingUtils.operationDialog(this, e, TaxeditorStorePlugin.PLUGIN_ID, operationlabel, null);
326
                } finally {
327
                    monitor.done();
328
                }
329

    
330
                String statusString = status.equals(Status.OK_STATUS) ? "completed"
331
                        : "cancelled";
332
                setStatusLine(operationlabel + " " + statusString + ".");
333

    
334
            }
335
        };
336

    
337
        try {
338
            runInUI(runnable, null);
339
        } catch (Exception e) {
340
            MessagingUtils.messageDialog("Error executing operation", AbstractUtility.class, "An error occured while executing " + operation.getLabel(), e);
341
        }
342

    
343
        return Status.OK_STATUS;
344
    }
345

    
346
    /**
347
     * Executes a remoting monitored operation
348
     *
349
     * @param label for the operation
350
     * @param uuid of the remoting monitor already started on the server
351
     * @param pollInterval in milliseconds
352
     * @param cancelable flag which determines whether the operation can be cancelled
353
     * @param postOp callback for running post operation logic
354
     * @return
355
     */
356
    public static IStatus executeMoniteredOperation(final String label,
357
            final UUID uuid,
358
            final int pollInterval,
359
            final boolean cancelable,
360
            final IPostMoniteredOperationEnabled postOp,
361
            final IFeedbackGenerator feedbackGenerator) {
362

    
363
        try {
364
            // get the remoting monitor the first time to make sure that the
365
            // operation is valid
366
            final IProgressMonitorService progressMonitorService = CdmApplicationState.getCurrentAppConfig().getProgressMonitorService();
367
            final IRemotingProgressMonitor firstRemotingMonitor = progressMonitorService.getRemotingMonitor(uuid);
368
            if(firstRemotingMonitor == null) {
369
                throw new IllegalStateException("Remoting progress monitor is null");
370
            }
371

    
372
            Job job = new Job(label) {
373

    
374

    
375
                @Override
376
                public IStatus run(IProgressMonitor monitor) {
377
                    // run the monitor until the operation is finished
378
                    IRemotingProgressMonitor remotingMonitor;
379
                    try {
380
                        remotingMonitor = CdmStore.getProgressMonitorClientManager().pollMonitor(label,
381
                                uuid,
382
                                pollInterval,
383
                                postOp,
384
                                feedbackGenerator,
385
                                monitor);
386
                    } catch (Exception ex) {
387
                        return new Status(Status.ERROR, TaxeditorStorePlugin.PLUGIN_ID, "Operation Interrupted", ex);
388
                    }
389
                    final StringBuilder reportSb = new StringBuilder();
390
                    // collect reports
391
                    for(String report : remotingMonitor.getReports()) {
392
                        reportSb.append(report);
393
                    }
394
                    if(!StringUtils.isBlank(reportSb.toString())) {
395
                        Display.getDefault().asyncExec(new Runnable() {
396
                            @Override
397
                            public void run() {
398
                                // display reports with possibility to save
399
                                ReportTextDialog dialog = new ReportTextDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
400
                                dialog.setTitle(label + " Report");
401
                                dialog.setReportText(reportSb.toString());
402
                                dialog.open();
403
                            }
404
                        });
405
                    }
406
                    return Status.OK_STATUS;
407
                }
408

    
409
                @Override
410
                protected void canceling() {
411
                    CdmStore.getCurrentApplicationConfiguration().getProgressMonitorService().cancel(uuid);
412
                }
413
            };
414

    
415
            // configure the job
416
            job.setProperty(IProgressConstants.KEEP_PROPERTY, true);
417
            job.setUser(true);
418
            // schedule job
419
            job.schedule();
420

    
421
        } catch (Exception e) {
422
            MessagingUtils.errorDialog("Error executing operation",
423
                    AbstractUtility.class,
424
                    "An error occured while executing " + label,
425
                    TaxeditorStorePlugin.PLUGIN_ID,
426
                    e,
427
                    true);
428
        }
429

    
430
        return Status.OK_STATUS;
431
    }
432

    
433
    public static IOperationHistory getOperationHistory() {
434
        return getWorkbench().getOperationSupport().getOperationHistory();
435
    }
436

    
437
    public static void setStatusLine(final String message) {
438
        Display.getDefault().asyncExec(new Runnable() {
439

    
440
            @Override
441
            public void run() {
442
                statusLineManager.setMessage(message);
443
            }
444

    
445
        });
446

    
447
    }
448

    
449
    public static IProgressMonitor getMonitor() {
450
        statusLineManager.setCancelEnabled(false);
451
        return statusLineManager.getProgressMonitor();
452
    }
453

    
454
    /**
455
     * Starts either the given {@link IProgressMonitor} if it's not
456
     * <code>null</code> or a new {@link NullProgressMonitor}.
457
     *
458
     * @param progressMonitor
459
     *            The {@link IProgressMonitor} or <code>null</code> if no
460
     *            progress should be reported.
461
     * @param taskName
462
     *            The name of the main task.
463
     * @param steps
464
     *            The number of steps this task is subdivided into.
465
     * @return The {@link IProgressMonitor}.
466
     */
467
    public static IProgressMonitor startMainMonitor(
468
            IProgressMonitor progressMonitor, String taskName, int steps) {
469
        IProgressMonitor newMonitor = progressMonitor;
470
        if (newMonitor == null) {
471
            newMonitor = new NullProgressMonitor();
472
        }
473
        newMonitor.beginTask(taskName == null ? "" : taskName, steps);
474
        newMonitor.subTask(" ");
475
        return newMonitor;
476
    }
477

    
478
    /**
479
     * Creates a {@link SubProgressMonitor} if the given
480
     * {@link IProgressMonitor} is not <code>null</code> and not a
481
     * {@link NullProgressMonitor}.
482
     *
483
     * @param progressMonitor
484
     *            The parent {@link IProgressMonitor} of the
485
     *            {@link SubProgressMonitor} to be created.
486
     * @param ticks
487
     *            The number of steps this subtask is subdivided into. Must be a
488
     *            positive number and must not be
489
     *            {@link IProgressMonitor#UNKNOWN}.
490
     * @return The {@link IProgressMonitor}.
491
     */
492
    public static IProgressMonitor getSubProgressMonitor(
493
            IProgressMonitor progressMonitor, int ticks) {
494
        if (progressMonitor == null) {
495
            return new NullProgressMonitor();
496
        }
497
        if (progressMonitor instanceof NullProgressMonitor) {
498
            return progressMonitor;
499
        }
500

    
501
        return new SubProgressMonitor(progressMonitor, ticks);
502
    }
503

    
504
    /**
505
     * Checks whether the user canceled this operation. If not canceled, the
506
     * given number of steps are declared as done.
507
     *
508
     * @param newMonitor
509
     *            a {@link org.eclipse.core.runtime.IProgressMonitor} object.
510
     * @param steps
511
     *            a int.
512
     */
513
    public static void workedChecked(IProgressMonitor newMonitor, int steps) {
514
        // In case the progress monitor was canceled throw an exception.
515
        if (newMonitor.isCanceled()) {
516
            throw new OperationCanceledException();
517
        }
518
        // Otherwise declare this step as done.
519
        newMonitor.worked(steps);
520
    }
521

    
522
    /**
523
     * Present a progress dialog to the user. This dialog will block the UI
524
     *
525
     * @param runnable
526
     *            an implementation of {@link IRunnableWithProgress}
527
     * @throws java.lang.InterruptedException
528
     *             if any.
529
     * @throws java.lang.reflect.InvocationTargetException
530
     *             if any.
531
     */
532
    public static void busyCursorWhile(IRunnableWithProgress runnable)
533
            throws InvocationTargetException, InterruptedException {
534
        getProgressService().busyCursorWhile(runnable);
535
    }
536

    
537
    public static void runInUI(IRunnableWithProgress runnable,
538
            ISchedulingRule rule) throws InvocationTargetException,
539
            InterruptedException {
540
        getProgressService().runInUI(getWorkbenchWindow(), runnable, rule);
541
    }
542

    
543
    public static void run(boolean fork, boolean cancelable,
544
            IRunnableWithProgress runnable) throws InvocationTargetException,
545
            InterruptedException {
546
        getProgressService().run(fork, cancelable, runnable);
547
    }
548

    
549
    public static IProgressService getProgressService() {
550
        IWorkbench workbench = PlatformUI.getWorkbench();
551
        return workbench.getProgressService();
552
    }
553

    
554
    public static IWorkbenchSiteProgressService getProgressService2() {
555
        return (IWorkbenchSiteProgressService) getService(IWorkbenchSiteProgressService.class);
556
    }
557

    
558
    public static String getPluginId() {
559
        return "eu.taxeditor";
560
    }
561

    
562
    public static IEditorPart getActiveEditor() {
563
        return getActivePage() != null ? getActivePage().getActiveEditor()
564
                : null;
565
    }
566

    
567
    public static Object getActiveE4Editor() {
568
        //FIXME E4 this can be simplified/removed when fully migrated
569
        if(getActivePage()!=null){
570
            IEditorPart activeEditor = getActivePage().getActiveEditor();
571
            Object activePart = getActivePage().getActivePart();
572
            if(activeEditor==null){
573
                activePart = TaxeditorStorePlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getService(EPartService.class).getActivePart();
574
            }
575
            Object wrappedPart = WorkbenchUtility.getE4WrappedPart(activePart);
576
            return wrappedPart!=null?wrappedPart:activeEditor;
577
        }
578
        return null;
579
    }
580

    
581
    public static DetailsViewPart getDetailsView() {
582
        return (DetailsViewPart) getView(DetailsViewPart.ID, false);
583
    }
584

    
585
    public static void refreshDetailsViewer() {
586
        if (getDetailsView() != null) {
587
            ((AbstractCdmDataViewer) getDetailsView().getViewer()).refresh();
588
        }
589
    }
590

    
591
    public static void reflowDetailsViewer() {
592
        if (getDetailsView() != null) {
593
            ((AbstractCdmDataViewer) getDetailsView().getViewer()).reflow();
594
        }
595
    }
596

    
597
    public static SupplementalDataViewPart getSupplementalDataView() {
598
        return (SupplementalDataViewPart) getView(SupplementalDataViewPart.ID,
599
                false);
600
    }
601

    
602
    public static void reflowSupplementalViewer() {
603
        if (getSupplementalDataView() != null) {
604
            ((AbstractCdmDataViewer) getSupplementalDataView().getViewer())
605
            .reflow();
606
        }
607
    }
608

    
609

    
610
    /**
611
     * Orders a Collection of {@link IEnumTerm}s according to the term
612
     * hierarchy. <br>
613
     * <br>
614
     * The returned map will be be ordered primarily by root elements,
615
     * secondarily by the child elements and their children resp., both ascending alphabetically. <br>
616
     * @param terms
617
     *            A {@link Collection} of {@link IEnumTerm}s for which the term
618
     *            hierarchy should be created
619
     * @return a map which holds the terms as keys and their string
620
     *         representation via {@link IEnumTerm#getMessage()} as values
621
     */
622
    public static <T extends IEnumTerm<T>> LinkedHashMap<T, String> orderTerms(Collection<T> terms) {
623
        TreeSet<TermNode<T>> parentElements = new TreeSet<TermNode<T>>();
624
        parentElements.addAll(getTermHierarchy(terms));
625

    
626
        // create list according to the type hierarchy (root elements alphabetically with recursive children also alphabetically)
627
        LinkedHashMap<T, String> result = new LinkedHashMap<T, String>();
628
        parseTermTree(parentElements, result, -1);
629
        return result;
630
    }
631

    
632
    private static<T extends IEnumTerm<T>> void parseTermTree(Collection<TermNode<T>> children, LinkedHashMap<T, String> result, int depth){
633
        depth++;
634
        for(TermNode<T> node:children){
635
            String indentString = "";
636
            for(int i=0;i<depth;i++){
637
                indentString += "  ";
638
            }
639
            if(depth>0){
640
                indentString += "- ";
641
            }
642
            result.put(node.term, indentString + node.term.getMessage());
643
            parseTermTree(node.children, result, depth);
644
        }
645
    }
646

    
647
    private static<T extends IEnumTerm<T>> void addToParents(List<TermNode<T>> parents, Collection<T> terms){
648
        List<TermNode<T>> hasChildrenList = new ArrayList<TermNode<T>>();
649
        for(T term:terms){
650
            // only terms with parents
651
            if(term.getKindOf()!=null){
652
                TermNode<T> parentNode = new TermNode<T>(term.getKindOf());
653
                TermNode<T> childNode = new TermNode<T>(term);
654
                if(parents.contains(parentNode)){
655
                    // parent found in parent list -> add this term to parent's child list
656
                    parents.get(parents.indexOf(parentNode)).addChild(childNode);
657
                    if(!term.getGeneralizationOf().isEmpty()){
658
                        // has more children -> add to list which will be the parent for the next recursion
659
                        hasChildrenList.add(childNode);
660
                    }
661
                }
662
            }
663
        }
664
        if(!hasChildrenList.isEmpty()){
665
            addToParents(hasChildrenList, terms);
666
        }
667
    }
668

    
669
    private static<T extends IEnumTerm<T>> List<TermNode<T>> getTermHierarchy(Collection<T> terms){
670
        List<TermNode<T>> parents = new ArrayList<TermNode<T>>();
671
        // get root elements
672
        for(T term:terms){
673
            T parentTerm = term.getKindOf();
674
            if(parentTerm==null){
675
                // root element
676
                parents.add(new TermNode<T>(term));
677
            }
678
        }
679
        addToParents(parents, terms);
680
        return parents;
681
    }
682

    
683
    @SuppressWarnings("unchecked")
684
    /**
685
     * Recursively iterates over all term parents until no more parent is found i.e. the root node
686
     * @param term The term for which the parent should be found
687
     * @return the root terms of the term hierarchy
688
     */
689
    private static<T extends IEnumTerm<T>> T getParentFor(T term){
690
        // PP: cast should be safe. Why is Eclipse complaining??
691
        T parent = term.getKindOf();
692
        if(parent==null){
693
            return term;
694
        }
695
        else{
696
            return getParentFor(term.getKindOf());
697
        }
698
    }
699

    
700
    private static class TermNode<T extends IEnumTerm<T>> implements Comparable<TermNode<T>>{
701
        private final T term;
702
        private final TreeSet<TermNode<T>> children;
703

    
704
        public TermNode(T term) {
705
            super();
706
            this.term = term;
707
            this.children = new TreeSet<TermNode<T>>();
708
        }
709

    
710
        public void addChild(TermNode<T> child){
711
            this.children.add(child);
712
        }
713

    
714
        public TreeSet<TermNode<T>> getChildren() {
715
            return children;
716
        }
717

    
718
        public T getTerm() {
719
            return term;
720
        }
721

    
722
        @Override
723
        public int hashCode() {
724
            final int prime = 31;
725
            int result = 1;
726
            result = prime * result + ((term == null) ? 0 : term.hashCode());
727
            return result;
728
        }
729

    
730
        @Override
731
        public boolean equals(Object obj) {
732
            if (this == obj) {
733
                return true;
734
            }
735
            if (obj == null) {
736
                return false;
737
            }
738
            if (getClass() != obj.getClass()) {
739
                return false;
740
            }
741
            TermNode other = (TermNode) obj;
742
            if (term == null) {
743
                if (other.term != null) {
744
                    return false;
745
                }
746
            } else if (!term.equals(other.term)) {
747
                return false;
748
            }
749
            return true;
750
        }
751

    
752
        @Override
753
        public int compareTo(TermNode<T> that) {
754
            return this.term.getMessage().compareTo(that.term.getMessage());
755
        }
756
    }
757

    
758

    
759
    public static void executeCommand(String commandId, Object source, String pluginId) {
760
        IHandlerService handlerService = (IHandlerService) AbstractUtility.getService(IHandlerService.class);
761
        Exception exception = null;
762
        try {
763
            handlerService.executeCommand(commandId, null);
764
        } catch (ExecutionException e) {
765
            exception = e;
766
        } catch (NotDefinedException e) {
767
            exception = e;
768
        } catch (NotEnabledException e) {
769
            exception = e;
770
        } catch (NotHandledException e) {
771
            exception = e;
772
        } finally {
773
            if(exception != null) {
774
                MessagingUtils.errorDialog("Error executing command",
775
                        source,
776
                        "Could not execute command with id " + commandId ,
777
                        pluginId,
778
                        exception,
779
                        true);
780
            }
781
        }
782
    }
783

    
784
    public static Object getElementsFromSelectionChangedEvent(SelectionChangedEvent event) {
785
        IStructuredSelection selection = (IStructuredSelection) event.getSelection();
786
        Object selectionToSet = selection;
787
        if(selection.size() == 1){
788
            selectionToSet = selection.getFirstElement();
789
        }
790
        else if(!selection.isEmpty()){
791
            selectionToSet = selection.toArray();
792
        }
793
        return selectionToSet;
794
    }
795
}
(2-2/39)