
org.tools4j.groovytables.ClosureMethod.groovy Maven / Gradle / Ivy
package org.tools4j.groovytables
/**
* User: ben
* Date: 8/11/2016
* Time: 6:42 AM
*/
class ClosureMethod implements Callable {
final Closure closure
ClosureMethod(final Closure closure) {
this.closure = closure
}
interface ClosureCall{
T call(Object[] coercedArgs)
}
static class ClosureCallUsingDelegateProperties implements ClosureCall{
private final Closure closure
private final List columnHeadings
ClosureCallUsingDelegateProperties(Closure closure, final List columnHeadings) {
this.columnHeadings = columnHeadings
this.closure = closure
}
def call(Object[] coercedArgs) {
final Object delegate = new Object()
int i = 0
columnHeadings.each { final String heading ->
delegate.metaClass[heading] = coercedArgs[i++]
}
closure.setDelegate(delegate)
closure.setResolveStrategy(Closure.DELEGATE_FIRST)
closure.call()
}
}
static class ClosureCallUsingClosureArguments implements ClosureCall {
private final Closure closure
ClosureCallUsingClosureArguments(final Closure closure) {
this.closure = closure
}
T call(Object[] coercedArgs) {
return closure.curry(coercedArgs).call()
}
}
@Override
ClosureCallPrecursor getCallPrecursor(final List columnHeadings, final Object... rawArgs) {
if(columnHeadings == null || columnHeadings.size() == 0){
return getCallPrecursor(rawArgs)
}
if(closure.getMaximumNumberOfParameters() > 1){
throw new IllegalArgumentException("Cannot determine how to call closure. You have specified column headings" +
" " + columnHeadings + " AND you have specified " + closure.getMaximumNumberOfParameters() + " closure parameters." +
" Please choose just one approach. i.e. specify column headings, and no closure parameters, or specify closure" +
" parameters and no column headings.")
}
return new ClosureCallPrecursor(Suitability.SUITABLE, rawArgs, rawArgs, new ClosureCallUsingDelegateProperties(closure, columnHeadings))
}
@Override
ClosureCallPrecursor getCallPrecursor(final Object... rawArgs) {
Logger.info(" Getting ClosureCallPrecursor with parameters ${closure.getParameterTypes()}")
if(closure.getMaximumNumberOfParameters() <= 1){
throw new IllegalArgumentException("Cannot call closure. Please either specify column headings" +
" for each of your " + rawArgs.size() + " columns. Or, declare " + rawArgs.size() + " arguments" +
" in your closure to accept the row values: " + rawArgs)
} else if(closure.getMaximumNumberOfParameters() > 1 && closure.getMaximumNumberOfParameters() != rawArgs.length){
throw new IllegalArgumentException("Mismatched number of args, closure has:$closure.maximumNumberOfParameters != table has:$rawArgs.length. (Please note, use of varargs is not supported).")
}
Logger.info(" Correct number of args: $rawArgs.length")
Suitability worstSuitabilityOfThisExecutable = Suitability.SUITABLE;
final List coercedResults = new ArrayList<>(closure.getMaximumNumberOfParameters());
for (int i = 0; i < closure.getParameterTypes().size(); i++) {
final Class closureParamType = closure.getParameterTypes()[i];
Object rawArg = rawArgs[i]
final ValueCoercionResult coercionResult = ValueCoerser.coerceToType(rawArg, closureParamType);
worstSuitabilityOfThisExecutable = worstSuitabilityOfThisExecutable.worseOf(coercionResult.getSuitability())
Logger.info(" Coercion result for arg:${rawArg.getClass().simpleName}[$rawArg] to:$closureParamType.simpleName : $coercionResult")
coercedResults.add(coercionResult);
if (coercionResult.getSuitability() == Suitability.NOT_SUITABLE) {
throw new IllegalArgumentException("Error processing row $rawArgs. Could not coerce argument '$rawArg' of class <${rawArg.getClass().simpleName}>" +
" to closure argument of type <$closureParamType.>")
}
}
return new ClosureCallPrecursor(
worstSuitabilityOfThisExecutable,
rawArgs,
coercedResults.collect{it.result}.toArray(),
new ClosureCallUsingClosureArguments(closure)
);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy