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.templating.inheritance;
35
36 import info.magnolia.jcr.inheritance.InheritanceContentDecorator;
37 import info.magnolia.jcr.iterator.RangeIteratorImpl;
38 import info.magnolia.jcr.predicate.AbstractPredicate;
39 import info.magnolia.jcr.util.NodeTypes;
40 import info.magnolia.rendering.template.InheritanceConfiguration;
41
42 import java.util.ArrayList;
43 import java.util.Collection;
44 import java.util.Collections;
45 import java.util.Comparator;
46 import java.util.List;
47
48 import javax.jcr.Node;
49 import javax.jcr.NodeIterator;
50 import javax.jcr.RepositoryException;
51
52 import org.apache.commons.lang3.StringUtils;
53
54
55
56
57
58
59
60
61
62
63
64 public class DefaultInheritanceContentDecorator extends InheritanceContentDecorator {
65
66 private final InheritanceConfiguration configuration;
67 private final AbstractPredicate<Node> componentPredicate;
68 private final Comparator<Node> componentComparator;
69
70 public DefaultInheritanceContentDecorator(Node destination, InheritanceConfiguration configuration) throws RepositoryException {
71 super(destination);
72 this.configuration = configuration;
73
74 componentPredicate = configuration.getComponentPredicate();
75
76 componentComparator = configuration.getComponentComparator();
77
78 if (configuration.isEnabled() != null && configuration.isEnabled()) {
79
80 Node firstAnchor = findFirstAnchor();
81
82 if (firstAnchor != null && firstAnchor.getDepth() != 0) {
83
84
85 String relativePathToAnchor = getPathRelativeToParent(firstAnchor, getDestination());
86
87 Node node = firstAnchor.getParent();
88 while (node.getDepth() != 0) {
89
90 if (isAnchor(node)) {
91
92 Node source = null;
93 if (relativePathToAnchor == null) {
94 source = node;
95 } else {
96 if (node.hasNode(relativePathToAnchor)) {
97 source = node.getNode(relativePathToAnchor);
98 }
99 }
100
101 if (source != null) {
102 addSource(source);
103 }
104 }
105
106 node = node.getParent();
107 }
108 }
109 }
110 }
111
112 protected Node findFirstAnchor() throws RepositoryException {
113 Node node = getDestination();
114 while (node.getDepth() != 0) {
115 if (isAnchor(node)) {
116 return node;
117 }
118 node = node.getParent();
119 }
120 return null;
121 }
122
123 private String getPathRelativeToParent(Node parent, Node child) throws RepositoryException {
124 String childPath = child.getPath();
125 if (parent.getDepth() == 0) {
126 return childPath;
127 }
128 String parentPathWithTrailingSlash = parent.getPath() + "/";
129 if (!childPath.startsWith(parentPathWithTrailingSlash)) {
130 return null;
131 }
132 return StringUtils.removeStart(childPath, parentPathWithTrailingSlash);
133 }
134
135
136
137
138
139
140
141
142 protected boolean isAnchor(Node node) throws RepositoryException {
143 return node.isNodeType(NodeTypes.Content.NAME);
144 }
145
146 @Override
147 protected boolean inheritsNodes(Node node) throws RepositoryException {
148 return configuration.isInheritsComponents();
149 }
150
151 @Override
152 protected boolean inheritsProperties(Node node) throws RepositoryException {
153 return configuration.isInheritsProperties();
154 }
155
156 @Override
157 protected boolean isSourceChildInherited(Node node) throws RepositoryException {
158 return componentPredicate.evaluateTyped(node);
159 }
160
161 @Override
162 protected NodeIterator sortInheritedNodes(NodeIterator destinationChildren, List<NodeIterator> sourceChildren) throws RepositoryException {
163 ArrayList<Node> nodes = new ArrayList<Node>();
164 while (destinationChildren.hasNext()) {
165 Node node = destinationChildren.nextNode();
166 nodes.add(node);
167 }
168 for (NodeIterator nodeIterator : sourceChildren) {
169 while (nodeIterator.hasNext()) {
170 Node node = nodeIterator.nextNode();
171 if (isSourceChildInherited(node)) {
172 nodes.add(node);
173 }
174 }
175 }
176 Collections.sort(nodes, componentComparator);
177 return new NodeIteratorImpl(nodes);
178 }
179
180 private static class NodeIteratorImpl extends RangeIteratorImpl<Node> implements NodeIterator {
181
182 private NodeIteratorImpl(Collection<Node> nodes) {
183 super(nodes);
184 }
185
186 @Override
187 public Node nextNode() {
188 return super.next();
189 }
190 }
191 }