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

org.http4k.contract.routeSpec.kt Maven / Gradle / Ivy

package org.http4k.contract

import org.http4k.core.Filter
import org.http4k.core.HttpHandler
import org.http4k.core.Request
import org.http4k.lens.BodyLens
import org.http4k.lens.Failure
import org.http4k.lens.Lens
import org.http4k.lens.LensFailure
import org.http4k.lens.Path
import org.http4k.lens.PathLens

abstract class ContractRouteSpec internal constructor(val pathFn: (PathSegments) -> PathSegments,
                                                      val requestParams: List>,
                                                      val body: BodyLens<*>?,
                                                      vararg val pathLenses: PathLens<*>) : Filter {

    abstract infix operator fun  div(next: PathLens): ContractRouteSpec

    open infix operator fun div(next: String) = div(Path.fixed(next))

    override fun invoke(nextHandler: HttpHandler): HttpHandler =
        { req ->
            val body = body?.let { listOf(it::invoke) } ?: emptyList<(Request) -> Any?>()
            val errors = body.plus(requestParams).fold(emptyList()) { memo, next ->
                try {
                    next(req)
                    memo
                } catch (e: LensFailure) {
                    memo.plus(e.failures)
                }
            }
            if (errors.isEmpty()) nextHandler(req) else throw LensFailure(errors)
        }

    internal fun describe(contractRoot: PathSegments): String = "${pathFn(contractRoot)}${if (pathLenses.isNotEmpty()) "/${pathLenses.joinToString("/")}" else ""}"
}

class ContractRouteSpec0 internal constructor(pathFn: (PathSegments) -> PathSegments, requestParams: List>, body: BodyLens<*>?) : ContractRouteSpec(pathFn, requestParams, body) {
    override infix operator fun div(next: String) = ContractRouteSpec0({ it / next }, emptyList(), body)

    override infix operator fun  div(next: PathLens) = ContractRouteSpec1(pathFn, requestParams, body, next)
}

class ContractRouteSpec1 internal constructor(pathFn: (PathSegments) -> PathSegments, requestParams: List>, body: BodyLens<*>?, val a: PathLens) : ContractRouteSpec(pathFn, requestParams, body, a) {
    override infix operator fun div(next: String) = div(Path.fixed(next))

    override infix operator fun  div(next: PathLens) = ContractRouteSpec2(pathFn, requestParams, body, a, next)
}

class ContractRouteSpec2 internal constructor(pathFn: (PathSegments) -> PathSegments, requestParams: List>, body: BodyLens<*>?, val a: PathLens, val b: PathLens) : ContractRouteSpec(pathFn, requestParams, body, a, b) {
    override infix operator fun div(next: String) = div(Path.fixed(next))

    override infix operator fun  div(next: PathLens) = ContractRouteSpec3(pathFn, requestParams, body, a, b, next)
}

class ContractRouteSpec3 internal constructor(pathFn: (PathSegments) -> PathSegments, requestParams: List>, body: BodyLens<*>?,
                                                                   val a: PathLens, val b: PathLens, val c: PathLens) : ContractRouteSpec(pathFn, requestParams, body, a, b, c) {
    override infix operator fun div(next: String) = div(Path.fixed(next))

    override infix operator fun  div(next: PathLens) = ContractRouteSpec4(pathFn, requestParams, body, a, b, c, next)
}

class ContractRouteSpec4 internal constructor(pathFn: (PathSegments) -> PathSegments, requestParams: List>, body: BodyLens<*>?,
                                                                          val a: PathLens, val b: PathLens, val c: PathLens, val d: PathLens) : ContractRouteSpec(pathFn, requestParams, body, a, b, c, d) {
    override infix operator fun div(next: String) = throw UnsupportedOperationException("no longer paths!")

    override infix operator fun  div(next: PathLens) = throw UnsupportedOperationException("no longer paths!")
}