// Path: engine/src/main/java/com/impossibl/stencil/engine/ExecutionException.java
// public class ExecutionException extends RuntimeException {
// 
//   private static final long serialVersionUID = 376006343757200461L;
//   
//   ExecutionLocation location;
// 
//   public ExecutionException() {
//   }
// 
//   public ExecutionException(String message, Throwable cause, ExecutionLocation location) {
//     super(location + ": " + message, cause);
//     this.location = location;
//   }
//   
//   public ExecutionException(String message, ExecutionLocation location) {
//     super(location + ": " + message);
//     this.location = location;
//   }
// 
//   public ExecutionException(Throwable cause, ExecutionLocation location) {
//     super(cause);
//     this.location = location;
//   }
// 
//   public ExecutionLocation getLocation() {
//     return location;
//   }
// 
//   public void setLocation(ExecutionLocation location) {
//     this.location = location;
//   }
// 
// }
// 
// Path: engine/src/main/java/com/impossibl/stencil/engine/InvocationException.java
// public class InvocationException extends ExecutionException {
// 
//   private static final long serialVersionUID = -5527033329538312329L;
// 
//   public InvocationException() {
// 	}
// 
//   public InvocationException(String message, Throwable cause, ExecutionLocation location) {
//     super(message, cause, location);
//   }
// 
//   public InvocationException(String message, ExecutionLocation location) {
//     super(message, location);
//   }
// 
// }


import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import com.impossibl.stencil.api.Named;
import com.impossibl.stencil.engine.ExecutionException;
import com.impossibl.stencil.engine.InvocationException;
import com.thoughtworks.paranamer.AnnotationParanamer;
import com.thoughtworks.paranamer.CachingParanamer;
import com.thoughtworks.paranamer.Paranamer;
    throw new ExecutionException("invalid auto-function: no '" + name + "' method declared", null);
  }

  /**
   * Invokes the given method mapping named parameters to positions based on a
   * given list of parameter names.
   * 
   * @param method Method to invoke
   * @param paramNames Positioned list of parameter names to map direct mapping
   * @param params Named parameters to use
   * @param instance Instance to invoke method on
   * @return Result of method invocation
   * @throws Throwable
   */
  public static Object exec(Method method, String[] paramNames, Map<String,?> params, Object instance) throws Throwable {
    
    Object[] paramValues = new Object[paramNames.length];

    for(int c=0; c < paramNames.length; ++c) {
      paramValues[c] = params.get(paramNames[c]);
    }
    
    try {
      return method.invoke(instance, paramValues);
    }
    catch (IllegalAccessException e) {
      //Shouldn't happen
      throw new RuntimeException(e);
    }
    catch (IllegalArgumentException e) {
// Path: engine/src/main/java/com/impossibl/stencil/engine/ExecutionException.java
// public class ExecutionException extends RuntimeException {
// 
//   private static final long serialVersionUID = 376006343757200461L;
//   
//   ExecutionLocation location;
// 
//   public ExecutionException() {
//   }
// 
//   public ExecutionException(String message, Throwable cause, ExecutionLocation location) {
//     super(location + ": " + message, cause);
//     this.location = location;
//   }
//   
//   public ExecutionException(String message, ExecutionLocation location) {
//     super(location + ": " + message);
//     this.location = location;
//   }
// 
//   public ExecutionException(Throwable cause, ExecutionLocation location) {
//     super(cause);
//     this.location = location;
//   }
// 
//   public ExecutionLocation getLocation() {
//     return location;
//   }
// 
//   public void setLocation(ExecutionLocation location) {
//     this.location = location;
//   }
// 
// }
// 
// Path: engine/src/main/java/com/impossibl/stencil/engine/InvocationException.java
// public class InvocationException extends ExecutionException {
// 
//   private static final long serialVersionUID = -5527033329538312329L;
// 
//   public InvocationException() {
// 	}
// 
//   public InvocationException(String message, Throwable cause, ExecutionLocation location) {
//     super(message, cause, location);
//   }
// 
//   public InvocationException(String message, ExecutionLocation location) {
//     super(message, location);
//   }
// 
// }


// Path: engine/src/main/java/com/impossibl/stencil/api/impl/AnnotatedExtensions.java
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import com.impossibl.stencil.api.Named;
import com.impossibl.stencil.engine.ExecutionException;
import com.impossibl.stencil.engine.InvocationException;
import com.thoughtworks.paranamer.AnnotationParanamer;
import com.thoughtworks.paranamer.CachingParanamer;
import com.thoughtworks.paranamer.Paranamer;

    throw new ExecutionException("invalid auto-function: no '" + name + "' method declared", null);
  }

  /**
   * Invokes the given method mapping named parameters to positions based on a
   * given list of parameter names.
   * 
   * @param method Method to invoke
   * @param paramNames Positioned list of parameter names to map direct mapping
   * @param params Named parameters to use
   * @param instance Instance to invoke method on
   * @return Result of method invocation
   * @throws Throwable
   */
  public static Object exec(Method method, String[] paramNames, Map<String,?> params, Object instance) throws Throwable {
    
    Object[] paramValues = new Object[paramNames.length];

    for(int c=0; c < paramNames.length; ++c) {
      paramValues[c] = params.get(paramNames[c]);
    }
    
    try {
      return method.invoke(instance, paramValues);
    }
    catch (IllegalAccessException e) {
      //Shouldn't happen
      throw new RuntimeException(e);
    }
    catch (IllegalArgumentException e) {
      throw new InvocationException("invalid arguments", e, null);