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.rendering.engine;
35
36 import info.magnolia.registry.RegistrationException;
37 import info.magnolia.rendering.context.RenderingContext;
38 import info.magnolia.rendering.context.RenderingListener;
39 import info.magnolia.rendering.renderer.Renderer;
40 import info.magnolia.rendering.renderer.registry.RendererRegistry;
41 import info.magnolia.rendering.template.RenderableDefinition;
42 import info.magnolia.rendering.template.assignment.TemplateDefinitionAssignment;
43 import info.magnolia.rendering.template.variation.RenderableVariationResolver;
44
45 import java.util.Collections;
46 import java.util.Map;
47
48 import javax.inject.Provider;
49 import javax.jcr.Node;
50
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54
55
56
57
58
59 public class DefaultRenderingEngine implements RenderingEngine {
60
61 protected static final Map<String, Object> EMPTY_CONTEXT = Collections.emptyMap();
62
63 private RendererRegistry rendererRegistry;
64 private TemplateDefinitionAssignment templateDefinitionAssignment;
65 private Provider<RenderingContext> renderingContextProvider;
66 private RenderableVariationResolver variationResolver;
67
68 private Boolean autoPopulateFromRequest = true;
69 private Boolean renderEmptyAreas = true;
70
71 private static final Logger log = LoggerFactory.getLogger(DefaultRenderingEngine.class);
72
73
74
75
76 protected DefaultRenderingEngine() {
77 }
78
79 public DefaultRenderingEngine(RendererRegistry rendererRegistry, TemplateDefinitionAssignment templateDefinitionAssignment, RenderableVariationResolver variationResolver, Provider<RenderingContext> renderingContextProvider) {
80 this.rendererRegistry = rendererRegistry;
81 this.templateDefinitionAssignment = templateDefinitionAssignment;
82 this.variationResolver = variationResolver;
83 this.renderingContextProvider = renderingContextProvider;
84 }
85
86 @Override
87 public void render(Node content, OutputProvider out) throws RenderException {
88 render(content, EMPTY_CONTEXT, out);
89 }
90
91 @Override
92 public void render(Node content, Map<String, Object> contextObjects, OutputProvider out) throws RenderException {
93 render(content, getRenderableDefinitionFor(content), contextObjects, out);
94 }
95
96 @Override
97 public void render(Node content, RenderableDefinition definition, Map<String, Object> contextObjects, OutputProvider out) throws RenderException {
98
99 final Renderer renderer = getRendererFor(definition);
100 final RenderingContext renderingContext = getRenderingContext();
101
102 RenderableDefinition variation = variationResolver.resolveVariation(definition);
103 definition = variation != null ? variation : definition;
104
105 renderingContext.push(content, definition, out);
106 renderingContext.before(content, definition, contextObjects, out);
107 try {
108 renderer.render(renderingContext, contextObjects);
109 } catch (RenderException e) {
110 renderingContext.handleException(e);
111 }
112
113 finally {
114 renderingContext.after(content, definition, contextObjects, out);
115 renderingContext.pop();
116 }
117 }
118
119 protected RenderableDefinition getRenderableDefinitionFor(Node content) throws RenderException {
120 try {
121 return templateDefinitionAssignment.getAssignedTemplateDefinition(content);
122 } catch (RegistrationException e) {
123 throw new RenderException("Can't resolve RenderableDefinition for node [" + content + "]", e);
124 }
125 }
126
127 protected Renderer getRendererFor(RenderableDefinition definition) throws RenderException {
128 final String renderType = definition.getRenderType();
129 if (renderType == null) {
130 throw new RenderException("No renderType defined for definition [" + definition + "]");
131 }
132 try {
133 return rendererRegistry.getRenderer(renderType);
134 } catch (RegistrationException e) {
135 throw new RenderException("Can't find renderer [" + renderType + "]", e);
136 }
137 }
138
139 @Override
140 public RenderingContext getRenderingContext() {
141 return renderingContextProvider.get();
142 }
143
144 @Override
145 public void initListeners(OutputProvider output) {
146 RenderingContext context = this.getRenderingContext();
147
148 for (Class<RenderingListener> listener : this.rendererRegistry.getListeners()) {
149 RenderingListener renderingListener;
150 try {
151 renderingListener = listener.getConstructor(ResponseOutputProvider.class).newInstance(output);
152 context.addListener(renderingListener);
153 } catch (Exception e) {
154 log.error("Error when instantiating listener '{}'.", listener, e);
155 }
156 }
157 }
158
159 @Override
160 public Boolean getAutoPopulateFromRequest() {
161 return autoPopulateFromRequest;
162 }
163
164 public void setAutoPopulateFromRequest(Boolean autopopulateFromRequest) {
165 this.autoPopulateFromRequest = autopopulateFromRequest;
166 }
167
168 @Override
169 public Boolean getRenderEmptyAreas() {
170 return renderEmptyAreas;
171 }
172
173 public void setRenderEmptyAreas(Boolean renderEmptyAreas) {
174 this.renderEmptyAreas = renderEmptyAreas;
175 }
176 }