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