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