Project

General

Profile

Download (24.9 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

    
20
import org.eclipse.core.commands.ExecutionException;
21
import org.eclipse.core.commands.NotEnabledException;
22
import org.eclipse.core.commands.NotHandledException;
23
import org.eclipse.core.commands.common.NotDefinedException;
24
import org.eclipse.core.commands.operations.AbstractOperation;
25
import org.eclipse.core.commands.operations.IOperationHistory;
26
import org.eclipse.core.runtime.IAdaptable;
27
import org.eclipse.core.runtime.IProgressMonitor;
28
import org.eclipse.core.runtime.IStatus;
29
import org.eclipse.core.runtime.NullProgressMonitor;
30
import org.eclipse.core.runtime.OperationCanceledException;
31
import org.eclipse.core.runtime.Status;
32
import org.eclipse.core.runtime.SubProgressMonitor;
33
import org.eclipse.core.runtime.jobs.ISchedulingRule;
34
import org.eclipse.jface.action.IStatusLineManager;
35
import org.eclipse.jface.operation.IRunnableWithProgress;
36
import org.eclipse.jface.resource.ColorRegistry;
37
import org.eclipse.jface.resource.FontRegistry;
38
import org.eclipse.jface.window.ApplicationWindow;
39
import org.eclipse.swt.graphics.Color;
40
import org.eclipse.swt.graphics.Font;
41
import org.eclipse.swt.widgets.Display;
42
import org.eclipse.swt.widgets.Shell;
43
import org.eclipse.ui.IEditorPart;
44
import org.eclipse.ui.IViewPart;
45
import org.eclipse.ui.IViewReference;
46
import org.eclipse.ui.IWorkbench;
47
import org.eclipse.ui.IWorkbenchPage;
48
import org.eclipse.ui.IWorkbenchPart;
49
import org.eclipse.ui.PartInitException;
50
import org.eclipse.ui.PlatformUI;
51
import org.eclipse.ui.handlers.IHandlerService;
52
import org.eclipse.ui.ide.undo.WorkspaceUndoUtil;
53
import org.eclipse.ui.part.EditorPart;
54
import org.eclipse.ui.progress.IProgressService;
55
import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
56
import org.eclipse.ui.themes.ITheme;
57
import org.eclipse.ui.themes.IThemeManager;
58

    
59
import eu.etaxonomy.cdm.model.common.IEnumTerm;
60
import eu.etaxonomy.taxeditor.operation.AbstractPostOperation;
61
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
62
import eu.etaxonomy.taxeditor.operation.RemotingCdmHandler;
63
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
64
import eu.etaxonomy.taxeditor.view.AbstractCdmDataViewer;
65
import eu.etaxonomy.taxeditor.view.detail.DetailsViewPart;
66
import eu.etaxonomy.taxeditor.view.supplementaldata.SupplementalDataViewPart;
67

    
68
/**
69
 * <p>
70
 * Abstract AbstractUtility class.
71
 * </p>
72
 *
73
 * @author n.hoffmann
74
 * @created 11.05.2009
75
 * @version 1.0
76
 */
77
public abstract class AbstractUtility {
78

    
79
    /** Constant <code>statusLineManager</code> */
80
    protected static IStatusLineManager statusLineManager;
81

    
82

    
83
	/**
84
	 * <p>
85
	 * closeAll
86
	 * </p>
87
	 *
88
	 * @return a boolean.
89
	 */
90
	public static boolean closeAll() {
91
		return getActivePage().closeAllEditors(true);
92
	}
93

    
94
	/**
95
	 * Close the given editor.
96
	 *
97
	 * @param editor
98
	 *            The <tt>MultipageTaxonEditor</tt> to close.
99
	 * @return <tt>true</tt> on success
100
	 */
101
	public static boolean close(EditorPart editor) {
102
		return getActivePage().closeEditor(editor, true);
103
	}
104

    
105
	/**
106
	 * <p>
107
	 * getShell
108
	 * </p>
109
	 *
110
	 * @return a {@link org.eclipse.swt.widgets.Shell} object.
111
	 */
112
	public static Shell getShell() {
113

    
114
		return TaxeditorStorePlugin.getDefault().getWorkbench()
115
				.getActiveWorkbenchWindow().getShell();
116
	}
117

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

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

    
131
	/**
132
	 * <p>
133
	 * getActivePart
134
	 * </p>
135
	 *
136
	 * @return a {@link org.eclipse.ui.IWorkbenchPart} object.
137
	 */
138
	public static IWorkbenchPart getActivePart() {
139
		return getActivePage() != null ? getActivePage().getActivePart() : null;
140
	}
141

    
142
	public static IWorkbench getWorkbench() {
143
		return TaxeditorStorePlugin.getDefault().getWorkbench();
144
	}
145

    
146
	/**
147
	 * <p>
148
	 * getWorkbenchWindow
149
	 * </p>
150
	 *
151
	 * @return a {@link org.eclipse.jface.window.ApplicationWindow} object.
152
	 */
153
	public static ApplicationWindow getWorkbenchWindow() {
154
		if (getWorkbench().getWorkbenchWindowCount() > 1) {
155
			throw new IllegalStateException("More than one workbench window");
156
		}
157
		return (ApplicationWindow) getWorkbench().getWorkbenchWindows()[0];
158
	}
159

    
160
	/**
161
	 * <p>
162
	 * showView
163
	 * </p>
164
	 *
165
	 * @param id
166
	 *            a {@link java.lang.String} object.
167
	 * @return a {@link org.eclipse.ui.IViewPart} object.
168
	 */
169
	public static IViewPart showView(String id) {
170
		try {
171
			return PlatformUI.getWorkbench().getActiveWorkbenchWindow()
172
					.getActivePage()
173
					.showView(id, null, IWorkbenchPage.VIEW_VISIBLE);
174
		} catch (PartInitException e) {
175
			MessagingUtils.messageDialog("Error opening view", AbstractUtility.class, "Could not open view: " + id, e);
176
			return null;
177
		}
178
	}
179

    
180
	/**
181
	 * <p>
182
	 * hideView
183
	 * </p>
184
	 *
185
	 * @param view
186
	 *            a {@link org.eclipse.ui.IViewPart} object.
187
	 */
188
	public static void hideView(IViewPart view) {
189
		PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
190
				.hideView(view);
191
	}
192

    
193
	/**
194
	 * <p>
195
	 * getView
196
	 * </p>
197
	 *
198
	 * @param id
199
	 *            a {@link java.lang.String} object.
200
	 * @param restore
201
	 *            a boolean.
202
	 * @return a {@link org.eclipse.ui.IViewPart} object.
203
	 */
204
	public static IViewPart getView(String id, boolean restore) {
205
		IViewReference[] references = PlatformUI.getWorkbench()
206
				.getActiveWorkbenchWindow().getActivePage().getViewReferences();
207
		for (IViewReference reference : references) {
208
			if (reference.getId().equals(id)) {
209
				return reference.getView(restore);
210
			}
211
		}
212
		return null;
213
	}
214

    
215
	/**
216
	 * <p>
217
	 * getService
218
	 * </p>
219
	 *
220
	 * @param api
221
	 *            a {@link java.lang.Class} object.
222
	 * @return a {@link java.lang.Object} object.
223
	 */
224
	public static Object getService(Class api) {
225
		return TaxeditorStorePlugin.getDefault().getWorkbench().getService(api);
226
	}
227

    
228
	/**
229
	 * <p>
230
	 * getCurrentTheme
231
	 * </p>
232
	 *
233
	 * @return a {@link org.eclipse.ui.themes.ITheme} object.
234
	 */
235
	public static ITheme getCurrentTheme() {
236
		IThemeManager themeManager = TaxeditorStorePlugin.getDefault()
237
				.getWorkbench().getThemeManager();
238
		return themeManager.getCurrentTheme();
239
	}
240

    
241
	/**
242
	 * Fonts registered to the plugin may be obtained with the Eclipse themeing
243
	 * functionality. Thus fonts are chooseable by the user via
244
	 * Preferences->General->Appearance->Colors and Fonts
245
	 *
246
	 * @return the FontRegistry for the current theme
247
	 */
248
	public static FontRegistry getFontRegistry() {
249
		return getCurrentTheme().getFontRegistry();
250
	}
251

    
252
	/**
253
	 * <p>
254
	 * getFont
255
	 * </p>
256
	 *
257
	 * @param symbolicName
258
	 *            a {@link java.lang.String} object.
259
	 * @return a {@link org.eclipse.swt.graphics.Font} object.
260
	 */
261
	public static Font getFont(String symbolicName) {
262
		return getFontRegistry().get(symbolicName);
263
	}
264

    
265
	/**
266
	 * Color registered to the plugin may be obtained with the Eclipse themeing
267
	 * functionality. Thus colors are editable by the user via
268
	 * Preferences->General->Appearance->Colors and Fonts
269
	 *
270
	 * @return the ColorRegistry for the current theme
271
	 */
272
	public static ColorRegistry getColorRegistry() {
273
		return getCurrentTheme().getColorRegistry();
274
	}
275

    
276
	/**
277
	 * <p>
278
	 * getColor
279
	 * </p>
280
	 *
281
	 * @param symbolicName
282
	 *            a {@link java.lang.String} object.
283
	 * @return a {@link org.eclipse.swt.graphics.Color} object.
284
	 */
285
	public static Color getColor(String symbolicName) {
286
		return getColorRegistry().get(symbolicName);
287
	}
288

    
289
	/**
290
	 * <p>
291
	 * executeOperation
292
	 * </p>
293
	 *
294
	 * @param operation
295
	 *            a
296
	 *            {@link eu.etaxonomy.taxeditor.operation.AbstractPostTaxonOperation}
297
	 *            object.
298
	 * @return a {@link org.eclipse.core.runtime.IStatus} object.
299
	 */
300
	public static IStatus executeOperation(final AbstractPostOperation operation) {
301
		if (getOperationHistory() == null) {
302
			throw new IllegalArgumentException(
303
					"There is no operation history for this context");
304
		}
305

    
306
		final IAdaptable uiInfoAdapter = WorkspaceUndoUtil
307
				.getUIInfoAdapter(getShell());
308

    
309
		IRunnableWithProgress runnable = new IRunnableWithProgress() {
310

    
311
			@Override
312
            public void run(IProgressMonitor monitor)
313
					throws InvocationTargetException, InterruptedException {
314
				String operationlabel = operation.getLabel();
315
                monitor.beginTask(operationlabel, 100);
316
				IStatus status = Status.CANCEL_STATUS;
317
				try {
318
					operation.addContext(IOperationHistory.GLOBAL_UNDO_CONTEXT);
319
					status = getOperationHistory().execute(operation, monitor,
320
							uiInfoAdapter);
321
				} catch (ExecutionException e) {
322

    
323
					MessagingUtils.operationDialog(this, e, TaxeditorStorePlugin.PLUGIN_ID, operationlabel, null);
324

    
325
				} finally {
326
					monitor.done();
327
				}
328

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

    
333
			}
334
		};
335

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

    
342
		IPostOperationEnabled postOperationEnabled = operation
343
				.getPostOperationEnabled();
344
		if (postOperationEnabled != null) {
345
			postOperationEnabled.onComplete();
346
		}
347
		return Status.OK_STATUS;
348
	}
349

    
350
	   public static IStatus executeOperation(final AbstractOperation operation, final RemotingCdmHandler handler) {
351
	        if (getOperationHistory() == null) {
352
	            throw new IllegalArgumentException(
353
	                    "There is no operation history for this context");
354
	        }
355

    
356
	        final IAdaptable uiInfoAdapter = WorkspaceUndoUtil
357
	                .getUIInfoAdapter(getShell());
358

    
359
	        IRunnableWithProgress runnable = new IRunnableWithProgress() {
360

    
361
	            @Override
362
	            public void run(IProgressMonitor monitor)
363
	                    throws InvocationTargetException, InterruptedException {
364
	                String operationlabel = operation.getLabel();
365
	                monitor.beginTask(operationlabel, 100);
366
	                IStatus status = Status.CANCEL_STATUS;
367
	                try {
368
	                    operation.addContext(IOperationHistory.GLOBAL_UNDO_CONTEXT);
369
	                    status = getOperationHistory().execute(operation, monitor,
370
	                            uiInfoAdapter);
371
	                    if(handler != null) {
372
	                        handler.postOperation(status);
373
	                    }
374
	                } catch (ExecutionException e) {
375
	                    MessagingUtils.operationDialog(this, e, TaxeditorStorePlugin.PLUGIN_ID, operationlabel, null);
376
	                } finally {
377
	                    monitor.done();
378
	                }
379

    
380
	                String statusString = status.equals(Status.OK_STATUS) ? "completed"
381
	                        : "cancelled";
382
	                setStatusLine(operationlabel + " " + statusString + ".");
383

    
384
	            }
385
	        };
386

    
387
	        try {
388
	            runInUI(runnable, null);
389
	        } catch (Exception e) {
390
	            MessagingUtils.messageDialog("Error executing operation", AbstractUtility.class, "An error occured while executing " + operation.getLabel(), e);
391
	        }
392

    
393
	        return Status.OK_STATUS;
394
	    }
395
	/**
396
	 * <p>
397
	 * getOperationHistory
398
	 * </p>
399
	 *
400
	 * @return a {@link org.eclipse.core.commands.operations.IOperationHistory}
401
	 *         object.
402
	 */
403
	public static IOperationHistory getOperationHistory() {
404
		return getWorkbench().getOperationSupport().getOperationHistory();
405
	}
406

    
407
	/**
408
	 * <p>
409
	 * setStatusLine
410
	 * </p>
411
	 *
412
	 * @param message
413
	 *            a {@link java.lang.String} object.
414
	 */
415
	public static void setStatusLine(final String message) {
416
		Display.getDefault().asyncExec(new Runnable() {
417

    
418
			@Override
419
            public void run() {
420
				statusLineManager.setMessage(message);
421
			}
422

    
423
		});
424

    
425
	}
426

    
427
	/**
428
	 * <p>
429
	 * getMonitor
430
	 * </p>
431
	 *
432
	 * @return a {@link org.eclipse.core.runtime.IProgressMonitor} object.
433
	 */
434
	public static IProgressMonitor getMonitor() {
435
		statusLineManager.setCancelEnabled(false);
436
		return statusLineManager.getProgressMonitor();
437
	}
438

    
439
	/**
440
	 * Starts either the given {@link IProgressMonitor} if it's not
441
	 * <code>null</code> or a new {@link NullProgressMonitor}.
442
	 *
443
	 * @param progressMonitor
444
	 *            The {@link IProgressMonitor} or <code>null</code> if no
445
	 *            progress should be reported.
446
	 * @param taskName
447
	 *            The name of the main task.
448
	 * @param steps
449
	 *            The number of steps this task is subdivided into.
450
	 * @return The {@link IProgressMonitor}.
451
	 */
452
	public static IProgressMonitor startMainMonitor(
453
			IProgressMonitor progressMonitor, String taskName, int steps) {
454
		IProgressMonitor newMonitor = progressMonitor;
455
		if (newMonitor == null) {
456
			newMonitor = new NullProgressMonitor();
457
		}
458
		newMonitor.beginTask(taskName == null ? "" : taskName, steps);
459
		newMonitor.subTask(" ");
460
		return newMonitor;
461
	}
462

    
463
	/**
464
	 * Creates a {@link SubProgressMonitor} if the given
465
	 * {@link IProgressMonitor} is not <code>null</code> and not a
466
	 * {@link NullProgressMonitor}.
467
	 *
468
	 * @param progressMonitor
469
	 *            The parent {@link IProgressMonitor} of the
470
	 *            {@link SubProgressMonitor} to be created.
471
	 * @param ticks
472
	 *            The number of steps this subtask is subdivided into. Must be a
473
	 *            positive number and must not be
474
	 *            {@link IProgressMonitor#UNKNOWN}.
475
	 * @return The {@link IProgressMonitor}.
476
	 */
477
	public static IProgressMonitor getSubProgressMonitor(
478
			IProgressMonitor progressMonitor, int ticks) {
479
		if (progressMonitor == null) {
480
			return new NullProgressMonitor();
481
		}
482
		if (progressMonitor instanceof NullProgressMonitor) {
483
			return progressMonitor;
484
		}
485

    
486
		return new SubProgressMonitor(progressMonitor, ticks);
487
	}
488

    
489
	/**
490
	 * Checks whether the user canceled this operation. If not canceled, the
491
	 * given number of steps are declared as done.
492
	 *
493
	 * @param newMonitor
494
	 *            a {@link org.eclipse.core.runtime.IProgressMonitor} object.
495
	 * @param steps
496
	 *            a int.
497
	 */
498
	public static void workedChecked(IProgressMonitor newMonitor, int steps) {
499
		// In case the progress monitor was canceled throw an exception.
500
		if (newMonitor.isCanceled()) {
501
			throw new OperationCanceledException();
502
		}
503
		// Otherwise declare this step as done.
504
		newMonitor.worked(steps);
505
	}
506

    
507
	/**
508
	 * Present a progress dialog to the user. This dialog will block the UI
509
	 *
510
	 * @param runnable
511
	 *            an implementation of {@link IRunnableWithProgress}
512
	 * @throws java.lang.InterruptedException
513
	 *             if any.
514
	 * @throws java.lang.reflect.InvocationTargetException
515
	 *             if any.
516
	 */
517
	public static void busyCursorWhile(IRunnableWithProgress runnable)
518
			throws InvocationTargetException, InterruptedException {
519
		getProgressService().busyCursorWhile(runnable);
520
	}
521

    
522
	/**
523
	 * <p>
524
	 * runInUI
525
	 * </p>
526
	 *
527
	 * @see {@link IProgressService#runInUI(org.eclipse.jface.operation.IRunnableContext, IRunnableWithProgress, ISchedulingRule)}
528
	 * @param runnable
529
	 *            a {@link org.eclipse.jface.operation.IRunnableWithProgress}
530
	 *            object.
531
	 * @param rule
532
	 *            a {@link org.eclipse.core.runtime.jobs.ISchedulingRule}
533
	 *            object.
534
	 * @throws java.lang.reflect.InvocationTargetException
535
	 *             if any.
536
	 * @throws java.lang.InterruptedException
537
	 *             if any.
538
	 */
539
	public static void runInUI(IRunnableWithProgress runnable,
540
			ISchedulingRule rule) throws InvocationTargetException,
541
			InterruptedException {
542
		getProgressService().runInUI(getWorkbenchWindow(), runnable, rule);
543
	}
544

    
545
	/**
546
	 * <p>
547
	 * run
548
	 * </p>
549
	 *
550
	 * @param fork
551
	 *            a boolean.
552
	 * @param cancelable
553
	 *            a boolean.
554
	 * @param runnable
555
	 *            a {@link org.eclipse.jface.operation.IRunnableWithProgress}
556
	 *            object.
557
	 * @throws java.lang.reflect.InvocationTargetException
558
	 *             if any.
559
	 * @throws java.lang.InterruptedException
560
	 *             if any.
561
	 */
562
	public static void run(boolean fork, boolean cancelable,
563
			IRunnableWithProgress runnable) throws InvocationTargetException,
564
			InterruptedException {
565
		getProgressService().run(fork, cancelable, runnable);
566
	}
567

    
568
	/**
569
	 * <p>
570
	 * getProgressService
571
	 * </p>
572
	 *
573
	 * @return a {@link org.eclipse.ui.progress.IProgressService} object.
574
	 */
575
	public static IProgressService getProgressService() {
576
		IWorkbench workbench = PlatformUI.getWorkbench();
577
		return workbench.getProgressService();
578
	}
579

    
580
	/**
581
	 * <p>
582
	 * getProgressService2
583
	 * </p>
584
	 *
585
	 * @return a {@link org.eclipse.ui.progress.IWorkbenchSiteProgressService}
586
	 *         object.
587
	 */
588
	public static IWorkbenchSiteProgressService getProgressService2() {
589
		return (IWorkbenchSiteProgressService) getService(IWorkbenchSiteProgressService.class);
590
	}
591

    
592
	/**
593
	 * <p>
594
	 * getPluginId
595
	 * </p>
596
	 *
597
	 * @return a {@link java.lang.String} object.
598
	 */
599
	public static String getPluginId() {
600
		return "eu.taxeditor";
601
	}
602

    
603
	/**
604
	 * <p>
605
	 * getActiveEditor
606
	 * </p>
607
	 *
608
	 * @return a {@link org.eclipse.ui.IEditorPart} object.
609
	 */
610
	public static IEditorPart getActiveEditor() {
611
		return getActivePage() != null ? getActivePage().getActiveEditor()
612
				: null;
613
	}
614

    
615
	/**
616
	 * <p>
617
	 * getDetailsView
618
	 * </p>
619
	 *
620
	 * @return a {@link eu.etaxonomy.taxeditor.view.detail.DetailsViewPart}
621
	 *         object.
622
	 */
623
	public static DetailsViewPart getDetailsView() {
624
		return (DetailsViewPart) getView(DetailsViewPart.ID, false);
625
	}
626

    
627
	/**
628
	 * <p>
629
	 * refreshDetailsViewer
630
	 * </p>
631
	 */
632
	public static void refreshDetailsViewer() {
633
		if (getDetailsView() != null) {
634
			((AbstractCdmDataViewer) getDetailsView().getViewer()).refresh();
635
		}
636
	}
637

    
638
	/**
639
	 * <p>
640
	 * reflowDetailsViewer
641
	 * </p>
642
	 */
643
	public static void reflowDetailsViewer() {
644
		if (getDetailsView() != null) {
645
			((AbstractCdmDataViewer) getDetailsView().getViewer()).reflow();
646
		}
647
	}
648

    
649
	public static SupplementalDataViewPart getSupplementalDataView() {
650
		return (SupplementalDataViewPart) getView(SupplementalDataViewPart.ID,
651
				false);
652
	}
653

    
654
	public static void reflowSupplementalViewer() {
655
		if (getSupplementalDataView() != null) {
656
			((AbstractCdmDataViewer) getSupplementalDataView().getViewer())
657
					.reflow();
658
		}
659
	}
660

    
661

    
662
    /**
663
     * Orders a Collection of {@link IEnumTerm}s according to the term
664
     * hierarchy. <br>
665
     * <br>
666
     * The returned map will be be ordered primarily by root elements,
667
     * secondarily by the child elements and their children resp., both ascending alphabetically. <br>
668
     * @param terms
669
     *            A {@link Collection} of {@link IEnumTerm}s for which the term
670
     *            hierarchy should be created
671
     * @return a map which holds the terms as keys and their string
672
     *         representation via {@link IEnumTerm#getMessage()} as values
673
     */
674
    public static <T extends IEnumTerm<T>> LinkedHashMap<T, String> orderTerms(Collection<T> terms) {
675
        TreeSet<TermNode<T>> parentElements = new TreeSet<TermNode<T>>();
676
        parentElements.addAll(getTermHierarchy(terms));
677

    
678
        // create list according to the type hierarchy (root elements alphabetically with recursive children also alphabetically)
679
        LinkedHashMap<T, String> result = new LinkedHashMap<T, String>();
680
        parseTermTree(parentElements, result, -1);
681
        return result;
682
    }
683

    
684
    private static<T extends IEnumTerm<T>> void parseTermTree(Collection<TermNode<T>> children, LinkedHashMap<T, String> result, int depth){
685
        depth++;
686
        for(TermNode<T> node:children){
687
            String indentString = "";
688
            for(int i=0;i<depth;i++){
689
                indentString += "  ";
690
            }
691
            if(depth>0){
692
                indentString += "- ";
693
            }
694
            result.put(node.term, indentString + node.term.getMessage());
695
            parseTermTree(node.children, result, depth);
696
        }
697
    }
698

    
699
    private static<T extends IEnumTerm<T>> void addToParents(List<TermNode<T>> parents, Collection<T> terms){
700
        List<TermNode<T>> hasChildrenList = new ArrayList<TermNode<T>>();
701
        for(T term:terms){
702
            // only terms with parents
703
            if(term.getKindOf()!=null){
704
                TermNode<T> parentNode = new TermNode<T>(term.getKindOf());
705
                TermNode<T> childNode = new TermNode<T>(term);
706
                if(parents.contains(parentNode)){
707
                    // parent found in parent list -> add this term to parent's child list
708
                    parents.get(parents.indexOf(parentNode)).addChild(childNode);
709
                    if(!term.getGeneralizationOf().isEmpty()){
710
                        // has more children -> add to list which will be the parent for the next recursion
711
                        hasChildrenList.add(childNode);
712
                    }
713
                }
714
            }
715
        }
716
        if(!hasChildrenList.isEmpty()){
717
            addToParents(hasChildrenList, terms);
718
        }
719
    }
720

    
721
    private static<T extends IEnumTerm<T>> List<TermNode<T>> getTermHierarchy(Collection<T> terms){
722
        List<TermNode<T>> parents = new ArrayList<TermNode<T>>();
723
        // get root elements
724
        for(T term:terms){
725
            T parentTerm = term.getKindOf();
726
            if(parentTerm==null){
727
                // root element
728
                parents.add(new TermNode<T>(term));
729
            }
730
        }
731
        addToParents(parents, terms);
732
        return parents;
733
    }
734

    
735
    @SuppressWarnings("unchecked")
736
    /**
737
     * Recursively iterates over all term parents until no more parent is found i.e. the root node
738
     * @param term The term for which the parent should be found
739
     * @return the root terms of the term hierarchy
740
     */
741
    private static<T extends IEnumTerm<T>> T getParentFor(T term){
742
        // PP: cast should be safe. Why is Eclipse complaining??
743
        T parent = term.getKindOf();
744
        if(parent==null){
745
            return term;
746
        }
747
        else{
748
            return getParentFor(term.getKindOf());
749
        }
750
    }
751

    
752
    private static class TermNode<T extends IEnumTerm<T>> implements Comparable<TermNode<T>>{
753
        private final T term;
754
        private final TreeSet<TermNode<T>> children;
755

    
756
        /**
757
         * @param term
758
         * @param children
759
         */
760
        public TermNode(T term) {
761
            super();
762
            this.term = term;
763
            this.children = new TreeSet<TermNode<T>>();
764
        }
765

    
766
        public void addChild(TermNode<T> child){
767
            this.children.add(child);
768
        }
769

    
770
        /**
771
         * @return the children
772
         */
773
        public TreeSet<TermNode<T>> getChildren() {
774
            return children;
775
        }
776

    
777
        /**
778
         * @return the term
779
         */
780
        public T getTerm() {
781
            return term;
782
        }
783

    
784
        /* (non-Javadoc)
785
         * @see java.lang.Object#hashCode()
786
         */
787
        @Override
788
        public int hashCode() {
789
            final int prime = 31;
790
            int result = 1;
791
            result = prime * result + ((term == null) ? 0 : term.hashCode());
792
            return result;
793
        }
794

    
795
        /* (non-Javadoc)
796
         * @see java.lang.Object#equals(java.lang.Object)
797
         */
798
        @Override
799
        public boolean equals(Object obj) {
800
            if (this == obj) {
801
                return true;
802
            }
803
            if (obj == null) {
804
                return false;
805
            }
806
            if (getClass() != obj.getClass()) {
807
                return false;
808
            }
809
            TermNode other = (TermNode) obj;
810
            if (term == null) {
811
                if (other.term != null) {
812
                    return false;
813
                }
814
            } else if (!term.equals(other.term)) {
815
                return false;
816
            }
817
            return true;
818
        }
819

    
820
        /* (non-Javadoc)
821
         * @see java.lang.Comparable#compareTo(java.lang.Object)
822
         */
823
        @Override
824
        public int compareTo(TermNode<T> that) {
825
            return this.term.getMessage().compareTo(that.term.getMessage());
826
        }
827
    }
828

    
829

    
830
    public static void executeCommand(String commandId, Object source, String pluginId) {
831
        IHandlerService handlerService = (IHandlerService) AbstractUtility.getService(IHandlerService.class);
832
        Exception exception = null;
833
        try {
834
            handlerService.executeCommand(commandId, null);
835
        } catch (ExecutionException e) {
836
            exception = e;
837
        } catch (NotDefinedException e) {
838
            exception = e;
839
        } catch (NotEnabledException e) {
840
            exception = e;
841
        } catch (NotHandledException e) {
842
            exception = e;
843
        } finally {
844
            if(exception != null) {
845
                MessagingUtils.errorDialog("Error executing command",
846
                        source,
847
                        "Could not execute command with id " + commandId ,
848
                        pluginId,
849
                        exception,
850
                        true);
851
            }
852
        }
853
    }
854
}
(2-2/39)