merge-update from trunk
[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.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.apache.log4j.Logger;
21 import org.eclipse.core.commands.ExecutionException;
22 import org.eclipse.core.commands.operations.IOperationHistory;
23 import org.eclipse.core.runtime.IAdaptable;
24 import org.eclipse.core.runtime.ILog;
25 import org.eclipse.core.runtime.IProgressMonitor;
26 import org.eclipse.core.runtime.IStatus;
27 import org.eclipse.core.runtime.NullProgressMonitor;
28 import org.eclipse.core.runtime.OperationCanceledException;
29 import org.eclipse.core.runtime.Status;
30 import org.eclipse.core.runtime.SubProgressMonitor;
31 import org.eclipse.core.runtime.jobs.ISchedulingRule;
32 import org.eclipse.jface.action.IStatusLineManager;
33 import org.eclipse.jface.dialogs.MessageDialog;
34 import org.eclipse.jface.operation.IRunnableWithProgress;
35 import org.eclipse.jface.resource.ColorRegistry;
36 import org.eclipse.jface.resource.FontRegistry;
37 import org.eclipse.jface.window.ApplicationWindow;
38 import org.eclipse.swt.graphics.Color;
39 import org.eclipse.swt.graphics.Font;
40 import org.eclipse.swt.widgets.Display;
41 import org.eclipse.swt.widgets.Shell;
42 import org.eclipse.ui.IEditorPart;
43 import org.eclipse.ui.IViewPart;
44 import org.eclipse.ui.IViewReference;
45 import org.eclipse.ui.IWorkbench;
46 import org.eclipse.ui.IWorkbenchPage;
47 import org.eclipse.ui.IWorkbenchPart;
48 import org.eclipse.ui.PartInitException;
49 import org.eclipse.ui.PlatformUI;
50 import org.eclipse.ui.ide.undo.WorkspaceUndoUtil;
51 import org.eclipse.ui.part.EditorPart;
52 import org.eclipse.ui.progress.IProgressService;
53 import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
54 import org.eclipse.ui.themes.ITheme;
55 import org.eclipse.ui.themes.IThemeManager;
56
57 import eu.etaxonomy.cdm.model.common.IEnumTerm;
58 import eu.etaxonomy.taxeditor.operation.AbstractPostOperation;
59 import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
60 import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
61 import eu.etaxonomy.taxeditor.view.AbstractCdmDataViewer;
62 import eu.etaxonomy.taxeditor.view.detail.DetailsViewPart;
63 import eu.etaxonomy.taxeditor.view.supplementaldata.SupplementalDataViewPart;
64
65 /**
66 * <p>
67 * Abstract AbstractUtility class.
68 * </p>
69 *
70 * @author n.hoffmann
71 * @created 11.05.2009
72 * @version 1.0
73 */
74 public abstract class AbstractUtility {
75
76 /** Constant <code>statusLineManager</code> */
77 protected static IStatusLineManager statusLineManager;
78
79 /**
80 * <p>
81 * closeAll
82 * </p>
83 *
84 * @return a boolean.
85 */
86 public static boolean closeAll() {
87 return getActivePage().closeAllEditors(true);
88 }
89
90 /**
91 * Close the given editor.
92 *
93 * @param editor
94 * The <tt>MultipageTaxonEditor</tt> to close.
95 * @return <tt>true</tt> on success
96 */
97 public static boolean close(EditorPart editor) {
98 return getActivePage().closeEditor(editor, true);
99 }
100
101 /**
102 * <p>
103 * getShell
104 * </p>
105 *
106 * @return a {@link org.eclipse.swt.widgets.Shell} object.
107 */
108 public static Shell getShell() {
109
110 return TaxeditorStorePlugin.getDefault().getWorkbench()
111 .getActiveWorkbenchWindow().getShell();
112 }
113
114 /**
115 * <p>
116 * getActivePage
117 * </p>
118 *
119 * @return a {@link org.eclipse.ui.IWorkbenchPage} object.
120 */
121 public static IWorkbenchPage getActivePage() {
122
123 return TaxeditorStorePlugin.getDefault().getWorkbench()
124 .getActiveWorkbenchWindow().getActivePage();
125 }
126
127 /**
128 * <p>
129 * getActivePart
130 * </p>
131 *
132 * @return a {@link org.eclipse.ui.IWorkbenchPart} object.
133 */
134 public static IWorkbenchPart getActivePart() {
135 return getActivePage() != null ? getActivePage().getActivePart() : null;
136 }
137
138 public static IWorkbench getWorkbench() {
139 return TaxeditorStorePlugin.getDefault().getWorkbench();
140 }
141
142 /**
143 * <p>
144 * getWorkbenchWindow
145 * </p>
146 *
147 * @return a {@link org.eclipse.jface.window.ApplicationWindow} object.
148 */
149 public static ApplicationWindow getWorkbenchWindow() {
150 if (getWorkbench().getWorkbenchWindowCount() > 1) {
151 throw new IllegalStateException("More than one workbench window");
152 }
153 return (ApplicationWindow) getWorkbench().getWorkbenchWindows()[0];
154 }
155
156 /**
157 * <p>
158 * showView
159 * </p>
160 *
161 * @param id
162 * a {@link java.lang.String} object.
163 * @return a {@link org.eclipse.ui.IViewPart} object.
164 */
165 public static IViewPart showView(String id) {
166 try {
167 return PlatformUI.getWorkbench().getActiveWorkbenchWindow()
168 .getActivePage()
169 .showView(id, null, IWorkbenchPage.VIEW_VISIBLE);
170 } catch (PartInitException e) {
171 errorDialog("Error opening view", AbstractUtility.class, "Could not open view: " + id, e);
172 return null;
173 }
174 }
175
176 /**
177 * <p>
178 * hideView
179 * </p>
180 *
181 * @param view
182 * a {@link org.eclipse.ui.IViewPart} object.
183 */
184 public static void hideView(IViewPart view) {
185 PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
186 .hideView(view);
187 }
188
189 /**
190 * <p>
191 * getView
192 * </p>
193 *
194 * @param id
195 * a {@link java.lang.String} object.
196 * @param restore
197 * a boolean.
198 * @return a {@link org.eclipse.ui.IViewPart} object.
199 */
200 public static IViewPart getView(String id, boolean restore) {
201 IViewReference[] references = PlatformUI.getWorkbench()
202 .getActiveWorkbenchWindow().getActivePage().getViewReferences();
203 for (IViewReference reference : references) {
204 if (reference.getId().equals(id)) {
205 return reference.getView(restore);
206 }
207 }
208 return null;
209 }
210
211 /**
212 * <p>
213 * getService
214 * </p>
215 *
216 * @param api
217 * a {@link java.lang.Class} object.
218 * @return a {@link java.lang.Object} object.
219 */
220 public static Object getService(Class api) {
221 return TaxeditorStorePlugin.getDefault().getWorkbench().getService(api);
222 }
223
224 /**
225 * <p>
226 * getCurrentTheme
227 * </p>
228 *
229 * @return a {@link org.eclipse.ui.themes.ITheme} object.
230 */
231 public static ITheme getCurrentTheme() {
232 IThemeManager themeManager = TaxeditorStorePlugin.getDefault()
233 .getWorkbench().getThemeManager();
234 return themeManager.getCurrentTheme();
235 }
236
237 /**
238 * Fonts registered to the plugin may be obtained with the Eclipse themeing
239 * functionality. Thus fonts are chooseable by the user via
240 * Preferences->General->Appearance->Colors and Fonts
241 *
242 * @return the FontRegistry for the current theme
243 */
244 public static FontRegistry getFontRegistry() {
245 return getCurrentTheme().getFontRegistry();
246 }
247
248 /**
249 * <p>
250 * getFont
251 * </p>
252 *
253 * @param symbolicName
254 * a {@link java.lang.String} object.
255 * @return a {@link org.eclipse.swt.graphics.Font} object.
256 */
257 public static Font getFont(String symbolicName) {
258 return getFontRegistry().get(symbolicName);
259 }
260
261 /**
262 * Color registered to the plugin may be obtained with the Eclipse themeing
263 * functionality. Thus colors are editable by the user via
264 * Preferences->General->Appearance->Colors and Fonts
265 *
266 * @return the ColorRegistry for the current theme
267 */
268 public static ColorRegistry getColorRegistry() {
269 return getCurrentTheme().getColorRegistry();
270 }
271
272 /**
273 * <p>
274 * getColor
275 * </p>
276 *
277 * @param symbolicName
278 * a {@link java.lang.String} object.
279 * @return a {@link org.eclipse.swt.graphics.Color} object.
280 */
281 public static Color getColor(String symbolicName) {
282 return getColorRegistry().get(symbolicName);
283 }
284
285 /**
286 * Open a message box that informs the user about unimplemented
287 * functionality. This method is for developer convenience.
288 *
289 * @param source
290 * a {@link java.lang.Object} object.
291 */
292 public static void notImplementedMessage(Object source) {
293 warningDialog("Not yet implemented", source,
294 "This functionality is not yet implemented.");
295 }
296
297 /**
298 * <p>
299 * informationDialog
300 * </p>
301 *
302 * @param title
303 * a {@link java.lang.String} object.
304 * @param message
305 * a {@link java.lang.String} object.
306 */
307 public static void informationDialog(final String title,
308 final String message) {
309 Display.getDefault().asyncExec(new Runnable() {
310
311 @Override
312 public void run() {
313 MessageDialog.openInformation(getShell(), title, message);
314 }
315 });
316 }
317
318 public static void informationDialog(final String title,
319 final IStatus status) {
320 informationDialog(title, status.getMessage());
321 }
322
323 /**
324 * <p>
325 * warningDialog
326 * </p>
327 *
328 * @param title
329 * The dialogs title
330 * @param source
331 * The object where the warning was generated (used by log4j)
332 * @param message
333 * An informative String to be presented to the user
334 */
335 public static void warningDialog(final String title, final Object source,
336 final String message) {
337 Display.getDefault().asyncExec(new Runnable() {
338
339 @Override
340 public void run() {
341 MessageDialog.openWarning(getShell(), title, message);
342 Class<? extends Object> clazz = source != null ? source
343 .getClass() : AbstractUtility.class;
344 warn(clazz, message);
345 }
346 });
347 }
348
349 /**
350 * @param title
351 * @param termBase
352 * @param status
353 */
354 public static void warningDialog(String title, Object source,
355 IStatus status) {
356 warningDialog(title, source, status.getMessage());
357 }
358
359 /**
360 * <p>
361 * errorDialog
362 * </p>
363 *
364 * @param title
365 * The dialogs title
366 * @param source
367 * The object where the warning was generated (used by log4j)
368 * @param message
369 * An informative String to be presented to the user
370 * @param title
371 * The dialogs title
372 * @param t
373 * a Throwable if one exists or null
374 */
375 public static void errorDialog(final String title, final Object source,
376 final String message, final Throwable t) {
377 Display.getDefault().asyncExec(new Runnable() {
378
379 @Override
380 public void run() {
381 MessageDialog.openError(getShell(), title, message + getCauseRecursively(t));
382 Class<? extends Object> clazz = source != null ? source
383 .getClass() : this.getClass();
384 error(clazz, message, t);
385 }
386
387 private String getCauseRecursively(Throwable t) {
388 if(t == null){
389 return null;
390 }
391
392 if(t.getCause() != null){
393 return getCauseRecursively(t.getCause());
394 }else{
395 return String.format("\n\nException: %s\nMessage: %s", t.getClass().getSimpleName(), t.getMessage());
396 }
397
398 }
399 });
400 }
401
402 public static void errorDialog(final String title, final Object source,
403 final String message){
404 errorDialog(title, source, message, null);
405 }
406
407 /**
408 * <p>
409 * errorDialog
410 * </p>
411 *
412 * @param title
413 * a {@link java.lang.String} object.
414 * @param source
415 * a {@link java.lang.Object} object.
416 * @param status
417 * a {@link org.eclipse.core.runtime.IStatus} object.
418 */
419 public static void errorDialog(final String title, final Object source,
420 final IStatus status) {
421 Display.getDefault().asyncExec(new Runnable() {
422
423 @Override
424 public void run() {
425 MessageDialog.openError(getShell(), title, status.getMessage());
426 Class<? extends Object> clazz = source != null ? source
427 .getClass() : this.getClass();
428 error(clazz, status.getMessage(), status.getException());
429 }
430 });
431 }
432
433 /**
434 * <p>
435 * confirmDialog
436 * </p>
437 *
438 * @param title
439 * a {@link java.lang.String} object.
440 * @param message
441 * a {@link java.lang.String} object.
442 * @return a boolean.
443 */
444 public static boolean confirmDialog(String title, String message) {
445 return MessageDialog.openQuestion(getShell(), title, message);
446 }
447
448 /**
449 * <p>
450 * executeOperation
451 * </p>
452 *
453 * @param operation
454 * a
455 * {@link eu.etaxonomy.taxeditor.operation.AbstractPostTaxonOperation}
456 * object.
457 * @return a {@link org.eclipse.core.runtime.IStatus} object.
458 */
459 public static IStatus executeOperation(final AbstractPostOperation operation) {
460 if (getOperationHistory() == null) {
461 throw new IllegalArgumentException(
462 "There is no operation history for this context");
463 }
464
465 final IAdaptable uiInfoAdapter = WorkspaceUndoUtil
466 .getUIInfoAdapter(getShell());
467
468 IRunnableWithProgress runnable = new IRunnableWithProgress() {
469
470 @Override
471 public void run(IProgressMonitor monitor)
472 throws InvocationTargetException, InterruptedException {
473 monitor.beginTask(operation.getLabel(), 100);
474 IStatus status = Status.CANCEL_STATUS;
475 try {
476 operation.addContext(IOperationHistory.GLOBAL_UNDO_CONTEXT);
477 status = getOperationHistory().execute(operation, monitor,
478 uiInfoAdapter);
479 } catch (ExecutionException e) {
480 errorDialog("Error executing operation", getClass(), String.format("An error occured while executing %s.", operation.getLabel()), e);
481 } finally {
482 monitor.done();
483 }
484
485 String statusString = status.equals(Status.OK_STATUS) ? "completed"
486 : "cancelled";
487 setStatusLine(operation.getLabel() + " " + statusString + ".");
488
489 }
490 };
491
492 try {
493 runInUI(runnable, null);
494 } catch (Exception e) {
495 errorDialog("Error executing operation", AbstractUtility.class, "An error occured while executing " + operation.getLabel(), e);
496 }
497
498 // // Start the main progress monitor.
499 // IProgressMonitor newMonitor =
500 // startMainMonitor(getMonitor(),operation.getLabel(), 100);
501 //
502 // // Check whether operation was canceled and do some steps.
503 // workedChecked(newMonitor, 10);
504 //
505 // try {
506 // IStatus status = getOperationHistory().execute(operation, newMonitor,
507 // WorkspaceUndoUtil.getUIInfoAdapter(getShell()));
508 //
509 // // Check whether operation was canceled and do some steps.
510 // workedChecked(newMonitor, 30);
511 //
512 // String statusString = status.equals(Status.OK_STATUS) ? "completed" :
513 // "cancelled";
514 // setStatusLine(operation.getLabel() + " " + statusString + ".");
515 //
516 // return status;
517 // } catch (ExecutionException e) {
518 // logger.error("Error executing operation: " + operation.getLabel(),
519 // e);
520 // errorDialog("Error executing operation: " + operation.getLabel(),
521 // "Please refer to the error log.");
522 // }
523 // finally {
524 //
525 // // Stop the progress monitor.
526 // newMonitor.done();
527 // }
528
529 IPostOperationEnabled postOperationEnabled = operation
530 .getPostOperationEnabled();
531 if (postOperationEnabled != null) {
532 postOperationEnabled.onComplete();
533 }
534 return Status.OK_STATUS;
535 }
536
537 /**
538 * <p>
539 * getOperationHistory
540 * </p>
541 *
542 * @return a {@link org.eclipse.core.commands.operations.IOperationHistory}
543 * object.
544 */
545 public static IOperationHistory getOperationHistory() {
546 return getWorkbench().getOperationSupport().getOperationHistory();
547 }
548
549 /**
550 * <p>
551 * setStatusLine
552 * </p>
553 *
554 * @param message
555 * a {@link java.lang.String} object.
556 */
557 public static void setStatusLine(final String message) {
558 Display.getDefault().asyncExec(new Runnable() {
559
560 @Override
561 public void run() {
562 statusLineManager.setMessage(message);
563 }
564
565 });
566
567 }
568
569 /**
570 * <p>
571 * getMonitor
572 * </p>
573 *
574 * @return a {@link org.eclipse.core.runtime.IProgressMonitor} object.
575 */
576 public static IProgressMonitor getMonitor() {
577 statusLineManager.setCancelEnabled(false);
578 return statusLineManager.getProgressMonitor();
579 }
580
581 /**
582 * Starts either the given {@link IProgressMonitor} if it's not
583 * <code>null</code> or a new {@link NullProgressMonitor}.
584 *
585 * @param progressMonitor
586 * The {@link IProgressMonitor} or <code>null</code> if no
587 * progress should be reported.
588 * @param taskName
589 * The name of the main task.
590 * @param steps
591 * The number of steps this task is subdivided into.
592 * @return The {@link IProgressMonitor}.
593 */
594 public static IProgressMonitor startMainMonitor(
595 IProgressMonitor progressMonitor, String taskName, int steps) {
596 IProgressMonitor newMonitor = progressMonitor;
597 if (newMonitor == null) {
598 newMonitor = new NullProgressMonitor();
599 }
600 newMonitor.beginTask(taskName == null ? "" : taskName, steps);
601 newMonitor.subTask(" ");
602 return newMonitor;
603 }
604
605 /**
606 * Creates a {@link SubProgressMonitor} if the given
607 * {@link IProgressMonitor} is not <code>null</code> and not a
608 * {@link NullProgressMonitor}.
609 *
610 * @param progressMonitor
611 * The parent {@link IProgressMonitor} of the
612 * {@link SubProgressMonitor} to be created.
613 * @param ticks
614 * The number of steps this subtask is subdivided into. Must be a
615 * positive number and must not be
616 * {@link IProgressMonitor#UNKNOWN}.
617 * @return The {@link IProgressMonitor}.
618 */
619 public static IProgressMonitor getSubProgressMonitor(
620 IProgressMonitor progressMonitor, int ticks) {
621 if (progressMonitor == null) {
622 return new NullProgressMonitor();
623 }
624 if (progressMonitor instanceof NullProgressMonitor) {
625 return progressMonitor;
626 }
627
628 return new SubProgressMonitor(progressMonitor, ticks);
629 }
630
631 /**
632 * Checks whether the user canceled this operation. If not canceled, the
633 * given number of steps are declared as done.
634 *
635 * @param newMonitor
636 * a {@link org.eclipse.core.runtime.IProgressMonitor} object.
637 * @param steps
638 * a int.
639 */
640 public static void workedChecked(IProgressMonitor newMonitor, int steps) {
641 // In case the progress monitor was canceled throw an exception.
642 if (newMonitor.isCanceled()) {
643 throw new OperationCanceledException();
644 }
645 // Otherwise declare this step as done.
646 newMonitor.worked(steps);
647 }
648
649 /**
650 * Present a progress dialog to the user. This dialog will block the UI
651 *
652 * @param runnable
653 * an implementation of {@link IRunnableWithProgress}
654 * @throws java.lang.InterruptedException
655 * if any.
656 * @throws java.lang.reflect.InvocationTargetException
657 * if any.
658 */
659 public static void busyCursorWhile(IRunnableWithProgress runnable)
660 throws InvocationTargetException, InterruptedException {
661 getProgressService().busyCursorWhile(runnable);
662 }
663
664 /**
665 * <p>
666 * runInUI
667 * </p>
668 *
669 * @see {@link IProgressService#runInUI(org.eclipse.jface.operation.IRunnableContext, IRunnableWithProgress, ISchedulingRule)}
670 * @param runnable
671 * a {@link org.eclipse.jface.operation.IRunnableWithProgress}
672 * object.
673 * @param rule
674 * a {@link org.eclipse.core.runtime.jobs.ISchedulingRule}
675 * object.
676 * @throws java.lang.reflect.InvocationTargetException
677 * if any.
678 * @throws java.lang.InterruptedException
679 * if any.
680 */
681 public static void runInUI(IRunnableWithProgress runnable,
682 ISchedulingRule rule) throws InvocationTargetException,
683 InterruptedException {
684 getProgressService().runInUI(getWorkbenchWindow(), runnable, rule);
685 }
686
687 /**
688 * <p>
689 * run
690 * </p>
691 *
692 * @param fork
693 * a boolean.
694 * @param cancelable
695 * a boolean.
696 * @param runnable
697 * a {@link org.eclipse.jface.operation.IRunnableWithProgress}
698 * object.
699 * @throws java.lang.reflect.InvocationTargetException
700 * if any.
701 * @throws java.lang.InterruptedException
702 * if any.
703 */
704 public static void run(boolean fork, boolean cancelable,
705 IRunnableWithProgress runnable) throws InvocationTargetException,
706 InterruptedException {
707 getProgressService().run(fork, cancelable, runnable);
708 }
709
710 /**
711 * <p>
712 * getProgressService
713 * </p>
714 *
715 * @return a {@link org.eclipse.ui.progress.IProgressService} object.
716 */
717 public static IProgressService getProgressService() {
718 IWorkbench workbench = PlatformUI.getWorkbench();
719 return workbench.getProgressService();
720 }
721
722 /**
723 * <p>
724 * getProgressService2
725 * </p>
726 *
727 * @return a {@link org.eclipse.ui.progress.IWorkbenchSiteProgressService}
728 * object.
729 */
730 public static IWorkbenchSiteProgressService getProgressService2() {
731 return (IWorkbenchSiteProgressService) getService(IWorkbenchSiteProgressService.class);
732 }
733
734 /**
735 * <p>
736 * info
737 * </p>
738 *
739 * @param message
740 * a {@link java.lang.String} object.
741 */
742 public static void info(String message) {
743 IStatus status = new Status(IStatus.INFO, getPluginId(), message);
744 info(status);
745 }
746
747 /**
748 * <p>
749 * info
750 * </p>
751 *
752 * @param status
753 * a {@link org.eclipse.core.runtime.IStatus} object.
754 */
755 public static void info(IStatus status) {
756 log(status);
757 }
758
759 /**
760 * <p>
761 * warn
762 * </p>
763 *
764 * @param source
765 * a {@link java.lang.Class} object.
766 * @param message
767 * a {@link java.lang.String} object.
768 */
769 public static void warn(Class source, String message) {
770 IStatus status = new Status(IStatus.WARNING, getPluginId(), message);
771 getLog4JLogger(source).warn(message);
772 log(status);
773 }
774
775 public static void warn(Class source, IStatus status) {
776 getLog4JLogger(source).warn(status.getMessage(), status.getException());
777 log(status);
778 }
779
780 public static void warn(Class source, Throwable t) {
781 IStatus status = new Status(IStatus.WARNING, getPluginId(), t.getMessage(), t);
782 getLog4JLogger(source).warn(t);
783 log(status);
784 }
785
786 /**
787 * <p>
788 * error
789 * </p>
790 *
791 * @param source
792 * a {@link java.lang.Class} object.
793 * @param t
794 * a {@link java.lang.Throwable} object.
795 */
796 public static void error(Class source, Throwable t) {
797 error(source.getClass(), t.getMessage(), t);
798 }
799
800 /**
801 * <p>
802 * error
803 * </p>
804 *
805 * @param source
806 * a {@link java.lang.Class} object.
807 * @param message
808 * a {@link java.lang.String} object.
809 * @param t
810 * a {@link java.lang.Throwable} object.
811 */
812 public static void error(Class source, String message, Throwable t) {
813 IStatus status = new Status(IStatus.ERROR, getPluginId(), message, t);
814 error(source, status);
815 }
816
817 /**
818 * <p>
819 * error
820 * </p>
821 *
822 * @param source
823 * a {@link java.lang.Class} object.
824 * @param status
825 * a {@link org.eclipse.core.runtime.IStatus} object.
826 */
827 public static void error(Class source, IStatus status) {
828 getLog4JLogger(source)
829 .error(status.getMessage(), status.getException());
830 log(status);
831 }
832
833 /**
834 * <p>
835 * getLog4JLogger
836 * </p>
837 *
838 * @param clazz
839 * a {@link java.lang.Class} object.
840 * @return a {@link org.apache.log4j.Logger} object.
841 */
842 public static Logger getLog4JLogger(Class clazz) {
843 return Logger.getLogger(clazz);
844 }
845
846 /**
847 * @see {@link ILog#log(IStatus)}
848 *
849 * @param status
850 */
851 private static void log(IStatus status) {
852 TaxeditorStorePlugin.getDefault().getLog().log(status);
853 }
854
855 /**
856 * <p>
857 * getPluginId
858 * </p>
859 *
860 * @return a {@link java.lang.String} object.
861 */
862 public static String getPluginId() {
863 return "eu.taxeditor";
864 }
865
866 /**
867 * <p>
868 * getActiveEditor
869 * </p>
870 *
871 * @return a {@link org.eclipse.ui.IEditorPart} object.
872 */
873 public static IEditorPart getActiveEditor() {
874 return getActivePage() != null ? getActivePage().getActiveEditor()
875 : null;
876 }
877
878 /**
879 * <p>
880 * getDetailsView
881 * </p>
882 *
883 * @return a {@link eu.etaxonomy.taxeditor.view.detail.DetailsViewPart}
884 * object.
885 */
886 public static DetailsViewPart getDetailsView() {
887 return (DetailsViewPart) getView(DetailsViewPart.ID, false);
888 }
889
890 /**
891 * <p>
892 * refreshDetailsViewer
893 * </p>
894 */
895 public static void refreshDetailsViewer() {
896 if (getDetailsView() != null) {
897 ((AbstractCdmDataViewer) getDetailsView().getViewer()).refresh();
898 }
899 }
900
901 /**
902 * <p>
903 * reflowDetailsViewer
904 * </p>
905 */
906 public static void reflowDetailsViewer() {
907 if (getDetailsView() != null) {
908 ((AbstractCdmDataViewer) getDetailsView().getViewer()).reflow();
909 }
910 }
911
912 public static SupplementalDataViewPart getSupplementalDataView() {
913 return (SupplementalDataViewPart) getView(SupplementalDataViewPart.ID,
914 false);
915 }
916
917 public static void reflowSupplementalViewer() {
918 if (getSupplementalDataView() != null) {
919 ((AbstractCdmDataViewer) getSupplementalDataView().getViewer())
920 .reflow();
921 }
922 }
923
924
925 /**
926 * Orders a Collection of {@link IEnumTerm}s according to the term
927 * hierarchy. <br>
928 * <br>
929 * The returned map will be be ordered primarily by root elements,
930 * secondarily by the child elements and their children resp., both ascending alphabetically. <br>
931 * @param terms
932 * A {@link Collection} of {@link IEnumTerm}s for which the term
933 * hierarchy should be created
934 * @return a map which holds the terms as keys and their string
935 * representation via {@link IEnumTerm#getMessage()} as values
936 */
937 public static <T extends IEnumTerm<T>> LinkedHashMap<T, String> orderTerms(Collection<T> terms) {
938 TreeSet<TermNode<T>> parentElements = new TreeSet<TermNode<T>>();
939 parentElements.addAll(getTermHierarchy(terms));
940
941 // create list according to the type hierarchy (root elements alphabetically with recursive children also alphabetically)
942 LinkedHashMap<T, String> result = new LinkedHashMap<T, String>();
943 parseTermTree(parentElements, result, -1);
944 return result;
945 }
946
947 private static<T extends IEnumTerm<T>> void parseTermTree(Collection<TermNode<T>> children, LinkedHashMap<T, String> result, int depth){
948 depth++;
949 for(TermNode<T> node:children){
950 String indentString = "";
951 for(int i=0;i<depth;i++){
952 indentString += " ";
953 }
954 if(depth>0){
955 indentString += "- ";
956 }
957 result.put(node.term, indentString + node.term.getMessage());
958 parseTermTree(node.children, result, depth);
959 }
960 }
961
962 private static<T extends IEnumTerm<T>> void addToParents(List<TermNode<T>> parents, Collection<T> terms){
963 List<TermNode<T>> hasChildrenList = new ArrayList<TermNode<T>>();
964 for(T term:terms){
965 // only terms with parents
966 if(term.getKindOf()!=null){
967 TermNode<T> parentNode = new TermNode<T>(term.getKindOf());
968 TermNode<T> childNode = new TermNode<T>(term);
969 if(parents.contains(parentNode)){
970 // parent found in parent list -> add this term to parent's child list
971 parents.get(parents.indexOf(parentNode)).addChild(childNode);
972 if(!term.getGeneralizationOf().isEmpty()){
973 // has more children -> add to list which will be the parent for the next recursion
974 hasChildrenList.add(childNode);
975 }
976 }
977 }
978 }
979 if(!hasChildrenList.isEmpty()){
980 addToParents(hasChildrenList, terms);
981 }
982 }
983
984 private static<T extends IEnumTerm<T>> List<TermNode<T>> getTermHierarchy(Collection<T> terms){
985 List<TermNode<T>> parents = new ArrayList<TermNode<T>>();
986 // get root elements
987 for(T term:terms){
988 T parentTerm = term.getKindOf();
989 if(parentTerm==null){
990 // root element
991 parents.add(new TermNode<T>(term));
992 }
993 }
994 addToParents(parents, terms);
995 return parents;
996 }
997
998 @SuppressWarnings("unchecked")
999 /**
1000 * Recursively iterates over all term parents until no more parent is found i.e. the root node
1001 * @param term The term for which the parent should be found
1002 * @return the root terms of the term hierarchy
1003 */
1004 private static<T extends IEnumTerm<T>> T getParentFor(T term){
1005 // PP: cast should be safe. Why is Eclipse complaining??
1006 T parent = term.getKindOf();
1007 if(parent==null){
1008 return term;
1009 }
1010 else{
1011 return getParentFor(term.getKindOf());
1012 }
1013 }
1014
1015 private static class TermNode<T extends IEnumTerm<T>> implements Comparable<TermNode<T>>{
1016 private final T term;
1017 private final TreeSet<TermNode<T>> children;
1018
1019 /**
1020 * @param term
1021 * @param children
1022 */
1023 public TermNode(T term) {
1024 super();
1025 this.term = term;
1026 this.children = new TreeSet<TermNode<T>>();
1027 }
1028
1029 public void addChild(TermNode<T> child){
1030 this.children.add(child);
1031 }
1032
1033 /**
1034 * @return the children
1035 */
1036 public TreeSet<TermNode<T>> getChildren() {
1037 return children;
1038 }
1039
1040 /**
1041 * @return the term
1042 */
1043 public T getTerm() {
1044 return term;
1045 }
1046
1047 /* (non-Javadoc)
1048 * @see java.lang.Object#hashCode()
1049 */
1050 @Override
1051 public int hashCode() {
1052 final int prime = 31;
1053 int result = 1;
1054 result = prime * result + ((term == null) ? 0 : term.hashCode());
1055 return result;
1056 }
1057
1058 /* (non-Javadoc)
1059 * @see java.lang.Object#equals(java.lang.Object)
1060 */
1061 @Override
1062 public boolean equals(Object obj) {
1063 if (this == obj) {
1064 return true;
1065 }
1066 if (obj == null) {
1067 return false;
1068 }
1069 if (getClass() != obj.getClass()) {
1070 return false;
1071 }
1072 TermNode other = (TermNode) obj;
1073 if (term == null) {
1074 if (other.term != null) {
1075 return false;
1076 }
1077 } else if (!term.equals(other.term)) {
1078 return false;
1079 }
1080 return true;
1081 }
1082
1083 /* (non-Javadoc)
1084 * @see java.lang.Comparable#compareTo(java.lang.Object)
1085 */
1086 @Override
1087 public int compareTo(TermNode<T> that) {
1088 return this.term.getMessage().compareTo(that.term.getMessage());
1089 }
1090 }
1091
1092 }