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.admincentral.tree.container;
35
36 import info.magnolia.context.MgnlContext;
37 import info.magnolia.jcr.RuntimeRepositoryException;
38 import info.magnolia.jcr.util.NodeTypes;
39 import info.magnolia.jcr.util.NodeUtil;
40 import info.magnolia.ui.model.workbench.definition.WorkbenchDefinition;
41 import info.magnolia.ui.vaadin.integration.jcr.JcrItemAdapter;
42 import info.magnolia.ui.vaadin.integration.jcr.container.AbstractJcrContainer;
43
44 import java.util.ArrayList;
45 import java.util.Collection;
46 import java.util.Collections;
47 import java.util.Comparator;
48 import java.util.List;
49
50 import javax.jcr.Item;
51 import javax.jcr.Node;
52 import javax.jcr.NodeIterator;
53 import javax.jcr.Property;
54 import javax.jcr.PropertyIterator;
55 import javax.jcr.RepositoryException;
56 import javax.jcr.Session;
57
58 import org.apache.commons.lang.StringUtils;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
61
62 import com.vaadin.data.Container;
63
64
65
66
67 public class HierarchicalJcrContainer extends AbstractJcrContainer implements Container.Hierarchical {
68
69 private static final Logger log = LoggerFactory.getLogger(HierarchicalJcrContainer.class);
70
71 private static class ItemNameComparator implements Comparator<Item> {
72 @Override
73 public int compare(Item lhs, Item rhs) {
74 try {
75 return lhs.getName().compareTo(rhs.getName());
76 } catch (RepositoryException e) {
77 throw new RuntimeRepositoryException(e);
78 }
79 }
80 }
81
82 public HierarchicalJcrContainer(WorkbenchDefinition workbenchDefinition) {
83 super(workbenchDefinition);
84 }
85
86 @Override
87 public Collection<String> getChildren(Object itemId) {
88 try {
89 long start = System.currentTimeMillis();
90 Collection<Item> children = getChildren(getItemByPath((String) itemId));
91 log.debug("Fetched {} children in {}ms", children.size(), System.currentTimeMillis() - start);
92 return createContainerIds(children);
93 } catch (RepositoryException e) {
94 throw new RuntimeRepositoryException(e);
95 }
96 }
97
98 @Override
99 public String getParent(Object itemId) {
100 try {
101 Item item = getItemByPath((String) itemId);
102 if (item.isNode() && item.getDepth() == 0) {
103 return null;
104 }
105 return item.getParent().getPath();
106 } catch (RepositoryException e) {
107 throw new RuntimeRepositoryException(e);
108 }
109 }
110
111 @Override
112 public Collection<String> rootItemIds() {
113 try {
114 return createContainerIds(getRootItemIds());
115 } catch (RepositoryException e) {
116 throw new RuntimeRepositoryException(e);
117 }
118 }
119
120 @Override
121 public boolean setParent(Object itemId, Object newParentId) throws UnsupportedOperationException {
122 fireItemSetChange();
123 return true;
124 }
125
126 @Override
127 public boolean areChildrenAllowed(Object itemId) {
128 final JcrItemAdapter item = ((JcrItemAdapter) getItem(itemId));
129 return item.isNode() && hasChildren(itemId);
130 }
131
132 @Override
133 public boolean setChildrenAllowed(Object itemId, boolean areChildrenAllowed) throws UnsupportedOperationException {
134 throw new UnsupportedOperationException();
135 }
136
137 @Override
138 public boolean isRoot(Object itemId) {
139 try {
140 return isRoot(getItemByPath((String) itemId));
141 } catch (RepositoryException e) {
142 throw new RuntimeRepositoryException(e);
143 }
144 }
145
146 @Override
147 public boolean hasChildren(Object itemId) {
148 try {
149 final Item item = getItemByPath((String) itemId);
150 return item.isNode() && !getChildren(item).isEmpty();
151 } catch (RepositoryException e) {
152 throw new RuntimeRepositoryException(e);
153 }
154 }
155
156 protected Collection<String> createContainerIds(Collection<Item> children) throws RepositoryException {
157 ArrayList<String> ids = new ArrayList<String>();
158 for (Item child : children) {
159 ids.add(child.getPath());
160 }
161 return ids;
162 }
163
164 @Override
165 public List<String> getSortableContainerPropertyIds() {
166
167 return Collections.emptyList();
168 }
169
170 public Collection<Item> getChildren(Item item) throws RepositoryException {
171 if (!item.isNode()) {
172 return Collections.emptySet();
173 }
174
175 Node node = (Node) item;
176
177 ArrayList<Item> items = new ArrayList<Item>();
178
179 ArrayList<Node> mainItemTypeNodes = new ArrayList<Node>();
180 ArrayList<Node> groupingItemTypeNodes = new ArrayList<Node>();
181 NodeIterator iterator = node.getNodes();
182 final String mainItemTypeName = getMainItemTypeAsString();
183 final String groupingItemTypeName = getWorkbenchDefinition().getGroupingItemType() == null ? null : getWorkbenchDefinition().getGroupingItemType().getItemType();
184 String currentNodeTypeName;
185 while (iterator.hasNext()) {
186 Node next = iterator.nextNode();
187 currentNodeTypeName = next.getPrimaryNodeType().getName();
188 if (mainItemTypeName.equals(currentNodeTypeName)) {
189 mainItemTypeNodes.add(next);
190 }
191 if (groupingItemTypeName != null && groupingItemTypeName.equals(currentNodeTypeName)) {
192 groupingItemTypeNodes.add(next);
193 }
194 }
195
196 items.addAll(groupingItemTypeNodes);
197 items.addAll(mainItemTypeNodes);
198
199 if (getWorkbenchDefinition().includeProperties()) {
200 ArrayList<Property> properties = new ArrayList<Property>();
201 PropertyIterator propertyIterator = node.getProperties();
202 while (propertyIterator.hasNext()) {
203 final Property property = propertyIterator.nextProperty();
204 final String propertyName = property.getName();
205 if (!propertyName.startsWith(NodeTypes.JCR_PREFIX) && !propertyName.startsWith(NodeTypes.MGNL_PREFIX)) {
206 properties.add(property);
207 }
208 }
209 ItemNameComparator itemNameComparator = new ItemNameComparator();
210 Collections.sort(properties, itemNameComparator);
211 items.addAll(properties);
212 }
213
214 return Collections.unmodifiableCollection(items);
215 }
216
217 public Collection<Item> getRootItemIds() throws RepositoryException {
218 return getChildren(getRootNode());
219 }
220
221
222
223
224
225 public boolean isRoot(Item item) throws RepositoryException {
226 int rootDepth = getRootNode().getDepth();
227 return item.getDepth() <= rootDepth + 1;
228 }
229
230 public Item getItemByPath(String path) throws RepositoryException {
231 String absolutePath = getPathInWorkspace(path);
232 return getSession().getItem(absolutePath);
233 }
234
235
236
237
238
239 public boolean moveItem(Item source, Item target) throws RepositoryException {
240 if (!basicMoveCheck(source, target)) {
241 return false;
242 }
243 NodeUtil.moveNode((Node) source, (Node) target);
244 source.getSession().save();
245
246 return true;
247 }
248
249 public boolean moveItemBefore(Item source, Item target) throws RepositoryException {
250 if (!basicMoveCheck(source, target)) {
251 return false;
252 }
253
254 NodeUtil.moveNodeBefore((Node) source, (Node) target);
255 source.getSession().save();
256
257 return true;
258 }
259
260 public boolean moveItemAfter(Item source, Item target) throws RepositoryException {
261 if (!basicMoveCheck(source, target)) {
262 return false;
263 }
264
265 NodeUtil.moveNodeAfter((Node) source, (Node) target);
266 source.getSession().save();
267
268 return true;
269 }
270
271
272
273
274 private boolean basicMoveCheck(Item source, Item target) throws RepositoryException {
275
276 if (!target.isNode() && !source.isNode()) {
277 return false;
278 }
279
280 if (target.getPath().equals(source.getPath())) {
281 return false;
282 }
283
284 return !target.getPath().startsWith(source.getPath());
285 }
286
287
288
289
290 String getPathInTree(Item item) throws RepositoryException {
291 String base = getWorkbenchDefinition().getPath();
292 return "/".equals(base) ? item.getPath() : StringUtils.substringAfter(item.getPath(), base);
293 }
294
295 private Session getSession() throws RepositoryException {
296 return MgnlContext.getJCRSession(getWorkspace());
297 }
298
299 private Node getRootNode() throws RepositoryException {
300 return getSession().getNode(getWorkbenchDefinition().getPath());
301 }
302
303 private String getPathInWorkspace(String pathInTree) {
304
305 if (pathInTree.startsWith("/")) {
306 return pathInTree;
307 }
308 String base = getWorkbenchDefinition().getPath();
309 return base + pathInTree;
310 }
311
312 }