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

commonMain.dev.kord.cache.map.internal.KeyValueQueryBuilder.kt Maven / Gradle / Ivy

The newest version!
package dev.kord.cache.map.internal

import dev.kord.cache.api.DataCache
import dev.kord.cache.api.Query
import dev.kord.cache.api.QueryBuilder
import dev.kord.cache.api.data.DataDescription
import dev.kord.cache.map.MapLikeCollection
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.*
import kotlin.reflect.KProperty1

internal class KeyValueQueryBuilder(
        private val cache: DataCache,
        private val collection: MapLikeCollection,
        private val description: DataDescription
) : QueryBuilder {

    private val actions = mutableListOf>()

    private val KProperty1.isPrimary get() = description.indexField.property == this

    @Suppress("UNCHECKED_CAST")
    override infix fun  KProperty1.eq(value: R) = when {
        isPrimary -> addIds(setOf(value as KEY))
        else -> predicate { it == value }
    }

    @Suppress("UNCHECKED_CAST")
    override fun  KProperty1.`in`(items: Iterable) = when {
        isPrimary -> when (items) {
            is ClosedRange<*> -> predicate { it in items }
            else -> addIds(items as Iterable)
        }
        else -> predicate { it in items }
    }

    @Suppress("UNCHECKED_CAST")
    override fun  KProperty1.ne(value: R) = when {
        isPrimary -> addNotId(value as KEY)
        else -> predicate { it != value }
    }

    @Suppress("UNCHECKED_CAST")
    override fun  KProperty1.notIn(items: Iterable) = when {
        isPrimary -> addNotId(items as Iterable)
        else -> predicate { it !in items }
    }

    override infix fun  KProperty1.predicate(predicate: (R) -> Boolean) {
        actions += Action.ValueAction { predicate(get(it)) }
    }

    @ExperimentalCoroutinesApi
    override fun build(): Query = ActionQuery(cache, collection, description, actions.sortedBy { it.impact })

    private fun addIds(keys: Iterable) {
        val index = actions.indexOfFirst { it is Action.SelectByIds }

        if (index == -1) {
            actions += Action.SelectByIds(keys.toSet())
            return
        }

        val action = actions.removeAt(index) as Action.SelectByIds
        actions += Action.SelectByIds(action.keys intersect keys.toSet())
    }

    private fun addNotId(keys: Iterable) {
        val index = actions.indexOfFirst { it is Action.SelectByIdNotPresent }

        if (index == -1) {
            actions += Action.SelectByIdNotPresent(keys.toList())
            return
        }

        val action = actions.removeAt(index) as Action.SelectByIdNotPresent
        actions += Action.SelectByIdNotPresent(keys + action.keys)
    }

    private fun addNotId(key: KEY) {
        val index = actions.indexOfFirst { it is Action.SelectByIdNotPresent }

        if (index == -1) {
            actions += Action.SelectByIdNotPresent(listOf(key))
            return
        }

        val action = actions.removeAt(index) as Action.SelectByIdNotPresent
        actions += Action.SelectByIdNotPresent(action.keys + key)
    }
}

internal abstract class Action(val impact: Int) {

    abstract fun onMap(description: DataDescription, collection: MapLikeCollection): Flow

    abstract suspend fun filter(description: DataDescription, value: VALUE): Boolean

    class ValueAction(val action: (VALUE) -> Boolean) : Action(0) {
        override fun onMap(description: DataDescription, collection: MapLikeCollection): Flow =
                collection.values().filter { action(it) }

        override suspend fun filter(description: DataDescription, value: VALUE): Boolean = action(value)
    }

    class SelectByIds(val keys: Set) : Action(50) {
        override fun onMap(description: DataDescription, collection: MapLikeCollection): Flow =
                keys.asFlow().mapNotNull { collection.get(it) }

        override suspend fun filter(description: DataDescription, value: VALUE): Boolean =
                description.indexField.property.get(value) in keys
    }

    class SelectByIdNotPresent(val keys: List) : Action(100) {
        override fun onMap(description: DataDescription, collection: MapLikeCollection): Flow = flow {
            val flow = if (keys.all { collection.get(it) == null }) collection.values()
            else collection.values().filter { description.indexField.property.get(it) !in keys }

            @Suppress("EXPERIMENTAL_API_USAGE")
            emitAll(flow)
        }

        override suspend fun filter(description: DataDescription, value: VALUE): Boolean =
                description.indexField.property.get(value) !in keys
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy