diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2014-10-04 12:24:51 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2014-10-04 12:24:51 -0400 |
commit | b8c1ca531321dbcee3ae237bad20fa8691b31f83 (patch) | |
tree | 2432ad47f835af34ebdddb2306598f6d7d34c9ff | |
parent | 5a08861fcb8c5bc5831a6b99c192aba0a7933952 (diff) | |
download | sangria-b8c1ca531321dbcee3ae237bad20fa8691b31f83.tar.xz |
contextual: Make ContextSensitiveBinder work with requireExplicitBindings().
Same as regular toProvider() bindings, an explicit binding for the
provider is *not* required, unless to provider itself is injected
somewhere. This is accomplished by generating a unique linked-key
binding for each ContextSensitiveProvider.
3 files changed, 42 insertions, 3 deletions
diff --git a/sangria-contextual/pom.xml b/sangria-contextual/pom.xml index c939076..702616f 100644 --- a/sangria-contextual/pom.xml +++ b/sangria-contextual/pom.xml @@ -38,6 +38,12 @@ </dependency> <dependency> + <groupId>com.tavianator.sangria</groupId> + <artifactId>sangria-test</artifactId> + <scope>test</scope> + </dependency> + + <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> diff --git a/sangria-contextual/src/main/java/com/tavianator/sangria/contextual/ContextSensitiveBinder.java b/sangria-contextual/src/main/java/com/tavianator/sangria/contextual/ContextSensitiveBinder.java index 6d5e502..fdc1ad0 100644 --- a/sangria-contextual/src/main/java/com/tavianator/sangria/contextual/ContextSensitiveBinder.java +++ b/sangria-contextual/src/main/java/com/tavianator/sangria/contextual/ContextSensitiveBinder.java @@ -40,6 +40,7 @@ import com.google.inject.spi.ProviderWithExtensionVisitor; import com.google.inject.spi.ProvisionListener; import com.tavianator.sangria.core.DelayedError; +import com.tavianator.sangria.core.UniqueAnnotations; /** * A binder for {@link ContextSensitiveProvider}s. @@ -139,10 +140,17 @@ public class ContextSensitiveBinder { public void toContextSensitiveProvider(Key<? extends ContextSensitiveProvider<? extends T>> key) { error.cancel(); - binder.bind(bindingKey).toProvider(new ProviderKeyAdapter<>(key)); + binder.bind(bindingKey).toProvider(new ProviderKeyAdapter<>(key, makeLinkedKey(key))); binder.bindListener(new BindingMatcher(bindingKey), new Trigger(bindingKey)); } + private <U> Key<U> makeLinkedKey(Key<U> key) { + Key<U> linkedKey = Key.get(key.getTypeLiteral(), UniqueAnnotations.create()); + binder.bind(linkedKey) + .to(key); + return linkedKey; + } + @Override public void toContextSensitiveProvider(ContextSensitiveProvider<? extends T> provider) { error.cancel(); @@ -190,15 +198,19 @@ public class ContextSensitiveBinder { private static class ProviderKeyAdapter<T> extends ProviderAdapter<T> implements ContextSensitiveProviderKeyBinding<T> { private final Key<? extends ContextSensitiveProvider<? extends T>> providerKey; + private final Key<? extends ContextSensitiveProvider<? extends T>> linkedKey; private Provider<? extends ContextSensitiveProvider<? extends T>> provider; - ProviderKeyAdapter(Key<? extends ContextSensitiveProvider<? extends T>> providerKey) { + ProviderKeyAdapter( + Key<? extends ContextSensitiveProvider<? extends T>> providerKey, + Key<? extends ContextSensitiveProvider<? extends T>> linkedKey) { this.providerKey = providerKey; + this.linkedKey = linkedKey; } @Inject void inject(Injector injector) { - provider = injector.getProvider(providerKey); + provider = injector.getProvider(linkedKey); } @Override diff --git a/sangria-contextual/src/test/java/com/tavianator/sangria/contextual/ContextSensitiveBinderTest.java b/sangria-contextual/src/test/java/com/tavianator/sangria/contextual/ContextSensitiveBinderTest.java index 1e2ab49..68250cb 100644 --- a/sangria-contextual/src/test/java/com/tavianator/sangria/contextual/ContextSensitiveBinderTest.java +++ b/sangria-contextual/src/test/java/com/tavianator/sangria/contextual/ContextSensitiveBinderTest.java @@ -28,6 +28,7 @@ import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.MembersInjector; +import com.google.inject.Module; import com.google.inject.Provider; import com.google.inject.ProvisionException; import com.google.inject.TypeLiteral; @@ -40,6 +41,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import static com.tavianator.sangria.test.SangriaMatchers.*; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; @@ -54,6 +56,10 @@ public class ContextSensitiveBinderTest { public @Rule ExpectedException thrown = ExpectedException.none(); private static class SelfProvider implements ContextSensitiveProvider<String> { + @Inject + SelfProvider() { + } + // For testing getInjectionPoints() in the SPI below @SuppressWarnings("unused") @Inject Injector injector; @@ -191,6 +197,21 @@ public class ContextSensitiveBinderTest { assertThat(hasSelf.selfProvider.get(), equalTo("<unknown>")); } + @Test + public void testBestPractices() { + Module module = new AbstractModule() { + @Override + protected void configure() { + ContextSensitiveBinder.create(binder()) + .bind(String.class) + .annotatedWith(Names.named("self")) + .toContextSensitiveProvider(SelfProvider.class); + } + }; + assertThat(module, is(atomic())); + assertThat(module, followsBestPractices()); + } + private static class RequiredContextProvider implements ContextSensitiveProvider<String> { @Override public String getInContext(InjectionPoint injectionPoint) { |