fix potential NPE
[taxeditor.git] / eu.etaxonomy.taxeditor.editor / src / main / java / eu / etaxonomy / taxeditor / editor / EditorUtil.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.editor;
11
12 import java.util.Collection;
13 import java.util.HashSet;
14 import java.util.UUID;
15
16 import org.eclipse.core.commands.ExecutionEvent;
17 import org.eclipse.core.commands.operations.IOperationHistory;
18 import org.eclipse.core.commands.operations.IUndoContext;
19 import org.eclipse.e4.ui.model.application.MApplication;
20 import org.eclipse.e4.ui.model.application.ui.basic.MPart;
21 import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
22 import org.eclipse.e4.ui.workbench.modeling.EModelService;
23 import org.eclipse.e4.ui.workbench.modeling.EPartService;
24 import org.eclipse.e4.ui.workbench.modeling.EPartService.PartState;
25 import org.eclipse.jface.dialogs.MessageDialog;
26 import org.eclipse.jface.viewers.ISelection;
27 import org.eclipse.jface.viewers.IStructuredSelection;
28 import org.eclipse.jface.viewers.TreeNode;
29 import org.eclipse.swt.widgets.Shell;
30 import org.eclipse.ui.IEditorPart;
31 import org.eclipse.ui.handlers.HandlerUtil;
32
33 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
34 import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
35 import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
36 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
37 import eu.etaxonomy.cdm.model.taxon.Synonym;
38 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
39 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
40 import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
41 import eu.etaxonomy.taxeditor.bulkeditor.e4.BulkEditorE4;
42 import eu.etaxonomy.taxeditor.bulkeditor.input.TaxonEditorInput;
43 import eu.etaxonomy.taxeditor.editor.descriptiveDataSet.DescriptiveDataSetEditor;
44 import eu.etaxonomy.taxeditor.editor.descriptiveDataSet.matrix.CharacterMatrixPart;
45 import eu.etaxonomy.taxeditor.editor.e4.TaxonEditorInputE4;
46 import eu.etaxonomy.taxeditor.editor.group.authority.CdmAuthorityEditorInput;
47 import eu.etaxonomy.taxeditor.editor.group.authority.e4.CdmAuthorityEditorE4;
48 import eu.etaxonomy.taxeditor.editor.internal.TaxeditorEditorPlugin;
49 import eu.etaxonomy.taxeditor.editor.l10n.Messages;
50 import eu.etaxonomy.taxeditor.editor.name.e4.TaxonNameEditorE4;
51 import eu.etaxonomy.taxeditor.editor.view.checklist.e4.DistributionEditorPart;
52 import eu.etaxonomy.taxeditor.editor.view.derivate.DerivateView;
53 import eu.etaxonomy.taxeditor.editor.view.derivate.DerivateViewEditorInput;
54 import eu.etaxonomy.taxeditor.model.AbstractUtility;
55 import eu.etaxonomy.taxeditor.model.MessagingUtils;
56 import eu.etaxonomy.taxeditor.workbench.WorkbenchUtility;
57 import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
58
59 /**
60 * Utility for the editor package
61 *
62 * @author n.hoffmann
63 * @created 20.01.2009
64 * @version 1.0
65 */
66 public class EditorUtil extends AbstractUtility {
67
68 private static final String NAME_EDITOR_ID = "eu.etaxonomy.taxeditor.editor.name.e4.TaxonNameEditorE4";
69
70 private static boolean factsVisible = true;
71
72 private static boolean mediaVisible = true;
73
74 public static void openDescriptiveDataSetEditor(UUID descriptiveDataSetUuid, EModelService modelService, EPartService partService, MApplication application){
75 Collection<MPart> parts = partService.getParts();
76 for (MPart part : parts) {
77 if(part.getObject() instanceof DescriptiveDataSetEditor
78 && ((DescriptiveDataSetEditor) part.getObject()).getDescriptiveDataSet().getUuid().equals(descriptiveDataSetUuid)){
79 partService.showPart(part, PartState.ACTIVATE);
80 return;
81 }
82 }
83 String partId = AppModelId.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_DESCRIPTIVEDATASET_DESCRIPTIVEDATASETEDITOR;
84 MPart part = showPart(partId, modelService, partService, application);
85 DescriptiveDataSetEditor editor = (DescriptiveDataSetEditor) part.getObject();
86 editor.init(descriptiveDataSetUuid);
87 }
88
89 public static void openCharacterMatrix(UUID descriptiveDataSetUuid, EModelService modelService, EPartService partService, MApplication application){
90 Collection<MPart> parts = partService.getParts();
91 for (MPart part : parts) {
92 if(part.getObject() instanceof CharacterMatrixPart
93 && ((CharacterMatrixPart) part.getObject()).getDescriptiveDataSet().getUuid().equals(descriptiveDataSetUuid)){
94 partService.showPart(part, PartState.ACTIVATE);
95 return;
96 }
97 }
98 String partId = AppModelId.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_DESCRIPTIVEDATASET_MATRIX_CHARACTERMATRIXPART;
99 MPart part = showPart(partId, modelService, partService, application);
100 CharacterMatrixPart editor = (CharacterMatrixPart) part.getObject();
101 editor.init(descriptiveDataSetUuid, true);
102 }
103
104 public static void openDistributionEditor(UUID parentTaxonUuid, EModelService modelService, EPartService partService, MApplication application){
105 Collection<MPart> parts = partService.getParts();
106 String partId = AppModelId.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_CHECKLIST_E4_DISTRIBUTIONEDITORPART;
107 String partIdFactualData = AppModelId.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_DESCRIPTIVE_E4_FACTUALDATAPARTE4;
108 String partIdMedia = AppModelId.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_MEDIA_E4_MEDIAVIEWPARTE4;
109 MPart part1 = partService.findPart(AppModelId.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_DESCRIPTIVE_E4_FACTUALDATAPARTE4);
110 if (part1!=null && part1.getWidget() != null){
111 factsVisible = true;
112 }else{
113 factsVisible = false;
114 }
115 part1 = partService.findPart(AppModelId.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_MEDIA_E4_MEDIAVIEWPARTE4);
116 if (part1!=null && part1.getWidget() != null){
117 mediaVisible = true;
118 }else{
119 mediaVisible = false;
120 }
121 closePart(partIdMedia, partService);
122 closePart(partIdFactualData, partService);
123 MPart part = showPart(partId, modelService, partService, application);
124 DistributionEditorPart editor = (DistributionEditorPart) part.getObject();
125 editor.init(parentTaxonUuid);
126 }
127
128
129 public static void openSpecimenEditor(DerivateViewEditorInput input, EModelService modelService, EPartService partService, MApplication application){
130 String partId = AppModelId.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_DERIVATE_DERIVATEVIEW;
131 MPart part = showPart(partId, modelService, partService, application);
132 DerivateView derivateView = (DerivateView) part.getObject();
133 derivateView.init(input);
134 }
135
136 public static void openRightsEditor(CdmAuthorityEditorInput input, EModelService modelService, EPartService partService, MApplication application){
137 Collection<MPart> parts = partService.getParts();
138 for (MPart part : parts) {
139 if(part.getObject() instanceof CdmAuthorityEditorE4
140 && ((CdmAuthorityEditorE4) part.getObject()).getInput().getGroup().equals(input.getGroup())){
141 partService.showPart(part, PartState.ACTIVATE);
142 return;
143 }
144 }
145 String partId = AppModelId.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_GROUP_AUTHORITY_E4_CDMAUTHORITYEDITORE4;
146 MPart part = showPart(partId, modelService, partService, application);
147 CdmAuthorityEditorE4 authorityView = (CdmAuthorityEditorE4) part.getObject();
148 authorityView.init(input);
149 }
150
151 public static MPart showPart(String partId, EModelService modelService, EPartService partService, MApplication application){
152 MPart part = partService.findPart(partId);
153 if(part==null || modelService.getPartDescriptor(partId).isAllowMultiple()){
154 part = partService.createPart(partId);
155 }
156 MPartStack editorAreaPartStack = WorkbenchUtility.getEditorAreaPartStack(application, modelService);
157 if(editorAreaPartStack!=null){
158 editorAreaPartStack.getChildren().add(part);
159 }
160 return partService.showPart(part, PartState.ACTIVATE);
161 }
162
163 public static MPart showPart(String partId, EModelService modelService, EPartService partService){
164 MPart part = partService.findPart(partId);
165 if(part==null || modelService.getPartDescriptor(partId).isAllowMultiple()){
166 part = partService.createPart(partId);
167 partService.activate(part);
168 }else{
169 partService.activate(part);
170 }
171
172 return part;
173 }
174
175 public static void openTaxonNodeE4(UUID taxonNodeUuid, EModelService modelService, EPartService partService, MApplication application) {
176 TaxonEditorInputE4 input = TaxonEditorInputE4.NewInstance(taxonNodeUuid);
177 openNameEditor_internal(input, modelService, partService, application);
178 }
179
180 public static void openTaxonBaseE4(UUID taxonBaseUuid, EModelService modelService, EPartService partService, MApplication application) {
181 TaxonEditorInputE4 input = TaxonEditorInputE4.NewInstanceFromTaxonBase(taxonBaseUuid);
182 openNameEditor_internal(input, modelService, partService, application);
183 }
184
185 public static void openTaxonBaseE4(UUID taxonBaseUuid) {
186 //FIXME E4 this can probably be removed when fully migrated
187 TaxonEditorInputE4 input = TaxonEditorInputE4.NewInstanceFromTaxonBase(taxonBaseUuid);
188
189 EPartService partService = TaxeditorEditorPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getService(EPartService.class);
190 EModelService modelService = TaxeditorEditorPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getService(EModelService.class);
191 openNameEditor_internal(input, modelService, partService, null);
192 }
193
194 private static void openNameEditor_internal(TaxonEditorInputE4 input, EModelService modelService, EPartService partService, MApplication application) {
195 TaxonBase taxonBase = input.getTaxon();
196 TaxonNode node = input.getTaxonNode();
197 if(taxonBase==null){
198 return;
199 }
200 boolean hasPermission = false;
201 // if (node != null){
202 // hasPermission = CdmStore.currentAuthentiationHasPermission(node, RequiredPermissions.TAXON_EDIT);
203 // }
204 // if (!hasPermission){
205 // MessagingUtils.warningDialog(Messages.EditorUtil_MISSING_PERMISSION, TaxonEditorInputE4.class, Messages.EditorUtil_MISSING_PERMISSION_MESSAGE);
206 // return;
207 // }
208 if (taxonBase.isOrphaned()) {
209 if(taxonBase.isInstanceOf(Synonym.class)){
210 MessagingUtils.warningDialog(Messages.EditorUtil_ORPHAN_ACCEPTED_TAXON, TaxonEditorInputE4.class, Messages.EditorUtil_ORPHAN_ACCEPTED_TAXON_MESSAGE);
211 return;
212 }
213 else{
214 MessagingUtils.warningDialog(Messages.EditorUtil_ORPHAN_TAXON, TaxonEditorInputE4.class, Messages.EditorUtil_ORPHAN_TAXON_MESSAGE);
215 return;
216 }
217 }
218
219
220 Collection<MPart> parts = partService.getParts();
221 //check if part is already opened
222 for (MPart part : parts) {
223 if(part.getObject() instanceof TaxonNameEditorE4
224 && ((TaxonNameEditorE4) part.getObject()).getTaxon()!=null
225 && ((TaxonNameEditorE4) part.getObject()).getTaxon().getUuid().equals(input.getTaxon().getUuid())){
226 if (part.isDirty()){
227 forceUserSaveE4Editor(((TaxonNameEditorE4) part.getObject()), getShell());
228 }
229 partService.hidePart(part);
230 break;
231 }
232 }
233 MPart part = showPart(NAME_EDITOR_ID, modelService, partService, application);
234
235 TaxonNameEditorE4 editor = (TaxonNameEditorE4) part.getObject();
236 editor.init(input);
237 MPart part1 = partService.findPart(AppModelId.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_DESCRIPTIVE_E4_FACTUALDATAPARTE4);
238 if (factsVisible){
239 String partIdFactualData = AppModelId.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_DESCRIPTIVE_E4_FACTUALDATAPARTE4;
240 showPart(partIdFactualData, modelService, partService);
241 factsVisible = false;
242 }
243 part1 = partService.findPart(AppModelId.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_MEDIA_E4_MEDIAVIEWPARTE4);
244 if (mediaVisible){
245 String partIdFactualData = AppModelId.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_MEDIA_E4_MEDIAVIEWPARTE4;
246 showPart(partIdFactualData, modelService, partService);
247 mediaVisible = false;
248 }
249 // String partIdFactualData = AppModelId.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_DESCRIPTIVE_E4_FACTUALDATAPARTE4;
250 // String partIdMedia = AppModelId.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_MEDIA_E4_MEDIAVIEWPARTE4;
251 // showPart(partIdMedia, modelService, partService);
252 // showPart(partIdFactualData, modelService, partService);
253 editor.setFocus();
254 }
255
256 public static Collection<MPart> checkForChanges(UUID taxonUUID, EPartService partService ){
257 Collection<MPart> parts = partService.getParts();
258 Collection<MPart> dirtyParts = new HashSet();
259 //check if part is already opened
260 boolean isDirty = false;
261 for (MPart part : parts) {
262 if(part.getObject() instanceof TaxonNameEditorE4
263 && ((TaxonNameEditorE4) part.getObject()).getTaxon()!=null
264 && ((TaxonNameEditorE4) part.getObject()).getTaxon().getUuid().equals(taxonUUID)){
265 if (part.isDirty()){
266 dirtyParts.add(part);
267 }
268
269 break;
270 }else if (taxonUUID == null){
271 if (part.isDirty()){
272 dirtyParts.add(part);
273 }
274 }
275 }
276 return dirtyParts;
277 }
278
279 public static Collection<IE4SavablePart> checkForTaxonChanges(UUID taxonUUID, EPartService partService ){
280 Collection<MPart> parts = partService.getParts();
281 Collection<IE4SavablePart> dirtyParts = new HashSet<>();
282 //check if part is already opened
283 for (MPart part : parts) {
284 if(part.getObject() instanceof TaxonNameEditorE4
285 && ((TaxonNameEditorE4) part.getObject()).getTaxon()!=null
286 && ((TaxonNameEditorE4) part.getObject()).getTaxon().getUuid().equals(taxonUUID)){
287 if (part.isDirty()){
288 dirtyParts.add((IE4SavablePart) part);
289 }
290
291 break;
292 }else if (taxonUUID == null){
293 if (part.isDirty() && (part.getObject() instanceof TaxonNameEditorE4 || (part.getObject() instanceof BulkEditorE4 && ((BulkEditorE4)part.getObject()).getEditorInput() instanceof TaxonEditorInput))){
294 dirtyParts.add((IE4SavablePart) part);
295 }
296 }
297 }
298 return dirtyParts;
299 }
300
301 /**
302 * An uninitialized taxon is one that hasn't been saved yet. As such, it
303 * should appear in neither the list of recent names nor in the taxonomic
304 * tree when opened.
305 *
306 * @param parentNodeUuid
307 * a {@link java.util.UUID} object.
308 */
309 public static void openEmptyE4(UUID parentNodeUuid) {
310 TaxonEditorInputE4 input = TaxonEditorInputE4
311 .NewEmptyInstance(parentNodeUuid);
312 EPartService partService = TaxeditorEditorPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getService(EPartService.class);
313 MPart part = partService.createPart(NAME_EDITOR_ID);
314 part = partService.showPart(part, PartState.ACTIVATE);
315 TaxonNameEditorE4 editor = (TaxonNameEditorE4) part.getObject();
316 editor.init(input);
317 }
318
319 /**
320 * <p>
321 * getUndoContext
322 * </p>
323 *
324 * @return a {@link org.eclipse.core.commands.operations.IUndoContext}
325 * object.
326 */
327 public static IUndoContext getUndoContext() {
328 return IOperationHistory.GLOBAL_UNDO_CONTEXT;
329 }
330
331 public static boolean isFactsVisible() {
332 return factsVisible;
333 }
334
335 public static void setFactsVisible(boolean factsVisible) {
336 EditorUtil.factsVisible = factsVisible;
337 }
338
339 public static boolean isMediaVisible() {
340 return mediaVisible;
341 }
342
343 public static void setMediaVisible(boolean mediaVisible) {
344 EditorUtil.mediaVisible = mediaVisible;
345 }
346
347 /**
348 * <p>
349 * forceUserSave
350 * </p>
351 *
352 * @param editor
353 * a {@link org.eclipse.ui.IEditorPart} object.
354 * @param shell
355 * a {@link org.eclipse.swt.widgets.Shell} object.
356 * @return a boolean.
357 */
358 public static boolean forceUserSave(IEditorPart editor, Shell shell) {
359 if (editor.isDirty()) {
360
361 boolean doSave = MessageDialog
362 .openConfirm(shell, Messages.EditorUtil_COMFIRM_SAVE,
363 Messages.EditorUtil_CONFIRM_SAVE_MESSAGE);
364
365 if (!doSave) {
366 return false;
367 }
368
369 editor.doSave(AbstractUtility.getMonitor());
370 }
371 return true;
372 }
373
374 public static boolean forceUserSaveE4Editor(TaxonNameEditorE4 editor, Shell shell) {
375 if (editor.isDirty()) {
376
377 boolean doSave = MessageDialog
378 .openConfirm(shell, Messages.EditorUtil_COMFIRM_SAVE,
379 Messages.EditorUtil_CONFIRM_SAVE_MESSAGE);
380
381 if (!doSave) {
382 return false;
383 }
384
385 editor.save(AbstractUtility.getMonitor());
386 }
387 return true;
388 }
389
390 /**
391 * <p>
392 * getSelection
393 * </p>
394 *
395 * @param event
396 * a {@link org.eclipse.core.commands.ExecutionEvent} object.
397 * @return a {@link org.eclipse.jface.viewers.IStructuredSelection} object.
398 */
399 public static IStructuredSelection getSelection(ExecutionEvent event) {
400 IEditorPart activeEditor = HandlerUtil.getActiveEditor(event);
401
402 return (IStructuredSelection) activeEditor.getSite()
403 .getSelectionProvider().getSelection();
404 }
405
406 /**
407 * <p>
408 * getPluginId
409 * </p>
410 *
411 * @return a {@link java.lang.String} object.
412 */
413 public static String getPluginId() {
414 return TaxeditorEditorPlugin.PLUGIN_ID;
415 }
416
417 /**
418 * Iterates recursively over all originals having the given specimen as a derivate.
419 * The first {@link DerivedUnit} with no more originals or the first {@link FieldUnit} is returned
420 * @param specimen the start element for which the originals are iterated recursively
421 * @return either a FieldUnit or a the topmost DerivedUnit (which can be itself)
422 */
423 public static SpecimenOrObservationBase<?> getTopMostDerivate(SpecimenOrObservationBase<?> specimen){
424 if(specimen==null){
425 return null;
426 }
427 if(specimen.isInstanceOf(FieldUnit.class)){
428 return specimen;
429 }
430 else if(specimen.isInstanceOf(DerivedUnit.class)){
431 DerivedUnit derivedUnit = HibernateProxyHelper.deproxy(specimen, DerivedUnit.class);
432 if(derivedUnit.getOriginals()!=null
433 && !(derivedUnit.getOriginals().isEmpty())){
434 for(SpecimenOrObservationBase<?> original:((DerivedUnit) specimen).getOriginals()){
435 return getTopMostDerivate(original);
436 }
437 }
438 }
439 return specimen;
440 }
441
442 /**
443 * If the current selection is a single {@link TreeNode} it will be returned.
444 * @param selection the selection to check
445 * @return the selected TreeNode or <code>null</code> if no TreeNode selected
446 */
447 public static TreeNode getTreeNodeOfSelection(ISelection selection){
448 if(selection instanceof IStructuredSelection
449 && ((IStructuredSelection) selection).size()==1
450 && ((IStructuredSelection) selection).getFirstElement() instanceof TreeNode){
451 return (TreeNode) ((IStructuredSelection) selection).getFirstElement();
452
453 }
454 return null;
455 }
456
457 public static void closeObsoleteEditor(TaxonNodeDto taxonNode, EPartService partService){
458 String treeIndex = taxonNode.getTreeIndex();
459 Collection<MPart> parts = partService.getParts();
460 for (MPart part : parts) {
461 Object object = part.getObject();
462 if(object instanceof TaxonNameEditorE4){
463 TaxonNameEditorE4 taxonEditor = (TaxonNameEditorE4)object;
464 TaxonNode node = taxonEditor.getEditorInput().getTaxonNode();
465 if (node.treeIndex()!= null){
466 if(node.treeIndex().startsWith(treeIndex)){
467 if (part.isDirty()){
468 forceUserSaveE4Editor(taxonEditor, getShell());
469 }
470 partService.hidePart(part);
471 }
472 }else{
473 logger.debug("The taxonnode of taxon " + node.getTaxon().getTitleCache() + " uuid: " + node.getUuid() + " has no treeindex");;
474 }
475 }
476 }
477 }
478
479
480 public static void closePart(String partID, EPartService partService){
481
482 Collection<MPart> parts = partService.getParts();
483 for (MPart part : parts) {
484 String elementId = part.getElementId();
485 if (elementId.equals(partID)){
486 partService.hidePart(part);
487 }
488 }
489 }
490
491 public static void updateEditor(TaxonNode taxonNode, TaxonNameEditorE4 editor){
492 String treeIndex = taxonNode.treeIndex();
493 TaxonNode node = editor.getEditorInput().getTaxonNode();
494 if(node.treeIndex().equals(treeIndex)){
495 TaxonEditorInputE4 input = TaxonEditorInputE4.NewInstance(node.getUuid());
496 editor.init(input);
497
498
499 }
500 }
501
502 }