// Path: src/main/java/fr/inria/gforge/spoon/assertgenerator/Logger.java
// public class Logger {
// 
// 	public static Map<String, Object> observations = new HashMap<>();
// 
// 	public static void observe(String name, Object object) {
// 		observations.put(name, object);
// 	}
// }
// 
// Path: src/main/java/fr/inria/gforge/spoon/assertgenerator/test/TestRunner.java
// public class TestRunner {
// 
//     private static Function<String[], URL[]> arrayStringToArrayUrl = (arrayStr) ->
//             Arrays.stream(arrayStr)
//                     .map(File::new)
//                     .map(File::toURI)
//                     .map(uri -> {
//                         try {
//                             return uri.toURL();
//                         } catch (MalformedURLException e) {
//                             throw new RuntimeException(e);
//                         }
//                     })
//                     .toArray(URL[]::new);
// 
//     //TODO should maybe run the Listener
// 
//     public static List<Failure> runTest(String fullQualifiedName, String testCaseName, String[] classpath) throws MalformedURLException, ClassNotFoundException {
//         ClassLoader classLoader = new URLClassLoader(
//                 arrayStringToArrayUrl.apply(classpath),
//                 ClassLoader.getSystemClassLoader()
//         );
//         Request request = Request.method(classLoader.loadClass(fullQualifiedName), testCaseName);
//         Runner runner = request.getRunner();
//         RunNotifier fNotifier = new RunNotifier();
//         final TestListener listener = new TestListener();
//         fNotifier.addFirstListener(listener);
//         fNotifier.fireTestRunStarted(runner.getDescription());
//         runner.run(fNotifier);
//         return listener.getTestFails();
//     }
// 
//     public static List<Failure> runTest(String fullQualifiedName, String[] classpath) throws MalformedURLException, ClassNotFoundException {
//         ClassLoader classLoader = new URLClassLoader(
//                 arrayStringToArrayUrl.apply(classpath),
//                 ClassLoader.getSystemClassLoader()
//         );
//         Request request = Request.classes(classLoader.loadClass(fullQualifiedName));
//         Runner runner = request.getRunner();
//         RunNotifier fNotifier = new RunNotifier();
//         final TestListener listener = new TestListener();
//         fNotifier.addFirstListener(listener);
//         fNotifier.fireTestRunStarted(runner.getDescription());
//         runner.run(fNotifier);
//         return listener.getTestFails();
//     }
// 
// }
// 
// Path: src/main/java/fr/inria/gforge/spoon/assertgenerator/Util.java
// public static List<CtMethod> getGetters(CtLocalVariable localVariable) {
// 	return ((Set<CtMethod<?>>) localVariable.getType().getDeclaration().getMethods()).stream()
// 			.filter(method -> method.getParameters().isEmpty() &&
// 					method.getType() != localVariable.getFactory().Type().VOID_PRIMITIVE &&
// 					(method.getSimpleName().startsWith("get") ||
// 							method.getSimpleName().startsWith("is"))
// 			).collect(Collectors.toList());
// }
// 
// Path: src/main/java/fr/inria/gforge/spoon/assertgenerator/Util.java
// public static String getKey(CtMethod method) {
// 	return method.getParent(CtClass.class).getSimpleName() + "#" + method.getSimpleName();
// }
// 
// Path: src/main/java/fr/inria/gforge/spoon/assertgenerator/Util.java
// public static CtInvocation invok(CtMethod method, CtLocalVariable localVariable) {
// 	final CtExecutableReference reference = method.getReference();
// 	final CtVariableAccess variableRead = method.getFactory().createVariableRead(localVariable.getReference(), false);
// 	return method.getFactory().createInvocation(variableRead, reference);
// }


