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

io.javalin.community.routing.dsl.defaults.DefaultContextScope.kt Maven / Gradle / Ivy

There is a newer version: 6.4.0
Show newest version
package io.javalin.community.routing.dsl.defaults

import io.javalin.community.routing.Route
import io.javalin.community.routing.dsl.DslRoute
import io.javalin.community.routing.dsl.RoutingDslConfiguration
import io.javalin.http.Context
import kotlin.reflect.full.createInstance
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.full.primaryConstructor
import kotlin.reflect.javaType

interface DefaultContextScope {
    val ctx: Context
}

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.CLASS)
annotation class Path(
    val path: String
)

open class DefaultContextScopeConfiguration<
    ROUTE : DslRoute,
    CONTEXT : DefaultContextScope,
    RESPONSE : Any
> : RoutingDslConfiguration() {

    @OptIn(ExperimentalStdlibApi::class)
    inline fun  method(method: Route, crossinline handler: (CONTEXT, PATH) -> RESPONSE) {
        val path = PATH::class.findAnnotation()
            ?.path
            ?: throw IllegalArgumentException("@Path annotation not found")

        val primaryConstructor = PATH::class.primaryConstructor

        primaryConstructor
            ?.parameters
            ?.forEach {
                require(path.contains("{${it.name}") || path.contains("<${it.name}>")) {
                    "Path parameter '${it.name}' not found in path $path (path type: ${PATH::class})"
                }
            }

        val standardHandler: CONTEXT.() -> RESPONSE = {
            val pathInstance = primaryConstructor
                ?.parameters
                ?.associateWith {
                    ctx.pathParamAsClass(
                        it.name ?: throw IllegalStateException("Unknown parameter name in class ${PATH::class}"),
                        it.type.javaType as Class<*>
                    ).get()
                }
                ?.let { primaryConstructor.callBy(it) }
                ?: PATH::class.createInstance()

            handler(this, pathInstance)
        }

        when (method) {
            Route.GET -> get(path, standardHandler)
            Route.POST -> post(path, standardHandler)
            Route.PUT -> put(path, standardHandler)
            Route.DELETE -> delete(path, standardHandler)
            Route.PATCH -> patch(path, standardHandler)
            Route.HEAD -> head(path, standardHandler)
            Route.OPTIONS -> options(path, standardHandler)
            Route.BEFORE -> before(path, standardHandler)
            Route.BEFORE_MATCHED -> beforeMatched(path, standardHandler)
            Route.AFTER -> after(path, standardHandler)
            Route.AFTER_MATCHED -> afterMatched(path, standardHandler)
        }
    }

    inline fun  get(crossinline handler: CONTEXT.(PATH) -> RESPONSE) = method(Route.GET, handler)
    inline fun  post(crossinline handler: CONTEXT.(PATH) -> RESPONSE) = method(Route.POST, handler)
    inline fun  put(crossinline handler: CONTEXT.(PATH) -> RESPONSE) = method(Route.PUT, handler)
    inline fun  delete(crossinline handler: CONTEXT.(PATH) -> RESPONSE) = method(Route.DELETE, handler)
    inline fun  patch(crossinline handler: CONTEXT.(PATH) -> RESPONSE) = method(Route.PATCH, handler)
    inline fun  head(crossinline handler: CONTEXT.(PATH) -> RESPONSE) = method(Route.HEAD, handler)
    inline fun  options(crossinline handler: CONTEXT.(PATH) -> RESPONSE) = method(Route.OPTIONS, handler)
    inline fun  before(crossinline handler: CONTEXT.(PATH) -> RESPONSE) = method(Route.BEFORE, handler)
    inline fun  beforeMatched(crossinline handler: CONTEXT.(PATH) -> RESPONSE) = method(Route.BEFORE_MATCHED, handler)
    inline fun  after(crossinline handler: CONTEXT.(PATH) -> RESPONSE) = method(Route.AFTER, handler)
    inline fun  afterMatched(crossinline handler: CONTEXT.(PATH) -> RESPONSE) = method(Route.AFTER_MATCHED, handler)

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy