
org.apache.ibatis.ognl.ASTChain Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mybatis Show documentation
Show all versions of mybatis Show documentation
The MyBatis SQL mapper framework makes it easier to use a relational database with object-oriented
applications. MyBatis couples objects with stored procedures or SQL statements using a XML descriptor or
annotations. Simplicity is the biggest advantage of the MyBatis data mapper over object relational mapping
tools.
/*
* 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 org.apache.ibatis.ognl.enhance.OrderedReturn;
import org.apache.ibatis.ognl.enhance.UnsupportedCompilationException;
import java.lang.reflect.Array;
public class ASTChain extends SimpleNode implements NodeType, OrderedReturn {
private static final long serialVersionUID = 6689037266594707682L;
private final boolean shortCircuit = Boolean.parseBoolean(System.getProperty("org.apache.ibatis.ognl.chain.short-circuit", "true"));
private Class> getterClass;
private Class> setterClass;
private String lastExpression;
private String coreExpression;
public ASTChain(int id) {
super(id);
}
public ASTChain(OgnlParser p, int id) {
super(p, id);
}
public String getLastExpression() {
return lastExpression;
}
public String getCoreExpression() {
return coreExpression;
}
public void jjtClose() {
flattenTree();
}
protected Object getValueBody(OgnlContext context, Object source) throws OgnlException {
Object result = source;
// short-circuit the chain only in case if the root is null and this isn't IN operator
if (shortCircuit && result == null && !(parent instanceof ASTIn)) {
return null;
}
for (int i = 0, ilast = children.length - 1; i <= ilast; ++i) {
// short-circuit the chain only in case if the root is null and accessing property
if (shortCircuit && result == null && (children[i] instanceof ASTProperty)) {
return null;
}
boolean handled = false;
if (i < ilast) {
if (children[i] instanceof ASTProperty) {
ASTProperty propertyNode = (ASTProperty) children[i];
int indexType = propertyNode.getIndexedPropertyType(context, result);
if ((indexType != OgnlRuntime.INDEXED_PROPERTY_NONE) && (children[i + 1] instanceof ASTProperty)) {
ASTProperty indexNode = (ASTProperty) children[i + 1];
if (indexNode.isIndexedAccess()) {
Object index = indexNode.getProperty(context, result);
if (index instanceof DynamicSubscript) {
if (indexType == OgnlRuntime.INDEXED_PROPERTY_INT) {
Object array = propertyNode.getValue(context, result);
int len = Array.getLength(array);
switch (((DynamicSubscript) index).getFlag()) {
case DynamicSubscript.ALL:
result = Array.newInstance(array.getClass().getComponentType(), len);
System.arraycopy(array, 0, result, 0, len);
handled = true;
i++;
break;
case DynamicSubscript.FIRST:
index = (len > 0) ? 0 : -1;
break;
case DynamicSubscript.MID:
index = (len > 0) ? (len / 2) : -1;
break;
case DynamicSubscript.LAST:
index = (len > 0) ? (len - 1) : -1;
break;
}
} else {
if (indexType == OgnlRuntime.INDEXED_PROPERTY_OBJECT) {
throw new OgnlException(
"DynamicSubscript '" + indexNode
+ "' not allowed for object indexed property '" + propertyNode
+ "'");
}
}
}
if (!handled) {
result = OgnlRuntime.getIndexedProperty(context, result,
propertyNode.getProperty(context, result).toString(),
index);
handled = true;
i++;
}
}
}
}
}
if (!handled) {
result = children[i].getValue(context, result);
}
}
return result;
}
protected void setValueBody(OgnlContext context, Object target, Object value)
throws OgnlException {
boolean handled = false;
for (int i = 0, ilast = children.length - 2; i <= ilast; ++i) {
if (children[i] instanceof ASTProperty) {
ASTProperty propertyNode = (ASTProperty) children[i];
int indexType = propertyNode.getIndexedPropertyType(context, target);
if ((indexType != OgnlRuntime.INDEXED_PROPERTY_NONE) && (children[i + 1] instanceof ASTProperty)) {
ASTProperty indexNode = (ASTProperty) children[i + 1];
if (indexNode.isIndexedAccess()) {
Object index = indexNode.getProperty(context, target);
if (index instanceof DynamicSubscript) {
if (indexType == OgnlRuntime.INDEXED_PROPERTY_INT) {
Object array = propertyNode.getValue(context, target);
int len = Array.getLength(array);
switch (((DynamicSubscript) index).getFlag()) {
case DynamicSubscript.ALL:
System.arraycopy(target, 0, value, 0, len);
handled = true;
i++;
break;
case DynamicSubscript.FIRST:
index = (len > 0) ? 0 : -1;
break;
case DynamicSubscript.MID:
index = (len > 0) ? (len / 2) : -1;
break;
case DynamicSubscript.LAST:
index = (len > 0) ? (len - 1) : -1;
break;
}
} else {
if (indexType == OgnlRuntime.INDEXED_PROPERTY_OBJECT) {
throw new OgnlException("DynamicSubscript '" + indexNode
+ "' not allowed for object indexed property '" + propertyNode
+ "'");
}
}
}
if (!handled && i == ilast) {
OgnlRuntime.setIndexedProperty(context, target,
propertyNode.getProperty(context, target).toString(),
index, value);
handled = true;
i++;
} else if (!handled) {
target = OgnlRuntime.getIndexedProperty(context, target,
propertyNode.getProperty(context, target).toString(),
index);
i++;
continue;
}
}
}
}
if (!handled) {
target = children[i].getValue(context, target);
}
}
if (!handled) {
children[children.length - 1].setValue(context, target, value);
}
}
public boolean isSimpleNavigationChain(OgnlContext context)
throws OgnlException {
boolean result = false;
if ((children != null) && (children.length > 0)) {
result = true;
for (int i = 0; result && (i < children.length); i++) {
if (children[i] instanceof SimpleNode) {
result = ((SimpleNode) children[i]).isSimpleProperty(context);
} else {
result = false;
}
}
}
return result;
}
public Class> getGetterClass() {
return getterClass;
}
public Class> getSetterClass() {
return setterClass;
}
public String toString() {
StringBuilder result = new StringBuilder();
if ((children != null) && (children.length > 0)) {
for (int i = 0; i < children.length; i++) {
if (i > 0) {
if (!(children[i] instanceof ASTProperty) || !((ASTProperty) children[i]).isIndexedAccess()) {
result.append(".");
}
}
result.append(children[i].toString());
}
}
return result.toString();
}
public String toGetSourceString(OgnlContext context, Object target) {
String prevChain = (String) context.get("_currentChain");
if (target != null) {
context.setCurrentObject(target);
context.setCurrentType(target.getClass());
}
String result = "";
NodeType _lastType = null;
boolean ordered = false;
boolean constructor = false;
try {
if ((children != null) && (children.length > 0)) {
for (Node child : children) {
String value = child.toGetSourceString(context, context.getCurrentObject());
if (child instanceof ASTCtor)
constructor = true;
if (child instanceof NodeType
&& ((NodeType) child).getGetterClass() != null) {
_lastType = (NodeType) child;
}
if (!(child instanceof ASTVarRef) && !constructor
&& !(child instanceof OrderedReturn && ((OrderedReturn) child).getLastExpression() != null)
&& (!(parent instanceof ASTSequence))) {
value = OgnlRuntime.getCompiler().castExpression(context, child, value);
}
if (child instanceof OrderedReturn && ((OrderedReturn) child).getLastExpression() != null) {
ordered = true;
OrderedReturn or = (OrderedReturn) child;
if (or.getCoreExpression() == null || or.getCoreExpression().trim().length() <= 0)
result = "";
else
result += or.getCoreExpression();
lastExpression = or.getLastExpression();
if (context.get(ExpressionCompiler.PRE_CAST) != null) {
lastExpression = context.remove(ExpressionCompiler.PRE_CAST) + lastExpression;
}
} else if (child instanceof ASTOr
|| child instanceof ASTAnd
|| child instanceof ASTCtor
|| (child instanceof ASTStaticField && parent == null)) {
context.put("_noRoot", "true");
result = value;
} else {
result += value;
}
context.put("_currentChain", result);
}
}
} catch (Throwable t) {
throw OgnlOps.castToRuntime(t);
}
if (_lastType != null) {
getterClass = _lastType.getGetterClass();
setterClass = _lastType.getSetterClass();
}
if (ordered) {
coreExpression = result;
}
context.put("_currentChain", prevChain);
return result;
}
public String toSetSourceString(OgnlContext context, Object target) {
String prevChain = (String) context.get("_currentChain");
String prevChild = (String) context.get("_lastChild");
if (prevChain != null)
throw new UnsupportedCompilationException("Can't compile nested chain expressions.");
if (target != null) {
context.setCurrentObject(target);
context.setCurrentType(target.getClass());
}
String result = "";
NodeType _lastType = null;
boolean constructor = false;
try {
if ((children != null) && (children.length > 0)) {
if (children[0] instanceof ASTConst) {
throw new UnsupportedCompilationException("Can't modify constant values.");
}
for (int i = 0; i < children.length; i++) {
if (i == (children.length - 1)) {
context.put("_lastChild", "true");
}
String value = children[i].toSetSourceString(context, context.getCurrentObject());
if (children[i] instanceof ASTCtor)
constructor = true;
if (children[i] instanceof NodeType
&& ((NodeType) children[i]).getGetterClass() != null) {
_lastType = (NodeType) children[i];
}
if (!(children[i] instanceof ASTVarRef) && !constructor
&& !(children[i] instanceof OrderedReturn && ((OrderedReturn) children[i]).getLastExpression() != null)
&& (!(parent instanceof ASTSequence))) {
value = OgnlRuntime.getCompiler().castExpression(context, children[i], value);
}
if (children[i] instanceof ASTOr
|| children[i] instanceof ASTAnd
|| children[i] instanceof ASTCtor
|| children[i] instanceof ASTStaticField) {
context.put("_noRoot", "true");
result = value;
} else
result += value;
context.put("_currentChain", result);
}
}
} catch (Throwable t) {
throw OgnlOps.castToRuntime(t);
}
context.put("_lastChild", prevChild);
context.put("_currentChain", prevChain);
if (_lastType != null)
setterClass = _lastType.getSetterClass();
return result;
}
@Override
public boolean isChain(OgnlContext context) {
return true;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy