Updating Multibinder to support injection of Collection<Provider<T>> alongside the usual Set<T>.
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=72818888
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/Multibinder.java b/extensions/multibindings/src/com/google/inject/multibindings/Multibinder.java
index 3ace927..98db1e4 100644
--- a/extensions/multibindings/src/com/google/inject/multibindings/Multibinder.java
+++ b/extensions/multibindings/src/com/google/inject/multibindings/Multibinder.java
@@ -35,6 +35,7 @@
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
+import com.google.inject.Provider;
import com.google.inject.TypeLiteral;
import com.google.inject.binder.LinkedBindingBuilder;
import com.google.inject.internal.Errors;
@@ -43,12 +44,14 @@
import com.google.inject.spi.HasDependencies;
import com.google.inject.spi.Message;
import com.google.inject.spi.ProviderInstanceBinding;
+import com.google.inject.spi.ProviderWithDependencies;
import com.google.inject.spi.ProviderWithExtensionVisitor;
import com.google.inject.spi.Toolable;
import com.google.inject.util.Types;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
+import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -76,6 +79,8 @@
* public SnackMachine(Set<Snack> snacks) { ... }
* }</code></pre>
*
+ * If desired, {@link Collection}{@code <Provider<Snack>>} can also be injected.
+ *
* <p>Contributing multibindings from different modules is supported. For
* example, it is okay for both {@code CandyModule} and {@code ChipsModule}
* to create their own {@code Multibinder<Snack>}, and to each contribute
@@ -117,7 +122,7 @@
public static <T> Multibinder<T> newSetBinder(Binder binder, TypeLiteral<T> type) {
binder = binder.skipSources(RealMultibinder.class, Multibinder.class);
RealMultibinder<T> result = new RealMultibinder<T>(binder, type,
- Key.get(Multibinder.<T>setOf(type)));
+ Key.get(Multibinder.<T>setOf(type)), Key.get(Multibinder.<T>collectionOfProvidersOf(type)));
binder.install(result);
return result;
}
@@ -138,7 +143,8 @@
Binder binder, TypeLiteral<T> type, Annotation annotation) {
binder = binder.skipSources(RealMultibinder.class, Multibinder.class);
RealMultibinder<T> result = new RealMultibinder<T>(binder, type,
- Key.get(Multibinder.<T>setOf(type), annotation));
+ Key.get(Multibinder.<T>setOf(type), annotation),
+ Key.get(Multibinder.<T>collectionOfProvidersOf(type), annotation));
binder.install(result);
return result;
}
@@ -160,7 +166,8 @@
Class<? extends Annotation> annotationType) {
binder = binder.skipSources(RealMultibinder.class, Multibinder.class);
RealMultibinder<T> result = new RealMultibinder<T>(binder, type,
- Key.get(Multibinder.<T>setOf(type), annotationType));
+ Key.get(Multibinder.<T>setOf(type), annotationType),
+ Key.get(Multibinder.<T>collectionOfProvidersOf(type), annotationType));
binder.install(result);
return result;
}
@@ -180,6 +187,14 @@
return (TypeLiteral<Set<T>>) TypeLiteral.get(type);
}
+ @SuppressWarnings("unchecked")
+ static <T> TypeLiteral<Collection<Provider<T>>> collectionOfProvidersOf(
+ TypeLiteral<T> elementType) {
+ Type providerType = Types.providerOf(elementType.getType());
+ Type type = Types.newParameterizedType(Collection.class, providerType);
+ return (TypeLiteral<Collection<Provider<T>>>) TypeLiteral.get(type);
+ }
+
/**
* Configures the bound set to silently discard duplicate elements. When multiple equal values are
* bound, the one that gets included is arbitrary. When multiple modules contribute elements to
@@ -230,6 +245,7 @@
private final TypeLiteral<T> elementType;
private final String setName;
private final Key<Set<T>> setKey;
+ private final Key<Collection<Provider<T>>> collectionOfProvidersKey;
private final Key<Boolean> permitDuplicatesKey;
/* the target injector's binder. non-null until initialization, null afterwards */
@@ -242,10 +258,13 @@
/** whether duplicates are allowed. Possibly configured by a different instance */
private boolean permitDuplicates;
- private RealMultibinder(Binder binder, TypeLiteral<T> elementType, Key<Set<T>> setKey) {
+ private RealMultibinder(Binder binder, TypeLiteral<T> elementType, Key<Set<T>> setKey,
+ Key<Collection<Provider<T>>> collectionOfProvidersKey) {
this.binder = checkNotNull(binder, "binder");
this.elementType = checkNotNull(elementType, "elementType");
this.setKey = checkNotNull(setKey, "setKey");
+ this.collectionOfProvidersKey =
+ checkNotNull(collectionOfProvidersKey, "collectionOfProviders");
this.setName = RealElement.nameOf(setKey);
this.permitDuplicatesKey = Key.get(Boolean.class, named(toString() + " permits duplicates"));
}
@@ -254,10 +273,11 @@
checkConfiguration(!isInitialized(), "Multibinder was already initialized");
binder.bind(setKey).toProvider(this);
+ binder.bind(collectionOfProvidersKey).toProvider(
+ new RealMultibinderCollectionOfProvidersProvider());
}
- @Override
- public Multibinder<T> permitDuplicates() {
+ @Override public Multibinder<T> permitDuplicates() {
binder.install(new PermitDuplicatesModule(permitDuplicatesKey));
return this;
}
@@ -371,7 +391,8 @@
Binding<?> binding = (Binding<?>) element;
return keyMatches(binding.getKey())
|| binding.getKey().equals(permitDuplicatesKey)
- || binding.getKey().equals(setKey);
+ || binding.getKey().equals(setKey)
+ || binding.getKey().equals(collectionOfProvidersKey);
} else {
return false;
}
@@ -397,6 +418,46 @@
@Override public String toString() {
return (setName.isEmpty() ? "" : setName + " ") + "Multibinder<" + elementType + ">";
}
+
+ final class RealMultibinderCollectionOfProvidersProvider
+ implements ProviderWithDependencies<Collection<Provider<T>>> {
+ @Override public Collection<Provider<T>> get() {
+ checkConfiguration(isInitialized(), "Multibinder is not initialized");
+
+ ImmutableList.Builder<Provider<T>> resultBuilder = new ImmutableList.Builder<Provider<T>>();
+ for (Binding<T> binding : bindings) {
+ resultBuilder.add(binding.getProvider());
+ }
+ return resultBuilder.build();
+ }
+
+ @Override public Set<Dependency<?>> getDependencies() {
+ if (!isInitialized()) {
+ return ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Injector.class)));
+ }
+ ImmutableSet.Builder<Dependency<?>> setBuilder = ImmutableSet.builder();
+ for (Dependency<?> dependency : dependencies) {
+ Key key = dependency.getKey();
+ setBuilder.add(
+ Dependency.get(key.ofType(Types.providerOf(key.getTypeLiteral().getType()))));
+ }
+ return setBuilder.build();
+ }
+
+ Key getCollectionKey() {
+ return RealMultibinder.this.collectionOfProvidersKey;
+ }
+
+ @Override public boolean equals(Object o) {
+ return o instanceof Multibinder.RealMultibinder.RealMultibinderCollectionOfProvidersProvider
+ && ((Multibinder.RealMultibinder.RealMultibinderCollectionOfProvidersProvider) o)
+ .getCollectionKey().equals(getCollectionKey());
+ }
+
+ @Override public int hashCode() {
+ return getCollectionKey().hashCode();
+ }
+ }
}
/**
@@ -411,8 +472,7 @@
this.key = key;
}
- @Override
- protected void configure() {
+ @Override protected void configure() {
bind(key).toInstance(true);
}
diff --git a/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java b/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java
index e4144db..91cf076 100644
--- a/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java
+++ b/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java
@@ -58,6 +58,7 @@
import com.google.inject.spi.LinkedKeyBinding;
import com.google.inject.util.Modules;
import com.google.inject.util.Providers;
+import com.google.inject.util.Types;
import junit.framework.TestCase;
@@ -72,6 +73,7 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -90,10 +92,14 @@
new TypeLiteral<Map<String, String>>() {};
final TypeLiteral<Set<String>> setOfString = new TypeLiteral<Set<String>>() {};
final TypeLiteral<Set<Integer>> setOfInteger = new TypeLiteral<Set<Integer>>() {};
+ final TypeLiteral<Collection<Provider<Integer>>> collectionOfProvidersOfIntegers =
+ new TypeLiteral<Collection<Provider<Integer>>>() {};
final TypeLiteral<String> stringType = TypeLiteral.get(String.class);
final TypeLiteral<Integer> intType = TypeLiteral.get(Integer.class);
final TypeLiteral<List<String>> listOfStrings = new TypeLiteral<List<String>>() {};
final TypeLiteral<Set<List<String>>> setOfListOfStrings = new TypeLiteral<Set<List<String>>>() {};
+ final TypeLiteral<Collection<Provider<String>>> collectionOfProvidersOfStrings =
+ new TypeLiteral<Collection<Provider<String>>>() {};
public void testMultibinderAggregatesMultipleModules() {
Module abc = new AbstractModule() {
@@ -114,12 +120,14 @@
Injector injector = Guice.createInjector(abc, de);
Key<Set<String>> setKey = Key.get(setOfString);
+ Key<Collection<Provider<String>>> collectionOfProvidersKey =
+ Key.get(collectionOfProvidersOfStrings);
Set<String> abcde = injector.getInstance(setKey);
Set<String> results = setOf("A", "B", "C", "D", "E");
assertEquals(results, abcde);
- assertSetVisitor(setKey, stringType, setOf(abc, de), BOTH, false, 0, instance("A"),
- instance("B"), instance("C"), instance("D"), instance("E"));
+ assertSetVisitor(setKey, collectionOfProvidersKey, stringType, setOf(abc, de), BOTH, false, 0,
+ instance("A"), instance("B"), instance("C"), instance("D"), instance("E"));
}
public void testMultibinderAggregationForAnnotationInstance() {
@@ -137,11 +145,13 @@
Injector injector = Guice.createInjector(module);
Key<Set<String>> setKey = Key.get(setOfString, Names.named("abc"));
+ Key<Collection<Provider<String>>> collectionOfProvidersKey =
+ Key.get(collectionOfProvidersOfStrings, Names.named("abc"));
Set<String> abc = injector.getInstance(setKey);
Set<String> results = setOf("A", "B", "C");
assertEquals(results, abc);
- assertSetVisitor(setKey, stringType, setOf(module), BOTH, false, 0, instance("A"),
- instance("B"), instance("C"));
+ assertSetVisitor(setKey, collectionOfProvidersKey, stringType, setOf(module), BOTH, false, 0,
+ instance("A"), instance("B"), instance("C"));
}
public void testMultibinderAggregationForAnnotationType() {
@@ -159,11 +169,13 @@
Injector injector = Guice.createInjector(module);
Key<Set<String>> setKey = Key.get(setOfString, Abc.class);
+ Key<Collection<Provider<String>>> collectionOfProvidersKey =
+ Key.get(collectionOfProvidersOfStrings, Abc.class);
Set<String> abcde = injector.getInstance(setKey);
Set<String> results = setOf("A", "B", "C");
assertEquals(results, abcde);
- assertSetVisitor(setKey, stringType, setOf(module), BOTH, false, 0, instance("A"),
- instance("B"), instance("C"));
+ assertSetVisitor(setKey, collectionOfProvidersKey, stringType, setOf(module), BOTH, false, 0,
+ instance("A"), instance("B"), instance("C"));
}
public void testMultibinderWithMultipleAnnotationValueSets() {
@@ -184,16 +196,21 @@
Injector injector = Guice.createInjector(module);
Key<Set<String>> abcSetKey = Key.get(setOfString, named("abc"));
+ Key<Collection<Provider<String>>> abcCollectionOfProvidersKey =
+ Key.get(collectionOfProvidersOfStrings, named("abc"));
Set<String> abc = injector.getInstance(abcSetKey);
Key<Set<String>> deSetKey = Key.get(setOfString, named("de"));
+ Key<Collection<Provider<String>>> deCollectionOfProvidersKey =
+ Key.get(collectionOfProvidersOfStrings, named("de"));
Set<String> de = injector.getInstance(deSetKey);
Set<String> abcResults = setOf("A", "B", "C");
assertEquals(abcResults, abc);
Set<String> deResults = setOf("D", "E");
assertEquals(deResults, de);
- assertSetVisitor(abcSetKey, stringType, setOf(module), BOTH, false, 1, instance("A"),
- instance("B"), instance("C"));
- assertSetVisitor(deSetKey, stringType, setOf(module), BOTH, false, 1, instance("D"), instance("E"));
+ assertSetVisitor(abcSetKey, abcCollectionOfProvidersKey, stringType, setOf(module), BOTH, false,
+ 1, instance("A"), instance("B"), instance("C"));
+ assertSetVisitor(deSetKey, deCollectionOfProvidersKey, stringType, setOf(module), BOTH, false,
+ 1, instance("D"), instance("E"));
}
public void testMultibinderWithMultipleAnnotationTypeSets() {
@@ -214,16 +231,21 @@
Injector injector = Guice.createInjector(module);
Key<Set<String>> abcSetKey = Key.get(setOfString, Abc.class);
+ Key<Collection<Provider<String>>> abcCollectionOfProvidersKey =
+ Key.get(collectionOfProvidersOfStrings, Abc.class);
Set<String> abc = injector.getInstance(abcSetKey);
Key<Set<String>> deSetKey = Key.get(setOfString, De.class);
+ Key<Collection<Provider<String>>> deCollectionOfProvidersKey =
+ Key.get(collectionOfProvidersOfStrings, De.class);
Set<String> de = injector.getInstance(deSetKey);
Set<String> abcResults = setOf("A", "B", "C");
assertEquals(abcResults, abc);
Set<String> deResults = setOf("D", "E");
assertEquals(deResults, de);
- assertSetVisitor(abcSetKey, stringType, setOf(module), BOTH, false, 1, instance("A"),
- instance("B"), instance("C"));
- assertSetVisitor(deSetKey, stringType, setOf(module), BOTH, false, 1, instance("D"), instance("E"));
+ assertSetVisitor(abcSetKey, abcCollectionOfProvidersKey, stringType, setOf(module), BOTH, false,
+ 1, instance("A"), instance("B"), instance("C"));
+ assertSetVisitor(deSetKey, deCollectionOfProvidersKey, stringType, setOf(module), BOTH, false,
+ 1, instance("D"), instance("E"));
}
public void testMultibinderWithMultipleSetTypes() {
@@ -239,8 +261,10 @@
assertEquals(setOf("A"), injector.getInstance(Key.get(setOfString)));
assertEquals(setOf(1), injector.getInstance(Key.get(setOfInteger)));
- assertSetVisitor(Key.get(setOfString), stringType, setOf(module), BOTH, false, 1, instance("A"));
- assertSetVisitor(Key.get(setOfInteger), intType, setOf(module), BOTH, false, 1, instance(1));
+ assertSetVisitor(Key.get(setOfString), Key.get(collectionOfProvidersOfStrings), stringType,
+ setOf(module), BOTH, false, 1, instance("A"));
+ assertSetVisitor(Key.get(setOfInteger), Key.get(collectionOfProvidersOfIntegers), intType,
+ setOf(module), BOTH, false, 1, instance(1));
}
public void testMultibinderWithEmptySet() {
@@ -253,7 +277,8 @@
Set<String> set = injector.getInstance(Key.get(setOfString));
assertEquals(Collections.emptySet(), set);
- assertSetVisitor(Key.get(setOfString), stringType, setOf(module), BOTH, false, 0);
+ assertSetVisitor(Key.get(setOfString), Key.get(collectionOfProvidersOfStrings), stringType,
+ setOf(module), BOTH, false, 0);
}
public void testMultibinderSetIsUnmodifiable() {
@@ -315,7 +340,8 @@
assertEquals(setOf(1), injector.getInstance(Key.get(setOfInteger)));
assertEquals(setOf(2), injector.getInstance(Key.get(setOfInteger)));
assertEquals(setOf(3), injector.getInstance(Key.get(setOfInteger)));
- assertSetVisitor(Key.get(setOfInteger), intType, setOf(module), BOTH, false, 0, providerInstance(1));
+ assertSetVisitor(Key.get(setOfInteger), Key.get(collectionOfProvidersOfIntegers), intType,
+ setOf(module), BOTH, false, 0, providerInstance(1));
}
public void testMultibinderSetForbidsDuplicateElements() {
@@ -344,8 +370,8 @@
}
// But we can still visit the module!
- assertSetVisitor(Key.get(setOfString), stringType, setOf(module1, module2), MODULE, false, 0,
- instance("A"), instance("A"));
+ assertSetVisitor(Key.get(setOfString), Key.get(collectionOfProvidersOfStrings), stringType,
+ setOf(module1, module2), MODULE, false, 0, instance("A"), instance("A"));
}
public void testMultibinderSetShowsBothElementsIfToStringDifferent() {
@@ -390,6 +416,8 @@
TypeLiteral<ValueType> valueType = TypeLiteral.get(ValueType.class);
TypeLiteral<Set<ValueType>> setOfValueType = new TypeLiteral<Set<ValueType>>() {};
+ TypeLiteral<Collection<Provider<ValueType>>> collectionOfProvidersOfValueType =
+ new TypeLiteral<Collection<Provider<ValueType>>>() {};
try {
injector.getInstance(Key.get(setOfValueType));
fail();
@@ -403,8 +431,9 @@
}
// But we can still visit the module!
- assertSetVisitor(Key.get(setOfValueType), valueType, setOf(module1, module2), MODULE, false, 0,
- instance(new ValueType(1, 2)), instance(new ValueType(1, 3)));
+ assertSetVisitor(Key.get(setOfValueType), Key.get(collectionOfProvidersOfValueType), valueType,
+ setOf(module1, module2), MODULE, false, 0, instance(new ValueType(1, 2)),
+ instance(new ValueType(1, 3)));
}
public void testMultibinderSetPermitDuplicateElements() {
@@ -426,8 +455,8 @@
Injector injector = Guice.createInjector(ab, bc);
assertEquals(setOf("A", "B", "C"), injector.getInstance(Key.get(setOfString)));
- assertSetVisitor(Key.get(setOfString), stringType, setOf(ab, bc), BOTH, true, 0,
- instance("A"), instance("B"), instance("C"));
+ assertSetVisitor(Key.get(setOfString), Key.get(collectionOfProvidersOfStrings), stringType,
+ setOf(ab, bc), BOTH, true, 0, instance("A"), instance("B"), instance("C"));
}
public void testMultibinderSetPermitDuplicateCallsToPermitDuplicates() {
@@ -450,8 +479,8 @@
Injector injector = Guice.createInjector(ab, bc);
assertEquals(setOf("A", "B", "C"), injector.getInstance(Key.get(setOfString)));
- assertSetVisitor(Key.get(setOfString), stringType, setOf(ab, bc), BOTH, true, 0,
- instance("A"), instance("B"), instance("C"));
+ assertSetVisitor(Key.get(setOfString), Key.get(collectionOfProvidersOfStrings), stringType,
+ setOf(ab, bc), BOTH, true, 0, instance("A"), instance("B"), instance("C"));
}
public void testMultibinderSetForbidsNullElements() {
@@ -632,8 +661,9 @@
assertEquals(ImmutableSet.of("A", "B", "C", "D", "E", "F"),
injector.getInstance(Key.get(setOfString)));
- assertSetVisitor(Key.get(setOfString), stringType, setOf(abcd, ef), BOTH, false, 0,
- instance("A"), instance("B"), instance("C"), instance("D"), instance("E"), instance("F"));
+ assertSetVisitor(Key.get(setOfString), Key.get(collectionOfProvidersOfStrings), stringType,
+ setOf(abcd, ef), BOTH, false, 0, instance("A"), instance("B"), instance("C"), instance("D"),
+ instance("E"), instance("F"));
}
/**
@@ -671,8 +701,9 @@
assertEquals(ImmutableSet.of("A", "B", "C", "D", "E", "F"),
injector.getInstance(Key.get(setOfString)));
- assertSetVisitor(Key.get(setOfString), stringType, setOf(abcd, ef), BOTH, true, 0,
- instance("A"), instance("B"), instance("C"), instance("D"), instance("E"), instance("F"));
+ assertSetVisitor(Key.get(setOfString), Key.get(collectionOfProvidersOfStrings), stringType,
+ setOf(abcd, ef), BOTH, true, 0, instance("A"), instance("B"), instance("C"), instance("D"),
+ instance("E"), instance("F"));
}
/**
@@ -1117,9 +1148,79 @@
assertTrue(collector.setbinding.containsElement(a));
assertFalse(collector.setbinding.containsElement(b));
assertFalse(collector.setbinding.containsElement(c));
-
+
assertFalse(collector.optionalbinding.containsElement(a));
assertFalse(collector.optionalbinding.containsElement(b));
assertTrue(collector.optionalbinding.containsElement(c));
}
+
+ public void testMultibinderCanInjectCollectionOfProviders() {
+ Module module = new AbstractModule() {
+ protected void configure() {
+ final Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
+ multibinder.addBinding().toProvider(Providers.of("A"));
+ multibinder.addBinding().toProvider(Providers.of("B"));
+ multibinder.addBinding().toInstance("C");
+ }
+ };
+
+ Injector injector = Guice.createInjector(module);
+ injector.getInstance(Key.get(collectionOfProvidersOfStrings));
+ Key<Collection<Provider<String>>> collectionKey = Key.get(collectionOfProvidersOfStrings);
+ Collection<Provider<String>> providers = injector.getInstance(collectionKey);
+ Collection<String> values = Lists.newArrayList();
+ for (Provider<String> provider : providers) {
+ values.add(provider.get());
+ }
+ Collection<String> expectedValues = ImmutableList.of("A", "B", "C");
+ assertEquals(expectedValues, values);
+ }
+
+ public void testMultibinderCanInjectCollectionOfProvidersWithAnnotation() {
+ final Annotation ann = Names.named("foo");
+ Module module = new AbstractModule() {
+ protected void configure() {
+ final Multibinder<String> multibinder =
+ Multibinder.newSetBinder(binder(), String.class, ann);
+ multibinder.addBinding().toProvider(Providers.of("A"));
+ multibinder.addBinding().toProvider(Providers.of("B"));
+ multibinder.addBinding().toInstance("C");
+ }
+ };
+ Injector injector = Guice.createInjector(module);
+ Key<Collection<Provider<String>>> collectionKey = Key.get(collectionOfProvidersOfStrings, ann);
+ Collection<Provider<String>> providers = injector.getInstance(collectionKey);
+ Collection<String> values = Lists.newArrayList();
+ for (Provider<String> provider : providers) {
+ values.add(provider.get());
+ }
+ Collection<String> expectedValues = ImmutableList.of("A", "B", "C");
+ assertEquals(expectedValues, values);
+ }
+
+ public void testMultibindingProviderDependencies() {
+ final Annotation setAnn = Names.named("foo");
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override protected void configure() {
+ Multibinder<String> multibinder =
+ Multibinder.newSetBinder(binder(), String.class, setAnn);
+ multibinder.addBinding().toInstance("a");
+ multibinder.addBinding().toInstance("b");
+ }
+ });
+ HasDependencies providerBinding =
+ (HasDependencies) injector.getBinding(new Key<Collection<Provider<String>>>(setAnn) {});
+ HasDependencies setBinding =
+ (HasDependencies) injector.getBinding(new Key<Set<String>>(setAnn) {});
+ // sanity check the size
+ assertEquals(setBinding.getDependencies().toString(), 2, setBinding.getDependencies().size());
+ Set<Dependency<?>> expected = Sets.newHashSet();
+ for (Dependency<?> dep : setBinding.getDependencies()) {
+ Key key = dep.getKey();
+ Dependency<?> providerDependency =
+ Dependency.get(key.ofType(Types.providerOf(key.getTypeLiteral().getType())));
+ expected.add(providerDependency);
+ }
+ assertEquals(expected, providerBinding.getDependencies());
+ }
}
diff --git a/extensions/multibindings/test/com/google/inject/multibindings/SpiUtils.java b/extensions/multibindings/test/com/google/inject/multibindings/SpiUtils.java
index 8849690..969d26e 100644
--- a/extensions/multibindings/test/com/google/inject/multibindings/SpiUtils.java
+++ b/extensions/multibindings/test/com/google/inject/multibindings/SpiUtils.java
@@ -21,6 +21,7 @@
import static com.google.inject.multibindings.MapBinder.mapOfJavaxProviderOf;
import static com.google.inject.multibindings.MapBinder.mapOfProviderOf;
import static com.google.inject.multibindings.MapBinder.mapOfSetOfProviderOf;
+import static com.google.inject.multibindings.Multibinder.collectionOfProvidersOf;
import static com.google.inject.multibindings.Multibinder.setOf;
import static com.google.inject.multibindings.OptionalBinder.optionalOfJavaxProvider;
import static com.google.inject.multibindings.OptionalBinder.optionalOfProvider;
@@ -32,6 +33,7 @@
import static com.google.inject.multibindings.SpiUtils.VisitType.INJECTOR;
import static com.google.inject.multibindings.SpiUtils.VisitType.MODULE;
import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
@@ -65,6 +67,7 @@
import com.google.inject.spi.ProviderKeyBinding;
import com.google.inject.spi.ProviderLookup;
+import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -254,7 +257,10 @@
Key<?> mapOfSetOfProvider = mapKey.ofType(mapOfSetOfProviderOf(keyType, valueType));
Key<?> mapOfSet = mapKey.ofType(mapOf(keyType, setOf(valueType)));
Key<?> setOfEntry = mapKey.ofType(setOf(entryOfProviderOf(keyType, valueType)));
+ Key<?> collectionOfProvidersOfEntry =
+ mapKey.ofType(collectionOfProvidersOf(entryOfProviderOf(keyType, valueType)));
boolean entrySetMatch = false;
+ boolean entryProviderCollectionMatch = false;
boolean mapProviderMatch = false;
boolean mapSetMatch = false;
boolean mapSetProviderMatch = false;
@@ -324,16 +330,20 @@
if(b != null) {
assertTrue(b.acceptTargetVisitor(visitor) instanceof MultibinderBinding);
}
+ } else if(key.equals(collectionOfProvidersOfEntry)) {
+ matched = true;
+ assertTrue(contains);
+ entryProviderCollectionMatch = true;
}
}
- if(!matched && contains) {
+ if (!matched && contains) {
otherMatches.add(element);
}
}
int otherMatchesSize = otherMatches.size();
- if(allowDuplicates) {
+ if (allowDuplicates) {
otherMatchesSize--; // allow for 1 duplicate binding
}
otherMatchesSize = otherMatchesSize / 3; // value, ProviderLookup per value, Map.Entry per value
@@ -341,6 +351,7 @@
.size() + duplicates, otherMatchesSize);
assertTrue(entrySetMatch);
+ assertTrue(entryProviderCollectionMatch);
assertTrue(mapProviderMatch);
assertEquals(allowDuplicates, mapSetMatch);
assertEquals(allowDuplicates, mapSetProviderMatch);
@@ -356,6 +367,7 @@
*
* @param <T> The type of the binding
* @param setKey The key the set belongs to.
+ * @param collectionOfProvidersKey The key to use for Collections of Providers of Elements.
* @param elementType the TypeLiteral of the element
* @param modules The modules that define the multibindings
* @param visitType The kind of test we should perform. A live Injector, a raw Elements (Module) test, or both.
@@ -363,7 +375,8 @@
* @param expectedMultibindings The number of other multibinders we expect to see.
* @param results The kind of bindings contained in the multibinder.
*/
- static <T> void assertSetVisitor(Key<T> setKey, TypeLiteral<?> elementType,
+ static <T> void assertSetVisitor(Key<Set<T>> setKey,
+ Key<Collection<Provider<T>>> collectionOfProvidersKey, TypeLiteral<?> elementType,
Iterable<? extends Module> modules, VisitType visitType, boolean allowDuplicates,
int expectedMultibindings, BindResult... results) {
if(visitType == null) {
@@ -371,22 +384,26 @@
}
if(visitType == BOTH || visitType == INJECTOR) {
- setInjectorTest(setKey, elementType, modules, allowDuplicates, expectedMultibindings, results);
+ setInjectorTest(setKey, collectionOfProvidersKey, elementType, modules, allowDuplicates,
+ expectedMultibindings, results);
}
if(visitType == BOTH || visitType == MODULE) {
- setModuleTest(setKey, elementType, modules, allowDuplicates, expectedMultibindings, results);
+ setModuleTest(setKey, collectionOfProvidersKey, elementType, modules, allowDuplicates,
+ expectedMultibindings, results);
}
}
@SuppressWarnings("unchecked")
- private static <T> void setInjectorTest(Key<T> setKey, TypeLiteral<?> elementType,
+ private static <T> void setInjectorTest(Key<Set<T>> setKey,
+ Key<Collection<Provider<T>>> collectionOfProvidersKey, TypeLiteral<?> elementType,
Iterable<? extends Module> modules, boolean allowDuplicates, int otherMultibindings,
BindResult... results) {
Injector injector = Guice.createInjector(modules);
- Visitor<T> visitor = new Visitor<T>();
- Binding<T> binding = injector.getBinding(setKey);
- MultibinderBinding<T> multibinder = (MultibinderBinding<T>)binding.acceptTargetVisitor(visitor);
+ Visitor<Set<T>> visitor = new Visitor<Set<T>>();
+ Binding<Set<T>> binding = injector.getBinding(setKey);
+ MultibinderBinding<Set<T>> multibinder =
+ (MultibinderBinding<Set<T>>)binding.acceptTargetVisitor(visitor);
assertNotNull(multibinder);
assertEquals(elementType, multibinder.getElementTypeLiteral());
assertEquals(allowDuplicates, multibinder.permitsDuplicates());
@@ -395,7 +412,7 @@
assertEquals("wrong bind elements, expected: " + bindResults
+ ", but was: " + multibinder.getElements(),
bindResults.size(), elements.size());
-
+
for(BindResult result : bindResults) {
Binding found = null;
for(Binding item : elements) {
@@ -424,8 +441,10 @@
List<Object> otherMultibinders = Lists.newArrayList();
List<Binding> otherContains = Lists.newArrayList();
+ boolean collectionOfProvidersMatch = false;
for(Binding b : injector.getAllBindings().values()) {
boolean contains = multibinder.containsElement(b);
+ Key key = b.getKey();
Object visited = b.acceptTargetVisitor(visitor);
if(visited != null) {
if(visited.equals(multibinder)) {
@@ -435,13 +454,18 @@
}
} else if(setOfElements.contains(b)) {
assertTrue(contains);
- } else if(contains) {
+ } else if (key.equals(collectionOfProvidersKey)) {
+ assertTrue(contains);
+ collectionOfProvidersMatch = true;
+ } else if (contains) {
if (!indexer.isIndexable(b) || !setOfIndexed.contains(b.acceptTargetVisitor(indexer))) {
otherContains.add(b);
}
}
}
-
+
+ assertTrue(collectionOfProvidersMatch);
+
if(allowDuplicates) {
assertEquals("contained more than it should: " + otherContains, 1, otherContains.size());
} else {
@@ -453,16 +477,17 @@
}
@SuppressWarnings("unchecked")
- private static <T> void setModuleTest(Key<T> setKey, TypeLiteral<?> elementType,
+ private static <T> void setModuleTest(Key<Set<T>> setKey,
+ Key<Collection<Provider<T>>> collectionOfProvidersKey, TypeLiteral<?> elementType,
Iterable<? extends Module> modules, boolean allowDuplicates, int otherMultibindings,
BindResult... results) {
List<BindResult> bindResults = Lists.newArrayList(results);
List<Element> elements = Elements.getElements(modules);
Visitor<T> visitor = new Visitor<T>();
- MultibinderBinding<T> multibinder = null;
+ MultibinderBinding<Set<T>> multibinder = null;
for(Element element : elements) {
if(element instanceof Binding && ((Binding)element).getKey().equals(setKey)) {
- multibinder = (MultibinderBinding<T>)((Binding)element).acceptTargetVisitor(visitor);
+ multibinder = (MultibinderBinding<Set<T>>)((Binding)element).acceptTargetVisitor(visitor);
break;
}
}
@@ -475,19 +500,21 @@
int duplicates = 0;
Set<IndexedBinding> setOfIndexed = Sets.newHashSet();
Indexer indexer = new Indexer(null);
+ boolean collectionOfProvidersMatch = false;
for(Element element : elements) {
boolean contains = multibinder.containsElement(element);
if(!contains) {
otherElements.add(element);
}
boolean matched = false;
+ Key key = null;
if(element instanceof Binding) {
Binding binding = (Binding)element;
if (indexer.isIndexable(binding)
&& !setOfIndexed.add((IndexedBinding) binding.acceptTargetVisitor(indexer))) {
duplicates++;
}
-
+ key = binding.getKey();
Object visited = binding.acceptTargetVisitor(visitor);
if(visited != null) {
matched = true;
@@ -498,12 +525,16 @@
}
}
}
-
- if(!matched && contains) {
+
+ if (collectionOfProvidersKey.equals(key)) {
+ assertTrue(contains);
+ assertFalse(matched);
+ collectionOfProvidersMatch = true;
+ } else if (!matched && contains) {
otherContains.add(element);
}
}
-
+
if(allowDuplicates) {
assertEquals("wrong contained elements: " + otherContains,
bindResults.size() + 1 + duplicates, otherContains.size());
@@ -511,10 +542,11 @@
assertEquals("wrong contained elements: " + otherContains,
bindResults.size() + duplicates, otherContains.size());
}
-
+
assertEquals("other multibindings found: " + otherMultibinders, otherMultibindings,
otherMultibinders.size());
-
+ assertTrue(collectionOfProvidersMatch);
+
// Validate that we can construct an injector out of the remaining bindings.
Guice.createInjector(Elements.getModule(otherElements));
}