Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

增加调用对象方法的功能 #169

Closed
lixinlin opened this issue Oct 1, 2019 · 23 comments
Closed

增加调用对象方法的功能 #169

lixinlin opened this issue Oct 1, 2019 · 23 comments

Comments

@lixinlin
Copy link

lixinlin commented Oct 1, 2019

如果表达式中引用了环境变量里面的对象,需要在表达式里能够调用这个对象的方法执行一些处理

@lixinlin
Copy link
Author

lixinlin commented Oct 8, 2019

这个方法不适用,表达式是通过配置配置进去的,程序会给表达式传递上下文参数,将所有可能需要的实例对象都传递给上下文作为表达式的参数,表达式里面根据传递的对象要进行一些对象方法的引用处理(其中还会用到其他对象的属性值),此时对于程序来说表达式到底会用到哪些实例是未知的,只有运行时加载了表达式才知道,所以不可能提前导入,下面是我debug源码以后加了补丁的代码,你看一下:
package com.googlecode.aviator;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;

import com.googlecode.aviator.exception.FunctionNotFoundException;
import com.googlecode.aviator.runtime.type.AviatorFunction;
import com.googlecode.aviator.runtime.type.AviatorObject;
import com.googlecode.aviator.runtime.type.AviatorRuntimeJavaType;
import com.googlecode.aviator.runtime.type.AviatorType;

/**

  • Runtime function delegator
  • @author dennis

*/
final class RuntimeFunctionDelegator extends AviatorObject implements AviatorFunction {

@OverRide
public int compare(AviatorObject other, Map<String, Object> env) {
throw new UnsupportedOperationException("Lambda function can't be compared.");
}

@OverRide
public AviatorType getAviatorType() {
return AviatorType.Lambda;
}

@OverRide
public Object getValue(Map<String, Object> env) {
return this;
}

@OverRide
public AviatorObject call(Map<String, Object> env) {
return getFunc(env).call(env);
}

@OverRide
public AviatorObject call(Map<String, Object> env, AviatorObject arg1) {
return getFunc(env, arg1).call(env, arg1);
}

@OverRide
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
return getFunc(env, arg1, arg2).call(env, arg1, arg2);
}

@OverRide
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2,
AviatorObject arg3) {
return getFunc(env, arg1, arg2, arg3).call(env, arg1, arg2, arg3);
}

@OverRide
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2,
AviatorObject arg3, AviatorObject arg4) {
return getFunc(env, arg1, arg2, arg3, arg4).call(env, arg1, arg2, arg3, arg4);
}

@OverRide
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2,
AviatorObject arg3, AviatorObject arg4, AviatorObject arg5) {
return getFunc(env, arg1, arg2, arg3, arg4, arg5).call(env, arg1, arg2, arg3, arg4, arg5);
}

@OverRide
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2,
AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6) {
return getFunc(env, arg1, arg2, arg3, arg4, arg5, arg6).call(env, arg1, arg2, arg3, arg4, arg5, arg6);
}

@OverRide
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2,
AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6,
AviatorObject arg7) {
return getFunc(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7).call(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}

@OverRide
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2,
AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6,
AviatorObject arg7, AviatorObject arg8) {
return getFunc(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8).call(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
}

@OverRide
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2,
AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6,
AviatorObject arg7, AviatorObject arg8, AviatorObject arg9) {
return getFunc(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9).call(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
}

@OverRide
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2,
AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6,
AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10) {
return getFunc(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10).call(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
}

@OverRide
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2,
AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6,
AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10,
AviatorObject arg11) {
return getFunc(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
arg11).call(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
arg11);
}

@OverRide
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2,
AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6,
AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10,
AviatorObject arg11, AviatorObject arg12) {
return getFunc(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
arg11, arg12).call(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
arg11, arg12);
}

@OverRide
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2,
AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6,
AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10,
AviatorObject arg11, AviatorObject arg12, AviatorObject arg13) {
return getFunc(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
arg11, arg12, arg13).call(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
arg11, arg12, arg13);
}

@OverRide
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2,
AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6,
AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10,
AviatorObject arg11, AviatorObject arg12, AviatorObject arg13, AviatorObject arg14) {
return getFunc(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
arg11, arg12, arg13, arg14).call(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
arg11, arg12, arg13, arg14);
}

