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<Snack> 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<Snack> 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