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;
35
36 import info.magnolia.context.MgnlContext;
37 import info.magnolia.jcr.util.NodeTypes;
38 import info.magnolia.jcr.util.NodeUtil;
39 import info.magnolia.ui.vaadin.integration.contentconnector.JcrContentConnectorDefinition;
40 import info.magnolia.ui.vaadin.integration.contentconnector.NodeTypeDefinition;
41 import info.magnolia.ui.vaadin.integration.jcr.JcrItemAdapter;
42 import info.magnolia.ui.vaadin.integration.jcr.JcrItemId;
43 import info.magnolia.ui.vaadin.integration.jcr.JcrItemUtil;
44 import info.magnolia.ui.workbench.container.AbstractJcrContainer;
45
46 import java.util.ArrayList;
47 import java.util.Collection;
48 import java.util.Collections;
49 import java.util.Comparator;
50 import java.util.List;
51
52 import javax.jcr.Item;
53 import javax.jcr.Node;
54 import javax.jcr.NodeIterator;
55 import javax.jcr.Property;
56 import javax.jcr.PropertyIterator;
57 import javax.jcr.RepositoryException;
58 import javax.jcr.Session;
59
60 import org.apache.commons.lang3.StringUtils;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63
64 import com.vaadin.data.Container;
65
66
67
68
69 public class HierarchicalJcrContainer extends AbstractJcrContainer implements Container.Hierarchical {
70
71 private static final Logger log = LoggerFactory.getLogger(HierarchicalJcrContainer.class);
72
73 private static class ItemNameComparator implements Comparator<Item> {
74 @Override
75 public int compare(Item lhs, Item rhs) {
76 try {
77 return lhs.getName().compareTo(rhs.getName());
78 } catch (RepositoryException e) {
79 log.warn("Cannot compare item names: " + e);
80 return 0;
81 }
82 }
83 }
84
85 public HierarchicalJcrContainer(JcrContentConnectorDefinition definition) {
86 super(definition);
87 }
88
89 @Override
90 public Collection<JcrItemId> getChildren(Object itemId) {
91 long start = System.currentTimeMillis();
92 Collection<Item> children = getChildren(getJcrItem(itemId));
93 log.debug("Fetched {} children in {}ms", children.size(), System.currentTimeMillis() - start);
94 return createContainerIds(children);
95 }
96
97 @Override
98 public JcrItemId getParent(Object itemId) {
99 try {
100 Item item = getJcrItem(itemId);
101 if (item.isNode() && item.getDepth() == 0) {
102 return null;
103 }
104 return JcrItemUtil.getItemId(item.getParent());
105 } catch (RepositoryException e) {
106 handleRepositoryException(log, "Cannot determine parent for itemId: " + itemId, e);
107 return null;
108 }
109 }
110
111 @Override
112 public Collection<JcrItemId> rootItemIds() {
113 try {
114 return createContainerIds(getRootItemIds());
115 } catch (RepositoryException e) {
116 handleRepositoryException(log, "Cannot retrieve root item id's", e);
117 return Collections.emptySet();
118 }
119 }
120
121 @Override
122 public void refresh() {
123 resetOffset();
124 clearItemIndexes();
125 fireItemSetChange();
126 }
127
128 @Override
129 public boolean setParent(Object itemId, Object newParentId) throws UnsupportedOperationException {
130 fireItemSetChange();
131 return true;
132 }
133
134 @Override
135 public boolean areChildrenAllowed(Object itemId) {
136 final JcrItemAdapter item = ((JcrItemAdapter) getItem(itemId));
137 if (item == null) {
138 return false;
139 }
140 return item.isNode() && hasChildren(itemId);
141 }
142
143 @Override
144 public boolean setChildrenAllowed(Object itemId, boolean areChildrenAllowed) throws UnsupportedOperationException {
145 throw new UnsupportedOperationException();
146 }
147
148 @Override
149 public boolean isRoot(Object itemId) {
150 try {
151 return isRoot(getJcrItem(itemId));
152 } catch (RepositoryException e) {
153 handleRepositoryException(log, "Cannot determine whether item is root - itemId: " + itemId, e);
154 return true;
155 }
156 }
157
158 @Override
159 public boolean hasChildren(Object itemId) {
160 final Item item = getJcrItem(itemId);
161 return item.isNode() && !getChildren(item).isEmpty();
162 }
163
164 protected Collection<JcrItemId> createContainerIds(Collection<Item> children) {
165 ArrayList<JcrItemId> ids = new ArrayList<JcrItemId>();
166 for (Item child : children) {
167 try {
168 JcrItemId itemId = JcrItemUtil.getItemId(child);
169 ids.add(itemId);
170 } catch (RepositoryException e) {
171 handleRepositoryException(log, "Cannot retrieve currentId", e);
172 }
173 }
174 return ids;
175 }
176
177 @Override
178 public List<String> getSortableContainerPropertyIds() {
179
180 return Collections.emptyList();
181 }
182
183 public Collection<Item> getChildren(Item item) {
184 if (!item.isNode()) {
185 return Collections.emptySet();
186 }
187
188 Node node = (Node) item;
189
190 ArrayList<Item> items = new ArrayList<Item>();
191
192 try {
193 NodeIterator iterator = node.getNodes();
194 while (iterator.hasNext()) {
195 Node next = iterator.nextNode();
196 if (isNodeVisible(next)) {
197 items.add(next);
198 }
199 }
200
201 if (getConfiguration().isIncludeProperties()) {
202 ArrayList<Property> properties = new ArrayList<Property>();
203 PropertyIterator propertyIterator = node.getProperties();
204 while (propertyIterator.hasNext()) {
205 final Property property = propertyIterator.nextProperty();
206 final String propertyName = property.getName();
207 if (!propertyName.startsWith(NodeTypes.JCR_PREFIX) && !propertyName.startsWith(NodeTypes.MGNL_PREFIX)) {
208 properties.add(property);
209 }
210 }
211 ItemNameComparator itemNameComparator = new ItemNameComparator();
212 Collections.sort(properties, itemNameComparator);
213 items.addAll(properties);
214 }
215 } catch (RepositoryException e) {
216 handleRepositoryException(log, "Could not retrieve children", e);
217 }
218
219 return Collections.unmodifiableCollection(items);
220 }
221
222 protected boolean isNodeVisible(Node node) throws RepositoryException {
223
224 if (!getConfiguration().isIncludeSystemNodes() && node.getName().startsWith("jcr:") || node.getName().startsWith("rep:")) {
225 return false;
226 }
227
228 String primaryNodeTypeName = node.getPrimaryNodeType().getName();
229 for (NodeTypeDefinition nodeTypeDefinition : getConfiguration().getNodeTypes()) {
230 if (nodeTypeDefinition.isStrict()) {
231 if (primaryNodeTypeName.equals(nodeTypeDefinition.getName())) {
232 return true;
233 }
234 } else if (NodeUtil.isNodeType(node, nodeTypeDefinition.getName())) {
235 return true;
236 }
237 }
238 return false;
239 }
240
241 public Collection<Item> getRootItemIds() throws RepositoryException {
242 return getChildren(getRootNode());
243 }
244
245
246
247
248
249 public boolean isRoot(Item item) throws RepositoryException {
250 if (item != null) {
251 try {
252 int rootDepth = getRootNode().getDepth();
253 return item.getDepth() <= rootDepth + 1;
254 } catch (RepositoryException e) {
255 handleRepositoryException(log, "Cannot determine depth of jcr item", e);
256 }
257 }
258 return true;
259 }
260
261
262
263
264 String getPathInTree(Item item) throws RepositoryException {
265 String base = getConfiguration().getRootPath();
266 return "/".equals(base) ? item.getPath() : StringUtils.substringAfter(item.getPath(), base);
267 }
268
269 private Session getSession() throws RepositoryException {
270 return MgnlContext.getJCRSession(getWorkspace());
271 }
272
273 private Node getRootNode() throws RepositoryException {
274 return getSession().getNode(getConfiguration().getRootPath());
275 }
276 }