package net.sourceforge.javautil.groovy.builder;
import groovy.lang.Closure;
import groovy.lang.MetaClass;
import groovy.lang.MetaMethod;
import net.sourceforge.javautil.groovy.util.MetaClassWrapper;
import org.codehaus.groovy.runtime.InvokerHelper;
/**
* This meta class is setup as the meta class for the closures before they are called on the builder. It principally has the purpose
* of redirecting print() and println() statements to the builder instead of the script.
*
* @author elponderador
*
*/
public class BuilderClosureMetaClass extends MetaClassWrapper {
private Object out;
private MetaMethod print;
private MetaMethod println;
/**
* Here we check to see if 'out' has print(Object) and/or println(Object). If it has either the MetaMethod
* is saved for later invocations.
*
* @param closure The closure to use (getMetaClass() is called on it) in order to wrap the standard functionality
* @param out The object that could have print(Object) and println(Object) methods on it
*
* @see #invokeMethod(Class, Object, String, Object[], boolean, boolean)
*/
public BuilderClosureMetaClass(Closure closure, Object out) {
super(closure.getMetaClass());
this.out = out;
MetaClass mc = InvokerHelper.getMetaClass(out);
print = mc.getMetaMethod("print", new Class[] { Object.class });
println = mc.getMetaMethod("println", new Class[] { Object.class });
}
/**
* Here we intercept calls to print(Object) and println(Object) and we call the builders versions if they were defined.
*/
@Override public Object invokeMethod(Class sender, Object receiver, String methodName, Object[] arguments, boolean isCallToSuper, boolean fromInsideClass) {
if ("print".equals(methodName) && arguments.length == 1 && print != null) {
return print.invoke(out, arguments);
}
else if ("println".equals(methodName) && arguments.length == 1 && println != null) {
return println.invoke(out, arguments);
}
else return super.invokeMethod(sender, receiver, methodName, arguments, isCallToSuper, fromInsideClass);
}
}