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; 201d3f8cd0a163c7439589d80e6377edbf2ca4b43dsamebimport static com.google.common.base.Preconditions.checkState; 21af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport static com.google.inject.multibindings.Multibinder.checkConfiguration; 22af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport static com.google.inject.util.Types.newParameterizedType; 23c66f08e3d6798e88f35be51679854568f337e7ebSam Berlinimport static java.lang.annotation.RetentionPolicy.RUNTIME; 24af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 25af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.common.base.Optional; 261d3f8cd0a163c7439589d80e6377edbf2ca4b43dsamebimport com.google.common.base.Throwables; 27af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.common.collect.ImmutableSet; 28af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.Binder; 29af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.Binding; 30af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.Inject; 31af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.Injector; 32af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.Key; 33af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.Module; 34af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.Provider; 35af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.TypeLiteral; 36af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.binder.LinkedBindingBuilder; 37af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.spi.BindingTargetVisitor; 38af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.spi.Dependency; 39c66f08e3d6798e88f35be51679854568f337e7ebSam Berlinimport com.google.inject.spi.Element; 40af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.spi.ProviderInstanceBinding; 41af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.spi.ProviderLookup; 42af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.spi.ProviderWithDependencies; 43af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.spi.ProviderWithExtensionVisitor; 44af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.spi.Toolable; 45af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport com.google.inject.util.Types; 46af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 47c66f08e3d6798e88f35be51679854568f337e7ebSam Berlinimport java.io.Serializable; 48c66f08e3d6798e88f35be51679854568f337e7ebSam Berlinimport java.lang.annotation.Annotation; 49c66f08e3d6798e88f35be51679854568f337e7ebSam Berlinimport java.lang.annotation.Retention; 501d3f8cd0a163c7439589d80e6377edbf2ca4b43dsamebimport java.lang.reflect.InvocationTargetException; 511d3f8cd0a163c7439589d80e6377edbf2ca4b43dsamebimport java.lang.reflect.Method; 52c66f08e3d6798e88f35be51679854568f337e7ebSam Berlinimport java.lang.reflect.Type; 53af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberimport java.util.Set; 54af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 55c66f08e3d6798e88f35be51679854568f337e7ebSam Berlinimport javax.inject.Qualifier; 56c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 57af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 58af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber/** 59af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * An API to bind optional values, optionally with a default value. 60af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * OptionalBinder fulfills two roles: <ol> 61af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <li>It allows a framework to define an injection point that may or 62af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * may not be bound by users. 63af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <li>It allows a framework to supply a default value that can be changed 64af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * by users. 65af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * </ol> 66af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 67af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <p>When an OptionalBinder is added, it will always supply the bindings: 68af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * {@code Optional<T>} and {@code Optional<Provider<T>>}. If 69af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * {@link #setBinding} or {@link #setDefault} are called, it will also 70af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * bind {@code T}. 71af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 72af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <p>{@code setDefault} is intended for use by frameworks that need a default 73af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * value. User code can call {@code setBinding} to override the default. 74af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <b>Warning: Even if setBinding is called, the default binding 75af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * will still exist in the object graph. If it is a singleton, it will be 76af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * instantiated in {@code Stage.PRODUCTION}.</b> 77af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 78af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <p>If setDefault or setBinding are linked to Providers, the Provider may return 79af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * {@code null}. If it does, the Optional bindings will be absent. Binding 80af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * setBinding to a Provider that returns null will not cause OptionalBinder 81af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * to fall back to the setDefault binding. 82af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 83842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * <p>If neither setDefault nor setBinding are called, it will try to link to a 84842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * user-supplied binding of the same type. If no binding exists, the optionals 85842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * will be absent. Otherwise, if a user-supplied binding of that type exists, 86842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * or if setBinding or setDefault are called, the optionals will return present 87842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * if they are bound to a non-null value. 88af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 89af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <p>Values are resolved at injection time. If a value is bound to a 90af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * provider, that provider's get method will be called each time the optional 91af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * is injected (unless the binding is also scoped, or an optional of provider is 92af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * injected). 93af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 94af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <p>Annotations are used to create different optionals of the same key/value 95af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * type. Each distinct annotation gets its own independent binding. 96af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 97af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <pre><code> 98af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * public class FrameworkModule extends AbstractModule { 99af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * protected void configure() { 100af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * OptionalBinder.newOptionalBinder(binder(), Renamer.class); 101af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * } 102af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * }</code></pre> 103af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 104af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <p>With this module, an {@link Optional}{@code <Renamer>} can now be 105842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * injected. With no other bindings, the optional will be absent. 106842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * Users can specify bindings in one of two ways: 107af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 108842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * <p>Option 1: 109842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * <pre><code> 110842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * public class UserRenamerModule extends AbstractModule { 111842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * protected void configure() { 112842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * bind(Renamer.class).to(ReplacingRenamer.class); 113842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * } 114842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * }</code></pre> 115842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * 116842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * <p>or Option 2: 117af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <pre><code> 118af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * public class UserRenamerModule extends AbstractModule { 119af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * protected void configure() { 120af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * OptionalBinder.newOptionalBinder(binder(), Renamer.class) 121af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * .setBinding().to(ReplacingRenamer.class); 122af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * } 123af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * }</code></pre> 124842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * With both options, the {@code Optional<Renamer>} will be present and supply the 125842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * ReplacingRenamer. 126af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 127af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <p>Default values can be supplied using: 128af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <pre><code> 129af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * public class FrameworkModule extends AbstractModule { 130af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * protected void configure() { 131af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, LookupUrl.class)) 13232780fa2a30bb10f7c85a0a43845308af7bcefddchristophf * .setDefault().toInstance(DEFAULT_LOOKUP_URL); 133af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * } 134af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * }</code></pre> 135af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * With the above module, code can inject an {@code @LookupUrl String} and it 136af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * will supply the DEFAULT_LOOKUP_URL. A user can change this value by binding 137af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <pre><code> 138af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * public class UserLookupModule extends AbstractModule { 139af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * protected void configure() { 140af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, LookupUrl.class)) 14132780fa2a30bb10f7c85a0a43845308af7bcefddchristophf * .setBinding().toInstance(CUSTOM_LOOKUP_URL); 142af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * } 143af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * }</code></pre> 144af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * ... which will override the default value. 145842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * 146842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * <p>If one module uses setDefault the only way to override the default is to use setBinding. 147842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * It is an error for a user to specify the binding without using OptionalBinder if 148842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * setDefault or setBinding are called. For example, 149842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * <pre><code> 150842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * public class FrameworkModule extends AbstractModule { 151842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * protected void configure() { 152842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, LookupUrl.class)) 15332780fa2a30bb10f7c85a0a43845308af7bcefddchristophf * .setDefault().toInstance(DEFAULT_LOOKUP_URL); 154842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * } 155842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * } 156842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * public class UserLookupModule extends AbstractModule { 157842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * protected void configure() { 15832780fa2a30bb10f7c85a0a43845308af7bcefddchristophf * bind(Key.get(String.class, LookupUrl.class)).toInstance(CUSTOM_LOOKUP_URL); 159842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * } 160842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * }</code></pre> 161842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * ... would generate an error, because both the framework and the user are trying to bind 162842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin * {@code @LookupUrl String}. 163af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 164af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * @author sameb@google.com (Sam Berlin) 165bac730fa1b717351736182034aff62827a383090Ben McCann * @since 4.0 166af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber */ 167af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruberpublic abstract class OptionalBinder<T> { 1681d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 1691d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb /* Reflectively capture java 8's Optional types so we can bind them if we're running in java8. */ 1701d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb private static final Class<?> JAVA_OPTIONAL_CLASS; 1711d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb private static final Method JAVA_EMPTY_METHOD; 1721d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb private static final Method JAVA_OF_NULLABLE_METHOD; 1731d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb static { 1741d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb Class<?> optional = null; 1751d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb Method empty = null; 1761d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb Method ofNullable = null; 1771d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb boolean useJavaOptional = false; 1781d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb try { 1791d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb optional = Class.forName("java.util.Optional"); 1801d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb empty = optional.getDeclaredMethod("empty"); 1811d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb ofNullable = optional.getDeclaredMethod("ofNullable", Object.class); 1821d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb useJavaOptional = true; 1831d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } catch (ClassNotFoundException ignored) { 1841d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } catch (NoSuchMethodException ignored) { 1851d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } catch (SecurityException ignored) { 1861d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 1871d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb JAVA_OPTIONAL_CLASS = useJavaOptional ? optional : null; 1881d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb JAVA_EMPTY_METHOD = useJavaOptional ? empty : null; 1891d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb JAVA_OF_NULLABLE_METHOD = useJavaOptional ? ofNullable : null; 1901d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 1911d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 192af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private OptionalBinder() {} 193af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 194af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber public static <T> OptionalBinder<T> newOptionalBinder(Binder binder, Class<T> type) { 1950b33461e35fa3a769ce23a9812a80acdc281f62csameb return newRealOptionalBinder(binder, Key.get(type)); 196af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 197af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 198af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber public static <T> OptionalBinder<T> newOptionalBinder(Binder binder, TypeLiteral<T> type) { 1990b33461e35fa3a769ce23a9812a80acdc281f62csameb return newRealOptionalBinder(binder, Key.get(type)); 200af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 201af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 202af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber public static <T> OptionalBinder<T> newOptionalBinder(Binder binder, Key<T> type) { 2030b33461e35fa3a769ce23a9812a80acdc281f62csameb return newRealOptionalBinder(binder, type); 2040b33461e35fa3a769ce23a9812a80acdc281f62csameb } 2050b33461e35fa3a769ce23a9812a80acdc281f62csameb 2060b33461e35fa3a769ce23a9812a80acdc281f62csameb static <T> RealOptionalBinder<T> newRealOptionalBinder(Binder binder, Key<T> type) { 207af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber binder = binder.skipSources(OptionalBinder.class, RealOptionalBinder.class); 208af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber RealOptionalBinder<T> optionalBinder = new RealOptionalBinder<T>(binder, type); 209af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber binder.install(optionalBinder); 210af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return optionalBinder; 211af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 212af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 213af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber @SuppressWarnings("unchecked") 214af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber static <T> TypeLiteral<Optional<T>> optionalOf( 215af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber TypeLiteral<T> type) { 216af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return (TypeLiteral<Optional<T>>) TypeLiteral.get( 217af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Types.newParameterizedType(Optional.class, type.getType())); 218af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 219af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 2201d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb static <T> TypeLiteral<?> javaOptionalOf( 2211d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb TypeLiteral<T> type) { 2221d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb checkState(JAVA_OPTIONAL_CLASS != null, "java.util.Optional not found"); 2231d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb return TypeLiteral.get(Types.newParameterizedType(JAVA_OPTIONAL_CLASS, type.getType())); 2241d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 2251d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 226af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber @SuppressWarnings("unchecked") 227af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber static <T> TypeLiteral<Optional<javax.inject.Provider<T>>> optionalOfJavaxProvider( 228af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber TypeLiteral<T> type) { 229af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return (TypeLiteral<Optional<javax.inject.Provider<T>>>) TypeLiteral.get( 230af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Types.newParameterizedType(Optional.class, 231af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber newParameterizedType(javax.inject.Provider.class, type.getType()))); 232af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 233af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 2341d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb static <T> TypeLiteral<?> javaOptionalOfJavaxProvider( 2351d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb TypeLiteral<T> type) { 2361d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb checkState(JAVA_OPTIONAL_CLASS != null, "java.util.Optional not found"); 2371d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb return TypeLiteral.get(Types.newParameterizedType(JAVA_OPTIONAL_CLASS, 2381d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb newParameterizedType(javax.inject.Provider.class, type.getType()))); 2391d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 2401d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 241af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber @SuppressWarnings("unchecked") 242af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber static <T> TypeLiteral<Optional<Provider<T>>> optionalOfProvider(TypeLiteral<T> type) { 243af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return (TypeLiteral<Optional<Provider<T>>>) TypeLiteral.get(Types.newParameterizedType( 244af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Optional.class, newParameterizedType(Provider.class, type.getType()))); 245af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 2461d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 2471d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb static <T> TypeLiteral<?> javaOptionalOfProvider(TypeLiteral<T> type) { 2481d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb checkState(JAVA_OPTIONAL_CLASS != null, "java.util.Optional not found"); 2491d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb return TypeLiteral.get(Types.newParameterizedType(JAVA_OPTIONAL_CLASS, 2501d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb newParameterizedType(Provider.class, type.getType()))); 2511d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 2521d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 253c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin @SuppressWarnings("unchecked") 254c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin static <T> Key<Provider<T>> providerOf(Key<T> key) { 255c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin Type providerT = Types.providerOf(key.getTypeLiteral().getType()); 256c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin return (Key<Provider<T>>) key.ofType(providerT); 257c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 258af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 259af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber /** 260af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * Returns a binding builder used to set the default value that will be injected. 261af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * The binding set by this method will be ignored if {@link #setBinding} is called. 262af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 263af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <p>It is an error to call this method without also calling one of the {@code to} 264af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * methods on the returned binding builder. 265af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber */ 266af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber public abstract LinkedBindingBuilder<T> setDefault(); 267af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 268af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 269af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber /** 270af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * Returns a binding builder used to set the actual value that will be injected. 271af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * This overrides any binding set by {@link #setDefault}. 272af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * 273af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * <p>It is an error to call this method without also calling one of the {@code to} 274af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * methods on the returned binding builder. 275af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber */ 276af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber public abstract LinkedBindingBuilder<T> setBinding(); 277af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 278af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber enum Source { DEFAULT, ACTUAL } 279c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 280c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin @Retention(RUNTIME) 281c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin @Qualifier 282c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin @interface Default { 283c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin String value(); 284c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 285c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 286c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin @Retention(RUNTIME) 287c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin @Qualifier 288c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin @interface Actual { 289c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin String value(); 290c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 291af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 292af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber /** 293af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * The actual OptionalBinder plays several roles. It implements Module to hide that 294af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * fact from the public API, and installs the various bindings that are exposed to the user. 295af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber */ 296af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber static final class RealOptionalBinder<T> extends OptionalBinder<T> implements Module { 297af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private final Key<T> typeKey; 298af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private final Key<Optional<T>> optionalKey; 299af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private final Key<Optional<javax.inject.Provider<T>>> optionalJavaxProviderKey; 300af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private final Key<Optional<Provider<T>>> optionalProviderKey; 301af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private final Provider<Optional<Provider<T>>> optionalProviderT; 302c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin private final Key<T> defaultKey; 303c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin private final Key<T> actualKey; 304af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 3051d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb private final Key javaOptionalKey; 3061d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb private final Key javaOptionalJavaxProviderKey; 3071d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb private final Key javaOptionalProviderKey; 3081d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 309af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber /** the target injector's binder. non-null until initialization, null afterwards */ 310af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private Binder binder; 311af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber /** the default binding, for the SPI. */ 312c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin private Binding<T> defaultBinding; 313af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber /** the actual binding, for the SPI */ 314c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin private Binding<T> actualBinding; 315c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 316c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin /** the dependencies -- initialized with defaults & overridden when tooled. */ 317c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin private Set<Dependency<?>> dependencies; 318c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin /** the dependencies -- initialized with defaults & overridden when tooled. */ 319c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin private Set<Dependency<?>> providerDependencies; 320af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 321af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private RealOptionalBinder(Binder binder, Key<T> typeKey) { 322af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber this.binder = binder; 323af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber this.typeKey = checkNotNull(typeKey); 324af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber TypeLiteral<T> literal = typeKey.getTypeLiteral(); 325af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber this.optionalKey = typeKey.ofType(optionalOf(literal)); 326af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber this.optionalJavaxProviderKey = typeKey.ofType(optionalOfJavaxProvider(literal)); 327af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber this.optionalProviderKey = typeKey.ofType(optionalOfProvider(literal)); 328af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber this.optionalProviderT = binder.getProvider(optionalProviderKey); 329c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin String name = RealElement.nameOf(typeKey); 330c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin this.defaultKey = Key.get(typeKey.getTypeLiteral(), new DefaultImpl(name)); 331c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin this.actualKey = Key.get(typeKey.getTypeLiteral(), new ActualImpl(name)); 332c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin // Until the injector initializes us, we don't know what our dependencies are, 333c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin // so initialize to the whole Injector (like Multibinder, and MapBinder indirectly). 334c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin this.dependencies = ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Injector.class))); 335c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin this.providerDependencies = 336c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Injector.class))); 3371d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 3381d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb if (JAVA_OPTIONAL_CLASS != null) { 3391d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb this.javaOptionalKey = typeKey.ofType(javaOptionalOf(literal)); 3401d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb this.javaOptionalJavaxProviderKey = typeKey.ofType(javaOptionalOfJavaxProvider(literal)); 3411d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb this.javaOptionalProviderKey = typeKey.ofType(javaOptionalOfProvider(literal)); 3421d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } else { 3431d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb this.javaOptionalKey = null; 3441d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb this.javaOptionalJavaxProviderKey = null; 3451d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb this.javaOptionalProviderKey = null; 3461d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 347af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 3481d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 349af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber /** 350af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * Adds a binding for T. Multiple calls to this are safe, and will be collapsed as duplicate 351af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * bindings. 352af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber */ 353af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private void addDirectTypeBinding(Binder binder) { 3549c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin binder.bind(typeKey).toProvider(new RealDirectTypeProvider()); 355af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 356af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 3570b33461e35fa3a769ce23a9812a80acdc281f62csameb Key<T> getKeyForDefaultBinding() { 358c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin checkConfiguration(!isInitialized(), "already initialized"); 359af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber addDirectTypeBinding(binder); 3600b33461e35fa3a769ce23a9812a80acdc281f62csameb return defaultKey; 361af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 362af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 3630b33461e35fa3a769ce23a9812a80acdc281f62csameb @Override public LinkedBindingBuilder<T> setDefault() { 3640b33461e35fa3a769ce23a9812a80acdc281f62csameb return binder.bind(getKeyForDefaultBinding()); 3650b33461e35fa3a769ce23a9812a80acdc281f62csameb } 3660b33461e35fa3a769ce23a9812a80acdc281f62csameb 3670b33461e35fa3a769ce23a9812a80acdc281f62csameb Key<T> getKeyForActualBinding() { 368c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin checkConfiguration(!isInitialized(), "already initialized"); 369af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber addDirectTypeBinding(binder); 3700b33461e35fa3a769ce23a9812a80acdc281f62csameb return actualKey; 3710b33461e35fa3a769ce23a9812a80acdc281f62csameb } 3720b33461e35fa3a769ce23a9812a80acdc281f62csameb 3730b33461e35fa3a769ce23a9812a80acdc281f62csameb @Override public LinkedBindingBuilder<T> setBinding() { 3740b33461e35fa3a769ce23a9812a80acdc281f62csameb return binder.bind(getKeyForActualBinding()); 375af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 376af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 377842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin @Override public void configure(Binder binder) { 378af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber checkConfiguration(!isInitialized(), "OptionalBinder was already initialized"); 379af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 3809c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin binder.bind(optionalProviderKey).toProvider(new RealOptionalProviderProvider()); 381af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 382af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber // Optional is immutable, so it's safe to expose Optional<Provider<T>> as 383af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber // Optional<javax.inject.Provider<T>> (since Guice provider implements javax Provider). 384af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber @SuppressWarnings({"unchecked", "cast"}) 385af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Key massagedOptionalProviderKey = (Key) optionalProviderKey; 386af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber binder.bind(optionalJavaxProviderKey).to(massagedOptionalProviderKey); 387af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 388af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber binder.bind(optionalKey).toProvider(new RealOptionalKeyProvider()); 3891d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 3901d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb // Bind the java-8 types if we know them. 3911d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb bindJava8Optional(binder); 3921d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 3931d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 3941d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb @SuppressWarnings("unchecked") 3951d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb private void bindJava8Optional(Binder binder) { 3961d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb if (JAVA_OPTIONAL_CLASS != null) { 3971d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb binder.bind(javaOptionalKey).toProvider(new JavaOptionalProvider()); 3981d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb binder.bind(javaOptionalProviderKey).toProvider(new JavaOptionalProviderProvider()); 3991d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb // for the javax version we reuse the guice version since they're type-compatible. 4001d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb binder.bind(javaOptionalJavaxProviderKey).to(javaOptionalProviderKey); 4011d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 4021d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 4031d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 4041d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb @SuppressWarnings("rawtypes") 4051d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb final class JavaOptionalProvider extends RealOptionalBinderProviderWithDependencies 4061d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb implements ProviderWithExtensionVisitor, OptionalBinderBinding { 4071d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb private JavaOptionalProvider() { 4081d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb super(typeKey); 4091d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 4101d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 4111d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb @Override public Object get() { 4121d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb Optional<Provider<T>> optional = optionalProviderT.get(); 4131d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb try { 4141d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb if (optional.isPresent()) { 4151d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb return JAVA_OF_NULLABLE_METHOD.invoke(JAVA_OPTIONAL_CLASS, optional.get().get()); 4161d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } else { 4171d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb return JAVA_EMPTY_METHOD.invoke(JAVA_OPTIONAL_CLASS); 4181d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 4191d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } catch (IllegalAccessException e) { 4201d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb throw new SecurityException(e); 4211d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } catch (IllegalArgumentException e) { 4221d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb throw new IllegalStateException(e); 4231d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } catch (InvocationTargetException e) { 4241d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb throw Throwables.propagate(e.getCause()); 4251d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 4261d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 4271d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 4281d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb @Override public Set<Dependency<?>> getDependencies() { 4291d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb return dependencies; 4301d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 4311d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 4321d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb @SuppressWarnings("unchecked") 4331d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb @Override public Object acceptExtensionVisitor(BindingTargetVisitor visitor, 4341d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb ProviderInstanceBinding binding) { 4351d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb if (visitor instanceof MultibindingsTargetVisitor) { 4361d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb return ((MultibindingsTargetVisitor) visitor).visit(this); 4371d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } else { 4381d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb return visitor.visit(binding); 4391d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 4401d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 4411d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 4421d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb @Override public boolean containsElement(Element element) { 4431d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb return RealOptionalBinder.this.containsElement(element); 4441d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 4451d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 4461d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb @Override public Binding getActualBinding() { 4471d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb return RealOptionalBinder.this.getActualBinding(); 4481d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 4491d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 4501d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb @Override public Binding getDefaultBinding() { 4511d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb return RealOptionalBinder.this.getDefaultBinding(); 4521d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 4531d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 4541d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb @Override public Key getKey() { 4551d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb return javaOptionalKey; 4561d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 4571d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 4581d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 4591d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb @SuppressWarnings("rawtypes") 4601d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb final class JavaOptionalProviderProvider extends RealOptionalBinderProviderWithDependencies { 4611d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb private JavaOptionalProviderProvider() { 4621d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb super(typeKey); 4631d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 4641d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 4651d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb @Override public Object get() { 4661d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb Optional<Provider<T>> optional = optionalProviderT.get(); 4671d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb try { 4681d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb if (optional.isPresent()) { 4691d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb return JAVA_OF_NULLABLE_METHOD.invoke(JAVA_OPTIONAL_CLASS, optional.get()); 4701d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } else { 4711d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb return JAVA_EMPTY_METHOD.invoke(JAVA_OPTIONAL_CLASS); 4721d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 4731d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } catch (IllegalAccessException e) { 4741d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb throw new SecurityException(e); 4751d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } catch (IllegalArgumentException e) { 4761d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb throw new IllegalStateException(e); 4771d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } catch (InvocationTargetException e) { 4781d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb throw Throwables.propagate(e.getCause()); 4791d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 4801d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 4811d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 4821d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb @Override public Set<Dependency<?>> getDependencies() { 4831d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb return providerDependencies; 4841d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 485af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 486af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 4879c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin final class RealDirectTypeProvider extends RealOptionalBinderProviderWithDependencies<T> { 4889c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin private RealDirectTypeProvider() { 4899c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin super(typeKey); 4909c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin } 4919c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin 4929c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin @Override public T get() { 4939c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin Optional<Provider<T>> optional = optionalProviderT.get(); 4949c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin if (optional.isPresent()) { 4959c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin return optional.get().get(); 4969c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin } 4979c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin // Let Guice handle blowing up if the injection point doesn't have @Nullable 4989c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin // (If it does have @Nullable, that's fine. This would only happen if 4999c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin // setBinding/setDefault themselves were bound to 'null'). 5009c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin return null; 5019c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin } 5029c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin 5039c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin @Override public Set<Dependency<?>> getDependencies() { 5049c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin return dependencies; 5059c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin } 5069c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin } 5079c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin 5089c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin final class RealOptionalProviderProvider 5099c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin extends RealOptionalBinderProviderWithDependencies<Optional<Provider<T>>> { 5109c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin private Optional<Provider<T>> optional; 5119c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin 5129c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin private RealOptionalProviderProvider() { 5139c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin super(typeKey); 5149c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin } 5159c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin 5169c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin @Toolable @Inject void initialize(Injector injector) { 5179c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin RealOptionalBinder.this.binder = null; 5189c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin actualBinding = injector.getExistingBinding(actualKey); 5199c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin defaultBinding = injector.getExistingBinding(defaultKey); 5209c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin Binding<T> userBinding = injector.getExistingBinding(typeKey); 5219c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin Binding<T> binding = null; 5229c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin if (actualBinding != null) { 5239c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin // TODO(sameb): Consider exposing an option that will allow 5249c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin // ACTUAL to fallback to DEFAULT if ACTUAL's provider returns null. 5259c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin // Right now, an ACTUAL binding can convert from present -> absent 5269c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin // if it's bound to a provider that returns null. 5279c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin binding = actualBinding; 5289c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin } else if (defaultBinding != null) { 5299c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin binding = defaultBinding; 5309c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin } else if (userBinding != null) { 5319c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin // If neither the actual or default is set, then we fallback 5329c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin // to the value bound to the type itself and consider that the 5339c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin // "actual binding" for the SPI. 5349c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin binding = userBinding; 5359c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin actualBinding = userBinding; 5369c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin } 5379c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin 5389c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin if (binding != null) { 5399c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin optional = Optional.of(binding.getProvider()); 5409c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin RealOptionalBinder.this.dependencies = 5419c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin ImmutableSet.<Dependency<?>>of(Dependency.get(binding.getKey())); 5429c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin RealOptionalBinder.this.providerDependencies = 5439c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin ImmutableSet.<Dependency<?>>of(Dependency.get(providerOf(binding.getKey()))); 5449c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin } else { 5459c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin optional = Optional.absent(); 5469c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin RealOptionalBinder.this.dependencies = ImmutableSet.of(); 5479c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin RealOptionalBinder.this.providerDependencies = ImmutableSet.of(); 5489c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin } 5499c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin } 5509c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin 5519c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin @Override public Optional<Provider<T>> get() { 5529c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin return optional; 5539c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin } 5549c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin 5559c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin @Override public Set<Dependency<?>> getDependencies() { 5569c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin return providerDependencies; 5579c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin } 5589c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin } 5599c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin 5609c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin final class RealOptionalKeyProvider 561af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber extends RealOptionalBinderProviderWithDependencies<Optional<T>> 562af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber implements ProviderWithExtensionVisitor<Optional<T>>, 563af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber OptionalBinderBinding<Optional<T>>, 564af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Provider<Optional<T>> { 5659c2457597fbfe89783f4a9065bab40ad149521a1Sam Berlin private RealOptionalKeyProvider() { 566c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin super(typeKey); 567af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 568af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 569842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin @Override public Optional<T> get() { 570af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber Optional<Provider<T>> optional = optionalProviderT.get(); 571af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (optional.isPresent()) { 572af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return Optional.fromNullable(optional.get().get()); 573af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } else { 574af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return Optional.absent(); 575af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 576af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 577af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 578842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin @Override public Set<Dependency<?>> getDependencies() { 579af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return dependencies; 580af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 581af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 582af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber @SuppressWarnings("unchecked") 583842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin @Override 584af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber public <B, R> R acceptExtensionVisitor(BindingTargetVisitor<B, R> visitor, 585af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber ProviderInstanceBinding<? extends B> binding) { 586af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber if (visitor instanceof MultibindingsTargetVisitor) { 587af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return ((MultibindingsTargetVisitor<Optional<T>, R>) visitor).visit(this); 588af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } else { 589af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return visitor.visit(binding); 590af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 591af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 592af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 593842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin @Override public Key<Optional<T>> getKey() { 594af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return optionalKey; 595af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 5961d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 597842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin @Override public Binding<?> getActualBinding() { 5981d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb return RealOptionalBinder.this.getActualBinding(); 599af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 6001d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 601842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin @Override public Binding<?> getDefaultBinding() { 6021d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb return RealOptionalBinder.this.getDefaultBinding(); 603af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 604af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 605842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin @Override public boolean containsElement(Element element) { 6061d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb return RealOptionalBinder.this.containsElement(element); 6071d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 6081d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 6091d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 6101d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb private Binding<?> getActualBinding() { 6111d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb if (isInitialized()) { 6121d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb return actualBinding; 6131d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } else { 6141d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb throw new UnsupportedOperationException( 6151d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb "getActualBinding() not supported from Elements.getElements, requires an Injector."); 6161d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 6171d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 6181d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 6191d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb private Binding<?> getDefaultBinding() { 6201d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb if (isInitialized()) { 6211d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb return defaultBinding; 6221d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } else { 6231d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb throw new UnsupportedOperationException( 6241d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb "getDefaultBinding() not supported from Elements.getElements, requires an Injector."); 6251d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 6261d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 6271d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 6281d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb private boolean containsElement(Element element) { 6291d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb Key<?> elementKey; 6301d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb if (element instanceof Binding) { 6311d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb elementKey = ((Binding<?>) element).getKey(); 6321d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } else if (element instanceof ProviderLookup) { 6331d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb elementKey = ((ProviderLookup<?>) element).getKey(); 6341d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } else { 6351d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb return false; // cannot match; 6361d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 6371d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb 6381d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb return elementKey.equals(optionalKey) 6391d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb || elementKey.equals(optionalProviderKey) 6401d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb || elementKey.equals(optionalJavaxProviderKey) 6411d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb || elementKey.equals(defaultKey) 6421d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb || elementKey.equals(actualKey) 6431d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb || matchesJ8Keys(elementKey) 6441d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb || matchesTypeKey(element, elementKey); 6451d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb } 646c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 6471d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb private boolean matchesJ8Keys(Key<?> elementKey) { 6481d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb if (JAVA_OPTIONAL_CLASS != null) { 6491d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb return elementKey.equals(javaOptionalKey) 6501d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb || elementKey.equals(javaOptionalProviderKey) 6511d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb || elementKey.equals(javaOptionalJavaxProviderKey); 652af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 6531d3f8cd0a163c7439589d80e6377edbf2ca4b43dsameb return false; 654af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 655af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 656af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber /** Returns true if the key & element indicate they were bound by this OptionalBinder. */ 657c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin private boolean matchesTypeKey(Element element, Key<?> elementKey) { 658af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber // Just doing .equals(typeKey) isn't enough, because the user can bind that themselves. 659af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return elementKey.equals(typeKey) 660af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber && element instanceof ProviderInstanceBinding 661af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber && (((ProviderInstanceBinding) element) 662af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber .getUserSuppliedProvider() instanceof RealOptionalBinderProviderWithDependencies); 663af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 664af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 665af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private boolean isInitialized() { 666af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return binder == null; 667af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 668af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 669af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber @Override public boolean equals(Object o) { 670af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return o instanceof RealOptionalBinder 671c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin && ((RealOptionalBinder<?>) o).typeKey.equals(typeKey); 672af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 673af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 674af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber @Override public int hashCode() { 675c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin return typeKey.hashCode(); 676af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 677af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 678af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber /** 679af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber * A base class for ProviderWithDependencies that need equality based on a specific object. 680af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber */ 681af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private abstract static class RealOptionalBinderProviderWithDependencies<T> implements 682af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber ProviderWithDependencies<T> { 683af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber private final Object equality; 684af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 685af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber public RealOptionalBinderProviderWithDependencies(Object equality) { 686af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber this.equality = equality; 687af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 688af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 689842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin @Override public boolean equals(Object obj) { 690af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return this.getClass() == obj.getClass() 691af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber && equality.equals(((RealOptionalBinderProviderWithDependencies<?>) obj).equality); 692af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 693af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber 694842f351c4b2b3b0a90d9f3bcf164d8fd19aede6cSam Berlin @Override public int hashCode() { 695af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber return equality.hashCode(); 696af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 697af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 698af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber } 699c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 700c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin static class DefaultImpl extends BaseAnnotation implements Default { 701c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin public DefaultImpl(String value) { 702c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin super(Default.class, value); 703c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 704c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 705c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 706c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin static class ActualImpl extends BaseAnnotation implements Actual { 707c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin public ActualImpl(String value) { 708c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin super(Actual.class, value); 709c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 710c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 711c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 712c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin abstract static class BaseAnnotation implements Serializable, Annotation { 713c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 714c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin private final String value; 715c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin private final Class<? extends Annotation> clazz; 716c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 717c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin BaseAnnotation(Class<? extends Annotation> clazz, String value) { 718c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin this.clazz = checkNotNull(clazz, "clazz"); 719c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin this.value = checkNotNull(value, "value"); 720c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 721c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 722c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin public String value() { 723c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin return this.value; 724c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 725c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 726c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin @Override public int hashCode() { 727c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin // This is specified in java.lang.Annotation. 728c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin return (127 * "value".hashCode()) ^ value.hashCode(); 729c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 730c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 731c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin @Override public boolean equals(Object o) { 73208125e9287e577e167ca1186eeff9e14c51250c4Sam Berlin // We check against each annotation type instead of BaseAnnotation 73308125e9287e577e167ca1186eeff9e14c51250c4Sam Berlin // so that we can compare against generated annotation implementations. 73408125e9287e577e167ca1186eeff9e14c51250c4Sam Berlin if (o instanceof Actual && clazz == Actual.class) { 73508125e9287e577e167ca1186eeff9e14c51250c4Sam Berlin Actual other = (Actual) o; 73608125e9287e577e167ca1186eeff9e14c51250c4Sam Berlin return value.equals(other.value()); 73708125e9287e577e167ca1186eeff9e14c51250c4Sam Berlin } else if (o instanceof Default && clazz == Default.class) { 73808125e9287e577e167ca1186eeff9e14c51250c4Sam Berlin Default other = (Default) o; 73908125e9287e577e167ca1186eeff9e14c51250c4Sam Berlin return value.equals(other.value()); 740c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 74108125e9287e577e167ca1186eeff9e14c51250c4Sam Berlin return false; 742c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 743c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 744c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin @Override public String toString() { 745c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin return "@" + clazz.getName() + (value.isEmpty() ? "" : "(value=" + value + ")"); 746c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 747c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 748c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin @Override public Class<? extends Annotation> annotationType() { 749c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin return clazz; 750c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 751c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin 752c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin private static final long serialVersionUID = 0; 753c66f08e3d6798e88f35be51679854568f337e7ebSam Berlin } 754af24f632f90fc91daeb30172b874405c131592c8Christian Edward Gruber} 755