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