• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 package com.google.inject.internal;
3 
4 import static com.google.inject.internal.Element.Type.MAPBINDER;
5 import static com.google.inject.internal.Errors.checkConfiguration;
6 import static com.google.inject.internal.Errors.checkNotNull;
7 import static com.google.inject.internal.RealMultibinder.setOf;
8 import static com.google.inject.util.Types.newParameterizedType;
9 import static com.google.inject.util.Types.newParameterizedTypeWithOwner;
10 
11 import com.google.common.base.Objects;
12 import com.google.common.base.Preconditions;
13 import com.google.common.collect.HashMultimap;
14 import com.google.common.collect.ImmutableList;
15 import com.google.common.collect.ImmutableMap;
16 import com.google.common.collect.ImmutableMultimap;
17 import com.google.common.collect.ImmutableSet;
18 import com.google.common.collect.LinkedHashMultimap;
19 import com.google.common.collect.Lists;
20 import com.google.common.collect.Maps;
21 import com.google.common.collect.Multimap;
22 import com.google.common.collect.Sets;
23 import com.google.inject.Binder;
24 import com.google.inject.Binding;
25 import com.google.inject.Injector;
26 import com.google.inject.Key;
27 import com.google.inject.Module;
28 import com.google.inject.Provider;
29 import com.google.inject.TypeLiteral;
30 import com.google.inject.binder.LinkedBindingBuilder;
31 import com.google.inject.internal.InternalProviderInstanceBindingImpl.InitializationTiming;
32 import com.google.inject.multibindings.MapBinderBinding;
33 import com.google.inject.multibindings.Multibinder;
34 import com.google.inject.multibindings.MultibindingsTargetVisitor;
35 import com.google.inject.spi.BindingTargetVisitor;
36 import com.google.inject.spi.Dependency;
37 import com.google.inject.spi.Element;
38 import com.google.inject.spi.ProviderInstanceBinding;
39 import com.google.inject.spi.ProviderWithExtensionVisitor;
40 import com.google.inject.util.Types;
41 import java.lang.annotation.Annotation;
42 import java.util.Collection;
43 import java.util.LinkedHashMap;
44 import java.util.List;
45 import java.util.Map;
46 import java.util.Set;
47 
48 /**
49  * The actual mapbinder plays several roles:
50  *
51  * <p>As a MapBinder, it acts as a factory for LinkedBindingBuilders for each of the map's values.
52  * It delegates to a {@link Multibinder} of entries (keys to value providers).
53  *
54  * <p>As a Module, it installs the binding to the map itself, as well as to a corresponding map
55  * whose values are providers.
56  *
57  * <p>As a module, this implements equals() and hashcode() in order to trick Guice into executing
58  * its configure() method only once. That makes it so that multiple mapbinders can be created for
59  * the same target map, but only one is bound. Since the list of bindings is retrieved from the
60  * injector itself (and not the mapbinder), each mapbinder has access to all contributions from all
61  * equivalent mapbinders.
62  *
63  * <p>Rather than binding a single Map.Entry&lt;K, V&gt;, the map binder binds keys and values
64  * independently. This allows the values to be properly scoped.
65  */
66 public final class RealMapBinder<K, V> implements Module {
67 
68   /**
69    * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a {@link
70    * Map} that is itself bound with no binding annotation.
71    */
newMapRealBinder( Binder binder, TypeLiteral<K> keyType, TypeLiteral<V> valueType)72   public static <K, V> RealMapBinder<K, V> newMapRealBinder(
73       Binder binder, TypeLiteral<K> keyType, TypeLiteral<V> valueType) {
74     binder = binder.skipSources(RealMapBinder.class);
75     return newRealMapBinder(
76         binder,
77         keyType,
78         valueType,
79         Key.get(mapOf(keyType, valueType)),
80         RealMultibinder.newRealSetBinder(binder, Key.get(entryOfProviderOf(keyType, valueType))));
81   }
82 
83   /**
84    * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a {@link
85    * Map} that is itself bound with {@code annotation}.
86    */
newRealMapBinder( Binder binder, TypeLiteral<K> keyType, TypeLiteral<V> valueType, Annotation annotation)87   public static <K, V> RealMapBinder<K, V> newRealMapBinder(
88       Binder binder, TypeLiteral<K> keyType, TypeLiteral<V> valueType, Annotation annotation) {
89     binder = binder.skipSources(RealMapBinder.class);
90     return newRealMapBinder(
91         binder,
92         keyType,
93         valueType,
94         Key.get(mapOf(keyType, valueType), annotation),
95         RealMultibinder.newRealSetBinder(
96             binder, Key.get(entryOfProviderOf(keyType, valueType), annotation)));
97   }
98 
99   /**
100    * Returns a new mapbinder that collects entries of {@code keyType}/{@code valueType} in a {@link
101    * Map} that is itself bound with {@code annotationType}.
102    */
newRealMapBinder( Binder binder, TypeLiteral<K> keyType, TypeLiteral<V> valueType, Class<? extends Annotation> annotationType)103   public static <K, V> RealMapBinder<K, V> newRealMapBinder(
104       Binder binder,
105       TypeLiteral<K> keyType,
106       TypeLiteral<V> valueType,
107       Class<? extends Annotation> annotationType) {
108     binder = binder.skipSources(RealMapBinder.class);
109     return newRealMapBinder(
110         binder,
111         keyType,
112         valueType,
113         Key.get(mapOf(keyType, valueType), annotationType),
114         RealMultibinder.newRealSetBinder(
115             binder, Key.get(entryOfProviderOf(keyType, valueType), annotationType)));
116   }
117 
118   @SuppressWarnings("unchecked") // a map of <K, V> is safely a Map<K, V>
mapOf(TypeLiteral<K> keyType, TypeLiteral<V> valueType)119   static <K, V> TypeLiteral<Map<K, V>> mapOf(TypeLiteral<K> keyType, TypeLiteral<V> valueType) {
120     return (TypeLiteral<Map<K, V>>)
121         TypeLiteral.get(Types.mapOf(keyType.getType(), valueType.getType()));
122   }
123 
124   @SuppressWarnings("unchecked") // a provider map <K, V> is safely a Map<K, Provider<V>>
mapOfProviderOf( TypeLiteral<K> keyType, TypeLiteral<V> valueType)125   static <K, V> TypeLiteral<Map<K, Provider<V>>> mapOfProviderOf(
126       TypeLiteral<K> keyType, TypeLiteral<V> valueType) {
127     return (TypeLiteral<Map<K, Provider<V>>>)
128         TypeLiteral.get(Types.mapOf(keyType.getType(), Types.providerOf(valueType.getType())));
129   }
130 
131   // provider map <K, V> is safely a Map<K, javax.inject.Provider<V>>>
132   @SuppressWarnings("unchecked")
mapOfJavaxProviderOf( TypeLiteral<K> keyType, TypeLiteral<V> valueType)133   static <K, V> TypeLiteral<Map<K, javax.inject.Provider<V>>> mapOfJavaxProviderOf(
134       TypeLiteral<K> keyType, TypeLiteral<V> valueType) {
135     return (TypeLiteral<Map<K, javax.inject.Provider<V>>>)
136         TypeLiteral.get(
137             Types.mapOf(
138                 keyType.getType(),
139                 newParameterizedType(javax.inject.Provider.class, valueType.getType())));
140   }
141 
142   @SuppressWarnings("unchecked") // a provider map <K, Set<V>> is safely a Map<K, Set<Provider<V>>>
mapOfSetOfProviderOf( TypeLiteral<K> keyType, TypeLiteral<V> valueType)143   static <K, V> TypeLiteral<Map<K, Set<Provider<V>>>> mapOfSetOfProviderOf(
144       TypeLiteral<K> keyType, TypeLiteral<V> valueType) {
145     return (TypeLiteral<Map<K, Set<Provider<V>>>>)
146         TypeLiteral.get(
147             Types.mapOf(keyType.getType(), Types.setOf(Types.providerOf(valueType.getType()))));
148   }
149 
150   @SuppressWarnings("unchecked") // a provider map <K, Set<V>> is safely a Map<K, Set<Provider<V>>>
mapOfSetOfJavaxProviderOf( TypeLiteral<K> keyType, TypeLiteral<V> valueType)151   static <K, V> TypeLiteral<Map<K, Set<javax.inject.Provider<V>>>> mapOfSetOfJavaxProviderOf(
152       TypeLiteral<K> keyType, TypeLiteral<V> valueType) {
153     return (TypeLiteral<Map<K, Set<javax.inject.Provider<V>>>>)
154         TypeLiteral.get(
155             Types.mapOf(
156                 keyType.getType(), Types.setOf(Types.javaxProviderOf(valueType.getType()))));
157   }
158 
159   @SuppressWarnings("unchecked") // a provider map <K, Set<V>> is safely a Map<K, Set<Provider<V>>>
mapOfCollectionOfProviderOf( TypeLiteral<K> keyType, TypeLiteral<V> valueType)160   static <K, V> TypeLiteral<Map<K, Collection<Provider<V>>>> mapOfCollectionOfProviderOf(
161       TypeLiteral<K> keyType, TypeLiteral<V> valueType) {
162     return (TypeLiteral<Map<K, Collection<Provider<V>>>>)
163         TypeLiteral.get(
164             Types.mapOf(
165                 keyType.getType(), Types.collectionOf(Types.providerOf(valueType.getType()))));
166   }
167 
168   @SuppressWarnings("unchecked") // a provider map <K, Set<V>> is safely a Map<K, Set<Provider<V>>>
169   static <K, V>
mapOfCollectionOfJavaxProviderOf( TypeLiteral<K> keyType, TypeLiteral<V> valueType)170       TypeLiteral<Map<K, Collection<javax.inject.Provider<V>>>> mapOfCollectionOfJavaxProviderOf(
171           TypeLiteral<K> keyType, TypeLiteral<V> valueType) {
172     return (TypeLiteral<Map<K, Collection<javax.inject.Provider<V>>>>)
173         TypeLiteral.get(
174             Types.mapOf(
175                 keyType.getType(), Types.collectionOf(Types.javaxProviderOf(valueType.getType()))));
176   }
177 
178   @SuppressWarnings("unchecked") // a provider entry <K, V> is safely a Map.Entry<K, Provider<V>>
entryOfProviderOf( TypeLiteral<K> keyType, TypeLiteral<V> valueType)179   static <K, V> TypeLiteral<Map.Entry<K, Provider<V>>> entryOfProviderOf(
180       TypeLiteral<K> keyType, TypeLiteral<V> valueType) {
181     return (TypeLiteral<Map.Entry<K, Provider<V>>>)
182         TypeLiteral.get(
183             newParameterizedTypeWithOwner(
184                 Map.class,
185                 Map.Entry.class,
186                 keyType.getType(),
187                 Types.providerOf(valueType.getType())));
188   }
189 
190   @SuppressWarnings("unchecked") // a provider entry <K, V> is safely a Map.Entry<K, Provider<V>>
entryOfJavaxProviderOf( TypeLiteral<K> keyType, TypeLiteral<V> valueType)191   static <K, V> TypeLiteral<Map.Entry<K, Provider<V>>> entryOfJavaxProviderOf(
192       TypeLiteral<K> keyType, TypeLiteral<V> valueType) {
193     return (TypeLiteral<Map.Entry<K, Provider<V>>>)
194         TypeLiteral.get(
195             newParameterizedTypeWithOwner(
196                 Map.class,
197                 Map.Entry.class,
198                 keyType.getType(),
199                 Types.javaxProviderOf(valueType.getType())));
200   }
201 
202   @SuppressWarnings("unchecked") // a provider entry <K, V> is safely a Map.Entry<K, Provider<V>>
203   static <K, V>
setOfEntryOfJavaxProviderOf( TypeLiteral<K> keyType, TypeLiteral<V> valueType)204       TypeLiteral<Set<Map.Entry<K, javax.inject.Provider<V>>>> setOfEntryOfJavaxProviderOf(
205           TypeLiteral<K> keyType, TypeLiteral<V> valueType) {
206     return (TypeLiteral<Set<Map.Entry<K, javax.inject.Provider<V>>>>)
207         TypeLiteral.get(Types.setOf(entryOfJavaxProviderOf(keyType, valueType).getType()));
208   }
209 
210   /** Given a Key<T> will return a Key<Provider<T>> */
211   @SuppressWarnings("unchecked")
getKeyOfProvider(Key<T> valueKey)212   private static <T> Key<Provider<T>> getKeyOfProvider(Key<T> valueKey) {
213     return (Key<Provider<T>>)
214         valueKey.ofType(Types.providerOf(valueKey.getTypeLiteral().getType()));
215   }
216 
217   // Note: We use valueTypeAndAnnotation effectively as a Pair<TypeLiteral, Annotation|Class>
218   // since it's an easy way to group a type and an optional annotation type or instance.
newRealMapBinder( Binder binder, TypeLiteral<K> keyType, Key<V> valueTypeAndAnnotation)219   static <K, V> RealMapBinder<K, V> newRealMapBinder(
220       Binder binder, TypeLiteral<K> keyType, Key<V> valueTypeAndAnnotation) {
221     binder = binder.skipSources(RealMapBinder.class);
222     TypeLiteral<V> valueType = valueTypeAndAnnotation.getTypeLiteral();
223     return newRealMapBinder(
224         binder,
225         keyType,
226         valueType,
227         valueTypeAndAnnotation.ofType(mapOf(keyType, valueType)),
228         RealMultibinder.newRealSetBinder(
229             binder, valueTypeAndAnnotation.ofType(entryOfProviderOf(keyType, valueType))));
230   }
231 
newRealMapBinder( Binder binder, TypeLiteral<K> keyType, TypeLiteral<V> valueType, Key<Map<K, V>> mapKey, RealMultibinder<Map.Entry<K, Provider<V>>> entrySetBinder)232   private static <K, V> RealMapBinder<K, V> newRealMapBinder(
233       Binder binder,
234       TypeLiteral<K> keyType,
235       TypeLiteral<V> valueType,
236       Key<Map<K, V>> mapKey,
237       RealMultibinder<Map.Entry<K, Provider<V>>> entrySetBinder) {
238     RealMapBinder<K, V> mapBinder =
239         new RealMapBinder<K, V>(binder, keyType, valueType, mapKey, entrySetBinder);
240     binder.install(mapBinder);
241     return mapBinder;
242   }
243 
244   // Until the injector initializes us, we don't know what our dependencies are,
245   // so initialize to the whole Injector.
246   private static final ImmutableSet<Dependency<?>> MODULE_DEPENDENCIES =
247       ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Injector.class)));
248 
249   private final BindingSelection<K, V> bindingSelection;
250   private final Binder binder;
251 
252   private final RealMultibinder<Map.Entry<K, Provider<V>>> entrySetBinder;
253 
RealMapBinder( Binder binder, TypeLiteral<K> keyType, TypeLiteral<V> valueType, Key<Map<K, V>> mapKey, RealMultibinder<Map.Entry<K, Provider<V>>> entrySetBinder)254   private RealMapBinder(
255       Binder binder,
256       TypeLiteral<K> keyType,
257       TypeLiteral<V> valueType,
258       Key<Map<K, V>> mapKey,
259       RealMultibinder<Map.Entry<K, Provider<V>>> entrySetBinder) {
260     this.bindingSelection = new BindingSelection<>(keyType, valueType, mapKey, entrySetBinder);
261     this.binder = binder;
262     this.entrySetBinder = entrySetBinder;
263   }
264 
permitDuplicates()265   public void permitDuplicates() {
266     checkConfiguration(!bindingSelection.isInitialized(), "MapBinder was already initialized");
267     entrySetBinder.permitDuplicates();
268     binder.install(new MultimapBinder<K, V>(bindingSelection));
269   }
270 
271   /** Adds a binding to the map for the given key. */
getKeyForNewValue(K key)272   Key<V> getKeyForNewValue(K key) {
273     checkNotNull(key, "key");
274     checkConfiguration(!bindingSelection.isInitialized(), "MapBinder was already initialized");
275     RealMultibinder<Map.Entry<K, Provider<V>>> entrySetBinder =
276         bindingSelection.getEntrySetBinder();
277 
278     Key<V> valueKey =
279         Key.get(
280             bindingSelection.getValueType(),
281             new RealElement(
282                 entrySetBinder.getSetName(), MAPBINDER, bindingSelection.getKeyType().toString()));
283     entrySetBinder.addBinding().toProvider(new ProviderMapEntry<K, V>(key, valueKey));
284     return valueKey;
285   }
286 
287   /**
288    * This creates two bindings. One for the {@code Map.Entry<K, Provider<V>>} and another for {@code
289    * V}.
290    */
addBinding(K key)291   public LinkedBindingBuilder<V> addBinding(K key) {
292     return binder.bind(getKeyForNewValue(key));
293   }
294 
295   @Override
configure(Binder binder)296   public void configure(Binder binder) {
297     checkConfiguration(!bindingSelection.isInitialized(), "MapBinder was already initialized");
298 
299     // Binds a Map<K, Provider<V>>
300     RealProviderMapProvider<K, V> providerMapProvider =
301         new RealProviderMapProvider<K, V>(bindingSelection);
302     binder.bind(bindingSelection.getProviderMapKey()).toProvider(providerMapProvider);
303 
304     // The map this exposes is internally an ImmutableMap, so it's OK to massage
305     // the guice Provider to javax Provider in the value (since Guice provider
306     // implements javax Provider).
307     @SuppressWarnings({"unchecked", "rawtypes"})
308     Provider<Map<K, javax.inject.Provider<V>>> javaxProviderMapProvider =
309         (Provider) providerMapProvider;
310     binder.bind(bindingSelection.getJavaxProviderMapKey()).toProvider(javaxProviderMapProvider);
311 
312     RealMapProvider<K, V> mapProvider = new RealMapProvider<>(bindingSelection);
313     binder.bind(bindingSelection.getMapKey()).toProvider(mapProvider);
314 
315     // The Map.Entries are all ProviderMapEntry instances which do not allow setValue, so it is
316     // safe to massage the return type like this
317     @SuppressWarnings({"unchecked", "rawtypes"})
318     Key<Set<Map.Entry<K, javax.inject.Provider<V>>>> massagedEntrySetProviderKey =
319         (Key) bindingSelection.getEntrySetBinder().getSetKey();
320     binder.bind(bindingSelection.getEntrySetJavaxProviderKey()).to(massagedEntrySetProviderKey);
321   }
322 
323   @Override
equals(Object o)324   public boolean equals(Object o) {
325     return o instanceof RealMapBinder
326         && ((RealMapBinder<?, ?>) o).bindingSelection.equals(bindingSelection);
327   }
328 
329   @Override
hashCode()330   public int hashCode() {
331     return bindingSelection.hashCode();
332   }
333 
334   /**
335    * The BindingSelection contains some of the core state and logic for the MapBinder.
336    *
337    * <p>It lazily computes the value for keys for various permutations of Maps that are provided by
338    * this module. It also builds up maps from {@code K} to {@code Binding<V>}, which is used by all
339    * of the internal factories to actually provide the desired maps.
340    *
341    * <p>During initialization time there is only one BindingSelection. It is possible that multiple
342    * different BindingSelections are constructed. Specifically, in the case of two different modules
343    * each adding bindings to the same MapBinder. If that happens, we define the BindingSelection
344    * held by the {@link RealMapProvider} to be the authoritative one. The logic for this exists in
345    * {@link RealMultimapBinderProviderWithDependencies}. This is done to avoid confusion because the
346    * BindingSelection contains mutable state.
347    */
348   private static final class BindingSelection<K, V> {
349     private enum InitializationState {
350       UNINITIALIZED,
351       INITIALIZED,
352       HAS_ERRORS;
353     }
354 
355     private final TypeLiteral<K> keyType;
356     private final TypeLiteral<V> valueType;
357     private final Key<Map<K, V>> mapKey;
358 
359     // Lazily computed
360     private Key<Map<K, javax.inject.Provider<V>>> javaxProviderMapKey;
361     private Key<Map<K, Provider<V>>> providerMapKey;
362     private Key<Map<K, Set<V>>> multimapKey;
363     private Key<Map<K, Set<Provider<V>>>> providerSetMultimapKey;
364     private Key<Map<K, Set<javax.inject.Provider<V>>>> javaxProviderSetMultimapKey;
365     private Key<Map<K, Collection<Provider<V>>>> providerCollectionMultimapKey;
366     private Key<Map<K, Collection<javax.inject.Provider<V>>>> javaxProviderCollectionMultimapKey;
367     private Key<Set<Map.Entry<K, javax.inject.Provider<V>>>> entrySetJavaxProviderKey;
368 
369     private final RealMultibinder<Map.Entry<K, Provider<V>>> entrySetBinder;
370 
371     private InitializationState initializationState;
372 
373     /**
374      * These are built during initialization and used by all factories to actually provide the
375      * relevant maps. These contain all of the necessary information about the map binder.
376      */
377     private ImmutableMap<K, Binding<V>> mapBindings;
378 
379     private ImmutableMap<K, Set<Binding<V>>> multimapBindings;
380     private ImmutableList<Map.Entry<K, Binding<V>>> entries;
381 
382     /**
383      * Indicates if this Map permits duplicates. It is initialized during initialization by querying
384      * the injector. This is done because multiple different modules can contribute to a MapBinder,
385      * and any one could set permitDuplicates.
386      */
387     private boolean permitsDuplicates;
388 
BindingSelection( TypeLiteral<K> keyType, TypeLiteral<V> valueType, Key<Map<K, V>> mapKey, RealMultibinder<Map.Entry<K, Provider<V>>> entrySetBinder)389     private BindingSelection(
390         TypeLiteral<K> keyType,
391         TypeLiteral<V> valueType,
392         Key<Map<K, V>> mapKey,
393         RealMultibinder<Map.Entry<K, Provider<V>>> entrySetBinder) {
394       this.keyType = keyType;
395       this.valueType = valueType;
396       this.mapKey = mapKey;
397       this.entrySetBinder = entrySetBinder;
398       this.initializationState = InitializationState.UNINITIALIZED;
399     }
400 
401     /**
402      * Will initialize internal data structures.
403      *
404      * @return {@code true} if initialization was successful, {@code false} if there were errors
405      */
tryInitialize(InjectorImpl injector, Errors errors)406     private boolean tryInitialize(InjectorImpl injector, Errors errors) {
407       // Every one of our providers will call this method, so only execute the logic once.
408       if (initializationState != InitializationState.UNINITIALIZED) {
409         return initializationState != InitializationState.HAS_ERRORS;
410       }
411 
412       // Multiple different modules can all contribute to the same MapBinder, and if any
413       // one of them permits duplicates, then the map binder as a whole will permit duplicates.
414       // Since permitDuplicates() may not have been called on this instance, we need to go
415       // to the injector to see if permitDuplicates was set.
416       permitsDuplicates = entrySetBinder.permitsDuplicates(injector);
417 
418       // We now build the Map<K, Set<Binding<V>>> from the entrySetBinder.
419       // The entrySetBinder contains all of the ProviderMapEntrys, and once
420       // we have those, it's easy to iterate through them to organize them by K.
421       Map<K, ImmutableSet.Builder<Binding<V>>> bindingMultimapMutable =
422           new LinkedHashMap<K, ImmutableSet.Builder<Binding<V>>>();
423       Map<K, Binding<V>> bindingMapMutable = new LinkedHashMap<>();
424       Multimap<K, Indexer.IndexedBinding> index = HashMultimap.create();
425       Indexer indexer = new Indexer(injector);
426       Multimap<K, Binding<V>> duplicates = null;
427 
428       ImmutableList.Builder<Map.Entry<K, Binding<V>>> entriesBuilder = ImmutableList.builder();
429 
430       // We get all of the Bindings that were put into the entrySetBinder
431       for (Binding<Map.Entry<K, Provider<V>>> binding :
432           injector.findBindingsByType(entrySetBinder.getElementTypeLiteral())) {
433         if (entrySetBinder.containsElement(binding)) {
434 
435           // Protected by findBindingByType() and the fact that all providers are added by us
436           // in addBinding(). It would theoretically be possible for someone to directly
437           // add their own binding to the entrySetBinder, but they shouldn't do that.
438           @SuppressWarnings({"unchecked", "rawtypes"})
439           ProviderInstanceBinding<ProviderMapEntry<K, V>> entryBinding =
440               (ProviderInstanceBinding) binding;
441 
442           // We added all these bindings initially, so we know they are ProviderMapEntrys
443           @SuppressWarnings({"unchecked", "rawtypes"})
444           ProviderMapEntry<K, V> entry = (ProviderMapEntry) entryBinding.getUserSuppliedProvider();
445           K key = entry.getKey();
446 
447           Key<V> valueKey = entry.getValueKey();
448           Binding<V> valueBinding = injector.getExistingBinding(valueKey);
449 
450           // Use the indexer to de-dupe user bindings. This is needed because of the
451           // uniqueId in RealElement. The uniqueId intentionally circumvents the regular
452           // Guice deduplication, so we need to re-implement our own here, ignoring
453           // uniqueId.
454           if (index.put(key, valueBinding.acceptTargetVisitor(indexer))) {
455 
456             entriesBuilder.add(Maps.immutableEntry(key, valueBinding));
457 
458             Binding<V> previous = bindingMapMutable.put(key, valueBinding);
459             // Check if this is a duplicate binding
460             if (previous != null && !permitsDuplicates) {
461               if (duplicates == null) {
462                 // This is linked for both keys and values to maintain order
463                 duplicates = LinkedHashMultimap.create();
464               }
465 
466               // We add both the previous and the current value to the duplicates map.
467               // This is because if there are three duplicates, we will only execute this code
468               // for the second and third, but we want all three values to display a helpful
469               // error message. We rely on the multimap to dedupe repeated values.
470               duplicates.put(key, previous);
471               duplicates.put(key, valueBinding);
472             }
473 
474             // Don't do extra work unless we need to
475             if (permitsDuplicates) {
476               // Create a set builder for this key if it's the first time we've seen it
477               if (!bindingMultimapMutable.containsKey(key)) {
478                 bindingMultimapMutable.put(key, ImmutableSet.<Binding<V>>builder());
479               }
480 
481               // Add the Binding<V>
482               bindingMultimapMutable.get(key).add(valueBinding);
483             }
484           }
485         }
486       }
487 
488       // It is safe to check if duplicates is non-null because if duplicates are allowed,
489       // we don't build up this data structure
490       if (duplicates != null) {
491         initializationState = InitializationState.HAS_ERRORS;
492         reportDuplicateKeysError(duplicates, errors);
493 
494         return false;
495       }
496 
497       // Build all of the ImmutableSet.Builders,
498       // transforming from Map<K, ImmutableSet.Builder<Binding<V>>> to
499       // ImmutableMap<K, Set<Binding<V>>>
500       ImmutableMap.Builder<K, Set<Binding<V>>> bindingsMultimapBuilder = ImmutableMap.builder();
501       for (Map.Entry<K, ImmutableSet.Builder<Binding<V>>> entry :
502           bindingMultimapMutable.entrySet()) {
503         bindingsMultimapBuilder.put(entry.getKey(), entry.getValue().build());
504       }
505       mapBindings = ImmutableMap.copyOf(bindingMapMutable);
506       multimapBindings = bindingsMultimapBuilder.build();
507 
508       entries = entriesBuilder.build();
509 
510       initializationState = InitializationState.INITIALIZED;
511 
512       return true;
513     }
514 
reportDuplicateKeysError( Multimap<K, Binding<V>> duplicates, Errors errors)515     private static <K, V> void reportDuplicateKeysError(
516         Multimap<K, Binding<V>> duplicates, Errors errors) {
517       StringBuilder sb = new StringBuilder("Map injection failed due to duplicated key ");
518       boolean first = true;
519       for (Map.Entry<K, Collection<Binding<V>>> entry : duplicates.asMap().entrySet()) {
520         K dupKey = entry.getKey();
521 
522         if (first) {
523           first = false;
524           sb.append("\"" + dupKey + "\", from bindings:\n");
525         } else {
526           sb.append("\n and key: \"" + dupKey + "\", from bindings:\n");
527         }
528 
529         for (Binding<V> dup : entry.getValue()) {
530           sb.append("\t at " + Errors.convert(dup.getSource()) + "\n");
531         }
532       }
533 
534       // TODO(user): Add a different error for every duplicated key
535       errors.addMessage(sb.toString());
536     }
537 
containsElement(Element element)538     private boolean containsElement(Element element) {
539       if (entrySetBinder.containsElement(element)) {
540         return true;
541       }
542 
543       Key<?> key;
544       if (element instanceof Binding) {
545         key = ((Binding<?>) element).getKey();
546       } else {
547         return false; // cannot match;
548       }
549 
550       return key.equals(getMapKey())
551           || key.equals(getProviderMapKey())
552           || key.equals(getJavaxProviderMapKey())
553           || key.equals(getMultimapKey())
554           || key.equals(getProviderSetMultimapKey())
555           || key.equals(getJavaxProviderSetMultimapKey())
556           || key.equals(getProviderCollectionMultimapKey())
557           || key.equals(getJavaxProviderCollectionMultimapKey())
558           || key.equals(entrySetBinder.getSetKey())
559           || key.equals(getEntrySetJavaxProviderKey())
560           || matchesValueKey(key);
561     }
562 
563     /** Returns true if the key indicates this is a value in the map. */
matchesValueKey(Key<?> key)564     private boolean matchesValueKey(Key<?> key) {
565       return key.getAnnotation() instanceof RealElement
566           && ((RealElement) key.getAnnotation()).setName().equals(entrySetBinder.getSetName())
567           && ((RealElement) key.getAnnotation()).type() == MAPBINDER
568           && ((RealElement) key.getAnnotation()).keyType().equals(keyType.toString())
569           && key.getTypeLiteral().equals(valueType);
570     }
571 
getProviderMapKey()572     private Key<Map<K, Provider<V>>> getProviderMapKey() {
573       Key<Map<K, Provider<V>>> local = providerMapKey;
574       if (local == null) {
575         local = providerMapKey = mapKey.ofType(mapOfProviderOf(keyType, valueType));
576       }
577       return local;
578     }
579 
getJavaxProviderMapKey()580     private Key<Map<K, javax.inject.Provider<V>>> getJavaxProviderMapKey() {
581       Key<Map<K, javax.inject.Provider<V>>> local = javaxProviderMapKey;
582       if (local == null) {
583         local = javaxProviderMapKey = mapKey.ofType(mapOfJavaxProviderOf(keyType, valueType));
584       }
585       return local;
586     }
587 
getMultimapKey()588     private Key<Map<K, Set<V>>> getMultimapKey() {
589       Key<Map<K, Set<V>>> local = multimapKey;
590       if (local == null) {
591         local = multimapKey = mapKey.ofType(mapOf(keyType, setOf(valueType)));
592       }
593       return local;
594     }
595 
getProviderSetMultimapKey()596     private Key<Map<K, Set<Provider<V>>>> getProviderSetMultimapKey() {
597       Key<Map<K, Set<Provider<V>>>> local = providerSetMultimapKey;
598       if (local == null) {
599         local = providerSetMultimapKey = mapKey.ofType(mapOfSetOfProviderOf(keyType, valueType));
600       }
601       return local;
602     }
603 
getJavaxProviderSetMultimapKey()604     private Key<Map<K, Set<javax.inject.Provider<V>>>> getJavaxProviderSetMultimapKey() {
605       Key<Map<K, Set<javax.inject.Provider<V>>>> local = javaxProviderSetMultimapKey;
606       if (local == null) {
607         local =
608             javaxProviderSetMultimapKey =
609                 mapKey.ofType(mapOfSetOfJavaxProviderOf(keyType, valueType));
610       }
611       return local;
612     }
613 
getProviderCollectionMultimapKey()614     private Key<Map<K, Collection<Provider<V>>>> getProviderCollectionMultimapKey() {
615       Key<Map<K, Collection<Provider<V>>>> local = providerCollectionMultimapKey;
616       if (local == null) {
617         local =
618             providerCollectionMultimapKey =
619                 mapKey.ofType(mapOfCollectionOfProviderOf(keyType, valueType));
620       }
621       return local;
622     }
623 
624     private Key<Map<K, Collection<javax.inject.Provider<V>>>>
getJavaxProviderCollectionMultimapKey()625         getJavaxProviderCollectionMultimapKey() {
626       Key<Map<K, Collection<javax.inject.Provider<V>>>> local = javaxProviderCollectionMultimapKey;
627       if (local == null) {
628         local =
629             javaxProviderCollectionMultimapKey =
630                 mapKey.ofType(mapOfCollectionOfJavaxProviderOf(keyType, valueType));
631       }
632       return local;
633     }
634 
getEntrySetJavaxProviderKey()635     private Key<Set<Map.Entry<K, javax.inject.Provider<V>>>> getEntrySetJavaxProviderKey() {
636       Key<Set<Map.Entry<K, javax.inject.Provider<V>>>> local = entrySetJavaxProviderKey;
637       if (local == null) {
638         local =
639             entrySetJavaxProviderKey =
640                 mapKey.ofType(setOfEntryOfJavaxProviderOf(keyType, valueType));
641       }
642       return local;
643     }
644 
getMapBindings()645     private ImmutableMap<K, Binding<V>> getMapBindings() {
646       checkConfiguration(isInitialized(), "MapBinder has not yet been initialized");
647       return mapBindings;
648     }
649 
getMultimapBindings()650     private ImmutableMap<K, Set<Binding<V>>> getMultimapBindings() {
651       checkConfiguration(isInitialized(), "MapBinder has not yet been initialized");
652       return multimapBindings;
653     }
654 
getEntries()655     private ImmutableList<Map.Entry<K, Binding<V>>> getEntries() {
656       checkConfiguration(isInitialized(), "MapBinder has not yet been initialized");
657       return entries;
658     }
659 
isInitialized()660     private boolean isInitialized() {
661       return initializationState == InitializationState.INITIALIZED;
662     }
663 
getKeyType()664     private TypeLiteral<K> getKeyType() {
665       return keyType;
666     }
667 
getValueType()668     private TypeLiteral<V> getValueType() {
669       return valueType;
670     }
671 
getMapKey()672     private Key<Map<K, V>> getMapKey() {
673       return mapKey;
674     }
675 
getEntrySetBinder()676     private RealMultibinder<Map.Entry<K, Provider<V>>> getEntrySetBinder() {
677       return entrySetBinder;
678     }
679 
permitsDuplicates()680     private boolean permitsDuplicates() {
681       if (isInitialized()) {
682         return permitsDuplicates;
683       } else {
684         throw new UnsupportedOperationException(
685             "permitsDuplicates() not supported for module bindings");
686       }
687     }
688 
689     @Override
equals(Object o)690     public boolean equals(Object o) {
691       return o instanceof BindingSelection && ((BindingSelection<?, ?>) o).mapKey.equals(mapKey);
692     }
693 
694     @Override
hashCode()695     public int hashCode() {
696       return mapKey.hashCode();
697     }
698   }
699 
700   private static final class RealProviderMapProvider<K, V>
701       extends RealMapBinderProviderWithDependencies<K, V, Map<K, Provider<V>>> {
702     private Map<K, Provider<V>> mapOfProviders;
703     private Set<Dependency<?>> dependencies = RealMapBinder.MODULE_DEPENDENCIES;
704 
RealProviderMapProvider(BindingSelection<K, V> bindingSelection)705     private RealProviderMapProvider(BindingSelection<K, V> bindingSelection) {
706       super(bindingSelection);
707     }
708 
709     @Override
getDependencies()710     public Set<Dependency<?>> getDependencies() {
711       return dependencies;
712     }
713 
714     @Override
doInitialize(InjectorImpl injector, Errors errors)715     protected void doInitialize(InjectorImpl injector, Errors errors) {
716       ImmutableMap.Builder<K, Provider<V>> mapOfProvidersBuilder = ImmutableMap.builder();
717       ImmutableSet.Builder<Dependency<?>> dependenciesBuilder = ImmutableSet.builder();
718       for (Map.Entry<K, Binding<V>> entry : bindingSelection.getMapBindings().entrySet()) {
719         mapOfProvidersBuilder.put(entry.getKey(), entry.getValue().getProvider());
720         dependenciesBuilder.add(Dependency.get(getKeyOfProvider(entry.getValue().getKey())));
721       }
722 
723       mapOfProviders = mapOfProvidersBuilder.build();
724       dependencies = dependenciesBuilder.build();
725     }
726 
727     @Override
doProvision(InternalContext context, Dependency<?> dependency)728     protected Map<K, Provider<V>> doProvision(InternalContext context, Dependency<?> dependency) {
729       return mapOfProviders;
730     }
731   }
732 
733   private static final class RealMapProvider<K, V>
734       extends RealMapBinderProviderWithDependencies<K, V, Map<K, V>>
735       implements ProviderWithExtensionVisitor<Map<K, V>>, MapBinderBinding<Map<K, V>> {
736     private Set<Dependency<?>> dependencies = RealMapBinder.MODULE_DEPENDENCIES;
737 
738     /**
739      * An array of all the injectors.
740      *
741      * <p>This is parallel to array of keys below
742      */
743     private SingleParameterInjector<V>[] injectors;
744 
745     private K[] keys;
746 
RealMapProvider(BindingSelection<K, V> bindingSelection)747     private RealMapProvider(BindingSelection<K, V> bindingSelection) {
748       super(bindingSelection);
749     }
750 
getBindingSelection()751     private BindingSelection<K, V> getBindingSelection() {
752       return bindingSelection;
753     }
754 
755     @Override
doInitialize(InjectorImpl injector, Errors errors)756     protected void doInitialize(InjectorImpl injector, Errors errors) throws ErrorsException {
757       @SuppressWarnings("unchecked")
758       K[] keysArray = (K[]) new Object[bindingSelection.getMapBindings().size()];
759       keys = keysArray;
760       ImmutableSet.Builder<Dependency<?>> dependenciesBuilder = ImmutableSet.builder();
761       int i = 0;
762       for (Map.Entry<K, Binding<V>> entry : bindingSelection.getMapBindings().entrySet()) {
763         dependenciesBuilder.add(Dependency.get(entry.getValue().getKey()));
764         keys[i] = entry.getKey();
765         i++;
766       }
767 
768       ImmutableSet<Dependency<?>> localDependencies = dependenciesBuilder.build();
769       dependencies = localDependencies;
770 
771       List<Dependency<?>> dependenciesList = localDependencies.asList();
772 
773       // We know the type because we built up our own sets of dependencies, it's just
774       // that the interface uses a "?" generic
775       @SuppressWarnings("unchecked")
776       SingleParameterInjector<V>[] typedInjectors =
777           (SingleParameterInjector<V>[]) injector.getParametersInjectors(dependenciesList, errors);
778       injectors = typedInjectors;
779     }
780 
781     @Override
doProvision(InternalContext context, Dependency<?> dependency)782     protected Map<K, V> doProvision(InternalContext context, Dependency<?> dependency)
783         throws InternalProvisionException {
784       SingleParameterInjector<V>[] localInjectors = injectors;
785       if (localInjectors == null) {
786         // if injectors == null, then we have no bindings so return the empty map.
787         return ImmutableMap.of();
788       }
789 
790       ImmutableMap.Builder<K, V> resultBuilder = ImmutableMap.builder();
791       K[] localKeys = keys;
792       for (int i = 0; i < localInjectors.length; i++) {
793         SingleParameterInjector<V> injector = localInjectors[i];
794         K key = localKeys[i];
795 
796         V value = injector.inject(context);
797 
798         if (value == null) {
799           throw createNullValueException(key, bindingSelection.getMapBindings().get(key));
800         }
801 
802         resultBuilder.put(key, value);
803       }
804 
805       return resultBuilder.build();
806     }
807 
808     @Override
getDependencies()809     public Set<Dependency<?>> getDependencies() {
810       return dependencies;
811     }
812 
813     @Override
814     @SuppressWarnings("unchecked")
acceptExtensionVisitor( BindingTargetVisitor<B, W> visitor, ProviderInstanceBinding<? extends B> binding)815     public <B, W> W acceptExtensionVisitor(
816         BindingTargetVisitor<B, W> visitor, ProviderInstanceBinding<? extends B> binding) {
817       if (visitor instanceof MultibindingsTargetVisitor) {
818         return ((MultibindingsTargetVisitor<Map<K, V>, W>) visitor).visit(this);
819       } else {
820         return visitor.visit(binding);
821       }
822     }
823 
824     @Override
getMapKey()825     public Key<Map<K, V>> getMapKey() {
826       return bindingSelection.getMapKey();
827     }
828 
829     @Override
getKeyTypeLiteral()830     public TypeLiteral<K> getKeyTypeLiteral() {
831       return bindingSelection.getKeyType();
832     }
833 
834     @Override
getValueTypeLiteral()835     public TypeLiteral<V> getValueTypeLiteral() {
836       return bindingSelection.getValueType();
837     }
838 
839     @Override
840     @SuppressWarnings("unchecked")
getEntries()841     public List<Map.Entry<?, Binding<?>>> getEntries() {
842       if (bindingSelection.isInitialized()) {
843         return (List<Map.Entry<?, Binding<?>>>) (List<?>) bindingSelection.getEntries();
844       } else {
845         throw new UnsupportedOperationException("getEntries() not supported for module bindings");
846       }
847     }
848 
849     @Override
getEntries(Iterable<? extends Element> elements)850     public List<Map.Entry<?, Binding<?>>> getEntries(Iterable<? extends Element> elements) {
851       // Iterate over the elements, building up the below maps
852       // This is a preprocessing step allowing us to only iterate over elements
853       // once and have O(n) runtime
854       ImmutableMultimap.Builder<K, Key<V>> keyToValueKeyBuilder = ImmutableMultimap.builder();
855       ImmutableMap.Builder<Key<V>, Binding<V>> valueKeyToBindingBuilder = ImmutableMap.builder();
856       ImmutableMap.Builder<Key<V>, K> valueKeyToKeyBuilder = ImmutableMap.builder();
857       ImmutableMap.Builder<Key<V>, Binding<Map.Entry<K, Provider<V>>>>
858           valueKeyToEntryBindingBuilder = ImmutableMap.builder();
859       for (Element element : elements) {
860         if (element instanceof Binding) {
861           Binding<?> binding = (Binding<?>) element;
862           if (bindingSelection.matchesValueKey(binding.getKey())
863               && binding.getKey().getTypeLiteral().equals(bindingSelection.valueType)) {
864             // Safe because of the check on the type literal above
865             @SuppressWarnings("unchecked")
866             Binding<V> typedBinding = (Binding<V>) binding;
867             Key<V> typedKey = typedBinding.getKey();
868             valueKeyToBindingBuilder.put(typedKey, typedBinding);
869           }
870         }
871 
872         if (element instanceof ProviderInstanceBinding
873             && bindingSelection.getEntrySetBinder().containsElement(element)) {
874           // Safe because of the instanceof check, and containsElement() check
875           @SuppressWarnings({"unchecked", "rawtypes"})
876           ProviderInstanceBinding<Map.Entry<K, Provider<V>>> entryBinding =
877               (ProviderInstanceBinding) element;
878 
879           // Safe because of the check for containsElement() above
880           @SuppressWarnings("unchecked")
881           Provider<Map.Entry<K, Provider<V>>> typedProvider =
882               (Provider<Map.Entry<K, Provider<V>>>) entryBinding.getUserSuppliedProvider();
883           Provider<Map.Entry<K, Provider<V>>> userSuppliedProvider = typedProvider;
884 
885           if (userSuppliedProvider instanceof ProviderMapEntry) {
886             // Safe because of the instanceof check
887             @SuppressWarnings("unchecked")
888             ProviderMapEntry<K, V> typedUserSuppliedProvider =
889                 (ProviderMapEntry<K, V>) userSuppliedProvider;
890             ProviderMapEntry<K, V> entry = typedUserSuppliedProvider;
891 
892             keyToValueKeyBuilder.put(entry.getKey(), entry.getValueKey());
893             valueKeyToEntryBindingBuilder.put(entry.getValueKey(), entryBinding);
894             valueKeyToKeyBuilder.put(entry.getValueKey(), entry.getKey());
895           }
896         }
897       }
898 
899       ImmutableMultimap<K, Key<V>> keyToValueKey = keyToValueKeyBuilder.build();
900       ImmutableMap<Key<V>, K> valueKeyToKey = valueKeyToKeyBuilder.build();
901       ImmutableMap<Key<V>, Binding<V>> valueKeyToBinding = valueKeyToBindingBuilder.build();
902       ImmutableMap<Key<V>, Binding<Map.Entry<K, Provider<V>>>> valueKeyToEntryBinding =
903           valueKeyToEntryBindingBuilder.build();
904 
905       // Check that there is a 1:1 mapping from keys from the ProviderMapEntrys to the
906       // keys from the Bindings.
907       Set<Key<V>> keysFromProviderMapEntrys = Sets.newHashSet(keyToValueKey.values());
908       Set<Key<V>> keysFromBindings = valueKeyToBinding.keySet();
909 
910       if (!keysFromProviderMapEntrys.equals(keysFromBindings)) {
911         Set<Key<V>> keysOnlyFromProviderMapEntrys =
912             Sets.difference(keysFromProviderMapEntrys, keysFromBindings);
913         Set<Key<V>> keysOnlyFromBindings =
914             Sets.difference(keysFromBindings, keysFromProviderMapEntrys);
915 
916         StringBuilder sb = new StringBuilder("Expected a 1:1 mapping from map keys to values.");
917 
918         if (!keysOnlyFromBindings.isEmpty()) {
919           sb.append(
920               Errors.format("%nFound these Bindings that were missing an associated entry:%n"));
921           for (Key<V> key : keysOnlyFromBindings) {
922             sb.append(
923                 Errors.format("  %s bound at: %s%n", key, valueKeyToBinding.get(key).getSource()));
924           }
925         }
926 
927         if (!keysOnlyFromProviderMapEntrys.isEmpty()) {
928           sb.append(Errors.format("%nFound these map keys without a corresponding value:%n"));
929           for (Key<V> key : keysOnlyFromProviderMapEntrys) {
930             sb.append(
931                 Errors.format(
932                     "  '%s' bound at: %s%n",
933                     valueKeyToKey.get(key), valueKeyToEntryBinding.get(key).getSource()));
934           }
935         }
936 
937         throw new IllegalArgumentException(sb.toString());
938       }
939 
940       // Now that we have the two maps, generate the result map
941       ImmutableList.Builder<Map.Entry<?, Binding<?>>> resultBuilder = ImmutableList.builder();
942       for (Map.Entry<K, Key<V>> entry : keyToValueKey.entries()) {
943         Binding<?> binding = valueKeyToBinding.get(entry.getValue());
944         // No null check for binding needed because of the above check to make sure all the
945         // values in keyToValueKey are present as keys in valueKeyToBinding
946 
947         @SuppressWarnings({"unchecked", "rawtypes"})
948         Map.Entry<?, Binding<?>> newEntry =
949             (Map.Entry) Maps.immutableEntry(entry.getKey(), binding);
950         resultBuilder.add(newEntry);
951       }
952       return resultBuilder.build();
953     }
954 
955     @Override
permitsDuplicates()956     public boolean permitsDuplicates() {
957       if (bindingSelection.isInitialized()) {
958         return bindingSelection.permitsDuplicates();
959       } else {
960         throw new UnsupportedOperationException(
961             "permitsDuplicates() not supported for module bindings");
962       }
963     }
964 
965     @Override
containsElement(Element element)966     public boolean containsElement(Element element) {
967       return bindingSelection.containsElement(element);
968     }
969   }
970 
971   /**
972    * Binds {@code Map<K, Set<V>>} and {{@code Map<K, Set<Provider<V>>>}.
973    *
974    * <p>This will only exist if permitDuplicates() is called.
975    */
976   private static final class MultimapBinder<K, V> implements Module {
977     private final BindingSelection<K, V> bindingSelection;
978 
MultimapBinder(BindingSelection<K, V> bindingSelection)979     private MultimapBinder(BindingSelection<K, V> bindingSelection) {
980       this.bindingSelection = bindingSelection;
981     }
982 
983     @Override
configure(Binder binder)984     public void configure(Binder binder) {
985       // Binds a Map<K, Set<Provider<V>>>
986       Provider<Map<K, Set<Provider<V>>>> multimapProvider =
987           new RealProviderMultimapProvider<K, V>(bindingSelection.getMapKey());
988       binder.bind(bindingSelection.getProviderSetMultimapKey()).toProvider(multimapProvider);
989 
990       // Provide links from a few different public keys to the providerMultimapKey.
991       // The collection this exposes is internally an ImmutableMap, so it's OK to massage
992       // the guice Provider to javax Provider in the value (since the guice Provider implements
993       // javax Provider).
994       @SuppressWarnings({"unchecked", "rawtypes"})
995       Provider<Map<K, Set<javax.inject.Provider<V>>>> javaxProvider = (Provider) multimapProvider;
996       binder.bind(bindingSelection.getJavaxProviderSetMultimapKey()).toProvider(javaxProvider);
997 
998       @SuppressWarnings({"unchecked", "rawtypes"})
999       Provider<Map<K, Collection<Provider<V>>>> collectionProvider = (Provider) multimapProvider;
1000       binder
1001           .bind(bindingSelection.getProviderCollectionMultimapKey())
1002           .toProvider(collectionProvider);
1003 
1004       @SuppressWarnings({"unchecked", "rawtypes"})
1005       Provider<Map<K, Collection<javax.inject.Provider<V>>>> collectionJavaxProvider =
1006           (Provider) multimapProvider;
1007       binder
1008           .bind(bindingSelection.getJavaxProviderCollectionMultimapKey())
1009           .toProvider(collectionJavaxProvider);
1010 
1011       // Binds a Map<K, Set<V>>
1012       @SuppressWarnings({"unchecked", "rawtypes"})
1013       Provider<Map<K, Set<V>>> realMultimapProvider =
1014           new RealMultimapProvider(bindingSelection.getMapKey());
1015       binder.bind(bindingSelection.getMultimapKey()).toProvider(realMultimapProvider);
1016     }
1017 
1018     @Override
hashCode()1019     public int hashCode() {
1020       return bindingSelection.hashCode();
1021     }
1022 
1023     @Override
equals(Object o)1024     public boolean equals(Object o) {
1025       return o instanceof MultimapBinder
1026           && ((MultimapBinder<?, ?>) o).bindingSelection.equals(bindingSelection);
1027     }
1028 
1029     private static final class RealProviderMultimapProvider<K, V>
1030         extends RealMultimapBinderProviderWithDependencies<K, V, Map<K, Set<Provider<V>>>> {
1031       private Map<K, Set<Provider<V>>> multimapOfProviders;
1032       private Set<Dependency<?>> dependencies = RealMapBinder.MODULE_DEPENDENCIES;
1033 
RealProviderMultimapProvider(Key<Map<K, V>> mapKey)1034       private RealProviderMultimapProvider(Key<Map<K, V>> mapKey) {
1035         super(mapKey);
1036       }
1037 
1038       @Override
getDependencies()1039       public Set<Dependency<?>> getDependencies() {
1040         return dependencies;
1041       }
1042 
1043       @Override
doInitialize(InjectorImpl injector, Errors errors)1044       protected void doInitialize(InjectorImpl injector, Errors errors) {
1045         ImmutableMap.Builder<K, Set<Provider<V>>> multimapOfProvidersBuilder =
1046             ImmutableMap.builder();
1047         ImmutableSet.Builder<Dependency<?>> dependenciesBuilder = ImmutableSet.builder();
1048         for (Map.Entry<K, Set<Binding<V>>> entry :
1049             bindingSelection.getMultimapBindings().entrySet()) {
1050           ImmutableSet.Builder<Provider<V>> providersBuilder = ImmutableSet.builder();
1051           for (Binding<V> binding : entry.getValue()) {
1052             providersBuilder.add(binding.getProvider());
1053             dependenciesBuilder.add(Dependency.get(getKeyOfProvider(binding.getKey())));
1054           }
1055 
1056           multimapOfProvidersBuilder.put(entry.getKey(), providersBuilder.build());
1057         }
1058         multimapOfProviders = multimapOfProvidersBuilder.build();
1059         dependencies = dependenciesBuilder.build();
1060       }
1061 
1062       @Override
doProvision( InternalContext context, Dependency<?> dependency)1063       protected Map<K, Set<Provider<V>>> doProvision(
1064           InternalContext context, Dependency<?> dependency) {
1065         return multimapOfProviders;
1066       }
1067     }
1068 
1069     private static final class RealMultimapProvider<K, V>
1070         extends RealMultimapBinderProviderWithDependencies<K, V, Map<K, Set<V>>> {
1071 
1072       /**
1073        * A simple class to hold a key and the associated bindings as an array.
1074        *
1075        * <p>Arrays are used for performance.
1076        */
1077       private static final class PerKeyData<K, V> {
1078         private final K key;
1079         private final Binding<V>[] bindings;
1080         private final SingleParameterInjector<V>[] injectors;
1081 
PerKeyData(K key, Binding<V>[] bindings, SingleParameterInjector<V>[] injectors)1082         private PerKeyData(K key, Binding<V>[] bindings, SingleParameterInjector<V>[] injectors) {
1083           Preconditions.checkArgument(bindings.length == injectors.length);
1084 
1085           this.key = key;
1086           this.bindings = bindings;
1087           this.injectors = injectors;
1088         }
1089       }
1090 
1091       private Set<Dependency<?>> dependencies = RealMapBinder.MODULE_DEPENDENCIES;
1092 
1093       private PerKeyData<K, V>[] perKeyDatas;
1094 
RealMultimapProvider(Key<Map<K, V>> mapKey)1095       private RealMultimapProvider(Key<Map<K, V>> mapKey) {
1096         super(mapKey);
1097       }
1098 
1099       @Override
getDependencies()1100       public Set<Dependency<?>> getDependencies() {
1101         return dependencies;
1102       }
1103 
1104       @Override
doInitialize(InjectorImpl injector, Errors errors)1105       protected void doInitialize(InjectorImpl injector, Errors errors) throws ErrorsException {
1106         @SuppressWarnings({"unchecked", "rawtypes"})
1107         PerKeyData<K, V>[] typedPerKeyData =
1108             new PerKeyData[bindingSelection.getMapBindings().size()];
1109         perKeyDatas = typedPerKeyData;
1110         ImmutableSet.Builder<Dependency<?>> dependenciesBuilder = ImmutableSet.builder();
1111         List<Dependency<?>> dependenciesForKey = Lists.newArrayList();
1112         int i = 0;
1113         for (Map.Entry<K, Set<Binding<V>>> entry :
1114             bindingSelection.getMultimapBindings().entrySet()) {
1115           // Clear the list of dependencies because we're reusing it for each different key
1116           dependenciesForKey.clear();
1117 
1118           Set<Binding<V>> bindings = entry.getValue();
1119           @SuppressWarnings({"unchecked", "rawtypes"})
1120           Binding<V>[] typedBindings = new Binding[bindings.size()];
1121           Binding<V>[] bindingsArray = typedBindings;
1122           int j = 0;
1123           for (Binding<V> binding : bindings) {
1124             Dependency<V> dependency = Dependency.get(binding.getKey());
1125             dependenciesBuilder.add(dependency);
1126             dependenciesForKey.add(dependency);
1127             bindingsArray[j] = binding;
1128             j++;
1129           }
1130 
1131           @SuppressWarnings("unchecked")
1132           SingleParameterInjector<V>[] injectors =
1133               (SingleParameterInjector<V>[])
1134                   injector.getParametersInjectors(dependenciesForKey, errors);
1135 
1136           perKeyDatas[i] = new PerKeyData<>(entry.getKey(), bindingsArray, injectors);
1137           i++;
1138         }
1139 
1140         dependencies = dependenciesBuilder.build();
1141       }
1142 
1143       @Override
doProvision(InternalContext context, Dependency<?> dependency)1144       protected Map<K, Set<V>> doProvision(InternalContext context, Dependency<?> dependency)
1145           throws InternalProvisionException {
1146         ImmutableMap.Builder<K, Set<V>> resultBuilder = ImmutableMap.builder();
1147 
1148         for (PerKeyData<K, V> perKeyData : perKeyDatas) {
1149           ImmutableSet.Builder<V> bindingsBuilder = ImmutableSet.builder();
1150           SingleParameterInjector<V>[] injectors = perKeyData.injectors;
1151           for (int i = 0; i < injectors.length; i++) {
1152             SingleParameterInjector<V> injector = injectors[i];
1153             V value = injector.inject(context);
1154 
1155             if (value == null) {
1156               throw createNullValueException(perKeyData.key, perKeyData.bindings[i]);
1157             }
1158 
1159             bindingsBuilder.add(value);
1160           }
1161 
1162           resultBuilder.put(perKeyData.key, bindingsBuilder.build());
1163         }
1164 
1165         return resultBuilder.build();
1166       }
1167     }
1168   }
1169 
1170   /** A factory for a {@code Map.Entry<K, Provider<V>>}. */
1171   //VisibleForTesting
1172   static final class ProviderMapEntry<K, V>
1173       extends InternalProviderInstanceBindingImpl.Factory<Map.Entry<K, Provider<V>>> {
1174     private final K key;
1175     private final Key<V> valueKey;
1176     private Map.Entry<K, Provider<V>> entry;
1177 
ProviderMapEntry(K key, Key<V> valueKey)1178     ProviderMapEntry(K key, Key<V> valueKey) {
1179       super(InitializationTiming.EAGER);
1180       this.key = key;
1181       this.valueKey = valueKey;
1182     }
1183 
1184     @Override
getDependencies()1185     public Set<Dependency<?>> getDependencies() {
1186       // The dependencies are Key<Provider<V>>
1187       return ImmutableSet.<Dependency<?>>of(Dependency.get(getKeyOfProvider(valueKey)));
1188     }
1189 
1190     @Override
initialize(InjectorImpl injector, Errors errors)1191     void initialize(InjectorImpl injector, Errors errors) {
1192       Binding<V> valueBinding = injector.getExistingBinding(valueKey);
1193       entry = Maps.immutableEntry(key, valueBinding.getProvider());
1194     }
1195 
1196     @Override
doProvision( InternalContext context, Dependency<?> dependency)1197     protected Map.Entry<K, Provider<V>> doProvision(
1198         InternalContext context, Dependency<?> dependency) {
1199       return entry;
1200     }
1201 
getKey()1202     K getKey() {
1203       return key;
1204     }
1205 
getValueKey()1206     Key<V> getValueKey() {
1207       return valueKey;
1208     }
1209 
1210     @Override
equals(Object obj)1211     public boolean equals(Object obj) {
1212       if (obj instanceof ProviderMapEntry) {
1213         ProviderMapEntry<?, ?> o = (ProviderMapEntry<?, ?>) obj;
1214         return key.equals(o.key) && valueKey.equals(o.valueKey);
1215       }
1216       return false;
1217     }
1218 
1219     @Override
hashCode()1220     public int hashCode() {
1221       return Objects.hashCode(key, valueKey);
1222     }
1223 
1224     @Override
toString()1225     public String toString() {
1226       return "ProviderMapEntry(" + key + ", " + valueKey + ")";
1227     }
1228   }
1229 
1230   /** A base class for ProviderWithDependencies that need equality based on a specific object. */
1231   private abstract static class RealMapBinderProviderWithDependencies<K, V, P>
1232       extends InternalProviderInstanceBindingImpl.Factory<P> {
1233     final BindingSelection<K, V> bindingSelection;
1234 
RealMapBinderProviderWithDependencies(BindingSelection<K, V> bindingSelection)1235     private RealMapBinderProviderWithDependencies(BindingSelection<K, V> bindingSelection) {
1236       // While MapBinders only depend on bindings created in modules so we could theoretically
1237       // initialize eagerly, they also depend on
1238       // 1. findBindingsByType returning results
1239       // 2. being able to call BindingImpl.acceptTargetVisitor
1240       // neither of those is available during eager initialization, so we use DELAYED
1241       super(InitializationTiming.DELAYED);
1242 
1243       this.bindingSelection = bindingSelection;
1244     }
1245 
1246     @Override
initialize(InjectorImpl injector, Errors errors)1247     final void initialize(InjectorImpl injector, Errors errors) throws ErrorsException {
1248       if (bindingSelection.tryInitialize(injector, errors)) {
1249         doInitialize(injector, errors);
1250       }
1251     }
1252 
1253     /**
1254      * Initialize the factory. BindingSelection is guaranteed to be initialized at this point and
1255      * this will be called prior to any provisioning.
1256      */
doInitialize(InjectorImpl injector, Errors errors)1257     protected abstract void doInitialize(InjectorImpl injector, Errors errors)
1258         throws ErrorsException;
1259 
1260     @Override
equals(Object obj)1261     public boolean equals(Object obj) {
1262       return obj != null
1263           && this.getClass() == obj.getClass()
1264           && bindingSelection.equals(
1265               ((RealMapBinderProviderWithDependencies<?, ?, ?>) obj).bindingSelection);
1266     }
1267 
1268     @Override
hashCode()1269     public int hashCode() {
1270       return bindingSelection.hashCode();
1271     }
1272   }
1273 
1274   /**
1275    * A base class for ProviderWithDependencies that need equality based on a specific object.
1276    *
1277    * <p>This differs from {@link RealMapBinderProviderWithDependencies} in that it gets the {@code
1278    * bindingSelection} from the injector at initialization time, rather than in the constructor.
1279    * This is done to allow all the providers to operate on the same instance of the {@link
1280    * BindingSelection}.
1281    */
1282   private abstract static class RealMultimapBinderProviderWithDependencies<K, V, P>
1283       extends InternalProviderInstanceBindingImpl.Factory<P> {
1284     final Key<Map<K, V>> mapKey;
1285     BindingSelection<K, V> bindingSelection;
1286 
RealMultimapBinderProviderWithDependencies(Key<Map<K, V>> mapKey)1287     private RealMultimapBinderProviderWithDependencies(Key<Map<K, V>> mapKey) {
1288       // While MapBinders only depend on bindings created in modules so we could theoretically
1289       // initialize eagerly, they also depend on
1290       // 1. findBindingsByType returning results
1291       // 2. being able to call BindingImpl.acceptTargetVisitor
1292       // neither of those is available during eager initialization, so we use DELAYED
1293       super(InitializationTiming.DELAYED);
1294 
1295       this.mapKey = mapKey;
1296     }
1297 
1298     /**
1299      * This will get the authoritative {@link BindingSelection} from the map provider. This
1300      * guarantees that everyone has the same instance of the bindingSelection and sees consistent
1301      * state.
1302      */
1303     @Override
initialize(InjectorImpl injector, Errors errors)1304     final void initialize(InjectorImpl injector, Errors errors) throws ErrorsException {
1305       Binding<Map<K, V>> mapBinding = injector.getExistingBinding(mapKey);
1306       ProviderInstanceBinding<Map<K, V>> providerInstanceBinding =
1307           (ProviderInstanceBinding<Map<K, V>>) mapBinding;
1308       @SuppressWarnings("unchecked")
1309       RealMapProvider<K, V> mapProvider =
1310           (RealMapProvider<K, V>) providerInstanceBinding.getUserSuppliedProvider();
1311 
1312       this.bindingSelection = mapProvider.getBindingSelection();
1313 
1314       if (bindingSelection.tryInitialize(injector, errors)) {
1315         doInitialize(injector, errors);
1316       }
1317     }
1318 
1319     /**
1320      * Initialize the factory. BindingSelection is guaranteed to be initialized at this point and
1321      * this will be called prior to any provisioning.
1322      */
doInitialize(InjectorImpl injector, Errors errors)1323     abstract void doInitialize(InjectorImpl injector, Errors errors) throws ErrorsException;
1324 
1325     @Override
equals(Object obj)1326     public boolean equals(Object obj) {
1327       return obj != null
1328           && this.getClass() == obj.getClass()
1329           && mapKey.equals(((RealMultimapBinderProviderWithDependencies<?, ?, ?>) obj).mapKey);
1330     }
1331 
1332     @Override
hashCode()1333     public int hashCode() {
1334       return mapKey.hashCode();
1335     }
1336   }
1337 
createNullValueException( K key, Binding<V> binding)1338   private static <K, V> InternalProvisionException createNullValueException(
1339       K key, Binding<V> binding) {
1340     return InternalProvisionException.create(
1341         "Map injection failed due to null value for key \"%s\", bound at: %s",
1342         key, binding.getSource());
1343   }
1344 }
1345