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

com.ancientlightstudios.quarkus.kotlin.openapi.emitter.serialization.SerializationStatementEmitter.kt Maven / Gradle / Ivy

There is a newer version: 0.4.14
Show newest version
package com.ancientlightstudios.quarkus.kotlin.openapi.emitter.serialization

import com.ancientlightstudios.quarkus.kotlin.openapi.emitter.CodeEmitter
import com.ancientlightstudios.quarkus.kotlin.openapi.emitter.EmitterContext
import com.ancientlightstudios.quarkus.kotlin.openapi.emitter.isNullable
import com.ancientlightstudios.quarkus.kotlin.openapi.models.kotlin.InvocationExpression.Companion.invoke
import com.ancientlightstudios.quarkus.kotlin.openapi.models.kotlin.KotlinExpression
import com.ancientlightstudios.quarkus.kotlin.openapi.models.kotlin.MethodName.Companion.rawMethodName
import com.ancientlightstudios.quarkus.kotlin.openapi.models.kotlin.NullCheckExpression.Companion.nullCheck
import com.ancientlightstudios.quarkus.kotlin.openapi.models.kotlin.VariableName.Companion.variableName
import com.ancientlightstudios.quarkus.kotlin.openapi.models.transformable.ContentType
import com.ancientlightstudios.quarkus.kotlin.openapi.models.types.*
import com.ancientlightstudios.quarkus.kotlin.openapi.utils.ProbableBug

class SerializationStatementEmitter(
    private val typeUsage: TypeUsage,
    baseStatement: KotlinExpression,
    private val contentType: ContentType,
    private val forceSkipNullCheck: Boolean = false
) : CodeEmitter {

    var resultStatement = baseStatement

    // if the type is null, or forced to be null, adds a null check to the statement
    //
    // e.g. if the base statement is just the variable name 'foo' it will produce 'foo?'
    override fun EmitterContext.emit() {
        // TODO: the check for content type is necessary right now, because there is no other transformation and would produce just a single ?
        // should be changed if we know how other content types work and how we can change the serialization and deserialization code
        if (!forceSkipNullCheck && typeUsage.isNullable() && contentType != ContentType.ApplicationOctetStream) {
            resultStatement = resultStatement.nullCheck()
        }

        resultStatement = when (val safeType = typeUsage.type) {
            is PrimitiveTypeDefinition -> emitForPrimitiveType(resultStatement)
            is EnumTypeDefinition -> emitForEnumType(resultStatement)
            is CollectionTypeDefinition -> emitForCollectionType(safeType, resultStatement)
            is ObjectTypeDefinition -> emitForObjectType(resultStatement)
            is OneOfTypeDefinition -> emitForOneOfType(resultStatement)
        }
    }

    // if it's a primitive type, generates an expression like this
    //
    // for plain/text
    //
    // .asString()
    //
    // for application/json
    //
    // .asJson()
    private fun emitForPrimitiveType(baseStatement: KotlinExpression): KotlinExpression {
        return when (contentType) {
            ContentType.TextPlain -> baseStatement.invoke("asString".rawMethodName())
            ContentType.ApplicationJson -> baseStatement.invoke("asJson".rawMethodName())
            ContentType.ApplicationOctetStream -> baseStatement
            else -> ProbableBug("Unsupported content type $contentType for primitive serialization")
        }
    }

    // if it's an enum type, generates an expression like this
    //
    // for plain/text
    //
    // .asString()
    //
    // for application/json
    //
    // .asJson()
    private fun emitForEnumType(baseStatement: KotlinExpression): KotlinExpression {
        return when (contentType) {
            ContentType.TextPlain -> baseStatement.invoke("asString".rawMethodName())
            ContentType.ApplicationJson -> baseStatement.invoke("asJson".rawMethodName())
            else -> ProbableBug("Unsupported content type $contentType for enum serialization")
        }
    }

    private fun EmitterContext.emitForCollectionType(
        typeDefinition: CollectionTypeDefinition, baseStatement: KotlinExpression
    ): KotlinExpression {
        val methodName = when (contentType) {
            ContentType.ApplicationJson -> "asJson".rawMethodName()
            ContentType.TextPlain -> "map".rawMethodName()
            else -> ProbableBug("Unsupported content type $contentType for collection serialization")
        }

        // produces:
        //
        // . {
        //     
        // }
        return baseStatement.invoke(methodName) {
            runEmitter(SerializationStatementEmitter(typeDefinition.items, "it".variableName(), contentType))
                .resultStatement.statement()
        }
    }

    // if it's an object type, generates an expression like this
    //
    // .asJson()
    private fun emitForObjectType(baseStatement: KotlinExpression): KotlinExpression {
        return when (contentType) {
            ContentType.ApplicationJson -> baseStatement.invoke("asJson".rawMethodName())
            else -> ProbableBug("Unsupported content type $contentType for object serialization")
        }
    }

    // if it's an oneOf type, generates an expression like this
    //
    // .asJson()
    private fun emitForOneOfType(baseStatement: KotlinExpression): KotlinExpression {
        return when (contentType) {
            ContentType.ApplicationJson -> baseStatement.invoke("asJson".rawMethodName())
            else -> ProbableBug("Unsupported content type $contentType for object serialization")
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy