```package de.nergie.vk.graphql import com.expedi...
# graphql-kotlin
s
Copy code
package de.nergie.vk.graphql

import com.expediagroup.graphql.generator.hooks.SchemaGeneratorHooks
import graphql.language.StringValue
import graphql.scalars.ExtendedScalars
import graphql.schema.Coercing
import graphql.schema.GraphQLScalarType
import graphql.schema.GraphQLType
import org.springframework.stereotype.Component
import java.math.BigDecimal
import java.time.Period
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.util.*
import kotlin.reflect.KType

@Component
class CustomSchemaGeneratorHooks() : SchemaGeneratorHooks {

    /**
     * Register additional GraphQL scalar types.
     */
    override fun willGenerateGraphQLType(type: KType): GraphQLType? = when (type.classifier) {
        ZonedDateTime::class -> graphqlZonedDateTimeType
        Period::class -> graphqlPeriodType
        UUID::class -> graphqlUUIDType
        BigDecimal::class -> ExtendedScalars.GraphQLBigDecimal
        else -> super.willGenerateGraphQLType(type)
    }
}

val graphqlZonedDateTimeType = GraphQLScalarType.newScalar()
    .name("ZonedDateTime")
    .description("A type representing a formatted java.time.ZonedDateTime")
    .coercing(ZonedDateTimeCoercing)
    .build()

object ZonedDateTimeCoercing : Coercing<ZonedDateTime, String> {

    private val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[.SSS]XXX")

    override fun parseValue(input: Any): ZonedDateTime {
        return ZonedDateTime.parse(serialize(input), formatter)
    }

    override fun parseLiteral(input: Any): ZonedDateTime {
        val string = (input as? StringValue)?.value
        return ZonedDateTime.parse(string, formatter)
    }

    override fun serialize(dataFetcherResult: Any): String {
        return when (dataFetcherResult) {
            is String -> dataFetcherResult
            is ZonedDateTime -> dataFetcherResult.format(formatter)
            else -> "Invalid Date: $dataFetcherResult"
        }
    }
}

val graphqlPeriodType = GraphQLScalarType.newScalar()
    .name("Period")
    .description("A type representing a formatted java.time.Period")
    .coercing(PeriodCoercing)
    .build()

object PeriodCoercing : Coercing<Period, String> {

    override fun parseValue(input: Any): Period {
        return Period.parse(serialize(input))
    }

    override fun parseLiteral(input: Any): Period {
        val string = (input as? StringValue)?.value
        return Period.parse(string)
    }

    override fun serialize(dataFetcherResult: Any): String {
        return when (dataFetcherResult) {
            is String -> dataFetcherResult
            is Period -> dataFetcherResult.toString()
            else -> "Invalid Period: ${dataFetcherResult.javaClass}"
        }
    }
}

val graphqlUUIDType = GraphQLScalarType.newScalar()
    .name("UUID")
    .description("A type representing a formatted java.util.UUID")
    .coercing(UUIDCoercing)
    .build()

object UUIDCoercing : Coercing<UUID, String> {
    override fun parseValue(input: Any): UUID = UUID.fromString(serialize(input))

    override fun parseLiteral(input: Any): UUID {
        val uuidString = (input as? StringValue)?.value
        return UUID.fromString(uuidString)
    }

    override fun serialize(dataFetcherResult: Any): String = dataFetcherResult.toString()
}