Kotlin reflection to generate one class from class similar with similar properties This code is intended to generate a class (domain) from a class with class with similar/identical properties (api). Motivation is to speed development time when using clean architecture.

import org.joda.time.DateTime
import org.joda.time.DateTimeZone
import javax.inject.Inject
import kotlin.reflect.KClass
import kotlin.reflect.KParameter
import kotlin.reflect.full.declaredMemberProperties
import kotlin.reflect.full.findAnnotation

class DomainApiReflectionAdapter&lt;DOMAIN : Any, API : Any&gt; constructor(
        val clazz: KClass&lt;DOMAIN&gt;
) {

    fun fromApi(apiModel: API): DOMAIN {
        return apiToDomain(apiModel, clazz)
    }

    inline fun &lt;API : Any, DOMAIN : Any&gt; apiToDomain(apiModel: API, clazz: KClass&lt;DOMAIN&gt;): DOMAIN {
        val factory = Factory(clazz)
        val apiProperties = toPropMap(apiModel)
        val constructorMap = mutableMapOf&lt;KParameter, Any?&gt;()
        for (param in factory.params) {
            param.findAnnotation&lt;AdapterValues&gt;()?.let {
                val iclass = param.type.classifier as KClass&lt;*&gt;
                println(iclass)
                constructorMap[param] = innerFactory.simpleConstruct(apiProperties)
            } ?: {
                if (param.name in apiProperties) {
                    constructorMap[param] = when {
                        param.type.classifier == List::class -&gt; {
                            val itype = param.type.arguments[0].type!!.classifier as KClass&lt;*&gt;
                            (apiProperties[param.name] as List&lt;*&gt;).map {
                                it?.toDomain(itype)
                            }
                        }
                        param.type.classifier == DateTime::class -&gt; DateTime(apiProperties[param.name] as Long, DateTimeZone.forID("UTC"))
                        else -&gt; apiProperties[param.name]
                    }
                }
            }()
        }

        return factory.construct(constructorMap)
    }

    fun &lt;K : Any&gt; toPropMap(model: K): Map&lt;String, Any?&gt; {
        return model.javaClass.kotlin.declaredMemberProperties
                .map { prop -&gt;
                    prop.name to prop.get(model)
                }.toMap()
    }

    companion object {
        inline fun &lt;reified DOMAIN : Any, API : Any&gt; instance(): DomainApiReflectionAdapter&lt;DOMAIN, API&gt; {
            return DomainApiReflectionAdapter(DOMAIN::class)
        }
    }

    inner class Factory&lt;DOMAIN : Any&gt;(clazz: KClass&lt;DOMAIN&gt;) {
        private val constructor = clazz.constructors.first()
        val params = constructor.parameters

        fun construct(map: Map&lt;KParameter, Any?&gt;): DOMAIN {
            return constructor.callBy(map)
        }

        fun simpleConstruct(apiProperties: Map&lt;String, Any?&gt;): DOMAIN {
            val innerMap = mutableMapOf&lt;KParameter, Any?&gt;()
            for (ip in params) {
                innerMap[ip] = apiProperties[ip.name]
            }
            return construct(innerMap)
        }
    }
}

fun &lt;DOMAIN : Any, API : Any&gt; API.toDomain(clazz: KClass&lt;DOMAIN&gt;): DOMAIN {
    val adapter = DomainApiReflectionAdapter&lt;DOMAIN, API&gt;(clazz)
    return adapter.fromApi(this)
}

abstract class Adapter&lt;A, B&gt; : (B) -&gt; A

@Target(AnnotationTarget.VALUE_PARAMETER)
annotation class AdapterClass()

@Target(AnnotationTarget.VALUE_PARAMETER)
annotation class AdapterValues(val parameters: Array&lt;String&gt;)
inline functions

inline function are great when:


You want to surround a lambda with a little code
You want to use reified types.


They are not great when you have a large function, as every call to that function will be replaced with the body of the function.

Therefor, inlining apiToDomain seams the wrong choice.
You have another function: API.toDomain.

associate

I found the following in your code:
    map{ it.a to it.b }.toMap() 

This can replaced by:

associate{ it.a to it.b }


(it can be used if you have one parameter)

associateWith

In kotlin 1.3, you can use associateWith for simpleConstruct:

val map = listOf(1,2,3).associateWith{ it.toString }
println(map) // [1:"1", 2:"2", 3:"3"]


when

your when looks like

when {
    param.type.classifier == List::class -&gt; 
    param.type.classifier == DateTime::class -&gt; 
    else -&gt;
}


this can be simplified to:

when(param.type.classifier) {
    List::class -&gt; 
    DateTime::class -&gt; 
    else -&gt;
}


run

in your function, you use {...}(). run{} does exactly the same, but you can't forget to invoke it. This is however a personal choice.

function bodies

I personnaly don't like functions where the body starts with return:

fun fromApi(apiModel: API): DOMAIN {
    return apiToDomain(apiModel, clazz)
}


you can rewrite this as:

fun fromApi(apiModel: API): DOMAIN = apiToDomain(apiModel, clazz)


or even like:

fun fromApi(apiModel: API) = apiToDomain(apiModel, clazz)


typealias

I dont know exactly the purpose of 

abstract class Adapter&lt;A, B&gt; : (B) -&gt; A


but maybe you can use a typealias?

typealias Adapter&lt;A, B&gt; = (B) -&gt; A


constructing

I thing you forgot a keyword in front of your constructor? As you wrote it out and you have a companion-object that creates a type of your class...
Ps. If you want to construct in your companion-object, but it should look like a constructor-call, you can use operator fun invoke(...)

Hope this helps a bit