• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * * Copyright 2022 Google LLC. All rights reserved.
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 beer
18 
19 import dagger.Binds
20 import dagger.Component
21 import dagger.Lazy
22 import dagger.Module
23 import dagger.Provides
24 import javax.inject.Inject
25 import javax.inject.Singleton
26 
27 interface Grains {
28   val name: String
29 }
30 
31 interface Hops {
32   val name: String
33 }
34 
35 interface Yeast {
36   val name: String
37 }
38 
39 interface Kettle {
steepnull40   fun steep()
41   fun heat()
42   fun boil()
43   fun cool()
44   fun ferment()
45   fun addGrains(grains: Grains)
46   fun addHops(hops: Hops)
47   fun addYeast(yeast: Yeast)
48   val isBoiling: Boolean
49   val hasCooled: Boolean
50   val isDone: Boolean
51 }
52 
53 interface Storage {
54   fun store()
55 }
56 
57 class PilsnerMalt
58 @Inject constructor() : Grains {
59   override val name get() = "Pilsner Malt"
60 }
61 
62 class Spalt
63 @Inject constructor() : Hops {
64   override val name get() = "Spalt"
65 }
66 
67 class Wyeast
68 @Inject constructor() : Yeast {
69   override val name get() = "Wyeast 2565 Kölsch"
70 }
71 
72 class BrewPot : Kettle {
73   var boiling: Boolean = false
74   var cool: Boolean = true
75   var done: Boolean = false
76 
addGrainsnull77   override fun addGrains(grains: Grains) {
78     println("Adding grains: " + grains.name)
79   }
80 
steepnull81   override fun steep() {
82     println("=> Steeping")
83   }
84 
heatnull85   override fun heat() {
86     println("=> Heating")
87     this.cool = false
88   }
89 
boilnull90   override fun boil() {
91     println("=> Boiling")
92     this.boiling = true
93   }
94 
coolnull95   override fun cool() {
96     println("=> Cooling")
97     this.boiling = false
98     this.cool = true
99   }
100 
addHopsnull101   override fun addHops(hops: Hops) {
102     println("Adding hops: " + hops.name)
103   }
104 
fermentnull105   override fun ferment() {
106     println("=> Fermenting")
107     this.done = true
108   }
109 
addYeastnull110   override fun addYeast(yeast: Yeast) {
111     println("Adding yeast: " + yeast.name)
112   }
113 
114   override val isBoiling get() = boiling
115   override val hasCooled get() = cool
116   override val isDone get() = done
117 }
118 
119 class Bottler
120 @Inject constructor(
121   private val kettle: Kettle
122 ) : Storage {
storenull123   override fun store() {
124     if (kettle.isDone) {
125       println("=> bottling")
126     }
127   }
128 }
129 
130 class BeerBrewer
131 @Inject constructor(
132   private val kettle: Lazy<Kettle>,
133   private val bottler: Bottler,
134   private val grains: Grains,
135   private val hops: Hops,
136   private val yeast: Yeast
137 ) {
brewnull138   fun brew() {
139     kettle.get().apply {
140       addGrains(grains)
141       steep()
142       heat()
143       boil()
144       if (isBoiling) addHops(hops)
145       cool()
146       if (hasCooled) addYeast(yeast)
147       ferment()
148     }
149     bottler.store()
150   }
151 }
152 
153 @Module
154 abstract class CommercialEquipmentModule {
155   @Binds
provideStoragenull156   abstract fun provideStorage(storage: Bottler): Storage
157 }
158 
159 @Module(includes = [CommercialEquipmentModule::class])
160 class BrewingEquipmentModule {
161   @Provides @Singleton
162   fun provideKettle(): Kettle = BrewPot()
163 }
164 
165 @Module
166 interface KolschRecipeModule {
167   @Binds
bindGrainsnull168   fun bindGrains(grains: PilsnerMalt): Grains
169 
170   @Binds
171   fun bindHops(hops: Spalt): Hops
172 
173   @Binds
174   fun bindYeast(yeast: Wyeast): Yeast
175 }
176 
177 @Singleton
178 @Component(modules = [BrewingEquipmentModule::class, KolschRecipeModule::class])
179 interface Brewery {
180   fun brewery(): BeerBrewer
181 }
182 
mainnull183 fun main(args: Array<String>) {
184   val beer = DaggerBrewery.builder().build()
185   beer.brewery().brew()
186 }
187