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