From fb1773662b189aeb9bc6d17d9c79e21655b83afb Mon Sep 17 00:00:00 2001 From: Conor Gallagher Date: Wed, 23 Jun 2021 11:00:49 +0100 Subject: [PATCH] Add support for the UUID format of strings (#57) * Add support for the UUID format of strings * Add parameter name for readability --- .../cjbooms/fabrikt/model/KotlinTypeInfo.kt | 3 +++ .../com/cjbooms/fabrikt/model/OasType.kt | 4 ++++ .../fabrikt/util/KaizenParserExtensions.kt | 3 +++ .../resources/examples/githubApi/api.yaml | 1 + .../githubApi/controllers/Controllers.kt | 19 ++++++++++--------- .../examples/optionalVsRequired/api.yaml | 3 ++- .../optionalVsRequired/models/Models.kt | 3 ++- 7 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/main/kotlin/com/cjbooms/fabrikt/model/KotlinTypeInfo.kt b/src/main/kotlin/com/cjbooms/fabrikt/model/KotlinTypeInfo.kt index e2417055..850a3f0a 100644 --- a/src/main/kotlin/com/cjbooms/fabrikt/model/KotlinTypeInfo.kt +++ b/src/main/kotlin/com/cjbooms/fabrikt/model/KotlinTypeInfo.kt @@ -10,6 +10,7 @@ import com.reprezen.kaizen.oasparser.model3.Schema import java.math.BigDecimal import java.time.LocalDate import java.time.OffsetDateTime +import java.util.UUID import kotlin.reflect.KClass sealed class KotlinTypeInfo(val modelKClass: KClass<*>, val generatedModelClassName: String? = null) { @@ -22,6 +23,7 @@ sealed class KotlinTypeInfo(val modelKClass: KClass<*>, val generatedModelClassN object Numeric : KotlinTypeInfo(BigDecimal::class) object Integer : KotlinTypeInfo(Int::class) object BigInt : KotlinTypeInfo(Long::class) + object Uuid : KotlinTypeInfo(UUID::class) object Boolean : KotlinTypeInfo(kotlin.Boolean::class) object UntypedObject : KotlinTypeInfo(Any::class) data class Object(val simpleClassName: String) : KotlinTypeInfo(GeneratedType::class, simpleClassName) @@ -47,6 +49,7 @@ sealed class KotlinTypeInfo(val modelKClass: KClass<*>, val generatedModelClassN OasType.Text -> Text OasType.Enum -> Enum(schema.getEnumValues(), schema.toModelClassName(enclosingName.toModelClassName())) + OasType.Uuid -> Uuid OasType.Double -> Double OasType.Float -> Float OasType.Number -> Numeric diff --git a/src/main/kotlin/com/cjbooms/fabrikt/model/OasType.kt b/src/main/kotlin/com/cjbooms/fabrikt/model/OasType.kt index f313425c..ead95460 100644 --- a/src/main/kotlin/com/cjbooms/fabrikt/model/OasType.kt +++ b/src/main/kotlin/com/cjbooms/fabrikt/model/OasType.kt @@ -6,6 +6,7 @@ import com.cjbooms.fabrikt.util.KaizenParserExtensions.isSchemaLess import com.cjbooms.fabrikt.util.KaizenParserExtensions.isTypedAdditionalProperties import com.cjbooms.fabrikt.util.KaizenParserExtensions.isUnknownAdditionalProperties import com.cjbooms.fabrikt.util.KaizenParserExtensions.isUntypedAdditionalProperties +import com.cjbooms.fabrikt.util.KaizenParserExtensions.isUuidDefinition import com.cjbooms.fabrikt.util.KaizenParserExtensions.safeType import com.reprezen.kaizen.oasparser.model3.Schema import kotlin.reflect.KClass @@ -30,6 +31,7 @@ sealed class OasType( object Array : OasType("array") object UntypedObject : OasType("object", specialization = Specialization.UNTYPED_OBJECT) object Enum : OasType("string", specialization = Specialization.ENUM) + object Uuid : OasType("string", specialization = Specialization.UUID) object Map : OasType("object", specialization = Specialization.MAP) object UnknownProperties : OasType("object", specialization = Specialization.UNKNOWN_ADDITIONAL_PROPERTIES) object UntypedProperties : OasType("object", specialization = Specialization.UNTYPED_OBJECT_ADDITIONAL_PROPERTIES) @@ -51,6 +53,7 @@ sealed class OasType( private fun Schema.getSpecialization(oasKey: String): Specialization = when { + isUuidDefinition() -> Specialization.UUID isEnumDefinition() -> Specialization.ENUM isInlineableMapDefinition() -> Specialization.MAP isTypedAdditionalProperties(oasKey) -> Specialization.TYPED_OBJECT_ADDITIONAL_PROPERTIES @@ -68,6 +71,7 @@ sealed class OasType( TYPED_OBJECT_ADDITIONAL_PROPERTIES, UNTYPED_OBJECT_ADDITIONAL_PROPERTIES, UNTYPED_OBJECT, + UUID, NONE } } diff --git a/src/main/kotlin/com/cjbooms/fabrikt/util/KaizenParserExtensions.kt b/src/main/kotlin/com/cjbooms/fabrikt/util/KaizenParserExtensions.kt index bf7af924..23eafcf5 100644 --- a/src/main/kotlin/com/cjbooms/fabrikt/util/KaizenParserExtensions.kt +++ b/src/main/kotlin/com/cjbooms/fabrikt/util/KaizenParserExtensions.kt @@ -66,6 +66,9 @@ object KaizenParserExtensions { ) ) + fun Schema.isUuidDefinition(): Boolean = + this.type == OasType.Text.type && (this.format?.equals("uuid", ignoreCase = true) == true) + @Suppress("UNCHECKED_CAST") fun Schema.getEnumValues(): List = when { this.hasEnums() -> this.enums.map { it.toString() } diff --git a/src/test/resources/examples/githubApi/api.yaml b/src/test/resources/examples/githubApi/api.yaml index 630ef0db..b490ad6b 100644 --- a/src/test/resources/examples/githubApi/api.yaml +++ b/src/test/resources/examples/githubApi/api.yaml @@ -716,6 +716,7 @@ components: required: false schema: type: string + format: uuid example: 84035561-4e44-4a06-98d2-1744eeefca6d FlowId: name: X-Flow-Id diff --git a/src/test/resources/examples/githubApi/controllers/Controllers.kt b/src/test/resources/examples/githubApi/controllers/Controllers.kt index 33eb27d3..8aad7e99 100644 --- a/src/test/resources/examples/githubApi/controllers/Controllers.kt +++ b/src/test/resources/examples/githubApi/controllers/Controllers.kt @@ -20,6 +20,7 @@ import org.springframework.web.bind.annotation.RequestHeader import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RequestMethod import org.springframework.web.bind.annotation.RequestParam +import java.util.UUID import javax.validation.Valid import javax.validation.constraints.Max import javax.validation.constraints.Min @@ -105,7 +106,7 @@ interface ContributorsController { @RequestBody @Valid contributor: Contributor, @RequestHeader(value = "X-Flow-Id", required = false) xFlowId: String?, - @RequestHeader(value = "Idempotency-Key", required = false) idempotencyKey: String? + @RequestHeader(value = "Idempotency-Key", required = false) idempotencyKey: UUID? ): ResponseEntity /** @@ -169,7 +170,7 @@ interface ContributorsController { @PathVariable(value = "id", required = true) id: String, @RequestHeader(value = "If-Match", required = true) ifMatch: String, @RequestHeader(value = "X-Flow-Id", required = false) xFlowId: String?, - @RequestHeader(value = "Idempotency-Key", required = false) idempotencyKey: String? + @RequestHeader(value = "Idempotency-Key", required = false) idempotencyKey: UUID? ): ResponseEntity } @@ -230,7 +231,7 @@ interface OrganisationsController { @RequestBody @Valid organisation: Organisation, @RequestHeader(value = "X-Flow-Id", required = false) xFlowId: String?, - @RequestHeader(value = "Idempotency-Key", required = false) idempotencyKey: String? + @RequestHeader(value = "Idempotency-Key", required = false) idempotencyKey: UUID? ): ResponseEntity /** @@ -294,7 +295,7 @@ interface OrganisationsController { @PathVariable(value = "id", required = true) id: String, @RequestHeader(value = "If-Match", required = true) ifMatch: String, @RequestHeader(value = "X-Flow-Id", required = false) xFlowId: String?, - @RequestHeader(value = "Idempotency-Key", required = false) idempotencyKey: String? + @RequestHeader(value = "Idempotency-Key", required = false) idempotencyKey: UUID? ): ResponseEntity } @@ -390,7 +391,7 @@ interface OrganisationsContributorsController { @PathVariable(value = "id", required = true) id: String, @RequestHeader(value = "If-Match", required = true) ifMatch: String, @RequestHeader(value = "X-Flow-Id", required = false) xFlowId: String?, - @RequestHeader(value = "Idempotency-Key", required = false) idempotencyKey: String? + @RequestHeader(value = "Idempotency-Key", required = false) idempotencyKey: UUID? ): ResponseEntity /** @@ -479,7 +480,7 @@ interface RepositoriesController { @RequestBody @Valid repository: Repository, @RequestHeader(value = "X-Flow-Id", required = false) xFlowId: String?, - @RequestHeader(value = "Idempotency-Key", required = false) idempotencyKey: String? + @RequestHeader(value = "Idempotency-Key", required = false) idempotencyKey: UUID? ): ResponseEntity /** @@ -543,7 +544,7 @@ interface RepositoriesController { @PathVariable(value = "id", required = true) id: String, @RequestHeader(value = "If-Match", required = true) ifMatch: String, @RequestHeader(value = "X-Flow-Id", required = false) xFlowId: String?, - @RequestHeader(value = "Idempotency-Key", required = false) idempotencyKey: String? + @RequestHeader(value = "Idempotency-Key", required = false) idempotencyKey: UUID? ): ResponseEntity } @@ -609,7 +610,7 @@ interface RepositoriesPullRequestsController { pullRequest: PullRequest, @PathVariable(value = "parent-id", required = true) parentId: String, @RequestHeader(value = "X-Flow-Id", required = false) xFlowId: String?, - @RequestHeader(value = "Idempotency-Key", required = false) idempotencyKey: String? + @RequestHeader(value = "Idempotency-Key", required = false) idempotencyKey: UUID? ): ResponseEntity /** @@ -672,6 +673,6 @@ interface RepositoriesPullRequestsController { @PathVariable(value = "id", required = true) id: String, @RequestHeader(value = "If-Match", required = true) ifMatch: String, @RequestHeader(value = "X-Flow-Id", required = false) xFlowId: String?, - @RequestHeader(value = "Idempotency-Key", required = false) idempotencyKey: String? + @RequestHeader(value = "Idempotency-Key", required = false) idempotencyKey: UUID? ): ResponseEntity } diff --git a/src/test/resources/examples/optionalVsRequired/api.yaml b/src/test/resources/examples/optionalVsRequired/api.yaml index d27b77ae..884c21d6 100644 --- a/src/test/resources/examples/optionalVsRequired/api.yaml +++ b/src/test/resources/examples/optionalVsRequired/api.yaml @@ -9,4 +9,5 @@ components: name: type: string gender: - type: string \ No newline at end of file + type: string + format: uuid \ No newline at end of file diff --git a/src/test/resources/examples/optionalVsRequired/models/Models.kt b/src/test/resources/examples/optionalVsRequired/models/Models.kt index 863636ee..e046c6c6 100644 --- a/src/test/resources/examples/optionalVsRequired/models/Models.kt +++ b/src/test/resources/examples/optionalVsRequired/models/Models.kt @@ -1,6 +1,7 @@ package examples.optionalVsRequired.models import com.fasterxml.jackson.annotation.JsonProperty +import java.util.UUID import javax.validation.constraints.NotNull import kotlin.String @@ -11,5 +12,5 @@ data class OptionalVsRequired( val name: String, @param:JsonProperty("gender") @get:JsonProperty("gender") - val gender: String? = null + val gender: UUID? = null )