OptionalBinder.java revision 842f351c4b2b3b0a90d9f3bcf164d8fd19aede6c
1af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber/** 2af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * Copyright (C) 2014 Google Inc. 3af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 4af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * Licensed under the Apache License, Version 2.0 (the "License"); 5af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * you may not use this file except in compliance with the License. 6af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * You may obtain a copy of the License at 7af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 8af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * http://www.apache.org/licenses/LICENSE-2.0 9af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 10af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * Unless required by applicable law or agreed to in writing, software 11af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * distributed under the License is distributed on an "AS IS" BASIS, 12af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * See the License for the specific language governing permissions and 14af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * limitations under the License. 15af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber */ 16af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 17af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberpackage com.google.inject.multibindings; 18af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 19af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport static com.google.common.base.Preconditions.checkNotNull; 20af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport static com.google.inject.multibindings.Multibinder.checkConfiguration; 21af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport static com.google.inject.util.Types.newParameterizedType; 22c66f08e3d6798e88f35be51679854568f337e7ebSam Berlinimport static java.lang.annotation.RetentionPolicy.RUNTIME; 23af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 24af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.common.base.Optional; 25af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.common.collect.ImmutableSet; 26af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.Binder; 27af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.Binding; 28af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.Inject; 29af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.Injector; 30af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.Key; 31af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.Module; 32af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.Provider; 33af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.TypeLiteral; 34af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.binder.LinkedBindingBuilder; 35af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.spi.BindingTargetVisitor; 36af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.spi.Dependency; 37c66f08e3d6798e88f35be51679854568f337e7ebSam Berlinimport com.google.inject.spi.Element; 38af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.spi.ProviderInstanceBinding; 39af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.spi.ProviderLookup; 40af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.spi.ProviderWithDependencies; 41af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.spi.ProviderWithExtensionVisitor; 42af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.spi.Toolable; 43af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.util.Types; 44af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 45c66f08e3d6798e88f35be51679854568f337e7ebSam Berlinimport java.io.Serializable; 46c66f08e3d6798e88f35be51679854568f337e7ebSam Berlinimport java.lang.annotation.Annotation; 47c66f08e3d6798e88f35be51679854568f337e7ebSam Berlinimport java.lang.annotation.Retention; 48c66f08e3d6798e88f35be51679854568f337e7ebSam Berlinimport java.lang.reflect.Type; 49af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport java.util.Set; 50af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 51c66f08e3d6798e88f35be51679854568f337e7ebSam Berlinimport javax.inject.Qualifier; 52c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 53af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 54af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber/** 55af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * An API to bind optional values, optionally with a default value. 56af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * OptionalBinder fulfills two roles: <ol> 57af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <li>It allows a framework to define an injection point that may or 58af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * may not be bound by users. 59af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <li>It allows a framework to supply a default value that can be changed 60af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * by users. 61af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * </ol> 62af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 63af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <p>When an OptionalBinder is added, it will always supply the bindings: 64af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * {@code Optional<T>} and {@code Optional<Provider<T>>}. If 65af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * {@link #setBinding} or {@link #setDefault} are called, it will also 66af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * bind {@code T}. 67af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 68af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <p>{@code setDefault} is intended for use by frameworks that need a default 69af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * value. User code can call {@code setBinding} to override the default. 70af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <b>Warning: Even if setBinding is called, the default binding 71af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * will still exist in the object graph. If it is a singleton, it will be 72af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * instantiated in {@code Stage.PRODUCTION}.</b> 73af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 74af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <p>If setDefault or setBinding are linked to Providers, the Provider may return 75af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * {@code null}. If it does, the Optional bindings will be absent. Binding 76af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * setBinding to a Provider that returns null will not cause OptionalBinder 77af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * to fall back to the setDefault binding. 78af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 79842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * <p>If neither setDefault nor setBinding are called, it will try to link to a 80842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * user-supplied binding of the same type. If no binding exists, the optionals 81842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * will be absent. Otherwise, if a user-supplied binding of that type exists, 82842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * or if setBinding or setDefault are called, the optionals will return present 83842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * if they are bound to a non-null value. 84af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 85af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <p>Values are resolved at injection time. If a value is bound to a 86af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * provider, that provider's get method will be called each time the optional 87af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * is injected (unless the binding is also scoped, or an optional of provider is 88af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * injected). 89af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 90af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <p>Annotations are used to create different optionals of the same key/value 91af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * type. Each distinct annotation gets its own independent binding. 92af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 93af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <pre><code> 94af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * public class FrameworkModule extends AbstractModule { 95af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * protected void configure() { 96af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * OptionalBinder.newOptionalBinder(binder(), Renamer.class); 97af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * } 98af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * }</code></pre> 99af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 100af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <p>With this module, an {@link Optional}{@code <Renamer>} can now be 101842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * injected. With no other bindings, the optional will be absent. 102842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * Users can specify bindings in one of two ways: 103af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 104842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * <p>Option 1: 105842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * <pre><code> 106842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * public class UserRenamerModule extends AbstractModule { 107842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * protected void configure() { 108842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * bind(Renamer.class).to(ReplacingRenamer.class); 109842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * } 110842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * }</code></pre> 111842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * 112842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * <p>or Option 2: 113af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <pre><code> 114af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * public class UserRenamerModule extends AbstractModule { 115af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * protected void configure() { 116af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * OptionalBinder.newOptionalBinder(binder(), Renamer.class) 117af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * .setBinding().to(ReplacingRenamer.class); 118af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * } 119af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * }</code></pre> 120842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * With both options, the {@code Optional<Renamer>} will be present and supply the 121842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * ReplacingRenamer. 122af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 123af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <p>Default values can be supplied using: 124af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <pre><code> 125af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * public class FrameworkModule extends AbstractModule { 126af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * protected void configure() { 127af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, LookupUrl.class)) 128af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * .setDefault().to(DEFAULT_LOOKUP_URL); 129af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * } 130af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * }</code></pre> 131af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * With the above module, code can inject an {@code @LookupUrl String} and it 132af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * will supply the DEFAULT_LOOKUP_URL. A user can change this value by binding 133af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <pre><code> 134af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * public class UserLookupModule extends AbstractModule { 135af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * protected void configure() { 136af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, LookupUrl.class)) 137af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * .setBinding().to(CUSTOM_LOOKUP_URL); 138af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * } 139af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * }</code></pre> 140af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * ... which will override the default value. 141842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * 142842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * <p>If one module uses setDefault the only way to override the default is to use setBinding. 143842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * It is an error for a user to specify the binding without using OptionalBinder if 144842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * setDefault or setBinding are called. For example, 145842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * <pre><code> 146842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * public class FrameworkModule extends AbstractModule { 147842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * protected void configure() { 148842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, LookupUrl.class)) 149842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * .setDefault().to(DEFAULT_LOOKUP_URL); 150842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * } 151842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * } 152842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * public class UserLookupModule extends AbstractModule { 153842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * protected void configure() { 154842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * bind(Key.get(String.class, LookupUrl.class)).to(CUSTOM_LOOKUP_URL); 155842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * } 156842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * }</code></pre> 157842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * ... would generate an error, because both the framework and the user are trying to bind 158842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * {@code @LookupUrl String}. 159af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 160af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * @author sameb@google.com (Sam Berlin) 161af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber */ 162af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberpublic abstract class OptionalBinder<T> { 163af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private OptionalBinder() {} 164af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 165af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber public static <T> OptionalBinder<T> newOptionalBinder(Binder binder, Class<T> type) { 166af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return newOptionalBinder(binder, Key.get(type)); 167af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 168af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 169af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber public static <T> OptionalBinder<T> newOptionalBinder(Binder binder, TypeLiteral<T> type) { 170af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return newOptionalBinder(binder, Key.get(type)); 171af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 172af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 173af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber public static <T> OptionalBinder<T> newOptionalBinder(Binder binder, Key<T> type) { 174af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber binder = binder.skipSources(OptionalBinder.class, RealOptionalBinder.class); 175af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber RealOptionalBinder<T> optionalBinder = new RealOptionalBinder<T>(binder, type); 176af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber binder.install(optionalBinder); 177af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return optionalBinder; 178af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 179af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 180af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber @SuppressWarnings("unchecked") 181af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber static <T> TypeLiteral<Optional<T>> optionalOf( 182af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber TypeLiteral<T> type) { 183af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return (TypeLiteral<Optional<T>>) TypeLiteral.get( 184af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Types.newParameterizedType(Optional.class, type.getType())); 185af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 186af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 187af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber @SuppressWarnings("unchecked") 188af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber static <T> TypeLiteral<Optional<javax.inject.Provider<T>>> optionalOfJavaxProvider( 189af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber TypeLiteral<T> type) { 190af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return (TypeLiteral<Optional<javax.inject.Provider<T>>>) TypeLiteral.get( 191af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Types.newParameterizedType(Optional.class, 192af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber newParameterizedType(javax.inject.Provider.class, type.getType()))); 193af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 194af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 195af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber @SuppressWarnings("unchecked") 196af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber static <T> TypeLiteral<Optional<Provider<T>>> optionalOfProvider(TypeLiteral<T> type) { 197af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return (TypeLiteral<Optional<Provider<T>>>) TypeLiteral.get(Types.newParameterizedType( 198af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Optional.class, newParameterizedType(Provider.class, type.getType()))); 199af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 200c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 201c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin @SuppressWarnings("unchecked") 202c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin static <T> Key<Provider<T>> providerOf(Key<T> key) { 203c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin Type providerT = Types.providerOf(key.getTypeLiteral().getType()); 204c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin return (Key<Provider<T>>) key.ofType(providerT); 205c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 206af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 207af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber /** 208af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * Returns a binding builder used to set the default value that will be injected. 209af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * The binding set by this method will be ignored if {@link #setBinding} is called. 210af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 211af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <p>It is an error to call this method without also calling one of the {@code to} 212af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * methods on the returned binding builder. 213af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber */ 214af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber public abstract LinkedBindingBuilder<T> setDefault(); 215af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 216af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 217af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber /** 218af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * Returns a binding builder used to set the actual value that will be injected. 219af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * This overrides any binding set by {@link #setDefault}. 220af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 221af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <p>It is an error to call this method without also calling one of the {@code to} 222af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * methods on the returned binding builder. 223af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber */ 224af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber public abstract LinkedBindingBuilder<T> setBinding(); 225af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 226af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber enum Source { DEFAULT, ACTUAL } 227c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 228c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin @Retention(RUNTIME) 229c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin @Qualifier 230c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin @interface Default { 231c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin String value(); 232c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 233c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 234c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin @Retention(RUNTIME) 235c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin @Qualifier 236c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin @interface Actual { 237c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin String value(); 238c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 239af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 240af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber /** 241af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * The actual OptionalBinder plays several roles. It implements Module to hide that 242af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * fact from the public API, and installs the various bindings that are exposed to the user. 243af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber */ 244af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber static final class RealOptionalBinder<T> extends OptionalBinder<T> implements Module { 245af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private final Key<T> typeKey; 246af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private final Key<Optional<T>> optionalKey; 247af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private final Key<Optional<javax.inject.Provider<T>>> optionalJavaxProviderKey; 248af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private final Key<Optional<Provider<T>>> optionalProviderKey; 249af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private final Provider<Optional<Provider<T>>> optionalProviderT; 250c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin private final Key<T> defaultKey; 251c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin private final Key<T> actualKey; 252af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 253af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber /** the target injector's binder. non-null until initialization, null afterwards */ 254af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private Binder binder; 255af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber /** the default binding, for the SPI. */ 256c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin private Binding<T> defaultBinding; 257af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber /** the actual binding, for the SPI */ 258c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin private Binding<T> actualBinding; 259c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 260c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin /** the dependencies -- initialized with defaults & overridden when tooled. */ 261c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin private Set<Dependency<?>> dependencies; 262c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin /** the dependencies -- initialized with defaults & overridden when tooled. */ 263c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin private Set<Dependency<?>> providerDependencies; 264af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 265af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private RealOptionalBinder(Binder binder, Key<T> typeKey) { 266af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber this.binder = binder; 267af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber this.typeKey = checkNotNull(typeKey); 268af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber TypeLiteral<T> literal = typeKey.getTypeLiteral(); 269af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber this.optionalKey = typeKey.ofType(optionalOf(literal)); 270af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber this.optionalJavaxProviderKey = typeKey.ofType(optionalOfJavaxProvider(literal)); 271af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber this.optionalProviderKey = typeKey.ofType(optionalOfProvider(literal)); 272af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber this.optionalProviderT = binder.getProvider(optionalProviderKey); 273c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin String name = RealElement.nameOf(typeKey); 274c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin this.defaultKey = Key.get(typeKey.getTypeLiteral(), new DefaultImpl(name)); 275c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin this.actualKey = Key.get(typeKey.getTypeLiteral(), new ActualImpl(name)); 276c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin // Until the injector initializes us, we don't know what our dependencies are, 277c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin // so initialize to the whole Injector (like Multibinder, and MapBinder indirectly). 278c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin this.dependencies = ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Injector.class))); 279c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin this.providerDependencies = 280c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Injector.class))); 281af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 282af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 283af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber /** 284af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * Adds a binding for T. Multiple calls to this are safe, and will be collapsed as duplicate 285af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * bindings. 286af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber */ 287af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private void addDirectTypeBinding(Binder binder) { 288af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber binder.bind(typeKey).toProvider(new RealOptionalBinderProviderWithDependencies<T>(typeKey) { 289842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin @Override public T get() { 290af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Optional<Provider<T>> optional = optionalProviderT.get(); 291af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (optional.isPresent()) { 292af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return optional.get().get(); 293af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 294af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber // Let Guice handle blowing up if the injection point doesn't have @Nullable 295af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber // (If it does have @Nullable, that's fine. This would only happen if 296af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber // setBinding/setDefault themselves were bound to 'null'). 297af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return null; 298af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 299af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 300842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin @Override public Set<Dependency<?>> getDependencies() { 301af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return dependencies; 302af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 303af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber }); 304af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 305af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 306af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber @Override public LinkedBindingBuilder<T> setDefault() { 307c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin checkConfiguration(!isInitialized(), "already initialized"); 308af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber addDirectTypeBinding(binder); 309c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin return binder.bind(defaultKey); 310af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 311af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 312af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber @Override public LinkedBindingBuilder<T> setBinding() { 313c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin checkConfiguration(!isInitialized(), "already initialized"); 314af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber addDirectTypeBinding(binder); 315c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin return binder.bind(actualKey); 316af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 317af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 318842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin @Override public void configure(Binder binder) { 319af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber checkConfiguration(!isInitialized(), "OptionalBinder was already initialized"); 320af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 321af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber binder.bind(optionalProviderKey).toProvider( 322af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber new RealOptionalBinderProviderWithDependencies<Optional<Provider<T>>>(typeKey) { 323af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private Optional<Provider<T>> optional; 324af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 325af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber @Toolable @Inject void initialize(Injector injector) { 326af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber RealOptionalBinder.this.binder = null; 327c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin actualBinding = injector.getExistingBinding(actualKey); 328c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin defaultBinding = injector.getExistingBinding(defaultKey); 329842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin Binding<T> userBinding = injector.getExistingBinding(typeKey); 330c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin Binding<T> binding = null; 331c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin if (actualBinding != null) { 332c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin // TODO(sameb): Consider exposing an option that will allow 333c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin // ACTUAL to fallback to DEFAULT if ACTUAL's provider returns null. 334c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin // Right now, an ACTUAL binding can convert from present -> absent 335c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin // if it's bound to a provider that returns null. 336c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin binding = actualBinding; 337c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } else if (defaultBinding != null) { 338c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin binding = defaultBinding; 339842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin } else if (userBinding != null) { 340842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin // If neither the actual or default is set, then we fallback 341842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin // to the value bound to the type itself and consider that the 342842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin // "actual binding" for the SPI. 343842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin binding = userBinding; 344842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin actualBinding = userBinding; 345c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 346c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 347c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin if (binding != null) { 348c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin optional = Optional.of(binding.getProvider()); 349c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin RealOptionalBinder.this.dependencies = 350c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin ImmutableSet.<Dependency<?>>of(Dependency.get(binding.getKey())); 351c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin RealOptionalBinder.this.providerDependencies = 352c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin ImmutableSet.<Dependency<?>>of(Dependency.get(providerOf(binding.getKey()))); 353c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } else { 354c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin optional = Optional.absent(); 355c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin RealOptionalBinder.this.dependencies = ImmutableSet.of(); 356c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin RealOptionalBinder.this.providerDependencies = ImmutableSet.of(); 357af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 358af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 359af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 360842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin @Override public Optional<Provider<T>> get() { 361af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return optional; 362af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 363af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 364842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin @Override public Set<Dependency<?>> getDependencies() { 365c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin return providerDependencies; 366af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 367af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber }); 368af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 369af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber // Optional is immutable, so it's safe to expose Optional<Provider<T>> as 370af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber // Optional<javax.inject.Provider<T>> (since Guice provider implements javax Provider). 371af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber @SuppressWarnings({"unchecked", "cast"}) 372af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Key massagedOptionalProviderKey = (Key) optionalProviderKey; 373af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber binder.bind(optionalJavaxProviderKey).to(massagedOptionalProviderKey); 374af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 375af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber binder.bind(optionalKey).toProvider(new RealOptionalKeyProvider()); 376af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 377af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 378af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private class RealOptionalKeyProvider 379af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber extends RealOptionalBinderProviderWithDependencies<Optional<T>> 380af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber implements ProviderWithExtensionVisitor<Optional<T>>, 381af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber OptionalBinderBinding<Optional<T>>, 382af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Provider<Optional<T>> { 383af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber RealOptionalKeyProvider() { 384c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin super(typeKey); 385af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 386af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 387842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin @Override public Optional<T> get() { 388af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Optional<Provider<T>> optional = optionalProviderT.get(); 389af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (optional.isPresent()) { 390af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return Optional.fromNullable(optional.get().get()); 391af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } else { 392af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return Optional.absent(); 393af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 394af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 395af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 396842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin @Override public Set<Dependency<?>> getDependencies() { 397af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return dependencies; 398af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 399af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 400af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber @SuppressWarnings("unchecked") 401842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin @Override 402af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber public <B, R> R acceptExtensionVisitor(BindingTargetVisitor<B, R> visitor, 403af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber ProviderInstanceBinding<? extends B> binding) { 404af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (visitor instanceof MultibindingsTargetVisitor) { 405af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return ((MultibindingsTargetVisitor<Optional<T>, R>) visitor).visit(this); 406af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } else { 407af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return visitor.visit(binding); 408af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 409af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 410af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 411842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin @Override public Key<Optional<T>> getKey() { 412af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return optionalKey; 413af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 414af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 415842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin @Override public Binding<?> getActualBinding() { 416af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (isInitialized()) { 417af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return actualBinding; 418af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } else { 419af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber throw new UnsupportedOperationException( 420af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber "getActualBinding() not supported from Elements.getElements, requires an Injector."); 421af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 422af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 423af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 424842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin @Override public Binding<?> getDefaultBinding() { 425af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (isInitialized()) { 426af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return defaultBinding; 427af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } else { 428af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber throw new UnsupportedOperationException( 429af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber "getDefaultBinding() not supported from Elements.getElements, requires an Injector."); 430af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 431af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 432af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 433842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin @Override public boolean containsElement(Element element) { 434c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin Key<?> elementKey; 435c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin if (element instanceof Binding) { 436c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin elementKey = ((Binding<?>) element).getKey(); 437c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } else if (element instanceof ProviderLookup) { 438c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin elementKey = ((ProviderLookup<?>) element).getKey(); 439af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } else { 440c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin return false; // cannot match; 4418f89a23e16435f81bd4e083185f2f2c5a520f954Sam Berlin } 442c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 443c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin return elementKey.equals(optionalKey) 444c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin || elementKey.equals(optionalProviderKey) 445c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin || elementKey.equals(optionalJavaxProviderKey) 446c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin || elementKey.equals(defaultKey) 447c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin || elementKey.equals(actualKey) 448c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin || matchesTypeKey(element, elementKey); 449af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 450af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 451af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 452af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber /** Returns true if the key & element indicate they were bound by this OptionalBinder. */ 453c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin private boolean matchesTypeKey(Element element, Key<?> elementKey) { 454af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber // Just doing .equals(typeKey) isn't enough, because the user can bind that themselves. 455af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return elementKey.equals(typeKey) 456af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber && element instanceof ProviderInstanceBinding 457af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber && (((ProviderInstanceBinding) element) 458af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber .getUserSuppliedProvider() instanceof RealOptionalBinderProviderWithDependencies); 459af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 460af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 461af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private boolean isInitialized() { 462af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return binder == null; 463af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 464af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 465af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber @Override public boolean equals(Object o) { 466af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return o instanceof RealOptionalBinder 467c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin && ((RealOptionalBinder<?>) o).typeKey.equals(typeKey); 468af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 469af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 470af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber @Override public int hashCode() { 471c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin return typeKey.hashCode(); 472af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 473af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 474af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber /** 475af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * A base class for ProviderWithDependencies that need equality based on a specific object. 476af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber */ 477af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private abstract static class RealOptionalBinderProviderWithDependencies<T> implements 478af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber ProviderWithDependencies<T> { 479af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private final Object equality; 480af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 481af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber public RealOptionalBinderProviderWithDependencies(Object equality) { 482af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber this.equality = equality; 483af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 484af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 485842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin @Override public boolean equals(Object obj) { 486af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return this.getClass() == obj.getClass() 487af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber && equality.equals(((RealOptionalBinderProviderWithDependencies<?>) obj).equality); 488af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 489af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 490842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin @Override public int hashCode() { 491af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return equality.hashCode(); 492af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 493af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 494af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 495c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 496c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin static class DefaultImpl extends BaseAnnotation implements Default { 497c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin public DefaultImpl(String value) { 498c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin super(Default.class, value); 499c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 500c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 501c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 502c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin static class ActualImpl extends BaseAnnotation implements Actual { 503c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin public ActualImpl(String value) { 504c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin super(Actual.class, value); 505c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 506c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 507c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 508c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin abstract static class BaseAnnotation implements Serializable, Annotation { 509c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 510c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin private final String value; 511c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin private final Class<? extends Annotation> clazz; 512c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 513c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin BaseAnnotation(Class<? extends Annotation> clazz, String value) { 514c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin this.clazz = checkNotNull(clazz, "clazz"); 515c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin this.value = checkNotNull(value, "value"); 516c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 517c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 518c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin public String value() { 519c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin return this.value; 520c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 521c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 522c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin @Override public int hashCode() { 523c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin // This is specified in java.lang.Annotation. 524c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin return (127 * "value".hashCode()) ^ value.hashCode(); 525c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 526c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 527c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin @Override public boolean equals(Object o) { 528c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin if (!(clazz.isInstance(o))) { 529c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin return false; 530c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 531c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 532c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin BaseAnnotation other = (BaseAnnotation) o; 533c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin return value.equals(other.value()); 534c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 535c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 536c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin @Override public String toString() { 537c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin return "@" + clazz.getName() + (value.isEmpty() ? "" : "(value=" + value + ")"); 538c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 539c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 540c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin @Override public Class<? extends Annotation> annotationType() { 541c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin return clazz; 542c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 543c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 544c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin private static final long serialVersionUID = 0; 545c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 546af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber} 547