commonMain.dev.kord.cache.map.internal.KeyValueQueryBuilder.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cache-map-jvm Show documentation
Show all versions of cache-map-jvm Show documentation
Adaptable cache with query-like operations
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