@OverRide
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2,
AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6,
AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10,
AviatorObject arg11, AviatorObject arg12, AviatorObject arg13, AviatorObject arg14,
AviatorObject arg15) {
return getFunc(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
arg11, arg12, arg13, arg14, arg15).call(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
arg11, arg12, arg13, arg14, arg15);
}

@OverRide
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2,
AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6,
AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10,
AviatorObject arg11, AviatorObject arg12, AviatorObject arg13, AviatorObject arg14,
AviatorObject arg15, AviatorObject arg16) {
return getFunc(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
arg11, arg12, arg13, arg14, arg15, arg16).call(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
arg11, arg12, arg13, arg14, arg15, arg16);
}

@OverRide
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2,
AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6,
AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10,
AviatorObject arg11, AviatorObject arg12, AviatorObject arg13, AviatorObject arg14,
AviatorObject arg15, AviatorObject arg16, AviatorObject arg17) {
return getFunc(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
arg11, arg12, arg13, arg14, arg15, arg16, arg17).call(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
arg11, arg12, arg13, arg14, arg15, arg16, arg17);
}

@OverRide
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2,
AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6,
AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10,
AviatorObject arg11, AviatorObject arg12, AviatorObject arg13, AviatorObject arg14,
AviatorObject arg15, AviatorObject arg16, AviatorObject arg17, AviatorObject arg18) {
return getFunc(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18).call(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18);
}

@OverRide
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2,
AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6,
AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10,
AviatorObject arg11, AviatorObject arg12, AviatorObject arg13, AviatorObject arg14,
AviatorObject arg15, AviatorObject arg16, AviatorObject arg17, AviatorObject arg18,
AviatorObject arg19) {
return getFunc(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19).call(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19);
}

@OverRide
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2,
AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6,
AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10,
AviatorObject arg11, AviatorObject arg12, AviatorObject arg13, AviatorObject arg14,
AviatorObject arg15, AviatorObject arg16, AviatorObject arg17, AviatorObject arg18,
AviatorObject arg19, AviatorObject arg20) {
return getFunc(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19, arg20).call(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19, arg20);
}

@OverRide
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2,
AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6,
AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10,
AviatorObject arg11, AviatorObject arg12, AviatorObject arg13, AviatorObject arg14,
AviatorObject arg15, AviatorObject arg16, AviatorObject arg17, AviatorObject arg18,
AviatorObject arg19, AviatorObject arg20, AviatorObject... args) {
AviatorObject[] argss = new AviatorObject[20+args.length];
argss[0]=arg1;
argss[1]=arg2;
argss[2]=arg3;
argss[3]=arg4;
argss[4]=arg5;
argss[5]=arg6;
argss[6]=arg7;
argss[7]=arg8;
argss[8]=arg9;
argss[9]=arg10;
argss[10]=arg11;
argss[11]=arg12;
argss[12]=arg13;
argss[13]=arg14;
argss[14]=arg15;
argss[15]=arg16;
argss[16]=arg17;
argss[17]=arg18;
argss[18]=arg19;
argss[19]=arg20;
int i=20;
for(AviatorObject aviatorObject:args) {
argss[i++] = aviatorObject;
}
return getFunc(env, argss).call(env, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19, arg20, args);
}

private final String name;

RuntimeFunctionDelegator(String name) {
this.name = name;
}

@OverRide
public String getName() {
return name;
}

private AviatorFunction getFunc(Map<String, Object> env, AviatorObject ...args) {
Object val = env.get(name);
if (val!=null && val instanceof AviatorFunction) {
return (AviatorFunction) val;
}else {
String[] names = name.split("\.");
Class[] parameterTypes = fetchTypes(env, args); Object[] objs = new Object[1]; Method m = detectMethod(names, 0, env, parameterTypes, objs); if(m!=null) { return new DelegateFunction(objs[0],m); } } throw new FunctionNotFoundException("Function not found: " + this.name); } private Method detectMethod(String[] names, int index, Object object, Class[] parameterTypes, Object[] objs) {
if(index==names.length-1) {
Method m = findMethod(object, names[index], parameterTypes, objs);
if(m!=null) {
return m;
}
}else if(object instanceof Map && ((Map)object).containsKey(names[index])) {
Object sobject = ((Map)object).get(names[index]);
return detectMethod(names, index+1, sobject, parameterTypes, objs);
}else {
Field f = findField(object, names[index]);
if(f!=null) {
try {
f.setAccessible(true);
Object sobject = f.get(object);
return detectMethod(names, index+1, sobject, parameterTypes, objs);
} catch (IllegalArgumentException | IllegalAccessException e) {
return null;
}
}
}

  return null;

}

