Project

General

Profile

Download (31 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.Collection;
15
import java.util.Comparator;
16
import java.util.LinkedHashMap;
17
import java.util.Map;
18
import java.util.Map.Entry;
19
import java.util.Set;
20
import java.util.TreeMap;
21
import java.util.TreeSet;
22

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

    
60
import eu.etaxonomy.cdm.model.common.IEnumTerm;
61
import eu.etaxonomy.taxeditor.operation.AbstractPostOperation;
62
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
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
	 * <p>
84
	 * closeAll
85
	 * </p>
86
	 *
87
	 * @return a boolean.
88
	 */
89
	public static boolean closeAll() {
90
		return getActivePage().closeAllEditors(true);
91
	}
92

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
288
	/**
289
	 * Open a message box that informs the user about unimplemented
290
	 * functionality. This method is for developer convenience.
291
	 *
292
	 * @param source
293
	 *            a {@link java.lang.Object} object.
294
	 */
295
	public static void notImplementedMessage(Object source) {
296
		warningDialog("Not yet implemented", source,
297
				"This functionality is not yet implemented.");
298
	}
299

    
300
	/**
301
	 * <p>
302
	 * informationDialog
303
	 * </p>
304
	 *
305
	 * @param title
306
	 *            a {@link java.lang.String} object.
307
	 * @param message
308
	 *            a {@link java.lang.String} object.
309
	 */
310
	public static void informationDialog(final String title,
311
			final String message) {
312
		Display.getDefault().asyncExec(new Runnable() {
313

    
314
			@Override
315
            public void run() {
316
				MessageDialog.openInformation(getShell(), title, message);
317
			}
318
		});
319
	}
320

    
321
	public static void informationDialog(final String title,
322
			final IStatus status) {
323
		informationDialog(title, status.getMessage());
324
	}
325

    
326
	/**
327
	 * <p>
328
	 * warningDialog
329
	 * </p>
330
	 *
331
	 * @param title
332
	 *            The dialogs title
333
	 * @param source
334
	 *            The object where the warning was generated (used by log4j)
335
	 * @param message
336
	 *            An informative String to be presented to the user
337
	 */
338
	public static void warningDialog(final String title, final Object source,
339
			final String message) {
340
		Display.getDefault().asyncExec(new Runnable() {
341

    
342
			@Override
343
            public void run() {
344
				MessageDialog.openWarning(getShell(), title, message);
345
				Class<? extends Object> clazz = source != null ? source
346
						.getClass() : AbstractUtility.class;
347
				warn(clazz, message);
348
			}
349
		});
350
	}
351

    
352
	/**
353
	 * @param title
354
	 * @param termBase
355
	 * @param status
356
	 */
357
	public static void warningDialog(String title, Object source,
358
			IStatus status) {
359
		warningDialog(title, source, status.getMessage());
360
	}
361

    
362
	/**
363
	 * <p>
364
	 * errorDialog
365
	 * </p>
366
	 *
367
	 * @param title
368
	 *            The dialogs title
369
	 * @param source
370
	 *            The object where the warning was generated (used by log4j)
371
	 * @param message
372
	 *            An informative String to be presented to the user
373
	 * @param title
374
	 *            The dialogs title
375
	 * @param t
376
	 *            a Throwable if one exists or null
377
	 */
378
	public static void errorDialog(final String title, final Object source,
379
			final String message, final Throwable t) {
380
		Display.getDefault().asyncExec(new Runnable() {
381

    
382
			@Override
383
            public void run() {
384
				MessageDialog.openError(getShell(), title, message + getCauseRecursively(t));
385
				Class<? extends Object> clazz = source != null ? source
386
						.getClass() : this.getClass();
387
				error(clazz, message, t);
388
			}
389

    
390
			private String getCauseRecursively(Throwable t) {
391
				if(t == null){
392
					return null;
393
				}
394

    
395
				if(t.getCause() != null){
396
					return getCauseRecursively(t.getCause());
397
				}else{
398
					return String.format("\n\nException: %s\nMessage: %s", t.getClass().getSimpleName(), t.getMessage());
399
				}
400

    
401
			}
402
		});
403
	}
404

    
405
	public static void errorDialog(final String title, final Object source,
406
			final String message){
407
		errorDialog(title, source, message, null);
408
	}
409

    
410
	/**
411
	 * <p>
412
	 * errorDialog
413
	 * </p>
414
	 *
415
	 * @param title
416
	 *            a {@link java.lang.String} object.
417
	 * @param source
418
	 *            a {@link java.lang.Object} object.
419
	 * @param status
420
	 *            a {@link org.eclipse.core.runtime.IStatus} object.
421
	 */
422
	public static void errorDialog(final String title, final Object source,
423
			final IStatus status) {
424
		Display.getDefault().asyncExec(new Runnable() {
425

    
426
			@Override
427
            public void run() {
428
				MessageDialog.openError(getShell(), title, status.getMessage());
429
				Class<? extends Object> clazz = source != null ? source
430
						.getClass() : this.getClass();
431
				error(clazz, status.getMessage(), status.getException());
432
			}
433
		});
434
	}
435

    
436
	/**
437
	 * <p>
438
	 * confirmDialog
439
	 * </p>
440
	 *
441
	 * @param title
442
	 *            a {@link java.lang.String} object.
443
	 * @param message
444
	 *            a {@link java.lang.String} object.
445
	 * @return a boolean.
446
	 */
447
	public static boolean confirmDialog(String title, String message) {
448
		return MessageDialog.openQuestion(getShell(), title, message);
449
	}
450

    
451
	/**
452
	 * <p>
453
	 * executeOperation
454
	 * </p>
455
	 *
456
	 * @param operation
457
	 *            a
458
	 *            {@link eu.etaxonomy.taxeditor.operation.AbstractPostOperation}
459
	 *            object.
460
	 * @return a {@link org.eclipse.core.runtime.IStatus} object.
461
	 */
462
	public static IStatus executeOperation(final AbstractPostOperation operation) {
463
		if (getOperationHistory() == null) {
464
			throw new IllegalArgumentException(
465
					"There is no operation history for this context");
466
		}
467

    
468
		final IAdaptable uiInfoAdapter = WorkspaceUndoUtil
469
				.getUIInfoAdapter(getShell());
470

    
471
		IRunnableWithProgress runnable = new IRunnableWithProgress() {
472

    
473
			@Override
474
            public void run(IProgressMonitor monitor)
475
					throws InvocationTargetException, InterruptedException {
476
				monitor.beginTask(operation.getLabel(), 100);
477
				IStatus status = Status.CANCEL_STATUS;
478
				try {
479
					operation.addContext(IOperationHistory.GLOBAL_UNDO_CONTEXT);
480
					status = getOperationHistory().execute(operation, monitor,
481
							uiInfoAdapter);
482
				} catch (ExecutionException e) {
483
					errorDialog("Error executing operation", getClass(), String.format("An error occured while executing %s.", operation.getLabel()), e);
484
				} finally {
485
					monitor.done();
486
				}
487

    
488
				String statusString = status.equals(Status.OK_STATUS) ? "completed"
489
						: "cancelled";
490
				setStatusLine(operation.getLabel() + " " + statusString + ".");
491

    
492
			}
493
		};
494

    
495
		try {
496
			runInUI(runnable, null);
497
		} catch (Exception e) {
498
			errorDialog("Error executing operation", AbstractUtility.class, "An error occured while executing " + operation.getLabel(), e);
499
		}
500

    
501
		// // Start the main progress monitor.
502
		// IProgressMonitor newMonitor =
503
		// startMainMonitor(getMonitor(),operation.getLabel(), 100);
504
		//
505
		// // Check whether operation was canceled and do some steps.
506
		// workedChecked(newMonitor, 10);
507
		//
508
		// try {
509
		// IStatus status = getOperationHistory().execute(operation, newMonitor,
510
		// WorkspaceUndoUtil.getUIInfoAdapter(getShell()));
511
		//
512
		// // Check whether operation was canceled and do some steps.
513
		// workedChecked(newMonitor, 30);
514
		//
515
		// String statusString = status.equals(Status.OK_STATUS) ? "completed" :
516
		// "cancelled";
517
		// setStatusLine(operation.getLabel() + " " + statusString + ".");
518
		//
519
		// return status;
520
		// } catch (ExecutionException e) {
521
		// logger.error("Error executing operation: " + operation.getLabel(),
522
		// e);
523
		// errorDialog("Error executing operation: " + operation.getLabel(),
524
		// "Please refer to the error log.");
525
		// }
526
		// finally {
527
		//
528
		// // Stop the progress monitor.
529
		// newMonitor.done();
530
		// }
531

    
532
		IPostOperationEnabled postOperationEnabled = operation
533
				.getPostOperationEnabled();
534
		if (postOperationEnabled != null) {
535
			postOperationEnabled.onComplete();
536
		}
537
		return Status.OK_STATUS;
538
	}
539

    
540
	/**
541
	 * <p>
542
	 * getOperationHistory
543
	 * </p>
544
	 *
545
	 * @return a {@link org.eclipse.core.commands.operations.IOperationHistory}
546
	 *         object.
547
	 */
548
	public static IOperationHistory getOperationHistory() {
549
		return getWorkbench().getOperationSupport().getOperationHistory();
550
	}
551

    
552
	/**
553
	 * <p>
554
	 * setStatusLine
555
	 * </p>
556
	 *
557
	 * @param message
558
	 *            a {@link java.lang.String} object.
559
	 */
560
	public static void setStatusLine(final String message) {
561
		Display.getDefault().asyncExec(new Runnable() {
562

    
563
			@Override
564
            public void run() {
565
				statusLineManager.setMessage(message);
566
			}
567

    
568
		});
569

    
570
	}
571

    
572
	/**
573
	 * <p>
574
	 * getMonitor
575
	 * </p>
576
	 *
577
	 * @return a {@link org.eclipse.core.runtime.IProgressMonitor} object.
578
	 */
579
	public static IProgressMonitor getMonitor() {
580
		statusLineManager.setCancelEnabled(false);
581
		return statusLineManager.getProgressMonitor();
582
	}
583

    
584
	/**
585
	 * Starts either the given {@link IProgressMonitor} if it's not
586
	 * <code>null</code> or a new {@link NullProgressMonitor}.
587
	 *
588
	 * @param progressMonitor
589
	 *            The {@link IProgressMonitor} or <code>null</code> if no
590
	 *            progress should be reported.
591
	 * @param taskName
592
	 *            The name of the main task.
593
	 * @param steps
594
	 *            The number of steps this task is subdivided into.
595
	 * @return The {@link IProgressMonitor}.
596
	 */
597
	public static IProgressMonitor startMainMonitor(
598
			IProgressMonitor progressMonitor, String taskName, int steps) {
599
		IProgressMonitor newMonitor = progressMonitor;
600
		if (newMonitor == null) {
601
			newMonitor = new NullProgressMonitor();
602
		}
603
		newMonitor.beginTask(taskName == null ? "" : taskName, steps);
604
		newMonitor.subTask(" ");
605
		return newMonitor;
606
	}
607

    
608
	/**
609
	 * Creates a {@link SubProgressMonitor} if the given
610
	 * {@link IProgressMonitor} is not <code>null</code> and not a
611
	 * {@link NullProgressMonitor}.
612
	 *
613
	 * @param progressMonitor
614
	 *            The parent {@link IProgressMonitor} of the
615
	 *            {@link SubProgressMonitor} to be created.
616
	 * @param ticks
617
	 *            The number of steps this subtask is subdivided into. Must be a
618
	 *            positive number and must not be
619
	 *            {@link IProgressMonitor#UNKNOWN}.
620
	 * @return The {@link IProgressMonitor}.
621
	 */
622
	public static IProgressMonitor getSubProgressMonitor(
623
			IProgressMonitor progressMonitor, int ticks) {
624
		if (progressMonitor == null) {
625
			return new NullProgressMonitor();
626
		}
627
		if (progressMonitor instanceof NullProgressMonitor) {
628
			return progressMonitor;
629
		}
630

    
631
		return new SubProgressMonitor(progressMonitor, ticks);
632
	}
633

    
634
	/**
635
	 * Checks whether the user canceled this operation. If not canceled, the
636
	 * given number of steps are declared as done.
637
	 *
638
	 * @param newMonitor
639
	 *            a {@link org.eclipse.core.runtime.IProgressMonitor} object.
640
	 * @param steps
641
	 *            a int.
642
	 */
643
	public static void workedChecked(IProgressMonitor newMonitor, int steps) {
644
		// In case the progress monitor was canceled throw an exception.
645
		if (newMonitor.isCanceled()) {
646
			throw new OperationCanceledException();
647
		}
648
		// Otherwise declare this step as done.
649
		newMonitor.worked(steps);
650
	}
651

    
652
	/**
653
	 * Present a progress dialog to the user. This dialog will block the UI
654
	 *
655
	 * @param runnable
656
	 *            an implementation of {@link IRunnableWithProgress}
657
	 * @throws java.lang.InterruptedException
658
	 *             if any.
659
	 * @throws java.lang.reflect.InvocationTargetException
660
	 *             if any.
661
	 */
662
	public static void busyCursorWhile(IRunnableWithProgress runnable)
663
			throws InvocationTargetException, InterruptedException {
664
		getProgressService().busyCursorWhile(runnable);
665
	}
666

    
667
	/**
668
	 * <p>
669
	 * runInUI
670
	 * </p>
671
	 *
672
	 * @see {@link IProgressService#runInUI(org.eclipse.jface.operation.IRunnableContext, IRunnableWithProgress, ISchedulingRule)}
673
	 * @param runnable
674
	 *            a {@link org.eclipse.jface.operation.IRunnableWithProgress}
675
	 *            object.
676
	 * @param rule
677
	 *            a {@link org.eclipse.core.runtime.jobs.ISchedulingRule}
678
	 *            object.
679
	 * @throws java.lang.reflect.InvocationTargetException
680
	 *             if any.
681
	 * @throws java.lang.InterruptedException
682
	 *             if any.
683
	 */
684
	public static void runInUI(IRunnableWithProgress runnable,
685
			ISchedulingRule rule) throws InvocationTargetException,
686
			InterruptedException {
687
		getProgressService().runInUI(getWorkbenchWindow(), runnable, rule);
688
	}
689

    
690
	/**
691
	 * <p>
692
	 * run
693
	 * </p>
694
	 *
695
	 * @param fork
696
	 *            a boolean.
697
	 * @param cancelable
698
	 *            a boolean.
699
	 * @param runnable
700
	 *            a {@link org.eclipse.jface.operation.IRunnableWithProgress}
701
	 *            object.
702
	 * @throws java.lang.reflect.InvocationTargetException
703
	 *             if any.
704
	 * @throws java.lang.InterruptedException
705
	 *             if any.
706
	 */
707
	public static void run(boolean fork, boolean cancelable,
708
			IRunnableWithProgress runnable) throws InvocationTargetException,
709
			InterruptedException {
710
		getProgressService().run(fork, cancelable, runnable);
711
	}
712

    
713
	/**
714
	 * <p>
715
	 * getProgressService
716
	 * </p>
717
	 *
718
	 * @return a {@link org.eclipse.ui.progress.IProgressService} object.
719
	 */
720
	public static IProgressService getProgressService() {
721
		IWorkbench workbench = PlatformUI.getWorkbench();
722
		return workbench.getProgressService();
723
	}
724

    
725
	/**
726
	 * <p>
727
	 * getProgressService2
728
	 * </p>
729
	 *
730
	 * @return a {@link org.eclipse.ui.progress.IWorkbenchSiteProgressService}
731
	 *         object.
732
	 */
733
	public static IWorkbenchSiteProgressService getProgressService2() {
734
		return (IWorkbenchSiteProgressService) getService(IWorkbenchSiteProgressService.class);
735
	}
736

    
737
	/**
738
	 * <p>
739
	 * info
740
	 * </p>
741
	 *
742
	 * @param message
743
	 *            a {@link java.lang.String} object.
744
	 */
745
	public static void info(String message) {
746
		IStatus status = new Status(IStatus.INFO, getPluginId(), message);
747
		info(status);
748
	}
749

    
750
	/**
751
	 * <p>
752
	 * info
753
	 * </p>
754
	 *
755
	 * @param status
756
	 *            a {@link org.eclipse.core.runtime.IStatus} object.
757
	 */
758
	public static void info(IStatus status) {
759
		log(status);
760
	}
761

    
762
	/**
763
	 * <p>
764
	 * warn
765
	 * </p>
766
	 *
767
	 * @param source
768
	 *            a {@link java.lang.Class} object.
769
	 * @param message
770
	 *            a {@link java.lang.String} object.
771
	 */
772
	public static void warn(Class source, String message) {
773
		IStatus status = new Status(IStatus.WARNING, getPluginId(), message);
774
		getLog4JLogger(source).warn(message);
775
		log(status);
776
	}
777

    
778
	public static void warn(Class source, IStatus status) {
779
		getLog4JLogger(source).warn(status.getMessage(), status.getException());
780
		log(status);
781
	}
782

    
783
	public static void warn(Class source, Throwable t) {
784
		IStatus status = new Status(IStatus.WARNING, getPluginId(), t.getMessage(), t);
785
		getLog4JLogger(source).warn(t);
786
		log(status);
787
	}
788

    
789
	/**
790
	 * <p>
791
	 * error
792
	 * </p>
793
	 *
794
	 * @param source
795
	 *            a {@link java.lang.Class} object.
796
	 * @param t
797
	 *            a {@link java.lang.Throwable} object.
798
	 */
799
	public static void error(Class source, Throwable t) {
800
		error(source.getClass(), t.getMessage(), t);
801
	}
802

    
803
	/**
804
	 * <p>
805
	 * error
806
	 * </p>
807
	 *
808
	 * @param source
809
	 *            a {@link java.lang.Class} object.
810
	 * @param message
811
	 *            a {@link java.lang.String} object.
812
	 * @param t
813
	 *            a {@link java.lang.Throwable} object.
814
	 */
815
	public static void error(Class source, String message, Throwable t) {
816
		IStatus status = new Status(IStatus.ERROR, getPluginId(), message, t);
817
		error(source, status);
818
	}
819

    
820
	/**
821
	 * <p>
822
	 * error
823
	 * </p>
824
	 *
825
	 * @param source
826
	 *            a {@link java.lang.Class} object.
827
	 * @param status
828
	 *            a {@link org.eclipse.core.runtime.IStatus} object.
829
	 */
830
	public static void error(Class source, IStatus status) {
831
		getLog4JLogger(source)
832
				.error(status.getMessage(), status.getException());
833
		log(status);
834
	}
835

    
836
	/**
837
	 * <p>
838
	 * getLog4JLogger
839
	 * </p>
840
	 *
841
	 * @param clazz
842
	 *            a {@link java.lang.Class} object.
843
	 * @return a {@link org.apache.log4j.Logger} object.
844
	 */
845
	public static Logger getLog4JLogger(Class clazz) {
846
		return Logger.getLogger(clazz);
847
	}
848

    
849
	/**
850
	 * @see {@link ILog#log(IStatus)}
851
	 *
852
	 * @param status
853
	 */
854
	private static void log(IStatus status) {
855
		TaxeditorStorePlugin.getDefault().getLog().log(status);
856
	}
857

    
858
	/**
859
	 * <p>
860
	 * getPluginId
861
	 * </p>
862
	 *
863
	 * @return a {@link java.lang.String} object.
864
	 */
865
	public static String getPluginId() {
866
		return "eu.taxeditor";
867
	}
868

    
869
	/**
870
	 * <p>
871
	 * getActiveEditor
872
	 * </p>
873
	 *
874
	 * @return a {@link org.eclipse.ui.IEditorPart} object.
875
	 */
876
	public static IEditorPart getActiveEditor() {
877
		return getActivePage() != null ? getActivePage().getActiveEditor()
878
				: null;
879
	}
880

    
881
	/**
882
	 * <p>
883
	 * getDetailsView
884
	 * </p>
885
	 *
886
	 * @return a {@link eu.etaxonomy.taxeditor.view.detail.DetailsViewPart}
887
	 *         object.
888
	 */
889
	public static DetailsViewPart getDetailsView() {
890
		return (DetailsViewPart) getView(DetailsViewPart.ID, false);
891
	}
892

    
893
	/**
894
	 * <p>
895
	 * refreshDetailsViewer
896
	 * </p>
897
	 */
898
	public static void refreshDetailsViewer() {
899
		if (getDetailsView() != null) {
900
			((AbstractCdmDataViewer) getDetailsView().getViewer()).refresh();
901
		}
902
	}
903

    
904
	/**
905
	 * <p>
906
	 * reflowDetailsViewer
907
	 * </p>
908
	 */
909
	public static void reflowDetailsViewer() {
910
		if (getDetailsView() != null) {
911
			((AbstractCdmDataViewer) getDetailsView().getViewer()).reflow();
912
		}
913
	}
914

    
915
	public static SupplementalDataViewPart getSupplementalDataView() {
916
		return (SupplementalDataViewPart) getView(SupplementalDataViewPart.ID,
917
				false);
918
	}
919

    
920
	public static void reflowSupplementalViewer() {
921
		if (getSupplementalDataView() != null) {
922
			((AbstractCdmDataViewer) getSupplementalDataView().getViewer())
923
					.reflow();
924
		}
925
	}
926

    
927

    
928
    /**
929
     * Orders a Collection of {@link IEnumTerm}s according to the term
930
     * hierarchy. The hierarchy will be reduced to two layers: one layer being
931
     * the root elements (that have no parents) and the other being their
932
     * children and children's children recursively.<br>
933
     * The returned map will be be ordered primarily by root elements and
934
     * secondarily by the child elements, both ascending alphabetically. <br>
935
     * <br>
936
     * The reduced hierarchy could look like this:<br>
937
     * <ul>
938
     * <li>Root1
939
     *  <ul>
940
     *   <li>child1
941
     *   <li>child2
942
     *   <li>childOfChild2
943
     *  </ul>
944
     * <li>root2
945
     * <ul><li>child4</ul>
946
     * </ul>
947
     *
948
     * @param terms
949
     *            A {@link Collection} of {@link IEnumTerm}s for which the term
950
     *            hierarchy should be created
951
     * @return a map which holds the terms as keys and their string
952
     *         representation via {@link IEnumTerm#getMessage()} as values
953
     */
954
    public static <T extends IEnumTerm<?>> Map<T, String> orderTerms(Collection<T> terms) {
955
        Comparator<T> comparator = new Comparator<T>() {
956
            @Override
957
            public int compare(T t1, T t2) {
958
                return t1.getMessage().compareTo(t2.getMessage());
959
            }
960
        };
961
        Map<T, String> result = new LinkedHashMap<T, String>();
962
        Map<T, Set<T>> termHierarchy = new TreeMap<T, Set<T>>(comparator);
963

    
964
        for(T term : terms) {
965
            Set<T> childList = new TreeSet<T>(comparator);
966
            // add root element as keys
967
            if(term.getKindOf()==null){
968
                termHierarchy.put(term, childList);
969
            }
970
            // add child element to topmost parent i.e. root
971
            else{
972
                T root = getRootFor(term);
973
                if(termHierarchy.containsKey(root)){
974
                    termHierarchy.get(root).add(term);
975
                }
976
                else{
977
                    childList.add(term);
978
                    termHierarchy.put(root, childList);
979
                }
980
            }
981
        }
982

    
983
        // create list according to the type hierarchy (root elements alphabetically with recursive children also alphabetically)
984
        for(Entry<T, Set<T>> entry:termHierarchy.entrySet()){
985
            T root = entry.getKey();
986
            result.put(root, root.getMessage());
987
            for(T child:entry.getValue()){
988
                result.put(child, "  " + child.getMessage());
989
            }
990
        }
991
        return result;
992
    }
993

    
994
    @SuppressWarnings("unchecked")
995
    /**
996
     * Recursively iterates over all term parents until no more parent is found i.e. the root node
997
     * @param term The term for which the parent should be found
998
     * @return the root terms of the term hierarchy
999
     */
1000
    private static<T extends IEnumTerm<?>> T getRootFor(T term){
1001
        // PP: cast should be safe. Why is Eclipse complaining??
1002
        T parent = (T) term.getKindOf();
1003
        if(parent==null){
1004
            return term;
1005
        }
1006
        else{
1007
            return getRootFor((T) term.getKindOf());
1008
        }
1009
    }
1010

    
1011
    
1012
//    /**
1013
//     * Orders a Collection of {@link IEnumTerm}s according to the term
1014
//     * hierarchy. The hierarchy will be reduced to two layers: one layer being
1015
//     * the root elements (that have no parents) and the other being their
1016
//     * children and children's children recursively.<br>
1017
//     * The returned map will be be ordered primarily by root elements and
1018
//     * secondarily by the child elements, both ascending alphabetically. <br>
1019
//     * <br>
1020
//     * The reduced hierarchy could look like this:<br>
1021
//     * <ul>
1022
//     * <li>Root1
1023
//     *  <ul>
1024
//     *   <li>child1
1025
//     *   <li>child2
1026
//     *   <li>childOfChild2
1027
//     *  </ul>
1028
//     * <li>root2
1029
//     * <ul><li>child4</ul>
1030
//     * </ul>
1031
//     *
1032
//     * @param terms
1033
//     *            A {@link Collection} of {@link IEnumTerm}s for which the term
1034
//     *            hierarchy should be created
1035
//     * @return a map which holds the terms as keys and their string
1036
//     *         representation via {@link IEnumTerm#getMessage()} as values
1037
//     */
1038
//    public static <T extends IEnumTerm<?>> LinkedHashMap<T, String> orderTerms(Collection<T> terms) {
1039
//        Comparator<TermNode<T>> comparator = new Comparator<TermNode<T>>() {
1040
//            @Override
1041
//            public int compare(TermNode<T> t1, TermNode<T> t2) {
1042
//                return t1.getTerm().getMessage().compareTo(t2.getTerm().getMessage());
1043
//            }
1044
//        };
1045
//        TreeSet<TermNode<T>> parentElements = new TreeSet<TermNode<T>>(comparator);
1046
//        for(T term : terms) {
1047
//            Set<T> childList = new TreeSet<T>(comparator);
1048
//            // add root element as keys
1049
//            if(term.getKindOf()==null){
1050
//                parentElements.add(new TermNode<T>(term));
1051
//            }
1052
//            // add child element to parent
1053
//            else{
1054
//                T parent = getParentFor(term);
1055
//                if(termHierarchy.containsKey(parent)){
1056
//                    termHierarchy.get(parent).add(term);
1057
//                }
1058
//                else{
1059
//                    childList.add(term);
1060
//                    termHierarchy.put(parent, childList);
1061
//                }
1062
//            }
1063
//        }
1064
//
1065
//        // create list according to the type hierarchy (root elements alphabetically with recursive children also alphabetically)
1066
//        LinkedHashMap<T, String> result = new LinkedHashMap<T, String>();
1067
//        for(Entry<T, Set<T>> entry:termHierarchy.entrySet()){
1068
//            T root = entry.getKey();
1069
//            result.put(root, root.getMessage());
1070
//            for(T child:entry.getValue()){
1071
//                result.put(child, "  " + child.getMessage());
1072
//            }
1073
//        }
1074
//        return result;
1075
//    }
1076
//
1077
//    private static addToParents(TreeSet<TermNode<T>> parents, Collection<T> terms){
1078
//        for(T term:terms){
1079
//
1080
//        }
1081
//    }
1082
//
1083
//    @SuppressWarnings("unchecked")
1084
//    /**
1085
//     * Recursively iterates over all term parents until no more parent is found i.e. the root node
1086
//     * @param term The term for which the parent should be found
1087
//     * @return the root terms of the term hierarchy
1088
//     */
1089
//    private static<T extends IEnumTerm<?>> T getParentFor(T term){
1090
//        // PP: cast should be safe. Why is Eclipse complaining??
1091
//        T parent = (T) term.getKindOf();
1092
//        if(parent==null){
1093
//            return term;
1094
//        }
1095
//        else{
1096
//            return getParentFor((T) term.getKindOf());
1097
//        }
1098
//    }
1099
//
1100
//    private class TermNode<T>{
1101
//        private final T term;
1102
//        private final TreeSet<TermNode<T>> children;
1103
//
1104
//        /**
1105
//         * @param term
1106
//         * @param children
1107
//         */
1108
//        public TermNode(T term) {
1109
//            super();
1110
//            this.term = term;
1111
//            this.children = new TreeSet<TermNode<T>>();
1112
//        }
1113
//
1114
//        public void addChild(TermNode<T> child){
1115
//            this.children.add(child);
1116
//        }
1117
//
1118
//        /**
1119
//         * @return the children
1120
//         */
1121
//        public TreeSet<TermNode<T>> getChildren() {
1122
//            return children;
1123
//        }
1124
//
1125
//        /**
1126
//         * @return the term
1127
//         */
1128
//        public T getTerm() {
1129
//            return term;
1130
//        }
1131
//    }
1132

    
1133
}
(2-2/32)