2 * Copyright (C) 2015 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
.navigation
.navigator
.e4
;
12 import java
.util
.EnumSet
;
13 import java
.util
.HashSet
;
14 import java
.util
.Iterator
;
16 import java
.util
.UUID
;
18 import org
.apache
.log4j
.Logger
;
19 import org
.eclipse
.core
.commands
.operations
.IUndoContext
;
20 import org
.eclipse
.jface
.dialogs
.MessageDialog
;
21 import org
.eclipse
.jface
.util
.LocalSelectionTransfer
;
22 import org
.eclipse
.jface
.viewers
.ISelection
;
23 import org
.eclipse
.jface
.viewers
.TreeSelection
;
24 import org
.eclipse
.jface
.viewers
.ViewerDropAdapter
;
25 import org
.eclipse
.swt
.dnd
.DND
;
26 import org
.eclipse
.swt
.dnd
.DropTargetEvent
;
27 import org
.eclipse
.swt
.dnd
.TransferData
;
29 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
30 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
31 import eu
.etaxonomy
.cdm
.model
.taxon
.ITaxonTreeNode
;
32 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
33 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.permission
.CRUD
;
34 import eu
.etaxonomy
.taxeditor
.model
.AbstractUtility
;
35 import eu
.etaxonomy
.taxeditor
.navigation
.l10n
.Messages
;
36 import eu
.etaxonomy
.taxeditor
.navigation
.navigator
.operation
.MoveTaxonOperation
;
37 import eu
.etaxonomy
.taxeditor
.operation
.AbstractPostOperation
;
38 import eu
.etaxonomy
.taxeditor
.preference
.PreferencesUtil
;
39 import eu
.etaxonomy
.taxeditor
.store
.CdmStore
;
45 public class TreeNodeDropAdapterE4
extends ViewerDropAdapter
{
47 protected static final String TREE_NODE_DROP_ADAPTER_UNSAVED_PARENT_MESSAGE
= Messages
.TreeNodeDropAdapter_UNSAVED_PARENT_MESSAGE
;
48 protected static final String TREE_NODE_DROP_ADAPTER_UNSAVED_PARENT
= Messages
.TreeNodeDropAdapter_UNSAVED_PARENT
;
49 protected static final String TREE_NODE_DROP_ADAPTER_MOVE_TAXON
= Messages
.TreeNodeDropAdapter_MOVE_TAXON
;
50 protected static final String TREE_NODE_DROP_ADAPTER_CANCEL
= Messages
.TreeNodeDropAdapter_CANCEL
;
51 protected static final String TREE_NODE_DROP_ADAPTER_BEHIND
= Messages
.TreeNodeDropAdapter_BEHIND
;
52 protected static final String TREE_NODE_DROP_ADAPTER_CHILD
= Messages
.TreeNodeDropAdapter_CHILD
;
53 protected static final String DO_YOU_WANT_TO_MOVE_THE_TAXONNODE_AS_CHILD_OR_BEHIND_THE_TARGET_NODE
= Messages
.TreeNodeDropAdapter_MOVE_BEHIND
;
54 protected static final String TARGET_NODE
= Messages
.TreeNodeDropAdapter_TARGET_NODE
;
56 private static final Logger logger
= Logger
.getLogger(TreeNodeDropAdapterE4
.class);
58 private TaxonNavigatorE4 taxonNavigator
;
60 public static final String ID
= "eu.etaxonomy.taxeditor.navigation.navigator.dropassistant"; //$NON-NLS-1$
62 private static final EnumSet
<CRUD
> UPDATE
= EnumSet
.of(CRUD
.UPDATE
);
64 public enum MovingType
{
65 CHILD
, PREVIOUS
, BEHIND
68 protected TreeNodeDropAdapterE4(TaxonNavigatorE4 navigator
) {
69 super(navigator
.getViewer());
70 this.taxonNavigator
= navigator
;
75 public boolean performDrop(Object data
) {
76 Object target
= getCurrentTarget();
77 if (getCurrentTarget() instanceof ITaxonTreeNode
) {
78 Set
<TaxonNode
> taxonNodes
= getSelectedTaxa();
79 ITaxonTreeNode targetTreeNode
= (ITaxonTreeNode
) target
;
80 if (targetTreeNode
instanceof Classification
){
81 targetTreeNode
= ((Classification
)targetTreeNode
).getRootNode();
82 targetTreeNode
= HibernateProxyHelper
.deproxy(targetTreeNode
, TaxonNode
.class);
84 if(taxonNodes
!= null) {
85 if (taxonNodes
.size() == 1){
86 return moveTaxon(taxonNodes
, targetTreeNode
);
88 if( MessageDialog
.openConfirm(null, Messages
.TreeNodeDropAdapter_MOVING
, Messages
.TreeNodeDropAdapter_MOVING_MESSAGE
)){
97 private Set
<TaxonNode
> getSelectedTaxa(){
98 HashSet
<TaxonNode
> taxonNodes
= new HashSet
<TaxonNode
>();
100 ISelection selection
= LocalSelectionTransfer
.getTransfer().getSelection();
101 if (selection
instanceof TreeSelection
) {
103 Iterator
<?
> selectionIterator
= ((TreeSelection
) selection
).iterator();
105 while (selectionIterator
.hasNext()){
106 Object object
= selectionIterator
.next();
107 if(object
instanceof TaxonNode
){
108 TaxonNode taxonNode
= (TaxonNode
) object
;
109 taxonNodes
.add(taxonNode
);
118 public boolean validateDrop(Object target
, int operation
,
119 TransferData transferType
) {
121 if (target
instanceof ITaxonTreeNode
) {
123 // check users permissions with target taxonnode and taxon
124 if (target
instanceof TaxonNode
) {
125 TaxonNode targetNode
= (TaxonNode
)target
;
126 boolean hasTargetNodePermission
= CdmStore
.currentAuthentiationHasPermission(targetNode
, UPDATE
);
127 boolean hasTargetTaxonPermission
= targetNode
.getTaxon() == null ?
129 CdmStore
.currentAuthentiationHasPermission(targetNode
.getTaxon(), UPDATE
);
131 if(logger
.isDebugEnabled()){
132 logger
.debug("target: " + targetNode
.getTaxon() == null?
"-" : targetNode
.getTaxon().getTitleCache()); //$NON-NLS-1$
135 if(!hasTargetNodePermission
|| ! hasTargetNodePermission
){
136 if(logger
.isDebugEnabled()){
137 logger
.debug("CANCEL_STATUS for target node: " + hasTargetNodePermission
+ " " + hasTargetTaxonPermission
+ " "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
143 // do not allow to drop onto itself and
144 // check users permissions with all selected taxon nodes and taxa
145 for(TaxonNode taxonNode
: getSelectedTaxa()){
146 if (logger
.isDebugEnabled()){
147 logger
.debug("selectedTaxa: " + taxonNode
.getTaxon() == null?
"-" : taxonNode
.getTaxon().getTitleCache()); //$NON-NLS-1$
149 boolean isClassification
= !taxonNode
.hasTaxon();
150 if (isClassification
) {
151 if(logger
.isDebugEnabled()){
152 logger
.debug("CANCEL_STATUS for selected classification " + taxonNode
.getClassification().getTitleCache()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
156 boolean isSameTaxonNode
= taxonNode
.equals(target
);
157 boolean hasTaxonNodePermission
= CdmStore
.currentAuthentiationHasPermission(taxonNode
, UPDATE
);
159 boolean hasTaxonPermission
=
160 CdmStore
.currentAuthentiationHasPermission(taxonNode
.getTaxon(), UPDATE
);CdmStore
.currentAuthentiationHasPermission(taxonNode
.getTaxon(), UPDATE
);
163 || !hasTaxonNodePermission
164 || !hasTaxonPermission
166 if(logger
.isDebugEnabled()){
167 logger
.debug("CANCEL_STATUS for selected " + isSameTaxonNode
+ Messages
.TreeNodeDropAdapter_10
+ hasTaxonNodePermission
+ " " + hasTaxonPermission
+ " "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
172 logger
.debug("OK_STATUS"); //$NON-NLS-1$
175 logger
.debug("CANCEL_STATUS"); //$NON-NLS-1$
180 private boolean moveTaxon(Set
<TaxonNode
> taxonNodes
, ITaxonTreeNode targetITaxonTreeNode
) {
183 if(targetITaxonTreeNode
instanceof TaxonNode
){
185 // Make sure parent taxon does not have unsaved changes
186 // if (NavigationUtil.isDirty(targetTaxonNode)){
187 // MessageDialog.openWarning(NavigationUtil.getShell(), TREE_NODE_DROP_ADAPTER_UNSAVED_PARENT, TREE_NODE_DROP_ADAPTER_UNSAVED_PARENT_MESSAGE);
192 Iterator
<TaxonNode
> taxIterator
= taxonNodes
.iterator();
193 Set
<UUID
> uuids
= new HashSet
<UUID
>();
194 TaxonNode node
= null;
195 while(taxIterator
.hasNext()){
196 node
= taxIterator
.next();
197 uuids
.add(node
.getUuid());
199 IUndoContext workspaceUndoContext
= taxonNavigator
.getUndoContext();
200 if (!PreferencesUtil
.getSortNodesNaturally()){
201 if (workspaceUndoContext
== null) {
202 logger
.error("Workspace undo context is null. DND operation cancelled"); //$NON-NLS-1$
206 AbstractPostOperation
<?
> operation
= new MoveTaxonOperation
207 (TREE_NODE_DROP_ADAPTER_MOVE_TAXON
, workspaceUndoContext
, uuids
, targetITaxonTreeNode
, taxonNavigator
, taxonNavigator
, MovingType
.CHILD
);
208 AbstractUtility
.executeOperation(operation
, taxonNavigator
.getSync());
210 logger
.info("Moved taxa to new parent " + targetITaxonTreeNode
); //$NON-NLS-1$
213 String
[] buttonLables
= {TREE_NODE_DROP_ADAPTER_CHILD
, TREE_NODE_DROP_ADAPTER_BEHIND
,TREE_NODE_DROP_ADAPTER_CANCEL
};
214 MessageDialog dialog
= new MessageDialog(null, TARGET_NODE
, null, DO_YOU_WANT_TO_MOVE_THE_TAXONNODE_AS_CHILD_OR_BEHIND_THE_TARGET_NODE
, MessageDialog
.QUESTION_WITH_CANCEL
, buttonLables
, 0);
216 int returnCode
= dialog
.getReturnCode();
217 if (returnCode
== 0){
218 if (workspaceUndoContext
== null) {
219 logger
.error("Workspace undo context is null. DND operation cancelled"); //$NON-NLS-1$
223 AbstractPostOperation
<?
> operation
= new MoveTaxonOperation
224 (TREE_NODE_DROP_ADAPTER_MOVE_TAXON
, workspaceUndoContext
, uuids
, targetITaxonTreeNode
, taxonNavigator
, taxonNavigator
, MovingType
.CHILD
);
225 AbstractUtility
.executeOperation(operation
, taxonNavigator
.getSync());
227 logger
.info("Moved taxa to new parent " + targetITaxonTreeNode
); //$NON-NLS-1$
229 }else if (returnCode
== 1){
230 if (workspaceUndoContext
== null) {
231 logger
.error("Workspace undo context is null. DND operation cancelled"); //$NON-NLS-1$
234 TaxonNode targetNode
= (TaxonNode
) targetITaxonTreeNode
;
236 AbstractPostOperation
<?
> operation
= new MoveTaxonOperation
237 (TREE_NODE_DROP_ADAPTER_MOVE_TAXON
, workspaceUndoContext
, uuids
, targetNode
, taxonNavigator
, taxonNavigator
, MovingType
.PREVIOUS
);
238 AbstractUtility
.executeOperation(operation
, taxonNavigator
.getSync());
240 logger
.info("Moved taxa to new parent " + targetITaxonTreeNode
); //$NON-NLS-1$
243 // } else if (returnCode == 2){
244 // IUndoContext workspaceUndoContext = NavigationUtil.getWorkbenchUndoContext();
245 // if (workspaceUndoContext == null) {
246 // logger.error("Workspace undo context is null. DND operation cancelled");
249 // TaxonNode targetNode = (TaxonNode) targetITaxonTreeNode;
251 // AbstractPostOperation operation = new MoveTaxonOperation
252 // ("Move Taxon", workspaceUndoContext, uuids, targetNode, this, taxonNavigator, MovingType.BEHIND);
253 // NavigationUtil.executeOperation(operation);
255 // logger.info("Moved taxa to new parent " + targetITaxonTreeNode);
267 public void dragOver(DropTargetEvent event
) {
268 super.dragOver(event
);
269 event
.feedback
= DND
.FEEDBACK_SELECT
| DND
.FEEDBACK_INSERT_AFTER
;