public Class[] fetchTypes(Map env, Object[] args){ Class[] parameterTypes = new Class<?>[args.length];
int i=0;
for(Object obj:args) {
if(obj instanceof AviatorObject) {
parameterTypes[i++] = ((AviatorObject)obj).getValue(env).getClass();
}else {
parameterTypes[i++] = obj.getClass();
}
}
return parameterTypes;
}

public Object delegateInvoke(Map<String, Object> env, Object object, String methodName, Object[] args) throws Exception {
Class[] parameterTypes = new Class[args.length];
int i=0;
for(Object obj:args) {
if(obj instanceof AviatorObject) {
parameterTypes[i++] = ((AviatorObject)obj).getValue(env).getClass();
}else {
parameterTypes[i++] = obj.getClass();
}
}
Object[] objs = new Object[1];
Method method = findMethod(object, methodName, parameterTypes,objs);
if(method!=null) {
method.setAccessible(true);
return method.invoke(object, args);
}
return null;
}
public Method[] findMethods(Object object) {
return object.getClass().getDeclaredMethods();
}
public Field[] findFields(Object object) {
return object.getClass().getDeclaredFields();
}
public Method findMethod(Object object, String methodName, Class[] parameterTypes, Object[] objs) { Method[] ms = findMethods(object); for(Method method:ms) { if(method.getName().equals(methodName)) { Class[] pts = method.getParameterTypes();
if(pts.length == parameterTypes.length) {
int i=0;
boolean notmetch = false;
for(Class clazz:pts) { Class sclazz = parameterTypes[i++];
if(!clazz.isAssignableFrom(sclazz)) {
notmetch = true;
break;
}
}
if(!notmetch) {
if(objs!=null) {
objs[0] = object;
}
return method;
}
}
}
}
return null;
}
public Field findField(Object object, String fieldName) {
Field[] fs = findFields(object);
for(Field f:fs) {
if(f.getName().equals(fieldName)) {
return f;
}
}
return null;
}

public class DelegateFunction implements AviatorFunction{
private Method method;
private Object owner;
public DelegateFunction(Object owner,Method method) {
super();
this.owner = owner;
this.method = method;
}
@OverRide
public String getName() {
return method.getName();
}
@OverRide
public AviatorObject call(Map<String, Object> env) {

	try {
		return new AviatorRuntimeJavaType(method.invoke(owner));
	} catch (Exception e) {
		return null;
	}
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1) {
	Object[] argss = new Object[1];
	argss[0]=arg1.getValue(env);
	try {
		return new AviatorRuntimeJavaType(method.invoke(owner, argss));
	} catch (Exception e) {
		e.printStackTrace();
		return null;
	}
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
	Object[] argss = new Object[2];
	argss[0]=arg1.getValue(env);
	  argss[1]=arg2.getValue(env);
	try {
		return new AviatorRuntimeJavaType(method.invoke(owner, argss));
	} catch (Exception e) {
		return null;
	}
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3) {
	Object[] argss = new Object[3];
	argss[0]=arg1.getValue(env);
	  argss[1]=arg2.getValue(env);
	  argss[2]=arg3.getValue(env);
	try {
		return new AviatorRuntimeJavaType(method.invoke(owner, argss));
	} catch (Exception e) {
		return null;
	}
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3,
		AviatorObject arg4) {
	Object[] argss = new Object[4];
	argss[0]=arg1.getValue(env);
	  argss[1]=arg2.getValue(env);
	  argss[2]=arg3.getValue(env);
	  argss[3]=arg4.getValue(env);
	try {
		return new AviatorRuntimeJavaType(method.invoke(owner, argss));
	} catch (Exception e) {
		return null;
	}
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3,
		AviatorObject arg4, AviatorObject arg5) {
	Object[] argss = new Object[5];
	argss[0]=arg1.getValue(env);
	  argss[1]=arg2.getValue(env);
	  argss[2]=arg3.getValue(env);
	  argss[3]=arg4.getValue(env);
	  argss[4]=arg5.getValue(env);
	try {
		return new AviatorRuntimeJavaType(method.invoke(owner, argss));
	} catch (Exception e) {
		return null;
	}
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3,
		AviatorObject arg4, AviatorObject arg5, AviatorObject arg6) {
	Object[] argss = new Object[6];
	argss[0]=arg1.getValue(env);
	  argss[1]=arg2.getValue(env);
	  argss[2]=arg3.getValue(env);
	  argss[3]=arg4.getValue(env);
	  argss[4]=arg5.getValue(env);
	  argss[5]=arg6.getValue(env);
	try {
		return new AviatorRuntimeJavaType(method.invoke(owner, argss));
	} catch (Exception e) {
		return null;
	}
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3,
		AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7) {
	Object[] argss = new Object[7];
	argss[0]=arg1.getValue(env);
	  argss[1]=arg2.getValue(env);
	  argss[2]=arg3.getValue(env);
	  argss[3]=arg4.getValue(env);
	  argss[4]=arg5.getValue(env);
	  argss[5]=arg6.getValue(env);
	  argss[6]=arg7.getValue(env);
	try {
		return new AviatorRuntimeJavaType(method.invoke(owner, argss));
	} catch (Exception e) {
		return null;
	}
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3,
		AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8) {
	Object[] argss = new Object[8];
	argss[0]=arg1.getValue(env);
	  argss[1]=arg2.getValue(env);
	  argss[2]=arg3.getValue(env);
	  argss[3]=arg4.getValue(env);
	  argss[4]=arg5.getValue(env);
	  argss[5]=arg6.getValue(env);
	  argss[6]=arg7.getValue(env);
	  argss[7]=arg8.getValue(env);
	try {
		return new AviatorRuntimeJavaType(method.invoke(owner, argss));
	} catch (Exception e) {
		return null;
	}
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3,
		AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8,
		AviatorObject arg9) {
	Object[] argss = new Object[9];
	argss[0]=arg1.getValue(env);
	  argss[1]=arg2.getValue(env);
	  argss[2]=arg3.getValue(env);
	  argss[3]=arg4.getValue(env);
	  argss[4]=arg5.getValue(env);
	  argss[5]=arg6.getValue(env);
	  argss[6]=arg7.getValue(env);
	  argss[7]=arg8.getValue(env);
	  argss[8]=arg9.getValue(env);
	try {
		return new AviatorRuntimeJavaType(method.invoke(owner, argss));
	} catch (Exception e) {
		return null;
	}
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3,
		AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8,
		AviatorObject arg9, AviatorObject arg10) {
	Object[] argss = new Object[10];
	argss[0]=arg1.getValue(env);
	  argss[1]=arg2.getValue(env);
	  argss[2]=arg3.getValue(env);
	  argss[3]=arg4.getValue(env);
	  argss[4]=arg5.getValue(env);
	  argss[5]=arg6.getValue(env);
	  argss[6]=arg7.getValue(env);
	  argss[7]=arg8.getValue(env);
	  argss[8]=arg9.getValue(env);
	  argss[9]=arg10.getValue(env);
	try {
		return new AviatorRuntimeJavaType(method.invoke(owner, argss));
	} catch (Exception e) {
		return null;
	}
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3,
		AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8,
		AviatorObject arg9, AviatorObject arg10, AviatorObject arg11) {
	Object[] argss = new Object[11];
	argss[0]=arg1.getValue(env);
	  argss[1]=arg2.getValue(env);
	  argss[2]=arg3.getValue(env);
	  argss[3]=arg4.getValue(env);
	  argss[4]=arg5.getValue(env);
	  argss[5]=arg6.getValue(env);
	  argss[6]=arg7.getValue(env);
	  argss[7]=arg8.getValue(env);
	  argss[8]=arg9.getValue(env);
	  argss[9]=arg10.getValue(env);
	  argss[10]=arg11.getValue(env);
	try {
		return new AviatorRuntimeJavaType(method.invoke(owner, argss));
	} catch (Exception e) {
		return null;
	}
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3,
		AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8,
		AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12) {
	Object[] argss = new Object[12];
	argss[0]=arg1.getValue(env);
	  argss[1]=arg2.getValue(env);
	  argss[2]=arg3.getValue(env);
	  argss[3]=arg4.getValue(env);
	  argss[4]=arg5.getValue(env);
	  argss[5]=arg6.getValue(env);
	  argss[6]=arg7.getValue(env);
	  argss[7]=arg8.getValue(env);
	  argss[8]=arg9.getValue(env);
	  argss[9]=arg10.getValue(env);
	  argss[10]=arg11.getValue(env);
	  argss[11]=arg12.getValue(env);
	try {
		return new AviatorRuntimeJavaType(method.invoke(owner, argss));
	} catch (Exception e) {
		return null;
	}
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3,
		AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8,
		AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13) {
	Object[] argss = new Object[13];
	argss[0]=arg1.getValue(env);
	  argss[1]=arg2.getValue(env);
	  argss[2]=arg3.getValue(env);
	  argss[3]=arg4.getValue(env);
	  argss[4]=arg5.getValue(env);
	  argss[5]=arg6.getValue(env);
	  argss[6]=arg7.getValue(env);
	  argss[7]=arg8.getValue(env);
	  argss[8]=arg9.getValue(env);
	  argss[9]=arg10.getValue(env);
	  argss[10]=arg11.getValue(env);
	  argss[11]=arg12.getValue(env);
	  argss[12]=arg13.getValue(env);
	try {
		return new AviatorRuntimeJavaType(method.invoke(owner, argss));
	} catch (Exception e) {
		return null;
	}
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3,
		AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8,
		AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13,
		AviatorObject arg14) {
	Object[] argss = new Object[14];
	argss[0]=arg1.getValue(env);
	  argss[1]=arg2.getValue(env);
	  argss[2]=arg3.getValue(env);
	  argss[3]=arg4.getValue(env);
	  argss[4]=arg5.getValue(env);
	  argss[5]=arg6.getValue(env);
	  argss[6]=arg7.getValue(env);
	  argss[7]=arg8.getValue(env);
	  argss[8]=arg9.getValue(env);
	  argss[9]=arg10.getValue(env);
	  argss[10]=arg11.getValue(env);
	  argss[11]=arg12.getValue(env);
	  argss[12]=arg13.getValue(env);
	  argss[13]=arg14.getValue(env);
	try {
		return new AviatorRuntimeJavaType(method.invoke(owner, argss));
	} catch (Exception e) {
		return null;
	}
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3,
		AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8,
		AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13,
		AviatorObject arg14, AviatorObject arg15) {
	Object[] argss = new Object[15];
	argss[0]=arg1.getValue(env);
	  argss[1]=arg2.getValue(env);
	  argss[2]=arg3.getValue(env);
	  argss[3]=arg4.getValue(env);
	  argss[4]=arg5.getValue(env);
	  argss[5]=arg6.getValue(env);
	  argss[6]=arg7.getValue(env);
	  argss[7]=arg8.getValue(env);
	  argss[8]=arg9.getValue(env);
	  argss[9]=arg10.getValue(env);
	  argss[10]=arg11.getValue(env);
	  argss[11]=arg12.getValue(env);
	  argss[12]=arg13.getValue(env);
	  argss[13]=arg14.getValue(env);
	  argss[14]=arg15.getValue(env);
	try {
		return new AviatorRuntimeJavaType(method.invoke(owner, argss));
	} catch (Exception e) {
		return null;
	}
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3,
		AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8,
		AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13,
		AviatorObject arg14, AviatorObject arg15, AviatorObject arg16) {
	Object[] argss = new Object[16];
	argss[0]=arg1.getValue(env);
	  argss[1]=arg2.getValue(env);
	  argss[2]=arg3.getValue(env);
	  argss[3]=arg4.getValue(env);
	  argss[4]=arg5.getValue(env);
	  argss[5]=arg6.getValue(env);
	  argss[6]=arg7.getValue(env);
	  argss[7]=arg8.getValue(env);
	  argss[8]=arg9.getValue(env);
	  argss[9]=arg10.getValue(env);
	  argss[10]=arg11.getValue(env);
	  argss[11]=arg12.getValue(env);
	  argss[12]=arg13.getValue(env);
	  argss[13]=arg14.getValue(env);
	  argss[14]=arg15.getValue(env);
	  argss[15]=arg16.getValue(env);
	try {
		return new AviatorRuntimeJavaType(method.invoke(owner, argss));
	} catch (Exception e) {
		return null;
	}
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3,
		AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8,
		AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13,
		AviatorObject arg14, AviatorObject arg15, AviatorObject arg16, AviatorObject arg17) {
	Object[] argss = new Object[17];
	argss[0]=arg1.getValue(env);
	  argss[1]=arg2.getValue(env);
	  argss[2]=arg3.getValue(env);
	  argss[3]=arg4.getValue(env);
	  argss[4]=arg5.getValue(env);
	  argss[5]=arg6.getValue(env);
	  argss[6]=arg7.getValue(env);
	  argss[7]=arg8.getValue(env);
	  argss[8]=arg9.getValue(env);
	  argss[9]=arg10.getValue(env);
	  argss[10]=arg11.getValue(env);
	  argss[11]=arg12.getValue(env);
	  argss[12]=arg13.getValue(env);
	  argss[13]=arg14.getValue(env);
	  argss[14]=arg15.getValue(env);
	  argss[15]=arg16.getValue(env);
	  argss[16]=arg17.getValue(env);
	try {
		return new AviatorRuntimeJavaType(method.invoke(owner, argss));
	} catch (Exception e) {
		return null;
	}
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3,
		AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8,
		AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13,
		AviatorObject arg14, AviatorObject arg15, AviatorObject arg16, AviatorObject arg17, AviatorObject arg18) {
	Object[] argss = new Object[18];
	argss[0]=arg1.getValue(env);
	  argss[1]=arg2.getValue(env);
	  argss[2]=arg3.getValue(env);
	  argss[3]=arg4.getValue(env);
	  argss[4]=arg5.getValue(env);
	  argss[5]=arg6.getValue(env);
	  argss[6]=arg7.getValue(env);
	  argss[7]=arg8.getValue(env);
	  argss[8]=arg9.getValue(env);
	  argss[9]=arg10.getValue(env);
	  argss[10]=arg11.getValue(env);
	  argss[11]=arg12.getValue(env);
	  argss[12]=arg13.getValue(env);
	  argss[13]=arg14.getValue(env);
	  argss[14]=arg15.getValue(env);
	  argss[15]=arg16.getValue(env);
	  argss[16]=arg17.getValue(env);
	  argss[17]=arg18.getValue(env);
	try {
		return new AviatorRuntimeJavaType(method.invoke(owner, argss));
	} catch (Exception e) {
		return null;
	}
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3,
		AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8,
		AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13,
		AviatorObject arg14, AviatorObject arg15, AviatorObject arg16, AviatorObject arg17, AviatorObject arg18,
		AviatorObject arg19) {
	Object[] argss = new Object[19];
	argss[0]=arg1.getValue(env);
	  argss[1]=arg2.getValue(env);
	  argss[2]=arg3.getValue(env);
	  argss[3]=arg4.getValue(env);
	  argss[4]=arg5.getValue(env);
	  argss[5]=arg6.getValue(env);
	  argss[6]=arg7.getValue(env);
	  argss[7]=arg8.getValue(env);
	  argss[8]=arg9.getValue(env);
	  argss[9]=arg10.getValue(env);
	  argss[10]=arg11.getValue(env);
	  argss[11]=arg12.getValue(env);
	  argss[12]=arg13.getValue(env);
	  argss[13]=arg14.getValue(env);
	  argss[14]=arg15.getValue(env);
	  argss[15]=arg16.getValue(env);
	  argss[16]=arg17.getValue(env);
	  argss[17]=arg18.getValue(env);
	  argss[18]=arg19.getValue(env);
	try {
		return new AviatorRuntimeJavaType(method.invoke(owner, argss));
	} catch (Exception e) {
		return null;
	}
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3,
		AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8,
		AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13,
		AviatorObject arg14, AviatorObject arg15, AviatorObject arg16, AviatorObject arg17, AviatorObject arg18,
		AviatorObject arg19, AviatorObject arg20) {
	Object[] argss = new Object[20];
	argss[0]=arg1.getValue(env);
	  argss[1]=arg2.getValue(env);
	  argss[2]=arg3.getValue(env);
	  argss[3]=arg4.getValue(env);
	  argss[4]=arg5.getValue(env);
	  argss[5]=arg6.getValue(env);
	  argss[6]=arg7.getValue(env);
	  argss[7]=arg8.getValue(env);
	  argss[8]=arg9.getValue(env);
	  argss[9]=arg10.getValue(env);
	  argss[10]=arg11.getValue(env);
	  argss[11]=arg12.getValue(env);
	  argss[12]=arg13.getValue(env);
	  argss[13]=arg14.getValue(env);
	  argss[14]=arg15.getValue(env);
	  argss[15]=arg16.getValue(env);
	  argss[16]=arg17.getValue(env);
	  argss[17]=arg18.getValue(env);
	  argss[18]=arg19.getValue(env);
	  argss[19]=arg20.getValue(env);
	  
	try {
		return new AviatorRuntimeJavaType(method.invoke(owner, argss));
	} catch (Exception e) {
		return null;
	}
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3,
		AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8,
		AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13,
		AviatorObject arg14, AviatorObject arg15, AviatorObject arg16, AviatorObject arg17, AviatorObject arg18,
		AviatorObject arg19, AviatorObject arg20, AviatorObject... args) {
	Object[] argss = new Object[20+args.length];
	argss[0]=arg1.getValue(env);
	  argss[1]=arg2.getValue(env);
	  argss[2]=arg3.getValue(env);
	  argss[3]=arg4.getValue(env);
	  argss[4]=arg5.getValue(env);
	  argss[5]=arg6.getValue(env);
	  argss[6]=arg7.getValue(env);
	  argss[7]=arg8.getValue(env);
	  argss[8]=arg9.getValue(env);
	  argss[9]=arg10.getValue(env);
	  argss[10]=arg11.getValue(env);
	  argss[11]=arg12.getValue(env);
	  argss[12]=arg13.getValue(env);
	  argss[13]=arg14.getValue(env);
	  argss[14]=arg15.getValue(env);
	  argss[15]=arg16.getValue(env);
	  argss[16]=arg17.getValue(env);
	  argss[17]=arg18.getValue(env);
	  argss[18]=arg19.getValue(env);
	  argss[19]=arg20.getValue(env);
	  int i=20;
	  for(AviatorObject aviatorObject:args) {
		  argss[i++] = aviatorObject.getValue(env);
	  }
	try {
		return new AviatorRuntimeJavaType(method.invoke(owner, argss));
	} catch (Exception e) {
		return null;
	}
}

}

}

@lixinlin
Copy link
Author

lixinlin commented Oct 8, 2019

另外就是有很多call的定义,为什么不集成到一起,通过动态参数的方式只弄一个call呢,对于固定参数个数的call,顶多做一下参数个数的判断,这样岂不是更好一些,这样定义一堆感觉很累赘

@killme2008
Copy link
Owner

这样的应用场景并不是 aviator 设计的初衷,aviator 本质上是希望能控制允许使用的方法,类似一个沙箱。你可以继续用补丁的方式。_

@killme2008
Copy link
Owner

至于为什么定义多个 call,主要是性能考虑。 你的场景可以考虑直接继承 AbstractVariadicFunction,实现一个方法即可

https://github.com/killme2008/aviator/blob/2a8928aca03688d0ce672f9dffe5b31adbba6fe3/src/main/java/com/googlecode/aviator/runtime/function/AbstractVariadicFunction.java

@lixinlin
Copy link
Author

lixinlin commented Oct 8, 2019

实际上大部分人可能用不上我说的功能,但是如果有需要的则会变得很方便,增加这个功能对原有的使用方式也不会有性能的影响,仅仅是建议,目前我的应用只能是先用这种源码补丁的方式处理,至于继承 AbstractVariadicFunction,有时间了看看怎么处理,目前对各个类的关系还不是很清晰,如何继承还不是很清楚,不过还是要谢谢你的回复

