Compare commits

..

52 Commits

Author SHA1 Message Date
Tino Fuhrmann
a0225deb9c Updated samples 2023-01-11 14:09:55 +01:00
Tino Fuhrmann
02631143f2 Regenerated samples 2023-01-10 12:58:23 +01:00
Tino Fuhrmann
be67222c69 Added example for calling the API 2023-01-10 11:50:41 +01:00
Tino Fuhrmann
a5774db324 Updated README, refined wording 2023-01-10 11:50:40 +01:00
Tino Fuhrmann
81ede197e1 Added exemplary usage of API to README.md 2023-01-10 11:50:38 +01:00
Tino Fuhrmann
cd5da90f7f Regenerate samples 2023-01-10 11:50:37 +01:00
Tino Fuhrmann
358baae19c Added additional documentation for configuration object 2023-01-10 11:50:36 +01:00
Kalarrs Topham
0b8c08c7a0 Add .ToString() if is Uuid/Guid (#14321) 2023-01-10 09:17:04 +08:00
William Cheng
a010713c42 update cli module dependencies (#14400) 2023-01-09 21:21:55 +08:00
William Cheng
d269a2a09d Add deepObject query string support in Java native client (#14378)
* add deepObject query string support in java native client

* fix array of query parameters

* minor fix

* update samples

* fix test
2023-01-06 17:10:06 +08:00
William Cheng
b22bf0a071 [js] fix boolean in oneOf, add tests (#14380) 2023-01-06 11:26:32 +08:00
William Cheng
c514dc3c1b add java native jakarta samples for test (#14381) 2023-01-05 21:55:53 +08:00
William Cheng
9bbf729d5e Merge branch 'master' of https://github.com/OpenAPITools/openapi-generator 2023-01-05 15:48:56 +08:00
William Cheng
95eaff0a00 update samples 2023-01-05 15:48:45 +08:00
s-jepsen
f848651b84 Fix @Generated annotation import for Java Native client. (#14376)
* Fix @Generated annotation import.

Apply fix to generatedAnnotation.mustache
Add changes to generated clients.

* Add changed files.
2023-01-05 15:42:20 +08:00
Oleh Kurpiak
e1220071f0 [Java][Spring] fix RequestPart/RequestParam handling on multipart request (#14357) 2023-01-05 10:22:32 +08:00
Oleh Kurpiak
ec9c7bdf2c [Java][Spring] fix EnumConverterConfiguration (#14356) 2023-01-05 10:19:17 +08:00
s-jepsen
cce3c963f3 Added check for hasHttpSignatureMethods. (#14339) 2023-01-04 15:26:06 +08:00
David Gamero
babfdff78a [typescript] migrate url-parse to URL WHATGW in https.ts (#14319)
* migrate

* remove extra blank line
2023-01-04 07:35:23 +01:00
Antoine Rey
917892db7d #14141 Add externalDocs to @Operation to the JavaSpring generator (#14177)
* #14141 Add externalDocs to @Operation to the JavaSpring generator

* #14141 Add externalDocs to @Operation to the JavaSpring generator : fix mustache template with #hasExternalDocs

* #14141 Add externalDocs to @Operation to the JavaSpring generator: fix indentation

* #14141 Add externalDocs to @Operation to the JavaSpring generator: fix carriage return

* #14141 Add externalDocs to @Operation to the JavaSpring generator: regenerate the spring-boot-oas3.yaml sample

* #14141 Add externalDocs to @Operation to the JavaSpring generator: generate-samples.sh

* #14141 Add externalDocs to @Operation to the JavaSpring generator: remove hasExternalDocs

* Fix ExternalDocumentation import generation and order

* #14141 Add externalDocs to @Operation to the JavaSpring generator: generate-samples.sh
2023-01-04 10:15:23 +08:00
Dan Michael O. Heggø
3dd313d35c [typescript] Add importFileExtension option to support ECMAScript module resolution (#14371)
* Rename 'extensionForDeno' to 'importFileExtension'

* Add importFileExtension option to typescript generator

* Fix typo, update docs

* Update docstring
2023-01-03 17:45:49 +01:00
Oleh Kurpiak
38fdbe0c2c [Java] fix bigDecimalAsString config option (#14370) 2023-01-03 23:49:08 +08:00
stropho
a6eb96ea34 typescript-axios single request param in factory (#14358) 2023-01-03 08:22:38 +01:00
Beppe Catanese
d0800c46e1 12551 [Go] Skipping marshalling of readonly fields (#14335)
* Skip toSerialize for readOnly fields

* Commit regenerated files
2023-01-02 23:35:54 +08:00
Julien Herr
921199bba7 [kotlin-spring] Move Jackson annotation from field to getter (#10825)
* Move Jackson annotation from field to getter

In some case, Jackson will duplicate entries when the annotation is on field
See https://github.com/FasterXML/jackson-databind/issues/1609

* Update samples
2023-01-02 15:32:57 +00:00
devhl-labs
b8b8c5c208 [csharp-netcore] Added samples for composed schemas (#14348)
* added samples for composed schemas

* continue ignoring standard for now
2023-01-02 23:27:01 +08:00
devhl-labs
466495e919 added new pipeline to build standard (#14349) 2023-01-02 23:25:05 +08:00
William Cheng
421e7c9d3e [Java] Better tests for jakarta option (webclient, resttemplate) (#14363)
* test java jakarta in new workflow jdk 17

* update workflow

* skip jakarta test in jdk11
2023-01-02 20:55:39 +08:00
Paul Parenko
fd2b141c53 when using useJakartaEe=true also set java 17 (#14360)
webclient now uses Sring Boot 3.0.1 with `useJakartaEe`
2023-01-02 20:29:32 +08:00
Ahmed Fwela
da8d984ea4 [dart-dio] Fix non legacy discriminator behavior (#14291)
* override createDiscriminator

* assign discriminator = null to remove duplicates

* added discriminatorValue extension

* added _defaults

* formatting

* samples

* use gitter instead

* remove comment

* updated samples

* revert formatting changes

* update samples

* change file permissions

* remove discriminator check for anyOf

* add comment to createDiscriminator
2023-01-02 18:59:33 +08:00
Nick Ufer
16a7fb8acd [KOTLIN] feat: adds maven-publish to 'kotlin' client generator (#14344)
* [KOTLIN] feat: adds maven-publish to 'kotlin' client generator

* [KOTLIN] chore: regenerate samples
2023-01-02 09:20:41 +00:00
Oleh Kurpiak
dc99a450dd [Java][Spring] fix @Operation content for array response (#14201) 2023-01-02 17:10:48 +08:00
Paul Parenko
456cca1a28 [Java] Fix #14276 Java Templates uses jakarta or javax package if useJakartaEe is enabled (#14343)
* Fix #14276 Java Templates uses jakarta or javax package if useJakartaEe
is true

* generated samples after useJakartaEe changes

* generated docs after useJakartaEe changes
2023-01-02 16:28:44 +08:00
William Cheng
dee0703269 remove empty spaces in blank lines in python nextgen client (#14347) 2023-01-02 00:59:24 +08:00
tom300z
2236cebe02 Bugfixes for python-nextgen (#14334)
* Fix swapped operators

Signed-off-by: Tom Hörberg <tom@hoerberg.de>

* add conversion to support non-string params

Signed-off-by: Tom Hörberg <tom@hoerberg.de>

* Provide better fix for nonstring url param values

Signed-off-by: Tom Hörberg <tom@hoerberg.de>

* Updated python-nextgen sample files

Signed-off-by: Tom Hörberg <tom@hoerberg.de>

Signed-off-by: Tom Hörberg <tom@hoerberg.de>
2023-01-02 00:06:25 +08:00
Oleh Kurpiak
be93d1f839 [Java][Jersey2] revert configurable javax package for javax.net (#14341) 2023-01-01 22:41:14 +08:00
Oleh Kurpiak
7c587ce061 [Java] configurable Javax/Jakarta package (#14310) 2022-12-30 22:33:55 +08:00
William Cheng
b71aecbe9e Add OpenAPI Normalizer (#14172)
* add x-parent support

* add docstring

* add openapi normalizer rule to use ref as parent in allof

* add openapi normalizer with 1 rule

* revise wordings

* fix javadoc warnings

* better test

* fix docstring

* minor update

* minor improvements

* fix typo
2022-12-30 16:03:21 +08:00
William Cheng
3a8265b6ee Update opeanpi-generator dependencies (#14328)
* update openapi-generator dep

* update dep, fix tests with new spec

* update kotlin version

* revert cafferine version

* add back testng version and scope
2022-12-28 17:28:07 +08:00
Hui Yu
04ebe9e1a0 [C][Client] Check cJSON_IsNull when the data type is string (#14332) 2022-12-28 16:32:13 +08:00
Thomas von Rosenberg
88fa9ef3c2 [rust] Fix declaration for arrays with object and array references (#14198)
* [rust] Fix declaration for arrays with object and array references

For arrays with an item defined by reference to an array or an object,
the generated type declaration was `Vec<core::models::Array>` or
`Vec<core::models::Map>` without defining a `Array` or `Map` so that the
code didn't compile.

* [rust] Fix trailing whitespace in petstore definition
2022-12-28 15:08:21 +08:00
0xNF
341a8535c7 [Dart] Fix array of array nullable and non-nullable value generation (#13461)
* [Dart] Added non-invalid defaults for non nullable array of arrays (#13460)

* [Dart] Update samples
2022-12-28 00:01:08 +08:00
renaud-twd
efdc94b113 Fix enum generation for php-symfony generator (#14105)
* fix(symfony): enum generation

* docs(php symfony): update samples and docs
2022-12-27 23:42:41 +08:00
Kristof Neirynck
8a2a059887 [Java] fix LocalTime import for dateLibrary java8 (#14111)
The import mapping for LocalTime still pointed to org.joda.time.*.
This one line made the jodatime dependency required.
2022-12-27 23:41:42 +08:00
Thomas von Rosenberg
63f6569e6f [rust] Fix model constructor for required enum array (#14196)
For a required enum array property the generated model constructor used
the type `RequiredEnums` instead of `Vec<RequiredEnums>`.
2022-12-27 23:25:01 +08:00
Dee Luo
444d411b5e perf: \GuzzleHttp\json_encode is deprecated, use \GuzzleHttp\Utils::jsonEncode instead (#14323) 2022-12-27 16:58:44 +08:00
William Cheng
ad2e1b7e62 add test for debugSupportingFiles (#14331) 2022-12-27 16:53:54 +08:00
John Mitchell
fd0bfae65a Java Feign - DefaultApi20Impl is only needed if OAuth is enabled (#14289)
* DefaultApi20Impl is only needed if OAuth is enabled

* Checking updated generate files
2022-12-27 16:50:08 +08:00
julien Lengrand-Lambert
a99c58011a Add JsonIgnore annotation to avoid debugSupportingFiles creating heap space issues (#14298)
* Updates Codegen operation to ignore debugSupportingFiles

* Removes JsonIgnore annotation and rename method instead

* Remove unused import
2022-12-27 16:39:42 +08:00
William Cheng
c27180849f fix gem bundler version (#14329) 2022-12-27 16:37:58 +08:00
William Cheng
68beec623f update swift samples 2022-12-27 16:00:36 +08:00
jase
cfef750e18 [BUG][Swift] fix decimal encoding referencing not existing extension method "encodeToJSON" (#14307)
* feat: add decimal extension "encodeToJSON"

* feat: add decimal extension "encodeToJSON"
2022-12-25 11:02:07 +00:00
1410 changed files with 70752 additions and 10373 deletions

View File

@@ -91,5 +91,7 @@ jobs:
git config --global core.safecrlf false
git config --global core.autocrlf true
mvn clean package -Dmaven.test.skip=true -Dmaven.javadoc.skip=true
# test with java (jersey2) client generation only as ensure-uptodate script is run in another job instead
# test with java (jersey2) client generation only as ensure-up-to-date script is run in another job instead
./bin/generate-samples.sh ./bin/configs/java-jersey2-8.yaml
# test debugSupportingFiles
./bin/generate-samples.sh ./bin/configs/python.yaml -- --global-property debugSupportingFiles

View File

@@ -0,0 +1,30 @@
name: Samples C# .Net Standard
on:
push:
paths:
- 'samples/client/petstore/csharp-netcore/**netstandard**/'
pull_request:
paths:
- 'samples/client/petstore/csharp-netcore/**netstandard**/'
jobs:
build:
name: Build .Net projects
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
sample:
# clients
- samples/client/petstore/csharp-netcore/OpenAPIClient-generichost-netstandard2.0
steps:
- uses: actions/checkout@v3
- uses: actions/setup-dotnet@v3.0.3
with:
dotnet-version: 2.1.*
- name: Build
working-directory: ${{ matrix.sample }}
run: dotnet build Org.OpenAPITools.sln
- name: Test
working-directory: ${{ matrix.sample }}
run: dotnet test Org.OpenAPITools.sln

View File

@@ -4,11 +4,13 @@ on:
push:
paths:
- 'samples/client/petstore/csharp-netcore/**net6.0**/'
- 'samples/client/petstore/csharp-netcore/OpenAPIClient-generichost-netcore**/'
- 'samples/server/petstore/aspnetcore-6.0/**'
- 'samples/server/petstore/aspnetcore-6.0-pocoModels/**'
pull_request:
paths:
- 'samples/client/petstore/csharp-netcore/**net6.0**/'
- 'samples/client/petstore/csharp-netcore/OpenAPIClient-generichost-netcore**/'
- 'samples/server/petstore/aspnetcore-6.0/**'
- 'samples/server/petstore/aspnetcore-6.0-pocoModels/**'
jobs:
@@ -22,6 +24,9 @@ jobs:
# clients
- samples/client/petstore/csharp-netcore/OpenAPIClient-generichost-net6.0
- samples/client/petstore/csharp-netcore/OpenAPIClient-generichost-net6.0-nrt
- samples/client/petstore/csharp-netcore/OpenAPIClient-generichost-netcore-latest-allOf
- samples/client/petstore/csharp-netcore/OpenAPIClient-generichost-netcore-latest-oneOf
- samples/client/petstore/csharp-netcore/OpenAPIClient-generichost-netcore-latest-anyOf
- samples/server/petstore/aspnetcore-6.0
- samples/server/petstore/aspnetcore-6.0-pocoModels
- samples/server/petstore/aspnetcore-6.0-project4Models

View File

@@ -8,7 +8,7 @@ on:
- samples/client/petstore/java-micronaut-client/**
- samples/openapi3/client/petstore/java/jersey2-java8-special-characters/**
- samples/openapi3/client/petstore/java/jersey2-java8-swagger1/**
- samples/openapi3/client/petstore/java/native/**
- samples/openapi3/client/petstore/java/native**
pull_request:
paths:
- 'samples/client/petstore/java/**'
@@ -16,7 +16,7 @@ on:
- samples/client/petstore/java-micronaut-client/**
- samples/openapi3/client/petstore/java/jersey2-java8-special-characters/**
- samples/openapi3/client/petstore/java/jersey2-java8-swagger1/**
- samples/openapi3/client/petstore/java/native/**
- samples/openapi3/client/petstore/java/native**
jobs:
build:
name: Build Java Client JDK11
@@ -29,6 +29,7 @@ jobs:
- samples/client/petstore/jaxrs-cxf-client
- samples/client/petstore/java/native
- samples/client/petstore/java/native-async
- samples/client/petstore/java/native-jakarta
- samples/client/petstore/java/retrofit2
- samples/client/petstore/java/retrofit2rx2
- samples/client/petstore/java/retrofit2rx3

View File

@@ -0,0 +1,39 @@
name: Samples Java Client JDK17
on:
push:
paths:
- samples/client/petstore/java/resttemplate-jakarta/**
- samples/client/petstore/java/webclient-jakarta/**
pull_request:
paths:
- samples/client/petstore/java/resttemplate-jakarta/**
- samples/client/petstore/java/webclient-jakarta/**
jobs:
build:
name: Build Java Client JDK17
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
sample:
# clients
- samples/client/petstore/java/resttemplate-jakarta
- samples/client/petstore/java/webclient-jakarta
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: 17
- name: Cache maven dependencies
uses: actions/cache@v3
env:
cache-name: maven-repository
with:
path: |
~/.m2
key: ${{ runner.os }}-${{ github.job }}-${{ env.cache-name }}-${{ hashFiles('**/pom.xml') }}
- name: Build
working-directory: ${{ matrix.sample }}
run: mvn clean package

View File

@@ -71,7 +71,7 @@ before_install:
# install rust
- curl https://sh.rustup.rs -sSf | sh -s -- -y -v
# required when sudo: required for the Ruby petstore tests
- gem install bundler
- gem install bundler -v 2.3.26
# set python 3.6.3 as default
- source ~/virtualenv/python3.6/bin/activate
# -- skip bash test to shorten build time

View File

@@ -0,0 +1,12 @@
# for csharp-netcore generichost
generatorName: csharp-netcore
outputDir: samples/client/petstore/csharp-netcore/OpenAPIClient-generichost-netcore-latest-allOf
inputSpec: modules/openapi-generator/src/test/resources/3_0/allOf.yaml
library: generichost
templateDir: modules/openapi-generator/src/main/resources/csharp-netcore
additionalProperties:
packageGuid: '{321C8C3F-0156-40C1-AE42-D59761FB9B6C}'
useCompareNetObjects: true
disallowAdditionalPropertiesIfNotPresent: false
targetFramework: net7.0
nullableReferenceTypes: true

View File

@@ -0,0 +1,12 @@
# for csharp-netcore generichost
generatorName: csharp-netcore
outputDir: samples/client/petstore/csharp-netcore/OpenAPIClient-generichost-netcore-latest-anyOf
inputSpec: modules/openapi-generator/src/test/resources/3_0/anyOf.yaml
library: generichost
templateDir: modules/openapi-generator/src/main/resources/csharp-netcore
additionalProperties:
packageGuid: '{321C8C3F-0156-40C1-AE42-D59761FB9B6C}'
useCompareNetObjects: true
disallowAdditionalPropertiesIfNotPresent: false
targetFramework: net7.0
nullableReferenceTypes: true

View File

@@ -0,0 +1,12 @@
# for csharp-netcore generichost
generatorName: csharp-netcore
outputDir: samples/client/petstore/csharp-netcore/OpenAPIClient-generichost-netcore-latest-oneOf
inputSpec: modules/openapi-generator/src/test/resources/3_0/oneOf.yaml
library: generichost
templateDir: modules/openapi-generator/src/main/resources/csharp-netcore
additionalProperties:
packageGuid: '{321C8C3F-0156-40C1-AE42-D59761FB9B6C}'
useCompareNetObjects: true
disallowAdditionalPropertiesIfNotPresent: false
targetFramework: net7.0
nullableReferenceTypes: true

View File

@@ -0,0 +1,9 @@
generatorName: java
outputDir: samples/client/petstore/java/native-jakarta
library: native
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/Java
additionalProperties:
artifactId: petstore-native-jakarta
hideGenerationTimestamp: "true"
useJakartaEe: "true"

View File

@@ -0,0 +1,10 @@
generatorName: java
outputDir: samples/client/petstore/java/resttemplate-jakarta
library: resttemplate
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/Java
additionalProperties:
artifactId: petstore-resttemplate
hideGenerationTimestamp: "true"
java8: true
useJakartaEe: true

View File

@@ -0,0 +1,9 @@
generatorName: java
outputDir: samples/client/petstore/java/webclient-jakarta
library: webclient
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml
templateDir: modules/openapi-generator/src/main/resources/Java
additionalProperties:
artifactId: petstore-webclient
hideGenerationTimestamp: "true"
useJakartaEe: true

View File

@@ -8,3 +8,4 @@ additionalProperties:
snapshotVersion: "true"
hideGenerationTimestamp: "true"
camelCaseDollarSign: "true"
modelNameSuffix: 'Dto'

View File

@@ -1,8 +0,0 @@
generatorName: typescript-koa-server
outputDir: samples/server/petstore/typescript-koa-server
#outputDir: /Users/williamcheng/Code/typescript/PetStore
inputSpec: modules/openapi-generator/src/test/resources/3_0/typescript-koa-server/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/typescript-koa-server
additionalProperties:
ngVersion: 15.0.3
supportsES6: true

View File

@@ -451,3 +451,16 @@ Another useful option is `inlineSchemaNameDefaults`, which allows you to customi
```
Note: Only arrayItemSuffix, mapItemSuffix are supported at the moment. `SKIP_SCHEMA_REUSE=true` is a special value to skip reusing inline schemas.
## OpenAPI Normalizer
OpenAPI Normalizer (off by default) transforms the input OpenAPI doc/spec (which may not perfectly conform to the specification) to make it workable with OpenAPI Generator. Here is a list of rules supported:
- `REF_AS_PARENT_IN_ALLOF`: when set to `true`, child schemas in `allOf` is considered a parent if it's a `$ref` (instead of inline schema)
Example:
```
java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java -i modules/openapi-generator/src/test/resources/3_0/allOf_extension_parent.yaml -o /tmp/java-okhttp/ --additional-properties hideGenerationTimestamp="true" --openapi-normalizer REF_AS_PARENT_IN_ALLOF=true
```

View File

@@ -63,6 +63,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|sourceFolder|source folder for generated code| |src/main/groovy|
|testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|
## SUPPORTED VENDOR EXTENSIONS

View File

@@ -93,8 +93,9 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|unhandledException|Declare operation methods to throw a generic exception and allow unhandled exceptions (useful for Spring `@ControllerAdvice` directives).| |false|
|useBeanValidation|Use BeanValidation API annotations| |true|
|useFeignClientUrl|Whether to generate Feign client with url parameter.| |true|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|useOptional|Use Optional container for optional parameters| |false|
|useSpringBoot3|Generate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports).| |true|
|useSpringBoot3|Generate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports).| |false|
|useSpringController|Annotate the generated API as a Spring Controller| |false|
|useSwaggerUI|Open the OpenApi specification in swagger-ui. Will also import and configure needed dependencies| |true|
|useTags|use tags for creating interface and controller classnames| |false|

View File

@@ -60,6 +60,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|sourceFolder|source folder for generated code| |src/main/java|
|testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|
## SUPPORTED VENDOR EXTENSIONS

View File

@@ -63,6 +63,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi|
|useAbstractClass|Whether to generate abstract classes for REST API instead of interfaces.| |false|
|useBeanValidation|Use Bean Validation| |false|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|
## SUPPORTED VENDOR EXTENSIONS

View File

@@ -65,6 +65,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|sourceFolder|source folder for generated code| |src/gen/java|
|testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|
## SUPPORTED VENDOR EXTENSIONS

View File

@@ -80,6 +80,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi|
|title|Client service name| |null|
|useBeanValidation|Use BeanValidation API annotations| |true|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|useOptional|Use Optional container for optional parameters| |false|
|visitable|Generate visitor for subtypes with a discriminator| |false|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|

View File

@@ -82,6 +82,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|title|Client service name| |null|
|useAuth|Whether to import authorization and to annotate controller methods accordingly| |true|
|useBeanValidation|Use BeanValidation API annotations| |true|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|useOptional|Use Optional container for optional parameters| |false|
|visitable|Generate visitor for subtypes with a discriminator| |false|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|

View File

@@ -70,6 +70,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi|
|title|a title describing the application| |OpenAPI Server|
|useBeanValidation|Use BeanValidation API annotations| |true|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|useTags|use tags for creating interface and controller classnames| |false|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|

View File

@@ -71,6 +71,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|springBootAdminUri|Spring-Boot URI| |null|
|testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi|
|title|server title name or client service name| |null|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|
|zipkinUri|Zipkin URI| |null|

View File

@@ -73,6 +73,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|title|server title name or client service name| |openapi-java-playframework|
|useBeanValidation|Use BeanValidation API annotations| |true|
|useInterfaces|Makes the controllerImp implements an interface to facilitate automatic completion when updating from version x to y of your spec| |true|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|useSwaggerUI|Add a route to /api which show your documentation in swagger-ui. Will also import needed dependencies| |true|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|
|wrapCalls|Add a wrapper to each controller function to handle things like metrics, response modification, etc..| |true|

View File

@@ -65,6 +65,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|sourceFolder|source folder for generated code| |src/main/java|
|testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|
## SUPPORTED VENDOR EXTENSIONS

View File

@@ -65,6 +65,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|sourceFolder|source folder for generated code| |src/main/java|
|testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|
## SUPPORTED VENDOR EXTENSIONS

View File

@@ -67,6 +67,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|sourceFolder|source folder for generated code| |src/main/java|
|testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|vertxSwaggerRouterVersion|Specify the version of the swagger router library| |null|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|

View File

@@ -83,6 +83,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|useAbstractionForFiles|Use alternative types instead of java.io.File to allow passing bytes without a file on disk. Available on resttemplate, webclient, libraries| |false|
|useBeanValidation|Use BeanValidation API annotations| |false|
|useGzipFeature|Send gzip-encoded requests| |false|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|useOneOfDiscriminatorLookup|Use the discriminator's mapping in oneOf to speed up the model lookup. IMPORTANT: Validation (e.g. one and only one match in oneOf's schemas) will be skipped. Only jersey2, jersey3, native, okhttp-gson support this option.| |false|
|usePlayWS|Use Play! Async HTTP client (Play WS API)| |false|
|useReflectionEqualsHashCode|Use org.apache.commons.lang3.builder for equals and hashCode in the models. WARNING: This will fail under a security manager, unless the appropriate permissions are set up correctly and also there's potential performance impact.| |false|

View File

@@ -76,6 +76,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi|
|title|a title describing the application| |OpenAPI Server|
|useBeanValidation|Use BeanValidation API annotations| |true|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|useSwaggerAnnotations|Whether to generate Swagger annotations.| |true|
|useTags|use tags for creating interface and controller classnames| |false|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|

View File

@@ -68,6 +68,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|useBeanValidation|Use BeanValidation API annotations| |false|
|useGenericResponse|Use generic response| |false|
|useGzipFeatureForTests|Use Gzip Feature for tests| |false|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|useLoggingFeatureForTests|Use Logging Feature for tests| |false|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|

View File

@@ -84,6 +84,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|useGenericResponse|Use generic response| |false|
|useGzipFeature|Use Gzip Feature| |false|
|useGzipFeatureForTests|Use Gzip Feature for tests| |false|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|useLoggingFeature|Use Logging Feature| |false|
|useLoggingFeatureForTests|Use Logging Feature for tests| |false|
|useMultipartFeature|Use Multipart Feature| |false|

View File

@@ -79,6 +79,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|useGenericResponse|Use generic response| |false|
|useGzipFeature|Use Gzip Feature| |false|
|useGzipFeatureForTests|Use Gzip Feature for tests| |false|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|useLoggingFeature|Use Logging Feature| |false|
|useLoggingFeatureForTests|Use Logging Feature for tests| |false|
|useMultipartFeature|Use Multipart Feature| |false|

View File

@@ -71,6 +71,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi|
|title|a title describing the application| |OpenAPI Server|
|useBeanValidation|Use BeanValidation API annotations| |true|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|useTags|use tags for creating interface and controller classnames| |false|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|

View File

@@ -70,6 +70,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi|
|title|a title describing the application| |OpenAPI Server|
|useBeanValidation|Use BeanValidation API annotations| |true|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|useSwaggerFeature|Use dynamic Swagger generator| |false|
|useTags|use tags for creating interface and controller classnames| |false|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|

View File

@@ -70,6 +70,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi|
|title|a title describing the application| |OpenAPI Server|
|useBeanValidation|Use BeanValidation API annotations| |true|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|useTags|use tags for creating interface and controller classnames| |false|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|

View File

@@ -76,6 +76,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi|
|title|a title describing the application| |OpenAPI Server|
|useBeanValidation|Use BeanValidation API annotations| |true|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|useSwaggerAnnotations|Whether to generate Swagger annotations.| |true|
|useTags|use tags for creating interface and controller classnames| |false|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|

View File

@@ -86,8 +86,9 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|unhandledException|Declare operation methods to throw a generic exception and allow unhandled exceptions (useful for Spring `@ControllerAdvice` directives).| |false|
|useBeanValidation|Use BeanValidation API annotations| |true|
|useFeignClientUrl|Whether to generate Feign client with url parameter.| |true|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|useOptional|Use Optional container for optional parameters| |false|
|useSpringBoot3|Generate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports).| |true|
|useSpringBoot3|Generate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports).| |false|
|useSpringController|Annotate the generated API as a Spring Controller| |false|
|useSwaggerUI|Open the OpenApi specification in swagger-ui. Will also import and configure needed dependencies| |true|
|useTags|use tags for creating interface and controller classnames| |false|

View File

@@ -24,6 +24,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|enumUnknownDefaultCase|If the server adds new enum cases, that are unknown by an old spec/client, the client will fail to parse the network response.With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the server sends an enum case that is not known by the client/spec, they can safely fallback to this case.|<dl><dt>**false**</dt><dd>No changes to the enum's are made, this is the default option.</dd><dt>**true**</dt><dd>With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the enum case sent by the server is not known by the client/spec, can safely be decoded to this case.</dd></dl>|false|
|fileContentDataType|Specifies the type to use for the content of a file - i.e. Blob (Browser, Deno) / Buffer (node)| |Buffer|
|framework|Specify the framework which should be used in the client code.|<dl><dt>**fetch-api**</dt><dd>fetch-api</dd><dt>**jquery**</dt><dd>jquery</dd></dl>|fetch-api|
|importFileExtension|File extension to use with relative imports. Set it to '.js' or '.mjs' when using [ESM](https://nodejs.org/api/esm.html). Defaults to '.ts' when 'platform' is set to 'deno'.| |null|
|legacyDiscriminatorBehavior|Set to false for generators with better support for discriminators. (Python, Java, Go, PowerShell, C#have this enabled by default).|<dl><dt>**true**</dt><dd>The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.</dd><dt>**false**</dt><dd>The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.</dd></dl>|true|
|modelPropertyNaming|Naming convention for the property: 'camelCase', 'PascalCase', 'snake_case' and 'original', which keeps the original name| |camelCase|
|npmName|The name under which you want to publish generated npm package. Required to generate a full package| |null|

View File

@@ -125,7 +125,7 @@
<dependency>
<groupId>io.airlift</groupId>
<artifactId>airline</artifactId>
<version>0.8</version>
<version>0.9</version>
</dependency>
<dependency>
<groupId>com.googlecode.lambdaj</groupId>
@@ -135,12 +135,12 @@
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.10</version>
<version>1.2.11</version>
</dependency>
<dependency>
<groupId>org.codehaus.janino</groupId>
<artifactId>janino</artifactId>
<version>3.1.0</version>
<version>3.1.9</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>

View File

@@ -80,6 +80,9 @@ public class ConfigHelp extends OpenApiGeneratorCommand {
@Option(name = {"--inline-schema-name-defaults"}, title = "inline schema name defaults", description = "default values used when naming inline schema name")
private Boolean inlineSchemaNameDefaults;
@Option(name = {"--openapi-normalizer"}, title = "openapi normalizer rules", description = "displays the OpenAPI normalizer rules (none)")
private Boolean openapiNormalizer;
@Option(name = {"--metadata"}, title = "metadata", description = "displays the generator metadata like the help txt for the generator and generator type etc")
private Boolean metadata;
@@ -494,6 +497,18 @@ public class ConfigHelp extends OpenApiGeneratorCommand {
sb.append(newline);
}
if (Boolean.TRUE.equals(openapiNormalizer)) {
sb.append(newline).append("OPENAPI NORMALIZER RULES").append(newline).append(newline);
Map<String, String> map = config.openapiNormalizer()
.entrySet()
.stream()
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> {
throw new IllegalStateException(String.format(Locale.ROOT, "Duplicated options! %s and %s", a, b));
}, TreeMap::new));
writePlainTextFromMap(sb, map, optIndent, optNestedIndent, "OpenAPI normalizer rule", "Set to");
sb.append(newline);
}
if (Boolean.TRUE.equals(instantiationTypes)) {
sb.append(newline).append("INSTANTIATION TYPES").append(newline).append(newline);
Map<String, String> map = config.instantiationTypes()

View File

@@ -180,6 +180,13 @@ public class Generate extends OpenApiGeneratorCommand {
+ " ONLY arrayItemSuffix, mapItemSuffix are supported at the moment. `SKIP_SCHEMA_REUSE=true` is a special value to skip reusing inline schemas.")
private List<String> inlineSchemaNameDefaults = new ArrayList<>();
@Option(
name = {"--openapi-normalizer"},
title = "OpenAPI normalizer rules",
description = "specifies the rules to be enabled in OpenAPI normalizer in the form of RULE_1=true,RULE_2=original."
+ " You can also have multiple occurrences of this option.")
private List<String> openapiNormalizer = new ArrayList<>();
@Option(
name = {"--server-variables"},
title = "server variables",
@@ -447,6 +454,7 @@ public class Generate extends OpenApiGeneratorCommand {
applySchemaMappingsKvpList(schemaMappings, configurator);
applyInlineSchemaNameMappingsKvpList(inlineSchemaNameMappings, configurator);
applyInlineSchemaNameDefaultsKvpList(inlineSchemaNameDefaults, configurator);
applyOpenAPINormalizerKvpList(openapiNormalizer, configurator);
applyTypeMappingsKvpList(typeMappings, configurator);
applyAdditionalPropertiesKvpList(additionalProperties, configurator);
applyLanguageSpecificPrimitivesCsvList(languageSpecificPrimitives, configurator);

View File

@@ -53,6 +53,7 @@ public final class GeneratorSettings implements Serializable {
private final Map<String, String> schemaMappings;
private final Map<String, String> inlineSchemaNameMappings;
private final Map<String, String> inlineSchemaNameDefaults;
private final Map<String, String> openapiNormalizer;
private final Set<String> languageSpecificPrimitives;
private final Map<String, String> reservedWordsMappings;
private final Map<String, String> serverVariables;
@@ -264,6 +265,15 @@ public final class GeneratorSettings implements Serializable {
return inlineSchemaNameDefaults;
}
/**
* Gets OpenAPI normalizer rules
*
* @return a map of rules
*/
public Map<String, String> getOpenAPINormalizer() {
return openapiNormalizer;
}
/**
* Gets language specific primitives. These are in addition to the "base" primitives defined in a generator.
* <p>
@@ -382,6 +392,7 @@ public final class GeneratorSettings implements Serializable {
schemaMappings = Collections.unmodifiableMap(builder.schemaMappings);
inlineSchemaNameMappings = Collections.unmodifiableMap(builder.inlineSchemaNameMappings);
inlineSchemaNameDefaults = Collections.unmodifiableMap(builder.inlineSchemaNameDefaults);
openapiNormalizer = Collections.unmodifiableMap(builder.openapiNormalizer);
languageSpecificPrimitives = Collections.unmodifiableSet(builder.languageSpecificPrimitives);
reservedWordsMappings = Collections.unmodifiableMap(builder.reservedWordsMappings);
serverVariables = Collections.unmodifiableMap(builder.serverVariables);
@@ -455,6 +466,7 @@ public final class GeneratorSettings implements Serializable {
schemaMappings = Collections.unmodifiableMap(new HashMap<>(0));
inlineSchemaNameMappings = Collections.unmodifiableMap(new HashMap<>(0));
inlineSchemaNameDefaults = Collections.unmodifiableMap(new HashMap<>(0));
openapiNormalizer = Collections.unmodifiableMap(new HashMap<>(0));
languageSpecificPrimitives = Collections.unmodifiableSet(new HashSet<>(0));
reservedWordsMappings = Collections.unmodifiableMap(new HashMap<>(0));
serverVariables = Collections.unmodifiableMap(new HashMap<>(0));
@@ -515,6 +527,9 @@ public final class GeneratorSettings implements Serializable {
if (copy.getInlineSchemaNameDefaults() != null) {
builder.inlineSchemaNameDefaults.putAll(copy.getInlineSchemaNameDefaults());
}
if (copy.getOpenAPINormalizer() != null) {
builder.openapiNormalizer.putAll(copy.getOpenAPINormalizer());
}
if (copy.getLanguageSpecificPrimitives() != null) {
builder.languageSpecificPrimitives.addAll(copy.getLanguageSpecificPrimitives());
}
@@ -557,6 +572,7 @@ public final class GeneratorSettings implements Serializable {
private Map<String, String> schemaMappings;
private Map<String, String> inlineSchemaNameMappings;
private Map<String, String> inlineSchemaNameDefaults;
private Map<String, String> openapiNormalizer;
private Set<String> languageSpecificPrimitives;
private Map<String, String> reservedWordsMappings;
private Map<String, String> serverVariables;
@@ -577,6 +593,7 @@ public final class GeneratorSettings implements Serializable {
schemaMappings = new HashMap<>();
inlineSchemaNameMappings = new HashMap<>();
inlineSchemaNameDefaults = new HashMap<>();
openapiNormalizer = new HashMap<>();
languageSpecificPrimitives = new HashSet<>();
reservedWordsMappings = new HashMap<>();
serverVariables = new HashMap<>();
@@ -897,6 +914,32 @@ public final class GeneratorSettings implements Serializable {
return this;
}
/**
* Sets the {@code openapiNormalizer} and returns a reference to this Builder so that the methods can be chained together.
*
* @param openapiNormalizer the {@code openapiNormalizer} to set
* @return a reference to this Builder
*/
public Builder withOpenAPINormalizer(Map<String, String> openapiNormalizer) {
this.openapiNormalizer = openapiNormalizer;
return this;
}
/**
* Sets a single {@code openapiNormalizer} and returns a reference to this Builder so that the methods can be chained together.
*
* @param key A key for the OpenAPI normalizer rule
* @param value The value of the OpenAPI normalizer rule
* @return a reference to this Builder
*/
public Builder withOpenAPINormalizer(String key, String value) {
if (this.openapiNormalizer == null) {
this.openapiNormalizer = new HashMap<>();
}
this.openapiNormalizer.put(key, value);
return this;
}
/**
* Sets the {@code languageSpecificPrimitives} and returns a reference to this Builder so that the methods can be chained together.
*
@@ -1085,6 +1128,7 @@ public final class GeneratorSettings implements Serializable {
Objects.equals(getSchemaMappings(), that.getSchemaMappings()) &&
Objects.equals(getInlineSchemaNameMappings(), that.getInlineSchemaNameMappings()) &&
Objects.equals(getInlineSchemaNameDefaults(), that.getInlineSchemaNameDefaults()) &&
Objects.equals(getOpenAPINormalizer(), that.getOpenAPINormalizer()) &&
Objects.equals(getLanguageSpecificPrimitives(), that.getLanguageSpecificPrimitives()) &&
Objects.equals(getReservedWordsMappings(), that.getReservedWordsMappings()) &&
Objects.equals(getGitHost(), that.getGitHost()) &&
@@ -1116,6 +1160,7 @@ public final class GeneratorSettings implements Serializable {
getSchemaMappings(),
getInlineSchemaNameMappings(),
getInlineSchemaNameDefaults(),
getOpenAPINormalizer(),
getLanguageSpecificPrimitives(),
getReservedWordsMappings(),
getGitHost(),

View File

@@ -118,6 +118,7 @@ class OpenApiGeneratorPlugin : Plugin<Project> {
schemaMappings.set(generate.schemaMappings)
inlineSchemaNameMappings.set(generate.inlineSchemaNameMappings)
inlineSchemaNameDefaults.set(generate.inlineSchemaNameDefaults)
openapiNormalizer.set(generate.openapiNormalizer)
invokerPackage.set(generate.invokerPackage)
groupId.set(generate.groupId)
id.set(generate.id)

View File

@@ -162,6 +162,11 @@ open class OpenApiGeneratorGenerateExtension(project: Project) {
*/
val inlineSchemaNameDefaults = project.objects.mapProperty<String, String>()
/**
* Specifies mappings (rules) in OpenAPI normalizer
*/
val openapiNormalizer = project.objects.mapProperty<String, String>()
/**
* Root package for generated code.
*/

View File

@@ -250,6 +250,13 @@ open class GenerateTask : DefaultTask() {
@Input
val inlineSchemaNameDefaults = project.objects.mapProperty<String, String>()
/**
* Specifies mappings (rules) in OpenAPI normalizer
*/
@Optional
@Input
val openapiNormalizer = project.objects.mapProperty<String, String>()
/**
* Root package for generated code.
*/
@@ -758,6 +765,12 @@ open class GenerateTask : DefaultTask() {
}
}
if (openapiNormalizer.isPresent) {
openapiNormalizer.get().forEach { entry ->
configurator.addOpenAPINormalizer(entry.key, entry.value)
}
}
if (typeMappings.isPresent) {
typeMappings.get().forEach { entry ->
configurator.addTypeMapping(entry.key, entry.value)

View File

@@ -315,6 +315,12 @@ public class CodeGenMojo extends AbstractMojo {
@Parameter(name = "inlineSchemaNameDefaults", property = "openapi.generator.maven.plugin.inlineSchemaNameDefaults")
private List<String> inlineSchemaNameDefaults;
/**
* A set of rules for OpenAPI normalizer
*/
@Parameter(name = "openapiNormalizer", property = "openapi.generator.maven.plugin.openapiNormalizer")
private List<String> openapiNormalizer;
/**
* A map of swagger spec types and the generated code types to use for them
*/
@@ -700,6 +706,12 @@ public class CodeGenMojo extends AbstractMojo {
configurator);
}
// Retained for backwards-compatibility with configOptions -> openapi-normalizer
if (openapiNormalizer == null && configOptions.containsKey("openapi-normalizer")) {
applyOpenAPINormalizerKvp(configOptions.get("openapi-normalizer").toString(),
configurator);
}
// Retained for backwards-compatibility with configOptions -> type-mappings
if (typeMappings == null && configOptions.containsKey("type-mappings")) {
applyTypeMappingsKvp(configOptions.get("type-mappings").toString(), configurator);
@@ -753,6 +765,11 @@ public class CodeGenMojo extends AbstractMojo {
applyInlineSchemaNameDefaultsKvpList(inlineSchemaNameDefaults, configurator);
}
// Apply OpenAPI normalizer rules
if (openapiNormalizer != null && (configOptions == null || !configOptions.containsKey("openapi-normalizer"))) {
applyOpenAPINormalizerKvpList(openapiNormalizer, configurator);
}
// Apply Type Mappings
if (typeMappings != null && (configOptions == null || !configOptions.containsKey("type-mappings"))) {
applyTypeMappingsKvpList(typeMappings, configurator);

View File

@@ -333,7 +333,7 @@
<dependency>
<groupId>com.github.javaparser</groupId>
<artifactId>javaparser-core</artifactId>
<version>3.24.0</version>
<version>3.24.9</version>
<scope>test</scope>
</dependency>
<dependency>
@@ -356,7 +356,7 @@
<dependency>
<groupId>org.commonmark</groupId>
<artifactId>commonmark</artifactId>
<version>0.20.0</version>
<version>0.21.0</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>

View File

@@ -147,6 +147,8 @@ public interface CodegenConfig {
Map<String, String> inlineSchemaNameDefault();
Map<String, String> openapiNormalizer();
Map<String, String> apiTemplateFiles();
Map<String, String> modelTemplateFiles();
@@ -330,4 +332,7 @@ public interface CodegenConfig {
boolean getUseInlineModelResolver();
boolean getAddSuffixToDuplicateOperationNicknames();
boolean getUseOpenAPINormalizer();
}

View File

@@ -207,7 +207,7 @@ public class CodegenOperation {
* returns a map where the key is the request body content type and the value is the current CodegenOperation
* this is needed by templates when a different signature is needed for each request body content type
*/
public Map<String, CodegenOperation> getContentTypeToOperation() {
public Map<String, CodegenOperation> contentTypeToOperation() {
LinkedHashMap<String, CodegenOperation> contentTypeToOperation = new LinkedHashMap<>();
if (bodyParam == null) {
return null;

View File

@@ -167,6 +167,8 @@ public class DefaultCodegen implements CodegenConfig {
protected Map<String, String> inlineSchemaNameMapping = new HashMap<>();
// a map to store the inline schema naming conventions
protected Map<String, String> inlineSchemaNameDefault = new HashMap<>();
// a map to store the rules in OpenAPI Normalizer
protected Map<String, String> openapiNormalizer = new HashMap<>();
protected String modelPackage = "", apiPackage = "", fileSuffix;
protected String modelNamePrefix = "", modelNameSuffix = "";
protected String apiNamePrefix = "", apiNameSuffix = "Api";
@@ -1137,6 +1139,11 @@ public class DefaultCodegen implements CodegenConfig {
return inlineSchemaNameDefault;
}
@Override
public Map<String, String> openapiNormalizer() {
return openapiNormalizer;
}
@Override
public String testPackage() {
return testPackage;
@@ -6455,7 +6462,7 @@ public class DefaultCodegen implements CodegenConfig {
return result;
}
public void writePropertyBack(String propertyKey, boolean value) {
public void writePropertyBack(String propertyKey, Object value) {
additionalProperties.put(propertyKey, value);
}
@@ -7939,6 +7946,9 @@ public class DefaultCodegen implements CodegenConfig {
@Override
public boolean getUseInlineModelResolver() { return true; }
@Override
public boolean getUseOpenAPINormalizer() { return true; }
/*
A function to convert yaml or json ingested strings like property names
And convert special characters like newline, tab, carriage return

View File

@@ -255,6 +255,12 @@ public class DefaultGenerator implements Generator {
config.processOpts();
// normalize the spec
if (config.getUseOpenAPINormalizer()) {
OpenAPINormalizer openapiNormalizer = new OpenAPINormalizer(openAPI, config.openapiNormalizer());
openapiNormalizer.normalize();
}
// resolve inline models
if (config.getUseInlineModelResolver()) {
InlineModelResolver inlineModelResolver = new InlineModelResolver();

View File

@@ -0,0 +1,384 @@
/*
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
* Copyright 2018 SmartBear Software
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openapitools.codegen;
import io.swagger.v3.oas.models.*;
import io.swagger.v3.oas.models.callbacks.Callback;
import io.swagger.v3.oas.models.media.*;
import io.swagger.v3.oas.models.parameters.Parameter;
import io.swagger.v3.oas.models.parameters.RequestBody;
import io.swagger.v3.oas.models.responses.ApiResponse;
import io.swagger.v3.oas.models.responses.ApiResponses;
import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.utils.ModelUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.stream.Collectors;
public class OpenAPINormalizer {
private OpenAPI openAPI;
private Map<String, String> rules = new HashMap<>();
final Logger LOGGER = LoggerFactory.getLogger(OpenAPINormalizer.class);
// ============= a list of rules =============
// when set to true, all rules are enabled
final String ALL = "ALL";
boolean enableAll;
// when set to true, $ref in allOf is treated as parent so that x-parent: true will be added
// to the schema in $ref (if x-parent is not present)
final String REF_AS_PARENT_IN_ALLOF = "REF_AS_PARENT_IN_ALLOF";
boolean enableRefAsParentInAllOf;
// ============= end of rules =============
/**
* Initializes OpenAPI Normalizer with a set of rules
*
* @param openAPI OpenAPI
* @param rules a map of rules
*/
public OpenAPINormalizer(OpenAPI openAPI, Map<String, String> rules) {
this.openAPI = openAPI;
this.rules = rules;
parseRules(rules);
}
/**
* Parses the rules.
*
* @param rules a map of rules
*/
public void parseRules(Map<String, String> rules) {
if (rules == null) {
return;
}
if ("true".equalsIgnoreCase(rules.get(ALL))) {
enableAll = true;
}
if (enableAll || "true".equalsIgnoreCase(rules.get(REF_AS_PARENT_IN_ALLOF))) {
enableRefAsParentInAllOf = true;
}
}
/**
* Normalizes the OpenAPI input, which may not perfectly conform to
* the specification.
*/
void normalize() {
if (rules == null || rules.isEmpty()) {
return;
}
if (this.openAPI.getComponents() == null) {
this.openAPI.setComponents(new Components());
}
if (this.openAPI.getComponents().getSchemas() == null) {
this.openAPI.getComponents().setSchemas(new HashMap<String, Schema>());
}
normalizePaths();
normalizeComponents();
}
/**
* Normalizes inline models in Paths
*/
private void normalizePaths() {
Paths paths = openAPI.getPaths();
if (paths == null) {
return;
}
for (Map.Entry<String, PathItem> pathsEntry : paths.entrySet()) {
PathItem path = pathsEntry.getValue();
List<Operation> operations = new ArrayList<>(path.readOperations());
// Include callback operation as well
for (Operation operation : path.readOperations()) {
Map<String, Callback> callbacks = operation.getCallbacks();
if (callbacks != null) {
operations.addAll(callbacks.values().stream()
.flatMap(callback -> callback.values().stream())
.flatMap(pathItem -> pathItem.readOperations().stream())
.collect(Collectors.toList()));
}
}
for (Operation operation : operations) {
normalizeRequestBody(operation);
normalizeParameters(operation);
normalizeResponses(operation);
}
}
}
/**
* Normalizes schemas in content
*
* @param content target content
*/
private void normalizeContent(Content content) {
if (content == null || content.isEmpty()) {
return;
}
for (String contentType : content.keySet()) {
MediaType mediaType = content.get(contentType);
if (mediaType == null) {
continue;
} else if (mediaType.getSchema() == null) {
continue;
} else {
normalizeSchema(mediaType.getSchema(), new HashSet<>());
}
}
}
/**
* Normalizes schemas in RequestBody
*
* @param operation target operation
*/
private void normalizeRequestBody(Operation operation) {
RequestBody requestBody = operation.getRequestBody();
if (requestBody == null) {
return;
}
// unalias $ref
if (requestBody.get$ref() != null) {
String ref = ModelUtils.getSimpleRef(requestBody.get$ref());
requestBody = openAPI.getComponents().getRequestBodies().get(ref);
if (requestBody == null) {
return;
}
}
normalizeContent(requestBody.getContent());
}
/**
* Normalizes schemas in parameters
*
* @param operation target operation
*/
private void normalizeParameters(Operation operation) {
List<Parameter> parameters = operation.getParameters();
if (parameters == null) {
return;
}
for (Parameter parameter : parameters) {
if (parameter.getSchema() == null) {
continue;
} else {
normalizeSchema(parameter.getSchema(), new HashSet<>());
}
}
}
/**
* Normalizes schemas in ApiResponses
*
* @param operation target operation
*/
private void normalizeResponses(Operation operation) {
ApiResponses responses = operation.getResponses();
if (responses == null) {
return;
}
for (Map.Entry<String, ApiResponse> responsesEntry : responses.entrySet()) {
if (responsesEntry.getValue() == null) {
continue;
} else {
normalizeContent(responsesEntry.getValue().getContent());
}
}
}
/**
* Normalizes schemas in components
*/
private void normalizeComponents() {
Map<String, Schema> schemas = openAPI.getComponents().getSchemas();
if (schemas == null) {
return;
}
List<String> schemaNames = new ArrayList<String>(schemas.keySet());
for (String schemaName : schemaNames) {
Schema schema = schemas.get(schemaName);
if (schema == null) {
LOGGER.warn("{} not fount found in openapi/components/schemas.", schemaName);
} else {
normalizeSchema(schema, new HashSet<>());
}
}
}
/**
* Normalizes a schema
*
* @param schema Schema
* @param visitedSchemas a set of visited schemas
*/
public void normalizeSchema(Schema schema, Set<Schema> visitedSchemas) {
if (schema == null) {
return;
}
if (StringUtils.isNotEmpty(schema.get$ref())) {
// not need to process $ref
return;
}
if ((visitedSchemas.contains(schema))) {
return; // skip due to circular reference
} else {
visitedSchemas.add(schema);
}
if (schema instanceof ArraySchema) {
normalizeSchema(schema.getItems(), visitedSchemas);
} else if (schema.getAdditionalProperties() instanceof Schema) { // map
normalizeSchema((Schema) schema.getAdditionalProperties(), visitedSchemas);
} else if (ModelUtils.isComposedSchema(schema)) {
ComposedSchema m = (ComposedSchema) schema;
if (m.getAllOf() != null && !m.getAllOf().isEmpty()) {
normalizeAllOf(m, visitedSchemas);
}
if (m.getOneOf() != null && !m.getOneOf().isEmpty()) {
normalizeOneOf(m, visitedSchemas);
}
if (m.getAnyOf() != null && !m.getAnyOf().isEmpty()) {
normalizeAnyOf(m, visitedSchemas);
}
if (m.getProperties() != null && !m.getProperties().isEmpty()) {
normalizeProperties(m.getProperties(), visitedSchemas);
}
if (m.getAdditionalProperties() != null) {
// normalizeAdditionalProperties(m);
}
} else if (schema.getNot() != null) {// not schema
normalizeSchema(schema.getNot(), visitedSchemas);
} else if (schema.getProperties() != null && !schema.getProperties().isEmpty()) {
normalizeProperties(schema.getProperties(), visitedSchemas);
} else if (schema instanceof Schema) {
normalizeNonComposedSchema(schema, visitedSchemas);
} else {
throw new RuntimeException("Unknown schema type found in normalizer: " + schema);
}
}
private void normalizeNonComposedSchema(Schema schema, Set<Schema> visitedSchemas) {
// normalize non-composed schema (e.g. schema with only properties)
}
private void normalizeProperties(Map<String, Schema> properties, Set<Schema> visitedSchemas) {
if (properties == null) {
return;
}
for (Map.Entry<String, Schema> propertiesEntry : properties.entrySet()) {
Schema property = propertiesEntry.getValue();
normalizeSchema(property, visitedSchemas);
}
}
private void normalizeAllOf(Schema schema, Set<Schema> visitedSchemas) {
for (Object item : schema.getAllOf()) {
if (!(item instanceof Schema)) {
throw new RuntimeException("Error! allOf schema is not of the type Schema: " + item);
}
// normalize allOf sub schemas one by one
normalizeSchema((Schema) item, visitedSchemas);
}
// process rules here
processUseAllOfRefAsParent(schema);
}
private void normalizeOneOf(Schema schema, Set<Schema> visitedSchemas) {
for (Object item : schema.getAllOf()) {
if (!(item instanceof Schema)) {
throw new RuntimeException("Error! allOf schema is not of the type Schema: " + item);
}
// normalize oenOf sub schemas one by one
normalizeSchema((Schema) item, visitedSchemas);
}
// process rules here
}
private void normalizeAnyOf(Schema schema, Set<Schema> visitedSchemas) {
for (Object item : schema.getAllOf()) {
if (!(item instanceof Schema)) {
throw new RuntimeException("Error! allOf schema is not of the type Schema: " + item);
}
// normalize anyOf sub schemas one by one
normalizeSchema((Schema) item, visitedSchemas);
}
// process rules here
}
// ===================== a list of rules =====================
// all rules (fuctions) start with the word "process"
private void processUseAllOfRefAsParent(Schema schema) {
if (!enableRefAsParentInAllOf) {
return;
}
for (Object item : schema.getAllOf()) {
if (!(item instanceof Schema)) {
throw new RuntimeException("Error! allOf schema is not of the type Schema: " + item);
}
Schema s = (Schema) item;
if (StringUtils.isNotEmpty(s.get$ref())) {
String ref = ModelUtils.getSimpleRef(s.get$ref());
// TODO need to check for requestBodies?
Schema refSchema = openAPI.getComponents().getSchemas().get(ref);
if (refSchema == null) {
throw new RuntimeException("schema cannot be null with ref " + ref);
}
if (refSchema.getExtensions() == null) {
refSchema.setExtensions(new HashMap<>());
}
if (refSchema.getExtensions().containsKey("x-parent")) {
// doing nothing as x-parent already exists
} else {
refSchema.getExtensions().put("x-parent", true);
}
LOGGER.debug("processUseAllOfRefAsParent added `x-parent: true` to {}", refSchema);
}
}
}
// ===================== end of rules =====================
}

View File

@@ -71,6 +71,7 @@ public class CodegenConfigurator {
private Map<String, String> schemaMappings = new HashMap<>();
private Map<String, String> inlineSchemaNameMappings = new HashMap<>();
private Map<String, String> inlineSchemaNameDefaults = new HashMap<>();
private Map<String, String> openapiNormalizer = new HashMap<>();
private Set<String> languageSpecificPrimitives = new HashSet<>();
private Map<String, String> reservedWordsMappings = new HashMap<>();
private Map<String, String> serverVariables = new HashMap<>();
@@ -123,6 +124,9 @@ public class CodegenConfigurator {
if(generatorSettings.getInlineSchemaNameDefaults() != null) {
configurator.inlineSchemaNameDefaults.putAll(generatorSettings.getInlineSchemaNameDefaults());
}
if(generatorSettings.getOpenAPINormalizer() != null) {
configurator.openapiNormalizer.putAll(generatorSettings.getOpenAPINormalizer());
}
if(generatorSettings.getLanguageSpecificPrimitives() != null) {
configurator.languageSpecificPrimitives.addAll(generatorSettings.getLanguageSpecificPrimitives());
}
@@ -210,6 +214,12 @@ public class CodegenConfigurator {
return this;
}
public CodegenConfigurator addOpenAPINormalizer(String key, String value) {
this.openapiNormalizer.put(key, value);
generatorSettingsBuilder.withOpenAPINormalizer(key, value);
return this;
}
public CodegenConfigurator addInstantiationType(String key, String value) {
this.instantiationTypes.put(key, value);
generatorSettingsBuilder.withInstantiationType(key, value);
@@ -382,6 +392,12 @@ public class CodegenConfigurator {
return this;
}
public CodegenConfigurator setOpenAPINormalizer(Map<String, String> openapiNormalizer) {
this.openapiNormalizer = openapiNormalizer;
generatorSettingsBuilder.withOpenAPINormalizer(openapiNormalizer);
return this;
}
public CodegenConfigurator setInputSpec(String inputSpec) {
this.inputSpec = inputSpec;
workflowSettingsBuilder.withInputSpec(inputSpec);
@@ -661,6 +677,7 @@ public class CodegenConfigurator {
config.schemaMapping().putAll(generatorSettings.getSchemaMappings());
config.inlineSchemaNameMapping().putAll(generatorSettings.getInlineSchemaNameMappings());
config.inlineSchemaNameDefault().putAll(generatorSettings.getInlineSchemaNameDefaults());
config.openapiNormalizer().putAll(generatorSettings.getOpenAPINormalizer());
config.languageSpecificPrimitives().addAll(generatorSettings.getLanguageSpecificPrimitives());
config.reservedWordsMappings().putAll(generatorSettings.getReservedWordsMappings());
config.additionalProperties().putAll(generatorSettings.getAdditionalProperties());

View File

@@ -120,6 +120,19 @@ public final class CodegenConfiguratorUtils {
}
}
public static void applyOpenAPINormalizerKvpList(List<String> openapiNormalizer, CodegenConfigurator configurator) {
for (String propString : openapiNormalizer) {
applyOpenAPINormalizerKvp(propString, configurator);
}
}
public static void applyOpenAPINormalizerKvp(String openapiNormalizer, CodegenConfigurator configurator) {
final Map<String, String> map = createMapFromKeyValuePairs(openapiNormalizer);
for (Map.Entry<String, String> entry : map.entrySet()) {
configurator.addOpenAPINormalizer(entry.getKey().trim(), entry.getValue().trim());
}
}
public static void applyTypeMappingsKvpList(List<String> typeMappings, CodegenConfigurator configurator) {
for (String propString : typeMappings) {
applyTypeMappingsKvp(propString, configurator);

View File

@@ -80,12 +80,9 @@ public class ExampleGenerator {
if (ModelUtils.isArraySchema(responseSchema)) { // array of schema
ArraySchema as = (ArraySchema) responseSchema;
if (as.getItems() != null && StringUtils.isEmpty(as.getItems().get$ref())) { // array of primitive types
if (as.getItems() != null) { // array of primitive types
return generate((Map<String, Object>) responseSchema.getExample(),
new ArrayList<String>(producesInfo), as.getItems());
} else if (as.getItems() != null && !StringUtils.isEmpty(as.getItems().get$ref())) { // array of model
return generate((Map<String, Object>) responseSchema.getExample(),
new ArrayList<String>(producesInfo), ModelUtils.getSimpleRef(as.getItems().get$ref()));
new ArrayList<>(producesInfo), as);
} else {
// TODO log warning message as such case is not handled at the moment
return null;

View File

@@ -155,6 +155,9 @@ public class XmlExampleGenerator {
}
} else if (StringUtils.isNotEmpty(schema.get$ref())) {
Schema actualSchema = examples.get(schema.get$ref());
if (actualSchema == null) {
actualSchema = examples.get(ModelUtils.getSimpleRef(schema.get$ref()));
}
sb.append(toXml(actualSchema, indent, path));
} else {
if (name != null) {

View File

@@ -83,6 +83,8 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
public static final String TEST_OUTPUT = "testOutput";
public static final String IMPLICIT_HEADERS = "implicitHeaders";
public static final String IMPLICIT_HEADERS_REGEX = "implicitHeadersRegex";
public static final String JAVAX_PACKAGE = "javaxPackage";
public static final String USE_JAKARTA_EE = "useJakartaEe";
public static final String CAMEL_CASE_DOLLAR_SIGN = "camelCaseDollarSign";
@@ -137,6 +139,7 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
protected String implicitHeadersRegex = null;
protected boolean camelCaseDollarSign = false;
protected boolean useJakartaEe = false;
private Map<String, String> schemaKeyToModelNameCache = new HashMap<>();
@@ -272,6 +275,7 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
cliOptions.add(CliOption.newBoolean(IMPLICIT_HEADERS, "Skip header parameters in the generated API methods using @ApiImplicitParams annotation.", implicitHeaders));
cliOptions.add(CliOption.newString(IMPLICIT_HEADERS_REGEX, "Skip header parameters that matches given regex in the generated API methods using @ApiImplicitParams annotation. Note: this parameter is ignored when implicitHeaders=true"));
cliOptions.add(CliOption.newBoolean(CAMEL_CASE_DOLLAR_SIGN, "Fix camelCase when starting with $ sign. when true : $Value when false : $value"));
cliOptions.add(CliOption.newBoolean(USE_JAKARTA_EE, "whether to use Jakarta EE namespace instead of javax"));
cliOptions.add(CliOption.newString(CodegenConstants.PARENT_GROUP_ID, CodegenConstants.PARENT_GROUP_ID_DESC));
cliOptions.add(CliOption.newString(CodegenConstants.PARENT_ARTIFACT_ID, CodegenConstants.PARENT_ARTIFACT_ID_DESC));
@@ -656,6 +660,7 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
additionalProperties.put("jsr310", "true");
typeMapping.put("date", "LocalDate");
importMapping.put("LocalDate", "java.time.LocalDate");
importMapping.put("LocalTime", "java.time.LocalTime");
if ("java8-localdatetime".equals(dateLibrary)) {
typeMapping.put("DateTime", "LocalDateTime");
importMapping.put("LocalDateTime", "java.time.LocalDateTime");
@@ -670,6 +675,17 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
if (additionalProperties.containsKey(TEST_OUTPUT)) {
setOutputTestFolder(additionalProperties.get(TEST_OUTPUT).toString());
}
if (additionalProperties.containsKey(USE_JAKARTA_EE)) {
this.setUseJakartaEe(Boolean.parseBoolean(additionalProperties.get(USE_JAKARTA_EE).toString()));
}
additionalProperties.put(USE_JAKARTA_EE, useJakartaEe);
if (useJakartaEe) {
applyJakartaPackage();
} else {
applyJavaxPackage();
}
}
@Override
@@ -721,6 +737,14 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
}
}
protected void applyJavaxPackage() {
writePropertyBack(JAVAX_PACKAGE, "javax");
}
protected void applyJakartaPackage() {
writePropertyBack(JAVAX_PACKAGE, "jakarta");
}
@Override
public String escapeReservedWord(String name) {
if (this.reservedWordsMappings().containsKey(name)) {
@@ -1351,7 +1375,7 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
}
if (serializeBigDecimalAsString) {
if ("decimal".equals(property.baseType)) {
if ("decimal".equals(property.baseType) || "bigdecimal".equalsIgnoreCase(property.baseType)) {
// we serialize BigDecimal as `string` to avoid precision loss
property.vendorExtensions.put("x-extra-annotation", "@JsonSerialize(using = ToStringSerializer.class)");
@@ -1936,6 +1960,10 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
this.camelCaseDollarSign = camelCaseDollarSign;
}
public void setUseJakartaEe(boolean useJakartaEe) {
this.useJakartaEe = useJakartaEe;
}
@Override
public String escapeQuotationMark(String input) {
// remove " to avoid code injection

View File

@@ -19,10 +19,13 @@ package org.openapitools.codegen.languages;
import com.google.common.collect.Sets;
import com.samskivert.mustache.Mustache;
import com.samskivert.mustache.Template;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.media.Discriminator;
import io.swagger.v3.oas.models.media.Schema;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.*;
import org.openapitools.codegen.CodegenDiscriminator.MappedModel;
import org.openapitools.codegen.api.TemplatePathLocator;
import org.openapitools.codegen.config.GlobalSettings;
import org.openapitools.codegen.meta.GeneratorMetadata;
@@ -44,6 +47,7 @@ import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -275,7 +279,7 @@ public class DartDioClientCodegen extends AbstractDartCodegen {
imports.put("Uint8List", "dart:typed_data");
imports.put("MultipartFile", DIO_IMPORT);
}
private void configureDateLibrary(String srcFolder) {
switch (dateLibrary) {
case DATE_LIBRARY_TIME_MACHINE:
@@ -400,6 +404,7 @@ public class DartDioClientCodegen extends AbstractDartCodegen {
private final String kHasAncestorOnlyProps = "x-has-ancestor-only-props";
private final String kSelfAndAncestorOnlyProps = "x-self-and-ancestor-only-props";
private final String kHasSelfAndAncestorOnlyProps = "x-has-self-and-ancestor-only-props";
private final String kParentDiscriminator = "x-parent-discriminator";
// adapts codegen models and property to dart rules of inheritance
private void adaptToDartInheritance(Map<String, ModelsMap> objs) {
@@ -449,6 +454,14 @@ public class DartDioClientCodegen extends AbstractDartCodegen {
cm.vendorExtensions.put(kIsChild, isChild);
cm.vendorExtensions.put(kIsParent, isParent);
cm.vendorExtensions.put(kIsPure, isPure);
if (!isParent && (cm.oneOf == null || cm.oneOf.isEmpty())) {
//discriminator has no meaning here
if (cm.discriminator!=null) {
cm.vendorExtensions.put(kParentDiscriminator, cm.discriminator);
cm.discriminator=null;
}
}
// when pure:
// vars = allVars = selfOnlyProperties = kSelfAndAncestorOnlyProps
// ancestorOnlyProps = empty
@@ -541,6 +554,30 @@ public class DartDioClientCodegen extends AbstractDartCodegen {
}
}
/// override the default behavior of createDiscriminator
/// to remove extra mappings added as a side effect of setLegacyDiscriminatorBehavior(false)
/// this ensures 1-1 schema mapping instead of 1-many
@Override
protected CodegenDiscriminator createDiscriminator(String schemaName, Schema schema, OpenAPI openAPI) {
CodegenDiscriminator sub = super.createDiscriminator(schemaName, schema, openAPI);
Discriminator originalDiscriminator = schema.getDiscriminator();
if (originalDiscriminator!=null) {
Map<String,String> originalMapping = originalDiscriminator.getMapping();
if (originalMapping != null && !originalMapping.isEmpty()) {
//we already have a discriminator mapping, remove everything else
for (MappedModel currentMappings : new HashSet<>(sub.getMappedModels())) {
if (originalMapping.containsKey(currentMappings.getMappingName())) {
//all good
} else {
sub.getMapping().remove(currentMappings.getMappingName());
sub.getMappedModels().remove(currentMappings);
}
}
}
}
return sub;
}
@Override
public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs) {
objs = super.postProcessAllModels(objs);

View File

@@ -511,7 +511,6 @@ public class JavaClientCodegen extends AbstractJavaCodegen
supportingFiles.add(new SupportingFile("ParamExpander.mustache", invokerFolder, "ParamExpander.java"));
}
supportingFiles.add(new SupportingFile("EncodingUtils.mustache", invokerFolder, "EncodingUtils.java"));
supportingFiles.add(new SupportingFile("auth/DefaultApi20Impl.mustache", authFolder, "DefaultApi20Impl.java"));
} else if (OKHTTP_GSON.equals(getLibrary()) || StringUtils.isEmpty(getLibrary())) {
// the "okhttp-gson" library template requires "ApiCallback.mustache" for async call
supportingFiles.add(new SupportingFile("ApiCallback.mustache", invokerFolder, "ApiCallback.java"));
@@ -576,7 +575,7 @@ public class JavaClientCodegen extends AbstractJavaCodegen
// The flag below should be set for all Java libraries, but the templates need to be ported
// one by one for each library.
supportsAdditionalPropertiesWithComposedSchema = true;
applyJakartaPackage();
} else if (NATIVE.equals(getLibrary())) {
supportingFiles.add(new SupportingFile("ApiResponse.mustache", invokerFolder, "ApiResponse.java"));
supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java"));
@@ -714,6 +713,7 @@ public class JavaClientCodegen extends AbstractJavaCodegen
// Add OauthPasswordGrant.java and OauthClientCredentialsGrant.java for feign library
if (FEIGN.equals(getLibrary())) {
supportingFiles.add(new SupportingFile("auth/DefaultApi20Impl.mustache", authFolder, "DefaultApi20Impl.java"));
supportingFiles.add(new SupportingFile("auth/OauthPasswordGrant.mustache", authFolder, "OauthPasswordGrant.java"));
supportingFiles.add(new SupportingFile("auth/OauthClientCredentialsGrant.mustache", authFolder, "OauthClientCredentialsGrant.java"));
supportingFiles.add(new SupportingFile("auth/ApiErrorDecoder.mustache", authFolder, "ApiErrorDecoder.java"));

View File

@@ -457,16 +457,16 @@ public class PythonNextgenClientCodegen extends AbstractPythonCodegen implements
fieldCustomization.add("strict=True");
if (cp.getMaximum() != null) {
if (cp.getExclusiveMaximum()) {
fieldCustomization.add("gt=" + cp.getMaximum());
fieldCustomization.add("lt=" + cp.getMaximum());
} else {
fieldCustomization.add("ge=" + cp.getMaximum());
fieldCustomization.add("le=" + cp.getMaximum());
}
}
if (cp.getMinimum() != null) {
if (cp.getExclusiveMinimum()) {
fieldCustomization.add("lt=" + cp.getMinimum());
fieldCustomization.add("gt=" + cp.getMinimum());
} else {
fieldCustomization.add("le=" + cp.getMinimum());
fieldCustomization.add("ge=" + cp.getMinimum());
}
}
if (cp.getMultipleOf() != null) {

View File

@@ -424,8 +424,9 @@ public class RustClientCodegen extends AbstractRustCodegen implements CodegenCon
@Override
public String getTypeDeclaration(Schema p) {
if (ModelUtils.isArraySchema(p)) {
ArraySchema ap = (ArraySchema) p;
Schema unaliasSchema = unaliasSchema(p);
if (ModelUtils.isArraySchema(unaliasSchema)) {
ArraySchema ap = (ArraySchema) unaliasSchema;
Schema inner = ap.getItems();
if (inner == null) {
LOGGER.warn("{}(array property) does not have a proper inner type defined.Default to string",
@@ -433,10 +434,10 @@ public class RustClientCodegen extends AbstractRustCodegen implements CodegenCon
inner = new StringSchema().description("TODO default missing array inner type to string");
}
return "Vec<" + getTypeDeclaration(inner) + ">";
} else if (ModelUtils.isMapSchema(p)) {
Schema inner = getAdditionalProperties(p);
} else if (ModelUtils.isMapSchema(unaliasSchema)) {
Schema inner = getAdditionalProperties(unaliasSchema);
if (inner == null) {
LOGGER.warn("{}(map property) does not have a proper inner type defined. Default to string", p.getName());
LOGGER.warn("{}(map property) does not have a proper inner type defined. Default to string", unaliasSchema.getName());
inner = new StringSchema().description("TODO default missing map inner type to string");
}
return "::std::collections::HashMap<String, " + getTypeDeclaration(inner) + ">";
@@ -444,7 +445,7 @@ public class RustClientCodegen extends AbstractRustCodegen implements CodegenCon
// Not using the supertype invocation, because we want to UpperCamelize
// the type.
String schemaType = getSchemaType(p);
String schemaType = getSchemaType(unaliasSchema);
if (typeMapping.containsKey(schemaType)) {
return typeMapping.get(schemaType);
}

View File

@@ -105,7 +105,6 @@ public class SpringCodegen extends AbstractJavaCodegen
public static final String RETURN_SUCCESS_CODE = "returnSuccessCode";
public static final String UNHANDLED_EXCEPTION_HANDLING = "unhandledException";
public static final String USE_SPRING_BOOT3 = "useSpringBoot3";
public static final String USE_JAKARTA_EE = "useJakartaEe";
public static final String REQUEST_MAPPING_OPTION = "requestMappingMode";
public static final String USE_REQUEST_MAPPING_ON_CONTROLLER = "useRequestMappingOnController";
public static final String USE_REQUEST_MAPPING_ON_INTERFACE = "useRequestMappingOnInterface";
@@ -243,7 +242,7 @@ public class SpringCodegen extends AbstractJavaCodegen
useSwaggerUI));
cliOptions.add(CliOption.newBoolean(USE_SPRING_BOOT3,
"Generate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports).",
useSwaggerUI));
useSpringBoot3));
supportedLibraries.put(SPRING_BOOT, "Spring-boot Server application.");
supportedLibraries.put(SPRING_CLOUD_LIBRARY,
@@ -474,9 +473,7 @@ public class SpringCodegen extends AbstractJavaCodegen
if (AnnotationLibrary.SWAGGER1.equals(getAnnotationLibrary())) {
throw new IllegalArgumentException(AnnotationLibrary.SWAGGER1.getPropertyName() + " is not supported with Spring Boot > 3.x");
}
writePropertyBack(USE_JAKARTA_EE, true);
} else {
writePropertyBack(USE_JAKARTA_EE, false);
applyJakartaPackage();
}
writePropertyBack(USE_SPRING_BOOT3, isUseSpringBoot3());

View File

@@ -73,6 +73,8 @@ public class TypeScriptClientCodegen extends DefaultCodegen implements CodegenCo
private static final String PLATFORM_SWITCH = "platform";
private static final String PLATFORM_SWITCH_DESC = "Specifies the platform the code should run on. The default is 'node' for the 'request' framework and 'browser' otherwise.";
private static final String[] PLATFORMS = { "browser", "node", "deno" };
private static final String IMPORT_FILE_EXTENSION_SWITCH = "importFileExtension";
private static final String IMPORT_FILE_EXTENSION_SWITCH_DESC = "File extension to use with relative imports. Set it to '.js' or '.mjs' when using [ESM](https://nodejs.org/api/esm.html). Defaults to '.ts' when 'platform' is set to 'deno'.";
private static final String FILE_CONTENT_DATA_TYPE= "fileContentDataType";
private static final String FILE_CONTENT_DATA_TYPE_DESC = "Specifies the type to use for the content of a file - i.e. Blob (Browser, Deno) / Buffer (node)";
private static final String USE_RXJS_SWITCH = "useRxJS";
@@ -198,6 +200,7 @@ public class TypeScriptClientCodegen extends DefaultCodegen implements CodegenCo
cliOptions.add(new CliOption(TypeScriptClientCodegen.USE_RXJS_SWITCH, TypeScriptClientCodegen.USE_RXJS_SWITCH_DESC).defaultValue("false"));
cliOptions.add(new CliOption(TypeScriptClientCodegen.USE_OBJECT_PARAMS_SWITCH, TypeScriptClientCodegen.USE_OBJECT_PARAMS_DESC).defaultValue("false"));
cliOptions.add(new CliOption(TypeScriptClientCodegen.USE_INVERSIFY_SWITCH, TypeScriptClientCodegen.USE_INVERSIFY_SWITCH_DESC).defaultValue("false"));
cliOptions.add(new CliOption(TypeScriptClientCodegen.IMPORT_FILE_EXTENSION_SWITCH, TypeScriptClientCodegen.IMPORT_FILE_EXTENSION_SWITCH_DESC));
CliOption frameworkOption = new CliOption(TypeScriptClientCodegen.FRAMEWORK_SWITCH, TypeScriptClientCodegen.FRAMEWORK_SWITCH_DESC);
for (String option: TypeScriptClientCodegen.FRAMEWORKS) {
@@ -835,8 +838,9 @@ public class TypeScriptClientCodegen extends DefaultCodegen implements CodegenCo
supportingFiles.add(new SupportingFile("tsconfig.mustache", "", "tsconfig.json"));
}
if ("deno".equals(propPlatform)) {
additionalProperties.put("extensionForDeno", ".ts");
Object fileExtension = additionalProperties.get(IMPORT_FILE_EXTENSION_SWITCH);
if (fileExtension == null && "deno".equals(propPlatform)) {
additionalProperties.put(IMPORT_FILE_EXTENSION_SWITCH, ".ts");
}
final boolean useRxJS = convertPropertyToBooleanAndWriteBack(USE_RXJS_SWITCH);

View File

@@ -1,633 +0,0 @@
/*
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
* Copyright 2018 SmartBear Software
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openapitools.codegen.languages;
import io.swagger.v3.oas.models.media.Schema;
import org.openapitools.codegen.*;
import org.openapitools.codegen.meta.features.DocumentationFeature;
import org.openapitools.codegen.meta.features.GlobalFeature;
import org.openapitools.codegen.model.ModelMap;
import org.openapitools.codegen.model.ModelsMap;
import org.openapitools.codegen.model.OperationMap;
import org.openapitools.codegen.model.OperationsMap;
import org.openapitools.codegen.utils.ModelUtils;
import org.openapitools.codegen.utils.SemVer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.apache.commons.lang3.StringUtils.capitalize;
import static org.openapitools.codegen.utils.CamelizeOption.LOWERCASE_FIRST_LETTER;
import static org.openapitools.codegen.utils.StringUtils.*;
public class TypeScriptKoaServerCodegen extends AbstractTypeScriptClientCodegen {
private final Logger LOGGER = LoggerFactory.getLogger(TypeScriptKoaServerCodegen.class);
private static String CLASS_NAME_PREFIX_PATTERN = "^[a-zA-Z0-9]*$";
private static String CLASS_NAME_SUFFIX_PATTERN = "^[a-zA-Z0-9]*$";
private static String FILE_NAME_SUFFIX_PATTERN = "^[a-zA-Z0-9.-]*$";
public static enum QUERY_PARAM_OBJECT_FORMAT_TYPE {dot, json, key}
public static enum PROVIDED_IN_LEVEL {none, root, any, platform}
private static final String DEFAULT_IMPORT_PREFIX = "./";
private static final String DEFAULT_MODEL_IMPORT_DIRECTORY_PREFIX = "../";
public static final String NPM_REPOSITORY = "npmRepository";
public static final String WITH_INTERFACES = "withInterfaces";
public static final String USE_SINGLE_REQUEST_PARAMETER = "useSingleRequestParameter";
public static final String TAGGED_UNIONS = "taggedUnions";
public static final String NG_VERSION = "ngVersion";
public static final String PROVIDED_IN = "providedIn";
public static final String ENFORCE_GENERIC_MODULE_WITH_PROVIDERS = "enforceGenericModuleWithProviders";
public static final String HTTP_CONTEXT_IN_OPTIONS = "httpContextInOptions";
public static final String API_MODULE_PREFIX = "apiModulePrefix";
public static final String CONFIGURATION_PREFIX = "configurationPrefix";
public static final String SERVICE_SUFFIX = "serviceSuffix";
public static final String SERVICE_FILE_SUFFIX = "serviceFileSuffix";
public static final String MODEL_SUFFIX = "modelSuffix";
public static final String MODEL_FILE_SUFFIX = "modelFileSuffix";
public static final String FILE_NAMING = "fileNaming";
public static final String STRING_ENUMS = "stringEnums";
public static final String STRING_ENUMS_DESC = "Generate string enums instead of objects for enum values.";
public static final String QUERY_PARAM_OBJECT_FORMAT = "queryParamObjectFormat";
protected String ngVersion = "15.0.3";
protected String npmRepository = null;
private boolean useSingleRequestParameter = false;
protected String serviceSuffix = "Service";
protected String serviceFileSuffix = ".service";
protected String modelSuffix = "";
protected String modelFileSuffix = "";
protected String fileNaming = "camelCase";
protected Boolean stringEnums = false;
protected QUERY_PARAM_OBJECT_FORMAT_TYPE queryParamObjectFormat = QUERY_PARAM_OBJECT_FORMAT_TYPE.dot;
protected PROVIDED_IN_LEVEL providedIn = PROVIDED_IN_LEVEL.root;
private boolean taggedUnions = false;
public TypeScriptKoaServerCodegen() {
super();
modifyFeatureSet(features -> features
.includeDocumentationFeatures(DocumentationFeature.Readme)
.includeGlobalFeatures(GlobalFeature.ParameterStyling)
);
this.outputFolder = "generated-code/typescript-koa";
supportsMultipleInheritance = true;
embeddedTemplateDir = templateDir = "typescript-koa";
modelTemplateFiles.put("model.mustache", ".ts");
apiTemplateFiles.put("api.service.mustache", ".ts");
languageSpecificPrimitives.add("Blob");
typeMapping.put("file", "Blob");
apiPackage = "api";
modelPackage = "model";
this.cliOptions.add(new CliOption(NPM_REPOSITORY,
"Use this property to set an url your private npmRepo in the package.json"));
this.cliOptions.add(CliOption.newBoolean(WITH_INTERFACES,
"Setting this property to true will generate interfaces next to the default class implementations.",
false));
this.cliOptions.add(CliOption.newBoolean(USE_SINGLE_REQUEST_PARAMETER,
"Setting this property to true will generate functions with a single argument containing all API endpoint parameters instead of one argument per parameter.",
false));
this.cliOptions.add(CliOption.newBoolean(TAGGED_UNIONS,
"Use discriminators to create tagged unions instead of extending interfaces.",
this.taggedUnions));
CliOption providedInCliOpt = new CliOption(PROVIDED_IN,
"Use this property to provide Injectables in wanted level.").defaultValue("root");
Map<String, String> providedInOptions = new HashMap<>();
providedInOptions.put(PROVIDED_IN_LEVEL.none.toString(), "No providedIn)");
providedInOptions.put(PROVIDED_IN_LEVEL.root.toString(), "The application-level injector in most apps.");
providedInOptions.put(PROVIDED_IN_LEVEL.platform.toString(), "A special singleton platform injector shared by all applications on the page.");
providedInOptions.put(PROVIDED_IN_LEVEL.any.toString(), "Provides a unique instance in each lazy loaded module while all eagerly loaded modules share one instance.");
providedInCliOpt.setEnum(providedInOptions);
this.cliOptions.add(providedInCliOpt);
this.cliOptions.add(new CliOption(API_MODULE_PREFIX, "The prefix of the generated ApiModule."));
this.cliOptions.add(new CliOption(CONFIGURATION_PREFIX, "The prefix of the generated Configuration."));
this.cliOptions.add(new CliOption(SERVICE_SUFFIX, "The suffix of the generated service.").defaultValue(this.serviceSuffix));
this.cliOptions.add(new CliOption(SERVICE_FILE_SUFFIX, "The suffix of the file of the generated service (service<suffix>.ts).").defaultValue(this.serviceFileSuffix));
this.cliOptions.add(new CliOption(MODEL_SUFFIX, "The suffix of the generated model."));
this.cliOptions.add(new CliOption(MODEL_FILE_SUFFIX, "The suffix of the file of the generated model (model<suffix>.ts)."));
this.cliOptions.add(new CliOption(FILE_NAMING, "Naming convention for the output files: 'camelCase', 'kebab-case'.").defaultValue(this.fileNaming));
this.cliOptions.add(new CliOption(STRING_ENUMS, STRING_ENUMS_DESC).defaultValue(String.valueOf(this.stringEnums)));
this.cliOptions.add(new CliOption(QUERY_PARAM_OBJECT_FORMAT, "The format for query param objects: 'dot', 'json', 'key'.").defaultValue(this.queryParamObjectFormat.name()));
}
@Override
protected void addAdditionPropertiesToCodeGenModel(CodegenModel codegenModel, Schema schema) {
codegenModel.additionalPropertiesType = getTypeDeclaration(getAdditionalProperties(schema));
addImport(codegenModel, codegenModel.additionalPropertiesType);
}
@Override
public String getName() {
return "typescript-koa-server";
}
@Override
public String getHelp() {
return "Generates a TypeScript Koa (2.x) server.";
}
@Override
public void processOpts() {
super.processOpts();
supportingFiles.add(new SupportingFile("env.example.mustache", "", ".env.example"));
supportingFiles.add(new SupportingFile("jest.config.js.mustache", "", ".jest.config.js"));
supportingFiles.add(new SupportingFile("app.ts.mustache", "", "app.ts"));
supportingFiles.add(new SupportingFile("build.js.mustache", "", "build.js"));
supportingFiles.add(new SupportingFile("docker-compose.mustache", "", "docker-compose.yml"));
supportingFiles.add(new SupportingFile("nodemon.mustache", "", "nodemon.json"));
supportingFiles.add(new SupportingFile("package.mustache", "", "package.json"));
supportingFiles.add(new SupportingFile("tsconfig.mustache", "", "tsconfig.json"));
// app/session folder
supportingFiles.add(new SupportingFile("sessions.service.ts.mustache", "app" + File.separator + "services", "sessions.service.ts"));
supportingFiles.add(new SupportingFile("sessions.index.ts.mustache", "app" + File.separator + "ervices", "index.ts"));
// app/helpers folder
supportingFiles.add(new SupportingFile("client.ts.mustache", "app" + File.separator + "helpers", "client.ts"));
// app/jobs folder
supportingFiles.add(new SupportingFile("jobs.README.mustache", "app" + File.separator + "jobs", "README.md"));
// app/controllers
supportingFiles.add(new SupportingFile("index.ts.mustache", "app" + File.separator + "controllers", "index.ts"));
supportingFiles.add(new SupportingFile("sessions.controller.ts.mustache", "app" + File.separator + "controllers", "sessions.controller.ts"));
// app/controllers/__tests__
supportingFiles.add(new SupportingFile("session.test.js.mustache", "app" + File.separator + "controllers" + File.separator + "__tests__", "session.test.js"));
// configs
supportingFiles.add(new SupportingFile("application.ts.mustache", "configs", "application.ts"));
supportingFiles.add(new SupportingFile("bootstrap.ts.mustache", "configs", "bootstrap.ts"));
supportingFiles.add(new SupportingFile("interceptors.ts.mustache", "configs", "interceptors.ts"));
supportingFiles.add(new SupportingFile("koa.middlewares.ts.mustache", "configs", "koa.middlewares.ts"));
supportingFiles.add(new SupportingFile("routing.middlewares.ts.mustache", "configs", "routing.middlewares.ts"));
supportingFiles.add(new SupportingFile("routing.options.ts.mustache", "configs", "routing.options.ts"));
supportingFiles.add(new SupportingFile("utils.ts.mustache", "configs", "utils.ts"));
// configs/constants
supportingFiles.add(new SupportingFile("development.ts.mustache", "configs" + File.separator + "constants", "development.ts"));
supportingFiles.add(new SupportingFile("envs.ts.mustache", "configs" + File.separator + "constants", "envs.ts"));
supportingFiles.add(new SupportingFile("configs.constants.index.ts.mustache", "configs" + File.separator + "constants", "index.ts"));
supportingFiles.add(new SupportingFile("production.ts.mustache", "configs" + File.separator + "constants", "production.ts"));
supportingFiles.add(new SupportingFile("staging.ts.mustache", "configs" + File.separator + "constants", "staging.ts"));
// prisma
supportingFiles.add(new SupportingFile("schema.prisma.mustache", "prisma", "schema.prisma"));
supportingFiles.add(new SupportingFile("gitignore", "", ".gitignore"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
if (additionalProperties.containsKey(CONFIGURATION_PREFIX)) {
String configurationPrefix = additionalProperties.get(CONFIGURATION_PREFIX).toString();
validateClassPrefixArgument("Configuration", configurationPrefix);
additionalProperties.put("configurationClassName", configurationPrefix + "Configuration");
additionalProperties.put("configurationParametersInterfaceName", configurationPrefix + "ConfigurationParameters");
} else {
additionalProperties.put("configurationClassName", "Configuration");
additionalProperties.put("configurationParametersInterfaceName", "ConfigurationParameters");
}
}
private String getIndexDirectory() {
String indexPackage = modelPackage.substring(0, Math.max(0, modelPackage.lastIndexOf('.')));
return indexPackage.replace('.', File.separatorChar);
}
public void setStringEnums(boolean value) {
stringEnums = value;
}
public Boolean getStringEnums() {
return stringEnums;
}
public boolean getQueryParamObjectFormatDot() {
return QUERY_PARAM_OBJECT_FORMAT_TYPE.dot.equals(queryParamObjectFormat);
}
public boolean getQueryParamObjectFormatJson() {
return QUERY_PARAM_OBJECT_FORMAT_TYPE.json.equals(queryParamObjectFormat);
}
public boolean getQueryParamObjectFormatKey() {
return QUERY_PARAM_OBJECT_FORMAT_TYPE.key.equals(queryParamObjectFormat);
}
@Override
public boolean isDataTypeFile(final String dataType) {
return "Blob".equals(dataType);
}
@Override
public String getTypeDeclaration(Schema p) {
if (ModelUtils.isFileSchema(p)) {
return "Blob";
} else {
return super.getTypeDeclaration(p);
}
}
private String applyLocalTypeMapping(String type) {
if (typeMapping.containsKey(type)) {
type = typeMapping.get(type);
}
return type;
}
@Override
public void postProcessParameter(CodegenParameter parameter) {
super.postProcessParameter(parameter);
parameter.dataType = applyLocalTypeMapping(parameter.dataType);
}
@Override
public OperationsMap postProcessOperationsWithModels(OperationsMap operations, List<ModelMap> allModels) {
OperationMap objs = operations.getOperations();
// Add filename information for api imports
objs.put("apiFilename", getApiFilenameFromClassname(objs.getClassname()));
List<CodegenOperation> ops = objs.getOperation();
boolean hasSomeFormParams = false;
boolean hasSomeEncodableParams = false;
for (CodegenOperation op : ops) {
if (op.getHasFormParams()) {
hasSomeFormParams = true;
}
op.httpMethod = op.httpMethod.toLowerCase(Locale.ENGLISH);
// Prep a string buffer where we're going to set up our new version of the string.
StringBuilder pathBuffer = new StringBuilder();
ParameterExpander paramExpander = new ParameterExpander(op, this::toParamName);
int insideCurly = 0;
// Iterate through existing string, one character at a time.
for (int i = 0; i < op.path.length(); i++) {
switch (op.path.charAt(i)) {
case '{':
// We entered curly braces, so track that.
insideCurly++;
break;
case '}':
// We exited curly braces, so track that.
insideCurly--;
pathBuffer.append(paramExpander.buildPathEntry());
hasSomeEncodableParams = true;
break;
default:
char nextChar = op.path.charAt(i);
if (insideCurly > 0) {
paramExpander.appendToParameterName(nextChar);
} else {
pathBuffer.append(nextChar);
}
break;
}
}
// Overwrite path to TypeScript template string, after applying everything we just did.
op.path = pathBuffer.toString();
}
operations.put("hasSomeFormParams", hasSomeFormParams);
operations.put("hasSomeEncodableParams", hasSomeEncodableParams);
// Add additional filename information for model imports in the services
List<Map<String, String>> imports = operations.getImports();
for (Map<String, String> im : imports) {
// This property is not used in the templates any more, subject for removal
im.put("filename", im.get("import"));
im.put("classname", im.get("classname"));
}
return operations;
}
@Override
public ModelsMap postProcessModels(ModelsMap objs) {
ModelsMap result = super.postProcessModels(objs);
return postProcessModelsEnum(result);
}
@Override
public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs) {
Map<String, ModelsMap> result = super.postProcessAllModels(objs);
for (ModelsMap entry : result.values()) {
for (ModelMap mo : entry.getModels()) {
CodegenModel cm = mo.getModel();
if (taggedUnions) {
mo.put(TAGGED_UNIONS, true);
if (cm.discriminator != null && cm.children != null) {
for (CodegenModel child : cm.children) {
cm.imports.add(child.classname);
setChildDiscriminatorValue(cm, child);
}
}
// with tagged union, a child model doesn't extend the parent (all properties are just copied over)
// it means we don't need to import that parent any more
if (cm.parent != null) {
cm.imports.remove(cm.parent);
// however, it's possible that the child model contains a recursive reference to the parent
// in order to support this case, we update the list of imports from properties once again
for (CodegenProperty cp : cm.allVars) {
addImportsForPropertyType(cm, cp);
}
removeSelfReferenceImports(cm);
}
}
// Add additional filename information for imports
Set<String> parsedImports = parseImports(cm);
mo.put("tsImports", toTsImports(cm, parsedImports));
}
}
return result;
}
private void setChildDiscriminatorValue(CodegenModel parent, CodegenModel child) {
if (child.vendorExtensions.isEmpty() ||
!child.vendorExtensions.containsKey("x-discriminator-value")
) {
for (CodegenProperty prop : child.allVars) {
if (prop.baseName.equals(parent.discriminator.getPropertyName())) {
for (CodegenDiscriminator.MappedModel mappedModel : parent.discriminator.getMappedModels()) {
if (mappedModel.getModelName().equals(child.classname)) {
prop.discriminatorValue = mappedModel.getMappingName();
}
}
}
}
}
}
/**
* Parse imports
*/
private Set<String> parseImports(CodegenModel cm) {
Set<String> newImports = new HashSet<>();
if (cm.imports.size() > 0) {
for (String name : cm.imports) {
if (name.indexOf(" | ") >= 0) {
String[] parts = name.split(" \\| ");
Collections.addAll(newImports, parts);
} else {
newImports.add(name);
}
}
}
return newImports;
}
private List<Map<String, String>> toTsImports(CodegenModel cm, Set<String> imports) {
List<Map<String, String>> tsImports = new ArrayList<>();
for (String im : imports) {
if (!im.equals(cm.classname)) {
HashMap<String, String> tsImport = new HashMap<>();
// TVG: This is used as class name in the import statements of the model file
tsImport.put("classname", im);
tsImport.put("filename", toModelFilename(removeModelPrefixSuffix(im)));
tsImports.add(tsImport);
}
}
return tsImports;
}
@Override
public String toApiName(String name) {
if (name.length() == 0) {
return "DefaultService";
}
return camelize(name) + serviceSuffix;
}
@Override
public String toApiFilename(String name) {
if (name.length() == 0) {
return "default.service";
}
return this.convertUsingFileNamingConvention(name) + serviceFileSuffix;
}
@Override
public String toApiImport(String name) {
if (importMapping.containsKey(name)) {
return importMapping.get(name);
}
return apiPackage() + "/" + toApiFilename(name);
}
@Override
public String toModelFilename(String name) {
if (importMapping.containsKey(name)) {
return importMapping.get(name);
}
return DEFAULT_IMPORT_PREFIX + this.convertUsingFileNamingConvention(super.toModelFilename(name)) + modelFileSuffix;
}
@Override
public String toModelImport(String name) {
if (importMapping.containsKey(name)) {
return importMapping.get(name);
}
return DEFAULT_MODEL_IMPORT_DIRECTORY_PREFIX + modelPackage() + "/" + toModelFilename(name).substring(DEFAULT_IMPORT_PREFIX.length());
}
public String getNpmRepository() {
return npmRepository;
}
public void setNpmRepository(String npmRepository) {
this.npmRepository = npmRepository;
}
private boolean getUseSingleRequestParameter() {
return useSingleRequestParameter;
}
private void setUseSingleRequestParameter(boolean useSingleRequestParameter) {
this.useSingleRequestParameter = useSingleRequestParameter;
}
private String getApiFilenameFromClassname(String classname) {
String name = classname.substring(0, classname.length() - serviceSuffix.length());
return toApiFilename(name);
}
@Override
public String toModelName(String name) {
name = addSuffix(name, modelSuffix);
return super.toModelName(name);
}
public String removeModelPrefixSuffix(String name) {
String result = name;
if (modelSuffix.length() > 0 && result.endsWith(modelSuffix)) {
result = result.substring(0, result.length() - modelSuffix.length());
}
String prefix = capitalize(this.modelNamePrefix);
String suffix = capitalize(this.modelNameSuffix);
if (prefix.length() > 0 && result.startsWith(prefix)) {
result = result.substring(prefix.length());
}
if (suffix.length() > 0 && result.endsWith(suffix)) {
result = result.substring(0, result.length() - suffix.length());
}
return result;
}
/**
* Validates that the given string value only contains '-', '.' and alpha numeric characters.
* Throws an IllegalArgumentException, if the string contains any other characters.
*
* @param argument The name of the argument being validated. This is only used for displaying an error message.
* @param value The value that is being validated.
*/
private void validateFileSuffixArgument(String argument, String value) {
if (!value.matches(FILE_NAME_SUFFIX_PATTERN)) {
throw new IllegalArgumentException(
String.format(Locale.ROOT, "%s file suffix only allows '.', '-' and alphanumeric characters.", argument)
);
}
}
/**
* Validates that the given string value only contains alpha numeric characters.
* Throws an IllegalArgumentException, if the string contains any other characters.
*
* @param argument The name of the argument being validated. This is only used for displaying an error message.
* @param value The value that is being validated.
*/
private void validateClassPrefixArgument(String argument, String value) {
if (!value.matches(CLASS_NAME_PREFIX_PATTERN)) {
throw new IllegalArgumentException(
String.format(Locale.ROOT, "%s class prefix only allows alphanumeric characters.", argument)
);
}
}
/**
* Validates that the given string value only contains alpha numeric characters.
* Throws an IllegalArgumentException, if the string contains any other characters.
*
* @param argument The name of the argument being validated. This is only used for displaying an error message.
* @param value The value that is being validated.
*/
private void validateClassSuffixArgument(String argument, String value) {
if (!value.matches(CLASS_NAME_SUFFIX_PATTERN)) {
throw new IllegalArgumentException(
String.format(Locale.ROOT, "%s class suffix only allows alphanumeric characters.", argument)
);
}
}
/**
* Set the query param object format.
*
* @param format the query param object format to use
*/
public void setQueryParamObjectFormat(String format) {
try {
queryParamObjectFormat = QUERY_PARAM_OBJECT_FORMAT_TYPE.valueOf(format);
} catch (IllegalArgumentException e) {
String values = Stream.of(QUERY_PARAM_OBJECT_FORMAT_TYPE.values())
.map(value -> "'" + value.name() + "'")
.collect(Collectors.joining(", "));
String msg = String.format(Locale.ROOT, "Invalid query param object format '%s'. Must be one of %s.", format, values);
throw new IllegalArgumentException(msg);
}
}
/**
* Set the file naming type.
*
* @param fileNaming the file naming to use
*/
private void setFileNaming(String fileNaming) {
if ("camelCase".equals(fileNaming) || "kebab-case".equals(fileNaming)) {
this.fileNaming = fileNaming;
} else {
throw new IllegalArgumentException("Invalid file naming '" +
fileNaming + "'. Must be 'camelCase' or 'kebab-case'");
}
}
/**
* Converts the original name according to the current <code>fileNaming</code> strategy.
*
* @param originalName the original name to transform
* @return the transformed name
*/
private String convertUsingFileNamingConvention(String originalName) {
String name = this.removeModelPrefixSuffix(originalName);
if ("kebab-case".equals(fileNaming)) {
name = dashize(underscore(name));
} else {
name = camelize(name, LOWERCASE_FIRST_LETTER);
}
return name;
}
/**
* Set the Injectable level
*
* @param level the wanted level
*/
public void setProvidedIn(String level) {
try {
providedIn = PROVIDED_IN_LEVEL.valueOf(level);
} catch (IllegalArgumentException e) {
String values = Stream.of(PROVIDED_IN_LEVEL.values())
.map(value -> "'" + value.name() + "'")
.collect(Collectors.joining(", "));
String msg = String.format(Locale.ROOT, "Invalid providedIn level '%s'. Must be one of %s.", level, values);
throw new IllegalArgumentException(msg);
}
}
/**
*
*/
private boolean getIsProvidedInNone() {
return PROVIDED_IN_LEVEL.none.equals(providedIn);
}
}

View File

@@ -308,15 +308,15 @@ public class ModelUtils {
/**
* Invoke the specified visitor function for every schema that matches mimeType in the OpenAPI document.
*
* <p>
* To avoid infinite recursion, referenced schemas are visited only once. When a referenced schema is visited,
* it is added to visitedSchemas.
*
* @param openAPI the OpenAPI document that contains schema objects.
* @param schema the root schema object to be visited.
* @param mimeType the mime type. TODO: does not seem to be used in a meaningful way.
* @param openAPI the OpenAPI document that contains schema objects.
* @param schema the root schema object to be visited.
* @param mimeType the mime type. TODO: does not seem to be used in a meaningful way.
* @param visitedSchemas the list of referenced schemas that have been visited.
* @param visitor the visitor function which is invoked for every visited schema.
* @param visitor the visitor function which is invoked for every visited schema.
*/
private static void visitSchema(OpenAPI openAPI, Schema schema, String mimeType, List<String> visitedSchemas, OpenAPISchemaVisitor visitor) {
visitor.visit(schema, mimeType);
@@ -425,13 +425,14 @@ public class ModelUtils {
/**
* Return true if the specified schema is an object with a fixed number of properties.
*
* <p>
* A ObjectSchema differs from a MapSchema in the following way:
* - An ObjectSchema is not extensible, i.e. it has a fixed number of properties.
* - A MapSchema is an object that can be extended with an arbitrary set of properties.
* The payload may include dynamic properties.
*
* <p>
* For example, an OpenAPI schema is considered an ObjectSchema in the following scenarios:
* <p>
*
* type: object
* additionalProperties: false
@@ -479,16 +480,17 @@ public class ModelUtils {
* Return true if the specified 'schema' is an object that can be extended with additional properties.
* Additional properties means a Schema should support all explicitly defined properties plus any
* undeclared properties.
*
* <p>
* A MapSchema differs from an ObjectSchema in the following way:
* - An ObjectSchema is not extensible, i.e. it has a fixed number of properties.
* - A MapSchema is an object that can be extended with an arbitrary set of properties.
* The payload may include dynamic properties.
*
* The payload may include dynamic properties.
* <p>
* Note that isMapSchema returns true for a composed schema (allOf, anyOf, oneOf) that also defines
* additionalproperties.
*
* <p>
* For example, an OpenAPI schema is considered a MapSchema in the following scenarios:
* <p>
*
* type: object
* additionalProperties: true
@@ -772,14 +774,14 @@ public class ModelUtils {
/**
* Check to see if the schema is a free form object.
*
* <p>
* A free form object is an object (i.e. 'type: object' in a OAS document) that:
* 1) Does not define properties, and
* 2) Is not a composed schema (no anyOf, oneOf, allOf), and
* 3) additionalproperties is not defined, or additionalproperties: true, or additionalproperties: {}.
*
* <p>
* Examples:
*
* <p>
* components:
* schemas:
* arbitraryObject:
@@ -798,7 +800,7 @@ public class ModelUtils {
* The value can be any type except the 'null' value.
*
* @param openAPI the object that encapsulates the OAS document.
* @param schema potentially containing a '$ref'
* @param schema potentially containing a '$ref'
* @return true if it's a free-form object
*/
public static boolean isFreeFormObject(OpenAPI openAPI, Schema schema) {
@@ -1054,10 +1056,10 @@ public class ModelUtils {
/**
* Return the first Schema from a specified OAS 'content' section.
*
* <p>
* For example, given the following OAS, this method returns the schema
* for the 'application/json' content type because it is listed first in the OAS.
*
* <p>
* responses:
* '200':
* content:
@@ -1099,8 +1101,8 @@ public class ModelUtils {
/**
* Has self reference?
*
* @param openAPI OpenAPI spec.
* @param schema Schema
* @param openAPI OpenAPI spec.
* @param schema Schema
* @param visitedSchemaNames A set of visited schema names
* @return boolean true if it has at least one self reference
*/
@@ -1257,7 +1259,7 @@ public class ModelUtils {
/**
* Returns the additionalProperties Schema for the specified input schema.
*
* <p>
* The additionalProperties keyword is used to control the handling of additional, undeclared
* properties, that is, properties whose names are not listed in the properties keyword.
* The additionalProperties keyword may be either a boolean or an object.
@@ -1267,9 +1269,9 @@ public class ModelUtils {
* to the boolean value True or setting additionalProperties: {}
*
* @param openAPI the object that encapsulates the OAS document.
* @param schema the input schema that may or may not have the additionalProperties keyword.
* @param schema the input schema that may or may not have the additionalProperties keyword.
* @return the Schema of the additionalProperties. The null value is returned if no additional
* properties are allowed.
* properties are allowed.
*/
public static Schema getAdditionalProperties(OpenAPI openAPI, Schema schema) {
Object addProps = schema.getAdditionalProperties();
@@ -1380,10 +1382,10 @@ public class ModelUtils {
* that specify a determinator.
* If there are multiple elements in the composed schema and it is not clear
* which one should be the parent, return null.
*
* <p>
* For example, given the following OAS spec, the parent of 'Dog' is Animal
* because 'Animal' specifies a discriminator.
*
* <p>
* animal:
* type: object
* discriminator:
@@ -1391,6 +1393,7 @@ public class ModelUtils {
* properties:
* type: string
*
* <p>
* dog:
* allOf:
* - $ref: '#/components/schemas/animal'
@@ -1418,10 +1421,10 @@ public class ModelUtils {
LOGGER.error("Failed to obtain schema from {}", parentName);
return "UNKNOWN_PARENT_NAME";
} else if (hasOrInheritsDiscriminator(s, allSchemas)) {
// discriminator.propertyName is used
// discriminator.propertyName is used or x-parent is used
return parentName;
} else {
// not a parent since discriminator.propertyName is not set
// not a parent since discriminator.propertyName or x-parent is not set
hasAmbiguousParents = true;
refedWithoutDiscriminator.add(parentName);
}
@@ -1476,7 +1479,7 @@ public class ModelUtils {
LOGGER.error("Failed to obtain schema from {}", parentName);
names.add("UNKNOWN_PARENT_NAME");
} else if (hasOrInheritsDiscriminator(s, allSchemas)) {
// discriminator.propertyName is used
// discriminator.propertyName is used or x-parent is used
names.add(parentName);
if (includeAncestors && s instanceof ComposedSchema) {
names.addAll(getAllParentsName((ComposedSchema) s, allSchemas, true));
@@ -1501,7 +1504,8 @@ public class ModelUtils {
}
private static boolean hasOrInheritsDiscriminator(Schema schema, Map<String, Schema> allSchemas) {
if (schema.getDiscriminator() != null && StringUtils.isNotEmpty(schema.getDiscriminator().getPropertyName())) {
if ((schema.getDiscriminator() != null && StringUtils.isNotEmpty(schema.getDiscriminator().getPropertyName()))
|| (isExtensionParent(schema))) { // x-parent is used
return true;
} else if (StringUtils.isNotEmpty(schema.get$ref())) {
String parentName = getSimpleRef(schema.get$ref());
@@ -1523,18 +1527,43 @@ public class ModelUtils {
return false;
}
/**
* If it's a boolean, returns the value of the extension `x-parent`.
* If it's string, return true if it's non-empty.
* If the return value is `true`, the schema is a parent.
*
* @param schema Schema
* @return boolean
*/
public static boolean isExtensionParent(Schema schema) {
if (schema.getExtensions() == null) {
return false;
} else {
Object xParent = schema.getExtensions().get("x-parent");
if (xParent == null) {
return false;
} else if (xParent instanceof Boolean) {
return (Boolean) xParent;
} else if (xParent instanceof String) {
return StringUtils.isNotEmpty((String) xParent);
} else {
return false;
}
}
}
/**
* Return true if the 'nullable' attribute is set to true in the schema, i.e. if the value
* of the property can be the null value.
*
* <p>
* In addition, if the OAS document is 3.1 or above, isNullable returns true if the input
* schema is a 'oneOf' composed document with at most two children, and one of the children
* is the 'null' type.
*
* <p>
* The caller is responsible for resolving schema references before invoking isNullable.
* If the input schema is a $ref and the referenced schema has 'nullable: true', this method
* returns false (because the nullable attribute is defined in the referenced schema).
*
* <p>
* The 'nullable' attribute was introduced in OAS 3.0.
* The 'nullable' attribute is deprecated in OAS 3.1. In a OAS 3.1 document, the preferred way
* to specify nullable properties is to use the 'null' type.
@@ -1564,11 +1593,11 @@ public class ModelUtils {
/**
* Return true if the specified composed schema is 'oneOf', contains one or two elements,
* and at least one of the elements is the 'null' type.
*
* <p>
* The 'null' type is supported in OAS 3.1 and above.
* In the example below, the 'OptionalOrder' can have the null value because the 'null'
* type is one of the elements under 'oneOf'.
*
* <p>
* OptionalOrder:
* oneOf:
* - type: 'null'
@@ -1591,13 +1620,13 @@ public class ModelUtils {
/**
* isNullType returns true if the input schema is the 'null' type.
*
* <p>
* The 'null' type is supported in OAS 3.1 and above. It is not supported
* in OAS 2.0 and OAS 3.0.x.
*
* <p>
* For example, the "null" type could be used to specify that a value must
* either be null or a specified type:
*
* <p>
* OptionalOrder:
* oneOf:
* - type: 'null'
@@ -1617,6 +1646,7 @@ public class ModelUtils {
* For when a type is not defined on a schema
* Note: properties, additionalProperties, enums, validations, items, and composed schemas (oneOf/anyOf/allOf)
* can be defined or omitted on these any type schemas
*
* @param schema the schema that we are checking
* @return boolean
*/
@@ -1713,7 +1743,7 @@ public class ModelUtils {
private static ObjectMapper getRightMapper(String data) {
ObjectMapper mapper;
if (data.trim().startsWith("{")) {
if (data.trim().startsWith("{")) {
mapper = JSON_MAPPER;
} else {
mapper = YAML_MAPPER;
@@ -1725,11 +1755,9 @@ public class ModelUtils {
* Parse and return a JsonNode representation of the input OAS document.
*
* @param location the URL of the OAS document.
* @param auths the list of authorization values to access the remote URL.
*
* @throws java.lang.Exception if an error occurs while retrieving the OpenAPI document.
*
* @param auths the list of authorization values to access the remote URL.
* @return A JsonNode representation of the input OAS document.
* @throws java.lang.Exception if an error occurs while retrieving the OpenAPI document.
*/
public static JsonNode readWithInfo(String location, List<AuthorizationValue> auths) throws Exception {
String data;
@@ -1756,14 +1784,13 @@ public class ModelUtils {
/**
* Parse the OAS document at the specified location, get the swagger or openapi version
* as specified in the source document, and return the version.
*
* <p>
* For OAS 2.0 documents, return the value of the 'swagger' attribute.
* For OAS 3.x documents, return the value of the 'openapi' attribute.
*
* @param openAPI the object that encapsulates the OAS document.
* @param openAPI the object that encapsulates the OAS document.
* @param location the URL of the OAS document.
* @param auths the list of authorization values to access the remote URL.
*
* @param auths the list of authorization values to access the remote URL.
* @return the version of the OpenAPI document.
*/
public static SemVer getOpenApiVersion(OpenAPI openAPI, String location, List<AuthorizationValue> auths) {

View File

@@ -635,7 +635,7 @@ fail:
{{^isEnum}}
{{#isString}}
{{^required}}if ({{{name}}}) { {{/required}}
if(!cJSON_IsString({{{name}}}))
if(!cJSON_IsString({{{name}}}){{^required}} && !cJSON_IsNull({{{name}}}){{/required}})
{
goto end; //String
}
@@ -880,7 +880,7 @@ fail:
{{/isEnum}}
{{^isEnum}}
{{#isString}}
{{^required}}{{{name}}} ? {{/required}}strdup({{{name}}}->valuestring){{^required}} : NULL{{/required}}{{^-last}},{{/-last}}
{{^required}}{{{name}}} && !cJSON_IsNull({{{name}}}) ? {{/required}}strdup({{{name}}}->valuestring){{^required}} : NULL{{/required}}{{^-last}},{{/-last}}
{{/isString}}
{{/isEnum}}
{{#isByteArray}}

View File

@@ -21,9 +21,9 @@ import com.sun.jersey.api.client.WebResource.Builder;
import com.sun.jersey.multipart.FormDataMultiPart;
import com.sun.jersey.multipart.file.FileDataBodyPart;
import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.Response.Status.Family;
import javax.ws.rs.core.MediaType;
import {{javaxPackage}}.ws.rs.core.Cookie;
import {{javaxPackage}}.ws.rs.core.Response.Status.Family;
import {{javaxPackage}}.ws.rs.core.MediaType;
import java.util.Collection;
import java.util.Collections;

View File

@@ -2,8 +2,8 @@ package {{invokerPackage}};
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.ValidationException;
import {{javaxPackage}}.validation.ConstraintViolation;
import {{javaxPackage}}.validation.ValidationException;
public class BeanValidationException extends ValidationException {
/**

View File

@@ -1 +1 @@
@javax.annotation.Generated(value = "{{generatorClass}}"{{^hideGenerationTimestamp}}, date = "{{generatedDate}}"{{/hideGenerationTimestamp}})
@{{javaxPackage}}.annotation.Generated(value = "{{generatorClass}}"{{^hideGenerationTimestamp}}, date = "{{generatedDate}}"{{/hideGenerationTimestamp}})

View File

@@ -343,7 +343,12 @@
{{#openApiNullable}}
<jackson-databind-nullable-version>0.2.4</jackson-databind-nullable-version>
{{/openApiNullable}}
{{#useJakartaEe}}
<jakarta-annotation-version>2.1.1</jakarta-annotation-version>
{{/useJakartaEe}}
{{^useJakartaEe}}
<jakarta-annotation-version>1.3.5</jakarta-annotation-version>
{{/useJakartaEe}}
{{#useBeanValidation}}
<beanvalidation-version>3.0.2</beanvalidation-version>
{{/useBeanValidation}}

View File

@@ -386,7 +386,12 @@
<jackson-databind-nullable-version>0.2.4</jackson-databind-nullable-version>
{{/openApiNullable}}
<jackson-databind-version>2.13.4.2</jackson-databind-version>
{{#useJakartaEe}}
<jakarta-annotation-version>2.1.1</jakarta-annotation-version>
{{/useJakartaEe}}
{{^useJakartaEe}}
<jakarta-annotation-version>1.3.5</jakarta-annotation-version>
{{/useJakartaEe}}
<junit-version>5.7.0</junit-version>
<maven-plugin-version>1.0.0</maven-plugin-version>
<scribejava-version>8.0.0</scribejava-version>

View File

@@ -14,7 +14,7 @@ import com.google.api.client.http.HttpMethods;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.json.Json;
import javax.ws.rs.core.UriBuilder;
import {{javaxPackage}}.ws.rs.core.UriBuilder;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;

View File

@@ -307,7 +307,12 @@
{{#joda}}
<jodatime-version>2.9.9</jodatime-version>
{{/joda}}
{{#useJakartaEe}}
<jakarta-annotation-version>2.1.1</jakarta-annotation-version>
{{/useJakartaEe}}
{{^useJakartaEe}}
<jakarta-annotation-version>1.3.5</jakarta-annotation-version>
{{/useJakartaEe}}
<maven-plugin-version>1.0.0</maven-plugin-version>
<junit-version>4.13.2</junit-version>
</properties>

View File

@@ -6,7 +6,7 @@ import {{invokerPackage}}.ApiException;
import java.util.Objects;
import java.lang.reflect.Type;
import java.util.Map;
import javax.ws.rs.core.GenericType;
import {{javaxPackage}}.ws.rs.core.GenericType;
import com.fasterxml.jackson.annotation.JsonValue;

View File

@@ -1,15 +1,15 @@
package {{invokerPackage}};
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import {{javaxPackage}}.ws.rs.client.Client;
import {{javaxPackage}}.ws.rs.client.ClientBuilder;
import {{javaxPackage}}.ws.rs.client.Entity;
import {{javaxPackage}}.ws.rs.client.Invocation;
import {{javaxPackage}}.ws.rs.client.WebTarget;
import {{javaxPackage}}.ws.rs.core.Form;
import {{javaxPackage}}.ws.rs.core.GenericType;
import {{javaxPackage}}.ws.rs.core.MediaType;
import {{javaxPackage}}.ws.rs.core.Response;
import {{javaxPackage}}.ws.rs.core.Response.Status;
{{#hasOAuthMethods}}
import com.github.scribejava.core.model.OAuth2AccessToken;
@@ -251,7 +251,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
/**
* <p>Getter for the field <code>httpClient</code>.</p>
*
* @return a {@link javax.ws.rs.client.Client} object.
* @return a {@link {{javaxPackage}}.ws.rs.client.Client} object.
*/
public Client getHttpClient() {
return httpClient;
@@ -260,7 +260,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
/**
* <p>Setter for the field <code>httpClient</code>.</p>
*
* @param httpClient a {@link javax.ws.rs.client.Client} object.
* @param httpClient a {@link {{javaxPackage}}.ws.rs.client.Client} object.
* @return a {@link org.openapitools.client.ApiClient} object.
*/
public ApiClient setHttpClient(Client httpClient) {
@@ -1098,7 +1098,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
/**
* <p>Prepare the file for download from the response.</p>
*
* @param response a {@link javax.ws.rs.core.Response} object.
* @param response a {@link {{javaxPackage}}.ws.rs.core.Response} object.
* @return a {@link java.io.File} object.
* @throws java.io.IOException if any.
*/
@@ -1387,7 +1387,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* To completely disable certificate validation (at your own risk), you can
* override this method and invoke disableCertificateValidation(clientBuilder).
*
* @param clientBuilder a {@link javax.ws.rs.client.ClientBuilder} object.
* @param clientBuilder a {@link {{javaxPackage}}.ws.rs.client.ClientBuilder} object.
*/
protected void customizeClientBuilder(ClientBuilder clientBuilder) {
// No-op extension point
@@ -1399,7 +1399,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* Please note that trusting all certificates is extremely risky.
* This may be useful in a development environment with self-signed certificates.
*
* @param clientBuilder a {@link javax.ws.rs.client.ClientBuilder} object.
* @param clientBuilder a {@link {{javaxPackage}}.ws.rs.client.ClientBuilder} object.
* @throws java.security.KeyManagementException if any.
* @throws java.security.NoSuchAlgorithmException if any.
*/
@@ -1426,7 +1426,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
/**
* <p>Build the response headers.</p>
*
* @param response a {@link javax.ws.rs.core.Response} object.
* @param response a {@link {{javaxPackage}}.ws.rs.core.Response} object.
* @return a {@link java.util.Map} of response headers.
*/
protected Map<String, List<String>> buildResponseHeaders(Response response) {

View File

@@ -19,8 +19,8 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.ext.ContextResolver;
import {{javaxPackage}}.ws.rs.core.GenericType;
import {{javaxPackage}}.ws.rs.ext.ContextResolver;
{{>generatedAnnotation}}
public class JSON implements ContextResolver<ObjectMapper> {

View File

@@ -1,5 +1,5 @@
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.Response;
import {{javaxPackage}}.ws.rs.core.GenericType;
import {{javaxPackage}}.ws.rs.core.Response;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

View File

@@ -6,7 +6,7 @@ import {{invokerPackage}}.ApiResponse;
import {{invokerPackage}}.Configuration;
import {{invokerPackage}}.Pair;
import javax.ws.rs.core.GenericType;
import {{javaxPackage}}.ws.rs.core.GenericType;
{{#imports}}import {{import}};
{{/imports}}

View File

@@ -10,7 +10,7 @@ import com.github.scribejava.core.exceptions.OAuthException;
import com.github.scribejava.core.model.OAuth2AccessToken;
import com.github.scribejava.core.oauth.OAuth20Service;
import javax.ws.rs.core.UriBuilder;
import {{javaxPackage}}.ws.rs.core.UriBuilder;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;

View File

@@ -36,15 +36,15 @@ import com.fasterxml.jackson.annotation.JsonCreator;
{{/vendorExtensions.x-has-readonly-properties}}
{{/jackson}}
{{#withXml}}
import javax.xml.bind.annotation.*;
import {{javaxPackage}}.xml.bind.annotation.*;
{{/withXml}}
{{#parcelableModel}}
import android.os.Parcelable;
import android.os.Parcel;
{{/parcelableModel}}
{{#useBeanValidation}}
import javax.validation.constraints.*;
import javax.validation.Valid;
import {{javaxPackage}}.validation.constraints.*;
import {{javaxPackage}}.validation.Valid;
{{/useBeanValidation}}
{{#performBeanValidation}}
import org.hibernate.validator.constraints.*;

View File

@@ -1,5 +1,5 @@
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.Response;
import {{javaxPackage}}.ws.rs.core.GenericType;
import {{javaxPackage}}.ws.rs.core.Response;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

View File

@@ -206,14 +206,14 @@ public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtens
{{/deprecated}}
{{#required}}
{{#isNullable}}
@javax.annotation.Nullable
@{{javaxPackage}}.annotation.Nullable
{{/isNullable}}
{{^isNullable}}
@javax.annotation.Nonnull
@{{javaxPackage}}.annotation.Nonnull
{{/isNullable}}
{{/required}}
{{^required}}
@javax.annotation.Nullable
@{{javaxPackage}}.annotation.Nullable
{{/required}}
{{#useBeanValidation}}
{{>beanValidation}}

View File

@@ -387,7 +387,12 @@
<jackson-version>2.13.4</jackson-version>
<jackson-databind-version>2.13.4.2</jackson-databind-version>
<jackson-databind-nullable-version>0.2.4</jackson-databind-nullable-version>
{{#useJakartaEe}}
<jakarta-annotation-version>2.1.1</jakarta-annotation-version>
{{/useJakartaEe}}
{{^useJakartaEe}}
<jakarta-annotation-version>1.3.5</jakarta-annotation-version>
{{/useJakartaEe}}
{{#useBeanValidation}}
<beanvalidation-version>2.0.2</beanvalidation-version>
{{/useBeanValidation}}

View File

@@ -6,7 +6,7 @@ import {{invokerPackage}}.ApiException;
import java.util.Objects;
import java.lang.reflect.Type;
import java.util.Map;
import jakarta.ws.rs.core.GenericType;
import {{javaxPackage}}.ws.rs.core.GenericType;
import com.fasterxml.jackson.annotation.JsonValue;

View File

@@ -1,15 +1,15 @@
package {{invokerPackage}};
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.Entity;
import jakarta.ws.rs.client.Invocation;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.Form;
import jakarta.ws.rs.core.GenericType;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
import {{javaxPackage}}.ws.rs.client.Client;
import {{javaxPackage}}.ws.rs.client.ClientBuilder;
import {{javaxPackage}}.ws.rs.client.Entity;
import {{javaxPackage}}.ws.rs.client.Invocation;
import {{javaxPackage}}.ws.rs.client.WebTarget;
import {{javaxPackage}}.ws.rs.core.Form;
import {{javaxPackage}}.ws.rs.core.GenericType;
import {{javaxPackage}}.ws.rs.core.MediaType;
import {{javaxPackage}}.ws.rs.core.Response;
import {{javaxPackage}}.ws.rs.core.Response.Status;
{{#hasOAuthMethods}}
import com.github.scribejava.core.model.OAuth2AccessToken;
@@ -251,7 +251,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
/**
* <p>Getter for the field <code>httpClient</code>.</p>
*
* @return a {@link jakarta.ws.rs.client.Client} object.
* @return a {@link {{javaxPackage}}.ws.rs.client.Client} object.
*/
public Client getHttpClient() {
return httpClient;
@@ -260,7 +260,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
/**
* <p>Setter for the field <code>httpClient</code>.</p>
*
* @param httpClient a {@link jakarta.ws.rs.client.Client} object.
* @param httpClient a {@link {{javaxPackage}}.ws.rs.client.Client} object.
* @return a {@link org.openapitools.client.ApiClient} object.
*/
public ApiClient setHttpClient(Client httpClient) {
@@ -1098,7 +1098,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
/**
* <p>Prepare the file for download from the response.</p>
*
* @param response a {@link jakarta.ws.rs.core.Response} object.
* @param response a {@link {{javaxPackage}}.ws.rs.core.Response} object.
* @return a {@link java.io.File} object.
* @throws java.io.IOException if any.
*/
@@ -1234,7 +1234,12 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
queryParams,
allHeaderParams,
cookieParams,
{{#hasHttpSignatureMethods}}
serializeToString(body, formParams, contentType, isBodyNullable),
{{/hasHttpSignatureMethods}}
{{^hasHttpSignatureMethods}}
null,
{{/hasHttpSignatureMethods}}
method,
target.getUri());
@@ -1382,7 +1387,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* To completely disable certificate validation (at your own risk), you can
* override this method and invoke disableCertificateValidation(clientBuilder).
*
* @param clientBuilder a {@link jakarta.ws.rs.client.ClientBuilder} object.
* @param clientBuilder a {@link {{javaxPackage}}.ws.rs.client.ClientBuilder} object.
*/
protected void customizeClientBuilder(ClientBuilder clientBuilder) {
// No-op extension point
@@ -1394,7 +1399,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* Please note that trusting all certificates is extremely risky.
* This may be useful in a development environment with self-signed certificates.
*
* @param clientBuilder a {@link jakarta.ws.rs.client.ClientBuilder} object.
* @param clientBuilder a {@link {{javaxPackage}}.ws.rs.client.ClientBuilder} object.
* @throws java.security.KeyManagementException if any.
* @throws java.security.NoSuchAlgorithmException if any.
*/
@@ -1421,7 +1426,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
/**
* <p>Build the response headers.</p>
*
* @param response a {@link jakarta.ws.rs.core.Response} object.
* @param response a {@link {{javaxPackage}}.ws.rs.core.Response} object.
* @return a {@link java.util.Map} of response headers.
*/
protected Map<String, List<String>> buildResponseHeaders(Response response) {

View File

@@ -19,8 +19,8 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import jakarta.ws.rs.core.GenericType;
import jakarta.ws.rs.ext.ContextResolver;
import {{javaxPackage}}.ws.rs.core.GenericType;
import {{javaxPackage}}.ws.rs.ext.ContextResolver;
{{>generatedAnnotation}}
public class JSON implements ContextResolver<ObjectMapper> {

View File

@@ -1,5 +1,5 @@
import jakarta.ws.rs.core.GenericType;
import jakarta.ws.rs.core.Response;
import {{javaxPackage}}.ws.rs.core.GenericType;
import {{javaxPackage}}.ws.rs.core.Response;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

View File

@@ -6,7 +6,7 @@ import {{invokerPackage}}.ApiResponse;
import {{invokerPackage}}.Configuration;
import {{invokerPackage}}.Pair;
import jakarta.ws.rs.core.GenericType;
import {{javaxPackage}}.ws.rs.core.GenericType;
{{#imports}}import {{import}};
{{/imports}}

View File

@@ -10,7 +10,7 @@ import com.github.scribejava.core.exceptions.OAuthException;
import com.github.scribejava.core.model.OAuth2AccessToken;
import com.github.scribejava.core.oauth.OAuth20Service;
import jakarta.ws.rs.core.UriBuilder;
import {{javaxPackage}}.ws.rs.core.UriBuilder;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;

View File

@@ -1 +1 @@
@jakarta.annotation.Generated(value = "{{generatorClass}}"{{^hideGenerationTimestamp}}, date = "{{generatedDate}}"{{/hideGenerationTimestamp}})
@{{javaxPackage}}.annotation.Generated(value = "{{generatorClass}}"{{^hideGenerationTimestamp}}, date = "{{generatedDate}}"{{/hideGenerationTimestamp}})

View File

@@ -36,15 +36,15 @@ import com.fasterxml.jackson.annotation.JsonCreator;
{{/vendorExtensions.x-has-readonly-properties}}
{{/jackson}}
{{#withXml}}
import javax.xml.bind.annotation.*;
import {{javaxPackage}}.xml.bind.annotation.*;
{{/withXml}}
{{#parcelableModel}}
import android.os.Parcelable;
import android.os.Parcel;
{{/parcelableModel}}
{{#useBeanValidation}}
import javax.validation.constraints.*;
import javax.validation.Valid;
import {{javaxPackage}}.validation.constraints.*;
import {{javaxPackage}}.validation.Valid;
{{/useBeanValidation}}
{{#performBeanValidation}}
import org.hibernate.validator.constraints.*;

View File

@@ -1,5 +1,5 @@
import jakarta.ws.rs.core.GenericType;
import jakarta.ws.rs.core.Response;
import {{javaxPackage}}.ws.rs.core.GenericType;
import {{javaxPackage}}.ws.rs.core.Response;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

View File

@@ -206,14 +206,14 @@ public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtens
{{/deprecated}}
{{#required}}
{{#isNullable}}
@jakarta.annotation.Nullable
@{{javaxPackage}}.annotation.Nullable
{{/isNullable}}
{{^isNullable}}
@jakarta.annotation.Nonnull
@{{javaxPackage}}.annotation.Nonnull
{{/isNullable}}
{{/required}}
{{^required}}
@jakarta.annotation.Nullable
@{{javaxPackage}}.annotation.Nullable
{{/required}}
{{#useBeanValidation}}
{{>beanValidation}}

View File

@@ -17,8 +17,8 @@ import org.apache.cxf.jaxrs.ext.multipart.*;
{{/disableMultipart}}
{{#useBeanValidation}}
import javax.validation.constraints.*;
import javax.validation.Valid;
import {{javaxPackage}}.validation.constraints.*;
import {{javaxPackage}}.validation.Valid;
{{/useBeanValidation}}
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;

View File

@@ -338,21 +338,24 @@ public class {{classname}} {
{{#hasQueryParams}}
{{javaUtilPrefix}}List<Pair> localVarQueryParams = new {{javaUtilPrefix}}ArrayList<>();
StringJoiner localVarQueryDeepObjectStringJoiner = new StringJoiner("&");
String localVarQueryParameterBaseName;
{{#queryParams}}
localVarQueryParameterBaseName = "{{{baseName}}}";
{{#collectionFormat}}
localVarQueryParams.addAll(ApiClient.parameterToPairs("{{{collectionFormat}}}", "{{baseName}}", {{paramName}}));
{{/collectionFormat}}
{{^collectionFormat}}
{{#isDeepObject}}
if ({{paramName}} != null) {
{{#items.vars}}
{{#isArray}}
localVarQueryParams.addAll(ApiClient.parameterToPairs("csv", "{{paramName}}[{{name}}]", {{paramName}}.{{getter}}()));
{{/isArray}}
{{^isArray}}
localVarQueryParams.addAll(ApiClient.parameterToPairs("{{paramName}}[{{name}}]", {{paramName}}.{{getter}}()));
{{/isArray}}
{{/items.vars}}
{{#isArray}}
for (int i=0; i < {{paramName}}.size(); i++) {
localVarQueryDeepObjectStringJoiner.add({{paramName}}.get(i).toUrlQueryString(String.format("{{baseName}}[%d]", i)));
}
{{/isArray}}
{{^isArray}}
localVarQueryDeepObjectStringJoiner.add({{paramName}}.toUrlQueryString("{{baseName}}"));
{{/isArray}}
}
{{/isDeepObject}}
{{^isDeepObject}}
@@ -378,9 +381,12 @@ public class {{classname}} {
{{/collectionFormat}}
{{/queryParams}}
if (!localVarQueryParams.isEmpty()) {
if (!localVarQueryParams.isEmpty() || localVarQueryDeepObjectStringJoiner.length() != 0) {
{{javaUtilPrefix}}StringJoiner queryJoiner = new {{javaUtilPrefix}}StringJoiner("&");
localVarQueryParams.forEach(p -> queryJoiner.add(p.getName() + '=' + p.getValue()));
if (localVarQueryDeepObjectStringJoiner.length() != 0) {
queryJoiner.add(localVarQueryDeepObjectStringJoiner.toString());
}
localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath + '?' + queryJoiner.toString()));
} else {
localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath));

View File

@@ -1 +1 @@
@javax.annotation.processing.Generated(value = "{{generatorClass}}"{{^hideGenerationTimestamp}}, date = "{{generatedDate}}"{{/hideGenerationTimestamp}})
@{{javaxPackage}}.annotation.Generated(value = "{{generatorClass}}"{{^hideGenerationTimestamp}}, date = "{{generatedDate}}"{{/hideGenerationTimestamp}})

View File

@@ -16,10 +16,13 @@ import com.fasterxml.jackson.annotation.JsonAnySetter;
{{/additionalPropertiesType}}
{{/model}}
{{/models}}
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
import java.util.Arrays;
import java.util.Map;
import java.util.HashMap;
import java.util.StringJoiner;
{{#imports}}
import {{import}};
{{/imports}}
@@ -36,15 +39,15 @@ import com.fasterxml.jackson.annotation.JsonCreator;
{{/vendorExtensions.x-has-readonly-properties}}
{{/jackson}}
{{#withXml}}
import javax.xml.bind.annotation.*;
import {{javaxPackage}}.xml.bind.annotation.*;
{{/withXml}}
{{#parcelableModel}}
import android.os.Parcelable;
import android.os.Parcel;
{{/parcelableModel}}
{{#useBeanValidation}}
import javax.validation.constraints.*;
import javax.validation.Valid;
import {{javaxPackage}}.validation.constraints.*;
import {{javaxPackage}}.validation.Valid;
{{/useBeanValidation}}
{{#performBeanValidation}}
import org.hibernate.validator.constraints.*;

View File

@@ -0,0 +1,115 @@
{{#jackson}}
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
{{/jackson}}
{{#gson}}
import java.io.IOException;
import com.google.gson.TypeAdapter;
import com.google.gson.annotations.JsonAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
{{/gson}}
/**
* {{description}}{{^description}}Gets or Sets {{{name}}}{{/description}}
*/
{{#gson}}
@JsonAdapter({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.Adapter.class)
{{/gson}}
{{#jsonb}}
@JsonbTypeSerializer({{datatypeWithEnum}}.Serializer.class)
@JsonbTypeDeserializer({{datatypeWithEnum}}.Deserializer.class)
{{/jsonb}}
{{>additionalEnumTypeAnnotations}}public enum {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} {
{{#allowableValues}}{{#enumVars}}
{{#enumDescription}}
/**
* {{.}}
*/
{{/enumDescription}}
{{#withXml}}
@XmlEnumValue({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}})
{{/withXml}}
{{{name}}}({{{value}}}){{^-last}},
{{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}}
private {{{dataType}}} value;
{{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) {
this.value = value;
}
{{#jackson}}
@JsonValue
{{/jackson}}
public {{{dataType}}} getValue() {
return value;
}
@Override
public String toString() {
return String.valueOf(value);
}
{{#jackson}}
@JsonCreator
{{/jackson}}
public static {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue({{{dataType}}} value) {
for ({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) {
if (b.value.equals(value)) {
return b;
}
}
{{#isNullable}}return null;{{/isNullable}}{{^isNullable}}{{#enumUnknownDefaultCase}}{{#allowableValues}}{{#enumVars}}{{#-last}}return {{{name}}};{{/-last}}{{/enumVars}}{{/allowableValues}}{{/enumUnknownDefaultCase}}{{^enumUnknownDefaultCase}}throw new IllegalArgumentException("Unexpected value '" + value + "'");{{/enumUnknownDefaultCase}}{{/isNullable}}
}
/**
* Convert the instance into URL query string.
*
* @param prefix prefix of the query string
* @return URL query string
*/
public String toUrlQueryString(String prefix) {
if (prefix == null) {
prefix = "";
}
return String.format("%s=%s", prefix, this.toString());
}
{{#gson}}
public static class Adapter extends TypeAdapter<{{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}> {
@Override
public void write(final JsonWriter jsonWriter, final {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} enumeration) throws IOException {
jsonWriter.value(enumeration.getValue());
}
@Override
public {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException {
{{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{^isNumber}}{{^isInteger}}next{{{dataType}}}(){{/isInteger}}{{/isNumber}};
return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
}
}
{{/gson}}
{{#jsonb}}
public static final class Deserializer implements JsonbDeserializer<{{datatypeWithEnum}}> {
@Override
public {{datatypeWithEnum}} deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) {
for ({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) {
if (String.valueOf(b.value).equals(parser.getString())) {
return b;
}
}
{{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + parser.getString() + "'");{{/useNullForUnknownEnumValue}}
}
}
public static final class Serializer implements JsonbSerializer<{{datatypeWithEnum}}> {
@Override
public void serialize({{datatypeWithEnum}} obj, JsonGenerator generator, SerializationContext ctx) {
generator.write(obj.value);
}
}
{{/jsonb}}
}

View File

@@ -206,14 +206,14 @@ public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtens
{{/deprecated}}
{{#required}}
{{#isNullable}}
@javax.annotation.Nullable
@{{javaxPackage}}.annotation.Nullable
{{/isNullable}}
{{^isNullable}}
@javax.annotation.Nonnull
@{{javaxPackage}}.annotation.Nonnull
{{/isNullable}}
{{/required}}
{{^required}}
@javax.annotation.Nullable
@{{javaxPackage}}.annotation.Nullable
{{/required}}
{{#useBeanValidation}}
{{>beanValidation}}
@@ -349,6 +349,131 @@ public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtens
return o.toString().replace("\n", "\n ");
}
/**
* Convert the instance into URL query string.
*
* @param prefix prefix of the query string
* @return URL query string
*/
public String toUrlQueryString(String prefix) {
if (prefix == null) {
prefix = "";
}
StringJoiner joiner = new StringJoiner("&");
{{#allVars}}
// add `{{baseName}}` to the URL query string
{{#isArray}}
{{#items.isPrimitiveType}}
{{#uniqueItems}}
if ({{getter}}() != null) {
int i = 0;
for ({{items.dataType}} _item : {{getter}}()) {
joiner.add(String.format("%s[{{baseName}}][%d]=%s", prefix, i, URLEncoder.encode(String.valueOf(_item), StandardCharsets.UTF_8).replaceAll("\\+", "%20")));
}
i++;
}
{{/uniqueItems}}
{{^uniqueItems}}
if ({{getter}}() != null) {
for (int i = 0; i < {{getter}}().size(); i++) {
joiner.add(String.format("%s[{{baseName}}][%d]=%s", prefix, i, URLEncoder.encode(String.valueOf({{getter}}().get(i)), StandardCharsets.UTF_8).replaceAll("\\+", "%20")));
}
}
{{/uniqueItems}}
{{/items.isPrimitiveType}}
{{^items.isPrimitiveType}}
{{#items.isModel}}
{{#uniqueItems}}
if ({{getter}}() != null) {
int i = 0;
for ({{items.dataType}} _item : {{getter}}()) {
if ({{getter}}().get(i) != null) {
joiner.add(_item.toUrlQueryString(String.format("%s[{{baseName}}][%d]", prefix, i)));
}
}
i++;
}
{{/uniqueItems}}
{{^uniqueItems}}
if ({{getter}}() != null) {
for (int i = 0; i < {{getter}}().size(); i++) {
if ({{getter}}().get(i) != null) {
joiner.add({{getter}}().get(i).toUrlQueryString(String.format("%s[{{baseName}}][%d]", prefix, i)));
}
}
}
{{/uniqueItems}}
{{/items.isModel}}
{{^items.isModel}}
{{#uniqueItems}}
if ({{getter}}() != null) {
int i = 0;
for ({{items.dataType}} _item : {{getter}}()) {
if (_item != null) {
joiner.add(String.format("%s[{{baseName}}][%d]=%s", prefix, i, URLEncoder.encode(String.valueOf(_item), StandardCharsets.UTF_8).replaceAll("\\+", "%20")));
}
i++;
}
}
{{/uniqueItems}}
{{^uniqueItems}}
if ({{getter}}() != null) {
for (int i = 0; i < {{getter}}().size(); i++) {
if ({{getter}}().get(i) != null) {
joiner.add(String.format("%s[{{baseName}}][%d]=%s", prefix, i, URLEncoder.encode(String.valueOf({{getter}}().get(i)), StandardCharsets.UTF_8).replaceAll("\\+", "%20")));
}
}
}
{{/uniqueItems}}
{{/items.isModel}}
{{/items.isPrimitiveType}}
{{/isArray}}
{{^isArray}}
{{#isMap}}
{{#items.isPrimitiveType}}
if ({{getter}}() != null) {
for (String _key : {{getter}}().keySet()) {
joiner.add(String.format("%s[{{baseName}}][%s]=%s", prefix, {{getter}}().get(_key), URLEncoder.encode(String.valueOf({{getter}}().get(_key)), StandardCharsets.UTF_8).replaceAll("\\+", "%20")));
}
}
{{/items.isPrimitiveType}}
{{^items.isPrimitiveType}}
if ({{getter}}() != null) {
for (String _key : {{getter}}().keySet()) {
if ({{getter}}().get(_key) != null) {
joiner.add({{getter}}().get(_key).toUrlQueryString(String.format("%s[{{baseName}}][%s]", prefix, _key)));
}
}
}
{{/items.isPrimitiveType}}
{{/isMap}}
{{^isMap}}
{{#isPrimitiveType}}
if ({{getter}}() != null) {
joiner.add(String.format("%s[{{{baseName}}}]=%s", prefix, URLEncoder.encode(String.valueOf({{{getter}}}()), StandardCharsets.UTF_8).replaceAll("\\+", "%20")));
}
{{/isPrimitiveType}}
{{^isPrimitiveType}}
{{#isModel}}
if ({{getter}}() != null) {
joiner.add({{getter}}().toUrlQueryString(prefix + "[{{{baseName}}}]"));
}
{{/isModel}}
{{^isModel}}
if ({{getter}}() != null) {
joiner.add(String.format("%s[{{{baseName}}}]=%s", prefix, URLEncoder.encode(String.valueOf({{{getter}}}()), StandardCharsets.UTF_8).replaceAll("\\+", "%20")));
}
{{/isModel}}
{{/isPrimitiveType}}
{{/isMap}}
{{/isArray}}
{{/allVars}}
return joiner.toString();
}
{{#parcelableModel}}
public void writeToParcel(Parcel out, int flags) {

Some files were not shown because too many files have changed in this diff Show More