// Path: core/src/main/java/eu/drus/jpa/unit/spi/DecoratorExecutor.java
// public class DecoratorExecutor {
// 
//     private static final Comparator<TestDecorator> BEFORE_COMPARATOR = (a, b) -> a.getPriority() - b.getPriority();
//     private static final Comparator<TestDecorator> AFTER_COMPARATOR = (a, b) -> b.getPriority() - a.getPriority();
// 
//     public void processBeforeAll(final TestInvocation invocation) throws Exception {
//         final Iterator<TestClassDecorator> it = classDecoratorIterator(invocation.getContext(), BEFORE_COMPARATOR);
//         while (it.hasNext()) {
//             it.next().beforeAll(invocation);
//         }
//     }
// 
//     public void processAfterAll(final TestInvocation invocation) throws Exception {
//         final Iterator<TestClassDecorator> it = classDecoratorIterator(invocation.getContext(), AFTER_COMPARATOR);
//         while (it.hasNext()) {
//             it.next().afterAll(invocation);
//         }
//     }
// 
//     public void processBefore(final TestInvocation invocation) throws Exception {
//         final Iterator<TestMethodDecorator> it = methodDecoratorIterator(invocation.getContext(), BEFORE_COMPARATOR);
//         while (it.hasNext()) {
//             it.next().beforeTest(invocation);
//         }
//     }
// 
//     public void processAfter(final TestInvocation invocation) throws Exception {
//         final Iterator<TestMethodDecorator> it = methodDecoratorIterator(invocation.getContext(), AFTER_COMPARATOR);
//         while (it.hasNext()) {
//             it.next().afterTest(invocation);
//         }
//     }
// 
//     private Iterator<TestClassDecorator> classDecoratorIterator(final ExecutionContext ctx, final Comparator<TestDecorator> comparator) {
//         return getClassDecorators().stream().filter(d -> d.isConfigurationSupported(ctx)).sorted(comparator).iterator();
//     }
// 
//     private Iterator<TestMethodDecorator> methodDecoratorIterator(final ExecutionContext ctx, final Comparator<TestDecorator> comparator) {
//         return getMethodDecorators().stream().filter(d -> d.isConfigurationSupported(ctx)).sorted(comparator).iterator();
//     }
// }
// 
// Path: core/src/main/java/eu/drus/jpa/unit/util/ReflectionUtils.java
// public final class ReflectionUtils {
//     private ReflectionUtils() {}
//     
//     private static Field findField(final Object src, final String fieldName) throws NoSuchFieldException {
// 		Class<?> current = src.getClass();
//     	Field field = null;
//     	
//     	while(current != null && field == null) {
//     		field = getField(current, fieldName);
//     		current = current.getSuperclass();
//     	}
//     	
//     	if(field == null) {
//     		throw new NoSuchFieldException(src + " does not declare " + fieldName);
//     	}
//     	
// 		return field;
// 	}
// 
// 	private static Field getField(Class<?> clazz, final String fieldName) {
// 		for (Field field : clazz.getDeclaredFields()) {
// 			if(field.getName().equals(fieldName)) {
// 				return field;
// 			}
// 		}
// 		return null;
// 	}
//     
//     public static void injectValue(final Object obj, final String fieldName, final Object value) throws NoSuchFieldException, IllegalAccessException {
//     	injectValue(obj, findField(obj, fieldName), value);
//     }
// 
//     public static void injectValue(final Object obj, final Field field, final Object value) throws IllegalAccessException {
//         final boolean isAccessible = field.isAccessible();
//         field.setAccessible(true);
//         try {
//             field.set(obj, value);
//         } finally {
//             field.setAccessible(isAccessible);
//         }
//     }
//     
//     public static Object getValue(final Object src, final String fieldName) throws IllegalAccessException, NoSuchFieldException {
//     	return getValue(src, findField(src, fieldName));
//     }
// 
//     public static Object getValue(final Object src, final Field field) throws IllegalAccessException {
//         final boolean isAccessible = field.isAccessible();
//         field.setAccessible(true);
//         try {
//             return field.get(src);
//         } finally {
//             field.setAccessible(isAccessible);
//         }
//     }
// }


import static net.bytebuddy.implementation.MethodDelegation.to;
import static net.bytebuddy.implementation.MethodDelegation.toField;
import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith;
import static net.bytebuddy.matcher.ElementMatchers.isClone;
import static net.bytebuddy.matcher.ElementMatchers.isDeclaredBy;
import static net.bytebuddy.matcher.ElementMatchers.isEquals;
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
import static net.bytebuddy.matcher.ElementMatchers.not;
import java.lang.reflect.Modifier;
import eu.drus.jpa.unit.api.JpaUnitException;
import eu.drus.jpa.unit.spi.DecoratorExecutor;
import eu.drus.jpa.unit.util.ReflectionUtils;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
package eu.drus.jpa.unit.concordion;




public interface EnhancedProxy {

	static Object create(final Object bean, DecoratorExecutor executor) {
		try {
			Object proxy = new ByteBuddy()
				.subclass(bean.getClass())
				.implement(EnhancedProxy.class)
				.defineField("bean", bean.getClass(), Modifier.PRIVATE)
				.defineField("executor", DecoratorExecutor.class, Modifier.PRIVATE)
				.method(isEquals())
					.intercept(to(EqualsInterceptor.class))
				.method(not(isDeclaredBy(Object.class).or(isAnnotatedWith(nameStartsWith("org.concordion.api")))))
					.intercept(to(ConcordionInterceptor.class))
				.method(isDeclaredBy(Object.class).and(not(isEquals().or(isClone()))))
					.intercept(toField("bean"))
				.make()
				.load(bean.getClass().getClassLoader(), ClassLoadingStrategy.Default.INJECTION)
				.getLoaded()
				.newInstance();
			
// Path: core/src/main/java/eu/drus/jpa/unit/spi/DecoratorExecutor.java
// public class DecoratorExecutor {
// 
//     private static final Comparator<TestDecorator> BEFORE_COMPARATOR = (a, b) -> a.getPriority() - b.getPriority();
//     private static final Comparator<TestDecorator> AFTER_COMPARATOR = (a, b) -> b.getPriority() - a.getPriority();
// 
//     public void processBeforeAll(final TestInvocation invocation) throws Exception {
//         final Iterator<TestClassDecorator> it = classDecoratorIterator(invocation.getContext(), BEFORE_COMPARATOR);
//         while (it.hasNext()) {
//             it.next().beforeAll(invocation);
//         }
//     }
// 
//     public void processAfterAll(final TestInvocation invocation) throws Exception {
//         final Iterator<TestClassDecorator> it = classDecoratorIterator(invocation.getContext(), AFTER_COMPARATOR);
//         while (it.hasNext()) {
//             it.next().afterAll(invocation);
//         }
//     }
// 
//     public void processBefore(final TestInvocation invocation) throws Exception {
//         final Iterator<TestMethodDecorator> it = methodDecoratorIterator(invocation.getContext(), BEFORE_COMPARATOR);
//         while (it.hasNext()) {
//             it.next().beforeTest(invocation);
//         }
//     }
// 
//     public void processAfter(final TestInvocation invocation) throws Exception {
//         final Iterator<TestMethodDecorator> it = methodDecoratorIterator(invocation.getContext(), AFTER_COMPARATOR);
//         while (it.hasNext()) {
//             it.next().afterTest(invocation);
//         }
//     }
// 
//     private Iterator<TestClassDecorator> classDecoratorIterator(final ExecutionContext ctx, final Comparator<TestDecorator> comparator) {
//         return getClassDecorators().stream().filter(d -> d.isConfigurationSupported(ctx)).sorted(comparator).iterator();
//     }
// 
//     private Iterator<TestMethodDecorator> methodDecoratorIterator(final ExecutionContext ctx, final Comparator<TestDecorator> comparator) {
//         return getMethodDecorators().stream().filter(d -> d.isConfigurationSupported(ctx)).sorted(comparator).iterator();
//     }
// }
// 
// Path: core/src/main/java/eu/drus/jpa/unit/util/ReflectionUtils.java
// public final class ReflectionUtils {
//     private ReflectionUtils() {}
//     
//     private static Field findField(final Object src, final String fieldName) throws NoSuchFieldException {
// 		Class<?> current = src.getClass();
//     	Field field = null;
//     	
//     	while(current != null && field == null) {
//     		field = getField(current, fieldName);
//     		current = current.getSuperclass();
//     	}
//     	
//     	if(field == null) {
//     		throw new NoSuchFieldException(src + " does not declare " + fieldName);
//     	}
//     	
// 		return field;
// 	}
// 
// 	private static Field getField(Class<?> clazz, final String fieldName) {
// 		for (Field field : clazz.getDeclaredFields()) {
// 			if(field.getName().equals(fieldName)) {
// 				return field;
// 			}
// 		}
// 		return null;
// 	}
//     
//     public static void injectValue(final Object obj, final String fieldName, final Object value) throws NoSuchFieldException, IllegalAccessException {
//     	injectValue(obj, findField(obj, fieldName), value);
//     }
// 
//     public static void injectValue(final Object obj, final Field field, final Object value) throws IllegalAccessException {
//         final boolean isAccessible = field.isAccessible();
//         field.setAccessible(true);
//         try {
//             field.set(obj, value);
//         } finally {
//             field.setAccessible(isAccessible);
//         }
//     }
//     
//     public static Object getValue(final Object src, final String fieldName) throws IllegalAccessException, NoSuchFieldException {
//     	return getValue(src, findField(src, fieldName));
//     }
// 
//     public static Object getValue(final Object src, final Field field) throws IllegalAccessException {
//         final boolean isAccessible = field.isAccessible();
//         field.setAccessible(true);
//         try {
//             return field.get(src);
//         } finally {
//             field.setAccessible(isAccessible);
//         }
//     }
// }


// Path: concordion/src/main/java/eu/drus/jpa/unit/concordion/EnhancedProxy.java
import static net.bytebuddy.implementation.MethodDelegation.to;
import static net.bytebuddy.implementation.MethodDelegation.toField;
import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith;
import static net.bytebuddy.matcher.ElementMatchers.isClone;
import static net.bytebuddy.matcher.ElementMatchers.isDeclaredBy;
import static net.bytebuddy.matcher.ElementMatchers.isEquals;
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
import static net.bytebuddy.matcher.ElementMatchers.not;
import java.lang.reflect.Modifier;
import eu.drus.jpa.unit.api.JpaUnitException;
import eu.drus.jpa.unit.spi.DecoratorExecutor;
import eu.drus.jpa.unit.util.ReflectionUtils;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;

package eu.drus.jpa.unit.concordion;




public interface EnhancedProxy {

	static Object create(final Object bean, DecoratorExecutor executor) {
		try {
			Object proxy = new ByteBuddy()
				.subclass(bean.getClass())
				.implement(EnhancedProxy.class)
				.defineField("bean", bean.getClass(), Modifier.PRIVATE)
				.defineField("executor", DecoratorExecutor.class, Modifier.PRIVATE)
				.method(isEquals())
					.intercept(to(EqualsInterceptor.class))
				.method(not(isDeclaredBy(Object.class).or(isAnnotatedWith(nameStartsWith("org.concordion.api")))))
					.intercept(to(ConcordionInterceptor.class))
				.method(isDeclaredBy(Object.class).and(not(isEquals().or(isClone()))))
					.intercept(toField("bean"))
				.make()
				.load(bean.getClass().getClassLoader(), ClassLoadingStrategy.Default.INJECTION)
				.getLoaded()
				.newInstance();
			
			ReflectionUtils.injectValue(proxy, "bean", bean);