15019270849439d3aa58bc086a4514d7471716a35limpbizkit/**
25019270849439d3aa58bc086a4514d7471716a35limpbizkit * Copyright (C) 2008 Google Inc.
35019270849439d3aa58bc086a4514d7471716a35limpbizkit *
45019270849439d3aa58bc086a4514d7471716a35limpbizkit * Licensed under the Apache License, Version 2.0 (the "License");
55019270849439d3aa58bc086a4514d7471716a35limpbizkit * you may not use this file except in compliance with the License.
65019270849439d3aa58bc086a4514d7471716a35limpbizkit * You may obtain a copy of the License at
75019270849439d3aa58bc086a4514d7471716a35limpbizkit *
85019270849439d3aa58bc086a4514d7471716a35limpbizkit * http://www.apache.org/licenses/LICENSE-2.0
95019270849439d3aa58bc086a4514d7471716a35limpbizkit *
105019270849439d3aa58bc086a4514d7471716a35limpbizkit * Unless required by applicable law or agreed to in writing, software
115019270849439d3aa58bc086a4514d7471716a35limpbizkit * distributed under the License is distributed on an "AS IS" BASIS,
125019270849439d3aa58bc086a4514d7471716a35limpbizkit * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135019270849439d3aa58bc086a4514d7471716a35limpbizkit * See the License for the specific language governing permissions and
145019270849439d3aa58bc086a4514d7471716a35limpbizkit * limitations under the License.
155019270849439d3aa58bc086a4514d7471716a35limpbizkit */
165019270849439d3aa58bc086a4514d7471716a35limpbizkit
175019270849439d3aa58bc086a4514d7471716a35limpbizkitpackage com.google.inject.multibindings;
185019270849439d3aa58bc086a4514d7471716a35limpbizkit
193d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruberimport static com.google.common.base.Predicates.equalTo;
20b159fc53326acc2a224b51f954e15f62fe1356d0lukesimport static com.google.common.primitives.Ints.MAX_POWER_OF_TWO;
213d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruberimport static com.google.common.collect.Iterables.filter;
223d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruberimport static com.google.common.collect.Iterables.getOnlyElement;
2321a19670ce07439d616a7a38a9907560eaa6a25dSam Berlinimport static com.google.inject.multibindings.Element.Type.MULTIBINDER;
24b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport static com.google.inject.name.Names.named;
25b7a02b02d81c830d148355c90bc309bcd66fb592sberlin
263d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruberimport com.google.common.base.Objects;
27b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport com.google.common.collect.ImmutableList;
28b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport com.google.common.collect.ImmutableSet;
29b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport com.google.common.collect.Lists;
30c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlinimport com.google.common.collect.Sets;
31398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkitimport com.google.inject.AbstractModule;
329532e6267f55105992301add5accfb5c62fdeed8limpbizkitimport com.google.inject.Binder;
339532e6267f55105992301add5accfb5c62fdeed8limpbizkitimport com.google.inject.Binding;
3472d11dd102eeebf081aa5363469d28b25f9b1384limpbizkitimport com.google.inject.ConfigurationException;
359532e6267f55105992301add5accfb5c62fdeed8limpbizkitimport com.google.inject.Inject;
369532e6267f55105992301add5accfb5c62fdeed8limpbizkitimport com.google.inject.Injector;
379532e6267f55105992301add5accfb5c62fdeed8limpbizkitimport com.google.inject.Key;
389532e6267f55105992301add5accfb5c62fdeed8limpbizkitimport com.google.inject.Module;
394faa20e3081448792933834aedfe972add806292Sam Berlinimport com.google.inject.Provider;
409532e6267f55105992301add5accfb5c62fdeed8limpbizkitimport com.google.inject.TypeLiteral;
419532e6267f55105992301add5accfb5c62fdeed8limpbizkitimport com.google.inject.binder.LinkedBindingBuilder;
42b1f42f5df9c4cd8e157a28c24c4e8eb627a7f052limpbizkitimport com.google.inject.internal.Errors;
4375fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlinimport com.google.inject.spi.BindingTargetVisitor;
44ddb3862415e078080293abba05f1a24a921c007climpbizkitimport com.google.inject.spi.Dependency;
45ddb3862415e078080293abba05f1a24a921c007climpbizkitimport com.google.inject.spi.HasDependencies;
4672d11dd102eeebf081aa5363469d28b25f9b1384limpbizkitimport com.google.inject.spi.Message;
4775fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlinimport com.google.inject.spi.ProviderInstanceBinding;
484faa20e3081448792933834aedfe972add806292Sam Berlinimport com.google.inject.spi.ProviderWithDependencies;
4975fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlinimport com.google.inject.spi.ProviderWithExtensionVisitor;
508bc8387f63053ac03b609277093a06019c7b18b3sberlinimport com.google.inject.spi.Toolable;
519532e6267f55105992301add5accfb5c62fdeed8limpbizkitimport com.google.inject.util.Types;
52b7a02b02d81c830d148355c90bc309bcd66fb592sberlin
533d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruberimport java.lang.annotation.Annotation;
543d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruberimport java.lang.reflect.Type;
554faa20e3081448792933834aedfe972add806292Sam Berlinimport java.util.Collection;
563d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruberimport java.util.LinkedHashMap;
573d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruberimport java.util.List;
583d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruberimport java.util.Map;
593d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruberimport java.util.Set;
603d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber
615019270849439d3aa58bc086a4514d7471716a35limpbizkit/**
625019270849439d3aa58bc086a4514d7471716a35limpbizkit * An API to bind multiple values separately, only to later inject them as a
635019270849439d3aa58bc086a4514d7471716a35limpbizkit * complete collection. Multibinder is intended for use in your application's
645019270849439d3aa58bc086a4514d7471716a35limpbizkit * module:
655019270849439d3aa58bc086a4514d7471716a35limpbizkit * <pre><code>
665019270849439d3aa58bc086a4514d7471716a35limpbizkit * public class SnacksModule extends AbstractModule {
675019270849439d3aa58bc086a4514d7471716a35limpbizkit *   protected void configure() {
685019270849439d3aa58bc086a4514d7471716a35limpbizkit *     Multibinder&lt;Snack&gt; multibinder
695019270849439d3aa58bc086a4514d7471716a35limpbizkit *         = Multibinder.newSetBinder(binder(), Snack.class);
705019270849439d3aa58bc086a4514d7471716a35limpbizkit *     multibinder.addBinding().toInstance(new Twix());
715019270849439d3aa58bc086a4514d7471716a35limpbizkit *     multibinder.addBinding().toProvider(SnickersProvider.class);
725019270849439d3aa58bc086a4514d7471716a35limpbizkit *     multibinder.addBinding().to(Skittles.class);
735019270849439d3aa58bc086a4514d7471716a35limpbizkit *   }
745019270849439d3aa58bc086a4514d7471716a35limpbizkit * }</code></pre>
755019270849439d3aa58bc086a4514d7471716a35limpbizkit *
765019270849439d3aa58bc086a4514d7471716a35limpbizkit * <p>With this binding, a {@link Set}{@code <Snack>} can now be injected:
775019270849439d3aa58bc086a4514d7471716a35limpbizkit * <pre><code>
785019270849439d3aa58bc086a4514d7471716a35limpbizkit * class SnackMachine {
795019270849439d3aa58bc086a4514d7471716a35limpbizkit *   {@literal @}Inject
805019270849439d3aa58bc086a4514d7471716a35limpbizkit *   public SnackMachine(Set&lt;Snack&gt; snacks) { ... }
815019270849439d3aa58bc086a4514d7471716a35limpbizkit * }</code></pre>
825019270849439d3aa58bc086a4514d7471716a35limpbizkit *
834faa20e3081448792933834aedfe972add806292Sam Berlin * If desired, {@link Collection}{@code <Provider<Snack>>} can also be injected.
844faa20e3081448792933834aedfe972add806292Sam Berlin *
850e23eb0505fcf0b4e7c53c26c1ecdb6a18362d2alimpbizkit * <p>Contributing multibindings from different modules is supported. For
86c2bee817056d21696eb269287edeb110da90ff24Sam Berlin * example, it is okay for both {@code CandyModule} and {@code ChipsModule}
87c2bee817056d21696eb269287edeb110da90ff24Sam Berlin * to create their own {@code Multibinder<Snack>}, and to each contribute
880e23eb0505fcf0b4e7c53c26c1ecdb6a18362d2alimpbizkit * bindings to the set of snacks. When that set is injected, it will contain
890e23eb0505fcf0b4e7c53c26c1ecdb6a18362d2alimpbizkit * elements from both modules.
900e896db46024dc7596302f8622276d1c7df02c6bSam Berlin *
910e23eb0505fcf0b4e7c53c26c1ecdb6a18362d2alimpbizkit * <p>The set's iteration order is consistent with the binding order. This is
920e23eb0505fcf0b4e7c53c26c1ecdb6a18362d2alimpbizkit * convenient when multiple elements are contributed by the same module because
930e23eb0505fcf0b4e7c53c26c1ecdb6a18362d2alimpbizkit * that module can order its bindings appropriately. Avoid relying on the
940e23eb0505fcf0b4e7c53c26c1ecdb6a18362d2alimpbizkit * iteration order of elements contributed by different modules, since there is
950e23eb0505fcf0b4e7c53c26c1ecdb6a18362d2alimpbizkit * no equivalent mechanism to order modules.
960e896db46024dc7596302f8622276d1c7df02c6bSam Berlin *
976542fdb264fdcb205af3318f430228cffb191290sberlin * <p>The set is unmodifiable.  Elements can only be added to the set by
986542fdb264fdcb205af3318f430228cffb191290sberlin * configuring the multibinder.  Elements can never be removed from the set.
995019270849439d3aa58bc086a4514d7471716a35limpbizkit *
1005019270849439d3aa58bc086a4514d7471716a35limpbizkit * <p>Elements are resolved at set injection time. If an element is bound to a
1015019270849439d3aa58bc086a4514d7471716a35limpbizkit * provider, that provider's get method will be called each time the set is
1025019270849439d3aa58bc086a4514d7471716a35limpbizkit * injected (unless the binding is also scoped).
1035019270849439d3aa58bc086a4514d7471716a35limpbizkit *
1045019270849439d3aa58bc086a4514d7471716a35limpbizkit * <p>Annotations are be used to create different sets of the same element
1055019270849439d3aa58bc086a4514d7471716a35limpbizkit * type. Each distinct annotation gets its own independent collection of
1065019270849439d3aa58bc086a4514d7471716a35limpbizkit * elements.
1075019270849439d3aa58bc086a4514d7471716a35limpbizkit *
1085019270849439d3aa58bc086a4514d7471716a35limpbizkit * <p><strong>Elements must be distinct.</strong> If multiple bound elements
1095019270849439d3aa58bc086a4514d7471716a35limpbizkit * have the same value, set injection will fail.
1105019270849439d3aa58bc086a4514d7471716a35limpbizkit *
1115019270849439d3aa58bc086a4514d7471716a35limpbizkit * <p><strong>Elements must be non-null.</strong> If any set element is null,
1125019270849439d3aa58bc086a4514d7471716a35limpbizkit * set injection will fail.
1135019270849439d3aa58bc086a4514d7471716a35limpbizkit *
1145019270849439d3aa58bc086a4514d7471716a35limpbizkit * @author jessewilson@google.com (Jesse Wilson)
1155019270849439d3aa58bc086a4514d7471716a35limpbizkit */
1165019270849439d3aa58bc086a4514d7471716a35limpbizkitpublic abstract class Multibinder<T> {
1175019270849439d3aa58bc086a4514d7471716a35limpbizkit  private Multibinder() {}
1189532e6267f55105992301add5accfb5c62fdeed8limpbizkit
1195019270849439d3aa58bc086a4514d7471716a35limpbizkit  /**
120cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit   * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
121cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit   * itself bound with no binding annotation.
1225019270849439d3aa58bc086a4514d7471716a35limpbizkit   */
123cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit  public static <T> Multibinder<T> newSetBinder(Binder binder, TypeLiteral<T> type) {
1240b33461e35fa3a769ce23a9812a80acdc281f62csameb    return newRealSetBinder(binder, Key.get(type));
1255019270849439d3aa58bc086a4514d7471716a35limpbizkit  }
1265019270849439d3aa58bc086a4514d7471716a35limpbizkit
1275019270849439d3aa58bc086a4514d7471716a35limpbizkit  /**
128cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit   * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
129cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit   * itself bound with no binding annotation.
1305019270849439d3aa58bc086a4514d7471716a35limpbizkit   */
131cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit  public static <T> Multibinder<T> newSetBinder(Binder binder, Class<T> type) {
1320b33461e35fa3a769ce23a9812a80acdc281f62csameb    return newRealSetBinder(binder, Key.get(type));
133cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit  }
134cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit
135cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit  /**
136cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit   * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
137cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit   * itself bound with {@code annotation}.
138cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit   */
139cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit  public static <T> Multibinder<T> newSetBinder(
140cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit      Binder binder, TypeLiteral<T> type, Annotation annotation) {
1410b33461e35fa3a769ce23a9812a80acdc281f62csameb    return newRealSetBinder(binder, Key.get(type, annotation));
1425019270849439d3aa58bc086a4514d7471716a35limpbizkit  }
1435019270849439d3aa58bc086a4514d7471716a35limpbizkit
1445019270849439d3aa58bc086a4514d7471716a35limpbizkit  /**
145cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit   * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
146cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit   * itself bound with {@code annotation}.
147cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit   */
148cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit  public static <T> Multibinder<T> newSetBinder(
149cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit      Binder binder, Class<T> type, Annotation annotation) {
1500b33461e35fa3a769ce23a9812a80acdc281f62csameb    return newRealSetBinder(binder, Key.get(type, annotation));
151cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit  }
152cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit
153cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit  /**
154cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit   * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
155cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit   * itself bound with {@code annotationType}.
1565019270849439d3aa58bc086a4514d7471716a35limpbizkit   */
157cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit  public static <T> Multibinder<T> newSetBinder(Binder binder, TypeLiteral<T> type,
1585019270849439d3aa58bc086a4514d7471716a35limpbizkit      Class<? extends Annotation> annotationType) {
1590b33461e35fa3a769ce23a9812a80acdc281f62csameb    return newRealSetBinder(binder, Key.get(type, annotationType));
1600b33461e35fa3a769ce23a9812a80acdc281f62csameb  }
1610b33461e35fa3a769ce23a9812a80acdc281f62csameb
1620b33461e35fa3a769ce23a9812a80acdc281f62csameb  /**
1630b33461e35fa3a769ce23a9812a80acdc281f62csameb   * Returns a new multibinder that collects instances of the key's type in a {@link Set} that is
1640b33461e35fa3a769ce23a9812a80acdc281f62csameb   * itself bound with the annotation (if any) of the key.
165646e1742c047dc9a768f2bc065b33e9b5ab49006cgdecker   *
166bac730fa1b717351736182034aff62827a383090Ben McCann   * @since 4.0
1670b33461e35fa3a769ce23a9812a80acdc281f62csameb   */
1680b33461e35fa3a769ce23a9812a80acdc281f62csameb  public static <T> Multibinder<T> newSetBinder(Binder binder, Key<T> key) {
1690b33461e35fa3a769ce23a9812a80acdc281f62csameb    return newRealSetBinder(binder, key);
1700b33461e35fa3a769ce23a9812a80acdc281f62csameb  }
1710b33461e35fa3a769ce23a9812a80acdc281f62csameb
1720b33461e35fa3a769ce23a9812a80acdc281f62csameb  /**
1730b33461e35fa3a769ce23a9812a80acdc281f62csameb   * Implementation of newSetBinder.
1740b33461e35fa3a769ce23a9812a80acdc281f62csameb   */
1750b33461e35fa3a769ce23a9812a80acdc281f62csameb  static <T> RealMultibinder<T> newRealSetBinder(Binder binder, Key<T> key) {
1766663d02af7c384ce351a76928d1b6c929224b582limpbizkit    binder = binder.skipSources(RealMultibinder.class, Multibinder.class);
1770b33461e35fa3a769ce23a9812a80acdc281f62csameb    RealMultibinder<T> result = new RealMultibinder<T>(binder, key.getTypeLiteral(),
1780b33461e35fa3a769ce23a9812a80acdc281f62csameb        key.ofType(setOf(key.getTypeLiteral())));
1796663d02af7c384ce351a76928d1b6c929224b582limpbizkit    binder.install(result);
1805019270849439d3aa58bc086a4514d7471716a35limpbizkit    return result;
1815019270849439d3aa58bc086a4514d7471716a35limpbizkit  }
1825019270849439d3aa58bc086a4514d7471716a35limpbizkit
183cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit  /**
184cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit   * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
185cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit   * itself bound with {@code annotationType}.
186cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit   */
187cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit  public static <T> Multibinder<T> newSetBinder(Binder binder, Class<T> type,
188cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit      Class<? extends Annotation> annotationType) {
1890b33461e35fa3a769ce23a9812a80acdc281f62csameb    return newSetBinder(binder, Key.get(type, annotationType));
190cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit  }
191cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit
192cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit  @SuppressWarnings("unchecked") // wrapping a T in a Set safely returns a Set<T>
1930efcc6c784a0466ce88f30b70d651476bd7fa5eenetdpb  static <T> TypeLiteral<Set<T>> setOf(TypeLiteral<T> elementType) {
194cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit    Type type = Types.setOf(elementType.getType());
19583b510c924832d38df1a3030e69863098432fffblimpbizkit    return (TypeLiteral<Set<T>>) TypeLiteral.get(type);
19683b510c924832d38df1a3030e69863098432fffblimpbizkit  }
19783b510c924832d38df1a3030e69863098432fffblimpbizkit
1984faa20e3081448792933834aedfe972add806292Sam Berlin  @SuppressWarnings("unchecked")
1994faa20e3081448792933834aedfe972add806292Sam Berlin  static <T> TypeLiteral<Collection<Provider<T>>> collectionOfProvidersOf(
2004faa20e3081448792933834aedfe972add806292Sam Berlin      TypeLiteral<T> elementType) {
2014faa20e3081448792933834aedfe972add806292Sam Berlin    Type providerType = Types.providerOf(elementType.getType());
2024faa20e3081448792933834aedfe972add806292Sam Berlin    Type type = Types.newParameterizedType(Collection.class, providerType);
2034faa20e3081448792933834aedfe972add806292Sam Berlin    return (TypeLiteral<Collection<Provider<T>>>) TypeLiteral.get(type);
2044faa20e3081448792933834aedfe972add806292Sam Berlin  }
2054faa20e3081448792933834aedfe972add806292Sam Berlin
206bed1413751f54dc6804dcb2a4c28300081788603flan  @SuppressWarnings("unchecked")
207bed1413751f54dc6804dcb2a4c28300081788603flan  static <T> TypeLiteral<Collection<javax.inject.Provider<T>>> collectionOfJavaxProvidersOf(
208bed1413751f54dc6804dcb2a4c28300081788603flan      TypeLiteral<T> elementType) {
209bed1413751f54dc6804dcb2a4c28300081788603flan    Type providerType =
210bed1413751f54dc6804dcb2a4c28300081788603flan        Types.newParameterizedType(javax.inject.Provider.class, elementType.getType());
211bed1413751f54dc6804dcb2a4c28300081788603flan    Type type = Types.newParameterizedType(Collection.class, providerType);
212bed1413751f54dc6804dcb2a4c28300081788603flan    return (TypeLiteral<Collection<javax.inject.Provider<T>>>) TypeLiteral.get(type);
213bed1413751f54dc6804dcb2a4c28300081788603flan  }
214bed1413751f54dc6804dcb2a4c28300081788603flan
2155019270849439d3aa58bc086a4514d7471716a35limpbizkit  /**
216398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit   * Configures the bound set to silently discard duplicate elements. When multiple equal values are
2170efcc6c784a0466ce88f30b70d651476bd7fa5eenetdpb   * bound, the one that gets included is arbitrary. When multiple modules contribute elements to
218398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit   * the set, this configuration option impacts all of them.
219398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit   *
220398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit   * @return this multibinder
221c13b5454a5cfa7d188e9a047017ac0de63ec4dfbsberlin   * @since 3.0
222398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit   */
223398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit  public abstract Multibinder<T> permitDuplicates();
224398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit
225398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit  /**
2265019270849439d3aa58bc086a4514d7471716a35limpbizkit   * Returns a binding builder used to add a new element in the set. Each
2275019270849439d3aa58bc086a4514d7471716a35limpbizkit   * bound element must have a distinct value. Bound providers will be
2285019270849439d3aa58bc086a4514d7471716a35limpbizkit   * evaluated each time the set is injected.
2295019270849439d3aa58bc086a4514d7471716a35limpbizkit   *
2305019270849439d3aa58bc086a4514d7471716a35limpbizkit   * <p>It is an error to call this method without also calling one of the
2315019270849439d3aa58bc086a4514d7471716a35limpbizkit   * {@code to} methods on the returned binding builder.
2325019270849439d3aa58bc086a4514d7471716a35limpbizkit   *
2335019270849439d3aa58bc086a4514d7471716a35limpbizkit   * <p>Scoping elements independently is supported. Use the {@code in} method
2345019270849439d3aa58bc086a4514d7471716a35limpbizkit   * to specify a binding scope.
2355019270849439d3aa58bc086a4514d7471716a35limpbizkit   */
2365019270849439d3aa58bc086a4514d7471716a35limpbizkit  public abstract LinkedBindingBuilder<T> addBinding();
2375019270849439d3aa58bc086a4514d7471716a35limpbizkit
2385019270849439d3aa58bc086a4514d7471716a35limpbizkit  /**
2395019270849439d3aa58bc086a4514d7471716a35limpbizkit   * The actual multibinder plays several roles:
2405019270849439d3aa58bc086a4514d7471716a35limpbizkit   *
2415019270849439d3aa58bc086a4514d7471716a35limpbizkit   * <p>As a Multibinder, it acts as a factory for LinkedBindingBuilders for
2425019270849439d3aa58bc086a4514d7471716a35limpbizkit   * each of the set's elements. Each binding is given an annotation that
2435019270849439d3aa58bc086a4514d7471716a35limpbizkit   * identifies it as a part of this set.
2445019270849439d3aa58bc086a4514d7471716a35limpbizkit   *
2455019270849439d3aa58bc086a4514d7471716a35limpbizkit   * <p>As a Module, it installs the binding to the set itself. As a module,
2465019270849439d3aa58bc086a4514d7471716a35limpbizkit   * this implements equals() and hashcode() in order to trick Guice into
2475019270849439d3aa58bc086a4514d7471716a35limpbizkit   * executing its configure() method only once. That makes it so that
2485019270849439d3aa58bc086a4514d7471716a35limpbizkit   * multiple multibinders can be created for the same target collection, but
2495019270849439d3aa58bc086a4514d7471716a35limpbizkit   * only one is bound. Since the list of bindings is retrieved from the
2505019270849439d3aa58bc086a4514d7471716a35limpbizkit   * injector itself (and not the multibinder), each multibinder has access to
2515019270849439d3aa58bc086a4514d7471716a35limpbizkit   * all contributions from all multibinders.
2525019270849439d3aa58bc086a4514d7471716a35limpbizkit   *
2535019270849439d3aa58bc086a4514d7471716a35limpbizkit   * <p>As a Provider, this constructs the set instances.
2545019270849439d3aa58bc086a4514d7471716a35limpbizkit   *
2555019270849439d3aa58bc086a4514d7471716a35limpbizkit   * <p>We use a subclass to hide 'implements Module, Provider' from the public
2565019270849439d3aa58bc086a4514d7471716a35limpbizkit   * API.
2575019270849439d3aa58bc086a4514d7471716a35limpbizkit   */
258ddb3862415e078080293abba05f1a24a921c007climpbizkit  static final class RealMultibinder<T> extends Multibinder<T>
2596c69bcf53d4122b0f05f44783c0d8a61afd83911Christian Edward Gruber      implements Module, ProviderWithExtensionVisitor<Set<T>>, HasDependencies,
2606c69bcf53d4122b0f05f44783c0d8a61afd83911Christian Edward Gruber          MultibinderBinding<Set<T>> {
261c75363acf0118de3123ef5e90cd0682562ea2d79limpbizkit
262cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit    private final TypeLiteral<T> elementType;
2635019270849439d3aa58bc086a4514d7471716a35limpbizkit    private final String setName;
26483b510c924832d38df1a3030e69863098432fffblimpbizkit    private final Key<Set<T>> setKey;
2654faa20e3081448792933834aedfe972add806292Sam Berlin    private final Key<Collection<Provider<T>>> collectionOfProvidersKey;
266bed1413751f54dc6804dcb2a4c28300081788603flan    private final Key<Collection<javax.inject.Provider<T>>> collectionOfJavaxProvidersKey;
267398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit    private final Key<Boolean> permitDuplicatesKey;
2685019270849439d3aa58bc086a4514d7471716a35limpbizkit
26983b510c924832d38df1a3030e69863098432fffblimpbizkit    /* the target injector's binder. non-null until initialization, null afterwards */
2705019270849439d3aa58bc086a4514d7471716a35limpbizkit    private Binder binder;
27183b510c924832d38df1a3030e69863098432fffblimpbizkit
27275fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin    /* a binding for each element in the set. null until initialization, non-null afterwards */
27375fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin    private ImmutableList<Binding<T>> bindings;
274ddb3862415e078080293abba05f1a24a921c007climpbizkit    private Set<Dependency<?>> dependencies;
2755019270849439d3aa58bc086a4514d7471716a35limpbizkit
276398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit    /** whether duplicates are allowed. Possibly configured by a different instance */
277398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit    private boolean permitDuplicates;
278398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit
2799c8b61815fa15ee3457b9c816afe24a6fdaf7014flan    private RealMultibinder(Binder binder, TypeLiteral<T> elementType, Key<Set<T>> setKey) {
2801601ae5cc3d7931d4ce4b78e0b493acdd6132ff1kevinb      this.binder = checkNotNull(binder, "binder");
2811601ae5cc3d7931d4ce4b78e0b493acdd6132ff1kevinb      this.elementType = checkNotNull(elementType, "elementType");
2821601ae5cc3d7931d4ce4b78e0b493acdd6132ff1kevinb      this.setKey = checkNotNull(setKey, "setKey");
2839c8b61815fa15ee3457b9c816afe24a6fdaf7014flan      this.collectionOfProvidersKey = setKey.ofType(collectionOfProvidersOf(elementType));
284bed1413751f54dc6804dcb2a4c28300081788603flan      this.collectionOfJavaxProvidersKey = setKey.ofType(collectionOfJavaxProvidersOf(elementType));
285cade897b45ffe5d9d4e48ae7009cf74d8a91e335Christian Edward Gruber      this.setName = RealElement.nameOf(setKey);
286398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit      this.permitDuplicatesKey = Key.get(Boolean.class, named(toString() + " permits duplicates"));
2875019270849439d3aa58bc086a4514d7471716a35limpbizkit    }
2880e896db46024dc7596302f8622276d1c7df02c6bSam Berlin
2895019270849439d3aa58bc086a4514d7471716a35limpbizkit    public void configure(Binder binder) {
29072d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit      checkConfiguration(!isInitialized(), "Multibinder was already initialized");
2915019270849439d3aa58bc086a4514d7471716a35limpbizkit
2925019270849439d3aa58bc086a4514d7471716a35limpbizkit      binder.bind(setKey).toProvider(this);
2934faa20e3081448792933834aedfe972add806292Sam Berlin      binder.bind(collectionOfProvidersKey).toProvider(
2944faa20e3081448792933834aedfe972add806292Sam Berlin          new RealMultibinderCollectionOfProvidersProvider());
295bed1413751f54dc6804dcb2a4c28300081788603flan
296bed1413751f54dc6804dcb2a4c28300081788603flan      // The collection this exposes is internally an ImmutableList, so it's OK to massage
297bed1413751f54dc6804dcb2a4c28300081788603flan      // the guice Provider to javax Provider in the value (since the guice Provider implements
298bed1413751f54dc6804dcb2a4c28300081788603flan      // javax Provider).
299bed1413751f54dc6804dcb2a4c28300081788603flan      @SuppressWarnings("unchecked")
300bed1413751f54dc6804dcb2a4c28300081788603flan      Key key = (Key) collectionOfProvidersKey;
301bed1413751f54dc6804dcb2a4c28300081788603flan      binder.bind(collectionOfJavaxProvidersKey).to(key);
3025019270849439d3aa58bc086a4514d7471716a35limpbizkit    }
3035019270849439d3aa58bc086a4514d7471716a35limpbizkit
3044faa20e3081448792933834aedfe972add806292Sam Berlin    @Override public Multibinder<T> permitDuplicates() {
305398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit      binder.install(new PermitDuplicatesModule(permitDuplicatesKey));
306398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit      return this;
307398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit    }
3080b33461e35fa3a769ce23a9812a80acdc281f62csameb
3090b33461e35fa3a769ce23a9812a80acdc281f62csameb    Key<T> getKeyForNewItem() {
31072d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit      checkConfiguration(!isInitialized(), "Multibinder was already initialized");
3110b33461e35fa3a769ce23a9812a80acdc281f62csameb      return Key.get(elementType, new RealElement(setName, MULTIBINDER, ""));
3120b33461e35fa3a769ce23a9812a80acdc281f62csameb    }
3135019270849439d3aa58bc086a4514d7471716a35limpbizkit
3140b33461e35fa3a769ce23a9812a80acdc281f62csameb    @Override public LinkedBindingBuilder<T> addBinding() {
3150b33461e35fa3a769ce23a9812a80acdc281f62csameb      return binder.bind(getKeyForNewItem());
3165019270849439d3aa58bc086a4514d7471716a35limpbizkit    }
3175019270849439d3aa58bc086a4514d7471716a35limpbizkit
3185019270849439d3aa58bc086a4514d7471716a35limpbizkit    /**
3195019270849439d3aa58bc086a4514d7471716a35limpbizkit     * Invoked by Guice at Injector-creation time to prepare providers for each
3205019270849439d3aa58bc086a4514d7471716a35limpbizkit     * element in this set. At this time the set's size is known, but its
3215019270849439d3aa58bc086a4514d7471716a35limpbizkit     * contents are only evaluated when get() is invoked.
3225019270849439d3aa58bc086a4514d7471716a35limpbizkit     */
3238bc8387f63053ac03b609277093a06019c7b18b3sberlin    @Toolable @Inject void initialize(Injector injector) {
32475fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin      List<Binding<T>> bindings = Lists.newArrayList();
325c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin      Set<Indexer.IndexedBinding> index = Sets.newHashSet();
326c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin      Indexer indexer = new Indexer(injector);
327ddb3862415e078080293abba05f1a24a921c007climpbizkit      List<Dependency<?>> dependencies = Lists.newArrayList();
328b8a655214c52cdd8012733577ec3b65281c8be66dhanji      for (Binding<?> entry : injector.findBindingsByType(elementType)) {
329e97e15b186baa9fc874eabdf5d293d3f47acebfclimpbizkit        if (keyMatches(entry.getKey())) {
330b8a655214c52cdd8012733577ec3b65281c8be66dhanji          @SuppressWarnings("unchecked") // protected by findBindingsByType()
331b8a655214c52cdd8012733577ec3b65281c8be66dhanji          Binding<T> binding = (Binding<T>) entry;
332c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin          if (index.add(binding.acceptTargetVisitor(indexer))) {
333c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin            bindings.add(binding);
334c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin            dependencies.add(Dependency.get(binding.getKey()));
335c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin          }
3365019270849439d3aa58bc086a4514d7471716a35limpbizkit        }
3375019270849439d3aa58bc086a4514d7471716a35limpbizkit      }
3385019270849439d3aa58bc086a4514d7471716a35limpbizkit
33975fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin      this.bindings = ImmutableList.copyOf(bindings);
340ddb3862415e078080293abba05f1a24a921c007climpbizkit      this.dependencies = ImmutableSet.copyOf(dependencies);
341398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit      this.permitDuplicates = permitsDuplicates(injector);
3425019270849439d3aa58bc086a4514d7471716a35limpbizkit      this.binder = null;
3435019270849439d3aa58bc086a4514d7471716a35limpbizkit    }
3445019270849439d3aa58bc086a4514d7471716a35limpbizkit
345b159fc53326acc2a224b51f954e15f62fe1356d0lukes    // This is forked from com.google.common.collect.Maps.capacity
346b159fc53326acc2a224b51f954e15f62fe1356d0lukes    private static int mapCapacity(int numBindings) {
347b159fc53326acc2a224b51f954e15f62fe1356d0lukes      if (numBindings < 3) {
348b159fc53326acc2a224b51f954e15f62fe1356d0lukes        return numBindings + 1;
349b159fc53326acc2a224b51f954e15f62fe1356d0lukes      } else  if (numBindings < MAX_POWER_OF_TWO) {
350b159fc53326acc2a224b51f954e15f62fe1356d0lukes        return (int) (numBindings / 0.75F + 1.0F);
351b159fc53326acc2a224b51f954e15f62fe1356d0lukes      }
352b159fc53326acc2a224b51f954e15f62fe1356d0lukes      return Integer.MAX_VALUE;
353b159fc53326acc2a224b51f954e15f62fe1356d0lukes    }
354b159fc53326acc2a224b51f954e15f62fe1356d0lukes
355398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit    boolean permitsDuplicates(Injector injector) {
356398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit      return injector.getBindings().containsKey(permitDuplicatesKey);
357398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit    }
358398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit
359e97e15b186baa9fc874eabdf5d293d3f47acebfclimpbizkit    private boolean keyMatches(Key<?> key) {
360cfa95ae7f134ffadbdb454dbb731bd9093c6e162limpbizkit      return key.getTypeLiteral().equals(elementType)
3617c533acbed7ce9c051e847a290dd2060915e91aalimpbizkit          && key.getAnnotation() instanceof Element
36221a19670ce07439d616a7a38a9907560eaa6a25dSam Berlin          && ((Element) key.getAnnotation()).setName().equals(setName)
36321a19670ce07439d616a7a38a9907560eaa6a25dSam Berlin          && ((Element) key.getAnnotation()).type() == MULTIBINDER;
3645019270849439d3aa58bc086a4514d7471716a35limpbizkit    }
3655019270849439d3aa58bc086a4514d7471716a35limpbizkit
3665019270849439d3aa58bc086a4514d7471716a35limpbizkit    private boolean isInitialized() {
3675019270849439d3aa58bc086a4514d7471716a35limpbizkit      return binder == null;
3685019270849439d3aa58bc086a4514d7471716a35limpbizkit    }
3695019270849439d3aa58bc086a4514d7471716a35limpbizkit
3705019270849439d3aa58bc086a4514d7471716a35limpbizkit    public Set<T> get() {
37172d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit      checkConfiguration(isInitialized(), "Multibinder is not initialized");
3725019270849439d3aa58bc086a4514d7471716a35limpbizkit
373b159fc53326acc2a224b51f954e15f62fe1356d0lukes      Map<T, Binding<T>> result = new LinkedHashMap<T, Binding<T>>(mapCapacity(bindings.size()));
37475fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin      for (Binding<T> binding : bindings) {
37575fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin        final T newValue = binding.getProvider().get();
3761bf1e9e0ddef515aaa41a70aa34821ff5564a71dsameb        checkConfiguration(newValue != null,
3771bf1e9e0ddef515aaa41a70aa34821ff5564a71dsameb            "Set injection failed due to null element bound at: %s",
3781bf1e9e0ddef515aaa41a70aa34821ff5564a71dsameb            binding.getSource());
3793d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber        Binding<T> duplicateBinding = result.put(newValue, binding);
3803d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber        if (!permitDuplicates && duplicateBinding != null) {
3813d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber          throw newDuplicateValuesException(result, binding, newValue, duplicateBinding);
3823d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber        }
3835019270849439d3aa58bc086a4514d7471716a35limpbizkit      }
3843d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber      return ImmutableSet.copyOf(result.keySet());
3855019270849439d3aa58bc086a4514d7471716a35limpbizkit    }
3860e896db46024dc7596302f8622276d1c7df02c6bSam Berlin
38775fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin    @SuppressWarnings("unchecked")
388287355590aa8ad2d87f8ebfac3a0710e3b442c27sberlin    public <B, V> V acceptExtensionVisitor(
38975fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin        BindingTargetVisitor<B, V> visitor,
39075fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin        ProviderInstanceBinding<? extends B> binding) {
3916c69bcf53d4122b0f05f44783c0d8a61afd83911Christian Edward Gruber      if (visitor instanceof MultibindingsTargetVisitor) {
3926c69bcf53d4122b0f05f44783c0d8a61afd83911Christian Edward Gruber        return ((MultibindingsTargetVisitor<Set<T>, V>) visitor).visit(this);
39375fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin      } else {
39475fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin        return visitor.visit(binding);
39575fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin      }
39675fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin    }
3970efcc6c784a0466ce88f30b70d651476bd7fa5eenetdpb
398e97e15b186baa9fc874eabdf5d293d3f47acebfclimpbizkit    String getSetName() {
399e97e15b186baa9fc874eabdf5d293d3f47acebfclimpbizkit      return setName;
400e97e15b186baa9fc874eabdf5d293d3f47acebfclimpbizkit    }
4010e896db46024dc7596302f8622276d1c7df02c6bSam Berlin
40275fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin    public TypeLiteral<?> getElementTypeLiteral() {
40375fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin      return elementType;
40475fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin    }
4050efcc6c784a0466ce88f30b70d651476bd7fa5eenetdpb
40675fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin    public Key<Set<T>> getSetKey() {
407e97e15b186baa9fc874eabdf5d293d3f47acebfclimpbizkit      return setKey;
408e97e15b186baa9fc874eabdf5d293d3f47acebfclimpbizkit    }
4090e896db46024dc7596302f8622276d1c7df02c6bSam Berlin
41075fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin    @SuppressWarnings("unchecked")
41175fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin    public List<Binding<?>> getElements() {
4126c69bcf53d4122b0f05f44783c0d8a61afd83911Christian Edward Gruber      if (isInitialized()) {
4136c69bcf53d4122b0f05f44783c0d8a61afd83911Christian Edward Gruber        return (List<Binding<?>>) (List<?>) bindings; // safe because bindings is immutable.
41475fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin      } else {
41575fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin        throw new UnsupportedOperationException("getElements() not supported for module bindings");
41675fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin      }
41775fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin    }
4180e896db46024dc7596302f8622276d1c7df02c6bSam Berlin
41975fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin    public boolean permitsDuplicates() {
4206c69bcf53d4122b0f05f44783c0d8a61afd83911Christian Edward Gruber      if (isInitialized()) {
42175fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin        return permitDuplicates;
42275fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin      } else {
4236c69bcf53d4122b0f05f44783c0d8a61afd83911Christian Edward Gruber        throw new UnsupportedOperationException(
4240e896db46024dc7596302f8622276d1c7df02c6bSam Berlin            "permitsDuplicates() not supported for module bindings");
42575fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin      }
42675fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin    }
42775fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin
42875fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin    public boolean containsElement(com.google.inject.spi.Element element) {
4296c69bcf53d4122b0f05f44783c0d8a61afd83911Christian Edward Gruber      if (element instanceof Binding) {
4306c69bcf53d4122b0f05f44783c0d8a61afd83911Christian Edward Gruber        Binding<?> binding = (Binding<?>) element;
4310e896db46024dc7596302f8622276d1c7df02c6bSam Berlin        return keyMatches(binding.getKey())
43275fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin            || binding.getKey().equals(permitDuplicatesKey)
4334faa20e3081448792933834aedfe972add806292Sam Berlin            || binding.getKey().equals(setKey)
434bed1413751f54dc6804dcb2a4c28300081788603flan            || binding.getKey().equals(collectionOfProvidersKey)
435bed1413751f54dc6804dcb2a4c28300081788603flan            || binding.getKey().equals(collectionOfJavaxProvidersKey);
43675fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin      } else {
43775fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin        return false;
43875fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin      }
43975fcf6f3a7ae2000b8ed85038dfd33bedd0503fasberlin    }
4405019270849439d3aa58bc086a4514d7471716a35limpbizkit
441ddb3862415e078080293abba05f1a24a921c007climpbizkit    public Set<Dependency<?>> getDependencies() {
442aab9eba90f6aa02ad3b87b6746d0cb6a82fe5b23sberlin      if (!isInitialized()) {
443aab9eba90f6aa02ad3b87b6746d0cb6a82fe5b23sberlin        return ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Injector.class)));
444aab9eba90f6aa02ad3b87b6746d0cb6a82fe5b23sberlin      } else {
445aab9eba90f6aa02ad3b87b6746d0cb6a82fe5b23sberlin        return dependencies;
446aab9eba90f6aa02ad3b87b6746d0cb6a82fe5b23sberlin      }
447ddb3862415e078080293abba05f1a24a921c007climpbizkit    }
448ddb3862415e078080293abba05f1a24a921c007climpbizkit
4497c533acbed7ce9c051e847a290dd2060915e91aalimpbizkit    @Override public boolean equals(Object o) {
45083b510c924832d38df1a3030e69863098432fffblimpbizkit      return o instanceof RealMultibinder
451e97e15b186baa9fc874eabdf5d293d3f47acebfclimpbizkit          && ((RealMultibinder<?>) o).setKey.equals(setKey);
4525019270849439d3aa58bc086a4514d7471716a35limpbizkit    }
4537c533acbed7ce9c051e847a290dd2060915e91aalimpbizkit
4547c533acbed7ce9c051e847a290dd2060915e91aalimpbizkit    @Override public int hashCode() {
455c913489bebe76fb0b6b430010c69b66164b52b4dlimpbizkit      return setKey.hashCode();
4567c533acbed7ce9c051e847a290dd2060915e91aalimpbizkit    }
4577c533acbed7ce9c051e847a290dd2060915e91aalimpbizkit
4587c533acbed7ce9c051e847a290dd2060915e91aalimpbizkit    @Override public String toString() {
459c00df28be8bfa45b2bdc8b4d3c101c20a9cbdc12Sam Berlin      return (setName.isEmpty() ? "" : setName + " ") + "Multibinder<" + elementType + ">";
4605019270849439d3aa58bc086a4514d7471716a35limpbizkit    }
4614faa20e3081448792933834aedfe972add806292Sam Berlin
4624faa20e3081448792933834aedfe972add806292Sam Berlin    final class RealMultibinderCollectionOfProvidersProvider
4634faa20e3081448792933834aedfe972add806292Sam Berlin        implements ProviderWithDependencies<Collection<Provider<T>>> {
4644faa20e3081448792933834aedfe972add806292Sam Berlin      @Override public Collection<Provider<T>> get() {
4654faa20e3081448792933834aedfe972add806292Sam Berlin        checkConfiguration(isInitialized(), "Multibinder is not initialized");
466b159fc53326acc2a224b51f954e15f62fe1356d0lukes        int size = bindings.size();
467b159fc53326acc2a224b51f954e15f62fe1356d0lukes        @SuppressWarnings("unchecked")  // safe because we only put Provider<T> into it.
468b159fc53326acc2a224b51f954e15f62fe1356d0lukes        Provider<T>[] providers = new Provider[size];
469b159fc53326acc2a224b51f954e15f62fe1356d0lukes        for (int i = 0; i < size; i++) {
470b159fc53326acc2a224b51f954e15f62fe1356d0lukes          providers[i] = bindings.get(i).getProvider();
4714faa20e3081448792933834aedfe972add806292Sam Berlin        }
472b159fc53326acc2a224b51f954e15f62fe1356d0lukes        return ImmutableList.copyOf(providers);
4734faa20e3081448792933834aedfe972add806292Sam Berlin      }
4744faa20e3081448792933834aedfe972add806292Sam Berlin
4754faa20e3081448792933834aedfe972add806292Sam Berlin      @Override public Set<Dependency<?>> getDependencies() {
4764faa20e3081448792933834aedfe972add806292Sam Berlin        if (!isInitialized()) {
4774faa20e3081448792933834aedfe972add806292Sam Berlin          return ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Injector.class)));
4784faa20e3081448792933834aedfe972add806292Sam Berlin        }
4794faa20e3081448792933834aedfe972add806292Sam Berlin        ImmutableSet.Builder<Dependency<?>> setBuilder = ImmutableSet.builder();
4804faa20e3081448792933834aedfe972add806292Sam Berlin        for (Dependency<?> dependency : dependencies) {
4814faa20e3081448792933834aedfe972add806292Sam Berlin          Key key = dependency.getKey();
4824faa20e3081448792933834aedfe972add806292Sam Berlin          setBuilder.add(
4834faa20e3081448792933834aedfe972add806292Sam Berlin              Dependency.get(key.ofType(Types.providerOf(key.getTypeLiteral().getType()))));
4844faa20e3081448792933834aedfe972add806292Sam Berlin        }
4854faa20e3081448792933834aedfe972add806292Sam Berlin        return setBuilder.build();
4864faa20e3081448792933834aedfe972add806292Sam Berlin      }
4874faa20e3081448792933834aedfe972add806292Sam Berlin
4884faa20e3081448792933834aedfe972add806292Sam Berlin      Key getCollectionKey() {
4894faa20e3081448792933834aedfe972add806292Sam Berlin        return RealMultibinder.this.collectionOfProvidersKey;
4904faa20e3081448792933834aedfe972add806292Sam Berlin      }
4914faa20e3081448792933834aedfe972add806292Sam Berlin
4924faa20e3081448792933834aedfe972add806292Sam Berlin      @Override public boolean equals(Object o) {
4934faa20e3081448792933834aedfe972add806292Sam Berlin        return o instanceof Multibinder.RealMultibinder.RealMultibinderCollectionOfProvidersProvider
4944faa20e3081448792933834aedfe972add806292Sam Berlin            && ((Multibinder.RealMultibinder.RealMultibinderCollectionOfProvidersProvider) o)
4954faa20e3081448792933834aedfe972add806292Sam Berlin                .getCollectionKey().equals(getCollectionKey());
4964faa20e3081448792933834aedfe972add806292Sam Berlin      }
4974faa20e3081448792933834aedfe972add806292Sam Berlin
4984faa20e3081448792933834aedfe972add806292Sam Berlin      @Override public int hashCode() {
4994faa20e3081448792933834aedfe972add806292Sam Berlin        return getCollectionKey().hashCode();
5004faa20e3081448792933834aedfe972add806292Sam Berlin      }
5014faa20e3081448792933834aedfe972add806292Sam Berlin    }
5025019270849439d3aa58bc086a4514d7471716a35limpbizkit  }
50372d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit
504398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit  /**
505398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit   * We install the permit duplicates configuration as its own binding, all by itself. This way,
506136dd75b214b44ee605b08bdd70111d9f3cb41falimpbizkit   * if only one of a multibinder's users remember to call permitDuplicates(), they're still
507398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit   * permitted.
508398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit   */
509398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit  private static class PermitDuplicatesModule extends AbstractModule {
510398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit    private final Key<Boolean> key;
511398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit
512398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit    PermitDuplicatesModule(Key<Boolean> key) {
513398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit      this.key = key;
514398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit    }
515398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit
5164faa20e3081448792933834aedfe972add806292Sam Berlin    @Override protected void configure() {
517398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit      bind(key).toInstance(true);
518398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit    }
519398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit
520398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit    @Override public boolean equals(Object o) {
521398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit      return o instanceof PermitDuplicatesModule
522398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit          && ((PermitDuplicatesModule) o).key.equals(key);
523398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit    }
524398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit
525398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit    @Override public int hashCode() {
526398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit      return getClass().hashCode() ^ key.hashCode();
527398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit    }
528398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit  }
529398017ae4ed96750fa54dc9ce59dc2f974dcf541limpbizkit
53072d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit  static void checkConfiguration(boolean condition, String format, Object... args) {
53172d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit    if (condition) {
53272d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit      return;
53372d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit    }
53472d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit
535b1f42f5df9c4cd8e157a28c24c4e8eb627a7f052limpbizkit    throw new ConfigurationException(ImmutableSet.of(new Message(Errors.format(format, args))));
53672d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit  }
53772d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit
5383d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber  private static <T> ConfigurationException newDuplicateValuesException(
5393d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber      Map<T, Binding<T>> existingBindings,
5403d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber      Binding<T> binding,
5413d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber      final T newValue,
5423d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber      Binding<T> duplicateBinding) {
5433d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber    T oldValue = getOnlyElement(filter(existingBindings.keySet(), equalTo(newValue)));
5443d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber    String oldString = oldValue.toString();
5453d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber    String newString = newValue.toString();
5463d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber    if (Objects.equal(oldString, newString)) {
5473d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber      // When the value strings match, just show the source of the bindings
5483d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber      return new ConfigurationException(ImmutableSet.of(new Message(Errors.format(
5493d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber          "Set injection failed due to duplicated element \"%s\""
5503d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber              + "\n    Bound at %s\n    Bound at %s",
5513d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber          newValue,
5523d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber          duplicateBinding.getSource(),
5533d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber          binding.getSource()))));
5543d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber    } else {
5553d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber      // When the value strings don't match, include them both as they may be useful for debugging
5563d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber      return new ConfigurationException(ImmutableSet.of(new Message(Errors.format(
5573d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber          "Set injection failed due to multiple elements comparing equal:"
5583d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber              + "\n    \"%s\"\n        bound at %s"
5593d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber              + "\n    \"%s\"\n        bound at %s",
5603d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber          oldValue,
5613d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber          duplicateBinding.getSource(),
5623d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber          newValue,
5633d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber          binding.getSource()))));
5643d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber    }
5653d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber  }
5663d3a9fa2eba286d8408ea933a28a0dcce6d7f7d1Christian Edward Gruber
56772d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit  static <T> T checkNotNull(T reference, String name) {
56872d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit    if (reference != null) {
56972d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit      return reference;
57072d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit    }
57172d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit
57272d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit    NullPointerException npe = new NullPointerException(name);
57372d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit    throw new ConfigurationException(ImmutableSet.of(
5740e896db46024dc7596302f8622276d1c7df02c6bSam Berlin        new Message(npe.toString(), npe)));
57572d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit  }
576e97e15b186baa9fc874eabdf5d293d3f47acebfclimpbizkit}
577