package net.sourceforge.javautil.groovy.dsl;
import java.util.List;
import org.codehaus.groovy.ast.ClassNode;
import net.sourceforge.javautil.common.exception.ThrowableManagerRegistry;
import net.sourceforge.javautil.groovy.util.MetaClassWrapper;
import groovy.lang.Binding;
import groovy.lang.GroovySystem;
import groovy.lang.MetaClass;
import groovy.lang.MetaMethod;
import groovy.lang.MetaProperty;
import groovy.lang.MissingMethodException;
import groovy.lang.MissingPropertyException;
/**
* This will wrap ALL {@link MetaClass}'s generated by the {@link GroovySystem} and intervene
* where in order to provide the added functionality according to the {@link GroovyDSLContext}.
*
* @author elponderador
* @author $Author$
* @version $Id$
*/
public class GroovyMetaClass extends MetaClassWrapper {
protected GroovyDSLManager manager;
public GroovyMetaClass(MetaClass metaClass) {
super(metaClass);
}
@Override public Object invokeStaticMethod(Object object, String methodName, Object[] arguments) {
try {
return super.invokeStaticMethod(object, methodName, arguments);
} catch (MissingMethodException e) {
return this.invokeGraceletDSLMethod(object, methodName, arguments, e);
}
}
@Override public Object invokeMethod(Object object, String methodName, Object[] arguments) {
try {
return super.invokeMethod(object, methodName, arguments);
} catch (MissingMethodException e) {
return this.invokeGraceletDSLMethod(object, methodName, arguments, e);
}
}
@Override public Object getProperty(Object object, String property) {
try {
return super.getProperty(object, property);
} catch (MissingPropertyException e) {
return this.invokeGraceletDSLProperty(object, property, null, true);
}
}
@Override public void setProperty(Object object, String property, Object newValue) {
try {
super.setProperty(object, property, newValue);
} catch (MissingPropertyException e) {
this.invokeGraceletDSLProperty(object, property, newValue, false);
}
}
@Override public Object getProperty(Class sender, Object receiver, String property, boolean isCallToSuper, boolean fromInsideClass) {
try {
return super.getProperty(sender, receiver, property, isCallToSuper, fromInsideClass);
} catch (MissingPropertyException e) {
return this.invokeGraceletDSLProperty(receiver, property, null, true);
}
}
@Override public void setProperty(Class sender, Object receiver, String property, Object value, boolean isCallToSuper, boolean fromInsideClass) {
try {
super.setProperty(sender, receiver, property, value, isCallToSuper, fromInsideClass);
} catch (MissingPropertyException e) {
this.invokeGraceletDSLProperty(receiver, property, value, false);
}
}
public Object invokeGraceletDSLMethod(Object instance, String methodName, Object[] arguments, MissingMethodException me) {
if (manager == null) manager = GroovyDSLContext.getManager();
if (manager == null) throw me;
GroovyDSLMethod method = null;
MetaClass mc = this;
while (true) {
method = manager.findMethod(mc, instance, methodName, arguments);
if (method != null) break;
else if (mc.getTheClass() != Object.class) mc = GroovySystem.getMetaClassRegistry().getMetaClass(mc.getTheClass().getSuperclass());
else break;
}
if (method == null) {
try {
Binding dsl = GroovyDSLBinding.getInstance();
if (dsl != null) return dsl.invokeMethod(methodName, arguments); else throw me;
} catch (MissingMethodException eee) {
throw me;
}
}
try {
return method.invoke(this, instance, methodName, arguments);
} catch (Exception e) {
throw ThrowableManagerRegistry.caught(e);
}
}
public Object invokeGraceletDSLProperty(Object instance, String propertyName, Object optionalValue, boolean isGetter) {
try {
return super.invokeMissingProperty(instance, propertyName, optionalValue, isGetter);
} catch (MissingPropertyException e) {
if (manager == null) manager = GroovyDSLContext.getManager();
if (manager == null) throw e;
GroovyDSLProperty property = null;
MetaClass mc = this;
while (true) {
property = manager.findProperty(mc, instance, propertyName);
if (property != null) break;
else if (mc.getTheClass() != Object.class) mc = GroovySystem.getMetaClassRegistry().getMetaClass(mc.getTheClass().getSuperclass());
else break;
}
if (property == null) {
try {
Binding dsl = GroovyDSLBinding.getInstance();
if (dsl != null) {
if (isGetter) return dsl.getVariable(propertyName); else dsl.setVariable(propertyName, optionalValue);
} else throw e;
} catch (MissingPropertyException ee) {
throw e;
}
}
try {
if (isGetter) return property.get(this, instance, propertyName);
else property.set(this, instance, propertyName, optionalValue);
return null;
} catch (Exception e1) {
throw ThrowableManagerRegistry.caught(e1);
}
}
}
}