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.module.templating;
35
36 import java.io.Writer;
37 import java.lang.reflect.InvocationTargetException;
38 import java.util.HashMap;
39 import java.util.Iterator;
40 import java.util.Map;
41
42 import org.apache.commons.lang.exception.ExceptionUtils;
43
44 import info.magnolia.cms.core.Content;
45 import info.magnolia.cms.core.AggregationState;
46 import info.magnolia.cms.i18n.I18nContentWrapper;
47 import info.magnolia.context.MgnlContext;
48
49
50
51
52
53
54
55
56
57
58 public abstract class AbstractRenderer {
59
60 private static final String MODEL_ATTRIBUTE = RenderingModel.class.getName();
61
62 public AbstractRenderer() {
63 }
64
65 protected void render(Content content, RenderableDefinition definition, Writer out) throws RenderException {
66
67 final RenderingModel parentModel = (RenderingModel) MgnlContext.getAttribute(MODEL_ATTRIBUTE);
68 RenderingModel model;
69 try {
70 model = newModel(content, definition, parentModel);
71 }
72 catch (Exception e) {
73 throw new RenderException("Can't create rendering model: " + ExceptionUtils.getRootCauseMessage(e), e);
74 }
75
76 final String actionResult = model.execute();
77 if(RenderingModel.SKIP_RENDERING.equals(actionResult)){
78 return;
79 }
80 String templatePath = determineTemplatePath(content, definition, model, actionResult);
81
82 final Map ctx = newContext();
83 final Map savedContextState = saveContextState(ctx);
84 setupContext(ctx, content, definition, model, actionResult);
85 MgnlContext.setAttribute(MODEL_ATTRIBUTE, model);
86 onRender(content, definition, out, ctx, templatePath);
87 MgnlContext.setAttribute(MODEL_ATTRIBUTE, parentModel);
88
89 restoreContext(ctx, savedContextState);
90 }
91
92 protected String determineTemplatePath(Content content, RenderableDefinition definition, RenderingModel model, final String actionResult) {
93 String templatePath = definition.determineTemplatePath(actionResult, model);
94
95 if (templatePath == null) {
96 throw new IllegalStateException("Unable to render " + definition.getClass().getName() + " " + definition.getName() + " in page " + content.getHandle() + ": templatePath not set.");
97 }
98 return templatePath;
99 }
100
101
102
103
104 protected RenderingModel newModel(Content content, RenderableDefinition definition, RenderingModel parentModel) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
105 final Content wrappedContent = wrapNodeForModel(content, getMainContentSafely(content));
106 return definition.newModel(wrappedContent, definition, parentModel);
107 }
108
109
110 protected Map saveContextState(final Map ctx) {
111 Map state = new HashMap();
112
113 saveAttribute(ctx, state, "content");
114 saveAttribute(ctx, state, "actionResult");
115 saveAttribute(ctx, state, "state");
116 saveAttribute(ctx, state, "def");
117
118 saveAttribute(ctx, state, getPageAttributeName());
119 return state;
120 }
121
122 protected void saveAttribute(final Map ctx, Map state, String name) {
123 state.put(name, ctx.get(name));
124 }
125
126 protected void restoreContext(final Map ctx, Map state) {
127 for (Iterator iterator = state.keySet().iterator(); iterator.hasNext();) {
128 String name = (String) iterator.next();
129 setContextAttribute(ctx, name, state.get(name));
130 }
131 }
132
133 protected void setupContext(final Map ctx, Content content, RenderableDefinition definition, RenderingModel model, Object actionResult){
134 final Content mainContent = getMainContentSafely(content);
135
136 setContextAttribute(ctx, getPageAttributeName(), wrapNodeForTemplate(mainContent, mainContent));
137 setContextAttribute(ctx, "content", wrapNodeForTemplate(content, mainContent));
138 setContextAttribute(ctx, "def", definition);
139 setContextAttribute(ctx, "state", getAggregationStateSafely());
140 setContextAttribute(ctx, "mgnl", getMagnoliaTemplatingUtilities());
141 setContextAttribute(ctx, "model", model);
142 setContextAttribute(ctx, "actionResult", actionResult);
143 }
144
145
146
147
148 protected Content getMainContentSafely(Content current) {
149 AggregationState state = getAggregationStateSafely();
150 if(state != null){
151 return state.getMainContent();
152 }
153 return current;
154 }
155
156
157
158
159 protected AggregationState getAggrigationStateSafely() {
160 return getAggregationStateSafely();
161 }
162
163
164
165
166 protected AggregationState getAggregationStateSafely() {
167 if(MgnlContext.isWebContext()){
168 return MgnlContext.getAggregationState();
169 }
170 return null;
171 }
172
173 protected MagnoliaTemplatingUtilities getMagnoliaTemplatingUtilities() {
174 return MagnoliaTemplatingUtilities.getInstance();
175 }
176
177
178
179
180
181
182 protected Content wrapNodeForModel(Content currentContent, Content mainContent) {
183 return new I18nContentWrapper(currentContent);
184 }
185
186
187
188
189
190
191
192
193 protected Content wrapNodeForTemplate(Content currentContent, Content mainContent) {
194 return new I18nContentWrapper(currentContent);
195 }
196
197 protected Object setContextAttribute(final Map ctx, final String name, Object value) {
198 return ctx.put(name, value);
199 }
200
201
202
203
204 protected String getPageAttributeName() {
205 return "page";
206 }
207
208
209
210
211 protected abstract Map newContext();
212
213
214
215
216
217 protected abstract void onRender(Content content, RenderableDefinition definition, Writer out, Map ctx, String templatePath) throws RenderException;
218
219 }