package jfun.yan.xml;
import java.util.HashMap;
import jfun.util.Misc;
import jfun.yan.Component;
import jfun.yan.ComponentMap;
import jfun.yan.Components;
import jfun.yan.Container;
import jfun.yan.Creator;
import jfun.yan.DelegatingComponent;
import jfun.yan.Dependency;
import jfun.yan.ParameterBinder;
import jfun.yan.PropertyBinder;
import jfun.yan.factory.ThreadLocalScope;
import jfun.yan.function.Signature;
/**
* Some common wiring modes.
* <p>
* @author Ben Yu
* Nov 16, 2005 11:00:43 AM
*/
public class Modes {
/**
* The singleton mode.
*/
public static final SingletonMode simple_singleton = new SingletonMode(){
public Component decorate(Component c) {
return c.singleton();
}
public String toString(){
return Constants.ON;
}
};
/**
* The thread local scope singleton mode.
*/
public static final SingletonMode thread_local_singleton = new SingletonMode(){
public Component decorate(Component c) {
return c.singleton(new ThreadLocalScope());
}
public String toString(){
return Constants.ON;
}
};
/**
* Wire parameters by type.
*/
public static ParameterBinder params_bytype = new ParameterBinder(){
private final HashMap cache = new HashMap();
public Creator bind(Signature src, int ind, Class type) {
return useType(type, cache);
}
public String toString(){
return Constants.BYTYPE;
}
};
/**
* Wire properties by name.
*/
public static PropertyBinder props_byname = new PropertyBinder(){
private final HashMap cache = new HashMap();
public Creator bind(Class component_type, Object key, Class type) {
return useKey(key, cache);
}
public String toString(){
return Constants.BYNAME;
}
};
/**
* Wire properties by type.
*/
public static PropertyBinder props_bytype = new PropertyBinder(){
private final HashMap cache = new HashMap();
public Creator bind(Class component_type, Object key, Class type) {
return useType(type, cache);
}
public String toString(){
return Constants.BYTYPE;
}
};
/**
* Wire properties by fully qualified name.
* <p>
* For example, property balance in "com.ajoo.BankAccount" will resolve to
* a component named "com.ajoo.Bankaccount.balance".
* </p>
*/
public static PropertyBinder props_byqualifiedname = new PropertyBinder(){
private final HashMap cache = new HashMap();
public Creator bind(Class component_type, Object key, Class type) {
return useKey(Misc.getTypeName(component_type)+"."+key, cache);
}
public String toString(){
return Constants.BYQUALIFIEDNAME;
}
};
/**
* The autodetect mode.
* <p>
* It will search by type first, if ambiguity happens or dependency not found,
* byname is used, then byqualifiedname, until the component is found.
* </p>
*/
public static PropertyBinder props_autodetect = new PropertyBinder(){
public Creator bind(final Class component_type, final Object key, final Class type) {
final Object[] alt_keys = {key, Misc.getTypeName(component_type)+'.'+key};
return Components.autodetect(type, alt_keys);
}
public String toString(){
return Constants.AUTODETECT;
}
};
private static Component useKey(Object key, java.util.Map cache){
synchronized(cache){
Component result = (Component)cache.get(key);
if(result == null){
result = useKey(key);
cache.put(key, result);
}
return result;
}
}
private static Component useType(Class type, java.util.Map cache){
synchronized(cache){
Component result = (Component)cache.get(type);
if(result == null){
result = useType(type);
cache.put(type, result);
}
return result;
}
}
//useKey used in auto-wiring expects no property and argument, so optimize.
private static Component useKey(final Object key){
return new DelegatingComponent(Components.useKey(key)){
public Object create(Dependency dep){
final ComponentMap cmap = dep.getComponentMap();
if(cmap instanceof Container){
return ((Container)cmap).getInstance(key);
}
else return super.create(dep);
}
};
}
//useKey used in auto-wiring expects no property and argument, so optimize.
private static Component useType(final Class type){
return new DelegatingComponent(Components.useType(type)){
public Object create(Dependency dep){
final ComponentMap cmap = dep.getComponentMap();
if(cmap instanceof Container){
return ((Container)cmap).getInstanceOfType(type);
}
else return super.create(dep);
}
};
}
}