import fr.inria.gforge.spoon.assertgenerator.Logger;
import fr.inria.gforge.spoon.assertgenerator.test.TestRunner;
import spoon.Launcher;
import spoon.SpoonModelBuilder;
import spoon.reflect.code.CtInvocation;
import spoon.reflect.code.CtLocalVariable;
import spoon.reflect.code.CtTypeAccess;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.factory.Factory;
import spoon.reflect.reference.CtExecutableReference;
import java.util.List;
import static fr.inria.gforge.spoon.assertgenerator.Util.getGetters;
import static fr.inria.gforge.spoon.assertgenerator.Util.getKey;
import static fr.inria.gforge.spoon.assertgenerator.Util.invok;
import java.net.MalformedURLException;
		CtMethod<?> clone = testMethod.clone();
		instrument(clone, localVariables);
		testClass.addMethod(clone);
		System.out.println(clone);
		run(launcher, testClass, clone);
		testClass.removeMethod(clone);
		testClass.addMethod(testMethod);
	}

	public void run(Launcher launcher, CtClass testClass, CtMethod<?> clone) {
		String fullQualifiedName = testClass.getQualifiedName();
		String testMethodName = clone.getSimpleName();
		try {
			final SpoonModelBuilder compiler = launcher.createCompiler();
			compiler.compile(SpoonModelBuilder.InputType.CTTYPES);
			TestRunner.runTest(fullQualifiedName, testMethodName, new String[]{"spooned-classes"});
		} catch (ClassNotFoundException | MalformedURLException e) {
			throw new RuntimeException(e);
		}
	}

	@SuppressWarnings("unchecked")
	public void instrument(CtMethod<?> testMethod, List<CtLocalVariable> ctLocalVariables) {
		ctLocalVariables.forEach(ctLocalVariable -> this.instrument(testMethod, ctLocalVariable));
	}

	void instrument(CtMethod testMethod, CtLocalVariable localVariable) {
		List<CtMethod> getters = getGetters(localVariable);
		getters.forEach(getter -> {
			CtInvocation invocationToGetter =
// Path: src/main/java/fr/inria/gforge/spoon/assertgenerator/Logger.java
// public class Logger {
// 
// 	public static Map<String, Object> observations = new HashMap<>();
// 
// 	public static void observe(String name, Object object) {
// 		observations.put(name, object);
// 	}
// }
// 
// Path: src/main/java/fr/inria/gforge/spoon/assertgenerator/test/TestRunner.java
// public class TestRunner {
// 
//     private static Function<String[], URL[]> arrayStringToArrayUrl = (arrayStr) ->
//             Arrays.stream(arrayStr)
//                     .map(File::new)
//                     .map(File::toURI)
//                     .map(uri -> {
//                         try {
//                             return uri.toURL();
//                         } catch (MalformedURLException e) {
//                             throw new RuntimeException(e);
//                         }
//                     })
//                     .toArray(URL[]::new);
// 
//     //TODO should maybe run the Listener
// 
//     public static List<Failure> runTest(String fullQualifiedName, String testCaseName, String[] classpath) throws MalformedURLException, ClassNotFoundException {
//         ClassLoader classLoader = new URLClassLoader(
//                 arrayStringToArrayUrl.apply(classpath),
//                 ClassLoader.getSystemClassLoader()
//         );
//         Request request = Request.method(classLoader.loadClass(fullQualifiedName), testCaseName);
//         Runner runner = request.getRunner();
//         RunNotifier fNotifier = new RunNotifier();
//         final TestListener listener = new TestListener();
//         fNotifier.addFirstListener(listener);
//         fNotifier.fireTestRunStarted(runner.getDescription());
//         runner.run(fNotifier);
//         return listener.getTestFails();
//     }
// 
//     public static List<Failure> runTest(String fullQualifiedName, String[] classpath) throws MalformedURLException, ClassNotFoundException {
//         ClassLoader classLoader = new URLClassLoader(
//                 arrayStringToArrayUrl.apply(classpath),
//                 ClassLoader.getSystemClassLoader()
//         );
//         Request request = Request.classes(classLoader.loadClass(fullQualifiedName));
//         Runner runner = request.getRunner();
//         RunNotifier fNotifier = new RunNotifier();
//         final TestListener listener = new TestListener();
//         fNotifier.addFirstListener(listener);
//         fNotifier.fireTestRunStarted(runner.getDescription());
//         runner.run(fNotifier);
//         return listener.getTestFails();
//     }
// 
// }
// 
// Path: src/main/java/fr/inria/gforge/spoon/assertgenerator/Util.java
// public static List<CtMethod> getGetters(CtLocalVariable localVariable) {
// 	return ((Set<CtMethod<?>>) localVariable.getType().getDeclaration().getMethods()).stream()
// 			.filter(method -> method.getParameters().isEmpty() &&
// 					method.getType() != localVariable.getFactory().Type().VOID_PRIMITIVE &&
// 					(method.getSimpleName().startsWith("get") ||
// 							method.getSimpleName().startsWith("is"))
// 			).collect(Collectors.toList());
// }
// 
// Path: src/main/java/fr/inria/gforge/spoon/assertgenerator/Util.java
// public static String getKey(CtMethod method) {
// 	return method.getParent(CtClass.class).getSimpleName() + "#" + method.getSimpleName();
// }
// 
// Path: src/main/java/fr/inria/gforge/spoon/assertgenerator/Util.java
// public static CtInvocation invok(CtMethod method, CtLocalVariable localVariable) {
// 	final CtExecutableReference reference = method.getReference();
// 	final CtVariableAccess variableRead = method.getFactory().createVariableRead(localVariable.getReference(), false);
// 	return method.getFactory().createInvocation(variableRead, reference);
// }


// Path: src/main/java/fr/inria/gforge/spoon/assertgenerator/workflow/Collector.java
import fr.inria.gforge.spoon.assertgenerator.Logger;
import fr.inria.gforge.spoon.assertgenerator.test.TestRunner;
import spoon.Launcher;
import spoon.SpoonModelBuilder;
import spoon.reflect.code.CtInvocation;
import spoon.reflect.code.CtLocalVariable;
import spoon.reflect.code.CtTypeAccess;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.factory.Factory;
import spoon.reflect.reference.CtExecutableReference;
import java.util.List;
import static fr.inria.gforge.spoon.assertgenerator.Util.getGetters;
import static fr.inria.gforge.spoon.assertgenerator.Util.getKey;
import static fr.inria.gforge.spoon.assertgenerator.Util.invok;
import java.net.MalformedURLException;

		CtMethod<?> clone = testMethod.clone();
		instrument(clone, localVariables);
		testClass.addMethod(clone);
		System.out.println(clone);
		run(launcher, testClass, clone);
		testClass.removeMethod(clone);
		testClass.addMethod(testMethod);
	}

	public void run(Launcher launcher, CtClass testClass, CtMethod<?> clone) {
		String fullQualifiedName = testClass.getQualifiedName();
		String testMethodName = clone.getSimpleName();
		try {
			final SpoonModelBuilder compiler = launcher.createCompiler();
			compiler.compile(SpoonModelBuilder.InputType.CTTYPES);
			TestRunner.runTest(fullQualifiedName, testMethodName, new String[]{"spooned-classes"});
		} catch (ClassNotFoundException | MalformedURLException e) {
			throw new RuntimeException(e);
		}
	}

	@SuppressWarnings("unchecked")
	public void instrument(CtMethod<?> testMethod, List<CtLocalVariable> ctLocalVariables) {
		ctLocalVariables.forEach(ctLocalVariable -> this.instrument(testMethod, ctLocalVariable));
	}

	void instrument(CtMethod testMethod, CtLocalVariable localVariable) {
		List<CtMethod> getters = getGetters(localVariable);
		getters.forEach(getter -> {
			CtInvocation invocationToGetter =
					invok(getter, localVariable);