package com.hubspot.blazar.guice;
import com.google.inject.Binder;
import com.google.inject.Binding;
import com.google.inject.Key;
import com.google.inject.MembersInjector;
import com.google.inject.Module;
import com.google.inject.PrivateBinder;
import com.google.inject.Provider;
import com.google.inject.Scope;
import com.google.inject.Stage;
import com.google.inject.TypeLiteral;
import com.google.inject.binder.AnnotatedBindingBuilder;
import com.google.inject.binder.AnnotatedConstantBindingBuilder;
import com.google.inject.binder.LinkedBindingBuilder;
import com.google.inject.matcher.Matcher;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.Message;
import com.google.inject.spi.ModuleAnnotatedMethodScanner;
import com.google.inject.spi.ProvisionListener;
import com.google.inject.spi.TypeConverter;
import com.google.inject.spi.TypeListener;
import org.aopalliance.intercept.MethodInterceptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
public abstract class ConfigurationAwareModule<Configuration> implements Module {
private volatile Configuration configuration = null;
@Override
public final void configure(Binder binder) {
configure(decorate(binder), getConfiguration());
}
public void setConfiguration(Configuration configuration) {
checkState(this.configuration == null, "configuration was already set!");
this.configuration = checkNotNull(configuration, "configuration is null");
}
protected Configuration getConfiguration() {
return checkNotNull(this.configuration, "configuration was not set!");
}
protected abstract void configure(final Binder binder, final Configuration configuration);
private Binder decorate(final Binder binder) {
return new Binder() {
@Override
@SuppressWarnings("unchecked")
public void install(Module module) {
if (module instanceof ConfigurationAwareModule<?>) {
((ConfigurationAwareModule<Configuration>) module).setConfiguration(getConfiguration());
}
binder.install(module);
}
@Override
public void bindInterceptor(Matcher<? super Class<?>> classMatcher,
Matcher<? super Method> methodMatcher,
MethodInterceptor... interceptors) {
binder.bindInterceptor(classMatcher, methodMatcher, interceptors);
}
@Override
public void bindScope(Class<? extends Annotation> annotationType, Scope scope) {
binder.bindScope(annotationType, scope);
}
@Override
public <T> LinkedBindingBuilder<T> bind(Key<T> key) {
return binder.bind(key);
}
@Override
public <T> AnnotatedBindingBuilder<T> bind(TypeLiteral<T> typeLiteral) {
return binder.bind(typeLiteral);
}
@Override
public <T> AnnotatedBindingBuilder<T> bind(Class<T> type) {
return binder.bind(type);
}
@Override
public AnnotatedConstantBindingBuilder bindConstant() {
return binder.bindConstant();
}
@Override
public <T> void requestInjection(TypeLiteral<T> type, T instance) {
binder.requestInjection(type, instance);
}
@Override
public void requestInjection(Object instance) {
binder.requestInjection(instance);
}
@Override
public void requestStaticInjection(Class<?>... types) {
binder.requestStaticInjection(types);
}
@Override
public Stage currentStage() {
return binder.currentStage();
}
@Override
public void addError(String message, Object... arguments) {
binder.addError(message, arguments);
}
@Override
public void addError(Throwable t) {
binder.addError(t);
}
@Override
public void addError(Message message) {
binder.addError(message);
}
@Override
public <T> Provider<T> getProvider(Key<T> key) {
return binder.getProvider(key);
}
@Override
public <T> Provider<T> getProvider(Dependency<T> dependency) {
return binder.getProvider(dependency);
}
@Override
public <T> Provider<T> getProvider(Class<T> type) {
return binder.getProvider(type);
}
@Override
public <T> MembersInjector<T> getMembersInjector(TypeLiteral<T> typeLiteral) {
return binder.getMembersInjector(typeLiteral);
}
@Override
public <T> MembersInjector<T> getMembersInjector(Class<T> type) {
return binder.getMembersInjector(type);
}
@Override
public void convertToTypes(Matcher<? super TypeLiteral<?>> typeMatcher, TypeConverter converter) {
binder.convertToTypes(typeMatcher, converter);
}
@Override
public void bindListener(Matcher<? super TypeLiteral<?>> typeMatcher, TypeListener listener) {
binder.bindListener(typeMatcher, listener);
}
@Override
public void bindListener(Matcher<? super Binding<?>> bindingMatcher, ProvisionListener... listeners) {
binder.bindListener(bindingMatcher, listeners);
}
@Override
public Binder withSource(Object source) {
return binder.withSource(source);
}
@Override
public Binder skipSources(Class... classesToSkip) {
return binder.skipSources(classesToSkip);
}
@Override
public PrivateBinder newPrivateBinder() {
return binder.newPrivateBinder();
}
@Override
public void requireExplicitBindings() {
binder.requireExplicitBindings();
}
@Override
public void disableCircularProxies() {
binder.disableCircularProxies();
}
@Override
public void requireAtInjectOnConstructors() {
binder.requireAtInjectOnConstructors();
}
@Override
public void requireExactBindingAnnotations() {
binder.requireExactBindingAnnotations();
}
@Override
public void scanModulesForAnnotatedMethods(ModuleAnnotatedMethodScanner scanner) {
binder.scanModulesForAnnotatedMethods(scanner);
}
};
}
}