net.hasor.db.ognl.ASTAdd Maven / Gradle / Ivy
The newest version!
//--------------------------------------------------------------------------
// Copyright (c) 1998-2004, Drew Davidson and Luke Blanshard
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// Neither the name of the Drew Davidson nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//--------------------------------------------------------------------------
package ognl;
import ognl.enhance.ExpressionCompiler;
import java.math.BigDecimal;
import java.math.BigInteger;
/**
* @author Luke Blanshard ([email protected])
* @author Drew Davidson ([email protected])
*/
class ASTAdd extends NumericExpression
{
public ASTAdd(int id)
{
super(id);
}
public ASTAdd(OgnlParser p, int id)
{
super(p, id);
}
public void jjtClose()
{
flattenTree();
}
protected Object getValueBody( OgnlContext context, Object source ) throws OgnlException
{
Object result = _children[0].getValue( context, source );
for ( int i=1; i < _children.length; ++i )
result = OgnlOps.add( result, _children[i].getValue(context, source) );
return result;
}
public String getExpressionOperator(int index)
{
return "+";
}
boolean isWider(NodeType type, NodeType lastType)
{
if (lastType == null)
return true;
//System.out.println("checking isWider(" + type.getGetterClass() + " , " + lastType.getGetterClass() + ")");
if (String.class.isAssignableFrom(lastType.getGetterClass()))
return false;
if (String.class.isAssignableFrom(type.getGetterClass()))
return true;
if (_parent != null && String.class.isAssignableFrom(type.getGetterClass()))
return true;
if (String.class.isAssignableFrom(lastType.getGetterClass()) && Object.class == type.getGetterClass())
return false;
if (_parent != null && String.class.isAssignableFrom(lastType.getGetterClass()))
return false;
else if (_parent == null && String.class.isAssignableFrom(lastType.getGetterClass()))
return true;
else if (_parent == null && String.class.isAssignableFrom(type.getGetterClass()))
return false;
if (BigDecimal.class.isAssignableFrom(type.getGetterClass())
|| BigInteger.class.isAssignableFrom(type.getGetterClass()))
return true;
if (BigDecimal.class.isAssignableFrom(lastType.getGetterClass())
|| BigInteger.class.isAssignableFrom(lastType.getGetterClass()))
return false;
if (Double.class.isAssignableFrom(type.getGetterClass()))
return true;
if (Integer.class.isAssignableFrom(type.getGetterClass())
&& Double.class.isAssignableFrom(lastType.getGetterClass()))
return false;
if (Float.class.isAssignableFrom(type.getGetterClass())
&& Integer.class.isAssignableFrom(lastType.getGetterClass()))
return true;
return true;
}
public String toGetSourceString(OgnlContext context, Object target)
{
try {
String result = "";
NodeType lastType = null;
// go through once to determine the ultimate type
if ((_children != null) && (_children.length > 0))
{
Class currType = context.getCurrentType();
Class currAccessor = context.getCurrentAccessor();
Object cast = context.get(ExpressionCompiler.PRE_CAST);
for ( int i = 0; i < _children.length; ++i )
{
_children[i].toGetSourceString(context, target);
if (NodeType.class.isInstance(_children[i])
&& ((NodeType)_children[i]).getGetterClass() != null
&& isWider((NodeType)_children[i], lastType))
{
lastType = (NodeType)_children[i];
}
}
context.put(ExpressionCompiler.PRE_CAST, cast);
context.setCurrentType(currType);
context.setCurrentAccessor(currAccessor);
}
// reset context since previous children loop would have changed it
context.setCurrentObject(target);
if ((_children != null) && (_children.length > 0))
{
for ( int i = 0; i < _children.length; ++i )
{
if (i > 0)
result += " " + getExpressionOperator(i) + " ";
String expr = _children[i].toGetSourceString(context, target);
if ((expr != null && "null".equals(expr))
|| (!ASTConst.class.isInstance(_children[i])
&& (expr == null || expr.trim().length() <= 0)))
{
expr = "null";
}
//System.out.println("astadd child class: " + _children[i].getClass().getName() + " and return expr: " + expr);
if (ASTProperty.class.isInstance(_children[i]))
{
expr = ExpressionCompiler.getRootExpression(_children[i], context.getRoot(), context) + expr;
context.setCurrentAccessor(context.getRoot().getClass());
} else if (ASTMethod.class.isInstance(_children[i]))
{
String chain = (String)context.get("_currentChain");
String rootExpr = ExpressionCompiler.getRootExpression(_children[i], context.getRoot(), context);
//System.out.println("astadd chains is >>" + chain + "<< and rootExpr is >>" + rootExpr + "<<");
// dirty fix for overly aggressive casting dot operations
if (rootExpr.endsWith(".") && chain != null && chain.startsWith(")."))
{
chain = chain.substring(1, chain.length());
}
expr = rootExpr + (chain != null ? chain + "." : "") + expr;
context.setCurrentAccessor(context.getRoot().getClass());
} else if (ExpressionNode.class.isInstance(_children[i]))
{
expr = "(" + expr + ")";
} else if ((_parent == null || !ASTChain.class.isInstance(_parent))
&& ASTChain.class.isInstance(_children[i]))
{
String rootExpr = ExpressionCompiler.getRootExpression(_children[i], context.getRoot(), context);
if (!ASTProperty.class.isInstance(_children[i].jjtGetChild(0))
&& rootExpr.endsWith(")") && expr.startsWith(")"))
expr = expr.substring(1, expr.length());
expr = rootExpr + expr;
context.setCurrentAccessor(context.getRoot().getClass());
String cast = (String)context.remove(ExpressionCompiler.PRE_CAST);
if (cast == null)
cast = "";
expr = cast + expr;
}
// turn quoted characters into quoted strings
if (context.getCurrentType() != null && context.getCurrentType() == Character.class
&& ASTConst.class.isInstance(_children[i]))
{
if (expr.indexOf('\'') >= 0)
expr = expr.replaceAll("'", "\"");
context.setCurrentType(String.class);
} else {
if (!ASTVarRef.class.isAssignableFrom(_children[i].getClass())
&& !ASTProperty.class.isInstance(_children[i])
&& !ASTMethod.class.isInstance(_children[i])
&& !ASTSequence.class.isInstance(_children[i])
&& !ASTChain.class.isInstance(_children[i])
&& !NumericExpression.class.isAssignableFrom(_children[i].getClass())
&& !ASTStaticField.class.isInstance(_children[i])
&& !ASTStaticMethod.class.isInstance(_children[i])
&& !ASTTest.class.isInstance(_children[i]))
{
if (lastType != null && String.class.isAssignableFrom(lastType.getGetterClass()))
{
//System.out.println("Input expr >>" + expr + "<<");
if (expr.indexOf(""") >= 0)
expr = expr.replaceAll(""", "\"");
if (expr.indexOf('"') >= 0)
expr = expr.replaceAll("\"", "'");
expr = "\"" + expr + "\"";
//System.out.println("Expr now >>" + expr + "<<");
}
}
}
result += expr;
// hanlde addition for numeric types when applicable or just string concatenation
if ( (lastType == null || !String.class.isAssignableFrom(lastType.getGetterClass()))
&& !ASTConst.class.isAssignableFrom(_children[i].getClass())
&& !NumericExpression.class.isAssignableFrom(_children[i].getClass()))
{
if (context.getCurrentType() != null && Number.class.isAssignableFrom(context.getCurrentType())
&& !ASTMethod.class.isInstance(_children[i]))
{
if (ASTVarRef.class.isInstance(_children[i])
|| ASTProperty.class.isInstance(_children[i])
|| ASTChain.class.isInstance(_children[i]))
result += ".";
result += OgnlRuntime.getNumericValueGetter(context.getCurrentType());
context.setCurrentType(OgnlRuntime.getPrimitiveWrapperClass(context.getCurrentType()));
}
}
if (lastType != null)
context.setCurrentAccessor(lastType.getGetterClass());
}
}
if (_parent == null || ASTSequence.class.isAssignableFrom(_parent.getClass()))
{
if (_getterClass != null && String.class.isAssignableFrom(_getterClass))
_getterClass = Object.class;
} else
{
context.setCurrentType(_getterClass);
}
try
{
Object contextObj = getValueBody(context, target);
context.setCurrentObject(contextObj);
} catch (Throwable t)
{
throw OgnlOps.castToRuntime(t);
}
return result;
} catch (Throwable t)
{
throw OgnlOps.castToRuntime(t);
}
}
}