package org.magenta.core.injection; import java.lang.reflect.Field; import java.lang.reflect.Method; import net.sf.cglib.proxy.Callback; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import org.magenta.DataSpecification; import org.magenta.Fixture; import org.magenta.annotations.InjectDataSpecification; import com.google.common.base.Supplier; public class DataSpecificationFieldHandler<S extends DataSpecification> implements FieldInjectionHandler<S> { @Override public boolean handle(Field f, Object target, Supplier<Fixture<S>> current) { if (f.isAnnotationPresent(org.magenta.annotations.InjectDataSpecification.class)) { InjectDataSpecification annotation = f.getAnnotation(org.magenta.annotations.InjectDataSpecification.class); if (DataSpecification.class.isAssignableFrom(f.getType())) { Enhancer e = new Enhancer(); e.setSuperclass(current.get().getSpecification().getClass()); e.setCallback(interceptor(supplierOfDataSpecification(current))); e.setInterceptDuringConstruction(false); DataSpecification proxy = (DataSpecification)e.create(); FieldInjectorUtils.injectInto(target, f, proxy); return true; }else{ throw new IllegalStateException("Invalid field : Annotation ["+InjectDataSpecification.class.getName()+"] is present on field named ["+f.getName()+"] on the class ["+f.getDeclaringClass().getCanonicalName()+"],\n but this field type should implement ["+DataSpecification.class.getName()+"] instead of ["+f.getType()+"]."); } } else { return false; } } private Callback interceptor(final Supplier<S> current) { return new MethodInterceptor() { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { return method.invoke(current.get(), args); } }; } private Supplier<S> supplierOfDataSpecification(final Supplier<Fixture<S>> current) { return new Supplier<S>(){ @Override public S get() { return current.get().getSpecification(); } }; } }