Support default values from OpenAPI spec in generated models

This commit is contained in:
Niels van Velzen 2022-08-06 22:12:02 +02:00 committed by Max Rumpf
parent 3003a3a592
commit 0b69e2aaf5
5 changed files with 63 additions and 28 deletions

View File

@ -5,19 +5,18 @@ import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.KModifier
import com.squareup.kotlinpoet.MemberName import com.squareup.kotlinpoet.MemberName
import com.squareup.kotlinpoet.ParameterSpec import com.squareup.kotlinpoet.ParameterSpec
import com.squareup.kotlinpoet.ParameterizedTypeName
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.plusParameter import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.plusParameter
import com.squareup.kotlinpoet.buildCodeBlock import com.squareup.kotlinpoet.buildCodeBlock
import org.jellyfin.openapi.builder.Builder import org.jellyfin.openapi.builder.Builder
import org.jellyfin.openapi.builder.extra.DeprecatedAnnotationSpecBuilder import org.jellyfin.openapi.builder.extra.DeprecatedAnnotationSpecBuilder
import org.jellyfin.openapi.builder.extra.DescriptionBuilder import org.jellyfin.openapi.builder.extra.DescriptionBuilder
import org.jellyfin.openapi.builder.extra.defaultValue
import org.jellyfin.openapi.constants.Classes import org.jellyfin.openapi.constants.Classes
import org.jellyfin.openapi.constants.Packages import org.jellyfin.openapi.constants.Packages
import org.jellyfin.openapi.constants.Strings import org.jellyfin.openapi.constants.Strings
import org.jellyfin.openapi.constants.Types import org.jellyfin.openapi.constants.Types
import org.jellyfin.openapi.model.ApiServiceOperation import org.jellyfin.openapi.model.ApiServiceOperation
import org.jellyfin.openapi.model.ApiServiceOperationParameter import org.jellyfin.openapi.model.ApiServiceOperationParameter
import org.jellyfin.openapi.model.CustomDefaultValue
import org.jellyfin.openapi.model.IntRangeValidation import org.jellyfin.openapi.model.IntRangeValidation
import org.jellyfin.openapi.model.ParameterValidation import org.jellyfin.openapi.model.ParameterValidation
@ -44,30 +43,7 @@ open class OperationBuilder(
protected fun buildParameter( protected fun buildParameter(
data: ApiServiceOperationParameter, data: ApiServiceOperationParameter,
) = ParameterSpec.builder(data.name, data.type).apply { ) = ParameterSpec.builder(data.name, data.type).apply {
// Determine class name without parameters defaultValue(data)
val typeClassName = when (data.type) {
is ClassName -> data.type
is ParameterizedTypeName -> data.type.rawType
else -> null
}
// Set default value
when (data.defaultValue) {
is String -> defaultValue("%S", data.defaultValue)
is Int -> defaultValue("%L", data.defaultValue)
is Boolean -> defaultValue("%L", data.defaultValue)
is CustomDefaultValue -> defaultValue(data.defaultValue.build())
// Set value to null by default for nullable values
null -> when {
typeClassName == Types.COLLECTION ->
defaultValue("%M()", MemberName("kotlin.collections", "emptyList"))
typeClassName == Types.LIST ->
defaultValue("%M()", MemberName("kotlin.collections", "emptyList"))
typeClassName == Types.MAP ->
defaultValue("%M()", MemberName("kotlin.collections", "emptyMap"))
data.type.isNullable -> defaultValue("%L", "null")
}
}
// Add description // Add description
descriptionBuilder.build(data.description)?.let { descriptionBuilder.build(data.description)?.let {

View File

@ -0,0 +1,57 @@
package org.jellyfin.openapi.builder.extra
import com.squareup.kotlinpoet.ClassName
import com.squareup.kotlinpoet.MemberName
import com.squareup.kotlinpoet.ParameterSpec
import com.squareup.kotlinpoet.ParameterizedTypeName
import com.squareup.kotlinpoet.TypeName
import org.jellyfin.openapi.constants.Types
import org.jellyfin.openapi.model.ApiServiceOperationParameter
import org.jellyfin.openapi.model.CustomDefaultValue
import org.jellyfin.openapi.model.ObjectApiModelProperty
fun ParameterSpec.Builder.defaultValue(
type: TypeName,
defaultValue: Any?,
allowEmptyCollection: Boolean,
) {
// Determine class name without parameters
val typeClassName = when (type) {
is ClassName -> type
is ParameterizedTypeName -> type.rawType
else -> null
}
// Set default value
when (defaultValue) {
is String -> defaultValue("%S", defaultValue)
is Int -> defaultValue("%L", defaultValue)
is Boolean -> defaultValue("%L", defaultValue)
is CustomDefaultValue -> defaultValue(defaultValue.build())
// Set value to null by default for nullable values
null -> when {
typeClassName == Types.COLLECTION && allowEmptyCollection ->
defaultValue("%M()", MemberName("kotlin.collections", "emptyList"))
typeClassName == Types.LIST && allowEmptyCollection ->
defaultValue("%M()", MemberName("kotlin.collections", "emptyList"))
typeClassName == Types.MAP && allowEmptyCollection ->
defaultValue("%M()", MemberName("kotlin.collections", "emptyMap"))
type.isNullable -> defaultValue("%L", "null")
}
}
}
fun ParameterSpec.Builder.defaultValue(parameter: ApiServiceOperationParameter) = defaultValue(
type = parameter.type,
defaultValue = parameter.defaultValue,
allowEmptyCollection = true,
)
fun ParameterSpec.Builder.defaultValue(property: ObjectApiModelProperty) = defaultValue(
type = property.type,
defaultValue = property.defaultValue,
allowEmptyCollection = false,
)

View File

@ -13,6 +13,7 @@ import org.jellyfin.openapi.builder.Builder
import org.jellyfin.openapi.builder.extra.DeprecatedAnnotationSpecBuilder import org.jellyfin.openapi.builder.extra.DeprecatedAnnotationSpecBuilder
import org.jellyfin.openapi.builder.extra.DescriptionBuilder import org.jellyfin.openapi.builder.extra.DescriptionBuilder
import org.jellyfin.openapi.builder.extra.TypeSerializerBuilder import org.jellyfin.openapi.builder.extra.TypeSerializerBuilder
import org.jellyfin.openapi.builder.extra.defaultValue
import org.jellyfin.openapi.constants.Packages import org.jellyfin.openapi.constants.Packages
import org.jellyfin.openapi.constants.Strings import org.jellyfin.openapi.constants.Strings
import org.jellyfin.openapi.constants.Types import org.jellyfin.openapi.constants.Types
@ -32,8 +33,7 @@ class ObjectModelBuilder(
data.properties.forEach { property -> data.properties.forEach { property ->
// Create constructor parameter // Create constructor parameter
addParameter(ParameterSpec.builder(property.name, property.type).apply { addParameter(ParameterSpec.builder(property.name, property.type).apply {
// Set value to null by default for nullable values defaultValue(property)
if (property.type.isNullable) defaultValue("%L", "null")
}.build()) }.build())
// Create class property // Create class property

View File

@ -36,6 +36,7 @@ class OpenApiModelBuilder(
ObjectApiModelProperty( ObjectApiModelProperty(
name = name, name = name,
originalName = originalName, originalName = originalName,
defaultValue = property.default,
type = openApiTypeBuilder.build(ModelTypePath(data.name, name), property), type = openApiTypeBuilder.build(ModelTypePath(data.name, name), property),
description = property.description, description = property.description,
deprecated = property.deprecated == true deprecated = property.deprecated == true

View File

@ -5,6 +5,7 @@ import com.squareup.kotlinpoet.TypeName
data class ObjectApiModelProperty( data class ObjectApiModelProperty(
val name: String, val name: String,
val originalName: String, val originalName: String,
val defaultValue: Any?,
val type: TypeName, val type: TypeName,
val description: String?, val description: String?,
val deprecated: Boolean val deprecated: Boolean