001 package org.apache.commons.ognl; 002 003 /* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022 import org.apache.commons.ognl.enhance.ExpressionCompiler; 023 024 /** 025 * Base class for numeric expressions. 026 */ 027 public abstract class NumericExpression 028 extends ExpressionNode 029 implements NodeType 030 { 031 032 private static final long serialVersionUID = -174952564587478850L; 033 034 protected Class<?> getterClass; 035 036 public NumericExpression( int id ) 037 { 038 super( id ); 039 } 040 041 public NumericExpression( OgnlParser p, int id ) 042 { 043 super( p, id ); 044 } 045 046 /** 047 * {@inheritDoc} 048 */ 049 public Class<?> getGetterClass() 050 { 051 if ( getterClass != null ) 052 { 053 return getterClass; 054 } 055 056 return Double.TYPE; 057 } 058 059 /** 060 * {@inheritDoc} 061 */ 062 public Class<?> getSetterClass() 063 { 064 return null; 065 } 066 067 /** 068 * {@inheritDoc} 069 */ 070 @Override 071 public String toGetSourceString( OgnlContext context, Object target ) 072 { 073 Object value; 074 StringBuilder result = new StringBuilder( "" ); 075 076 try 077 { 078 079 value = getValueBody( context, target ); 080 081 if ( value != null ) 082 { 083 getterClass = value.getClass(); 084 } 085 086 for ( int i = 0; i < children.length; i++ ) 087 { 088 if ( i > 0 ) 089 { 090 result.append( " " ).append( getExpressionOperator( i ) ).append( " " ); 091 } 092 String str = OgnlRuntime.getChildSource( context, target, children[i] ); 093 094 result.append( coerceToNumeric( str, context, children[i] ) ); 095 } 096 097 } 098 catch ( Throwable t ) 099 { 100 throw OgnlOps.castToRuntime( t ); 101 } 102 103 return result.toString(); 104 } 105 106 public String coerceToNumeric( String source, OgnlContext context, Node child ) 107 { 108 StringBuilder ret = new StringBuilder( source ); 109 Object value = context.getCurrentObject(); 110 111 if ( ASTConst.class.isInstance( child ) && value != null ) 112 { 113 return value.toString(); 114 } 115 116 if ( context.getCurrentType() != null && !context.getCurrentType().isPrimitive() 117 && context.getCurrentObject() != null && Number.class.isInstance( context.getCurrentObject() ) ) 118 { 119 ret = new StringBuilder( "((" ).append( 120 ExpressionCompiler.getCastString( context.getCurrentObject().getClass() ) ).append( ")" ).append( 121 ret ).append( ")." ).append( 122 OgnlRuntime.getNumericValueGetter( context.getCurrentObject().getClass() ) ); 123 } 124 else if ( context.getCurrentType() != null && context.getCurrentType().isPrimitive() 125 && ( ASTConst.class.isInstance( child ) || NumericExpression.class.isInstance( child ) ) ) 126 { 127 @SuppressWarnings( "unchecked" ) // checked by the condition in the if clause 128 Class<? extends Number> numberClass = (Class<? extends Number>) context.getCurrentType(); 129 ret.append( OgnlRuntime.getNumericLiteral( numberClass ) ); 130 } 131 else if ( context.getCurrentType() != null && String.class.isAssignableFrom( context.getCurrentType() ) ) 132 { 133 ret = new StringBuilder( "Double.parseDouble(" ) 134 .append( ret ) 135 .append( ")" ); 136 context.setCurrentType( Double.TYPE ); 137 } 138 139 if ( NumericExpression.class.isInstance( child ) ) 140 { 141 ret = new StringBuilder( "(" ).append( ret ).append( ")" ); 142 } 143 144 return ret.toString(); 145 } 146 }