package jfun.yan.xml.nuts.optional;
import java.lang.reflect.Array;
import java.util.Iterator;
import java.util.List;
import jfun.util.Misc;
import jfun.yan.Binder;
import jfun.yan.Component;
import jfun.yan.Creator;
import jfun.yan.xml.NutsUtils;
import jfun.yan.xml.nuts.DelegatingNut;
/**
* This Nut class enables calling a method/constructor with
* argument list created dynamically, rather than through the
* <code>arg</code> and <code>args</code> sub-elements literally.
* <p>
* @author Ben Yu
* Nov 10, 2005 12:10:12 AM
*/
public class WithArgumentsNut extends DelegatingNut {
private Component args;
public Component getArgs() {
checkMandatory("args", args);
return args;
}
public void setArgs(Component args) {
this.args = args;
}
public Component eval(){
final Component a = getArgs();
final Component cc = getMandatory();
Component result = a.bind(new Binder(){
public Creator bind(Object v) throws Throwable {
if(v==null) return cc;
if(v.getClass().isArray()){
final int sz = Array.getLength(v);
final Component[] cargs = new Component[sz];
if(v instanceof Object[]){
final Object[] arr = (Object[])v;
for(int i=0; i<cargs.length; i++){
cargs[i] = NutsUtils.asComponent(arr[i]);
}
}
else{
for(int i=0; i<cargs.length; i++){
cargs[i] = NutsUtils.asComponent(Array.get(v, i));
}
}
return cc.withArguments(cargs);
}
else if(v instanceof List){
final List list = (List)v;
final int sz = list.size();
final Component[] cargs = new Component[sz];
int i=0;
for(Iterator it=list.iterator(); it.hasNext(); i++){
cargs[i] = NutsUtils.asComponent(it.next());
}
return cc.withArguments(cargs);
}
else{
throw raise(Misc.getTypeName(v.getClass())+
" cannot be used as argument list");
}
}
});
final Class type = cc.getType();
if(type!=null)
result = cast(type, result);
return result;
}
}