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.subcomponent; 18 19 import com.google.common.util.concurrent.ListenableFuture; 20 import dagger.Component; 21 import dagger.Module; 22 import dagger.Provides; 23 import dagger.producers.ProducerModule; 24 import dagger.producers.Produces; 25 import dagger.producers.Production; 26 import dagger.producers.ProductionComponent; 27 import dagger.producers.ProductionSubcomponent; 28 import java.lang.annotation.Retention; 29 import java.lang.annotation.RetentionPolicy; 30 import java.util.concurrent.Executor; 31 import java.util.concurrent.atomic.AtomicInteger; 32 import javax.inject.Inject; 33 import javax.inject.Provider; 34 import javax.inject.Qualifier; 35 36 final class SubcomponentsWithBoundExecutor { 37 @Retention(RetentionPolicy.RUNTIME) // Technically a JSR330 requirement 38 @Qualifier 39 @interface FromParent {} 40 41 @Retention(RetentionPolicy.RUNTIME) // Technically a JSR330 requirement 42 @Qualifier 43 @interface FromChild {} 44 45 @Retention(RetentionPolicy.RUNTIME) // Technically a JSR330 requirement 46 @Qualifier 47 @interface FromGrandchild {} 48 49 static final class CountingExecutor implements Executor { 50 private final AtomicInteger executionCount; 51 CountingExecutor(AtomicInteger executionCount)52 CountingExecutor(AtomicInteger executionCount) { 53 this.executionCount = executionCount; 54 } 55 56 @Override execute(Runnable runnable)57 public void execute(Runnable runnable) { 58 executionCount.incrementAndGet(); 59 runnable.run(); 60 } 61 } 62 63 @Module 64 static final class ExecutorModule { 65 private final AtomicInteger constructionCount; 66 private final AtomicInteger executionCount; 67 ExecutorModule(AtomicInteger constructionCount, AtomicInteger executionCount)68 ExecutorModule(AtomicInteger constructionCount, AtomicInteger executionCount) { 69 this.constructionCount = constructionCount; 70 this.executionCount = executionCount; 71 } 72 73 @Provides 74 @Production executor()75 Executor executor() { 76 constructionCount.incrementAndGet(); 77 return new CountingExecutor(executionCount); 78 } 79 } 80 81 @Module 82 static final class ParentModule { 83 @Provides 84 @FromParent fromParent()85 static String fromParent() { 86 return "parent"; 87 } 88 } 89 90 @Component(modules = {ParentModule.class, ExecutorModule.class}) 91 interface ParentComponent { injectsChildBuilder()92 InjectsChildBuilder injectsChildBuilder(); 93 newChildComponentBuilder()94 ChildComponent.Builder newChildComponentBuilder(); 95 } 96 97 @ProducerModule 98 static final class ParentProducerModule { 99 @Produces 100 @FromParent fromParent()101 static String fromParent() { 102 return "parentproduction"; 103 } 104 } 105 106 @ProductionComponent(modules = {ParentProducerModule.class, ExecutorModule.class}) 107 interface ParentProductionComponent { newChildComponentBuilder()108 ChildComponent.Builder newChildComponentBuilder(); 109 110 @ProductionComponent.Builder 111 interface Builder { executorModule(ExecutorModule executorModule)112 Builder executorModule(ExecutorModule executorModule); 113 build()114 ParentProductionComponent build(); 115 } 116 } 117 118 @ProducerModule 119 static final class ChildProducerModule { 120 @Produces 121 @FromChild fromChild(@romParent String fromParent)122 static String fromChild(@FromParent String fromParent) { 123 return "child:" + fromParent; 124 } 125 } 126 127 @ProductionSubcomponent(modules = ChildProducerModule.class) 128 interface ChildComponent { 129 @FromChild fromChild()130 ListenableFuture<String> fromChild(); 131 newGrandchildComponentBuilder()132 GrandchildComponent.Builder newGrandchildComponentBuilder(); newGrandchildComponent()133 GrandchildComponentWithoutBuilder newGrandchildComponent(); 134 135 @ProductionSubcomponent.Builder 136 interface Builder { build()137 ChildComponent build(); 138 } 139 } 140 141 static final class InjectsChildBuilder { 142 private final Provider<ChildComponent.Builder> childBuilder; 143 144 @Inject InjectsChildBuilder(Provider<ChildComponent.Builder> childBuilder)145 InjectsChildBuilder(Provider<ChildComponent.Builder> childBuilder) { 146 this.childBuilder = childBuilder; 147 } 148 childBuilder()149 ChildComponent.Builder childBuilder() { 150 return childBuilder.get(); 151 } 152 } 153 154 @ProducerModule 155 static final class GrandchildProducerModule { 156 @Produces 157 @FromGrandchild fromGranchild(@romChild String fromChild)158 static String fromGranchild(@FromChild String fromChild) { 159 return "grandchild:" + fromChild; 160 } 161 } 162 163 @ProductionSubcomponent(modules = GrandchildProducerModule.class) 164 interface GrandchildComponent { 165 @FromGrandchild fromGrandchild()166 ListenableFuture<String> fromGrandchild(); 167 168 @ProductionSubcomponent.Builder 169 interface Builder { build()170 GrandchildComponent build(); 171 } 172 } 173 174 @ProductionSubcomponent(modules = GrandchildProducerModule.class) 175 interface GrandchildComponentWithoutBuilder { 176 @FromGrandchild fromGrandchild()177 ListenableFuture<String> fromGrandchild(); 178 } 179 SubcomponentsWithBoundExecutor()180 private SubcomponentsWithBoundExecutor() {} 181 } 182