2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.taxeditor
.editor
;
12 import java
.util
.Collection
;
13 import java
.util
.HashSet
;
14 import java
.util
.List
;
15 import java
.util
.UUID
;
17 import org
.eclipse
.core
.commands
.ExecutionEvent
;
18 import org
.eclipse
.core
.commands
.operations
.IOperationHistory
;
19 import org
.eclipse
.core
.commands
.operations
.IUndoContext
;
20 import org
.eclipse
.e4
.ui
.model
.application
.MApplication
;
21 import org
.eclipse
.e4
.ui
.model
.application
.ui
.basic
.MPart
;
22 import org
.eclipse
.e4
.ui
.model
.application
.ui
.basic
.MPartStack
;
23 import org
.eclipse
.e4
.ui
.workbench
.modeling
.EModelService
;
24 import org
.eclipse
.e4
.ui
.workbench
.modeling
.EPartService
;
25 import org
.eclipse
.e4
.ui
.workbench
.modeling
.EPartService
.PartState
;
26 import org
.eclipse
.jface
.dialogs
.MessageDialog
;
27 import org
.eclipse
.jface
.viewers
.ISelection
;
28 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
29 import org
.eclipse
.jface
.viewers
.TreeNode
;
30 import org
.eclipse
.swt
.widgets
.Shell
;
31 import org
.eclipse
.ui
.IEditorPart
;
32 import org
.eclipse
.ui
.handlers
.HandlerUtil
;
34 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
35 import eu
.etaxonomy
.cdm
.model
.occurrence
.DerivedUnit
;
36 import eu
.etaxonomy
.cdm
.model
.occurrence
.FieldUnit
;
37 import eu
.etaxonomy
.cdm
.model
.occurrence
.SpecimenOrObservationBase
;
38 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
39 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
40 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
41 import eu
.etaxonomy
.cdm
.persistence
.dto
.TaxonNodeDto
;
42 import eu
.etaxonomy
.cdm
.persistence
.dto
.UuidAndTitleCache
;
43 import eu
.etaxonomy
.taxeditor
.bulkeditor
.e4
.BulkEditorE4
;
44 import eu
.etaxonomy
.taxeditor
.bulkeditor
.input
.TaxonEditorInput
;
45 import eu
.etaxonomy
.taxeditor
.editor
.descriptiveDataSet
.DescriptiveDataSetEditor
;
46 import eu
.etaxonomy
.taxeditor
.editor
.descriptiveDataSet
.matrix
.CharacterMatrixPart
;
47 import eu
.etaxonomy
.taxeditor
.editor
.e4
.TaxonEditorInputE4
;
48 import eu
.etaxonomy
.taxeditor
.editor
.group
.authority
.CdmAuthorityEditorInput
;
49 import eu
.etaxonomy
.taxeditor
.editor
.group
.authority
.e4
.CdmAuthorityEditorE4
;
50 import eu
.etaxonomy
.taxeditor
.editor
.internal
.TaxeditorEditorPlugin
;
51 import eu
.etaxonomy
.taxeditor
.editor
.l10n
.Messages
;
52 import eu
.etaxonomy
.taxeditor
.editor
.name
.e4
.TaxonNameEditorE4
;
53 import eu
.etaxonomy
.taxeditor
.editor
.view
.checklist
.e4
.DistributionEditorPart
;
54 import eu
.etaxonomy
.taxeditor
.editor
.view
.derivate
.DerivateView
;
55 import eu
.etaxonomy
.taxeditor
.editor
.view
.derivate
.DerivateViewEditorInput
;
56 import eu
.etaxonomy
.taxeditor
.model
.AbstractUtility
;
57 import eu
.etaxonomy
.taxeditor
.model
.MessagingUtils
;
58 import eu
.etaxonomy
.taxeditor
.workbench
.WorkbenchUtility
;
59 import eu
.etaxonomy
.taxeditor
.workbench
.part
.IE4SavablePart
;
62 * Utility for the editor package
68 public class EditorUtil
extends AbstractUtility
{
70 private static final String NAME_EDITOR_ID
= "eu.etaxonomy.taxeditor.editor.name.e4.TaxonNameEditorE4";
72 private static boolean factsVisible
= true;
74 private static boolean mediaVisible
= true;
76 public static void openDescriptiveDataSetEditor(UUID descriptiveDataSetUuid
, EModelService modelService
, EPartService partService
, MApplication application
){
77 Collection
<MPart
> parts
= partService
.getParts();
78 for (MPart part
: parts
) {
79 if(part
.getObject() instanceof DescriptiveDataSetEditor
80 && ((DescriptiveDataSetEditor
) part
.getObject()).getDescriptiveDataSet().getUuid().equals(descriptiveDataSetUuid
)){
81 partService
.showPart(part
, PartState
.ACTIVATE
);
85 String partId
= AppModelId
.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_DESCRIPTIVEDATASET_DESCRIPTIVEDATASETEDITOR
;
86 MPart part
= showPart(partId
, modelService
, partService
, application
);
87 DescriptiveDataSetEditor editor
= (DescriptiveDataSetEditor
) part
.getObject();
88 editor
.init(descriptiveDataSetUuid
);
91 public static void openCharacterMatrix(UUID descriptiveDataSetUuid
, EModelService modelService
, EPartService partService
, MApplication application
){
92 Collection
<MPart
> parts
= partService
.getParts();
93 for (MPart part
: parts
) {
94 if(part
.getObject() instanceof CharacterMatrixPart
95 && ((CharacterMatrixPart
) part
.getObject()).getDescriptiveDataSet().getUuid().equals(descriptiveDataSetUuid
)){
96 partService
.showPart(part
, PartState
.ACTIVATE
);
100 String partId
= AppModelId
.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_DESCRIPTIVEDATASET_MATRIX_CHARACTERMATRIXPART
;
101 MPart part
= showPart(partId
, modelService
, partService
, application
);
102 CharacterMatrixPart editor
= (CharacterMatrixPart
) part
.getObject();
103 editor
.init(descriptiveDataSetUuid
, true);
106 public static void openDistributionEditor(UuidAndTitleCache parentUuidAndTitleCache
, EModelService modelService
, EPartService partService
, MApplication application
){
107 Collection
<MPart
> parts
= partService
.getParts();
108 String partId
= AppModelId
.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_CHECKLIST_E4_DISTRIBUTIONEDITORPART
;
109 checkAndCloseFactsAndMediaParts(partService
);
110 MPart part
= showPart(partId
, modelService
, partService
, application
);
111 DistributionEditorPart editor
= (DistributionEditorPart
) part
.getObject();
112 editor
.init(parentUuidAndTitleCache
);
115 public static void openDistributionEditor(List
<UuidAndTitleCache
> parentTaxonUuidList
, EModelService modelService
, EPartService partService
, MApplication application
){
116 Collection
<MPart
> parts
= partService
.getParts();
117 String partId
= AppModelId
.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_CHECKLIST_E4_DISTRIBUTIONEDITORPART
;
118 checkAndCloseFactsAndMediaParts(partService
);
119 MPart part
= showPart(partId
, modelService
, partService
, application
);
120 DistributionEditorPart editor
= (DistributionEditorPart
) part
.getObject();
121 editor
.init(parentTaxonUuidList
);
124 public static void checkAndCloseFactsAndMediaParts(EPartService partService
) {
125 String partIdFactualData
= AppModelId
.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_DESCRIPTIVE_E4_FACTUALDATAPARTE4
;
126 String partIdMedia
= AppModelId
.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_MEDIA_E4_MEDIAVIEWPARTE4
;
127 MPart part1
= partService
.findPart(AppModelId
.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_DESCRIPTIVE_E4_FACTUALDATAPARTE4
);
128 if (factsVisible
|| (part1
!=null && part1
.getWidget() != null && partService
.isPartVisible(part1
))){
131 factsVisible
= false;
133 part1
= partService
.findPart(AppModelId
.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_MEDIA_E4_MEDIAVIEWPARTE4
);
134 if (mediaVisible
|| (part1
!=null && part1
.getWidget() != null && partService
.isPartVisible(part1
))){
137 mediaVisible
= false;
139 closePart(partIdMedia
, partService
);
140 closePart(partIdFactualData
, partService
);
144 public static void openSpecimenEditor(DerivateViewEditorInput input
, EModelService modelService
, EPartService partService
, MApplication application
){
145 String partId
= AppModelId
.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_DERIVATE_DERIVATEVIEW
;
146 MPart part
= showPart(partId
, modelService
, partService
, application
);
147 DerivateView derivateView
= (DerivateView
) part
.getObject();
148 derivateView
.init(input
);
151 public static void openRightsEditor(CdmAuthorityEditorInput input
, EModelService modelService
, EPartService partService
, MApplication application
){
152 Collection
<MPart
> parts
= partService
.getParts();
153 for (MPart part
: parts
) {
154 if(part
.getObject() instanceof CdmAuthorityEditorE4
155 && ((CdmAuthorityEditorE4
) part
.getObject()).getInput().getGroup().equals(input
.getGroup())){
156 partService
.showPart(part
, PartState
.ACTIVATE
);
160 String partId
= AppModelId
.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_GROUP_AUTHORITY_E4_CDMAUTHORITYEDITORE4
;
161 MPart part
= showPart(partId
, modelService
, partService
, application
);
162 CdmAuthorityEditorE4 authorityView
= (CdmAuthorityEditorE4
) part
.getObject();
163 authorityView
.init(input
);
166 public static MPart
showPart(String partId
, EModelService modelService
, EPartService partService
, MApplication application
){
167 MPart part
= partService
.findPart(partId
);
168 if(part
==null || modelService
.getPartDescriptor(partId
).isAllowMultiple()){
169 part
= partService
.createPart(partId
);
171 MPartStack editorAreaPartStack
= WorkbenchUtility
.getEditorAreaPartStack(application
, modelService
);
172 if(editorAreaPartStack
!=null){
173 editorAreaPartStack
.getChildren().add(part
);
175 return partService
.showPart(part
, PartState
.ACTIVATE
);
178 public static MPart
showPart(String partId
, EModelService modelService
, EPartService partService
){
179 MPart part
= partService
.findPart(partId
);
180 if(part
==null || modelService
.getPartDescriptor(partId
).isAllowMultiple()){
181 part
= partService
.createPart(partId
);
182 partService
.activate(part
);
184 partService
.activate(part
);
190 public static void openTaxonNodeE4(UUID taxonNodeUuid
, EModelService modelService
, EPartService partService
, MApplication application
) {
191 TaxonEditorInputE4 input
= TaxonEditorInputE4
.NewInstance(taxonNodeUuid
);
192 openNameEditor_internal(input
, modelService
, partService
, application
);
195 public static void openTaxonBaseE4(UUID taxonBaseUuid
, EModelService modelService
, EPartService partService
, MApplication application
) {
196 TaxonEditorInputE4 input
= TaxonEditorInputE4
.NewInstanceFromTaxonBase(taxonBaseUuid
);
197 openNameEditor_internal(input
, modelService
, partService
, application
);
200 public static void openTaxonBaseE4(UUID taxonBaseUuid
) {
201 //FIXME E4 this can probably be removed when fully migrated
202 TaxonEditorInputE4 input
= TaxonEditorInputE4
.NewInstanceFromTaxonBase(taxonBaseUuid
);
204 EPartService partService
= TaxeditorEditorPlugin
.getDefault().getWorkbench().getActiveWorkbenchWindow().getService(EPartService
.class);
205 EModelService modelService
= TaxeditorEditorPlugin
.getDefault().getWorkbench().getActiveWorkbenchWindow().getService(EModelService
.class);
206 openNameEditor_internal(input
, modelService
, partService
, null);
209 private static void openNameEditor_internal(TaxonEditorInputE4 input
, EModelService modelService
, EPartService partService
, MApplication application
) {
210 TaxonBase taxonBase
= input
.getTaxon();
211 TaxonNode node
= input
.getTaxonNode();
215 boolean hasPermission
= false;
216 // if (node != null){
217 // hasPermission = CdmStore.currentAuthentiationHasPermission(node, RequiredPermissions.TAXON_EDIT);
219 // if (!hasPermission){
220 // MessagingUtils.warningDialog(Messages.EditorUtil_MISSING_PERMISSION, TaxonEditorInputE4.class, Messages.EditorUtil_MISSING_PERMISSION_MESSAGE);
223 if (taxonBase
.isOrphaned()) {
224 if(taxonBase
.isInstanceOf(Synonym
.class)){
225 MessagingUtils
.warningDialog(Messages
.EditorUtil_ORPHAN_ACCEPTED_TAXON
, TaxonEditorInputE4
.class, Messages
.EditorUtil_ORPHAN_ACCEPTED_TAXON_MESSAGE
);
229 MessagingUtils
.warningDialog(Messages
.EditorUtil_ORPHAN_TAXON
, TaxonEditorInputE4
.class, Messages
.EditorUtil_ORPHAN_TAXON_MESSAGE
);
235 Collection
<MPart
> parts
= partService
.getParts();
236 //check if part is already opened
237 for (MPart part
: parts
) {
238 if(part
.getObject() instanceof TaxonNameEditorE4
239 && ((TaxonNameEditorE4
) part
.getObject()).getTaxon()!=null
240 && ((TaxonNameEditorE4
) part
.getObject()).getTaxon().getUuid().equals(input
.getTaxon().getUuid())){
242 forceUserSaveE4Editor(((TaxonNameEditorE4
) part
.getObject()), getShell());
244 partService
.hidePart(part
);
248 MPart part
= showPart(NAME_EDITOR_ID
, modelService
, partService
, application
);
250 TaxonNameEditorE4 editor
= (TaxonNameEditorE4
) part
.getObject();
252 MPart part1
= partService
.findPart(AppModelId
.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_DESCRIPTIVE_E4_FACTUALDATAPARTE4
);
254 showFacts(modelService
, partService
);
255 factsVisible
= false;
257 part1
= partService
.findPart(AppModelId
.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_MEDIA_E4_MEDIAVIEWPARTE4
);
259 showMedia(modelService
, partService
);
260 mediaVisible
= false;
262 // String partIdFactualData = AppModelId.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_DESCRIPTIVE_E4_FACTUALDATAPARTE4;
263 // String partIdMedia = AppModelId.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_MEDIA_E4_MEDIAVIEWPARTE4;
264 // showPart(partIdMedia, modelService, partService);
265 // showPart(partIdFactualData, modelService, partService);
269 public static void showMedia(EModelService modelService
, EPartService partService
) {
270 String partIdFactualData
= AppModelId
.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_MEDIA_E4_MEDIAVIEWPARTE4
;
271 showPart(partIdFactualData
, modelService
, partService
);
275 public static void showFacts(EModelService modelService
, EPartService partService
) {
276 String partIdFactualData
= AppModelId
.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_EDITOR_VIEW_DESCRIPTIVE_E4_FACTUALDATAPARTE4
;
277 showPart(partIdFactualData
, modelService
, partService
);
281 public static Collection
<MPart
> checkForChanges(UUID taxonUUID
, EPartService partService
){
282 Collection
<MPart
> parts
= partService
.getParts();
283 Collection
<MPart
> dirtyParts
= new HashSet();
284 //check if part is already opened
285 boolean isDirty
= false;
286 for (MPart part
: parts
) {
287 if(part
.getObject() instanceof TaxonNameEditorE4
288 && ((TaxonNameEditorE4
) part
.getObject()).getTaxon()!=null
289 && ((TaxonNameEditorE4
) part
.getObject()).getTaxon().getUuid().equals(taxonUUID
)){
291 dirtyParts
.add(part
);
295 }else if (taxonUUID
== null){
297 dirtyParts
.add(part
);
304 public static Collection
<IE4SavablePart
> checkForTaxonChanges(UUID taxonUUID
, EPartService partService
){
305 Collection
<MPart
> parts
= partService
.getParts();
306 Collection
<IE4SavablePart
> dirtyParts
= new HashSet
<>();
307 //check if part is already opened
308 for (MPart part
: parts
) {
309 if(part
.getObject() instanceof TaxonNameEditorE4
310 && ((TaxonNameEditorE4
) part
.getObject()).getTaxon()!=null
311 && ((TaxonNameEditorE4
) part
.getObject()).getTaxon().getUuid().equals(taxonUUID
)){
313 dirtyParts
.add((IE4SavablePart
) part
);
317 }else if (taxonUUID
== null){
318 if (part
.isDirty() && (part
.getObject() instanceof TaxonNameEditorE4
|| (part
.getObject() instanceof BulkEditorE4
&& ((BulkEditorE4
)part
.getObject()).getEditorInput() instanceof TaxonEditorInput
))){
319 dirtyParts
.add((IE4SavablePart
) part
.getObject());
327 * An uninitialized taxon is one that hasn't been saved yet. As such, it
328 * should appear in neither the list of recent names nor in the taxonomic
331 * @param parentNodeUuid
332 * a {@link java.util.UUID} object.
334 public static void openEmptyE4(UUID parentNodeUuid
) {
335 TaxonEditorInputE4 input
= TaxonEditorInputE4
336 .NewEmptyInstance(parentNodeUuid
);
337 EPartService partService
= TaxeditorEditorPlugin
.getDefault().getWorkbench().getActiveWorkbenchWindow().getService(EPartService
.class);
338 MPart part
= partService
.createPart(NAME_EDITOR_ID
);
339 part
= partService
.showPart(part
, PartState
.ACTIVATE
);
340 TaxonNameEditorE4 editor
= (TaxonNameEditorE4
) part
.getObject();
349 * @return a {@link org.eclipse.core.commands.operations.IUndoContext}
352 public static IUndoContext
getUndoContext() {
353 return IOperationHistory
.GLOBAL_UNDO_CONTEXT
;
356 public static boolean isFactsVisible() {
360 public static void setFactsVisible(boolean factsVisible
) {
361 EditorUtil
.factsVisible
= factsVisible
;
364 public static boolean isMediaVisible() {
368 public static void setMediaVisible(boolean mediaVisible
) {
369 EditorUtil
.mediaVisible
= mediaVisible
;
378 * a {@link org.eclipse.ui.IEditorPart} object.
380 * a {@link org.eclipse.swt.widgets.Shell} object.
383 public static boolean forceUserSave(IEditorPart editor
, Shell shell
) {
384 if (editor
.isDirty()) {
386 boolean doSave
= MessageDialog
387 .openConfirm(shell
, Messages
.EditorUtil_COMFIRM_SAVE
,
388 Messages
.EditorUtil_CONFIRM_SAVE_MESSAGE
);
394 editor
.doSave(AbstractUtility
.getMonitor());
399 public static boolean forceUserSaveE4Editor(TaxonNameEditorE4 editor
, Shell shell
) {
400 if (editor
.isDirty()) {
402 boolean doSave
= MessageDialog
403 .openConfirm(shell
, Messages
.EditorUtil_COMFIRM_SAVE
,
404 Messages
.EditorUtil_CONFIRM_SAVE_MESSAGE
);
410 editor
.save(AbstractUtility
.getMonitor());
421 * a {@link org.eclipse.core.commands.ExecutionEvent} object.
422 * @return a {@link org.eclipse.jface.viewers.IStructuredSelection} object.
424 public static IStructuredSelection
getSelection(ExecutionEvent event
) {
425 IEditorPart activeEditor
= HandlerUtil
.getActiveEditor(event
);
427 return (IStructuredSelection
) activeEditor
.getSite()
428 .getSelectionProvider().getSelection();
436 * @return a {@link java.lang.String} object.
438 public static String
getPluginId() {
439 return TaxeditorEditorPlugin
.PLUGIN_ID
;
443 * Iterates recursively over all originals having the given specimen as a derivate.
444 * The first {@link DerivedUnit} with no more originals or the first {@link FieldUnit} is returned
445 * @param specimen the start element for which the originals are iterated recursively
446 * @return either a FieldUnit or a the topmost DerivedUnit (which can be itself)
448 public static SpecimenOrObservationBase
<?
> getTopMostDerivate(SpecimenOrObservationBase
<?
> specimen
){
452 if(specimen
.isInstanceOf(FieldUnit
.class)){
455 else if(specimen
.isInstanceOf(DerivedUnit
.class)){
456 DerivedUnit derivedUnit
= HibernateProxyHelper
.deproxy(specimen
, DerivedUnit
.class);
457 if(derivedUnit
.getOriginals()!=null
458 && !(derivedUnit
.getOriginals().isEmpty())){
459 for(SpecimenOrObservationBase
<?
> original
:((DerivedUnit
) specimen
).getOriginals()){
460 return getTopMostDerivate(original
);
468 * If the current selection is a single {@link TreeNode} it will be returned.
469 * @param selection the selection to check
470 * @return the selected TreeNode or <code>null</code> if no TreeNode selected
472 public static TreeNode
getTreeNodeOfSelection(ISelection selection
){
473 if(selection
instanceof IStructuredSelection
474 && ((IStructuredSelection
) selection
).size()==1
475 && ((IStructuredSelection
) selection
).getFirstElement() instanceof TreeNode
){
476 return (TreeNode
) ((IStructuredSelection
) selection
).getFirstElement();
482 public static void closeObsoleteEditor(TaxonNodeDto taxonNode
, EPartService partService
){
483 String treeIndex
= taxonNode
.getTreeIndex();
484 Collection
<MPart
> parts
= partService
.getParts();
485 for (MPart part
: parts
) {
486 Object object
= part
.getObject();
487 if(object
instanceof TaxonNameEditorE4
){
488 TaxonNameEditorE4 taxonEditor
= (TaxonNameEditorE4
)object
;
489 TaxonNode node
= taxonEditor
.getEditorInput().getTaxonNode();
490 if (node
.treeIndex()!= null){
491 if(node
.treeIndex().startsWith(treeIndex
)){
493 forceUserSaveE4Editor(taxonEditor
, getShell());
495 partService
.hidePart(part
);
498 logger
.debug("The taxonnode of taxon " + node
.getTaxon().getTitleCache() + " uuid: " + node
.getUuid() + " has no treeindex");;
505 public static void closePart(String partID
, EPartService partService
){
507 Collection
<MPart
> parts
= partService
.getParts();
508 for (MPart part
: parts
) {
509 String elementId
= part
.getElementId();
510 if (elementId
.equals(partID
)){
511 partService
.hidePart(part
);
516 public static void updateEditor(TaxonNode taxonNode
, TaxonNameEditorE4 editor
){
517 String treeIndex
= taxonNode
.treeIndex();
518 TaxonNode node
= editor
.getEditorInput().getTaxonNode();
519 if(node
.treeIndex().equals(treeIndex
)){
520 TaxonEditorInputE4 input
= TaxonEditorInputE4
.NewInstance(node
.getUuid());