minor
[taxeditor.git] / eu.etaxonomy.taxeditor.navigation / src / main / java / eu / etaxonomy / taxeditor / navigation / navigator / e4 / TreeNodeDropAdapterE4.java
1 /**
2 * Copyright (C) 2015 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.navigator.e4;
11
12 import java.util.EnumSet;
13 import java.util.HashSet;
14 import java.util.Iterator;
15 import java.util.Set;
16 import java.util.UUID;
17
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;
28
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;
40
41 /**
42 * @author k.luther
43 * @date 02.06.2015
44 */
45 public class TreeNodeDropAdapterE4 extends ViewerDropAdapter {
46
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;
55
56 private static final Logger logger = Logger.getLogger(TreeNodeDropAdapterE4.class);
57
58 private TaxonNavigatorE4 taxonNavigator;
59
60 public static final String ID = "eu.etaxonomy.taxeditor.navigation.navigator.dropassistant"; //$NON-NLS-1$
61
62 private static final EnumSet<CRUD> UPDATE = EnumSet.of(CRUD.UPDATE);
63
64 public enum MovingType{
65 CHILD, PREVIOUS, BEHIND
66 }
67
68 protected TreeNodeDropAdapterE4(TaxonNavigatorE4 navigator) {
69 super(navigator.getViewer());
70 this.taxonNavigator = navigator;
71 }
72
73 /** {@inheritDoc} */
74 @Override
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);
83 }
84 if(taxonNodes != null) {
85 if (taxonNodes.size() == 1){
86 return moveTaxon(taxonNodes, targetTreeNode);
87 } else{
88 if( MessageDialog.openConfirm(null, Messages.TreeNodeDropAdapter_MOVING, Messages.TreeNodeDropAdapter_MOVING_MESSAGE)){
89 return true;
90 }
91 }
92 }
93 }
94 return false;
95 }
96
97 private Set<TaxonNode> getSelectedTaxa(){
98 HashSet<TaxonNode> taxonNodes = new HashSet<TaxonNode>();
99
100 ISelection selection = LocalSelectionTransfer.getTransfer().getSelection();
101 if (selection instanceof TreeSelection) {
102
103 Iterator<?> selectionIterator = ((TreeSelection) selection).iterator();
104
105 while (selectionIterator.hasNext()){
106 Object object = selectionIterator.next();
107 if(object instanceof TaxonNode){
108 TaxonNode taxonNode = (TaxonNode) object;
109 taxonNodes.add(taxonNode);
110 }
111 }
112 }
113 return taxonNodes;
114 }
115
116 /** {@inheritDoc} */
117 @Override
118 public boolean validateDrop(Object target, int operation,
119 TransferData transferType) {
120
121 if (target instanceof ITaxonTreeNode) {
122
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 ?
128 true :
129 CdmStore.currentAuthentiationHasPermission(targetNode.getTaxon(), UPDATE);
130
131 if(logger.isDebugEnabled()){
132 logger.debug("target: " + targetNode.getTaxon() == null? "-" : targetNode.getTaxon().getTitleCache()); //$NON-NLS-1$
133 }
134
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$
138 }
139 return false;
140 }
141 }
142
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$
148 }
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$
153 }
154 return false;
155 }
156 boolean isSameTaxonNode = taxonNode.equals(target);
157 boolean hasTaxonNodePermission = CdmStore.currentAuthentiationHasPermission(taxonNode, UPDATE);
158
159 boolean hasTaxonPermission =
160 CdmStore.currentAuthentiationHasPermission(taxonNode.getTaxon(), UPDATE);CdmStore.currentAuthentiationHasPermission(taxonNode.getTaxon(), UPDATE);
161 if (
162 isSameTaxonNode
163 || !hasTaxonNodePermission
164 || !hasTaxonPermission
165 ) {
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$
168 }
169 return false;
170 }
171 }
172 logger.debug("OK_STATUS"); //$NON-NLS-1$
173 return true;
174 }
175 logger.debug("CANCEL_STATUS"); //$NON-NLS-1$
176 return false;
177 }
178
179
180 private boolean moveTaxon(Set<TaxonNode> taxonNodes, ITaxonTreeNode targetITaxonTreeNode) {
181
182
183 if(targetITaxonTreeNode instanceof TaxonNode){
184
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);
188 // return false;
189 // }
190
191 }
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());
198 }
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$
203 return false;
204 }
205
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());
209
210 logger.info("Moved taxa to new parent " + targetITaxonTreeNode); //$NON-NLS-1$
211 return true;
212 }else{
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);
215 dialog.open();
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$
220 return false;
221 }
222
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());
226
227 logger.info("Moved taxa to new parent " + targetITaxonTreeNode); //$NON-NLS-1$
228 return true;
229 }else if (returnCode == 1){
230 if (workspaceUndoContext == null) {
231 logger.error("Workspace undo context is null. DND operation cancelled"); //$NON-NLS-1$
232 return false;
233 }
234 TaxonNode targetNode = (TaxonNode) targetITaxonTreeNode;
235
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());
239
240 logger.info("Moved taxa to new parent " + targetITaxonTreeNode); //$NON-NLS-1$
241 return true;
242 }
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");
247 // return false;
248 // }
249 // TaxonNode targetNode = (TaxonNode) targetITaxonTreeNode;
250 //
251 // AbstractPostOperation operation = new MoveTaxonOperation
252 // ("Move Taxon", workspaceUndoContext, uuids, targetNode, this, taxonNavigator, MovingType.BEHIND);
253 // NavigationUtil.executeOperation(operation);
254 //
255 // logger.info("Moved taxa to new parent " + targetITaxonTreeNode);
256 // return true;
257 // }
258 else{
259 return false;
260 }
261
262
263 }
264 }
265
266 @Override
267 public void dragOver(DropTargetEvent event) {
268 super.dragOver(event);
269 event.feedback = DND.FEEDBACK_SELECT | DND.FEEDBACK_INSERT_AFTER;
270 }
271
272 }