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

com.lightningkite.lightningdb.Modification.kt Maven / Gradle / Ivy

@file:SharedCode

package com.lightningkite.lightningdb

import com.lightningkite.khrysalis.*
import kotlinx.serialization.*
import kotlin.reflect.KProperty1

@Serializable(ModificationSerializer::class)
// Why is this class open instead of sealed?  See https://github.com/Kotlin/kotlinx.serialization/issues/1843
open class Modification protected constructor()  {
    open override fun hashCode(): Int { fatalError() }
    open override fun equals(other: Any?): Boolean { fatalError() }
    open operator fun invoke(on: T): T { fatalError() }
    open fun invokeDefault(): T { fatalError() }

    @Deprecated("Use the modification {} builder instead")
    infix fun then(other: Modification): Modification.Chain = Modification.Chain(listOf(this, other))

    @Serializable(ModificationChainSerializer::class)
    data class Chain(val modifications: List>): Modification() {
        override fun invoke(on: T): T = modifications.fold(on) { item, mod -> mod(item) }
        override fun invokeDefault(): T {
            val on = modifications[0].invokeDefault()
            return modifications.drop(1).fold(on) { item, mod -> mod(item) }
        }
    }

    @Serializable(ModificationIfNotNullSerializer::class)
    data class IfNotNull(val modification: Modification): Modification() {
        override fun invoke(on: T?): T? = on?.let { modification(it) }
        override fun invokeDefault(): T? = null
    }

    @Serializable(ModificationAssignSerializer::class)
    data class Assign(val value: T): Modification() {
        override fun invoke(on: T): T = value
        override fun invokeDefault(): T = value
    }

    @Serializable(ModificationCoerceAtMostSerializer::class)
    data class CoerceAtMost>(val value: T): Modification() {
        override fun invoke(on: T): T = on.coerceAtMost(value)
        override fun invokeDefault(): T = value
    }

    @Serializable(ModificationCoerceAtLeastSerializer::class)
    data class CoerceAtLeast>(val value: T): Modification() {
        override fun invoke(on: T): T = on.coerceAtLeast(value)
        override fun invokeDefault(): T = value
    }

    @Serializable(ModificationIncrementSerializer::class)
    data class Increment(val by: T): Modification() {
        override fun invoke(on: T): T = on + by
        override fun invokeDefault(): T = by
    }

    @Serializable(ModificationMultiplySerializer::class)
    data class Multiply(val by: T): Modification() {
        override fun invoke(on: T): T = on * by
        @Suppress("UNCHECKED_CAST")
        override fun invokeDefault(): T = when(by) {
            is Byte -> 0.toByte() as T
            is Short -> 0.toShort() as T
            is Int -> 0 as T
            is Long -> 0L as T
            is Float -> 0f as T
            is Double -> 0.0 as T
            else -> fatalError()
        }
    }

    @Serializable(ModificationAppendStringSerializer::class)
    data class AppendString(val value: String): Modification() {
        override fun invoke(on: String): String = on + value
        override fun invokeDefault(): String = value
    }

    @Serializable(ModificationListAppendSerializer::class)
    data class ListAppend(val items: List): Modification>() {
        override fun invoke(on: List): List = on + items
        override fun invokeDefault(): List = items
    }

    @Serializable(ModificationListRemoveSerializer::class)
    data class ListRemove(val condition: Condition): Modification>() {
        override fun invoke(on: List): List = on.filter { !condition(it) }
        override fun invokeDefault(): List = listOf()
    }

    @Serializable(ModificationListRemoveInstancesSerializer::class)
    data class ListRemoveInstances(val items: List): Modification>() {
        override fun invoke(on: List): List = on - items
        override fun invokeDefault(): List = listOf()
    }

