package org.embulk;
import java.util.ArrayList;
import java.util.List;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import com.google.common.collect.ImmutableList;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
public class GuiceBinder
implements TestRule
{
private final List<Module> baseModules;
private List<Module> extraModules;
private Injector injector;
public GuiceBinder(Module... baseModules)
{
this.baseModules = ImmutableList.copyOf(baseModules);
reset();
}
private void reset()
{
extraModules = new ArrayList<Module>();
injector = null;
}
public synchronized void addModule(Module module)
{
if (injector != null) {
throw new IllegalStateException("Injector is already initialized. Call addModule before getInjector or getInstance");
}
extraModules.add(module);
}
public synchronized Injector getInjector()
{
if (injector == null) {
ImmutableList.Builder<Module> modules = ImmutableList.builder();
modules.addAll(baseModules);
modules.addAll(extraModules);
injector = Guice.createInjector(modules.build());
}
return injector;
}
public <T> T getInstance(Class<T> klass)
{
return getInjector().getInstance(klass);
}
@Override
public Statement apply(Statement base, Description description)
{
return new GuceBinderWatcher().apply(base, description);
}
private class GuceBinderWatcher
extends TestWatcher
{
@Override
protected void starting(Description description)
{
reset();
}
}
}