Merge branch 'develop' into nameEditorE4
[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.TaxonName;
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(TaxonName.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 TaxonNode){
109 TaxonNode taxonNode = (TaxonNode)selectedObject;
110 Classification classification = taxonNode.getClassification();
111 if(classification!=null && classification.getRootNode().equals(taxonNode)){
112 NewClassificationWizard classificationWizard = new NewClassificationWizard();
113 classificationWizard.init(null, null);
114 classificationWizard.setEntity(classification);
115 WizardDialog dialog = new WizardDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), classificationWizard);
116 dialog.open();
117 }
118 else{
119 EditorUtil.openTaxonNodeE4(entityUuid);
120 }
121 }else if(selectedObject instanceof TaxonBase){
122 TaxonBase taxonBase = (TaxonBase)selectedObject;
123 if(taxonBase.isOrphaned()){
124 openInBulkEditor(taxonBase);
125 }
126 else{
127 EditorUtil.openTaxonBaseE4(entityUuid);
128 }
129 }else if(selectedObject instanceof TaxonName){
130 openInBulkEditor(selectedObject);
131 }else if(selectedObject instanceof PolytomousKey){
132 EditorUtil.openPolytomousKey(entityUuid);
133 }else{
134 MessagingUtils.warningDialog(Messages.NavigationUtil_UNSUPPORTED_TYPE, NavigationUtil.class, Messages.NavigationUtil_UNSUPPORTED_TYPE_MESSAGE + selectedObject);
135 }
136 } catch (PartInitException e) {
137 MessagingUtils.error(NavigationUtil.class, ERROR_OPENING_THE_EDITOR, e);
138 } catch (Exception e) {
139 MessagingUtils.errorDialog(Messages.NavigationUtil_CREATE_FAILED,
140 NavigationUtil.class,
141 e.getMessage(), TaxeditorStorePlugin.PLUGIN_ID,
142 e,
143 true);
144
145 }
146 }
147
148 private static void openInBulkEditor(ICdmBase selectedObject) {
149 ICommandService commandService = PlatformUI.getWorkbench().getService(ICommandService.class);
150 IHandlerService handlerService = PlatformUI.getWorkbench().getService(IHandlerService.class);
151 String openInBulkEditorCommand = "eu.etaxonomy.taxeditor.bulkeditor.openBulkEditorForIdentifiableEntity"; //$NON-NLS-1$
152 Command command = commandService.getCommand(openInBulkEditorCommand);
153 if(command.isDefined()){
154 Map<String, UUID> params = new HashMap<String, UUID>();
155 params.put(openInBulkEditorCommand+".uuid", selectedObject.getUuid()); //$NON-NLS-1$
156 ParameterizedCommand parameterizedCommand = ParameterizedCommand.generateCommand(command, params);
157 try {
158 if(parameterizedCommand!=null){
159 handlerService.executeCommand(parameterizedCommand, null);
160 return;
161 }
162 else{
163 handlerService.executeCommand(command.getId(), null);
164 return;
165 }
166 } catch (NotDefinedException nde) {
167 throw new RuntimeException("Could not find open command: " + command.getId()); //$NON-NLS-1$
168 } catch (Exception exception) {
169 MessagingUtils.error(NavigationUtil.class, "An exception occured while trying to execute "+command.getId(), exception); //$NON-NLS-1$
170 }
171 }
172 }
173
174 /**
175 * <p>openEmpty</p>
176 *
177 * @param parentNodeUuid a {@link java.util.UUID} object.
178 */
179 public static void openEmpty(UUID parentNodeUuid) {
180 try {
181 EditorUtil.openEmptyE4(parentNodeUuid);
182 } catch (PartInitException e) {
183 MessagingUtils.error(NavigationUtil.class, ERROR_OPENING_THE_EDITOR, e);
184 }
185 }
186
187 /**
188 * <p>getShell</p>
189 *
190 * @return a {@link org.eclipse.swt.widgets.Shell} object.
191 */
192 public static Shell getShell() {
193 return getActiveWindow().getShell();
194 }
195
196 /**
197 * <p>getActiveWindow</p>
198 *
199 * @return a {@link org.eclipse.ui.IWorkbenchWindow} object.
200 */
201 public static IWorkbenchWindow getActiveWindow() {
202 return TaxeditorNavigationPlugin.getDefault().getWorkbench().
203 getActiveWorkbenchWindow();
204 }
205
206 /**
207 * <p>getWorkbenchUndoContext</p>
208 *
209 * @return a {@link org.eclipse.core.commands.operations.IUndoContext} object.
210 */
211 public static IUndoContext getWorkbenchUndoContext() {
212 return TaxeditorEditorPlugin.getDefault().getWorkbench().
213 getOperationSupport().getUndoContext();
214 }
215
216 /**
217 * <p>getUndoContext</p>
218 *
219 * @return a {@link org.eclipse.core.commands.operations.IUndoContext} object.
220 */
221 public static IUndoContext getUndoContext() {
222 // FIXME this has to be more specific. Every widget has to have its own undo context
223 // return IOperationHistory.GLOBAL_UNDO_CONTEXT;
224
225 // Plug-ins that wish their operations to be undoable from workbench views
226 // such as the Navigator or Package Explorer should assign the workbench
227 // undo context to their operations.
228 if (defaultUndoContext == null) {
229 defaultUndoContext = new UndoContext();
230 }
231 return defaultUndoContext;
232 }
233
234 /**
235 * Whether a taxonNode has unsaved changes.
236 *
237 * @param taxonNode a {@link eu.etaxonomy.cdm.model.taxon.TaxonNode} object.
238 * @return a boolean.
239 */
240 public static boolean isDirty(TaxonNode taxonNode){
241
242 for (IEditorReference reference : getActivePage().getEditorReferences()) {
243
244 try {
245 if (reference.getEditorInput() instanceof TaxonEditorInput) {
246 TaxonEditorInput editorInput = (TaxonEditorInput) reference.getEditorInput();
247 if(editorInput.getTaxonNode().equals(taxonNode) && reference.isDirty()){
248 return true;
249 }
250 }
251 } catch (PartInitException e) {
252 MessagingUtils.error(NavigationUtil.class, e.getMessage(), e);
253 throw new RuntimeException(e);
254 }
255
256 }
257 return false;
258 }
259
260 /**
261 * <p>selectInNavigator</p>
262 *
263 * @param element a {@link java.lang.Object} object.
264 * @param parentElement a {@link java.lang.Object} object.
265 */
266 public static void selectInNavigator(final Object element, final Object parentElement) {
267 Display.getDefault().asyncExec(new Runnable(){
268
269 @Override
270 public void run() {
271 TaxonNavigator navigator = showNavigator();
272
273 if (navigator != null) {
274 CommonViewer viewer = navigator.getCommonViewer();
275 if (viewer != null) {
276 if (parentElement != null) {
277 viewer.setExpandedState(parentElement, true);
278 }
279 viewer.setSelection(new StructuredSelection(element));
280 }
281 }
282 }
283
284 });
285 }
286
287 /**
288 * <p>openSearch</p>
289 *
290 * @param selection a {@link java.lang.Object} object.
291 */
292 public static void openSearch(Object selection) {
293 if(selection instanceof Taxon){
294 Taxon taxon = (Taxon) selection;
295
296 handleOpeningOfMultipleTaxonNodes(taxon.getTaxonNodes());
297
298 }else if(selection instanceof Synonym){
299 Synonym synonym = (Synonym) selection;
300
301 Set<Taxon> accTaxa = new HashSet<Taxon>();
302 if (synonym.getAcceptedTaxon() != null){
303 accTaxa.add(synonym.getAcceptedTaxon());
304 }
305 handleOpeningOfMultipleTaxa(accTaxa);
306
307 }else{
308 MessagingUtils.warningDialog(NOT_IMPLEMENTED_YET, NavigationUtil.class, Messages.NavigationUtil_ORPHAN_NAME_MESSAGE);
309 }
310
311 }
312
313 private static void handleOpeningOfMultipleTaxa(Set<Taxon> acceptedTaxa) {
314 if(acceptedTaxa.size() == 1){
315 openEditor(acceptedTaxa.iterator().next());
316 }else if(acceptedTaxa.size() > 1){
317 // FIXME implement a dialog that shows all possible taxa and let the user choose which he wants to open.
318 MessagingUtils.warningDialog(NOT_IMPLEMENTED_YET, NavigationUtil.class, Messages.NavigationUtil_MULTI_TREE);
319 }else if(acceptedTaxa.size() == 0){
320 // this is an undesired state
321 MessagingUtils.warningDialog(NOT_IMPLEMENTED_YET, NavigationUtil.class, Messages.NavigationUtil_ORPHAN_TAXON);
322 }
323 }
324
325 /**
326 * @param taxonNodes
327 */
328 private static void handleOpeningOfMultipleTaxonNodes(
329 Set<TaxonNode> taxonNodes) {
330
331 if(taxonNodes.size() == 1){
332 openEditor(taxonNodes.iterator().next());
333 }else if(taxonNodes.size() > 1){
334 // FIXME implement a dialog that shows all possible taxa and let the user choose which he wants to open.
335 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.");
336 }else if(taxonNodes.size() == 0){
337 // this is an undesired state
338 MessagingUtils.warningDialog(Messages.NavigationUtil_INCORRECT_STATE, NavigationUtil.class, Messages.NavigationUtil_INCORRECT_STATE_MESSAGE);
339 }
340 }
341
342 /**
343 * <p>showNavigator</p>
344 *
345 * @return the TaxonNavigator instance if present
346 */
347 public static TaxonNavigator showNavigator() {
348 return (TaxonNavigator) showView(TaxonNavigator.ID);
349 }
350
351 /**
352 * <p>getNavigator</p>
353 *
354 * @param restore a boolean.
355 * @return a {@link eu.etaxonomy.taxeditor.navigation.navigator.TaxonNavigator} object.
356 */
357 public static TaxonNavigator getNavigator(boolean restore) {
358 return (TaxonNavigator) getView(TaxonNavigator.ID, restore);
359 }
360
361 /**
362 * <p>getOpenEditors</p>
363 *
364 * @return a {@link java.util.Set} object.
365 */
366 public static Set<IEditorPart> getOpenEditors() {
367 return EditorUtil.getOpenEditors();
368 }
369
370 /**
371 * <p>getPluginId</p>
372 *
373 * @return a {@link java.lang.String} object.
374 */
375 public static String getPluginId(){
376 return TaxeditorNavigationPlugin.PLUGIN_ID;
377 }
378
379 }