All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jvmMain.internal.KClass.kt Maven / Gradle / Ivy

There is a newer version: 0.23.0
Show newest version
package io.kform.internal

import kotlin.reflect.KClass
import kotlin.reflect.KMutableProperty1
import kotlin.reflect.KVisibility

internal actual fun  constructFromKClass(
    kClass: KClass,
    childValues: Map,
    childProps: Map>
): T {
    // HACK: We try to find a "callable" constructor by matching property names with argument names;
    //  this is obviously **very** error-prone but will work nicely for the typical case where data
    //  classes are used
    val minConstructor =
        kClass.constructors
            // Find all callable constructors (where params are either optional or their names match
            // child prop names)
            .filter { constructor ->
                constructor.visibility != KVisibility.PRIVATE &&
                    constructor.parameters.all { param ->
                        param.name in childValues || param.isOptional
                    }
            }
            // Pick the constructor that takes the minimum amount of child properties
            .minByOrNull { constructor -> constructor.parameters.size }
            ?: error(
                "Could not find a callable constructor for '${kClass::qualifiedName}'. " +
                    "Please provide a [constructorFunction] when creating the schema."
            )

    // Create an instance of the class and keep track of which props were used to construct it
    val usedProps = HashSet(childValues.size)
    val instance =
        minConstructor.call(
            *minConstructor.parameters
                .map { param ->
                    if (param.name in childValues) {
                        usedProps += param.name!!
                        childValues[param.name]
                    } else null
                }
                .toTypedArray()
        )

    // Manually set props that weren't used in the construction of the instance
    if (usedProps.size < childValues.size) {
        for ((name, value) in childValues) {
            if (name !in usedProps) {
                childProps[name]!!.set(instance, value)
            }
        }
    }

    return instance
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy