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

org.jetbrains.kotlinx.dataframe.io.DefaultReadOpenApiMethod.kt Maven / Gradle / Ivy

package org.jetbrains.kotlinx.dataframe.io

import com.squareup.kotlinpoet.ClassName
import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.LambdaTypeName
import com.squareup.kotlinpoet.ParameterSpec
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
import com.squareup.kotlinpoet.PropertySpec
import com.squareup.kotlinpoet.STAR
import com.squareup.kotlinpoet.TypeSpec
import com.squareup.kotlinpoet.UNIT
import com.squareup.kotlinpoet.asClassName
import com.squareup.kotlinpoet.asTypeName
import org.jetbrains.kotlinx.dataframe.DataFrame
import org.jetbrains.kotlinx.dataframe.api.ConvertSchemaDsl
import org.jetbrains.kotlinx.dataframe.api.DataSchemaEnum
import org.jetbrains.kotlinx.dataframe.api.JsonPath
import org.jetbrains.kotlinx.dataframe.codeGen.AbstractDefaultReadMethod
import org.jetbrains.kotlinx.dataframe.codeGen.Marker
import java.io.InputStream
import java.net.URL
import kotlin.reflect.typeOf

private const val VALUE_COLUMN_NAME: String = "value"

/**
 * Used to add `readJson` and `convertToMyMarker` functions to the generated interfaces.
 * Makes sure [convertDataRowsWithOpenApi] is always used in conversions.
 */
internal object DefaultReadOpenApiMethod : AbstractDefaultReadMethod(
    path = null,
    arguments = MethodArguments.EMPTY,
    methodName = "",
) {

    override val additionalImports: List = listOf(
        "import org.jetbrains.kotlinx.dataframe.io.readJson",
        "import org.jetbrains.kotlinx.dataframe.io.readJsonStr",
        "import org.jetbrains.kotlinx.dataframe.api.convertTo",
        "import org.jetbrains.kotlinx.dataframe.api.first",
        "import org.jetbrains.kotlinx.dataframe.api.${JsonPath::class.simpleName}",
        "import org.jetbrains.kotlinx.dataframe.api.${DataSchemaEnum::class.simpleName}",
        "import org.jetbrains.kotlinx.dataframe.io.JSON.TypeClashTactic.*",
        "import org.jetbrains.kotlinx.dataframe.io.${ConvertSchemaDsl<*>::convertDataRowsWithOpenApi.name}",
    )

    override fun toDeclaration(marker: Marker, visibility: String): String {
        val returnType = DataFrame::class.asClassName().parameterizedBy(ClassName("", listOf(marker.shortName)))

        // convertTo: ConvertSchemaDsl.() -> Unit = {}
        val convertToParameter = ParameterSpec.builder(
            name = "convertTo",
            type = LambdaTypeName.get(
                receiver = ConvertSchemaDsl::class
                    .asClassName()
                    .parameterizedBy(ClassName("", listOf(marker.shortName))),
                parameters = emptyList(),
                returnType = UNIT,
            ),
        ).defaultValue("{}")
            .build()

        fun getConvertMethod(): String =
            """
            return convertTo<${marker.shortName}> { 
                ${ConvertSchemaDsl<*>::convertDataRowsWithOpenApi.name}() 
                convertTo()
            }
            """.trimIndent()

        fun getReadAndConvertMethod(readMethod: String): String =
            """
            return ${DataFrame::class.asClassName()}
                .$readMethod${if (marker is OpenApiMarker.AdditionalPropertyInterface) "[\"$VALUE_COLUMN_NAME\"].first().let { it as DataFrame<*> }" else ""}
                .convertTo${marker.shortName}()
            """.trimIndent()

        val typeSpec = TypeSpec.companionObjectBuilder()
            .addFunction(
                FunSpec.builder("convertTo${marker.shortName}")
                    .receiver(DataFrame::class.asClassName().parameterizedBy(STAR))
                    .addParameter(convertToParameter)
                    .addCode(getConvertMethod())
                    .returns(returnType)
                    .build(),
            )
            .addProperty(
                PropertySpec.Companion.builder(name = "keyValuePaths", type = typeOf>().asTypeName())
                    .getter(
                        FunSpec.getterBuilder()
                            .addCode(
                                run {
                                    val additionalPropertyPaths = (marker as OpenApiMarker)
                                        .additionalPropertyPaths
                                        .distinct()

                                    "return listOf(${
                                        additionalPropertyPaths.joinToString {
                                            "JsonPath(\"\"\"${it.path}\"\"\")"
                                        }
                                    })"
                                },
                            ).build(),
                    ).build(),
            )
            .addFunction(
                FunSpec.builder("readJson")
                    .returns(returnType)
                    .addParameter("url", URL::class)
                    .addCode(
                        getReadAndConvertMethod(
                            "readJson(url, typeClashTactic = ANY_COLUMNS, keyValuePaths = keyValuePaths)",
                        ),
                    ).build(),
            )
            .addFunction(
                FunSpec.builder("readJson")
                    .returns(returnType)
                    .addParameter("path", String::class)
                    .addCode(
                        getReadAndConvertMethod(
                            "readJson(path, typeClashTactic = ANY_COLUMNS, keyValuePaths = keyValuePaths)",
                        ),
                    ).build(),
            )
            .addFunction(
                FunSpec.builder("readJson")
                    .returns(returnType)
                    .addParameter("stream", InputStream::class)
                    .addCode(
                        getReadAndConvertMethod(
                            "readJson(stream, typeClashTactic = ANY_COLUMNS, keyValuePaths = keyValuePaths)",
                        ),
                    ).build(),
            )
            .addFunction(
                FunSpec.builder("readJsonStr")
                    .returns(returnType)
                    .addParameter("text", String::class)
                    .addCode(
                        getReadAndConvertMethod(
                            "readJsonStr(text, typeClashTactic = ANY_COLUMNS, keyValuePaths = keyValuePaths)",
                        ),
                    ).build(),
            ).build()

        return typeSpec.toString()
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy