diff --git a/README.md b/README.md index d0183d6c..e763bc67 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ This section documents the available CLI parameters for controlling what gets ge | | `RESILIENCE4J` - Generates a fault tolerance service for the client using the following library "io.github.resilience4j:resilience4j-all:+" | `--http-model-opts` | Select the options for the http models that you want to be generated. | | CHOOSE ANY OF: + | | `X_EXTENSIBLE_ENUMS` - This option treats x-extensible-enums as enums | | `JAVA_SERIALIZATION` - This option adds Java Serializable interface to the generated models | | `QUARKUS_REFLECTION` - This option adds @RegisterForReflection to the generated models. Requires dependency "'io.quarkus:quarkus-core:+" | `--output-directory` | Allows the generation dir to be overridden. Defaults to current dir diff --git a/src/main/kotlin/com/cjbooms/fabrikt/cli/CodeGen.kt b/src/main/kotlin/com/cjbooms/fabrikt/cli/CodeGen.kt index 00b23bc7..d178cfb3 100644 --- a/src/main/kotlin/com/cjbooms/fabrikt/cli/CodeGen.kt +++ b/src/main/kotlin/com/cjbooms/fabrikt/cli/CodeGen.kt @@ -2,6 +2,7 @@ package com.cjbooms.fabrikt.cli import com.beust.jcommander.ParameterException import com.cjbooms.fabrikt.configurations.Packages +import com.cjbooms.fabrikt.generators.MutableSettings import com.cjbooms.fabrikt.model.SourceApi import java.nio.file.Files import java.nio.file.Path @@ -46,7 +47,7 @@ object CodeGen { val packages = Packages(basePackage) val sourceApi = SourceApi.create(suppliedApi, apiFragments, baseDir) val generator = CodeGenerator(packages, sourceApi, codeGenTypes, modelOptions, clientOptions) - + MutableSettings.updateSettings(codeGenTypes, modelOptions, clientOptions) generator.generate().forEach { it.writeFileTo(outputDir.toFile()) } } } diff --git a/src/main/kotlin/com/cjbooms/fabrikt/cli/CodeGenOptions.kt b/src/main/kotlin/com/cjbooms/fabrikt/cli/CodeGenOptions.kt index dc927c8a..366f4d94 100644 --- a/src/main/kotlin/com/cjbooms/fabrikt/cli/CodeGenOptions.kt +++ b/src/main/kotlin/com/cjbooms/fabrikt/cli/CodeGenOptions.kt @@ -46,6 +46,7 @@ enum class ClientCodeGenOptionType(private val description: String) { } enum class ModelCodeGenOptionType(val description: String) { + X_EXTENSIBLE_ENUMS("This option treats x-extensible-enums as enums"), JAVA_SERIALIZATION("This option adds Java Serializable interface to the generated models"), QUARKUS_REFLECTION("This option adds @RegisterForReflection to the generated models. Requires dependency \"'io.quarkus:quarkus-core:+\""); diff --git a/src/main/kotlin/com/cjbooms/fabrikt/generators/MutableSettings.kt b/src/main/kotlin/com/cjbooms/fabrikt/generators/MutableSettings.kt new file mode 100644 index 00000000..87640019 --- /dev/null +++ b/src/main/kotlin/com/cjbooms/fabrikt/generators/MutableSettings.kt @@ -0,0 +1,20 @@ +package com.cjbooms.fabrikt.generators + +import com.cjbooms.fabrikt.cli.ClientCodeGenOptionType +import com.cjbooms.fabrikt.cli.CodeGenerationType +import com.cjbooms.fabrikt.cli.ModelCodeGenOptionType + +object MutableSettings { + var generationTypes: MutableSet = mutableSetOf() + var modelOptions: MutableSet = mutableSetOf() + var clientOptions: MutableSet = mutableSetOf() + fun updateSettings( + genTypes: Set, + modelOptions: Set, + clientOptions: Set + ) { + this.generationTypes = genTypes.toMutableSet() + this.modelOptions = modelOptions.toMutableSet() + this.clientOptions = clientOptions.toMutableSet() + } +} diff --git a/src/main/kotlin/com/cjbooms/fabrikt/util/KaizenParserExtensions.kt b/src/main/kotlin/com/cjbooms/fabrikt/util/KaizenParserExtensions.kt index 59d23594..bdc3c5e5 100644 --- a/src/main/kotlin/com/cjbooms/fabrikt/util/KaizenParserExtensions.kt +++ b/src/main/kotlin/com/cjbooms/fabrikt/util/KaizenParserExtensions.kt @@ -1,5 +1,7 @@ package com.cjbooms.fabrikt.util +import com.cjbooms.fabrikt.cli.ModelCodeGenOptionType +import com.cjbooms.fabrikt.generators.MutableSettings import com.cjbooms.fabrikt.model.OasType import com.cjbooms.fabrikt.model.PropertyInfo import com.cjbooms.fabrikt.util.NormalisedString.toMapValueClassName @@ -54,12 +56,16 @@ object KaizenParserExtensions { fun Schema.isInlineableMapDefinition() = hasAdditionalProperties() && properties?.isEmpty() == true fun Schema.isEnumDefinition(): Boolean = - this.type == OasType.Text.type && (this.hasEnums() || extensions.containsKey(EXTENSIBLE_ENUM_KEY)) + this.type == OasType.Text.type && (this.hasEnums() || + (MutableSettings.modelOptions.contains(ModelCodeGenOptionType.X_EXTENSIBLE_ENUMS) && + extensions.containsKey(EXTENSIBLE_ENUM_KEY))) @Suppress("UNCHECKED_CAST") - fun Schema.getEnumValues(): List = - if (this.hasEnums()) this.enums.map { it.toString() } - else extensions[EXTENSIBLE_ENUM_KEY]?.let { it as List } ?: emptyList() + fun Schema.getEnumValues(): List = when { + this.hasEnums() -> this.enums.map { it.toString() } + !MutableSettings.modelOptions.contains(ModelCodeGenOptionType.X_EXTENSIBLE_ENUMS) -> emptyList() + else -> extensions[EXTENSIBLE_ENUM_KEY]?.let { it as List } ?: emptyList() + } fun Schema.hasAdditionalProperties(): Boolean = isObjectType() && Overlay.of(additionalPropertiesSchema).isPresent diff --git a/src/test/kotlin/com/cjbooms/fabrikt/generators/ModelGeneratorTest.kt b/src/test/kotlin/com/cjbooms/fabrikt/generators/ModelGeneratorTest.kt index edace888..5270c91f 100644 --- a/src/test/kotlin/com/cjbooms/fabrikt/generators/ModelGeneratorTest.kt +++ b/src/test/kotlin/com/cjbooms/fabrikt/generators/ModelGeneratorTest.kt @@ -19,7 +19,7 @@ import org.junit.jupiter.params.provider.MethodSource class ModelGeneratorTest { private fun testCases(): Stream = Stream.of( -/* "arrays", + "arrays", "anyOfOneOfAllOf", "deepNestedSharingReferences", "defaultValues", @@ -30,19 +30,20 @@ class ModelGeneratorTest { "githubApi", "inLinedObject", "mapExamples", - "mixingCamelSnakeLispCase",*/ - "oneOfPolymorphicModels" -/* "optionalVsRequired", + "mixingCamelSnakeLispCase", + "oneOfPolymorphicModels", + "optionalVsRequired", "polymorphicModels", "requiredReadOnly", "validationAnnotations", - "wildCardTypes"*/ + "wildCardTypes" ) @ParameterizedTest @MethodSource("testCases") fun `correct models are generated for different OpenApi Specifications`(testCaseName: String) { print("Testcase: $testCaseName") + MutableSettings.modelOptions.add(ModelCodeGenOptionType.X_EXTENSIBLE_ENUMS) val basePackage = "examples.$testCaseName" val apiLocation = javaClass.getResource("/examples/$testCaseName/api.yaml") val sourceApi = SourceApi(apiLocation.readText(), baseDir = Paths.get(apiLocation.toURI())) diff --git a/src/test/resources/examples/enumPolymorphicDiscriminator/api.yaml b/src/test/resources/examples/enumPolymorphicDiscriminator/api.yaml index 02dd5ebb..9cefc42d 100644 --- a/src/test/resources/examples/enumPolymorphicDiscriminator/api.yaml +++ b/src/test/resources/examples/enumPolymorphicDiscriminator/api.yaml @@ -34,7 +34,7 @@ components: EnumDiscriminator: type: string - x-extensible-enum: + enum: - obj_one - obj_two diff --git a/src/test/resources/examples/githubApi/api.yaml b/src/test/resources/examples/githubApi/api.yaml index 82775d07..630ef0db 100644 --- a/src/test/resources/examples/githubApi/api.yaml +++ b/src/test/resources/examples/githubApi/api.yaml @@ -751,7 +751,7 @@ components: in: query schema: type: string - x-extensible-enum: + enum: - active - inactive - all @@ -1022,7 +1022,7 @@ components: readOnly: true status: type: string - x-extensible-enum: + enum: - active - inactive description: States whether the entity is currently active or inactive @@ -1092,7 +1092,7 @@ components: readOnly: true status: type: string - x-extensible-enum: + enum: - active - inactive description: States whether the entity is currently active or inactive @@ -1167,7 +1167,7 @@ components: readOnly: true status: type: string - x-extensible-enum: + enum: - active - inactive description: States whether the entity is currently active or inactive @@ -1182,7 +1182,7 @@ components: type: string visibility: type: string - x-extensible-enum: + enum: - Private - Public tags: @@ -1246,7 +1246,7 @@ components: readOnly: true status: type: string - x-extensible-enum: + enum: - active - inactive description: States whether the entity is currently active or inactive diff --git a/src/test/resources/examples/javaSerializableModels/api.yaml b/src/test/resources/examples/javaSerializableModels/api.yaml index 2fa8b07a..5e2f3799 100644 --- a/src/test/resources/examples/javaSerializableModels/api.yaml +++ b/src/test/resources/examples/javaSerializableModels/api.yaml @@ -219,7 +219,7 @@ components: readOnly: true third_attr: type: "string" - x-extensible-enum: + enum: - "enum_type_1" - "enum_type_2" description: "Enum types for attribute 3" @@ -231,7 +231,7 @@ components: model_type: type: "string" description: "The model discrimination type" - x-extensible-enum: + enum: - "first_model" - "second_model" - "third_model" diff --git a/src/test/resources/examples/okHttpClient/api.yaml b/src/test/resources/examples/okHttpClient/api.yaml index 2fa8b07a..5e2f3799 100644 --- a/src/test/resources/examples/okHttpClient/api.yaml +++ b/src/test/resources/examples/okHttpClient/api.yaml @@ -219,7 +219,7 @@ components: readOnly: true third_attr: type: "string" - x-extensible-enum: + enum: - "enum_type_1" - "enum_type_2" description: "Enum types for attribute 3" @@ -231,7 +231,7 @@ components: model_type: type: "string" description: "The model discrimination type" - x-extensible-enum: + enum: - "first_model" - "second_model" - "third_model" diff --git a/src/test/resources/examples/quarkusReflectionModels/api.yaml b/src/test/resources/examples/quarkusReflectionModels/api.yaml index 2fa8b07a..f732be40 100644 --- a/src/test/resources/examples/quarkusReflectionModels/api.yaml +++ b/src/test/resources/examples/quarkusReflectionModels/api.yaml @@ -1,184 +1,7 @@ openapi: "3.0.0" info: - title: "API Example" - version: "1.0" paths: - /example-path-1: - get: - summary: "GET example path 1" - parameters: - - $ref: "#/components/parameters/QueryParam1" - - $ref: "#/components/parameters/QueryParam2" - responses: - 200: - description: "successful operation" - headers: - Cache-Control: - $ref: "#/components/headers/CacheControl" - content: - application/json: - schema: - $ref: "#/components/schemas/QueryResult" - - post: - summary: "POST example path 1" - parameters: - - $ref: "#/components/parameters/QueryParam1" - requestBody: - $ref: "#/components/requestBodies/PostBody" - responses: - 201: - headers: - Location: - $ref: "#/components/headers/Location" - description: "Successful operation" - - /example-path-2/{path_param}: - get: - summary: "GET example path 2" - parameters: - - $ref: "#/components/parameters/PathParam" - - $ref: "#/components/parameters/QueryParam2" - - $ref: "#/components/parameters/IfNoneMatch" - responses: - 200: - description: "successful operation" - headers: - Cache-Control: - $ref: "#/components/headers/CacheControl" - content: - application/json: - schema: - discriminator: - propertyName: "model_type" - oneOf: - - $ref: "#/components/schemas/FirstModel" - - $ref: "#/components/schemas/SecondModel" - - $ref: "#/components/schemas/ThirdModel" - 304: - description: "Returned in conjunction with use of the If-None-Match header.\ - \ Indicates that the resource as described by the passed etag value has\ - \ not changed" - head: - summary: "HEAD example path 2" - parameters: - - $ref: "#/components/parameters/PathParam" - - $ref: "#/components/parameters/QueryParam3" - - $ref: "#/components/parameters/IfNoneMatch" - responses: - 200: - description: "Record Exists" - 304: - description: "Returned in conjunction with use of the If-None-Match header.\ - \ Indicates that the resource as described by the passed etag value has\ - \ not changed" - - put: - summary: "PUT example path 2" - parameters: - - $ref: "#/components/parameters/PathParam" - - $ref: "#/components/parameters/IfMatch" - requestBody: - $ref: "#/components/requestBodies/PutBody" - responses: - 204: - description: "Operation successful" - - /example-path-3/{path_param}/subresource: - put: - summary: "PUT example path 3" - parameters: - - $ref: "#/components/parameters/QueryParam1" - - $ref: "#/components/parameters/PathParam" - - $ref: "#/components/parameters/IfMatch" - requestBody: - $ref: "#/components/requestBodies/PutBody" - responses: - 204: - description: "Operation successful" - components: - parameters: - PathParam: - name: "path_param" - description: "The resource id" - in: "path" - required: true - schema: - type: "string" - - IfMatch: - name: "If-Match" - description: "The RFC7232 If-Match header field" - in: "header" - schema: - type: "string" - required: true - - IfNoneMatch: - name: "If-None-Match" - description: "The RFC7232 If-None-Match header field" - in: "header" - schema: - type: "string" - required: false - - QueryParam1: - name: "query_param1" - in: "query" - schema: - type: "array" - items: - type: "string" - required: false - allowEmptyValue: false - - QueryParam2: - name: "query_param2" - in: "query" - schema: - type: integer - required: false - - QueryParam3: - name: "query_param3" - in: "query" - schema: - type: boolean - required: false - - headers: - Location: - description: "The Location header indicates the URL of a newly created resource" - schema: - type: "string" - - CacheControl: - description: "The RFC7234 Cache Control header" - schema: - type: "string" - example: "must-revalidate, max-age=5" - - requestBodies: - PostBody: - required: true - content: - application/json: - schema: - discriminator: - propertyName: "model_type" - oneOf: - - $ref: "#/components/schemas/FirstModel" - - $ref: "#/components/schemas/SecondModel" - - $ref: "#/components/schemas/ThirdModel" - PutBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/FirstModel" - - schemas: QueryResult: type: "object" @@ -219,7 +42,7 @@ components: readOnly: true third_attr: type: "string" - x-extensible-enum: + enum: - "enum_type_1" - "enum_type_2" description: "Enum types for attribute 3" @@ -231,7 +54,7 @@ components: model_type: type: "string" description: "The model discrimination type" - x-extensible-enum: + enum: - "first_model" - "second_model" - "third_model"