1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.jexl3.internal;
18
19 import org.apache.commons.jexl3.JxltEngine;
20 import org.apache.commons.jexl3.internal.TemplateEngine.CompositeExpression;
21 import org.apache.commons.jexl3.internal.TemplateEngine.ConstantExpression;
22 import org.apache.commons.jexl3.internal.TemplateEngine.DeferredExpression;
23 import org.apache.commons.jexl3.internal.TemplateEngine.ImmediateExpression;
24 import org.apache.commons.jexl3.internal.TemplateEngine.NestedExpression;
25 import org.apache.commons.jexl3.internal.TemplateEngine.TemplateExpression;
26
27 import org.apache.commons.jexl3.parser.ASTBlock;
28 import org.apache.commons.jexl3.parser.ASTFunctionNode;
29 import org.apache.commons.jexl3.parser.ASTIdentifier;
30 import org.apache.commons.jexl3.parser.ASTJexlScript;
31 import org.apache.commons.jexl3.parser.ASTNumberLiteral;
32 import org.apache.commons.jexl3.parser.JexlNode;
33
34
35
36
37
38 public class TemplateDebugger extends Debugger {
39
40 private ASTJexlScript script;
41
42 private TemplateExpression[] exprs;
43
44
45
46
47 public TemplateDebugger() {
48
49 }
50
51 @Override
52 public void reset() {
53 super.reset();
54
55 exprs = null;
56 script = null;
57 }
58
59
60
61
62
63
64 public boolean debug(final JxltEngine.Expression je) {
65 if (je instanceof TemplateExpression) {
66 final TemplateEngine.TemplateExpression te = (TemplateEngine.TemplateExpression) je;
67 return visit(te, this) != null;
68 }
69 return false;
70 }
71
72
73
74
75
76
77 public boolean debug(final JxltEngine.Template jt) {
78 if (!(jt instanceof TemplateScript)) {
79 return false;
80 }
81 final TemplateScript ts = (TemplateScript) jt;
82
83 this.exprs = ts.getExpressions() == null? new TemplateExpression[0] : ts.getExpressions();
84 this.script = ts.getScript();
85 start = 0;
86 end = 0;
87 indentLevel = 0;
88 builder.setLength(0);
89 cause = script;
90 final int num = script.jjtGetNumChildren();
91 for (int i = 0; i < num; ++i) {
92 final JexlNode child = script.jjtGetChild(i);
93 acceptStatement(child, null);
94 }
95
96 if (builder.length() > 0 && builder.charAt(builder.length() - 1) != '\n') {
97 builder.append('\n');
98 }
99 end = builder.length();
100 return end > 0;
101 }
102
103
104 @Override
105 protected Object visit(final ASTBlock node, final Object data) {
106
107 if (exprs == null) {
108 return super.visit(node, data);
109 }
110
111 builder.append('{');
112 if (indent > 0) {
113 indentLevel += 1;
114 builder.append('\n');
115 } else {
116 builder.append(' ');
117 }
118 final int num = node.jjtGetNumChildren();
119 for (int i = 0; i < num; ++i) {
120 final JexlNode child = node.jjtGetChild(i);
121 acceptStatement(child, data);
122 }
123
124 newJexlLine();
125 if (indent > 0) {
126 indentLevel -= 1;
127 for (int i = 0; i < indentLevel; ++i) {
128 for(int s = 0; s < indent; ++s) {
129 builder.append(' ');
130 }
131 }
132 }
133 builder.append('}');
134
135 return data;
136 }
137
138 @Override
139 protected Object acceptStatement(final JexlNode child, final Object data) {
140
141 if (exprs == null) {
142 return super.acceptStatement(child, data);
143 }
144 final TemplateExpression te = getPrintStatement(child);
145 if (te != null) {
146
147 newJxltLine();
148 return visit(te, data);
149 }
150
151 newJexlLine();
152 return super.acceptStatement(child, data);
153 }
154
155
156
157
158
159
160 private TemplateExpression getPrintStatement(final JexlNode child) {
161 if (exprs != null && child instanceof ASTFunctionNode) {
162 final ASTFunctionNode node = (ASTFunctionNode) child;
163 final ASTIdentifier ns = (ASTIdentifier) node.jjtGetChild(0);
164 final JexlNode args = node.jjtGetChild(1);
165 if ("jexl".equals(ns.getNamespace())
166 && "print".equals(ns.getName())
167 && args.jjtGetNumChildren() == 1
168 && args.jjtGetChild(0) instanceof ASTNumberLiteral) {
169 final ASTNumberLiteral exprn = (ASTNumberLiteral) args.jjtGetChild(0);
170 final int n = exprn.getLiteral().intValue();
171 if (n >= 0 && n < exprs.length) {
172 return exprs[n];
173 }
174 }
175 }
176 return null;
177 }
178
179
180
181
182 private void newJexlLine() {
183 final int length = builder.length();
184 if (length == 0) {
185 builder.append("$$ ");
186 } else {
187 for (int i = length - 1; i >= 0; --i) {
188 final char c = builder.charAt(i);
189 switch (c) {
190 case '\n':
191 builder.append("$$ ");
192 return;
193 case '}':
194 builder.append("\n$$ ");
195 return;
196 case ' ':
197 case ';':
198 return;
199 default:
200 }
201 }
202 }
203 }
204
205
206
207
208 private void newJxltLine() {
209 final int length = builder.length();
210 for (int i = length - 1; i >= 0; --i) {
211 final char c = builder.charAt(i);
212 switch (c) {
213 case '\n':
214 case ';':
215 return;
216 case '}':
217 builder.append('\n');
218 return;
219 default:
220 }
221 }
222 }
223
224
225
226
227
228
229
230 private Object visit(final TemplateExpression expr, final Object data) {
231 Object r;
232 switch (expr.getType()) {
233 case CONSTANT:
234 r = visit((ConstantExpression) expr, data);
235 break;
236 case IMMEDIATE:
237 r = visit((ImmediateExpression) expr, data);
238 break;
239 case DEFERRED:
240 r = visit((DeferredExpression) expr, data);
241 break;
242 case NESTED:
243 r = visit((NestedExpression) expr, data);
244 break;
245 case COMPOSITE:
246 r = visit((CompositeExpression) expr, data);
247 break;
248 default:
249 r = null;
250 }
251 return r;
252 }
253
254
255
256
257
258
259
260 private Object visit(final ConstantExpression expr, final Object data) {
261 expr.asString(builder);
262 return data;
263 }
264
265
266
267
268
269
270
271 private Object visit(final ImmediateExpression expr, final Object data) {
272 builder.append(expr.isImmediate() ? '$' : '#');
273 builder.append('{');
274 super.accept(expr.node, data);
275 builder.append('}');
276 return data;
277 }
278
279
280
281
282
283
284
285 private Object visit(final DeferredExpression expr, final Object data) {
286 builder.append(expr.isImmediate() ? '$' : '#');
287 builder.append('{');
288 super.accept(expr.node, data);
289 builder.append('}');
290 return data;
291 }
292
293
294
295
296
297
298
299 private Object visit(final NestedExpression expr, final Object data) {
300 super.accept(expr.node, data);
301 return data;
302 }
303
304
305
306
307
308
309 private Object visit(final CompositeExpression expr, final Object data) {
310 for (final TemplateExpression ce : expr.exprs) {
311 visit(ce, data);
312 }
313 return data;
314 }
315
316 }