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 public ExtendingContentWrapper(Content wrappedContent) {
127 this(wrappedContent, false);
128 }
129
130
131
132
133
134 protected ExtendingContentWrapper(Content wrappedContent, Content extendedContent) {
135 super(wrapIfNeeded(wrappedContent));
136 extending = true;
137 try {
138 if (getWrappedContent().hasNodeData(EXTENDING_NODE_DATA)) {
139 NodeData extendingNodeData = getWrappedContent().getNodeData(EXTENDING_NODE_DATA);
140
141
142 extending = !EXTENDING_NODE_DATA_OVERRIDE.equals(extendingNodeData.getString());
143 }
144 }
145 catch (RepositoryException e) {
146 throw new RuntimeException("Can't determine extends point for node [" + wrappedContent + "]", e);
147 }
148
149 this.extendedContent = wrapIfNeeded(extendedContent);
150 }
151
152 private boolean isExists(String extendedNode, Content parent) throws RepositoryException {
153 if (extendedNode.startsWith("/")){
154 return getWrappedContent().getHierarchyManager().isExist(extendedNode);
155 }
156 return parent.hasContent(extendedNode);
157 }
158
159 private static Content wrapIfNeeded(Content content) {
160 if (content instanceof ExtendingContentWrapper) {
161 return content;
162 }
163 return new ExtendingContentWrapper(content);
164 }
165
166 public boolean isExtending() {
167 return this.extending;
168 }
169
170 @Override
171 public Content getWrappedContent() {
172 Content wrapped = super.getWrappedContent();
173 if (wrapped instanceof ExtendingContentWrapper) {
174 ExtendingContentWrapper wrappedECW = (ExtendingContentWrapper) wrapped;
175 if (!wrappedECW.extending) {
176
177 return ((ExtendingContentWrapper) wrapped).getWrappedContent();
178 }
179 }
180 return super.getWrappedContent();
181 }
182 @Override
183 public boolean hasContent(String name) throws RepositoryException {
184 if (getWrappedContent().hasContent(name)) {
185 return true;
186 }
187 else if (extending && extendedContent.hasContent(name)) {
188 return true;
189 }
190 return false;
191 }
192
193 @Override
194 public Content getContent(String name) throws RepositoryException {
195 Content content;
196 if (getWrappedContent().hasContent(name)) {
197 content = getWrappedContent().getContent(name);
198 }
199 else if (extending && extendedContent.hasContent(name)) {
200 content = extendedContent.getContent(name);
201 }
202 else {
203
204 content = getWrappedContent().getContent(name);
205 }
206 return wrap(content);
207 }
208
209 @Override
210 public Collection<Content> getChildren(ContentFilter filter, String namePattern, Comparator<Content> orderCriteria) {
211 Collection<Content> directChildren = ((AbstractContent)getWrappedContent()).getChildren(filter, namePattern, orderCriteria);
212 if (extending) {
213 Collection<Content> inheritedChildren = ((AbstractContent)extendedContent).getChildren(filter, namePattern, orderCriteria);
214
215 LinkedHashMap<String, Content> merged = new LinkedHashMap<String, Content>();
216 for (Content content : inheritedChildren) {
217 merged.put(content.getName(), content);
218 }
219 for (Content content : directChildren) {
220 merged.put(content.getName(), content);
221 }
222 return wrapContentNodes(merged.values());
223 }
224 return wrapContentNodes(directChildren);
225 }
226
227 @Override
228 public NodeData getNodeData(String name) {
229 if (EXTENDING_NODE_DATA.equals(name)) {
230 return new DefaultNodeData(extendedContent, name) {
231 @Override
232 public boolean isExist() {
233 return false;
234 }
235
236 @Override
237 public void save() throws RepositoryException {
238
239 }
240 };
241 }
242 try {
243 if (getWrappedContent().hasNodeData(name)) {
244 return wrap(getWrappedContent().getNodeData(name));
245 }
246 else if (extending && extendedContent.hasNodeData(name)) {
247 return wrap(extendedContent.getNodeData(name));
248 }
249 else {
250 return wrap(getWrappedContent().getNodeData(name));
251 }
252 }
253 catch (RepositoryException e) {
254 throw new RuntimeException("Can't read nodedata from extended node [" + extendedContent + "]", e);
255 }
256 }
257
258 @Override
259 public boolean hasNodeData(String name) throws RepositoryException {
260 if (EXTENDING_NODE_DATA.equals(name)) {
261 return false;
262 }
263 return super.hasNodeData(name);
264 }
265
266 @Override
267 public Collection<NodeData> getNodeDataCollection() {
268 final Content wrapped = getWrappedContent();
269 Collection<NodeData> directChildren = wrapped.getNodeDataCollection();
270 try {
271 if (wrapped.hasNodeData(EXTENDING_NODE_DATA)) {
272 for (NodeData child : directChildren) {
273 if (EXTENDING_NODE_DATA.equals(child.getName())) {
274 directChildren.remove(child);
275 break;
276 }
277 }
278 }
279 } catch (RepositoryException e) {
280 throw new RuntimeException("Can't read nodedata collection from node [" + wrapped.getHandle() + "]", e);
281 }
282 if (extending) {
283 Collection<NodeData> inheritedChildren = extendedContent.getNodeDataCollection();
284
285 SortedMap<String, NodeData> merged = new TreeMap<String, NodeData>();
286 for (NodeData nodeData : inheritedChildren) {
287 merged.put(nodeData.getName(), nodeData);
288 }
289 for (NodeData nodeData : directChildren) {
290 merged.put(nodeData.getName(), nodeData);
291 }
292 return wrapNodeDatas(merged.values());
293 }
294 return wrapNodeDatas(directChildren);
295 }
296
297 @Override
298 protected Content wrap(Content node) {
299
300 try {
301 if (extending && extendedContent.hasContent(node.getName())) {
302
303 Content extendedSubContent = extendedContent.getContent(node.getName());
304 return new ExtendingContentWrapper(node, extendedSubContent);
305 }
306 }
307 catch (RepositoryException e) {
308 throw new RuntimeException("Can't wrap " + node, e);
309 }
310 return wrapIfNeeded(node);
311 }
312
313 }