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

commonMain.dk.cachet.carp.common.infrastructure.serialization.UnknownDeviceSerializers.kt Maven / Gradle / Ivy

package dk.cachet.carp.common.infrastructure.serialization

import dk.cachet.carp.common.application.Trilean
import dk.cachet.carp.common.application.data.DataType
import dk.cachet.carp.common.application.devices.AnyDeviceDescriptor
import dk.cachet.carp.common.application.devices.AnyMasterDeviceDescriptor
import dk.cachet.carp.common.application.devices.DeviceDescriptor
import dk.cachet.carp.common.application.devices.DeviceRegistration
import dk.cachet.carp.common.application.devices.DeviceRegistrationBuilder
import dk.cachet.carp.common.application.devices.MasterDeviceDescriptor
import dk.cachet.carp.common.application.sampling.SamplingConfiguration
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlin.reflect.KClass


/**
 * A wrapper used to load extending types from [DeviceDescriptor] serialized as JSON which are unknown at runtime.
 */
@Serializable( DeviceDescriptorSerializer::class )
data class CustomDeviceDescriptor(
    override val className: String,
    override val jsonSource: String,
    val serializer: Json
) : DeviceDescriptor>(), UnknownPolymorphicWrapper
{
    override val roleName: String
    override val defaultSamplingConfiguration: Map

    // This information is not serialized. Therefore, the supported types are unknown.
    override fun getSupportedDataTypes(): Set = emptySet()

    init
    {
        val json = Json( serializer ) { ignoreUnknownKeys = true }
        val baseMembers = json.decodeFromString( BaseMembers.serializer(), jsonSource )
        roleName = baseMembers.roleName
        defaultSamplingConfiguration = baseMembers.defaultSamplingConfiguration
    }

    override fun createDeviceRegistrationBuilder(): DeviceRegistrationBuilder =
        throw UnsupportedOperationException( "The concrete type of this device is not known. Therefore, it is unknown which registration builder is required." )

    override fun getRegistrationClass(): KClass = DeviceRegistration::class

    /**
     * For unknown types, it cannot be determined whether or not a given registration is valid.
     */
    override fun isValidRegistration( registration: DeviceRegistration ) = Trilean.UNKNOWN
}


/**
 * A wrapper used to load extending types from [MasterDeviceDescriptor] serialized as JSON which are unknown at runtime.
 */
@Serializable( MasterDeviceDescriptorSerializer::class )
data class CustomMasterDeviceDescriptor(
    override val className: String,
    override val jsonSource: String,
    val serializer: Json
) : MasterDeviceDescriptor>(), UnknownPolymorphicWrapper
{
    override val roleName: String
    override val defaultSamplingConfiguration: Map

    // This information is not serialized. Therefore, the supported types are unknown.
    override fun getSupportedDataTypes(): Set = emptySet()

    init
    {
        val json = Json( serializer ) { ignoreUnknownKeys = true }
        val baseMembers = json.decodeFromString( BaseMembers.serializer(), jsonSource )
        roleName = baseMembers.roleName
        defaultSamplingConfiguration = baseMembers.defaultSamplingConfiguration
    }

    override fun createDeviceRegistrationBuilder(): DeviceRegistrationBuilder =
        throw UnsupportedOperationException( "The concrete type of this device is not known. Therefore, it is unknown which registration builder is required." )

    override fun getRegistrationClass(): KClass = DeviceRegistration::class

    /**
     * For unknown types, it cannot be determined whether or not a given registration is valid.
     */
    override fun isValidRegistration( registration: DeviceRegistration ) = Trilean.UNKNOWN
}


@Serializable
private data class BaseMembers(
    override val roleName: String,
    override val defaultSamplingConfiguration: Map
) : DeviceDescriptor>()
{
    override fun getSupportedDataTypes(): Set =
        throw UnsupportedOperationException()
    override fun createDeviceRegistrationBuilder(): DeviceRegistrationBuilder =
        throw UnsupportedOperationException()
    override fun getRegistrationClass(): KClass =
        throw UnsupportedOperationException()
    override fun isValidRegistration( registration: DeviceRegistration ): Trilean =
        throw UnsupportedOperationException()
}


/**
 * Custom serializer for [DeviceDescriptor] which enables deserializing types that are unknown at runtime, yet extend from [DeviceDescriptor].
 */
object DeviceDescriptorSerializer : UnknownPolymorphicSerializer( DeviceDescriptor::class, DeviceDescriptor::class, false )
{
    override fun createWrapper( className: String, json: String, serializer: Json ): AnyDeviceDescriptor
    {
        val jsonObject = serializer.parseToJsonElement( json ) as JsonObject
        val isMasterDevice = jsonObject.containsKey( AnyMasterDeviceDescriptor::isMasterDevice.name )

        return if ( isMasterDevice )
        {
            CustomMasterDeviceDescriptor( className, json, serializer )
        }
        else
        {
            CustomDeviceDescriptor( className, json, serializer )
        }
    }
}

/**
 * Custom serializer for [MasterDeviceDescriptor] which enables deserializing types that are unknown at runtime, yet extend from [MasterDeviceDescriptor].
 */
object MasterDeviceDescriptorSerializer : KSerializer
    by createUnknownPolymorphicSerializer( { className, json, serializer -> CustomMasterDeviceDescriptor( className, json, serializer ) } )


/**
 * A wrapper used to load extending types from [DeviceRegistration] serialized as JSON which are unknown at runtime.
 */
@Serializable( DeviceRegistrationSerializer::class )
data class CustomDeviceRegistration(
    override val className: String,
    override val jsonSource: String,
    val serializer: Json
) : DeviceRegistration(), UnknownPolymorphicWrapper
{
    @Serializable
    private data class BaseMembers( override val deviceId: String ) : DeviceRegistration()

    override val deviceId: String

    init
    {
        val json = Json( serializer ) { ignoreUnknownKeys = true }
        val baseMembers = json.decodeFromString( BaseMembers.serializer(), jsonSource )
        deviceId = baseMembers.deviceId
    }
}

/**
 * Custom serializer for a [DeviceRegistration] which enables deserializing types that are unknown at runtime, yet extend from [DeviceRegistration].
 */
object DeviceRegistrationSerializer : KSerializer
    by createUnknownPolymorphicSerializer( { className, json, serializer -> CustomDeviceRegistration( className, json, serializer ) } )




© 2015 - 2025 Weber Informatics LLC | Privacy Policy