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