@killme2008
Copy link
Owner

killme2008 commented Oct 8, 2019

从我个人角度是不大推荐采用修改源码的方式,因为后续升级都会很困难,一些 bug 修复或者新特性没办法及时跟上。

你这里的需求,理论上可以通过提供一个 MethodMissing 的机制来扩展,类似你可以为 evaluator 提供一个

interface MethodMissing {
  void onMethodMissing(String name, Map<String, Object> env, AviatorObject...args);
}

这个接口的实现,就可以将你的定制逻辑放进去,而不用去修改源码,你认为呢?

为什么不加入自动导入的方式,核心原因前面也提过了, aviator 希望整个求值使用到的方法和函数都是受控的,不是用户想执行就能执行什么,这里有安全和管控的因素在。

@lixinlin
Copy link
Author

lixinlin commented Oct 8, 2019

这个建议的机制不错,我看看怎么通过实现这个做到我想要的能力,实际上我也是没有发现更好的方式而不得已用了修改源码的方式进行处理,我比较了一些表达式的库,相比较而言,你写的这套还是比较优秀的。

@killme2008
Copy link
Owner

已经加了个 issue #170 , 这个实现还是比较容易的,我会抓紧搞定下。 后续发布后,建议你再修改。

@lixinlin
Copy link
Author

