Coverage Report - org.apache.commons.ognl.ASTAdd
 
Classes in this File Line Coverage Branch Coverage Complexity
ASTAdd
89%
100/112
79%
128/162
13.375
 
 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 org.apache.commons.ognl.enhance.ExpressionCompiler;
 23  
 
 24  
 import java.math.BigDecimal;
 25  
 import java.math.BigInteger;
 26  
 
 27  
 /**
 28  
  * $Id: ASTAdd.java 1194869 2011-10-29 11:10:16Z mcucchiara $
 29  
  * @author Luke Blanshard (blanshlu@netscape.net)
 30  
  * @author Drew Davidson (drew@ognl.org)
 31  
  */
 32  
 class ASTAdd
 33  
     extends NumericExpression
 34  
 {
 35  
     public ASTAdd( int id )
 36  
     {
 37  136
         super( id );
 38  136
     }
 39  
 
 40  
     public ASTAdd( OgnlParser p, int id )
 41  
     {
 42  0
         super( p, id );
 43  0
     }
 44  
 
 45  
     public void jjtClose()
 46  
     {
 47  136
         flattenTree();
 48  136
     }
 49  
 
 50  
     protected Object getValueBody( OgnlContext context, Object source )
 51  
         throws OgnlException
 52  
     {
 53  117
         Object result = children[0].getValue( context, source );
 54  
 
 55  254
         for ( int i = 1; i < children.length; ++i )
 56  
         {
 57  138
             result = OgnlOps.add( result, children[i].getValue( context, source ) );
 58  
         }
 59  
 
 60  116
         return result;
 61  
     }
 62  
 
 63  
     public String getExpressionOperator( int index )
 64  
     {
 65  66
         return "+";
 66  
     }
 67  
 
 68  
     boolean isWider( NodeType type, NodeType lastType )
 69  
     {
 70  113
         if ( lastType == null )
 71  
         {
 72  52
             return true;
 73  
         }
 74  
 
 75  
         // System.out.println("checking isWider(" + type.getGetterClass() + " , " + lastType.getGetterClass() + ")");
 76  
 
 77  61
         if ( String.class.isAssignableFrom( lastType.getGetterClass() ) )
 78  
         {
 79  26
             return false;
 80  
         }
 81  
 
 82  35
         if ( String.class.isAssignableFrom( type.getGetterClass() ) )
 83  
         {
 84  3
             return true;
 85  
         }
 86  
 
 87  32
         if ( parent != null && String.class.isAssignableFrom( type.getGetterClass() ) )
 88  
         {
 89  0
             return true;
 90  
         }
 91  
 
 92  32
         if ( String.class.isAssignableFrom( lastType.getGetterClass() ) && Object.class == type.getGetterClass() )
 93  
         {
 94  0
             return false;
 95  
         }
 96  
 
 97  32
         if ( parent != null && String.class.isAssignableFrom( lastType.getGetterClass() ) )
 98  
         {
 99  0
             return false;
 100  
         }
 101  32
         else if ( parent == null && String.class.isAssignableFrom( lastType.getGetterClass() ) )
 102  
         {
 103  0
             return true;
 104  
         }
 105  32
         else if ( parent == null && String.class.isAssignableFrom( type.getGetterClass() ) )
 106  
         {
 107  0
             return false;
 108  
         }
 109  
 
 110  32
         if ( BigDecimal.class.isAssignableFrom( type.getGetterClass() )
 111  
             || BigInteger.class.isAssignableFrom( type.getGetterClass() ) )
 112  
         {
 113  5
             return true;
 114  
         }
 115  
 
 116  27
         if ( BigDecimal.class.isAssignableFrom( lastType.getGetterClass() )
 117  
             || BigInteger.class.isAssignableFrom( lastType.getGetterClass() ) )
 118  
         {
 119  1
             return false;
 120  
         }
 121  
 
 122  26
         if ( Double.class.isAssignableFrom( type.getGetterClass() ) )
 123  
         {
 124  1
             return true;
 125  
         }
 126  
 
 127  25
         if ( Integer.class.isAssignableFrom( type.getGetterClass() )
 128  
             && Double.class.isAssignableFrom( lastType.getGetterClass() ) )
 129  
         {
 130  2
             return false;
 131  
         }
 132  
 
 133  23
         if ( Float.class.isAssignableFrom( type.getGetterClass() )
 134  
             && Integer.class.isAssignableFrom( lastType.getGetterClass() ) )
 135  
         {
 136  0
             return true;
 137  
         }
 138  
 
 139  23
         return true;
 140  
     }
 141  
 
 142  
     public String toGetSourceString( OgnlContext context, Object target )
 143  
     {
 144  
         try
 145  
         {
 146  56
             String result = "";
 147  56
             NodeType lastType = null;
 148  
 
 149  
             // go through once to determine the ultimate type
 150  
 
 151  56
             if ( ( children != null ) && ( children.length > 0 ) )
 152  
             {
 153  56
                 Class currType = context.getCurrentType();
 154  56
                 Class currAccessor = context.getCurrentAccessor();
 155  
 
 156  56
                 Object cast = context.get( ExpressionCompiler.PRE_CAST );
 157  
 
 158  175
                 for ( int i = 0; i < children.length; ++i )
 159  
                 {
 160  122
                     children[i].toGetSourceString( context, target );
 161  
 
 162  119
                     if ( NodeType.class.isInstance( children[i] )
 163  
                         && ( (NodeType) children[i] ).getGetterClass() != null
 164  
                         && isWider( (NodeType) children[i], lastType ) )
 165  
                     {
 166  84
                         lastType = (NodeType) children[i];
 167  
                     }
 168  
                 }
 169  
 
 170  53
                 context.put( ExpressionCompiler.PRE_CAST, cast );
 171  
 
 172  53
                 context.setCurrentType( currType );
 173  53
                 context.setCurrentAccessor( currAccessor );
 174  
             }
 175  
 
 176  
             // reset context since previous children loop would have changed it
 177  
 
 178  53
             context.setCurrentObject( target );
 179  
 
 180  53
             if ( ( children != null ) && ( children.length > 0 ) )
 181  
             {
 182  
 
 183  172
                 for ( int i = 0; i < children.length; ++i )
 184  
                 {
 185  119
                     if ( i > 0 )
 186  
                     {
 187  66
                         result += " " + getExpressionOperator( i ) + " ";
 188  
                     }
 189  
 
 190  119
                     String expr = children[i].toGetSourceString( context, target );
 191  
 
 192  119
                     if ( ( expr != null && "null".equals( expr ) )
 193  
                         || ( !ASTConst.class.isInstance( children[i] )
 194  
                         && ( expr == null || expr.trim().length() <= 0 ) ) )
 195  
                     {
 196  1
                         expr = "null";
 197  
                     }
 198  
 
 199  
                     // System.out.println("astadd child class: " + _children[i].getClass().getName() +
 200  
                     // " and return expr: " + expr);
 201  
 
 202  119
                     if ( ASTProperty.class.isInstance( children[i] ) )
 203  
                     {
 204  11
                         expr = ExpressionCompiler.getRootExpression( children[i], context.getRoot(), context ) + expr;
 205  11
                         context.setCurrentAccessor( context.getRoot().getClass() );
 206  
                     }
 207  108
                     else if ( ASTMethod.class.isInstance( children[i] ) )
 208  
                     {
 209  2
                         String chain = (String) context.get( "_currentChain" );
 210  2
                         String rootExpr =
 211  
                             ExpressionCompiler.getRootExpression( children[i], context.getRoot(), context );
 212  
 
 213  
                         // System.out.println("astadd chains is >>" + chain + "<< and rootExpr is >>" + rootExpr +
 214  
                         // "<<");
 215  
 
 216  
                         // dirty fix for overly aggressive casting dot operations
 217  2
                         if ( rootExpr.endsWith( "." ) && chain != null && chain.startsWith( ")." ) )
 218  
                         {
 219  0
                             chain = chain.substring( 1, chain.length() );
 220  
                         }
 221  
 
 222  2
                         expr = rootExpr + ( chain != null ? chain + "." : "" ) + expr;
 223  2
                         context.setCurrentAccessor( context.getRoot().getClass() );
 224  
 
 225  2
                     }
 226  106
                     else if ( ExpressionNode.class.isInstance( children[i] ) )
 227  
                     {
 228  10
                         expr = "(" + expr + ")";
 229  
                     }
 230  96
                     else if ( ( parent == null || !ASTChain.class.isInstance( parent ) )
 231  
                         && ASTChain.class.isInstance( children[i] ) )
 232  
                     {
 233  12
                         String rootExpr =
 234  
                             ExpressionCompiler.getRootExpression( children[i], context.getRoot(), context );
 235  
 
 236  12
                         if ( !ASTProperty.class.isInstance( children[i].jjtGetChild( 0 ) ) && rootExpr.endsWith( ")" )
 237  
                             && expr.startsWith( ")" ) )
 238  
                         {
 239  0
                             expr = expr.substring( 1, expr.length() );
 240  
                         }
 241  
 
 242  12
                         expr = rootExpr + expr;
 243  12
                         context.setCurrentAccessor( context.getRoot().getClass() );
 244  
 
 245  12
                         String cast = (String) context.remove( ExpressionCompiler.PRE_CAST );
 246  12
                         if ( cast == null )
 247  
                         {
 248  3
                             cast = "";
 249  
                         }
 250  
 
 251  12
                         expr = cast + expr;
 252  
                     }
 253  
 
 254  
                     // turn quoted characters into quoted strings
 255  
 
 256  119
                     if ( context.getCurrentType() != null && context.getCurrentType() == Character.class
 257  
                         && ASTConst.class.isInstance( children[i] ) )
 258  
                     {
 259  6
                         expr = expr.replaceAll( "'", "\"" );
 260  6
                         context.setCurrentType( String.class );
 261  
                     }
 262  
                     else
 263  
                     {
 264  
 
 265  113
                         if ( !ASTVarRef.class.isAssignableFrom( children[i].getClass() )
 266  
                             && !ASTProperty.class.isInstance( children[i] )
 267  
                             && !ASTMethod.class.isInstance( children[i] )
 268  
                             && !ASTSequence.class.isInstance( children[i] )
 269  
                             && !ASTChain.class.isInstance( children[i] )
 270  
                             && !NumericExpression.class.isAssignableFrom( children[i].getClass() )
 271  
                             && !ASTStaticField.class.isInstance( children[i] )
 272  
                             && !ASTStaticMethod.class.isInstance( children[i] )
 273  
                             && !ASTTest.class.isInstance( children[i] ) )
 274  
                         {
 275  70
                             if ( lastType != null && String.class.isAssignableFrom( lastType.getGetterClass() ) )
 276  
                             {
 277  
                                 // System.out.println("Input expr >>" + expr + "<<");
 278  34
                                 expr = expr.replaceAll( "&quot;", "\"" );
 279  34
                                 expr = expr.replaceAll( "\"", "'" );
 280  34
                                 expr = "\"" + expr + "\"";
 281  
                                 // System.out.println("Expr now >>" + expr + "<<");
 282  
                             }
 283  
                         }
 284  
                     }
 285  
 
 286  119
                     result += expr;
 287  
 
 288  
                     // hanlde addition for numeric types when applicable or just string concatenation
 289  
 
 290  119
                     if ( ( lastType == null || !String.class.isAssignableFrom( lastType.getGetterClass() ) )
 291  
                         && !ASTConst.class.isAssignableFrom( children[i].getClass() )
 292  
                         && !NumericExpression.class.isAssignableFrom( children[i].getClass() ) )
 293  
                     {
 294  22
                         if ( context.getCurrentType() != null
 295  
                             && Number.class.isAssignableFrom( context.getCurrentType() )
 296  
                             && !ASTMethod.class.isInstance( children[i] ) )
 297  
                         {
 298  2
                             if ( ASTVarRef.class.isInstance( children[i] )
 299  
                                 || ASTProperty.class.isInstance( children[i] )
 300  
                                 || ASTChain.class.isInstance( children[i] ) )
 301  
                             {
 302  2
                                 result += ".";
 303  
                             }
 304  
 
 305  2
                             result += OgnlRuntime.getNumericValueGetter( context.getCurrentType() );
 306  2
                             context.setCurrentType( OgnlRuntime.getPrimitiveWrapperClass( context.getCurrentType() ) );
 307  
                         }
 308  
                     }
 309  
 
 310  119
                     if ( lastType != null )
 311  
                     {
 312  117
                         context.setCurrentAccessor( lastType.getGetterClass() );
 313  
                     }
 314  
                 }
 315  
             }
 316  
 
 317  53
             if ( parent == null || ASTSequence.class.isAssignableFrom( parent.getClass() ) )
 318  
             {
 319  28
                 if ( getterClass != null && String.class.isAssignableFrom( getterClass ) )
 320  
                 {
 321  0
                     getterClass = Object.class;
 322  
                 }
 323  
             }
 324  
             else
 325  
             {
 326  25
                 context.setCurrentType( getterClass );
 327  
             }
 328  
 
 329  
             try
 330  
             {
 331  53
                 Object contextObj = getValueBody( context, target );
 332  52
                 context.setCurrentObject( contextObj );
 333  
             }
 334  1
             catch ( Throwable t )
 335  
             {
 336  1
                 throw OgnlOps.castToRuntime( t );
 337  52
             }
 338  
 
 339  52
             return result;
 340  
 
 341  
         }
 342  4
         catch ( Throwable t )
 343  
         {
 344  4
             throw OgnlOps.castToRuntime( t );
 345  
         }
 346  
     }
 347  
     
 348  
     public <R, P> R accept( NodeVisitor<? extends R, ? super P> visitor, P data )
 349  
         throws OgnlException
 350  
     {
 351  0
         return visitor.visit( this, data );
 352  
     }
 353  
 }