package jfun.yan.xml.nuts;
import java.util.ArrayList;
import java.util.List;
import jfun.util.Misc;
import jfun.yan.Component;
import jfun.yan.Components;
import jfun.yan.Map;
import jfun.yan.lifecycle.DefaultLifecycleManager;
import jfun.yan.util.ReflectionUtil;
import jfun.yan.xml.ConfigurationException;
import jfun.yan.xml.Location;
import jfun.yan.xml.nut.Nut;
/**
* Common utility function that may worth being reused
* by various Nut implementations.
* <p>
* @author Ben Yu
* Nov 10, 2005 12:31:52 AM
*/
public class Util {
private static void assertMethodName(Component c, String mname,
Location loc){
final Class type = c.getType();
if(type!=null){
try{
type.getMethod(mname, null);
}
catch(NoSuchMethodException e){
throw new ConfigurationException("lifecycle method "
+ mname + " not defined by "+ Misc.getTypeName(type),
loc);
}
}
}
/**
* Create a Component that adds lifecycle support.
* @param c the Component to add lifecycle to.
* @param loc the location of the Component in the source file.
* @param man the lifecycle manager.
* @param starter the starter method name.
* @param stopper the stopper method name.
* @param disposer the disposer method name.
* @return the Component with lifecycle.
*/
private static Component wrapLifecycle(
Component c, Location loc,
DefaultLifecycleManager man,
String starter, String stopper, String disposer){
//we do initialization before wiring. So skip the default lifecycle manager
//for initializers.
final DefaultLifecycleManager.DefaultLifecycle lifecycle =
man.newLifecycle();
if(disposer != null){
assertMethodName(c, disposer, loc);
lifecycle.disposer(disposer);
}
if(starter != null){
assertMethodName(c, starter, loc);
lifecycle.starter(starter);
}
if(stopper != null){
assertMethodName(c, stopper, loc);
lifecycle.stopper(stopper);
}
c = lifecycle.manage(c);
return c;
}
/**
* Create a Component that adds lifecycle support.
* @param c the Component to add lifecycle to.
* @param loc the location of the Component in the source file.
* @param man the lifecycle manager.
* @param initializer the initializer method name. Null if not available.
* @param starter the starter method name. Null if not available.
* @param stopper the stopper method name. Null if not available.
* @param disposer the disposer method name. Null if not available.
* @return the Component with lifecycle.
*/
public static Component wrapLifecycle(
Component c, Location loc,
DefaultLifecycleManager man,
String initializer, String starter, String stopper, String disposer){
if(initializer != null){
assertMethodName(c, initializer, loc);
Class realtype = c.isConcrete()?c.getType():null;
c = c.followedBy(
Components.invokingMethod(realtype, initializer, null, false));
}
return wrapLifecycle(c, loc, man, starter, stopper, disposer);
}
/**
* Create a Component that adds lifecycle support.
* @param c the Component to add lifecycle to.
* @param ln the LifecycleNut object.
* @return the Component with life cycle.
*/
public static Component wrapLifecycle(
Component c, LifecycleDeclaration ln){
return wrapLifecycle(c, ln.getTagLocation(),
ln.getNutEnvironment().getLifecycleManager(),
ln.getInitializer(), ln.getStarter(), ln.getStopper(), ln.getDisposer()
);
}
/**
* Convert a Component so that the instantiation result is of a certain type.
* @param nut the Nut object that does the conversion.
* @param elem_type the element type.
* @param c the Component to convert.
* @return the new Component object.
*/
public static Component convert(final Nut nut,
final Class elem_type, final Component c){
final Class type = c.getType();
if(type!=null && ReflectionUtil.isAssignableFrom(elem_type, type)){
return c;
}
return c.map(new Map(){
public Object map(Object obj){
try{
return nut.convert(elem_type, obj);
}
catch(ConfigurationException e){
throw new ConfigurationException(
e.getMessage() + ": "+ c, e, e.getLocation());
}
}
public String toString(){
return c.toString();
}
});
}
/**
* Convert an array of Component object so that the instantiation results
* are of a certain type.
* @param nut the Nut object to perform the conversion.
* @param elem_type the element type.
* @param elems the array of Components.
* @return the new array of Components.
*/
public static Component[] convert(Nut nut,
final Class elem_type, Component[] elems){
final Component[] ret = new Component[elems.length];
for(int i=0; i<ret.length; i++){
ret[i] = convert(nut, elem_type, elems[i]);
}
return ret;
}
}