lixinlin commented Oct 8, 2019

好的,这种跟进速度超赞

@killme2008
Copy link
Owner

已实现,可以参考这个 PR

#171 看看是否可以满足你的要求。

@lixinlin
Copy link
Author

好的,我看看

@lixinlin
Copy link
Author

看了实现过程,这样可以实现对象的方法调用,如果是对象的属性的方法(多级的那种,a.b.c.fun(xx)这种),貌似就不行了:)

@lixinlin
Copy link
Author

不过这种机制提供了一个可扩展的机制,可以自己实现一个FunctionMissing,做那种深度遍历的处理,也算是可以解决了:)

@killme2008
Copy link
Owner

@lixinlin 嵌套正常调用应该是 fun(x.a.b.c) 吧?

@lixinlin
Copy link
Author

a对象的b属性对象的c属性对象的fun,这种,例如表达式:obja.objb.objc.funx(yy)+5

@killme2008
Copy link
Owner

@lixinlin 我明白你的意思。 aviator 支持 a.b.c 这样的语法糖的,他可以获取 a 的 b 属性的 c 属性。因此上述调用可以改成 funx(obja.objb.objc) +5 的。

@killme2008
Copy link
Owner

这里主要的差异在于 aviator 的方法调用都是 method(this) ,而不是 this.method() 的方式。不是 dot 语法, dot 只作为 namespace 分割符。

dot 可以做变量的嵌套访问,参见

https://github.com/killme2008/aviator/wiki#%E5%8F%98%E9%87%8F%E7%9A%84%E8%AF%AD%E6%B3%95%E7%B3%96

所以理论上这个 PR 可以替代你原来的实现的,只是需要改下调用方式,非常不推荐采用 a.b.c.method() 的方式,都应该是 method(a.b.c),否则跟标准库是不一致的,容易困惑。

@lixinlin
Copy link
Author

这个语法有点怪,那参数怎么传递?method(a.b.c, arg1, arg2)这种形式?

@killme2008
Copy link
Owner

@lixinlin 是的,内置函数和通过导入的方法都是这种方式

@lixinlin
Copy link
Author

绕了一圈竟然是用法上的问题:)

@killme2008
Copy link
Owner

@lixinlin 4.2.5 已经发布,理论上你可以无缝替换使用了,只是需要改下表达式。

参见

https://github.com/killme2008/aviator/wiki/%E8%B0%83%E7%94%A8-Java-%E6%96%B9%E6%B3%95%E5%92%8C-Function-Missing

@lixinlin
Copy link
Author

ok

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants