// Path: x_common/reflection/src/main/java/org/zalando/techtalks/hackingjava/common/reflection/ReflectionHelper.java
// public static <T> T instantiate(final Class<? extends T> type, final Object... params) {
//     try {
//         final Constructor<T> constructor = findCompatibleConstructor(type, params);
//         constructor.setAccessible(true);
//         return constructor.newInstance(params);
//     } catch (InvocationTargetException | InstantiationException | IllegalAccessException e) {
//         throw new IllegalStateException(e);
//     }
// }
// 
// Path: x_common/reflection/src/main/java/org/zalando/techtalks/hackingjava/common/reflection/ReflectionHelper.java
// public static Object invokeMethod(final Object targetObject,
//                                   final String methodName,
//                                   final Object... params) {
//     try {
//         final List<Method> methodsByName = findMethodsByName(targetObject.getClass(),
//                                                              methodName);
//         final Method method =
//             methodsByName.stream()                                                            //
//                 .filter(candidate -> candidate.getParameterCount() == params.length) //
//                 .findFirst()                                                         //
//                 .orElseThrow(ReflectionHelper::noAppropriateMethodFound);
// 
//         method.setAccessible(true);
//         return method.invoke(targetObject, params); //
//     } catch (InvocationTargetException | IllegalAccessException e) {
//         throw new IllegalStateException(e);
//     }
// 
// }


import java.util.Objects;
import org.hamcrest.CoreMatchers;
import org.junit.Test;
import static org.junit.Assert.assertThat;
import static org.zalando.techtalks.hackingjava.common.reflection.ReflectionHelper.instantiate;
import static org.zalando.techtalks.hackingjava.common.reflection.ReflectionHelper.invokeMethod;
                return Objects.equals(this.foo, other.foo) && Objects.equals(this.bar, other.bar);
            } else {
                return false;
            }
        }
    }

    @Test
    public void instantiateWithParams() {
        assertThat(instantiate(TwoArgs.class, 123, "abc"),
                   CoreMatchers.is(CoreMatchers.equalTo(new TwoArgs(123, "abc"))));
    }

    @Test
    public void invokeMethodWithoutParam() {
        class MethodWithoutParam {
            String foo() {
                return "bar";
            }
        }
        assertThat(invokeMethod(new MethodWithoutParam(), "foo"), CoreMatchers.is("bar"));
    }

    @Test
    public void invokeMethodWithParams() {
        class MethodWithTwoParams {
            String foo(final String fizz, final int buzz) {
                return fizz + buzz;
            }
        }
// Path: x_common/reflection/src/main/java/org/zalando/techtalks/hackingjava/common/reflection/ReflectionHelper.java
// public static <T> T instantiate(final Class<? extends T> type, final Object... params) {
//     try {
//         final Constructor<T> constructor = findCompatibleConstructor(type, params);
//         constructor.setAccessible(true);
//         return constructor.newInstance(params);
//     } catch (InvocationTargetException | InstantiationException | IllegalAccessException e) {
//         throw new IllegalStateException(e);
//     }
// }
// 
// Path: x_common/reflection/src/main/java/org/zalando/techtalks/hackingjava/common/reflection/ReflectionHelper.java
// public static Object invokeMethod(final Object targetObject,
//                                   final String methodName,
//                                   final Object... params) {
//     try {
//         final List<Method> methodsByName = findMethodsByName(targetObject.getClass(),
//                                                              methodName);
//         final Method method =
//             methodsByName.stream()                                                            //
//                 .filter(candidate -> candidate.getParameterCount() == params.length) //
//                 .findFirst()                                                         //
//                 .orElseThrow(ReflectionHelper::noAppropriateMethodFound);
// 
//         method.setAccessible(true);
//         return method.invoke(targetObject, params); //
//     } catch (InvocationTargetException | IllegalAccessException e) {
//         throw new IllegalStateException(e);
//     }
// 
// }


// Path: x_common/reflection/src/test/java/org/zalando/techtalks/hackingjava/common/reflection/ReflectionHelperTest.java
import java.util.Objects;
import org.hamcrest.CoreMatchers;
import org.junit.Test;
import static org.junit.Assert.assertThat;
import static org.zalando.techtalks.hackingjava.common.reflection.ReflectionHelper.instantiate;
import static org.zalando.techtalks.hackingjava.common.reflection.ReflectionHelper.invokeMethod;

                return Objects.equals(this.foo, other.foo) && Objects.equals(this.bar, other.bar);
            } else {
                return false;
            }
        }
    }

    @Test
    public void instantiateWithParams() {
        assertThat(instantiate(TwoArgs.class, 123, "abc"),
                   CoreMatchers.is(CoreMatchers.equalTo(new TwoArgs(123, "abc"))));
    }

    @Test
    public void invokeMethodWithoutParam() {
        class MethodWithoutParam {
            String foo() {
                return "bar";
            }
        }
        assertThat(invokeMethod(new MethodWithoutParam(), "foo"), CoreMatchers.is("bar"));
    }

    @Test
    public void invokeMethodWithParams() {
        class MethodWithTwoParams {
            String foo(final String fizz, final int buzz) {
                return fizz + buzz;
            }
        }
        assertThat(invokeMethod(new MethodWithTwoParams(), "foo", "abc", 123),