Merge branch 'release/5.24.0'
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / termtree / e4 / TermTreeDtoDropAdapter.java
1 /**
2 * Copyright (C) 2017 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 package eu.etaxonomy.taxeditor.termtree.e4;
10
11 import java.util.Arrays;
12 import java.util.Collection;
13 import java.util.Collections;
14 import java.util.UUID;
15
16 import org.eclipse.e4.ui.di.UISynchronize;
17 import org.eclipse.jface.util.LocalSelectionTransfer;
18 import org.eclipse.jface.viewers.IStructuredSelection;
19 import org.eclipse.jface.viewers.TreeViewer;
20 import org.eclipse.jface.viewers.Viewer;
21 import org.eclipse.jface.viewers.ViewerDropAdapter;
22 import org.eclipse.swt.dnd.DropTargetEvent;
23 import org.eclipse.swt.dnd.TransferData;
24
25 import eu.etaxonomy.cdm.model.description.Feature;
26 import eu.etaxonomy.cdm.model.term.IHasTermType;
27 import eu.etaxonomy.cdm.model.term.OrderedTermVocabulary;
28 import eu.etaxonomy.cdm.model.term.TermType;
29 import eu.etaxonomy.cdm.model.term.TermVocabulary;
30 import eu.etaxonomy.cdm.persistence.dto.TermDto;
31 import eu.etaxonomy.cdm.persistence.dto.TermNodeDto;
32 import eu.etaxonomy.cdm.persistence.dto.TermTreeDto;
33 import eu.etaxonomy.taxeditor.editor.definedterm.TermTransfer;
34 import eu.etaxonomy.taxeditor.editor.definedterm.e4.DefinedTermDropAdapterE4;
35 import eu.etaxonomy.taxeditor.l10n.Messages;
36 import eu.etaxonomy.taxeditor.model.MessagingUtils;
37 import eu.etaxonomy.taxeditor.termtree.TermNodeDtoTransfer;
38 import eu.etaxonomy.taxeditor.termtree.e4.operation.AddFeatureOperation;
39 import eu.etaxonomy.taxeditor.termtree.e4.operation.AddOntologyTermOperation;
40 import eu.etaxonomy.taxeditor.termtree.e4.operation.MoveFeatureOperation;
41 import eu.etaxonomy.taxeditor.ui.dialog.selection.TermVocabularySelectionDialog;
42 import eu.etaxonomy.taxeditor.view.webimport.termimport.wrapper.OntologyTermWrapper;
43
44 public class TermTreeDtoDropAdapter extends ViewerDropAdapter {
45
46 protected ITermTreeEditor editor;
47 private UISynchronize sync;
48
49 public TermTreeDtoDropAdapter(ITermTreeEditor editor, Viewer viewer, UISynchronize sync) {
50 super(viewer);
51 this.editor = editor;
52 this.sync = sync;
53 }
54
55 @Override
56 public boolean performDrop(Object data) {
57 Object currentTarget = getCurrentTarget();
58 TermNodeDto target = null;
59 if(currentTarget instanceof TermTreeDto){
60 target = ((TermTreeDto) currentTarget).getRoot();
61 }
62 else if(currentTarget instanceof TermNodeDto){
63 target = (TermNodeDto) currentTarget;
64 }
65
66 int position = 0;
67 int location = getCurrentLocation();
68 UUID parentUuid = target.getParentUuid();
69 if(parentUuid!=null){
70 TermNodeDto parent = editor.getNodeDtoForUuid(parentUuid);
71 if (location == LOCATION_BEFORE) {
72 position = Math.max(0, parent.getIndex(target));
73 target = parent;
74 }
75
76 if (location == LOCATION_AFTER) {
77 position = parent.getIndex(target)+1;
78 target = parent;
79 }
80 }
81
82 Collection<Object> droppedObjects = Collections.emptyList();
83 if(data instanceof Object[]){
84 droppedObjects = Arrays.asList((Object[])data);
85 }
86 else if(data instanceof IStructuredSelection){
87 droppedObjects = ((IStructuredSelection) data).toList();
88 }
89 TreeViewer viewer = (TreeViewer) getViewer();
90
91 // cannot drop a feature node onto itself
92 for (Object droppedObject : droppedObjects) {
93 if(droppedObject==null){
94 MessagingUtils.warningDialog(DefinedTermDropAdapterE4.MOVE_FAILED, this.getClass(),
95 Messages.FeatureTreeDropAdapter_MOVE_FAILED_SAVE_MESSAGE);
96 return false;
97 }
98 if (droppedObject.equals(target)) {
99 return false;
100 }
101
102 }
103 for (Object droppedObject : droppedObjects) {
104 //check term type compatibility
105 TermType targetType = target.getType();
106
107 TermType droppedType = null;
108 if(droppedObject instanceof IHasTermType){
109 droppedType = ((IHasTermType)droppedObject).getTermType();
110 if(droppedType!=null && !droppedType.equals(targetType) && !droppedType.isKindOf(targetType)){
111 MessagingUtils.warningDialog(DefinedTermDropAdapterE4.TERM_TYPE_ERROR_TITLE, this, DefinedTermDropAdapterE4.TERM_TYPE_ERROR_MESSAGE);
112 continue;
113 }
114 }
115 else if(droppedObject instanceof TermDto){
116 droppedType = ((TermDto)droppedObject).getTermType();
117 if(droppedType!=null && !droppedType.equals(targetType) && !droppedType.isKindOf(targetType)){
118 MessagingUtils.warningDialog(DefinedTermDropAdapterE4.TERM_TYPE_ERROR_TITLE, this, DefinedTermDropAdapterE4.TERM_TYPE_ERROR_MESSAGE);
119 continue;
120 }
121 }
122 if(droppedObject instanceof TermNodeDto){
123 if (((TermNodeDto)droppedObject).getUuid() == null || target.getUuid() == null){
124 MessagingUtils.warningDialog("The new imported node needs to be saved first", this, "Newly created nodes can not be moved or used as parent without saving");
125 return false;
126 }
127 TermNodeDto droppedNode = editor.getNodeDtoForUuid(((TermNodeDto) droppedObject).getUuid());
128 TermNodeDto oldParent = editor.getNodeDtoForUuid(droppedNode.getParentUuid());
129 boolean isCircle = checkCircle(droppedNode, target);
130 if (isCircle || droppedNode.equals(target)){
131 return false;
132 }
133 int currentPosition = oldParent.getIndex(droppedNode);
134
135 if(currentPosition<position && target.equals(oldParent)){
136 position -= 1;
137 }
138 MoveFeatureOperation operation = new MoveFeatureOperation(droppedNode.getUuid(), droppedNode.getTerm().getUuid(), target.getUuid(), position, getCurrentOperation(), editor, editor);
139
140 Object o = oldParent.getChildren().remove(currentPosition);
141
142 target.getChildren().add(position, droppedNode);
143 droppedNode.setParentUuid(target.getUuid());
144 editor.setNodeDtoForUuid(droppedNode);
145 editor.setNodeDtoForUuid(target);
146 editor.setNodeDtoForUuid(oldParent);
147 editor.setDirty();
148 editor.addOperation(operation);
149 }
150 else if(droppedObject instanceof Feature){
151 Feature droppedFeature = (Feature) droppedObject;
152 AddFeatureOperation operation = new AddFeatureOperation(
153 droppedFeature.getUuid(),
154 target.getUuid(), position, editor, editor);
155 editor.setDirty();
156 editor.addOperation(operation);
157 }
158 else if(droppedObject instanceof TermDto){
159 TermDto termDto = (TermDto) droppedObject;
160 // check if target feature tree has the same type as the dropped term
161 if(!termDto.getTermType().equals(targetType)){
162 MessagingUtils.warningDialog(DefinedTermDropAdapterE4.TERM_TYPE_ERROR_TITLE, this, DefinedTermDropAdapterE4.TERM_TYPE_ERROR_MESSAGE);
163 continue;
164 }
165 AddFeatureOperation operation = new AddFeatureOperation(
166 termDto.getUuid(),
167 target.getUuid(), position, editor, editor);
168 TermNodeDto newDto = new TermNodeDto(termDto, target, position, target.getTree(), null, null, null);
169
170 editor.setDirty();
171 editor.addOperation(operation);
172 }
173 else if(droppedObject instanceof OntologyTermWrapper){
174 OntologyTermWrapper wrapper = (OntologyTermWrapper)droppedObject;
175 TermVocabulary vocabulary = wrapper.getTermVocabulary();
176 if(vocabulary==null){
177 vocabulary = TermVocabularySelectionDialog.select(
178 Messages.FeatureTreeDropAdapter_CHOOSE_VOC, viewer.getControl().getShell(), null);
179
180 if(vocabulary instanceof OrderedTermVocabulary){
181 MessagingUtils.warningDialog(Messages.FeatureTreeDropAdapter_IMPORT_NOT_POSSIBLE, this,
182 Messages.FeatureTreeDropAdapter_ORDER_VOC_NOT_POSSIBLE);
183 return false;
184 }
185 if(vocabulary == null){
186 return false;
187 }
188 }
189
190
191 AddOntologyTermOperation operation = new AddOntologyTermOperation(wrapper, target.getUuid(), vocabulary, editor, editor);
192
193 editor.setDirty();
194 editor.addOperation(operation);
195
196 }
197 }
198 editor.getViewer().refresh();
199 return true;
200 }
201
202 /**
203 * @param droppedNode
204 * @param target
205 */
206 private boolean checkCircle(TermNodeDto droppedNode, TermNodeDto newParent) {
207 boolean result = false;
208 if (droppedNode.getChildren().contains(newParent) ){
209 return true;
210 }
211 if (newParent.getParentUuid() != null){
212 result = checkCircle(droppedNode, editor.getNodeDtoForUuid(newParent.getParentUuid()));
213
214 }
215 return result;
216
217 }
218
219 @Override
220 public boolean validateDrop(Object target, int operation, TransferData transferData) {
221 boolean
222 isSupported = TermNodeDtoTransfer.getInstance().isSupportedType(transferData);
223 isSupported |= TermTransfer.getInstance().isSupportedType(transferData);
224 isSupported |= LocalSelectionTransfer.getTransfer().isSupportedType(transferData);
225 isSupported &= getViewer().getInput()!=null;
226 DropTargetEvent event = this.getCurrentEvent();
227
228 TermTreeDto rootTree = null;
229 if (getSelectedObject() instanceof TermNodeDto){
230 TermNodeDto selectedNode = (TermNodeDto)getSelectedObject();
231 rootTree = selectedNode.getTree();
232 }
233 if(target instanceof TermTreeDto && getCurrentLocation()!=ViewerDropAdapter.LOCATION_ON){
234 return false;
235 }
236 if (target == null){
237 return false;
238 }
239 if (target instanceof TermNodeDto && ((TermNodeDto)target).getTree().isFlat() && getCurrentLocation() == LOCATION_ON){
240 return false;
241 }
242 TermDto term = null;
243 if (getSelectedObject() instanceof TermNodeDto){
244 term = ((TermNodeDto)getSelectedObject()).getTerm();
245 isSupported = checkDuplication(target, rootTree, term);
246 }
247
248 if (term == null){
249 TermTransfer transfer = TermTransfer.getInstance();
250 if (transfer.getSelection() != null){
251 TermDto dto = transfer.getSelection();
252 isSupported = checkDuplication(target, rootTree, dto);
253
254 }
255 }
256 return isSupported;
257 }
258
259 private boolean checkDuplication(Object target, TermTreeDto rootTree, TermDto term) {
260 boolean isSupported = true;
261 TermTreeDto targetTree = null;
262 if (target instanceof TermNodeDto){
263 targetTree = ((TermNodeDto)target).getTree();
264 }else if (target instanceof TermTreeDto){
265 targetTree = (TermTreeDto)target;
266 }
267 if (targetTree != null && !targetTree.isAllowDuplicate()){
268 for (TermDto dto: targetTree.getTerms()){
269 if (dto != null && dto.getUuid().equals(term.getUuid()) && !(rootTree != null && targetTree.equals(rootTree))){
270 return false;
271 }
272 }
273 }
274 return true;
275 }
276
277
278
279 }