aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/moe/nea/ledger/utils/DIProvider.kt
blob: 98d1bbc82b346687b3a0bfb00ffeb0685666b2fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package moe.nea.ledger.utils

import java.lang.reflect.AnnotatedElement
import java.lang.reflect.Constructor

fun interface DIProvider<T : Any> : BaseDIProvider<T, Unit> {
	override fun provideWithContext(di: DI, context: Unit): T {
		return provide(di)
	}

	override fun createContext(element: AnnotatedElement) {
	}

	override fun createEmptyContext() {
	}

	fun provide(di: DI): T

	companion object {

		fun <T : Any> fromInjectableClass(clazz: Class<T>): DIProvider<T> {
			@Suppress("UNCHECKED_CAST")
			val cons = (clazz.constructors.find { it.getAnnotation(Inject::class.java) != null }
				?: clazz.constructors.find { it.parameterCount == 0 }
				?: error("Could not find DI injection entrypoint for class $clazz"))
					as Constructor<out T>
			return DIProvider { di ->
				val typArgs = cons.parameters.map {
					di.provide(it.type, it)
				}.toTypedArray()
				val instance = cons.newInstance(*typArgs)
				for (it in clazz.fields) {
					if (it.getAnnotation(Inject::class.java) == null) continue
					it.set(instance, di.provide(it.type, it))
				}
				instance
			}
		}

		fun <T : Any> singeleton(value: T): DIProvider<T> {
			return DIProvider { _ -> value }
		}
	}

}

interface BaseDIProvider<T : Any, C> {
	fun createContext(element: AnnotatedElement): C
	fun provideWithContext(di: DI, context: C): T
	fun createEmptyContext(): C
}