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<K, V>, 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