1 /* 2 * Copyright (C) 2016 The Dagger Authors. 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 dagger.functional.producers.optional; 18 19 import static java.lang.annotation.RetentionPolicy.RUNTIME; 20 21 import com.google.auto.value.AutoValue; 22 import com.google.common.base.Optional; 23 import com.google.common.util.concurrent.ListenableFuture; 24 import dagger.BindsOptionalOf; 25 import dagger.Module; 26 import dagger.Provides; 27 import dagger.producers.Produced; 28 import dagger.producers.Producer; 29 import dagger.producers.ProducerModule; 30 import dagger.producers.Produces; 31 import dagger.producers.Production; 32 import dagger.producers.ProductionComponent; 33 import dagger.producers.ProductionSubcomponent; 34 import java.lang.annotation.Retention; 35 import java.util.concurrent.Executor; 36 import java.util.concurrent.Executors; 37 import javax.annotation.Nullable; 38 import javax.inject.Provider; 39 import javax.inject.Qualifier; 40 41 /** Classes to support testing {@code BindsOptionalOf} functionality. */ 42 final class OptionalBindingComponents { 43 44 /** A qualifier. */ 45 @Qualifier 46 @Retention(RUNTIME) 47 @interface SomeQualifier {} 48 49 /** A value object that contains various optionally-bound objects. */ 50 @AutoValue 51 abstract static class Values { optionalInstance()52 abstract Optional<Value> optionalInstance(); 53 optionalProducer()54 abstract Optional<Producer<Value>> optionalProducer(); 55 optionalProduced()56 abstract Optional<Produced<Value>> optionalProduced(); 57 } 58 59 enum Value { 60 VALUE, 61 QUALIFIED_VALUE 62 } 63 64 @Module 65 static final class ExecutorModule { 66 @Provides 67 @Production executor()68 static Executor executor() { 69 return Executors.newSingleThreadExecutor(); 70 } 71 } 72 73 /** Binds optionals and {@link Values}. */ 74 @ProducerModule 75 abstract static class OptionalBindingModule { 76 @BindsOptionalOf value()77 abstract Value value(); 78 79 @BindsOptionalOf 80 @SomeQualifier qualifiedValue()81 abstract Value qualifiedValue(); 82 83 @BindsOptionalOf nullableObject()84 abstract Object nullableObject(); 85 86 @Produces values( Optional<Value> optionalInstance, Optional<Producer<Value>> optionalProducer, Optional<Produced<Value>> optionalProduced)87 static Values values( 88 Optional<Value> optionalInstance, 89 Optional<Producer<Value>> optionalProducer, 90 Optional<Produced<Value>> optionalProduced) { 91 return new AutoValue_OptionalBindingComponents_Values( 92 optionalInstance, optionalProducer, optionalProduced); 93 } 94 95 @Produces 96 @SomeQualifier qualifiedValues( Optional<Value> optionalInstance, Optional<Producer<Value>> optionalProducer, Optional<Produced<Value>> optionalProduced)97 static Values qualifiedValues( 98 Optional<Value> optionalInstance, 99 Optional<Producer<Value>> optionalProducer, 100 Optional<Produced<Value>> optionalProduced) { 101 return new AutoValue_OptionalBindingComponents_Values( 102 optionalInstance, optionalProducer, optionalProduced); 103 } 104 } 105 106 /** Binds {@link Value} using {@link Producer}s. */ 107 @ProducerModule 108 abstract static class ConcreteBindingProducerModule { 109 @Produces value()110 static Value value() { 111 return Value.VALUE; 112 } 113 114 @Produces 115 @SomeQualifier qualifiedValue()116 static Value qualifiedValue() { 117 return Value.QUALIFIED_VALUE; 118 } 119 120 // @Produces @Nullable has no effect (and ProducesMethodValidator warns when the two are used 121 // together. Use a @Provides method and let it be wrapped into a producerFromProvider for the 122 // purposes of the test 123 @Provides 124 @Nullable nullableObject()125 static Object nullableObject() { 126 return null; 127 } 128 } 129 130 /** Binds {@link Value} using {@link Provider}s. */ 131 @Module 132 abstract static class ConcreteBindingModule { 133 @Provides value()134 static Value value() { 135 return Value.VALUE; 136 } 137 138 @Provides 139 @SomeQualifier qualifiedValue()140 static Value qualifiedValue() { 141 return Value.QUALIFIED_VALUE; 142 } 143 144 @Provides 145 @Nullable nullableObject()146 static Object nullableObject() { 147 return null; 148 } 149 } 150 151 interface OptionalBindingComponent { values()152 ListenableFuture<Values> values(); 153 optionalInstance()154 ListenableFuture<Optional<Value>> optionalInstance(); 155 optionalProducer()156 ListenableFuture<Optional<Producer<Value>>> optionalProducer(); 157 optionalProduced()158 ListenableFuture<Optional<Produced<Value>>> optionalProduced(); 159 160 @SomeQualifier qualifiedValues()161 ListenableFuture<Values> qualifiedValues(); 162 163 @SomeQualifier qualifiedOptionalInstance()164 ListenableFuture<Optional<Value>> qualifiedOptionalInstance(); 165 166 @SomeQualifier qualifiedOptionalProducer()167 ListenableFuture<Optional<Producer<Value>>> qualifiedOptionalProducer(); 168 169 @SomeQualifier qualifiedOptionalProduced()170 ListenableFuture<Optional<Produced<Value>>> qualifiedOptionalProduced(); 171 172 // Nullable bindings can satisfy optional bindings except for Optional<Foo>. optionalNullableProducer()173 ListenableFuture<Optional<Producer<Object>>> optionalNullableProducer(); 174 optionalNullableProduced()175 ListenableFuture<Optional<Produced<Object>>> optionalNullableProduced(); 176 } 177 178 @ProductionComponent(modules = {ExecutorModule.class, OptionalBindingModule.class}) 179 interface AbsentOptionalBindingComponent extends OptionalBindingComponent { presentChild()180 PresentOptionalBindingSubcomponent presentChild(); 181 } 182 183 @ProductionComponent( 184 modules = { 185 ExecutorModule.class, 186 OptionalBindingModule.class, 187 ConcreteBindingProducerModule.class 188 } 189 ) 190 interface PresentOptionalBindingComponent extends OptionalBindingComponent {} 191 192 @ProductionSubcomponent(modules = ConcreteBindingProducerModule.class) 193 interface PresentOptionalBindingSubcomponent extends OptionalBindingComponent {} 194 195 @ProductionComponent( 196 modules = {ExecutorModule.class, OptionalBindingModule.class, ConcreteBindingModule.class} 197 ) 198 interface PresentOptionalProvisionBindingComponent extends OptionalBindingComponent {} 199 } 200