package org.baderlab.csplugins.enrichmentmap;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import com.google.inject.AbstractModule;
import com.google.inject.TypeLiteral;
import com.google.inject.matcher.AbstractMatcher;
import com.google.inject.spi.InjectionListener;
import com.google.inject.spi.TypeEncounter;
import com.google.inject.spi.TypeListener;
/**
* Guice module, makes the @AfterInjection annotation work.
*
* @author mkucera
*
*/
public class AfterInjectionModule extends AbstractModule {
@Override
protected void configure() {
// Call methods annotated with @AfterInjection after injection, mainly used to create UIs
bindListener(new AfterInjectionMatcher(), new TypeListener() {
AfterInjectionInvoker invoker = new AfterInjectionInvoker();
@Override
public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
encounter.register(invoker);
}
});
}
/**
* Guice matcher that matches types that have a method annotated with @AfterInjection
*/
static class AfterInjectionMatcher extends AbstractMatcher<TypeLiteral<?>> {
@Override
public boolean matches(TypeLiteral<?> typeLiteral) {
Method[] methods = typeLiteral.getRawType().getDeclaredMethods();
return Arrays.stream(methods).anyMatch(m -> m.isAnnotationPresent(AfterInjection.class));
}
}
/**
* Invokes methods annotated with @AfterInjection
*/
static class AfterInjectionInvoker implements InjectionListener<Object> {
@Override
public void afterInjection(Object injectee) {
Method[] methods = injectee.getClass().getDeclaredMethods();
for(Method method : methods) {
if(method.isAnnotationPresent(AfterInjection.class)) {
try {
method.setAccessible(true);
method.invoke(injectee);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}
}