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

org.http4k.connect.Paged.kt Maven / Gradle / Ivy

There is a newer version: 5.35.2.0
Show newest version
package org.http4k.connect

import dev.forkhandles.result4k.Failure
import dev.forkhandles.result4k.Result
import dev.forkhandles.result4k.Success
import dev.forkhandles.result4k.map
import dev.forkhandles.result4k.peekFailure
import org.http4k.core.Response
import org.http4k.format.AutoMarshalling
import org.http4k.lens.LensExtractor
import kotlin.reflect.KClass

/**
 * Represents a Paged response
 */
interface Paged : Iterable {
    fun token(): Token?
    val items: List
    override fun iterator() = items.iterator()
}

/**
 * Superclass for all Paged actions
 */
interface PagedAction, Self : PagedAction> :
    Action> {
    fun next(token: Token): Self
}

/**
 * Paginate the response of the passed action
 */
fun , Rsp : Paged> paginated(
    fn: (Action) -> Result, action: Action
): Sequence, RemoteFailure>> {

    var nextRequest: Action? = action

    return generateSequence {
        nextRequest
            ?.let {
                fn(it).map { rsp ->
                    nextRequest = rsp.token()?.let(it::next)
                    rsp.items
                }
            }
    }.map { it.peekFailure { nextRequest = null } }
}

/**
 * Superclass for paged actions where the response can be auto-marshalled
 */
abstract class AutomarshalledPagedAction<
    Token,
    ItemType : Any,
    PageType : Paged,
    Self : AutomarshalledPagedAction
    >(
    private val toResult: (List, Token?) -> PageType,
    private val autoMarshalling: AutoMarshalling,
    private val kClass: KClass
) : PagedAction,
    LensExtractor {

    override fun toResult(response: Response): Result = with(response) {
        when {
            status.successful -> {
                val itemsAsListEvenWhenTheyAreNot =
                    bodyString().let { if (it.trimStart().startsWith("[")) it else """[$it]""" }
                Success(
                    toResult(
                        autoMarshalling
                            .asA(
                                """{"items":$itemsAsListEvenWhenTheyAreNot}""".trimIndent(),
                                kClass
                            ).items,
                        this@AutomarshalledPagedAction(this)
                    )
                )
            }

            else -> Failure(asRemoteFailure(this))
        }
    }

    override fun equals(other: Any?) = when {
        this === other -> true
        javaClass != other?.javaClass -> false
        else -> toRequest() == (other as Action<*>).toRequest()
    }

    override fun hashCode() = toRequest().hashCode()
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy