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.jcr.wrapper;
35
36 import info.magnolia.cms.core.MgnlNodeType;
37 import info.magnolia.jcr.RuntimeRepositoryException;
38 import info.magnolia.jcr.iterator.ChainedNodeIterator;
39 import info.magnolia.jcr.iterator.FilteringNodeIterator;
40 import info.magnolia.jcr.predicate.AbstractPredicate;
41
42 import java.util.ArrayList;
43 import java.util.List;
44
45 import javax.jcr.Node;
46 import javax.jcr.NodeIterator;
47 import javax.jcr.PathNotFoundException;
48 import javax.jcr.Property;
49 import javax.jcr.RepositoryException;
50
51 import org.apache.commons.lang.StringUtils;
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 public class InheritanceNodeWrapper extends ChildWrappingNodeWrapper {
73
74 private final Node start;
75 private final AbstractPredicate<Node> filter;
76
77 public InheritanceNodeWrapper(Node node) {
78 this(node, node);
79 }
80
81 public InheritanceNodeWrapper(Node node, AbstractPredicate<Node> filter) {
82 this(node, node, filter);
83 }
84
85 public InheritanceNodeWrapper(Node node, Node start, AbstractPredicate<Node> filter) {
86 super(node);
87 this.start = start;
88 this.filter = filter;
89 }
90
91 public InheritanceNodeWrapper(Node node, Node start) {
92 super(node);
93 this.start = start;
94 this.filter = new AbstractPredicate<Node>() {
95
96 @Override
97 public boolean evaluateTyped(Node t) {
98 return true;
99 }
100 };
101 }
102
103
104
105
106 protected InheritanceNodeWrapper findAnchor() throws RepositoryException{
107 if(this.getDepth() == 0){
108 return null;
109 }
110 if(isAnchor()){
111 return this;
112 }
113
114 return ((InheritanceNodeWrapper)wrapNode(this.getParent())).findAnchor();
115 }
116
117
118
119
120 protected InheritanceNodeWrapper findNextAnchor() throws RepositoryException{
121 final InheritanceNodeWrapper currentAnchor = findAnchor();
122 if(currentAnchor != null && this.getDepth() >0){
123 return ((InheritanceNodeWrapper)wrapNode(currentAnchor.getParent())).findAnchor();
124 }
125 return null;
126 }
127
128
129
130
131 protected boolean isAnchor() {
132 try {
133 return this.isNodeType(MgnlNodeType.NT_CONTENT);
134 } catch (RepositoryException e) {
135 throw new RuntimeRepositoryException(e);
136 }
137 }
138
139
140
141
142 protected Node getNodeSafely(String relPath) throws RepositoryException {
143 if(getWrappedNode().hasNode(relPath)) {
144 return wrapNode(getWrappedNode().getNode(relPath));
145 }
146
147 String innerPath = resolveInnerPath() + "/" + relPath;
148 innerPath = StringUtils.removeStart(innerPath,"/");
149
150 Node inherited = getNodeSafely(findNextAnchor(), innerPath);
151 return inherited;
152 }
153
154
155
156
157 protected String resolveInnerPath() throws RepositoryException {
158 final String path;
159 InheritanceNodeWrapper anchor = findAnchor();
160
161 if(anchor == null){
162 path = this.getPath();
163 }
164 else{
165 path = StringUtils.substringAfter(this.getPath(), anchor.getPath());
166 }
167 return StringUtils.removeStart(path,"/");
168 }
169
170
171
172
173 protected Node getNodeSafely(InheritanceNodeWrapper anchor, String path) throws RepositoryException{
174 if(anchor == null){
175 return null;
176 }
177 if(StringUtils.isEmpty(path)){
178 return anchor;
179 }
180 return anchor.getNodeSafely(path);
181 }
182
183
184 @Override
185 public boolean hasNode(String relPath) throws RepositoryException {
186 return getNodeSafely(relPath) != null;
187 }
188
189 @Override
190 public Node getNode(String relPath) throws PathNotFoundException, RepositoryException {
191 Node inherited = getNodeSafely(relPath);
192 if (inherited == null || !filter.evaluateTyped(inherited)) {
193 throw new PathNotFoundException("Can't inherit a node [" + relPath + "] on node [" + getWrappedNode().getPath() + "]");
194 }
195 return wrapNode(inherited);
196 }
197
198 @Override
199 public NodeIterator getNodes() throws RepositoryException {
200 List<NodeIterator> nodes = new ArrayList<NodeIterator>();
201
202
203 try {
204 Node inherited = getNodeSafely(findNextAnchor(), resolveInnerPath());
205 if(inherited != null && !inherited.getPath().startsWith(this.getPath())){
206 nodes.add(inherited.getNodes());
207 }
208 }
209 catch (RepositoryException e) {
210 throw new RuntimeException("Can't inherit children from " + getWrappedNode(), e);
211 }
212
213 nodes.add(getWrappedNode().getNodes());
214
215 return wrapNodeIterator(new FilteringNodeIterator(new ChainedNodeIterator(nodes), filter));
216 }
217
218 @Override
219 public NodeIterator getNodes(String namePattern) throws RepositoryException {
220 List<NodeIterator> nodes = new ArrayList<NodeIterator>();
221
222
223 try {
224 Node inherited = getNodeSafely(findNextAnchor(), resolveInnerPath());
225 if(inherited != null && !inherited.getPath().startsWith(this.getPath())){
226 nodes.add(inherited.getNodes(namePattern));
227 }
228 }
229 catch (RepositoryException e) {
230 throw new RepositoryException("Can't inherit children from " + getWrappedNode(), e);
231 }
232
233 nodes.add(getWrappedNode().getNodes(namePattern));
234
235 return wrapNodeIterator(new FilteringNodeIterator(new ChainedNodeIterator(nodes), filter));
236 }
237
238 @Override
239 public Property getProperty(String relPath) throws PathNotFoundException, RepositoryException {
240 try {
241 if (getWrappedNode().hasProperty(relPath)) {
242 return getWrappedNode().getProperty(relPath);
243 }
244 Node inherited = getNodeSafely(findNextAnchor(), resolveInnerPath());
245 if(inherited != null){
246 return inherited.getProperty(relPath);
247 } else {
248 throw new PathNotFoundException("No property exists at " + relPath + " or current Session does not have read access to it.");
249 }
250 }
251 catch (RepositoryException e) {
252 throw new RepositoryException("Can't inherit property " + relPath + " for " + getWrappedNode(), e);
253 }
254 }
255
256 @Override
257 public boolean hasProperty(String name) throws RepositoryException {
258 try {
259 if (getWrappedNode().hasProperty(name)) {
260 return true;
261 }
262 Node inherited = getNodeSafely(findNextAnchor(), resolveInnerPath());
263 if (inherited != null) {
264 return inherited.hasProperty(name);
265 }
266 } catch (RepositoryException e) {
267 throw new RuntimeException("Can't inherit nodedata " + name + " for " + getWrappedNode(), e);
268
269 }
270
271 return super.hasProperty(name);
272 }
273
274
275
276
277 public boolean isInherited() {
278 try {
279 return !this.getPath().startsWith(start.getPath());
280 } catch (RepositoryException e) {
281 throw new RuntimeRepositoryException(e);
282 }
283 }
284
285 @Override
286 public Node wrapNode(Node node) {
287 if(node instanceof InheritanceNodeWrapper) {
288 return node;
289 }
290 return new InheritanceNodeWrapper(node, start, filter);
291 }
292 }