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