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

io.justdevit.kotlin.boost.domain.model.Identifier.kt Maven / Gradle / Ivy

package io.justdevit.kotlin.boost.domain.model

import io.justdevit.kotlin.boost.serialization.UUID
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.Contextual
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.descriptors.SerialKind
import kotlinx.serialization.descriptors.buildSerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder

interface Identifier {
    val value: T
}

@Serializable
abstract class CompositeIdentifier : Identifier {

    @Contextual
    var internal: InternalIdentifier = UndefinedInternalIdentifier()
}

@Serializable
sealed interface InternalIdentifier {
    val value: T?
}

@Serializable
@SerialName("UNDEFINED")
class UndefinedInternalIdentifier : InternalIdentifier {
    @Transient
    override val value: T? = null
}

@Serializable
@SerialName("UUID")
data class UuidInternalIdentifier(override val value: UUID) : InternalIdentifier

fun UUID?.toInternalIdentifier() =
    when (this) {
        null -> UndefinedInternalIdentifier()
        else -> UuidInternalIdentifier(this)
    }

@Serializable
@SerialName("STRING")
data class StringInternalIdentifier(override val value: String) : InternalIdentifier

fun String?.toInternalIdentifier() =
    when (this) {
        null -> UndefinedInternalIdentifier()
        else -> StringInternalIdentifier(this)
    }

@Serializable
@SerialName("LONG")
data class LongInternalIdentifier(override val value: Long) : InternalIdentifier

fun Long?.toInternalIdentifier() =
    when (this) {
        null -> UndefinedInternalIdentifier()
        else -> LongInternalIdentifier(this)
    }

@Serializable
@SerialName("INT")
data class IntInternalIdentifier(override val value: Int) : InternalIdentifier

fun Int?.toInternalIdentifier() =
    when (this) {
        null -> UndefinedInternalIdentifier()
        else -> IntInternalIdentifier(this)
    }

@Serializable(LazyInternalIdentifierSerializer::class)
internal class LazyInternalIdentifier : InternalIdentifier {

    @Transient
    var supplier: (() -> @Contextual Any?)? = null

    @Transient
    override val value: @Contextual Any?
        get() = supplier!!()
}

@Suppress("UNCHECKED_CAST")
fun  lazyInternalIdentifier(supplier: () -> T?) =
    LazyInternalIdentifier().apply {
        this.supplier = supplier
    } as InternalIdentifier

fun  coLazyInternalIdentifier(supplier: suspend () -> T?) =
    lazyInternalIdentifier {
        runBlocking { supplier() }
    }

internal object LazyInternalIdentifierSerializer : KSerializer {

    @OptIn(InternalSerializationApi::class, ExperimentalSerializationApi::class)
    override val descriptor: SerialDescriptor = buildSerialDescriptor("io.justdevit.kotlin.boost.domain.LazyInternalIdentifierSerializer", SerialKind.CONTEXTUAL)

    override fun deserialize(decoder: Decoder) = throw UnsupportedOperationException("Deserialization of ${LazyInternalIdentifier::class.simpleName} is not supported.")

    override fun serialize(encoder: Encoder, value: LazyInternalIdentifier) {
        when (value.value) {
            is UUID -> encoder.encodeSerializableValue(UuidInternalIdentifier.serializer(), UuidInternalIdentifier(value.value as UUID))

            is String -> encoder.encodeSerializableValue(StringInternalIdentifier.serializer(), StringInternalIdentifier(value.value as String))

            is Long -> encoder.encodeSerializableValue(LongInternalIdentifier.serializer(), LongInternalIdentifier(value.value as Long))

            is Int -> encoder.encodeSerializableValue(IntInternalIdentifier.serializer(), IntInternalIdentifier(value.value as Int))

            else -> encoder.encodeSerializableValue(
                UndefinedInternalIdentifier.serializer(Unit.serializer()),
                UndefinedInternalIdentifier(),
            )
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy