b40d349320f1c713889dd6af26036c69c3cadcd9
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / model / AbstractUtility.java
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 * Orders a Collection of {@link IEnumTerm}s according to the term
929 * hierarchy. The hierarchy will be reduced to two layers: one layer being
930 * the root elements (that have no parents) and the other being their
931 * children and children's children recursively.<br>
932 * The returned map will be be ordered primarily by root elements and
933 * secondarily by the child elements, both ascending alphabetically. <br>
934 * <br>
935 * The reduced hierarchy could look like this:<br>
936 * <ul>
937 * <li>Root1
938 * <ul>
939 * <li>child1
940 * <li>child2
941 * <li>childOfChild2
942 * </ul>
943 * <li>root2
944 * <ul><li>child4</ul>
945 * </ul>
946 *
947 * @param terms
948 * A {@link Collection} of {@link IEnumTerm}s for which the term
949 * hierarchy should be created
950 * @return a map which holds the terms as keys and their string
951 * representation via {@link IEnumTerm#getMessage()} as values
952 */
953 public static <T extends IEnumTerm<?>> Map<T, String> orderTerms(Collection<T> terms) {
954 Comparator<T> comparator = new Comparator<T>() {
955 @Override
956 public int compare(T t1, T t2) {
957 return t1.getMessage().compareTo(t2.getMessage());
958 }
959 };
960 Map<T, String> result = new LinkedHashMap<T, String>();
961 Map<T, Set<T>> termHierarchy = new TreeMap<T, Set<T>>(comparator);
962
963 for(T term : terms) {
964 Set<T> childList = new TreeSet<T>(comparator);
965 // add root element as keys
966 if(term.getKindOf()==null){
967 termHierarchy.put(term, childList);
968 }
969 // add child element to topmost parent i.e. root
970 else{
971 T root = getRootFor(term);
972 if(termHierarchy.containsKey(root)){
973 termHierarchy.get(root).add(term);
974 }
975 else{
976 childList.add(term);
977 termHierarchy.put(root, childList);
978 }
979 }
980 }
981
982 // create list according to the type hierarchy (root elements alphabetically with recursive children also alphabetically)
983 for(Entry<T, Set<T>> entry:termHierarchy.entrySet()){
984 T root = entry.getKey();
985 result.put(root, root.getMessage());
986 for(T child:entry.getValue()){
987 result.put(child, " " + child.getMessage());
988 }
989 }
990 return result;
991 }
992
993 @SuppressWarnings("unchecked")
994 /**
995 * Recursively iterates over all term parents until no more parent is found i.e. the root node
996 * @param term The term for which the parent should be found
997 * @return the root terms of the term hierarchy
998 */
999 private static<T extends IEnumTerm<?>> T getRootFor(T term){
1000 // PP: cast should be safe. Why is Eclipse complaining??
1001 T parent = (T) term.getKindOf();
1002 if(parent==null){
1003 return term;
1004 }
1005 else{
1006 return getRootFor((T) term.getKindOf());
1007 }
1008 }
1009
1010 }