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