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 info.magnolia.jcr.util.NodeTypes;
37 import info.magnolia.jcr.util.NodeUtil;
38 import info.magnolia.ui.vaadin.integration.contentconnector.ContentConnector;
39 import info.magnolia.ui.vaadin.integration.contentconnector.JcrContentConnector;
40 import info.magnolia.ui.vaadin.integration.jcr.JcrItemAdapter;
41
42 import javax.inject.Inject;
43 import javax.jcr.Node;
44 import javax.jcr.RepositoryException;
45
46 import org.apache.commons.lang3.StringUtils;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49
50 import com.vaadin.v7.data.Item;
51
52
53
54
55
56
57 public class JcrDropConstraint extends AlwaysTrueDropConstraint implements DropConstraint {
58
59 private static final Logger log = LoggerFactory.getLogger(JcrDropConstraint.class);
60
61 private final ContentConnector contentConnector;
62
63 @Inject
64 public JcrDropConstraint(ContentConnector contentConnector) {
65 this.contentConnector = contentConnector;
66 }
67
68
69
70
71
72
73 @Deprecated
74 public JcrDropConstraint() {
75 this(null);
76 }
77
78 @Override
79 public boolean allowedAsChild(Item sourceItem, Item targetItem) {
80 if ((sourceItem instanceof JcrItemAdapter) && (targetItem instanceof JcrItemAdapter)) {
81 JcrItemAdapter source = (JcrItemAdapter) sourceItem;
82 JcrItemAdapter target = (JcrItemAdapter) targetItem;
83
84 return allowedAsChild(source.getJcrItem(), target.getJcrItem());
85 }
86
87 return true;
88 }
89
90 protected boolean allowedAsChild(javax.jcr.Item source, javax.jcr.Item target) {
91 try {
92 boolean movable = basicCheck(source, target);
93 if (movable) {
94
95 if (target.isSame(source.getParent())
96
97 || ((Node) target).hasNode(source.getName())
98 || ((Node) target).hasProperty(source.getName())) {
99 return false;
100 }
101
102
103 if (source.isNode()
104 && NodeUtil.isNodeType((Node) source, NodeTypes.Folder.NAME)
105 && !(isRoot(target) || NodeUtil.isNodeType((Node) target, NodeTypes.Folder.NAME))) {
106 log.debug("Could not move a Folder under a node", ((Node) source).getPrimaryNodeType().getName());
107 return false;
108 }
109 }
110
111 return movable;
112 } catch (RepositoryException e) {
113 log.warn("Cannot check allow as child due to exception: ", e);
114 }
115
116 return true;
117 }
118
119 protected boolean basicCheck(javax.jcr.Item source, javax.jcr.Item target) {
120
121 if (!target.isNode()) {
122 log.debug("Could not move a node under a property");
123 return false;
124 }
125
126
127 if (isAncestorOf(source, target)) {
128 return false;
129 }
130
131 return true;
132 }
133
134 protected boolean isAncestorOf(javax.jcr.Item ancestor, javax.jcr.Item node) {
135 try {
136 for (javax.jcr.Item n = node; !isRoot(n); n = n.getParent()) {
137 if (ancestor.isSame(n)) {
138 return true;
139 }
140 }
141 } catch (RepositoryException e) {
142 log.warn("Cannot get ancestor of item:", e);
143 }
144 return false;
145 }
146
147 protected boolean isRoot(javax.jcr.Item item) {
148 try {
149
150 String rootPath = contentConnector instanceof JcrContentConnector ? ((JcrContentConnector) contentConnector).getContentConnectorDefinition().getRootPath() : "/";
151 if (item != null && item.isNode() && (item.getParent() == null || StringUtils.equals(item.getPath(), rootPath))) {
152 return true;
153 }
154 } catch (RepositoryException e) {
155 return true;
156 }
157
158 return false;
159 }
160
161 @Override
162 public boolean allowedBefore(Item sourceItem, Item targetItem) {
163 if ((sourceItem instanceof JcrItemAdapter) && (targetItem instanceof JcrItemAdapter)) {
164 JcrItemAdapter source = (JcrItemAdapter) sourceItem;
165 JcrItemAdapter target = (JcrItemAdapter) targetItem;
166
167 return allowedSibling(source.getJcrItem(), target.getJcrItem());
168 }
169 return true;
170 }
171
172 protected boolean allowedSibling(javax.jcr.Item source, javax.jcr.Item target) {
173 try {
174
175 if (!source.isNode()) {
176 return false;
177 }
178
179 boolean movable = basicCheck(source, target);
180 if (movable &&
181
182 (isRoot(target) ||
183
184 target.getParent().hasNode(source.getName()) && !target.getParent().isSame(source.getParent()))) {
185 return false;
186 }
187
188 return movable;
189 } catch (RepositoryException e) {
190 log.warn("Cannot check allow before due to exception: ", e);
191 }
192
193 return true;
194 }
195
196 @Override
197 public boolean allowedAfter(Item sourceItem, Item targetItem) {
198 if ((sourceItem instanceof JcrItemAdapter) && (targetItem instanceof JcrItemAdapter)) {
199 JcrItemAdapter source = (JcrItemAdapter) sourceItem;
200 JcrItemAdapter target = (JcrItemAdapter) targetItem;
201
202 return allowedSibling(source.getJcrItem(), target.getJcrItem());
203 }
204 return true;
205 }
206
207 @Override
208 public boolean allowedToMove(Item sourceItem) {
209 JcrItemAdapter jcrSourceItem = (JcrItemAdapter) sourceItem;
210 return jcrSourceItem != null;
211 }
212 }