Skip to content

Commit

Permalink
Added feature to set schema mappings when generation clients. (#846)
Browse files Browse the repository at this point in the history
* Added feature to set schema mappings when generation clients.

* Updated Restreactive test with schemamapping

* Updated the YearMonth schema to be correct format.

* Updated the documentation

---------

Co-authored-by: Ricardo Zanini <[email protected]>
  • Loading branch information
denvitaharen and ricardozanini authored Nov 29, 2024
1 parent b4d52c0 commit 0bff422
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public enum ConfigName {
ADDITIONAL_API_TYPE_ANNOTATIONS("additional-api-type-annotations"),
TYPE_MAPPINGS("type-mappings"),
IMPORT_MAPPINGS("import-mappings"),
SCHEMA_MAPPINGS("schema-mappings"),
NORMALIZER("open-api-normalizer"),
RETURN_RESPONSE("return-response"),
ENABLE_SECURITY_GENERATION("enable-security-generation"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ public class CommonItemConfig {
@ConfigItem(name = "import-mappings")
public Map<String, String> importMappings;

/**
* Schema Mapping is an OpenAPI Generator configuration specifying which Java types (the values) should be
* imported when a given schema type (the keys of this map) is used
*/
@ConfigItem(name = "schema-mappings")
public Map<String, String> schemaMappings;

/**
* The specified annotations will be added to the generated model files
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,9 @@ protected void generate(OpenApiGeneratorOptions options) {
getValues(smallRyeConfig, openApiFilePath, CodegenConfig.ConfigName.IMPORT_MAPPINGS, String.class, String.class)
.ifPresent(generator::withImportMappings);

getValues(smallRyeConfig, openApiFilePath, CodegenConfig.ConfigName.SCHEMA_MAPPINGS, String.class, String.class)
.ifPresent(generator::withSchemaMappings);

getValues(smallRyeConfig, openApiFilePath, CodegenConfig.ConfigName.NORMALIZER, String.class, String.class)
.ifPresent(generator::withOpenApiNormalizer);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,11 @@ public OpenApiClientGeneratorWrapper withImportMappings(final Map<String, String
return this;
}

public OpenApiClientGeneratorWrapper withSchemaMappings(final Map<String, String> typeMappings) {
typeMappings.forEach(configurator::addSchemaMapping);
return this;
}

public OpenApiClientGeneratorWrapper withOpenApiNormalizer(final Map<String, String> openApiNormalizer) {
configurator.setOpenapiNormalizer(openApiNormalizer);
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,23 @@ components:
UserId:
type: string
format: uuid
YearMonth:
type: object
properties:
year:
format: int32
type: integer
month:
format: int32
type: integer
prolepticMonth:
format: int64
type: integer
monthValue:
format: int32
type: integer
leapYear:
type: boolean

MultipartRequestBody:
type: object
Expand All @@ -46,5 +63,7 @@ components:
$ref: '#/components/schemas/SomeDateTime'
binaryStringFile:
$ref: '#/components/schemas/BinaryStringFile'
yearMonth:
$ref: '#/components/schemas/YearMonth'


Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
quarkus.openapi-generator.codegen.spec.type_mappings_testing_yml.type-mappings.UUID=String
quarkus.openapi-generator.codegen.spec.type_mappings_testing_yml.type-mappings.File=InputStream
quarkus.openapi-generator.codegen.spec.type_mappings_testing_yml.import-mappings.File=java.io.InputStream
quarkus.openapi-generator.codegen.spec.type_mappings_testing_yml.schema-mappings.YearMonth=java.time.YearMonth
quarkus.openapi-generator.codegen.spec.type_mappings_testing_yml.base-package=org.acme.openapi.typemapping
quarkus.openapi-generator.codegen.spec.type_mappings_testing_yml.additional-api-type-annotations=@org.eclipse.microprofile.rest.client.annotation.RegisterProvider(io.quarkiverse.openapi.generator.it.type.mapping.OffsetDateTimeParamConverterProvider.class)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.time.OffsetDateTime;
import java.time.YearMonth;
import java.time.ZoneOffset;

import jakarta.inject.Inject;
Expand Down Expand Up @@ -41,10 +42,12 @@ class TypeAndImportMappingRestEasyClassicTest {
public void canMapTypesAndImportToDifferentValues() {
final String testUuid = "00112233-4455-6677-8899-aabbccddeeff";
final InputStream testFile = new ByteArrayInputStream("Content of the file".getBytes(StandardCharsets.UTF_8));
final YearMonth testYearMonth = YearMonth.parse("2024-06");

TypeMappingApi.PostTheDataMultipartForm requestBody = new TypeMappingApi.PostTheDataMultipartForm();
requestBody.id = testUuid; // String instead of UUID
requestBody.binaryStringFile = testFile; // InputStream instead of File
requestBody.yearMonth = testYearMonth; // YearMonth instead of String
// dateTime remains OffsetDateTime (as is default)
requestBody.dateTime = OffsetDateTime.of(2000, 2, 13, 4, 5, 6, 0, ZoneOffset.UTC);

Expand All @@ -63,6 +66,10 @@ public void canMapTypesAndImportToDifferentValues() {
.withName("binaryStringFile")
.withHeader("Content-Disposition", containing("filename="))
.withHeader(ContentTypeHeader.KEY, equalTo(MediaType.APPLICATION_OCTET_STREAM))
.withBody(equalTo("Content of the file")).build()));
.withBody(equalTo("Content of the file")).build())
.withRequestBodyPart(new MultipartValuePatternBuilder()
.withName("yearMonth")
.withHeader(ContentTypeHeader.KEY, equalTo(MediaType.APPLICATION_JSON))
.withBody(equalTo("\"2024-06\"")).build()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.time.OffsetDateTime;
import java.time.YearMonth;
import java.time.ZoneOffset;

import jakarta.inject.Inject;
Expand Down Expand Up @@ -37,10 +38,12 @@ public class TypeAndImportMappingRestEasyReactiveTest {
public void canMapTypesAndImportToDifferentValues() {
final String testUuid = "00112233-4455-6677-8899-aabbccddeeff";
final InputStream testFile = new ByteArrayInputStream("Content of the file".getBytes(StandardCharsets.UTF_8));
final YearMonth testYearMonth = YearMonth.parse("2024-06");

TypeMappingApi.PostTheDataMultipartForm requestBody = new TypeMappingApi.PostTheDataMultipartForm();
requestBody.id = testUuid; // String instead of UUID
requestBody.binaryStringFile = testFile; // InputStream instead of File
requestBody.yearMonth = testYearMonth; // YearMonth instead of String
// dateTime remains OffsetDateTime (as is default)
requestBody.dateTime = OffsetDateTime.of(2000, 2, 13, 4, 5, 6, 0, ZoneOffset.UTC);

Expand All @@ -52,6 +55,12 @@ public void canMapTypesAndImportToDifferentValues() {
.withHeader(ContentTypeHeader.KEY, equalTo(MediaType.TEXT_PLAIN + "; charset=UTF-8"))
.withBody(equalTo(testUuid)).build()));

typeMappingServer.verify(postRequestedFor(urlEqualTo("/type-mapping"))
.withRequestBodyPart(new MultipartValuePatternBuilder()
.withName("yearMonth")
.withHeader(ContentTypeHeader.KEY, equalTo(MediaType.APPLICATION_JSON))
.withBody(equalTo("\"2024-06\"")).build()));

typeMappingServer.verify(postRequestedFor(urlEqualTo("/type-mapping"))
.withRequestBodyPart(new MultipartValuePatternBuilder()
.withName("dateTime")
Expand Down
7 changes: 5 additions & 2 deletions docs/modules/ROOT/pages/client.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ See the module `integration-tests/register-provider` for an example of how to us

Use the property key `quarkus.openapi-generator.codegen.validateSpec=false` to disable validating the input specification file before code generation. By default, invalid specifications will result in an error.

== Type and import mappings
== Type, schema and import mappings

It's possible to remap types in the generated files. For example, instead of a `File` you can configure the code generator to use `InputStream` for all file upload parts of multipart request, or you could change all `UUID` types to `String`. You can configure this in your `application.properties` using the following configuration keys:

Expand All @@ -129,6 +129,9 @@ It's possible to remap types in the generated files. For example, instead of a `
|Import Mapping
|`quarkus.openapi-generator.codegen.spec.[filename].import-mappings.[type]`
|`quarkus.openapi-generator.codegen.spec.my_spec_yml.import-mappings.File=java.io.InputStream` will replace the default `import java.io.File` with `import java.io.InputStream`
|Schema Mapping
|`quarkus.openapi-generator.codegen.spec.[filename].schema-mappings.[type]`
|`quarkus.openapi-generator.codegen.spec.my_spec_yml.schema-mappings.YearMonth=java.time.YearMonth` will use `java.time.YearMonth` as type for all schemas of the chosen type in the file.
|===

Note that these configuration properties are maps. For the type-mapping the keys are OAS data types and the values are Java types.
Expand All @@ -141,7 +144,7 @@ quarkus.openapi-generator.codegen.spec.my_spec_yml.type-mappings.DateTime=Instan
quarkus.openapi-generator.codegen.spec.my_spec_yml.import-mappings.Instant=java.time.Instant
----

It's also possible to only use a type mapping with a fully qualified name, for instance `quarkus.openapi-generator.codegen.spec.my_spec_yml.type-mappings.File=java.io.InputStream`. For more information and a list of all types see the OpenAPI generator documentation on https://openapi-generator.tech/docs/usage/#type-mappings-and-import-mappings[Type Mappings and Import Mappings].
It's also possible to only use a type mapping with a fully qualified name, for instance `quarkus.openapi-generator.codegen.spec.my_spec_yml.type-mappings.File=java.io.InputStream`. For more information and a list of all types see the OpenAPI generator documentation on https://openapi-generator.tech/docs/usage/#type-mappings-and-import-mappings[Type Mappings and Import Mappings] and https://openapi-generator.tech/docs/customization#schema-mapping[Schema mapping].

See the module https://github.com/quarkiverse/quarkus-openapi-generator/tree/main/integration-tests/type-mapping[type-mapping] for an example of how to use this feature.

Expand Down

0 comments on commit 0bff422

Please sign in to comment.