package jfun.yan.xml.nuts.optional;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Iterator;
import jfun.yan.Binder;
import jfun.yan.Components;
import jfun.yan.Creator;
import jfun.yan.Monad;
import jfun.yan.xml.nuts.DelegatingBinderNut;
/**
* This Nut class creates a Binder object that passes each element in
* an array/collection/map to another Binder object for subsequent changes.
* <p>
* If the object is not an array/collection/Map, it directly calls against the object
* itself.
* </p>
* <p>
* @author Ben Yu
* Nov 12, 2005 11:59:27 PM
*/
public class ForeachNut extends DelegatingBinderNut {
public Binder eval() throws Exception {
final Binder binder = getMandatory();
return new Binder(){
public Creator bind(Object v)
throws Throwable{
if(v==null) return Components.value(null);
final Creator[] steps = getNextSteps(v, binder);
return Monad.sequence(steps);
}
public String toString(){
return "foreach";
}
};
}
private static Creator[] getNextSteps(Object obj, Binder next)
throws Throwable{
if(obj instanceof java.util.Map){
return getNextSteps((java.util.Map)obj, next);
}
else if(obj instanceof Object[]){
return getNextSteps((Object[])obj, next);
}
else if(obj instanceof Collection){
return getNextSteps((Collection)obj, next);
}
else if(obj.getClass().isArray()){
return getNextStepsForArray(obj, next);
}
else{
return new Creator[]{next.bind(obj)};
}
}
private static Creator[] getNextStepsForArray(Object arr, Binder next)
throws Throwable{
final int sz = Array.getLength(arr);
final Creator[] result = new Creator[sz];
for(int i=0; i<sz ;i++){
result[i] = next.bind(Array.get(arr, i));
}
return result;
}
private static Creator[] getNextSteps(Object[] arr, Binder next)
throws Throwable{
final Creator[] result = new Creator[arr.length];
for(int i=0; i<arr.length ;i++){
result[i] = next.bind(arr[i]);
}
return result;
}
private static Creator[] getNextSteps(java.util.Map m, Binder next)
throws Throwable{
return getNextSteps(m.values(), next);
}
private static Creator[] getNextSteps(Collection c, Binder next)
throws Throwable{
final Creator[] result = new Creator[c.size()];
int i=0;
for(Iterator it = c.iterator(); it.hasNext();i++){
result[i] = next.bind(it.next());
}
return result;
}
}