use of org.mvel2.optimizers.impl.refl.nodes.MapAccessor in project mvel by mikebrock.
the class ReflectiveAccessorOptimizer method getCollectionPropertyAO.
private Object getCollectionPropertyAO(Object ctx, String prop) throws Exception {
if (prop.length() > 0) {
ctx = getBeanPropertyAO(ctx, prop);
}
if (ctx == null)
return null;
int _start = ++cursor;
skipWhitespace();
if (cursor == end)
throw new CompileException("unterminated '['", this.expr, this.start);
String item;
if (scanTo(']'))
throw new CompileException("unterminated '['", this.expr, this.start);
item = new String(expr, _start, cursor - _start);
boolean itemSubExpr = true;
Object idx = null;
try {
idx = parseInt(item);
itemSubExpr = false;
} catch (Exception e) {
// not a number;
}
ExecutableStatement itemStmt = null;
if (itemSubExpr) {
idx = (itemStmt = (ExecutableStatement) subCompileExpression(item.toCharArray(), pCtx)).getValue(ctx, thisRef, variableFactory);
}
++cursor;
if (ctx instanceof Map) {
if (hasPropertyHandler(Map.class)) {
return propHandler(item, ctx, Map.class);
} else {
if (itemSubExpr) {
addAccessorNode(new MapAccessorNest(itemStmt, null));
} else {
addAccessorNode(new MapAccessor(parseInt(item)));
}
return ((Map) ctx).get(idx);
}
} else if (ctx instanceof List) {
if (hasPropertyHandler(List.class)) {
return propHandler(item, ctx, List.class);
} else {
if (itemSubExpr) {
addAccessorNode(new ListAccessorNest(itemStmt, null));
} else {
addAccessorNode(new ListAccessor(parseInt(item)));
}
return ((List) ctx).get((Integer) idx);
}
} else if (ctx.getClass().isArray()) {
if (hasPropertyHandler(Array.class)) {
return propHandler(item, ctx, Array.class);
} else {
if (itemSubExpr) {
addAccessorNode(new ArrayAccessorNest(itemStmt));
} else {
addAccessorNode(new ArrayAccessor(parseInt(item)));
}
return Array.get(ctx, (Integer) idx);
}
} else if (ctx instanceof CharSequence) {
if (hasPropertyHandler(CharSequence.class)) {
return propHandler(item, ctx, CharSequence.class);
} else {
if (itemSubExpr) {
addAccessorNode(new IndexedCharSeqAccessorNest(itemStmt));
} else {
addAccessorNode(new IndexedCharSeqAccessor(parseInt(item)));
}
return ((CharSequence) ctx).charAt((Integer) idx);
}
} else {
TypeDescriptor tDescr = new TypeDescriptor(expr, this.start, end - this.start, 0);
if (tDescr.isArray()) {
Class cls = getClassReference((Class) ctx, tDescr, variableFactory, pCtx);
rootNode = new StaticReferenceAccessor(cls);
return cls;
}
throw new CompileException("illegal use of []: unknown type: " + ctx.getClass().getName(), this.expr, this.st);
}
}
use of org.mvel2.optimizers.impl.refl.nodes.MapAccessor in project mvel by mikebrock.
the class ReflectiveAccessorOptimizer method getCollectionProperty.
/**
* Handle accessing a property embedded in a collections, map, or array
*
* @param ctx -
* @param prop -
* @return -
* @throws Exception -
*/
private Object getCollectionProperty(Object ctx, String prop) throws Exception {
if (prop.length() > 0) {
ctx = getBeanProperty(ctx, prop);
}
if (ctx == null)
return null;
int start = ++cursor;
skipWhitespace();
if (cursor == end)
throw new CompileException("unterminated '['", this.expr, this.start);
String item;
if (scanTo(']'))
throw new CompileException("unterminated '['", this.expr, this.start);
item = new String(expr, start, cursor - start);
boolean itemSubExpr = true;
Object idx = null;
try {
idx = parseInt(item);
itemSubExpr = false;
} catch (Exception e) {
// not a number;
}
ExecutableStatement itemStmt = null;
if (itemSubExpr) {
try {
idx = (itemStmt = (ExecutableStatement) subCompileExpression(item.toCharArray(), pCtx)).getValue(ctx, thisRef, variableFactory);
} catch (CompileException e) {
e.setExpr(this.expr);
e.setCursor(start);
throw e;
}
}
++cursor;
if (ctx instanceof Map) {
if (itemSubExpr) {
addAccessorNode(new MapAccessorNest(itemStmt, null));
} else {
addAccessorNode(new MapAccessor(parseInt(item)));
}
return ((Map) ctx).get(idx);
} else if (ctx instanceof List) {
if (itemSubExpr) {
addAccessorNode(new ListAccessorNest(itemStmt, null));
} else {
addAccessorNode(new ListAccessor(parseInt(item)));
}
return ((List) ctx).get((Integer) idx);
} else if (ctx.getClass().isArray()) {
if (itemSubExpr) {
addAccessorNode(new ArrayAccessorNest(itemStmt));
} else {
addAccessorNode(new ArrayAccessor(parseInt(item)));
}
return Array.get(ctx, (Integer) idx);
} else if (ctx instanceof CharSequence) {
if (itemSubExpr) {
addAccessorNode(new IndexedCharSeqAccessorNest(itemStmt));
} else {
addAccessorNode(new IndexedCharSeqAccessor(parseInt(item)));
}
return ((CharSequence) ctx).charAt((Integer) idx);
} else {
TypeDescriptor tDescr = new TypeDescriptor(expr, this.start, length, 0);
if (tDescr.isArray()) {
Class cls = getClassReference((Class) ctx, tDescr, variableFactory, pCtx);
rootNode = new StaticReferenceAccessor(cls);
return cls;
}
throw new CompileException("illegal use of []: unknown type: " + ctx.getClass().getName(), this.expr, this.start);
}
}
use of org.mvel2.optimizers.impl.refl.nodes.MapAccessor in project mvel by mikebrock.
the class ReflectiveAccessorOptimizer method optimizeSetAccessor.
public Accessor optimizeSetAccessor(ParserContext pCtx, char[] property, int start, int offset, Object ctx, Object thisRef, VariableResolverFactory factory, boolean rootThisRef, Object value, Class ingressType) {
this.rootNode = this.currNode = null;
this.expr = property;
this.start = start;
this.first = true;
this.length = start + offset;
this.ctx = ctx;
this.thisRef = thisRef;
this.variableFactory = factory;
this.ingressType = ingressType;
char[] root = null;
int split = findLastUnion();
PropertyVerifier verifier = new PropertyVerifier(property, this.pCtx = pCtx);
if (split != -1) {
root = subset(property, 0, split++);
// todo: must use the property verifier.
property = subset(property, split, property.length - split);
}
if (root != null) {
this.length = end = (this.expr = root).length;
compileGetChain();
ctx = this.val;
}
if (ctx == null) {
throw new PropertyAccessException("could not access property: " + new String(property, this.start, length) + "; parent is null: " + new String(expr), expr, this.start);
}
try {
this.length = end = (this.expr = property).length;
int st;
this.cursor = st = 0;
skipWhitespace();
if (collection) {
st = cursor;
if (cursor == end)
throw new PropertyAccessException("unterminated '['", expr, this.start);
if (scanTo(']'))
throw new PropertyAccessException("unterminated '['", expr, this.start);
String ex = new String(property, st, cursor - st);
if (ctx instanceof Map) {
if (MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING && hasPropertyHandler(Map.class)) {
propHandlerSet(ex, ctx, Map.class, value);
} else {
// noinspection unchecked
((Map) ctx).put(eval(ex, ctx, variableFactory), convert(value, returnType = verifier.analyze()));
addAccessorNode(new MapAccessorNest(ex, returnType));
}
return rootNode;
} else if (ctx instanceof List) {
if (MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING && hasPropertyHandler(List.class)) {
propHandlerSet(ex, ctx, List.class, value);
} else {
// noinspection unchecked
((List) ctx).set(eval(ex, ctx, variableFactory, Integer.class), convert(value, returnType = verifier.analyze()));
addAccessorNode(new ListAccessorNest(ex, returnType));
}
return rootNode;
} else if (MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING && hasPropertyHandler(ctx.getClass())) {
propHandlerSet(ex, ctx, ctx.getClass(), value);
return rootNode;
} else if (ctx.getClass().isArray()) {
if (MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING && hasPropertyHandler(Array.class)) {
propHandlerSet(ex, ctx, Array.class, value);
} else {
// noinspection unchecked
Array.set(ctx, eval(ex, ctx, variableFactory, Integer.class), convert(value, getBaseComponentType(ctx.getClass())));
addAccessorNode(new ArrayAccessorNest(ex));
}
return rootNode;
} else {
throw new PropertyAccessException("cannot bind to collection property: " + new String(property) + ": not a recognized collection type: " + ctx.getClass(), expr, this.st);
}
} else if (MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING && hasPropertyHandler(ctx.getClass())) {
propHandlerSet(new String(property), ctx, ctx.getClass(), value);
return rootNode;
}
String tk = new String(property, 0, length);
if (hasSetListeners()) {
notifySetListeners(ctx, tk, variableFactory, value);
addAccessorNode(new Notify(tk));
}
Member member = getFieldOrWriteAccessor(ctx.getClass(), tk, value == null ? null : ingressType);
if (member instanceof Field) {
Field fld = (Field) member;
if (value != null && !fld.getType().isAssignableFrom(value.getClass())) {
if (!canConvert(fld.getType(), value.getClass())) {
throw new CompileException("cannot convert type: " + value.getClass() + ": to " + fld.getType(), this.expr, this.start);
}
fld.set(ctx, convert(value, fld.getType()));
addAccessorNode(new DynamicFieldAccessor(fld));
} else if (value == null && fld.getType().isPrimitive()) {
fld.set(ctx, PropertyTools.getPrimitiveInitialValue(fld.getType()));
addAccessorNode(new FieldAccessor(fld));
} else {
fld.set(ctx, value);
addAccessorNode(new FieldAccessor(fld));
}
} else if (member != null) {
Method meth = (Method) member;
if (value != null && !meth.getParameterTypes()[0].isAssignableFrom(value.getClass())) {
if (!canConvert(meth.getParameterTypes()[0], value.getClass())) {
throw new CompileException("cannot convert type: " + value.getClass() + ": to " + meth.getParameterTypes()[0], this.expr, this.start);
}
meth.invoke(ctx, convert(value, meth.getParameterTypes()[0]));
} else if (value == null && meth.getParameterTypes()[0].isPrimitive()) {
meth.invoke(ctx, PropertyTools.getPrimitiveInitialValue(meth.getParameterTypes()[0]));
} else {
meth.invoke(ctx, value);
}
addAccessorNode(new SetterAccessor(meth));
} else if (ctx instanceof Map) {
// noinspection unchecked
((Map) ctx).put(tk, value);
addAccessorNode(new MapAccessor(tk));
} else {
throw new PropertyAccessException("could not access property (" + tk + ") in: " + ingressType.getName(), this.expr, this.start);
}
} catch (InvocationTargetException e) {
throw new PropertyAccessException("could not access property: " + new String(property), this.expr, st, e);
} catch (IllegalAccessException e) {
throw new PropertyAccessException("could not access property: " + new String(property), this.expr, st, e);
} catch (IllegalArgumentException e) {
throw new PropertyAccessException("error binding property: " + new String(property) + " (value <<" + value + ">>::" + (value == null ? "null" : value.getClass().getCanonicalName()) + ")", this.expr, st, e);
}
return rootNode;
}
use of org.mvel2.optimizers.impl.refl.nodes.MapAccessor in project drools by kiegroup.
the class ConditionAnalyzer method analyzeAccessorInvocation.
private Invocation analyzeAccessorInvocation(AccessorNode accessorNode, ASTNode containingNode, Invocation formerInvocation, Class<?> variableType) {
if (accessorNode instanceof GetterAccessor) {
return new MethodInvocation(((GetterAccessor) accessorNode).getMethod(), variableType == null ? conditionClass : variableType.getName());
}
if (accessorNode instanceof MethodAccessor) {
MethodAccessor methodAccessor = (MethodAccessor) accessorNode;
Method method = methodAccessor.getMethod();
MethodInvocation invocation = new MethodInvocation(method);
boolean isVarArgs = method.isVarArgs();
readInvocationParams(invocation, methodAccessor.getParms(), methodAccessor.getParameterTypes(), isVarArgs);
return invocation;
}
if (accessorNode instanceof ConstructorAccessor) {
ConstructorAccessor constructorAccessor = (ConstructorAccessor) accessorNode;
Constructor constructor = constructorAccessor.getConstructor();
ConstructorInvocation invocation = new ConstructorInvocation(constructor);
readInvocationParams(invocation, constructorAccessor.getParameters(), constructorAccessor.getParameterTypes(), constructor.isVarArgs());
return invocation;
}
if (accessorNode instanceof ArrayAccessor) {
ArrayAccessor arrayAccessor = (ArrayAccessor) accessorNode;
return new ArrayAccessInvocation(formerInvocation != null ? formerInvocation.getReturnType() : Object[].class, new FixedExpression(int.class, arrayAccessor.getIndex()));
}
if (accessorNode instanceof ArrayAccessorNest) {
ArrayAccessorNest arrayAccessorNest = (ArrayAccessorNest) accessorNode;
ExecutableAccessor index = (ExecutableAccessor) arrayAccessorNest.getIndex();
return new ArrayAccessInvocation(formerInvocation != null ? formerInvocation.getReturnType() : Object[].class, analyzeNode(index.getNode()));
}
if (accessorNode instanceof ArrayLength) {
return new ArrayLengthInvocation();
}
if (accessorNode instanceof ListAccessor) {
Class<?> listType = getListType(formerInvocation);
ListAccessor listAccessor = (ListAccessor) accessorNode;
return new ListAccessInvocation(listType, new FixedExpression(int.class, listAccessor.getIndex()));
}
if (accessorNode instanceof ListAccessorNest) {
Class<?> listType = getListType(formerInvocation);
ListAccessorNest listAccessorNest = (ListAccessorNest) accessorNode;
ExecutableAccessor index = (ExecutableAccessor) listAccessorNest.getIndex();
return new ListAccessInvocation(listType, analyzeNode(index.getNode()));
}
if (accessorNode instanceof MapAccessor) {
MapAccessor mapAccessor = (MapAccessor) accessorNode;
return new MapAccessInvocation(Object.class, Object.class, new FixedExpression(Object.class, mapAccessor.getProperty()));
}
if (accessorNode instanceof MapAccessorNest) {
Class<?> keyType = Object.class;
Class<?> valueType = Object.class;
Type[] generics = getGenerics(formerInvocation);
if (generics != null && generics.length == 2 && generics[0] instanceof Class) {
keyType = (Class<?>) generics[0];
if (generics[1] instanceof Class)
valueType = (Class<?>) generics[1];
}
MapAccessorNest mapAccessor = (MapAccessorNest) accessorNode;
ExecutableStatement statement = mapAccessor.getProperty();
if (statement instanceof ExecutableLiteral) {
return new MapAccessInvocation(keyType, valueType, new FixedExpression(keyType, ((ExecutableLiteral) statement).getLiteral()));
} else {
return new MapAccessInvocation(keyType, valueType, analyzeNode(((ExecutableAccessor) statement).getNode()));
}
}
if (accessorNode instanceof FieldAccessor) {
return new FieldAccessInvocation(((FieldAccessor) accessorNode).getField());
}
if (accessorNode instanceof StaticVarAccessor) {
Field field = ((StaticVarAccessor) accessorNode).getField();
return new FieldAccessInvocation(field);
}
if (accessorNode instanceof ThisValueAccessor) {
return new ThisInvocation(accessorNode.getNextNode() == null ? containingNode.getEgressType() : Object.class);
}
throw new RuntimeException("Unknown AccessorNode type: " + accessorNode.getClass().getName());
}
Aggregations