我有一个相当复杂的问题。我目前正在为 ERP 系统开发一种基于 groovy 的脚本语言。“我的”脚本语言的功能和语法基于erp系统使用的已经存在的旧FO语言。
因此:我通过调用从 ERP 中获取值,当前选择的数据集在哪里以及h.fieldname
我想要我的字段值的字段的名称。我得到例如字符串类型的字段值。我现在想要的是用一些基于“旧”语法的函数来扩展我检索到的这些字符串。h
fieldname
// some samples
// get last 3 characters
h.fieldname >> 3
// get first 4 characters
h.fieldname << 4
// should still work even if h.fieldname, returns something which extends String but is not a String
assert h.fieldname == "Foo"
更新
我试图利用@daggett的答案,这里是我的方法:
public abstract class BaseScript extends Script implements GroovyObject {
@Override
public Object run() {
Object o = null;
try {
final ExpandoMetaClass metaClass = new ExpandoMetaClass(String.class, false, true);
//Closure c = { int x-> delegate[-x..-1] };
//ClosureMetaMethod foo = new ClosureMetaMethod("rightShift ", c , doCall);
metaClass.initialize();
o = runCode();
} catch (Exception e) {
this.onerror(e);
} finally {
this.always();
}
return o;
}
public abstract Object runCode();
public Object always() {
return null;
}
public Object onerror(Object ex) {
if (ex instanceof Exception) {
Exception e = (Exception) ex;
e.printStackTrace();
}
return null;
}
}
但老实说,我不知道如何实现它,我也找不到任何例子。
更新 2 和解决方案
基于@daggett 的回答。
package groovy.runtime.metaclass.java.lang;
import groovy.lang.DelegatingMetaClass;
import groovy.lang.MetaClass;
public class StringMetaClass extends DelegatingMetaClass {
public StringMetaClass(Class<?> theClass) {
super(theClass);
}
public StringMetaClass(MetaClass metaClass) {
super(metaClass);
}
@Override
public Object invokeMethod(Object object, String name, Object[] args) {
// implementiert "test" >> 3
if (name.equals("rightShift")) {
if (args.length == 1) {
if (args[0] instanceof Integer) {
String str = object.toString();
int x = ((Integer) args[0]).intValue();
if (str.length() > x) {
return str.substring(str.length() - x);
}
return str;
} else {
throw new IllegalArgumentException("wrong argument type, should be integer");
}
} else {
throw new IllegalArgumentException("too many arguments");
}
}
// implementiert "test" << 3
if (name.equals("leftShift")) {
if (args.length == 1) {
if (args[0] instanceof Integer) {
String str = object.toString();
int x = ((Integer) args[0]).intValue();
if (str.length() > x) {
return str.substring(0,x);
}
return str;
} else {
throw new IllegalArgumentException("wrong argument type, should be integer");
}
} else {
throw new IllegalArgumentException("too many arguments");
}
}
else {
return super.invokeMethod(object, name, args);
}
}
}