package javaf.syb;
import javaf.prelude.*;
import java.lang.reflect.*;
import java.util.List;
public class Query {
/**
* Apply a type-specific function if possible; apply generic function otherwise.
*/
public static <X,Y> Function<Object,Y> or(final Function<X,Y> f, final Function<Object,Y> otherwise) {
return new Function<Object,Y>() {
@SuppressWarnings("unchecked")
public Y apply(Object x) {
try {
return f.apply((X)x);
}
catch (ClassCastException _) {
return otherwise.apply(x);
}
}
};
}
/**
* Apply a function if possible; return default otherwise.
*/
public static <X,Y> Function<Object,Y> orDefault(final Function<X,Y> f, final Y otherwise) {
return or(f, new Function<Object,Y>() { public Y apply(Object x) { return otherwise; }});
}
/**
* Apply a query to all immediate sub-objects.
*/
public static <Y> Function<Object,Y> all(final Function<Object,Y> f, final BinaryOperator<Y> op, final Y initial) {
return new Function<Object,Y>() {
@SuppressWarnings("rawtypes")
public Y apply(Object x) {
Y y = initial;
// Special case for lists
if (x instanceof List)
for (Object o : (List)x)
y = op.apply(y, f.apply(o));
else {
// Regular case based on getters
for (Method m : x.getClass().getDeclaredMethods()) {
if (m.getName().startsWith("get")
&& m.getParameterTypes().length == 0) {
try {
y = op.apply(y, f.apply(m.invoke(x, new Object[]{})));
}
catch (IllegalAccessException e) {
// assert "DEAD CODE"
} catch (IllegalArgumentException e) {
// assert "DEAD CODE"
} catch (InvocationTargetException e) {
// assert "DEAD CODE"
}
}
}
}
return y;
}
};
}
/**
* Apply a function to each and every sub-object in bottom-up manner.
*/
public static <Y> Function<Object,Y> everything(final Function<Object,Y> f, final BinaryOperator<Y> op, final Y initial) {
return new Function<Object,Y>() {
public Y apply(Object x) {
return op.apply(f.apply(x), all(everything(f, op, initial), op, initial).apply(x));
}
};
}
}