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.inject.internal.RealOptionalBinder.newRealOptionalBinder; 20 21 import com.google.common.base.Optional; 22 import com.google.inject.Binder; 23 import com.google.inject.Key; 24 import com.google.inject.TypeLiteral; 25 import com.google.inject.binder.LinkedBindingBuilder; 26 import com.google.inject.internal.RealOptionalBinder; 27 28 /** 29 * An API to bind optional values, optionally with a default value. OptionalBinder fulfills two 30 * roles: 31 * 32 * <ol> 33 * <li>It allows a framework to define an injection point that may or may not be bound by users. 34 * <li>It allows a framework to supply a default value that can be changed by users. 35 * </ol> 36 * 37 * <p>When an OptionalBinder is added, it will always supply the bindings: {@code Optional<T>} and 38 * {@code Optional<Provider<T>>}. If {@link #setBinding} or {@link #setDefault} are called, it will 39 * also bind {@code T}. 40 * 41 * <p>{@code setDefault} is intended for use by frameworks that need a default value. User code can 42 * call {@code setBinding} to override the default. <b>Warning: Even if setBinding is called, the 43 * default binding will still exist in the object graph. If it is a singleton, it will be 44 * instantiated in {@code Stage.PRODUCTION}.</b> 45 * 46 * <p>If setDefault or setBinding are linked to Providers, the Provider may return {@code null}. If 47 * it does, the Optional bindings will be absent. Binding setBinding to a Provider that returns null 48 * will not cause OptionalBinder to fall back to the setDefault binding. 49 * 50 * <p>If neither setDefault nor setBinding are called, it will try to link to a user-supplied 51 * binding of the same type. If no binding exists, the optionals will be absent. Otherwise, if a 52 * user-supplied binding of that type exists, or if setBinding or setDefault are called, the 53 * optionals will return present if they are bound to a non-null value. 54 * 55 * <p>Values are resolved at injection time. If a value is bound to a provider, that provider's get 56 * method will be called each time the optional is injected (unless the binding is also scoped, or 57 * an optional of provider is injected). 58 * 59 * <p>Annotations are used to create different optionals of the same key/value type. Each distinct 60 * annotation gets its own independent binding. 61 * 62 * <pre><code> 63 * public class FrameworkModule extends AbstractModule { 64 * protected void configure() { 65 * OptionalBinder.newOptionalBinder(binder(), Renamer.class); 66 * } 67 * }</code></pre> 68 * 69 * <p>With this module, an {@link Optional}{@code <Renamer>} can now be injected. With no other 70 * bindings, the optional will be absent. Users can specify bindings in one of two ways: 71 * 72 * <p>Option 1: 73 * 74 * <pre><code> 75 * public class UserRenamerModule extends AbstractModule { 76 * protected void configure() { 77 * bind(Renamer.class).to(ReplacingRenamer.class); 78 * } 79 * }</code></pre> 80 * 81 * <p>or Option 2: 82 * 83 * <pre><code> 84 * public class UserRenamerModule extends AbstractModule { 85 * protected void configure() { 86 * OptionalBinder.newOptionalBinder(binder(), Renamer.class) 87 * .setBinding().to(ReplacingRenamer.class); 88 * } 89 * }</code></pre> 90 * 91 * With both options, the {@code Optional<Renamer>} will be present and supply the ReplacingRenamer. 92 * 93 * <p>Default values can be supplied using: 94 * 95 * <pre><code> 96 * public class FrameworkModule extends AbstractModule { 97 * protected void configure() { 98 * OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, LookupUrl.class)) 99 * .setDefault().toInstance(DEFAULT_LOOKUP_URL); 100 * } 101 * }</code></pre> 102 * 103 * With the above module, code can inject an {@code @LookupUrl String} and it will supply the 104 * DEFAULT_LOOKUP_URL. A user can change this value by binding 105 * 106 * <pre><code> 107 * public class UserLookupModule extends AbstractModule { 108 * protected void configure() { 109 * OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, LookupUrl.class)) 110 * .setBinding().toInstance(CUSTOM_LOOKUP_URL); 111 * } 112 * }</code></pre> 113 * 114 * ... which will override the default value. 115 * 116 * <p>If one module uses setDefault the only way to override the default is to use setBinding. It is 117 * an error for a user to specify the binding without using OptionalBinder if setDefault or 118 * setBinding are called. For example, 119 * 120 * <pre><code> 121 * public class FrameworkModule extends AbstractModule { 122 * protected void configure() { 123 * OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, LookupUrl.class)) 124 * .setDefault().toInstance(DEFAULT_LOOKUP_URL); 125 * } 126 * } 127 * public class UserLookupModule extends AbstractModule { 128 * protected void configure() { 129 * bind(Key.get(String.class, LookupUrl.class)).toInstance(CUSTOM_LOOKUP_URL); 130 * } 131 * }</code></pre> 132 * 133 * ... would generate an error, because both the framework and the user are trying to bind 134 * {@code @LookupUrl String}. 135 * 136 * @author sameb@google.com (Sam Berlin) 137 * @since 4.0 138 */ 139 public class OptionalBinder<T> { 140 // This class is non-final due to users mocking this in tests :( 141 newOptionalBinder(Binder binder, Class<T> type)142 public static <T> OptionalBinder<T> newOptionalBinder(Binder binder, Class<T> type) { 143 return new OptionalBinder<T>( 144 newRealOptionalBinder(binder.skipSources(OptionalBinder.class), Key.get(type))); 145 } 146 newOptionalBinder(Binder binder, TypeLiteral<T> type)147 public static <T> OptionalBinder<T> newOptionalBinder(Binder binder, TypeLiteral<T> type) { 148 return new OptionalBinder<T>( 149 newRealOptionalBinder(binder.skipSources(OptionalBinder.class), Key.get(type))); 150 } 151 newOptionalBinder(Binder binder, Key<T> type)152 public static <T> OptionalBinder<T> newOptionalBinder(Binder binder, Key<T> type) { 153 return new OptionalBinder<T>( 154 newRealOptionalBinder(binder.skipSources(OptionalBinder.class), type)); 155 } 156 157 private final RealOptionalBinder<T> delegate; 158 OptionalBinder(RealOptionalBinder<T> delegate)159 private OptionalBinder(RealOptionalBinder<T> delegate) { 160 this.delegate = delegate; 161 } 162 163 /** 164 * Returns a binding builder used to set the default value that will be injected. The binding set 165 * by this method will be ignored if {@link #setBinding} is called. 166 * 167 * <p>It is an error to call this method without also calling one of the {@code to} methods on the 168 * returned binding builder. 169 */ setDefault()170 public LinkedBindingBuilder<T> setDefault() { 171 return delegate.setDefault(); 172 } 173 174 /** 175 * Returns a binding builder used to set the actual value that will be injected. This overrides 176 * any binding set by {@link #setDefault}. 177 * 178 * <p>It is an error to call this method without also calling one of the {@code to} methods on the 179 * returned binding builder. 180 */ setBinding()181 public LinkedBindingBuilder<T> setBinding() { 182 return delegate.setBinding(); 183 } 184 185 // Some tests depend on equals/hashCode behavior of OptionalBinder 186 187 @Override equals(Object obj)188 public boolean equals(Object obj) { 189 if (obj instanceof OptionalBinder) { 190 return delegate.equals(((OptionalBinder<?>) obj).delegate); 191 } 192 return false; 193 } 194 195 @Override hashCode()196 public int hashCode() { 197 return delegate.hashCode(); 198 } 199 } 200