@@ -15,6 +15,26 @@ import kotlin.reflect.full.findAnnotations
1515import kotlin.reflect.full.functions
1616import kotlin.reflect.full.isSubclassOf
1717
18+ /* *
19+ * A cached entry in the [FromDynamicType] dispatch table,
20+ * pairing a factory method with its annotation metadata.
21+ */
22+ private data class FactoryEntry (
23+ val function : KFunction <* >,
24+ val annotation : FromDynamicType ,
25+ )
26+
27+ /* *
28+ * Cached dispatch table of [ValueFactory] methods annotated with [FromDynamicType].
29+ */
30+ private val factoryEntries: List <FactoryEntry > by lazy {
31+ ValueFactory ::class .declaredFunctions.flatMap { function ->
32+ function.findAnnotations<FromDynamicType >().map { annotation ->
33+ FactoryEntry (function, annotation)
34+ }
35+ }
36+ }
37+
1838/* *
1939 * A converter of a value that potentially holds any type (its value is stored as a plain string)
2040 * to a specific, statically defined [Value] type that can be used as an input for a function call argument.
@@ -54,25 +74,25 @@ class DynamicValueConverter(
5474 ? : throw NoSuchElementException (element = raw, values)
5575 }
5676
57- // Gets ValueFactory methods annotated with @FromDynamicType(X::class),
58- // and the one with a matching type is invoked.
59- for (function in ValueFactory ::class .declaredFunctions) {
60- val annotations = function.findAnnotations<FromDynamicType >()
61- val from = annotations.find { type.isSubclassOf(it.unwrappedType) } ? : continue
77+ // Looks up the pre-built dispatch table for a matching factory method.
78+ for ((function, annotation) in factoryEntries) {
79+ if (! type.isSubclassOf(annotation.unwrappedType)) continue
6280
6381 // The factory method is suitable. Invoking it.
6482
6583 return try {
6684 when {
6785 // Fetch the context from the function call if it's required.
68- from .requiresContext -> {
86+ annotation .requiresContext -> {
6987 if (context == null ) {
7088 throw IllegalStateException (" Function call does not have an attached context" )
7189 }
7290 function.call(ValueFactory , raw, context)
7391 }
7492
75- else -> function.call(ValueFactory , raw)
93+ else -> {
94+ function.call(ValueFactory , raw)
95+ }
7696 } as InputValue <* >?
7797 } catch (e: InvocationTargetException ) {
7898 throw e.cause ? : e
0 commit comments