ref #7010 Adapt edit polytomous key handler
[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.api.service.ITaxonNodeService;
30 import eu.etaxonomy.cdm.api.service.UpdateResult;
31 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
32 import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
33 import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
34 import eu.etaxonomy.taxeditor.navigation.l10n.Messages;
35 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
36 import eu.etaxonomy.taxeditor.store.CdmStore;
37
38 /**
39 * @author k.luther
40 * @date 02.06.2015
41 */
42 public class TreeNodeDropAdapterE4 extends ViewerDropAdapter {
43
44 protected static final String TREE_NODE_DROP_ADAPTER_UNSAVED_PARENT_MESSAGE = Messages.TreeNodeDropAdapter_UNSAVED_PARENT_MESSAGE;
45 protected static final String TREE_NODE_DROP_ADAPTER_UNSAVED_PARENT = Messages.TreeNodeDropAdapter_UNSAVED_PARENT;
46 protected static final String TREE_NODE_DROP_ADAPTER_MOVE_TAXON = Messages.TreeNodeDropAdapter_MOVE_TAXON;
47 protected static final String TREE_NODE_DROP_ADAPTER_CANCEL = Messages.TreeNodeDropAdapter_CANCEL;
48 protected static final String TREE_NODE_DROP_ADAPTER_BEHIND = Messages.TreeNodeDropAdapter_BEHIND;
49 protected static final String TREE_NODE_DROP_ADAPTER_CHILD = Messages.TreeNodeDropAdapter_CHILD;
50 protected static final String DO_YOU_WANT_TO_MOVE_THE_TAXONNODE_AS_CHILD_OR_BEHIND_THE_TARGET_NODE = Messages.TreeNodeDropAdapter_MOVE_BEHIND;
51 protected static final String TARGET_NODE = Messages.TreeNodeDropAdapter_TARGET_NODE;
52
53 private static final Logger logger = Logger.getLogger(TreeNodeDropAdapterE4.class);
54
55 private TaxonNavigatorE4 taxonNavigator;
56 UpdateResult result;
57
58 public static final String ID = "eu.etaxonomy.taxeditor.navigation.navigator.dropassistant"; //$NON-NLS-1$
59
60 private static final EnumSet<CRUD> UPDATE = EnumSet.of(CRUD.UPDATE);
61
62 public enum MovingType{
63 CHILD, PREVIOUS, BEHIND
64 }
65
66 protected TreeNodeDropAdapterE4(TaxonNavigatorE4 navigator) {
67 super(navigator.getViewer());
68 this.taxonNavigator = navigator;
69 }
70
71 /** {@inheritDoc} */
72 @Override
73 public boolean performDrop(Object data) {
74 Object target = getCurrentTarget();
75 if (getCurrentTarget() instanceof TaxonNodeDto) {
76 Set<TaxonNodeDto> taxonNodes = getSelectedTaxa();
77 TaxonNodeDto targetTreeNode = (TaxonNodeDto) target;
78 // if (targetTreeNode.getType() != null && targetTreeNode.getType().equals(Classification.class)){
79 // targetTreeNode = ((Classification)targetTreeNode).getRootNode();
80 // targetTreeNode = HibernateProxyHelper.deproxy(targetTreeNode, TaxonNode.class);
81 // }
82 if(taxonNodes != null) {
83 if (taxonNodes.size() == 1){
84 boolean success = moveTaxon(taxonNodes, targetTreeNode);
85 if (success){
86 taxonNavigator.refresh();
87 }
88 return success;
89 } else{
90 if( MessageDialog.openConfirm(null, Messages.TreeNodeDropAdapter_MOVING, Messages.TreeNodeDropAdapter_MOVING_MESSAGE)){
91 return true;
92 }
93 }
94 }
95 }
96 return false;
97 }
98
99 private Set<TaxonNodeDto> getSelectedTaxa(){
100 HashSet<TaxonNodeDto> taxonNodes = new HashSet();
101
102 ISelection selection = LocalSelectionTransfer.getTransfer().getSelection();
103 if (selection instanceof TreeSelection) {
104
105 Iterator<?> selectionIterator = ((TreeSelection) selection).iterator();
106
107 while (selectionIterator.hasNext()){
108 Object object = selectionIterator.next();
109 if(object instanceof TaxonNodeDto){
110 TaxonNodeDto taxonNode = (TaxonNodeDto) object;
111 taxonNodes.add(taxonNode);
112 }
113 }
114 }
115 return taxonNodes;
116 }
117
118 /** {@inheritDoc} */
119 @Override
120 public boolean validateDrop(Object target, int operation,
121 TransferData transferType) {
122
123 if (target instanceof TaxonNodeDto) {
124
125 // check users permissions with target taxonnode and taxon
126 if (target instanceof TaxonNodeDto) {
127 TaxonNodeDto targetNode = (TaxonNodeDto)target;
128 TaxonNode node = CdmStore.getService(ITaxonNodeService.class).load(targetNode.getUuid());
129 boolean hasTargetNodePermission = CdmStore.currentAuthentiationHasPermission(node, UPDATE);
130 boolean hasTargetTaxonPermission = node.getTaxon() == null ?
131 true :
132 CdmStore.currentAuthentiationHasPermission(node.getTaxon(), UPDATE);
133
134 if(logger.isDebugEnabled()){
135 logger.debug("target: " + node.getTaxon() == null? "-" : node.getTaxon().getTitleCache()); //$NON-NLS-1$
136 }
137
138 if(!hasTargetNodePermission || ! hasTargetNodePermission){
139 if(logger.isDebugEnabled()){
140 logger.debug("CANCEL_STATUS for target node: " + hasTargetNodePermission + " " + hasTargetTaxonPermission + " "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
141 }
142 return false;
143 }
144 }
145
146 // do not allow to drop onto itself and
147 // check users permissions with all selected taxon nodes and taxa
148 for(TaxonNodeDto taxonNode : getSelectedTaxa()){
149 if (logger.isDebugEnabled()){
150 logger.debug("selectedTaxa: " + taxonNode.getTaxonUuid() == null? "-" : taxonNode.getTitleCache()); //$NON-NLS-1$
151 }
152 boolean isClassification = taxonNode.getTaxonUuid()== null;
153 if (isClassification) {
154 if(logger.isDebugEnabled()){
155 logger.debug("CANCEL_STATUS for selected classification " + taxonNode.getClassificationUUID()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
156 }
157 return false;
158 }
159 boolean isSameTaxonNode = taxonNode.equals(target);
160 TaxonNode node = CdmStore.getService(ITaxonNodeService.class).load(taxonNode.getUuid());
161 boolean hasTaxonNodePermission = CdmStore.currentAuthentiationHasPermission(node, UPDATE);
162
163 boolean hasTaxonPermission =
164 CdmStore.currentAuthentiationHasPermission(node.getTaxon(), UPDATE);CdmStore.currentAuthentiationHasPermission(node.getTaxon(), UPDATE);
165 if (
166 isSameTaxonNode
167 || !hasTaxonNodePermission
168 || !hasTaxonPermission
169 ) {
170 if(logger.isDebugEnabled()){
171 logger.debug("CANCEL_STATUS for selected " + isSameTaxonNode + Messages.TreeNodeDropAdapter_10 + hasTaxonNodePermission + " " + hasTaxonPermission + " "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
172 }
173 return false;
174 }
175 }
176 logger.debug("OK_STATUS"); //$NON-NLS-1$
177 return true;
178 }
179 logger.debug("CANCEL_STATUS"); //$NON-NLS-1$
180 return false;
181 }
182
183
184 private boolean moveTaxon(Set<TaxonNodeDto> taxonNodes, TaxonNodeDto targetITaxonTreeNode) {
185 Iterator<TaxonNodeDto> taxIterator = taxonNodes.iterator();
186 Set<UUID> uuids = new HashSet<UUID>();
187 TaxonNodeDto node = null;
188 while(taxIterator.hasNext()){
189 node = taxIterator.next();
190 uuids.add(node.getUuid());
191 }
192 IUndoContext workspaceUndoContext = taxonNavigator.getUndoContext();
193 if (!PreferencesUtil.getSortNodesNaturally()){
194 if (workspaceUndoContext == null) {
195 logger.error("Workspace undo context is null. DND operation cancelled"); //$NON-NLS-1$
196 return false;
197 }
198 result =CdmStore.getService(ITaxonNodeService.class).moveTaxonNodes(uuids,targetITaxonTreeNode.getUuid(), 0);
199
200 logger.info("Moved taxa to new parent " + targetITaxonTreeNode); //$NON-NLS-1$
201 return true;
202 }else{
203 String[] buttonLables = {TREE_NODE_DROP_ADAPTER_CHILD, TREE_NODE_DROP_ADAPTER_BEHIND,TREE_NODE_DROP_ADAPTER_CANCEL};
204 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);
205 dialog.open();
206 int returnCode = dialog.getReturnCode();
207
208 if (returnCode == 0){
209 if (workspaceUndoContext == null) {
210 logger.error("Workspace undo context is null. DND operation cancelled"); //$NON-NLS-1$
211 return false;
212 }
213
214 result = CdmStore.getService(ITaxonNodeService.class).moveTaxonNodes(uuids,targetITaxonTreeNode.getUuid(), 0);
215
216 logger.info("Moved taxa to new parent " + targetITaxonTreeNode); //$NON-NLS-1$
217 return true;
218 }else if (returnCode == 1){
219 if (workspaceUndoContext == null) {
220 logger.error("Workspace undo context is null. DND operation cancelled"); //$NON-NLS-1$
221 return false;
222 }
223
224
225 CdmStore.getService(ITaxonNodeService.class).moveTaxonNodes(uuids,targetITaxonTreeNode.getUuid(), 2);
226 logger.info("Moved taxa to new parent " + targetITaxonTreeNode); //$NON-NLS-1$
227 return true;
228 }
229 // } else if (returnCode == 2){
230 // IUndoContext workspaceUndoContext = NavigationUtil.getWorkbenchUndoContext();
231 // if (workspaceUndoContext == null) {
232 // logger.error("Workspace undo context is null. DND operation cancelled");
233 // return false;
234 // }
235 // TaxonNode targetNode = (TaxonNode) targetITaxonTreeNode;
236 //
237 // AbstractPostOperation operation = new MoveTaxonOperation
238 // ("Move Taxon", workspaceUndoContext, uuids, targetNode, this, taxonNavigator, MovingType.BEHIND);
239 // NavigationUtil.executeOperation(operation);
240 //
241 // logger.info("Moved taxa to new parent " + targetITaxonTreeNode);
242 // return true;
243 // }
244 else{
245 return false;
246 }
247
248
249 }
250 }
251
252 @Override
253 public void dragOver(DropTargetEvent event) {
254 super.dragOver(event);
255 event.feedback = DND.FEEDBACK_SELECT | DND.FEEDBACK_INSERT_AFTER;
256 }
257
258 }