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 }