Compare commits

...

107 Commits

Author SHA1 Message Date
William Cheng
7f8b853f50 Prepare 6.6.0 release (#15466)
* prepare 6.6.0 release

* update samples
2023-05-11 10:01:36 +08:00
William Cheng
bb8098a66f add --quite to mvn cmd in travis.ci 2023-05-10 17:17:08 +08:00
William Cheng
edc589ac81 update doc 2023-05-10 17:08:48 +08:00
Jérôme Tama
6e747259ae Initial OIDC support (#15417)
* Initial OIDC support

* Removes 'println'
Changes OIDC to OpenIdConnect
Adds generated files

* fix rebase errors
2023-05-10 16:51:37 +08:00
Tiffany Marrel
8a6c708884 [Java] Cleanup documentation (#15300)
* [Java] fix documentation of API authorization in README files

fix hierarchy level + add internal links + align wording across generators

* [Java] fix anchor links in documentation
2023-05-10 14:14:44 +08:00
Tiffany Marrel
f9937e77d6 [csharp C#] cleanup documentation (#15305)
* [C# csharp] fix documentation of API authorization in README files

fix hierarchy level + add internal links + align wording across generators

* [C# csharp] fix anchor links in documentation
2023-05-10 14:11:43 +08:00
Tiffany Marrel
ef5dc1c8a0 [Julia] Cleanup README docs (#15295)
* [Julia] fix documentation of API authorization in README files

fix hierarchy level + add internal links + align wording across generators

* [Julia] fix anchor links in documentation
2023-05-10 14:10:35 +08:00
Jacob Wang
b4d2c14f12 Update scala versions to 2.13.10 and 2.12.17 (#15459)
* Update scala versions to 2.13.10 and 2.12.17

* update samples
2023-05-10 01:30:45 +08:00
Nuno Miguel Micaelo Borges
4e27041bdc Add microprofile OpenApi annotations to JavaRxSpec (quarkus library). Add OpenID support (core) (#15407)
* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

* Issue #795: Add microprofile OpenAPI annotations for quarkus library in JaxRsSpec

---------

Co-authored-by: Nuno Borges <Nuno.Borges@ctw.bmwgroup.com>
2023-05-10 00:55:41 +08:00
Tiffany Marrel
c251202869 [Python] cleanup documentation (#15301)
* [Python] fix documentation of API authorization in README files

fix hierarchy level + add internal links + align wording across generators

* [Python] fix anchor links in documentation
2023-05-09 16:24:56 +00:00
Csaba Kozák
da9ad4a008 [kotlin][client] Small improvements (#15429)
* [kotlin][client] update Gradle wrapper in generated project

* [kotlin][client] Add @JsonClass(generateAdapter = false) to generated enums when using moshi library

This is needed, so the moshi generated R8 rules will include the enum classes:

https://github.com/square/moshi#enums

* [kotlin][client] Update generated samples
2023-05-09 16:28:54 +01:00
Tiffany Marrel
ef35e6d7ea [rust] fix documentation of API authorization in README files (#15352)
fix hierarchy level + align wording across generators
2023-05-09 14:30:54 +08:00
Tiffany Marrel
76fd2a2f66 [Scala] cleanup documentation (#15304)
* [Scala] fix documentation of API authorization in README files

fix hierarchy level + add internal links + align wording across generators

* [Scala] fix anchor links in documentation
2023-05-09 14:30:28 +08:00
Tiffany Marrel
1443dd9493 [perl] fix documentation of API authorization in README files (#15356)
align wording across generators
2023-05-09 14:26:30 +08:00
Tiffany Marrel
9cb14aeb8c [php] fix documentation of API authorization in README files (#15306)
fix hierarchy level + align wording across generators
2023-05-09 14:25:14 +08:00
Tiffany Marrel
4deaad557e [Go] fix documentation of API authorization in README files (#15345)
align wording across generators
2023-05-09 14:24:16 +08:00
Tiffany Marrel
adfb963831 [objc] fix documentation of API authorization in README files (#15347)
fix hierarchy level + align wording across generators
2023-05-09 14:23:19 +08:00
Tiffany Marrel
55e9f66cae [JavaScript] fix documentation of API authorization in README files (#15346)
align wording across generators
2023-05-09 14:22:41 +08:00
Tiffany Marrel
be651e7776 [powershell] cleanup documentation (#15355)
* [powershell] fix documentation of API authorization in README files

fix hierarchy level + add internal links + align wording across generators

* [powershell] fix anchor links in documentation
2023-05-09 14:21:09 +08:00
Tiffany Marrel
2b19d5f94d [Ruby] fix documentation of API authorization in README files (#15353)
align wording across generators
2023-05-09 14:17:34 +08:00
Tiffany Marrel
e32da0efda [apex] fix documentation of API authorization in README files (#15348)
align wording across generators
2023-05-09 14:16:58 +08:00
Tiffany Marrel
63913f2d0a [c] fix documentation of API authorization in README files (#15341)
align wording across generators
2023-05-09 14:15:27 +08:00
Tiffany Marrel
ba8ca1e7ac [R] fix documentation of API authorization in README files (#15354)
align wording across generators
2023-05-09 14:07:50 +08:00
Jorge Rodríguez Martín
fb059c259c [BUG][JAVA][restTemplate] ApiClient is not compatible with spring-web 6 Observation API (#15421)
* ApiClient is not compatible with spring-web 6 Observation API. Field uri is never filled

* Update samples
2023-05-09 14:04:51 +08:00
William Cheng
3cf646cda8 [csharp-netcore] fix back slash in regex (#15441)
* fix back slash in regex (csharp-netcore)

* undo add pattern test

* update shasum
2023-05-09 13:52:46 +08:00
devhl-labs
7bc10b03d0 [csharp-netcore][generichost] Move deserialization to method (#15454)
* removed extra line break

* moved deserialization to method
2023-05-09 13:47:15 +08:00
Dan Čermák
ff9b38404e Fix repository url in pyproject.toml (#15444)
The url had the repo id & user id in the wrong order
2023-05-09 01:29:34 +08:00
Tiffany Marrel
3685c0c1d6 [dart] cleanup documentation (#15344)
* [dart] fix documentation of API authorization in README files

fix hierarchy level + add internal links + align wording across generators

* [dart] fix anchor links in documentation

* [dart] address review comments

This reverts commit cff17aca and part of commit eecf1dd4
2023-05-09 01:27:51 +08:00
Ahmed Fwela
3d722c1083 [dart-dio] fix endpoints returning null (#15433)
* fix endpoints returning null

* add const back
2023-05-09 01:27:29 +08:00
William Cheng
f82a311bf8 update samples 2023-05-08 18:02:59 +08:00
Dan Čermák
5d602c628e Add Python 3.11 to github-workflow.mustache (#15442) 2023-05-08 17:51:42 +08:00
Beppe Catanese
3d2ec72461 [JAVA] Okhttp-gson: blank line between annotations and method signature (#15430)
* Remove extra blank line

* Regenerate samples
2023-05-08 14:39:46 +08:00
William Cheng
b4eb7071e4 [python-nextgen] support constructor with position argument in oneOf/anyOf model (#15434)
* support position constructor

* update samples

* update test
2023-05-08 10:00:57 +08:00
Tomasz Prus
72cb03b865 [python-nextgen] fix typing for bytes with validations (#15437)
* [python-nextgen] fix typing for bytes with validations

* update samples
2023-05-08 10:00:29 +08:00
devhl-labs
c6b31a3e08 removed extra line break (#15438) 2023-05-08 09:54:34 +08:00
William Cheng
cc620d8ba2 fix incorrect mustache tag (#15424) 2023-05-05 16:15:53 +08:00
Tiago Silva
56495d1486 Python Allow clients to define TLS Server name when using (#15283)
This PR allows users to define custom SNI when using the python clients

Fixes https://github.com/OpenAPITools/openapi-generator/issues/15282
2023-05-05 16:11:57 +08:00
William Cheng
737cb362b0 add option, update doc (#15419) 2023-05-05 14:59:33 +08:00
William Cheng
7259d812bd [csharp-netcore] Better handling of oneOf/anyOf with duplicated data type (#15377)
* better handling of oneOf/anyOf with duplicated data type

* update generichost template

* remove newline in eof

* bug fix (#15413)

---------

Co-authored-by: devhl-labs <shawnkanyer@gmail.com>
2023-05-05 14:25:45 +08:00
Jorge Rodríguez Martín
76c05b2991 Add property generateClientAsBean for config creation of ApiClient.java and XXXApi.java (#15416) 2023-05-05 14:18:44 +08:00
William Cheng
182240ea1d [csharp-netcore] Better regular expression (#15378)
* do not escape regular expression in c#

* update samples

* better code format
2023-05-04 18:42:30 +08:00
William Cheng
6fa089adee Add @deprecated to methods in python-nextgen (#15380)
* add @deprecated to methods in python-nextgen

* add deprecated as comment

* add deprecation warnings

* add warnings import

* remove import
2023-05-04 18:17:24 +08:00
William Cheng
854afc9be1 Update elm workflow to cover more tests (#15415)
* add more elm tests

* trigger build failure

* Revert "trigger build failure"

This reverts commit 83b407f5a1.
2023-05-04 16:16:58 +08:00
William Cheng
bc6d30832b add copyright, remove unused import (#15394) 2023-05-04 16:14:30 +08:00
William Cheng
a0b79d87f2 Minor improvement to the N4JS client generator (#15414)
* minor improvement to the N4JS client generator

* mark generator as beta
2023-05-04 16:13:10 +08:00
mmews-n4
db478c3452 Support language N4JS (2nd) (#15397)
* n4js initial commit

* incorporate feedback from user

* add tests

* fix media type in case of DELETE method

* fix media type

* some minor fixes

* options fix for booleans

* small fixes

* generated files by ./bin/utils/ensure-up-to-date

* remove String::toLowerCase due to de.thetaphi:forbiddenapis

* adjust test expectation

* fix test expectations

* fix test expectation

* add note to section 'Languages/Generators'

* remove file according to review

* replace tabs by spaces

* replace tabs by spaces (2)

* update two generated files

* remove test file

* move statement
2023-05-03 20:50:21 +08:00
William Cheng
aea7cef6a1 Revert "Support language N4JS (#15089)" (#15396)
This reverts commit a83470066e.
2023-05-03 15:43:07 +08:00
mmews-n4
a83470066e Support language N4JS (#15089)
* n4js initial commit

* incorporate feedback from user

* add tests

* fix media type in case of DELETE method

* fix media type

* some minor fixes

* options fix for booleans

* small fixes

* generated files by ./bin/utils/ensure-up-to-date

* remove String::toLowerCase due to de.thetaphi:forbiddenapis

* adjust test expectation

* fix test expectations

* fix test expectation

* add note to section 'Languages/Generators'

* remove file according to review
2023-05-03 15:23:45 +08:00
William Cheng
0cbf118757 add surefire rerun tests (#15390) 2023-05-03 15:19:55 +08:00
Robert Schweizer
0a4648f7a0 fix(python-nextgen): Date query params typo (#15395) 2023-05-03 15:17:51 +08:00
William Cheng
4e8d41bd79 Fix circleci test failures (#15317)
* fix circleci test failures

* trigger test

* update circleici pom.xml

* rearrange test

* comment out tests

* fix test

* comment out python-prior

* comment out test

* fix import

* comment out tests
2023-05-03 15:17:25 +08:00
Christopher Kobusch
45a3fe05f5 Add Xojo client generator (#15194)
* Add Xojo client

* Add Xojo client generator

* Add Xojo client generator

* hide generation timestamp for xojo samples

---------

Co-authored-by: William Cheng <wing328hk@gmail.com>
2023-05-03 14:06:40 +08:00
Beppe Catanese
61aadb32bd [GO] Add go.mod in go-gin-server generator (#15339)
* Add go.mod

* Add test

* Generate import path

* Update samples
2023-05-03 11:45:24 +08:00
William Cheng
92bcdea2fa Revert "Remove CXF imports and dependency (#15364)" (#15392)
This reverts commit 6686fb87b9.
2023-05-03 11:00:12 +08:00
William Cheng
021d3a311a [python-nextgen] Add ApiResponse object (#15367)
* add ApiResponse object

* fix tests

* improve api response

* add back _preload_content, add tests
2023-05-03 09:45:54 +08:00
William Cheng
bec32ae67f update samples 2023-05-03 09:43:43 +08:00
vanwobe
8a9afabb61 https://github.com/OpenAPITools/openapi-generator/issues/14599 (#15388)
Co-authored-by: vanwobe <bert.vanwolleghem@ext.ec.europa.eu>
2023-05-03 09:30:11 +08:00
Michel Wohlert
502a8a8ebf Fix request parameter encode call (#15313)
Co-authored-by: Wohlert, Michel <michel.wohlert@karlstorz.com>
2023-05-03 01:10:32 +08:00
Steffen Nießing
6686fb87b9 Remove CXF imports and dependency (#15364) 2023-05-03 01:09:16 +08:00
Albina Gimaletdinova
f8d5c547e3 Add urls to ktor and Vert.x in README (#15369) 2023-05-02 23:11:24 +08:00
Peter Leibiger
e356b770d2 [dart][dart-dio] Fix property deprecation and add parameter deprecation (#15374)
Addresses problems in #13818
2023-05-02 19:42:06 +08:00
Noor Dawod
fefbfd6aa2 Drop default value when unnecessary. (#15368)
* Drop default value when unnecessary.

* Simplify code.

* Simplify code.

* Generate Petstore sample code.
2023-05-02 19:41:33 +08:00
André Andersson
42fa07dd33 [Elm] Add support for petstore spec (#15257)
* Add petstore config

* Expand lambda to allow formatting of partials

* Fix order of operation with parenthesis

* Fix not exposing needed enum to string converters

* Add support for form params including files

* Add generated petstore client

* Regenerate existing elm client

* Add script that all files compile successfully

* Remove old unmaintained petstore client

* Add pipeline to try and compile elm clients
2023-05-02 16:50:57 +08:00
William Cheng
961980f284 [python-nextgen] add support for StrictBytes (#15365)
* add strictbyte support in python-nextgen client

* update samples

* use union of strictbytes, strictstr for backward compatibility
2023-05-01 10:51:22 +08:00
William Cheng
c7c5dd2673 remove unused file 2023-05-01 10:05:39 +08:00
Tiffany Marrel
5f8c4ec640 [swift5] cleanup documentation (#15351)
* [swift5] fix documentation of API authorization in README files

fix hierarchy level + add internal links + align wording across generators

* [swift5] fix anchor links in documentation

---------

Co-authored-by: Tiffany Marrel <tiffany.marrel@flowable.com>
2023-04-30 09:11:45 +01:00
William Cheng
ab819b9b18 mark python-nextgen as stable (#15360) 2023-04-29 13:51:01 +08:00
William Cheng
1f4d323020 fix enum support in oneof/anyof in python-nextgen (#15340) 2023-04-29 13:50:47 +08:00
Rodrigo de Almeida - RMA3
e07069731d [JAVA] Enumeration comparison in Java using equalsIgnoreCase when String - Fix issue 8084 (#15273)
* fix issue 8084

* add config

* add config

---------

Co-authored-by: Rodrigo Maciel de Almeida <rodrigo.almeida@wefin.com.br>
2023-04-28 17:27:41 +03:00
William Cheng
64c3be93a8 fix URL to 6.6.0 snapshot version 2023-04-28 14:08:18 +08:00
William Cheng
2bd1a15217 [python-nextgen] fix empty dict in body parameter (#15336)
* add more tests for python-nextgen

* update samples

* add fix for empty dict body

* update samples
2023-04-28 14:06:27 +08:00
William Cheng
f4c041e496 fix to_json, to_dict in python nextgen (#15337) 2023-04-28 14:04:30 +08:00
William Cheng
f4e0eb9bc9 Update git-commit-id maven plugin to newer version (#15332)
* update git commit plugin to newer version

* roll back to previous version
2023-04-28 08:45:14 +08:00
Oleh Kurpiak
1f23b019fa [Spring] fix Paginated without params (#15315) (fix #15265) 2023-04-27 14:32:11 +03:00
Tiffany Marrel
da96058f5b [kotlin] cleanup documentation (#15307)
* [kotlin] fix documentation of API authorization in README files

fix hierarchy level + add internal links + align wording across generators

* [kotlin] fix anchor links in documentation

---------

Co-authored-by: Tiffany Marrel <tiffany.marrel@flowable.com>
2023-04-27 11:33:15 +01:00
William Cheng
e211e1451d update extension to 1.17, update config (#15326) 2023-04-27 15:01:09 +08:00
martin-mfg
e0f42961c5 add missing documentation for maven and gradle options (#15322) 2023-04-27 12:43:37 +08:00
CTerasa-ep
b847140834 [C++][Pistache] Generate API generalization interface (#15279)
* [C++][Pistache] Refactor setupSupportingFiles

Supporting files are set up in the CppPistacheServerCodegen()
constructor as well as in processOpts(). Refactor the code and extract a
method setupSupportingFiles().

* [C++][Pistache] Refactor: Simplify isQueryParam condition

Both branches of the if/else do the same steps. Refactor this out and
invert logic.

* [C++][Pistache] Refactor: Add injectImplInFilename

Both branches of the if/else if do the similar steps and are dependent
on the suffix. Make this obvious by introducing a new method
injectImplInFilename(String result, String suffix).

* [C++][Pistache] Refactor: injectImplInFilename: remove index search

We do not need the separatorChar index to inject the "Impl" string.
Simply truncate the whole string.

Also rename the parameter from 'result' to' filename'.

* CppPistacheServer: Refactor postProcessOperationsWithModels

Pull out the post-processing for a single operation, and also pull out
post-processing for parameters.

Introduce boolean expressions for supported parsing per parameter, and
consumption of JSON.

Reorder code to make locality more explicit i.e. how consumeJSON and
isParsingSupported is generated and used.

* CppPistacheServer: Refactor to use functional matching

Functional matching like anyMatch() directly state what boolean value is
 searched.

 However, the Predicates deserve to heave names themselves.

* CppPistacheServer: Add base class for Api

Looking at the generated main-api-server.cpp code it gets obvious that
the API classes are self similar with a similar interface.
Only the construction and teh initialization is called in the main()
function. Leverage this fact to create a generalization ApiBase.

Introduce ApiBase as a pure virtual base class to the concrete API
classes and declare init() as virtual.

Pull the route member into the base class.

With this change we could have a container hold all the ApiImpl
objects later and call init() on all of them using a for_each loop.

* CppPistacheServer: Use ApiBase for ApiImpl storage

Refactor the main-api-server template to use a vector for ApiImpl
storage instead of separate objects. This leverages the previously
added ApiBase generalization.

 We push all concrete ApiImpl objects into a vector and call init() on
  each of them.

* [C++][Pistache]: Update generated sample

Due to teh addition of ApiBase class update the generated sample.

* [C++][Pistache] Add comment for postProcessSingleParam

* [C++][Pistache] Rename and comment implFilenameFromApiFilename

While writing the comment, I realized that the method name could be more
precise. Thus rename injectImplInFilename to implFilenameFromApiFilename
and add comment.
2023-04-26 20:01:58 +08:00
William Cheng
b8ccd25a79 [python-nextgen] Various fixes reported by pylint (#15309)
* various pylint fixes

* rearrange test

* Revert "rearrange test"

This reverts commit 24d777a8a8.
2023-04-26 17:12:10 +08:00
Beppe Catanese
6f24ad3625 [JAVA] OkHttp-GSON deprecated field only deprecates getter method (#15287)
* Deprecate build and setter methods

* Test with deprecated property

* Update samples

* Remove extra line

* Regenerate samples
2023-04-26 11:40:30 +08:00
Jaemin Park
de27749047 [cpp-ue4] Fix byte array writing in JSON to be valid base64 string (#15242)
* Fix byte array writing in JSON to be valid base64 string
- remove ToStringFormatArg
- use ToUrlString to path parameters
- use Base64UrlEncode only in ToUrlString

* Use LexToString instead of FString::Format
2023-04-25 00:21:27 +08:00
William Cheng
d6e19f8f55 fix minus sign in enum naming in python-nextgen (#15291) 2023-04-24 16:07:29 +08:00
William Cheng
52417f0597 use Field(...) for required properties in python-nextgen (#15290) 2023-04-24 16:07:09 +08:00
Dávid Gracza
98c2794b5d [Kotlin-Spring] add Kotlin based Spring-cloud openfeign generator (#15048) 2023-04-24 16:02:00 +08:00
William Cheng
e51908f176 [openapi-normalizer] Fix nullable boolean check in oneOf schema (#15276)
* fix nullable boolean check in oneof

* minor fix

* fix spec
2023-04-22 16:39:12 +08:00
William Cheng
b5745e6f26 [python-nextgen] Fix enum query parameter (#15278)
* fix enum query parameter in python-nextgen

* update samples
2023-04-22 16:08:59 +08:00
Matheus Teles
33e0c6775f Update beanValidationCore.mustache (#13631) (fix #3519)
* Update beanValidationCore.mustache

Update to use x-pattern-message for message customization

* Update spring.md

Update this page adding documentation for x-pattern-message

* added unit test
meet requested corrections

* build the project

* remove space

---------

Co-authored-by: Rodrigo de Almeida - RMA3 <rodrigo.ma3@gmail.com>
Co-authored-by: Rodrigo Maciel de Almeida <rodrigo.almeida@wefin.com.br>
2023-04-21 10:08:27 +03:00
Ivo Wever
2679819694 [Ruby] Client: fix base_url when no server_operation_index is defined (#15162)
As discussed in https://github.com/OpenAPITools/openapi-generator/pull/7415#discussion_r1113274416, it seems unlikely the code was correct.

server_operation_index is a hash table. In Ruby, `hash[key]` will return the value associated with `key`. If key is absent, `nil` is returned. Because that is sometimes undesirable, there is also `hash.fetch(key)`, which raises an error if the key is absent. It also allows you to specify a default to fall back on: `hash.fetch(key, default)` will return `default` if the key is absent.

So, since not all users will specify a 'server per operation' (or at least: I'm not), the old code would usually set `index` to the `server_index`, which is initialized to 0. The subsequent `if index == nil` will usually return false (`0 != nil` in Ruby), after which the `server_url` call on line 177 constructs the url based on the `server_operation_variables` and `operation_server_settings`, assuming we are dealing with the case where a server per operation is configured. The case where the url should be constructed from `scheme`, `host`, etc. is only called if either `server_index` is explicitly set to `nil` or the key `operation` is explicitly associated with the value `nil` in the `server_operation_index` hash table, both of which seem inappropriate.
2023-04-21 11:11:42 +08:00
Jaemin Park
e6c64d3917 Fix multi collection format has duplicated prefix (#15260)
Co-authored-by: Jaemin Park <nullbus@nm-fc.com>
2023-04-21 11:08:32 +08:00
Rodrigo de Almeida - RMA3
2c78ff78ed Fix issue 15264 - Replace @Controller with @RestController when using useSpringController (#15266)
* fix issue 15264

* If useResponseEntity true then keep @Controller if not @RestController

---------

Co-authored-by: Rodrigo Maciel de Almeida <rodrigo.almeida@wefin.com.br>
2023-04-20 18:35:09 +03:00
Oleh Kurpiak
ede1c9ca3e update samples 2023-04-20 17:47:44 +03:00
Vidur B
564a86ccda fix: set final query parameter value to enum value (#15133)
Use `<enum>.value` for query parameters that take an Enum, as otherwise the `name` of the enum will be used.
2023-04-20 15:54:57 +08:00
William Cheng
90d7da0b5f fix travis badge in readme 2023-04-20 14:17:17 +08:00
William Cheng
fdf53ac01e update mvn in workflow to use gradle enterprise (#15256) 2023-04-19 16:17:45 +08:00
William Cheng
0176957e26 [python-nextgen] better sample code (#15248)
* better python-nextgen sample code

* remove future import

* fix signing doc

* better test

* use hasHttpBearerMethods instead
2023-04-19 15:55:06 +08:00
yateeshc
e3fdac0711 rename hasBearerMethods to hasHttpBearerMethods (#15259) 2023-04-19 15:20:04 +08:00
Rodrigo de Almeida - RMA3
9b2917f3a9 Fix issue 12341 (#15234)
* if method return type is void then no return

* build the project

* fix build the project

* fix build the project

* fix return

* fix build the project

* fix build the project

* fix build the project

---------

Co-authored-by: Rodrigo Maciel de Almeida <rodrigo.almeida@wefin.com.br>
2023-04-18 23:56:12 +03:00
William Cheng
f5b4490bc9 [python-nextgen] Fix dict of dict of object in python-nextgen (#15239)
* fix dict of dict of object in python nextgen

* update samples
2023-04-18 14:59:08 +08:00
William Cheng
1881100742 use png version of pinterest logo 2023-04-18 12:00:41 +08:00
William Cheng
1ac39c7fa9 add Pinterest to the user list (#15247) 2023-04-18 11:51:53 +08:00
William Cheng
58425f54c0 Add workflow for gradle enterprise (#15211)
* add workflow for gradle enterprise

* add xml files

* remove build cache

* install

* update

* just clean

* trigger build

* mvn clean install
2023-04-18 11:38:53 +08:00
Robin Karlsson
91815bf555 [java] Fix anyof generics (#15210) (#15230) 2023-04-17 14:43:19 +08:00
André Andersson
096aabd360 Fix printing empty notes (#15238) 2023-04-17 14:42:30 +08:00
William Cheng
70a6106626 add null check in string with regular expression (#15233) 2023-04-16 23:46:17 +08:00
Robin Karlsson
738beb401e [java][jersey] Fix UUID path parameters (#15114) (#15229) 2023-04-16 23:32:15 +08:00
Dennis Kugelmann
03359ae4d5 [pub] Add repository and publish_to as configurable option in pubspec.yaml (#15232)
* Add repository as configurable option to pub client libraries

* Generate files

* Make repository null by default

* Update pubRepository mustache template

Co-authored-by: Ahmed Fwela <63286031+ahmednfwela@users.noreply.github.com>

* Regenerate samples and documentation

* Support setting publish_to in pubspec.yaml

---------

Co-authored-by: Ahmed Fwela <63286031+ahmednfwela@users.noreply.github.com>
2023-04-16 21:37:29 +08:00
Noor Dawod
cbf5598c59 Fix generated code when a list is actually a set. (#15027) 2023-04-16 21:32:59 +08:00
3297 changed files with 61919 additions and 23364 deletions

View File

@@ -48,6 +48,8 @@ jobs:
- name: Build with Maven
shell: bash
run: mvn -nsu -B --quiet -Djacoco.skip=true -Dorg.slf4j.simpleLogger.defaultLogLevel=error --no-transfer-progress clean install --file pom.xml ${{ matrix.flags }}
env:
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
- name: Upload Maven build artifact
uses: actions/upload-artifact@v3
@@ -63,6 +65,8 @@ jobs:
- name: Test Maven plugin integration
if: matrix.java == '8'
shell: bash
env:
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
run: |
cd modules/openapi-generator-maven-plugin
mvn verify -Pintegration

View File

@@ -35,6 +35,8 @@ jobs:
${{ runner.os }}-test-gradle-plugin-${{ env.cache-name }}-
${{ runner.os }}-test-gradle-plugin-
- name: Run tests
env:
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
run: |
mvn --no-snapshot-updates --batch-mode --quiet install -DskipTests -Dorg.slf4j.simpleLogger.defaultLogLevel=error
(cd modules/openapi-generator-gradle-plugin/samples/local-spec && ./gradlew buildGoSdk) # using gradle-6.8.3 via wrapper

View File

@@ -38,6 +38,8 @@ jobs:
${{ runner.os }}-build-
- name: Run unit tests
run: cd modules/openapi-generator && mvn --no-snapshot-updates --batch-mode -Dtest="**/functional/*Test" test -Dorg.slf4j.simpleLogger.defaultLogLevel=error
env:
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
- name: Publish unit test reports
if: ${{ always() }}
uses: actions/upload-artifact@v3

View File

@@ -34,6 +34,8 @@ jobs:
${{ runner.os }}-test-maven-plugin-${{ env.cache-name }}-
${{ runner.os }}-test-maven-plugin-
- name: Run tests
env:
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
run: |
mvn clean install -DskipTests -Dmaven.javadoc.skip=true
mvn --no-snapshot-updates --quiet clean compile -f modules/openapi-generator-maven-plugin/examples/java-client.xml -Dorg.slf4j.simpleLogger.defaultLogLevel=error

View File

@@ -37,6 +37,8 @@ jobs:
${{ runner.os }}-build-
- name: Run maven
run: mvn --no-snapshot-updates --batch-mode --quiet install -DskipTests -Dorg.slf4j.simpleLogger.defaultLogLevel=error
env:
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
- run: ls -la modules/openapi-generator-cli/target
- name: Upload openapi-generator-cli.jar artifact
uses: actions/upload-artifact@v3
@@ -73,6 +75,8 @@ jobs:
${{ runner.os }}-build-
- name: Run unit tests
run: mvn --no-snapshot-updates --batch-mode --quiet --fail-at-end test -Dorg.slf4j.simpleLogger.defaultLogLevel=error
env:
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
- name: Publish unit test reports
if: ${{ always() }}
uses: actions/upload-artifact@v3

35
.github/workflows/samples-elm.yaml vendored Normal file
View File

@@ -0,0 +1,35 @@
name: Samples Elm
on:
push:
paths:
- samples/client/petstore/elm/**
- samples/openapi3/client/elm/**
pull_request:
paths:
- samples/client/petstore/elm/**
- samples/openapi3/client/elm/**
jobs:
build:
name: Build Elm clients
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
sample:
# clients
- samples/client/petstore/elm
- samples/openapi3/client/elm
steps:
- uses: actions/checkout@v3
- uses: jorelali/setup-elm@v5
with:
elm-version: 0.19.1
- name: Build
working-directory: ${{ matrix.sample }}
# Try to compile all .elm files
# This fails if:
# An .elm file couldn't be compiled
# No .elm files were found
# No elm.json file could be found in the root of the working directory
run: elm make $(find . -name *.elm) --output=/dev/null

View File

@@ -38,6 +38,7 @@ jobs:
- samples/server/petstore/jaxrs-cxf-annotated-base-path
- samples/server/petstore/jaxrs-cxf-cdi
- samples/server/petstore/jaxrs-cxf-non-spring-app
- samples/server/petstore/jaxrs-spec-microprofile-openapi-annotations
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3

View File

@@ -56,6 +56,7 @@ jobs:
- samples/client/petstore/kotlin-jvm-vertx-jackson
- samples/client/petstore/kotlin-jvm-vertx-jackson-coroutines
- samples/client/petstore/kotlin-jvm-vertx-moshi
- samples/client/petstore/kotlin-spring-cloud
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3

View File

@@ -0,0 +1,27 @@
name: Python Server
on:
push:
paths:
- samples/server/petstore/python-aiohttp/**
pull_request:
paths:
- samples/server/petstore/python-aiohttp/**
jobs:
build:
name: Test Python server
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
sample:
# servers
- samples/server/petstore/python-aiohttp/
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.7'
- name: Test
working-directory: ${{ matrix.sample }}
run: make test-all

13
.mvn/extensions.xml Normal file
View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<extensions>
<extension>
<groupId>com.gradle</groupId>
<artifactId>gradle-enterprise-maven-extension</artifactId>
<version>1.17</version>
</extension>
<extension>
<groupId>com.gradle</groupId>
<artifactId>common-custom-user-data-maven-extension</artifactId>
<version>1.11.1</version>
</extension>
</extensions>

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!-- Common gradle-enterprise.xml configuration for Maven shared between CI agents and developers building locally.
The build cache credentials required for CI builds to write to the remote build cache are read from environment variables.
Possibly, the credentials are configured in Jenkins via Credentials plugin (https://plugins.jenkins.io/credentials/) and
Credentials Binding plugin (https://plugins.jenkins.io/credentials-binding/), or the credentials are injected using the
vendor-specific mechanism of the CI server running the build.
Note: In the XML configuration below, you need to adjust
- the server url of your Gradle Enterprise server
- the name of the environment variable that reveals the build is running in a CI environment
- the names of the environment variables holding the build cache credentials
to the specifics of your CI server settings. -->
<gradleEnterprise
xmlns="https://www.gradle.com/gradle-enterprise-maven" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.gradle.com/gradle-enterprise-maven https://www.gradle.com/schema/gradle-enterprise-maven.xsd">
<server>
<url>https://ge.openapi-generator.tech/</url> <!-- adjust to your GE server -->
<allowUntrusted>false</allowUntrusted> <!-- ensure a trusted certificate is configured -->
</server>
<buildScan>
<captureGoalInputFiles>true</captureGoalInputFiles>
<backgroundBuildScanUpload>#{isFalse(env['CI'])}</backgroundBuildScanUpload> <!-- adjust to your CI provider -->
<publish>ALWAYS</publish>
<publishIfAuthenticated>true</publishIfAuthenticated>
<obfuscation>
<!-- Use a redacted value.-->
<ipAddresses>#{{'0.0.0.0'}}</ipAddresses>
</obfuscation>
</buildScan>
<buildCache>
<local>
<enabled>false</enabled>
</local>
<remote>
<enabled>false</enabled>
</remote>
</buildCache>
</gradleEnterprise>

View File

@@ -158,7 +158,7 @@ after_success:
- if [ $SONATYPE_USERNAME ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
if [ "$TRAVIS_BRANCH" = "master" ] && [ -z $TRAVIS_TAG ]; then
echo "Publishing from branch $TRAVIS_BRANCH";
mvn clean deploy -DskipTests=true -B -U -P release --settings CI/settings.xml -Dorg.slf4j.simpleLogger.defaultLogLevel=error;
mvn clean deploy --quiet -DskipTests=true -B -U -P release --settings CI/settings.xml -Dorg.slf4j.simpleLogger.defaultLogLevel=error;
echo "Finished mvn clean deploy for $TRAVIS_BRANCH";
pushd .;
cd modules/openapi-generator-gradle-plugin;
@@ -167,7 +167,7 @@ after_success:
popd;
elif [ -z $TRAVIS_TAG ] && [[ "$TRAVIS_BRANCH" =~ ^[0-9]+\.[0-9]+\.x$ ]]; then
echo "Publishing from branch $TRAVIS_BRANCH";
mvn clean deploy --settings CI/settings.xml -Dorg.slf4j.simpleLogger.defaultLogLevel=error;
mvn clean deploy --quiet --settings CI/settings.xml -Dorg.slf4j.simpleLogger.defaultLogLevel=error;
echo "Finished mvn clean deploy for $TRAVIS_BRANCH";
pushd .;
cd modules/openapi-generator-gradle-plugin;

View File

@@ -79,7 +79,8 @@ elif [ "$NODE_INDEX" = "4" ]; then
#mvn --no-snapshot-updates --quiet verify -Psamples.circleci.node4 -Dorg.slf4j.simpleLogger.defaultLogLevel=error
(cd samples/openapi3/client/petstore/python && make test)
(cd samples/openapi3/client/petstore/python-prior && make test)
# comment out due to ModuleNotFoundError: No module named 'urllib3.request'
#(cd samples/openapi3/client/petstore/python-prior && make test)
(cd samples/openapi3/client/3_0_3_unit_test/python && make test)
else

View File

@@ -73,6 +73,7 @@ Code change should conform to the programming style guide of the respective lang
- Scala: http://docs.scala-lang.org/style/
- Swift: [Apple Developer](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html)
- TypeScript: https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines
- Xojo: https://documentation.xojo.com/topics/code_management/coding_guidelines.html
For other languages, feel free to suggest.

View File

@@ -16,13 +16,13 @@
<div align="center">
[Master](https://github.com/OpenAPITools/openapi-generator/tree/master) (`6.6.0`):
[![Build Status](https://img.shields.io/travis/OpenAPITools/openapi-generator/master.svg?label=Integration%20Test)](https://app.travis-ci.com/github/OpenAPITools/openapi-generator/builds)
[![Build Status](https://api.travis-ci.com/OpenAPITools/openapi-generator.svg?branch=master&status=passed)](https://app.travis-ci.com/github/OpenAPITools/openapi-generator/builds)
[![Integration Test2](https://circleci.com/gh/OpenAPITools/openapi-generator.svg?style=shield)](https://circleci.com/gh/OpenAPITools/openapi-generator)
[![Windows Test](https://ci.appveyor.com/api/projects/status/github/openapitools/openapi-generator?branch=master&svg=true&passingText=Windows%20Test%20-%20OK&failingText=Windows%20Test%20-%20Fails)](https://ci.appveyor.com/project/WilliamCheng/openapi-generator)
[![Bitrise](https://img.shields.io/bitrise/4a2b10a819d12b67/master?label=bitrise%3A%20Swift+4,5&token=859FMDR8QHwabCzwvZK6vQ)](https://app.bitrise.io/app/4a2b10a819d12b67)
[7.0.x](https://github.com/OpenAPITools/openapi-generator/tree/7.0.x) (`7.0.x`):
[![Build Status](https://img.shields.io/travis/OpenAPITools/openapi-generator/7.0.x.svg?label=Integration%20Test)](https://app.travis-ci.com/github/OpenAPITools/openapi-generator/builds)
[![Build Status](https://api.travis-ci.com/OpenAPITools/openapi-generator.svg?branch=7.0.x&status=passed)](https://app.travis-ci.com/github/OpenAPITools/openapi-generator/builds)
[![Integration Test2](https://circleci.com/gh/OpenAPITools/openapi-generator/tree/7.0.x.svg?style=shield)](https://circleci.com/gh/OpenAPITools/openapi-generator)
[![Windows Test](https://ci.appveyor.com/api/projects/status/github/openapitools/openapi-generator?branch=7.0.x&svg=true&passingText=Windows%20Test%20-%20OK&failingText=Windows%20Test%20-%20Fails)](https://ci.appveyor.com/project/WilliamCheng/openapi-generator)
[![Bitrise](https://img.shields.io/bitrise/4a2b10a819d12b67/7.0.x?label=bitrise%3A%20Swift+4,5&token=859FMDR8QHwabCzwvZK6vQ)](https://app.bitrise.io/app/4a2b10a819d12b67)
@@ -76,13 +76,13 @@ If you find OpenAPI Generator useful for work, please consider asking your compa
## Overview
OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an [OpenAPI Spec](https://github.com/OAI/OpenAPI-Specification) (both 2.0 and 3.0 are supported). Currently, the following languages/frameworks are supported:
| | Languages/Frameworks |
| -------------------------------- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **API clients** | **ActionScript**, **Ada**, **Apex**, **Bash**, **C**, **C#** (.net 2.0, 3.5 or later, .NET Standard 1.3 - 2.1, .NET Core 3.1, .NET 5.0. Libraries: RestSharp, GenericHost, HttpClient), **C++** (Arduino, cpp-restsdk, Qt5, Tizen, Unreal Engine 4), **Clojure**, **Crystal**, **Dart**, **Elixir**, **Elm**, **Eiffel**, **Erlang**, **Go**, **Groovy**, **Haskell** (http-client, Servant), **Java** (Apache HttpClient 4.x, Apache HttpClient 5.x, Jersey1.x, Jersey2.x, OkHttp, Retrofit1.x, Retrofit2.x, Feign, RestTemplate, RESTEasy, Vertx, Google API Client Library for Java, Rest-assured, Spring 5 Web Client, MicroProfile Rest Client, Helidon), **Jetbrains HTTP Client**, **Julia**, **k6**, **Kotlin**, **Lua**, **Nim**, **Node.js/JavaScript** (ES5, ES6, AngularJS with Google Closure Compiler annotations, Flow types, Apollo GraphQL DataStore), **Objective-C**, **OCaml**, **Perl**, **PHP**, **PowerShell**, **Python**, **R**, **Ruby**, **Rust** (hyper, reqwest, rust-server), **Scala** (akka, http4s, scalaz, sttp, swagger-async-httpclient), **Swift** (2.x, 3.x, 4.x, 5.x), **Typescript** (AngularJS, Angular (2.x - 15.x), Aurelia, Axios, Fetch, Inversify, jQuery, Nestjs, Node, redux-query, Rxjs) |
| **Server stubs** | **Ada**, **C#** (ASP.NET Core, Azure Functions), **C++** (Pistache, Restbed, Qt5 QHTTPEngine), **Erlang**, **F#** (Giraffe), **Go** (net/http, Gin, Echo), **Haskell** (Servant, Yesod), **Java** (MSF4J, Spring, Undertow, JAX-RS: CDI, CXF, Inflector, Jersey, RestEasy, Play Framework, [PKMST](https://github.com/ProKarma-Inc/pkmst-getting-started-examples), [Vert.x](https://vertx.io/), [Apache Camel](https://camel.apache.org/), [Helidon](https://helidon.io/)), **Julia**, **Kotlin** (Spring Boot, Ktor, Vertx), **PHP** (Laravel, Lumen, [Mezzio (fka Zend Expressive)](https://github.com/mezzio/mezzio), Slim, Silex, [Symfony](https://symfony.com/)), **Python** (FastAPI, Flask), **NodeJS**, **Ruby** (Sinatra, Rails5), **Rust** ([rust-server](https://openapi-generator.tech/docs/generators/rust-server/)), **Scala** (Akka, [Finch](https://github.com/finagle/finch), [Lagom](https://github.com/lagom/lagom), [Play](https://www.playframework.com/), Scalatra) |
| **API documentation generators** | **HTML**, **Confluence Wiki**, **Asciidoc**, **Markdown**, **PlantUML** |
| **Configuration files** | [**Apache2**](https://httpd.apache.org/) |
| **Others** | **GraphQL**, **JMeter**, **Ktorm**, **MySQL Schema**, **Protocol Buffer**, **WSDL** |
| | Languages/Frameworks |
| -------------------------------- |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **API clients** | **ActionScript**, **Ada**, **Apex**, **Bash**, **C**, **C#** (.net 2.0, 3.5 or later, .NET Standard 1.3 - 2.1, .NET Core 3.1, .NET 5.0. Libraries: RestSharp, GenericHost, HttpClient), **C++** (Arduino, cpp-restsdk, Qt5, Tizen, Unreal Engine 4), **Clojure**, **Crystal**, **Dart**, **Elixir**, **Elm**, **Eiffel**, **Erlang**, **Go**, **Groovy**, **Haskell** (http-client, Servant), **Java** (Apache HttpClient 4.x, Apache HttpClient 5.x, Jersey1.x, Jersey2.x, OkHttp, Retrofit1.x, Retrofit2.x, Feign, RestTemplate, RESTEasy, Vertx, Google API Client Library for Java, Rest-assured, Spring 5 Web Client, MicroProfile Rest Client, Helidon), **Jetbrains HTTP Client**, **Julia**, **k6**, **Kotlin**, **Lua**, **N4JS**, **Nim**, **Node.js/JavaScript** (ES5, ES6, AngularJS with Google Closure Compiler annotations, Flow types, Apollo GraphQL DataStore), **Objective-C**, **OCaml**, **Perl**, **PHP**, **PowerShell**, **Python**, **R**, **Ruby**, **Rust** (hyper, reqwest, rust-server), **Scala** (akka, http4s, scalaz, sttp, swagger-async-httpclient), **Swift** (2.x, 3.x, 4.x, 5.x), **Typescript** (AngularJS, Angular (2.x - 15.x), Aurelia, Axios, Fetch, Inversify, jQuery, Nestjs, Node, redux-query, Rxjs), **XoJo** |
| **Server stubs** | **Ada**, **C#** (ASP.NET Core, Azure Functions), **C++** (Pistache, Restbed, Qt5 QHTTPEngine), **Erlang**, **F#** (Giraffe), **Go** (net/http, Gin, Echo), **Haskell** (Servant, Yesod), **Java** (MSF4J, Spring, Undertow, JAX-RS: CDI, CXF, Inflector, Jersey, RestEasy, Play Framework, [PKMST](https://github.com/ProKarma-Inc/pkmst-getting-started-examples), [Vert.x](https://vertx.io/), [Apache Camel](https://camel.apache.org/), [Helidon](https://helidon.io/)), **Julia**, **Kotlin** (Spring Boot, [Ktor](https://github.com/ktorio/ktor), [Vert.x](https://vertx.io/)), **PHP** (Laravel, Lumen, [Mezzio (fka Zend Expressive)](https://github.com/mezzio/mezzio), Slim, Silex, [Symfony](https://symfony.com/)), **Python** (FastAPI, Flask), **NodeJS**, **Ruby** (Sinatra, Rails5), **Rust** ([rust-server](https://openapi-generator.tech/docs/generators/rust-server/)), **Scala** (Akka, [Finch](https://github.com/finagle/finch), [Lagom](https://github.com/lagom/lagom), [Play](https://www.playframework.com/), Scalatra) |
| **API documentation generators** | **HTML**, **Confluence Wiki**, **Asciidoc**, **Markdown**, **PlantUML** |
| **Configuration files** | [**Apache2**](https://httpd.apache.org/) |
| **Others** | **GraphQL**, **JMeter**, **Ktorm**, **MySQL Schema**, **Protocol Buffer**, **WSDL** |
## Table of contents
@@ -121,7 +121,7 @@ The OpenAPI Specification has undergone 3 revisions since initial creation in 20
| OpenAPI Generator Version | Release Date | Notes |
| --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | ------------------------------------------------- |
| 7.0.0 (upcoming major release) [SNAPSHOT](https://oss.sonatype.org/content/repositories/snapshots/org/openapitools/openapi-generator-cli/7.0.0-SNAPSHOT/) | May/Jun 2023 | Major release with breaking changes (no fallback) |
| 6.6.0 (upcoming minor release) [SNAPSHOT](https://oss.sonatype.org/content/repositories/snapshots/org/openapitools/openapi-generator-cli/6.5.0-SNAPSHOT/) | 28.04.2023 | Minor release with breaking changes (with fallback) |
| 6.6.0 (upcoming minor release) [SNAPSHOT](https://oss.sonatype.org/content/repositories/snapshots/org/openapitools/openapi-generator-cli/6.6.0-SNAPSHOT/) | 28.04.2023 | Minor release with breaking changes (with fallback) |
| [6.5.0](https://github.com/OpenAPITools/openapi-generator/releases/tag/v6.5.0) (latest stable release) | 01.04.2023 | Minor release with breaking changes (with fallback) |
| [5.4.0](https://github.com/OpenAPITools/openapi-generator/releases/tag/v5.4.0) | 31.01.2022 | Minor release with breaking changes (with fallback) |
| [4.3.1](https://github.com/OpenAPITools/openapi-generator/releases/tag/v4.3.1) | 06.05.2020 | Patch release (enhancements, bug fixes, etc) |
@@ -269,7 +269,7 @@ If you're a nix user, you can enter OpenAPI Generator shell, by typing:
```sh
nix develop
```
It will enter a shell with Java 8 and Maven installed.
It will enter a shell with Java 8 and Maven installed.
Direnv supports automatically loading of the nix developer shell, so if you're using direnv too, type:
```sh
@@ -680,6 +680,7 @@ Here are some companies/projects (alphabetical order) using OpenAPI Generator in
- [Paxos](https://www.paxos.com)
- [Plaid](https://plaid.com)
- [PLAID, Inc.](https://plaid.co.jp/)
- [Pinterest](https://www.pinterest.com)
- [Ponicode](https://ponicode.dev/)
- [Pricefx](https://www.pricefx.com/)
- [PrintNanny](https://www.print-nanny.com/)
@@ -991,6 +992,7 @@ Here is a list of template creators:
* Kotlin (MultiPlatform): @andrewemery
* Kotlin (Volley): @alisters
* Lua: @daurnimator
* N4JS: @mmews-n4
* Nim: @hokamoto
* OCaml: @cgensoul
* Perl: @wing328 [:heart:](https://www.patreon.com/wing328)
@@ -1023,6 +1025,7 @@ Here is a list of template creators:
* TypeScript (Node): @mhardorf
* TypeScript (Rxjs): @denyo
* TypeScript (redux-query): @petejohansonxo
* Xojo: @Topheee
* Server Stubs
* Ada: @stcarrez
* C# ASP.NET 5: @jimschubert [:heart:](https://www.patreon.com/jimschubert)
@@ -1152,6 +1155,7 @@ If you want to join the committee, please kindly apply by sending an email to te
| Julia | @tanmaykm (2023/01) |
| Kotlin | @jimschubert (2017/09) [:heart:](https://www.patreon.com/jimschubert), @dr4ke616 (2018/08) @karismann (2019/03) @Zomzog (2019/04) @andrewemery (2019/10) @4brunu (2019/11) @yutaka0m (2020/03) |
| Lua | @daurnimator (2017/08) |
| N4JS | @mmews-n4 (2023/03) |
| Nim | |
| NodeJS/Javascript | @CodeNinjai (2017/07) @frol (2017/07) @cliffano (2017/07) |
| ObjC | |
@@ -1166,6 +1170,7 @@ If you want to join the committee, please kindly apply by sending an email to te
| Scala | @clasnake (2017/07), @jimschubert (2017/09) [:heart:](https://www.patreon.com/jimschubert), @shijinkui (2018/01), @ramzimaalej (2018/03), @chameleon82 (2020/03), @Bouillie (2020/04) |
| Swift | @jgavris (2017/07) @ehyche (2017/08) @Edubits (2017/09) @jaz-ah (2017/09) @4brunu (2019/11) |
| TypeScript | @TiFu (2017/07) @taxpon (2017/07) @sebastianhaas (2017/07) @kenisteward (2017/07) @Vrolijkx (2017/09) @macjohnny (2018/01) @topce (2018/10) @akehir (2019/07) @petejohansonxo (2019/11) @amakhrov (2020/02) @davidgamero (2022/03) @mkusaka (2022/04) |
| Xojo | @Topheee (2023/04) |
Past Members of Technical Committee:

View File

@@ -0,0 +1,4 @@
generatorName: elm
outputDir: samples/client/petstore/elm
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/elm

View File

@@ -0,0 +1,13 @@
generatorName: jaxrs-spec
outputDir: samples/server/petstore/jaxrs-spec-microprofile-openapi-annotations
inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml
templateDir: modules/openapi-generator/src/main/resources/JavaJaxRS/spec
additionalProperties:
artifactId: jaxrs-spec-petstore-server
serializableModel: "true"
hideGenerationTimestamp: "true"
implicitHeadersRegex: (api_key|enum_header_string)
generateBuilders: "true"
useMicroProfileOpenAPIAnnotations: "true"
library: "quarkus"
dateLibrary: "java8-localdatetime"

View File

@@ -0,0 +1,12 @@
generatorName: kotlin-spring
outputDir: samples/client/petstore/kotlin-spring-cloud
library: spring-cloud
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/kotlin-spring
additionalProperties:
documentationProvider: none
annotationLibrary: none
useSwaggerUI: "false"
serializableModel: "true"
beanValidations: "true"
interfaceOnly: "true"

View File

@@ -0,0 +1,9 @@
generatorName: n4js
outputDir: samples/client/petstore/n4js
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/n4js
additionalProperties:
apiPackage: "api"
modelPackage: "model"
fetchExecuterConstName: "FETCH_EXEC"
fetchExecuterConstImplPath: "FetchExecuterMock"

View File

@@ -0,0 +1,8 @@
generatorName: xojo-client
outputDir: samples/client/petstore/xojo/client-synchronous
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/xojo-client
additionalProperties:
hideGenerationTimestamp: "true"
supportsAsync: "false"
projectName: "XojoOpenAPIClientSynchronous"

View File

@@ -0,0 +1,7 @@
generatorName: xojo-client
outputDir: samples/client/petstore/xojo/client
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/xojo-client
additionalProperties:
hideGenerationTimestamp: "true"
supportsAsync: "true"

View File

@@ -3,7 +3,7 @@
- filename: "samples/client/petstore/csharp-netcore/OpenAPIClient/src/Org.OpenAPITools.Test/JSONComposedSchemaTests.cs"
sha256: 054adb6efaff70f492e471cb3e4d628d22cda814906808fd3fcce36ce710b7ee
- filename: "samples/client/petstore/csharp-netcore/OpenAPIClient/src/Org.OpenAPITools.Test/Api/PetApiTests.cs"
sha256: ff6a5fccd4c026d85fe7232911cda445f5065dcefd03abe258e19af5b28d05c5
sha256: 7dad88554fe630d25c787cae05305d302d5e34ca810aee4fa23f20055f9188e1
- filename: "samples/client/petstore/csharp-netcore/OpenAPIClient/src/Org.OpenAPITools.Test/linux-logo.png"
sha256: 0a67c32728197e942b13bdda064b73793f12f5c795f1e5cf35a3adf69c973230
# java okhttp gson test files

View File

@@ -77,6 +77,7 @@ Code change should conform to the programming style guide of the respective lang
- Scala: http://docs.scala-lang.org/style/
- Swift: [Apple Developer](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html)
- TypeScript: https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines
- Xojo: https://documentation.xojo.com/topics/code_management/coding_guidelines.html
For other languages, feel free to suggest.

View File

@@ -44,6 +44,7 @@ The following generators are available:
* [k6 (beta)](generators/k6.md)
* [kotlin](generators/kotlin.md)
* [lua (beta)](generators/lua.md)
* [n4js (beta)](generators/n4js.md)
* [nim (beta)](generators/nim.md)
* [objc](generators/objc.md)
* [ocaml](generators/ocaml.md)
@@ -53,7 +54,7 @@ The following generators are available:
* [powershell (beta)](generators/powershell.md)
* [python](generators/python.md)
* [python-legacy](generators/python-legacy.md)
* [python-nextgen (beta)](generators/python-nextgen.md)
* [python-nextgen](generators/python-nextgen.md)
* [python-prior](generators/python-prior.md)
* [r](generators/r.md)
* [ruby](generators/ruby.md)
@@ -75,6 +76,7 @@ The following generators are available:
* [typescript-node](generators/typescript-node.md)
* [typescript-redux-query](generators/typescript-redux-query.md)
* [typescript-rxjs](generators/typescript-rxjs.md)
* [xojo-client](generators/xojo-client.md)
## SERVER generators

View File

@@ -290,7 +290,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| ---- | --------- | ---------- |
|BasicAuth|✓|OAS2,OAS3
|ApiKey|✓|OAS2,OAS3
|OpenIDConnect||OAS3
|OpenIDConnect||OAS3
|BearerToken|✓|OAS3
|OAuth2_Implicit|✓|OAS2,OAS3
|OAuth2_Password|✓|OAS2,OAS3

View File

@@ -247,7 +247,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| ---- | --------- | ---------- |
|BasicAuth|✓|OAS2,OAS3
|ApiKey|✓|OAS2,OAS3
|OpenIDConnect||OAS3
|OpenIDConnect||OAS3
|BearerToken|✓|OAS3
|OAuth2_Implicit|✓|OAS2,OAS3
|OAuth2_Password|✓|OAS2,OAS3

View File

@@ -258,7 +258,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| ---- | --------- | ---------- |
|BasicAuth|✓|OAS2,OAS3
|ApiKey|✓|OAS2,OAS3
|OpenIDConnect||OAS3
|OpenIDConnect||OAS3
|BearerToken|✓|OAS3
|OAuth2_Implicit|✓|OAS2,OAS3
|OAuth2_Password|✓|OAS2,OAS3

View File

@@ -43,7 +43,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|packageVersion|C# package version.| |1.0.0|
|releaseNote|Release note, default to 'Minor update'.| |Minor update|
|returnICollection|Return ICollection&lt;T&gt; instead of the concrete type.| |false|
|skipOneOfAnyOfGetter|Skip the generation of getter for sub-schemas in oneOf/anyOf models.| |false|
|sourceFolder|source folder for generated code| |src|
|targetFramework|The target .NET framework version. To target multiple frameworks, use `;` as the separator, e.g. `netstandard2.1;netcoreapp3.1`|<dl><dt>**netstandard1.3**</dt><dd>.NET Standard 1.3 compatible</dd><dt>**netstandard1.4**</dt><dd>.NET Standard 1.4 compatible</dd><dt>**netstandard1.5**</dt><dd>.NET Standard 1.5 compatible</dd><dt>**netstandard1.6**</dt><dd>.NET Standard 1.6 compatible</dd><dt>**netstandard2.0**</dt><dd>.NET Standard 2.0 compatible</dd><dt>**netstandard2.1**</dt><dd>.NET Standard 2.1 compatible</dd><dt>**netcoreapp3.1**</dt><dd>.NET Core 3.1 compatible (End of Support 13 Dec 2022)</dd><dt>**net47**</dt><dd>.NET Framework 4.7 compatible</dd><dt>**net48**</dt><dd>.NET Framework 4.8 compatible</dd><dt>**net6.0**</dt><dd>.NET 6.0 compatible</dd><dt>**net7.0**</dt><dd>.NET 7.0 compatible</dd></dl>|netstandard2.0|
|useCollection|Deserialize array types to Collection&lt;T&gt; instead of List&lt;T&gt;.| |false|

View File

@@ -32,6 +32,8 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|pubHomepage|Homepage in generated pubspec| |homepage|
|pubLibrary|Library name in generated code| |openapi.api|
|pubName|Name in generated pubspec| |openapi|
|pubPublishTo|Publish_to in generated pubspec| |null|
|pubRepository|Repository in generated pubspec| |null|
|pubVersion|Version in generated pubspec| |1.0.0|
|serializationLibrary|Specify serialization library|<dl><dt>**built_value**</dt><dd>[DEFAULT] built_value</dd><dt>**json_serializable**</dt><dd>[BETA] json_serializable</dd></dl>|built_value|
|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true|

View File

@@ -30,6 +30,8 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|pubHomepage|Homepage in generated pubspec| |homepage|
|pubLibrary|Library name in generated code| |openapi.api|
|pubName|Name in generated pubspec| |openapi|
|pubPublishTo|Publish_to in generated pubspec| |null|
|pubRepository|Repository in generated pubspec| |null|
|pubVersion|Version in generated pubspec| |1.0.0|
|serializationLibrary|Specify serialization library|<dl><dt>**native_serialization**</dt><dd>Use native serializer, backwards compatible</dd></dl>|native_serialization|
|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true|

View File

@@ -305,7 +305,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| ---- | --------- | ---------- |
|BasicAuth|✓|OAS2,OAS3
|ApiKey|✓|OAS2,OAS3
|OpenIDConnect||OAS3
|OpenIDConnect||OAS3
|BearerToken|✓|OAS3
|OAuth2_Implicit|✓|OAS2,OAS3
|OAuth2_Password|✓|OAS2,OAS3

View File

@@ -94,6 +94,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|title|server title name or client service name| |OpenAPI Spring|
|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|
|useEnumCaseInsensitive|Use `equalsIgnoreCase` when String for enum comparison| |false|
|useFeignClientUrl|Whether to generate Feign client with url parameter.| |true|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |false|
@@ -120,6 +121,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|x-field-extra-annotation|List of custom annotations to be added to property|FIELD|null
|x-spring-paginated|Add org.springframework.data.domain.Pageable to controller method. Can be used to handle page & size query parameters|OPERATION|false
|x-version-param|Marker property that tells that this parameter would be used for endpoint versioning. Applicable for headers & query params. true/false|OPERATION_PARAMETER|null
|x-pattern-message|Add this property whenever you need to customize the invalidation error message for the regex pattern of a variable|FIELD|null
## IMPORT MAPPING

View File

@@ -49,6 +49,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|
|errorObjectType|Error Object type. (This option is for okhttp-gson-next-gen only)| |null|
|fullJavaUtil|whether to use fully qualified name for classes under java.util. This option only works for Java API client| |false|
|generateClientAsBean|For resttemplate, configure whether to create `ApiClient.java` and Apis clients as bean (with `@Component` annotation).| |false|
|gradleProperties|Append additional Gradle properties to the gradle.properties file| |null|
|groupId|groupId in generated pom.xml| |org.openapitools|
|hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |false|

View File

@@ -258,7 +258,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| ---- | --------- | ---------- |
|BasicAuth|✓|OAS2,OAS3
|ApiKey|✓|OAS2,OAS3
|OpenIDConnect||OAS3
|OpenIDConnect||OAS3
|BearerToken|✓|OAS3
|OAuth2_Implicit|✓|OAS2,OAS3
|OAuth2_Password|✓|OAS2,OAS3

View File

@@ -204,7 +204,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| ---- | --------- | ---------- |
|BasicAuth|✓|OAS2,OAS3
|ApiKey|✓|OAS2,OAS3
|OpenIDConnect||OAS3
|OpenIDConnect||OAS3
|BearerToken|✓|OAS3
|OAuth2_Implicit|✓|OAS2,OAS3
|OAuth2_Password|✓|OAS2,OAS3

View File

@@ -259,7 +259,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| ---- | --------- | ---------- |
|BasicAuth|✓|OAS2,OAS3
|ApiKey|✓|OAS2,OAS3
|OpenIDConnect||OAS3
|OpenIDConnect||OAS3
|BearerToken|✓|OAS3
|OAuth2_Implicit|✓|OAS2,OAS3
|OAuth2_Password|✓|OAS2,OAS3

View File

@@ -78,6 +78,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|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|
|useMicroProfileOpenAPIAnnotations|Whether to generate Microprofile OpenAPI annotations. Only valid when library is set to quarkus.| |false|
|useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |false|
|useSwaggerAnnotations|Whether to generate Swagger annotations.| |true|
|useTags|use tags for creating interface and controller classnames| |false|

View File

@@ -78,6 +78,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|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|
|useMicroProfileOpenAPIAnnotations|Whether to generate Microprofile OpenAPI annotations. Only valid when library is set to quarkus.| |false|
|useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |false|
|useSwaggerAnnotations|Whether to generate Swagger annotations.| |true|
|useTags|use tags for creating interface and controller classnames| |false|

View File

@@ -151,7 +151,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| ---- | --------- | ---------- |
|BasicAuth|✓|OAS2,OAS3
|ApiKey|✓|OAS2,OAS3
|OpenIDConnect||OAS3
|OpenIDConnect||OAS3
|BearerToken|✓|OAS3
|OAuth2_Implicit|✓|OAS2,OAS3
|OAuth2_Password|✓|OAS2,OAS3

View File

@@ -203,7 +203,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| ---- | --------- | ---------- |
|BasicAuth|✓|OAS2,OAS3
|ApiKey|✓|OAS2,OAS3
|OpenIDConnect||OAS3
|OpenIDConnect||OAS3
|BearerToken|✓|OAS3
|OAuth2_Implicit|✗|OAS2,OAS3
|OAuth2_Password|✗|OAS2,OAS3

View File

@@ -202,7 +202,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| ---- | --------- | ---------- |
|BasicAuth|✓|OAS2,OAS3
|ApiKey|✓|OAS2,OAS3
|OpenIDConnect||OAS3
|OpenIDConnect||OAS3
|BearerToken|✓|OAS3
|OAuth2_Implicit|✗|OAS2,OAS3
|OAuth2_Password|✗|OAS2,OAS3

View File

@@ -151,7 +151,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| ---- | --------- | ---------- |
|BasicAuth|✓|OAS2,OAS3
|ApiKey|✓|OAS2,OAS3
|OpenIDConnect||OAS3
|OpenIDConnect||OAS3
|BearerToken|✓|OAS3
|OAuth2_Implicit|✓|OAS2,OAS3
|OAuth2_Password|✓|OAS2,OAS3

View File

@@ -26,6 +26,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|artifactVersion|Generated artifact's package version.| |1.0.0|
|basePackage|base package (invokerPackage) for generated code| |org.openapitools|
|beanQualifiers|Whether to add fully-qualifier class names as bean qualifiers in @Component and @RestController annotations. May be used to prevent bean names clash if multiple generated libraries (contexts) added to single project.| |false|
|configPackage|configuration package for generated code| |org.openapitools.configuration|
|delegatePattern|Whether to generate the server files using the delegate pattern| |false|
|documentationProvider|Select the OpenAPI documentation provider.|<dl><dt>**none**</dt><dd>Do not publish an OpenAPI specification.</dd><dt>**source**</dt><dd>Publish the original input OpenAPI specification.</dd><dt>**springfox**</dt><dd>Generate an OpenAPI 2 (fka Swagger RESTful API Documentation Specification) specification using SpringFox 2.x. Deprecated (for removal); use springdoc instead.</dd><dt>**springdoc**</dt><dd>Generate an OpenAPI 3 specification using SpringDoc.</dd></dl>|springdoc|
|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |camelCase|
@@ -33,7 +34,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|gradleBuildFile|generate a gradle build file using the Kotlin DSL| |true|
|groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools|
|interfaceOnly|Whether to generate only API interface stubs without the server files.| |false|
|library|library template (sub-template)|<dl><dt>**spring-boot**</dt><dd>Spring-boot Server application.</dd></dl>|spring-boot|
|library|library template (sub-template)|<dl><dt>**spring-boot**</dt><dd>Spring-boot Server application.</dd><dt>**spring-cloud**</dt><dd>Spring-Cloud-Feign client with Spring-Boot auto-configured settings.</dd></dl>|spring-boot|
|modelMutable|Create mutable models| |false|
|modelPackage|model package for generated code| |org.openapitools.model|
|packageName|Generated artifact package name.| |org.openapitools|
@@ -50,6 +51,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|sourceFolder|source folder for generated code| |src/main/kotlin|
|title|server title name or client service name| |OpenAPI Kotlin Spring|
|useBeanValidation|Use BeanValidation API annotations to validate data types| |true|
|useFeignClientUrl|Whether to generate Feign client with url parameter.| |true|
|useSpringBoot3|Generate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports). Enabling this option will also enable `useJakartaEe`.| |false|
|useSwaggerUI|Open the OpenApi specification in swagger-ui. Will also import and configure needed dependencies| |true|
|useTags|Whether to use tags for creating interface and controller class names| |false|

View File

@@ -168,7 +168,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| ---- | --------- | ---------- |
|BasicAuth|✓|OAS2,OAS3
|ApiKey|✓|OAS2,OAS3
|OpenIDConnect||OAS3
|OpenIDConnect||OAS3
|BearerToken|✓|OAS3
|OAuth2_Implicit|✓|OAS2,OAS3
|OAuth2_Password|✓|OAS2,OAS3

244
docs/generators/n4js.md Normal file
View File

@@ -0,0 +1,244 @@
---
title: Documentation for the n4js Generator
---
## METADATA
| Property | Value | Notes |
| -------- | ----- | ----- |
| generator name | n4js | pass this to the generate command after -g |
| generator stability | BETA | |
| generator type | CLIENT | |
| generator language | Java | |
| generator default templating engine | mustache | |
| helpTxt | Generates a n4js client. | |
## CONFIG OPTIONS
These options may be applied as additional-properties (cli) or configOptions (plugins). Refer to [configuration docs](https://openapi-generator.tech/docs/configuration) for more details.
| Option | Description | Values | Default |
| ------ | ----------- | ------ | ------- |
|apiNamePrefix|Prefix that will be appended to all API names ('tags'). Default: empty string. e.g. Pet =&gt; Pet.| |null|
|apiPackage|package for generated api classes| |null|
|checkRequiredParamsNotNull|Iff true null-checks are performed for required parameters.| |null|
|checkSuperfluousBodyProps|Iff true a new copy of the given body object is transmitted. This copy only contains those properties defined in its model specification.| |null|
|generateDefaultApiExecuter|Iff true a default implementation of the api executer interface is generated.| |null|
|modelPackage|package for generated models| |null|
## IMPORT MAPPING
| Type/Alias | Imports |
| ---------- | ------- |
## INSTANTIATION TYPES
| Type/Alias | Instantiated By |
| ---------- | --------------- |
## LANGUAGE PRIMITIVES
<ul class="column-ul">
<li>Array</li>
<li>Error</li>
<li>Object</li>
<li>String</li>
<li>any</li>
<li>any+</li>
<li>boolean</li>
<li>int</li>
<li>number</li>
<li>object</li>
<li>string</li>
</ul>
## RESERVED WORDS
<ul class="column-ul">
<li>abstract</li>
<li>await</li>
<li>boolean</li>
<li>break</li>
<li>byte</li>
<li>case</li>
<li>catch</li>
<li>char</li>
<li>class</li>
<li>const</li>
<li>continue</li>
<li>debugger</li>
<li>default</li>
<li>delete</li>
<li>do</li>
<li>double</li>
<li>else</li>
<li>enum</li>
<li>export</li>
<li>extends</li>
<li>false</li>
<li>final</li>
<li>finally</li>
<li>float</li>
<li>for</li>
<li>formParams</li>
<li>function</li>
<li>goto</li>
<li>headerParams</li>
<li>if</li>
<li>implements</li>
<li>import</li>
<li>in</li>
<li>instanceof</li>
<li>int</li>
<li>interface</li>
<li>let</li>
<li>long</li>
<li>native</li>
<li>new</li>
<li>null</li>
<li>package</li>
<li>private</li>
<li>protected</li>
<li>public</li>
<li>queryParameters</li>
<li>requestOptions</li>
<li>return</li>
<li>short</li>
<li>static</li>
<li>super</li>
<li>switch</li>
<li>synchronized</li>
<li>this</li>
<li>throw</li>
<li>transient</li>
<li>true</li>
<li>try</li>
<li>typeof</li>
<li>useFormData</li>
<li>var</li>
<li>varLocalDeferred</li>
<li>varLocalPath</li>
<li>void</li>
<li>volatile</li>
<li>while</li>
<li>with</li>
<li>yield</li>
</ul>
## FEATURE SET
### Client Modification Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|BasePath|✗|ToolingExtension
|Authorizations|✗|ToolingExtension
|UserAgent|✗|ToolingExtension
|MockServer|✗|ToolingExtension
### Data Type Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Custom|✗|OAS2,OAS3
|Int32|✓|OAS2,OAS3
|Int64|✓|OAS2,OAS3
|Float|✓|OAS2,OAS3
|Double|✓|OAS2,OAS3
|Decimal|✓|ToolingExtension
|String|✓|OAS2,OAS3
|Byte|✓|OAS2,OAS3
|Binary|✓|OAS2,OAS3
|Boolean|✓|OAS2,OAS3
|Date|✓|OAS2,OAS3
|DateTime|✓|OAS2,OAS3
|Password|✓|OAS2,OAS3
|File|✓|OAS2
|Uuid|✗|
|Array|✓|OAS2,OAS3
|Null|✗|OAS3
|AnyType|✗|OAS2,OAS3
|Object|✓|OAS2,OAS3
|Maps|✓|ToolingExtension
|CollectionFormat|✓|OAS2
|CollectionFormatMulti|✓|OAS2
|Enum|✓|OAS2,OAS3
|ArrayOfEnum|✓|ToolingExtension
|ArrayOfModel|✓|ToolingExtension
|ArrayOfCollectionOfPrimitives|✓|ToolingExtension
|ArrayOfCollectionOfModel|✓|ToolingExtension
|ArrayOfCollectionOfEnum|✓|ToolingExtension
|MapOfEnum|✓|ToolingExtension
|MapOfModel|✓|ToolingExtension
|MapOfCollectionOfPrimitives|✓|ToolingExtension
|MapOfCollectionOfModel|✓|ToolingExtension
|MapOfCollectionOfEnum|✓|ToolingExtension
### Documentation Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Readme|✗|ToolingExtension
|Model|✓|ToolingExtension
|Api|✓|ToolingExtension
### Global Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Host|✓|OAS2,OAS3
|BasePath|✓|OAS2,OAS3
|Info|✓|OAS2,OAS3
|Schemes|✗|OAS2,OAS3
|PartialSchemes|✓|OAS2,OAS3
|Consumes|✓|OAS2
|Produces|✓|OAS2
|ExternalDocumentation|✓|OAS2,OAS3
|Examples|✓|OAS2,OAS3
|XMLStructureDefinitions|✗|OAS2,OAS3
|MultiServer|✗|OAS3
|ParameterizedServer|✗|OAS3
|ParameterStyling|✗|OAS3
|Callbacks|✓|OAS3
|LinkObjects|✗|OAS3
### Parameter Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Path|✓|OAS2,OAS3
|Query|✓|OAS2,OAS3
|Header|✓|OAS2,OAS3
|Body|✓|OAS2
|FormUnencoded|✓|OAS2
|FormMultipart|✓|OAS2
|Cookie|✓|OAS3
### Schema Support Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Simple|✓|OAS2,OAS3
|Composite|✓|OAS2,OAS3
|Polymorphism|✓|OAS2,OAS3
|Union|✗|OAS3
|allOf|✗|OAS2,OAS3
|anyOf|✗|OAS3
|oneOf|✗|OAS3
|not|✗|OAS3
### Security Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|BasicAuth|✓|OAS2,OAS3
|ApiKey|✓|OAS2,OAS3
|OpenIDConnect|✓|OAS3
|BearerToken|✓|OAS3
|OAuth2_Implicit|✓|OAS2,OAS3
|OAuth2_Password|✓|OAS2,OAS3
|OAuth2_ClientCredentials|✓|OAS2,OAS3
|OAuth2_AuthorizationCode|✓|OAS2,OAS3
### Wire Format Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|JSON|✓|OAS2,OAS3
|XML|✓|OAS2,OAS3
|PROTOBUF|✗|ToolingExtension
|Custom|✗|OAS2,OAS3

View File

@@ -150,7 +150,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| ---- | --------- | ---------- |
|BasicAuth|✓|OAS2,OAS3
|ApiKey|✓|OAS2,OAS3
|OpenIDConnect||OAS3
|OpenIDConnect||OAS3
|BearerToken|✓|OAS3
|OAuth2_Implicit|✓|OAS2,OAS3
|OAuth2_Password|✓|OAS2,OAS3

View File

@@ -217,7 +217,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| ---- | --------- | ---------- |
|BasicAuth|✓|OAS2,OAS3
|ApiKey|✓|OAS2,OAS3
|OpenIDConnect||OAS3
|OpenIDConnect||OAS3
|BearerToken|✓|OAS3
|OAuth2_Implicit|✓|OAS2,OAS3
|OAuth2_Password|✓|OAS2,OAS3

View File

@@ -223,7 +223,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| ---- | --------- | ---------- |
|BasicAuth|✓|OAS2,OAS3
|ApiKey|✓|OAS2,OAS3
|OpenIDConnect||OAS3
|OpenIDConnect||OAS3
|BearerToken|✓|OAS3
|OAuth2_Implicit|✓|OAS2,OAS3
|OAuth2_Password|✓|OAS2,OAS3

View File

@@ -7,7 +7,7 @@ title: Documentation for the python-nextgen Generator
| Property | Value | Notes |
| -------- | ----- | ----- |
| generator name | python-nextgen | pass this to the generate command after -g |
| generator stability | BETA | |
| generator stability | STABLE | |
| generator type | CLIENT | |
| generator language | Python | |
| generator language version | 3.7+ | |

View File

@@ -87,6 +87,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|title|server title name or client service name| |OpenAPI Spring|
|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|
|useEnumCaseInsensitive|Use `equalsIgnoreCase` when String for enum comparison| |false|
|useFeignClientUrl|Whether to generate Feign client with url parameter.| |true|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |false|
@@ -113,6 +114,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|x-field-extra-annotation|List of custom annotations to be added to property|FIELD|null
|x-spring-paginated|Add org.springframework.data.domain.Pageable to controller method. Can be used to handle page & size query parameters|OPERATION|false
|x-version-param|Marker property that tells that this parameter would be used for endpoint versioning. Applicable for headers & query params. true/false|OPERATION_PARAMETER|null
|x-pattern-message|Add this property whenever you need to customize the invalidation error message for the regex pattern of a variable|FIELD|null
## IMPORT MAPPING

View File

@@ -339,7 +339,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| ---- | --------- | ---------- |
|BasicAuth|✓|OAS2,OAS3
|ApiKey|✓|OAS2,OAS3
|OpenIDConnect||OAS3
|OpenIDConnect||OAS3
|BearerToken|✓|OAS3
|OAuth2_Implicit|✓|OAS2,OAS3
|OAuth2_Password|✓|OAS2,OAS3

View File

@@ -156,7 +156,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| ---- | --------- | ---------- |
|BasicAuth|✓|OAS2,OAS3
|ApiKey|✓|OAS2,OAS3
|OpenIDConnect||OAS3
|OpenIDConnect||OAS3
|BearerToken|✓|OAS3
|OAuth2_Implicit|✓|OAS2,OAS3
|OAuth2_Password|✓|OAS2,OAS3

View File

@@ -0,0 +1,297 @@
---
title: Documentation for the xojo-client Generator
---
## METADATA
| Property | Value | Notes |
| -------- | ----- | ----- |
| generator name | xojo-client | pass this to the generate command after -g |
| generator stability | STABLE | |
| generator type | CLIENT | |
| generator language | Xojo | |
| generator default templating engine | mustache | |
| helpTxt | Generates a Xojo client module. | |
## CONFIG OPTIONS
These options may be applied as additional-properties (cli) or configOptions (plugins). Refer to [configuration docs](https://openapi-generator.tech/docs/configuration) for more details.
| Option | Description | Values | Default |
| ------ | ----------- | ------ | ------- |
|allowUnicodeIdentifiers|boolean, toggles whether unicode identifiers are allowed in names or not, default is false| |false|
|apiNamePrefix|Prefix that will be appended to all API classes. Default: empty string.| |null|
|apiPackage|package for generated api classes| |null|
|disallowAdditionalPropertiesIfNotPresent|If false, the 'additionalProperties' implementation (set to true by default) is compliant with the OAS and JSON schema specifications. If true (default), keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.|<dl><dt>**false**</dt><dd>The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.</dd><dt>**true**</dt><dd>Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.</dd></dl>|true|
|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true|
|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|
|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|
|library|library template (sub-template)|<dl><dt>**httpsocket**</dt><dd>[DEFAULT] HTTP client: HTTPSocket</dd></dl>|httpsocket|
|modelPackage|package for generated models| |null|
|nonPublicApi|Generates code with reduced access modifiers; allows embedding elsewhere without exposing non-public API calls to consumers.| |null|
|prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false|
|projectName|Project name in Xojo| |null|
|serializationLibrary|What serialization library to use: 'xoson' (default).| |xoson|
|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true|
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|supportsAsync|Generate code that supports async operations.| |null|
## IMPORT MAPPING
| Type/Alias | Imports |
| ---------- | ------- |
## INSTANTIATION TYPES
| Type/Alias | Instantiated By |
| ---------- | --------------- |
## LANGUAGE PRIMITIVES
<ul class="column-ul">
<li>Boolean</li>
<li>Color</li>
<li>Currency</li>
<li>Double</li>
<li>Int16</li>
<li>Int32</li>
<li>Int64</li>
<li>Int8</li>
<li>Integer</li>
<li>Single</li>
<li>String</li>
<li>UInt16</li>
<li>UInt32</li>
<li>UInt64</li>
<li>UInt8</li>
<li>UInteger</li>
</ul>
## RESERVED WORDS
<ul class="column-ul">
<li>#bad</li>
<li>#else</li>
<li>#elseif</li>
<li>#endif</li>
<li>#if</li>
<li>#pragma</li>
<li>#tag</li>
<li>addhandler</li>
<li>addressof</li>
<li>aggregates</li>
<li>and</li>
<li>apis</li>
<li>array</li>
<li>as</li>
<li>assigns</li>
<li>async</li>
<li>attributes</li>
<li>await</li>
<li>break</li>
<li>byref</li>
<li>byval</li>
<li>call</li>
<li>case</li>
<li>catch</li>
<li>class</li>
<li>column</li>
<li>const</li>
<li>continue</li>
<li>ctype</li>
<li>declare</li>
<li>delegate</li>
<li>dim</li>
<li>do</li>
<li>downto</li>
<li>each</li>
<li>else</li>
<li>elseif</li>
<li>end</li>
<li>enum</li>
<li>event</li>
<li>exception</li>
<li>exit</li>
<li>extends</li>
<li>false</li>
<li>file</li>
<li>finally</li>
<li>for</li>
<li>function</li>
<li>global</li>
<li>goto</li>
<li>handles</li>
<li>if</li>
<li>implements</li>
<li>in</li>
<li>inherits</li>
<li>interface</li>
<li>is</li>
<li>isa</li>
<li>lib</li>
<li>line</li>
<li>loop</li>
<li>me</li>
<li>mod</li>
<li>models</li>
<li>module</li>
<li>namespace</li>
<li>new</li>
<li>next</li>
<li>nil</li>
<li>not</li>
<li>of</li>
<li>optional</li>
<li>or</li>
<li>paramarray</li>
<li>private</li>
<li>property</li>
<li>protected</li>
<li>public</li>
<li>raise</li>
<li>raiseevent</li>
<li>redim</li>
<li>rem</li>
<li>removehandler</li>
<li>return</li>
<li>select</li>
<li>self</li>
<li>shared</li>
<li>soft</li>
<li>static</li>
<li>step</li>
<li>structure</li>
<li>sub</li>
<li>super</li>
<li>then</li>
<li>to</li>
<li>true</li>
<li>try</li>
<li>until</li>
<li>using</li>
<li>var</li>
<li>void</li>
<li>weakaddressof</li>
<li>wend</li>
<li>while</li>
<li>with</li>
<li>xor</li>
</ul>
## FEATURE SET
### Client Modification Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|BasePath|✗|ToolingExtension
|Authorizations|✗|ToolingExtension
|UserAgent|✗|ToolingExtension
|MockServer|✗|ToolingExtension
### Data Type Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Custom|✗|OAS2,OAS3
|Int32|✓|OAS2,OAS3
|Int64|✓|OAS2,OAS3
|Float|✓|OAS2,OAS3
|Double|✓|OAS2,OAS3
|Decimal|✓|ToolingExtension
|String|✓|OAS2,OAS3
|Byte|✓|OAS2,OAS3
|Binary|✓|OAS2,OAS3
|Boolean|✓|OAS2,OAS3
|Date|✓|OAS2,OAS3
|DateTime|✓|OAS2,OAS3
|Password|✓|OAS2,OAS3
|File|✓|OAS2
|Uuid|✗|
|Array|✓|OAS2,OAS3
|Null|✗|OAS3
|AnyType|✗|OAS2,OAS3
|Object|✓|OAS2,OAS3
|Maps|✓|ToolingExtension
|CollectionFormat|✓|OAS2
|CollectionFormatMulti|✓|OAS2
|Enum|✓|OAS2,OAS3
|ArrayOfEnum|✓|ToolingExtension
|ArrayOfModel|✓|ToolingExtension
|ArrayOfCollectionOfPrimitives|✓|ToolingExtension
|ArrayOfCollectionOfModel|✓|ToolingExtension
|ArrayOfCollectionOfEnum|✓|ToolingExtension
|MapOfEnum|✓|ToolingExtension
|MapOfModel|✓|ToolingExtension
|MapOfCollectionOfPrimitives|✓|ToolingExtension
|MapOfCollectionOfModel|✓|ToolingExtension
|MapOfCollectionOfEnum|✓|ToolingExtension
### Documentation Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Readme|✗|ToolingExtension
|Model|✓|ToolingExtension
|Api|✓|ToolingExtension
### Global Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Host|✓|OAS2,OAS3
|BasePath|✓|OAS2,OAS3
|Info|✓|OAS2,OAS3
|Schemes|✗|OAS2,OAS3
|PartialSchemes|✓|OAS2,OAS3
|Consumes|✓|OAS2
|Produces|✓|OAS2
|ExternalDocumentation|✓|OAS2,OAS3
|Examples|✓|OAS2,OAS3
|XMLStructureDefinitions|✗|OAS2,OAS3
|MultiServer|✗|OAS3
|ParameterizedServer|✗|OAS3
|ParameterStyling|✗|OAS3
|Callbacks|✓|OAS3
|LinkObjects|✗|OAS3
### Parameter Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Path|✓|OAS2,OAS3
|Query|✓|OAS2,OAS3
|Header|✓|OAS2,OAS3
|Body|✓|OAS2
|FormUnencoded|✓|OAS2
|FormMultipart|✓|OAS2
|Cookie|✓|OAS3
### Schema Support Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Simple|✓|OAS2,OAS3
|Composite|✓|OAS2,OAS3
|Polymorphism|✓|OAS2,OAS3
|Union|✗|OAS3
|allOf|✗|OAS2,OAS3
|anyOf|✗|OAS3
|oneOf|✗|OAS3
|not|✗|OAS3
### Security Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|BasicAuth|✓|OAS2,OAS3
|ApiKey|✓|OAS2,OAS3
|OpenIDConnect|✓|OAS3
|BearerToken|✓|OAS3
|OAuth2_Implicit|✓|OAS2,OAS3
|OAuth2_Password|✓|OAS2,OAS3
|OAuth2_ClientCredentials|✓|OAS2,OAS3
|OAuth2_AuthorizationCode|✓|OAS2,OAS3
### Wire Format Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|JSON|✓|OAS2,OAS3
|XML|✓|OAS2,OAS3
|PROTOBUF|✗|ToolingExtension
|Custom|✗|OAS2,OAS3

View File

@@ -4,7 +4,7 @@
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-project</artifactId>
<!-- RELEASE_VERSION -->
<version>6.6.0-SNAPSHOT</version>
<version>6.6.0</version>
<!-- /RELEASE_VERSION -->
<relativePath>../..</relativePath>
</parent>

View File

@@ -6,7 +6,7 @@
<artifactId>openapi-generator-project</artifactId>
<groupId>org.openapitools</groupId>
<!-- RELEASE_VERSION -->
<version>6.6.0-SNAPSHOT</version>
<version>6.6.0</version>
<!-- /RELEASE_VERSION -->
<relativePath>../..</relativePath>
</parent>

View File

@@ -154,6 +154,16 @@ apply plugin: 'org.openapi.generator'
|None
|The Open API 2.0/3.x specification location.
|inputSpecRootDirectory
|String
|None
|Local root folder with spec file(s)
|mergedFileName
|String
|None
|Name of the file that will contain all merged specs
|remoteInputSpec
|String
|None
@@ -224,11 +234,31 @@ apply plugin: 'org.openapi.generator'
|None
|Sets mappings between OpenAPI spec types and generated code types in the format of OpenAPIType=generatedType,OpenAPIType=generatedType. For example: `array=List,map=Map,string=String`. You can also have multiple occurrences of this option. To map a specified format, use type+format, e.g. string+password=EncryptedString will map `type: string, format: password` to `EncryptedString`.
|schemaMappings
|Map(String,String)
|None
|specifies mappings between the schema and the new name in the format of schema_a=Cat,schema_b=Bird. https://openapi-generator.tech/docs/customization/#schema-mapping
|inlineSchemaNameMappings
|Map(String,String)
|None
|specifies mappings between the inline schema name and the new name in the format of inline_object_2=Cat,inline_object_5=Bird.
|inlineSchemaNameDefaults
|Map(String,String)
|None
|specifies the default values used when naming inline schema as such array items in the format of arrayItemSuffix=_inner,mapItemSuffix=_value. ONLY arrayItemSuffix, mapItemSuffix are supported at the moment. `SKIP_SCHEMA_REUSE=true` is a special value to skip reusing inline schemas.
|additionalProperties
|Map(String,Any)
|None
|Sets additional properties that can be referenced by the mustache templates.
|serverVariables
|Map(String,String)
|None
|Sets server variable for server URL template substitution, in the format of name=value,name=value. You can also have multiple occurrences of this option.
|languageSpecificPrimitives
|List(String)
|None
@@ -352,7 +382,7 @@ apply plugin: 'org.openapi.generator'
|configOptions
|Map(String,String)
|None
|A map of options specific to a generator. To see the full list of generator-specified parameters, please refer to [generators docs](https://github.com/OpenAPITools/openapi-generator/blob/master/docs/generators.md). Note that any config options from a generator specific document may go here, and some generators may duplicate other options which are siblings to `configOptions`.
|A map of options specific to a generator. To see the full list of generator-specified parameters, please refer to https://github.com/OpenAPITools/openapi-generator/blob/master/docs/generators.md[generators docs]. Note that any config options from a generator specific document may go here, and some generators may duplicate other options which are siblings to `configOptions`.
|logToStderr
|Boolean
@@ -369,6 +399,11 @@ apply plugin: 'org.openapi.generator'
|false
|To skip spec validation. When true, we will skip the default behavior of validating a spec before generation.
|openapiNormalizer
|Map(String,String)
|None
|specifies the rules to be enabled in OpenAPI normalizer in the form of RULE_1=true,RULE_2=original.
|generateAliasAsModel
|Boolean
|false

View File

@@ -1,5 +1,5 @@
# RELEASE_VERSION
openApiGeneratorVersion=6.6.0-SNAPSHOT
openApiGeneratorVersion=6.6.0
# /RELEASE_VERSION
# BEGIN placeholders

View File

@@ -4,7 +4,7 @@
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-project</artifactId>
<!-- RELEASE_VERSION -->
<version>6.6.0-SNAPSHOT</version>
<version>6.6.0</version>
<!-- /RELEASE_VERSION -->
<relativePath>../..</relativePath>
</parent>

View File

@@ -1,3 +1,3 @@
# RELEASE_VERSION
openApiGeneratorVersion=6.6.0-SNAPSHOT
openApiGeneratorVersion=6.6.0
# /RELEASE_VERSION

View File

@@ -106,7 +106,7 @@ open class GenerateTask : DefaultTask() {
val inputSpecRootDirectory = project.objects.property<String>();
/**
* Name of the file that will contains all merged specs
* Name of the file that will contain all merged specs
*/
@Input
@Optional

View File

@@ -45,8 +45,11 @@ mvn clean compile
|--------|----------|-------------|
| `verbose` | `openapi.generator.maven.plugin.verbose` | verbose mode (`false` by default)
| `inputSpec` | `openapi.generator.maven.plugin.inputSpec` | OpenAPI Spec file path
| `inputSpecRootDirectory` | `openapi.generator.maven.plugin.inputSpecRootDirectory` | Local root folder with spec file(s)
| `mergedFileName` | `openapi.generator.maven.plugin.mergedFileName` | Name of the file that will contain all merged specs
| `language` | `openapi.generator.maven.plugin.language` | target generation language (deprecated, replaced by `generatorName` as values here don't represent only 'language' any longer)
| `generatorName` | `openapi.generator.maven.plugin.generatorName` | target generator name
| `cleanupOutput` | `openapi.generator.maven.plugin.cleanupOutput` | Defines whether the output directory should be cleaned up before generating the output (`false` by default).
| `output` | `openapi.generator.maven.plugin.output` | target output path (default is `${project.build.directory}/generated-sources/openapi`. Can also be set globally through the `openapi.generator.maven.plugin.output` property)
| `gitHost` | `openapi.generator.maven.plugin.gitHost` | The git host, e.g. gitlab.com
| `gitUserId` | `openapi.generator.maven.plugin.gitUserId` | sets git information of the project
@@ -76,11 +79,15 @@ mvn clean compile
| `enablePostProcessFile` | `openapi.generator.maven.plugin.` | enable file post-processing hook
| `skipValidateSpec` | `openapi.generator.maven.plugin.skipValidateSpec` | Whether or not to skip validating the input spec prior to generation. By default, invalid specifications will result in an error.
| `strictSpec` | `openapi.generator.maven.plugin.strictSpec` | Whether or not to treat an input document strictly against the spec. 'MUST' and 'SHALL' wording in OpenAPI spec is strictly adhered to. e.g. when false, no fixes will be applied to documents which pass validation but don't follow the spec.
| `openapiNormalizer` | `openapi.generator.maven.plugin.openapiNormalizer` | specifies the rules to be enabled in OpenAPI normalizer in the form of RULE_1=true,RULE_2=original.
| `generateAliasAsModel` | `openapi.generator.maven.plugin.generateAliasAsModel` | generate alias (array, map) as model
| `configOptions` | N/A | a **map** of generator-specific parameters. To show a full list of generator-specified parameters (options), please use `configHelp` (explained below)
| `instantiationTypes` | `openapi.generator.maven.plugin.instantiationTypes` | sets instantiation type mappings in the format of type=instantiatedType,type=instantiatedType. For example (in Java): `array=ArrayList,map=HashMap`. In other words array types will get instantiated as ArrayList in generated code. You can also have multiple occurrences of this option
| `importMappings` | `openapi.generator.maven.plugin.importMappings` | specifies mappings between a given class and the import that should be used for that class in the format of type=import,type=import. You can also have multiple occurrences of this option
| `typeMappings` | `openapi.generator.maven.plugin.typeMappings` | sets mappings between OpenAPI spec types and generated code types in the format of OpenAPIType=generatedType,OpenAPIType=generatedType. For example: `array=List,map=Map,string=String`. You can also have multiple occurrences of this option. To map a specified format, use type+format, e.g. string+password=EncryptedString will map `type: string, format: password` to `EncryptedString`.
| `schemaMappings` | `openapi.generator.maven.plugin.schemaMappings` | specifies mappings between the schema and the new name in the format of schema_a=Cat,schema_b=Bird. https://openapi-generator.tech/docs/customization/#schema-mapping
| `inlineSchemaNameMappings` | `openapi.generator.maven.plugin.inlineSchemaNameMappings` | specifies mappings between the inline schema name and the new name in the format of inline_object_2=Cat,inline_object_5=Bird.
| `inlineSchemaNameDefaults` | `openapi.generator.maven.plugin.inlineSchemaNameDefaults` | specifies the default values used when naming inline schema as such array items in the format of arrayItemSuffix=_inner,mapItemSuffix=_value. ONLY arrayItemSuffix, mapItemSuffix are supported at the moment. `SKIP_SCHEMA_REUSE=true` is a special value to skip reusing inline schemas.
| `languageSpecificPrimitives` | `openapi.generator.maven.plugin.languageSpecificPrimitives` | specifies additional language specific primitive types in the format of type1,type2,type3,type3. For example: `String,boolean,Boolean,Double`. You can also have multiple occurrences of this option
| `additionalProperties` | `openapi.generator.maven.plugin.additionalProperties` | sets additional properties that can be referenced by the mustache templates in the format of name=value,name=value. You can also have multiple occurrences of this option
| `serverVariableOverrides` | `openapi.generator.maven.plugin.serverVariableOverrides` | A map of server variable overrides for specs that support server URL templating

View File

@@ -13,7 +13,7 @@
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<!-- RELEASE_VERSION -->
<version>6.6.0-SNAPSHOT</version>
<version>6.6.0</version>
<!-- /RELEASE_VERSION -->
<executions>
<execution>

View File

@@ -15,7 +15,7 @@
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<!-- RELEASE_VERSION -->
<version>6.6.0-SNAPSHOT</version>
<version>6.6.0</version>
<!-- /RELEASE_VERSION -->
<executions>
<execution>

View File

@@ -19,7 +19,7 @@
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<!-- RELEASE_VERSION -->
<version>6.6.0-SNAPSHOT</version>
<version>6.6.0</version>
<!-- /RELEASE_VERSION -->
<dependencies>
<dependency>

View File

@@ -13,7 +13,7 @@
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<!-- RELEASE_VERSION -->
<version>6.6.0-SNAPSHOT</version>
<version>6.6.0</version>
<!-- /RELEASE_VERSION -->
<executions>
<execution>

View File

@@ -13,7 +13,7 @@
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<!-- RELEASE_VERSION -->
<version>6.6.0-SNAPSHOT</version>
<version>6.6.0</version>
<!-- /RELEASE_VERSION -->
<executions>
<execution>

View File

@@ -20,7 +20,7 @@
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<!-- RELEASE_VERSION -->
<version>6.6.0-SNAPSHOT</version>
<version>6.6.0</version>
<!-- /RELEASE_VERSION -->
<executions>
<execution>

View File

@@ -5,7 +5,7 @@
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-project</artifactId>
<!-- RELEASE_VERSION -->
<version>6.6.0-SNAPSHOT</version>
<version>6.6.0</version>
<!-- /RELEASE_VERSION -->
<relativePath>../..</relativePath>
</parent>

View File

@@ -116,7 +116,7 @@ public class CodeGenMojo extends AbstractMojo {
private String inputSpecRootDirectory;
/**
* Name of the file that will contains all merged specs
* Name of the file that will contain all merged specs
*/
@Parameter(name = "mergedFileName", property = "openapi.generator.maven.plugin.mergedFileName", defaultValue = "_merged_spec")
private String mergedFileName;

View File

@@ -4,7 +4,7 @@
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-project</artifactId>
<!-- RELEASE_VERSION -->
<version>6.6.0-SNAPSHOT</version>
<version>6.6.0</version>
<!-- /RELEASE_VERSION -->
<relativePath>../..</relativePath>
</parent>

View File

@@ -4,7 +4,7 @@
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-project</artifactId>
<!-- RELEASE_VERSION -->
<version>6.6.0-SNAPSHOT</version>
<version>6.6.0</version>
<!-- /RELEASE_VERSION -->
<relativePath>../..</relativePath>
</parent>
@@ -60,7 +60,7 @@
<generateGitPropertiesFilename>${project.build.outputDirectory}/openapi-generator-git.properties</generateGitPropertiesFilename>
<!-- REVIEWER NOTE: Never allow external contributors to change these without full clarification. -->
<includeOnlyProperties>
<includeOnlyProperty>^git.build.(time|version)$</includeOnlyProperty>
<includeOnlyProperty>^git.build.version$</includeOnlyProperty>
<includeOnlyProperty>^git.commit.id.(abbrev|full)$</includeOnlyProperty>
</includeOnlyProperties>
<commitIdGenerationMode>full</commitIdGenerationMode>

View File

@@ -101,6 +101,7 @@ public class CodegenModel implements IJsonSchemaValidationProperties {
public boolean hasChildren;
public boolean isMap;
public boolean isNull;
public boolean isVoid = false;
/**
* Indicates the OAS schema specifies "deprecated: true".
*/
@@ -880,6 +881,16 @@ public class CodegenModel implements IJsonSchemaValidationProperties {
this.isNull = isNull;
}
@Override
public boolean getIsVoid() {
return isVoid;
}
@Override
public void setIsVoid(boolean isVoid) {
this.isVoid = isVoid;
}
@Override
public boolean getAdditionalPropertiesIsAnyType() {
return additionalPropertiesIsAnyType;

View File

@@ -26,7 +26,7 @@ public class CodegenOperation {
public final List<CodegenProperty> responseHeaders = new ArrayList<CodegenProperty>();
public boolean hasAuthMethods, hasConsumes, hasProduces, hasParams, hasOptionalParams, hasRequiredParams,
returnTypeIsPrimitive, returnSimpleType, subresourceOperation, isMap,
isArray, isMultipart,
isArray, isMultipart, isVoid = false,
hasVersionHeaders = false, hasVersionQueryParams = false,
isResponseBinary = false, isResponseFile = false, isResponseOptional = false, hasReference = false, defaultReturnType = false,
isRestfulIndex, isRestfulShow, isRestfulCreate, isRestfulUpdate, isRestfulDestroy,
@@ -329,6 +329,7 @@ public class CodegenOperation {
sb.append(", returnProperty=").append(returnProperty);
sb.append(", isArray=").append(isArray);
sb.append(", isMultipart=").append(isMultipart);
sb.append(", isVoid=").append(isVoid);
sb.append(", isResponseBinary=").append(isResponseBinary);
sb.append(", isResponseFile=").append(isResponseFile);
sb.append(", isResponseFile=").append(isResponseOptional);
@@ -406,6 +407,7 @@ public class CodegenOperation {
isMap == that.isMap &&
isArray == that.isArray &&
isMultipart == that.isMultipart &&
isVoid == that.isVoid &&
isResponseBinary == that.isResponseBinary &&
isResponseFile == that.isResponseFile &&
isResponseOptional == that.isResponseOptional &&
@@ -471,7 +473,7 @@ public class CodegenOperation {
return Objects.hash(responseHeaders, hasAuthMethods, hasConsumes, hasProduces, hasParams, hasOptionalParams,
hasRequiredParams, returnTypeIsPrimitive, returnSimpleType, subresourceOperation, isMap,
isArray, isMultipart, isResponseBinary, isResponseFile, isResponseOptional, hasReference,
isArray, isMultipart, isVoid, isResponseBinary, isResponseFile, isResponseOptional, hasReference,
hasDefaultResponse, isRestfulIndex, isRestfulShow, isRestfulCreate, isRestfulUpdate, isRestfulDestroy,
isRestful, isDeprecated, isCallbackRequest, uniqueItems, path, operationId, returnType, httpMethod,
returnBaseType, returnContainer, summary, unescapedNotes, notes, baseName, defaultResponse,

View File

@@ -39,6 +39,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
public boolean isArray, isMap;
public boolean isFile;
public boolean isEnum;
public boolean isEnumRef; // true if the enum is a ref (model) but not defined inline
private boolean additionalPropertiesIsAnyType;
private boolean hasVars;
public List<String> _enum;
@@ -107,6 +108,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
private Integer maxProperties;
private Integer minProperties;
public boolean isNull;
public boolean isVoid = false;
private boolean hasRequired;
private boolean hasDiscriminatorWithNonEmptyMapping;
private CodegenComposedSchemas composedSchemas;
@@ -158,6 +160,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
output.enumDefaultValue = this.enumDefaultValue;
output.example = this.example;
output.isEnum = this.isEnum;
output.isEnumRef = this.isEnumRef;
output.maxProperties = this.maxProperties;
output.minProperties = this.minProperties;
output.maximum = this.maximum;
@@ -165,6 +168,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
output.pattern = this.pattern;
output.additionalProperties = this.additionalProperties;
output.isNull = this.isNull;
output.isVoid = this.isVoid;
output.setAdditionalPropertiesIsAnyType(this.getAdditionalPropertiesIsAnyType());
output.setHasVars(this.hasVars);
output.setHasRequired(this.hasRequired);
@@ -245,7 +249,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
@Override
public int hashCode() {
return Objects.hash(isFormParam, isQueryParam, isPathParam, isHeaderParam, isCookieParam, isBodyParam, isContainer, isCollectionFormatMulti, isPrimitiveType, isModel, isExplode, baseName, paramName, dataType, datatypeWithEnum, dataFormat, collectionFormat, description, unescapedDescription, baseType, defaultValue, enumDefaultValue, enumName, style, isDeepObject, isAllowEmptyValue, example, jsonSchema, isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isDecimal, isByteArray, isBinary, isBoolean, isDate, isDateTime, isUuid, isUri, isEmail, isPassword, isFreeFormObject, isAnyType, isArray, isMap, isFile, isEnum, _enum, allowableValues, items, mostInnerItems, additionalProperties, vars, requiredVars, vendorExtensions, hasValidation, getMaxProperties(), getMinProperties(), isNullable, isDeprecated, required, getMaximum(), getExclusiveMaximum(), getMinimum(), getExclusiveMinimum(), getMaxLength(), getMinLength(), getPattern(), getMaxItems(), getMinItems(), getUniqueItems(), contentType, multipleOf, isNull, additionalPropertiesIsAnyType, hasVars, hasRequired, isShort, isUnboundedInteger, hasDiscriminatorWithNonEmptyMapping, composedSchemas, hasMultipleTypes, schema, content, requiredVarsMap, ref, uniqueItemsBoolean, schemaIsFromAdditionalProperties);
return Objects.hash(isFormParam, isQueryParam, isPathParam, isHeaderParam, isCookieParam, isBodyParam, isContainer, isCollectionFormatMulti, isPrimitiveType, isModel, isExplode, baseName, paramName, dataType, datatypeWithEnum, dataFormat, collectionFormat, description, unescapedDescription, baseType, defaultValue, enumDefaultValue, enumName, style, isDeepObject, isAllowEmptyValue, example, jsonSchema, isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isDecimal, isByteArray, isBinary, isBoolean, isDate, isDateTime, isUuid, isUri, isEmail, isPassword, isFreeFormObject, isAnyType, isArray, isMap, isFile, isEnum, isEnumRef, _enum, allowableValues, items, mostInnerItems, additionalProperties, vars, requiredVars, vendorExtensions, hasValidation, getMaxProperties(), getMinProperties(), isNullable, isDeprecated, required, getMaximum(), getExclusiveMaximum(), getMinimum(), getExclusiveMinimum(), getMaxLength(), getMinLength(), getPattern(), getMaxItems(), getMinItems(), getUniqueItems(), contentType, multipleOf, isNull, isVoid, additionalPropertiesIsAnyType, hasVars, hasRequired, isShort, isUnboundedInteger, hasDiscriminatorWithNonEmptyMapping, composedSchemas, hasMultipleTypes, schema, content, requiredVarsMap, ref, uniqueItemsBoolean, schemaIsFromAdditionalProperties);
}
@Override
@@ -289,11 +293,13 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
isMap == that.isMap &&
isFile == that.isFile &&
isEnum == that.isEnum &&
isEnumRef == that.isEnumRef &&
hasValidation == that.hasValidation &&
isNullable == that.isNullable &&
isDeprecated == that.isDeprecated &&
required == that.required &&
isNull == that.isNull &&
isVoid == that.isVoid &&
hasDiscriminatorWithNonEmptyMapping == that.getHasDiscriminatorWithNonEmptyMapping() &&
getAdditionalPropertiesIsAnyType() == that.getAdditionalPropertiesIsAnyType() &&
hasMultipleTypes == that.getHasMultipleTypes() &&
@@ -347,6 +353,15 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
Objects.equals(multipleOf, that.multipleOf);
}
/**
* Return true if it's an enum (inline or ref)
*
* @return true if it's an enum (inline or ref)
*/
public boolean getIsEnumOrRef() {
return isEnum || isEnumRef;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("CodegenParameter{");
@@ -403,6 +418,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
sb.append(", isMap=").append(isMap);
sb.append(", isFile=").append(isFile);
sb.append(", isEnum=").append(isEnum);
sb.append(", isEnumRef=").append(isEnumRef);
sb.append(", _enum=").append(_enum);
sb.append(", allowableValues=").append(allowableValues);
sb.append(", items=").append(items);
@@ -431,6 +447,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
sb.append(", contentType=").append(contentType);
sb.append(", multipleOf=").append(multipleOf);
sb.append(", isNull=").append(isNull);
sb.append(", isVoid=").append(isVoid);
sb.append(", getAdditionalPropertiesIsAnyType=").append(additionalPropertiesIsAnyType);
sb.append(", getHasVars=").append(hasVars);
sb.append(", getHasRequired=").append(hasRequired);
@@ -454,7 +471,8 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
// use schema.setContains or content.mediaType.schema.setContains instead of this
@Override
public void setContains(CodegenProperty contains) {}
public void setContains(CodegenProperty contains) {
}
// use schema.getDependentRequired or content.mediaType.schema.getDependentRequired instead of this
@Override
@@ -464,7 +482,8 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
// use schema.setDependentRequired or content.mediaType.schema.setDependentRequired instead of this
@Override
public void setDependentRequired(LinkedHashMap<String, List<String>> dependentRequired) {}
public void setDependentRequired(LinkedHashMap<String, List<String>> dependentRequired) {
}
// use schema.getIsBooleanSchemaTrue or content.mediaType.schema.getIsBooleanSchemaTrue instead of this
@Override
@@ -474,7 +493,8 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
// use schema.setIsBooleanSchemaTrue or content.mediaType.schema.setIsBooleanSchemaTrue instead of this
@Override
public void setIsBooleanSchemaTrue(boolean isBooleanSchemaTrue) {}
public void setIsBooleanSchemaTrue(boolean isBooleanSchemaTrue) {
}
// use schema.getIsBooleanSchemaFalse or content.mediaType.schema.getIsBooleanSchemaFalse instead of this
@Override
@@ -484,7 +504,8 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
// use schema.setIsBooleanSchemaFalse or content.mediaType.schema.setIsBooleanSchemaFalse instead of this
@Override
public void setIsBooleanSchemaFalse(boolean isBooleanSchemaFalse) {}
public void setIsBooleanSchemaFalse(boolean isBooleanSchemaFalse) {
}
// use schema.getFormat or content.mediaType.schema.getFormat instead of this
@Override
@@ -494,7 +515,8 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
// use schema.setFormat or content.mediaType.schema.setFormat instead of this
@Override
public void setFormat(String format) {}
public void setFormat(String format) {
}
@Override
public String getPattern() {
@@ -766,7 +788,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
this.requiredVars = requiredVars;
}
public boolean requiredAndNotNullable(){
public boolean requiredAndNotNullable() {
return required && !isNullable;
}
@@ -784,6 +806,16 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
this.isNull = isNull;
}
@Override
public boolean getIsVoid() {
return isVoid;
}
@Override
public void setIsVoid(boolean isVoid) {
this.isVoid = isVoid;
}
@Override
public boolean getHasValidation() {
return hasValidation;
@@ -908,16 +940,24 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
}
@Override
public Map<String, CodegenProperty> getRequiredVarsMap() { return requiredVarsMap; }
public Map<String, CodegenProperty> getRequiredVarsMap() {
return requiredVarsMap;
}
@Override
public void setRequiredVarsMap(Map<String, CodegenProperty> requiredVarsMap) { this.requiredVarsMap=requiredVarsMap; }
public void setRequiredVarsMap(Map<String, CodegenProperty> requiredVarsMap) {
this.requiredVarsMap = requiredVarsMap;
}
@Override
public String getRef() { return ref; }
public String getRef() {
return ref;
}
@Override
public void setRef(String ref) { this.ref=ref; }
public void setRef(String ref) {
this.ref = ref;
}
@Override
public boolean getSchemaIsFromAdditionalProperties() {

View File

@@ -136,6 +136,7 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti
public boolean isEmail;
public boolean isPassword;
public boolean isNull;
public boolean isVoid = false;
/**
* The type is a free-form object, i.e. it is a map of string to values with no declared properties.
* A OAS free-form schema may include the 'additionalProperties' attribute, which puts a constraint
@@ -258,6 +259,8 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti
this.isBooleanSchemaFalse = isBooleanSchemaFalse;
}
public String getOpenApiType() { return openApiType; }
public String getBaseName() {
return baseName;
}
@@ -875,6 +878,16 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti
this.isNull = isNull;
}
@Override
public boolean getIsVoid() {
return isVoid;
}
@Override
public void setIsVoid(boolean isVoid) {
this.isVoid = isVoid;
}
@Override
public boolean getHasValidation() {
return hasValidation;
@@ -1096,6 +1109,7 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti
sb.append(", xmlNamespace='").append(xmlNamespace).append('\'');
sb.append(", isXmlWrapped=").append(isXmlWrapped);
sb.append(", isNull=").append(isNull);
sb.append(", isVoid=").append(isVoid);
sb.append(", getAdditionalPropertiesIsAnyType=").append(getAdditionalPropertiesIsAnyType());
sb.append(", getHasVars=").append(getHasVars());
sb.append(", getHasRequired=").append(getHasRequired());
@@ -1167,6 +1181,7 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti
isXmlAttribute == that.isXmlAttribute &&
isXmlWrapped == that.isXmlWrapped &&
isNull == that.isNull &&
isVoid == that.isVoid &&
hasMultipleTypes == that.getHasMultipleTypes() &&
hasDiscriminatorWithNonEmptyMapping == that.hasDiscriminatorWithNonEmptyMapping &&
isBooleanSchemaTrue == that.getIsBooleanSchemaTrue() &&
@@ -1243,7 +1258,7 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti
allowableValues, items, mostInnerItems, additionalProperties, vars, requiredVars,
vendorExtensions, hasValidation, isInherited, discriminatorValue, nameInCamelCase,
nameInSnakeCase, enumName, maxItems, minItems, isXmlAttribute, xmlPrefix, xmlName,
xmlNamespace, isXmlWrapped, isNull, additionalPropertiesIsAnyType, hasVars, hasRequired,
xmlNamespace, isXmlWrapped, isNull, isVoid, additionalPropertiesIsAnyType, hasVars, hasRequired,
hasDiscriminatorWithNonEmptyMapping, composedSchemas, hasMultipleTypes, requiredVarsMap,
ref, uniqueItemsBoolean, schemaIsFromAdditionalProperties, isBooleanSchemaTrue, isBooleanSchemaFalse,
format, dependentRequired, contains);

View File

@@ -62,6 +62,7 @@ public class CodegenResponse implements IJsonSchemaValidationProperties {
public boolean isBinary = false;
public boolean isFile = false;
public boolean isNull;
public boolean isVoid = false;
public Object schema;
public String jsonSchema;
public Map<String, Object> vendorExtensions = new HashMap<String, Object>();
@@ -101,7 +102,7 @@ public class CodegenResponse implements IJsonSchemaValidationProperties {
isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isDecimal, isByteArray, isBoolean, isDate,
isDateTime, isUuid, isEmail, isPassword, isModel, isFreeFormObject, isAnyType, isDefault, simpleType, primitiveType,
isMap, isArray, isBinary, isFile, schema, jsonSchema, vendorExtensions, items, additionalProperties,
vars, requiredVars, isNull, hasValidation, isShort, isUnboundedInteger,
vars, requiredVars, isNull, isVoid, hasValidation, isShort, isUnboundedInteger,
getMaxProperties(), getMinProperties(), uniqueItems, getMaxItems(), getMinItems(), getMaxLength(),
getMinLength(), exclusiveMinimum, exclusiveMaximum, getMinimum(), getMaximum(), getPattern(),
is1xx, is2xx, is3xx, is4xx, is5xx, additionalPropertiesIsAnyType, hasVars, hasRequired,
@@ -145,6 +146,7 @@ public class CodegenResponse implements IJsonSchemaValidationProperties {
items == that.items &&
additionalProperties == that.additionalProperties &&
isNull == that.isNull &&
isVoid == that.isVoid &&
hasValidation == that.hasValidation &&
is1xx == that.is1xx &&
is2xx == that.is2xx &&
@@ -603,6 +605,7 @@ public class CodegenResponse implements IJsonSchemaValidationProperties {
sb.append(", vars='").append(vars).append('\'');
sb.append(", requiredVars='").append(requiredVars).append('\'');
sb.append(", isNull='").append(isNull);
sb.append(", isVoid='").append(isVoid);
sb.append(", hasValidation='").append(hasValidation);
sb.append(", getAdditionalPropertiesIsAnyType=").append(additionalPropertiesIsAnyType);
sb.append(", getHasVars=").append(hasVars);
@@ -646,6 +649,16 @@ public class CodegenResponse implements IJsonSchemaValidationProperties {
this.isNull = isNull;
}
@Override
public boolean getIsVoid() {
return isVoid;
}
@Override
public void setIsVoid(boolean isVoid) {
this.isVoid = isVoid;
}
@Override
public boolean getHasValidation() {
return hasValidation;

View File

@@ -25,9 +25,10 @@ import java.util.Objects;
public class CodegenSecurity {
public String name;
public String description;
public String type;
public String scheme;
public Boolean isBasic, isOAuth, isApiKey;
public Boolean isBasic, isOAuth, isApiKey, isOpenId;
// is Basic is true for all http authentication type.
// Those are to differentiate basic and bearer authentication
// isHttpSignature is to support HTTP signature authorization scheme.
@@ -42,12 +43,15 @@ public class CodegenSecurity {
public String flow, authorizationUrl, tokenUrl, refreshUrl;
public List<Map<String, Object>> scopes;
public Boolean isCode, isPassword, isApplication, isImplicit;
// OpenId specific
public String openIdConnectUrl;
// Return a copy of the security object, filtering out any scopes from the passed-in list.
public CodegenSecurity filterByScopeNames(List<String> filterScopes) {
CodegenSecurity filteredSecurity = new CodegenSecurity();
// Copy all fields except the scopes.
filteredSecurity.name = name;
filteredSecurity.description = description;
filteredSecurity.type = type;
filteredSecurity.isBasic = isBasic;
filteredSecurity.isBasicBasic = isBasicBasic;
@@ -55,6 +59,7 @@ public class CodegenSecurity {
filteredSecurity.isBasicBearer = isBasicBearer;
filteredSecurity.isApiKey = isApiKey;
filteredSecurity.isOAuth = isOAuth;
filteredSecurity.isOpenId = isOpenId;
filteredSecurity.keyParamName = keyParamName;
filteredSecurity.isCode = isCode;
filteredSecurity.isImplicit = isImplicit;
@@ -67,6 +72,7 @@ public class CodegenSecurity {
filteredSecurity.tokenUrl = tokenUrl;
filteredSecurity.authorizationUrl = authorizationUrl;
filteredSecurity.refreshUrl = refreshUrl;
filteredSecurity.openIdConnectUrl = openIdConnectUrl;
// It is not possible to deep copy the extensions, as we have no idea what types they are.
// So the filtered method *will* refer to the original extensions, if any.
filteredSecurity.vendorExtensions = new HashMap<String, Object>(vendorExtensions);
@@ -93,10 +99,12 @@ public class CodegenSecurity {
if (o == null || getClass() != o.getClass()) return false;
CodegenSecurity that = (CodegenSecurity) o;
return Objects.equals(name, that.name) &&
Objects.equals(description, that.description) &&
Objects.equals(type, that.type) &&
Objects.equals(scheme, that.scheme) &&
Objects.equals(isBasic, that.isBasic) &&
Objects.equals(isOAuth, that.isOAuth) &&
Objects.equals(isOpenId, that.isOpenId) &&
Objects.equals(isApiKey, that.isApiKey) &&
Objects.equals(isBasicBasic, that.isBasicBasic) &&
Objects.equals(isHttpSignature, that.isHttpSignature) &&
@@ -115,26 +123,30 @@ public class CodegenSecurity {
Objects.equals(isCode, that.isCode) &&
Objects.equals(isPassword, that.isPassword) &&
Objects.equals(isApplication, that.isApplication) &&
Objects.equals(isImplicit, that.isImplicit);
Objects.equals(isImplicit, that.isImplicit) &&
Objects.equals(openIdConnectUrl, that.openIdConnectUrl);
}
@Override
public int hashCode() {
return Objects.hash(name, type, scheme, isBasic, isOAuth, isApiKey,
return Objects.hash(name, description, type, scheme, isBasic, isOAuth, isOpenId, isApiKey,
isBasicBasic, isHttpSignature, isBasicBearer, bearerFormat, vendorExtensions,
keyParamName, isKeyInQuery, isKeyInHeader, isKeyInCookie, flow,
authorizationUrl, tokenUrl, refreshUrl, scopes, isCode, isPassword, isApplication, isImplicit);
authorizationUrl, tokenUrl, refreshUrl, scopes, isCode, isPassword, isApplication, isImplicit,
openIdConnectUrl);
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("CodegenSecurity{");
sb.append("name='").append(name).append('\'');
sb.append("description='").append(description).append('\'');
sb.append(", type='").append(type).append('\'');
sb.append(", scheme='").append(scheme).append('\'');
sb.append(", isBasic=").append(isBasic);
sb.append(", isOAuth=").append(isOAuth);
sb.append(", isOpenIdConnect=").append(isOpenId);
sb.append(", isApiKey=").append(isApiKey);
sb.append(", isBasicBasic=").append(isBasicBasic);
sb.append(", isHttpSignature=").append(isHttpSignature);
@@ -154,6 +166,7 @@ public class CodegenSecurity {
sb.append(", isPassword=").append(isPassword);
sb.append(", isApplication=").append(isApplication);
sb.append(", isImplicit=").append(isImplicit);
sb.append(", openIdConnectUrl=").append(openIdConnectUrl);
sb.append('}');
return sb.toString();
}

View File

@@ -42,7 +42,6 @@ import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.servers.Server;
import io.swagger.v3.oas.models.servers.ServerVariable;
import io.swagger.v3.parser.util.SchemaTypeUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.text.StringEscapeUtils;
@@ -78,24 +77,6 @@ import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import io.swagger.v3.core.util.Json;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.PathItem;
import io.swagger.v3.oas.models.callbacks.Callback;
import io.swagger.v3.oas.models.examples.Example;
import io.swagger.v3.oas.models.headers.Header;
import io.swagger.v3.oas.models.media.*;
import io.swagger.v3.oas.models.parameters.*;
import io.swagger.v3.oas.models.responses.ApiResponse;
import io.swagger.v3.oas.models.responses.ApiResponses;
import io.swagger.v3.oas.models.security.OAuthFlow;
import io.swagger.v3.oas.models.security.OAuthFlows;
import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.servers.Server;
import io.swagger.v3.oas.models.servers.ServerVariable;
import io.swagger.v3.parser.util.SchemaTypeUtil;
import static org.openapitools.codegen.CodegenConstants.UNSUPPORTED_V310_SPEC_MSG;
import static org.openapitools.codegen.utils.OnceLogger.once;
import static org.openapitools.codegen.utils.StringUtils.*;
@@ -148,8 +129,8 @@ public class DefaultCodegen implements CodegenConfig {
.includeSecurityFeatures(
SecurityFeature.BasicAuth, SecurityFeature.ApiKey, SecurityFeature.BearerToken,
SecurityFeature.OAuth2_Implicit, SecurityFeature.OAuth2_Password,
SecurityFeature.OAuth2_ClientCredentials, SecurityFeature.OAuth2_AuthorizationCode
// OpenIDConnect not yet supported
SecurityFeature.OAuth2_ClientCredentials, SecurityFeature.OAuth2_AuthorizationCode,
SecurityFeature.OpenIDConnect
)
.includeWireFormatFeatures(
WireFormatFeature.JSON, WireFormatFeature.XML
@@ -5167,6 +5148,7 @@ public class DefaultCodegen implements CodegenConfig {
// enum
updateCodegenPropertyEnum(codegenProperty);
codegenParameter.isEnum = codegenProperty.isEnum;
codegenParameter.isEnumRef = codegenProperty.isEnumRef;
codegenParameter._enum = codegenProperty._enum;
codegenParameter.allowableValues = codegenProperty.allowableValues;
@@ -5292,7 +5274,7 @@ public class DefaultCodegen implements CodegenConfig {
final SecurityScheme securityScheme = securitySchemeMap.get(key);
if (SecurityScheme.Type.APIKEY.equals(securityScheme.getType())) {
final CodegenSecurity cs = defaultCodegenSecurity(key, securityScheme);
cs.isBasic = cs.isOAuth = false;
cs.isBasic = cs.isOAuth = cs.isOpenId = false;
cs.isApiKey = true;
cs.keyParamName = securityScheme.getName();
cs.isKeyInHeader = securityScheme.getIn() == SecurityScheme.In.HEADER;
@@ -5301,7 +5283,7 @@ public class DefaultCodegen implements CodegenConfig {
codegenSecurities.add(cs);
} else if (SecurityScheme.Type.HTTP.equals(securityScheme.getType())) {
final CodegenSecurity cs = defaultCodegenSecurity(key, securityScheme);
cs.isKeyInHeader = cs.isKeyInQuery = cs.isKeyInCookie = cs.isApiKey = cs.isOAuth = false;
cs.isKeyInHeader = cs.isKeyInQuery = cs.isKeyInCookie = cs.isApiKey = cs.isOAuth = cs.isOpenId = false;
cs.isBasic = true;
if ("basic".equalsIgnoreCase(securityScheme.getScheme())) {
cs.isBasicBasic = true;
@@ -5362,6 +5344,15 @@ public class DefaultCodegen implements CodegenConfig {
if (isFlowEmpty) {
once(LOGGER).error("Invalid flow definition defined in the security scheme: {}", flows);
}
} else if (SecurityScheme.Type.OPENIDCONNECT.equals(securityScheme.getType())) {
final CodegenSecurity cs = defaultCodegenSecurity(key, securityScheme);
cs.isKeyInHeader = cs.isKeyInQuery = cs.isKeyInCookie = cs.isApiKey = cs.isBasic = false;
cs.isOpenId = true;
cs.openIdConnectUrl = securityScheme.getOpenIdConnectUrl();
if (securityScheme.getFlows() != null) {
setOpenIdConnectInfo(cs, securityScheme.getFlows().getAuthorizationCode());
}
codegenSecurities.add(cs);
} else {
once(LOGGER).error("Unknown type `{}` found in the security definition `{}`.", securityScheme.getType(), securityScheme.getName());
}
@@ -5373,8 +5364,9 @@ public class DefaultCodegen implements CodegenConfig {
private CodegenSecurity defaultCodegenSecurity(String key, SecurityScheme securityScheme) {
final CodegenSecurity cs = CodegenModelFactory.newInstance(CodegenModelType.SECURITY);
cs.name = key;
cs.description = securityScheme.getDescription();
cs.type = securityScheme.getType().toString();
cs.isCode = cs.isPassword = cs.isApplication = cs.isImplicit = false;
cs.isCode = cs.isPassword = cs.isApplication = cs.isImplicit = cs.isOpenId = false;
cs.isHttpSignature = false;
cs.isBasicBasic = cs.isBasicBearer = false;
cs.scheme = securityScheme.getScheme();
@@ -5386,7 +5378,7 @@ public class DefaultCodegen implements CodegenConfig {
private CodegenSecurity defaultOauthCodegenSecurity(String key, SecurityScheme securityScheme) {
final CodegenSecurity cs = defaultCodegenSecurity(key, securityScheme);
cs.isKeyInHeader = cs.isKeyInQuery = cs.isKeyInCookie = cs.isApiKey = cs.isBasic = false;
cs.isKeyInHeader = cs.isKeyInQuery = cs.isKeyInCookie = cs.isApiKey = cs.isBasic = cs.isOpenId = false;
cs.isOAuth = true;
return cs;
}
@@ -6611,6 +6603,18 @@ public class DefaultCodegen implements CodegenConfig {
}
}
private void setOpenIdConnectInfo(CodegenSecurity codegenSecurity, OAuthFlow flow) {
if (flow.getScopes() != null && !flow.getScopes().isEmpty()) {
List<Map<String, Object>> scopes = new ArrayList<>();
for (Map.Entry<String, String> scopeEntry : flow.getScopes().entrySet()) {
Map<String, Object> scope = new HashMap<>();
scope.put("scope", scopeEntry.getKey());
scopes.add(scope);
}
codegenSecurity.scopes = scopes;
}
}
private void addConsumesInfo(Operation operation, CodegenOperation codegenOperation) {
RequestBody requestBody = ModelUtils.getReferencedRequestBody(this.openAPI, operation.getRequestBody());
if (requestBody == null || requestBody.getContent() == null || requestBody.getContent().isEmpty()) {
@@ -6824,6 +6828,7 @@ public class DefaultCodegen implements CodegenConfig {
// non-array/map
updateCodegenPropertyEnum(codegenProperty);
codegenParameter.isEnum = codegenProperty.isEnum;
codegenParameter.isEnumRef = codegenProperty.isEnumRef;
codegenParameter._enum = codegenProperty._enum;
codegenParameter.allowableValues = codegenProperty.allowableValues;
@@ -8033,11 +8038,20 @@ public class DefaultCodegen implements CodegenConfig {
return null;
}
List<CodegenProperty> xOf = new ArrayList<>();
Set<String> dataTypeSet = new HashSet<>(); // to keep track of dataType
int i = 0;
for (Schema xOfSchema : xOfCollection) {
CodegenProperty cp = fromProperty(collectionName + "_" + i, xOfSchema, false);
xOf.add(cp);
i += 1;
if (dataTypeSet.contains(cp.dataType)) {
// add "x-duplicated-data-type" to indicate if the dataType already occurs before
// in other sub-schemas of allOf/anyOf/oneOf
cp.vendorExtensions.putIfAbsent("x-duplicated-data-type", true);
} else {
dataTypeSet.add(cp.dataType);
}
}
return xOf;
}

View File

@@ -608,6 +608,20 @@ public class DefaultGenerator implements Generator {
operation.put("basePathWithoutHost", removeTrailingSlash(config.encodePath(url.getPath())));
operation.put("contextPath", contextPath);
operation.put("baseName", tag);
Optional.ofNullable(openAPI.getTags()).orElseGet(Collections::emptyList).stream()
.map(Tag::getName)
.filter(Objects::nonNull)
.filter(tag::equalsIgnoreCase)
.findFirst()
.ifPresent(tagName -> operation.put("operationTagName", config.escapeText(tagName)));
operation.put("operationTagDescription", "");
Optional.ofNullable(openAPI.getTags()).orElseGet(Collections::emptyList).stream()
.filter(t -> tag.equalsIgnoreCase(t.getName()))
.map(Tag::getDescription)
.filter(Objects::nonNull)
.findFirst()
.ifPresent(description -> operation.put("operationTagDescription", config.escapeText(description)));
Optional.ofNullable(config.additionalProperties().get("appVersion")).ifPresent(version -> operation.put("version", version));
operation.put("apiPackage", config.apiPackage());
operation.put("modelPackage", config.modelPackage());
operation.putAll(config.additionalProperties());
@@ -616,6 +630,8 @@ public class DefaultGenerator implements Generator {
operation.put("importPath", config.toApiImport(tag));
operation.put("classFilename", config.toApiFilename(tag));
operation.put("strictSpecBehavior", config.isStrictSpecBehavior());
Optional.ofNullable(openAPI.getInfo()).map(Info::getLicense).ifPresent(license -> operation.put("license", license));
Optional.ofNullable(openAPI.getInfo()).map(Info::getContact).ifPresent(contact -> operation.put("contact", contact));
if (allModels == null || allModels.isEmpty()) {
operation.put("hasModel", false);
@@ -866,6 +882,10 @@ public class DefaultGenerator implements Generator {
bundle.put("hasOAuthMethods", true);
bundle.put("oauthMethods", ProcessUtils.getOAuthMethods(authMethods));
}
if (ProcessUtils.hasOpenIdConnectMethods(authMethods)) {
bundle.put("hasOpenIdConnectMethods", true);
bundle.put("openIdConnectMethods", ProcessUtils.getOpenIdConnectMethods(authMethods));
}
if (ProcessUtils.hasHttpBearerMethods(authMethods)) {
bundle.put("hasHttpBearerMethods", true);
bundle.put("httpBearerMethods", ProcessUtils.getHttpBearerMethods(authMethods));
@@ -1280,7 +1300,7 @@ public class DefaultGenerator implements Generator {
*/
private Set<Map<String, String>> toImportsObjects(Map<String, String> mappedImports) {
Set<Map<String, String>> result = new TreeSet<>(
Comparator.comparing(o -> o.get("classname"))
Comparator.comparing(o -> o.get("classname"))
);
mappedImports.forEach((key, value) -> {
@@ -1393,6 +1413,32 @@ public class DefaultGenerator implements Generator {
}
authMethods.put(key, oauthUpdatedScheme);
} else if (securityScheme.getType().equals(SecurityScheme.Type.OPENIDCONNECT)) {
// Security scheme only allows to add scope in Flows, so randomly using authorization code flow
OAuthFlows openIdConnectUpdatedFlows = new OAuthFlows();
OAuthFlow flow = new OAuthFlow();
Scopes flowScopes = new Scopes();
securities.stream()
.map(secReq -> secReq.get(key))
.filter(Objects::nonNull)
.flatMap(List::stream)
.forEach(value -> flowScopes.put(value, value));
flow.scopes(flowScopes);
openIdConnectUpdatedFlows.authorizationCode(flow);
SecurityScheme openIdConnectUpdatedScheme = new SecurityScheme()
.type(securityScheme.getType())
.description(securityScheme.getDescription())
.name(securityScheme.getName())
.$ref(securityScheme.get$ref())
.in(securityScheme.getIn())
.scheme(securityScheme.getScheme())
.bearerFormat(securityScheme.getBearerFormat())
.openIdConnectUrl(securityScheme.getOpenIdConnectUrl())
.extensions(securityScheme.getExtensions())
.flows(openIdConnectUpdatedFlows);
authMethods.put(key, openIdConnectUpdatedScheme);
} else {
authMethods.put(key, securityScheme);
}

View File

@@ -33,7 +33,7 @@ public enum GeneratorLanguage {
OBJECTIVE_C("Objective-C"), OCAML("OCaml"), PERL("Perl"), PHP("PHP"),
POWERSHELL("PowerShell"), PROTOBUF("Protocol Buffers (Protobuf)"), PYTHON("Python"),
R("R"), RUBY("Ruby"), RUST("Rust"), SCALA("Scala"), SWIFT("Swift"),
WSDL("Web Services Description Language (WSDL)"), JULIA("Julia");
WSDL("Web Services Description Language (WSDL)"), JULIA("Julia"), XOJO("Xojo");
private final String label;

View File

@@ -151,6 +151,10 @@ public interface IJsonSchemaValidationProperties {
void setIsNull(boolean isNull);
boolean getIsVoid();
void setIsVoid(boolean isVoid);
boolean getHasValidation();
void setHasValidation(boolean hasValidation);

View File

@@ -691,7 +691,7 @@ public class OpenAPINormalizer {
// if only one element left, simplify to just the element (schema)
if (schema.getOneOf().size() == 1) {
if (schema.getNullable()) { // retain nullable setting
if (Boolean.TRUE.equals(schema.getNullable())) { // retain nullable setting
((Schema) schema.getOneOf().get(0)).setNullable(true);
}
return (Schema) schema.getOneOf().get(0);

View File

@@ -16,6 +16,7 @@ public enum VendorExtension {
X_CLASS_EXTRA_ANNOTATION("x-class-extra-annotation", ExtensionLevel.MODEL, "List of custom annotations to be added to model", null),
X_FIELD_EXTRA_ANNOTATION("x-field-extra-annotation", ExtensionLevel.FIELD, "List of custom annotations to be added to property", null),
X_VERSION_PARAM("x-version-param", ExtensionLevel.OPERATION_PARAMETER, "Marker property that tells that this parameter would be used for endpoint versioning. Applicable for headers & query params. true/false", null),
X_PATTERN_MESSAGE("x-pattern-message", ExtensionLevel.FIELD, "Add this property whenever you need to customize the invalidation error message for the regex pattern of a variable", null),
;
private final String name;

View File

@@ -43,7 +43,7 @@ public class MergedSpecBuilder {
deleteMergedFileFromPreviousRun();
List<String> specRelatedPaths = getAllSpecFilesInDirectory();
if (specRelatedPaths.isEmpty()) {
throw new RuntimeException("Spec directory doesn't contains any specification");
throw new RuntimeException("Spec directory doesn't contain any specification");
}
LOGGER.info("In spec root directory {} found specs {}", inputSpecRootDirectory, specRelatedPaths);

View File

@@ -506,40 +506,40 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
// https://github.com/OpenAPITools/openapi-generator/issues/12324
// TODO: why do these collections contain different instances?
// fixing allVars should suffice instead of patching every collection
for (CodegenProperty property : model.allVars){
for (CodegenProperty property : model.allVars) {
patchProperty(model, property);
}
for (CodegenProperty property : model.vars){
for (CodegenProperty property : model.vars) {
patchProperty(model, property);
}
for (CodegenProperty property : model.readWriteVars){
for (CodegenProperty property : model.readWriteVars) {
patchProperty(model, property);
}
for (CodegenProperty property : model.optionalVars){
for (CodegenProperty property : model.optionalVars) {
patchProperty(model, property);
}
for (CodegenProperty property : model.parentVars){
for (CodegenProperty property : model.parentVars) {
patchProperty(model, property);
}
for (CodegenProperty property : model.requiredVars){
for (CodegenProperty property : model.requiredVars) {
patchProperty(model, property);
}
for (CodegenProperty property : model.readOnlyVars){
for (CodegenProperty property : model.readOnlyVars) {
patchProperty(model, property);
}
for (CodegenProperty property : model.nonNullableVars){
for (CodegenProperty property : model.nonNullableVars) {
patchProperty(model, property);
}
}
return processed;
}
private void patchProperty(CodegenModel model, CodegenProperty property){
private void patchProperty(CodegenModel model, CodegenProperty property) {
/**
* Hotfix for this issue
* https://github.com/OpenAPITools/openapi-generator/issues/12155
*/
if (property.dataType.equals("List") && property.getComposedSchemas() != null && property.getComposedSchemas().getAllOf() != null){
* Hotfix for this issue
* https://github.com/OpenAPITools/openapi-generator/issues/12155
*/
if (property.dataType.equals("List") && property.getComposedSchemas() != null && property.getComposedSchemas().getAllOf() != null) {
List<CodegenProperty> composedSchemas = property.getComposedSchemas().getAllOf();
if (composedSchemas.size() == 0) {
return;
@@ -567,26 +567,28 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
}
}
/** Mitigates https://github.com/OpenAPITools/openapi-generator/issues/13709 */
/**
* Mitigates https://github.com/OpenAPITools/openapi-generator/issues/13709
*/
private void removeCircularReferencesInComposedSchemas(CodegenModel cm) {
cm.anyOf.removeIf(anyOf -> anyOf.equals(cm.classname));
cm.oneOf.removeIf(oneOf -> oneOf.equals(cm.classname));
cm.allOf.removeIf(allOf -> allOf.equals(cm.classname));
CodegenComposedSchemas composedSchemas = cm.getComposedSchemas();
if (composedSchemas != null){
if (composedSchemas != null) {
List<CodegenProperty> anyOf = composedSchemas.getAnyOf();
if (anyOf != null) {
anyOf.removeIf(p -> p.dataType.equals(cm.classname));
}
List<CodegenProperty> oneOf = composedSchemas.getOneOf();
if (oneOf != null){
if (oneOf != null) {
oneOf.removeIf(p -> p.dataType.equals(cm.classname));
}
List<CodegenProperty> allOf = composedSchemas.getAllOf();
if (allOf != null){
if (allOf != null) {
allOf.removeIf(p -> p.dataType.equals(cm.classname));
}
}
@@ -599,7 +601,7 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
// this is needed for enumRefs like OuterEnum marked as nullable and also have string values
// keep isString true so that the index will be used as the enum value instead of a string
// this is inline with C# enums with string values
if ("string?".equals(dataType)){
if ("string?".equals(dataType)) {
enumVars.forEach((enumVar) -> {
enumVar.put("isString", true);
});
@@ -1086,6 +1088,7 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
/**
* Return the default value of the property
*
* @param p OpenAPI property object
* @return string presentation of the default value of the property
*/
@@ -1272,9 +1275,13 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
return toModelName(name) + "Tests";
}
public void setLicenseUrl(String licenseUrl) {this.licenseUrl = licenseUrl;}
public void setLicenseUrl(String licenseUrl) {
this.licenseUrl = licenseUrl;
}
public void setLicenseName(String licenseName) {this.licenseName = licenseName;}
public void setLicenseName(String licenseName) {
this.licenseName = licenseName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
@@ -1328,12 +1335,12 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
return interfacePrefix;
}
public void setNullableReferenceTypes(final Boolean nullReferenceTypesFlag){
public void setNullableReferenceTypes(final Boolean nullReferenceTypesFlag) {
this.nullReferenceTypesFlag = nullReferenceTypesFlag;
additionalProperties.put("nullableReferenceTypes", nullReferenceTypesFlag);
additionalProperties.put("nrt", nullReferenceTypesFlag);
if (nullReferenceTypesFlag){
if (nullReferenceTypesFlag) {
additionalProperties.put("nrt?", "?");
additionalProperties.put("nrt!", "!");
} else {
@@ -1342,7 +1349,7 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
}
}
public boolean getNullableReferencesTypes(){
public boolean getNullableReferencesTypes() {
return this.nullReferenceTypesFlag;
}
@@ -1442,7 +1449,7 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
*/
protected boolean isValueType(CodegenProperty var) {
return (valueTypes.contains(var.dataType) || var.isEnum ) ;
return (valueTypes.contains(var.dataType) || var.isEnum);
}
@Override
@@ -1581,8 +1588,8 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
// use isNullable, OptionalParameterLambda, or RequiredParameterLambda
if (!parameter.required && (nullReferenceTypesFlag || nullableType.contains(parameter.dataType))) {
parameter.dataType = parameter.dataType.endsWith("?")
? parameter.dataType
: parameter.dataType + "?";
? parameter.dataType
: parameter.dataType + "?";
}
}
@@ -1617,5 +1624,26 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
}
@Override
public GeneratorLanguage generatorLanguage() { return GeneratorLanguage.C_SHARP; }
public GeneratorLanguage generatorLanguage() {
return GeneratorLanguage.C_SHARP;
}
@Override
public String toRegularExpression(String pattern) {
return addRegularExpressionDelimiter(pattern);
}
@Override
public String addRegularExpressionDelimiter(String pattern) {
if (StringUtils.isEmpty(pattern)) {
return pattern;
}
if (!pattern.matches("^/.*")) {
return "/" + pattern + "/";
}
return pattern;
}
}

View File

@@ -44,6 +44,8 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
public static final String PUB_AUTHOR = "pubAuthor";
public static final String PUB_AUTHOR_EMAIL = "pubAuthorEmail";
public static final String PUB_HOMEPAGE = "pubHomepage";
public static final String PUB_REPOSITORY = "pubRepository";
public static final String PUB_PUBLISH_TO = "pubPublishTo";
public static final String USE_ENUM_EXTENSION = "useEnumExtension";
protected String pubLibrary = "openapi.api";
@@ -53,6 +55,8 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
protected String pubAuthor = "Author";
protected String pubAuthorEmail = "author@homepage";
protected String pubHomepage = "homepage";
protected String pubRepository = null;
protected String pubPublishTo = null;
protected boolean useEnumExtension = false;
protected String sourceFolder = "src";
protected String libPath = "lib" + File.separator;
@@ -190,6 +194,8 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
addOption(PUB_AUTHOR, "Author name in generated pubspec", pubAuthor);
addOption(PUB_AUTHOR_EMAIL, "Email address of the author in generated pubspec", pubAuthorEmail);
addOption(PUB_HOMEPAGE, "Homepage in generated pubspec", pubHomepage);
addOption(PUB_REPOSITORY, "Repository in generated pubspec", pubRepository);
addOption(PUB_PUBLISH_TO, "Publish_to in generated pubspec", pubPublishTo);
addOption(USE_ENUM_EXTENSION, "Allow the 'x-enum-values' extension for enums", String.valueOf(useEnumExtension));
addOption(CodegenConstants.SOURCE_FOLDER, CodegenConstants.SOURCE_FOLDER_DESC, sourceFolder);
}
@@ -274,6 +280,20 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
additionalProperties.put(PUB_HOMEPAGE, pubHomepage);
}
if (additionalProperties.containsKey(PUB_REPOSITORY)) {
this.setPubRepository((String) additionalProperties.get(PUB_REPOSITORY));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_REPOSITORY, pubRepository);
}
if (additionalProperties.containsKey(PUB_PUBLISH_TO)) {
this.setPubPublishTo((String) additionalProperties.get(PUB_PUBLISH_TO));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_PUBLISH_TO, pubPublishTo);
}
if (additionalProperties.containsKey(USE_ENUM_EXTENSION)) {
this.setUseEnumExtension(convertPropertyToBooleanAndWriteBack(USE_ENUM_EXTENSION));
} else {
@@ -768,6 +788,14 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
this.pubHomepage = pubHomepage;
}
public void setPubRepository(String pubRepository) {
this.pubRepository = pubRepository;
}
public void setPubPublishTo(String pubPublishTo) {
this.pubPublishTo = pubPublishTo;
}
public void setUseEnumExtension(boolean useEnumExtension) {
this.useEnumExtension = useEnumExtension;
}

View File

@@ -44,6 +44,22 @@ public abstract class AbstractJavaJAXRSServerCodegen extends AbstractJavaCodegen
* Mustache template for the JAX-RS Codegen.
*/
protected static final String JAXRS_TEMPLATE_DIRECTORY_NAME = "JavaJaxRS";
protected static final String X_MICROPROFILE_OPEN_API_RETURN_SCHEMA_CONTAINER = "x-microprofile-open-api-return-schema-container";
protected static final String X_MICROPROFILE_OPEN_API_RETURN_UNIQUE_ITEMS = "x-microprofile-open-api-return-unique-items";
protected static final String X_MICROPROFILE_OPEN_API_SCHEMA_TYPE = "x-microprofile-open-api-schema-type";
protected static final String SCHEMA_TYPE_ARRAY = "org.eclipse.microprofile.openapi.annotations.enums.SchemaType.ARRAY";
protected static final Map<String,String> ARRAY_OF_MICROPROFILE_OPEN_API_SCHEMA_TYPES;
static {
final Map<String, String> schemaTypes = new HashMap<>();
schemaTypes.put("integer", "org.eclipse.microprofile.openapi.annotations.enums.SchemaType.INTEGER");
schemaTypes.put("number", "org.eclipse.microprofile.openapi.annotations.enums.SchemaType.NUMBER");
schemaTypes.put("boolean", "org.eclipse.microprofile.openapi.annotations.enums.SchemaType.BOOLEAN");
schemaTypes.put("string", "org.eclipse.microprofile.openapi.annotations.enums.SchemaType.STRING");
schemaTypes.put("object", "org.eclipse.microprofile.openapi.annotations.enums.SchemaType.OBJECT");
schemaTypes.put("array", "org.eclipse.microprofile.openapi.annotations.enums.SchemaType.ARRAY");
ARRAY_OF_MICROPROFILE_OPEN_API_SCHEMA_TYPES = Collections.unmodifiableMap(schemaTypes);
}
protected String implFolder = "src/main/java";
protected String testResourcesFolder = "src/test/resources";
protected String title = "OpenAPI Server";
@@ -233,11 +249,18 @@ public abstract class AbstractJavaJAXRSServerCodegen extends AbstractJavaCodegen
if ("array".equals(resp.containerType)) {
resp.containerType = "List";
resp.vendorExtensions.put(X_MICROPROFILE_OPEN_API_RETURN_SCHEMA_CONTAINER, SCHEMA_TYPE_ARRAY);
} else if ("set".equals(resp.containerType)) {
resp.containerType = "Set";
resp.vendorExtensions.put(X_MICROPROFILE_OPEN_API_RETURN_SCHEMA_CONTAINER, SCHEMA_TYPE_ARRAY);
resp.vendorExtensions.put(X_MICROPROFILE_OPEN_API_RETURN_UNIQUE_ITEMS, true);
} else if ("map".equals(resp.containerType)) {
resp.containerType = "Map";
}
if (resp.getResponseHeaders() != null) {
handleHeaders(resp.getResponseHeaders());
}
}
}
@@ -271,6 +294,17 @@ public abstract class AbstractJavaJAXRSServerCodegen extends AbstractJavaCodegen
return objs;
}
private static void handleHeaders(List<CodegenParameter> headers) {
for (CodegenParameter header : headers) {
if (header.getSchema() != null && header.getSchema().getOpenApiType() != null) {
final String schemaType = ARRAY_OF_MICROPROFILE_OPEN_API_SCHEMA_TYPES.get(header.getSchema().getOpenApiType());
if (schemaType != null) {
header.vendorExtensions.put(X_MICROPROFILE_OPEN_API_SCHEMA_TYPE, schemaType);
}
}
}
}
@Override
public String toApiName(final String name) {
String computed = name;

View File

@@ -117,10 +117,6 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen {
protected boolean needsCustomHttpMethod = false;
protected boolean needsUriBuilder = false;
// skip generation of getter for oneOf/anyOf sub-schemas to avoid duplicate getter
// when the subschemas are of the same type but with different constraints (e.g. array of string)
protected boolean skipOneOfAnyOfGetter = false;
public CSharpNetCoreClientCodegen() {
super();
@@ -331,10 +327,6 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen {
CodegenConstants.CASE_INSENSITIVE_RESPONSE_HEADERS_DESC,
this.caseInsensitiveResponseHeaders);
addSwitch(CodegenConstants.SKIP_ONEOF_ANYOF_GETTER,
CodegenConstants.SKIP_ONEOF_ANYOF_GETTER_DESC,
this.skipOneOfAnyOfGetter);
regexModifiers = new HashMap<>();
regexModifiers.put('i', "IgnoreCase");
regexModifiers.put('m', "Multiline");
@@ -806,7 +798,6 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen {
syncBooleanProperty(additionalProperties, CodegenConstants.OPTIONAL_METHOD_ARGUMENT, this::setOptionalMethodArgumentFlag, optionalMethodArgumentFlag);
syncBooleanProperty(additionalProperties, CodegenConstants.NON_PUBLIC_API, this::setNonPublicApi, isNonPublicApi());
syncBooleanProperty(additionalProperties, CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP, this::setUseOneOfDiscriminatorLookup, this.useOneOfDiscriminatorLookup);
syncBooleanProperty(additionalProperties, CodegenConstants.SKIP_ONEOF_ANYOF_GETTER, this::setSkipOneOfAnyOfGetter, this.skipOneOfAnyOfGetter);
syncBooleanProperty(additionalProperties, "supportsFileParameters", this::setSupportsFileParameters, this.supportsFileParameters);
final String testPackageName = testPackageName();
@@ -1187,14 +1178,6 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen {
return this.useOneOfDiscriminatorLookup;
}
public void setSkipOneOfAnyOfGetter(boolean skipOneOfAnyOfGetter) {
this.skipOneOfAnyOfGetter = skipOneOfAnyOfGetter;
}
public boolean getSkipOneOfAnyOfGetter() {
return this.skipOneOfAnyOfGetter;
}
@Override
public String toEnumVarName(String value, String datatype) {
if (value.length() == 0) {

View File

@@ -34,6 +34,7 @@ import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.*;
import java.util.function.Predicate;
import static org.openapitools.codegen.utils.StringUtils.underscore;
@@ -113,11 +114,7 @@ public class CppPistacheServerCodegen extends AbstractCppCodegen {
VARIABLE_NAME_FIRST_CHARACTER_UPPERCASE_DESC,
Boolean.toString(this.variableNameFirstCharacterUppercase));
supportingFiles.add(new SupportingFile("helpers-header.mustache", "model", modelNamePrefix + "Helpers.h"));
supportingFiles.add(new SupportingFile("helpers-source.mustache", "model", modelNamePrefix + "Helpers.cpp"));
supportingFiles.add(new SupportingFile("main-api-server.mustache", "", modelNamePrefix + "main-api-server.cpp"));
supportingFiles.add(new SupportingFile("cmake.mustache", "", "CMakeLists.txt"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
setupSupportingFiles();
languageSpecificPrimitives = new HashSet<>(
Arrays.asList("int", "char", "bool", "long", "float", "double", "int32_t", "int64_t"));
@@ -149,6 +146,16 @@ public class CppPistacheServerCodegen extends AbstractCppCodegen {
importMapping.put("nlohmann::json", "#include <nlohmann/json.hpp>");
}
private void setupSupportingFiles() {
supportingFiles.clear();
supportingFiles.add(new SupportingFile("api-base-header.mustache", "api", "ApiBase.h"));
supportingFiles.add(new SupportingFile("helpers-header.mustache", "model", modelNamePrefix + "Helpers.h"));
supportingFiles.add(new SupportingFile("helpers-source.mustache", "model", modelNamePrefix + "Helpers.cpp"));
supportingFiles.add(new SupportingFile("main-api-server.mustache", "", modelNamePrefix + "main-api-server.cpp"));
supportingFiles.add(new SupportingFile("cmake.mustache", "", "CMakeLists.txt"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
}
@Override
public void processOpts() {
super.processOpts();
@@ -157,12 +164,7 @@ public class CppPistacheServerCodegen extends AbstractCppCodegen {
}
if (additionalProperties.containsKey("modelNamePrefix")) {
additionalProperties().put("prefix", modelNamePrefix);
supportingFiles.clear();
supportingFiles.add(new SupportingFile("helpers-header.mustache", "model", modelNamePrefix + "Helpers.h"));
supportingFiles.add(new SupportingFile("helpers-source.mustache", "model", modelNamePrefix + "Helpers.cpp"));
supportingFiles.add(new SupportingFile("main-api-server.mustache", "", modelNamePrefix + "main-api-server.cpp"));
supportingFiles.add(new SupportingFile("cmake.mustache", "", "CMakeLists.txt"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
setupSupportingFiles();
}
if (additionalProperties.containsKey(RESERVED_WORD_PREFIX_OPTION)) {
reservedWordPrefix = (String) additionalProperties.get(RESERVED_WORD_PREFIX_OPTION);
@@ -267,63 +269,69 @@ public class CppPistacheServerCodegen extends AbstractCppCodegen {
operations.put("classnameSnakeLowerCase", underscore(classname).toLowerCase(Locale.ROOT));
List<CodegenOperation> operationList = operations.getOperation();
for (CodegenOperation op : operationList) {
boolean consumeJson = false;
boolean isParsingSupported = true;
if (op.bodyParam != null) {
if (op.bodyParam.vendorExtensions == null) {
op.bodyParam.vendorExtensions = new HashMap<>();
}
boolean isStringOrDate = op.bodyParam.isString || op.bodyParam.isDate;
op.bodyParam.vendorExtensions.put("x-codegen-pistache-is-string-or-date", isStringOrDate);
}
if (op.consumes != null) {
for (Map<String, String> consume : op.consumes) {
if (consume.get("mediaType") != null && consume.get("mediaType").equals("application/json")) {
consumeJson = true;
}
}
}
op.httpMethod = op.httpMethod.substring(0, 1).toUpperCase(Locale.ROOT) + op.httpMethod.substring(1).toLowerCase(Locale.ROOT);
for (CodegenParameter param : op.allParams) {
if (param.isFormParam) isParsingSupported = false;
if (param.isFile) isParsingSupported = false;
if (param.isCookieParam) isParsingSupported = false;
//TODO: This changes the info about the real type but it is needed to parse the header params
if (param.isHeaderParam) {
param.dataType = "std::optional<Pistache::Http::Header::Raw>";
param.baseType = "std::optional<Pistache::Http::Header::Raw>";
} else if (param.isQueryParam) {
if (param.isPrimitiveType) {
param.dataType = "std::optional<" + param.dataType + ">";
} else {
param.dataType = "std::optional<" + param.dataType + ">";
param.baseType = "std::optional<" + param.baseType + ">";
}
}
}
if (op.vendorExtensions == null) {
op.vendorExtensions = new HashMap<>();
}
op.vendorExtensions.put("x-codegen-pistache-consumes-json", consumeJson);
op.vendorExtensions.put("x-codegen-pistache-is-parsing-supported", isParsingSupported);
// Check if any one of the operations needs a model, then at API file level, at least one model has to be included.
for (String hdr : op.imports) {
if (importMapping.containsKey(hdr)) {
continue;
}
operations.put("hasModelImport", true);
}
postProcessSingleOperation(operations, op);
}
return objs;
}
private void postProcessSingleOperation(OperationMap operations, CodegenOperation op) {
if (op.vendorExtensions == null) {
op.vendorExtensions = new HashMap<>();
}
if (op.bodyParam != null) {
if (op.bodyParam.vendorExtensions == null) {
op.bodyParam.vendorExtensions = new HashMap<>();
}
boolean isStringOrDate = op.bodyParam.isString || op.bodyParam.isDate;
op.bodyParam.vendorExtensions.put("x-codegen-pistache-is-string-or-date", isStringOrDate);
}
boolean consumeJson = false;
if (op.consumes != null) {
Predicate<Map<String,String>> isMediaTypeJson = consume -> (consume.get("mediaType") != null && consume.get("mediaType").equals("application/json"));
consumeJson = op.consumes.stream().anyMatch(isMediaTypeJson);
}
op.vendorExtensions.put("x-codegen-pistache-consumes-json", consumeJson);
op.httpMethod = op.httpMethod.substring(0, 1).toUpperCase(Locale.ROOT) + op.httpMethod.substring(1).toLowerCase(Locale.ROOT);
boolean isParsingSupported = true;
for (CodegenParameter param : op.allParams) {
boolean paramSupportsParsing = (!param.isFormParam && !param.isFile && !param.isCookieParam);
isParsingSupported = isParsingSupported && paramSupportsParsing;
postProcessSingleParam(param);
}
op.vendorExtensions.put("x-codegen-pistache-is-parsing-supported", isParsingSupported);
// Check if any one of the operations needs a model, then at API file level, at least one model has to be included.
Predicate<String> importNotInImportMapping = hdr -> !importMapping.containsKey(hdr);
if (op.imports.stream().anyMatch(importNotInImportMapping)) {
operations.put("hasModelImport", true);
}
}
/**
* postProcessSingleParam - Modifies a single parameter, adjusting generated
* data types for Header and Query parameters.
* @param param CodegenParameter to be modified.
*/
private static void postProcessSingleParam(CodegenParameter param) {
//TODO: This changes the info about the real type but it is needed to parse the header params
if (param.isHeaderParam) {
param.dataType = "std::optional<Pistache::Http::Header::Raw>";
param.baseType = "std::optional<Pistache::Http::Header::Raw>";
} else if (param.isQueryParam) {
param.dataType = "std::optional<" + param.dataType + ">";
if (!param.isPrimitiveType) {
param.baseType = "std::optional<" + param.baseType + ">";
}
}
}
@Override
public String toModelFilename(String name) {
return toModelName(name);
@@ -334,17 +342,27 @@ public class CppPistacheServerCodegen extends AbstractCppCodegen {
String result = super.apiFilename(templateName, tag);
if (templateName.endsWith("impl-header.mustache")) {
int ix = result.lastIndexOf(File.separatorChar);
result = result.substring(0, ix) + result.substring(ix, result.length() - 2) + "Impl.h";
result = result.replace(apiFileFolder(), implFileFolder());
result = implFilenameFromApiFilename(result, ".h");
} else if (templateName.endsWith("impl-source.mustache")) {
int ix = result.lastIndexOf(File.separatorChar);
result = result.substring(0, ix) + result.substring(ix, result.length() - 4) + "Impl.cpp";
result = result.replace(apiFileFolder(), implFileFolder());
result = implFilenameFromApiFilename(result, ".cpp");
}
return result;
}
/**
* implFilenameFromApiFilename - Inserts the string "Impl" in front of the
* suffix and replace "api" with "impl" directory prefix.
*
* @param filename Filename of the api-file to be modified
* @param suffix Suffix of the file (usually ".cpp" or ".h")
* @return a filename string of impl file.
*/
private String implFilenameFromApiFilename(String filename, String suffix) {
String result = filename.substring(0, filename.length() - suffix.length()) + "Impl" + suffix;
result = result.replace(apiFileFolder(), implFileFolder());
return result;
}
@Override
public String toApiFilename(String name) {
return toApiName(name);

View File

@@ -147,7 +147,7 @@ public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("DateTime", "Posix");
typeMapping.put("password", "String");
typeMapping.put("ByteArray", "String");
typeMapping.put("file", "String");
typeMapping.put("file", "File");
typeMapping.put("binary", "String");
typeMapping.put("UUID", "Uuid");
typeMapping.put("URI", "String");
@@ -373,14 +373,22 @@ public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig {
response.isModel = !response.primitiveType;
}
});
// an empty string is truthy so we explicitly set empty notes to null
// So we don't print empty notes
if (op.notes != null && op.notes.isEmpty())
op.notes = null;
});
final boolean includeTime = anyOperationResponse(ops, response -> response.isDate || response.isDateTime) ||
anyOperationParam(ops, param -> (param.isDate || param.isDateTime) || itemsIncludesType(param.items, p -> p.isDate || p.isDateTime));
final boolean includeUuid = anyOperationResponse(ops, response -> response.isUuid) ||
anyOperationParam(ops, param -> param.isUuid || itemsIncludesType(param.items, p -> p.isUuid));
final boolean includeFile = anyOperationResponse(ops, response -> response.isFile) ||
anyOperationParam(ops, param -> param.isFile || itemsIncludesType(param.items, p -> p.isFile));
operations.put("includeTime", includeTime);
operations.put("includeUuid", includeUuid);
operations.put("includeFile", includeFile);
return operations;
}
@@ -469,7 +477,7 @@ public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig {
private static class RemoveWhitespaceLambda implements Mustache.Lambda {
@Override
public void execute(final Template.Fragment fragment, final Writer writer) throws IOException {
writer.write(fragment.execute().replaceAll("\\s+", ""));
writer.write(fragment.execute().replaceAll("\\s+", " ").trim());
}
}

View File

@@ -191,6 +191,7 @@ public class GoGinServerCodegen extends AbstractGoCodegen {
supportingFiles.add(new SupportingFile("routers.mustache", apiPath, "routers.go"));
supportingFiles.add(new SupportingFile("README.mustache", apiPath, "README.md")
.doNotOverwrite());
supportingFiles.add(new SupportingFile("go.mod.mustache", "go.mod"));
}
@Override

View File

@@ -99,6 +99,8 @@ public class JavaClientCodegen extends AbstractJavaCodegen
public static final String SERIALIZATION_LIBRARY_JACKSON = "jackson";
public static final String SERIALIZATION_LIBRARY_JSONB = "jsonb";
public static final String GENERATE_CLIENT_AS_BEAN = "generateClientAsBean";
protected String gradleWrapperPackage = "gradle.wrapper";
protected boolean useRxJava = false;
protected boolean useRxJava2 = false;
@@ -132,6 +134,7 @@ public class JavaClientCodegen extends AbstractJavaCodegen
protected Map<String, MpRestClientVersion> mpRestClientVersions = new HashMap<>();
protected boolean useSingleRequestParameter = false;
protected boolean webclientBlockingOperations = false;
protected boolean generateClientAsBean = false;
private static class MpRestClientVersion {
public final String rootPackage;
@@ -213,6 +216,7 @@ public class JavaClientCodegen extends AbstractJavaCodegen
cliOptions.add(CliOption.newString(MICROPROFILE_REST_CLIENT_VERSION, "Version of MicroProfile Rest Client API."));
cliOptions.add(CliOption.newBoolean(CodegenConstants.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. ONLY jersey2, jersey3, okhttp-gson support this option."));
cliOptions.add(CliOption.newBoolean(WEBCLIENT_BLOCKING_OPERATIONS, "Making all WebClient operations blocking(sync). Note that if on operation 'x-webclient-blocking: false' then such operation won't be sync", this.webclientBlockingOperations));
cliOptions.add(CliOption.newBoolean(GENERATE_CLIENT_AS_BEAN, "For resttemplate, configure whether to create `ApiClient.java` and Apis clients as bean (with `@Component` annotation).", this.generateClientAsBean));
supportedLibraries.put(JERSEY1, "HTTP client: Jersey client 1.19.x. JSON processing: Jackson 2.9.x. Enable gzip request encoding using '-DuseGzipFeature=true'. IMPORTANT NOTE: jersey 1.x is no longer actively maintained so please upgrade to 'jersey3' or other HTTP libraries instead.");
supportedLibraries.put(JERSEY2, "HTTP client: Jersey client 2.25.1. JSON processing: Jackson 2.9.x");
@@ -445,6 +449,10 @@ public class JavaClientCodegen extends AbstractJavaCodegen
additionalProperties.put(SUPPORT_URL_QUERY, Boolean.parseBoolean(additionalProperties.get(SUPPORT_URL_QUERY).toString()));
}
if (additionalProperties.containsKey(GENERATE_CLIENT_AS_BEAN)) {
this.setGenerateClientAsBean(convertPropertyToBooleanAndWriteBack(GENERATE_CLIENT_AS_BEAN));
}
final String invokerFolder = (sourceFolder + '/' + invokerPackage).replace(".", "/");
final String apiFolder = (sourceFolder + '/' + apiPackage).replace(".", "/");
final String modelsFolder = (sourceFolder + File.separator + modelPackage().replace('.', File.separatorChar)).replace('/', File.separatorChar);
@@ -1195,6 +1203,10 @@ public class JavaClientCodegen extends AbstractJavaCodegen
this.errorObjectType = errorObjectType;
}
public void setGenerateClientAsBean(boolean generateClientAsBean) {
this.generateClientAsBean = generateClientAsBean;
}
/**
* Serialization library.
*

View File

@@ -33,6 +33,7 @@ public class JavaJAXRSSpecServerCodegen extends AbstractJavaJAXRSServerCodegen {
public static final String RETURN_RESPONSE = "returnResponse";
public static final String GENERATE_POM = "generatePom";
public static final String USE_SWAGGER_ANNOTATIONS = "useSwaggerAnnotations";
public static final String USE_MICROPROFILE_OPENAPI_ANNOTATIONS = "useMicroProfileOpenAPIAnnotations";
public static final String OPEN_API_SPEC_FILE_LOCATION = "openApiSpecFileLocation";
public static final String GENERATE_BUILDERS = "generateBuilders";
@@ -47,6 +48,7 @@ public class JavaJAXRSSpecServerCodegen extends AbstractJavaJAXRSServerCodegen {
private boolean generatePom = true;
private boolean generateBuilders = false;
private boolean useSwaggerAnnotations = true;
private boolean useMicroProfileOpenAPIAnnotations = false;
protected boolean useGzipFeature = false;
private boolean useJackson = false;
@@ -105,6 +107,7 @@ public class JavaJAXRSSpecServerCodegen extends AbstractJavaJAXRSServerCodegen {
cliOptions.add(CliOption.newBoolean(INTERFACE_ONLY, "Whether to generate only API interface stubs without the server files.").defaultValue(String.valueOf(interfaceOnly)));
cliOptions.add(CliOption.newBoolean(RETURN_RESPONSE, "Whether generate API interface should return javax.ws.rs.core.Response instead of a deserialized entity. Only useful if interfaceOnly is true.").defaultValue(String.valueOf(returnResponse)));
cliOptions.add(CliOption.newBoolean(USE_SWAGGER_ANNOTATIONS, "Whether to generate Swagger annotations.", useSwaggerAnnotations));
cliOptions.add(CliOption.newBoolean(USE_MICROPROFILE_OPENAPI_ANNOTATIONS, "Whether to generate Microprofile OpenAPI annotations. Only valid when library is set to quarkus.", useMicroProfileOpenAPIAnnotations));
cliOptions.add(CliOption.newString(OPEN_API_SPEC_FILE_LOCATION, "Location where the file containing the spec will be generated in the output folder. No file generated when set to null or empty string."));
cliOptions.add(CliOption.newBoolean(SUPPORT_ASYNC, "Wrap responses in CompletionStage type, allowing asynchronous computation (requires JAX-RS 2.1).", supportAsync));
}
@@ -147,6 +150,14 @@ public class JavaJAXRSSpecServerCodegen extends AbstractJavaJAXRSServerCodegen {
}
writePropertyBack(USE_SWAGGER_ANNOTATIONS, useSwaggerAnnotations);
if (QUARKUS_LIBRARY.equals(library)) {
if (additionalProperties.containsKey(USE_MICROPROFILE_OPENAPI_ANNOTATIONS)) {
useMicroProfileOpenAPIAnnotations = Boolean.parseBoolean(additionalProperties.get(USE_MICROPROFILE_OPENAPI_ANNOTATIONS).toString());
}
writePropertyBack(USE_MICROPROFILE_OPENAPI_ANNOTATIONS, useMicroProfileOpenAPIAnnotations);
}
if (additionalProperties.containsKey(GENERATE_BUILDERS)) {
generateBuilders = Boolean.parseBoolean(additionalProperties.get(GENERATE_BUILDERS).toString());
}

View File

@@ -22,11 +22,24 @@ import com.samskivert.mustache.Mustache.Lambda;
import com.samskivert.mustache.Template;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import org.openapitools.codegen.*;
import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.CodegenModel;
import org.openapitools.codegen.CodegenOperation;
import org.openapitools.codegen.CodegenParameter;
import org.openapitools.codegen.CodegenProperty;
import org.openapitools.codegen.CodegenResponse;
import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.SupportingFile;
import org.openapitools.codegen.languages.features.BeanValidationFeatures;
import org.openapitools.codegen.languages.features.DocumentationProviderFeatures;
import org.openapitools.codegen.languages.features.SwaggerUIFeatures;
import org.openapitools.codegen.meta.features.*;
import org.openapitools.codegen.meta.features.DocumentationFeature;
import org.openapitools.codegen.meta.features.GlobalFeature;
import org.openapitools.codegen.meta.features.ParameterFeature;
import org.openapitools.codegen.meta.features.SchemaSupportFeature;
import org.openapitools.codegen.meta.features.SecurityFeature;
import org.openapitools.codegen.meta.features.WireFormatFeature;
import org.openapitools.codegen.model.ModelMap;
import org.openapitools.codegen.model.ModelsMap;
import org.openapitools.codegen.model.OperationMap;
@@ -39,7 +52,14 @@ import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.net.URL;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import static org.openapitools.codegen.utils.CamelizeOption.LOWERCASE_FIRST_LETTER;
@@ -58,10 +78,15 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
"ApiResponse"
));
public static final String OPEN_BRACE = "{";
public static final String CLOSE_BRACE = "}";
public static final String TITLE = "title";
public static final String SERVER_PORT = "serverPort";
public static final String CONFIG_PACKAGE = "configPackage";
public static final String BASE_PACKAGE = "basePackage";
public static final String SPRING_BOOT = "spring-boot";
public static final String SPRING_CLOUD_LIBRARY = "spring-cloud";
public static final String EXCEPTION_HANDLER = "exceptionHandler";
public static final String GRADLE_BUILD_FILE = "gradleBuildFile";
public static final String SERVICE_INTERFACE = "serviceInterface";
@@ -69,6 +94,7 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
public static final String SKIP_DEFAULT_INTERFACE = "skipDefaultInterface";
public static final String REACTIVE = "reactive";
public static final String INTERFACE_ONLY = "interfaceOnly";
public static final String USE_FEIGN_CLIENT_URL = "useFeignClientUrl";
public static final String DELEGATE_PATTERN = "delegatePattern";
public static final String USE_TAGS = "useTags";
public static final String BEAN_QUALIFIERS = "beanQualifiers";
@@ -76,6 +102,7 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
public static final String USE_SPRING_BOOT3 = "useSpringBoot3";
private String basePackage;
protected String configPackage;
private String invokerPackage;
private String serverPort = "8080";
private String title = "OpenAPI Kotlin Spring";
@@ -88,6 +115,7 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
private boolean serviceImplementation = false;
private boolean reactive = false;
private boolean interfaceOnly = false;
protected boolean useFeignClientUrl = true;
private boolean delegatePattern = false;
protected boolean useTags = false;
private boolean beanQualifiers = false;
@@ -128,12 +156,16 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
artifactId = "openapi-spring";
basePackage = invokerPackage = "org.openapitools";
configPackage = "org.openapitools.configuration";
apiPackage = "org.openapitools.api";
modelPackage = "org.openapitools.model";
// cliOptions default redefinition need to be updated
updateOption(CodegenConstants.ARTIFACT_ID, this.artifactId);
additionalProperties.put("openbrace", OPEN_BRACE);
additionalProperties.put("closebrace", CLOSE_BRACE);
// Use lists instead of arrays
typeMapping.put("array", "kotlin.collections.List");
typeMapping.put("list", "kotlin.collections.List");
@@ -142,6 +174,7 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
typeMapping.put("file", "org.springframework.core.io.Resource");
addOption(TITLE, "server title name or client service name", title);
addOption(CONFIG_PACKAGE, "configuration package for generated code", this.getConfigPackage());
addOption(BASE_PACKAGE, "base package (invokerPackage) for generated code", basePackage);
addOption(SERVER_PORT, "configuration the port in which the sever is to run on", serverPort);
addOption(CodegenConstants.MODEL_PACKAGE, "model package for generated code", modelPackage);
@@ -158,6 +191,7 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
addSwitch(SKIP_DEFAULT_INTERFACE, "Whether to skip generation of default implementations for interfaces", skipDefaultInterface);
addSwitch(REACTIVE, "use coroutines for reactive behavior", reactive);
addSwitch(INTERFACE_ONLY, "Whether to generate only API interface stubs without the server files.", interfaceOnly);
addSwitch(USE_FEIGN_CLIENT_URL, "Whether to generate Feign client with url parameter.", useFeignClientUrl);
addSwitch(DELEGATE_PATTERN, "Whether to generate the server files using the delegate pattern", delegatePattern);
addSwitch(USE_TAGS, "Whether to use tags for creating interface and controller class names", useTags);
addSwitch(BEAN_QUALIFIERS, "Whether to add fully-qualifier class names as bean qualifiers in @Component and " +
@@ -165,6 +199,8 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
" (contexts) added to single project.", beanQualifiers);
addSwitch(USE_SPRING_BOOT3, "Generate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports). Enabling this option will also enable `useJakartaEe`.", useSpringBoot3);
supportedLibraries.put(SPRING_BOOT, "Spring-boot Server application.");
supportedLibraries.put(SPRING_CLOUD_LIBRARY,
"Spring-Cloud-Feign client with Spring-Boot auto-configured settings.");
setLibrary(SPRING_BOOT);
CliOption cliOpt = new CliOption(CodegenConstants.LIBRARY, CodegenConstants.LIBRARY_DESC);
@@ -243,6 +279,14 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
getDocumentationProvider().equals(DocumentationProvider.SOURCE);
}
public void setConfigPackage(String configPackage) {
this.configPackage = configPackage;
}
public String getConfigPackage() {
return configPackage;
}
public String getBasePackage() {
return this.basePackage;
}
@@ -300,6 +344,10 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
this.serviceInterface = serviceInterface;
}
public void setUseFeignClientUrl(boolean useFeignClientUrl) {
this.useFeignClientUrl = useFeignClientUrl;
}
public boolean getServiceImplementation() {
return this.serviceImplementation;
}
@@ -454,6 +502,12 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
LOGGER.info("Set base package to invoker package ({})", basePackage);
}
if (additionalProperties.containsKey(CONFIG_PACKAGE)) {
this.setConfigPackage((String) additionalProperties.get(CONFIG_PACKAGE));
} else {
additionalProperties.put(CONFIG_PACKAGE, configPackage);
}
if (additionalProperties.containsKey(BASE_PACKAGE)) {
this.setBasePackage((String) additionalProperties.get(BASE_PACKAGE));
} else {
@@ -504,10 +558,15 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
}
writePropertyBack(SKIP_DEFAULT_INTERFACE, skipDefaultInterface);
if (additionalProperties.containsKey(REACTIVE) && library.equals(SPRING_BOOT)) {
this.setReactive(convertPropertyToBoolean(REACTIVE));
// spring webflux doesn't support @ControllerAdvice
this.setExceptionHandler(false);
if (additionalProperties.containsKey(REACTIVE)) {
if (SPRING_CLOUD_LIBRARY.equals(library)) {
throw new IllegalArgumentException("Currently, reactive option doesn't supported by Spring Cloud");
}
if (library.equals(SPRING_BOOT)) {
this.setReactive(convertPropertyToBoolean(REACTIVE));
// spring webflux doesn't support @ControllerAdvice
this.setExceptionHandler(false);
}
}
writePropertyBack(REACTIVE, reactive);
writePropertyBack(EXCEPTION_HANDLER, exceptionHandler);
@@ -521,6 +580,15 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
this.setInterfaceOnly(Boolean.parseBoolean(additionalProperties.get(INTERFACE_ONLY).toString()));
}
if (library.equals(SPRING_CLOUD_LIBRARY)) {
this.setInterfaceOnly(true);
}
if (additionalProperties.containsKey(USE_FEIGN_CLIENT_URL)) {
this.setUseFeignClientUrl(Boolean.parseBoolean(additionalProperties.get(USE_FEIGN_CLIENT_URL).toString()));
}
writePropertyBack(USE_FEIGN_CLIENT_URL, useFeignClientUrl);
if (additionalProperties.containsKey(DELEGATE_PATTERN)) {
this.setDelegatePattern(Boolean.parseBoolean(additionalProperties.get(DELEGATE_PATTERN).toString()));
}
@@ -557,11 +625,6 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
apiTestTemplateFiles.put("api_test.mustache", ".kt");
}
if (SPRING_BOOT.equals(library)) {
supportingFiles.add(new SupportingFile("apiUtil.mustache",
(sourceFolder + File.separator + apiPackage).replace(".", java.io.File.separator), "ApiUtil.kt"));
}
if (this.serviceInterface) {
apiTemplateFiles.put("service.mustache", "Service.kt");
} else if (this.serviceImplementation) {
@@ -579,13 +642,17 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
if (this.exceptionHandler) {
if (this.exceptionHandler && !library.equals(SPRING_CLOUD_LIBRARY)) {
supportingFiles.add(new SupportingFile("exceptions.mustache",
sanitizeDirectory(sourceFolder + File.separator + apiPackage), "Exceptions.kt"));
}
if (library.equals(SPRING_BOOT)) {
LOGGER.info("Setup code generator for Kotlin Spring Boot");
supportingFiles.add(new SupportingFile("apiUtil.mustache",
(sourceFolder + File.separator + apiPackage).replace(".", java.io.File.separator), "ApiUtil.kt"));
if (isUseSpringBoot3()) {
supportingFiles.add(new SupportingFile("pom-sb3.mustache", "", "pom.xml"));
} else {
@@ -621,7 +688,36 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
}
}
if (!reactive) {
if (library.equals(SPRING_CLOUD_LIBRARY)) {
LOGGER.info("Setup code generator for Kotlin Spring Cloud Client");
if (isUseSpringBoot3()) {
supportingFiles.add(new SupportingFile("pom-sb3.mustache", "pom.xml"));
} else {
supportingFiles.add(new SupportingFile("pom.mustache", "pom.xml"));
}
if (this.gradleBuildFile) {
if (isUseSpringBoot3()) {
supportingFiles.add(new SupportingFile("buildGradle-sb3-Kts.mustache", "build.gradle.kts"));
} else {
supportingFiles.add(new SupportingFile("buildGradleKts.mustache", "build.gradle.kts"));
}
supportingFiles.add(new SupportingFile("settingsGradle.mustache", "settings.gradle"));
}
supportingFiles.add(new SupportingFile("apiKeyRequestInterceptor.mustache",
(sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator),
"ApiKeyRequestInterceptor.kt"));
supportingFiles.add(new SupportingFile("clientConfiguration.mustache",
(sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator),
"ClientConfiguration.kt"));
apiTemplateFiles.put("apiClient.mustache", "Client.kt");
apiTestTemplateFiles.clear();
}
if (!reactive && !library.equals(SPRING_CLOUD_LIBRARY)) {
if (DocumentationProvider.SPRINGFOX.equals(getDocumentationProvider())) {
supportingFiles.add(new SupportingFile("springfoxDocumentationConfig.mustache",
(sourceFolder + File.separator + basePackage).replace(".", java.io.File.separator),

View File

@@ -0,0 +1,690 @@
/*
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* 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 static org.openapitools.codegen.CodegenConstants.API_NAME_PREFIX;
import static org.openapitools.codegen.CodegenConstants.API_NAME_PREFIX_DESC;
import static org.openapitools.codegen.CodegenConstants.API_PACKAGE;
import static org.openapitools.codegen.CodegenConstants.API_PACKAGE_DESC;
import static org.openapitools.codegen.CodegenConstants.MODEL_PACKAGE;
import static org.openapitools.codegen.CodegenConstants.MODEL_PACKAGE_DESC;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.CodegenModel;
import org.openapitools.codegen.CodegenOperation;
import org.openapitools.codegen.CodegenProperty;
import org.openapitools.codegen.CodegenResponse;
import org.openapitools.codegen.CodegenSecurity;
import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.DefaultCodegen;
import org.openapitools.codegen.IJsonSchemaValidationProperties;
import org.openapitools.codegen.SupportingFile;
import org.openapitools.codegen.config.GlobalSettings;
import org.openapitools.codegen.meta.GeneratorMetadata;
import org.openapitools.codegen.meta.Stability;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.ComposedSchema;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.parameters.Parameter;
public class N4jsClientCodegen extends DefaultCodegen implements CodegenConfig {
public static final String CHECK_REQUIRED_PARAMS_NOT_NULL = "checkRequiredParamsNotNull";
public static final String CHECK_SUPERFLUOUS_BODY_PROPS = "checkSuperfluousBodyProps";
public static final String GENERATE_DEFAULT_API_EXECUTER = "generateDefaultApiExecuter";
final Logger LOGGER = LoggerFactory.getLogger(N4jsClientCodegen.class);
final Set<String> forbiddenChars = new HashSet<>();
private boolean checkRequiredBodyPropsNotNull = true;
private boolean checkSuperfluousBodyProps = true;
private boolean generateDefaultApiExecuter = true;
public CodegenType getTag() {
return CodegenType.CLIENT;
}
public String getName() {
return "n4js";
}
public String getHelp() {
return "Generates a n4js client.";
}
public N4jsClientCodegen() {
super();
generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
.stability(Stability.BETA)
.build();
specialCharReplacements.clear();
outputFolder = "generated-code" + File.separator + "n4js";
modelTemplateFiles.put("model.mustache", ".n4jsd");
apiTemplateFiles.put("api.mustache", ".n4js");
embeddedTemplateDir = templateDir = "n4js";
apiPackage = "";
modelPackage = "";
typeMapping = new HashMap<String, String>();
typeMapping.put("Set", "Set");
typeMapping.put("set", "Set");
typeMapping.put("Array", "Array");
typeMapping.put("array", "Array");
typeMapping.put("boolean", "boolean");
typeMapping.put("string", "string");
typeMapping.put("char", "string");
typeMapping.put("float", "number");
typeMapping.put("long", "int");
typeMapping.put("short", "int");
typeMapping.put("int", "int");
typeMapping.put("integer", "int");
typeMapping.put("number", "number");
typeMapping.put("double", "number");
typeMapping.put("object", "object");
typeMapping.put("Map", "any");
typeMapping.put("map", "any");
typeMapping.put("date", "string");
typeMapping.put("DateTime", "string");
typeMapping.put("binary", "any");
typeMapping.put("File", "any");
typeMapping.put("file", "any");
typeMapping.put("ByteArray", "string");
typeMapping.put("UUID", "string");
typeMapping.put("URI", "string");
typeMapping.put("Error", "Error");
typeMapping.put("AnyType", "any");
importMapping.clear(); // not used
supportsInheritance = true;
supportsMultipleInheritance = false;
reservedWords.addAll(Arrays.asList(
// local variable names used in API methods (endpoints)
"varLocalPath", "queryParameters", "headerParams", "formParams", "useFormData", "varLocalDeferred",
"requestOptions",
// N4JS reserved words
"abstract", "await", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue",
"debugger", "default", "delete", "do", "double", "else", "enum", "export", "extends", "false", "final",
"finally", "float", "for", "function", "goto", "if", "implements", "import", "in", "instanceof", "int",
"interface", "let", "long", "native", "new", "null", "package", "private", "protected", "public",
"return", "short", "static", "super", "switch", "synchronized", "this", "throw", "transient", "true",
"try", "typeof", "var", "void", "volatile", "while", "with", "yield"));
languageSpecificPrimitives = new HashSet<>(Arrays.asList("string", "String", "boolean", "number", "int",
"Object", "object", "Array", "any", "any+", "Error"));
defaultIncludes.add("~Object+");
defaultIncludes.add("Object+");
forbiddenChars.add("@");
cliOptions.clear();
cliOptions.add(new CliOption(API_PACKAGE, API_PACKAGE_DESC));
cliOptions.add(new CliOption(MODEL_PACKAGE, MODEL_PACKAGE_DESC));
cliOptions.add(new CliOption(API_NAME_PREFIX, API_NAME_PREFIX_DESC));
cliOptions.add(new CliOption(CHECK_REQUIRED_PARAMS_NOT_NULL,
"Iff true null-checks are performed for required parameters."));
cliOptions.add(new CliOption(CHECK_SUPERFLUOUS_BODY_PROPS,
"Iff true a new copy of the given body object is transmitted. This copy only contains those properties defined in its model specification."));
cliOptions.add(new CliOption(GENERATE_DEFAULT_API_EXECUTER,
"Iff true a default implementation of the api executer interface is generated."));
}
@Override
public void processOpts() {
super.processOpts();
// disable since otherwise Modules/Classes are not generated iff used as
// parameters only
GlobalSettings.setProperty("skipFormModel", "false");
supportingFiles.clear();
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("ApiHelper.mustache", apiPackage, "ApiHelper.n4js"));
checkRequiredBodyPropsNotNull = processBooleanOpt(CHECK_REQUIRED_PARAMS_NOT_NULL,
checkRequiredBodyPropsNotNull);
checkSuperfluousBodyProps = processBooleanOpt(CHECK_SUPERFLUOUS_BODY_PROPS, checkSuperfluousBodyProps);
generateDefaultApiExecuter = processBooleanOpt(GENERATE_DEFAULT_API_EXECUTER, generateDefaultApiExecuter);
if (additionalProperties.get(API_PACKAGE) instanceof String) {
apiPackage = additionalProperties.get(API_PACKAGE).toString();
} else {
additionalProperties.put(API_PACKAGE, apiPackage);
}
if (additionalProperties.get(MODEL_PACKAGE) instanceof String) {
modelPackage = additionalProperties.get(MODEL_PACKAGE).toString();
} else {
additionalProperties.put(MODEL_PACKAGE, modelPackage);
}
if (additionalProperties.get(API_NAME_PREFIX) instanceof String) {
apiNamePrefix = additionalProperties.get(API_NAME_PREFIX).toString();
} else {
additionalProperties.put(API_NAME_PREFIX, apiNamePrefix);
}
}
private boolean processBooleanOpt(String OPT, boolean defaultValue) {
boolean passedValue = defaultValue;
if (additionalProperties.containsKey(OPT)) {
Object value = additionalProperties.get(OPT);
if (value instanceof Boolean) {
passedValue = (Boolean) value;
} else {
try {
passedValue = Boolean.parseBoolean(value.toString());
} catch (Exception e) {
// ignore
}
}
}
additionalProperties.put(OPT, passedValue);
return defaultValue;
}
@Override
public String toModelFilename(String name) {
String modelFilename = super.toModelFilename(name);
if (typeMapping.containsKey(modelFilename) || defaultIncludes.contains(modelFilename)) {
return modelFilename;
}
return modelFilename;
}
public boolean checkRequiredBodyPropsNotNull() {
return checkRequiredBodyPropsNotNull;
}
public boolean checkSuperfluousBodyProps() {
return checkSuperfluousBodyProps;
}
public boolean generateDefaultApiExecuter() {
return generateDefaultApiExecuter;
}
@Override
public boolean getUseInlineModelResolver() {
return false;
}
@Override
public void setOpenAPI(OpenAPI openAPI) {
super.setOpenAPI(openAPI);
typeAliases.put("object", "~Object+");
}
@Override
protected boolean isReservedWord(String word) {
// case sensitive matching
return reservedWords.contains(word);
}
@Override
public String toAnyOfName(List<String> names, ComposedSchema composedSchema) {
List<String> types = getTypesFromSchemas(composedSchema.getAnyOf());
return String.join(" | ", types);
}
@Override
public String toOneOfName(List<String> names, ComposedSchema composedSchema) {
List<String> types = getTypesFromSchemas(composedSchema.getOneOf());
return String.join(" | ", types);
}
@Override
public String toAllOfName(List<String> names, ComposedSchema composedSchema) {
List<String> types = getTypesFromSchemas(composedSchema.getAllOf());
return String.join(" & ", types);
}
/**
* Extracts the list of type names from a list of schemas. Excludes `AnyType` if
* there are other valid types extracted.
*
* @param schemas list of schemas
* @return list of types
*/
@SuppressWarnings("rawtypes")
protected List<String> getTypesFromSchemas(List<Schema> schemas) {
List<Schema> filteredSchemas = schemas.size() > 1 ? schemas.stream()
.filter(schema -> !"AnyType".equals(super.getSchemaType(schema))).collect(Collectors.toList())
: schemas;
return filteredSchemas.stream().map(schema -> getTypeDeclaration(schema)).distinct()
.collect(Collectors.toList());
}
@Override
protected void addImports(Set<String> importsToBeAddedTo, IJsonSchemaValidationProperties type) {
Set<String> imports = type.getImports(importContainerType, importBaseType, generatorMetadata.getFeatureSet());
Set<String> mappedImports = new HashSet<>();
for (String imp : imports) {
String mappedImp = imp;
if (typeMapping.containsKey(imp)) {
mappedImp = typeMapping.get(imp);
} else {
mappedImp = imp;
}
mappedImports.add(mappedImp);
}
addImports(importsToBeAddedTo, mappedImports);
}
@Override
protected void addImport(Set<String> importsToBeAddedTo, String type) {
String[] parts = splitComposedType(type);
for (String s : parts) {
super.addImport(importsToBeAddedTo, s);
}
}
private String[] splitComposedType(String name) {
return name.replace(" ", "").split("[|&<>]");
}
@Override
public ModelsMap postProcessModels(ModelsMap objs) {
objs = super.postProcessModels(objs);
for (ModelMap modelMap : objs.getModels()) {
CodegenModel cgModel = modelMap.getModel();
if (cgModel.unescapedDescription != null && !cgModel.unescapedDescription.contains("\n * ")) {
cgModel.description = escapeTextWhileAllowingNewLines(cgModel.unescapedDescription.trim()).replace("\n",
"\n * ");
}
}
postProcessModelsEnum(objs); // enable enums
return objs;
}
@Override
protected void addImportsForPropertyType(CodegenModel model, CodegenProperty property) {
if (model.getIsAnyType()) {
return; // disable (unused) imports created for properties of type aliases
}
super.addImportsForPropertyType(model, property);
}
@Override
public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs) {
objs = super.postProcessAllModels(objs);
for (String modelName : objs.keySet()) {
ModelsMap modelsMap = objs.get(modelName);
// imports
List<Map<String, String>> imports = modelsMap.getImports();
ArrayList<Map<String, String>> n4jsImports = new ArrayList<Map<String, String>>();
modelsMap.put("n4jsimports", n4jsImports);
String className = modelsMap.get("classname").toString();
for (Map<String, String> imp : imports) {
Map<String, String> n4jsImport = toN4jsImports(className, objs, imp);
if (n4jsImport != null) {
n4jsImports.add(n4jsImport);
}
}
// app description -> module documentation
adjustDescriptionWithNewLines(modelsMap);
}
return objs;
}
@Override
public OperationsMap postProcessOperationsWithModels(OperationsMap operations, List<ModelMap> allModels) {
OperationMap objs = operations.getOperations();
boolean needImportCleanCopyBody = false;
// The api.mustache template requires all of the auth methods for the whole api
// Loop over all the operations and pick out each unique auth method
Map<String, CodegenSecurity> authMethodsMap = new HashMap<>();
for (CodegenOperation op : objs.getOperation()) {
if (op.hasAuthMethods) {
for (CodegenSecurity sec : op.authMethods) {
authMethodsMap.put(sec.name, sec);
}
}
if (op.bodyParam != null && !op.bodyParam.vars.isEmpty()) {
needImportCleanCopyBody = true;
}
if (op.responses != null && op.responses.size() > 0) {
Map<String, CodegenResponse> responses2xx = new LinkedHashMap<>();
Map<String, CodegenResponse> responses4xx = new LinkedHashMap<>();
for (CodegenResponse response : op.responses) {
if (response.is2xx) {
responses2xx.put(response.baseType, response);
}
if (response.is4xx) {
responses4xx.put(response.baseType, response);
}
}
op.vendorExtensions.put("responses2xx", new ArrayList<>(responses2xx.values()));
op.vendorExtensions.put("responses4xx", new ArrayList<>(responses4xx.values()));
}
}
operations.put("needImportCleanCopyBody", needImportCleanCopyBody);
// If there were any auth methods specified add them to the operations context
if (!authMethodsMap.isEmpty()) {
operations.put("authMethods", authMethodsMap.values());
operations.put("hasAuthMethods", true);
}
// Add additional filename information for model imports in the apis
Iterator<Map<String, String>> iter = operations.getImports().iterator();
while (iter.hasNext()) {
Map<String, String> im = iter.next();
String className = im.get("classname");
className = convertToModelName(className);
String adjClassName = typeMapping.getOrDefault(className, className);
if (needToImport(adjClassName)) {
im.put("classname", className);
im.put("filename", toModelImport(className));
} else {
iter.remove();
}
}
// app description -> module documentation
adjustDescriptionWithNewLines(additionalProperties);
return operations;
}
private String convertToModelName(String modelName) {
if (modelName == null) {
return modelName;
}
Schema<?> schema = ModelUtils.getSchema(openAPI, modelName);
if (schema == null) {
return modelName;
}
if (ModelUtils.isObjectSchema(schema)) {
return toModelFilename(modelName);
}
return modelName;
}
private void adjustDescriptionWithNewLines(Map<String, Object> map) {
if (map.containsKey("appDescriptionWithNewLines")
&& !map.get("appDescriptionWithNewLines").toString().contains("\n * ")) {
String appDescriptionWithNewLines = map.get("appDescriptionWithNewLines").toString();
appDescriptionWithNewLines = appDescriptionWithNewLines.trim().replace("\n", "\n * ");
map.put("appDescriptionWithNewLines", appDescriptionWithNewLines);
}
}
private Map<String, String> toN4jsImports(String className, Map<String, ModelsMap> objs, Map<String, String> imp) {
String modelImpName = imp.get("import");
if (modelImpName == null) {
return null;
}
String modelName = fromModelImport(modelImpName);
if (!objs.containsKey(modelName)) {
return null;
}
ModelsMap modelsMap = objs.get(modelName);
String impClassName = modelsMap.get("classname").toString();
if (impClassName == null || Objects.equals(impClassName, className)) {
return null;
}
Map<String, String> n4jsImport = new HashMap<>();
n4jsImport.put("elementname", impClassName);
n4jsImport.put("modulename", modelImpName);
return n4jsImport;
}
@Override
public String toModelImport(String name) {
if ("".equals(modelPackage())) {
return name;
} else {
return modelPackage() + "/" + name;
}
}
protected String fromModelImport(String modelImportName) {
if ("".equals(modelPackage())) {
return modelImportName;
} else if (modelImportName == null) {
return modelImportName;
} else {
if (modelImportName.startsWith(modelPackage() + "/")) {
String nameWithoutModelPackage = modelImportName.substring(1 + modelPackage().length());
if (modelNamePrefix != null && nameWithoutModelPackage.startsWith(modelNamePrefix)) {
return nameWithoutModelPackage.substring(modelNamePrefix.length());
}
return nameWithoutModelPackage;
}
return modelImportName;
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public String getTypeDeclaration(Schema p) {
if (ModelUtils.isArraySchema(p)) {
Schema<?> items = getSchemaItems((ArraySchema) p);
return getTypeDeclaration(unaliasSchema(items)) + "[]";
} else if (ModelUtils.isMapSchema(p)) {
return "~Object+";
} else if (ModelUtils.isStringSchema(p)) {
if (p.getEnum() != null) {
return enumValuesToEnumTypeUnion(p.getEnum(), "string");
}
} else if (ModelUtils.isIntegerSchema(p) || ModelUtils.isNumberSchema(p)) {
// Handle integer and double enums
if (p.getEnum() != null) {
return numericEnumValuesToEnumTypeUnion(new ArrayList<Number>(p.getEnum()));
}
} else if (ModelUtils.isFileSchema(p)) {
return "File";
} else if (ModelUtils.isObjectSchema(p)
|| ModelUtils.isObjectSchema(ModelUtils.getReferencedSchema(openAPI, p))) {
String result = super.getTypeDeclaration(p);
return toModelFilename(result);
} else if (ModelUtils.isBinarySchema(p)) {
return "ArrayBuffer";
}
return super.getTypeDeclaration(p);
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
protected String getParameterDataType(Parameter parameter, Schema p) {
// handle enums of various data types
if (ModelUtils.isArraySchema(p)) {
ArraySchema mp1 = (ArraySchema) p;
Schema<?> inner = mp1.getItems();
return getParameterDataType(parameter, inner) + "[]";
} else if (ModelUtils.isMapSchema(p)) {
return "~Object+";
} else if (ModelUtils.isStringSchema(p)) {
// Handle string enums
if (p.getEnum() != null) {
return enumValuesToEnumTypeUnion(p.getEnum(), "string");
}
} else if (ModelUtils.isObjectSchema(p)
|| ModelUtils.isObjectSchema(ModelUtils.getReferencedSchema(openAPI, p))) {
String result = super.getTypeDeclaration(p);
return toModelFilename(result);
} else if (ModelUtils.isIntegerSchema(p) || ModelUtils.isNumberSchema(p)) {
// Handle integer and double enums
if (p.getEnum() != null) {
return numericEnumValuesToEnumTypeUnion(new ArrayList<Number>(p.getEnum()));
}
}
return this.getTypeDeclaration(p);
}
@Override
protected String getSingleSchemaType(@SuppressWarnings("rawtypes") Schema schema) {
Schema<?> unaliasSchema = unaliasSchema(schema);
if (StringUtils.isNotBlank(unaliasSchema.get$ref())) {
String schemaName = ModelUtils.getSimpleRef(unaliasSchema.get$ref());
if (StringUtils.isNotEmpty(schemaName)) {
if (schemaMapping.containsKey(schemaName)) {
return schemaName;
}
}
}
return super.getSingleSchemaType(unaliasSchema);
}
/**
* Converts a list of strings to a literal union for representing enum values as
* a type. Example output: 'available' | 'pending' | 'sold'
*
* @param values list of allowed enum values
* @param dataType either "string" or "number"
* @return a literal union for representing enum values as a type
*/
private String enumValuesToEnumTypeUnion(List<String> values, String dataType) {
StringBuilder b = new StringBuilder();
boolean isFirst = true;
for (String value : values) {
if (!isFirst) {
b.append(" | ");
}
b.append(toEnumValue(value, dataType));
isFirst = false;
}
return b.toString();
}
/**
* Converts a list of numbers to a literal union for representing enum values as
* a type. Example output: 3 | 9 | 55
*
* @param values a list of numbers
* @return a literal union for representing enum values as a type
*/
private String numericEnumValuesToEnumTypeUnion(List<Number> values) {
List<String> stringValues = new ArrayList<>();
for (Number value : values) {
stringValues.add(value.toString());
}
return enumValuesToEnumTypeUnion(stringValues, "number");
}
@Override
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
if (property.unescapedDescription != null && property.unescapedDescription.contains("\n")) {
property.description = escapeTextWhileAllowingNewLines(property.unescapedDescription.trim()).replace("\n",
"\n * ");
}
}
@Override
public String escapeText(String input) {
input = escapeTextWhileAllowingNewLines(input);
if (input == null) {
return input;
}
// remove \n, \r
return input.replaceAll("[\\n\\r]", " ");
}
@Override
public String escapeTextWhileAllowingNewLines(String input) {
if (input == null) {
return input;
}
// remove \t
// outer unescape to retain the original multi-byte characters
// finally escalate characters avoiding code injection
return escapeUnsafeCharacters(
StringEscapeUtils.unescapeEcmaScript(StringEscapeUtils.escapeEcmaScript(input).replace("\\/", "/"))
.replaceAll("[\\t]", " "));
}
@Override
public String escapeReservedWord(String name) {
return "_" + name;
}
@Override
public String toVarName(final String name) {
String name2 = super.toVarName(name);
for (String forbiddenChar : forbiddenChars) {
if (name2.contains(forbiddenChar)) {
return "[\"" + name2 + "\"]";
}
}
return name2;
}
@Override
public String toParamName(String name) {
String name2 = super.toParamName(name);
for (String forbiddenChar : forbiddenChars) {
if (name2.contains(forbiddenChar)) {
return "[\"" + name2 + "\"]";
}
}
return name2;
}
@Override
public String escapeQuotationMark(String input) {
// remove ', " to avoid code injection
return input.replace("\"", "").replace("'", "");
}
@Override
public String escapeUnsafeCharacters(String input) {
return input.replace("*/", "*_/").replace("/*", "/_*");
}
}

View File

@@ -102,7 +102,7 @@ public class PythonNextgenClientCodegen extends AbstractPythonCodegen implements
);
generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
.stability(Stability.BETA)
.stability(Stability.STABLE)
.build();
// clear import mapping (from default generator) as python does not use it
@@ -354,6 +354,7 @@ public class PythonNextgenClientCodegen extends AbstractPythonCodegen implements
}
supportingFiles.add(new SupportingFile("api_client.mustache", packagePath(), "api_client.py"));
supportingFiles.add(new SupportingFile("api_response.mustache", packagePath(), "api_response.py"));
if ("asyncio".equals(getLibrary())) {
supportingFiles.add(new SupportingFile("asyncio/rest.mustache", packagePath(), "rest.py"));
@@ -414,6 +415,7 @@ public class PythonNextgenClientCodegen extends AbstractPythonCodegen implements
* @param pydantic pydantic imports
* @param datetimeImports datetime imports
* @param modelImports model imports
* @param exampleImports example imports
* @param classname class name
* @return pydantic type
*
@@ -423,6 +425,7 @@ public class PythonNextgenClientCodegen extends AbstractPythonCodegen implements
Set<String> pydanticImports,
Set<String> datetimeImports,
Set<String> modelImports,
Set<String> exampleImports,
String classname) {
if (cp == null) {
// if codegen parameter (e.g. map/dict of undefined type) is null, default to string
@@ -444,13 +447,13 @@ public class PythonNextgenClientCodegen extends AbstractPythonCodegen implements
}
pydanticImports.add("conlist");
return String.format(Locale.ROOT, "conlist(%s%s)",
getPydanticType(cp.items, typingImports, pydanticImports, datetimeImports, modelImports, classname),
getPydanticType(cp.items, typingImports, pydanticImports, datetimeImports, modelImports, exampleImports, classname),
constraints);
} else if (cp.isMap) {
typingImports.add("Dict");
return String.format(Locale.ROOT, "Dict[str, %s]",
getPydanticType(cp.items, typingImports, pydanticImports, datetimeImports, modelImports, classname));
} else if (cp.isString || cp.isBinary || cp.isByteArray) {
getPydanticType(cp.items, typingImports, pydanticImports, datetimeImports, modelImports, exampleImports, classname));
} else if (cp.isString) {
if (cp.hasValidation) {
List<String> fieldCustomization = new ArrayList<>();
// e.g. constr(regex=r'/[a-z]/i', strict=True)
@@ -565,12 +568,10 @@ public class PythonNextgenClientCodegen extends AbstractPythonCodegen implements
pydanticImports.add("conint");
return String.format(Locale.ROOT, "%s(%s)", "conint",
StringUtils.join(fieldCustomization, ", "));
} else {
pydanticImports.add("StrictInt");
return "StrictInt";
}
/* comment out the following as byte/binary is a string at the moment (path to the file, e.g. "/var/tmp/a.gif")
} else if (cp.isBinary || cp.isByteArray) {
if (cp.hasValidation) {
List<String> fieldCustomization = new ArrayList<>();
@@ -582,14 +583,23 @@ public class PythonNextgenClientCodegen extends AbstractPythonCodegen implements
if (cp.getMaxLength() != null) {
fieldCustomization.add("max_length=" + cp.getMaxLength());
}
if (cp.getPattern() != null) {
pydanticImports.add("validator");
// use validator instead as regex doesn't support flags, e.g. IGNORECASE
//fieldCustomization.add(Locale.ROOT, String.format(Locale.ROOT, "regex=r'%s'", cp.getPattern()));
}
pydanticImports.add("conbytes");
return String.format(Locale.ROOT, "%s(%s)", "conbytes", StringUtils.join(fieldCustomization, ", "));
pydanticImports.add("constr");
typingImports.add("Union");
return String.format(Locale.ROOT, "Union[conbytes(%s), constr(%<s)]", StringUtils.join(fieldCustomization, ", "));
} else {
// same as above which has validation
pydanticImports.add("StrictBytes");
return "StrictBytes";
}*/
pydanticImports.add("StrictStr");
typingImports.add("Union");
return "Union[StrictBytes, StrictStr]";
}
} else if (cp.isBoolean) {
pydanticImports.add("StrictBool");
return "StrictBool";
@@ -643,6 +653,7 @@ public class PythonNextgenClientCodegen extends AbstractPythonCodegen implements
// add model prefix
hasModelsToImport = true;
modelImports.add(cp.dataType);
exampleImports.add(cp.dataType);
return cp.dataType;
} else if (cp.getContent() != null) {
LinkedHashMap<String, CodegenMediaType> contents = cp.getContent();
@@ -650,7 +661,7 @@ public class PythonNextgenClientCodegen extends AbstractPythonCodegen implements
CodegenMediaType cmt = contents.get(key);
// TODO process the first one only at the moment
if (cmt != null)
return getPydanticType(cmt.getSchema(), typingImports, pydanticImports, datetimeImports, modelImports, classname);
return getPydanticType(cmt.getSchema(), typingImports, pydanticImports, datetimeImports, modelImports, exampleImports, classname);
}
throw new RuntimeException("Error! Failed to process getPydanticType when getting the content: " + cp);
} else {
@@ -666,6 +677,7 @@ public class PythonNextgenClientCodegen extends AbstractPythonCodegen implements
* @param pydantic pydantic imports
* @param datetimeImports datetime imports
* @param modelImports model imports
* @param exampleImports example imports
* @param classname class name
* @return pydantic type
*
@@ -675,6 +687,7 @@ public class PythonNextgenClientCodegen extends AbstractPythonCodegen implements
Set<String> pydanticImports,
Set<String> datetimeImports,
Set<String> modelImports,
Set<String> exampleImports,
String classname) {
if (cp == null) {
// if codegen property (e.g. map/dict of undefined type) is null, default to string
@@ -715,11 +728,11 @@ public class PythonNextgenClientCodegen extends AbstractPythonCodegen implements
pydanticImports.add("conlist");
typingImports.add("List"); // for return type
return String.format(Locale.ROOT, "conlist(%s%s)",
getPydanticType(cp.items, typingImports, pydanticImports, datetimeImports, modelImports, classname),
getPydanticType(cp.items, typingImports, pydanticImports, datetimeImports, modelImports, exampleImports, classname),
constraints);
} else if (cp.isMap) {
typingImports.add("Dict");
return String.format(Locale.ROOT, "Dict[str, %s]", getPydanticType(cp.items, typingImports, pydanticImports, datetimeImports, modelImports, classname));
return String.format(Locale.ROOT, "Dict[str, %s]", getPydanticType(cp.items, typingImports, pydanticImports, datetimeImports, modelImports, exampleImports, classname));
} else if (cp.isString) {
if (cp.hasValidation) {
List<String> fieldCustomization = new ArrayList<>();
@@ -857,11 +870,15 @@ public class PythonNextgenClientCodegen extends AbstractPythonCodegen implements
}
pydanticImports.add("conbytes");
return String.format(Locale.ROOT, "%s(%s)", "conbytes", StringUtils.join(fieldCustomization, ", "));
pydanticImports.add("constr");
typingImports.add("Union");
return String.format(Locale.ROOT, "Union[conbytes(%s), constr(%<s)]", StringUtils.join(fieldCustomization, ", "));
} else {
// same as above which has validation
pydanticImports.add("StrictBytes");
return "StrictBytes";
pydanticImports.add("StrictStr");
typingImports.add("Union");
return "Union[StrictBytes, StrictStr]";
}
} else if (cp.isBoolean) {
pydanticImports.add("StrictBool");
@@ -917,6 +934,7 @@ public class PythonNextgenClientCodegen extends AbstractPythonCodegen implements
// for parameter model, import directly
hasModelsToImport = true;
modelImports.add(cp.dataType);
exampleImports.add(cp.dataType);
} else {
if (circularImports.containsKey(cp.dataType)) {
if (circularImports.get(cp.dataType).contains(classname)) {
@@ -926,6 +944,7 @@ public class PythonNextgenClientCodegen extends AbstractPythonCodegen implements
// not circular import, so ok to import it
hasModelsToImport = true;
modelImports.add(cp.dataType);
exampleImports.add(cp.dataType);
}
} else {
LOGGER.error("Failed to look up {} from the imports (map of set) of models.", cp.dataType);
@@ -948,10 +967,11 @@ public class PythonNextgenClientCodegen extends AbstractPythonCodegen implements
OperationMap objectMap = objs.getOperations();
List<CodegenOperation> operations = objectMap.getOperation();
for (CodegenOperation operation : operations) {
TreeSet<String> exampleImports = new TreeSet<>(); // import for each operation to be show in sample code
List<CodegenParameter> params = operation.allParams;
for (CodegenParameter param : params) {
String typing = getPydanticType(param, typingImports, pydanticImports, datetimeImports, modelImports, null);
String typing = getPydanticType(param, typingImports, pydanticImports, datetimeImports, modelImports, exampleImports, null);
List<String> fields = new ArrayList<>();
String firstField = "";
@@ -1003,9 +1023,18 @@ public class PythonNextgenClientCodegen extends AbstractPythonCodegen implements
// update typing import for operation return type
if (!StringUtils.isEmpty(operation.returnType)) {
String typing = getPydanticType(operation.returnProperty, typingImports,
new TreeSet<>() /* skip pydantic import for return type */, datetimeImports, modelImports, null);
new TreeSet<>() /* skip pydantic import for return type */, datetimeImports, modelImports, exampleImports, null);
}
// add import for code samples
// import models one by one
if (!exampleImports.isEmpty()) {
List<String> imports = new ArrayList<>();
for (String exampleImport : exampleImports) {
imports.add("from " + packageName + ".models." + underscore(exampleImport) + " import " + exampleImport);
}
operation.vendorExtensions.put("x-py-example-import", imports);
}
}
List<Map<String, String>> newImports = new ArrayList<>();
@@ -1040,21 +1069,6 @@ public class PythonNextgenClientCodegen extends AbstractPythonCodegen implements
}
}
/* TODO
// need models import
if (hasModelsToImport) {
Map<String, String> item = new HashMap<>();
item.put("import", String.format(Locale.ROOT, "from %s import models", packageName));
newImports.add(item);
}
// models import
if (hasModelsToImport) {
Map<String, String> item = new HashMap<>();
item.put("import", String.format(Locale.ROOT, "from %s import %s", modelPackage, StringUtils.join(modelImports, ", ")));
newImports.add(item);
}*/
// reset imports with newImports
objs.setImports(newImports);
return objs;
@@ -1185,6 +1199,7 @@ public class PythonNextgenClientCodegen extends AbstractPythonCodegen implements
TreeSet<String> modelImports = new TreeSet<>();
for (ModelMap m : objs.getModels()) {
TreeSet<String> exampleImports = new TreeSet<>();
List<String> readOnlyFields = new ArrayList<>();
hasModelsToImport = false;
int property_count = 1;
@@ -1229,7 +1244,7 @@ public class PythonNextgenClientCodegen extends AbstractPythonCodegen implements
//loop through properties/schemas to set up typing, pydantic
for (CodegenProperty cp : codegenProperties) {
String typing = getPydanticType(cp, typingImports, pydanticImports, datetimeImports, modelImports, model.classname);
String typing = getPydanticType(cp, typingImports, pydanticImports, datetimeImports, modelImports, exampleImports, model.classname);
List<String> fields = new ArrayList<>();
String firstField = "";
@@ -1286,6 +1301,12 @@ public class PythonNextgenClientCodegen extends AbstractPythonCodegen implements
fieldCustomization = String.format(Locale.ROOT, "Field(%s)", StringUtils.join(fields, ", "));
}
if ("...".equals(fieldCustomization)) {
// use Field() to avoid pylint warnings
pydanticImports.add("Field");
fieldCustomization = "Field(...)";
}
cp.vendorExtensions.put("x-py-typing", typing + " = " + fieldCustomization);
// setup x-py-name for each oneOf/anyOf schema
@@ -1509,7 +1530,7 @@ public class PythonNextgenClientCodegen extends AbstractPythonCodegen implements
public String toEnumVariableName(String name, String datatype) {
if ("int".equals(datatype)) {
return "NUMBER_" + name;
return "NUMBER_" + name.replace("-", "MINUS_");
}
// remove quote e.g. 'abc' => abc

View File

@@ -112,6 +112,7 @@ 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_RESPONSE_ENTITY = "useResponseEntity";
public static final String USE_ENUM_CASE_INSENSITIVE = "useEnumCaseInsensitive";
public static final String USE_SPRING_BOOT3 = "useSpringBoot3";
public static final String REQUEST_MAPPING_OPTION = "requestMappingMode";
public static final String USE_REQUEST_MAPPING_ON_CONTROLLER = "useRequestMappingOnController";
@@ -160,6 +161,7 @@ public class SpringCodegen extends AbstractJavaCodegen
protected boolean useSpringController = false;
protected boolean useSwaggerUI = true;
protected boolean useResponseEntity = true;
protected boolean useEnumCaseInsensitive = false;
protected boolean useSpringBoot3 = false;
protected boolean generatedConstructorWithRequiredArgs = true;
protected RequestMappingMode requestMappingMode = RequestMappingMode.controller;
@@ -254,6 +256,9 @@ public class SpringCodegen extends AbstractJavaCodegen
"Use the `ResponseEntity` type to wrap return values of generated API methods. "
+ "If disabled, method are annotated using a `@ResponseStatus` annotation, which has the status of the first response declared in the Api definition",
useResponseEntity));
cliOptions.add(CliOption.newBoolean(USE_ENUM_CASE_INSENSITIVE,
"Use `equalsIgnoreCase` when String for enum comparison",
useEnumCaseInsensitive));
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). Enabling this option will also enable `useJakartaEe`.",
useSpringBoot3));
@@ -501,6 +506,11 @@ public class SpringCodegen extends AbstractJavaCodegen
writePropertyBack(USE_RESPONSE_ENTITY, useResponseEntity);
additionalProperties.put("springHttpStatus", new SpringHttpStatusLambda());
if (additionalProperties.containsKey(USE_ENUM_CASE_INSENSITIVE)) {
this.setUseEnumCaseInsensitive(Boolean.parseBoolean(additionalProperties.get(USE_ENUM_CASE_INSENSITIVE).toString()));
}
writePropertyBack(USE_ENUM_CASE_INSENSITIVE, useEnumCaseInsensitive);
if (additionalProperties.containsKey(USE_SPRING_BOOT3)) {
this.setUseSpringBoot3(convertPropertyToBoolean(USE_SPRING_BOOT3));
}
@@ -812,6 +822,11 @@ public class SpringCodegen extends AbstractJavaCodegen
public void setReturnContainer(final String returnContainer) {
resp.containerType = returnContainer;
}
@Override
public void setIsVoid(boolean isVoid) {
resp.isVoid = isVoid;
}
});
}
}
@@ -827,6 +842,11 @@ public class SpringCodegen extends AbstractJavaCodegen
public void setReturnContainer(final String returnContainer) {
operation.returnContainer = returnContainer;
}
@Override
public void setIsVoid(boolean isVoid) {
operation.isVoid = isVoid;
}
});
prepareVersioningParameters(ops);
@@ -848,6 +868,8 @@ public class SpringCodegen extends AbstractJavaCodegen
void setReturnType(String returnType);
void setReturnContainer(String returnContainer);
void setIsVoid(boolean isVoid);
}
/**
@@ -859,6 +881,7 @@ public class SpringCodegen extends AbstractJavaCodegen
final String rt = returnType;
if (rt == null) {
dataTypeAssigner.setReturnType("Void");
dataTypeAssigner.setIsVoid(true);
} else if (rt.startsWith("List") || rt.startsWith("java.util.List")) {
final int start = rt.indexOf("<");
final int end = rt.lastIndexOf(">");
@@ -1047,6 +1070,10 @@ public class SpringCodegen extends AbstractJavaCodegen
this.useResponseEntity = useResponseEntity;
}
public void setUseEnumCaseInsensitive(boolean useEnumCaseInsensitive) {
this.useEnumCaseInsensitive = useEnumCaseInsensitive;
}
@Override
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
super.postProcessModelProperty(model, property);
@@ -1242,6 +1269,7 @@ public class SpringCodegen extends AbstractJavaCodegen
List<VendorExtension> extensions = super.getSupportedVendorExtensions();
extensions.add(VendorExtension.X_SPRING_PAGINATED);
extensions.add(VendorExtension.X_VERSION_PARAM);
extensions.add(VendorExtension.X_PATTERN_MESSAGE);
return extensions;
}

View File

@@ -0,0 +1,760 @@
/*
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* 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.ArraySchema;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.openapitools.codegen.*;
import org.openapitools.codegen.meta.GeneratorMetadata;
import org.openapitools.codegen.meta.Stability;
import org.openapitools.codegen.model.ModelMap;
import org.openapitools.codegen.model.ModelsMap;
import org.openapitools.codegen.model.OperationsMap;
import org.openapitools.codegen.utils.ModelUtils;
import java.io.File;
import java.util.*;
import java.util.function.Consumer;
import static org.openapitools.codegen.utils.CamelizeOption.LOWERCASE_FIRST_LETTER;
import static org.openapitools.codegen.utils.StringUtils.camelize;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.WordUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class XojoClientCodegen extends DefaultCodegen implements CodegenConfig {
public static final String CODEGEN_MODULE_NAME = "xojo-client";
public static final String LIBRARY_HTTPSOCKET = "httpsocket";
public static final String SERIALIZATION_LIBRARY_DESC = "What serialization library to use: 'xoson' (default).";
public static final String PROJECT_NAME_DESC = "Project name in Xojo";
public enum SERIALIZATION_LIBRARY_TYPE {xoson}
protected String projectName = "OpenAPIClient";
protected boolean nonPublicApi = false;
protected boolean supportsAsync = true;
protected SERIALIZATION_LIBRARY_TYPE serializationLibrary = SERIALIZATION_LIBRARY_TYPE.xoson;
// Number for each object that appears in the xojo_project file.
// We start with a relatively high value, to have space for other static objects.
protected int projectObjectNumber = 100042;
private final Logger LOGGER = LoggerFactory.getLogger(XojoClientCodegen.class);
public void setProjectName(String projectName) {
this.projectName = projectName;
}
public void setNonPublicApi(boolean nonPublicApi) {
this.nonPublicApi = nonPublicApi;
}
public void setSupportsAsync(Boolean supportsAsync) {
this.supportsAsync = supportsAsync;
}
@Override
public String apiFileFolder() {
return outputFolder + File.separator + projectName + File.separator + apiPackage().replace('.', File.separatorChar);
}
@Override
public String modelFileFolder() {
return outputFolder + File.separator + projectName + File.separator + modelPackage().replace('.', File.separatorChar);
}
public XojoClientCodegen() {
super();
this.useOneOfInterfaces = true;
generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
.stability(Stability.STABLE)
.build();
outputFolder = "generated-code" + File.separator + CODEGEN_MODULE_NAME;
modelTemplateFiles.put("model.mustache", ".xojo_code");
modelTemplateFiles.put("modelOptionalEnum.mustache", "Optional.xojo_code");
apiTemplateFiles.put("api.mustache", ".xojo_code");
embeddedTemplateDir = templateDir = CODEGEN_MODULE_NAME;
apiPackage = "APIs";
modelPackage = "Models";
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("App.mustache",
"",
"App.xojo_code"));
supportingFiles.add(new SupportingFile("BuildAutomation.mustache",
"",
"Build Automation.xojo_code"));
supportingFiles.add(new SupportingFile("api_mock.mustache",
"",
"Mock.xojo_code"));
languageSpecificPrimitives = new HashSet<>(
Arrays.asList(
"Integer",
"Int8",
"Int16",
"Int32",
"Int64",
"UInteger",
"UInt8",
"UInt16",
"UInt32",
"UInt64",
"Single",
"Double",
"Boolean",
"String",
"Color",
"Currency")
);
setReservedWordsLowerCase(
Arrays.asList(
// name used by Xojo client
"Models", "APIs",
// Xojo keywords. This list is taken from here:
// https://documentation.xojo.com/getting_started/using_the_xojo_language/reserved_words.html
//
"#Bad", "#Else", "#Elseif", "#Endif", "#If", "#Pragma", "#Tag", "AddHandler", "AddressOf", "Aggregates", "And", "Array", "As", "Assigns", "Async", "Attributes", "Await", "Break", "ByRef", "ByVal", "Call", "Case", "Catch", "Class", "Const", "Continue", "CType", "Declare", "Delegate", "Dim", "Do", "DownTo", "Each", "Else", "ElseIf", "End", "Enum", "Event", "Exception", "Exit", "Extends", "False", "Finally", "For", "Function", "Global", "GoTo", "Handles", "If", "Implements", "In", "Inherits", "Interface", "Is", "IsA", "Lib", "Loop", "Me", "Mod", "Module", "Namespace", "New", "Next", "Nil", "Not", /*"Object",*/ "Of", "Optional", "Or", "ParamArray", "Private", "Property", "Protected", "Public", "Raise", "RaiseEvent", "Redim", "Rem", "RemoveHandler", "Return", "Select", "Self", "Shared", "Soft", "Static", "Step", "Structure", "Sub", "Super", "Then", "To", "True", "Try", "Until", "Using", "Var", "WeakAddressOf", "Wend", "While", "With", "Xor",
// The following are other words we want to reserve
"Void", "COLUMN", "FILE", "FUNCTION", "LINE"
)
);
typeMapping = new HashMap<>();
typeMapping.put("map", "Dictionary");
typeMapping.put("set", "Array");
typeMapping.put("Date", "Date");
typeMapping.put("DateTime", "Date");
typeMapping.put("boolean", "Boolean");
typeMapping.put("string", "String");
typeMapping.put("char", "Byte");
typeMapping.put("short", "Int16");
typeMapping.put("int", "Integer");
typeMapping.put("long", "Int64");
typeMapping.put("integer", "Integer");
typeMapping.put("Integer", "Integer");
typeMapping.put("float", "Single");
typeMapping.put("number", "Double");
typeMapping.put("double", "Double");
typeMapping.put("file", "FolderItem");
typeMapping.put("binary", "FolderItem");
typeMapping.put("ByteArray", "MemoryBlock");
typeMapping.put("UUID", "String");
typeMapping.put("URI", "String");
typeMapping.put("decimal", "Currency");
typeMapping.put("object", "Object");
typeMapping.put("AnyType", "Variant");
typeMapping.put("null", "nil");
// in the future we should also support URLConnection
supportedLibraries.put(LIBRARY_HTTPSOCKET, "[DEFAULT] HTTP client: HTTPSocket");
CliOption libraryOption = new CliOption(CodegenConstants.LIBRARY, CodegenConstants.LIBRARY_DESC);
libraryOption.setEnum(supportedLibraries);
libraryOption.setDefault(LIBRARY_HTTPSOCKET);
cliOptions.add(libraryOption);
setLibrary(LIBRARY_HTTPSOCKET);
CliOption serializationLibraryOpt = new CliOption(CodegenConstants.SERIALIZATION_LIBRARY, SERIALIZATION_LIBRARY_DESC);
cliOptions.add(serializationLibraryOpt.defaultValue(serializationLibrary.name()));
cliOptions.add(new CliOption(CodegenConstants.API_NAME_PREFIX, "Prefix that will be appended to all API classes. Default: empty string."));
cliOptions.add(new CliOption(CodegenConstants.PROJECT_NAME, PROJECT_NAME_DESC));
cliOptions.add(new CliOption(CodegenConstants.NON_PUBLIC_API, CodegenConstants.NON_PUBLIC_API_DESC));
cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.SUPPORTS_ASYNC, CodegenConstants.SUPPORTS_ASYNC_DESC));
cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC));
}
private static CodegenModel reconcileProperties(CodegenModel codegenModel,
CodegenModel parentCodegenModel) {
// To support inheritance in this generator, we will analyze
// the parent and child models, look for properties that match, and remove
// them from the child models and leave them in the parent.
// Because the child models extend the parents, the properties
// will be available via the parent.
// Get the properties for the parent and child models
final List<CodegenProperty> parentModelCodegenProperties = parentCodegenModel.vars;
List<CodegenProperty> codegenProperties = codegenModel.vars;
codegenModel.allVars = new ArrayList<CodegenProperty>(codegenProperties);
codegenModel.parentVars = parentCodegenModel.allVars;
// Iterate over all of the parent model properties
boolean removedChildProperty = false;
for (CodegenProperty parentModelCodegenProperty : parentModelCodegenProperties) {
// Now that we have found a prop in the parent class,
// and search the child class for the same prop.
Iterator<CodegenProperty> iterator = codegenProperties.iterator();
while (iterator.hasNext()) {
CodegenProperty codegenProperty = iterator.next();
if (codegenProperty.baseName.equals(parentModelCodegenProperty.baseName)) {
// We found a property in the child class that is
// a duplicate of the one in the parent, so remove it.
iterator.remove();
removedChildProperty = true;
}
}
}
if (removedChildProperty) {
codegenModel.vars = codegenProperties;
}
return codegenModel;
}
@Override
public String getTypeDeclaration(Schema p) {
if (ModelUtils.isArraySchema(p)) {
ArraySchema ap = (ArraySchema) p;
Schema inner = ap.getItems();
return super.getTypeDeclaration(inner);
}
return super.getTypeDeclaration(p);
}
@Override
public String getSchemaType(Schema p) {
String openAPIType = super.getSchemaType(p);
String type;
if (typeMapping.containsKey(openAPIType)) {
type = typeMapping.get(openAPIType);
if (languageSpecificPrimitives.contains(type) || defaultIncludes.contains(type)) {
return type;
}
} else {
type = openAPIType;
}
return toModelName(type);
}
@Override
public String escapeReservedWord(String name) {
LOGGER.warn("Escaping word '" + name + "' to 'Escaped" + name + "'. This will likely cause issues at runtime!");
return "Escaped" + name;
}
@Override
public CodegenType getTag() {
return CodegenType.CLIENT;
}
@Override
public String getName() {
return CODEGEN_MODULE_NAME;
}
@Override
public String getHelp() {
return "Generates a Xojo client module.";
}
@Override
public void processOpts() {
super.processOpts();
// mandatory settings to ensure compilation
setSortParamsByRequiredFlag(true);
setEnsureUniqueParams(true);
setAllowUnicodeIdentifiers(false);
// Setup nonPublicApi option, which generates code with reduced access
// modifiers; allows embedding elsewhere without exposing non-public API calls
// to consumers
if (additionalProperties.containsKey(CodegenConstants.NON_PUBLIC_API)) {
setNonPublicApi(convertPropertyToBooleanAndWriteBack(CodegenConstants.NON_PUBLIC_API));
}
additionalProperties.put(CodegenConstants.NON_PUBLIC_API, nonPublicApi);
if (additionalProperties.containsKey(CodegenConstants.SERIALIZATION_LIBRARY)) {
setSerializationLibrary((String) additionalProperties.get(CodegenConstants.SERIALIZATION_LIBRARY));
additionalProperties.put(this.serializationLibrary.name(), true);
} else {
additionalProperties.put(this.serializationLibrary.name(), true);
}
syncBooleanProperty(additionalProperties, CodegenConstants.SUPPORTS_ASYNC, this::setSupportsAsync, this.supportsAsync);
syncStringProperty(additionalProperties, CodegenConstants.PROJECT_NAME, this::setProjectName, this.projectName);
syncStringProperty(additionalProperties, CodegenConstants.LIBRARY, this::setLibrary, this.library);
if (supportsAsync) {
apiTemplateFiles.put("CallbackHandler.mustache", "CallbackHandler.xojo_code");
}
supportingFiles.add(new SupportingFile("MainModule.mustache",
"",
projectName + ".xojo_code"));
supportingFiles.add(new SupportingFile("APIsModule.mustache",
projectName,
"APIs.xojo_code"));
supportingFiles.add(new SupportingFile("ModelModule.mustache",
projectName,
"Models.xojo_code"));
supportingFiles.add(new SupportingFile("Project.mustache",
"",
projectName + ".xojo_project"));
supportingFiles.add(new SupportingFile("Exception.mustache",
projectName,
projectName + "Exception.xojo_code"));
supportingFiles.add(new SupportingFile("Resources.mustache",
"",
projectName + ".xojo_resources"));
}
@Override
public CodegenModel fromModel(String name, Schema model) {
Map<String, Schema> allDefinitions = ModelUtils.getSchemas(this.openAPI);
CodegenModel codegenModel = super.fromModel(name, model);
codegenModel.vendorExtensions.put("x-xojo-project-id", String.format(Locale.ROOT, "%014XFF", projectObjectNumber));
projectObjectNumber = projectObjectNumber + 16;
if (allDefinitions != null) {
String parentSchema = codegenModel.parentSchema;
// multilevel inheritance: reconcile properties of all the parents
while (parentSchema != null) {
final Schema parentModel = allDefinitions.get(parentSchema);
final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent,
parentModel);
codegenModel = XojoClientCodegen.reconcileProperties(codegenModel, parentCodegenModel);
// get the next parent
parentSchema = parentCodegenModel.parentSchema;
}
}
return codegenModel;
}
@Override
public String escapeQuotationMark(String input) {
// escape " in strings to avoid code injection
return input.replace("\"", "\"\"");
}
@Override
public String escapeUnsafeCharacters(String input) {
// if a backslash occurs in a property note for instance, Xojo crashes.
return input.replace("*/", "*_/").replace("/*", "/_*").replace("\\", "");
}
@Override
public ModelsMap postProcessModels(ModelsMap objs) {
ModelsMap postProcessedModelsEnum = postProcessModelsEnum(objs);
return postProcessedModelsEnum;
}
@Override
public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<ModelMap> allModels) {
objs = super.postProcessOperationsWithModels(objs, allModels);
Map<String, Object> vendorExtensions = (Map<String, Object>)objs.get("vendorExtensions");
if (null == vendorExtensions) {
vendorExtensions = new HashMap<>();
objs.put("vendorExtensions", vendorExtensions);
}
vendorExtensions.put("x-xojo-project-id", String.format(Locale.ROOT, "%014XFF", projectObjectNumber));
projectObjectNumber = projectObjectNumber + 16;
return objs;
}
@Override
public void postProcess() {
System.out.println("################################################################################");
System.out.println("# Thanks for using OpenAPI Generator. #");
System.out.println("# Please consider donation to help us maintain this project \uD83D\uDE4F #");
System.out.println("# https://opencollective.com/openapi_generator/donate #");
System.out.println("# #");
System.out.println("# xojo-client contributed by Christopher Kobusch (https://github.com/Topheee). #");
System.out.println("################################################################################");
}
// escape api key name
@Override
@SuppressWarnings("static-method")
public List<CodegenSecurity> fromSecurity(Map<String, SecurityScheme> securitySchemeMap) {
List<CodegenSecurity> securities = super.fromSecurity(securitySchemeMap);
for (CodegenSecurity sec : securities) {
if (sec.isApiKey) sec.name = toVarName(sec.name);
}
return securities;
}
@Override
public GeneratorLanguage generatorLanguage() { return GeneratorLanguage.XOJO; }
@Override
public String toOperationId(String operationId) {
operationId = camelize(sanitizeName(operationId));
// Throw exception if method name is empty.
// This should not happen but keep the check just in case
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
// method name cannot use reserved keyword, e.g. return
if (isReservedWord(operationId)) {
String newOperationId = camelize(("Call_" + operationId));
LOGGER.warn("{} (reserved word) cannot be used as method name. Renamed to {}", operationId, newOperationId);
return newOperationId;
}
// operationId starts with a number
if (operationId.matches("^\\d.*")) {
LOGGER.warn("{} (starting with a number) cannot be used as method name. Renamed to {}", operationId, camelize(sanitizeName("call_" + operationId), LOWERCASE_FIRST_LETTER));
operationId = camelize(sanitizeName("Call_" + operationId));
}
return operationId;
}
@Override
public String toEnumValue(String value, String datatype) {
return "\"" + value + "\"";
}
@Override
public String toEnumVarName(String name, String datatype) {
if (name.length() == 0) {
return "empty";
}
if (enumUnknownDefaultCase) {
if (name.equals(enumUnknownDefaultCaseName)) {
return camelize(name);
}
}
// Reserved Name
String nameLowercase = StringUtils.lowerCase(name);
if (isReservedWord(nameLowercase)) {
return escapeReservedWord(nameLowercase);
}
// Prefix with underscore if name starts with number
if (name.matches("[+-]?\\d.*")) {
LOGGER.warn("Escaping enum var name '" + name + "' to 'Escaped" + replaceSpecialCharacters(camelize(name)) + "'. This will likely cause issues at runtime!");
return "Escaped" + replaceSpecialCharacters(camelize(name));
}
// for symbol, e.g. $, #
if (getSymbolName(name) != null) {
return camelize(WordUtils.capitalizeFully(getSymbolName(name).toUpperCase(Locale.ROOT)));
}
// Camelize only when we have a structure defined below
boolean camelized = false;
if (name.matches("[A-Z][a-z0-9]+[a-zA-Z0-9]*")) {
name = camelize(name);
camelized = true;
}
// Check for numerical conversions
if ("Int".equals(datatype) || "Int32".equals(datatype) || "Int64".equals(datatype)
|| "Float".equals(datatype) || "Double".equals(datatype)) {
String varName = "number" + camelize(name);
return replaceSpecialCharacters(varName);
}
// If we have already camelized the word, don't progress
// any further
if (camelized) {
return replaceSpecialCharacters(name);
}
char[] separators = {'-', '_', ' ', ':', '(', ')'};
return camelize(replaceSpecialCharacters(WordUtils.capitalizeFully(StringUtils.lowerCase(name), separators)
.replaceAll("[-_ :\\(\\)]", "")));
}
private String replaceSpecialCharacters(String name) {
for (Map.Entry<String, String> specialCharacters : specialCharReplacements.entrySet()) {
String specialChar = specialCharacters.getKey();
String replacement = specialCharacters.getValue();
// Underscore is the only special character we'll allow
if (!specialChar.equals("_") && name.contains(specialChar)) {
name = replaceCharacters(name, specialChar, replacement);
}
}
// Fallback, replace unknowns with underscore.
name = name.replaceAll("\\W+", "_");
return name;
}
private String replaceCharacters(String word, String oldValue, String newValue) {
if (!word.contains(oldValue)) {
return word;
}
if (word.equals(oldValue)) {
return newValue;
}
int i = word.indexOf(oldValue);
String start = word.substring(0, i);
String end = recurseOnEndOfWord(word, oldValue, newValue, i);
return start + newValue + end;
}
private String recurseOnEndOfWord(String word, String oldValue, String newValue, int lastReplacedValue) {
String end = word.substring(lastReplacedValue + 1);
if (!end.isEmpty()) {
end = titleCase(end);
end = replaceCharacters(end, oldValue, newValue);
}
return end;
}
private String titleCase(final String input) {
return input.substring(0, 1).toUpperCase(Locale.ROOT) + input.substring(1);
}
@Override
public String toVarName(String name) {
// sanitize name
name = sanitizeName(name);
// if it's all upper case, do nothing
if (name.matches("^[A-Z_]*$")) {
return name;
}
// for reserved word or word starting with number, append _
if (isReservedWord(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name);
}
return name;
}
@Override
public String toParamName(String name) {
// sanitize name
name = sanitizeName(name);
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_");
// if it's all upper case, do nothing
if (name.matches("^[A-Z_]*$")) {
return name;
}
// camelize(lower) the variable name
// pet_id => petId
name = camelize(name, LOWERCASE_FIRST_LETTER);
// for reserved words prepend with 'Escaped'
if (isReservedWord(name)) {
name = escapeReservedWord(name);
}
// for words starting with number, prepend _
if (name.matches("^\\d.*")) {
name = "_" + name;
}
return name;
}
@Override
public String toModelFilename(String name) {
name = super.toModelFilename(name);
// sanitize name
name = sanitizeName(name);
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_");
if (isReservedWord(name)) {
name = escapeReservedWord(name);
}
// for words starting with number, prepend A
if (name.matches("^\\d.*")) {
name = "A" + name;
}
if (!name.equals(toModelName(name))) {
LOGGER.error("Model file name '" + name + "' differs from model name '" + toModelName(name) + "'. This will result in compilation errors.");
}
return name;
}
@Override
public String toModelName(String name) {
name = sanitizeName(name);
if (!StringUtils.isEmpty(modelNameSuffix) && !isLanguageSpecificType(name)) { // set model suffix
name = name + "_" + modelNameSuffix;
}
if (!StringUtils.isEmpty(modelNamePrefix) && !isLanguageSpecificType(name)) { // set model prefix
name = modelNamePrefix + "_" + name;
}
// camelize the model name
// phone_number => PhoneNumber
name = camelize(name);
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(name)) {
String modelName = "Model" + name;
LOGGER.warn("{} (reserved word) cannot be used as model name. Renamed to {}", name, modelName);
return modelName;
}
// model name starts with number
if (name.matches("^\\d.*")) {
// e.g. 200Response => Model200Response (after camelize)
String modelName = "Model" + name;
LOGGER.warn("{} (model name starts with number) cannot be used as model name. Renamed to {}", name,
modelName);
return modelName;
}
return name;
}
@Override
public String toExampleValue(Schema schema) {
if (schema.getExample() != null) {
return schema.getExample().toString();
}
return getPropertyDefaultValue(schema);
}
@Override
public String toDefaultValue(Schema schema) {
if (schema.getDefault() != null) {
return schema.getDefault().toString();
}
return getPropertyDefaultValue(schema);
}
@Override
public void setParameterExampleValue(CodegenParameter codegenParameter) {
super.setParameterExampleValue(codegenParameter);
if (Boolean.TRUE.equals(codegenParameter.isBinary)) {
codegenParameter.example = "GetTemporaryFolderItem";
} else if (Boolean.TRUE.equals(codegenParameter.isByteArray)) {
codegenParameter.example = "New MemoryBlock(8)";
} else if (Boolean.TRUE.equals(codegenParameter.isFile)) {
codegenParameter.example = "GetTemporaryFolderItem";
} else if (Boolean.TRUE.equals(codegenParameter.isDate)) {
codegenParameter.example = "New Date";
} else if (Boolean.TRUE.equals(codegenParameter.isDateTime)) {
codegenParameter.example = "New Date";
} else if (Boolean.TRUE.equals(codegenParameter.isString)) {
codegenParameter.example = codegenParameter.paramName + "_example";
} else if (Boolean.TRUE.equals(codegenParameter.isFreeFormObject)) {
codegenParameter.example = "New Dictionary";
}
}
public SERIALIZATION_LIBRARY_TYPE getSerializationLibrary() {
return this.serializationLibrary;
}
/**
* Sets the serialization engine for Xojo
*
* @param enumSerializationLibrary The string representation of the serialization library as defined by
* {@link org.openapitools.codegen.languages.XojoClientCodegen.SERIALIZATION_LIBRARY_TYPE}
*/
public void setSerializationLibrary(final String enumSerializationLibrary) {
try {
this.serializationLibrary = SERIALIZATION_LIBRARY_TYPE.valueOf(enumSerializationLibrary);
} catch (IllegalArgumentException ex) {
StringBuilder sb = new StringBuilder(enumSerializationLibrary + " is an invalid enum property naming option. Please choose from:");
for (SERIALIZATION_LIBRARY_TYPE t : SERIALIZATION_LIBRARY_TYPE.values()) {
sb.append("\n ").append(t.name());
}
throw new RuntimeException(sb.toString());
}
}
private String getPropertyDefaultValue(Schema schema) {
if (ModelUtils.isBooleanSchema(schema)) {
return "False";
} else if (ModelUtils.isDateSchema(schema)) {
return "Nil";
} else if (ModelUtils.isDateTimeSchema(schema)) {
return "Nil";
} else if (ModelUtils.isNumberSchema(schema)) {
return "0";
} else if (ModelUtils.isIntegerSchema(schema)) {
return "0";
} else if (ModelUtils.isStringSchema(schema)) {
return "Sample";
} else if (ModelUtils.isObjectSchema(schema)) {
return "Nil";
} else {
return "Nil";
}
}
private void syncBooleanProperty(final Map<String, Object> additionalProperties, final String key, final Consumer<Boolean> setter, final Boolean defaultValue) {
if (additionalProperties.containsKey(key)) {
setter.accept(convertPropertyToBooleanAndWriteBack(key));
} else {
additionalProperties.put(key, defaultValue);
setter.accept(defaultValue);
}
}
private void syncStringProperty(final Map<String, Object> additionalProperties, final String key, final Consumer<String> setter, final String defaultValue) {
if (additionalProperties.containsKey(key)) {
setter.accept((String) additionalProperties.get(key));
} else {
additionalProperties.put(key, defaultValue);
setter.accept(defaultValue);
}
}
private Boolean isLanguageSpecificType(String name) {
return languageSpecificPrimitives.contains(name);
}
}

View File

@@ -241,6 +241,61 @@ public class ProcessUtils {
return false;
}
/**
* Returns true if the specified OAS model has at least one operation with OpenIdConnect authentication.
*
* @param openAPI An instance of OpenAPI
* @return True if at least one operation has OpenIdConnect security scheme defined
*/
public static boolean hasOpenIdConnectMethods(OpenAPI openAPI) {
final Map<String, SecurityScheme> securitySchemes = getSecuritySchemes(openAPI);
if (securitySchemes != null) {
for (Map.Entry<String, SecurityScheme> scheme : securitySchemes.entrySet()) {
if (SecurityScheme.Type.OPENIDCONNECT.equals(scheme.getValue().getType())) {
return true;
}
}
}
return false;
}
/**
* Returns a list of OpenIdConnect Codegen security objects
*
* @param authMethods List of auth methods.
* @return A list of OpenIdConnect Codegen security objects
*/
public static List<CodegenSecurity> getOpenIdConnectMethods(List<CodegenSecurity> authMethods) {
List<CodegenSecurity> oauthMethods = new ArrayList<>();
for (CodegenSecurity cs : authMethods) {
if (Boolean.TRUE.equals(cs.isOpenId)) {
oauthMethods.add(cs);
}
}
return oauthMethods;
}
/**
* Returns a list of OpenIdConnect Codegen security objects
*
* @param authMethods List of auth methods.
* @return A list of OpenIdConnect Codegen security objects
*/
public static boolean hasOpenIdConnectMethods(List<CodegenSecurity> authMethods) {
for (CodegenSecurity cs : authMethods) {
if (Boolean.TRUE.equals(cs.isOpenId)) {
return true;
}
}
return false;
}
/**
* Returns true if the specified OAS model has at least one operation with HTTP bearer authentication.
*

View File

@@ -80,16 +80,9 @@ Category | Method | HTTP request | Description
## Documentation for Authorization
{{^authMethods}}
All endpoints do not require authorization.
{{/authMethods}}
{{^authMethods}}Endpoints do not require authorization.{{/authMethods}}
{{#hasAuthMethods}}Authentication schemes defined for the API:{{/hasAuthMethods}}
{{#authMethods}}
{{#last}}
Authentication schemes defined for the API:
{{/last}}
{{/authMethods}}
{{#authMethods}}
### {{name}}
{{#isApiKey}}- **Type**: API key

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