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