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.jdk8; 18 19 import static java.lang.annotation.RetentionPolicy.RUNTIME; 20 21 import com.google.auto.value.AutoValue; 22 import dagger.BindsOptionalOf; 23 import dagger.Component; 24 import dagger.Lazy; 25 import dagger.Module; 26 import dagger.Provides; 27 import dagger.Subcomponent; 28 import java.lang.annotation.Retention; 29 import java.util.Optional; 30 import javax.annotation.Nullable; 31 import javax.inject.Inject; 32 import javax.inject.Provider; 33 import javax.inject.Qualifier; 34 35 /** Classes to support testing {@code BindsOptionalOf} functionality. */ 36 public final class OptionalBindingComponents { 37 38 /** A qualifier. */ 39 @Qualifier 40 @Retention(RUNTIME) 41 public @interface SomeQualifier {} 42 43 /** A value object that contains various optionally-bound objects. */ 44 @AutoValue 45 public abstract static class Values { optionalInstance()46 abstract Optional<Value> optionalInstance(); 47 optionalProvider()48 abstract Optional<Provider<Value>> optionalProvider(); 49 optionalLazy()50 abstract Optional<Lazy<Value>> optionalLazy(); 51 optionalLazyProvider()52 abstract Optional<Provider<Lazy<Value>>> optionalLazyProvider(); 53 } 54 55 // Default access so that it's inaccessible to OptionalBindingComponentsWithInaccessibleTypes. 56 enum Value { 57 VALUE, 58 QUALIFIED_VALUE 59 } 60 61 static final class InjectedThing { 62 @Inject InjectedThing()63 InjectedThing() {} 64 } 65 66 /** Binds optionals and {@link Values}. */ 67 @Module 68 public abstract static class OptionalBindingModule { 69 @BindsOptionalOf value()70 abstract Value value(); 71 72 @BindsOptionalOf qualifiedValue()73 @SomeQualifier abstract Value qualifiedValue(); 74 75 // Valid because it's qualified. 76 @BindsOptionalOf qualifiedInjectedThing()77 @SomeQualifier abstract InjectedThing qualifiedInjectedThing(); 78 79 @BindsOptionalOf nullableObject()80 abstract Object nullableObject(); 81 82 @Provides values( Optional<Value> optionalInstance, Optional<Provider<Value>> optionalProvider, Optional<Lazy<Value>> optionalLazy, Optional<Provider<Lazy<Value>>> optionalLazyProvider)83 static Values values( 84 Optional<Value> optionalInstance, 85 Optional<Provider<Value>> optionalProvider, 86 Optional<Lazy<Value>> optionalLazy, 87 Optional<Provider<Lazy<Value>>> optionalLazyProvider) { 88 return new AutoValue_OptionalBindingComponents_Values( 89 optionalInstance, optionalProvider, optionalLazy, optionalLazyProvider); 90 } 91 92 @Provides 93 @SomeQualifier qualifiedValues( @omeQualifier Optional<Value> optionalInstance, @SomeQualifier Optional<Provider<Value>> optionalProvider, @SomeQualifier Optional<Lazy<Value>> optionalLazy, @SomeQualifier Optional<Provider<Lazy<Value>>> optionalLazyProvider)94 static Values qualifiedValues( 95 @SomeQualifier Optional<Value> optionalInstance, 96 @SomeQualifier Optional<Provider<Value>> optionalProvider, 97 @SomeQualifier Optional<Lazy<Value>> optionalLazy, 98 @SomeQualifier Optional<Provider<Lazy<Value>>> optionalLazyProvider) { 99 return new AutoValue_OptionalBindingComponents_Values( 100 optionalInstance, optionalProvider, optionalLazy, optionalLazyProvider); 101 } 102 } 103 104 /** Binds {@link Value}. */ 105 @Module 106 public abstract static class ConcreteBindingModule { 107 /** @param cycle to demonstrate that optional {@link Provider} injection can break cycles */ 108 @Provides value(Optional<Provider<Value>> cycle)109 static Value value(Optional<Provider<Value>> cycle) { 110 return Value.VALUE; 111 } 112 113 @Provides qualifiedValue()114 @SomeQualifier static Value qualifiedValue() { 115 return Value.QUALIFIED_VALUE; 116 } 117 118 @Provides 119 @Nullable nullableObject()120 static Object nullableObject() { 121 return null; 122 } 123 } 124 125 /** Interface for components used to test optional bindings. */ 126 public interface OptionalBindingComponent { values()127 Values values(); 128 129 @SomeQualifier qualifiedValues()130 Values qualifiedValues(); 131 132 // Nullable bindings can satisfy optional bindings except for Optional<Foo>. 133 optionalNullableProvider()134 Optional<Provider<Object>> optionalNullableProvider(); 135 optionalNullableLazy()136 Optional<Lazy<Object>> optionalNullableLazy(); 137 optionalNullableLazyProvider()138 Optional<Provider<Lazy<Object>>> optionalNullableLazyProvider(); 139 } 140 141 @Component(modules = OptionalBindingModule.class) 142 interface EmptyOptionalBindingComponent extends OptionalBindingComponent { presentChild()143 PresentOptionalBindingSubcomponent presentChild(); 144 } 145 146 @Component(modules = {OptionalBindingModule.class, ConcreteBindingModule.class}) 147 interface PresentOptionalBindingComponent extends OptionalBindingComponent {} 148 149 @Subcomponent(modules = ConcreteBindingModule.class) 150 interface PresentOptionalBindingSubcomponent extends OptionalBindingComponent {} 151 } 152