Merge branch 'develop' of https://dev.e-taxonomy.eu/git/taxeditor into actualBranch
[taxeditor.git] / eu.etaxonomy.taxeditor.navigation / src / main / java / eu / etaxonomy / taxeditor / navigation / navigator / TreeNodeDropAdapter.java
1 // $Id$
2 /**
3 * Copyright (C) 2015 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
9 */
10
11 package eu.etaxonomy.taxeditor.navigation.navigator;
12
13 import java.util.EnumSet;
14 import java.util.HashSet;
15 import java.util.Iterator;
16 import java.util.Set;
17 import java.util.UUID;
18
19 import org.apache.log4j.Logger;
20 import org.eclipse.core.commands.operations.IUndoContext;
21 import org.eclipse.jface.dialogs.MessageDialog;
22 import org.eclipse.jface.util.LocalSelectionTransfer;
23 import org.eclipse.jface.viewers.ISelection;
24 import org.eclipse.jface.viewers.TreeSelection;
25 import org.eclipse.jface.viewers.ViewerDropAdapter;
26 import org.eclipse.swt.dnd.DND;
27 import org.eclipse.swt.dnd.DropTargetEvent;
28 import org.eclipse.swt.dnd.TransferData;
29
30 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
31 import eu.etaxonomy.cdm.model.common.CdmBase;
32 import eu.etaxonomy.cdm.model.taxon.Classification;
33 import eu.etaxonomy.cdm.model.taxon.ITaxonTreeNode;
34 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
35 import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
36 import eu.etaxonomy.taxeditor.navigation.NavigationUtil;
37 import eu.etaxonomy.taxeditor.navigation.navigator.operation.MoveTaxonOperation;
38 import eu.etaxonomy.taxeditor.operation.AbstractPostOperation;
39 import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
40 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
41 import eu.etaxonomy.taxeditor.store.CdmStore;
42
43 /**
44 * <p>TreeNodeDropAdapter class.</p>
45 *
46 * @author k.luther
47 * @date 02.06.2015
48 * @version 1.0
49 */
50 public class TreeNodeDropAdapter extends ViewerDropAdapter implements IPostOperationEnabled {
51
52 /**
53 * @param viewer
54 */
55 protected TreeNodeDropAdapter(TaxonNavigatorViewer navigatorViewer) {
56 super(navigatorViewer);
57 this.navigatorViewer = navigatorViewer;
58
59 }
60
61 private final TaxonNavigatorViewer navigatorViewer;
62 private static final Logger logger = Logger.getLogger(TreeNodeDropAdapter.class);
63
64 /** Constant <code>ID="eu.etaxonomy.taxeditor.navigation.navig"{trunked}</code> */
65 public static final String ID = "eu.etaxonomy.taxeditor.navigation.navigator.dropassistant"; //$NON-NLS-1$
66
67 private static final EnumSet<CRUD> UPDATE = EnumSet.of(CRUD.UPDATE);
68
69
70
71 /* (non-Javadoc)
72 * @see org.eclipse.ui.navigator.CommonDropAdapterAssistant#handleDrop(org.eclipse.ui.navigator.CommonDropAdapter, org.eclipse.swt.dnd.DropTargetEvent, java.lang.Object)
73 */
74 /** {@inheritDoc} */
75 @Override
76 public boolean performDrop(Object target) {
77
78
79 if (target instanceof ITaxonTreeNode) {
80 Set<TaxonNode> taxonNodes = getSelectedTaxa();
81 ITaxonTreeNode targetTreeNode = (ITaxonTreeNode) target;
82 if (targetTreeNode instanceof Classification){
83 targetTreeNode = ((Classification)targetTreeNode).getRootNode();
84 targetTreeNode = HibernateProxyHelper.deproxy(targetTreeNode, TaxonNode.class);
85 }
86 if(taxonNodes != null) {
87 if (taxonNodes.size() == 1){
88 return moveTaxon(taxonNodes, targetTreeNode);
89 } else{
90 if( MessageDialog.openConfirm(null, "Moving taxon", "The operation move accepted taxon to other parent is available only for a single taxon.")){
91 return true;
92 }
93 }
94 }
95 }
96
97 return false;
98 }
99
100 private Set<TaxonNode> getSelectedTaxa(){
101 HashSet<TaxonNode> taxonNodes = new HashSet<TaxonNode>();
102
103 ISelection selection = LocalSelectionTransfer.getTransfer().getSelection();
104 if (selection instanceof TreeSelection) {
105
106 Iterator selectionIterator = ((TreeSelection) selection).iterator();
107
108 while (selectionIterator.hasNext()){
109 Object object = selectionIterator.next();
110 if(object instanceof TaxonNode){
111 TaxonNode taxonNode = (TaxonNode) object;
112 taxonNodes.add(taxonNode);
113 }
114 }
115 }
116 return taxonNodes.size() > 0 ? taxonNodes : null;
117 }
118
119 /* (non-Javadoc)
120 * @see org.eclipse.ui.navigator.CommonDropAdapter#validateDrop(java.lang.Object, int, org.eclipse.swt.dnd.TransferData)
121 */
122 /** {@inheritDoc} */
123 @Override
124 public boolean validateDrop(Object target, int operation,
125 TransferData transferType) {
126
127 if (target instanceof ITaxonTreeNode) {
128
129 // check users permissions with target taxonnode and taxon
130 if (target instanceof TaxonNode) {
131 TaxonNode targetNode = (TaxonNode)target;
132 Boolean hasTargetNodePermission = CdmStore.currentAuthentiationHasPermission(targetNode, UPDATE);
133 Boolean hasTargetTaxonPermission = CdmStore.currentAuthentiationHasPermission(targetNode.getTaxon(), UPDATE);
134
135 if(logger.isDebugEnabled()){
136 logger.debug("target: " + targetNode.getTaxon().getTitleCache());
137 }
138
139 if(!hasTargetNodePermission || ! hasTargetNodePermission){
140 if(logger.isDebugEnabled()){
141 logger.debug("CANCEL_STATUS for target node: " + hasTargetNodePermission.toString() + " " + hasTargetTaxonPermission.toString() + " ");
142 }
143 return false;
144 }
145 }
146
147 // do not allow to drop onto itself and
148 // check users permissions with all selected taxon nodes and taxa
149 for(TaxonNode taxonNode : getSelectedTaxa()){
150 logger.debug("selectedTaxa: " + taxonNode.getTaxon().getTitleCache());
151 Boolean isSameTaxonNode = taxonNode.equals(target);
152 Boolean hasTaxonNodePermission = CdmStore.currentAuthentiationHasPermission(taxonNode, UPDATE);
153 Boolean hasTaxonPermission = CdmStore.currentAuthentiationHasPermission(taxonNode.getTaxon(), UPDATE);
154 if (
155 isSameTaxonNode
156 || !hasTaxonNodePermission
157 || !hasTaxonPermission
158 ) {
159 if(logger.isDebugEnabled()){
160 logger.debug("CANCEL_STATUS for selected " + isSameTaxonNode.toString() + " " + hasTaxonNodePermission.toString() + " " + hasTaxonPermission.toString() + " ");
161 }
162 return false;
163 }
164 }
165 logger.debug("OK_STATUS");
166 return true;
167 }
168 logger.debug("CANCEL_STATUS");
169 return false;
170 }
171
172
173 /**
174 * @param childTaxonNode
175 * @param parentTaxon
176 * @return
177 */
178 private boolean moveTaxon(Set<TaxonNode> taxonNodes, ITaxonTreeNode targetITaxonTreeNode) {
179
180 TaxonNavigator taxonNavigator;
181 taxonNavigator = (TaxonNavigator) NavigationUtil.showView(TaxonNavigator.ID);
182
183 if(targetITaxonTreeNode instanceof TaxonNode){
184
185 TaxonNode targetTaxonNode = (TaxonNode) targetITaxonTreeNode;
186 // Make sure parent taxon does not have unsaved changes
187 if (NavigationUtil.isDirty(targetTaxonNode)){
188 MessageDialog.openWarning(NavigationUtil.getShell(), "Unsaved Parent Taxon", "There are unsaved " +
189 "changes in the parent taxon. Pleas save first.");
190 return false;
191 }
192
193 }
194 Iterator<TaxonNode> taxIterator = taxonNodes.iterator();
195 Set<UUID> uuids = new HashSet<UUID>();
196 TaxonNode node = null;
197 while(taxIterator.hasNext()){
198 node = taxIterator.next();
199 uuids.add(node.getUuid());
200 }
201 if (!PreferencesUtil.getSortNodesNaturally()){
202 IUndoContext workspaceUndoContext = NavigationUtil.getWorkbenchUndoContext();
203 if (workspaceUndoContext == null) {
204 logger.error("Workspace undo context is null. DND operation cancelled");
205 return false;
206 }
207
208 AbstractPostOperation operation = new MoveTaxonOperation
209 ("Move Taxon", workspaceUndoContext, uuids, targetITaxonTreeNode, this, taxonNavigator, true);
210 NavigationUtil.executeOperation(operation);
211
212 logger.info("Moved taxa to new parent " + targetITaxonTreeNode);
213 return true;
214 }else{
215 String[] buttonLables = {"Parent", "Predecessor", "Cancel"};
216 MessageDialog dialog = new MessageDialog(null, "Target node", null, "Do you want to use the target node as parent or do you want to move the taxon below the target.", MessageDialog.QUESTION_WITH_CANCEL, buttonLables, 0);
217 dialog.open();
218 int returnCode = dialog.getReturnCode();
219 if (returnCode == 0){
220 IUndoContext workspaceUndoContext = NavigationUtil.getWorkbenchUndoContext();
221 if (workspaceUndoContext == null) {
222 logger.error("Workspace undo context is null. DND operation cancelled");
223 return false;
224 }
225
226 AbstractPostOperation operation = new MoveTaxonOperation
227 ("Move Taxon", workspaceUndoContext, uuids, targetITaxonTreeNode, this, taxonNavigator, true);
228 NavigationUtil.executeOperation(operation);
229
230 logger.info("Moved taxa to new parent " + targetITaxonTreeNode);
231 return true;
232 }else if (returnCode == 1){
233 IUndoContext workspaceUndoContext = NavigationUtil.getWorkbenchUndoContext();
234 if (workspaceUndoContext == null) {
235 logger.error("Workspace undo context is null. DND operation cancelled");
236 return false;
237 }
238
239 AbstractPostOperation operation = new MoveTaxonOperation
240 ("Move Taxon", workspaceUndoContext, uuids, targetITaxonTreeNode, this, taxonNavigator, false);
241 NavigationUtil.executeOperation(operation);
242
243 logger.info("Moved taxa to new parent " + targetITaxonTreeNode);
244 return true;
245 } else{
246 return false;
247 }
248
249
250 }
251 }
252
253 /* (non-Javadoc)
254 * @see eu.etaxonomy.taxeditor.operations.IPostOperationEnabled#postOperation(eu.etaxonomy.cdm.model.common.CdmBase)
255 */
256 /** {@inheritDoc} */
257 @Override
258 public boolean postOperation(CdmBase objectAffectedByOperation) {
259 return true;
260 }
261
262 /**
263 * <p>onComplete</p>
264 *
265 * @return a boolean.
266 */
267 @Override
268 public boolean onComplete() {
269 // TODO Auto-generated method stub
270 return false;
271 }
272 @Override
273 public void dragOver(DropTargetEvent event) {
274 super.dragOver(event);
275 event.feedback = DND.FEEDBACK_SELECT | DND.FEEDBACK_INSERT_AFTER;
276
277 }
278
279 }