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 @Override
104
105 public void setWrappedNode(Node node) {
106 this.wrapped = node;
107 }
108
109
110
111
112 protected InheritanceNodeWrapper findAnchor() throws RepositoryException{
113 if(this.getDepth() == 0){
114 return null;
115 }
116 if(isAnchor()){
117 return this;
118 }
119
120 return ((InheritanceNodeWrapper)wrapNode(this.getParent())).findAnchor();
121 }
122
123
124
125
126 protected InheritanceNodeWrapper findNextAnchor() throws RepositoryException{
127 final InheritanceNodeWrapper currentAnchor = findAnchor();
128 if(currentAnchor != null && this.getDepth() >0){
129 return ((InheritanceNodeWrapper)wrapNode(currentAnchor.getParent())).findAnchor();
130 }
131 return null;
132 }
133
134
135
136
137 protected boolean isAnchor() {
138 try {
139 return this.isNodeType(MgnlNodeType.NT_CONTENT);
140 } catch (RepositoryException e) {
141 throw new RuntimeRepositoryException(e);
142 }
143 }
144
145
146
147
148 protected Node getNodeSafely(String relPath) throws RepositoryException {
149 if(getWrappedNode().hasNode(relPath)) {
150 return wrapNode(getWrappedNode().getNode(relPath));
151 }
152
153 String innerPath = resolveInnerPath() + "/" + relPath;
154 innerPath = StringUtils.removeStart(innerPath,"/");
155
156 Node inherited = getNodeSafely(findNextAnchor(), innerPath);
157 return inherited;
158 }
159
160
161
162
163 protected String resolveInnerPath() throws RepositoryException {
164 final String path;
165 InheritanceNodeWrapper anchor = findAnchor();
166
167 if(anchor == null){
168 path = this.getPath();
169 }
170 else{
171 path = StringUtils.substringAfter(this.getPath(), anchor.getPath());
172 }
173 return StringUtils.removeStart(path,"/");
174 }
175
176
177
178
179 protected Node getNodeSafely(InheritanceNodeWrapper anchor, String path) throws RepositoryException{
180 if(anchor == null){
181 return null;
182 }
183 if(StringUtils.isEmpty(path)){
184 return anchor;
185 }
186 return anchor.getNodeSafely(path);
187 }
188
189
190 @Override
191 public boolean hasNode(String relPath) throws RepositoryException {
192 return getNodeSafely(relPath) != null;
193 }
194
195 @Override
196 public Node getNode(String relPath) throws PathNotFoundException, RepositoryException {
197 Node inherited = getNodeSafely(relPath);
198 if (inherited == null || !filter.evaluateTyped(inherited)) {
199 throw new PathNotFoundException("Can't inherit a node [" + relPath + "] on node [" + getWrappedNode().getPath() + "]");
200 }
201 return wrapNode(inherited);
202 }
203
204 @Override
205 public NodeIterator getNodes() throws RepositoryException {
206 List<NodeIterator> nodes = new ArrayList<NodeIterator>();
207
208
209 try {
210 Node inherited = getNodeSafely(findNextAnchor(), resolveInnerPath());
211 if(inherited != null && !inherited.getPath().startsWith(this.getPath())){
212 nodes.add(inherited.getNodes());
213 }
214 }
215 catch (RepositoryException e) {
216 throw new RuntimeException("Can't inherit children from " + getWrappedNode(), e);
217 }
218
219 nodes.add(getWrappedNode().getNodes());
220
221 return wrapNodeIterator(new FilteringNodeIterator(new ChainedNodeIterator(nodes), filter));
222 }
223
224 @Override
225 public NodeIterator getNodes(String namePattern) throws RepositoryException {
226 List<NodeIterator> nodes = new ArrayList<NodeIterator>();
227
228
229 try {
230 Node inherited = getNodeSafely(findNextAnchor(), resolveInnerPath());
231 if(inherited != null && !inherited.getPath().startsWith(this.getPath())){
232 nodes.add(inherited.getNodes(namePattern));
233 }
234 }
235 catch (RepositoryException e) {
236 throw new RepositoryException("Can't inherit children from " + getWrappedNode(), e);
237 }
238
239 nodes.add(getWrappedNode().getNodes(namePattern));
240
241 return wrapNodeIterator(new FilteringNodeIterator(new ChainedNodeIterator(nodes), filter));
242 }
243
244 @Override
245 public Property getProperty(String relPath) throws PathNotFoundException, RepositoryException {
246 try {
247 if (getWrappedNode().hasProperty(relPath)) {
248 return getWrappedNode().getProperty(relPath);
249 }
250 Node inherited = getNodeSafely(findNextAnchor(), resolveInnerPath());
251 if(inherited != null){
252 return inherited.getProperty(relPath);
253 } else {
254 throw new PathNotFoundException("No property exists at " + relPath + " or current Session does not have read access to it.");
255 }
256 }
257 catch (RepositoryException e) {
258 throw new RepositoryException("Can't inherit property " + relPath + " for " + getWrappedNode(), e);
259 }
260 }
261
262 @Override
263 public boolean hasProperty(String name) throws RepositoryException {
264 try {
265 if (getWrappedNode().hasProperty(name)) {
266 return true;
267 }
268 Node inherited = getNodeSafely(findNextAnchor(), resolveInnerPath());
269 if (inherited != null) {
270 return inherited.hasProperty(name);
271 }
272 } catch (RepositoryException e) {
273 throw new RuntimeException("Can't inherit nodedata " + name + " for " + getWrappedNode(), e);
274
275 }
276
277 return super.hasProperty(name);
278 }
279
280
281
282
283 public boolean isInherited() {
284 try {
285 return !this.getPath().startsWith(start.getPath());
286 } catch (RepositoryException e) {
287 throw new RuntimeRepositoryException(e);
288 }
289 }
290
291 @Override
292 public Node wrapNode(Node node) {
293 if(node instanceof InheritanceNodeWrapper) {
294 return node;
295 }
296 return new InheritanceNodeWrapper(node, start, filter);
297 }
298 }