1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.ui.workbench.tree.drop;
35
36 import static info.magnolia.jcr.util.NodeUtil.*;
37
38 import info.magnolia.jcr.util.NodeUtil;
39 import info.magnolia.ui.vaadin.integration.jcr.JcrItemAdapter;
40 import info.magnolia.ui.workbench.tree.HierarchicalJcrContainer;
41 import info.magnolia.ui.workbench.tree.MoveHandler;
42 import info.magnolia.ui.workbench.tree.MoveLocation;
43
44 import javax.jcr.Item;
45 import javax.jcr.Node;
46 import javax.jcr.Property;
47 import javax.jcr.RepositoryException;
48
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52 import com.vaadin.event.DataBoundTransferable;
53 import com.vaadin.event.Transferable;
54 import com.vaadin.event.dd.DragAndDropEvent;
55 import com.vaadin.event.dd.DropHandler;
56 import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
57 import com.vaadin.event.dd.acceptcriteria.ServerSideCriterion;
58 import com.vaadin.shared.ui.dd.VerticalDropLocation;
59 import com.vaadin.ui.AbstractSelect.AbstractSelectTargetDetails;
60 import com.vaadin.ui.TreeTable;
61
62
63
64
65
66
67 public class TreeViewDropHandler implements MoveHandler, DropHandler {
68
69 private final Logger log = LoggerFactory.getLogger(getClass());
70
71 private TreeTable tree;
72 private DropConstraint constraint;
73 private AcceptCriterion serverSideCriterion;
74
75 public TreeViewDropHandler() {
76 createAcceptCriterion();
77 }
78
79 public TreeViewDropHandler(TreeTable tree, DropConstraint constraint) {
80 this.tree = tree;
81 this.constraint = constraint;
82 createAcceptCriterion();
83 }
84
85 @Override
86 public void drop(DragAndDropEvent dropEvent) {
87
88
89
90 Transferable t = dropEvent.getTransferable();
91
92
93
94 if (t.getSourceComponent() != tree || !(t instanceof DataBoundTransferable)) {
95 return;
96 }
97
98 AbstractSelectTargetDetails target = (AbstractSelectTargetDetails) dropEvent.getTargetDetails();
99
100 Object sourceItemId = getSourceId(dropEvent);
101 Object targetItemId = target.getItemIdOver();
102
103 VerticalDropLocation location = target.getDropLocation();
104
105 if (location == null) {
106 log.debug("DropLocation is null. Do nothing.");
107 return;
108 }
109
110 moveNode(sourceItemId, targetItemId, location);
111
112 }
113
114
115
116
117 @Override
118 public AcceptCriterion getAcceptCriterion() {
119 return serverSideCriterion;
120 }
121
122
123
124
125
126
127
128
129
130
131
132
133
134 private void moveNode(Object sourceItemId, Object targetItemId, VerticalDropLocation location) {
135 log.debug("DropLocation: {}", location.name());
136
137 HierarchicalJcrContainer container = (HierarchicalJcrContainer) tree.getContainerDataSource();
138 JcrItemAdapter sourceItem = (JcrItemAdapter) container.getItem(sourceItemId);
139 JcrItemAdapter targetItem = (JcrItemAdapter) container.getItem(targetItemId);
140
141
142
143
144
145
146
147
148 if (location == VerticalDropLocation.MIDDLE) {
149 if (constraint.allowedAsChild(sourceItem, targetItem)) {
150
151 moveItem(sourceItem, targetItem, MoveLocation.INSIDE);
152 container.setParent(sourceItemId, targetItemId);
153 }
154 } else {
155 Object parentId = container.getParent(targetItemId);
156 if (location == VerticalDropLocation.TOP) {
157 if (parentId != null && constraint.allowedBefore(sourceItem, targetItem)) {
158
159 moveItem(sourceItem, targetItem, MoveLocation.BEFORE);
160 container.setParent(sourceItemId, parentId);
161 }
162 } else if (location == VerticalDropLocation.BOTTOM) {
163 if (parentId != null && constraint.allowedAfter(sourceItem, targetItem)) {
164 moveItem(sourceItem, targetItem, MoveLocation.AFTER);
165 container.setParent(sourceItemId, parentId);
166 }
167 }
168 }
169 }
170
171
172
173
174
175 private void createAcceptCriterion() {
176 serverSideCriterion = new ServerSideCriterion() {
177
178 @Override
179 public boolean accept(DragAndDropEvent dragEvent) {
180 Object sourceItemId = getSourceId(dragEvent);
181 HierarchicalJcrContainer container = (HierarchicalJcrContainer) tree.getContainerDataSource();
182 JcrItemAdapter sourceItem = (JcrItemAdapter) container.getItem(sourceItemId);
183
184 return constraint.allowedToMove(sourceItem);
185 }
186 };
187
188 }
189
190 private Object getSourceId(DragAndDropEvent dropEvent) {
191 Transferable t = dropEvent.getTransferable();
192 return ((DataBoundTransferable) t).getItemId();
193 }
194
195
196
197
198 public boolean basicMoveCheck(Item source, Item target) {
199 try {
200
201 if (!target.isNode()) {
202 return false;
203 }
204
205 if (target.getPath().equals(source.getPath()) && target.getSession().getWorkspace().getName().equals(source.getSession().getWorkspace().getName())) {
206 return false;
207 }
208
209 return !NodeUtil.isSame((Node) target, source.getParent());
210 } catch (RepositoryException re) {
211 log.debug("Cannot determine whether drag and drop is possible due to: {}", re.getMessage(), re);
212 return false;
213 }
214 }
215
216
217
218
219
220 public void moveNode(Node nodeToMove, Node newParent, MoveLocation location) throws RepositoryException {
221 if (!basicMoveCheck(nodeToMove, newParent)) {
222 return;
223 }
224 switch (location) {
225 case INSIDE:
226 String newPath = combinePathAndName(newParent.getPath(), nodeToMove.getName());
227 nodeToMove.getSession().move(nodeToMove.getPath(), newPath);
228 break;
229 case BEFORE:
230 moveNodeBefore(nodeToMove, newParent);
231 break;
232 case AFTER:
233 moveNodeAfter(nodeToMove, newParent);
234 break;
235 }
236 }
237
238
239
240
241
242 @Override
243 public boolean moveItem(com.vaadin.data.Item source, com.vaadin.data.Item target, MoveLocation location) {
244 Item sourceItem = ((JcrItemAdapter) source).getJcrItem();
245 Item targetItem = ((JcrItemAdapter) target).getJcrItem();
246 if (!basicMoveCheck(sourceItem, targetItem)) {
247 return false;
248 }
249 try {
250 final Node targetNode = (Node) targetItem;
251 if (sourceItem.isNode()) {
252 moveNode((Node) sourceItem, targetNode, location);
253 } else {
254 NodeUtil.moveProperty((Property) sourceItem, targetNode);
255 }
256 sourceItem.getSession().save();
257 return true;
258 } catch (RepositoryException re) {
259 log.debug("Cannot execute drag and drop action", re);
260 return false;
261 }
262 }
263
264 @Override
265 public DropHandler asDropHandler() {
266 return this;
267 }
268 }