• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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