package ca.svarb.utils;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
import ca.svarb.jyacl.Attribute;
/**
* Given an input interface "aClass", ClassMaker will return
* an instance of that interface. The methods of the interface
* will return values as specifed by the getterMap.<p>
*
* For example, given an interface "IPerson":<p>
*
* <pre>
* interface IPerson {
* String getName();
* Integer getAge();
* }
* </pre>
*
* Use the following to create an instance of IPerson that
* returns "Ali" for name and 32 for age:<p>
*
* <pre>
* Map<String, Object> getterMap = new HashMap<String, Object>();
* getterMap.put("name", "Ali");
* getterMap.put("age", new Integer(32));
*
* ClassMaker maker = new ClassMaker();
* IPerson instance = (IPerson)maker.makeInstance(IPerson.class, getterMap);
* </pre>
*
* The getterMap should provide a return value for all "get...()" and "is...()"
* methods from the interface. If an attempt is make to read a value from
* an interface method for which the getterMap does not specify a value,
* an Exception will be thrown.<p>
*
* @author bmodi
*
*/
public class ClassMaker {
public Object makeInstance(Class<? extends Object> aClass, Map<String, Object> getterMap) {
InvocationHandler handler = new OptionInvocationHandler(getterMap);
Class<?>[] interfaces = new Class<?>[] {aClass};
Object newProxyInstance = Proxy.newProxyInstance(aClass.getClassLoader(),
interfaces, handler);
return newProxyInstance;
}
}
/**
* Handler for the methods of the interface that get
* called from client code. The handler will
* identify the method being called and then return
* the corresponding value from the getterMap.
*/
class OptionInvocationHandler implements InvocationHandler {
private Map<String, Object> getterMap;
public OptionInvocationHandler(Map<String, Object> getterMap) {
this.getterMap=getterMap;
}
public Object invoke(Object proxy, Method method, Object[] args) {
String attributeName = new Attribute(method.getName()).getName();
if ( !getterMap.containsKey(attributeName) ) {
throw new IllegalStateException("No value provided in getterMap for \""+attributeName+"\" attribute.");
}
Object value = getterMap.get(attributeName);
return value;
}
}