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

jvmMain.ch.softappeal.yass2.generate.ServiceGenerate.kt Maven / Gradle / Ivy

There is a newer version: 5.0.0
Show newest version
package ch.softappeal.yass2.generate

import ch.softappeal.yass2.*
import ch.softappeal.yass2.remote.*
import kotlin.reflect.full.*

fun generateRemote(
    serviceIds: List>, factoryName: String = "generatedRemoteProxyFactory", invokerName: String = "generatedInvoker"
): String {
    require(serviceIds.map { it.id }.toSet().size == serviceIds.size) { "duplicated service id's" }
    return with(StringBuilder(10_000)) {
        fun out(s: String, level: Int = 0) = append(s.replaceIndent("    ".repeat(level))).append('\n')
        out("""
            @Suppress("UNCHECKED_CAST", "PARAMETER_NAME_CHANGED_ON_OVERRIDE", "RemoveRedundantQualifierName", "SpellCheckingInspection")
            fun $factoryName(tunnel: ch.softappeal.yass2.remote.Tunnel) = object : ${RemoteProxyFactory::class.qualifiedName} {
                suspend operator fun ch.softappeal.yass2.remote.Tunnel.invoke(serviceId: Int, functionId: Int, vararg parameters: Any?): Any? =
                    this(${Request::class.qualifiedName}(serviceId, functionId, listOf(*parameters))).process()
            
                override fun  create(serviceId: ${ServiceId::class.qualifiedName}): S = when (serviceId.id) {
        """)
        serviceIds.forEach { serviceId ->
            serviceId.service.checkService()
            out("""
                ${serviceId.id} -> object : ${serviceId.service.qualifiedName} {
            """, 2)
            serviceId.service.serviceFunctions().withIndex().forEach { (index, function) ->
                with(function) {
                    functionSignature(index, this)
                    if (hasResult()) append(" = ") else append(" {\n                ")
                    append("tunnel(${serviceId.id}, $index")
                    valueParameters.forEach { append(", p${it.index}") }
                    append(")")
                    if (hasResult() && returnType.needsCast()) append(" as $returnType")
                    if (!hasResult()) append("\n            }")
                    append("\n")
                }
            }
            out("""
                } as S
            """, 2)
        }
        out("""
                    else -> error("no service id ${'$'}{serviceId.id}")
                }
            }
    
            @Suppress("RemoveRedundantQualifierName", "SpellCheckingInspection")
            suspend fun $invokerName(request: ${Request::class.qualifiedName}, service: ${Service::class.qualifiedName}): Any? {
                val p = request.parameters
                return when (request.serviceId) {
        """)
        serviceIds.forEach { serviceId ->
            out("""
                ${serviceId.id} -> when (request.functionId) {
            """, 2)
            serviceId.service.serviceFunctions().withIndex().forEach { (index, function) ->
                append("            $index -> (service.implementation as ${serviceId.service.qualifiedName}).${function.name}(")
                function.valueParameters.forEach { parameter ->
                    if (parameter.index != 1) append(", ")
                    append("p[${parameter.index - 1}]")
                    if (parameter.type.needsCast()) append(" as ${parameter.type}")
                }
                append(")\n")
            }
            out("""
                    else -> error("no function id ${'$'}{request.functionId} for service id ${'$'}{request.serviceId}")
                }
            """, 2)
        }
        out("""
                    else -> error("no service id ${'$'}{request.serviceId}")
                }
            }
        """)
    }.toString()
}