1 package org.apache.commons.ognl;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.math.BigDecimal;
23 import java.math.BigInteger;
24
25
26
27
28
29
30
31
32
33 public class ToStringVisitor
34 implements NodeVisitor<StringBuilder, StringBuilder>
35 {
36 static final ToStringVisitor INSTANCE = new ToStringVisitor();
37
38 public StringBuilder visit( ASTSequence node, StringBuilder data )
39 {
40 return commaSeparatedChildren( node, data );
41 }
42
43 private StringBuilder commaSeparatedChildren( SimpleNode node, StringBuilder data )
44 {
45 if ( ( node.children != null ) )
46 {
47 for ( int i = 0; i < node.children.length; ++i )
48 {
49 if ( i > 0 )
50 {
51 data.append( ", " );
52 }
53 recurse( node.children[i], data );
54 }
55 }
56 return data;
57 }
58
59 public StringBuilder visit( ASTAssign node, StringBuilder data )
60 {
61 return concatInfix( node, " = ", data );
62 }
63
64 public StringBuilder visit( ASTTest node, StringBuilder data )
65 {
66 return visitExpressionNode( node, data );
67 }
68
69 private StringBuilder visitExpressionNode( ExpressionNode node, StringBuilder data )
70 {
71 if ( node.parent != null )
72 {
73 data.append( "(" );
74 }
75
76 if ( ( node.children != null ) && ( node.children.length > 0 ) )
77 {
78 for ( int i = 0; i < node.children.length; ++i )
79 {
80 if ( i > 0 )
81 {
82 data.append( " " ).append( node.getExpressionOperator( i ) ).append( " " );
83 }
84 recurse( node.children[i], data );
85 }
86 }
87
88 if ( node.parent != null )
89 {
90 data.append( ')' );
91 }
92 return data;
93 }
94
95 public StringBuilder visit( ASTOr node, StringBuilder data )
96 {
97 return visitExpressionNode( node, data );
98 }
99
100 public StringBuilder visit( ASTAnd node, StringBuilder data )
101 {
102 return visitExpressionNode( node, data );
103 }
104
105 public StringBuilder visit( ASTBitOr node, StringBuilder data )
106 {
107 return visitExpressionNode( node, data );
108 }
109
110 public StringBuilder visit( ASTXor node, StringBuilder data )
111 {
112 return visitExpressionNode( node, data );
113 }
114
115 public StringBuilder visit( ASTBitAnd node, StringBuilder data )
116 {
117 return visitExpressionNode( node, data );
118 }
119
120 public StringBuilder visit( ASTEq node, StringBuilder data )
121 {
122 return visitExpressionNode( node, data );
123 }
124
125 public StringBuilder visit( ASTNotEq node, StringBuilder data )
126 {
127 return visitExpressionNode( node, data );
128 }
129
130 public StringBuilder visit( ASTLess node, StringBuilder data )
131 {
132 return visitExpressionNode( node, data );
133 }
134
135 public StringBuilder visit( ASTGreater node, StringBuilder data )
136 {
137 return visitExpressionNode( node, data );
138 }
139
140 public StringBuilder visit( ASTLessEq node, StringBuilder data )
141 {
142 return visitExpressionNode( node, data );
143 }
144
145 public StringBuilder visit( ASTGreaterEq node, StringBuilder data )
146 {
147 return visitExpressionNode( node, data );
148 }
149
150 public StringBuilder visit( ASTIn node, StringBuilder data )
151 {
152 final String infix = " in ";
153 return concatInfix( node, infix, data );
154 }
155
156 private StringBuilder concatInfix( SimpleNode node, String infix, StringBuilder data )
157 {
158 return concatInfix( node.children[0], infix, node.children[1], data );
159 }
160
161 private StringBuilder concatInfix( Node left, String infix, Node right, StringBuilder data )
162 {
163 recurse( left, data ).append( infix );
164 return recurse( right, data );
165 }
166
167 public StringBuilder visit( ASTNotIn node, StringBuilder data )
168 {
169 return concatInfix( node, " not in ", data );
170 }
171
172 public StringBuilder visit( ASTShiftLeft node, StringBuilder data )
173 {
174 return visitExpressionNode( node, data );
175 }
176
177 public StringBuilder visit( ASTShiftRight node, StringBuilder data )
178 {
179 return visitExpressionNode( node, data );
180 }
181
182 public StringBuilder visit( ASTUnsignedShiftRight node, StringBuilder data )
183 {
184 return visitExpressionNode( node, data );
185 }
186
187 public StringBuilder visit( ASTAdd node, StringBuilder data )
188 {
189 return visitExpressionNode( node, data );
190 }
191
192 public StringBuilder visit( ASTSubtract node, StringBuilder data )
193 {
194 return visitExpressionNode( node, data );
195 }
196
197 public StringBuilder visit( ASTMultiply node, StringBuilder data )
198 {
199 return visitExpressionNode( node, data );
200 }
201
202 public StringBuilder visit( ASTDivide node, StringBuilder data )
203 {
204 return visitExpressionNode( node, data );
205 }
206
207 public StringBuilder visit( ASTRemainder node, StringBuilder data )
208 {
209 return visitExpressionNode( node, data );
210 }
211
212 public StringBuilder visit( ASTNegate node, StringBuilder data )
213 {
214 return appendPrefixed( "-", node, data );
215 }
216
217 public StringBuilder visit( ASTBitNegate node, StringBuilder data )
218 {
219 return appendPrefixed( "~", node, data );
220 }
221
222 private StringBuilder appendPrefixed( String prefix, SimpleNode node, StringBuilder data )
223 {
224 data.append( prefix );
225 return recurse( node.children[0], data );
226 }
227
228 public StringBuilder visit( ASTNot node, StringBuilder data )
229 {
230 return visitExpressionNode( node, data );
231 }
232
233 public StringBuilder visit( ASTInstanceof node, StringBuilder data )
234 {
235 return recurse( node.children[0], data ).append( " instanceof " ).append( node.getTargetType() );
236 }
237
238 public StringBuilder visit( ASTChain node, StringBuilder data )
239 {
240
241 if ( ( node.children != null ) && ( node.children.length > 0 ) )
242 {
243 for ( int i = 0; i < node.children.length; i++ )
244 {
245 if ( i > 0 )
246 {
247 if ( !( node.children[i] instanceof ASTProperty )
248 || !( (ASTProperty) node.children[i] ).isIndexedAccess() )
249 {
250 data.append( "." );
251 }
252 }
253 recurse( node.children[i], data );
254 }
255 }
256 return data;
257 }
258
259 public StringBuilder visit( ASTEval node, StringBuilder data )
260 {
261 data.append( "(" );
262 concatInfix( node, ")(", data );
263 return data.append( ")" );
264 }
265
266 public StringBuilder visit( ASTConst node, StringBuilder data )
267 {
268 final Object value = node.getValue();
269 if ( value == null )
270 {
271 data.append( "null" );
272 }
273 else
274 {
275 if ( value instanceof String )
276 {
277 data.append( '\"' ).append( OgnlOps.getEscapeString( value.toString() ) ).append( '\"' );
278 }
279 else
280 {
281 if ( value instanceof Character )
282 {
283 data.append( '\'' ).append( OgnlOps.getEscapedChar( (Character) value ) ).append( '\'' );
284 }
285 else
286 {
287 if ( value instanceof Node )
288 {
289 data.append( ":[ " );
290 recurse( (Node) value, data );
291 data.append( " ]" );
292 }
293 else
294 {
295 data.append( value );
296 if ( value instanceof Long )
297 {
298 data.append( 'L' );
299 }
300 else if ( value instanceof BigDecimal )
301 {
302 data.append( 'B' );
303 }
304 else if ( value instanceof BigInteger )
305 {
306 data.append( 'H' );
307 }
308 }
309 }
310 }
311 }
312 return data;
313 }
314
315 public StringBuilder visit( ASTThisVarRef node, StringBuilder data )
316 {
317 return data.append( "#this" );
318 }
319
320 public StringBuilder visit( ASTRootVarRef node, StringBuilder data )
321 {
322 return data.append( "#root" );
323 }
324
325 public StringBuilder visit( ASTVarRef node, StringBuilder data )
326 {
327 return data.append( "#" ).append( node.getName() );
328 }
329
330 public StringBuilder visit( ASTList node, StringBuilder data )
331 {
332 return wrappedCommaSeparatedChildren( "{ ", node, " }", data );
333 }
334
335 public StringBuilder visit( ASTMap node, StringBuilder data )
336 {
337 data.append( "#" );
338
339 if ( node.getClassName() != null )
340 {
341 data.append( "@" ).append( node.getClassName() ).append( "@" );
342 }
343
344 data.append( "{ " );
345 for ( int i = 0; i < node.jjtGetNumChildren(); ++i )
346 {
347 ASTKeyValue kv = (ASTKeyValue) node.children[i];
348
349 if ( i > 0 )
350 {
351 data.append( ", " );
352 }
353 concatInfix( kv.getKey(), " : ", kv.getValue(), data );
354 }
355 return data.append( " }" );
356 }
357
358 public StringBuilder visit( ASTKeyValue node, StringBuilder data )
359 {
360 return concatInfix( node.getKey(), " -> ", node.getValue(), data );
361 }
362
363 public StringBuilder visit( ASTStaticField node, StringBuilder data )
364 {
365 return data.append( "@" ).append( node.getClassName() ).append( "@" ).append( node.getFieldName() );
366 }
367
368 public StringBuilder visit( ASTCtor node, StringBuilder data )
369 {
370 data.append( "new " ).append( node.getClassName() );
371
372 if ( node.isArray() )
373 {
374 if ( node.children[0] instanceof ASTConst )
375 {
376 indexedChild( node, data );
377 }
378 else
379 {
380 appendPrefixed( "[] ", node, data );
381 }
382 }
383 else
384 {
385 wrappedCommaSeparatedChildren( "(", node, ")", data );
386 }
387 return data;
388 }
389
390 private StringBuilder wrappedCommaSeparatedChildren( String prefix, SimpleNode node, String suffix,
391 StringBuilder data )
392 {
393 data.append( prefix );
394 return commaSeparatedChildren( node, data ).append( suffix );
395 }
396
397 public StringBuilder visit( ASTProperty node, StringBuilder data )
398 {
399 if ( node.isIndexedAccess() )
400 {
401 indexedChild( node, data );
402 }
403 else
404 {
405 data.append( ( (ASTConst) node.children[0] ).getValue() );
406 }
407 return data;
408 }
409
410 private StringBuilder indexedChild( SimpleNode node, StringBuilder data )
411 {
412 return surroundedNode( "[", node.children[0], "]", data );
413 }
414
415 public StringBuilder visit( ASTStaticMethod node, StringBuilder data )
416 {
417 data.append( "@" ).append( node.getClassName() ).append( "@" ).append( node.getMethodName() );
418 return wrappedCommaSeparatedChildren( "(", node, ")", data );
419 }
420
421 public StringBuilder visit( ASTMethod node, StringBuilder data )
422 {
423 data.append( node.getMethodName() );
424 return wrappedCommaSeparatedChildren( "(", node, ")", data );
425 }
426
427 public StringBuilder visit( ASTProject node, StringBuilder data )
428 {
429 return surroundedNode( "{ ", node.children[0], " }", data );
430 }
431
432 private StringBuilder surroundedNode( String open, Node inner, String close, StringBuilder data )
433 {
434 data.append( open );
435 return recurse( inner, data ).append( close );
436 }
437
438 public StringBuilder visit( ASTSelect node, StringBuilder data )
439 {
440 return surroundedNode( "{? ", node.children[0], " }", data );
441 }
442
443 public StringBuilder visit( ASTSelectFirst node, StringBuilder data )
444 {
445 return surroundedNode( "{^ ", node.children[0], " }", data );
446 }
447
448 public StringBuilder visit( ASTSelectLast node, StringBuilder data )
449 {
450 return surroundedNode( "{$ ", node.children[0], " }", data );
451 }
452
453 private StringBuilder recurse( Node child, StringBuilder data )
454 {
455 try
456 {
457 return child == null ? data.append( "null" ) : child.accept( this, data );
458 }
459 catch ( OgnlException e )
460 {
461
462 throw new RuntimeException( e );
463 }
464 }
465
466 }