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.context;
35
36 import info.magnolia.cms.core.AggregationState;
37 import info.magnolia.cms.core.Content;
38 import info.magnolia.cms.util.ContentUtil;
39 import info.magnolia.objectfactory.annotation.LocalScoped;
40 import info.magnolia.rendering.engine.OutputProvider;
41 import info.magnolia.rendering.engine.RenderException;
42 import info.magnolia.rendering.engine.RenderExceptionHandler;
43 import info.magnolia.rendering.template.RenderableDefinition;
44 import info.magnolia.rendering.util.AppendableWriter;
45
46 import java.io.IOException;
47 import java.io.OutputStream;
48 import java.util.EmptyStackException;
49 import java.util.Stack;
50
51 import javax.inject.Inject;
52 import javax.inject.Provider;
53 import javax.jcr.Node;
54
55
56
57
58
59
60 @LocalScoped
61 public class AggregationStateBasedRenderingContext implements RenderingContext {
62
63
64
65
66 private static class StackState {
67
68 RenderableDefinition renderableDefinition;
69 OutputProvider outputProvider;
70 Content legacyContent;
71
72 private StackState(RenderableDefinition renderableDefinition, OutputProvider outputProvider, Content legacyContent) {
73 this.renderableDefinition = renderableDefinition;
74 this.outputProvider = outputProvider;
75 this.legacyContent = legacyContent;
76 }
77 }
78
79 private final AggregationState aggregationState;
80 private final Stack<StackState> stack = new Stack<StackState>();
81 private RenderableDefinition currentRenderableDefinition;
82 private OutputProvider currentOutputProvider;
83 private RenderExceptionHandler exceptionHandler;
84
85
86
87
88
89
90 private int depth = 0;
91
92 @Inject
93 public AggregationStateBasedRenderingContext(Provider<AggregationState> aggregationStateProvider, RenderExceptionHandler exceptionHandler) {
94 this(aggregationStateProvider.get(), exceptionHandler);
95 }
96
97 public AggregationStateBasedRenderingContext(AggregationState aggregationState, RenderExceptionHandler exceptionHandler) {
98 this.aggregationState = aggregationState;
99 this.exceptionHandler = exceptionHandler;
100 }
101
102 @Override
103 public Node getMainContent() {
104
105 Content mainContent = aggregationState.getMainContent();
106 return mainContent != null ? mainContent.getJCRNode() : null;
107 }
108
109 @Override
110 public Node getCurrentContent() {
111 Content currentContent = aggregationState.getCurrentContent();
112 return currentContent != null ? currentContent.getJCRNode() : null;
113 }
114
115 @Override
116 public RenderableDefinition getRenderableDefinition() {
117 return currentRenderableDefinition;
118 }
119
120 @Override
121 public void push(Node content, RenderableDefinition renderableDefinition) {
122 push(content, renderableDefinition, null);
123 }
124
125 @Override
126 public void push(Node content, RenderableDefinition renderableDefinition, OutputProvider outputProvider) {
127
128
129
130 Content legacyContent = ContentUtil.asContent(content);
131
132 if (aggregationState.getMainContent() == null) {
133 aggregationState.setMainContent(legacyContent);
134 }
135
136 if (depth > 0) {
137 stack.push(new StackState(currentRenderableDefinition, currentOutputProvider, aggregationState.getCurrentContent()));
138 }
139 aggregationState.setCurrentContent(legacyContent);
140 currentRenderableDefinition = renderableDefinition;
141 currentOutputProvider = outputProvider != null ? outputProvider : currentOutputProvider;
142 depth++;
143 }
144
145 @Override
146 public void pop() {
147 if (depth == 0) {
148 throw new EmptyStackException();
149 } else if (depth == 1) {
150 aggregationState.setCurrentContent(null);
151 currentRenderableDefinition = null;
152 currentOutputProvider = null;
153 } else {
154 StackState state = stack.pop();
155 aggregationState.setCurrentContent(state.legacyContent);
156 currentRenderableDefinition = state.renderableDefinition;
157 currentOutputProvider = state.outputProvider;
158 }
159 depth--;
160
161 }
162
163 @Override
164 public OutputProvider getOutputProvider() {
165 return currentOutputProvider;
166 }
167
168 @Override
169 public AppendableWriter getAppendable() throws IOException {
170 return new AppendableWriter(this.currentOutputProvider.getAppendable());
171 }
172
173 @Override
174 public OutputStream getOutputStream() throws IOException {
175 return this.currentOutputProvider.getOutputStream();
176 }
177
178 @Override
179 public void handleException(RenderException renderException) {
180 exceptionHandler.handleException(renderException, this);
181 }
182 }