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.contentapp;
35
36 import static info.magnolia.ui.contentapp.JcrDataProviderUtils.*;
37
38 import info.magnolia.jcr.RuntimeRepositoryException;
39 import info.magnolia.jcr.iterator.FilteringPropertyIterator;
40 import info.magnolia.jcr.predicate.AbstractPredicate;
41 import info.magnolia.jcr.predicate.JCRMgnlPropertyHidingPredicate;
42 import info.magnolia.jcr.util.NodeUtil;
43 import info.magnolia.ui.datasource.jcr.JcrDatasource;
44 import info.magnolia.ui.datasource.jcr.JcrDatasourceDefinition;
45 import info.magnolia.ui.filter.DataFilter;
46
47 import java.util.Collection;
48 import java.util.Comparator;
49 import java.util.stream.Stream;
50
51 import javax.jcr.Item;
52 import javax.jcr.Node;
53 import javax.jcr.Property;
54 import javax.jcr.RepositoryException;
55
56 import com.google.common.collect.Lists;
57 import com.machinezoo.noexception.Exceptions;
58 import com.vaadin.data.provider.AbstractBackEndHierarchicalDataProvider;
59 import com.vaadin.data.provider.HierarchicalQuery;
60 import com.vaadin.data.provider.Query;
61
62
63
64
65 public class HierarchicalJcrDataProvider extends AbstractBackEndHierarchicalDataProvider<Item, DataFilter> {
66
67 private final JcrDatasource datasource;
68 private final JcrDatasourceDefinition datasourceDefinition;
69
70 public HierarchicalJcrDataProvider(JcrDatasourceDefinition definition, JcrDatasource datasource) {
71 this.datasource = datasource;
72 this.datasourceDefinition = definition;
73 }
74
75 @Override
76 public int getChildCount(HierarchicalQuery<Item, DataFilter> query) {
77 Item parent = query.getParent() == null ? getRootNode() : query.getParent();
78 return (int) getChildren(parent, datasourceDefinition.isIncludeProperties(), query).count();
79 }
80
81 @Override
82 public boolean hasChildren(Item item) {
83 return getChildren(item, datasourceDefinition.isIncludeProperties(), new Query<>()).count() > 0;
84 }
85
86 @Override
87 protected Stream<Item> fetchChildrenFromBackEnd(HierarchicalQuery<Item, DataFilter> query) {
88 final Item parent = query.getParent() == null ? getRootNode() : query.getParent();
89 return getChildren(parent, datasourceDefinition.isIncludeProperties(), query)
90 .skip(query.getOffset())
91 .limit(query.getLimit());
92 }
93
94 private Item getRootNode() {
95 try {
96 return datasource.getJCRSession().getNode(datasourceDefinition.getRootPath());
97 } catch (RepositoryException e) {
98 throw new RuntimeRepositoryException(e);
99 }
100 }
101
102 private Stream<Item> getChildren(Item item, boolean includeProperties, Query<Item, DataFilter> query) {
103 Stream<? extends Item> stream = Stream.empty();
104 if (item.isNode()) {
105 Node node = (Node) item;
106 Collection<AbstractPredicate<Node>> predicates = query.getFilter()
107 .map(dataFilter -> Lists.newArrayList(new NodeTypeFilteringPredicate(datasourceDefinition), new PropertyFilteringPredicate(query), new ActivationStatusFilteringPredicate(query)))
108 .orElse(Lists.newArrayList(new NodeTypeFilteringPredicate(datasourceDefinition)));
109
110 stream = streamJcrItems((Exceptions.wrap().get(() -> NodeUtil.getNodes(node, new ChainedPredicate(predicates)).iterator())));
111 if (includeProperties) {
112 Stream<Property> properties = streamJcrItems(Exceptions.wrap().get(() -> new FilteringPropertyIterator(node.getProperties(), shouldIncludeSystemProperties(query) ? new AlwaysTruePredicate() : new JCRMgnlPropertyHidingPredicate())));
113 stream = Stream.concat(stream, properties.sorted(Comparator.comparing(Exceptions.wrap().function(Item::getName))));
114 }
115 }
116 return (Stream<Item>) stream;
117 }
118
119 private boolean shouldIncludeSystemProperties(Query<Item, DataFilter> query) {
120 return query.getFilter()
121 .map(dataFilter -> dataFilter.<Boolean>getProperty("includeSystemProperties"))
122 .orElse(false);
123 }
124 }