org.apache.ibatis.ognl.ASTAdd Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.apache.servicemix.bundles.mybatis
Show all versions of org.apache.servicemix.bundles.mybatis
This OSGi bundle wraps ${pkgArtifactId} ${pkgVersion} jar file.
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.ibatis.ognl;
import org.apache.ibatis.ognl.enhance.ExpressionCompiler;
import java.math.BigDecimal;
import java.math.BigInteger;
public class ASTAdd extends NumericExpression {
private static final long serialVersionUID = -7027437312703768232L;
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 {
StringBuilder result = new StringBuilder();
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 (Node child : children) {
child.toGetSourceString(context, target);
if (child instanceof NodeType
&& ((NodeType) child).getGetterClass() != null
&& isWider((NodeType) child, lastType)) {
lastType = (NodeType) child;
}
}
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.append(" ").append(getExpressionOperator(i)).append(" ");
String expr = children[i].toGetSourceString(context, target);
if (("null".equals(expr))
|| (!(children[i] instanceof ASTConst)
&& (expr == null || expr.trim().length() <= 0))) {
expr = "null";
}
//System.out.println("astadd child class: " + _children[i].getClass().getName() + " and return expr: " + expr);
if (children[i] instanceof ASTProperty) {
expr = ExpressionCompiler.getRootExpression(children[i], context.getRoot(), context) + expr;
context.setCurrentAccessor(context.getRoot().getClass());
} else if (children[i] instanceof ASTMethod) {
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);
}
expr = rootExpr + (chain != null ? chain + "." : "") + expr;
context.setCurrentAccessor(context.getRoot().getClass());
} else if (children[i] instanceof ExpressionNode) {
expr = "(" + expr + ")";
} else if ((!(parent instanceof ASTChain))
&& children[i] instanceof ASTChain) {
String rootExpr = ExpressionCompiler.getRootExpression(children[i], context.getRoot(), context);
if (!(children[i].jjtGetChild(0) instanceof ASTProperty)
&& rootExpr.endsWith(")") && expr.startsWith(")"))
expr = expr.substring(1);
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
&& children[i] instanceof ASTConst) {
if (expr.indexOf('\'') >= 0)
expr = expr.replaceAll("'", "\"");
context.setCurrentType(String.class);
} else {
if (!ASTVarRef.class.isAssignableFrom(children[i].getClass())
&& !(children[i] instanceof ASTProperty)
&& !(children[i] instanceof ASTMethod)
&& !(children[i] instanceof ASTSequence)
&& !(children[i] instanceof ASTChain)
&& !NumericExpression.class.isAssignableFrom(children[i].getClass())
&& !(children[i] instanceof ASTStaticField)
&& !(children[i] instanceof ASTStaticMethod)
&& !(children[i] instanceof ASTTest)) {
if (lastType != null && String.class.isAssignableFrom(lastType.getGetterClass())) {
//System.out.println("Input expr >>" + expr + "<<");
if (expr.contains("""))
expr = expr.replaceAll(""", "\"");
if (expr.indexOf('"') >= 0)
expr = expr.replaceAll("\"", "'");
expr = "\"" + expr + "\"";
//System.out.println("Expr now >>" + expr + "<<");
}
}
}
result.append(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())
&& !(children[i] instanceof ASTMethod)) {
if (children[i] instanceof ASTVarRef
|| children[i] instanceof ASTProperty
|| children[i] instanceof ASTChain)
result.append(".");
result.append(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.toString();
} catch (Throwable t) {
throw OgnlOps.castToRuntime(t);
}
}
}