Merge branch 'develop' into LibrAlign
[taxeditor.git] / eu.etaxonomy.taxeditor.navigation / src / main / java / eu / etaxonomy / taxeditor / navigation / navigator / TreeNodeDropAdapter.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;
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.common.CdmBase;
31 import eu.etaxonomy.cdm.model.taxon.Classification;
32 import eu.etaxonomy.cdm.model.taxon.ITaxonTreeNode;
33 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
34 import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
35 import eu.etaxonomy.taxeditor.navigation.NavigationUtil;
36 import eu.etaxonomy.taxeditor.navigation.navigator.operation.MoveTaxonOperation;
37 import eu.etaxonomy.taxeditor.operation.AbstractPostOperation;
38 import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
39 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
40 import eu.etaxonomy.taxeditor.store.CdmStore;
41
42 /**
43 * <p>TreeNodeDropAdapter class.</p>
44 *
45 * @author k.luther
46 * @date 02.06.2015
47 */
48 public class TreeNodeDropAdapter extends ViewerDropAdapter implements IPostOperationEnabled {
49
50 private static final Logger logger = Logger.getLogger(TreeNodeDropAdapter.class);
51
52 private final TaxonNavigatorViewer navigatorViewer;
53
54 /**
55 * @param viewer
56 */
57 protected TreeNodeDropAdapter(TaxonNavigatorViewer navigatorViewer) {
58 super(navigatorViewer);
59 this.navigatorViewer = navigatorViewer;
60 }
61
62
63 /** Constant <code>ID="eu.etaxonomy.taxeditor.navigation.navig"{trunked}</code> */
64 public static final String ID = "eu.etaxonomy.taxeditor.navigation.navigator.dropassistant"; //$NON-NLS-1$
65
66 private static final EnumSet<CRUD> UPDATE = EnumSet.of(CRUD.UPDATE);
67
68 public enum MovingType{
69 CHILD, PREVIOUS, BEHIND
70 }
71
72
73 /** {@inheritDoc} */
74 @Override
75 public boolean performDrop(Object target) {
76
77
78 if (target instanceof ITaxonTreeNode) {
79 Set<TaxonNode> taxonNodes = getSelectedTaxa();
80 ITaxonTreeNode targetTreeNode = (ITaxonTreeNode) target;
81 if (targetTreeNode instanceof Classification){
82 targetTreeNode = ((Classification)targetTreeNode).getRootNode();
83 targetTreeNode = HibernateProxyHelper.deproxy(targetTreeNode, TaxonNode.class);
84 }
85 if(taxonNodes != null) {
86 if (taxonNodes.size() == 1){
87 return moveTaxon(taxonNodes, targetTreeNode);
88 } else{
89 if( MessageDialog.openConfirm(null, "Moving taxon", "The operation move accepted taxon to other parent is available only for a single taxon.")){
90 return true;
91 }
92 }
93 }
94 }
95
96 return false;
97 }
98
99 private Set<TaxonNode> getSelectedTaxa(){
100 HashSet<TaxonNode> taxonNodes = new HashSet<TaxonNode>();
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 TaxonNode){
110 TaxonNode taxonNode = (TaxonNode) object;
111 taxonNodes.add(taxonNode);
112 }
113 }
114 }
115 return taxonNodes.size() > 0 ? taxonNodes : null;
116 }
117
118 /** {@inheritDoc} */
119 @Override
120 public boolean validateDrop(Object target, int operation,
121 TransferData transferType) {
122
123 if (target instanceof ITaxonTreeNode) {
124
125 // check users permissions with target taxonnode and taxon
126 if (target instanceof TaxonNode) {
127 TaxonNode targetNode = (TaxonNode)target;
128 Boolean hasTargetNodePermission = CdmStore.currentAuthentiationHasPermission(targetNode, UPDATE);
129 Boolean hasTargetTaxonPermission = CdmStore.currentAuthentiationHasPermission(targetNode.getTaxon(), UPDATE);
130
131 if(logger.isDebugEnabled()){
132 logger.debug("target: " + targetNode.getTaxon().getTitleCache());
133 }
134
135 if(!hasTargetNodePermission || ! hasTargetNodePermission){
136 if(logger.isDebugEnabled()){
137 logger.debug("CANCEL_STATUS for target node: " + hasTargetNodePermission.toString() + " " + hasTargetTaxonPermission.toString() + " ");
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 logger.debug("selectedTaxa: " + taxonNode.getTaxon().getTitleCache());
147 Boolean isSameTaxonNode = taxonNode.equals(target);
148 Boolean hasTaxonNodePermission = CdmStore.currentAuthentiationHasPermission(taxonNode, UPDATE);
149 Boolean hasTaxonPermission = CdmStore.currentAuthentiationHasPermission(taxonNode.getTaxon(), UPDATE);
150 if (
151 isSameTaxonNode
152 || !hasTaxonNodePermission
153 || !hasTaxonPermission
154 ) {
155 if(logger.isDebugEnabled()){
156 logger.debug("CANCEL_STATUS for selected " + isSameTaxonNode.toString() + " " + hasTaxonNodePermission.toString() + " " + hasTaxonPermission.toString() + " ");
157 }
158 return false;
159 }
160 }
161 logger.debug("OK_STATUS");
162 return true;
163 }
164 logger.debug("CANCEL_STATUS");
165 return false;
166 }
167
168
169 /**
170 * @param childTaxonNode
171 * @param parentTaxon
172 * @return
173 */
174 private boolean moveTaxon(Set<TaxonNode> taxonNodes, ITaxonTreeNode targetITaxonTreeNode) {
175
176 TaxonNavigator taxonNavigator;
177 taxonNavigator = (TaxonNavigator) NavigationUtil.showView(TaxonNavigator.ID);
178
179 if(targetITaxonTreeNode instanceof TaxonNode){
180
181 TaxonNode targetTaxonNode = (TaxonNode) targetITaxonTreeNode;
182 // Make sure parent taxon does not have unsaved changes
183 if (NavigationUtil.isDirty(targetTaxonNode)){
184 MessageDialog.openWarning(NavigationUtil.getShell(), "Unsaved Parent Taxon", "There are unsaved " +
185 "changes in the parent taxon. Pleas save first.");
186 return false;
187 }
188
189 }
190 Iterator<TaxonNode> taxIterator = taxonNodes.iterator();
191 Set<UUID> uuids = new HashSet<UUID>();
192 TaxonNode node = null;
193 while(taxIterator.hasNext()){
194 node = taxIterator.next();
195 uuids.add(node.getUuid());
196 }
197 if (!PreferencesUtil.getSortNodesNaturally()){
198 IUndoContext workspaceUndoContext = NavigationUtil.getWorkbenchUndoContext();
199 if (workspaceUndoContext == null) {
200 logger.error("Workspace undo context is null. DND operation cancelled");
201 return false;
202 }
203
204 AbstractPostOperation<?> operation = new MoveTaxonOperation
205 ("Move Taxon", workspaceUndoContext, uuids, targetITaxonTreeNode, this, taxonNavigator, MovingType.CHILD);
206 NavigationUtil.executeOperation(operation);
207
208 logger.info("Moved taxa to new parent " + targetITaxonTreeNode);
209 return true;
210 }else{
211 String[] buttonLables = {"Child", "Behind","Cancel"};
212 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);
213 dialog.open();
214 int returnCode = dialog.getReturnCode();
215 if (returnCode == 0){
216 IUndoContext workspaceUndoContext = NavigationUtil.getWorkbenchUndoContext();
217 if (workspaceUndoContext == null) {
218 logger.error("Workspace undo context is null. DND operation cancelled");
219 return false;
220 }
221
222 AbstractPostOperation<?> operation = new MoveTaxonOperation
223 ("Move Taxon", workspaceUndoContext, uuids, targetITaxonTreeNode, this, taxonNavigator, MovingType.CHILD);
224 NavigationUtil.executeOperation(operation);
225
226 logger.info("Moved taxa to new parent " + targetITaxonTreeNode);
227 return true;
228 }else if (returnCode == 1){
229 IUndoContext workspaceUndoContext = NavigationUtil.getWorkbenchUndoContext();
230 if (workspaceUndoContext == null) {
231 logger.error("Workspace undo context is null. DND operation cancelled");
232 return false;
233 }
234 TaxonNode targetNode = (TaxonNode) targetITaxonTreeNode;
235
236 AbstractPostOperation<?> operation = new MoveTaxonOperation
237 ("Move Taxon", workspaceUndoContext, uuids, targetNode, this, taxonNavigator, MovingType.PREVIOUS);
238 NavigationUtil.executeOperation(operation);
239
240 logger.info("Moved taxa to new parent " + targetITaxonTreeNode);
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 /* (non-Javadoc)
267 * @see eu.etaxonomy.taxeditor.operations.IPostOperationEnabled#postOperation(eu.etaxonomy.cdm.model.common.CdmBase)
268 */
269 /** {@inheritDoc} */
270 @Override
271 public boolean postOperation(CdmBase objectAffectedByOperation) {
272 return true;
273 }
274
275 /**
276 * <p>onComplete</p>
277 *
278 * @return a boolean.
279 */
280 @Override
281 public boolean onComplete() {
282 // TODO Auto-generated method stub
283 return false;
284 }
285 @Override
286 public void dragOver(DropTargetEvent event) {
287 super.dragOver(event);
288 event.feedback = DND.FEEDBACK_SELECT | DND.FEEDBACK_INSERT_AFTER;
289
290 }
291
292 }