org.mvel2.ast.InlineCollectionNode Maven / Gradle / Ivy
The newest version!
/**
* MVEL 2.0
* Copyright (C) 2007 The Codehaus
* Mike Brock, Dhanji Prasanna, John Graham, Mark Proctor
*
* Licensed 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.mvel2.ast;
import org.mvel2.CompileException;
import org.mvel2.MVEL;
import org.mvel2.ParserContext;
import org.mvel2.compiler.AbstractParser;
import org.mvel2.integration.VariableResolverFactory;
import org.mvel2.optimizers.AccessorOptimizer;
import org.mvel2.optimizers.OptimizerFactory;
import org.mvel2.util.CollectionParser;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.mvel2.util.ParseTools.*;
/**
* @author Christopher Brock
*/
public class InlineCollectionNode extends ASTNode {
private Object collectionGraph;
int trailingStart;
int trailingOffset;
public InlineCollectionNode(char[] expr, int start, int end, int fields, ParserContext pctx) {
super(expr, start, end, fields | INLINE_COLLECTION, pctx);
if ((fields & COMPILE_IMMEDIATE) != 0) {
parseGraph(true, null, pctx);
try {
AccessorOptimizer ao = OptimizerFactory.getThreadAccessorOptimizer();
accessor = ao.optimizeCollection(pctx, collectionGraph, egressType, expr, trailingStart, trailingOffset, null, null, null);
egressType = ao.getEgressType();
}
finally {
OptimizerFactory.clearThreadAccessorOptimizer();
}
}
}
public InlineCollectionNode(char[] expr, int start, int end, int fields, Class type, ParserContext pctx) {
super(expr, start, end, fields | INLINE_COLLECTION, pctx);
this.egressType = type;
if ((fields & COMPILE_IMMEDIATE) != 0) {
try {
parseGraph(true, type, pctx);
AccessorOptimizer ao = OptimizerFactory.getThreadAccessorOptimizer();
accessor = ao.optimizeCollection(pctx, collectionGraph, egressType, expr, this.trailingStart, trailingOffset, null, null, null);
egressType = ao.getEgressType();
}
finally {
OptimizerFactory.clearThreadAccessorOptimizer();
}
}
}
public Object getReducedValueAccelerated(Object ctx, Object thisValue, VariableResolverFactory factory) {
if (accessor != null) {
return accessor.getValue(ctx, thisValue, factory);
}
else {
try {
AccessorOptimizer ao = OptimizerFactory.getThreadAccessorOptimizer();
if (collectionGraph == null) parseGraph(true, null, null);
accessor = ao.optimizeCollection(AbstractParser.getCurrentThreadParserContext(), collectionGraph,
egressType, expr, trailingStart, trailingOffset, ctx, thisValue, factory);
egressType = ao.getEgressType();
return accessor.getValue(ctx, thisValue, factory);
}
finally {
OptimizerFactory.clearThreadAccessorOptimizer();
}
}
}
public Object getReducedValue(Object ctx, Object thisValue, VariableResolverFactory factory) {
parseGraph(false, egressType, AbstractParser.getCurrentThreadParserContext());
return execGraph(collectionGraph, egressType, ctx, factory);
}
private void parseGraph(boolean compile, Class type, ParserContext pCtx) {
CollectionParser parser = new CollectionParser();
if (type == null) {
collectionGraph = ((List) parser.parseCollection(expr, start, offset, compile, pCtx)).get(0);
}
else {
collectionGraph = ((List) parser.parseCollection(expr, start, offset, compile, type, pCtx)).get(0);
}
trailingStart = parser.getCursor() + 2;
trailingOffset = offset - (trailingStart - start);
if (this.egressType == null) this.egressType = collectionGraph.getClass();
}
private Object execGraph(Object o, Class type, Object ctx, VariableResolverFactory factory) {
if (o instanceof List) {
ArrayList list = new ArrayList(((List) o).size());
for (Object item : (List) o) {
list.add(execGraph(item, type, ctx, factory));
}
return list;
}
else if (o instanceof Map) {
HashMap map = new HashMap();
for (Object item : ((Map) o).keySet()) {
map.put(execGraph(item, type, ctx, factory), execGraph(((Map) o).get(item), type, ctx, factory));
}
return map;
}
else if (o instanceof Object[]) {
int dim = 0;
if (type != null) {
String nm = type.getName();
while (nm.charAt(dim) == '[') dim++;
}
else {
type = Object[].class;
dim = 1;
}
Object newArray = Array.newInstance(getSubComponentType(type), ((Object[]) o).length);
try {
Class cls = dim > 1 ? findClass(null, repeatChar('[', dim - 1) + "L" + getBaseComponentType(type).getName() + ";", AbstractParser.getCurrentThreadParserContext())
: type;
int c = 0;
for (Object item : (Object[]) o) {
Array.set(newArray, c++, execGraph(item, cls, ctx, factory));
}
return newArray;
}
catch (IllegalArgumentException e) {
throw new CompileException("type mismatch in array", expr, start, e);
}
catch (ClassNotFoundException e) {
throw new RuntimeException("this error should never throw:" + getBaseComponentType(type).getName(), e);
}
}
else {
if (type.isArray()) {
return MVEL.eval((String) o, ctx, factory, getBaseComponentType(type));
}
else {
return MVEL.eval((String) o, ctx, factory);
}
}
}
}