    @Serializable(ModificationListDropFirstSerializer::class)
    class ListDropFirst: Modification>() {
        override fun invoke(on: List): List = on.drop(1)
        override fun invokeDefault(): List = listOf()
        override fun hashCode(): Int = 1
        @Suppress("UNCHECKED_CAST")
        override fun equals(other: Any?): Boolean = (other as? Modification.ListDropFirst) != null
    }

    @Serializable(ModificationListDropLastSerializer::class)
    class ListDropLast: Modification>() {
        override fun invoke(on: List): List = on.dropLast(1)
        override fun invokeDefault(): List = listOf()
        override fun hashCode(): Int = 1
        @Suppress("UNCHECKED_CAST")
        override fun equals(other: Any?): Boolean = (other as? Modification.ListDropLast) != null
    }

    @Serializable()
    @SerialName("ListPerElement")
    data class ListPerElement(val condition: Condition, val modification: Modification): Modification>() {
        override fun invoke(on: List): List = on.map { if(condition(it)) modification(it) else it }
        override fun invokeDefault(): List = listOf()
    }

    @Serializable(ModificationSetAppendSerializer::class)
    data class SetAppend(val items: Set): Modification>() {
        override fun invoke(on: Set): Set = (on + items)
        override fun invokeDefault(): Set = items
    }

    @Serializable(ModificationSetRemoveSerializer::class)
    data class SetRemove(val condition: Condition): Modification>() {
        override fun invoke(on: Set): Set = on.filter { !condition(it) }.toSet()
        override fun invokeDefault(): Set = setOf()
    }

    @Serializable(ModificationSetRemoveInstancesSerializer::class)
    data class SetRemoveInstances(val items: Set): Modification>() {
        override fun invoke(on: Set): Set = on - items
        override fun invokeDefault(): Set = setOf()
    }

    @Serializable(ModificationSetDropFirstSerializer::class)
    class SetDropFirst: Modification>() {
        override fun invoke(on: Set): Set = on.drop(1).toSet()
        override fun invokeDefault(): Set = setOf()
        override fun hashCode(): Int = 1
        @Suppress("UNCHECKED_CAST")
        override fun equals(other: Any?): Boolean = (other as? Modification.SetDropFirst) != null
    }

    @Serializable(ModificationSetDropLastSerializer::class)
    class SetDropLast: Modification>() {
        override fun invoke(on: Set): Set = on.toList().dropLast(1).toSet()
        override fun invokeDefault(): Set = setOf()
        override fun hashCode(): Int = 1
        @Suppress("UNCHECKED_CAST")
        override fun equals(other: Any?): Boolean = (other as? Modification.SetDropLast) != null
    }

    @Serializable()
    @SerialName("SetPerElement")
    data class SetPerElement(val condition: Condition, val modification: Modification): Modification>() {
        override fun invoke(on: Set): Set = on.map { if(condition(it)) modification(it) else it }.toSet()
        override fun invokeDefault(): Set = setOf()
    }

    @Serializable(ModificationCombineSerializer::class)
    data class Combine(val map: Map): Modification>() {
        override fun invoke(on: Map): Map = on + map
        override fun invokeDefault(): Map = map
    }

    @Serializable(ModificationModifyByKeySerializer::class)
    data class ModifyByKey(val map: Map>): Modification>() {
        override fun invoke(on: Map): Map = on + map.mapValues { (on[it.key]?.let { e -> it.value(e) } ?: it.value.invokeDefault()) }
        override fun invokeDefault(): Map = map.mapValues { it.value.invokeDefault() }
    }

    @Serializable(ModificationRemoveKeysSerializer::class)
    data class RemoveKeys(val fields: Set): Modification>() {
        override fun invoke(on: Map): Map = on.filterKeys { it !in fields }
        override fun invokeDefault(): Map = mapOf()
    }

    data class OnField(val key: KProperty1, val modification: Modification): Modification() {
        override fun invoke(on: K): K = key.setCopy(on, modification(key.get(on)))
        override fun invokeDefault(): K {
            fatalError("Cannot mutate a field that doesn't exist")
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy