Merge remote-tracking branch 'origin/master' into 6.0.x

This commit is contained in:
William Cheng 2021-03-03 16:19:20 +08:00
commit d96197bcbd
1471 changed files with 69970 additions and 14636 deletions

6
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"

View File

@ -10,7 +10,7 @@ jobs:
build:
runs-on: ubuntu-latest
if: ${{ github.repository_owner == 'OpenAPITools' }}
steps:
- uses: actions/checkout@v1
- name: Set up JDK 11

View File

@ -149,6 +149,8 @@ install:
script:
# fail fast
- set -e
# fail if the template files contains tabs
- /bin/bash ./bin/utils/detect_tab_in_templates.sh
# fail if the test files have changes
- bin/utils/detect_test_file_changes.rb bin/utils/test_file_list.yaml
# fail if templates/generators contain carriage return '\r'

View File

@ -69,7 +69,7 @@ OpenAPI Generator allows generation of API client libraries (SDK generation), se
| | Languages/Frameworks |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **API clients** | **ActionScript**, **Ada**, **Apex**, **Bash**, **C**, **C#** (.net 2.0, 3.5 or later, .NET Standard 1.3 - 2.0, .NET Core 2.0, .NET 5.0), **C++** (cpp-restsdk, Qt5, Tizen, Unreal Engine 4), **Clojure**, **Crystal**, **Dart**, **Elixir**, **Elm**, **Eiffel**, **Erlang**, **Go**, **Groovy**, **Haskell** (http-client, Servant), **Java** (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), **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 - 11.x), Aurelia, Axios, Fetch, Inversify, jQuery, Nestjs, Node, redux-query, Rxjs) |
| **API clients** | **ActionScript**, **Ada**, **Apex**, **Bash**, **C**, **C#** (.net 2.0, 3.5 or later, .NET Standard 1.3 - 2.0, .NET Core 2.0, .NET 5.0. Libraries: RestSharp, HttpClient), **C++** (cpp-restsdk, Qt5, Tizen, Unreal Engine 4), **Clojure**, **Crystal**, **Dart**, **Elixir**, **Elm**, **Eiffel**, **Erlang**, **Go**, **Groovy**, **Haskell** (http-client, Servant), **Java** (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), **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 - 11.x), Aurelia, Axios, Fetch, Inversify, jQuery, Nestjs, Node, redux-query, Rxjs) |
| **Server stubs** | **Ada**, **C#** (ASP.NET Core, NancyFx), **C++** (Pistache, Restbed, Qt5 QHTTPEngine), **Erlang**, **F#** (Giraffe), **Go** (net/http, Gin), **Haskell** (Servant), **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/)), **Kotlin** (Spring Boot, Ktor, Vertx), **PHP** (Laravel, Lumen, Slim, Silex, [Symfony](https://symfony.com/), [Zend Expressive](https://github.com/zendframework/zend-expressive)), **Python** (Flask), **NodeJS**, **Ruby** (Sinatra, Rails5), **Rust** (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/) |
@ -606,6 +606,7 @@ Here are some companies/projects (alphabetical order) using OpenAPI Generator in
- [GetYourGuide](https://www.getyourguide.com/)
- [GMO Pepabo](https://pepabo.com/en/)
- [GoDaddy](https://godaddy.com)
- [Gumtree](https://gumtree.com)
- [Here](https://developer.here.com/)
- [IBM](https://www.ibm.com/)
- [Instana](https://www.instana.com)
@ -801,6 +802,8 @@ Here are some companies/projects (alphabetical order) using OpenAPI Generator in
- 2020-12-15 - [Next.js + NestJS + GraphQLで変化に追従するフロントエンドへ 〜 ショッピングクーポンの事例紹介](https://techblog.yahoo.co.jp/entry/2020121530052952/) by [小倉 陸](https://github.com/ogugu9) at [Yahoo! JAPAN Tech Blog](https://techblog.yahoo.co.jp/)
- 2021-01-08 - [Hello, New API Part 1](https://www.nginx.com/blog/hello-new-api-part-1/) by [Jeremy Schulman](https://www.nginx.com/people/jeremy-schulman/) at [Major League Baseball](https://www.mlb.com)
- 2021-01-18 - [「アプリ開発あるある」を疑うことから始まった、API Clientコードの自動生成【デブスト2020】](https://codezine.jp/article/detail/13406?p=2) by [CodeZine編集部](https://codezine.jp/author/1)
- 2021-02-05 - [REST-API-Roundtrip with SpringDoc and OpenAPI Generator](https://blog.viadee.de/en/rest-api-roundtrip) by [Benjamin Klatt](https://twitter.com/benklatt) at [viadee](https://www.viadee.de/en/)
- 2021-02-17 - [REST-API-Roundtrip with SpringDoc and OpenAPI Generator](https://medium.com/nerd-for-tech/rest-api-roundtrip-with-springdoc-and-openapi-generator-30bd27ccf698) by [cloud @viadee](https://cloud-viadee.medium.com/)
## [6 - About Us](#table-of-contents)
@ -834,6 +837,7 @@ Here is a list of template creators:
* C# (.NET 2.0): @who
* C# (.NET Standard 1.3 ): @Gronsak
* C# (.NET 4.5 refactored): @jimschubert [:heart:](https://www.patreon.com/jimschubert)
* C# (HttpClient): @Blackclaws
* Clojure: @xhh
* Crystal: @wing328
* Dart: @yissachar

View File

@ -35,12 +35,16 @@ install:
- ps: Install-Module Pester -Force -Scope CurrentUser
build_script:
- dotnet --info
# build C# aspnetcore 5.0 server
- dotnet build samples\server\petstore\aspnetcore-5.0\Org.OpenAPITools.sln
# build C# aspnetcore 3.1 server
- dotnet build samples\server\petstore\aspnetcore-3.1\Org.OpenAPITools.sln
# build C# aspnetcore 3.0 server
- dotnet build samples\server\petstore\aspnetcore-3.0\Org.OpenAPITools.sln
# build C# aspnetcore 2.2 server
- dotnet build samples\server\petstore\aspnetcore\Org.OpenAPITools.sln
# build C# API client (httpclient)
- dotnet build samples\client\petstore\csharp-netcore\OpenAPIClient-httpclient\Org.OpenAPITools.sln
# build C# API client (netcore)
- dotnet build samples\client\petstore\csharp-netcore\OpenAPIClient\Org.OpenAPITools.sln
- dotnet build samples\client\petstore\csharp-netcore\OpenAPIClientCore\Org.OpenAPITools.sln
@ -62,6 +66,8 @@ build_script:
# run the locally installed openapi-generator-gradle-plugin
- gradle -b modules\openapi-generator-gradle-plugin\samples\local-spec\build.gradle buildGoSdk --stacktrace
test_script:
# test c# API client (httpclient)
- dotnet test samples\client\petstore\csharp-netcore\OpenAPIClient-httpclient\src\Org.OpenAPITools.Test\Org.OpenAPITools.Test.csproj
# test c# API client (netcore)
- dotnet test samples\client\petstore\csharp-netcore\OpenAPIClientCore\src\Org.OpenAPITools.Test\Org.OpenAPITools.Test.csproj
- dotnet test samples\client\petstore\csharp-netcore\OpenAPIClient\src\Org.OpenAPITools.Test\Org.OpenAPITools.Test.csproj

View File

@ -0,0 +1,7 @@
generatorName: aspnetcore
outputDir: samples/server/petstore/aspnetcore-5.0
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/aspnetcore/3.0
additionalProperties:
packageGuid: '{3C799344-F285-4669-8FD5-7ED9B795D5C5}'
aspnetCoreVersion: "5.0"

View File

@ -0,0 +1,12 @@
# for .net standard httpclient
generatorName: csharp-netcore
outputDir: samples/client/petstore/csharp-netcore/OpenAPIClient-httpclient
inputSpec: modules/openapi-generator/src/test/resources/3_0/java/petstore-with-fake-endpoints-models-for-testing-with-http-signature.yaml
templateDir: modules/openapi-generator/src/main/resources/csharp-netcore
library: httpclient
additionalProperties:
packageGuid: '{321C8C3F-0156-40C1-AE42-D59761FB9B6C}'
useCompareNetObjects: true
disallowAdditionalPropertiesIfNotPresent: false
useOneOfDiscriminatorLookup: true
targetFramework: netstandard2.1

View File

@ -0,0 +1,7 @@
generatorName: dart
outputDir: samples/openapi3/client/petstore/dart2/petstore_json_serializable_client_lib_fake
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml
templateDir: modules/openapi-generator/src/main/resources/dart2
additionalProperties:
hideGenerationTimestamp: "true"
serializationLibrary: json_serializable

View File

@ -0,0 +1,28 @@
#!/bin/bash
#
# Look for \t in the template folders and report errors if found
# as these tabs should be replaced with 4-space instead
## declare an array of folders
declare -a samples=("modules/openapi-generator/src/main/resources/kotlin-server"
"modules/openapi-generator/src/main/resources/kotlin-spring"
"modules/openapi-generator/src/main/resources/dart-dio"
"modules/openapi-generator/src/main/resources/dart"
"modules/openapi-generator/src/main/resources/dart2"
"modules/openapi-generator/src/main/resources/aspnetcore"
"modules/openapi-generator/src/main/resources/powershell"
)
## now loop through the above array
for i in "${samples[@]}"
do
# grep for \t in the folder
RESULT=`grep -R -P "\t" $i`
echo -e "$RESULT"
if [ "$RESULT" != "" ]; then
echo "Template files contain tab '\\t'. Please remove it or replace it with 4-space."
exit 1;
fi
done

View File

@ -7,7 +7,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| Option | Description | Values | Default |
| ------ | ----------- | ------ | ------- |
|aspnetCoreVersion|ASP.NET Core version: 3.1, 3.0, 2.2, 2.1, 2.0 (deprecated)| |3.1|
|aspnetCoreVersion|ASP.NET Core version: 5.0, 3.1, 3.0, 2.2, 2.1, 2.0 (deprecated)| |3.1|
|buildTarget|Target to build an application or library| |program|
|classModifier|Class Modifier for controller classes: Empty string or abstract.| ||
|compatibilityVersion|ASP.Net Core CompatibilityVersion| |Version_2_2|

View File

@ -12,6 +12,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|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|
|hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |true|
|interfacePrefix|Prefix interfaces with a community standard or widely accepted prefix.| |I|
|library|HTTP library template (sub-template) to use|<dl><dt>**httpclient**</dt><dd>HttpClient (https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient) (Beta support)</dd><dt>**restsharp**</dt><dd>RestSharp (https://github.com/restsharp/RestSharp)</dd></dl>|restsharp|
|licenseId|The identifier of the license| |null|
|modelPropertyNaming|Naming convention for the property: 'camelCase', 'PascalCase', 'snake_case' and 'original', which keeps the original name| |PascalCase|
|netCoreProjectFile|Use the new format (.NET Core) for .NET project files (.csproj).| |false|

View File

@ -12,7 +12,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|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|
|legacyDiscriminatorBehavior|Set to true 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|
|nullableFields|Is the null fields should be in the JSON payload| |null|
|nullableFields|Make all fields nullable in the JSON payload| |null|
|prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false|
|pubAuthor|Author name in generated pubspec| |null|
|pubAuthorEmail|Email address of the author in generated pubspec| |null|

View File

@ -19,6 +19,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|pubLibrary|Library name in generated code| |null|
|pubName|Name in generated pubspec| |null|
|pubVersion|Version in generated pubspec| |null|
|serializationLibrary|Specify serialization library|<dl><dt>**native_serialization**</dt><dd>Use native serializer, backwards compatible</dd><dt>**json_serializable**</dt><dd>Use json_serializable</dd></dl>|native_serialization|
|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true|
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|sourceFolder|Source folder for generated code| |null|

View File

@ -8,6 +8,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| Option | Description | Values | Default |
| ------ | ----------- | ------ | ------- |
|apiPath|Name of the folder that contains the Go source code| |go|
|enumClassPrefix|Prefix enum with class name| |false|
|hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |true|
|packageName|Go package name (convention: lowercase).| |openapi|
|packageVersion|Go package version.| |1.0.0|

View File

@ -52,7 +52,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|scmDeveloperConnection|SCM developer connection in generated pom.xml| |scm:git:git@github.com:openapitools/openapi-generator.git|
|scmUrl|SCM URL in generated pom.xml| |https://github.com/openapitools/openapi-generator|
|serializableModel|boolean - toggle &quot;implements Serializable&quot; for generated models| |false|
|serializationLibrary|Serialization library, default depends from the library|<dl><dt>**jackson**</dt><dd>Use Jackson as serialization library</dd><dt>**gson**</dt><dd>Use Gson as serialization library</dd></dl>|null|
|serializationLibrary|Serialization library, default depends from the library|<dl><dt>**jsonb**</dt><dd>Use JSON-B as serialization library</dd><dt>**jackson**</dt><dd>Use Jackson as serialization library</dd><dt>**gson**</dt><dd>Use Gson as serialization library</dd></dl>|null|
|snapshotVersion|Uses a SNAPSHOT version.|<dl><dt>**true**</dt><dd>Use a SnapShot Version</dd><dt>**false**</dt><dd>Use a Release Version</dd></dl>|null|
|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true|
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|

View File

@ -33,7 +33,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| Type/Alias | Instantiated By |
| ---------- | --------------- |
|array|array|
|map|map|
|map|array|
## LANGUAGE PRIMITIVES

View File

@ -33,7 +33,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| Type/Alias | Instantiated By |
| ---------- | --------------- |
|array|array|
|map|map|
|map|array|
## LANGUAGE PRIMITIVES

View File

@ -33,7 +33,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| Type/Alias | Instantiated By |
| ---------- | --------------- |
|array|array|
|map|map|
|map|array|
## LANGUAGE PRIMITIVES

View File

@ -33,7 +33,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| Type/Alias | Instantiated By |
| ---------- | --------------- |
|array|array|
|map|map|
|map|array|
## LANGUAGE PRIMITIVES

View File

@ -34,7 +34,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| Type/Alias | Instantiated By |
| ---------- | --------------- |
|array|array|
|map|map|
|map|array|
## LANGUAGE PRIMITIVES

View File

@ -39,7 +39,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| Type/Alias | Instantiated By |
| ---------- | --------------- |
|array|array|
|map|map|
|map|array|
## LANGUAGE PRIMITIVES

View File

@ -34,7 +34,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| Type/Alias | Instantiated By |
| ---------- | --------------- |
|array|array|
|map|map|
|map|array|
## LANGUAGE PRIMITIVES

View File

@ -42,13 +42,14 @@ These options may be applied as additional-properties (cli) or configOptions (pl
<li>Dict</li>
<li>List</li>
<li>bool</li>
<li>byte</li>
<li>bytearray</li>
<li>bytes</li>
<li>date</li>
<li>datetime</li>
<li>dict</li>
<li>file</li>
<li>float</li>
<li>int</li>
<li>list</li>
<li>object</li>
<li>str</li>
</ul>
@ -56,9 +57,14 @@ These options may be applied as additional-properties (cli) or configOptions (pl
## RESERVED WORDS
<ul class="column-ul">
<li>all_params</li>
<li>and</li>
<li>as</li>
<li>assert</li>
<li>async</li>
<li>auth_settings</li>
<li>await</li>
<li>body_params</li>
<li>break</li>
<li>class</li>
<li>continue</li>
@ -71,21 +77,27 @@ These options may be applied as additional-properties (cli) or configOptions (pl
<li>false</li>
<li>finally</li>
<li>for</li>
<li>form_params</li>
<li>from</li>
<li>global</li>
<li>header_params</li>
<li>if</li>
<li>import</li>
<li>in</li>
<li>is</li>
<li>lambda</li>
<li>local_var_files</li>
<li>none</li>
<li>nonlocal</li>
<li>not</li>
<li>or</li>
<li>pass</li>
<li>path_params</li>
<li>print</li>
<li>property</li>
<li>query_params</li>
<li>raise</li>
<li>resource_path</li>
<li>return</li>
<li>self</li>
<li>true</li>

View File

@ -42,13 +42,14 @@ These options may be applied as additional-properties (cli) or configOptions (pl
<li>Dict</li>
<li>List</li>
<li>bool</li>
<li>byte</li>
<li>bytearray</li>
<li>bytes</li>
<li>date</li>
<li>datetime</li>
<li>dict</li>
<li>file</li>
<li>float</li>
<li>int</li>
<li>list</li>
<li>object</li>
<li>str</li>
</ul>
@ -56,9 +57,14 @@ These options may be applied as additional-properties (cli) or configOptions (pl
## RESERVED WORDS
<ul class="column-ul">
<li>all_params</li>
<li>and</li>
<li>as</li>
<li>assert</li>
<li>async</li>
<li>auth_settings</li>
<li>await</li>
<li>body_params</li>
<li>break</li>
<li>class</li>
<li>continue</li>
@ -71,21 +77,27 @@ These options may be applied as additional-properties (cli) or configOptions (pl
<li>false</li>
<li>finally</li>
<li>for</li>
<li>form_params</li>
<li>from</li>
<li>global</li>
<li>header_params</li>
<li>if</li>
<li>import</li>
<li>in</li>
<li>is</li>
<li>lambda</li>
<li>local_var_files</li>
<li>none</li>
<li>nonlocal</li>
<li>not</li>
<li>or</li>
<li>pass</li>
<li>path_params</li>
<li>print</li>
<li>property</li>
<li>query_params</li>
<li>raise</li>
<li>resource_path</li>
<li>return</li>
<li>self</li>
<li>true</li>

View File

@ -42,13 +42,14 @@ These options may be applied as additional-properties (cli) or configOptions (pl
<li>Dict</li>
<li>List</li>
<li>bool</li>
<li>byte</li>
<li>bytearray</li>
<li>bytes</li>
<li>date</li>
<li>datetime</li>
<li>dict</li>
<li>file</li>
<li>float</li>
<li>int</li>
<li>list</li>
<li>object</li>
<li>str</li>
</ul>
@ -56,9 +57,14 @@ These options may be applied as additional-properties (cli) or configOptions (pl
## RESERVED WORDS
<ul class="column-ul">
<li>all_params</li>
<li>and</li>
<li>as</li>
<li>assert</li>
<li>async</li>
<li>auth_settings</li>
<li>await</li>
<li>body_params</li>
<li>break</li>
<li>class</li>
<li>continue</li>
@ -71,21 +77,27 @@ These options may be applied as additional-properties (cli) or configOptions (pl
<li>false</li>
<li>finally</li>
<li>for</li>
<li>form_params</li>
<li>from</li>
<li>global</li>
<li>header_params</li>
<li>if</li>
<li>import</li>
<li>in</li>
<li>is</li>
<li>lambda</li>
<li>local_var_files</li>
<li>none</li>
<li>nonlocal</li>
<li>not</li>
<li>or</li>
<li>pass</li>
<li>path_params</li>
<li>print</li>
<li>property</li>
<li>query_params</li>
<li>raise</li>
<li>resource_path</li>
<li>return</li>
<li>self</li>
<li>true</li>

View File

@ -23,7 +23,7 @@ import java.util.stream.Stream;
@Command(name = "template", description = "Retrieve templates for local modification")
public class AuthorTemplate extends OpenApiGeneratorCommand {
private static final Logger LOGGER = LoggerFactory.getLogger(AuthorTemplate.class);
private final Logger LOGGER = LoggerFactory.getLogger(AuthorTemplate.class);
@Option(name = {"-g", "--generator-name"}, title = "generator name",
description = "generator to use (see list command for list)",

View File

@ -43,7 +43,7 @@ import static org.apache.commons.lang3.StringUtils.isEmpty;
@Command(name = "config-help", description = "Config help for chosen lang")
public class ConfigHelp extends OpenApiGeneratorCommand {
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigHelp.class);
private final Logger LOGGER = LoggerFactory.getLogger(ConfigHelp.class);
private static final String FORMAT_TEXT = "text";
private static final String FORMAT_MARKDOWN = "markdown";

View File

@ -217,6 +217,10 @@ public class Generate extends OpenApiGeneratorCommand {
description = CodegenConstants.REMOVE_OPERATION_ID_PREFIX_DESC)
private Boolean removeOperationIdPrefix;
@Option(name = {"--skip-operation-example"}, title = "skip examples defined in the operation",
description = CodegenConstants.SKIP_OPERATION_EXAMPLE_DESC)
private Boolean skipOperationExample;
@Option(name = {"--skip-validate-spec"},
title = "skip spec validation",
description = "Skips the default behavior of validating an input specification.")
@ -393,6 +397,10 @@ public class Generate extends OpenApiGeneratorCommand {
configurator.setRemoveOperationIdPrefix(removeOperationIdPrefix);
}
if (skipOperationExample != null) {
configurator.setSkipOperationExample(skipOperationExample);
}
if (enablePostProcessFile != null) {
configurator.setEnablePostProcessFile(enablePostProcessFile);
}

View File

@ -65,7 +65,7 @@ import java.util.stream.Stream;
public class GenerateBatch extends OpenApiGeneratorCommand {
private static AtomicInteger failures = new AtomicInteger(0);
private static AtomicInteger successes = new AtomicInteger(0);
private static final Logger LOGGER = LoggerFactory.getLogger(GenerateBatch.class);
private final Logger LOGGER = LoggerFactory.getLogger(GenerateBatch.class);
@Option(name = {"-v", "--verbose"}, description = "verbose mode")
private Boolean verbose;

View File

@ -53,5 +53,5 @@ public interface TemplateProcessor {
* @param path The path which has caused an error
* @param context The reason for the error
*/
default void error(Path path, String context) { };
default void error(Path path, String context) { }
}

View File

@ -30,10 +30,10 @@ import java.util.*;
public final class GeneratorSettings implements Serializable {
private static final Logger LOGGER = LoggerFactory.getLogger(GeneratorSettings.class);
private static String DEFAULT_GIT_HOST = "github.com";
private static String DEFAULT_GIT_USER_ID = "GIT_USER_ID";
private static String DEFAULT_GIT_REPO_ID = "GIT_REPO_ID";
private static String DEFAULT_RELEASE_NOTE = "Minor update";
private static final String DEFAULT_GIT_HOST = "github.com";
private static final String DEFAULT_GIT_USER_ID = "GIT_USER_ID";
private static final String DEFAULT_GIT_REPO_ID = "GIT_REPO_ID";
private static final String DEFAULT_RELEASE_NOTE = "Minor update";
private String generatorName;
private String apiPackage;
@ -48,13 +48,13 @@ public final class GeneratorSettings implements Serializable {
private String artifactVersion;
private String library;
private ImmutableMap<String, String> instantiationTypes;
private ImmutableMap<String, String> typeMappings;
private ImmutableMap<String, Object> additionalProperties;
private ImmutableMap<String, String> importMappings;
private ImmutableSet<String> languageSpecificPrimitives;
private ImmutableMap<String, String> reservedWordMappings;
private ImmutableMap<String, String> serverVariables;
private final ImmutableMap<String, String> instantiationTypes;
private final ImmutableMap<String, String> typeMappings;
private final ImmutableMap<String, Object> additionalProperties;
private final ImmutableMap<String, String> importMappings;
private final ImmutableSet<String> languageSpecificPrimitives;
private final ImmutableMap<String, String> reservedWordMappings;
private final ImmutableMap<String, String> serverVariables;
private String gitHost;
private String gitUserId;

View File

@ -36,12 +36,13 @@ import java.util.regex.Pattern;
*/
@SuppressWarnings("WeakerAccess")
public class WorkflowSettings {
private static final AtomicLong lastWarning = new AtomicLong(0);
private static final Logger LOGGER = LoggerFactory.getLogger(WorkflowSettings.class);
public static final String DEFAULT_OUTPUT_DIR = ".";
public static final boolean DEFAULT_VERBOSE = false;
public static final boolean DEFAULT_SKIP_OVERWRITE = false;
public static final boolean DEFAULT_REMOVE_OPERATION_ID_PREFIX = false;
public static final boolean DEFAULT_SKIP_OPERATION_EXAMPLE = false;
public static final boolean DEFAULT_LOG_TO_STDERR = false;
public static final boolean DEFAULT_VALIDATE_SPEC = true;
public static final boolean DEFAULT_ENABLE_POST_PROCESS_FILE = false;
@ -56,6 +57,7 @@ public class WorkflowSettings {
private boolean verbose = DEFAULT_VERBOSE;
private boolean skipOverwrite = DEFAULT_SKIP_OVERWRITE;
private boolean removeOperationIdPrefix = DEFAULT_REMOVE_OPERATION_ID_PREFIX;
private boolean skipOperationExample = DEFAULT_SKIP_OPERATION_EXAMPLE;
private boolean logToStderr = DEFAULT_LOG_TO_STDERR;
private boolean validateSpec = DEFAULT_VALIDATE_SPEC;
private boolean enablePostProcessFile = DEFAULT_ENABLE_POST_PROCESS_FILE;
@ -104,6 +106,7 @@ public class WorkflowSettings {
builder.verbose = copy.isVerbose();
builder.skipOverwrite = copy.isSkipOverwrite();
builder.removeOperationIdPrefix = copy.isRemoveOperationIdPrefix();
builder.skipOperationExample = copy.isSkipOperationExample();
builder.logToStderr = copy.isLogToStderr();
builder.validateSpec = copy.isValidateSpec();
builder.enablePostProcessFile = copy.isEnablePostProcessFile();
@ -169,6 +172,15 @@ public class WorkflowSettings {
return removeOperationIdPrefix;
}
/**
* Indicates whether or not to skip examples defined in the operation.
*
* @return <code>true</code> if the examples defined in the operation should be skipped.
*/
public boolean isSkipOperationExample() {
return skipOperationExample;
}
/**
* Indicates whether or not the generator's executor will write all log messages (not just errors) to STDOUT. Useful for
* piping the JSON output of debug options (e.g. <code>-DdebugOperations</code>) to an external parser directly while testing a generator.
@ -284,6 +296,7 @@ public class WorkflowSettings {
private Boolean verbose = DEFAULT_VERBOSE;
private Boolean skipOverwrite = DEFAULT_SKIP_OVERWRITE;
private Boolean removeOperationIdPrefix = DEFAULT_REMOVE_OPERATION_ID_PREFIX;
private Boolean skipOperationExample = DEFAULT_SKIP_OPERATION_EXAMPLE;
private Boolean logToStderr = DEFAULT_LOG_TO_STDERR;
private Boolean validateSpec = DEFAULT_VALIDATE_SPEC;
private Boolean enablePostProcessFile = DEFAULT_ENABLE_POST_PROCESS_FILE;
@ -295,7 +308,7 @@ public class WorkflowSettings {
private String ignoreFileOverride;
// NOTE: All collections must be mutable in the builder, and copied to a new immutable collection in .build()
private Map<String, String> globalProperties = new HashMap<>();;
private Map<String, String> globalProperties = new HashMap<>();
private Builder() {
}
@ -362,6 +375,17 @@ public class WorkflowSettings {
return this;
}
/**
* Sets the {@code skipOperationExample} and returns a reference to this Builder so that the methods can be chained together.
*
* @param skipOperationExample the {@code skipOperationExample} to set
* @return a reference to this Builder
*/
public Builder withSkipOperationExample(Boolean skipOperationExample) {
this.skipOperationExample = skipOperationExample != null ? skipOperationExample : Boolean.valueOf(DEFAULT_REMOVE_OPERATION_ID_PREFIX);
return this;
}
/**
* Sets the {@code logToStderr} and returns a reference to this Builder so that the methods can be chained together.
*
@ -568,6 +592,7 @@ public class WorkflowSettings {
return isVerbose() == that.isVerbose() &&
isSkipOverwrite() == that.isSkipOverwrite() &&
isRemoveOperationIdPrefix() == that.isRemoveOperationIdPrefix() &&
isSkipOperationExample() == that.isSkipOperationExample() &&
isLogToStderr() == that.isLogToStderr() &&
isValidateSpec() == that.isValidateSpec() &&
isEnablePostProcessFile() == that.isEnablePostProcessFile() &&
@ -590,6 +615,7 @@ public class WorkflowSettings {
isVerbose(),
isSkipOverwrite(),
isRemoveOperationIdPrefix(),
isSkipOperationExample(),
isLogToStderr(),
isValidateSpec(),
isGenerateAliasAsModel(),

View File

@ -294,6 +294,11 @@ apply plugin: 'org.openapi.generator'
|false
|Remove prefix of operationId, e.g. config_getId => getId.
|skipOperationExample
|Boolean
|false
|Skip examples defined in the operation
|apiFilesConstrainedTo
|List(String)
|None

View File

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

View File

@ -125,6 +125,7 @@ class OpenApiGeneratorPlugin : Plugin<Project> {
reservedWordsMappings.set(generate.reservedWordsMappings)
ignoreFileOverride.set(generate.ignoreFileOverride)
removeOperationIdPrefix.set(generate.removeOperationIdPrefix)
skipOperationExample.set(generate.skipOperationExample)
apiFilesConstrainedTo.set(generate.apiFilesConstrainedTo)
modelFilesConstrainedTo.set(generate.modelFilesConstrainedTo)
supportingFilesConstrainedTo.set(generate.supportingFilesConstrainedTo)

View File

@ -201,6 +201,11 @@ open class OpenApiGeneratorGenerateExtension(project: Project) {
*/
val removeOperationIdPrefix = project.objects.property<Boolean?>()
/**
* Skip examples defined in the operation
*/
val skipOperationExample = project.objects.property<Boolean?>()
/**
* Defines which API-related files should be generated. This allows you to create a subset of generated files (or none at all).
*

View File

@ -304,6 +304,13 @@ open class GenerateTask : DefaultTask() {
@Input
val removeOperationIdPrefix = project.objects.property<Boolean?>()
/**
* Remove examples defined in the operation
*/
@Optional
@Input
val skipOperationExample = project.objects.property<Boolean?>()
/**
* Defines which API-related files should be generated. This allows you to create a subset of generated files (or none at all).
*
@ -615,6 +622,10 @@ open class GenerateTask : DefaultTask() {
configurator.setRemoveOperationIdPrefix(value!!)
}
skipOperationExample.ifNotEmpty { value ->
configurator.setSkipOperationExample(value!!)
}
logToStderr.ifNotEmpty { value ->
configurator.setLogToStderr(value)
}

View File

@ -70,6 +70,7 @@ mvn clean compile
| `ignoreFileOverride` | `openapi.generator.maven.plugin.ignoreFileOverride` | specifies the full path to a `.openapi-generator-ignore` used for pattern based overrides of generated outputs
| `httpUserAgent` | `openapi.generator.maven.plugin.httpUserAgent` | Sets custom User-Agent header value
| `removeOperationIdPrefix` | `openapi.generator.maven.plugin.removeOperationIdPrefix` | remove operationId prefix (e.g. user_getName => getName)
| `skipOperationExample` | `openapi.generator.maven.plugin.skipOperationExample` | skip examples defined in the operation
| `logToStderr` | `openapi.generator.maven.plugin.logToStderr` | write all log messages (not just errors) to STDOUT
| `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.

View File

@ -73,7 +73,7 @@ import com.google.common.io.Files;
@Mojo(name = "generate", defaultPhase = LifecyclePhase.GENERATE_SOURCES, threadSafe = true)
public class CodeGenMojo extends AbstractMojo {
private static final Logger LOGGER = LoggerFactory.getLogger(CodeGenMojo.class);
private final Logger LOGGER = LoggerFactory.getLogger(CodeGenMojo.class);
/**
* The build context is only avail when running from within eclipse.
@ -237,6 +237,12 @@ public class CodeGenMojo extends AbstractMojo {
@Parameter(name = "removeOperationIdPrefix", property = "openapi.generator.maven.plugin.removeOperationIdPrefix")
private Boolean removeOperationIdPrefix;
/**
* To skip examples defined in the operation
*/
@Parameter(name = "skipOperationExample", property = "openapi.generator.maven.plugin.skipOperationExample")
private Boolean skipOperationExample;
/**
* To write all log messages (not just errors) to STDOUT
*/
@ -485,6 +491,10 @@ public class CodeGenMojo extends AbstractMojo {
configurator.setRemoveOperationIdPrefix(removeOperationIdPrefix);
}
if (skipOperationExample != null) {
configurator.setSkipOperationExample(skipOperationExample);
}
if (isNotEmpty(inputSpec)) {
configurator.setInputSpec(inputSpec);
}
@ -748,7 +758,10 @@ public class CodeGenMojo extends AbstractMojo {
if (storedInputSpecHashFile.getParent() != null && !new File(storedInputSpecHashFile.getParent()).exists()) {
File parent = new File(storedInputSpecHashFile.getParent());
parent.mkdirs();
if (!parent.mkdirs()) {
throw new RuntimeException("Failed to create the folder " + parent.getAbsolutePath() +
" to store the checksum of the input spec.");
}
}
Files.asCharSink(storedInputSpecHashFile, StandardCharsets.UTF_8).write(inputSpecHash);
@ -780,7 +793,7 @@ public class CodeGenMojo extends AbstractMojo {
File inputSpecTempFile = inputSpecFile;
if (inputSpecRemoteUrl != null) {
inputSpecTempFile = File.createTempFile("openapi-spec", ".tmp");
inputSpecTempFile = java.nio.file.Files.createTempFile("openapi-spec", ".tmp").toFile();
URLConnection conn = inputSpecRemoteUrl.openConnection();
if (isNotEmpty(auth)) {

View File

@ -35,6 +35,7 @@ import org.springframework.http.HttpStatus;
import org.springframework.web.server.ResponseStatusException;
import java.io.File;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
@ -181,9 +182,7 @@ public class Generator {
private static File getTmpFolder() {
try {
File outputFolder = File.createTempFile("codegen-", "-tmp");
outputFolder.delete();
outputFolder.mkdir();
File outputFolder = Files.createTempDirectory("codegen-tmp").toFile();
outputFolder.deleteOnExit();
return outputFolder;
} catch (Exception e) {

View File

@ -214,6 +214,10 @@ public interface CodegenConfig {
void setRemoveOperationIdPrefix(boolean removeOperationIdPrefix);
boolean isSkipOperationExample();
void setSkipOperationExample(boolean skipOperationExample);
public boolean isHideGenerationTimestamp();
public void setHideGenerationTimestamp(boolean hideGenerationTimestamp);

View File

@ -309,6 +309,9 @@ public class CodegenConstants {
public static final String REMOVE_OPERATION_ID_PREFIX = "removeOperationIdPrefix";
public static final String REMOVE_OPERATION_ID_PREFIX_DESC = "Remove prefix of operationId, e.g. config_getId => getId";
public static final String SKIP_OPERATION_EXAMPLE = "skipOperationExample";
public static final String SKIP_OPERATION_EXAMPLE_DESC = "Skip examples defined in operations to avoid out of memory errors.";
public static final String STRIP_PACKAGE_NAME = "stripPackageName";
public static final String STRIP_PACKAGE_NAME_DESC = "Whether to strip leading dot-separated packages from generated model classes";

View File

@ -27,7 +27,7 @@ import java.util.*;
public class CodegenParameter implements IJsonSchemaValidationProperties {
public boolean isFormParam, isQueryParam, isPathParam, isHeaderParam,
isCookieParam, isBodyParam, isContainer,
isCollectionFormatMulti, isPrimitiveType, isModel, isExplode;
isCollectionFormatMulti, isPrimitiveType, isModel, isExplode, isDeepObject;
public String baseName, paramName, dataType, datatypeWithEnum, dataFormat, contentType,
collectionFormat, description, unescapedDescription, baseType, defaultValue, enumName, style;
@ -195,6 +195,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
output.isMap = this.isMap;
output.isExplode = this.isExplode;
output.style = this.style;
output.isDeepObject = this.isDeepObject;
output.contentType = this.contentType;
return output;
@ -202,7 +203,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, enumName, style, example, jsonSchema, isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isDecimal, isByteArray, isBinary, isBoolean, isDate, isDateTime, isUuid, isUri, isEmail, isFreeFormObject, isAnyType, isArray, isMap, isFile, isEnum, _enum, allowableValues, items, mostInnerItems, additionalProperties, vars, requiredVars, vendorExtensions, hasValidation, getMaxProperties(), getMinProperties(), isNullable, required, getMaximum(), getExclusiveMaximum(), getMinimum(), getExclusiveMinimum(), getMaxLength(), getMinLength(), getPattern(), getMaxItems(), getMinItems(), getUniqueItems(), contentType, multipleOf, isNull);
return Objects.hash(isFormParam, isQueryParam, isPathParam, isHeaderParam, isCookieParam, isBodyParam, isContainer, isCollectionFormatMulti, isPrimitiveType, isModel, isExplode, baseName, paramName, dataType, datatypeWithEnum, dataFormat, collectionFormat, description, unescapedDescription, baseType, defaultValue, enumName, style, isDeepObject, example, jsonSchema, isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isDecimal, isByteArray, isBinary, isBoolean, isDate, isDateTime, isUuid, isUri, isEmail, isFreeFormObject, isAnyType, isArray, isMap, isFile, isEnum, _enum, allowableValues, items, mostInnerItems, additionalProperties, vars, requiredVars, vendorExtensions, hasValidation, getMaxProperties(), getMinProperties(), isNullable, required, getMaximum(), getExclusiveMaximum(), getMinimum(), getExclusiveMinimum(), getMaxLength(), getMinLength(), getPattern(), getMaxItems(), getMinItems(), getUniqueItems(), contentType, multipleOf, isNull);
}
@Override
@ -262,6 +263,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
Objects.equals(defaultValue, that.defaultValue) &&
Objects.equals(enumName, that.enumName) &&
Objects.equals(style, that.style) &&
Objects.equals(isDeepObject, that.isDeepObject) &&
Objects.equals(example, that.example) &&
Objects.equals(jsonSchema, that.jsonSchema) &&
Objects.equals(_enum, that._enum) &&
@ -311,6 +313,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
sb.append(", defaultValue='").append(defaultValue).append('\'');
sb.append(", enumName='").append(enumName).append('\'');
sb.append(", style='").append(style).append('\'');
sb.append(", deepObject='").append(isDeepObject).append('\'');
sb.append(", example='").append(example).append('\'');
sb.append(", jsonSchema='").append(jsonSchema).append('\'');
sb.append(", isString=").append(isString);

View File

@ -78,7 +78,7 @@ import static org.openapitools.codegen.utils.OnceLogger.once;
import static org.openapitools.codegen.utils.StringUtils.*;
public class DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(DefaultCodegen.class);
public static FeatureSet DefaultFeatureSet;
@ -142,10 +142,10 @@ public class DefaultCodegen implements CodegenConfig {
protected GeneratorMetadata generatorMetadata;
protected String inputSpec;
protected String outputFolder = "";
protected Set<String> defaultIncludes = new HashSet<String>();
protected Map<String, String> typeMapping = new HashMap<String, String>();
protected Map<String, String> instantiationTypes = new HashMap<String, String>();
protected Set<String> reservedWords = new HashSet<String>();
protected Set<String> defaultIncludes;
protected Map<String, String> typeMapping;
protected Map<String, String> instantiationTypes;
protected Set<String> reservedWords;
protected Set<String> languageSpecificPrimitives = new HashSet<String>();
protected Map<String, String> importMapping = new HashMap<String, String>();
protected String modelPackage = "", apiPackage = "", fileSuffix;
@ -177,6 +177,11 @@ public class DefaultCodegen implements CodegenConfig {
protected List<CliOption> cliOptions = new ArrayList<CliOption>();
protected boolean skipOverwrite;
protected boolean removeOperationIdPrefix;
protected boolean skipOperationExample;
protected final static Pattern JSON_MIME_PATTERN = Pattern.compile("(?i)application\\/json(;.*)?");
protected final static Pattern JSON_VENDOR_MIME_PATTERN = Pattern.compile("(?i)application\\/vnd.(.*)+json(;.*)?");
private static final Pattern COMMON_PREFIX_ENUM_NAME = Pattern.compile("[a-zA-Z0-9]+\\z");
/**
* True if the code generator supports multiple class inheritance.
@ -314,36 +319,41 @@ public class DefaultCodegen implements CodegenConfig {
}
if (additionalProperties.containsKey(CodegenConstants.REMOVE_OPERATION_ID_PREFIX)) {
this.setRemoveOperationIdPrefix(Boolean.valueOf(additionalProperties
this.setRemoveOperationIdPrefix(Boolean.parseBoolean(additionalProperties
.get(CodegenConstants.REMOVE_OPERATION_ID_PREFIX).toString()));
}
if (additionalProperties.containsKey(CodegenConstants.SKIP_OPERATION_EXAMPLE)) {
this.setSkipOperationExample(Boolean.parseBoolean(additionalProperties
.get(CodegenConstants.SKIP_OPERATION_EXAMPLE).toString()));
}
if (additionalProperties.containsKey(CodegenConstants.DOCEXTENSION)) {
this.setDocExtension(String.valueOf(additionalProperties
.get(CodegenConstants.DOCEXTENSION).toString()));
}
if (additionalProperties.containsKey(CodegenConstants.ENABLE_POST_PROCESS_FILE)) {
this.setEnablePostProcessFile(Boolean.valueOf(additionalProperties
this.setEnablePostProcessFile(Boolean.parseBoolean(additionalProperties
.get(CodegenConstants.ENABLE_POST_PROCESS_FILE).toString()));
}
if (additionalProperties.containsKey(CodegenConstants.GENERATE_ALIAS_AS_MODEL)) {
ModelUtils.setGenerateAliasAsModel(Boolean.valueOf(additionalProperties
ModelUtils.setGenerateAliasAsModel(Boolean.parseBoolean(additionalProperties
.get(CodegenConstants.GENERATE_ALIAS_AS_MODEL).toString()));
}
if (additionalProperties.containsKey(CodegenConstants.REMOVE_ENUM_VALUE_PREFIX)) {
this.setRemoveEnumValuePrefix(Boolean.valueOf(additionalProperties
this.setRemoveEnumValuePrefix(Boolean.parseBoolean(additionalProperties
.get(CodegenConstants.REMOVE_ENUM_VALUE_PREFIX).toString()));
}
if (additionalProperties.containsKey(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR)) {
this.setLegacyDiscriminatorBehavior(Boolean.valueOf(additionalProperties
this.setLegacyDiscriminatorBehavior(Boolean.parseBoolean(additionalProperties
.get(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR).toString()));
}
if (additionalProperties.containsKey(CodegenConstants.DISALLOW_ADDITIONAL_PROPERTIES_IF_NOT_PRESENT)) {
this.setDisallowAdditionalPropertiesIfNotPresent(Boolean.valueOf(additionalProperties
this.setDisallowAdditionalPropertiesIfNotPresent(Boolean.parseBoolean(additionalProperties
.get(CodegenConstants.DISALLOW_ADDITIONAL_PROPERTIES_IF_NOT_PRESENT).toString()));
}
}
@ -396,10 +406,9 @@ public class DefaultCodegen implements CodegenConfig {
Map<String, Object> modelValue = new HashMap<>(additionalProperties());
modelValue.put("model", cm);
List<Object> modelsValue = Arrays.asList(modelValue);
List<Map<String, String>> importsValue = new ArrayList<Map<String, String>>();
List<Map<String, String>> importsValue = new ArrayList<>();
Map<String, Object> objsValue = new HashMap<>();
objsValue.put("models", modelsValue);
objsValue.put("models", Collections.singletonList(modelValue));
objsValue.put("package", modelPackage());
objsValue.put("imports", importsValue);
objsValue.put("classname", cm.classname);
@ -410,7 +419,7 @@ public class DefaultCodegen implements CodegenConfig {
// Gather data from all the models that contain oneOf into OneOfImplementorAdditionalData classes
// (see docstring of that class to find out what information is gathered and why)
Map<String, OneOfImplementorAdditionalData> additionalDataMap = new HashMap<String, OneOfImplementorAdditionalData>();
for (Map.Entry modelsEntry : objs.entrySet()) {
for (Map.Entry<String, Object> modelsEntry : objs.entrySet()) {
Map<String, Object> modelsAttrs = (Map<String, Object>) modelsEntry.getValue();
List<Object> models = (List<Object>) modelsAttrs.get("models");
List<Map<String, String>> modelsImports = (List<Map<String, String>>) modelsAttrs.getOrDefault("imports", new ArrayList<Map<String, String>>());
@ -432,7 +441,7 @@ public class DefaultCodegen implements CodegenConfig {
}
// Add all the data from OneOfImplementorAdditionalData classes to the implementing models
for (Map.Entry modelsEntry : objs.entrySet()) {
for (Map.Entry<String, Object> modelsEntry : objs.entrySet()) {
Map<String, Object> modelsAttrs = (Map<String, Object>) modelsEntry.getValue();
List<Object> models = (List<Object>) modelsAttrs.get("models");
List<Map<String, String>> imports = (List<Map<String, String>>) modelsAttrs.get("imports");
@ -458,10 +467,8 @@ public class DefaultCodegen implements CodegenConfig {
protected Map<String, Schema> getModelNameToSchemaCache() {
if (modelNameToSchemaCache == null) {
// Create a cache to efficiently lookup schema based on model name.
Map<String, Schema> m = new HashMap<String, Schema>();
ModelUtils.getSchemas(openAPI).forEach((key, schema) -> {
m.put(toModelName(key), schema);
});
Map<String, Schema> m = new HashMap<>();
ModelUtils.getSchemas(openAPI).forEach((key, schema) -> m.put(toModelName(key), schema));
modelNameToSchemaCache = Collections.unmodifiableMap(m);
}
return modelNameToSchemaCache;
@ -502,7 +509,7 @@ public class DefaultCodegen implements CodegenConfig {
cm.setParentModel(allModels.get(cm.getParent()));
}
if (cm.getInterfaces() != null && !cm.getInterfaces().isEmpty()) {
cm.setInterfaceModels(new ArrayList<CodegenModel>(cm.getInterfaces().size()));
cm.setInterfaceModels(new ArrayList<>(cm.getInterfaces().size()));
for (String intf : cm.getInterfaces()) {
CodegenModel intfModel = allModels.get(intf);
if (intfModel != null) {
@ -520,7 +527,7 @@ public class DefaultCodegen implements CodegenConfig {
// TODO Determine what to do if the parent discriminator name == the grandparent discriminator name
while (parent != null) {
if (parent.getChildren() == null) {
parent.setChildren(new ArrayList<CodegenModel>());
parent.setChildren(new ArrayList<>());
}
parent.getChildren().add(cm);
parent.hasChildren = true;
@ -569,13 +576,13 @@ public class DefaultCodegen implements CodegenConfig {
}
return prop.dataType == null ? null : prop;
})
.filter(prop -> prop != null)
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
private void setCircularReferencesOnProperties(final String root,
final Map<String, List<CodegenProperty>> dependencyMap) {
dependencyMap.getOrDefault(root, new ArrayList<>()).stream()
dependencyMap.getOrDefault(root, new ArrayList<>())
.forEach(prop -> {
final List<String> unvisited =
Collections.singletonList(prop.isContainer ? prop.items.dataType : prop.dataType);
@ -680,7 +687,8 @@ public class DefaultCodegen implements CodegenConfig {
String prefix = StringUtils.getCommonPrefix(listStr);
// exclude trailing characters that should be part of a valid variable
// e.g. ["status-on", "status-off"] => "status-" (not "status-o")
return prefix.replaceAll("[a-zA-Z0-9]+\\z", "");
final Matcher matcher = COMMON_PREFIX_ENUM_NAME.matcher(prefix);
return matcher.replaceAll("");
} catch (ArrayStoreException e) {
// do nothing, just return default value
}
@ -1622,7 +1630,7 @@ public class DefaultCodegen implements CodegenConfig {
} else if (Parameter.StyleEnum.SPACEDELIMITED.equals(qp.getStyle())) {
paramPart.append("%20");
} else {
LOGGER.warn("query parameter '" + param.getName() + "style not support: " + qp.getStyle());
LOGGER.warn("query parameter '{}' style not support: {}", param.getName(), qp.getStyle());
}
} else {
paramPart.append(param.getName());
@ -1998,7 +2006,7 @@ public class DefaultCodegen implements CodegenConfig {
}
return getAlias(schemaName);
} else {
LOGGER.warn("Error obtaining the datatype from ref:" + unaliasSchema.get$ref() + ". Default to 'object'");
LOGGER.warn("Error obtaining the datatype from ref: {}. Default to 'object'", unaliasSchema.get$ref());
return "object";
}
} else { // primitive type or model
@ -2086,7 +2094,7 @@ public class DefaultCodegen implements CodegenConfig {
return "AnyType";
} else if (StringUtils.isNotEmpty(schema.getType())) {
if (!importMapping.containsKey(schema.getType())) {
LOGGER.warn("Unknown type found in the schema: " + schema.getType());
LOGGER.warn("Unknown type found in the schema: {}", schema.getType());
}
return schema.getType();
}
@ -2793,10 +2801,10 @@ public class DefaultCodegen implements CodegenConfig {
* @return the list of oneOf and anyOf MappedModel that need to be added to the discriminator map
*/
protected List<MappedModel> getOneOfAnyOfDescendants(String composedSchemaName, String discPropName, ComposedSchema c, OpenAPI openAPI) {
ArrayList<List<Schema>> listOLists = new ArrayList<List<Schema>>();
ArrayList<List<Schema>> listOLists = new ArrayList<>();
listOLists.add(c.getOneOf());
listOLists.add(c.getAnyOf());
List<MappedModel> descendentSchemas = new ArrayList();
List<MappedModel> descendentSchemas = new ArrayList<>();
for (List<Schema> schemaList : listOLists) {
if (schemaList == null) {
continue;
@ -3055,11 +3063,11 @@ public class DefaultCodegen implements CodegenConfig {
LOGGER.error("Undefined property/schema for `{}`. Default to type:string.", name);
return null;
}
LOGGER.debug("debugging fromProperty for " + name + " : " + p);
LOGGER.debug("debugging fromProperty for {} : {}", name, p);
NamedSchema ns = new NamedSchema(name, p);
CodegenProperty cpc = schemaCodegenPropertyCache.get(ns);
if (cpc != null) {
LOGGER.debug("Cached fromProperty for " + name + " : " + p.getName());
LOGGER.debug("Cached fromProperty for {} : {}", name, p.getName());
return cpc;
}
// unalias schema
@ -3311,8 +3319,8 @@ public class DefaultCodegen implements CodegenConfig {
property.isModel = (ModelUtils.isComposedSchema(refOrCurrent) || ModelUtils.isObjectSchema(refOrCurrent)) && ModelUtils.isModel(refOrCurrent);
}
addVarsRequiredVarsAdditionaProps(p, property);
LOGGER.debug("debugging from property return: " + property);
addVarsRequiredVarsAdditionalProps(p, property);
LOGGER.debug("debugging from property return: {}", property);
schemaCodegenPropertyCache.put(ns, property);
return property;
}
@ -3325,7 +3333,9 @@ public class DefaultCodegen implements CodegenConfig {
*/
protected void updatePropertyForArray(CodegenProperty property, CodegenProperty innerProperty) {
if (innerProperty == null) {
LOGGER.warn("skipping invalid array property " + Json.pretty(property));
if(LOGGER.isWarnEnabled()) {
LOGGER.warn("skipping invalid array property {}", Json.pretty(property));
}
return;
}
property.dataFormat = innerProperty.dataFormat;
@ -3358,7 +3368,9 @@ public class DefaultCodegen implements CodegenConfig {
*/
protected void updatePropertyForMap(CodegenProperty property, CodegenProperty innerProperty) {
if (innerProperty == null) {
LOGGER.warn("skipping invalid map property " + Json.pretty(property));
if(LOGGER.isWarnEnabled()) {
LOGGER.warn("skipping invalid map property {}", Json.pretty(property));
}
return;
}
if (!languageSpecificPrimitives.contains(innerProperty.baseType)) {
@ -3407,7 +3419,7 @@ public class DefaultCodegen implements CodegenConfig {
protected Map<String, Object> getInnerEnumAllowableValues(CodegenProperty property) {
CodegenProperty currentProperty = getMostInnerItems(property);
return currentProperty == null ? new HashMap<String, Object>() : currentProperty.allowableValues;
return currentProperty == null ? new HashMap<>() : currentProperty.allowableValues;
}
/**
@ -3547,14 +3559,18 @@ public class DefaultCodegen implements CodegenConfig {
}
}
// generate examples
String exampleStatusCode = "200";
for (String key : operation.getResponses().keySet()) {
if (operation.getResponses().get(key) == methodResponse && !key.equals("default")) {
exampleStatusCode = key;
// check skipOperationExample, which can be set to true to avoid out of memory errors for large spec
if (!isSkipOperationExample()) {
// generate examples
String exampleStatusCode = "200";
for (String key : operation.getResponses().keySet()) {
if (operation.getResponses().get(key) == methodResponse && !key.equals("default")) {
exampleStatusCode = key;
}
}
op.examples = new ExampleGenerator(schemas, this.openAPI).generateFromResponseSchema(exampleStatusCode, responseSchema, getProducesInfo(this.openAPI, operation));
}
op.examples = new ExampleGenerator(schemas, this.openAPI).generateFromResponseSchema(exampleStatusCode, responseSchema, getProducesInfo(this.openAPI, operation));
op.defaultResponse = toDefaultValue(responseSchema);
op.returnType = cm.dataType;
op.returnFormat = cm.dataFormat;
@ -3604,7 +3620,7 @@ public class DefaultCodegen implements CodegenConfig {
String httpMethod,
Operation operation,
List<Server> servers) {
LOGGER.debug("fromOperation => operation: " + operation);
LOGGER.debug("fromOperation => operation: {}", operation);
if (operation == null)
throw new RuntimeException("operation cannot be null in fromOperation");
@ -3768,7 +3784,7 @@ public class DefaultCodegen implements CodegenConfig {
// ensure unique params
if (ensureUniqueParams) {
if (!isParameterNameUnique(p, allParams)) {
while (!isParameterNameUnique(p, allParams)) {
p.paramName = generateNextName(p.paramName);
}
}
@ -3784,7 +3800,7 @@ public class DefaultCodegen implements CodegenConfig {
} else if (param instanceof CookieParameter || "cookie".equalsIgnoreCase(param.getIn())) {
cookieParams.add(p.copy());
} else {
LOGGER.warn("Unknown parameter type " + p.baseType + " for " + p.baseName);
LOGGER.warn("Unknown parameter type {} for {}", p.baseType, p.baseName);
}
}
@ -3794,7 +3810,7 @@ public class DefaultCodegen implements CodegenConfig {
if (!prependFormOrBodyParameters) {
for (CodegenParameter cp : formParams) {
if (ensureUniqueParams) {
if (!isParameterNameUnique(cp, allParams)) {
while (!isParameterNameUnique(cp, allParams)) {
cp.paramName = generateNextName(cp.paramName);
}
}
@ -3803,7 +3819,7 @@ public class DefaultCodegen implements CodegenConfig {
for (CodegenParameter cp : bodyParams) {
if (ensureUniqueParams) {
if (!isParameterNameUnique(cp, allParams)) {
while (!isParameterNameUnique(cp, allParams)) {
cp.paramName = generateNextName(cp.paramName);
}
}
@ -4021,7 +4037,7 @@ public class DefaultCodegen implements CodegenConfig {
} else if (Boolean.TRUE.equals(cp.isAnyType)) {
r.isAnyType = true;
} else {
LOGGER.debug("Property type is not primitive: " + cp.dataType);
LOGGER.debug("Property type is not primitive: {}", cp.dataType);
}
if (cp.isContainer) {
@ -4037,7 +4053,7 @@ public class DefaultCodegen implements CodegenConfig {
r.primitiveType = (r.baseType == null || languageSpecificPrimitives().contains(r.baseType));
addVarsRequiredVarsAdditionaProps(responseSchema, r);
addVarsRequiredVarsAdditionalProps(responseSchema, r);
}
if (r.baseType == null) {
@ -4133,8 +4149,8 @@ public class DefaultCodegen implements CodegenConfig {
codegenParameter.jsonSchema = Json.pretty(parameter);
if (GlobalSettings.getProperty("debugParser") != null) {
LOGGER.info("working on Parameter " + parameter.getName());
LOGGER.info("JSON schema: " + codegenParameter.jsonSchema);
LOGGER.info("working on Parameter {}", parameter.getName());
LOGGER.info("JSON schema: {}", codegenParameter.jsonSchema);
}
if (parameter.getExtensions() != null && !parameter.getExtensions().isEmpty()) {
@ -4159,7 +4175,7 @@ public class DefaultCodegen implements CodegenConfig {
if (parameterSchema != null) {
parameterSchema = unaliasSchema(parameterSchema, Collections.<String, String>emptyMap());
if (parameterSchema == null) {
LOGGER.warn("warning! Schema not found for parameter \"" + parameter.getName() + "\", using String");
LOGGER.warn("warning! Schema not found for parameter \" {} \", using String", parameter.getName());
parameterSchema = new StringSchema().description("//TODO automatically added by openapi-generator due to missing type definition.");
}
ModelUtils.syncValidationProperties(parameterSchema, codegenParameter);
@ -4173,6 +4189,7 @@ public class DefaultCodegen implements CodegenConfig {
if (parameter.getStyle() != null) {
codegenParameter.style = parameter.getStyle().toString();
codegenParameter.isDeepObject = Parameter.StyleEnum.DEEPOBJECT == parameter.getStyle();
}
// the default value is false
@ -4307,10 +4324,10 @@ public class DefaultCodegen implements CodegenConfig {
codegenParameter.pattern != null || codegenParameter.multipleOf != null) {
codegenParameter.hasValidation = true;
}
addVarsRequiredVarsAdditionaProps(parameterSchema, codegenParameter);
addVarsRequiredVarsAdditionalProps(parameterSchema, codegenParameter);
} else {
LOGGER.error("ERROR! Not handling " + parameter + " as Body Parameter at the moment");
LOGGER.error("Not handling {} as Body Parameter at the moment", parameter);
}
if (parameter instanceof QueryParameter || "query".equalsIgnoreCase(parameter.getIn())) {
@ -4323,7 +4340,7 @@ public class DefaultCodegen implements CodegenConfig {
} else if (parameter instanceof CookieParameter || "cookie".equalsIgnoreCase(parameter.getIn())) {
codegenParameter.isCookieParam = true;
} else {
LOGGER.warn("Unknown parameter type: " + parameter.getName());
LOGGER.warn("Unknown parameter type: {}", parameter.getName());
}
// default to UNKNOWN_PARAMETER_NAME if paramName is null
@ -4332,12 +4349,25 @@ public class DefaultCodegen implements CodegenConfig {
codegenParameter.paramName = "UNKNOWN_PARAMETER_NAME";
}
if (codegenParameter.isQueryParam && codegenParameter.isDeepObject) {
Schema schema = ModelUtils.getSchema(openAPI, codegenParameter.dataType);
codegenParameter.items = fromProperty(codegenParameter.paramName, schema);
Map<String, Schema<?>> properties = schema.getProperties();
codegenParameter.items.vars =
properties.entrySet().stream()
.map(entry -> {
CodegenProperty property = fromProperty(entry.getKey(), entry.getValue());
property.baseName = codegenParameter.baseName + "[" + entry.getKey() + "]";
return property;
}).collect(Collectors.toList());
}
// set the parameter example value
// should be overridden by lang codegen
setParameterExampleValue(codegenParameter, parameter);
postProcessParameter(codegenParameter);
LOGGER.debug("debugging codegenParameter return: " + codegenParameter);
LOGGER.debug("debugging codegenParameter return: {}", codegenParameter);
return codegenParameter;
}
@ -4528,7 +4558,7 @@ public class DefaultCodegen implements CodegenConfig {
}
}
operationId = sanitizeName(builder.toString());
LOGGER.warn("Empty operationId found for path: " + httpMethod + " " + path + ". Renamed to auto-generated operationId: " + operationId);
LOGGER.warn("Empty operationId found for path: {} {}. Renamed to auto-generated operationId: {}", httpMethod, path, operationId);
}
return operationId;
}
@ -4575,7 +4605,7 @@ public class DefaultCodegen implements CodegenConfig {
Schema schema;
if (header.getSchema() == null) {
LOGGER.warn("No schema defined for Header '" + headerEntry.getKey() + "', using a String schema");
LOGGER.warn("No schema defined for Header '{}', using a String schema", headerEntry.getKey());
schema = new StringSchema();
} else {
schema = header.getSchema();
@ -4940,10 +4970,18 @@ public class DefaultCodegen implements CodegenConfig {
return removeOperationIdPrefix;
}
public boolean isSkipOperationExample() {
return skipOperationExample;
}
public void setRemoveOperationIdPrefix(boolean removeOperationIdPrefix) {
this.removeOperationIdPrefix = removeOperationIdPrefix;
}
public void setSkipOperationExample(boolean skipOperationExample) {
this.skipOperationExample = skipOperationExample;
}
public boolean isHideGenerationTimestamp() {
return hideGenerationTimestamp;
}
@ -5304,7 +5342,7 @@ public class DefaultCodegen implements CodegenConfig {
} else if (Boolean.TRUE.equals(property.isAnyType)) {
parameter.isAnyType = true;
} else {
LOGGER.debug("Property type is not primitive: " + property.dataType);
LOGGER.debug("Property type is not primitive: {}", property.dataType);
}
if (Boolean.TRUE.equals(property.isFile)) {
@ -5475,7 +5513,7 @@ public class DefaultCodegen implements CodegenConfig {
public boolean convertPropertyToBoolean(String propertyKey) {
final Object booleanValue = additionalProperties.get(propertyKey);
Boolean result = Boolean.FALSE;
boolean result = Boolean.FALSE;
if (booleanValue instanceof Boolean) {
result = (Boolean) booleanValue;
} else if (booleanValue instanceof String) {
@ -5504,7 +5542,6 @@ public class DefaultCodegen implements CodegenConfig {
if (flow.getScopes() != null && !flow.getScopes().isEmpty()) {
List<Map<String, Object>> scopes = new ArrayList<>();
int count = 0, numScopes = flow.getScopes().size();
for (Map.Entry<String, String> scopeEntry : flow.getScopes().entrySet()) {
Map<String, Object> scope = new HashMap<>();
scope.put("scope", scopeEntry.getKey());
@ -5523,7 +5560,6 @@ public class DefaultCodegen implements CodegenConfig {
Set<String> consumes = requestBody.getContent().keySet();
List<Map<String, String>> mediaTypeList = new ArrayList<>();
int count = 0;
for (String key : consumes) {
Map<String, String> mediaType = new HashMap<>();
if ("*/*".equals(key)) {
@ -5594,13 +5630,12 @@ public class DefaultCodegen implements CodegenConfig {
existingMediaTypes.add(mediaType.get("mediaType"));
}
int count = 0;
for (String key : produces) {
// escape quotation to avoid code injection, "*/*" is a special case, do nothing
String encodedKey = "*/*".equals(key) ? key : escapeText(escapeQuotationMark(key));
//Only unique media types should be added to "produces"
if (!existingMediaTypes.contains(encodedKey)) {
Map<String, String> mediaType = new HashMap<String, String>();
Map<String, String> mediaType = new HashMap<>();
mediaType.put("mediaType", encodedKey);
codegenOperation.produces.add(mediaType);
codegenOperation.hasProduces = Boolean.TRUE;
@ -5664,8 +5699,8 @@ public class DefaultCodegen implements CodegenConfig {
}
public List<CodegenParameter> fromRequestBodyToFormParameters(RequestBody body, Set<String> imports) {
List<CodegenParameter> parameters = new ArrayList<CodegenParameter>();
LOGGER.debug("debugging fromRequestBodyToFormParameters= " + body);
List<CodegenParameter> parameters = new ArrayList<>();
LOGGER.debug("debugging fromRequestBodyToFormParameters= {}", body);
Schema schema = ModelUtils.getSchemaFromRequestBody(body);
schema = ModelUtils.getReferencedSchema(this.openAPI, schema);
List<String> allRequired = new ArrayList<String>();
@ -5674,7 +5709,7 @@ public class DefaultCodegen implements CodegenConfig {
if (!properties.isEmpty()) {
for (Map.Entry<String, Schema> entry : properties.entrySet()) {
CodegenParameter codegenParameter = CodegenModelFactory.newInstance(CodegenModelType.PARAMETER);
CodegenParameter codegenParameter;
// key => property name
// value => property schema
Schema s = entry.getValue();
@ -5696,7 +5731,7 @@ public class DefaultCodegen implements CodegenConfig {
if (codegenParameter.baseType != null && codegenParameter.enumName != null) {
codegenParameter.datatypeWithEnum = codegenParameter.dataType.replace(codegenParameter.baseType, codegenParameter.enumName);
} else {
LOGGER.warn("Could not compute datatypeWithEnum from " + codegenParameter.baseType + ", " + codegenParameter.enumName);
LOGGER.warn("Could not compute datatypeWithEnum from {}, {}", codegenParameter.baseType, codegenParameter.enumName);
}
//TODO fix collectformat for form parameters
//collectionFormat = getCollectionFormat(s);
@ -5866,7 +5901,7 @@ public class DefaultCodegen implements CodegenConfig {
"It could be due to form parameter defined in OpenAPI v2 spec with incorrect consumes. " +
"A correct 'consumes' for form parameters should be " +
"'application/x-www-form-urlencoded' or 'multipart/?'");
LOGGER.warn("schema: " + schema);
LOGGER.warn("schema: {}", schema);
LOGGER.warn("codegenModel is null. Default to UNKNOWN_BASE_TYPE");
codegenModelName = "UNKNOWN_BASE_TYPE";
codegenModelDescription = "UNKNOWN_DESCRIPTION";
@ -5912,7 +5947,7 @@ public class DefaultCodegen implements CodegenConfig {
}
String name = null;
LOGGER.debug("Request body = " + body);
LOGGER.debug("Request body = {}", body);
Schema schema = ModelUtils.getSchemaFromRequestBody(body);
if (schema == null) {
throw new RuntimeException("Request body cannot be null. Possible cause: missing schema in body parameter (OAS v2): " + body);
@ -6065,7 +6100,7 @@ public class DefaultCodegen implements CodegenConfig {
setParameterNullable(codegenParameter, codegenProperty);
}
addVarsRequiredVarsAdditionaProps(schema, codegenParameter);
addVarsRequiredVarsAdditionalProps(schema, codegenParameter);
addJsonSchemaForBodyRequestInCaseItsNotPresent(codegenParameter, body);
// set the parameter's example value
@ -6075,7 +6110,7 @@ public class DefaultCodegen implements CodegenConfig {
return codegenParameter;
}
private void addVarsRequiredVarsAdditionaProps(Schema schema, IJsonSchemaValidationProperties property){
private void addVarsRequiredVarsAdditionalProps(Schema schema, IJsonSchemaValidationProperties property){
if (!"object".equals(schema.getType())) {
return;
}
@ -6105,7 +6140,6 @@ public class DefaultCodegen implements CodegenConfig {
CodegenProperty cp = fromProperty("", (Schema) schema.getAdditionalProperties());
property.setAdditionalProperties(cp);
}
return;
}
private void addJsonSchemaForBodyRequestInCaseItsNotPresent(CodegenParameter codegenParameter, RequestBody body) {
@ -6225,7 +6259,9 @@ public class DefaultCodegen implements CodegenConfig {
codegenServerVariable.value = value;
if (enums != null && !enums.isEmpty() && !enums.contains(value)) {
LOGGER.warn("Variable override of '{}' is not listed in the enum of allowed values ({}).", value, StringUtils.join(enums, ","));
if(LOGGER.isWarnEnabled()) { // prevents calculating StringUtils.join when debug isn't enabled
LOGGER.warn("Variable override of '{}' is not listed in the enum of allowed values ({}).", value, StringUtils.join(enums, ","));
}
}
} else {
codegenServerVariable.value = variable.getDefault();
@ -6365,7 +6401,7 @@ public class DefaultCodegen implements CodegenConfig {
CodegenModel cm = new CodegenModel();
cm.discriminator = createDiscriminator("", (Schema) cs, openAPI);
cm.discriminator = createDiscriminator("", cs, openAPI);
if (!this.getLegacyDiscriminatorBehavior()) {
cm.addDiscriminatorMappedModelsImports();
}
@ -6542,9 +6578,6 @@ public class DefaultCodegen implements CodegenConfig {
return ModelUtils.getAdditionalProperties(openAPI, schema);
}
final protected static Pattern JSON_MIME_PATTERN = Pattern.compile("(?i)application\\/json(;.*)?");
final protected static Pattern JSON_VENDOR_MIME_PATTERN = Pattern.compile("(?i)application\\/vnd.(.*)+json(;.*)?");
/**
* Check if the given MIME is a JSON MIME.
* JSON MIME examples:

View File

@ -832,9 +832,8 @@ public class DefaultGenerator implements Generator {
@Override
public List<File> generate() {
if (openAPI == null) {
throw new RuntimeException("missing OpenAPI input!");
throw new RuntimeException("Issues with the OpenAPI input. Possible causes: invalid/missing spec, malformed JSON/YAML files, etc.");
}
if (config == null) {

View File

@ -52,7 +52,7 @@ public class InlineModelResolver {
structureMapper.writer(new DefaultPrettyPrinter());
}
static final Logger LOGGER = LoggerFactory.getLogger(InlineModelResolver.class);
final Logger LOGGER = LoggerFactory.getLogger(InlineModelResolver.class);
void flatten(OpenAPI openapi) {
this.openapi = openapi;
@ -118,7 +118,7 @@ public class InlineModelResolver {
Schema model = ModelUtils.getSchemaFromRequestBody(requestBody);
if (model instanceof ObjectSchema) {
Schema obj = (Schema) model;
Schema obj = model;
if (obj.getType() == null || "object".equals(obj.getType())) {
if (obj.getProperties() != null && obj.getProperties().size() > 0) {
flattenProperties(openAPI, obj.getProperties(), pathname);
@ -213,7 +213,7 @@ public class InlineModelResolver {
Schema model = parameter.getSchema();
if (model instanceof ObjectSchema) {
Schema obj = (Schema) model;
Schema obj = model;
if (obj.getType() == null || "object".equals(obj.getType())) {
if (obj.getProperties() != null && obj.getProperties().size() > 0) {
flattenProperties(openAPI, obj.getProperties(), pathname);
@ -431,7 +431,7 @@ public class InlineModelResolver {
flattenComposedChildren(openAPI, modelName + "_anyOf", m.getAnyOf());
flattenComposedChildren(openAPI, modelName + "_oneOf", m.getOneOf());
} else if (model instanceof Schema) {
Schema m = (Schema) model;
Schema m = model;
Map<String, Schema> properties = m.getProperties();
flattenProperties(openAPI, properties, modelName);
fixStringModel(m);

View File

@ -25,7 +25,7 @@ public class TemplateManager implements TemplatingExecutor, TemplateProcessor {
private final TemplatingEngineAdapter engineAdapter;
private final TemplatePathLocator[] templateLoaders;
private static final Logger LOGGER = LoggerFactory.getLogger(TemplateManager.class);
private final Logger LOGGER = LoggerFactory.getLogger(TemplateManager.class);
/**
* Constructs a new instance of a {@link TemplateManager}

View File

@ -429,6 +429,11 @@ public class CodegenConfigurator {
return this;
}
public CodegenConfigurator setSkipOperationExample(boolean skipOperationExample) {
workflowSettingsBuilder.withSkipOperationExample(skipOperationExample);
return this;
}
public CodegenConfigurator setSkipOverwrite(boolean skipOverwrite) {
workflowSettingsBuilder.withSkipOverwrite(skipOverwrite);
return this;
@ -583,6 +588,7 @@ public class CodegenConfigurator {
config.setSkipOverwrite(workflowSettings.isSkipOverwrite());
config.setIgnoreFilePathOverride(workflowSettings.getIgnoreFileOverride());
config.setRemoveOperationIdPrefix(workflowSettings.isRemoveOperationIdPrefix());
config.setSkipOperationExample(workflowSettings.isSkipOperationExample());
config.setEnablePostProcessFile(workflowSettings.isEnablePostProcessFile());
config.setEnableMinimalUpdate(workflowSettings.isEnableMinimalUpdate());
config.setStrictSpecBehavior(workflowSettings.isStrictSpecBehavior());

View File

@ -30,7 +30,7 @@ import java.math.BigDecimal;
import java.util.*;
public class ExampleGenerator {
private static final Logger LOGGER = LoggerFactory.getLogger(ExampleGenerator.class);
private final Logger LOGGER = LoggerFactory.getLogger(ExampleGenerator.class);
// TODO: move constants to more appropriate location
private static final String MIME_TYPE_JSON = "application/json";

View File

@ -36,7 +36,7 @@ import java.util.Locale;
*/
public class CodegenIgnoreProcessor {
private static final Logger LOGGER = LoggerFactory.getLogger(CodegenIgnoreProcessor.class);
private final Logger LOGGER = LoggerFactory.getLogger(CodegenIgnoreProcessor.class);
private File ignoreFile = null;
@ -65,7 +65,7 @@ public class CodegenIgnoreProcessor {
if (directory.exists() && directory.isDirectory()) {
loadFromFile(targetIgnoreFile);
} else {
LOGGER.warn("Output directory does not exist, or is inaccessible. No file (.openapi-generator-ignore) will be evaluated.");
LOGGER.info("Output directory ({}) does not exist, or is inaccessible. No file (.openapi-generator-ignore) will be evaluated.", baseDirectory);
}
}

View File

@ -43,7 +43,7 @@ import java.util.*;
import static org.openapitools.codegen.utils.StringUtils.camelize;
abstract public class AbstractAdaCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAdaCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(AbstractAdaCodegen.class);
protected String packageName = "defaultPackage";
protected String projectName = "defaultProject";

View File

@ -36,7 +36,7 @@ import static org.openapitools.codegen.utils.OnceLogger.once;
import static org.openapitools.codegen.utils.StringUtils.camelize;
public abstract class AbstractApexCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractApexCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(AbstractApexCodegen.class);
protected Boolean serializableModel = false;

View File

@ -83,7 +83,7 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
protected Set<String> valueTypes = new HashSet<String>();
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractCSharpCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(AbstractCSharpCodegen.class);
public AbstractCSharpCodegen() {
super();

View File

@ -48,7 +48,7 @@ import java.util.Map;
import java.util.Map.Entry;
abstract public class AbstractCppCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractCppCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(AbstractCppCodegen.class);
protected static final String RESERVED_WORD_PREFIX_OPTION = "reservedWordPrefix";
protected static final String RESERVED_WORD_PREFIX_DESC = "Prefix to prepend to reserved words in order to avoid conflicts";

View File

@ -0,0 +1,686 @@
package org.openapitools.codegen.languages;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.media.StringSchema;
import io.swagger.v3.oas.models.servers.Server;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.*;
import org.openapitools.codegen.meta.features.*;
import org.openapitools.codegen.utils.ModelUtils;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.openapitools.codegen.utils.StringUtils.*;
import static org.openapitools.codegen.utils.StringUtils.camelize;
public abstract class AbstractDartCodegen extends DefaultCodegen {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractDartCodegen.class);
public static final String PUB_LIBRARY = "pubLibrary";
public static final String PUB_NAME = "pubName";
public static final String PUB_VERSION = "pubVersion";
public static final String PUB_DESCRIPTION = "pubDescription";
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 USE_ENUM_EXTENSION = "useEnumExtension";
protected String pubLibrary = "openapi.api";
protected String pubName = "openapi";
protected String pubVersion = "1.0.0";
protected String pubDescription = "OpenAPI API client";
protected String pubAuthor = "Author";
protected String pubAuthorEmail = "author@homepage";
protected String pubHomepage = "homepage";
protected boolean useEnumExtension = false;
protected String sourceFolder = "";
protected String apiDocPath = "doc" + File.separator;
protected String modelDocPath = "doc" + File.separator;
protected String apiTestPath = "test" + File.separator;
protected String modelTestPath = "test" + File.separator;
// Names that must not be used as model names because they clash with existing
// default imports (dart:io, dart:async, package:http etc.) but are not basic dataTypes.
protected Set<String> additionalReservedWords;
public AbstractDartCodegen() {
super();
modifyFeatureSet(features -> features
.includeDocumentationFeatures(DocumentationFeature.Readme)
.securityFeatures(EnumSet.of(
SecurityFeature.OAuth2_Implicit,
SecurityFeature.BasicAuth,
SecurityFeature.ApiKey
))
.excludeGlobalFeatures(
GlobalFeature.XMLStructureDefinitions,
GlobalFeature.Callbacks,
GlobalFeature.LinkObjects,
GlobalFeature.ParameterStyling
)
.excludeSchemaSupportFeatures(
SchemaSupportFeature.Polymorphism
)
.includeParameterFeatures(
ParameterFeature.Cookie
)
.includeClientModificationFeatures(
ClientModificationFeature.BasePath
)
);
outputFolder = "generated-code/dart";
modelTemplateFiles.put("model.mustache", ".dart");
apiTemplateFiles.put("api.mustache", ".dart");
embeddedTemplateDir = templateDir = "dart2";
apiPackage = "lib.api";
modelPackage = "lib.model";
modelDocTemplateFiles.put("object_doc.mustache", ".md");
apiDocTemplateFiles.put("api_doc.mustache", ".md");
modelTestTemplateFiles.put("model_test.mustache", ".dart");
apiTestTemplateFiles.put("api_test.mustache", ".dart");
final List<String> reservedWordsList = new ArrayList<>();
try(BufferedReader reader = new BufferedReader(
new InputStreamReader(DartClientCodegen.class.getResourceAsStream("/dart/dart-keywords.txt"),
StandardCharsets.UTF_8))) {
while (reader.ready()) {
reservedWordsList.add(reader.readLine());
}
} catch (Exception e) {
LOGGER.error("Error reading dart keywords. Exception: {}", e.getMessage());
}
setReservedWordsLowerCase(reservedWordsList);
languageSpecificPrimitives = Sets.newHashSet(
"String",
"bool",
"int",
"num",
"double",
"dynamic"
);
typeMapping = new HashMap<>();
typeMapping.put("Array", "List");
typeMapping.put("array", "List");
typeMapping.put("map", "Map");
typeMapping.put("List", "List");
typeMapping.put("set", "Set");
typeMapping.put("boolean", "bool");
typeMapping.put("string", "String");
typeMapping.put("char", "String");
typeMapping.put("int", "int");
typeMapping.put("long", "int");
typeMapping.put("short", "int");
typeMapping.put("number", "num");
typeMapping.put("float", "double");
typeMapping.put("double", "double");
typeMapping.put("decimal", "double");
typeMapping.put("integer", "int");
typeMapping.put("Date", "DateTime");
typeMapping.put("date", "DateTime");
typeMapping.put("DateTime", "DateTime");
typeMapping.put("file", "MultipartFile");
typeMapping.put("binary", "MultipartFile");
typeMapping.put("UUID", "String");
typeMapping.put("URI", "String");
typeMapping.put("ByteArray", "String");
typeMapping.put("object", "Object");
typeMapping.put("AnyType", "Object");
// DataTypes of the above values which are automatically imported.
// They are also not allowed to be model names.
defaultIncludes = Sets.newHashSet(
"String",
"bool",
"int",
"num",
"double",
"dynamic",
"List",
"Set",
"Map",
"DateTime",
"Object",
"MultipartFile"
);
additionalReservedWords = Sets.newHashSet(
"File",
"Client",
"Future",
"Response"
);
cliOptions.add(new CliOption(PUB_LIBRARY, "Library name in generated code"));
cliOptions.add(new CliOption(PUB_NAME, "Name in generated pubspec"));
cliOptions.add(new CliOption(PUB_VERSION, "Version in generated pubspec"));
cliOptions.add(new CliOption(PUB_DESCRIPTION, "Description in generated pubspec"));
cliOptions.add(new CliOption(PUB_AUTHOR, "Author name in generated pubspec"));
cliOptions.add(new CliOption(PUB_AUTHOR_EMAIL, "Email address of the author in generated pubspec"));
cliOptions.add(new CliOption(PUB_HOMEPAGE, "Homepage in generated pubspec"));
cliOptions.add(new CliOption(USE_ENUM_EXTENSION, "Allow the 'x-enum-values' extension for enums"));
cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, "Source folder for generated code"));
}
@Override
public CodegenType getTag() {
return CodegenType.CLIENT;
}
@Override
public String getName() {
return "dart";
}
@Override
public String getHelp() {
return "Generates a Dart 2.x client library.";
}
@Override
public void processOpts() {
super.processOpts();
if (StringUtils.isEmpty(System.getenv("DART_POST_PROCESS_FILE"))) {
LOGGER.info("Environment variable DART_POST_PROCESS_FILE not defined so the Dart code may not be properly formatted. To define it, try `export DART_POST_PROCESS_FILE=\"/usr/local/bin/dartfmt -w\"` (Linux/Mac)");
LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
}
if (additionalProperties.containsKey(PUB_NAME)) {
this.setPubName((String) additionalProperties.get(PUB_NAME));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_NAME, pubName);
}
if (additionalProperties.containsKey(PUB_LIBRARY)) {
this.setPubLibrary((String) additionalProperties.get(PUB_LIBRARY));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_LIBRARY, pubLibrary);
}
if (additionalProperties.containsKey(PUB_VERSION)) {
this.setPubVersion((String) additionalProperties.get(PUB_VERSION));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_VERSION, pubVersion);
}
if (additionalProperties.containsKey(PUB_DESCRIPTION)) {
this.setPubDescription((String) additionalProperties.get(PUB_DESCRIPTION));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_DESCRIPTION, pubDescription);
}
if (additionalProperties.containsKey(PUB_AUTHOR)) {
this.setPubAuthor((String) additionalProperties.get(PUB_AUTHOR));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_AUTHOR, pubAuthor);
}
if (additionalProperties.containsKey(PUB_AUTHOR_EMAIL)) {
this.setPubAuthorEmail((String) additionalProperties.get(PUB_AUTHOR_EMAIL));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_AUTHOR_EMAIL, pubAuthorEmail);
}
if (additionalProperties.containsKey(PUB_HOMEPAGE)) {
this.setPubHomepage((String) additionalProperties.get(PUB_HOMEPAGE));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_HOMEPAGE, pubHomepage);
}
if (additionalProperties.containsKey(USE_ENUM_EXTENSION)) {
this.setUseEnumExtension(convertPropertyToBooleanAndWriteBack(USE_ENUM_EXTENSION));
} else {
// Not set, use to be passed to template.
additionalProperties.put(USE_ENUM_EXTENSION, useEnumExtension);
}
if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) {
this.setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER));
}
// make api and model doc path available in mustache template
additionalProperties.put("apiDocPath", apiDocPath);
additionalProperties.put("modelDocPath", modelDocPath);
// check to not overwrite a custom templateDir
if (templateDir == null) {
embeddedTemplateDir = templateDir = "dart2";
}
}
@Override
protected boolean isReservedWord(String word) {
// consider everything as reserved that is either a keyword,
// a default included type, or a type include through some library
return super.isReservedWord(word) ||
defaultIncludes().contains(word) ||
additionalReservedWords.contains(word);
}
@Override
public String escapeReservedWord(String name) {
return name + "_";
}
@Override
public String apiFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + apiPackage().replace('.', File.separatorChar);
}
@Override
public String modelFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + modelPackage().replace('.', File.separatorChar);
}
@Override
public String apiTestFileFolder() {
return outputFolder + File.separator + apiTestPath.replace('/', File.separatorChar);
}
@Override
public String modelTestFileFolder() {
return outputFolder + File.separator + modelTestPath.replace('/', File.separatorChar);
}
@Override
public String apiDocFileFolder() {
return outputFolder + File.separator + apiDocPath.replace('/', File.separatorChar);
}
@Override
public String modelDocFileFolder() {
return outputFolder + File.separator + modelDocPath.replace('/', File.separatorChar);
}
@Override
public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replace("-", "_");
// always need to replace leading underscores first
name = name.replaceAll("^_", "");
// if it's all upper case, do nothing
if (name.matches("^[A-Z_]*$")) {
return name;
}
// replace all characters that have a mapping but ignore underscores
// append an underscore to each replacement so that it can be camelized
if (name.chars().anyMatch(character -> specialCharReplacements.containsKey("" + ((char) character)))) {
name = escape(name, specialCharReplacements, Lists.newArrayList("_"), "_");
}
// remove the rest
name = sanitizeName(name);
// camelize (lower first character) the variable name
// pet_id => petId
name = camelize(name, true);
if (name.matches("^\\d.*")) {
name = "n" + name;
}
if (isReservedWord(name)) {
name = escapeReservedWord(name);
}
return name;
}
@Override
public String toParamName(String name) {
// should be the same as variable name
return toVarName(name);
}
@Override
public String toModelName(final String name) {
String nameWithPrefixSuffix = sanitizeName(name);
if (!StringUtils.isEmpty(modelNamePrefix)) {
// add '_' so that model name can be camelized correctly
nameWithPrefixSuffix = modelNamePrefix + "_" + nameWithPrefixSuffix;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
// add '_' so that model name can be camelized correctly
nameWithPrefixSuffix = nameWithPrefixSuffix + "_" + modelNameSuffix;
}
// camelize the model name
// phone_number => PhoneNumber
final String camelizedName = camelize(nameWithPrefixSuffix);
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(camelizedName)) {
final String modelName = "Model" + camelizedName;
LOGGER.warn(camelizedName + " (reserved word) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
// model name starts with number
if (camelizedName.matches("^\\d.*")) {
final String modelName = "Model" + camelizedName; // e.g. 200Response => Model200Response (after camelize)
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
return camelizedName;
}
@Override
public String toModelFilename(String name) {
return underscore(toModelName(name));
}
@Override public String toModelDocFilename(String name) {
return toModelName(name);
}
@Override
public String toApiFilename(String name) {
return underscore(toApiName(name));
}
@Override
public String toApiTestFilename(String name) {
return toApiFilename(name) + "_test";
}
@Override
public String toModelTestFilename(String name) {
return toModelFilename(name) + "_test";
}
@Override
public String toDefaultValue(Schema schema) {
if (ModelUtils.isMapSchema(schema) || ModelUtils.isSet(schema)) {
return "const {}";
}
if (ModelUtils.isArraySchema(schema)) {
return "const []";
}
if (schema.getDefault() != null) {
if (ModelUtils.isDateSchema(schema) || ModelUtils.isDateTimeSchema(schema)) {
// this is currently not supported and would create compile errors
return null;
}
if (ModelUtils.isStringSchema(schema)) {
return "'" + schema.getDefault().toString().replace("'", "\\'") + "'";
}
return schema.getDefault().toString();
}
return null;
}
@Override
public String getTypeDeclaration(Schema p) {
Schema<?> schema = ModelUtils.unaliasSchema(this.openAPI, p, importMapping);
Schema<?> target = ModelUtils.isGenerateAliasAsModel() ? p : schema;
if (ModelUtils.isArraySchema(target)) {
Schema<?> items = getSchemaItems((ArraySchema) schema);
return getSchemaType(target) + "<" + getTypeDeclaration(items) + ">";
}
if (ModelUtils.isMapSchema(target)) {
// Note: ModelUtils.isMapSchema(p) returns true when p is a composed schema that also defines
// additionalproperties: true
Schema<?> inner = getAdditionalProperties(target);
if (inner == null) {
LOGGER.error("`{}` (map property) does not have a proper inner type defined. Default to type:string", p.getName());
inner = new StringSchema().description("TODO default missing map inner type to string");
p.setAdditionalProperties(inner);
}
return getSchemaType(target) + "<String, " + getTypeDeclaration(inner) + ">";
}
return super.getTypeDeclaration(p);
}
@Override
public String getSchemaType(Schema p) {
String openAPIType = super.getSchemaType(p);
if (openAPIType == null) {
LOGGER.error("No Type defined for Schema " + p);
}
if (typeMapping.containsKey(openAPIType)) {
return typeMapping.get(openAPIType);
}
if (languageSpecificPrimitives.contains(openAPIType)) {
return openAPIType;
}
return toModelName(openAPIType);
}
@Override
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
return postProcessModelsEnum(objs);
}
@Override
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
super.postProcessModelProperty(model, property);
if (!model.isEnum && property.isEnum) {
// These are inner enums, enums which do not exist as models, just as properties.
// They are handled via the enum_inline template and and are generated in the
// same file as the containing class. To prevent name clashes the inline enum classes
// are prefix with the classname of the containing class in the template.
// Here the datatypeWithEnum template variable gets updated to match that scheme.
// Also taking into account potential collection types e.g. List<JustSymbolEnum> -> List<EnumArraysJustSymbolEnum>
final String enumName = model.classname + property.enumName;
if (property.items != null) {
// inner items e.g. enums in collections, only works for one level
// but same is the case for DefaultCodegen
property.setDatatypeWithEnum(property.datatypeWithEnum.replace(property.items.datatypeWithEnum, enumName));
property.items.setDatatypeWithEnum(enumName);
property.items.setEnumName(enumName);
} else {
// plain enum property
property.setDatatypeWithEnum(property.datatypeWithEnum.replace(property.enumName, enumName));
}
property.setEnumName(enumName);
}
}
@Override
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, List<Server> servers) {
final CodegenOperation op = super.fromOperation(path, httpMethod, operation, servers);
for (CodegenResponse r : op.responses) {
// By default only set types are automatically added to operation imports, not sure why.
// Add all container type imports here, by default 'dart:core' imports are skipped
// but other sub classes may required specific container type imports.
if (r.containerType != null && typeMapping().containsKey(r.containerType)) {
final String value = typeMapping().get(r.containerType);
if (needToImport(value)) {
op.imports.add(value);
}
}
}
for (CodegenParameter p : op.allParams) {
if (p.isContainer) {
final String type = p.isArray ? "array" : "map";
if (typeMapping().containsKey(type)) {
final String value = typeMapping().get(type);
// Also add container imports for parameters.
if (needToImport(value)) {
op.imports.add(value);
}
}
}
}
return op;
}
@Override
protected void updateEnumVarsWithExtensions(List<Map<String, Object>> enumVars, Map<String, Object> vendorExtensions, String dataType) {
if (vendorExtensions != null && useEnumExtension && vendorExtensions.containsKey("x-enum-values")) {
// Use the x-enum-values extension for this enum
// Existing enumVars added by the default handling need to be removed first
enumVars.clear();
Object extension = vendorExtensions.get("x-enum-values");
List<Map<String, Object>> values = (List<Map<String, Object>>) extension;
for (Map<String, Object> value : values) {
Map<String, Object> enumVar = new HashMap<>();
enumVar.put("name", toEnumVarName((String) value.get("identifier"), dataType));
enumVar.put("value", toEnumValue(value.get("numericValue").toString(), dataType));
enumVar.put("isString", isDataTypeString(dataType));
if (value.containsKey("description")) {
enumVar.put("description", value.get("description").toString());
}
enumVars.add(enumVar);
}
} else {
super.updateEnumVarsWithExtensions(enumVars, vendorExtensions, dataType);
}
}
@Override
public String toEnumVarName(String value, String datatype) {
if (value.length() == 0) {
return "empty";
}
if (("number".equalsIgnoreCase(datatype) ||
"double".equalsIgnoreCase(datatype) ||
"int".equalsIgnoreCase(datatype)) &&
value.matches("^-?\\d.*")) {
// Only rename numeric values when the datatype is numeric
// AND the name is not changed by enum extensions (matches a numeric value).
boolean isNegative = value.startsWith("-");
return toVarName("number" + (isNegative ? "_negative" : "") + value);
}
return toVarName(value);
}
@Override
public String toEnumValue(String value, String datatype) {
if ("number".equalsIgnoreCase(datatype) ||
"int".equalsIgnoreCase(datatype)) {
return value;
} else {
return "'" + escapeText(value) + "'";
}
}
@Override
public String toOperationId(String operationId) {
operationId = super.toOperationId(operationId);
operationId = camelize(sanitizeName(operationId), true);
// method name cannot use reserved keyword, e.g. return
if (isReservedWord(operationId)) {
String newOperationId = camelize("call_" + operationId, true);
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId);
return newOperationId;
}
// operationId starts with a number
if (operationId.matches("^\\d.*")) {
LOGGER.warn(operationId + " (starting with a number) cannot be used as method name. Renamed to " + camelize("call_" + operationId), true);
operationId = camelize("call_" + operationId, true);
}
return operationId;
}
public void setPubLibrary(String pubLibrary) {
this.pubLibrary = pubLibrary;
}
public void setPubName(String pubName) {
this.pubName = pubName;
}
public void setPubVersion(String pubVersion) {
this.pubVersion = pubVersion;
}
public void setPubDescription(String pubDescription) {
this.pubDescription = pubDescription;
}
public void setPubAuthor(String pubAuthor) {
this.pubAuthor = pubAuthor;
}
public void setPubAuthorEmail(String pubAuthorEmail) {
this.pubAuthorEmail = pubAuthorEmail;
}
public void setPubHomepage(String pubHomepage) {
this.pubHomepage = pubHomepage;
}
public void setUseEnumExtension(boolean useEnumExtension) {
this.useEnumExtension = useEnumExtension;
}
public void setSourceFolder(String sourceFolder) {
this.sourceFolder = sourceFolder;
}
@Override
public String escapeQuotationMark(String input) {
// remove " to avoid code injection
return input.replace("\"", "");
}
@Override
public String escapeUnsafeCharacters(String input) {
return input.replace("*/", "*_/").replace("/*", "/_*");
}
@Override
public void postProcessFile(File file, String fileType) {
if (file == null) {
return;
}
String dartPostProcessFile = System.getenv("DART_POST_PROCESS_FILE");
if (StringUtils.isEmpty(dartPostProcessFile)) {
return; // skip if DART_POST_PROCESS_FILE env variable is not defined
}
// process all files with dart extension
if ("dart".equals(FilenameUtils.getExtension(file.toString()))) {
// currently only support "dartfmt -w yourcode.dart"
String command = dartPostProcessFile + " " + file.toString();
try {
Process p = Runtime.getRuntime().exec(command);
int exitValue = p.waitFor();
if (exitValue != 0) {
LOGGER.error("Error running the command ({}). Exit code: {}", command, exitValue);
} else {
LOGGER.info("Successfully executed: {}", command);
}
} catch (Exception e) {
LOGGER.error("Error running the command ({}). Exception: {}", command, e.getMessage());
}
}
}
}

View File

@ -36,7 +36,7 @@ import static org.openapitools.codegen.utils.StringUtils.camelize;
import static org.openapitools.codegen.utils.StringUtils.underscore;
public abstract class AbstractEiffelCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractEiffelCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(AbstractEiffelCodegen.class);
private final Set<String> parentModels = new HashSet<>();
private final Multimap<String, CodegenModel> childrenByParent = ArrayListMultimap.create();

View File

@ -77,7 +77,7 @@ public abstract class AbstractFSharpCodegen extends DefaultCodegen implements Co
protected Set<String> nullableType = new HashSet<String>();
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractFSharpCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(AbstractFSharpCodegen.class);
public AbstractFSharpCodegen() {
super();

View File

@ -34,7 +34,7 @@ import static org.openapitools.codegen.utils.StringUtils.underscore;
public abstract class AbstractGoCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractGoCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(AbstractGoCodegen.class);
private static final String NUMERIC_ENUM_PREFIX = "_";
protected boolean withGoCodegenComment = false;
@ -393,7 +393,7 @@ public abstract class AbstractGoCodegen extends DefaultCodegen implements Codege
String type = null;
if (ref != null && !ref.isEmpty()) {
type = openAPIType;
type = toModelName(openAPIType);
} else if ("object".equals(openAPIType) && isAnyTypeSchema(p)) {
// Arbitrary type. Note this is not the same thing as free-form object.
type = "interface{}";

View File

@ -32,7 +32,7 @@ import static org.openapitools.codegen.utils.StringUtils.underscore;
public abstract class AbstractGraphQLCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractGraphQLCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(AbstractGraphQLCodegen.class);
protected String specFolder = "spec";
protected String packageName = "openapi2graphql";

View File

@ -49,7 +49,7 @@ import static org.openapitools.codegen.utils.StringUtils.*;
public abstract class AbstractJavaCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractJavaCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(AbstractJavaCodegen.class);
private static final String ARTIFACT_VERSION_DEFAULT_VALUE = "1.0.0";
public static final String FULL_JAVA_UTIL = "fullJavaUtil";
@ -540,13 +540,6 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
}
}
if (additionalProperties.containsKey(WITH_XML)) {
setWithXml(Boolean.parseBoolean(additionalProperties.get(WITH_XML).toString()));
if (withXml) {
additionalProperties.put(WITH_XML, "true");
}
}
if (additionalProperties.containsKey(DATE_LIBRARY)) {
setDateLibrary(additionalProperties.get("dateLibrary").toString());
}

View File

@ -49,7 +49,7 @@ public abstract class AbstractJavaJAXRSServerCodegen extends AbstractJavaCodegen
protected boolean useBeanValidation = true;
protected boolean useTags = false;
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractJavaJAXRSServerCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(AbstractJavaJAXRSServerCodegen.class);
public AbstractJavaJAXRSServerCodegen() {
super();

View File

@ -49,7 +49,7 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
public static final String MODEL_MUTABLE = "modelMutable";
public static final String MODEL_MUTABLE_DESC = "Create mutable models";
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractKotlinCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(AbstractKotlinCodegen.class);
protected String artifactId;
protected String artifactVersion = "1.0.0";

View File

@ -37,7 +37,7 @@ import static org.openapitools.codegen.utils.StringUtils.underscore;
public abstract class AbstractPhpCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractPhpCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(AbstractPhpCodegen.class);
public static final String VARIABLE_NAMING_CONVENTION = "variableNamingConvention";
public static final String PACKAGE_NAME = "packageName";
@ -98,7 +98,7 @@ public abstract class AbstractPhpCodegen extends DefaultCodegen implements Codeg
);
instantiationTypes.put("array", "array");
instantiationTypes.put("map", "map");
instantiationTypes.put("map", "array");
// provide primitives to mustache template
@ -119,7 +119,7 @@ public abstract class AbstractPhpCodegen extends DefaultCodegen implements Codeg
typeMapping.put("Date", "\\DateTime");
typeMapping.put("DateTime", "\\DateTime");
typeMapping.put("file", "\\SplFileObject");
typeMapping.put("map", "map");
typeMapping.put("map", "array");
typeMapping.put("array", "array");
typeMapping.put("list", "array");
typeMapping.put("object", "object");
@ -307,7 +307,7 @@ public abstract class AbstractPhpCodegen extends DefaultCodegen implements Codeg
LOGGER.warn(p.getName() + "(map property) does not have a proper inner type defined. Default to string");
inner = new StringSchema().description("TODO default missing map inner type to string");
}
return getSchemaType(p) + "[string," + getTypeDeclaration(inner) + "]";
return getSchemaType(p) + "<string," + getTypeDeclaration(inner) + ">";
} else if (StringUtils.isNotBlank(p.get$ref())) { // model
String type = super.getTypeDeclaration(p);
return (!languageSpecificPrimitives.contains(type))

View File

@ -0,0 +1,702 @@
/*
* 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 com.github.curiousoddman.rgxgen.RgxGen;
import io.swagger.v3.oas.models.examples.Example;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.parameters.Parameter;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.*;
import org.openapitools.codegen.utils.ModelUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.openapitools.codegen.utils.StringUtils.camelize;
import static org.openapitools.codegen.utils.StringUtils.underscore;
abstract public class AbstractPythonCodegen extends DefaultCodegen implements CodegenConfig {
private final Logger LOGGER = LoggerFactory.getLogger(AbstractPythonCodegen.class);
protected String packageName = "openapi_client";
protected String packageVersion = "1.0.0";
protected String projectName; // for setup.py, e.g. petstore-api
public AbstractPythonCodegen() {
super();
// from https://docs.python.org/3/reference/lexical_analysis.html#keywords
setReservedWordsLowerCase(
Arrays.asList(
// local variable name used in API methods (endpoints)
"all_params", "resource_path", "path_params", "query_params",
"header_params", "form_params", "local_var_files", "body_params", "auth_settings",
// @property
"property",
// python reserved words
"and", "del", "from", "not", "while", "as", "elif", "global", "or", "with",
"assert", "else", "if", "pass", "yield", "break", "except", "import",
"print", "class", "exec", "in", "raise", "continue", "finally", "is",
"return", "def", "for", "lambda", "try", "self", "nonlocal", "None", "True",
"False", "async", "await"));
languageSpecificPrimitives.clear();
languageSpecificPrimitives.add("int");
languageSpecificPrimitives.add("float");
languageSpecificPrimitives.add("list");
languageSpecificPrimitives.add("dict");
languageSpecificPrimitives.add("bool");
languageSpecificPrimitives.add("str");
languageSpecificPrimitives.add("datetime");
languageSpecificPrimitives.add("date");
languageSpecificPrimitives.add("object");
// TODO file and binary is mapped as `file`
languageSpecificPrimitives.add("file");
languageSpecificPrimitives.add("bytes");
typeMapping.clear();
typeMapping.put("integer", "int");
typeMapping.put("float", "float");
typeMapping.put("number", "float");
typeMapping.put("long", "int");
typeMapping.put("double", "float");
typeMapping.put("array", "list");
typeMapping.put("set", "list");
typeMapping.put("map", "dict");
typeMapping.put("boolean", "bool");
typeMapping.put("string", "str");
typeMapping.put("date", "date");
typeMapping.put("DateTime", "datetime");
typeMapping.put("object", "object");
typeMapping.put("AnyType", "object");
typeMapping.put("file", "file");
// TODO binary should be mapped to byte array
// mapped to String as a workaround
typeMapping.put("binary", "str");
typeMapping.put("ByteArray", "str");
// map uuid to string for the time being
typeMapping.put("UUID", "str");
typeMapping.put("URI", "str");
typeMapping.put("null", "none_type");
}
@Override
public void processOpts() {
super.processOpts();
if (StringUtils.isEmpty(System.getenv("PYTHON_POST_PROCESS_FILE"))) {
LOGGER.info("Environment variable PYTHON_POST_PROCESS_FILE not defined so the Python code may not be properly formatted. To define it, try 'export PYTHON_POST_PROCESS_FILE=\"/usr/local/bin/yapf -i\"' (Linux/Mac)");
LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
}
}
@Override
public String escapeReservedWord(String name) {
if (this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}
@Override
public String getTypeDeclaration(Schema p) {
if (ModelUtils.isArraySchema(p)) {
ArraySchema ap = (ArraySchema) p;
Schema inner = ap.getItems();
return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]";
} else if (ModelUtils.isMapSchema(p)) {
Schema inner = getAdditionalProperties(p);
return getSchemaType(p) + "(str, " + getTypeDeclaration(inner) + ")";
}
return super.getTypeDeclaration(p);
}
/**
* Return the default value of the property
*
* @param p OpenAPI property object
* @return string presentation of the default value of the property
*/
@Override
public String toDefaultValue(Schema p) {
if (ModelUtils.isBooleanSchema(p)) {
if (p.getDefault() != null) {
if (Boolean.valueOf(p.getDefault().toString()) == false)
return "False";
else
return "True";
}
} else if (ModelUtils.isDateSchema(p)) {
// TODO
} else if (ModelUtils.isDateTimeSchema(p)) {
// TODO
} else if (ModelUtils.isNumberSchema(p)) {
if (p.getDefault() != null) {
return p.getDefault().toString();
}
} else if (ModelUtils.isIntegerSchema(p)) {
if (p.getDefault() != null) {
return p.getDefault().toString();
}
} else if (ModelUtils.isStringSchema(p)) {
if (p.getDefault() != null) {
if (Pattern.compile("\r\n|\r|\n").matcher((String) p.getDefault()).find())
return "'''" + p.getDefault() + "'''";
else
return "'" + ((String) p.getDefault()).replaceAll("'", "\'") + "'";
}
} else if (ModelUtils.isArraySchema(p)) {
if (p.getDefault() != null) {
return p.getDefault().toString();
}
}
return null;
}
@Override
public String toVarName(String name) {
// sanitize name
name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// remove dollar sign
name = name.replaceAll("$", "");
// if it's all uppper case, convert to lower case
if (name.matches("^[A-Z_]*$")) {
name = name.toLowerCase(Locale.ROOT);
}
// underscore the variable name
// petId => pet_id
name = underscore(name);
// remove leading underscore
name = name.replaceAll("^_*", "");
// for reserved word or word starting with number, append _
if (isReservedWord(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name);
}
return name;
}
@Override
public String toRegularExpression(String pattern) {
return addRegularExpressionDelimiter(pattern);
}
@Override
public String toParamName(String name) {
// to avoid conflicts with 'callback' parameter for async call
if ("callback".equals(name)) {
return "param_callback";
}
// should be the same as variable name
return toVarName(name);
}
@Override
public String toOperationId(String operationId) {
// throw exception if method name is empty (should not occur as an auto-generated method name will be used)
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)) {
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + underscore(sanitizeName("call_" + operationId)));
operationId = "call_" + operationId;
}
// operationId starts with a number
if (operationId.matches("^\\d.*")) {
LOGGER.warn(operationId + " (starting with a number) cannot be used as method name. Renamed to " + underscore(sanitizeName("call_" + operationId)));
operationId = "call_" + operationId;
}
return underscore(sanitizeName(operationId));
}
@Override
public String escapeQuotationMark(String input) {
// remove ' to avoid code injection
return input.replace("'", "");
}
@Override
public String escapeUnsafeCharacters(String input) {
// remove multiline comment
return input.replace("'''", "'_'_'");
}
@Override
public void postProcessFile(File file, String fileType) {
if (file == null) {
return;
}
String pythonPostProcessFile = System.getenv("PYTHON_POST_PROCESS_FILE");
if (StringUtils.isEmpty(pythonPostProcessFile)) {
return; // skip if PYTHON_POST_PROCESS_FILE env variable is not defined
}
// only process files with py extension
if ("py".equals(FilenameUtils.getExtension(file.toString()))) {
String command = pythonPostProcessFile + " " + file.toString();
try {
Process p = Runtime.getRuntime().exec(command);
int exitValue = p.waitFor();
if (exitValue != 0) {
LOGGER.error("Error running the command ({}). Exit value: {}", command, exitValue);
} else {
LOGGER.info("Successfully executed: " + command);
}
} catch (Exception e) {
LOGGER.error("Error running the command ({}). Exception: {}", command, e.getMessage());
}
}
}
@Override
public String toExampleValue(Schema schema) {
return toExampleValueRecursive(schema, new ArrayList<String>(), 5);
}
private String toExampleValueRecursive(Schema schema, List<String> included_schemas, int indentation) {
String indentation_string = "";
for (int i = 0; i < indentation; i++) indentation_string += " ";
String example = null;
if (schema.getExample() != null) {
example = schema.getExample().toString();
}
if (ModelUtils.isNullType(schema) && null != example) {
// The 'null' type is allowed in OAS 3.1 and above. It is not supported by OAS 3.0.x,
// though this tooling supports it.
return "None";
}
// correct "true"s into "True"s, since super.toExampleValue uses "toString()" on Java booleans
if (ModelUtils.isBooleanSchema(schema) && null != example) {
if ("false".equalsIgnoreCase(example)) example = "False";
else example = "True";
}
// correct "&#39;"s into "'"s after toString()
if (ModelUtils.isStringSchema(schema) && schema.getDefault() != null && !ModelUtils.isDateSchema(schema) && !ModelUtils.isDateTimeSchema(schema)) {
example = (String) schema.getDefault();
}
if (StringUtils.isNotBlank(example) && !"null".equals(example)) {
if (ModelUtils.isStringSchema(schema)) {
example = "'" + example + "'";
}
return example;
}
if (schema.getEnum() != null && !schema.getEnum().isEmpty()) {
// Enum case:
example = schema.getEnum().get(0).toString();
if (ModelUtils.isStringSchema(schema)) {
example = "'" + escapeText(example) + "'";
}
if (null == example)
LOGGER.warn("Empty enum. Cannot built an example!");
return example;
} else if (null != schema.get$ref()) {
// $ref case:
Map<String, Schema> allDefinitions = ModelUtils.getSchemas(this.openAPI);
String ref = ModelUtils.getSimpleRef(schema.get$ref());
if (allDefinitions != null) {
Schema refSchema = allDefinitions.get(ref);
if (null == refSchema) {
return "None";
} else {
String refTitle = refSchema.getTitle();
if (StringUtils.isBlank(refTitle) || "null".equals(refTitle)) {
refSchema.setTitle(ref);
}
if (StringUtils.isNotBlank(schema.getTitle()) && !"null".equals(schema.getTitle())) {
included_schemas.add(schema.getTitle());
}
return toExampleValueRecursive(refSchema, included_schemas, indentation);
}
} else {
LOGGER.warn("allDefinitions not defined in toExampleValue!\n");
}
}
if (ModelUtils.isDateSchema(schema)) {
example = "datetime.datetime.strptime('1975-12-30', '%Y-%m-%d').date()";
return example;
} else if (ModelUtils.isDateTimeSchema(schema)) {
example = "datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f')";
return example;
} else if (ModelUtils.isBinarySchema(schema)) {
example = "bytes(b'blah')";
return example;
} else if (ModelUtils.isByteArraySchema(schema)) {
example = "YQ==";
} else if (ModelUtils.isStringSchema(schema)) {
// a BigDecimal:
if ("Number".equalsIgnoreCase(schema.getFormat())) {
return "1";
}
if (StringUtils.isNotBlank(schema.getPattern())) {
String pattern = schema.getPattern();
RgxGen rgxGen = new RgxGen(patternCorrection(pattern));
// this seed makes it so if we have [a-z] we pick a
Random random = new Random(18);
String sample = rgxGen.generate(random);
// omit leading / and trailing /, omit trailing /i
Pattern valueExtractor = Pattern.compile("^/\\^?(.+?)\\$?/.?$");
Matcher m = valueExtractor.matcher(sample);
if (m.find()) {
example = m.group(m.groupCount());
} else {
example = sample;
}
}
if (example == null) {
example = "";
}
int len = 0;
if (null != schema.getMinLength()) {
len = schema.getMinLength().intValue();
if (len < 1) {
example = "";
} else {
for (int i = 0; i < len; i++) example += i;
}
}
} else if (ModelUtils.isIntegerSchema(schema)) {
if (schema.getMinimum() != null)
example = schema.getMinimum().toString();
else
example = "56";
} else if (ModelUtils.isNumberSchema(schema)) {
if (schema.getMinimum() != null)
example = schema.getMinimum().toString();
else
example = "1.337";
} else if (ModelUtils.isBooleanSchema(schema)) {
example = "True";
} else if (ModelUtils.isArraySchema(schema)) {
if (StringUtils.isNotBlank(schema.getTitle()) && !"null".equals(schema.getTitle())) {
included_schemas.add(schema.getTitle());
}
ArraySchema arrayschema = (ArraySchema) schema;
example = "[\n" + indentation_string + toExampleValueRecursive(arrayschema.getItems(), included_schemas, indentation + 1) + "\n" + indentation_string + "]";
} else if (ModelUtils.isMapSchema(schema)) {
if (StringUtils.isNotBlank(schema.getTitle()) && !"null".equals(schema.getTitle())) {
included_schemas.add(schema.getTitle());
}
Object additionalObject = schema.getAdditionalProperties();
if (additionalObject instanceof Schema) {
Schema additional = (Schema) additionalObject;
String the_key = "'key'";
if (additional.getEnum() != null && !additional.getEnum().isEmpty()) {
the_key = additional.getEnum().get(0).toString();
if (ModelUtils.isStringSchema(additional)) {
the_key = "'" + escapeText(the_key) + "'";
}
}
example = "{\n" + indentation_string + the_key + " : " + toExampleValueRecursive(additional, included_schemas, indentation + 1) + "\n" + indentation_string + "}";
} else {
example = "{ }";
}
} else if (ModelUtils.isObjectSchema(schema)) {
if (StringUtils.isBlank(schema.getTitle())) {
example = "None";
return example;
}
// I remove any property that is a discriminator, since it is not well supported by the python generator
String toExclude = null;
if (schema.getDiscriminator() != null) {
toExclude = schema.getDiscriminator().getPropertyName();
}
example = packageName + ".models." + underscore(schema.getTitle()) + "." + schema.getTitle() + "(";
// if required only:
// List<String> reqs = schema.getRequired();
// if required and optionals
List<String> reqs = new ArrayList<>();
if (schema.getProperties() != null && !schema.getProperties().isEmpty()) {
for (Object toAdd : schema.getProperties().keySet()) {
reqs.add((String) toAdd);
}
Map<String, Schema> properties = schema.getProperties();
Set<String> propkeys = null;
if (properties != null) propkeys = properties.keySet();
if (toExclude != null && reqs.contains(toExclude)) {
reqs.remove(toExclude);
}
for (String toRemove : included_schemas) {
if (reqs.contains(toRemove)) {
reqs.remove(toRemove);
}
}
if (StringUtils.isNotBlank(schema.getTitle()) && !"null".equals(schema.getTitle())) {
included_schemas.add(schema.getTitle());
}
if (null != schema.getRequired()) for (Object toAdd : schema.getRequired()) {
reqs.add((String) toAdd);
}
if (null != propkeys) for (String propname : propkeys) {
Schema schema2 = properties.get(propname);
if (reqs.contains(propname)) {
String refTitle = schema2.getTitle();
if (StringUtils.isBlank(refTitle) || "null".equals(refTitle)) {
schema2.setTitle(propname);
}
example += "\n" + indentation_string + underscore(propname) + " = " +
toExampleValueRecursive(schema2, included_schemas, indentation + 1) + ", ";
}
}
}
example += ")";
} else {
LOGGER.warn("Type " + schema.getType() + " not handled properly in toExampleValue");
}
if (ModelUtils.isStringSchema(schema)) {
example = "'" + escapeText(example) + "'";
}
return example;
}
@Override
public void setParameterExampleValue(CodegenParameter p) {
String example;
if (p.defaultValue == null) {
example = p.example;
} else {
p.example = p.defaultValue;
return;
}
String type = p.baseType;
if (type == null) {
type = p.dataType;
}
if ("String".equalsIgnoreCase(type) || "str".equalsIgnoreCase(type)) {
if (example == null) {
example = p.paramName + "_example";
}
example = "'" + escapeText(example) + "'";
} else if ("Integer".equals(type) || "int".equals(type)) {
if (example == null) {
example = "56";
}
} else if ("Float".equalsIgnoreCase(type) || "Double".equalsIgnoreCase(type)) {
if (example == null) {
example = "3.4";
}
} else if ("BOOLEAN".equalsIgnoreCase(type) || "bool".equalsIgnoreCase(type)) {
if (example == null) {
example = "True";
}
} else if ("file".equalsIgnoreCase(type)) {
if (example == null) {
example = "/path/to/file";
}
example = "'" + escapeText(example) + "'";
} else if ("Date".equalsIgnoreCase(type)) {
if (example == null) {
example = "2013-10-20";
}
example = "'" + escapeText(example) + "'";
} else if ("DateTime".equalsIgnoreCase(type)) {
if (example == null) {
example = "2013-10-20T19:20:30+01:00";
}
example = "'" + escapeText(example) + "'";
} else if (!languageSpecificPrimitives.contains(type)) {
// type is a model class, e.g. User
example = this.packageName + "." + type + "()";
} else {
LOGGER.warn("Type " + type + " not handled properly in setParameterExampleValue");
}
if (example == null) {
example = "None";
} else if (Boolean.TRUE.equals(p.isArray)) {
example = "[" + example + "]";
} else if (Boolean.TRUE.equals(p.isMap)) {
example = "{'key': " + example + "}";
}
p.example = example;
}
@Override
public void setParameterExampleValue(CodegenParameter codegenParameter, Parameter parameter) {
Schema schema = parameter.getSchema();
if (parameter.getExample() != null) {
codegenParameter.example = parameter.getExample().toString();
} else if (parameter.getExamples() != null && !parameter.getExamples().isEmpty()) {
Example example = parameter.getExamples().values().iterator().next();
if (example.getValue() != null) {
codegenParameter.example = example.getValue().toString();
}
} else if (schema != null && schema.getExample() != null) {
codegenParameter.example = schema.getExample().toString();
}
setParameterExampleValue(codegenParameter);
}
@Override
public String sanitizeTag(String tag) {
return sanitizeName(tag);
}
public String patternCorrection(String pattern) {
// Java does not recognize starting and ending forward slashes and mode modifiers
// It considers them as characters with no special meaning and tries to find them in the match string
boolean checkEnding = pattern.endsWith("/i") || pattern.endsWith("/g") || pattern.endsWith("/m");
if (checkEnding) pattern = pattern.substring(0, pattern.length() - 2);
if (pattern.endsWith("/")) pattern = pattern.substring(0, pattern.length() - 1);
if (pattern.startsWith("/")) pattern = pattern.substring(1);
return pattern;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
public void setPackageVersion(String packageVersion) {
this.packageVersion = packageVersion;
}
@Override
public String getSchemaType(Schema p) {
String openAPIType = super.getSchemaType(p);
String type = null;
if (typeMapping.containsKey(openAPIType)) {
type = typeMapping.get(openAPIType);
if (languageSpecificPrimitives.contains(type)) {
return type;
}
} else {
type = toModelName(openAPIType);
}
return type;
}
@Override
public String toModelName(String name) {
name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// remove dollar sign
name = name.replaceAll("$", "");
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(name)) {
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + camelize("model_" + name));
name = "model_" + name; // e.g. return => ModelReturn (after camelize)
}
// model name starts with number
if (name.matches("^\\d.*")) {
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + camelize("model_" + name));
name = "model_" + name; // e.g. 200Response => Model200Response (after camelize)
}
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
}
// camelize the model name
// phone_number => PhoneNumber
return camelize(name);
}
@Override
public String toModelFilename(String name) {
// underscore the model file name
// PhoneNumber => phone_number
return underscore(dropDots(toModelName(name)));
}
@Override
public String toModelTestFilename(String name) {
return "test_" + toModelFilename(name);
}
@Override
public String toApiFilename(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_");
// e.g. PhoneNumberApi.py => phone_number_api.py
return underscore(name + "_" + apiNameSuffix);
}
@Override
public String toApiTestFilename(String name) {
return "test_" + toApiFilename(name);
}
@Override
public String toApiName(String name) {
return super.toApiName(name);
}
@Override
public String toApiVarName(String name) {
if (name.length() == 0) {
return "default_api";
}
return underscore(name + "_" + apiNameSuffix);
}
protected static String dropDots(String str) {
return str.replaceAll("\\.", "_");
}
}

View File

@ -43,8 +43,8 @@ import java.util.*;
import static org.openapitools.codegen.utils.StringUtils.camelize;
import static org.openapitools.codegen.utils.StringUtils.underscore;
public abstract class AbstractPythonConnexionServerCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractPythonConnexionServerCodegen.class);
public abstract class AbstractPythonConnexionServerCodegen extends AbstractPythonCodegen implements CodegenConfig {
private final Logger LOGGER = LoggerFactory.getLogger(AbstractPythonConnexionServerCodegen.class);
public static final String CONTROLLER_PACKAGE = "controllerPackage";
public static final String DEFAULT_CONTROLLER = "defaultController";
@ -56,8 +56,6 @@ public abstract class AbstractPythonConnexionServerCodegen extends DefaultCodege
static final String MEDIA_TYPE = "mediaType";
protected int serverPort = 8080;
protected String packageName;
protected String packageVersion;
protected String controllerPackage;
protected String defaultController;
protected Map<Character, String> regexModifiers;
@ -75,49 +73,11 @@ public abstract class AbstractPythonConnexionServerCodegen extends DefaultCodege
modelPackage = "models";
testPackage = "test";
languageSpecificPrimitives.clear();
languageSpecificPrimitives.add("int");
languageSpecificPrimitives.add("float");
// TODO may remove these later to default to the setting in abstract python base class instead
languageSpecificPrimitives.add("List");
languageSpecificPrimitives.add("Dict");
languageSpecificPrimitives.add("bool");
languageSpecificPrimitives.add("str");
languageSpecificPrimitives.add("datetime");
languageSpecificPrimitives.add("date");
languageSpecificPrimitives.add("file");
languageSpecificPrimitives.add("object");
languageSpecificPrimitives.add("byte");
languageSpecificPrimitives.add("bytearray");
typeMapping.clear();
typeMapping.put("integer", "int");
typeMapping.put("float", "float");
typeMapping.put("number", "float");
typeMapping.put("long", "int");
typeMapping.put("double", "float");
typeMapping.put("array", "List");
typeMapping.put("map", "Dict");
typeMapping.put("boolean", "bool");
typeMapping.put("string", "str");
typeMapping.put("date", "date");
typeMapping.put("DateTime", "datetime");
typeMapping.put("object", "object");
typeMapping.put("file", "file");
typeMapping.put("UUID", "str");
typeMapping.put("URI", "str");
typeMapping.put("byte", "bytearray");
typeMapping.put("ByteArray", "bytearray");
// from https://docs.python.org/3/reference/lexical_analysis.html#keywords
setReservedWordsLowerCase(
Arrays.asList(
// @property
"property",
// python reserved words
"and", "del", "from", "not", "while", "as", "elif", "global", "or", "with",
"assert", "else", "if", "pass", "yield", "break", "except", "import",
"print", "class", "exec", "in", "raise", "continue", "finally", "is",
"return", "def", "for", "lambda", "try", "self", "None", "True", "False", "nonlocal"));
// set the output folder here
outputFolder = "generated-code/connexion";
@ -182,11 +142,6 @@ public abstract class AbstractPythonConnexionServerCodegen extends DefaultCodege
public void processOpts() {
super.processOpts();
if (StringUtils.isEmpty(System.getenv("PYTHON_POST_PROCESS_FILE"))) {
LOGGER.info("Environment variable PYTHON_POST_PROCESS_FILE not defined so the Python code may not be properly formatted. To define it, try 'export PYTHON_POST_PROCESS_FILE=\"/usr/local/bin/yapf -i\"' (Linux/Mac)");
LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
}
//apiTemplateFiles.clear();
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
@ -266,6 +221,7 @@ public abstract class AbstractPythonConnexionServerCodegen extends DefaultCodege
}
}
public String pythonSrcOutputFolder() {
return outputFolder + File.separator + pythonSrcRoot;
}
@ -274,10 +230,6 @@ public abstract class AbstractPythonConnexionServerCodegen extends DefaultCodege
return pkg.replace(".", File.separator);
}
private static String dropDots(String str) {
return str.replaceAll("\\.", "_");
}
@Override
public String apiPackage() {
return controllerPackage;
@ -324,20 +276,6 @@ public abstract class AbstractPythonConnexionServerCodegen extends DefaultCodege
return "test_" + toApiFilename(name);
}
/**
* Escapes a reserved word as defined in the `reservedWords` array. Handle escaping
* those terms here. This logic is only called if a variable matches the reserved words
*
* @return the escaped term
*/
@Override
public String escapeReservedWord(String name) {
if (this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name; // add an underscore to the name
}
/**
* Location to write api files. You can use the apiPackage() as defined when the class is
* instantiated
@ -367,21 +305,6 @@ public abstract class AbstractPythonConnexionServerCodegen extends DefaultCodege
return super.getTypeDeclaration(p);
}
@Override
public String getSchemaType(Schema p) {
String schemaType = super.getSchemaType(p);
String type = null;
if (typeMapping.containsKey(schemaType)) {
type = typeMapping.get(schemaType);
if (languageSpecificPrimitives.contains(type)) {
return type;
}
} else {
type = toModelName(schemaType);
}
return type;
}
@Override
public void preprocessOpenAPI(OpenAPI openAPI) {
// need vendor extensions for x-openapi-router-controller
@ -614,251 +537,11 @@ public abstract class AbstractPythonConnexionServerCodegen extends DefaultCodege
return super.postProcessSupportingFileData(objs);
}
@Override
public String toVarName(String name) {
// sanitize name
name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// remove dollar sign
name = name.replaceAll("$", "");
// if it's all uppper case, convert to lower case
if (name.matches("^[A-Z_]*$")) {
name = name.toLowerCase(Locale.ROOT);
}
// underscore the variable name
// petId => pet_id
name = underscore(name);
// remove leading underscore
name = name.replaceAll("^_*", "");
// 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) {
// to avoid conflicts with 'callback' parameter for async call
if ("callback".equals(name)) {
return "param_callback";
}
// should be the same as variable name
return toVarName(name);
}
@Override
public String toModelFilename(String name) {
// underscore the model file name
// PhoneNumber => phone_number
return underscore(dropDots(toModelName(name)));
}
@Override
public String toModelName(String name) {
name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// remove dollar sign
name = name.replaceAll("$", "");
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(name)) {
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + camelize("model_" + name));
name = "model_" + name; // e.g. return => ModelReturn (after camelize)
}
// model name starts with number
if (name.matches("^\\d.*")) {
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + camelize("model_" + name));
name = "model_" + name; // e.g. 200Response => Model200Response (after camelize)
}
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
}
// camelize the model name
// phone_number => PhoneNumber
return camelize(name);
}
@Override
public String toOperationId(String operationId) {
// throw exception if method name is empty (should not occur as an auto-generated method name will be used)
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)) {
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + underscore(sanitizeName("call_" + operationId)));
operationId = "call_" + operationId;
}
return underscore(sanitizeName(operationId));
}
/**
* Return the default value of the property
*
* @param p OpenAPI property object
* @return string presentation of the default value of the property
*/
@Override
public String toDefaultValue(Schema p) {
if (ModelUtils.isBooleanSchema(p)) {
if (p.getDefault() != null) {
if (p.getDefault().toString().equalsIgnoreCase("false"))
return "False";
else
return "True";
}
} else if (ModelUtils.isDateSchema(p)) {
// TODO
} else if (ModelUtils.isDateTimeSchema(p)) {
// TODO
} else if (ModelUtils.isNumberSchema(p)) {
if (p.getDefault() != null) {
return p.getDefault().toString();
}
} else if (ModelUtils.isIntegerSchema(p)) {
if (p.getDefault() != null) {
return p.getDefault().toString();
}
} else if (ModelUtils.isStringSchema(p)) {
if (p.getDefault() != null) {
return "'" + (String) p.getDefault() + "'";
}
}
return null;
}
@Override
public void setParameterExampleValue(CodegenParameter p) {
String example;
if (p.defaultValue == null) {
example = p.example;
} else {
p.example = p.defaultValue;
return;
}
String type = p.baseType;
if (type == null) {
type = p.dataType;
}
if ("String".equalsIgnoreCase(type) || "str".equalsIgnoreCase(type)) {
if (example == null) {
example = p.paramName + "_example";
}
example = "'" + escapeText(example) + "'";
} else if ("Integer".equals(type) || "int".equals(type)) {
if (p.minimum != null) {
example = "" + (Integer.valueOf(p.minimum) + 1);
}
if (p.maximum != null) {
example = "" + p.maximum;
} else if (example == null) {
example = "56";
}
} else if ("Long".equalsIgnoreCase(type)) {
if (p.minimum != null) {
example = "" + (Long.valueOf(p.minimum) + 1);
}
if (p.maximum != null) {
example = "" + p.maximum;
} else if (example == null) {
example = "789";
}
} else if ("Float".equalsIgnoreCase(type) || "Double".equalsIgnoreCase(type)) {
if (p.minimum != null) {
example = "" + p.minimum;
} else if (p.maximum != null) {
example = "" + p.maximum;
} else if (example == null) {
example = "3.4";
}
} else if ("BOOLEAN".equalsIgnoreCase(type) || "bool".equalsIgnoreCase(type)) {
if (example == null) {
example = "True";
}
} else if ("file".equalsIgnoreCase(type)) {
example = "(BytesIO(b'some file data'), 'file.txt')";
} else if ("Date".equalsIgnoreCase(type)) {
if (example == null) {
example = "2013-10-20";
}
example = "'" + escapeText(example) + "'";
} else if ("DateTime".equalsIgnoreCase(type)) {
if (example == null) {
example = "2013-10-20T19:20:30+01:00";
}
example = "'" + escapeText(example) + "'";
} else if (!languageSpecificPrimitives.contains(type)) {
// type is a model class, e.g. User
example = "{}";
} else {
LOGGER.warn("Type " + type + " not handled properly in setParameterExampleValue");
}
if (p.items != null && p.items.defaultValue != null) {
example = p.items.defaultValue;
}
if (example == null) {
if (Boolean.TRUE.equals(p.isArray)) {
example = "[]";
} else {
example = "None";
}
} else if (Boolean.TRUE.equals(p.isArray)) {
if (Boolean.TRUE.equals(p.isBodyParam)) {
example = "[" + example + "]";
}
} else if (Boolean.TRUE.equals(p.isMap)) {
example = "{'key': " + example + "}";
}
p.example = example;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public void setPackageVersion(String packageVersion) {
this.packageVersion = packageVersion;
}
public String packagePath() {
String pkgPath = packageName.replace('.', File.separatorChar);
return pythonSrcRoot + pkgPath;
}
@Override
public String escapeQuotationMark(String input) {
// remove ' to avoid code injection
return input.replace("'", "");
}
@Override
public String escapeUnsafeCharacters(String input) {
// remove multiline comment
return input.replace("'''", "'_'_'");
}
@Override
public String toModelImport(String name) {
String modelImport;
@ -1008,41 +691,4 @@ public abstract class AbstractPythonConnexionServerCodegen extends DefaultCodege
vendorExtensions.put("x-modifiers", modifiers);
}
}
@Override
public void postProcessFile(File file, String fileType) {
if (file == null) {
return;
}
String pythonPostProcessFile = System.getenv("PYTHON_POST_PROCESS_FILE");
if (StringUtils.isEmpty(pythonPostProcessFile)) {
return; // skip if PYTHON_POST_PROCESS_FILE env variable is not defined
}
// only process files with py extension
if ("py".equals(FilenameUtils.getExtension(file.toString()))) {
String command = pythonPostProcessFile + " " + file.toString();
try {
Process p = Runtime.getRuntime().exec(command);
int exitValue = p.waitFor();
if (exitValue != 0) {
LOGGER.error("Error running the command ({}). Exit value: {}", command, exitValue);
} else {
LOGGER.info("Successfully executed: " + command);
}
} catch (Exception e) {
LOGGER.error("Error running the command ({}). Exception: {}", command, e.getMessage());
}
}
}
/*
* We don't want to run `escapeText` on the pattern
* but forward it directly to the Python implementation.
*/
@Override
public String toRegularExpression(String pattern) {
return addRegularExpressionDelimiter(pattern);
}
}

View File

@ -40,7 +40,7 @@ import java.util.Locale;
import static org.openapitools.codegen.utils.StringUtils.underscore;
abstract public class AbstractRubyCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractRubyCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(AbstractRubyCodegen.class);
public AbstractRubyCodegen() {
super();

View File

@ -36,7 +36,7 @@ import static org.openapitools.codegen.utils.StringUtils.camelize;
import static org.openapitools.codegen.utils.StringUtils.underscore;
public abstract class AbstractScalaCodegen extends DefaultCodegen {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractScalaCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(AbstractScalaCodegen.class);
protected String modelPropertyNaming = CodegenConstants.ENUM_PROPERTY_NAMING_TYPE.camelCase.name();
protected String invokerPackage = "org.openapitools.client";

View File

@ -45,7 +45,7 @@ import static org.openapitools.codegen.utils.StringUtils.camelize;
import static org.openapitools.codegen.utils.StringUtils.underscore;
public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractTypeScriptClientCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(AbstractTypeScriptClientCodegen.class);
private static final String X_DISCRIMINATOR_TYPE = "x-discriminator-value";
private static final String UNDEFINED_VALUE = "undefined";

View File

@ -33,7 +33,7 @@ import java.util.HashSet;
import static org.openapitools.codegen.utils.StringUtils.camelize;
public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(AndroidClientCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(AndroidClientCodegen.class);
public static final String USE_ANDROID_MAVEN_GRADLE_PLUGIN = "useAndroidMavenGradlePlugin";
public static final String ANDROID_GRADLE_VERSION = "androidGradleVersion";
public static final String ANDROID_SDK_VERSION = "androidSdkVersion";

View File

@ -29,7 +29,7 @@ import static org.openapitools.codegen.utils.OnceLogger.once;
public class Apache2ConfigCodegen extends DefaultCodegen implements CodegenConfig {
public static final String USER_INFO_PATH = "userInfoPath";
private static final Logger LOGGER = LoggerFactory.getLogger(Apache2ConfigCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(Apache2ConfigCodegen.class);
protected String userInfoPath = "/var/www/html/";

View File

@ -42,7 +42,7 @@ public class ApexClientCodegen extends AbstractApexCodegen {
private static final String API_VERSION = "apiVersion";
private static final String BUILD_METHOD = "buildMethod";
private static final String NAMED_CREDENTIAL = "namedCredential";
private static final Logger LOGGER = LoggerFactory.getLogger(ApexClientCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(ApexClientCodegen.class);
private String classPrefix = "OAS";
private String apiVersion = "42.0";
private String buildMethod = "sfdx";

View File

@ -44,7 +44,7 @@ import io.swagger.v3.oas.models.OpenAPI;
*/
public class AsciidocDocumentationCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(AsciidocDocumentationCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(AsciidocDocumentationCodegen.class);
public static final String SPEC_DIR = "specDir";
public static final String SNIPPET_DIR = "snippetDir";

View File

@ -48,6 +48,7 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
public static final String GENERATE_BODY = "generateBody";
public static final String BUILD_TARGET = "buildTarget";
public static final String MODEL_CLASS_MODIFIER = "modelClassModifier";
public static final String TARGET_FRAMEWORK= "targetFramework";
public static final String PROJECT_SDK = "projectSdk";
public static final String SDK_WEB = "Microsoft.NET.Sdk.Web";
@ -68,7 +69,7 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
protected int serverPort = 8080;
protected String serverHost = "0.0.0.0";
protected CliOption swashbuckleVersion = new CliOption(SWASHBUCKLE_VERSION, "Swashbuckle version: 3.0.0, 4.0.0, 5.0.0");
protected CliOption aspnetCoreVersion = new CliOption(ASPNET_CORE_VERSION, "ASP.NET Core version: 3.1, 3.0, 2.2, 2.1, 2.0 (deprecated)");
protected CliOption aspnetCoreVersion = new CliOption(ASPNET_CORE_VERSION, "ASP.NET Core version: 5.0, 3.1, 3.0, 2.2, 2.1, 2.0 (deprecated)");
private CliOption classModifier = new CliOption(CLASS_MODIFIER, "Class Modifier for controller classes: Empty string or abstract.");
private CliOption operationModifier = new CliOption(OPERATION_MODIFIER, "Operation Modifier can be virtual or abstract");
private CliOption modelClassModifier = new CliOption(MODEL_CLASS_MODIFIER, "Model Class Modifier can be nothing or partial");
@ -123,7 +124,7 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
modelTemplateFiles.put("model.mustache", ".cs");
apiTemplateFiles.put("controller.mustache", ".cs");
embeddedTemplateDir = templateDir = "aspnetcore/2.1";
embeddedTemplateDir = templateDir = "aspnetcore/3.0";
// contextually reserved words
// NOTE: C# uses camel cased reserved words, while models are title cased. We don't want lowercase comparisons.
@ -190,6 +191,7 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
aspnetCoreVersion.addEnum("2.2", "ASP.NET Core 2.2");
aspnetCoreVersion.addEnum("3.0", "ASP.NET Core 3.0");
aspnetCoreVersion.addEnum("3.1", "ASP.NET Core 3.1");
aspnetCoreVersion.addEnum("5.0", "ASP.NET Core 5.0");
aspnetCoreVersion.setDefault("3.1");
aspnetCoreVersion.setOptValue(aspnetCoreVersion.getDefault());
addOption(aspnetCoreVersion.getOpt(), aspnetCoreVersion.getDescription(), aspnetCoreVersion.getOptValue());
@ -367,7 +369,7 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
supportingFiles.add(new SupportingFile("gitignore", packageFolder, ".gitignore"));
supportingFiles.add(new SupportingFile("validateModel.mustache", packageFolder + File.separator + "Attributes", "ValidateModelStateAttribute.cs"));
supportingFiles.add(new SupportingFile("typeConverter.mustache", packageFolder + File.separator + "Converters", "CustomEnumConverter.cs"));
if (aspnetCoreVersion.getOptValue().startsWith("3.")) {
if (aspnetCoreVersion.getOptValue().startsWith("3.") || aspnetCoreVersion.getOptValue().startsWith("5.0")) {
supportingFiles.add(new SupportingFile("OpenApi" + File.separator + "TypeExtensions.mustache", packageFolder + File.separator + "OpenApi", "TypeExtensions.cs"));
}
supportingFiles.add(new SupportingFile("Project.csproj.mustache", packageFolder, packageName + ".csproj"));
@ -535,7 +537,7 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
private void setAspnetCoreVersion(String packageFolder) {
setCliOption(aspnetCoreVersion);
if (aspnetCoreVersion.getOptValue().startsWith("3.")) {
if (aspnetCoreVersion.getOptValue().startsWith("3.") || aspnetCoreVersion.getOptValue().startsWith("5.0")) {
compatibilityVersion = null;
} else if ("2.0".equals(aspnetCoreVersion.getOptValue())) {
compatibilityVersion = null;
@ -552,6 +554,7 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
private String determineTemplateVersion(String frameworkVersion) {
switch (frameworkVersion) {
case "5.0":
case "3.1":
return "3.0";
@ -593,17 +596,25 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
LOGGER.warn("ASP.NET core version is " + aspnetCoreVersion.getOptValue() + " so changing to use frameworkReference instead of packageReference ");
useFrameworkReference = true;
additionalProperties.put(USE_FRAMEWORK_REFERENCE, useFrameworkReference);
additionalProperties.put(TARGET_FRAMEWORK, "netcoreapp" + aspnetCoreVersion);
} else if (aspnetCoreVersion.getOptValue().startsWith("5.")) {// default, do nothing
LOGGER.warn("ASP.NET core version is " + aspnetCoreVersion.getOptValue() + " so changing to use frameworkReference instead of packageReference ");
useFrameworkReference = true;
additionalProperties.put(USE_FRAMEWORK_REFERENCE, useFrameworkReference);
additionalProperties.put(TARGET_FRAMEWORK, "net5.0");
} else {
if (additionalProperties.containsKey(USE_FRAMEWORK_REFERENCE)) {
useFrameworkReference = convertPropertyToBooleanAndWriteBack(USE_FRAMEWORK_REFERENCE);
} else {
additionalProperties.put(USE_FRAMEWORK_REFERENCE, useFrameworkReference);
}
additionalProperties.put(TARGET_FRAMEWORK, "netcoreapp" + aspnetCoreVersion);
}
}
private void setUseNewtonsoft() {
if (aspnetCoreVersion.getOptValue().startsWith("2.")) {
LOGGER.warn("ASP.NET core version 2.X support has been deprecated. Please use ASP.NET core version 3.1 instead");
LOGGER.warn("ASP.NET core version is " + aspnetCoreVersion.getOptValue() + " so staying on default json library.");
useNewtonsoft = false;
additionalProperties.put(USE_NEWTONSOFT, useNewtonsoft);
@ -617,7 +628,7 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
}
private void setUseEndpointRouting() {
if (aspnetCoreVersion.getOptValue().startsWith("3.")) {
if (aspnetCoreVersion.getOptValue().startsWith("3.") || aspnetCoreVersion.getOptValue().startsWith("5.")) {
LOGGER.warn("ASP.NET core version is " + aspnetCoreVersion.getOptValue() + " so switching to old style endpoint routing.");
useDefaultRouting = false;
additionalProperties.put(USE_DEFAULT_ROUTING, useDefaultRouting);
@ -633,7 +644,7 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
private void setSwashbuckleVersion() {
setCliOption(swashbuckleVersion);
if (aspnetCoreVersion.getOptValue().startsWith("3.")) {
if (aspnetCoreVersion.getOptValue().startsWith("3.") || aspnetCoreVersion.getOptValue().startsWith("5.")) {
LOGGER.warn("ASP.NET core version is " + aspnetCoreVersion.getOptValue() + " so changing default Swashbuckle version to 5.0.0.");
swashbuckleVersion.setOptValue("5.0.0");
additionalProperties.put(SWASHBUCKLE_VERSION, swashbuckleVersion.getOptValue());

View File

@ -39,7 +39,7 @@ import java.util.*;
import static org.openapitools.codegen.utils.StringUtils.*;
public class BashClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(BashClientCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(BashClientCodegen.class);
protected String apiVersion = "1.0.0";

View File

@ -34,7 +34,7 @@ import static org.openapitools.codegen.utils.StringUtils.camelize;
import static org.openapitools.codegen.utils.StringUtils.underscore;
public class CLibcurlClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(CLibcurlClientCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(CLibcurlClientCodegen.class);
public static final String PROJECT_NAME = "projectName";
protected String moduleName;

View File

@ -36,7 +36,7 @@ import static org.openapitools.codegen.utils.StringUtils.underscore;
public class CSharpClientCodegen extends AbstractCSharpCodegen {
@SuppressWarnings({"hiding"})
private static final Logger LOGGER = LoggerFactory.getLogger(CSharpClientCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(CSharpClientCodegen.class);
private static final String NUNIT = "nunit";
private static final String RESTSHARP = "restsharp";
private static final String NEWTONSOFT_JSON = "newtonsoft-json";

View File

@ -31,7 +31,7 @@ import org.slf4j.LoggerFactory;
import java.io.File;
public class CSharpDotNet2ClientCodegen extends AbstractCSharpCodegen {
private static final Logger LOGGER = LoggerFactory.getLogger(CSharpDotNet2ClientCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(CSharpDotNet2ClientCodegen.class);
public static final String CLIENT_PACKAGE = "clientPackage";
protected String clientPackage = "Org.OpenAPITools.Client";

View File

@ -42,7 +42,7 @@ import static org.openapitools.codegen.CodegenType.SERVER;
import static org.openapitools.codegen.utils.StringUtils.camelize;
public class CSharpNancyFXServerCodegen extends AbstractCSharpCodegen {
private static final Logger LOGGER = LoggerFactory.getLogger(CSharpNancyFXServerCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(CSharpNancyFXServerCodegen.class);
private static final String API_NAMESPACE = "Modules";
private static final String MODEL_NAMESPACE = "Models";

View File

@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableMap;
import com.samskivert.mustache.Mustache;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.parser.util.SchemaTypeUtil;
import org.openapitools.codegen.*;
import org.openapitools.codegen.meta.features.*;
import org.openapitools.codegen.utils.ModelUtils;
@ -42,9 +43,14 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen {
// Defines the sdk option for targeted frameworks, which differs from targetFramework and targetFrameworkNuget
protected static final String MCS_NET_VERSION_KEY = "x-mcs-sdk";
protected static final String SUPPORTS_UWP = "supportsUWP";
protected static final String SUPPORTS_RETRY = "supportsRetry";
protected static final String NET_STANDARD = "netStandard";
// HTTP libraries
protected static final String RESTSHARP = "restsharp";
protected static final String HTTPCLIENT = "httpclient";
// Project Variable, determined from target framework. Not intended to be user-settable.
protected static final String TARGET_FRAMEWORK_IDENTIFIER = "targetFrameworkIdentifier";
// Project Variable, determined from target framework. Not intended to be user-settable.
@ -80,6 +86,7 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen {
// Defines nuget identifiers for target framework
protected String targetFrameworkNuget = targetFramework;
protected boolean supportsRetry = Boolean.TRUE;
protected boolean supportsAsync = Boolean.TRUE;
protected boolean netStandard = Boolean.FALSE;
@ -94,6 +101,9 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen {
protected String packageTags;
protected boolean useOneOfDiscriminatorLookup = false; // use oneOf discriminator's mapping for model lookup
protected boolean needsCustomHttpMethod = false;
protected boolean needsUriBuilder = false;
public CSharpNetCoreClientCodegen() {
super();
@ -290,6 +300,16 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen {
regexModifiers.put('m', "Multiline");
regexModifiers.put('s', "Singleline");
regexModifiers.put('x', "IgnorePatternWhitespace");
supportedLibraries.put(HTTPCLIENT, "HttpClient (https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient) (Beta support)");
supportedLibraries.put(RESTSHARP, "RestSharp (https://github.com/restsharp/RestSharp)");
CliOption libraryOption = new CliOption(CodegenConstants.LIBRARY, "HTTP library template (sub-template) to use");
libraryOption.setEnum(supportedLibraries);
// set RESTSHARP as the default
libraryOption.setDefault(RESTSHARP);
cliOptions.add(libraryOption);
setLibrary(RESTSHARP);
}
@Override
@ -556,8 +576,20 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen {
if (isEmpty(modelPackage)) {
setModelPackage("Model");
}
clientPackage = "Client";
if (RESTSHARP.equals(getLibrary())) {
additionalProperties.put("useRestSharp", true);
needsCustomHttpMethod = true;
} else if (HTTPCLIENT.equals(getLibrary())) {
setLibrary(HTTPCLIENT);
additionalProperties.put("useHttpClient", true);
needsUriBuilder = true;
} else {
throw new RuntimeException("Invalid HTTP library " + getLibrary() + ". Only restsharp, httpclient are supported.");
}
String framework = (String) additionalProperties.getOrDefault(CodegenConstants.DOTNET_FRAMEWORK, defaultFramework.name);
boolean strategyMatched = false;
FrameworkStrategy strategy = defaultFramework;
@ -578,7 +610,6 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen {
}
strategy.configureAdditionalProperties(additionalProperties);
setTargetFrameworkNuget(strategy.getNugetFrameworkIdentifier());
setTargetFramework(strategy.name);
setTestTargetFramework(strategy.testTargetFramework);
@ -614,6 +645,7 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen {
syncBooleanProperty(additionalProperties, CodegenConstants.VALIDATABLE, this::setValidatable, this.validatable);
syncBooleanProperty(additionalProperties, CodegenConstants.SUPPORTS_ASYNC, this::setSupportsAsync, this.supportsAsync);
syncBooleanProperty(additionalProperties, SUPPORTS_RETRY, this::setSupportsRetry, this.supportsRetry);
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);
@ -644,7 +676,12 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen {
supportingFiles.add(new SupportingFile("ExceptionFactory.mustache", clientPackageDir, "ExceptionFactory.cs"));
supportingFiles.add(new SupportingFile("OpenAPIDateConverter.mustache", clientPackageDir, "OpenAPIDateConverter.cs"));
supportingFiles.add(new SupportingFile("ClientUtils.mustache", clientPackageDir, "ClientUtils.cs"));
supportingFiles.add(new SupportingFile("HttpMethod.mustache", clientPackageDir, "HttpMethod.cs"));
if(needsCustomHttpMethod) {
supportingFiles.add(new SupportingFile("HttpMethod.mustache", clientPackageDir, "HttpMethod.cs"));
}
if(needsUriBuilder) {
supportingFiles.add(new SupportingFile("WebRequestPathBuilder.mustache", clientPackageDir, "WebRequestPathBuilder.cs"));
}
if (ProcessUtils.hasHttpSignatureMethods(openAPI)) {
supportingFiles.add(new SupportingFile("HttpSigningConfiguration.mustache", clientPackageDir, "HttpSigningConfiguration.cs"));
}
@ -654,7 +691,10 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen {
supportingFiles.add(new SupportingFile("ISynchronousClient.mustache", clientPackageDir, "ISynchronousClient.cs"));
supportingFiles.add(new SupportingFile("RequestOptions.mustache", clientPackageDir, "RequestOptions.cs"));
supportingFiles.add(new SupportingFile("Multimap.mustache", clientPackageDir, "Multimap.cs"));
supportingFiles.add(new SupportingFile("RetryConfiguration.mustache", clientPackageDir, "RetryConfiguration.cs"));
if (supportsRetry) {
supportingFiles.add(new SupportingFile("RetryConfiguration.mustache", clientPackageDir, "RetryConfiguration.cs"));
}
supportingFiles.add(new SupportingFile("IReadableConfiguration.mustache",
clientPackageDir, "IReadableConfiguration.cs"));
@ -717,6 +757,10 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen {
this.supportsAsync = supportsAsync;
}
public void setSupportsRetry(Boolean supportsRetry) {
this.supportsRetry = supportsRetry;
}
public void setTargetFramework(String dotnetFramework) {
if (!frameworks.containsKey(dotnetFramework)) {
throw new IllegalArgumentException("Invalid .NET framework version: " +
@ -1009,4 +1053,16 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen {
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("# This generator's contributed by Jim Schubert (https://github.com/jimschubert)#");
System.out.println("# Please support his work directly via https://patreon.com/jimschubert \uD83D\uDE4F #");
System.out.println("################################################################################");
}
}

View File

@ -38,7 +38,7 @@ import static org.openapitools.codegen.utils.StringUtils.dashize;
import static org.openapitools.codegen.utils.StringUtils.underscore;
public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(ClojureClientCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(ClojureClientCodegen.class);
private static final String PROJECT_NAME = "projectName";
private static final String PROJECT_DESCRIPTION = "projectDescription";
private static final String PROJECT_VERSION = "projectVersion";

View File

@ -36,7 +36,7 @@ import static org.openapitools.codegen.utils.OnceLogger.once;
import static org.openapitools.codegen.utils.StringUtils.underscore;
public class CppPistacheServerCodegen extends AbstractCppCodegen {
private static final Logger LOGGER = LoggerFactory.getLogger(CppPistacheServerCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(CppPistacheServerCodegen.class);
protected String implFolder = "impl";
protected boolean isAddExternalLibs = true;

View File

@ -16,7 +16,7 @@ import java.util.*;
import static org.openapitools.codegen.utils.OnceLogger.once;
public class CppQt5AbstractCodegen extends AbstractCppCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(CppQt5AbstractCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(CppQt5AbstractCodegen.class);
protected final String PREFIX = "OAI";
protected String apiVersion = "1.0.0";
protected static final String CPP_NAMESPACE = "cppNamespace";
@ -105,6 +105,7 @@ public class CppQt5AbstractCodegen extends AbstractCppCodegen implements Codegen
typeMapping.put("number", "double");
typeMapping.put("array", "QList");
typeMapping.put("map", "QMap");
typeMapping.put("set", "QSet");
typeMapping.put("object", PREFIX + "Object");
// mapped as "file" type for OAS 3.0
typeMapping.put("ByteArray", "QByteArray");
@ -122,6 +123,7 @@ public class CppQt5AbstractCodegen extends AbstractCppCodegen implements Codegen
systemIncludes.add("QString");
systemIncludes.add("QList");
systemIncludes.add("QMap");
systemIncludes.add("QSet");
systemIncludes.add("QDate");
systemIncludes.add("QDateTime");
systemIncludes.add("QByteArray");

View File

@ -42,7 +42,7 @@ import static org.openapitools.codegen.utils.StringUtils.camelize;
import static org.openapitools.codegen.utils.StringUtils.underscore;
public class CrystalClientCodegen extends DefaultCodegen {
private static final Logger LOGGER = LoggerFactory.getLogger(CrystalClientCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(CrystalClientCodegen.class);
private static final String NUMERIC_ENUM_PREFIX = "N";
protected static int emptyMethodNameCounter = 0;

View File

@ -17,290 +17,51 @@
package org.openapitools.codegen.languages;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.*;
import java.util.stream.Collectors;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.StringSchema;
import io.swagger.v3.oas.models.servers.Server;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.*;
import org.openapitools.codegen.meta.features.ClientModificationFeature;
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.utils.ModelUtils;
import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.SupportingFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.Schema;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import static org.openapitools.codegen.utils.StringUtils.*;
public class DartClientCodegen extends AbstractDartCodegen {
public class DartClientCodegen extends DefaultCodegen {
private static final Logger LOGGER = LoggerFactory.getLogger(DartClientCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(DartClientCodegen.class);
public static final String PUB_LIBRARY = "pubLibrary";
public static final String PUB_NAME = "pubName";
public static final String PUB_VERSION = "pubVersion";
public static final String PUB_DESCRIPTION = "pubDescription";
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 USE_ENUM_EXTENSION = "useEnumExtension";
protected String pubLibrary = "openapi.api";
protected String pubName = "openapi";
protected String pubVersion = "1.0.0";
protected String pubDescription = "OpenAPI API client";
protected String pubAuthor = "Author";
protected String pubAuthorEmail = "author@homepage";
protected String pubHomepage = "homepage";
protected boolean useEnumExtension = false;
protected String sourceFolder = "";
protected String apiDocPath = "doc" + File.separator;
protected String modelDocPath = "doc" + File.separator;
protected String apiTestPath = "test" + File.separator;
protected String modelTestPath = "test" + File.separator;
// Names that must not be used as model names because they clash with existing
// default imports (dart:io, dart:async, package:http etc.) but are not basic dataTypes.
protected Set<String> additionalReservedWords;
public static final String SERIALIZATION_LIBRARY_NATIVE = "native_serialization";
public static final String SERIALIZATION_LIBRARY_JSON_SERIALIZABLE = "json_serializable";
public DartClientCodegen() {
super();
modifyFeatureSet(features -> features
.includeDocumentationFeatures(DocumentationFeature.Readme)
.securityFeatures(EnumSet.of(
SecurityFeature.OAuth2_Implicit,
SecurityFeature.BasicAuth,
SecurityFeature.ApiKey
))
.excludeGlobalFeatures(
GlobalFeature.XMLStructureDefinitions,
GlobalFeature.Callbacks,
GlobalFeature.LinkObjects,
GlobalFeature.ParameterStyling
)
.excludeSchemaSupportFeatures(
SchemaSupportFeature.Polymorphism
)
.includeParameterFeatures(
ParameterFeature.Cookie
)
.includeClientModificationFeatures(
ClientModificationFeature.BasePath
)
);
final CliOption serializationLibrary = new CliOption(CodegenConstants.SERIALIZATION_LIBRARY,
"Specify serialization library");
serializationLibrary.setDefault(SERIALIZATION_LIBRARY_NATIVE);
serializationLibrary.setType("String");
outputFolder = "generated-code/dart";
modelTemplateFiles.put("model.mustache", ".dart");
apiTemplateFiles.put("api.mustache", ".dart");
embeddedTemplateDir = templateDir = "dart2";
apiPackage = "lib.api";
modelPackage = "lib.model";
modelDocTemplateFiles.put("object_doc.mustache", ".md");
apiDocTemplateFiles.put("api_doc.mustache", ".md");
modelTestTemplateFiles.put("model_test.mustache", ".dart");
apiTestTemplateFiles.put("api_test.mustache", ".dart");
final List<String> reservedWordsList = new ArrayList<>();
try(BufferedReader reader = new BufferedReader(
new InputStreamReader(DartClientCodegen.class.getResourceAsStream("/dart/dart-keywords.txt"),
StandardCharsets.UTF_8))) {
while (reader.ready()) {
reservedWordsList.add(reader.readLine());
}
} catch (Exception e) {
LOGGER.error("Error reading dart keywords. Exception: {}", e.getMessage());
}
setReservedWordsLowerCase(reservedWordsList);
languageSpecificPrimitives = Sets.newHashSet(
"String",
"bool",
"int",
"num",
"double",
"dynamic"
);
typeMapping = new HashMap<>();
typeMapping.put("Array", "List");
typeMapping.put("array", "List");
typeMapping.put("map", "Map");
typeMapping.put("List", "List");
typeMapping.put("set", "Set");
typeMapping.put("boolean", "bool");
typeMapping.put("string", "String");
typeMapping.put("char", "String");
typeMapping.put("int", "int");
typeMapping.put("long", "int");
typeMapping.put("short", "int");
typeMapping.put("number", "num");
typeMapping.put("float", "double");
typeMapping.put("double", "double");
typeMapping.put("decimal", "double");
typeMapping.put("integer", "int");
typeMapping.put("Date", "DateTime");
typeMapping.put("date", "DateTime");
typeMapping.put("DateTime", "DateTime");
typeMapping.put("file", "MultipartFile");
typeMapping.put("binary", "MultipartFile");
typeMapping.put("UUID", "String");
typeMapping.put("URI", "String");
typeMapping.put("ByteArray", "String");
typeMapping.put("object", "Object");
typeMapping.put("AnyType", "Object");
// DataTypes of the above values which are automatically imported.
// They are also not allowed to be model names.
defaultIncludes = Sets.newHashSet(
"String",
"bool",
"int",
"num",
"double",
"dynamic",
"List",
"Set",
"Map",
"DateTime",
"Object",
"MultipartFile"
);
additionalReservedWords = Sets.newHashSet(
"File",
"Client",
"Future",
"Response"
);
cliOptions.add(new CliOption(PUB_LIBRARY, "Library name in generated code"));
cliOptions.add(new CliOption(PUB_NAME, "Name in generated pubspec"));
cliOptions.add(new CliOption(PUB_VERSION, "Version in generated pubspec"));
cliOptions.add(new CliOption(PUB_DESCRIPTION, "Description in generated pubspec"));
cliOptions.add(new CliOption(PUB_AUTHOR, "Author name in generated pubspec"));
cliOptions.add(new CliOption(PUB_AUTHOR_EMAIL, "Email address of the author in generated pubspec"));
cliOptions.add(new CliOption(PUB_HOMEPAGE, "Homepage in generated pubspec"));
cliOptions.add(new CliOption(USE_ENUM_EXTENSION, "Allow the 'x-enum-values' extension for enums"));
cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, "Source folder for generated code"));
}
@Override
public CodegenType getTag() {
return CodegenType.CLIENT;
}
@Override
public String getName() {
return "dart";
}
@Override
public String getHelp() {
return "Generates a Dart 2.x client library.";
}
protected void defaultProcessOpts() {
super.processOpts();
final Map<String, String> serializationOptions = new HashMap<>();
serializationOptions.put(SERIALIZATION_LIBRARY_NATIVE, "Use native serializer, backwards compatible");
serializationOptions.put(SERIALIZATION_LIBRARY_JSON_SERIALIZABLE, "Use json_serializable");
serializationLibrary.setEnum(serializationOptions);
cliOptions.add(serializationLibrary);
}
@Override
public void processOpts() {
defaultProcessOpts();
super.processOpts();
if (StringUtils.isEmpty(System.getenv("DART_POST_PROCESS_FILE"))) {
LOGGER.info("Environment variable DART_POST_PROCESS_FILE not defined so the Dart code may not be properly formatted. To define it, try `export DART_POST_PROCESS_FILE=\"/usr/local/bin/dartfmt -w\"` (Linux/Mac)");
LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
}
if (additionalProperties.containsKey(PUB_NAME)) {
this.setPubName((String) additionalProperties.get(PUB_NAME));
// handle library not being set
if(additionalProperties.get(CodegenConstants.SERIALIZATION_LIBRARY) == null) {
this.library = SERIALIZATION_LIBRARY_NATIVE;
LOGGER.debug("Serialization library not set, using default {}", SERIALIZATION_LIBRARY_NATIVE);
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_NAME, pubName);
this.library = additionalProperties.get(CodegenConstants.SERIALIZATION_LIBRARY).toString();
}
if (additionalProperties.containsKey(PUB_LIBRARY)) {
this.setPubLibrary((String) additionalProperties.get(PUB_LIBRARY));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_LIBRARY, pubLibrary);
}
if (additionalProperties.containsKey(PUB_VERSION)) {
this.setPubVersion((String) additionalProperties.get(PUB_VERSION));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_VERSION, pubVersion);
}
if (additionalProperties.containsKey(PUB_DESCRIPTION)) {
this.setPubDescription((String) additionalProperties.get(PUB_DESCRIPTION));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_DESCRIPTION, pubDescription);
}
if (additionalProperties.containsKey(PUB_AUTHOR)) {
this.setPubAuthor((String) additionalProperties.get(PUB_AUTHOR));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_AUTHOR, pubAuthor);
}
if (additionalProperties.containsKey(PUB_AUTHOR_EMAIL)) {
this.setPubAuthorEmail((String) additionalProperties.get(PUB_AUTHOR_EMAIL));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_AUTHOR_EMAIL, pubAuthorEmail);
}
if (additionalProperties.containsKey(PUB_HOMEPAGE)) {
this.setPubHomepage((String) additionalProperties.get(PUB_HOMEPAGE));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_HOMEPAGE, pubHomepage);
}
if (additionalProperties.containsKey(USE_ENUM_EXTENSION)) {
this.setUseEnumExtension(convertPropertyToBooleanAndWriteBack(USE_ENUM_EXTENSION));
} else {
// Not set, use to be passed to template.
additionalProperties.put(USE_ENUM_EXTENSION, useEnumExtension);
}
if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) {
this.setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER));
}
// make api and model doc path available in mustache template
additionalProperties.put("apiDocPath", apiDocPath);
additionalProperties.put("modelDocPath", modelDocPath);
// check to not overwrite a custom templateDir
if (templateDir == null) {
embeddedTemplateDir = templateDir = "dart2";
}
this.setSerializationLibrary();
final String libFolder = sourceFolder + File.separator + "lib";
supportingFiles.add(new SupportingFile("pubspec.mustache", "", "pubspec.yaml"));
@ -319,410 +80,26 @@ public class DartClientCodegen extends DefaultCodegen {
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("travis.mustache", "", ".travis.yml"));
}
@Override
protected boolean isReservedWord(String word) {
// consider everything as reserved that is either a keyword,
// a default included type, or a type include through some library
return super.isReservedWord(word) ||
defaultIncludes().contains(word) ||
additionalReservedWords.contains(word);
}
private void setSerializationLibrary() {
final String serialization_library = getLibrary();
LOGGER.info("Using serialization library {}", serialization_library);
@Override
public String escapeReservedWord(String name) {
return name + "_";
}
switch (serialization_library) {
case SERIALIZATION_LIBRARY_JSON_SERIALIZABLE:
additionalProperties.put(SERIALIZATION_LIBRARY_JSON_SERIALIZABLE, "true");
// json_serializable requires build.yaml
supportingFiles.add(new SupportingFile("build.yaml.mustache",
"" /* main project dir */,
"build.yaml"));
break;
@Override
public String apiFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + apiPackage().replace('.', File.separatorChar);
}
case SERIALIZATION_LIBRARY_NATIVE: // fall trough to default backwards compatible generator
default:
additionalProperties.put(SERIALIZATION_LIBRARY_NATIVE, "true");
@Override
public String modelFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + modelPackage().replace('.', File.separatorChar);
}
@Override
public String apiTestFileFolder() {
return outputFolder + File.separator + apiTestPath.replace('/', File.separatorChar);
}
@Override
public String modelTestFileFolder() {
return outputFolder + File.separator + modelTestPath.replace('/', File.separatorChar);
}
@Override
public String apiDocFileFolder() {
return outputFolder + File.separator + apiDocPath.replace('/', File.separatorChar);
}
@Override
public String modelDocFileFolder() {
return outputFolder + File.separator + modelDocPath.replace('/', File.separatorChar);
}
@Override
public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replace("-", "_");
// always need to replace leading underscores first
name = name.replaceAll("^_", "");
// if it's all upper case, do nothing
if (name.matches("^[A-Z_]*$")) {
return name;
}
// replace all characters that have a mapping but ignore underscores
// append an underscore to each replacement so that it can be camelized
if (name.chars().anyMatch(character -> specialCharReplacements.containsKey("" + ((char) character)))) {
name = escape(name, specialCharReplacements, Lists.newArrayList("_"), "_");
}
// remove the rest
name = sanitizeName(name);
// camelize (lower first character) the variable name
// pet_id => petId
name = camelize(name, true);
if (name.matches("^\\d.*")) {
name = "n" + name;
}
if (isReservedWord(name)) {
name = escapeReservedWord(name);
}
return name;
}
@Override
public String toParamName(String name) {
// should be the same as variable name
return toVarName(name);
}
@Override
public String toModelName(final String name) {
String nameWithPrefixSuffix = sanitizeName(name);
if (!StringUtils.isEmpty(modelNamePrefix)) {
// add '_' so that model name can be camelized correctly
nameWithPrefixSuffix = modelNamePrefix + "_" + nameWithPrefixSuffix;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
// add '_' so that model name can be camelized correctly
nameWithPrefixSuffix = nameWithPrefixSuffix + "_" + modelNameSuffix;
}
// camelize the model name
// phone_number => PhoneNumber
final String camelizedName = camelize(nameWithPrefixSuffix);
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(camelizedName)) {
final String modelName = "Model" + camelizedName;
LOGGER.warn(camelizedName + " (reserved word) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
// model name starts with number
if (camelizedName.matches("^\\d.*")) {
final String modelName = "Model" + camelizedName; // e.g. 200Response => Model200Response (after camelize)
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
return camelizedName;
}
@Override
public String toModelFilename(String name) {
return underscore(toModelName(name));
}
@Override public String toModelDocFilename(String name) {
return toModelName(name);
}
@Override
public String toApiFilename(String name) {
return underscore(toApiName(name));
}
@Override
public String toApiTestFilename(String name) {
return toApiFilename(name) + "_test";
}
@Override
public String toModelTestFilename(String name) {
return toModelFilename(name) + "_test";
}
@Override
public String toDefaultValue(Schema schema) {
if (ModelUtils.isMapSchema(schema) || ModelUtils.isSet(schema)) {
return "const {}";
}
if (ModelUtils.isArraySchema(schema)) {
return "const []";
}
if (schema.getDefault() != null) {
if (ModelUtils.isDateSchema(schema) || ModelUtils.isDateTimeSchema(schema)) {
// this is currently not supported and would create compile errors
return null;
}
if (ModelUtils.isStringSchema(schema)) {
return "'" + schema.getDefault().toString().replace("'", "\\'") + "'";
}
return schema.getDefault().toString();
}
return null;
}
@Override
public String getTypeDeclaration(Schema p) {
Schema<?> schema = ModelUtils.unaliasSchema(this.openAPI, p, importMapping);
Schema<?> target = ModelUtils.isGenerateAliasAsModel() ? p : schema;
if (ModelUtils.isArraySchema(target)) {
Schema<?> items = getSchemaItems((ArraySchema) schema);
return getSchemaType(target) + "<" + getTypeDeclaration(items) + ">";
}
if (ModelUtils.isMapSchema(target)) {
// Note: ModelUtils.isMapSchema(p) returns true when p is a composed schema that also defines
// additionalproperties: true
Schema<?> inner = getAdditionalProperties(target);
if (inner == null) {
LOGGER.error("`{}` (map property) does not have a proper inner type defined. Default to type:string", p.getName());
inner = new StringSchema().description("TODO default missing map inner type to string");
p.setAdditionalProperties(inner);
}
return getSchemaType(target) + "<String, " + getTypeDeclaration(inner) + ">";
}
return super.getTypeDeclaration(p);
}
@Override
public String getSchemaType(Schema p) {
String openAPIType = super.getSchemaType(p);
if (openAPIType == null) {
LOGGER.error("No Type defined for Schema " + p);
}
if (typeMapping.containsKey(openAPIType)) {
return typeMapping.get(openAPIType);
}
if (languageSpecificPrimitives.contains(openAPIType)) {
return openAPIType;
}
return toModelName(openAPIType);
}
@Override
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
return postProcessModelsEnum(objs);
}
@Override
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
super.postProcessModelProperty(model, property);
if (!model.isEnum && property.isEnum) {
// These are inner enums, enums which do not exist as models, just as properties.
// They are handled via the enum_inline template and and are generated in the
// same file as the containing class. To prevent name clashes the inline enum classes
// are prefix with the classname of the containing class in the template.
// Here the datatypeWithEnum template variable gets updated to match that scheme.
// Also taking into account potential collection types e.g. List<JustSymbolEnum> -> List<EnumArraysJustSymbolEnum>
if (property.items != null) {
// basically inner items e.g. map of maps etc.
property.setDatatypeWithEnum(property.datatypeWithEnum.replace(property.items.datatypeWithEnum, model.classname + property.items.datatypeWithEnum));
} else {
property.setDatatypeWithEnum(property.datatypeWithEnum.replace(property.enumName, model.classname + property.enumName));
}
}
}
@Override
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, List<Server> servers) {
final CodegenOperation op = super.fromOperation(path, httpMethod, operation, servers);
for (CodegenResponse r : op.responses) {
// By default only set types are automatically added to operation imports, not sure why.
// Add all container type imports here, by default 'dart:core' imports are skipped
// but other sub classes may required specific container type imports.
if (r.containerType != null && typeMapping().containsKey(r.containerType)) {
final String value = typeMapping().get(r.containerType);
if (needToImport(value)) {
op.imports.add(value);
}
}
}
for (CodegenParameter p : op.allParams) {
if (p.isContainer) {
final String type = p.isArray ? "array" : "map";
if (typeMapping().containsKey(type)) {
final String value = typeMapping().get(type);
// Also add container imports for parameters.
if (needToImport(value)) {
op.imports.add(value);
}
}
}
}
return op;
}
@Override
protected void updateEnumVarsWithExtensions(List<Map<String, Object>> enumVars, Map<String, Object> vendorExtensions, String dataType) {
if (vendorExtensions != null && useEnumExtension && vendorExtensions.containsKey("x-enum-values")) {
// Use the x-enum-values extension for this enum
// Existing enumVars added by the default handling need to be removed first
enumVars.clear();
Object extension = vendorExtensions.get("x-enum-values");
List<Map<String, Object>> values = (List<Map<String, Object>>) extension;
for (Map<String, Object> value : values) {
Map<String, Object> enumVar = new HashMap<>();
enumVar.put("name", toEnumVarName((String) value.get("identifier"), dataType));
enumVar.put("value", toEnumValue(value.get("numericValue").toString(), dataType));
enumVar.put("isString", isDataTypeString(dataType));
if (value.containsKey("description")) {
enumVar.put("description", value.get("description").toString());
}
enumVars.add(enumVar);
}
} else {
super.updateEnumVarsWithExtensions(enumVars, vendorExtensions, dataType);
}
}
@Override
public String toEnumVarName(String value, String datatype) {
if (value.length() == 0) {
return "empty";
}
if (("number".equalsIgnoreCase(datatype) ||
"double".equalsIgnoreCase(datatype) ||
"int".equalsIgnoreCase(datatype)) &&
value.matches("^-?\\d.*")) {
// Only rename numeric values when the datatype is numeric
// AND the name is not changed by enum extensions (matches a numeric value).
boolean isNegative = value.startsWith("-");
return toVarName("number" + (isNegative ? "_negative" : "") + value);
}
return toVarName(value);
}
@Override
public String toEnumValue(String value, String datatype) {
if ("number".equalsIgnoreCase(datatype) ||
"int".equalsIgnoreCase(datatype)) {
return value;
} else {
return "'" + escapeText(value) + "'";
}
}
@Override
public String toOperationId(String operationId) {
operationId = super.toOperationId(operationId);
operationId = camelize(sanitizeName(operationId), true);
// method name cannot use reserved keyword, e.g. return
if (isReservedWord(operationId)) {
String newOperationId = camelize("call_" + operationId, true);
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId);
return newOperationId;
}
// operationId starts with a number
if (operationId.matches("^\\d.*")) {
LOGGER.warn(operationId + " (starting with a number) cannot be used as method name. Renamed to " + camelize("call_" + operationId), true);
operationId = camelize("call_" + operationId, true);
}
return operationId;
}
public void setPubLibrary(String pubLibrary) {
this.pubLibrary = pubLibrary;
}
public void setPubName(String pubName) {
this.pubName = pubName;
}
public void setPubVersion(String pubVersion) {
this.pubVersion = pubVersion;
}
public void setPubDescription(String pubDescription) {
this.pubDescription = pubDescription;
}
public void setPubAuthor(String pubAuthor) {
this.pubAuthor = pubAuthor;
}
public void setPubAuthorEmail(String pubAuthorEmail) {
this.pubAuthorEmail = pubAuthorEmail;
}
public void setPubHomepage(String pubHomepage) {
this.pubHomepage = pubHomepage;
}
public void setUseEnumExtension(boolean useEnumExtension) {
this.useEnumExtension = useEnumExtension;
}
public void setSourceFolder(String sourceFolder) {
this.sourceFolder = sourceFolder;
}
@Override
public String escapeQuotationMark(String input) {
// remove " to avoid code injection
return input.replace("\"", "");
}
@Override
public String escapeUnsafeCharacters(String input) {
return input.replace("*/", "*_/").replace("/*", "/_*");
}
@Override
public void postProcessFile(File file, String fileType) {
if (file == null) {
return;
}
String dartPostProcessFile = System.getenv("DART_POST_PROCESS_FILE");
if (StringUtils.isEmpty(dartPostProcessFile)) {
return; // skip if DART_POST_PROCESS_FILE env variable is not defined
}
// process all files with dart extension
if ("dart".equals(FilenameUtils.getExtension(file.toString()))) {
// currently only support "dartfmt -w yourcode.dart"
String command = dartPostProcessFile + " " + file.toString();
try {
Process p = Runtime.getRuntime().exec(command);
int exitValue = p.waitFor();
if (exitValue != 0) {
LOGGER.error("Error running the command ({}). Exit code: {}", command, exitValue);
} else {
LOGGER.info("Successfully executed: {}", command);
}
} catch (Exception e) {
LOGGER.error("Error running the command ({}). Exception: {}", command, e.getMessage());
}
}
}
}

View File

@ -32,15 +32,16 @@ import java.util.*;
import static org.openapitools.codegen.utils.StringUtils.underscore;
public class DartDioClientCodegen extends DartClientCodegen {
private static final Logger LOGGER = LoggerFactory.getLogger(DartDioClientCodegen.class);
public class DartDioClientCodegen extends AbstractDartCodegen {
private final Logger LOGGER = LoggerFactory.getLogger(DartDioClientCodegen.class);
public static final String NULLABLE_FIELDS = "nullableFields";
public static final String DATE_LIBRARY = "dateLibrary";
private static final String CLIENT_NAME = "clientName";
private boolean nullableFields = true;
private boolean nullableFields = false;
private String dateLibrary = "core";
public DartDioClientCodegen() {
@ -49,7 +50,7 @@ public class DartDioClientCodegen extends DartClientCodegen {
embeddedTemplateDir = "dart-dio";
this.setTemplateDir(embeddedTemplateDir);
cliOptions.add(new CliOption(NULLABLE_FIELDS, "Is the null fields should be in the JSON payload"));
cliOptions.add(new CliOption(NULLABLE_FIELDS, "Make all fields nullable in the JSON payload"));
CliOption dateLibrary = new CliOption(DATE_LIBRARY, "Option. Date library to use").defaultValue(this.getDateLibrary());
Map<String, String> dateOptions = new HashMap<>();
dateOptions.put("core", "Dart core library (DateTime)");
@ -149,7 +150,7 @@ public class DartDioClientCodegen extends DartClientCodegen {
@Override
public void processOpts() {
defaultProcessOpts();
super.processOpts();
if (StringUtils.isEmpty(System.getenv("DART_POST_PROCESS_FILE"))) {
LOGGER.info("Environment variable DART_POST_PROCESS_FILE not defined so the Dart code may not be properly formatted. To define it, try `export DART_POST_PROCESS_FILE=\"/usr/local/bin/dartfmt -w\"` (Linux/Mac)");
@ -163,49 +164,10 @@ public class DartDioClientCodegen extends DartClientCodegen {
additionalProperties.put(NULLABLE_FIELDS, nullableFields);
}
if (additionalProperties.containsKey(PUB_LIBRARY)) {
this.setPubLibrary((String) additionalProperties.get(PUB_LIBRARY));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_LIBRARY, pubLibrary);
}
if (additionalProperties.containsKey(PUB_NAME)) {
this.setPubName((String) additionalProperties.get(PUB_NAME));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_NAME, pubName);
}
if (!additionalProperties.containsKey(CLIENT_NAME)) {
additionalProperties.put(CLIENT_NAME, org.openapitools.codegen.utils.StringUtils.camelize(pubName));
}
if (additionalProperties.containsKey(PUB_VERSION)) {
this.setPubVersion((String) additionalProperties.get(PUB_VERSION));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_VERSION, pubVersion);
}
if (additionalProperties.containsKey(PUB_DESCRIPTION)) {
this.setPubDescription((String) additionalProperties.get(PUB_DESCRIPTION));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_DESCRIPTION, pubDescription);
}
if (additionalProperties.containsKey(USE_ENUM_EXTENSION)) {
this.setUseEnumExtension(convertPropertyToBooleanAndWriteBack(USE_ENUM_EXTENSION));
} else {
// Not set, use to be passed to template.
additionalProperties.put(USE_ENUM_EXTENSION, useEnumExtension);
}
if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) {
this.setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER));
}
if (additionalProperties.containsKey(DATE_LIBRARY)) {
this.setDateLibrary(additionalProperties.get(DATE_LIBRARY).toString());
}
@ -284,6 +246,34 @@ public class DartDioClientCodegen extends DartClientCodegen {
// enums are generated with built_value and make use of BuiltSet
model.imports.add("BuiltSet");
}
property.getVendorExtensions().put("x-built-value-serializer-type", createBuiltValueSerializerType(property));
}
private String createBuiltValueSerializerType(CodegenProperty property) {
final StringBuilder sb = new StringBuilder("const FullType(");
if (property.isContainer) {
appendCollection(sb, property);
} else {
sb.append(property.datatypeWithEnum);
}
sb.append(")");
return sb.toString();
}
private void appendCollection(StringBuilder sb, CodegenProperty property) {
sb.append(property.baseType);
sb.append(", [FullType(");
if (property.isMap) {
// a map always has string keys
sb.append("String), FullType(");
}
if (property.items.isContainer) {
appendCollection(sb, property.items);
} else {
sb.append(property.items.datatypeWithEnum);
}
sb.append(")]");
}
@Override

View File

@ -32,8 +32,9 @@ import java.util.*;
import static org.openapitools.codegen.utils.StringUtils.underscore;
public class DartJaguarClientCodegen extends DartClientCodegen {
private static final Logger LOGGER = LoggerFactory.getLogger(DartJaguarClientCodegen.class);
public class DartJaguarClientCodegen extends AbstractDartCodegen {
private final Logger LOGGER = LoggerFactory.getLogger(DartJaguarClientCodegen.class);
private static final String NULLABLE_FIELDS = "nullableFields";
private static final String SERIALIZATION_FORMAT = "serialization";
@ -41,26 +42,23 @@ public class DartJaguarClientCodegen extends DartClientCodegen {
private static final String IS_FORMAT_PROTO = "protoFormat";
private static final String CLIENT_NAME = "clientName";
private static Set<String> modelToIgnore = new HashSet<>();
private HashMap<String, String> protoTypeMapping = new HashMap<>();
private final Set<String> modelToIgnore = new HashSet<>();
private final HashMap<String, String> protoTypeMapping = new HashMap<>();
private static final String SERIALIZATION_JSON = "json";
private static final String SERIALIZATION_PROTO = "proto";
private boolean nullableFields = true;
public DartJaguarClientCodegen() {
super();
static {
modelToIgnore.add("datetime");
modelToIgnore.add("map");
modelToIgnore.add("object");
modelToIgnore.add("list");
modelToIgnore.add("file");
modelToIgnore.add("list<int>");
}
private static final String SERIALIZATION_JSON = "json";
private static final String SERIALIZATION_PROTO = "proto";
private boolean nullableFields = true;
private String serialization = SERIALIZATION_JSON;
public DartJaguarClientCodegen() {
super();
modifyFeatureSet(features -> features
.includeDocumentationFeatures(DocumentationFeature.Readme)
@ -150,7 +148,8 @@ public class DartJaguarClientCodegen extends DartClientCodegen {
@Override
public void processOpts() {
defaultProcessOpts();
super.processOpts();
if (additionalProperties.containsKey(NULLABLE_FIELDS)) {
nullableFields = convertPropertyToBooleanAndWriteBack(NULLABLE_FIELDS);
} else {
@ -159,7 +158,7 @@ public class DartJaguarClientCodegen extends DartClientCodegen {
}
if (additionalProperties.containsKey(SERIALIZATION_FORMAT)) {
serialization = ((String) additionalProperties.get(SERIALIZATION_FORMAT));
String serialization = ((String) additionalProperties.get(SERIALIZATION_FORMAT));
boolean isProto = serialization.equalsIgnoreCase(SERIALIZATION_PROTO);
additionalProperties.put(IS_FORMAT_JSON, serialization.equalsIgnoreCase(SERIALIZATION_JSON));
additionalProperties.put(IS_FORMAT_PROTO, isProto);
@ -172,35 +171,8 @@ public class DartJaguarClientCodegen extends DartClientCodegen {
additionalProperties.put(IS_FORMAT_PROTO, false);
}
if (additionalProperties.containsKey(PUB_LIBRARY)) {
this.setPubLibrary((String) additionalProperties.get(PUB_LIBRARY));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_LIBRARY, pubLibrary);
}
if (additionalProperties.containsKey(PUB_NAME)) {
this.setPubName((String) additionalProperties.get(PUB_NAME));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_NAME, pubName);
}
additionalProperties.put(CLIENT_NAME, org.openapitools.codegen.utils.StringUtils.camelize(pubName));
if (additionalProperties.containsKey(PUB_VERSION)) {
this.setPubVersion((String) additionalProperties.get(PUB_VERSION));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_VERSION, pubVersion);
}
if (additionalProperties.containsKey(PUB_DESCRIPTION)) {
this.setPubDescription((String) additionalProperties.get(PUB_DESCRIPTION));
} else {
//not set, use to be passed to template
additionalProperties.put(PUB_DESCRIPTION, pubDescription);
}
if (additionalProperties.containsKey(USE_ENUM_EXTENSION)) {
this.setUseEnumExtension(convertPropertyToBooleanAndWriteBack(USE_ENUM_EXTENSION));
} else {
@ -208,10 +180,6 @@ public class DartJaguarClientCodegen extends DartClientCodegen {
additionalProperties.put(USE_ENUM_EXTENSION, useEnumExtension);
}
if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) {
this.setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER));
}
// make api and model doc path available in mustache template
additionalProperties.put("apiDocPath", apiDocPath);
additionalProperties.put("modelDocPath", modelDocPath);

View File

@ -31,7 +31,7 @@ import java.util.Locale;
import java.util.UUID;
public class EiffelClientCodegen extends AbstractEiffelCodegen {
private static final Logger LOGGER = LoggerFactory.getLogger(EiffelClientCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(EiffelClientCodegen.class);
protected String libraryTarget = "openapi_eiffel_client";
protected String packageName = "Eiffel";

View File

@ -42,7 +42,7 @@ import static org.openapitools.codegen.utils.StringUtils.camelize;
import static org.openapitools.codegen.utils.StringUtils.underscore;
public class ElixirClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(ElixirClientCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(ElixirClientCodegen.class);
protected String apiVersion = "1.0.0";
protected String moduleName;

View File

@ -42,7 +42,7 @@ import java.util.stream.Stream;
import static org.openapitools.codegen.utils.StringUtils.camelize;
public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(ElmClientCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(ElmClientCodegen.class);
protected String packageName = "openapi";
protected String packageVersion = "1.0.0";

View File

@ -37,7 +37,7 @@ import static org.openapitools.codegen.utils.StringUtils.camelize;
import static org.openapitools.codegen.utils.StringUtils.underscore;
public class ErlangClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(ErlangClientCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(ErlangClientCodegen.class);
protected String packageName = "openapi";
protected String packageVersion = "1.0.0";
@ -298,7 +298,7 @@ public class ErlangClientCodegen extends DefaultCodegen implements CodegenConfig
@Override
public String toOperationId(String operationId) {
// method name cannot use reserved keyword, e.g. return
// method name cannot use reserved keyword, e.g. if
if (isReservedWord(operationId)) {
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + underscore(sanitizeName("call_" + operationId)).replaceAll("\\.", "_"));
operationId = "call_" + operationId;
@ -352,24 +352,33 @@ public class ErlangClientCodegen extends DefaultCodegen implements CodegenConfig
this.packageVersion = packageVersion;
}
/**
* Returns the number of required parameters plus 1.
*
* @param os List of Codegen Parameters
* @return the string representation of the number of required paramters plus 1
*/
String length(Object os) {
int l = 1;
for (CodegenParameter o : ((ExtendedCodegenOperation) os).allParams) {
CodegenParameter q = (CodegenParameter) o;
if (q.required)
if (o.required)
l++;
}
return Integer.toString(l);
}
/**
* Returns the number of required parameters or body parameters.
*
* @param os List of Codegen Parameters
* @return the number of required paramters or body parameters
*/
int lengthRequired(List<CodegenParameter> allParams) {
int l = 0;
for (CodegenParameter o : allParams) {
if (o.required || o.isBodyParam)
l++;
}
return l;
}

View File

@ -38,7 +38,7 @@ import static org.openapitools.codegen.utils.StringUtils.camelize;
import static org.openapitools.codegen.utils.StringUtils.underscore;
public class ErlangProperCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(ErlangProperCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(ErlangProperCodegen.class);
protected String packageName = "openapi";
protected String packageVersion = "1.0.0";

View File

@ -33,7 +33,7 @@ import static org.openapitools.codegen.utils.StringUtils.underscore;
public class ErlangServerCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(ErlangServerCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(ErlangServerCodegen.class);
protected String apiVersion = "1.0.0";
protected String apiPath = "src";

View File

@ -37,7 +37,7 @@ import static org.openapitools.codegen.utils.StringUtils.camelize;
import static org.openapitools.codegen.utils.StringUtils.underscore;
public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(FlashClientCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(FlashClientCodegen.class);
protected String packageName = "org.openapitools";
protected String packageVersion;

View File

@ -36,7 +36,7 @@ import org.slf4j.LoggerFactory;
public class FsharpFunctionsServerCodegen extends AbstractFSharpCodegen {
public static final String PROJECT_NAME = "projectName";
static final Logger LOGGER = LoggerFactory.getLogger(FsharpFunctionsServerCodegen.class);
final Logger LOGGER = LoggerFactory.getLogger(FsharpFunctionsServerCodegen.class);
public CodegenType getTag() {
return CodegenType.SERVER;

View File

@ -17,6 +17,7 @@
package org.openapitools.codegen.languages;
import com.google.common.collect.Iterables;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.apache.commons.lang3.StringUtils;
@ -36,7 +37,7 @@ import static org.openapitools.codegen.utils.StringUtils.camelize;
public class GoClientCodegen extends AbstractGoCodegen {
private static final Logger LOGGER = LoggerFactory.getLogger(GoClientCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(GoClientCodegen.class);
protected String packageVersion = "1.0.0";
protected String apiDocPath = "docs/";
protected String modelDocPath = "docs/";
@ -387,7 +388,7 @@ public class GoClientCodegen extends AbstractGoCodegen {
continue;
}
for (CodegenProperty param : model.vars) {
for (CodegenProperty param : Iterables.concat(model.vars, model.allVars, model.requiredVars, model.optionalVars)) {
param.vendorExtensions.put("x-go-base-type", param.dataType);
if (!param.isNullable || param.isMap || param.isArray ||
param.isFreeFormObject || param.isAnyType) {

View File

@ -32,7 +32,7 @@ import java.util.EnumSet;
public class GoDeprecatedClientCodegen extends AbstractGoCodegen {
private static final Logger LOGGER = LoggerFactory.getLogger(GoDeprecatedClientCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(GoDeprecatedClientCodegen.class);
protected String packageVersion = "1.0.0";
protected String apiDocPath = "docs/";

View File

@ -33,7 +33,7 @@ import java.util.Map;
public class GoGinServerCodegen extends AbstractGoCodegen {
private static final Logger LOGGER = LoggerFactory.getLogger(GoGinServerCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(GoGinServerCodegen.class);
protected String apiVersion = "1.0.0";
protected int serverPort = 8080;
@ -116,6 +116,8 @@ public class GoGinServerCodegen extends AbstractGoCodegen {
optServerPort.setType("int");
optServerPort.defaultValue(Integer.toString(serverPort));
cliOptions.add(optServerPort);
cliOptions.add(CliOption.newBoolean(CodegenConstants.ENUM_CLASS_PREFIX, CodegenConstants.ENUM_CLASS_PREFIX_DESC));
}
@Override
@ -165,6 +167,13 @@ public class GoGinServerCodegen extends AbstractGoCodegen {
additionalProperties.put("apiPath", apiPath);
}
if (additionalProperties.containsKey(CodegenConstants.ENUM_CLASS_PREFIX)) {
setEnumClassPrefix(Boolean.parseBoolean(additionalProperties.get(CodegenConstants.ENUM_CLASS_PREFIX).toString()));
if (enumClassPrefix) {
additionalProperties.put(CodegenConstants.ENUM_CLASS_PREFIX, true);
}
}
modelPackage = packageName;
apiPackage = packageName;

View File

@ -30,7 +30,7 @@ import java.util.Map;
public class GoServerCodegen extends AbstractGoCodegen {
private static final Logger LOGGER = LoggerFactory.getLogger(GoServerCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(GoServerCodegen.class);
protected String packageVersion = "1.0.0";
protected int serverPort = 8080;

View File

@ -30,7 +30,7 @@ import java.util.EnumSet;
public class GraphQLNodeJSExpressServerCodegen extends AbstractGraphQLCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(GraphQLNodeJSExpressServerCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(GraphQLNodeJSExpressServerCodegen.class);
@Override
public CodegenType getTag() {

View File

@ -28,7 +28,7 @@ import java.util.EnumSet;
public class GraphQLSchemaCodegen extends AbstractGraphQLCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(GraphQLSchemaCodegen.class);
private final Logger LOGGER = LoggerFactory.getLogger(GraphQLSchemaCodegen.class);
@Override
public CodegenType getTag() {

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