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