// Path: src/main/java/com/timgroup/stanislavski/reflection/MethodCall.java
// public class MethodCall {
//     private final Method method;
//     private final Object[] rawArgs;
//     private final List<MethodCallArgument<?>> arguments;
//     
//     public static MethodCall create(Method method, Object...args) {
//         return new MethodCall(method, args);
//     }
// 
//     private MethodCall(Method method, Object[] rawArgs) {
//         this.method = method;
//         this.rawArgs = rawArgs;
//         this.arguments = MethodCallArgument.wrapArguments(method, rawArgs);
//     }
// 
//     public Class<?> targetClass() {
//         return method.getDeclaringClass();
//     }
//     
//     public Class<?> returnType() {
//         return method.getReturnType();
//     }
// 
//     public String name() {
//         return method.getName();
//     }
// 
//     public List<MethodCallArgument<?>> arguments() {
//         return arguments;
//     }
// 
//     public boolean hasAnnotation(Class<? extends Annotation> annotationClass) {
//         return method.isAnnotationPresent(annotationClass);
//     }
//     
//     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
//         return method.getAnnotation(annotationClass);
//     }
// 
//     public MethodCallArgument<?> firstArgument() {
//         return arguments.get(0);
//     }
//     
//     public Object applyTo(Object target) throws Throwable {
//         try {
//             return this.method.invoke(target, rawArgs);
//         } catch (InvocationTargetException e) {
//             throw e.getCause();
//         }
//     }
//     
//     @Override public String toString() {
//         return String.format("%s: %s", method, arguments);
//     }
// 
//     public List<Object> argumentValues() {
//         return Lists.transform(arguments, MethodCallArgument.TO_VALUE);
//     }
// }


import java.lang.reflect.Method;
import java.util.List;
import org.hamcrest.Matchers;
import org.junit.Test;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.collect.Lists;
import com.timgroup.stanislavski.reflection.MethodCall;
import static org.hamcrest.MatcherAssert.assertThat;
package com.timgroup.stanislavski.interpreters;





public class InterpretersTest {

    private Function<String, String> toUpperCase() {
        return new Function<String, String>() {
            @Override public String apply(String arg0) {
                return arg0.toUpperCase();
            }
        };
    }
    
    public static interface TestInterface {
        public TestInterface foo(String value);
        
        @AddressesProperty("quux")
        public TestInterface baz(String value);
    }
    
    @Test public void
    constructs_a_name_value_interpreter_using_supplied_key_and_value_interpreters() throws SecurityException, NoSuchMethodException {
        KeyValuePairInterpreter<String, String> interpreter = 
                Interpreters.keyValuePairInterpreter(ExtractorFor.theMethodName()
                                                                 .compose(toUpperCase())
                                                                 .chain(AnnotationOverride.<AddressesProperty, String>obtainingValueOf(AddressesProperty.class)))
                            .obtainingValueWith(ExtractorFor.theFirstArgument()
                                                            .compose(Functions.toStringFunction()));
        
// Path: src/main/java/com/timgroup/stanislavski/reflection/MethodCall.java
// public class MethodCall {
//     private final Method method;
//     private final Object[] rawArgs;
//     private final List<MethodCallArgument<?>> arguments;
//     
//     public static MethodCall create(Method method, Object...args) {
//         return new MethodCall(method, args);
//     }
// 
//     private MethodCall(Method method, Object[] rawArgs) {
//         this.method = method;
//         this.rawArgs = rawArgs;
//         this.arguments = MethodCallArgument.wrapArguments(method, rawArgs);
//     }
// 
//     public Class<?> targetClass() {
//         return method.getDeclaringClass();
//     }
//     
//     public Class<?> returnType() {
//         return method.getReturnType();
//     }
// 
//     public String name() {
//         return method.getName();
//     }
// 
//     public List<MethodCallArgument<?>> arguments() {
//         return arguments;
//     }
// 
//     public boolean hasAnnotation(Class<? extends Annotation> annotationClass) {
//         return method.isAnnotationPresent(annotationClass);
//     }
//     
//     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
//         return method.getAnnotation(annotationClass);
//     }
// 
//     public MethodCallArgument<?> firstArgument() {
//         return arguments.get(0);
//     }
//     
//     public Object applyTo(Object target) throws Throwable {
//         try {
//             return this.method.invoke(target, rawArgs);
//         } catch (InvocationTargetException e) {
//             throw e.getCause();
//         }
//     }
//     
//     @Override public String toString() {
//         return String.format("%s: %s", method, arguments);
//     }
// 
//     public List<Object> argumentValues() {
//         return Lists.transform(arguments, MethodCallArgument.TO_VALUE);
//     }
// }


// Path: src/test/java/com/timgroup/stanislavski/interpreters/InterpretersTest.java
import java.lang.reflect.Method;
import java.util.List;
import org.hamcrest.Matchers;
import org.junit.Test;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.collect.Lists;
import com.timgroup.stanislavski.reflection.MethodCall;
import static org.hamcrest.MatcherAssert.assertThat;

package com.timgroup.stanislavski.interpreters;





public class InterpretersTest {

    private Function<String, String> toUpperCase() {
        return new Function<String, String>() {
            @Override public String apply(String arg0) {
                return arg0.toUpperCase();
            }
        };
    }
    
    public static interface TestInterface {
        public TestInterface foo(String value);
        
        @AddressesProperty("quux")
        public TestInterface baz(String value);
    }
    
    @Test public void
    constructs_a_name_value_interpreter_using_supplied_key_and_value_interpreters() throws SecurityException, NoSuchMethodException {
        KeyValuePairInterpreter<String, String> interpreter = 
                Interpreters.keyValuePairInterpreter(ExtractorFor.theMethodName()
                                                                 .compose(toUpperCase())
                                                                 .chain(AnnotationOverride.<AddressesProperty, String>obtainingValueOf(AddressesProperty.class)))
                            .obtainingValueWith(ExtractorFor.theFirstArgument()
                                                            .compose(Functions.toStringFunction()));
        
        List<MethodCall> callHistory = Lists.newArrayList(