package jfun.yan.etc;
import jfun.yan.Binder;
import jfun.yan.Component;
import jfun.yan.Map2;
import jfun.yan.Monad;
import jfun.yan.Mutation;
import jfun.yan.util.Utils;
/**
* This class provides helper functions to help dependency injections
* on objects not created by Yan.
* <p>
* @author Michelle Lei
*
*/
public class InjectorHelper{
/**
* To create a Component object that will instantiate an object
* that implements a certain injector interface.
* <p>
* The injector interface should describe at least one method
* that expects one and only one parameter object. This method is responsible
* for injecting dependencies into this parameter object.
* </p>
* <p>
* The injection logic is encapsulated in a Binder object.
* </p>
* @param injector_itf The injector interface class.
* @param binder the Binder object encapsulating the dependency injection logic.
* @return the Component that instantiates the injector object.
*/
public static Component getInjectorComponent(Class injector_itf, Binder binder){
return Utils.asComponent(binder).factory(injector_itf);
}
/**
* To create a Component that instantiates proxy.
* <p>
* The proxy object is responsible for injecting dependencies
* into return values from the proxied methods.
* </p>
* <p>
* The dependency injection logic is described by the <i>binder</i> object.
* </p>
* <p>
* The instance instantiated by the <i>proxied</i> Component is proxied.
* </p>
* <p>
* Only the dependencies of return values of <i>injectee_type</i> are injected.
* </p>
* @param cloader The ClassLoader used by the dynamic proxy.
* @param itf the interface that the proxy implements.
* @param proxied the Component that instantiates the proxied object.
* @param injectee_type only return values of this type gets injected.
* @param binder this object encapsulates the injection logic.
* @return the new Component that instantiates the proxied object.
*/
public static Component getProxyComponentReturningInjected(
final ClassLoader cloader, final Class itf,
Component proxied, final Class injectee_type, Binder binder){
final Component mutation = getInjectorComponent(Mutation.class, binder);
final Component injected = Monad.map(proxied, mutation, new Map2(){
public Object map(Object proxied, Object mut){
return InjectingProxy.getInjectingProxy(cloader, itf,
proxied, injectee_type, (Mutation)mut);
}
});
return injected;
}
/**
* To create a Component that instantiates proxy.
* <p>
* The proxy object is responsible for injecting dependencies
* into return values from the proxied methods.
* </p>
* <p>
* The dependency injection logic is described by the <i>binder</i> object.
* </p>
* <p>
* The instance instantiated by the <i>proxied</i> Component is proxied.
* </p>
* <p>
* Only the dependencies of return values of <i>injectee_type</i> are injected.
* </p>
* <p>
* The ClassLoader that loads the proxied instance is used to load the dynamic proxy.
* </p>
* @param itf the interface that the proxy implements.
* @param proxied the Component that instantiates the proxied object.
* @param injectee_type only return values of this type gets injected.
* @param binder this object encapsulates the injection logic.
* @return the new Component that instantiates the proxied object.
*/
public static Component getProxyComponentReturningInjected(final Class itf,
Component proxied, Class injectee_type, Binder binder){
return getProxyComponentReturningInjected(injectee_type.getClassLoader(),
itf, proxied, injectee_type, binder);
}
}