Merge branch 'release/4.6.0'
[taxeditor.git] / eu.etaxonomy.taxeditor.navigation / src / main / java / eu / etaxonomy / taxeditor / navigation / NavigationUtil.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.navigation;
11
12 import java.util.HashMap;
13 import java.util.HashSet;
14 import java.util.Map;
15 import java.util.Set;
16 import java.util.UUID;
17
18 import org.eclipse.core.commands.Command;
19 import org.eclipse.core.commands.ParameterizedCommand;
20 import org.eclipse.core.commands.common.NotDefinedException;
21 import org.eclipse.core.commands.operations.IUndoContext;
22 import org.eclipse.core.commands.operations.UndoContext;
23 import org.eclipse.jface.viewers.StructuredSelection;
24 import org.eclipse.jface.wizard.WizardDialog;
25 import org.eclipse.swt.widgets.Display;
26 import org.eclipse.swt.widgets.Shell;
27 import org.eclipse.ui.IEditorPart;
28 import org.eclipse.ui.IEditorReference;
29 import org.eclipse.ui.IWorkbenchWindow;
30 import org.eclipse.ui.PartInitException;
31 import org.eclipse.ui.PlatformUI;
32 import org.eclipse.ui.commands.ICommandService;
33 import org.eclipse.ui.handlers.IHandlerService;
34 import org.eclipse.ui.navigator.CommonViewer;
35
36 import eu.etaxonomy.cdm.api.service.IClassificationService;
37 import eu.etaxonomy.cdm.api.service.INameService;
38 import eu.etaxonomy.cdm.api.service.ITaxonNodeService;
39 import eu.etaxonomy.cdm.api.service.ITaxonService;
40 import eu.etaxonomy.cdm.model.common.ICdmBase;
41 import eu.etaxonomy.cdm.model.description.PolytomousKey;
42 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
43 import eu.etaxonomy.cdm.model.taxon.Classification;
44 import eu.etaxonomy.cdm.model.taxon.Synonym;
45 import eu.etaxonomy.cdm.model.taxon.Taxon;
46 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
47 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
48 import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
49 import eu.etaxonomy.taxeditor.editor.EditorUtil;
50 import eu.etaxonomy.taxeditor.editor.TaxonEditorInput;
51 import eu.etaxonomy.taxeditor.editor.internal.TaxeditorEditorPlugin;
52 import eu.etaxonomy.taxeditor.model.AbstractUtility;
53 import eu.etaxonomy.taxeditor.model.MessagingUtils;
54 import eu.etaxonomy.taxeditor.navigation.internal.TaxeditorNavigationPlugin;
55 import eu.etaxonomy.taxeditor.navigation.l10n.Messages;
56 import eu.etaxonomy.taxeditor.navigation.navigator.TaxonNavigator;
57 import eu.etaxonomy.taxeditor.newWizard.NewClassificationWizard;
58 import eu.etaxonomy.taxeditor.store.CdmStore;
59 import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
60
61 /**
62 * <p>NavigationUtil class.</p>
63 *
64 * @author n.hoffmann
65 * @created 24.03.2009
66 * @version 1.0
67 */
68 public class NavigationUtil extends AbstractUtility{
69
70 private static final String NOT_IMPLEMENTED_YET = Messages.NavigationUtil_NOT_IMPLEMENTED;
71 private static final String ERROR_OPENING_THE_EDITOR = Messages.NavigationUtil_OPEN_ERROR;
72 private static IUndoContext defaultUndoContext;
73
74 /**
75 * <p>openEditor</p>
76 *
77 * @param selectedObject a {@link eu.etaxonomy.cdm.model.common.CdmBase} object.
78 */
79 public static void openEditor(UuidAndTitleCache uuidAndTitleCache){
80 Class type = uuidAndTitleCache.getType();
81 ICdmBase cdmBase = null;
82 if(type.equals(Classification.class)){
83 cdmBase = CdmStore.getService(IClassificationService.class).load(uuidAndTitleCache.getUuid());
84 }
85 else if(type.equals(TaxonNode.class)){
86 cdmBase = CdmStore.getService(ITaxonNodeService.class).load(uuidAndTitleCache.getUuid());
87 }
88 else if(TaxonBase.class.isAssignableFrom(type)){
89 cdmBase = CdmStore.getService(ITaxonService.class).load(uuidAndTitleCache.getUuid());
90 }
91 else if(type.equals(TaxonNameBase.class)){
92 cdmBase = CdmStore.getService(INameService.class).load(uuidAndTitleCache.getUuid());
93 }
94 else{
95 MessagingUtils.warningDialog(Messages.NavigationUtil_UNKNOWN_TYPE, NavigationUtil.class, Messages.NavigationUtil_UNKNOWN_TYPE_MESSAGE);
96 }
97 if(cdmBase!=null){
98 openEditor(cdmBase);
99 }
100 else{
101 MessagingUtils.warningDialog(Messages.NavigationUtil_NOT_FOUND, NavigationUtil.class, Messages.NavigationUtil_NOT_FOUND_MESSAGE);
102 }
103 }
104
105 public static void openEditor(ICdmBase selectedObject){
106 UUID entityUuid = selectedObject.getUuid();
107 try {
108 if(selectedObject instanceof Classification){
109 NewClassificationWizard classificationWizard = new NewClassificationWizard();
110 classificationWizard.init(null, null);
111 classificationWizard.setEntity((Classification) selectedObject);
112 WizardDialog dialog = new WizardDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), classificationWizard);
113 dialog.open();
114 }
115 else if(selectedObject instanceof TaxonNode){
116 EditorUtil.openTaxonNode(entityUuid);
117 }else if(selectedObject instanceof TaxonBase){
118 TaxonBase taxonBase = (TaxonBase)selectedObject;
119 if(taxonBase.isOrphaned()){
120 openInBulkEditor(taxonBase);
121 }
122 else{
123 EditorUtil.openTaxonBase(entityUuid);
124 }
125 }else if(selectedObject instanceof TaxonNameBase){
126 openInBulkEditor(selectedObject);
127 }else if(selectedObject instanceof PolytomousKey){
128 EditorUtil.openPolytomousKey(entityUuid);
129 }else{
130 MessagingUtils.warningDialog(Messages.NavigationUtil_UNSUPPORTED_TYPE, NavigationUtil.class, Messages.NavigationUtil_UNSUPPORTED_TYPE_MESSAGE + selectedObject);
131 }
132 } catch (PartInitException e) {
133 MessagingUtils.error(NavigationUtil.class, ERROR_OPENING_THE_EDITOR, e);
134 } catch (Exception e) {
135 MessagingUtils.errorDialog(Messages.NavigationUtil_CREATE_FAILED,
136 NavigationUtil.class,
137 e.getMessage(), TaxeditorStorePlugin.PLUGIN_ID,
138 e,
139 true);
140
141 }
142 }
143
144 private static void openInBulkEditor(ICdmBase selectedObject) {
145 ICommandService commandService = (ICommandService)PlatformUI.getWorkbench().getService(ICommandService.class);
146 IHandlerService handlerService = (IHandlerService)PlatformUI.getWorkbench().getService(IHandlerService.class);
147 String openInBulkEditorCommand = "eu.etaxonomy.taxeditor.bulkeditor.openBulkEditorForIdentifiableEntity"; //$NON-NLS-1$
148 Command command = commandService.getCommand(openInBulkEditorCommand);
149 if(command.isDefined()){
150 Map<String, UUID> params = new HashMap<String, UUID>();
151 params.put(openInBulkEditorCommand+".uuid", selectedObject.getUuid()); //$NON-NLS-1$
152 ParameterizedCommand parameterizedCommand = ParameterizedCommand.generateCommand(command, params);
153 try {
154 if(parameterizedCommand!=null){
155 handlerService.executeCommand(parameterizedCommand, null);
156 return;
157 }
158 else{
159 handlerService.executeCommand(command.getId(), null);
160 return;
161 }
162 } catch (NotDefinedException nde) {
163 throw new RuntimeException("Could not find open command: " + command.getId()); //$NON-NLS-1$
164 } catch (Exception exception) {
165 MessagingUtils.error(NavigationUtil.class, "An exception occured while trying to execute "+command.getId(), exception); //$NON-NLS-1$
166 }
167 }
168 }
169
170 /**
171 * <p>openEmpty</p>
172 *
173 * @param parentNodeUuid a {@link java.util.UUID} object.
174 */
175 public static void openEmpty(UUID parentNodeUuid) {
176 try {
177 EditorUtil.openEmpty(parentNodeUuid);
178 } catch (PartInitException e) {
179 MessagingUtils.error(NavigationUtil.class, ERROR_OPENING_THE_EDITOR, e);
180 }
181 }
182
183 /**
184 * <p>getShell</p>
185 *
186 * @return a {@link org.eclipse.swt.widgets.Shell} object.
187 */
188 public static Shell getShell() {
189 return getActiveWindow().getShell();
190 }
191
192 /**
193 * <p>getActiveWindow</p>
194 *
195 * @return a {@link org.eclipse.ui.IWorkbenchWindow} object.
196 */
197 public static IWorkbenchWindow getActiveWindow() {
198 return TaxeditorNavigationPlugin.getDefault().getWorkbench().
199 getActiveWorkbenchWindow();
200 }
201
202 /**
203 * <p>getWorkbenchUndoContext</p>
204 *
205 * @return a {@link org.eclipse.core.commands.operations.IUndoContext} object.
206 */
207 public static IUndoContext getWorkbenchUndoContext() {
208 return TaxeditorEditorPlugin.getDefault().getWorkbench().
209 getOperationSupport().getUndoContext();
210 }
211
212 /**
213 * <p>getUndoContext</p>
214 *
215 * @return a {@link org.eclipse.core.commands.operations.IUndoContext} object.
216 */
217 public static IUndoContext getUndoContext() {
218 // FIXME this has to be more specific. Every widget has to have its own undo context
219 // return IOperationHistory.GLOBAL_UNDO_CONTEXT;
220
221 // Plug-ins that wish their operations to be undoable from workbench views
222 // such as the Navigator or Package Explorer should assign the workbench
223 // undo context to their operations.
224 if (defaultUndoContext == null) {
225 defaultUndoContext = new UndoContext();
226 }
227 return defaultUndoContext;
228 }
229
230 /**
231 * Whether a taxonNode has unsaved changes.
232 *
233 * @param taxonNode a {@link eu.etaxonomy.cdm.model.taxon.TaxonNode} object.
234 * @return a boolean.
235 */
236 public static boolean isDirty(TaxonNode taxonNode){
237
238 for (IEditorReference reference : getActivePage().getEditorReferences()) {
239
240 try {
241 if (reference.getEditorInput() instanceof TaxonEditorInput) {
242 TaxonEditorInput editorInput = (TaxonEditorInput) reference.getEditorInput();
243 if(editorInput.getTaxonNode().equals(taxonNode) && reference.isDirty()){
244 return true;
245 }
246 }
247 } catch (PartInitException e) {
248 MessagingUtils.error(NavigationUtil.class, e.getMessage(), e);
249 throw new RuntimeException(e);
250 }
251
252 }
253 return false;
254 }
255
256 /**
257 * <p>selectInNavigator</p>
258 *
259 * @param element a {@link java.lang.Object} object.
260 * @param parentElement a {@link java.lang.Object} object.
261 */
262 public static void selectInNavigator(final Object element, final Object parentElement) {
263 Display.getDefault().asyncExec(new Runnable(){
264
265 @Override
266 public void run() {
267 TaxonNavigator navigator = showNavigator();
268
269 if (navigator != null) {
270 CommonViewer viewer = navigator.getCommonViewer();
271 if (viewer != null) {
272 if (parentElement != null) {
273 viewer.setExpandedState(parentElement, true);
274 }
275 viewer.setSelection(new StructuredSelection(element));
276 }
277 }
278 }
279
280 });
281 }
282
283 /**
284 * <p>openSearch</p>
285 *
286 * @param selection a {@link java.lang.Object} object.
287 */
288 public static void openSearch(Object selection) {
289 if(selection instanceof Taxon){
290 Taxon taxon = (Taxon) selection;
291
292 handleOpeningOfMultipleTaxonNodes(taxon.getTaxonNodes());
293
294 }else if(selection instanceof Synonym){
295 Synonym synonym = (Synonym) selection;
296
297 Set<Taxon> accTaxa = new HashSet<Taxon>();
298 if (synonym.getAcceptedTaxon() != null){
299 accTaxa.add(synonym.getAcceptedTaxon());
300 }
301 handleOpeningOfMultipleTaxa(accTaxa);
302
303 }else{
304 MessagingUtils.warningDialog(NOT_IMPLEMENTED_YET, NavigationUtil.class, Messages.NavigationUtil_ORPHAN_NAME_MESSAGE);
305 }
306
307 }
308
309 private static void handleOpeningOfMultipleTaxa(Set<Taxon> acceptedTaxa) {
310 if(acceptedTaxa.size() == 1){
311 openEditor(acceptedTaxa.iterator().next());
312 }else if(acceptedTaxa.size() > 1){
313 // FIXME implement a dialog that shows all possible taxa and let the user choose which he wants to open.
314 MessagingUtils.warningDialog(NOT_IMPLEMENTED_YET, NavigationUtil.class, Messages.NavigationUtil_MULTI_TREE);
315 }else if(acceptedTaxa.size() == 0){
316 // this is an undesired state
317 MessagingUtils.warningDialog(NOT_IMPLEMENTED_YET, NavigationUtil.class, Messages.NavigationUtil_ORPHAN_TAXON);
318 }
319 }
320
321 /**
322 * @param taxonNodes
323 */
324 private static void handleOpeningOfMultipleTaxonNodes(
325 Set<TaxonNode> taxonNodes) {
326
327 if(taxonNodes.size() == 1){
328 openEditor(taxonNodes.iterator().next());
329 }else if(taxonNodes.size() > 1){
330 // FIXME implement a dialog that shows all possible taxa and let the user choose which he wants to open.
331 MessagingUtils.warningDialog(NOT_IMPLEMENTED_YET, NavigationUtil.class, "The accepted taxon is in multiple taxonomic trees. We currently do not know which one you want to open. This case is not handled yet by the software.");
332 }else if(taxonNodes.size() == 0){
333 // this is an undesired state
334 MessagingUtils.warningDialog(Messages.NavigationUtil_INCORRECT_STATE, NavigationUtil.class, Messages.NavigationUtil_INCORRECT_STATE_MESSAGE);
335 }
336 }
337
338 /**
339 * <p>showNavigator</p>
340 *
341 * @return the TaxonNavigator instance if present
342 */
343 public static TaxonNavigator showNavigator() {
344 return (TaxonNavigator) showView(TaxonNavigator.ID);
345 }
346
347 /**
348 * <p>getNavigator</p>
349 *
350 * @param restore a boolean.
351 * @return a {@link eu.etaxonomy.taxeditor.navigation.navigator.TaxonNavigator} object.
352 */
353 public static TaxonNavigator getNavigator(boolean restore) {
354 return (TaxonNavigator) getView(TaxonNavigator.ID, restore);
355 }
356
357 /**
358 * <p>getOpenEditors</p>
359 *
360 * @return a {@link java.util.Set} object.
361 */
362 public static Set<IEditorPart> getOpenEditors() {
363 return EditorUtil.getOpenEditors();
364 }
365
366 /**
367 * <p>getPluginId</p>
368 *
369 * @return a {@link java.lang.String} object.
370 */
371 public static String getPluginId(){
372 return TaxeditorNavigationPlugin.PLUGIN_ID;
373 }
374
375 }