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