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.cms.util;
35
36 import info.magnolia.cms.core.AbstractContent;
37 import info.magnolia.cms.core.Content;
38 import info.magnolia.cms.core.DefaultNodeData;
39 import info.magnolia.cms.core.NodeData;
40
41 import java.util.Collection;
42 import java.util.Comparator;
43 import java.util.LinkedHashMap;
44 import java.util.SortedMap;
45 import java.util.TreeMap;
46
47 import javax.jcr.RepositoryException;
48
49 import org.apache.commons.lang.StringUtils;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 public class ExtendingContentWrapper extends ContentWrapper {
75
76 protected static final String EXTENDING_NODE_DATA = "extends";
77 protected static final String EXTENDING_NODE_DATA_OVERRIDE = "override";
78
79 private boolean extending;
80
81 private Content extendedContent;
82
83 private static final Logger log = LoggerFactory.getLogger(ExtendingContentWrapper.class);
84
85
86 ExtendingContentWrapper(Content wrappedContent, boolean failOnError) {
87
88 super(wrappedContent);
89 try {
90 extending = getWrappedContent().hasNodeData(EXTENDING_NODE_DATA);
91 if (extending) {
92 NodeData extendingNodeData = getWrappedContent().getNodeData(EXTENDING_NODE_DATA);
93
94
95 String extendedNode = extendingNodeData.getString();
96
97 Content parent = extendingNodeData.getParent();
98
99 if (StringUtils.isBlank(extendedNode)) {
100
101 extending = false;
102 } else if (EXTENDING_NODE_DATA_OVERRIDE.equals(extendedNode)) {
103 extending = false;
104 }
105 if (extending) {
106 if (isExists(extendedNode, parent)) {
107
108 extendedContent = wrapIfNeeded(extendingNodeData.getReferencedContent());
109 } else {
110 String message = "Can't find referenced node for value: " + wrappedContent;
111 log.error(message);
112 extending = false;
113 if (failOnError) {
114 throw new RuntimeException(message);
115 }
116 }
117
118 }
119
120 }
121 } catch (RepositoryException e) {
122 throw new RuntimeException("Can't wrap node [" + wrappedContent + "]", e);
123 }
124 }
125
126
127 private boolean isExists(String extendedNode, Content parent) throws RepositoryException {
128 if (extendedNode.startsWith("/") && getWrappedContent().getHierarchyManager().isExist(extendedNode)) {
129 return true;
130 }
131
132 return parent.hasContent(extendedNode);
133 }
134
135 public ExtendingContentWrapper(Content wrappedContent) {
136 this(wrappedContent, false);
137 }
138
139
140
141
142
143 protected ExtendingContentWrapper(Content wrappedContent, Content extendedContent) {
144 super(wrapIfNeeded(wrappedContent));
145 extending = true;
146 try {
147 if (getWrappedContent().hasNodeData(EXTENDING_NODE_DATA)) {
148 NodeData extendingNodeData = getWrappedContent().getNodeData(EXTENDING_NODE_DATA);
149
150
151 extending = !EXTENDING_NODE_DATA_OVERRIDE.equals(extendingNodeData.getString());
152 }
153 }
154 catch (RepositoryException e) {
155 throw new RuntimeException("Can't determine extends point for node [" + wrappedContent + "]", e);
156 }
157
158 this.extendedContent = wrapIfNeeded(extendedContent);
159 }
160
161 private static Content wrapIfNeeded(Content content) {
162 if (content instanceof ExtendingContentWrapper) {
163 return content;
164 }
165 return new ExtendingContentWrapper(content);
166 }
167
168 public boolean isExtending() {
169 return this.extending;
170 }
171
172 @Override
173 public Content getWrappedContent() {
174 Content wrapped = super.getWrappedContent();
175 if (wrapped instanceof ExtendingContentWrapper) {
176 ExtendingContentWrapper wrappedECW = (ExtendingContentWrapper) wrapped;
177 if (!wrappedECW.extending) {
178
179 return ((ExtendingContentWrapper) wrapped).getWrappedContent();
180 }
181 }
182 return super.getWrappedContent();
183 }
184 @Override
185 public boolean hasContent(String name) throws RepositoryException {
186 if (getWrappedContent().hasContent(name)) {
187 return true;
188 }
189 else if (extending && extendedContent.hasContent(name)) {
190 return true;
191 }
192 return false;
193 }
194
195 @Override
196 public Content getContent(String name) throws RepositoryException {
197 Content content;
198 if (getWrappedContent().hasContent(name)) {
199 content = getWrappedContent().getContent(name);
200 }
201 else if (extending && extendedContent.hasContent(name)) {
202 content = extendedContent.getContent(name);
203 }
204 else {
205
206 content = getWrappedContent().getContent(name);
207 }
208 return wrap(content);
209 }
210
211 @Override
212 public Collection<Content> getChildren(ContentFilter filter, String namePattern, Comparator<Content> orderCriteria) {
213 Collection<Content> directChildren = ((AbstractContent)getWrappedContent()).getChildren(filter, namePattern, orderCriteria);
214 if (extending) {
215 Collection<Content> inheritedChildren = ((AbstractContent)extendedContent).getChildren(filter, namePattern, orderCriteria);
216
217 LinkedHashMap<String, Content> merged = new LinkedHashMap<String, Content>();
218 for (Content content : inheritedChildren) {
219 merged.put(content.getName(), content);
220 }
221 for (Content content : directChildren) {
222 merged.put(content.getName(), content);
223 }
224 return wrapContentNodes(merged.values());
225 }
226 else {
227 return wrapContentNodes(directChildren);
228 }
229 }
230
231 @Override
232 public NodeData getNodeData(String name) {
233 if (EXTENDING_NODE_DATA.equals(name)) {
234 return new DefaultNodeData(extendedContent, name) {
235 @Override
236 public boolean isExist() {
237 return false;
238 }
239
240 @Override
241 public void save() throws RepositoryException {
242
243 }
244 };
245 }
246 try {
247 if (getWrappedContent().hasNodeData(name)) {
248 return wrap(getWrappedContent().getNodeData(name));
249 }
250 else if (extending && extendedContent.hasNodeData(name)) {
251 return wrap(extendedContent.getNodeData(name));
252 }
253 else {
254 return wrap(getWrappedContent().getNodeData(name));
255 }
256 }
257 catch (RepositoryException e) {
258 throw new RuntimeException("Can't read nodedata from extended node [" + extendedContent + "]", e);
259 }
260 }
261
262 @Override
263 public boolean hasNodeData(String name) throws RepositoryException {
264 if (EXTENDING_NODE_DATA.equals(name)) {
265 return false;
266 }
267 return super.hasNodeData(name);
268 }
269
270 @Override
271 public Collection<NodeData> getNodeDataCollection() {
272 final Content wrapped = getWrappedContent();
273 Collection<NodeData> directChildren = wrapped.getNodeDataCollection();
274 try {
275 if (wrapped.hasNodeData(EXTENDING_NODE_DATA)) {
276 for (NodeData child : directChildren) {
277 if (EXTENDING_NODE_DATA.equals(child.getName())) {
278 directChildren.remove(child);
279 break;
280 }
281 }
282 }
283 } catch (RepositoryException e) {
284 throw new RuntimeException("Can't read nodedata collection from node [" + wrapped.getHandle() + "]", e);
285 }
286 if (extending) {
287 Collection<NodeData> inheritedChildren = extendedContent.getNodeDataCollection();
288
289 SortedMap<String, NodeData> merged = new TreeMap<String, NodeData>();
290 for (NodeData nodeData : inheritedChildren) {
291 merged.put(nodeData.getName(), nodeData);
292 }
293 for (NodeData nodeData : directChildren) {
294 merged.put(nodeData.getName(), nodeData);
295 }
296 return wrapNodeDatas(merged.values());
297 }
298 else {
299 return wrapNodeDatas(directChildren);
300 }
301 }
302
303 @Override
304 protected Content wrap(Content node) {
305
306 try {
307 if (extending && extendedContent.hasContent(node.getName())) {
308
309 Content extendedSubContent = extendedContent.getContent(node.getName());
310 return new ExtendingContentWrapper(node, extendedSubContent);
311 }
312 }
313 catch (RepositoryException e) {
314 throw new RuntimeException("Can't wrap " + node, e);
315 }
316 return wrapIfNeeded(node);
317 }
318
319 }