• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (C) 2014 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.inject.multibindings;
18 
19 import static com.google.common.base.Preconditions.checkNotNull;
20 import static com.google.common.base.Preconditions.checkState;
21 import static com.google.inject.multibindings.Multibinder.checkConfiguration;
22 import static com.google.inject.util.Types.newParameterizedType;
23 import static java.lang.annotation.RetentionPolicy.RUNTIME;
24 
25 import com.google.common.base.Optional;
26 import com.google.common.base.Throwables;
27 import com.google.common.collect.ImmutableSet;
28 import com.google.inject.Binder;
29 import com.google.inject.Binding;
30 import com.google.inject.Inject;
31 import com.google.inject.Injector;
32 import com.google.inject.Key;
33 import com.google.inject.Module;
34 import com.google.inject.Provider;
35 import com.google.inject.TypeLiteral;
36 import com.google.inject.binder.LinkedBindingBuilder;
37 import com.google.inject.spi.BindingTargetVisitor;
38 import com.google.inject.spi.Dependency;
39 import com.google.inject.spi.Element;
40 import com.google.inject.spi.ProviderInstanceBinding;
41 import com.google.inject.spi.ProviderLookup;
42 import com.google.inject.spi.ProviderWithDependencies;
43 import com.google.inject.spi.ProviderWithExtensionVisitor;
44 import com.google.inject.spi.Toolable;
45 import com.google.inject.util.Types;
46 
47 import java.io.Serializable;
48 import java.lang.annotation.Annotation;
49 import java.lang.annotation.Retention;
50 import java.lang.reflect.InvocationTargetException;
51 import java.lang.reflect.Method;
52 import java.lang.reflect.Type;
53 import java.util.Set;
54 
55 import javax.inject.Qualifier;
56 
57 
58 /**
59  * An API to bind optional values, optionally with a default value.
60  * OptionalBinder fulfills two roles: <ol>
61  * <li>It allows a framework to define an injection point that may or
62  *     may not be bound by users.
63  * <li>It allows a framework to supply a default value that can be changed
64  *     by users.
65  * </ol>
66  *
67  * <p>When an OptionalBinder is added, it will always supply the bindings:
68  * {@code Optional<T>} and {@code Optional<Provider<T>>}.  If
69  * {@link #setBinding} or {@link #setDefault} are called, it will also
70  * bind {@code T}.
71  *
72  * <p>{@code setDefault} is intended for use by frameworks that need a default
73  * value.  User code can call {@code setBinding} to override the default.
74  * <b>Warning: Even if setBinding is called, the default binding
75  * will still exist in the object graph.  If it is a singleton, it will be
76  * instantiated in {@code Stage.PRODUCTION}.</b>
77  *
78  * <p>If setDefault or setBinding are linked to Providers, the Provider may return
79  * {@code null}.  If it does, the Optional bindings will be absent.  Binding
80  * setBinding to a Provider that returns null will not cause OptionalBinder
81  * to fall back to the setDefault binding.
82  *
83  * <p>If neither setDefault nor setBinding are called, it will try to link to a
84  * user-supplied binding of the same type.  If no binding exists, the optionals
85  * will be absent.  Otherwise, if a user-supplied binding of that type exists,
86  * or if setBinding or setDefault are called, the optionals will return present
87  * if they are bound to a non-null value.
88  *
89  * <p>Values are resolved at injection time. If a value is bound to a
90  * provider, that provider's get method will be called each time the optional
91  * is injected (unless the binding is also scoped, or an optional of provider is
92  * injected).
93  *
94  * <p>Annotations are used to create different optionals of the same key/value
95  * type. Each distinct annotation gets its own independent binding.
96  *
97  * <pre><code>
98  * public class FrameworkModule extends AbstractModule {
99  *   protected void configure() {
100  *     OptionalBinder.newOptionalBinder(binder(), Renamer.class);
101  *   }
102  * }</code></pre>
103  *
104  * <p>With this module, an {@link Optional}{@code <Renamer>} can now be
105  * injected.  With no other bindings, the optional will be absent.
106  * Users can specify bindings in one of two ways:
107  *
108  * <p>Option 1:
109  * <pre><code>
110  * public class UserRenamerModule extends AbstractModule {
111  *   protected void configure() {
112  *     bind(Renamer.class).to(ReplacingRenamer.class);
113  *   }
114  * }</code></pre>
115  *
116  * <p>or Option 2:
117  * <pre><code>
118  * public class UserRenamerModule extends AbstractModule {
119  *   protected void configure() {
120  *     OptionalBinder.newOptionalBinder(binder(), Renamer.class)
121  *         .setBinding().to(ReplacingRenamer.class);
122  *   }
123  * }</code></pre>
124  * With both options, the {@code Optional<Renamer>} will be present and supply the
125  * ReplacingRenamer.
126  *
127  * <p>Default values can be supplied using:
128  * <pre><code>
129  * public class FrameworkModule extends AbstractModule {
130  *   protected void configure() {
131  *     OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, LookupUrl.class))
132  *         .setDefault().toInstance(DEFAULT_LOOKUP_URL);
133  *   }
134  * }</code></pre>
135  * With the above module, code can inject an {@code @LookupUrl String} and it
136  * will supply the DEFAULT_LOOKUP_URL.  A user can change this value by binding
137  * <pre><code>
138  * public class UserLookupModule extends AbstractModule {
139  *   protected void configure() {
140  *     OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, LookupUrl.class))
141  *         .setBinding().toInstance(CUSTOM_LOOKUP_URL);
142  *   }
143  * }</code></pre>
144  * ... which will override the default value.
145  *
146  * <p>If one module uses setDefault the only way to override the default is to use setBinding.
147  * It is an error for a user to specify the binding without using OptionalBinder if
148  * setDefault or setBinding are called.  For example,
149  * <pre><code>
150  * public class FrameworkModule extends AbstractModule {
151  *   protected void configure() {
152  *     OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, LookupUrl.class))
153  *         .setDefault().toInstance(DEFAULT_LOOKUP_URL);
154  *   }
155  * }
156  * public class UserLookupModule extends AbstractModule {
157  *   protected void configure() {
158  *     bind(Key.get(String.class, LookupUrl.class)).toInstance(CUSTOM_LOOKUP_URL);
159  *   }
160  * }</code></pre>
161  * ... would generate an error, because both the framework and the user are trying to bind
162  * {@code @LookupUrl String}.
163  *
164  * @author sameb@google.com (Sam Berlin)
165  * @since 4.0
166  */
167 public abstract class OptionalBinder<T> {
168 
169   /* Reflectively capture java 8's Optional types so we can bind them if we're running in java8. */
170   private static final Class<?> JAVA_OPTIONAL_CLASS;
171   private static final Method JAVA_EMPTY_METHOD;
172   private static final Method JAVA_OF_NULLABLE_METHOD;
173   static {
174     Class<?> optional = null;
175     Method empty = null;
176     Method ofNullable = null;
177     boolean useJavaOptional = false;
178     try {
179       optional = Class.forName("java.util.Optional");
180       empty = optional.getDeclaredMethod("empty");
181       ofNullable = optional.getDeclaredMethod("ofNullable", Object.class);
182       useJavaOptional = true;
183     } catch (ClassNotFoundException ignored) {
184     } catch (NoSuchMethodException ignored) {
185     } catch (SecurityException ignored) {
186     }
187     JAVA_OPTIONAL_CLASS = useJavaOptional ? optional : null;
188     JAVA_EMPTY_METHOD = useJavaOptional ? empty : null;
189     JAVA_OF_NULLABLE_METHOD = useJavaOptional ? ofNullable : null;
190   }
191 
OptionalBinder()192   private OptionalBinder() {}
193 
newOptionalBinder(Binder binder, Class<T> type)194   public static <T> OptionalBinder<T> newOptionalBinder(Binder binder, Class<T> type) {
195     return newRealOptionalBinder(binder, Key.get(type));
196   }
197 
newOptionalBinder(Binder binder, TypeLiteral<T> type)198   public static <T> OptionalBinder<T> newOptionalBinder(Binder binder, TypeLiteral<T> type) {
199     return newRealOptionalBinder(binder, Key.get(type));
200   }
201 
newOptionalBinder(Binder binder, Key<T> type)202   public static <T> OptionalBinder<T> newOptionalBinder(Binder binder, Key<T> type) {
203     return newRealOptionalBinder(binder, type);
204   }
205 
newRealOptionalBinder(Binder binder, Key<T> type)206   static <T> RealOptionalBinder<T> newRealOptionalBinder(Binder binder, Key<T> type) {
207     binder = binder.skipSources(OptionalBinder.class, RealOptionalBinder.class);
208     RealOptionalBinder<T> optionalBinder = new RealOptionalBinder<T>(binder, type);
209     binder.install(optionalBinder);
210     return optionalBinder;
211   }
212 
213   @SuppressWarnings("unchecked")
optionalOf( TypeLiteral<T> type)214   static <T> TypeLiteral<Optional<T>> optionalOf(
215       TypeLiteral<T> type) {
216     return (TypeLiteral<Optional<T>>) TypeLiteral.get(
217         Types.newParameterizedType(Optional.class,  type.getType()));
218   }
219 
javaOptionalOf( TypeLiteral<T> type)220   static <T> TypeLiteral<?> javaOptionalOf(
221       TypeLiteral<T> type) {
222     checkState(JAVA_OPTIONAL_CLASS != null, "java.util.Optional not found");
223     return TypeLiteral.get(Types.newParameterizedType(JAVA_OPTIONAL_CLASS, type.getType()));
224   }
225 
226   @SuppressWarnings("unchecked")
optionalOfJavaxProvider( TypeLiteral<T> type)227   static <T> TypeLiteral<Optional<javax.inject.Provider<T>>> optionalOfJavaxProvider(
228       TypeLiteral<T> type) {
229     return (TypeLiteral<Optional<javax.inject.Provider<T>>>) TypeLiteral.get(
230         Types.newParameterizedType(Optional.class,
231             newParameterizedType(javax.inject.Provider.class, type.getType())));
232   }
233 
javaOptionalOfJavaxProvider( TypeLiteral<T> type)234   static <T> TypeLiteral<?> javaOptionalOfJavaxProvider(
235       TypeLiteral<T> type) {
236     checkState(JAVA_OPTIONAL_CLASS != null, "java.util.Optional not found");
237     return TypeLiteral.get(Types.newParameterizedType(JAVA_OPTIONAL_CLASS,
238         newParameterizedType(javax.inject.Provider.class, type.getType())));
239   }
240 
241   @SuppressWarnings("unchecked")
optionalOfProvider(TypeLiteral<T> type)242   static <T> TypeLiteral<Optional<Provider<T>>> optionalOfProvider(TypeLiteral<T> type) {
243     return (TypeLiteral<Optional<Provider<T>>>) TypeLiteral.get(Types.newParameterizedType(
244         Optional.class, newParameterizedType(Provider.class, type.getType())));
245   }
246 
javaOptionalOfProvider(TypeLiteral<T> type)247   static <T> TypeLiteral<?> javaOptionalOfProvider(TypeLiteral<T> type) {
248     checkState(JAVA_OPTIONAL_CLASS != null, "java.util.Optional not found");
249     return TypeLiteral.get(Types.newParameterizedType(JAVA_OPTIONAL_CLASS,
250         newParameterizedType(Provider.class, type.getType())));
251   }
252 
253   @SuppressWarnings("unchecked")
providerOf(Key<T> key)254   static <T> Key<Provider<T>> providerOf(Key<T> key) {
255     Type providerT = Types.providerOf(key.getTypeLiteral().getType());
256     return (Key<Provider<T>>) key.ofType(providerT);
257   }
258 
259   /**
260    * Returns a binding builder used to set the default value that will be injected.
261    * The binding set by this method will be ignored if {@link #setBinding} is called.
262    *
263    * <p>It is an error to call this method without also calling one of the {@code to}
264    * methods on the returned binding builder.
265    */
setDefault()266   public abstract LinkedBindingBuilder<T> setDefault();
267 
268 
269   /**
270    * Returns a binding builder used to set the actual value that will be injected.
271    * This overrides any binding set by {@link #setDefault}.
272    *
273    * <p>It is an error to call this method without also calling one of the {@code to}
274    * methods on the returned binding builder.
275    */
setBinding()276   public abstract LinkedBindingBuilder<T> setBinding();
277 
278   enum Source { DEFAULT, ACTUAL }
279 
280   @Retention(RUNTIME)
281   @Qualifier
282   @interface Default {
value()283     String value();
284   }
285 
286   @Retention(RUNTIME)
287   @Qualifier
288   @interface Actual {
value()289     String value();
290   }
291 
292   /**
293    * The actual OptionalBinder plays several roles.  It implements Module to hide that
294    * fact from the public API, and installs the various bindings that are exposed to the user.
295    */
296   static final class RealOptionalBinder<T> extends OptionalBinder<T> implements Module {
297     private final Key<T> typeKey;
298     private final Key<Optional<T>> optionalKey;
299     private final Key<Optional<javax.inject.Provider<T>>> optionalJavaxProviderKey;
300     private final Key<Optional<Provider<T>>> optionalProviderKey;
301     private final Provider<Optional<Provider<T>>> optionalProviderT;
302     private final Key<T> defaultKey;
303     private final Key<T> actualKey;
304 
305     private final Key javaOptionalKey;
306     private final Key javaOptionalJavaxProviderKey;
307     private final Key javaOptionalProviderKey;
308 
309     /** the target injector's binder. non-null until initialization, null afterwards */
310     private Binder binder;
311     /** the default binding, for the SPI. */
312     private Binding<T> defaultBinding;
313     /** the actual binding, for the SPI */
314     private Binding<T> actualBinding;
315 
316     /** the dependencies -- initialized with defaults & overridden when tooled. */
317     private Set<Dependency<?>> dependencies;
318     /** the dependencies -- initialized with defaults & overridden when tooled. */
319     private Set<Dependency<?>> providerDependencies;
320 
RealOptionalBinder(Binder binder, Key<T> typeKey)321     private RealOptionalBinder(Binder binder, Key<T> typeKey) {
322       this.binder = binder;
323       this.typeKey = checkNotNull(typeKey);
324       TypeLiteral<T> literal = typeKey.getTypeLiteral();
325       this.optionalKey = typeKey.ofType(optionalOf(literal));
326       this.optionalJavaxProviderKey = typeKey.ofType(optionalOfJavaxProvider(literal));
327       this.optionalProviderKey = typeKey.ofType(optionalOfProvider(literal));
328       this.optionalProviderT = binder.getProvider(optionalProviderKey);
329       String name = RealElement.nameOf(typeKey);
330       this.defaultKey = Key.get(typeKey.getTypeLiteral(), new DefaultImpl(name));
331       this.actualKey = Key.get(typeKey.getTypeLiteral(), new ActualImpl(name));
332       // Until the injector initializes us, we don't know what our dependencies are,
333       // so initialize to the whole Injector (like Multibinder, and MapBinder indirectly).
334       this.dependencies = ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Injector.class)));
335       this.providerDependencies =
336           ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Injector.class)));
337 
338       if (JAVA_OPTIONAL_CLASS != null) {
339         this.javaOptionalKey = typeKey.ofType(javaOptionalOf(literal));
340         this.javaOptionalJavaxProviderKey = typeKey.ofType(javaOptionalOfJavaxProvider(literal));
341         this.javaOptionalProviderKey = typeKey.ofType(javaOptionalOfProvider(literal));
342       } else {
343         this.javaOptionalKey = null;
344         this.javaOptionalJavaxProviderKey = null;
345         this.javaOptionalProviderKey = null;
346       }
347     }
348 
349     /**
350      * Adds a binding for T. Multiple calls to this are safe, and will be collapsed as duplicate
351      * bindings.
352      */
addDirectTypeBinding(Binder binder)353     private void addDirectTypeBinding(Binder binder) {
354       binder.bind(typeKey).toProvider(new RealDirectTypeProvider());
355     }
356 
getKeyForDefaultBinding()357     Key<T> getKeyForDefaultBinding() {
358       checkConfiguration(!isInitialized(), "already initialized");
359       addDirectTypeBinding(binder);
360       return defaultKey;
361     }
362 
setDefault()363     @Override public LinkedBindingBuilder<T> setDefault() {
364       return binder.bind(getKeyForDefaultBinding());
365     }
366 
getKeyForActualBinding()367     Key<T> getKeyForActualBinding() {
368       checkConfiguration(!isInitialized(), "already initialized");
369       addDirectTypeBinding(binder);
370       return actualKey;
371     }
372 
setBinding()373     @Override public LinkedBindingBuilder<T> setBinding() {
374       return binder.bind(getKeyForActualBinding());
375     }
376 
configure(Binder binder)377     @Override public void configure(Binder binder) {
378       checkConfiguration(!isInitialized(), "OptionalBinder was already initialized");
379 
380       binder.bind(optionalProviderKey).toProvider(new RealOptionalProviderProvider());
381 
382       // Optional is immutable, so it's safe to expose Optional<Provider<T>> as
383       // Optional<javax.inject.Provider<T>> (since Guice provider implements javax Provider).
384       @SuppressWarnings({"unchecked", "cast"})
385       Key massagedOptionalProviderKey = (Key) optionalProviderKey;
386       binder.bind(optionalJavaxProviderKey).to(massagedOptionalProviderKey);
387 
388       binder.bind(optionalKey).toProvider(new RealOptionalKeyProvider());
389 
390       // Bind the java-8 types if we know them.
391       bindJava8Optional(binder);
392     }
393 
394     @SuppressWarnings("unchecked")
bindJava8Optional(Binder binder)395     private void bindJava8Optional(Binder binder) {
396       if (JAVA_OPTIONAL_CLASS != null) {
397         binder.bind(javaOptionalKey).toProvider(new JavaOptionalProvider());
398         binder.bind(javaOptionalProviderKey).toProvider(new JavaOptionalProviderProvider());
399         // for the javax version we reuse the guice version since they're type-compatible.
400         binder.bind(javaOptionalJavaxProviderKey).to(javaOptionalProviderKey);
401       }
402     }
403 
404     @SuppressWarnings("rawtypes")
405     final class JavaOptionalProvider extends RealOptionalBinderProviderWithDependencies
406         implements ProviderWithExtensionVisitor, OptionalBinderBinding {
JavaOptionalProvider()407       private JavaOptionalProvider() {
408         super(typeKey);
409       }
410 
get()411       @Override public Object get() {
412         Optional<Provider<T>> optional = optionalProviderT.get();
413         try {
414           if (optional.isPresent()) {
415             return JAVA_OF_NULLABLE_METHOD.invoke(JAVA_OPTIONAL_CLASS, optional.get().get());
416           } else {
417             return JAVA_EMPTY_METHOD.invoke(JAVA_OPTIONAL_CLASS);
418           }
419         } catch (IllegalAccessException e) {
420           throw new SecurityException(e);
421         } catch (IllegalArgumentException e) {
422           throw new IllegalStateException(e);
423         } catch (InvocationTargetException e) {
424           throw Throwables.propagate(e.getCause());
425         }
426       }
427 
getDependencies()428       @Override public Set<Dependency<?>> getDependencies() {
429         return dependencies;
430       }
431 
432       @SuppressWarnings("unchecked")
acceptExtensionVisitor(BindingTargetVisitor visitor, ProviderInstanceBinding binding)433       @Override public Object acceptExtensionVisitor(BindingTargetVisitor visitor,
434           ProviderInstanceBinding binding) {
435         if (visitor instanceof MultibindingsTargetVisitor) {
436           return ((MultibindingsTargetVisitor) visitor).visit(this);
437         } else {
438           return visitor.visit(binding);
439         }
440       }
441 
containsElement(Element element)442       @Override public boolean containsElement(Element element) {
443         return RealOptionalBinder.this.containsElement(element);
444       }
445 
getActualBinding()446       @Override public Binding getActualBinding() {
447         return RealOptionalBinder.this.getActualBinding();
448       }
449 
getDefaultBinding()450       @Override public Binding getDefaultBinding() {
451         return RealOptionalBinder.this.getDefaultBinding();
452       }
453 
getKey()454       @Override public Key getKey() {
455         return javaOptionalKey;
456       }
457     }
458 
459     @SuppressWarnings("rawtypes")
460     final class JavaOptionalProviderProvider extends RealOptionalBinderProviderWithDependencies {
JavaOptionalProviderProvider()461       private JavaOptionalProviderProvider() {
462         super(typeKey);
463       }
464 
get()465       @Override public Object get() {
466         Optional<Provider<T>> optional = optionalProviderT.get();
467         try {
468           if (optional.isPresent()) {
469             return JAVA_OF_NULLABLE_METHOD.invoke(JAVA_OPTIONAL_CLASS, optional.get());
470           } else {
471             return JAVA_EMPTY_METHOD.invoke(JAVA_OPTIONAL_CLASS);
472           }
473         } catch (IllegalAccessException e) {
474           throw new SecurityException(e);
475         } catch (IllegalArgumentException e) {
476           throw new IllegalStateException(e);
477         } catch (InvocationTargetException e) {
478           throw Throwables.propagate(e.getCause());
479         }
480       }
481 
getDependencies()482       @Override public Set<Dependency<?>> getDependencies() {
483         return providerDependencies;
484       }
485     }
486 
487     final class RealDirectTypeProvider extends RealOptionalBinderProviderWithDependencies<T> {
RealDirectTypeProvider()488       private RealDirectTypeProvider() {
489         super(typeKey);
490       }
491 
get()492       @Override public T get() {
493         Optional<Provider<T>> optional = optionalProviderT.get();
494         if (optional.isPresent()) {
495           return optional.get().get();
496         }
497         // Let Guice handle blowing up if the injection point doesn't have @Nullable
498         // (If it does have @Nullable, that's fine.  This would only happen if
499         //  setBinding/setDefault themselves were bound to 'null').
500         return null;
501       }
502 
getDependencies()503       @Override public Set<Dependency<?>> getDependencies() {
504         return dependencies;
505       }
506     }
507 
508     final class RealOptionalProviderProvider
509         extends RealOptionalBinderProviderWithDependencies<Optional<Provider<T>>> {
510       private Optional<Provider<T>> optional;
511 
RealOptionalProviderProvider()512       private RealOptionalProviderProvider() {
513         super(typeKey);
514       }
515 
initialize(Injector injector)516       @Toolable @Inject void initialize(Injector injector) {
517         RealOptionalBinder.this.binder = null;
518         actualBinding = injector.getExistingBinding(actualKey);
519         defaultBinding = injector.getExistingBinding(defaultKey);
520         Binding<T> userBinding = injector.getExistingBinding(typeKey);
521         Binding<T> binding = null;
522         if (actualBinding != null) {
523           // TODO(sameb): Consider exposing an option that will allow
524           // ACTUAL to fallback to DEFAULT if ACTUAL's provider returns null.
525           // Right now, an ACTUAL binding can convert from present -> absent
526           // if it's bound to a provider that returns null.
527           binding = actualBinding;
528         } else if (defaultBinding != null) {
529           binding = defaultBinding;
530         } else if (userBinding != null) {
531           // If neither the actual or default is set, then we fallback
532           // to the value bound to the type itself and consider that the
533           // "actual binding" for the SPI.
534           binding = userBinding;
535           actualBinding = userBinding;
536         }
537 
538         if (binding != null) {
539           optional = Optional.of(binding.getProvider());
540           RealOptionalBinder.this.dependencies =
541               ImmutableSet.<Dependency<?>>of(Dependency.get(binding.getKey()));
542           RealOptionalBinder.this.providerDependencies =
543               ImmutableSet.<Dependency<?>>of(Dependency.get(providerOf(binding.getKey())));
544         } else {
545           optional = Optional.absent();
546           RealOptionalBinder.this.dependencies = ImmutableSet.of();
547           RealOptionalBinder.this.providerDependencies = ImmutableSet.of();
548         }
549       }
550 
get()551       @Override public Optional<Provider<T>> get() {
552         return optional;
553       }
554 
getDependencies()555       @Override public Set<Dependency<?>> getDependencies() {
556         return providerDependencies;
557       }
558     }
559 
560     final class RealOptionalKeyProvider
561         extends RealOptionalBinderProviderWithDependencies<Optional<T>>
562         implements ProviderWithExtensionVisitor<Optional<T>>,
563             OptionalBinderBinding<Optional<T>>,
564             Provider<Optional<T>> {
RealOptionalKeyProvider()565       private RealOptionalKeyProvider() {
566         super(typeKey);
567       }
568 
get()569       @Override public Optional<T> get() {
570         Optional<Provider<T>> optional = optionalProviderT.get();
571         if (optional.isPresent()) {
572           return Optional.fromNullable(optional.get().get());
573         } else {
574           return Optional.absent();
575         }
576       }
577 
getDependencies()578       @Override public Set<Dependency<?>> getDependencies() {
579         return dependencies;
580       }
581 
582       @SuppressWarnings("unchecked")
583       @Override
acceptExtensionVisitor(BindingTargetVisitor<B, R> visitor, ProviderInstanceBinding<? extends B> binding)584       public <B, R> R acceptExtensionVisitor(BindingTargetVisitor<B, R> visitor,
585           ProviderInstanceBinding<? extends B> binding) {
586         if (visitor instanceof MultibindingsTargetVisitor) {
587           return ((MultibindingsTargetVisitor<Optional<T>, R>) visitor).visit(this);
588         } else {
589           return visitor.visit(binding);
590         }
591       }
592 
getKey()593       @Override public Key<Optional<T>> getKey() {
594         return optionalKey;
595       }
596 
getActualBinding()597       @Override public Binding<?> getActualBinding() {
598         return RealOptionalBinder.this.getActualBinding();
599       }
600 
getDefaultBinding()601       @Override public Binding<?> getDefaultBinding() {
602         return RealOptionalBinder.this.getDefaultBinding();
603       }
604 
containsElement(Element element)605       @Override public boolean containsElement(Element element) {
606         return RealOptionalBinder.this.containsElement(element);
607       }
608     }
609 
getActualBinding()610     private Binding<?> getActualBinding() {
611       if (isInitialized()) {
612         return actualBinding;
613       } else {
614         throw new UnsupportedOperationException(
615             "getActualBinding() not supported from Elements.getElements, requires an Injector.");
616       }
617     }
618 
getDefaultBinding()619     private Binding<?> getDefaultBinding() {
620       if (isInitialized()) {
621         return defaultBinding;
622       } else {
623         throw new UnsupportedOperationException(
624             "getDefaultBinding() not supported from Elements.getElements, requires an Injector.");
625       }
626     }
627 
containsElement(Element element)628     private boolean containsElement(Element element) {
629       Key<?> elementKey;
630       if (element instanceof Binding) {
631         elementKey = ((Binding<?>) element).getKey();
632       } else if (element instanceof ProviderLookup) {
633         elementKey = ((ProviderLookup<?>) element).getKey();
634       } else {
635         return false; // cannot match;
636       }
637 
638       return elementKey.equals(optionalKey)
639           || elementKey.equals(optionalProviderKey)
640           || elementKey.equals(optionalJavaxProviderKey)
641           || elementKey.equals(defaultKey)
642           || elementKey.equals(actualKey)
643           || matchesJ8Keys(elementKey)
644           || matchesTypeKey(element, elementKey);
645     }
646 
matchesJ8Keys(Key<?> elementKey)647     private boolean matchesJ8Keys(Key<?> elementKey) {
648       if (JAVA_OPTIONAL_CLASS != null) {
649         return elementKey.equals(javaOptionalKey)
650             || elementKey.equals(javaOptionalProviderKey)
651             || elementKey.equals(javaOptionalJavaxProviderKey);
652       }
653       return false;
654     }
655 
656     /** Returns true if the key & element indicate they were bound by this OptionalBinder. */
matchesTypeKey(Element element, Key<?> elementKey)657     private boolean matchesTypeKey(Element element, Key<?> elementKey) {
658       // Just doing .equals(typeKey) isn't enough, because the user can bind that themselves.
659       return elementKey.equals(typeKey)
660           && element instanceof ProviderInstanceBinding
661           && (((ProviderInstanceBinding) element)
662               .getUserSuppliedProvider() instanceof RealOptionalBinderProviderWithDependencies);
663     }
664 
isInitialized()665     private boolean isInitialized() {
666       return binder == null;
667     }
668 
equals(Object o)669     @Override public boolean equals(Object o) {
670       return o instanceof RealOptionalBinder
671           && ((RealOptionalBinder<?>) o).typeKey.equals(typeKey);
672     }
673 
hashCode()674     @Override public int hashCode() {
675       return typeKey.hashCode();
676     }
677 
678     /**
679      * A base class for ProviderWithDependencies that need equality based on a specific object.
680      */
681     private abstract static class RealOptionalBinderProviderWithDependencies<T> implements
682         ProviderWithDependencies<T> {
683       private final Object equality;
684 
RealOptionalBinderProviderWithDependencies(Object equality)685       public RealOptionalBinderProviderWithDependencies(Object equality) {
686         this.equality = equality;
687       }
688 
equals(Object obj)689       @Override public boolean equals(Object obj) {
690         return this.getClass() == obj.getClass()
691             && equality.equals(((RealOptionalBinderProviderWithDependencies<?>) obj).equality);
692       }
693 
hashCode()694       @Override public int hashCode() {
695         return equality.hashCode();
696       }
697     }
698   }
699 
700   static class DefaultImpl extends BaseAnnotation implements Default {
DefaultImpl(String value)701     public DefaultImpl(String value) {
702       super(Default.class, value);
703     }
704   }
705 
706   static class ActualImpl extends BaseAnnotation implements Actual {
ActualImpl(String value)707     public ActualImpl(String value) {
708       super(Actual.class, value);
709     }
710   }
711 
712   abstract static class BaseAnnotation implements Serializable, Annotation {
713 
714     private final String value;
715     private final Class<? extends Annotation> clazz;
716 
BaseAnnotation(Class<? extends Annotation> clazz, String value)717     BaseAnnotation(Class<? extends Annotation> clazz, String value) {
718       this.clazz = checkNotNull(clazz, "clazz");
719       this.value = checkNotNull(value, "value");
720     }
721 
value()722     public String value() {
723       return this.value;
724     }
725 
hashCode()726     @Override public int hashCode() {
727       // This is specified in java.lang.Annotation.
728       return (127 * "value".hashCode()) ^ value.hashCode();
729     }
730 
equals(Object o)731     @Override public boolean equals(Object o) {
732       // We check against each annotation type instead of BaseAnnotation
733       // so that we can compare against generated annotation implementations.
734       if (o instanceof Actual && clazz == Actual.class) {
735         Actual other = (Actual) o;
736         return value.equals(other.value());
737       } else if (o instanceof Default && clazz == Default.class) {
738         Default other = (Default) o;
739         return value.equals(other.value());
740       }
741       return false;
742     }
743 
toString()744     @Override public String toString() {
745       return "@" + clazz.getName() + (value.isEmpty() ? "" : "(value=" + value + ")");
746     }
747 
annotationType()748     @Override public Class<? extends Annotation> annotationType() {
749       return clazz;
750     }
751 
752     private static final long serialVersionUID = 0;
753   }
754 }
755