diff --git a/.github/workflows/check-supported-versions.yaml b/.github/workflows/check-supported-versions.yaml
index 35c95b5b2aa..430b0ea815c 100644
--- a/.github/workflows/check-supported-versions.yaml
+++ b/.github/workflows/check-supported-versions.yaml
@@ -24,18 +24,18 @@ jobs:
uses: actions/checkout@v2
- name: Set up JDK ${{ matrix.java }}
- uses: actions/setup-java@v1
+ uses: actions/setup-java@v2
with:
java-version: ${{ matrix.java }}
- - uses: actions/cache@v2.1.4
+ - uses: actions/cache@v2.1.5
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('pom.xml', 'modules/**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- - uses: actions/cache@v2.1.4
+ - uses: actions/cache@v2.1.5
with:
path: |
~/.gradle/caches
@@ -49,7 +49,7 @@ jobs:
run: mvn -nsu -B --quiet -Djacoco.skip=true -Dorg.slf4j.simpleLogger.defaultLogLevel=error --no-transfer-progress clean install --file pom.xml ${{ matrix.flags }}
- name: Upload Maven build artifact
- uses: actions/upload-artifact@v2.2.2
+ uses: actions/upload-artifact@v2.2.3
if: matrix.java == '8' && matrix.os == 'ubuntu-latest'
with:
name: artifact
diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml
index bc4992833b7..98f191f2c9c 100644
--- a/.github/workflows/sonar.yml
+++ b/.github/workflows/sonar.yml
@@ -14,7 +14,7 @@ jobs:
steps:
- uses: actions/checkout@v1
- name: Set up JDK 11
- uses: actions/setup-java@v1
+ uses: actions/setup-java@v2
with:
java-version: 11
- name: Compile with Maven
diff --git a/.travis.yml b/.travis.yml
index 9ba0b842f02..cc1f953acaa 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -62,6 +62,14 @@ addons:
- petstore.swagger.io
before_install:
+ - sudo rm -rf /var/lib/apt/lists/*
+ - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
+ - sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) edge"
+ - sudo apt-get update
+ - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
+ - mkdir -vp ~/.docker/cli-plugins/
+ - curl --silent -L "https://github.com/docker/buildx/releases/download/v0.3.0/buildx-v0.3.0.linux-amd64" > ~/.docker/cli-plugins/docker-buildx
+ - chmod a+x ~/.docker/cli-plugins/docker-buildx
# to run petstore server locally via docker
- echo "$DOCKER_HUB_PASSWORD" | docker login --username=$DOCKER_HUB_USERNAME --password-stdin || true
- docker pull swaggerapi/petstore
@@ -149,6 +157,8 @@ install:
script:
# fail fast
- set -e
+ # show docker buildx version
+ - docker buildx version
# fail if the template files contains tabs
- /bin/bash ./bin/utils/detect_tab_in_templates.sh
# fail if the test files have changes
@@ -199,12 +209,14 @@ after_success:
echo "$DOCKER_HUB_PASSWORD" | docker login --username=$DOCKER_HUB_USERNAME --password-stdin;
export cli_version=$(\mvn -o org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -v '\[');
export build_date=$(date -u +"%Y-%m-%dT%H:%M:%SZ");
- docker build --label=org.opencontainers.image.created=$build_date --label=org.opencontainers.image.title=openapi-generator-online --label=org.opencontainers.image.revision=$TRAVIS_COMMIT --label=org.opencontainers.image.version=$cli_version -t $DOCKER_GENERATOR_IMAGE_NAME ./modules/openapi-generator-online;
+ docker buildx create --use;
if [ ! -z "$TRAVIS_TAG" ]; then
- docker tag $DOCKER_GENERATOR_IMAGE_NAME:latest $DOCKER_GENERATOR_IMAGE_NAME:$TRAVIS_TAG;
+ docker buildx build --platform linux/amd64,linux/arm64 --label=org.opencontainers.image.created=$build_date --label=org.opencontainers.image.title=openapi-generator-online --label=org.opencontainers.image.revision=$TRAVIS_COMMIT --label=org.opencontainers.image.version=$cli_version -t $DOCKER_GENERATOR_IMAGE_NAME:latest -t $DOCKER_GENERATOR_IMAGE_NAME:$TRAVIS_TAG -t $DOCKER_GENERATOR_IMAGE_NAME ./modules/openapi-generator-online;
+ echo "Built and tagged $DOCKER_GENERATOR_IMAGE_NAME";
fi;
- if [ ! -z "$TRAVIS_TAG" ] || [ "$TRAVIS_BRANCH" = "master" ]; then
- docker push $DOCKER_GENERATOR_IMAGE_NAME && echo "Pushed to $DOCKER_GENERATOR_IMAGE_NAME";
+ if [ -z "$TRAVIS_TAG" ] && [ "$TRAVIS_BRANCH" = "master" ] && [ "$TRAVIS_PULL_REQUEST" = "false" ]; then
+ docker buildx build --push --platform linux/amd64,linux/arm64 --label=org.opencontainers.image.created=$build_date --label=org.opencontainers.image.title=openapi-generator-online --label=org.opencontainers.image.revision=$TRAVIS_COMMIT --label=org.opencontainers.image.version=$cli_version -t $DOCKER_GENERATOR_IMAGE_NAME ./modules/openapi-generator-online;
+ echo "Pushed to $DOCKER_GENERATOR_IMAGE_NAME for master";
fi;
fi;
## docker: build cli image and push to Docker Hub
@@ -213,12 +225,14 @@ after_success:
cp docker-entrypoint.sh ./modules/openapi-generator-cli;
export cli_version=$(\mvn -o org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -v '\[');
export build_date=$(date -u +"%Y-%m-%dT%H:%M:%SZ");
- docker build --label=org.opencontainers.image.created=$build_date --label=org.opencontainers.image.title=openapi-generator-cli --label=org.opencontainers.image.revision=$TRAVIS_COMMIT --label=org.opencontainers.image.version=$cli_version -t $DOCKER_CODEGEN_CLI_IMAGE_NAME ./modules/openapi-generator-cli;
+ docker buildx create --use;
+ docker buildx build --platform linux/amd64,linux/arm64 --label=org.opencontainers.image.created=$build_date --label=org.opencontainers.image.title=openapi-generator-cli --label=org.opencontainers.image.revision=$TRAVIS_COMMIT --label=org.opencontainers.image.version=$cli_version -t $DOCKER_CODEGEN_CLI_IMAGE_NAME ./modules/openapi-generator-cli;
if [ ! -z "$TRAVIS_TAG" ]; then
- docker tag $DOCKER_CODEGEN_CLI_IMAGE_NAME:latest $DOCKER_CODEGEN_CLI_IMAGE_NAME:$TRAVIS_TAG;
+ docker buildx build --platform linux/amd64,linux/arm64 --label=org.opencontainers.image.created=$build_date --label=org.opencontainers.image.title=openapi-generator-cli --label=org.opencontainers.image.revision=$TRAVIS_COMMIT --label=org.opencontainers.image.version=$cli_version -t $DOCKER_CODEGEN_CLI_IMAGE_NAME:latest -t $DOCKER_CODEGEN_CLI_IMAGE_NAME:$TRAVIS_TAG -t $DOCKER_CODEGEN_CLI_IMAGE_NAME ./modules/openapi-generator-cli;
+ echo "Built and tagged $DOCKER_GENERATOR_IMAGE_NAME";
fi;
- if [ ! -z "$TRAVIS_TAG" ] || [ "$TRAVIS_BRANCH" = "master" ]; then
- docker push $DOCKER_CODEGEN_CLI_IMAGE_NAME;
+ if [ -z "$TRAVIS_TAG" ] && [ "$TRAVIS_BRANCH" = "master" ] && [ "$TRAVIS_PULL_REQUEST" = "false" ]; then
+ docker buildx build --push --platform linux/amd64,linux/arm64 --label=org.opencontainers.image.created=$build_date --label=org.opencontainers.image.title=openapi-generator-cli --label=org.opencontainers.image.revision=$TRAVIS_COMMIT --label=org.opencontainers.image.version=$cli_version -t $DOCKER_CODEGEN_CLI_IMAGE_NAME ./modules/openapi-generator-cli;
echo "Pushed to $DOCKER_CODEGEN_CLI_IMAGE_NAME";
fi;
fi;
diff --git a/CI/.drone.yml b/CI/.drone.yml
index 49495e43094..037fb654724 100644
--- a/CI/.drone.yml
+++ b/CI/.drone.yml
@@ -2,6 +2,22 @@ kind: pipeline
name: default
steps:
+# test Java 11 HTTP client
+- name: java11-test
+ image: openjdk:11.0
+ commands:
+ - ./mvnw --quiet clean install -Dorg.slf4j.simpleLogger.defaultLogLevel=error
+ - ./mvnw --quiet verify -Psamples.droneio -Dorg.slf4j.simpleLogger.defaultLogLevel=error
+ # run ensure up-to-date
+ - /bin/bash bin/utils/ensure-up-to-date
+ # test java native client
+ - ./mvnw clean test -f samples/client/petstore/java/native/pom.xml
+ - ./mvnw clean test -f samples/client/petstore/java/native-async/pom.xml
+ - ./mvnw clean test -f samples/openapi3/client/petstore/java/native/pom.xml
+ # test all generators with fake petstore spec (2.0, 3.0)
+ - /bin/bash bin/utils/test-fake-petstore-for-all.sh
+ # generate test scripts
+ - /bin/bash bin/tests/run-all-test
# test nim client
- name: nim-client-test
image: nimlang/nim
@@ -38,21 +54,3 @@ steps:
image: haskell:8.6.5
commands:
- (cd samples/client/petstore/haskell-http-client/ && stack --install-ghc --no-haddock-deps haddock --fast && stack test --fast)
-# test Java 11 HTTP client
-- name: java11-test
- image: openjdk:11.0
- commands:
- - ./mvnw --quiet clean install -Dorg.slf4j.simpleLogger.defaultLogLevel=error
- - ./mvnw --quiet verify -Psamples.droneio -Dorg.slf4j.simpleLogger.defaultLogLevel=error
- # test java native client
- - ./mvnw clean test -f samples/client/petstore/java/native/pom.xml
- - ./mvnw clean test -f samples/client/petstore/java/native-async/pom.xml
- - ./mvnw clean test -f samples/openapi3/client/petstore/java/native/pom.xml
- # test all generators with fake petstore spec (2.0, 3.0)
- - /bin/bash bin/utils/test-fake-petstore-for-all.sh
- # generate test scripts
- - /bin/bash bin/tests/run-all-test
- # generate all petstore samples (client, servers, doc)
- - /bin/bash bin/generate-samples.sh
- # generate all petstore samples (openapi3)
- - /bin/bash bin/generate-samples.sh bin/configs/other/*.yaml
diff --git a/CI/circle_parallel.sh b/CI/circle_parallel.sh
index e66f5524256..b647131c7d7 100755
--- a/CI/circle_parallel.sh
+++ b/CI/circle_parallel.sh
@@ -47,7 +47,8 @@ elif [ "$NODE_INDEX" = "2" ]; then
git checkout -- .
# look for outdated samples
- ./bin/utils/ensure-up-to-date
+ #./bin/utils/ensure-up-to-date
+ # UPDATE: moved to drone.io
fi
echo "Running node $NODE_INDEX to test haskell"
# install haskell
diff --git a/README.md b/README.md
index 5b36ced7376..c27f86b1531 100644
--- a/README.md
+++ b/README.md
@@ -78,7 +78,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. 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) |
+| **Server stubs** | **Ada**, **C#** (ASP.NET Core, NancyFx), **C++** (Pistache, Restbed, Qt5 QHTTPEngine), **Erlang**, **F#** (Giraffe), **Go** (net/http, Gin, Echo), **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/) |
| **Others** | **GraphQL**, **JMeter**, **Ktorm**, **MySQL Schema**, **Protocol Buffer** |
@@ -659,6 +659,7 @@ Here are some companies/projects (alphabetical order) using OpenAPI Generator in
- [Stingray](http://www.stingray.com)
- [Suva](https://www.suva.ch/)
- [Telstra](https://dev.telstra.com)
+- [The University of Aizu](https://www.u-aizu.ac.jp/en/)
- [TravelTime platform](https://www.traveltimeplatform.com/)
- [TribalScale](https://www.tribalscale.com)
- [TUI InfoTec GmbH](http://www.tui-infotec.com/)
@@ -814,6 +815,14 @@ Here are some companies/projects (alphabetical order) using OpenAPI Generator in
- 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/)
+- 2021-03-08 - [OpenAPI Generator 工具的躺坑尝试](https://blog.csdn.net/u013019701/article/details/114531975) by [独家雨天](https://blog.csdn.net/u013019701) at [CSDN官方博客](https://blog.csdn.net/)
+- 2021-03-16 - [如何基于 Swagger 使用 OpenAPI Generator 生成 JMeter 脚本?](https://cloud.tencent.com/developer/article/1802704) by [高楼Zee](https://cloud.tencent.com/developer/user/5836255) at [腾讯云专栏](https://cloud.tencent.com/developer/column)
+- 2021-03-24 - [openapi-generator-cli による TypeScript 型定義](https://zenn.dev/takepepe/articles/openapi-generator-cli-ts) by [Takefumi Yoshii](https://zenn.dev/takepepe)
+- 2021-03-28 - [Trying out NestJS part 4: Generate Typescript clients from OpenAPI documents](https://dev.to/arnaudcortisse/trying-out-nestjs-part-4-generate-typescript-clients-from-openapi-documents-28mk) by [Arnaud Cortisse](https://dev.to/arnaudcortisse)
+- 2021-03-31 - [Open API Server Implementation Using OpenAPI Generator](https://www.baeldung.com/java-openapi-generator-server) at [Baeldung](https://www.baeldung.com/)
+- 2021-03-31 - [使用OpenAPI Generator實現Open API Server](https://www.1ju.org/article/java-openapi-generator-server) at [億聚網](https://www.1ju.org/)
+- 2022-04-19 - [Introducing Twilio’s OpenAPI Specification Beta](https://www.twilio.com/blog/introducing-twilio-open-api-specification-beta) by [GARETH PAUL JONES](https://www.twilio.com/blog/author/gpj) at [Twilio Blog](https://www.twilio.com/blog)
+- 2022-04-22 - [Leveraging OpenApi strengths in a Micro-Service environment](https://medium.com/unibuddy-technology-blog/leveraging-openapi-strengths-in-a-micro-service-environment-3d7f9e7c26ff) by Nicolas Jellab at [Unibuddy Technology Blog](https://medium.com/unibuddy-technology-blog)
## [6 - About Us](#table-of-contents)
@@ -926,6 +935,7 @@ Here is a list of template creators:
* Erlang Server: @galaxie
* F# (Giraffe) Server: @nmfisher
* Go Server: @guohuang
+ * Go (Echo) Server: @ph4r5h4d
* Go (Gin) Server: @kemokemo
* GraphQL Express Server: @renepardon
* Haskell Servant: @algas
@@ -1018,7 +1028,7 @@ If you want to join the committee, please kindly apply by sending an email to te
| Elm | @eriktim (2018/09) |
| Erlang | @tsloughter (2017/11) @jfacorro (2018/10) @robertoaloi (2018/10) |
| F# | @nmfisher (2019/05) |
-| Go | @antihax (2017/11) @grokify (2018/07) @kemokemo (2018/09) @jirikuncar (2021/01) |
+| Go | @antihax (2017/11) @grokify (2018/07) @kemokemo (2018/09) @jirikuncar (2021/01) @ph4r5h4d (2021/04) |
| GraphQL | @renepardon (2018/12) |
| Groovy | |
| Haskell | |
diff --git a/appveyor.yml b/appveyor.yml
index b5fe251f30a..ec69f197198 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -43,6 +43,8 @@ build_script:
- 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 (multiple frameworks)
+ - dotnet build samples\client\petstore\csharp-netcore\OpenAPIClientCoreAndNet47\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)
@@ -66,6 +68,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 (multiple frameworks)
+ - dotnet test samples\client\petstore\csharp-netcore\OpenAPIClientCoreAndNet47\src\Org.OpenAPITools.Test\Org.OpenAPITools.Test.csproj
# 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)
diff --git a/bin/configs/other/bash.yaml b/bin/configs/bash.yaml
similarity index 100%
rename from bin/configs/other/bash.yaml
rename to bin/configs/bash.yaml
diff --git a/bin/configs/csharp-netcore-OpenAPIClientCoreAndNet47.yaml b/bin/configs/csharp-netcore-OpenAPIClientCoreAndNet47.yaml
new file mode 100644
index 00000000000..58b30f42acb
--- /dev/null
+++ b/bin/configs/csharp-netcore-OpenAPIClientCoreAndNet47.yaml
@@ -0,0 +1,8 @@
+generatorName: csharp-netcore
+outputDir: samples/client/petstore/csharp-netcore/OpenAPIClientCoreAndNet47
+inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
+templateDir: modules/openapi-generator/src/main/resources/csharp-netcore
+additionalProperties:
+ packageGuid: '{321C8C3F-0156-40C1-AE42-D59761FB9B6C}'
+ targetFramework: netstandard2.1;netcoreapp3.0
+ useCompareNetObjects: "true"
diff --git a/bin/configs/dart-dio-next-petstore-client-lib-fake.yaml b/bin/configs/dart-dio-next-petstore-client-lib-fake.yaml
index 830b10ebb75..edcc346a19f 100644
--- a/bin/configs/dart-dio-next-petstore-client-lib-fake.yaml
+++ b/bin/configs/dart-dio-next-petstore-client-lib-fake.yaml
@@ -2,5 +2,9 @@ generatorName: dart-dio-next
outputDir: samples/openapi3/client/petstore/dart-dio-next/petstore_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/dart/libraries/dio
+typeMappings:
+ Client: "ModelClient"
+ File: "ModelFile"
+ EnumClass: "ModelEnumClass"
additionalProperties:
hideGenerationTimestamp: "true"
diff --git a/bin/configs/dart-dio-petstore-client-lib-fake.yaml b/bin/configs/dart-dio-petstore-client-lib-fake.yaml
index 2463da464ed..eca85edfd88 100644
--- a/bin/configs/dart-dio-petstore-client-lib-fake.yaml
+++ b/bin/configs/dart-dio-petstore-client-lib-fake.yaml
@@ -2,5 +2,9 @@ generatorName: dart-dio
outputDir: samples/openapi3/client/petstore/dart-dio/petstore_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/dart-dio
+typeMappings:
+ Client: "ModelClient"
+ File: "ModelFile"
+ EnumClass: "ModelEnumClass"
additionalProperties:
hideGenerationTimestamp: "true"
diff --git a/bin/configs/dart-dio-petstore-client-lib-oas2.yaml b/bin/configs/dart-dio-petstore-client-lib-oas2.yaml
deleted file mode 100644
index 447136518a8..00000000000
--- a/bin/configs/dart-dio-petstore-client-lib-oas2.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-generatorName: dart-dio
-outputDir: samples/client/petstore/dart-dio/petstore_client_lib
-inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore.yaml
-templateDir: modules/openapi-generator/src/main/resources/dart-dio
-additionalProperties:
- hideGenerationTimestamp: "true"
diff --git a/bin/configs/dart-petstore-client-lib-fake.yaml b/bin/configs/dart-petstore-client-lib-fake.yaml
index 8dda4df4b0a..d48cd8038b7 100644
--- a/bin/configs/dart-petstore-client-lib-fake.yaml
+++ b/bin/configs/dart-petstore-client-lib-fake.yaml
@@ -2,5 +2,8 @@ generatorName: dart
outputDir: samples/openapi3/client/petstore/dart2/petstore_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
+typeMappings:
+ Client: "ModelClient"
+ File: "ModelFile"
additionalProperties:
hideGenerationTimestamp: "true"
diff --git a/bin/configs/dart-petstore-client-lib-oas2.yaml b/bin/configs/dart-petstore-client-lib-oas2.yaml
deleted file mode 100644
index 861a829ac4f..00000000000
--- a/bin/configs/dart-petstore-client-lib-oas2.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-generatorName: dart
-outputDir: samples/client/petstore/dart2/petstore_client_lib
-inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore.yaml
-templateDir: modules/openapi-generator/src/main/resources/dart2
-additionalProperties:
- hideGenerationTimestamp: "true"
diff --git a/bin/configs/dart-petstore-json-serializable-client-lib-fake.yaml b/bin/configs/dart-petstore-json-serializable-client-lib-fake.yaml
index cb943d3d957..8582a881d51 100644
--- a/bin/configs/dart-petstore-json-serializable-client-lib-fake.yaml
+++ b/bin/configs/dart-petstore-json-serializable-client-lib-fake.yaml
@@ -2,6 +2,9 @@ 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
+typeMappings:
+ Client: "ModelClient"
+ File: "ModelFile"
additionalProperties:
hideGenerationTimestamp: "true"
serializationLibrary: json_serializable
diff --git a/bin/configs/go-echo-server-petstore-new.yaml b/bin/configs/go-echo-server-petstore-new.yaml
new file mode 100644
index 00000000000..bfc2e946c58
--- /dev/null
+++ b/bin/configs/go-echo-server-petstore-new.yaml
@@ -0,0 +1,6 @@
+generatorName: go-echo-server
+outputDir: samples/server/petstore/go-echo-server
+inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
+templateDir: modules/openapi-generator/src/main/resources/go-echo-server
+additionalProperties:
+ hideGenerationTimestamp: "true"
diff --git a/bin/configs/go-server-go-api-server.yaml b/bin/configs/go-server-go-api-server.yaml
index 6446d212a35..7fb761639b2 100644
--- a/bin/configs/go-server-go-api-server.yaml
+++ b/bin/configs/go-server-go-api-server.yaml
@@ -5,3 +5,4 @@ templateDir: modules/openapi-generator/src/main/resources/go-server
additionalProperties:
hideGenerationTimestamp: "true"
packageName: petstoreserver
+ addResponseHeaders: true
diff --git a/bin/configs/php-symfony-SymfonyBundle-php.yaml b/bin/configs/php-symfony-SymfonyBundle-php.yaml
index c77a71f14b7..f7c6218a50f 100644
--- a/bin/configs/php-symfony-SymfonyBundle-php.yaml
+++ b/bin/configs/php-symfony-SymfonyBundle-php.yaml
@@ -1,4 +1,4 @@
generatorName: php-symfony
outputDir: samples/server/petstore/php-symfony/SymfonyBundle-php
-inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore.yaml
+inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/php-symfony
diff --git a/bin/configs/swift5-default.yaml b/bin/configs/swift5-default.yaml
index ede36e7331c..fffd318be1a 100644
--- a/bin/configs/swift5-default.yaml
+++ b/bin/configs/swift5-default.yaml
@@ -1,6 +1,6 @@
generatorName: swift5
outputDir: samples/client/petstore/swift5/default
-inputSpec: modules/openapi-generator/src/test/resources/2_0/swift/petstore-with-fake-endpoints-models-for-testing.yaml
+inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml
templateDir: modules/openapi-generator/src/main/resources/swift5
generateAliasAsModel: true
additionalProperties:
diff --git a/bin/configs/swift5-rxswiftLibrary.yaml b/bin/configs/swift5-rxswiftLibrary.yaml
index f564ac3340c..49d0e24cca5 100644
--- a/bin/configs/swift5-rxswiftLibrary.yaml
+++ b/bin/configs/swift5-rxswiftLibrary.yaml
@@ -9,3 +9,4 @@ additionalProperties:
podSummary: PetstoreClient
projectName: PetstoreClient
podHomepage: https://github.com/openapitools/openapi-generator
+ useBacktickEscapes: true
diff --git a/bin/configs/swift5-urlsessionLibrary.yaml b/bin/configs/swift5-urlsessionLibrary.yaml
index 2fe5ecca0c7..b260611e602 100644
--- a/bin/configs/swift5-urlsessionLibrary.yaml
+++ b/bin/configs/swift5-urlsessionLibrary.yaml
@@ -9,3 +9,5 @@ additionalProperties:
podSummary: PetstoreClient
projectName: PetstoreClient
podHomepage: https://github.com/openapitools/openapi-generator
+ useSPMFileStructure: true
+ useClasses: true
diff --git a/bin/configs/typescript-axios-with-fake-endpoints-models-for-testing-with-http-signature.yaml b/bin/configs/typescript-axios-with-fake-endpoints-models-for-testing-with-http-signature.yaml
new file mode 100644
index 00000000000..1cb364d79ea
--- /dev/null
+++ b/bin/configs/typescript-axios-with-fake-endpoints-models-for-testing-with-http-signature.yaml
@@ -0,0 +1,3 @@
+generatorName: typescript-axios
+outputDir: samples/client/petstore/typescript-axios/builds/with-fake-endpoints-models-for-testing-with-http-signature
+inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing-with-http-signature.yaml
diff --git a/bin/meta-codegen.sh b/bin/meta-codegen.sh
index d2a05a0fe6a..5b90f6abc8c 100755
--- a/bin/meta-codegen.sh
+++ b/bin/meta-codegen.sh
@@ -1,5 +1,7 @@
#!/usr/bin/env bash
+set -e
+
SCRIPT="$0"
echo "# START SCRIPT: $SCRIPT"
@@ -18,8 +20,8 @@ ags="meta -n myClientCodegen -t DOCUMENTATION -p com.my.company.codegen -o sampl
java $JAVA_OPTS -jar $executable $ags
-(cd "$root"/samples/meta-codegen/ && mvn -B package -Djacoco.skip=true -DskipTests=true -f pom.xml)
+(./mvnw -B package -Djacoco.skip=true -DskipTests=true -f "$root"/samples/meta-codegen/pom.xml)
-ags2="generate -g myClientCodegen -i modules/openapi-generator/src/test/resources/2_0/petstore.json -o samples/meta-codegen/usage $@"
+ags2="generate -g myClientCodegen -i modules/openapi-generator/src/test/resources/3_0/petstore.json -o samples/meta-codegen/usage $@"
-java $JAVA_OPTS -cp ${root}/samples/meta-codegen/lib/target/myClientCodegen-openapi-generator-1.0.0.jar:$executable org.openapitools.codegen.OpenAPIGenerator $ags2
\ No newline at end of file
+java $JAVA_OPTS -cp ${root}/samples/meta-codegen/lib/target/myClientCodegen-openapi-generator-1.0.0.jar:$executable org.openapitools.codegen.OpenAPIGenerator $ags2
diff --git a/bin/utils/test-fake-petstore-for-all.sh b/bin/utils/test-fake-petstore-for-all.sh
index 6be320d6b99..1ec62890c3b 100755
--- a/bin/utils/test-fake-petstore-for-all.sh
+++ b/bin/utils/test-fake-petstore-for-all.sh
@@ -11,15 +11,16 @@ logfile="/tmp/generator-fake-petstore-output.log"
for GENERATOR in $(java -jar ${executable} list --short | sed -e 's/,/\'$'\n''/g')
do
- if eval java -jar ${executable} generate -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g ${GENERATOR} -o /tmp/openapi-generator-test-fake-petstore/2.0/${GENERATOR} > ${logfile} 2>&1; then
- echo "[OAS 2.0] Executed ${GENERATOR} successfully!"
- else
- echo "ERROR: Failed to run '${GENERATOR}' generator. The command was:"
- echo "java -jar ${executable} generate -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g ${GENERATOR} -o /tmp/openapi-generator-test-fake-petstore/2.0/${GENERATOR}"
- echo "ERROR: The output of the command was:"
- cat ${logfile}
- exit 1
- fi
+ # no longer test 2.0 spec as we migrated to 3.0 spec
+ #if eval java -jar ${executable} generate -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g ${GENERATOR} -o /tmp/openapi-generator-test-fake-petstore/2.0/${GENERATOR} > ${logfile} 2>&1; then
+ # echo "[OAS 2.0] Executed ${GENERATOR} successfully!"
+ #else
+ # echo "ERROR: Failed to run '${GENERATOR}' generator. The command was:"
+ # echo "java -jar ${executable} generate -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g ${GENERATOR} -o /tmp/openapi-generator-test-fake-petstore/2.0/${GENERATOR}"
+ # echo "ERROR: The output of the command was:"
+ # cat ${logfile}
+ # exit 1
+ #fi
if eval java -jar ${executable} generate -i modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml -g ${GENERATOR} -o /tmp/openapi-generator-test-fake-petstore/3.0/${GENERATOR} > ${logfile} 2>&1; then
echo "[OAS 3.0] Executed ${GENERATOR} successfully!"
diff --git a/docs/generators.md b/docs/generators.md
index e581cc54fb1..521bdc3dbf0 100644
--- a/docs/generators.md
+++ b/docs/generators.md
@@ -86,6 +86,7 @@ The following generators are available:
* [erlang-server](generators/erlang-server.md)
* [fsharp-functions (beta)](generators/fsharp-functions.md)
* [fsharp-giraffe-server (beta)](generators/fsharp-giraffe-server.md)
+* [go-echo-server (beta)](generators/go-echo-server.md)
* [go-gin-server](generators/go-gin-server.md)
* [go-server](generators/go-server.md)
* [graphql-nodejs-express-server](generators/graphql-nodejs-express-server.md)
diff --git a/docs/generators/csharp-netcore.md b/docs/generators/csharp-netcore.md
index c7935752d01..0887dcbfeca 100644
--- a/docs/generators/csharp-netcore.md
+++ b/docs/generators/csharp-netcore.md
@@ -29,7 +29,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|returnICollection|Return ICollection<T> instead of the concrete type.| |false|
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|sourceFolder|source folder for generated code| |src|
-|targetFramework|The target .NET framework version.|
**netstandard1.3** .NET Standard 1.3 compatible **netstandard1.4** .NET Standard 1.4 compatible **netstandard1.5** .NET Standard 1.5 compatible **netstandard1.6** .NET Standard 1.6 compatible **netstandard2.0** .NET Standard 2.0 compatible **netstandard2.1** .NET Standard 2.1 compatible **netcoreapp2.0** .NET Core 2.0 compatible **netcoreapp2.1** .NET Core 2.1 compatible **netcoreapp3.0** .NET Core 3.0 compatible **netcoreapp3.1** .NET Core 3.1 compatible **net47** .NET Framework 4.7 compatible **net5.0** .NET 5.0 compatible |netstandard2.0|
+|targetFramework|The target .NET framework version. To target multiple frameworks, use `;` as the separator, e.g. `netstandard2.1;netcoreapp3.0`|**netstandard1.3** .NET Standard 1.3 compatible **netstandard1.4** .NET Standard 1.4 compatible **netstandard1.5** .NET Standard 1.5 compatible **netstandard1.6** .NET Standard 1.6 compatible **netstandard2.0** .NET Standard 2.0 compatible **netstandard2.1** .NET Standard 2.1 compatible **netcoreapp2.0** .NET Core 2.0 compatible **netcoreapp2.1** .NET Core 2.1 compatible **netcoreapp3.0** .NET Core 3.0 compatible **netcoreapp3.1** .NET Core 3.1 compatible **net47** .NET Framework 4.7 compatible **net5.0** .NET 5.0 compatible |netstandard2.0|
|useCollection|Deserialize array types to Collection<T> instead of List<T>.| |false|
|useDateTimeOffset|Use DateTimeOffset to model date-time properties| |false|
|useOneOfDiscriminatorLookup|Use the discriminator's mapping in oneOf to speed up the model lookup. IMPORTANT: Validation (e.g. one and only one match in oneOf's schemas) will be skipped.| |false|
diff --git a/docs/generators/csharp.md b/docs/generators/csharp.md
index ec9c4454ff8..0b3185606ec 100644
--- a/docs/generators/csharp.md
+++ b/docs/generators/csharp.md
@@ -25,7 +25,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|returnICollection|Return ICollection<T> instead of the concrete type.| |false|
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|sourceFolder|source folder for generated code| |src|
-|targetFramework|The target .NET framework version.|**v3.5** .NET Framework 3.5 compatible **v4.0** .NET Framework 4.0 compatible **v4.5** .NET Framework 4.5 compatible **v4.5.2** .NET Framework 4.5.2+ compatible **netstandard1.3** .NET Standard 1.3 compatible (DEPRECATED. Please use `csharp-netcore` generator instead) **uwp** Universal Windows Platform (DEPRECATED. Please use `csharp-netcore` generator instead) |v4.5|
+|targetFramework|The target .NET framework version. To target multiple frameworks, use `;` as the separator, e.g. `netstandard2.1;netcoreapp3.0`|**v3.5** .NET Framework 3.5 compatible **v4.0** .NET Framework 4.0 compatible **v4.5** .NET Framework 4.5 compatible **v4.5.2** .NET Framework 4.5.2+ compatible **netstandard1.3** .NET Standard 1.3 compatible (DEPRECATED. Please use `csharp-netcore` generator instead) **uwp** Universal Windows Platform (DEPRECATED. Please use `csharp-netcore` generator instead) |v4.5|
|useCollection|Deserialize array types to Collection<T> instead of List<T>.| |false|
|useCompareNetObjects|Use KellermanSoftware.CompareNetObjects for deep recursive object comparison. WARNING: this option incurs potential performance impact.| |false|
|useDateTimeOffset|Use DateTimeOffset to model date-time properties| |false|
diff --git a/docs/generators/dart-dio-next.md b/docs/generators/dart-dio-next.md
index da4fbe4f9a8..d644e35b04a 100644
--- a/docs/generators/dart-dio-next.md
+++ b/docs/generators/dart-dio-next.md
@@ -44,7 +44,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl
String
bool
double
-dynamic
int
num
diff --git a/docs/generators/dart-dio.md b/docs/generators/dart-dio.md
index 767884d7eeb..9368dc7e7fc 100644
--- a/docs/generators/dart-dio.md
+++ b/docs/generators/dart-dio.md
@@ -30,11 +30,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| Type/Alias | Imports |
| ---------- | ------- |
-|BuiltList|package:built_collection/built_collection.dart|
-|BuiltMap|package:built_collection/built_collection.dart|
-|BuiltSet|package:built_collection/built_collection.dart|
-|JsonObject|package:built_value/json_object.dart|
-|Uint8List|dart:typed_data|
## INSTANTIATION TYPES
@@ -49,7 +44,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl
String
bool
double
-dynamic
int
num
diff --git a/docs/generators/dart-jaguar.md b/docs/generators/dart-jaguar.md
index d357bae3146..068b5728f02 100644
--- a/docs/generators/dart-jaguar.md
+++ b/docs/generators/dart-jaguar.md
@@ -44,7 +44,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl
String
bool
double
-dynamic
int
num
diff --git a/docs/generators/dart.md b/docs/generators/dart.md
index d550256877c..ef805b78451 100644
--- a/docs/generators/dart.md
+++ b/docs/generators/dart.md
@@ -43,7 +43,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl
String
bool
double
-dynamic
int
num
diff --git a/docs/generators/go-echo-server.md b/docs/generators/go-echo-server.md
new file mode 100644
index 00000000000..53c726fb85e
--- /dev/null
+++ b/docs/generators/go-echo-server.md
@@ -0,0 +1,206 @@
+---
+title: Config Options for go-echo-server
+sidebar_label: go-echo-server
+---
+
+These options may be applied as additional-properties (cli) or configOptions (plugins). Refer to [configuration docs](https://openapi-generator.tech/docs/configuration) for more details.
+
+| Option | Description | Values | Default |
+| ------ | ----------- | ------ | ------- |
+|hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |true|
+|packageName|Go package name (convention: lowercase).| |openapi|
+|packageVersion|Go package version.| |1.0.0|
+|serverPort|The network port the generated server binds to| |8080|
+
+## IMPORT MAPPING
+
+| Type/Alias | Imports |
+| ---------- | ------- |
+
+
+## INSTANTIATION TYPES
+
+| Type/Alias | Instantiated By |
+| ---------- | --------------- |
+
+
+## LANGUAGE PRIMITIVES
+
+
+bool
+byte
+complex128
+complex64
+float32
+float64
+int
+int32
+int64
+interface{}
+map[string]interface{}
+rune
+string
+uint
+uint32
+uint64
+
+
+## RESERVED WORDS
+
+
+bool
+break
+byte
+case
+chan
+complex128
+complex64
+const
+continue
+default
+defer
+else
+error
+fallthrough
+float32
+float64
+for
+func
+go
+goto
+if
+import
+int
+int16
+int32
+int64
+int8
+interface
+map
+nil
+package
+range
+return
+rune
+select
+string
+struct
+switch
+type
+uint
+uint16
+uint32
+uint64
+uint8
+uintptr
+var
+
+
+## FEATURE SET
+
+
+### Client Modification Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|BasePath|✗|ToolingExtension
+|Authorizations|✗|ToolingExtension
+|UserAgent|✗|ToolingExtension
+|MockServer|✗|ToolingExtension
+
+### Data Type Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|Custom|✗|OAS2,OAS3
+|Int32|✓|OAS2,OAS3
+|Int64|✓|OAS2,OAS3
+|Float|✓|OAS2,OAS3
+|Double|✓|OAS2,OAS3
+|Decimal|✓|ToolingExtension
+|String|✓|OAS2,OAS3
+|Byte|✓|OAS2,OAS3
+|Binary|✓|OAS2,OAS3
+|Boolean|✓|OAS2,OAS3
+|Date|✓|OAS2,OAS3
+|DateTime|✓|OAS2,OAS3
+|Password|✓|OAS2,OAS3
+|File|✓|OAS2
+|Array|✓|OAS2,OAS3
+|Maps|✓|ToolingExtension
+|CollectionFormat|✓|OAS2
+|CollectionFormatMulti|✓|OAS2
+|Enum|✓|OAS2,OAS3
+|ArrayOfEnum|✓|ToolingExtension
+|ArrayOfModel|✓|ToolingExtension
+|ArrayOfCollectionOfPrimitives|✓|ToolingExtension
+|ArrayOfCollectionOfModel|✓|ToolingExtension
+|ArrayOfCollectionOfEnum|✓|ToolingExtension
+|MapOfEnum|✓|ToolingExtension
+|MapOfModel|✓|ToolingExtension
+|MapOfCollectionOfPrimitives|✓|ToolingExtension
+|MapOfCollectionOfModel|✓|ToolingExtension
+|MapOfCollectionOfEnum|✓|ToolingExtension
+
+### Documentation Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|Readme|✓|ToolingExtension
+|Model|✓|ToolingExtension
+|Api|✓|ToolingExtension
+
+### Global Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|Host|✓|OAS2,OAS3
+|BasePath|✓|OAS2,OAS3
+|Info|✓|OAS2,OAS3
+|Schemes|✗|OAS2,OAS3
+|PartialSchemes|✓|OAS2,OAS3
+|Consumes|✓|OAS2
+|Produces|✓|OAS2
+|ExternalDocumentation|✓|OAS2,OAS3
+|Examples|✓|OAS2,OAS3
+|XMLStructureDefinitions|✗|OAS2,OAS3
+|MultiServer|✗|OAS3
+|ParameterizedServer|✗|OAS3
+|ParameterStyling|✗|OAS3
+|Callbacks|✗|OAS3
+|LinkObjects|✗|OAS3
+
+### Parameter Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|Path|✓|OAS2,OAS3
+|Query|✓|OAS2,OAS3
+|Header|✓|OAS2,OAS3
+|Body|✓|OAS2
+|FormUnencoded|✓|OAS2
+|FormMultipart|✓|OAS2
+|Cookie|✗|OAS3
+
+### Schema Support Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|Simple|✓|OAS2,OAS3
+|Composite|✓|OAS2,OAS3
+|Polymorphism|✗|OAS2,OAS3
+|Union|✗|OAS3
+
+### Security Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|BasicAuth|✗|OAS2,OAS3
+|ApiKey|✗|OAS2,OAS3
+|OpenIDConnect|✗|OAS3
+|BearerToken|✗|OAS3
+|OAuth2_Implicit|✗|OAS2,OAS3
+|OAuth2_Password|✗|OAS2,OAS3
+|OAuth2_ClientCredentials|✗|OAS2,OAS3
+|OAuth2_AuthorizationCode|✗|OAS2,OAS3
+
+### Wire Format Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|JSON|✓|OAS2,OAS3
+|XML|✓|OAS2,OAS3
+|PROTOBUF|✗|ToolingExtension
+|Custom|✗|OAS2,OAS3
diff --git a/docs/generators/go-server.md b/docs/generators/go-server.md
index e0abd3de52c..36ac78aea6d 100644
--- a/docs/generators/go-server.md
+++ b/docs/generators/go-server.md
@@ -7,6 +7,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| Option | Description | Values | Default |
| ------ | ----------- | ------ | ------- |
+|addResponseHeaders|To include response headers in ImplResponse| |false|
|enumClassPrefix|Prefix enum with class name| |false|
|featureCORS|Enable Cross-Origin Resource Sharing middleware| |false|
|hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |true|
diff --git a/docs/generators/swift5.md b/docs/generators/swift5.md
index ebf6f2b0e86..9774b434f13 100644
--- a/docs/generators/swift5.md
+++ b/docs/generators/swift5.md
@@ -33,7 +33,10 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|responseAs|Optionally use libraries to manage response. Currently PromiseKit, RxSwift, Result, Combine are available.| |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|
+|swiftPackagePath|Set a custom source path instead of OpenAPIClient/Classes/OpenAPIs.| |null|
|swiftUseApiNamespace|Flag to make all the API classes inner-class of {{projectName}}API| |null|
+|useBacktickEscapes|Escape reserved words using backticks (default: false)| |false|
+|useSPMFileStructure|Use SPM file structure and set the source path to Sources/{{projectName}} (default: false).| |null|
## IMPORT MAPPING
diff --git a/docs/plugins.md b/docs/plugins.md
index 224a0d5fa58..691c5fa85d1 100644
--- a/docs/plugins.md
+++ b/docs/plugins.md
@@ -15,7 +15,9 @@ Add to your `build->plugins` section (default phase is `generate-sources` phase)
org.openapitools
openapi-generator-maven-plugin
- 5.0.0
+
+ 5.1.0
+
diff --git a/docs/templating.md b/docs/templating.md
index fa901bc65aa..aba3fd49274 100644
--- a/docs/templating.md
+++ b/docs/templating.md
@@ -910,9 +910,9 @@ x-content-type: application/json
### Rust-server
-#### x-responseId
+#### x-response-id
-Each response may specify a unique `x-responseId`. `rust-server` will use this to name the corresponding enum variant in the code. e.g.
+Each response may specify a unique `x-response-id`. `rust-server` will use this to name the corresponding enum variant in the code. e.g.
```yaml
paths:
@@ -921,7 +921,7 @@ paths:
responses:
200:
description: OK
- x-responseId: Pong
+ x-response-id: Pong
```
### MySQL Schema
diff --git a/docs/usage.md b/docs/usage.md
index a5719e27761..bad47c90ade 100644
--- a/docs/usage.md
+++ b/docs/usage.md
@@ -10,12 +10,13 @@ This page demonstrates navigating the options via CLI. Commands are presented he
The `help` option lists all commands available to the CLI.
-```bash
+```text
openapi-generator-cli help
usage: openapi-generator-cli []
The most commonly used openapi-generator-cli commands are:
author Utilities for authoring generators or customizing templates.
+ batch Generate code in batch via external configs.
config-help Config help for chosen lang
generate Generate code with the specified generator.
help Display help information about openapi-generator
@@ -30,26 +31,28 @@ command.
## version
-The version command provides version information, returning either the semver version by default or the git sha when passed `--sha`.
+The version command provides version information, returning either the version by default, the git commit sha when passed `--sha`, or verbose output when passed `--full`.
-```bash
+```text
NAME
- openapi-generator-cli version - Show version information
+ openapi-generator-cli version - Show version information used in tooling
SYNOPSIS
- openapi-generator-cli version [--sha]
+ openapi-generator-cli version [--full] [--sha]
OPTIONS
+ --full
+ Full version details
+
--sha
Git commit SHA version
-
```
## list
The `list` command outputs a formatted list of every available generator. Pass the `-s/--short` option if you would like a CSV output for easy parsing.
-```bash
+```text
openapi-generator-cli help list
NAME
openapi-generator-cli list - Lists the available generators
@@ -66,7 +69,6 @@ OPTIONS
-s, --short
shortened output (suitable for scripting)
-
```
Example:
@@ -81,26 +83,49 @@ For the full list of generators, refer to the [Generators List](./generators.md)
The `config-help` option provides details about
-```bash
+```text
openapi-generator-cli help config-help
NAME
openapi-generator-cli config-help - Config help for chosen lang
SYNOPSIS
openapi-generator-cli config-help
- [(-f | --format )]
+ [(-f | --format )] [--feature-set]
+ [--full-details]
[(-g | --generator-name )]
- [--markdown-header] [--named-header]
- [(-o | --output )]
+ [--import-mappings] [--instantiation-types]
+ [--language-specific-primitive] [--markdown-header] [--named-header]
+ [(-o | --output )] [--reserved-words]
OPTIONS
-f , --format
Write output files in the desired format. Options are 'text',
'markdown' or 'yamlsample'. Default is 'text'.
+ --feature-set
+ displays feature set as supported by the generator
+
+ --full-details
+ displays CLI options as well as other configs/mappings (implies
+ --instantiation-types, --reserved-words,
+ --language-specific-primitives, --import-mappings,
+ --supporting-files)
+
-g , --generator-name
generator to get config help for
+ --import-mappings
+ displays the default import mappings (types and aliases, and what
+ imports they will pull into the template)
+
+ --instantiation-types
+ displays types used to instantiate simple type/alias names
+
+ --language-specific-primitive
+ displays the language specific primitives (types which require no
+ additional imports, or which may conflict with user defined model
+ names)
+
--markdown-header
When format=markdown, include this option to write out markdown
headers (e.g. for docusaurus).
@@ -112,6 +137,9 @@ OPTIONS
Optionally write help to this location, otherwise default is
standard output
+ --reserved-words
+ displays the reserved words which may result in renamed model or
+ property names
```
The option of note is `-g/--generator-name` (other options are exposed for tooling).
@@ -153,7 +181,7 @@ To pass these go client generator-specific options to the `generate` command for
The `meta` command creates a new Java class and template files, used for creating your own custom templates.
-```bash
+```text
openapi-generator-cli help meta
NAME
openapi-generator-cli meta - MetaGenerator. Generator for creating a new
@@ -161,11 +189,15 @@ NAME
the language you specify, and includes default templates to include.
SYNOPSIS
- openapi-generator-cli meta [(-n | --name )]
+ openapi-generator-cli meta [(-l | --language )]
+ [(-n | --name )]
[(-o | --output )]
[(-p | --package )] [(-t | --type )]
OPTIONS
+ -l , --language
+ the implementation language for the generator class
+
-n , --name
the human-readable name of the generator
@@ -186,7 +218,7 @@ For an in-depth example of using the `meta` command, see [Customization](./custo
The `validate` command allows you to validate an input specification, optionally providing recommendations for error fixes or other improvements (if available).
-```bash
+```text
openapi-generator-cli help validate
NAME
openapi-generator-cli validate - Validate specification
@@ -200,7 +232,6 @@ OPTIONS
location of the OpenAPI spec, as URL or file (required)
--recommend
-
```
Valid Spec Example (using [petstore-v3.0.yaml](https://raw.githubusercontent.com/OpenAPITools/openapi-generator/master/modules/openapi-generator-gradle-plugin/samples/local-spec/petstore-v3.0.yaml))
@@ -250,7 +281,7 @@ An example bash completion script can be found in the repo at [scripts/openapi-g
The `generate` command is the workhorse of the generator toolset. As such, it has _many_ more options available than the previous commands. The abbreviated options are below, but you may expand the full descriptions.
-```bash
+```text
openapi-generator-cli help generate
NAME
openapi-generator-cli generate - Generate code with the specified
@@ -269,23 +300,24 @@ SYNOPSIS
[--git-repo-id ] [--git-user-id ]
[--global-property ...] [--group-id ]
[--http-user-agent ]
- (-i | --input-spec )
+ [(-i | --input-spec )]
[--ignore-file-override ]
[--import-mappings ...]
[--instantiation-types ...]
[--invoker-package ]
[--language-specific-primitives ...]
- [--library ] [--log-to-stderr] [--minimal-update]
+ [--legacy-discriminator-behavior] [--library ]
+ [--log-to-stderr] [--minimal-update]
[--model-name-prefix ]
[--model-name-suffix ]
[--model-package ]
- [(-o | --output )]
- [(-p | --additional-properties )...]
+ [(-o | --output )] [(-p | --additional-properties )...]
[--package-name ] [--release-note ]
[--remove-operation-id-prefix]
[--reserved-words-mappings ...]
[(-s | --skip-overwrite)] [--server-variables ...]
- [--skip-validate-spec] [--strict-spec ]
+ [--skip-operation-example] [--skip-validate-spec]
+ [--strict-spec ]
[(-t | --template-dir )]
[--type-mappings ...] [(-v | --verbose)]
```
@@ -293,7 +325,7 @@ SYNOPSIS
generate OPTIONS
-```bash
+```text
OPTIONS
-a , --auth
adds authorization headers when fetching the OpenAPI definitions
@@ -303,7 +335,7 @@ OPTIONS
--api-name-suffix
Suffix that will be appended to all API names ('tags'). Default:
Api. e.g. Pet => PetApi. Note: Only ruby, python, jaxrs generators
- suppport this feature at the moment.
+ support this feature at the moment.
--api-package
package for generated api classes
@@ -367,7 +399,8 @@ OPTIONS
'OpenAPI-Generator/{packageVersion}/{language}'
-i , --input-spec
- location of the OpenAPI spec, as URL or file (required)
+ location of the OpenAPI spec, as URL or file (required if not loaded
+ via config using -c)
--ignore-file-override
Specifies an override location for the .openapi-generator-ignore
@@ -394,13 +427,18 @@ OPTIONS
String,boolean,Boolean,Double. You can also have multiple
occurrences of this option.
+ --legacy-discriminator-behavior
+ Set to false for generators with better support for discriminators.
+ (Python, Java, Go, PowerShell, C#have this enabled by default).
+
--library
library template (sub-template)
--log-to-stderr
write all log messages (not just errors) to STDOUT. Useful for
- piping the JSON output of debug options (e.g. `--global-property debugOperations=true`)
- to an external parser directly while testing a generator.
+ piping the JSON output of debug options (e.g. `--global-property
+ debugOperations`) to an external parser directly while testing a
+ generator.
--minimal-update
Only write output files that have changed.
@@ -445,6 +483,9 @@ OPTIONS
sets server variables overrides for spec documents which support
variable templating of servers.
+ --skip-operation-example
+ Skip examples defined in operations to avoid out of memory errors.
+
--skip-validate-spec
Skips the default behavior of validating an input specification.
@@ -464,7 +505,6 @@ OPTIONS
-v, --verbose
verbose mode
-
```
@@ -604,19 +644,22 @@ The `batch` command allows you to move all CLI arguments supported by the `gener
*NOTE*: This command supports an additional `!include` property which may point to another "shared" file, the base path to which can be
modified by `--includes-base-dir`. Starting with 5.0.0, the `!batch` command supports multiple `!include` properties, either sequential or nested. In order to support multiple `!include` properties in a JSON file, the property name can have a suffix, e.g. `!include1`, `!include2`, etc. The suffix have no meaning other than providing unique property names.
-```bash
+```text
openapi-generator-cli help batch
NAME
openapi-generator-cli batch - Generate code in batch via external
configs.
SYNOPSIS
- openapi-generator-cli batch [--fail-fast]
+ openapi-generator-cli batch [--clean] [--fail-fast]
[--includes-base-dir ] [(-r | --threads )]
[--root-dir ] [--timeout ] [(-v | --verbose)] [--]
...
OPTIONS
+ --clean
+ clean output of previously written files before generation
+
--fail-fast
fail fast on any errors
@@ -682,7 +725,7 @@ openapi-generator-cli batch *.yaml
This command group contains utilities for authoring generators or customizing templates.
-```
+```text
openapi-generator-cli help author
NAME
openapi-generator-cli author - Utilities for authoring generators or
@@ -690,9 +733,9 @@ NAME
SYNOPSIS
openapi-generator-cli author
- openapi-generator-cli author template [(-v | --verbose)]
+ openapi-generator-cli author template [--library ]
+ [(-v | --verbose)]
[(-o | --output )]
- [--library ]
(-g | --generator-name )
OPTIONS
@@ -708,13 +751,13 @@ COMMANDS
template
Retrieve templates for local modification
+ With --library option, library template (sub-template)
+
With --verbose option, verbose mode
With --output option, where to write the template files (defaults to
'out')
- With --library option, library template (sub-template)
-
With --generator-name option, generator to use (see list command for
list)
```
@@ -723,7 +766,8 @@ COMMANDS
This command allows user to extract templates from the CLI jar which simplifies customization efforts.
-```
+```text
+openapi-generator-cli help author template
NAME
openapi-generator-cli author template - Retrieve templates for local
modification
@@ -753,12 +797,12 @@ Example:
Extract Java templates, limiting to the `webclient` library.
-```
+```bash
openapi-generator-cli author template -g java --library webclient
```
Extract all Java templates:
-```
+```bash
openapi-generator-cli author template -g java
```
diff --git a/modules/openapi-generator-cli/Dockerfile b/modules/openapi-generator-cli/Dockerfile
index e9c64a54619..00fad3e7cdd 100644
--- a/modules/openapi-generator-cli/Dockerfile
+++ b/modules/openapi-generator-cli/Dockerfile
@@ -1,6 +1,4 @@
-FROM java:8-jre-alpine
-
-RUN apk add --no-cache bash
+FROM openjdk:11.0-jre-buster
ADD target/openapi-generator-cli.jar /opt/openapi-generator/modules/openapi-generator-cli/target/openapi-generator-cli.jar
diff --git a/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Generate.java b/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Generate.java
index f935b14e6d7..27447fad78a 100644
--- a/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Generate.java
+++ b/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Generate.java
@@ -134,7 +134,8 @@ public class Generate extends OpenApiGeneratorCommand {
title = "type mappings",
description = "sets mappings between OpenAPI spec types and generated code types "
+ "in the format of OpenAPIType=generatedType,OpenAPIType=generatedType. For example: array=List,map=Map,string=String."
- + " You can also have multiple occurrences of this option.")
+ + " You can also have multiple occurrences of this option."
+ + " To map a specified format, use type+format, e.g. string+password=EncryptedString will map `type: string, format: password` to `EncryptedString`.")
private List typeMappings = new ArrayList<>();
@Option(
diff --git a/modules/openapi-generator-gradle-plugin/README.adoc b/modules/openapi-generator-gradle-plugin/README.adoc
index ae55fb16136..08b09304900 100644
--- a/modules/openapi-generator-gradle-plugin/README.adoc
+++ b/modules/openapi-generator-gradle-plugin/README.adoc
@@ -212,7 +212,7 @@ apply plugin: 'org.openapi.generator'
|typeMappings
|Map(String,String)
|None
-|Sets mappings between OpenAPI spec types and generated code types.
+|Sets mappings between OpenAPI spec types and generated code types in the format of OpenAPIType=generatedType,OpenAPIType=generatedType. For example: `array=List,map=Map,string=String`. You can also have multiple occurrences of this option. To map a specified format, use type+format, e.g. string+password=EncryptedString will map `type: string, format: password` to `EncryptedString`.
|additionalProperties
|Map(String,Any)
diff --git a/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/tasks/GenerateTask.kt b/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/tasks/GenerateTask.kt
index b1dcd474ae8..c3e1efcee94 100644
--- a/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/tasks/GenerateTask.kt
+++ b/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/tasks/GenerateTask.kt
@@ -81,9 +81,8 @@ open class GenerateTask : DefaultTask() {
val outputDir = project.objects.property()
@Suppress("unused")
- @get:Internal
@set:Option(option = "input", description = "The input specification.")
- @Input
+ @Internal
var input: String? = null
set(value) {
inputSpec.set(value)
diff --git a/modules/openapi-generator-maven-plugin/README.md b/modules/openapi-generator-maven-plugin/README.md
index 627fa155e63..64151ad1418 100644
--- a/modules/openapi-generator-maven-plugin/README.md
+++ b/modules/openapi-generator-maven-plugin/README.md
@@ -79,7 +79,7 @@ mvn clean compile
| `configOptions` | N/A | a **map** of language-specific parameters. To show a full list of generator-specified parameters (options), please use `configHelp` (explained below)
| `instantiationTypes` | `openapi.generator.maven.plugin.instantiationTypes` | sets instantiation type mappings in the format of type=instantiatedType,type=instantiatedType. For example (in Java): `array=ArrayList,map=HashMap`. In other words array types will get instantiated as ArrayList in generated code. You can also have multiple occurrences of this option
| `importMappings` | `openapi.generator.maven.plugin.importMappings` | specifies mappings between a given class and the import that should be used for that class in the format of type=import,type=import. You can also have multiple occurrences of this option
-| `typeMappings` | `openapi.generator.maven.plugin.typeMappings` | sets mappings between OpenAPI spec types and generated code types in the format of OpenAPIType=generatedType,OpenAPIType=generatedType. For example: `array=List,map=Map,string=String`. You can also have multiple occurrences of this option
+| `typeMappings` | `openapi.generator.maven.plugin.typeMappings` | sets mappings between OpenAPI spec types and generated code types in the format of OpenAPIType=generatedType,OpenAPIType=generatedType. For example: `array=List,map=Map,string=String`. You can also have multiple occurrences of this option. To map a specified format, use type+format, e.g. string+password=EncryptedString will map `type: string, format: password` to `EncryptedString`.
| `languageSpecificPrimitives` | `openapi.generator.maven.plugin.languageSpecificPrimitives` | specifies additional language specific primitive types in the format of type1,type2,type3,type3. For example: `String,boolean,Boolean,Double`. You can also have multiple occurrences of this option
| `additionalProperties` | `openapi.generator.maven.plugin.additionalProperties` | sets additional properties that can be referenced by the mustache templates in the format of name=value,name=value. You can also have multiple occurrences of this option
| `serverVariableOverrides` | `openapi.generator.maven.plugin.serverVariableOverrides` | A map of server variable overrides for specs that support server URL templating
diff --git a/modules/openapi-generator-maven-plugin/src/main/java/org/openapitools/codegen/plugin/CodeGenMojo.java b/modules/openapi-generator-maven-plugin/src/main/java/org/openapitools/codegen/plugin/CodeGenMojo.java
index a697be42e32..8949156f4d8 100644
--- a/modules/openapi-generator-maven-plugin/src/main/java/org/openapitools/codegen/plugin/CodeGenMojo.java
+++ b/modules/openapi-generator-maven-plugin/src/main/java/org/openapitools/codegen/plugin/CodeGenMojo.java
@@ -43,6 +43,7 @@ import com.google.common.io.CharSource;
import io.swagger.v3.parser.util.ClasspathHelper;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
@@ -423,6 +424,9 @@ public class CodeGenMojo extends AbstractMojo {
@Parameter(property = "codegen.configHelp")
private boolean configHelp = false;
+ @Parameter(defaultValue = "${mojoExecution}", readonly = true)
+ private MojoExecution mojo;
+
/**
* The project being built.
*/
@@ -847,7 +851,7 @@ public class CodeGenMojo extends AbstractMojo {
name = Files.getNameWithoutExtension(segments[segments.length - 1]);
}
- return new File(output.getPath() + File.separator + ".openapi-generator" + File.separator + name + ".sha256");
+ return new File(output.getPath() + File.separator + ".openapi-generator" + File.separator + name + "-" + mojo.getExecutionId() + ".sha256");
}
private String getCompileSourceRoot() {
diff --git a/modules/openapi-generator-maven-plugin/src/test/java/org/openapitools/codegen/plugin/CodeGenMojoTest.java b/modules/openapi-generator-maven-plugin/src/test/java/org/openapitools/codegen/plugin/CodeGenMojoTest.java
index 521cb8e5efb..ad69be7e720 100644
--- a/modules/openapi-generator-maven-plugin/src/test/java/org/openapitools/codegen/plugin/CodeGenMojoTest.java
+++ b/modules/openapi-generator-maven-plugin/src/test/java/org/openapitools/codegen/plugin/CodeGenMojoTest.java
@@ -16,9 +16,20 @@
package org.openapitools.codegen.plugin;
+import org.apache.commons.io.FileUtils;
+import org.apache.maven.execution.DefaultMavenExecutionRequest;
+import org.apache.maven.execution.MavenExecutionRequest;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.MojoExecution;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.ProjectBuilder;
+import org.apache.maven.project.ProjectBuildingRequest;
+import org.eclipse.aether.DefaultRepositorySystemSession;
import org.openapitools.codegen.plugin.stubs.StubUtility;
import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.Map;
public class CodeGenMojoTest extends BaseTestCase {
@@ -29,8 +40,8 @@ public class CodeGenMojoTest extends BaseTestCase {
@SuppressWarnings("unchecked")
public void testCommonConfiguration() throws Exception {
- File testPom = StubUtility.basedPath(getUnitTestDir().toFile(), "common-maven", "common-maven.xml").toFile();
- final CodeGenMojo mojo = (CodeGenMojo) lookupMojo("generate", testPom);
+ File folder = Files.createTempDirectory("test").toFile();
+ CodeGenMojo mojo = loadMojo(folder, "src/test/resources/default");
mojo.execute();
assertEquals("java", getVariableValueFromObject(mojo, "generatorName"));
assertEquals("jersey2", getVariableValueFromObject(mojo, "library"));
@@ -42,4 +53,49 @@ public class CodeGenMojoTest extends BaseTestCase {
assertNotNull(configOptions);
assertEquals("joda", configOptions.get("dateLibrary"));
}
+
+ public void testHashGenerationFileContainsExecutionId() throws Exception {
+ // GIVEN
+ Path folder = Files.createTempDirectory("test");
+ CodeGenMojo mojo = loadMojo(folder.toFile(), "src/test/resources/default", "executionId");
+
+ // WHEN
+ mojo.execute();
+
+ // THEN
+ Path hashFolder = folder.resolve("target/generated-sources/common-maven/remote-openapi/.openapi-generator");
+ assertTrue(hashFolder.resolve("petstore.yaml-executionId.sha256").toFile().exists());
+ }
+
+ protected CodeGenMojo loadMojo(File temporaryFolder, String projectRoot) throws Exception {
+ return loadMojo(temporaryFolder, projectRoot, "default");
+ }
+
+ protected CodeGenMojo loadMojo(File temporaryFolder, String projectRoot, String executionId) throws Exception {
+ File file = new File(projectRoot);
+ FileUtils.copyDirectory(file, temporaryFolder);
+ MavenProject project = readMavenProject(temporaryFolder);
+ MavenSession session = newMavenSession(project);
+ MojoExecution execution = newMojoExecution("generate");
+ MojoExecution executionWithId = copyWithExecutionId(executionId, execution);
+ return (CodeGenMojo) lookupConfiguredMojo(session, executionWithId);
+ }
+
+ private MojoExecution copyWithExecutionId(String executionId, MojoExecution execution) {
+ MojoExecution executionWithId = new MojoExecution(execution.getMojoDescriptor(), executionId);
+ executionWithId.setConfiguration(execution.getConfiguration());
+ return executionWithId;
+ }
+
+ protected MavenProject readMavenProject(File basedir)
+ throws Exception {
+ File pom = new File(basedir, "pom.xml");
+ MavenExecutionRequest request = new DefaultMavenExecutionRequest();
+ request.setBaseDirectory(basedir);
+ ProjectBuildingRequest configuration = request.getProjectBuildingRequest();
+ configuration.setRepositorySession(new DefaultRepositorySystemSession());
+ MavenProject project = lookup(ProjectBuilder.class).build(pom, configuration).getProject();
+ assertNotNull(project);
+ return project;
+ }
}
\ No newline at end of file
diff --git a/modules/openapi-generator-maven-plugin/src/test/resources/unit/common-maven/petstore.yaml b/modules/openapi-generator-maven-plugin/src/test/resources/default/petstore.yaml
similarity index 100%
rename from modules/openapi-generator-maven-plugin/src/test/resources/unit/common-maven/petstore.yaml
rename to modules/openapi-generator-maven-plugin/src/test/resources/default/petstore.yaml
diff --git a/modules/openapi-generator-maven-plugin/src/test/resources/unit/common-maven/common-maven.xml b/modules/openapi-generator-maven-plugin/src/test/resources/default/pom.xml
similarity index 89%
rename from modules/openapi-generator-maven-plugin/src/test/resources/unit/common-maven/common-maven.xml
rename to modules/openapi-generator-maven-plugin/src/test/resources/default/pom.xml
index 767caeab2dd..95ab2451e5d 100644
--- a/modules/openapi-generator-maven-plugin/src/test/resources/unit/common-maven/common-maven.xml
+++ b/modules/openapi-generator-maven-plugin/src/test/resources/default/pom.xml
@@ -29,8 +29,7 @@
org.openapitools
openapi-generator-maven-plugin
-
- ${basedir}/src/test/resources/unit/common-maven/petstore.yaml
+ ${basedir}/petstore.yaml
java
joda
@@ -43,7 +42,7 @@
- default
+ executionId
generate-sources
generate
diff --git a/modules/openapi-generator-maven-plugin/src/test/resources/unit/common-maven/src/main/java/com/example/Example.java b/modules/openapi-generator-maven-plugin/src/test/resources/default/src/main/java/com/example/Example.java
similarity index 100%
rename from modules/openapi-generator-maven-plugin/src/test/resources/unit/common-maven/src/main/java/com/example/Example.java
rename to modules/openapi-generator-maven-plugin/src/test/resources/default/src/main/java/com/example/Example.java
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java
index 2e7151dc94e..631ff47eedb 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java
@@ -206,7 +206,7 @@ public class CodegenConstants {
public static final String MODEL_PROPERTY_NAMING_DESC = "Naming convention for the property: 'camelCase', 'PascalCase', 'snake_case' and 'original', which keeps the original name";
public static final String DOTNET_FRAMEWORK = "targetFramework";
- public static final String DOTNET_FRAMEWORK_DESC = "The target .NET framework version.";
+ public static final String DOTNET_FRAMEWORK_DESC = "The target .NET framework version. To target multiple frameworks, use `;` as the separator, e.g. `netstandard2.1;netcoreapp3.0`";
public static final String TEMPLATING_ENGINE = "templatingEngine";
public static final String TEMPLATING_ENGINE_DESC = "The templating engine plugin to use: \"mustache\" (default) or \"handlebars\" (beta)";
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenOperation.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenOperation.java
index b41adac4487..0a8e7b31991 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenOperation.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenOperation.java
@@ -29,7 +29,7 @@ public class CodegenOperation {
isArray, isMultipart,
isResponseBinary = false, isResponseFile = false, hasReference = false,
isRestfulIndex, isRestfulShow, isRestfulCreate, isRestfulUpdate, isRestfulDestroy,
- isRestful, isDeprecated, isCallbackRequest, uniqueItems;
+ isRestful, isDeprecated, isCallbackRequest, uniqueItems, hasDefaultResponse = false;
public String path, operationId, returnType, returnFormat, httpMethod, returnBaseType,
returnContainer, summary, unescapedNotes, notes, baseName, defaultResponse;
public CodegenDiscriminator discriminator;
@@ -168,6 +168,15 @@ public class CodegenOperation {
return nonempty(examples);
}
+ /**
+ * Check if there's a default response
+ *
+ * @return true if responses contain a default response, false otherwise
+ */
+ public boolean getHasDefaultResponse() {
+ return responses.stream().filter(response -> response.isDefault).findFirst().isPresent();
+ }
+
/**
* Check if act as Restful index method
*
@@ -270,6 +279,7 @@ public class CodegenOperation {
sb.append(", isResponseBinary=").append(isResponseBinary);
sb.append(", isResponseFile=").append(isResponseFile);
sb.append(", hasReference=").append(hasReference);
+ sb.append(", hasDefaultResponse=").append(hasDefaultResponse);
sb.append(", isRestfulIndex=").append(isRestfulIndex);
sb.append(", isRestfulShow=").append(isRestfulShow);
sb.append(", isRestfulCreate=").append(isRestfulCreate);
@@ -343,6 +353,7 @@ public class CodegenOperation {
isResponseBinary == that.isResponseBinary &&
isResponseFile == that.isResponseFile &&
hasReference == that.hasReference &&
+ hasDefaultResponse == that.hasDefaultResponse &&
isRestfulIndex == that.isRestfulIndex &&
isRestfulShow == that.isRestfulShow &&
isRestfulCreate == that.isRestfulCreate &&
@@ -400,7 +411,7 @@ public class CodegenOperation {
return Objects.hash(responseHeaders, hasAuthMethods, hasConsumes, hasProduces, hasParams, hasOptionalParams,
hasRequiredParams, returnTypeIsPrimitive, returnSimpleType, subresourceOperation, isMap,
- isArray, isMultipart, isResponseBinary, isResponseFile, hasReference, isRestfulIndex,
+ isArray, isMultipart, isResponseBinary, isResponseFile, hasReference, hasDefaultResponse, isRestfulIndex,
isRestfulShow, isRestfulCreate, isRestfulUpdate, isRestfulDestroy, isRestful, isDeprecated,
isCallbackRequest, uniqueItems, path, operationId, returnType, httpMethod, returnBaseType,
returnContainer, summary, unescapedNotes, notes, baseName, defaultResponse, discriminator, consumes,
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenSecurity.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenSecurity.java
index ca659105b7f..a5d5bd4ce85 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenSecurity.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenSecurity.java
@@ -39,7 +39,7 @@ public class CodegenSecurity {
public String keyParamName;
public Boolean isKeyInQuery, isKeyInHeader, isKeyInCookie;
// Oauth specific
- public String flow, authorizationUrl, tokenUrl;
+ public String flow, authorizationUrl, tokenUrl, refreshUrl;
public List> scopes;
public Boolean isCode, isPassword, isApplication, isImplicit;
@@ -66,6 +66,7 @@ public class CodegenSecurity {
filteredSecurity.flow = flow;
filteredSecurity.tokenUrl = tokenUrl;
filteredSecurity.authorizationUrl = authorizationUrl;
+ filteredSecurity.refreshUrl = refreshUrl;
// It is not possible to deep copy the extensions, as we have no idea what types they are.
// So the filtered method *will* refer to the original extensions, if any.
filteredSecurity.vendorExtensions = new HashMap(vendorExtensions);
@@ -109,6 +110,7 @@ public class CodegenSecurity {
Objects.equals(flow, that.flow) &&
Objects.equals(authorizationUrl, that.authorizationUrl) &&
Objects.equals(tokenUrl, that.tokenUrl) &&
+ Objects.equals(refreshUrl, that.refreshUrl) &&
Objects.equals(scopes, that.scopes) &&
Objects.equals(isCode, that.isCode) &&
Objects.equals(isPassword, that.isPassword) &&
@@ -122,7 +124,7 @@ public class CodegenSecurity {
return Objects.hash(name, type, scheme, isBasic, isOAuth, isApiKey,
isBasicBasic, isHttpSignature, isBasicBearer, bearerFormat, vendorExtensions,
keyParamName, isKeyInQuery, isKeyInHeader, isKeyInCookie, flow,
- authorizationUrl, tokenUrl, scopes, isCode, isPassword, isApplication, isImplicit);
+ authorizationUrl, tokenUrl, refreshUrl, scopes, isCode, isPassword, isApplication, isImplicit);
}
@Override
@@ -146,6 +148,7 @@ public class CodegenSecurity {
sb.append(", flow='").append(flow).append('\'');
sb.append(", authorizationUrl='").append(authorizationUrl).append('\'');
sb.append(", tokenUrl='").append(tokenUrl).append('\'');
+ sb.append(", refreshUrl='").append(refreshUrl).append('\'');
sb.append(", scopes=").append(scopes);
sb.append(", isCode=").append(isCode);
sb.append(", isPassword=").append(isPassword);
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java
index 590e925a142..2edf1bf15af 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java
@@ -2043,6 +2043,10 @@ public class DefaultCodegen implements CodegenConfig {
private String getPrimitiveType(Schema schema) {
if (schema == null) {
throw new RuntimeException("schema cannot be null in getPrimitiveType");
+ } else if (typeMapping.containsKey(schema.getType() + "+" + schema.getFormat())) {
+ // allows custom type_format mapping.
+ // use {type}+{format}
+ return typeMapping.get(schema.getType() + "+" + schema.getFormat());
} else if (ModelUtils.isNullType(schema)) {
// 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.
@@ -2702,14 +2706,14 @@ public class DefaultCodegen implements CodegenConfig {
String modelName = ModelUtils.getSimpleRef(oneOf.get$ref());
CodegenProperty thisCp = discriminatorFound(composedSchemaName, oneOf, discPropName, openAPI);
if (thisCp == null) {
- throw new RuntimeException("'" + composedSchemaName + "' defines discriminator '" + discPropName + "', but the referenced OneOf schema '" + modelName + "' is missing " + discPropName);
+ LOGGER.warn("'" + composedSchemaName + "' defines discriminator '" + discPropName + "', but the referenced OneOf schema '" + modelName + "' is missing " + discPropName);
}
if (cp.dataType == null) {
cp = thisCp;
continue;
}
if (cp != thisCp) {
- throw new RuntimeException("'" + composedSchemaName + "' defines discriminator '" + discPropName + "', but the OneOf schema '" + modelName + "' has a different " + discPropName + " definition than the prior OneOf schema's. Make sure the " + discPropName + " type and required values are the same");
+ LOGGER.warn("'" + composedSchemaName + "' defines discriminator '" + discPropName + "', but the OneOf schema '" + modelName + "' has a different " + discPropName + " definition than the prior OneOf schema's. Make sure the " + discPropName + " type and required values are the same");
}
}
return cp;
@@ -2721,14 +2725,14 @@ public class DefaultCodegen implements CodegenConfig {
String modelName = ModelUtils.getSimpleRef(anyOf.get$ref());
CodegenProperty thisCp = discriminatorFound(composedSchemaName, anyOf, discPropName, openAPI);
if (thisCp == null) {
- throw new RuntimeException("'" + composedSchemaName + "' defines discriminator '" + discPropName + "', but the referenced AnyOf schema '" + modelName + "' is missing " + discPropName);
+ LOGGER.warn("'" + composedSchemaName + "' defines discriminator '" + discPropName + "', but the referenced AnyOf schema '" + modelName + "' is missing " + discPropName);
}
if (cp.dataType == null) {
cp = thisCp;
continue;
}
if (cp != thisCp) {
- throw new RuntimeException("'" + composedSchemaName + "' defines discriminator '" + discPropName + "', but the AnyOf schema '" + modelName + "' has a different " + discPropName + " definition than the prior AnyOf schema's. Make sure the " + discPropName + " type and required values are the same");
+ LOGGER.warn("'" + composedSchemaName + "' defines discriminator '" + discPropName + "', but the AnyOf schema '" + modelName + "' has a different " + discPropName + " definition than the prior AnyOf schema's. Make sure the " + discPropName + " type and required values are the same");
}
}
return cp;
@@ -2787,7 +2791,7 @@ public class DefaultCodegen implements CodegenConfig {
}
}
if (discriminatorsPropNames.size() > 1) {
- throw new RuntimeException("The oneOf schemas have conflicting discriminator property names. " +
+ LOGGER.warn("The oneOf schemas have conflicting discriminator property names. " +
"oneOf schemas must have the same property name, but found " + String.join(", ", discriminatorsPropNames));
}
if (foundDisc != null && (hasDiscriminatorCnt + hasNullTypeCnt) == composedSchema.getOneOf().size() && discriminatorsPropNames.size() == 1) {
@@ -2816,7 +2820,7 @@ public class DefaultCodegen implements CodegenConfig {
}
}
if (discriminatorsPropNames.size() > 1) {
- throw new RuntimeException("The anyOf schemas have conflicting discriminator property names. " +
+ LOGGER.warn("The anyOf schemas have conflicting discriminator property names. " +
"anyOf schemas must have the same property name, but found " + String.join(", ", discriminatorsPropNames));
}
if (foundDisc != null && (hasDiscriminatorCnt + hasNullTypeCnt) == composedSchema.getAnyOf().size() && discriminatorsPropNames.size() == 1) {
@@ -2866,7 +2870,7 @@ public class DefaultCodegen implements CodegenConfig {
// schemas also has inline composed schemas
// Note: if it is only inline one level, then the inline model resolver will move it into its own
// schema and make it a $ref schema in the oneOf/anyOf location
- throw new RuntimeException("Invalid inline schema defined in oneOf/anyOf in '" + composedSchemaName + "'. Per the OpenApi spec, for this case when a composed schema defines a discriminator, the oneOf/anyOf schemas must use $ref. Change this inline definition to a $ref definition");
+ LOGGER.warn("Invalid inline schema defined in oneOf/anyOf in '" + composedSchemaName + "'. Per the OpenApi spec, for this case when a composed schema defines a discriminator, the oneOf/anyOf schemas must use $ref. Change this inline definition to a $ref definition");
}
CodegenProperty df = discriminatorFound(composedSchemaName, sc, discPropName, openAPI);
String modelName = ModelUtils.getSimpleRef(ref);
@@ -2886,7 +2890,7 @@ public class DefaultCodegen implements CodegenConfig {
msgSuffix += spacer + "invalid optional definition of " + discPropName + ", include it in required";
}
}
- throw new RuntimeException("'" + composedSchemaName + "' defines discriminator '" + discPropName + "', but the referenced schema '" + modelName + "' is incorrect. " + msgSuffix);
+ LOGGER.warn("'" + composedSchemaName + "' defines discriminator '" + discPropName + "', but the referenced schema '" + modelName + "' is incorrect. " + msgSuffix);
}
MappedModel mm = new MappedModel(modelName, toModelName(modelName));
descendentSchemas.add(mm);
@@ -5599,6 +5603,7 @@ public class DefaultCodegen implements CodegenConfig {
private void setOauth2Info(CodegenSecurity codegenSecurity, OAuthFlow flow) {
codegenSecurity.authorizationUrl = flow.getAuthorizationUrl();
codegenSecurity.tokenUrl = flow.getTokenUrl();
+ codegenSecurity.refreshUrl = flow.getRefreshUrl();
if (flow.getScopes() != null && !flow.getScopes().isEmpty()) {
List> scopes = new ArrayList<>();
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java
index 65c6302987d..6cd5d2926e8 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java
@@ -1,6 +1,7 @@
package org.openapitools.codegen.languages;
import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.ArraySchema;
@@ -51,9 +52,7 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
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 additionalReservedWords;
+ protected Map imports = new HashMap<>();
public AbstractDartCodegen() {
super();
@@ -112,13 +111,13 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
}
setReservedWordsLowerCase(reservedWordsList);
+ // These types return isPrimitive=true in templates
languageSpecificPrimitives = Sets.newHashSet(
"String",
"bool",
"int",
"num",
- "double",
- "dynamic"
+ "double"
);
typeMapping = new HashMap<>();
@@ -149,29 +148,31 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
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.
+ // Data types of the above values which are automatically imported
defaultIncludes = Sets.newHashSet(
"String",
"bool",
"int",
"num",
"double",
- "dynamic",
"List",
"Set",
"Map",
"DateTime",
- "Object",
- "MultipartFile"
+ "Object"
);
- additionalReservedWords = Sets.newHashSet(
- "File",
- "Client",
- "Future",
- "Response"
- );
+ imports.put("String", "dart:core");
+ imports.put("bool", "dart:core");
+ imports.put("int", "dart:core");
+ imports.put("num", "dart:core");
+ imports.put("double", "dart:core");
+ imports.put("List", "dart:core");
+ imports.put("Set", "dart:core");
+ imports.put("Map", "dart:core");
+ imports.put("DateTime", "dart:core");
+ imports.put("Object", "dart:core");
+ imports.put("MultipartFile", "package:http/http.dart");
cliOptions.add(new CliOption(PUB_LIBRARY, "Library name in generated code"));
cliOptions.add(new CliOption(PUB_NAME, "Name in generated pubspec"));
@@ -182,7 +183,6 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
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
@@ -279,13 +279,17 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
}
}
+ @Override
+ protected boolean needToImport(String type) {
+ // Import everything, unless it is from dart:core.
+ return StringUtils.isNotBlank(type) && (!imports.containsKey(type) || !imports.get(type).equals("dart:core"));
+ }
+
@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);
+ return super.isReservedWord(word) || defaultIncludes().contains(word);
}
@Override
@@ -367,20 +371,34 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
@Override
public String toModelName(final String name) {
- String nameWithPrefixSuffix = sanitizeName(name);
+ String sanitizedName = sanitizeName(name);
+
if (!StringUtils.isEmpty(modelNamePrefix)) {
// add '_' so that model name can be camelized correctly
- nameWithPrefixSuffix = modelNamePrefix + "_" + nameWithPrefixSuffix;
+ sanitizedName = modelNamePrefix + "_" + sanitizedName;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
// add '_' so that model name can be camelized correctly
- nameWithPrefixSuffix = nameWithPrefixSuffix + "_" + modelNameSuffix;
+ sanitizedName = sanitizedName + "_" + modelNameSuffix;
}
// camelize the model name
// phone_number => PhoneNumber
- final String camelizedName = camelize(nameWithPrefixSuffix);
+ final String camelizedName = camelize(sanitizedName);
+
+ // Check if there is a mapping that can be used
+ if (typeMapping().containsKey(camelizedName)) {
+ String typeName = typeMapping().get(camelizedName);
+ if (imports.containsKey(typeName)) {
+ // Anything with an import mapping is likely
+ // generator specific and can not be used as model name.
+ final String modelName = "Model" + camelizedName;
+ LOGGER.warn("{} (existing type) cannot be used as model name. Renamed to {}", camelizedName, modelName);
+ return modelName;
+ }
+ return typeName;
+ }
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(camelizedName)) {
@@ -473,11 +491,8 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
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;
+ if (typeMapping().containsKey(openAPIType)) {
+ return typeMapping().get(openAPIType);
}
return toModelName(openAPIType);
}
@@ -607,8 +622,9 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
// operationId starts with a number
if (operationId.matches("^\\d.*")) {
- LOGGER.warn("{} (starting with a number) cannot be used as method name. Renamed to {}", operationId, camelize("call_" + operationId), true);
- operationId = camelize("call_" + operationId, true);
+ String newOperationId = camelize("call_" + operationId, true);
+ LOGGER.warn("{} (starting with a number) cannot be used as method name. Renamed to {}", operationId, newOperationId);
+ operationId = newOperationId;
}
return operationId;
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java
index e45bc2ef3fe..cee83d467c8 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java
@@ -311,16 +311,17 @@ public abstract class AbstractGoCodegen extends DefaultCodegen implements Codege
@Override
public String toApiFilename(String name) {
+ final String apiName;
// replace - with _ e.g. created-at => created_at
- name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
-
+ String api = name.replaceAll("-", "_");
// e.g. PetApi.go => pet_api.go
- name = "api_" + underscore(name);
- if (isReservedFilename(name)) {
- LOGGER.warn(name + ".go with suffix (reserved word) cannot be used as filename. Renamed to " + name + "_.go");
- name += "_";
+ api = "api_" + underscore(api);
+ if (isReservedFilename(api)) {
+ LOGGER.warn(name + ".go with suffix (reserved word) cannot be used as filename. Renamed to " + api + "_.go");
+ api += "_";
}
- return name;
+ apiName = api;
+ return apiName;
}
/**
@@ -807,7 +808,7 @@ public abstract class AbstractGoCodegen extends DefaultCodegen implements Codege
return; // skip if GO_POST_PROCESS_FILE env variable is not defined
}
- // only procees the following type (or we can simply rely on the file extension to check if it's a Go file)
+ // only process the following type (or we can simply rely on the file extension to check if it's a Go file)
Set supportedFileType = new HashSet(
Arrays.asList(
"supporting-mustache",
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpNetCoreClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpNetCoreClientCodegen.java
index be64dde62f1..ff90d1e30e2 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpNetCoreClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpNetCoreClientCodegen.java
@@ -590,38 +590,51 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen {
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;
- for (FrameworkStrategy frameworkStrategy : frameworkStrategies) {
- if (framework.equals(frameworkStrategy.name)) {
- strategy = frameworkStrategy;
- strategyMatched = true;
+ String inputFramework = (String) additionalProperties.getOrDefault(CodegenConstants.DOTNET_FRAMEWORK, defaultFramework.name);
+ String[] frameworks;
+ List strategies = new ArrayList<>();
+
+ if (inputFramework.contains(";")) {
+ // multiple target framework
+ frameworks = inputFramework.split(";");
+ additionalProperties.put("multiTarget", true);
+ } else {
+ // just a single value
+ frameworks = new String [] {inputFramework};
+ }
+
+ for (String framework : frameworks) {
+ boolean strategyMatched = false;
+ for (FrameworkStrategy frameworkStrategy : frameworkStrategies) {
+ if (framework.equals(frameworkStrategy.name)) {
+ strategies.add(frameworkStrategy);
+ strategyMatched = true;
+ }
+
+ if (frameworkStrategy != FrameworkStrategy.NETSTANDARD_2_0 && "restsharp".equals(getLibrary())) {
+ LOGGER.warn("If using built-in templates, RestSharp only supports netstandard 2.0 or later.");
+ }
+ }
+
+ if (!strategyMatched) {
+ // throws exception if the input targetFramework is invalid
+ throw new IllegalArgumentException("The input (" + inputFramework + ") contains Invalid .NET framework version: " +
+ framework + ". List of supported versions: " +
+ frameworkStrategies.stream()
+ .map(p -> p.name)
+ .collect(Collectors.joining(", ")));
}
}
- // throws exception if the input targetFramework is invalid
- if (strategyMatched == false) {
- throw new IllegalArgumentException("Invalid .NET framework version: " +
- framework + ". List of supported versions: " +
- frameworkStrategies.stream()
- .map(p -> p.name)
- .collect(Collectors.joining(", ")));
- }
-
- strategy.configureAdditionalProperties(additionalProperties);
- setTargetFrameworkNuget(strategy.getNugetFrameworkIdentifier());
- setTargetFramework(strategy.name);
- setTestTargetFramework(strategy.testTargetFramework);
-
- if (strategy != FrameworkStrategy.NETSTANDARD_2_0) {
- LOGGER.warn("If using built-in templates-RestSharp only supports netstandard 2.0 or later.");
- }
+ configureAdditionalPropertiesForFrameworks(additionalProperties, strategies);
+ setTargetFrameworkNuget(strategies);
+ setTargetFramework(strategies);
+ setTestTargetFramework(strategies);
setSupportsAsync(Boolean.TRUE);
- setNetStandard(strategy.isNetStandard);
+ setNetStandard(strategies.stream().anyMatch(p -> Boolean.TRUE.equals(p.isNetStandard)));
- if (!strategy.isNetStandard) {
+ if (!netStandard) {
setNetCoreProjectFileFlag(true);
}
@@ -774,14 +787,39 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen {
LOGGER.info("Generating code for .NET Framework " + this.targetFramework);
}
+ public void setTargetFramework(List strategies) {
+ for (FrameworkStrategy strategy : strategies) {
+ if (!frameworks.containsKey(strategy.name)) {
+ throw new IllegalArgumentException("Invalid .NET framework version: " +
+ strategy.name + ". List of supported versions: " +
+ frameworkStrategies.stream()
+ .map(p -> p.name)
+ .collect(Collectors.joining(", ")));
+ }
+ }
+ this.targetFramework = strategies.stream().map(p -> p.name)
+ .collect(Collectors.joining(";"));
+ LOGGER.info("Generating code for .NET Framework " + this.targetFramework);
+ }
+
public void setTestTargetFramework(String testTargetFramework) {
this.testTargetFramework = testTargetFramework;
}
+ public void setTestTargetFramework(List strategies) {
+ this.testTargetFramework = strategies.stream().map(p -> p.testTargetFramework)
+ .collect(Collectors.joining(";"));
+ }
+
public void setTargetFrameworkNuget(String targetFrameworkNuget) {
this.targetFrameworkNuget = targetFrameworkNuget;
}
+ public void setTargetFrameworkNuget(List strategies) {
+ this.targetFrameworkNuget = strategies.stream().map(p -> p.getNugetFrameworkIdentifier())
+ .collect(Collectors.joining(";"));
+ }
+
public void setValidatable(boolean validatable) {
this.validatable = validatable;
}
@@ -1003,6 +1041,23 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen {
}
}
+ protected void configureAdditionalPropertiesForFrameworks(final Map properties, List strategies) {
+ properties.putIfAbsent(CodegenConstants.DOTNET_FRAMEWORK, strategies.stream()
+ .map(p -> p.name)
+ .collect(Collectors.joining(";")));
+
+ // not intended to be user-settable
+ properties.put(TARGET_FRAMEWORK_IDENTIFIER, strategies.stream()
+ .map(p -> p.getTargetFrameworkIdentifier())
+ .collect(Collectors.joining(";")));
+ properties.put(TARGET_FRAMEWORK_VERSION, strategies.stream()
+ .map(p -> p.getTargetFrameworkVersion())
+ .collect(Collectors.joining(";")));
+ properties.putIfAbsent(MCS_NET_VERSION_KEY, "4.6-api");
+
+ properties.put(NET_STANDARD, strategies.stream().anyMatch(p -> Boolean.TRUE.equals(p.isNetStandard)));
+ }
+
/**
* Return the instantiation type of the property, especially for map and array
*
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartClientCodegen.java
index 59578099cce..589ef137f34 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartClientCodegen.java
@@ -37,20 +37,6 @@ public class DartClientCodegen extends AbstractDartCodegen {
public DartClientCodegen() {
super();
-
- additionalReservedWords.addAll(
- Sets.newHashSet(
- "StreamedRequest",
- "ApiClient",
- "QueryParam",
- "Authentication",
- "HttpBasicAuth",
- "HttpBearerAuth",
- "ApiKeyAuth",
- "OAuth"
- )
- );
-
final CliOption serializationLibrary = CliOption.newString(CodegenConstants.SERIALIZATION_LIBRARY,
"Specify serialization library");
serializationLibrary.setDefault(SERIALIZATION_LIBRARY_NATIVE);
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java
index a0bafd5e8ac..23b50b2f756 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java
@@ -30,6 +30,7 @@ import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.*;
+import java.util.stream.Collectors;
import static org.openapitools.codegen.utils.StringUtils.underscore;
@@ -77,22 +78,11 @@ public class DartDioClientCodegen extends AbstractDartCodegen {
typeMapping.put("object", "JsonObject");
typeMapping.put("AnyType", "JsonObject");
- additionalReservedWords.addAll(Sets.newHashSet(
- "EnumClass",
- // The following are reserved dataTypes but can not be added to defaultIncludes
- // as this would prevent them from being added to the imports.
- "BuiltList",
- "BuiltSet",
- "BuiltMap",
- "Uint8List",
- "JsonObject"
- ));
-
- importMapping.put("BuiltList", "package:built_collection/built_collection.dart");
- importMapping.put("BuiltSet", "package:built_collection/built_collection.dart");
- importMapping.put("BuiltMap", "package:built_collection/built_collection.dart");
- importMapping.put("JsonObject", "package:built_value/json_object.dart");
- importMapping.put("Uint8List", "dart:typed_data");
+ imports.put("BuiltList", "package:built_collection/built_collection.dart");
+ imports.put("BuiltSet", "package:built_collection/built_collection.dart");
+ imports.put("BuiltMap", "package:built_collection/built_collection.dart");
+ imports.put("JsonObject", "package:built_value/json_object.dart");
+ imports.put("Uint8List", "dart:typed_data");
}
public String getDateLibrary() {
@@ -210,9 +200,8 @@ public class DartDioClientCodegen extends AbstractDartCodegen {
typeMapping.put("Date", "OffsetDate");
typeMapping.put("DateTime", "OffsetDateTime");
typeMapping.put("datetime", "OffsetDateTime");
- additionalReservedWords.addAll(Sets.newHashSet("OffsetDate", "OffsetDateTime"));
- importMapping.put("OffsetDate", "package:time_machine/time_machine.dart");
- importMapping.put("OffsetDateTime", "package:time_machine/time_machine.dart");
+ imports.put("OffsetDate", "package:time_machine/time_machine.dart");
+ imports.put("OffsetDateTime", "package:time_machine/time_machine.dart");
supportingFiles.add(new SupportingFile("local_date_serializer.mustache", libFolder, "local_date_serializer.dart"));
}
}
@@ -225,21 +214,9 @@ public class DartDioClientCodegen extends AbstractDartCodegen {
for (Object _mo : models) {
Map mo = (Map) _mo;
- Set modelImports = new HashSet<>();
CodegenModel cm = (CodegenModel) mo.get("model");
- for (String modelImport : cm.imports) {
- if (needToImport(modelImport)) {
- if (importMapping().containsKey(modelImport)) {
- modelImports.add(importMapping().get(modelImport));
- } else {
- modelImports.add("package:" + pubName + "/model/" + underscore(modelImport) + ".dart");
- }
- }
- }
-
- cm.imports = modelImports;
- boolean hasVars = cm.vars.size() > 0;
- cm.vendorExtensions.put("x-has-vars", hasVars);
+ cm.imports = rewriteImports(cm.imports);
+ cm.vendorExtensions.put("x-has-vars", !cm.vars.isEmpty());
}
return objs;
}
@@ -292,8 +269,7 @@ public class DartDioClientCodegen extends AbstractDartCodegen {
List operationList = (List) operations.get("operation");
Set> serializers = new HashSet<>();
- Set modelImports = new HashSet<>();
- Set fullImports = new HashSet<>();
+ Set resultImports = new HashSet<>();
for (CodegenOperation op : operationList) {
op.httpMethod = op.httpMethod.toLowerCase(Locale.ROOT);
@@ -331,23 +307,11 @@ public class DartDioClientCodegen extends AbstractDartCodegen {
op.vendorExtensions.put("x-is-form", isForm);
op.vendorExtensions.put("x-is-multipart", isMultipart);
+ resultImports.addAll(rewriteImports(op.imports));
if (op.getHasFormParams()) {
- fullImports.add("package:" + pubName + "/api_util.dart");
+ resultImports.add("package:" + pubName + "/api_util.dart");
}
- Set imports = new HashSet<>();
- for (String item : op.imports) {
- if (needToImport(item)) {
- if (importMapping().containsKey(item)) {
- fullImports.add(importMapping().get(item));
- } else {
- imports.add(underscore(item));
- }
- }
- }
- modelImports.addAll(imports);
- op.imports = imports;
-
if (op.returnContainer != null) {
final Map serializer = new HashMap<>();
serializer.put("isArray", Objects.equals("array", op.returnContainer) || Objects.equals("set", op.returnContainer));
@@ -358,11 +322,21 @@ public class DartDioClientCodegen extends AbstractDartCodegen {
}
}
- objs.put("modelImports", modelImports);
- objs.put("fullImports", fullImports);
+ objs.put("imports", resultImports.stream().sorted().collect(Collectors.toList()));
objs.put("serializers", serializers);
return objs;
}
+ private Set rewriteImports(Set originalImports) {
+ Set resultImports = Sets.newHashSet();
+ for (String modelImport : originalImports) {
+ if (imports.containsKey(modelImport)) {
+ resultImports.add(imports.get(modelImport));
+ } else {
+ resultImports.add("package:" + pubName + "/model/" + underscore(modelImport) + ".dart");
+ }
+ }
+ return resultImports;
+ }
}
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioNextClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioNextClientCodegen.java
index 7034bc4bece..764c1146426 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioNextClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioNextClientCodegen.java
@@ -30,6 +30,7 @@ import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.*;
+import java.util.stream.Collectors;
import static org.openapitools.codegen.utils.StringUtils.underscore;
@@ -186,22 +187,11 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen {
typeMapping.put("object", "JsonObject");
typeMapping.put("AnyType", "JsonObject");
- additionalReservedWords.addAll(Sets.newHashSet(
- "EnumClass",
- // The following are reserved dataTypes but can not be added to defaultIncludes
- // as this would prevent them from being added to the imports.
- "BuiltList",
- "BuiltSet",
- "BuiltMap",
- "Uint8List",
- "JsonObject"
- ));
-
- importMapping.put("BuiltList", "package:built_collection/built_collection.dart");
- importMapping.put("BuiltSet", "package:built_collection/built_collection.dart");
- importMapping.put("BuiltMap", "package:built_collection/built_collection.dart");
- importMapping.put("JsonObject", "package:built_value/json_object.dart");
- importMapping.put("Uint8List", "dart:typed_data");
+ imports.put("BuiltList", "package:built_collection/built_collection.dart");
+ imports.put("BuiltSet", "package:built_collection/built_collection.dart");
+ imports.put("BuiltMap", "package:built_collection/built_collection.dart");
+ imports.put("JsonObject", "package:built_value/json_object.dart");
+ imports.put("Uint8List", "dart:typed_data");
}
private void configureDateLibrary(String srcFolder) {
@@ -212,17 +202,22 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen {
typeMapping.put("Date", "OffsetDate");
typeMapping.put("DateTime", "OffsetDateTime");
typeMapping.put("datetime", "OffsetDateTime");
- additionalReservedWords.addAll(Sets.newHashSet("OffsetDate", "OffsetDateTime"));
- importMapping.put("OffsetDate", "package:time_machine/time_machine.dart");
- importMapping.put("OffsetDateTime", "package:time_machine/time_machine.dart");
+ imports.put("OffsetDate", "package:time_machine/time_machine.dart");
+ imports.put("OffsetDateTime", "package:time_machine/time_machine.dart");
if (SERIALIZATION_LIBRARY_BUILT_VALUE.equals(library)) {
- supportingFiles.add(new SupportingFile("serialization/built_value/local_date_serializer.mustache", srcFolder, "local_date_serializer.dart"));
+ supportingFiles.add(new SupportingFile("serialization/built_value/offset_date_serializer.mustache", srcFolder, "local_date_serializer.dart"));
}
break;
default:
case DATE_LIBRARY_CORE:
- // this option uses the dart core classes
additionalProperties.put("useDateLibCore", "true");
+ if (SERIALIZATION_LIBRARY_BUILT_VALUE.equals(library)) {
+ typeMapping.put("date", "Date");
+ typeMapping.put("Date", "Date");
+ importMapping.put("Date", "package:" + pubName + "/src/model/date.dart");
+ supportingFiles.add(new SupportingFile("serialization/built_value/date.mustache", srcFolder + File.separator + "model", "date.dart"));
+ supportingFiles.add(new SupportingFile("serialization/built_value/date_serializer.mustache", srcFolder, "date_serializer.dart"));
+ }
break;
}
}
@@ -261,21 +256,9 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen {
for (Object _mo : models) {
Map mo = (Map) _mo;
- Set modelImports = new HashSet<>();
CodegenModel cm = (CodegenModel) mo.get("model");
- for (String modelImport : cm.imports) {
- if (needToImport(modelImport)) {
- if (importMapping().containsKey(modelImport)) {
- modelImports.add(importMapping().get(modelImport));
- } else {
- modelImports.add("package:" + pubName + "/src/model/" + underscore(modelImport) + ".dart");
- }
- }
- }
-
- cm.imports = modelImports;
- boolean hasVars = cm.vars.size() > 0;
- cm.vendorExtensions.put("x-has-vars", hasVars);
+ cm.imports = rewriteImports(cm.imports);
+ cm.vendorExtensions.put("x-has-vars", !cm.vars.isEmpty());
}
return objs;
}
@@ -319,6 +302,7 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen {
sb.append(")]");
}
+
@Override
public Map postProcessOperationsWithModels(Map objs, List allModels) {
objs = super.postProcessOperationsWithModels(objs, allModels);
@@ -326,8 +310,7 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen {
List operationList = (List) operations.get("operation");
Set> serializers = new HashSet<>();
- Set modelImports = new HashSet<>();
- Set fullImports = new HashSet<>();
+ Set resultImports = new HashSet<>();
for (CodegenOperation op : operationList) {
op.httpMethod = op.httpMethod.toLowerCase(Locale.ROOT);
@@ -365,23 +348,11 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen {
op.vendorExtensions.put("x-is-form", isForm);
op.vendorExtensions.put("x-is-multipart", isMultipart);
+ resultImports.addAll(rewriteImports(op.imports));
if (op.getHasFormParams()) {
- fullImports.add("package:" + pubName + "/src/api_util.dart");
+ resultImports.add("package:" + pubName + "/src/api_util.dart");
}
- Set imports = new HashSet<>();
- for (String item : op.imports) {
- if (needToImport(item)) {
- if (importMapping().containsKey(item)) {
- fullImports.add(importMapping().get(item));
- } else {
- imports.add(underscore(item));
- }
- }
- }
- modelImports.addAll(imports);
- op.imports = imports;
-
if (op.returnContainer != null) {
final Map serializer = new HashMap<>();
serializer.put("isArray", Objects.equals("array", op.returnContainer) || Objects.equals("set", op.returnContainer));
@@ -392,11 +363,21 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen {
}
}
- objs.put("modelImports", modelImports);
- objs.put("fullImports", fullImports);
+ objs.put("imports", resultImports.stream().sorted().collect(Collectors.toList()));
objs.put("serializers", serializers);
return objs;
}
+ private Set rewriteImports(Set originalImports) {
+ Set resultImports = Sets.newHashSet();
+ for (String modelImport : originalImports) {
+ if (imports.containsKey(modelImport)) {
+ resultImports.add(imports.get(modelImport));
+ } else {
+ resultImports.add("package:" + pubName + "/src/model/" + underscore(modelImport) + ".dart");
+ }
+ }
+ return resultImports;
+ }
}
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/FsharpGiraffeServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/FsharpGiraffeServerCodegen.java
index d8d4f7fa3df..b62591c1d0e 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/FsharpGiraffeServerCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/FsharpGiraffeServerCodegen.java
@@ -280,4 +280,17 @@ public class FsharpGiraffeServerCodegen extends AbstractFSharpCodegen {
public String toRegularExpression(String pattern) {
return escapeText(pattern);
}
-}
\ No newline at end of file
+
+ @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 Nick Fisher (https://github.com/nmfisher) #");
+ System.out.println("# Please support his work directly via https://paypal.me/nickfisher1984 \uD83D\uDE4F #");
+ System.out.println("################################################################################");
+ }
+
+}
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoEchoServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoEchoServerCodegen.java
new file mode 100644
index 00000000000..3bd2a37a5e5
--- /dev/null
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoEchoServerCodegen.java
@@ -0,0 +1,184 @@
+/*
+ * 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 org.openapitools.codegen.*;
+
+import java.io.File;
+import java.util.*;
+
+import org.openapitools.codegen.meta.features.*;
+import org.openapitools.codegen.meta.GeneratorMetadata;
+import org.openapitools.codegen.meta.Stability;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GoEchoServerCodegen extends AbstractGoCodegen {
+ static final Logger LOGGER = LoggerFactory.getLogger(GoEchoServerCodegen.class);
+
+ protected String apiVersion = "1.0.0";
+ protected int serverPort = 8080;
+ protected String projectName = "openapi-go-echo-server";
+ protected String apiPath = "go";
+
+ private static final String MODEL_PACKAGE_NAME = "models";
+ private static final String API_PACKAGE_NAME = "handlers";
+ private static final String OUTPUT_PATH = "generated-code" + File.separator + "go-echo-server";
+
+ public CodegenType getTag() {
+ return CodegenType.SERVER;
+ }
+
+ public String getName() {
+ return "go-echo-server";
+ }
+
+ public String getHelp() {
+ return "Generates a go-echo server. (Beta)";
+ }
+
+ public GoEchoServerCodegen() {
+ super();
+
+ generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
+ .stability(Stability.BETA)
+ .build();
+
+ modifyFeatureSet(features -> features
+ .includeDocumentationFeatures(DocumentationFeature.Readme)
+ .wireFormatFeatures(EnumSet.of(WireFormatFeature.JSON, WireFormatFeature.XML))
+ .securityFeatures(EnumSet.noneOf(
+ SecurityFeature.class
+ ))
+ .excludeGlobalFeatures(
+ GlobalFeature.XMLStructureDefinitions,
+ GlobalFeature.Callbacks,
+ GlobalFeature.LinkObjects,
+ GlobalFeature.ParameterStyling
+ )
+ .excludeSchemaSupportFeatures(
+ SchemaSupportFeature.Polymorphism
+ )
+ .excludeParameterFeatures(
+ ParameterFeature.Cookie
+ )
+ );
+
+ outputFolder = OUTPUT_PATH;
+ modelTemplateFiles.put("model.mustache", ".go");
+ setModelPackage(MODEL_PACKAGE_NAME);
+ apiTemplateFiles.put("api.mustache", ".go");
+ embeddedTemplateDir = templateDir = "go-echo-server";
+
+ /*
+ * Reserved words. Override this with reserved words specific to your language
+ */
+ setReservedWordsLowerCase(
+ Arrays.asList(
+ // data type
+ "string", "bool", "uint", "uint8", "uint16", "uint32", "uint64",
+ "int", "int8", "int16", "int32", "int64", "float32", "float64",
+ "complex64", "complex128", "rune", "byte", "uintptr",
+ "break", "default", "func", "interface", "select",
+ "case", "defer", "go", "map", "struct",
+ "chan", "else", "goto", "package", "switch",
+ "const", "fallthrough", "if", "range", "type",
+ "continue", "for", "import", "return", "var", "error", "nil")
+ // Added "error" as it's used so frequently that it may as well be a keyword
+ );
+
+ CliOption optServerPort = new CliOption("serverPort", "The network port the generated server binds to");
+ optServerPort.setType("int");
+ optServerPort.defaultValue(Integer.toString(serverPort));
+ cliOptions.add(optServerPort);
+ }
+
+ @Override
+ public Map postProcessOperationsWithModels(Map objs, List allModels) {
+ objs = super.postProcessOperationsWithModels(objs, allModels);
+
+ Map operations = (Map) objs.get("operations");
+ List operationList = (List) operations.get("operation");
+ for (CodegenOperation op : operationList) {
+ if (op.path != null) {
+ op.path = op.path.replaceAll("\\{(.*?)\\}", ":$1");
+ }
+ }
+ return objs;
+ }
+
+ @Override
+ public void processOpts() {
+ super.processOpts();
+
+ if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
+ setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
+ } else {
+ setPackageName("openapi");
+ additionalProperties.put(CodegenConstants.PACKAGE_NAME, this.packageName);
+ }
+
+ /*
+ * Additional Properties. These values can be passed to the templates and
+ * are available in models, apis, and supporting files
+ */
+ if (additionalProperties.containsKey("apiVersion")) {
+ this.apiVersion = (String) additionalProperties.get("apiVersion");
+ } else {
+ additionalProperties.put("apiVersion", apiVersion);
+ }
+
+ if (additionalProperties.containsKey("serverPort")) {
+ this.serverPort = Integer.parseInt((String) additionalProperties.get("serverPort"));
+ } else {
+ additionalProperties.put("serverPort", serverPort);
+ }
+
+ if (additionalProperties.containsKey("apiPath")) {
+ this.apiPath = (String) additionalProperties.get("apiPath");
+ } else {
+ 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);
+ }
+ }
+
+ /*
+ set model and package names, this is mainly used inside the templates.
+ */
+ modelPackage = MODEL_PACKAGE_NAME;
+ apiPackage = API_PACKAGE_NAME;
+
+ /*
+ * Supporting Files. You can write single files for the generator with the
+ * entire object tree available. If the input file has a suffix of `.mustache
+ * it will be processed by the template engine. Otherwise, it will be copied
+ */
+ supportingFiles.add(new SupportingFile("openapi.mustache", ".docs/api", "openapi.yaml"));
+ supportingFiles.add(new SupportingFile("hello-world.mustache", "models", "hello-world.go"));
+ supportingFiles.add(new SupportingFile("go-mod.mustache", "", "go.mod"));
+ supportingFiles.add(new SupportingFile("handler-container.mustache", "handlers", "container.go"));
+ supportingFiles.add(new SupportingFile("main.mustache", "", "main.go"));
+ supportingFiles.add(new SupportingFile("Dockerfile.mustache", "", "Dockerfile"));
+ supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")
+ .doNotOverwrite());
+ }
+}
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoServerCodegen.java
index 2e08cb6f39d..a0f76b8c299 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoServerCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoServerCodegen.java
@@ -37,6 +37,7 @@ public class GoServerCodegen extends AbstractGoCodegen {
protected String projectName = "openapi-server";
protected String sourceFolder = "go";
protected Boolean corsFeatureEnabled = false;
+ protected Boolean addResponseHeaders = false;
public GoServerCodegen() {
@@ -80,6 +81,12 @@ public class GoServerCodegen extends AbstractGoCodegen {
cliOptions.add(CliOption.newBoolean(CodegenConstants.ENUM_CLASS_PREFIX, CodegenConstants.ENUM_CLASS_PREFIX_DESC));
+ // option to include headers in the response
+ CliOption optAddResponseHeaders = new CliOption("addResponseHeaders", "To include response headers in ImplResponse");
+ optAddResponseHeaders.setType("bool");
+ optAddResponseHeaders.defaultValue(addResponseHeaders.toString());
+ cliOptions.add(optAddResponseHeaders);
+
/*
* Models. You can write model files using the modelTemplateFiles map.
* if you want to create one template for file, you can do so here.
@@ -172,12 +179,19 @@ public class GoServerCodegen extends AbstractGoCodegen {
} else {
additionalProperties.put("serverPort", serverPort);
}
+
if (additionalProperties.containsKey("featureCORS")) {
this.setFeatureCORS(convertPropertyToBooleanAndWriteBack("featureCORS"));
} else {
additionalProperties.put("featureCORS", corsFeatureEnabled);
}
+ if (additionalProperties.containsKey("addResponseHeaders")) {
+ this.setAddResponseHeaders(convertPropertyToBooleanAndWriteBack("addResponseHeaders"));
+ } else {
+ additionalProperties.put("addResponseHeaders", addResponseHeaders);
+ }
+
if (additionalProperties.containsKey(CodegenConstants.ENUM_CLASS_PREFIX)) {
setEnumClassPrefix(Boolean.parseBoolean(additionalProperties.get(CodegenConstants.ENUM_CLASS_PREFIX).toString()));
if (enumClassPrefix) {
@@ -221,10 +235,8 @@ public class GoServerCodegen extends AbstractGoCodegen {
// override imports to only include packages for interface parameters
imports.clear();
- boolean addedOptionalImport = false;
boolean addedTimeImport = false;
boolean addedOSImport = false;
- boolean addedReflectImport = false;
for (CodegenOperation operation : operations) {
for (CodegenParameter param : operation.allParams) {
// import "os" if the operation uses files
@@ -233,7 +245,7 @@ public class GoServerCodegen extends AbstractGoCodegen {
addedOSImport = true;
}
- // import "time" if the operation has a required time parameter.
+ // import "time" if the operation has a required time parameter
if (param.required) {
if (!addedTimeImport && "time.Time".equals(param.dataType)) {
imports.add(createMapping("import", "time"));
@@ -314,4 +326,8 @@ public class GoServerCodegen extends AbstractGoCodegen {
public void setFeatureCORS(Boolean featureCORS) {
this.corsFeatureEnabled = featureCORS;
}
+
+ public void setAddResponseHeaders(Boolean addResponseHeaders) {
+ this.addResponseHeaders = addResponseHeaders;
+ }
}
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinClientCodegen.java
index 17afe550c70..72646d58cd7 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinClientCodegen.java
@@ -17,6 +17,8 @@
package org.openapitools.codegen.languages;
+import static java.util.Collections.sort;
+
import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.CodegenConstants;
@@ -463,6 +465,8 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
supportingFiles.add(new SupportingFile("jvm-common/infrastructure/LocalDateAdapter.kt.mustache", infrastructureFolder, "LocalDateAdapter.kt"));
supportingFiles.add(new SupportingFile("jvm-common/infrastructure/LocalDateTimeAdapter.kt.mustache", infrastructureFolder, "LocalDateTimeAdapter.kt"));
supportingFiles.add(new SupportingFile("jvm-common/infrastructure/OffsetDateTimeAdapter.kt.mustache", infrastructureFolder, "OffsetDateTimeAdapter.kt"));
+ supportingFiles.add(new SupportingFile("jvm-common/infrastructure/BigDecimalAdapter.kt.mustache", infrastructureFolder, "BigDecimalAdapter.kt"));
+ supportingFiles.add(new SupportingFile("jvm-common/infrastructure/BigIntegerAdapter.kt.mustache", infrastructureFolder, "BigIntegerAdapter.kt"));
break;
case gson:
@@ -654,6 +658,20 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
operation.path = operation.path.substring(1);
}
+ // sorting operation parameters to make sure path params are parsed before query params
+ if (operation.allParams != null) {
+ sort(operation.allParams, (one, another) -> {
+ if (one.isPathParam && another.isQueryParam) {
+ return -1;
+ }
+ if (one.isQueryParam && another.isPathParam){
+ return 1;
+ }
+
+ return 0;
+ });
+ }
+
// modify the data type of binary form parameters to a more friendly type for multiplatform builds
if (MULTIPLATFORM.equals(getLibrary()) && operation.allParams != null) {
for (CodegenParameter param : operation.allParams) {
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java
index cf3c64b0338..cdaae2afe67 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java
@@ -540,8 +540,10 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
.filter(cm -> Boolean.TRUE.equals(cm.isEnum) && cm.allowableValues != null)
.forEach(cm -> {
cm.imports.add(importMapping.get("JsonValue"));
+ cm.imports.add(importMapping.get("JsonProperty"));
Map item = new HashMap<>();
item.put("import", importMapping.get("JsonValue"));
+ item.put("import", importMapping.get("JsonProperty"));
imports.add(item);
});
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/NimClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/NimClientCodegen.java
index 02e4f1b701c..ff07db2ede8 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/NimClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/NimClientCodegen.java
@@ -31,6 +31,8 @@ import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.*;
+import static org.openapitools.codegen.utils.StringUtils.camelize;
+
public class NimClientCodegen extends DefaultCodegen implements CodegenConfig {
final Logger LOGGER = LoggerFactory.getLogger(NimClientCodegen.class);
@@ -297,14 +299,32 @@ public class NimClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String toVarName(String name) {
- if (isReservedWord(name)) {
- name = escapeReservedWord(name);
+ // sanitize name
+ name = sanitizeName(name, "\\W-[\\$]"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
+
+ if ("_".equals(name)) {
+ name = "_u";
}
+ // numbers are not allowed at the beginning
if (name.matches("^\\d.*")) {
name = "`" + name + "`";
}
+ // if it's all uppper case, do nothing
+ if (name.matches("^[A-Z0-9_]*$")) {
+ return name;
+ }
+
+ // camelize (lower first character) the variable name
+ // pet_id => petId
+ name = camelize(name, true);
+
+ // for reserved word or word starting with number, append _
+ if (isReservedWord(name)) {
+ name = escapeReservedWord(name);
+ }
+
return name;
}
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSymfonyServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSymfonyServerCodegen.java
index 9d468195f85..f3324629b45 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSymfonyServerCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSymfonyServerCodegen.java
@@ -416,20 +416,12 @@ public class PhpSymfonyServerCodegen extends AbstractPhpCodegen implements Codeg
if (param.isContainer) {
param.vendorExtensions.put("x-comment-type", param.dataType + "[]");
}
-
- // Quote default values for strings
- // @todo: The default values for headers, forms and query params are handled
- // in DefaultCodegen fromParameter with no real possibility to override
- // the functionality. Thus we are handling quoting of string values here
- if ("string".equals(param.dataType) && param.defaultValue != null && !param.defaultValue.isEmpty()) {
- param.defaultValue = "'" + param.defaultValue + "'";
- }
}
// Create a variable to display the correct return type in comments for interfaces
if (op.returnType != null) {
op.vendorExtensions.put("x-comment-type", op.returnType);
- if (op.returnContainer != null && "array".equals(op.returnContainer)) {
+ if ("array".equals(op.returnContainer)) {
op.vendorExtensions.put("x-comment-type", op.returnType + "[]");
}
} else {
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java
index fce3591fe57..a00683cbd4a 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java
@@ -1323,6 +1323,23 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
for (Map.Entry entry : requiredAndOptionalProps.entrySet()) {
String propName = entry.getKey();
Schema propSchema = entry.getValue();
+ boolean readOnly = false;
+ if (propSchema.getReadOnly() != null) {
+ readOnly = propSchema.getReadOnly();
+ }
+ if (readOnly) {
+ continue;
+ }
+ String ref = propSchema.get$ref();
+ if (ref != null) {
+ Schema refSchema = ModelUtils.getSchema(this.openAPI, ModelUtils.getSimpleRef(ref));
+ if (refSchema.getReadOnly() != null) {
+ readOnly = refSchema.getReadOnly();
+ }
+ if (readOnly) {
+ continue;
+ }
+ }
propName = toVarName(propName);
String propModelName = null;
Object propExample = null;
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubyClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubyClientCodegen.java
index 40b2d9c22ee..96a5f5d7c3f 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubyClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubyClientCodegen.java
@@ -748,8 +748,14 @@ public class RubyClientCodegen extends AbstractRubyCodegen {
return moduleName + "::" + codegenModel.classname + "::" + enumVars.get(0).get("name");
} else if (codegenModel.oneOf != null && !codegenModel.oneOf.isEmpty()) {
String subModel = (String) codegenModel.oneOf.toArray()[0];
- String oneOf = constructExampleCode(modelMaps.get(subModel), modelMaps, processedModelMap);
- return oneOf;
+ if (modelMaps.containsKey(subModel)) {
+ // oneOf models
+ return constructExampleCode(modelMaps.get(subModel), modelMaps, processedModelMap);
+ } else {
+ // TODO oneOf primitive type not supported at the moment
+ LOGGER.warn("oneOf example value not supported at the moment.");
+ return "nil";
+ }
} else {
processedModelMap.put(model, 1);
}
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubySinatraServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubySinatraServerCodegen.java
index 12f8f9a2a70..c81426eb017 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubySinatraServerCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubySinatraServerCodegen.java
@@ -87,6 +87,7 @@ public class RubySinatraServerCodegen extends AbstractRubyCodegen {
supportingFiles.add(new SupportingFile("Gemfile", "", "Gemfile"));
supportingFiles.add(new SupportingFile("README.md", "", "README.md"));
supportingFiles.add(new SupportingFile("openapi.mustache", "", "openapi.yaml"));
+ supportingFiles.add(new SupportingFile("Dockerfile", "", "Dockerfile"));
}
@Override
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java
index 5ff03773da1..a47e86573fb 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java
@@ -1560,12 +1560,12 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig {
LOGGER.trace("Post processing model: {}", cm);
- if (cm.dataType != null && "object".equals(cm.dataType)) {
+ if ("object".equals(cm.dataType)) {
// Object isn't a sensible default. Instead, we set it to
// 'null'. This ensures that we treat this model as a struct
// with multiple parameters.
cm.dataType = null;
- } else if (cm.dataType != null && "map".equals(cm.dataType)) {
+ } else if ("map".equals(cm.dataType)) {
if (!cm.allVars.isEmpty() || cm.additionalPropertiesType == null) {
// We don't yet support `additionalProperties` that also have
// properties. If we see variables, we ignore the
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java
index 058acbed956..4c4f0e19496 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java
@@ -336,8 +336,8 @@ public class SpringCodegen extends AbstractJavaCodegen
}
additionalProperties.put(UNHANDLED_EXCEPTION_HANDLING, this.isUnhandledException());
- typeMapping.put("file", "org.springframework.core.io.Resource");
- importMapping.put("org.springframework.core.io.Resource", "org.springframework.core.io.Resource");
+ typeMapping.put("file", "org.springframework.web.multipart.MultipartFile");
+ importMapping.put("org.springframework.web.multipart.MultipartFile", "org.springframework.web.multipart.MultipartFile");
if (useOptional) {
writePropertyBack(USE_OPTIONAL, useOptional);
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Swift4Codegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Swift4Codegen.java
index e5724a3c7e8..0133cfb3c17 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Swift4Codegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Swift4Codegen.java
@@ -534,12 +534,12 @@ public class Swift4Codegen extends DefaultCodegen implements CodegenConfig {
@Override
public boolean isDataTypeFile(String dataType) {
- return dataType != null && "URL".equals(dataType);
+ return "URL".equals(dataType);
}
@Override
public boolean isDataTypeBinary(final String dataType) {
- return dataType != null && "Data".equals(dataType);
+ return "Data".equals(dataType);
}
/**
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Swift5ClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Swift5ClientCodegen.java
index a5d71b4d302..5d7f86a40d3 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Swift5ClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Swift5ClientCodegen.java
@@ -61,6 +61,9 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
public static final String SWIFT_USE_API_NAMESPACE = "swiftUseApiNamespace";
public static final String DEFAULT_POD_AUTHORS = "OpenAPI Generator";
public static final String LENIENT_TYPE_CAST = "lenientTypeCast";
+ public static final String USE_SPM_FILE_STRUCTURE = "useSPMFileStructure";
+ public static final String SWIFT_PACKAGE_PATH = "swiftPackagePath";
+ public static final String USE_BACKTICK_ESCAPES = "useBacktickEscapes";
protected static final String LIBRARY_ALAMOFIRE = "alamofire";
protected static final String LIBRARY_URLSESSION = "urlsession";
protected static final String RESPONSE_LIBRARY_PROMISE_KIT = "PromiseKit";
@@ -73,9 +76,12 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
protected boolean objcCompatible = false;
protected boolean lenientTypeCast = false;
protected boolean readonlyProperties = false;
- protected boolean swiftUseApiNamespace;
+ protected boolean swiftUseApiNamespace = false;
+ protected boolean useSPMFileStructure = false;
+ protected String swiftPackagePath = "Classes" + File.separator + "OpenAPIs";
+ protected boolean useBacktickEscapes = false;
protected String[] responseAs = new String[0];
- protected String sourceFolder = "Classes" + File.separator + "OpenAPIs";
+ protected String sourceFolder = swiftPackagePath;
protected HashSet objcReservedWords;
protected String apiDocPath = "docs/";
protected String modelDocPath = "docs/";
@@ -197,7 +203,6 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
typeMapping = new HashMap<>();
typeMapping.put("array", "Array");
- typeMapping.put("List", "Array");
typeMapping.put("map", "Dictionary");
typeMapping.put("set", "Set");
typeMapping.put("date", "Date");
@@ -220,8 +225,8 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
typeMapping.put("UUID", "UUID");
typeMapping.put("URI", "String");
typeMapping.put("decimal", "Decimal");
- typeMapping.put("object", "Any");
- typeMapping.put("AnyType", "Any");
+ typeMapping.put("object", "AnyCodable");
+ typeMapping.put("AnyType", "AnyCodable");
importMapping = new HashMap<>();
@@ -259,8 +264,15 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
"Accept and cast values for simple types (string->bool, "
+ "string->int, int->string)")
.defaultValue(Boolean.FALSE.toString()));
+ cliOptions.add(new CliOption(USE_BACKTICK_ESCAPES,
+ "Escape reserved words using backticks (default: false)")
+ .defaultValue(Boolean.FALSE.toString()));
cliOptions.add(new CliOption(CodegenConstants.API_NAME_PREFIX, CodegenConstants.API_NAME_PREFIX_DESC));
+ cliOptions.add(new CliOption(USE_SPM_FILE_STRUCTURE, "Use SPM file structure"
+ + " and set the source path to Sources" + File.separator + "{{projectName}} (default: false)."));
+ cliOptions.add(new CliOption(SWIFT_PACKAGE_PATH, "Set a custom source path instead of "
+ + projectName + File.separator + "Classes" + File.separator + "OpenAPIs" + "."));
supportedLibraries.put(LIBRARY_URLSESSION, "[DEFAULT] HTTP client: URLSession");
supportedLibraries.put(LIBRARY_ALAMOFIRE, "HTTP client: Alamofire");
@@ -334,7 +346,15 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
final Schema additionalProperties = getAdditionalProperties(schema);
if (additionalProperties != null) {
- codegenModel.additionalPropertiesType = getSchemaType(additionalProperties);
+ Schema inner = null;
+ if (ModelUtils.isArraySchema(schema)) {
+ ArraySchema ap = (ArraySchema) schema;
+ inner = ap.getItems();
+ } else if (ModelUtils.isMapSchema(schema)) {
+ inner = getAdditionalProperties(schema);
+ }
+
+ codegenModel.additionalPropertiesType = inner != null ? getTypeDeclaration(inner) : getSchemaType(additionalProperties);
}
}
@@ -414,6 +434,20 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
additionalProperties.put(POD_AUTHORS, DEFAULT_POD_AUTHORS);
}
+ if (additionalProperties.containsKey(USE_SPM_FILE_STRUCTURE)) {
+ setUseSPMFileStructure(convertPropertyToBooleanAndWriteBack(USE_SPM_FILE_STRUCTURE));
+ sourceFolder = "Sources" + File.separator + projectName;
+ }
+
+ if (additionalProperties.containsKey(SWIFT_PACKAGE_PATH) && ((String)additionalProperties.get(SWIFT_PACKAGE_PATH)).length() > 0) {
+ setSwiftPackagePath((String)additionalProperties.get(SWIFT_PACKAGE_PATH));
+ sourceFolder = swiftPackagePath;
+ }
+
+ if (additionalProperties.containsKey(USE_BACKTICK_ESCAPES)) {
+ setUseBacktickEscapes(convertPropertyToBooleanAndWriteBack(USE_BACKTICK_ESCAPES));
+ }
+
setLenientTypeCast(convertPropertyToBooleanAndWriteBack(LENIENT_TYPE_CAST));
// make api and model doc path available in mustache template
@@ -501,7 +535,7 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
if (this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
- return "_" + name; // add an underscore to the name
+ return useBacktickEscapes && !objcCompatible ? "`" + name + "`" : "_" + name;
}
@Override
@@ -546,12 +580,12 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
@Override
public boolean isDataTypeFile(String dataType) {
- return dataType != null && "URL".equals(dataType);
+ return "URL".equals(dataType);
}
@Override
public boolean isDataTypeBinary(final String dataType) {
- return dataType != null && "Data".equals(dataType);
+ return "Data".equals(dataType);
}
/**
@@ -720,11 +754,16 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
// pet_id => petId
name = camelize(name, true);
- // for reserved word or word starting with number, append _
- if (isReservedWord(name) || name.matches("^\\d.*")) {
+ // for reserved words surround with `` or append _
+ if (isReservedWord(name)) {
name = escapeReservedWord(name);
}
+ // for words starting with number, append _
+ if (name.matches("^\\d.*")) {
+ name = "_" + name;
+ }
+
return name;
}
@@ -745,11 +784,16 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
// pet_id => petId
name = camelize(name, true);
- // for reserved word or word starting with number, append _
- if (isReservedWord(name) || name.matches("^\\d.*")) {
+ // for reserved words surround with ``
+ if (isReservedWord(name)) {
name = escapeReservedWord(name);
}
+ // for words starting with number, append _
+ if (name.matches("^\\d.*")) {
+ name = "_" + name;
+ }
+
return name;
}
@@ -806,6 +850,18 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
this.swiftUseApiNamespace = swiftUseApiNamespace;
}
+ public void setUseSPMFileStructure(boolean useSPMFileStructure) {
+ this.useSPMFileStructure = useSPMFileStructure;
+ }
+
+ public void setSwiftPackagePath(String swiftPackagePath) {
+ this.swiftPackagePath = swiftPackagePath;
+ }
+
+ public void setUseBacktickEscapes(boolean useBacktickEscapes) {
+ this.useBacktickEscapes = useBacktickEscapes;
+ }
+
@Override
public String toEnumValue(String value, String datatype) {
// for string, array of string
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAngularClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAngularClientCodegen.java
index 77bf353a41a..e91ddecda38 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAngularClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAngularClientCodegen.java
@@ -384,7 +384,7 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode
@Override
public boolean isDataTypeFile(final String dataType) {
- return dataType != null && "Blob".equals(dataType);
+ return "Blob".equals(dataType);
}
@Override
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptInversifyClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptInversifyClientCodegen.java
index 4b3daba3f85..6de4f086413 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptInversifyClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptInversifyClientCodegen.java
@@ -141,7 +141,7 @@ public class TypeScriptInversifyClientCodegen extends AbstractTypeScriptClientCo
@Override
public boolean isDataTypeFile(final String dataType) {
- return dataType != null && "Blob".equals(dataType);
+ return "Blob".equals(dataType);
}
@Override
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNestjsClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNestjsClientCodegen.java
index 4e5e6c903ce..771e66db0a4 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNestjsClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNestjsClientCodegen.java
@@ -216,7 +216,7 @@ public class TypeScriptNestjsClientCodegen extends AbstractTypeScriptClientCodeg
@Override
public boolean isDataTypeFile(final String dataType) {
- return dataType != null && "Blob".equals(dataType);
+ return "Blob".equals(dataType);
}
@Override
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNodeClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNodeClientCodegen.java
index 9ff6f444c57..613b9da70f2 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNodeClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNodeClientCodegen.java
@@ -82,7 +82,7 @@ public class TypeScriptNodeClientCodegen extends AbstractTypeScriptClientCodegen
@Override
public boolean isDataTypeFile(final String dataType) {
- return dataType != null && "RequestFile".equals(dataType);
+ return "RequestFile".equals(dataType);
}
@Override
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptRxjsClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptRxjsClientCodegen.java
index a2f79f519ad..bdecf7febe1 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptRxjsClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptRxjsClientCodegen.java
@@ -98,7 +98,7 @@ public class TypeScriptRxjsClientCodegen extends AbstractTypeScriptClientCodegen
@Override
public boolean isDataTypeFile(final String dataType) {
- return dataType != null && "Blob".equals(dataType);
+ return "Blob".equals(dataType);
}
@Override
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/jersey2/AbstractOpenApiSchema.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/jersey2/AbstractOpenApiSchema.mustache
index 6eb87a90b9b..734ef553e30 100644
--- a/modules/openapi-generator/src/main/resources/Java/libraries/jersey2/AbstractOpenApiSchema.mustache
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/jersey2/AbstractOpenApiSchema.mustache
@@ -1,6 +1,6 @@
{{>licenseInfo}}
-package {{invokerPackage}}.model;
+package {{modelPackage}};
import {{invokerPackage}}.ApiException;
import java.util.Objects;
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/native/ApiClient.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/native/ApiClient.mustache
index 4c915fb3f38..ea46db7331d 100644
--- a/modules/openapi-generator/src/main/resources/Java/libraries/native/ApiClient.mustache
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/native/ApiClient.mustache
@@ -16,7 +16,6 @@ import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
-import java.nio.charset.Charset;
import java.time.Duration;
{{#java8}}
import java.time.OffsetDateTime;
@@ -29,6 +28,8 @@ import java.util.StringJoiner;
import java.util.function.Consumer;
import java.util.stream.Collectors;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
/**
* Configuration and utility class for API clients.
*
@@ -45,8 +46,6 @@ import java.util.stream.Collectors;
{{>generatedAnnotation}}
public class ApiClient {
- private static final Charset UTF_8 = Charset.forName("UTF-8");
-
private HttpClient.Builder builder;
private ObjectMapper mapper;
private String scheme;
@@ -171,7 +170,7 @@ public class ApiClient {
public ApiClient(HttpClient.Builder builder, ObjectMapper mapper, String baseUri) {
this.builder = builder;
this.mapper = mapper;
- updateBaseUri(baseUri);
+ updateBaseUri(baseUri != null ? baseUri : getDefaultBaseUri());
interceptor = null;
readTimeout = null;
responseInterceptor = null;
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/native/api.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/native/api.mustache
index 2adef3a6b0e..e91e72f97b9 100644
--- a/modules/openapi-generator/src/main/resources/Java/libraries/native/api.mustache
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/native/api.mustache
@@ -65,6 +65,14 @@ public class {{classname}} {
}
{{/asyncNative}}
+ protected ApiException createApiException(HttpResponse response, String msgPrefix) throws IOException {
+ String body = response.body() == null ? null : new String(response.body().readAllBytes());
+ if (body != null) {
+ msgPrefix += ": " + body;
+ }
+ return new ApiException(response.statusCode(), msgPrefix, response.headers(), body);
+ }
+
{{#operation}}
{{#vendorExtensions.x-group-parameters}}
{{#hasParams}}
@@ -207,10 +215,7 @@ public class {{classname}} {
memberVarResponseInterceptor.accept(localVarResponse);
}
if (localVarResponse.statusCode()/ 100 != 2) {
- throw new ApiException(localVarResponse.statusCode(),
- "{{operationId}} call received non-success response",
- localVarResponse.headers(),
- localVarResponse.body() == null ? null : new String(localVarResponse.body().readAllBytes()));
+ throw createApiException(localVarResponse, "{{operationId}} call received non-success response");
}
return new ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>(
localVarResponse.statusCode(),
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/build.gradle.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/build.gradle.mustache
index c027064edd4..7e3d97298ea 100644
--- a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/build.gradle.mustache
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/build.gradle.mustache
@@ -40,14 +40,8 @@ if(hasProperty('target') && target == 'android') {
targetSdkVersion 25
}
compileOptions {
- {{#java8}}
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
- {{/java8}}
- {{^java8}}
- sourceCompatibility JavaVersion.VERSION_1_7
- targetCompatibility JavaVersion.VERSION_1_7
- {{/java8}}
}
// Rename the aar correctly
@@ -92,14 +86,8 @@ if(hasProperty('target') && target == 'android') {
apply plugin: 'java'
apply plugin: 'maven'
- {{#java8}}
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
- {{/java8}}
- {{^java8}}
- sourceCompatibility = JavaVersion.VERSION_1_7
- targetCompatibility = JavaVersion.VERSION_1_7
- {{/java8}}
install {
repositories.mavenInstaller {
@@ -116,8 +104,8 @@ if(hasProperty('target') && target == 'android') {
dependencies {
implementation 'io.swagger:swagger-annotations:1.5.24'
implementation "com.google.code.findbugs:jsr305:3.0.2"
- implementation 'com.squareup.okhttp3:okhttp:3.14.7'
- implementation 'com.squareup.okhttp3:logging-interceptor:3.14.7'
+ implementation 'com.squareup.okhttp3:okhttp:4.9.1'
+ implementation 'com.squareup.okhttp3:logging-interceptor:4.9.1'
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'io.gsonfire:gson-fire:1.8.4'
{{#hasOAuthMethods}}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/api.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/api.mustache
index 006e6cf8f93..dce5d647267 100644
--- a/modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/api.mustache
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/api.mustache
@@ -71,7 +71,7 @@ public class {{classname}} {
{{#isDeprecated}}
@Deprecated
{{/isDeprecated}}
- public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws RestClientException {
+ public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.web.multipart.MultipartFile{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws RestClientException {
{{#returnType}}
return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).getBody();
{{/returnType}}
@@ -99,7 +99,7 @@ public class {{classname}} {
{{#isDeprecated}}
@Deprecated
{{/isDeprecated}}
- public ResponseEntity<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws RestClientException {
+ public ResponseEntity<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.web.multipart.MultipartFile{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws RestClientException {
Object postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}};
{{#allParams}}{{#required}}
// verify the required parameter '{{paramName}}' is set
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/api_test.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/api_test.mustache
index 119194543c3..56d89a842d4 100644
--- a/modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/api_test.mustache
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/api_test.mustache
@@ -34,7 +34,7 @@ public class {{classname}}Test {
@Test
public void {{operationId}}Test() {
{{#allParams}}
- {{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}} = null;
+ {{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.web.multipart.MultipartFile{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}} = null;
{{/allParams}}
{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
diff --git a/modules/openapi-generator/src/main/resources/JavaJaxRS/pojo.mustache b/modules/openapi-generator/src/main/resources/JavaJaxRS/pojo.mustache
index 6bde84c3fdd..637add30c23 100644
--- a/modules/openapi-generator/src/main/resources/JavaJaxRS/pojo.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaJaxRS/pojo.mustache
@@ -87,7 +87,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}} {{#seriali
{{{vendorExtensions.x-extra-annotation}}}
{{/vendorExtensions.x-extra-annotation}}
{{#jackson}}
- @JsonProperty("{{baseName}}")
+ @JsonProperty(value = "{{baseName}}"{{#isReadOnly}}, access = JsonProperty.Access.READ_ONLY{{/isReadOnly}}{{#isWriteOnly}}, access = JsonProperty.Access.WRITE_ONLY{{/isWriteOnly}})
{{/jackson}}
@ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}")
{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}}
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/homeController.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/homeController.mustache
index f909a15b37d..2b244c540bc 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/homeController.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/homeController.mustache
@@ -4,7 +4,7 @@ package {{configPackage}};
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
-import org.springframework.core.io.Resource;
+import org.springframework.web.multipart.MultipartFile;
{{/useSpringfox}}
import org.springframework.stereotype.Controller;
{{^useSpringfox}}
diff --git a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig
index 886c41c7f4e..87ab2b5e352 100644
--- a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig
+++ b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig
@@ -131,3 +131,4 @@ org.openapitools.codegen.languages.TypeScriptNestjsClientCodegen
org.openapitools.codegen.languages.TypeScriptNodeClientCodegen
org.openapitools.codegen.languages.TypeScriptReduxQueryClientCodegen
org.openapitools.codegen.languages.TypeScriptRxjsClientCodegen
+org.openapitools.codegen.languages.GoEchoServerCodegen
diff --git a/modules/openapi-generator/src/main/resources/bash/Dockerfile.mustache b/modules/openapi-generator/src/main/resources/bash/Dockerfile.mustache
index b59e5a3665a..d5d8a907a31 100644
--- a/modules/openapi-generator/src/main/resources/bash/Dockerfile.mustache
+++ b/modules/openapi-generator/src/main/resources/bash/Dockerfile.mustache
@@ -1,7 +1,6 @@
-FROM ubuntu:16.10
+FROM alpine:3.12.0
-RUN apt-get update -y && apt-get full-upgrade -y
-RUN apt-get install -y bash-completion zsh curl cowsay git vim bsdmainutils
+RUN apk add --update --no-cache curl ca-certificates bash bash-completion zsh curl git vim ncurses util-linux
ADD {{scriptName}} /usr/bin/{{scriptName}}
ADD _{{scriptName}} /usr/local/share/zsh/site-functions/_{{scriptName}}
@@ -30,7 +29,7 @@ RUN echo 'export PROMPT="[{{appName}}] \$ "' >> ~/.zshrc
#
# Setup a welcome message with basic instruction
#
-RUN echo 'cat << EOF\n\
+RUN echo -e 'echo "\
\n\
This Docker provides preconfigured environment for running the command\n\
line REST client for $(tput setaf 6){{appName}}$(tput sgr0).\n\
@@ -63,7 +62,14 @@ $ {{scriptName}} -h\n\
By default you are logged into Zsh with full autocompletion for your REST API,\n\
but you can switch to Bash, where basic autocompletion is also supported.\n\
\n\
-EOF\n\
+"\
' | tee -a ~/.bashrc ~/.zshrc
-ENTRYPOINT ["zsh"]
+#
+# Poormans chsh & cleanup to make image as compact as possible
+#
+
+RUN sed -i 's/root:x:0:0:root:\/root:\/bin\/ash/root:x:0:0:root:\/root:\/bin\/zsh/' /etc/passwd
+RUN apk del git vim && rm -f /var/cache/apk/*
+
+ENTRYPOINT ["/bin/zsh"]
diff --git a/modules/openapi-generator/src/main/resources/cpp-qt5-client/helpers-body.mustache b/modules/openapi-generator/src/main/resources/cpp-qt5-client/helpers-body.mustache
index a4c04a8951c..0661117b0ab 100644
--- a/modules/openapi-generator/src/main/resources/cpp-qt5-client/helpers-body.mustache
+++ b/modules/openapi-generator/src/main/resources/cpp-qt5-client/helpers-body.mustache
@@ -9,47 +9,83 @@ namespace {{this}} {
class {{prefix}}SerializerSettings {
public:
- static void setDateTimeFormat(const QString & dtFormat){
- getInstance()->dateTimeFormat = dtFormat;
+ struct CustomDateTimeFormat{
+ bool isStringSet = false;
+ QString formatString;
+ bool isEnumSet = false;
+ Qt::DateFormat formatEnum;
+ };
+
+ static CustomDateTimeFormat getCustomDateTimeFormat() {
+ return getInstance()->customDateTimeFormat;
}
- static QString getDateTimeFormat() {
- return getInstance()->dateTimeFormat;
+
+ static void setDateTimeFormatString(const QString &dtFormat){
+ getInstance()->customDateTimeFormat.isStringSet = true;
+ getInstance()->customDateTimeFormat.isEnumSet = false;
+ getInstance()->customDateTimeFormat.formatString = dtFormat;
}
+
+ static void setDateTimeFormatEnum(const Qt::DateFormat &dtFormat){
+ getInstance()->customDateTimeFormat.isEnumSet = true;
+ getInstance()->customDateTimeFormat.isStringSet = false;
+ getInstance()->customDateTimeFormat.formatEnum = dtFormat;
+ }
+
static {{prefix}}SerializerSettings *getInstance(){
if(instance == nullptr){
instance = new {{prefix}}SerializerSettings();
}
return instance;
}
+
private:
explicit {{prefix}}SerializerSettings(){
instance = this;
- dateTimeFormat.clear();
+ customDateTimeFormat.isStringSet = false;
+ customDateTimeFormat.isEnumSet = false;
}
static {{prefix}}SerializerSettings *instance;
- QString dateTimeFormat;
+ CustomDateTimeFormat customDateTimeFormat;
};
{{prefix}}SerializerSettings * {{prefix}}SerializerSettings::instance = nullptr;
-bool setDateTimeFormat(const QString& dateTimeFormat){
+bool setDateTimeFormat(const QString &dateTimeFormat){
bool success = false;
auto dt = QDateTime::fromString(QDateTime::currentDateTime().toString(dateTimeFormat), dateTimeFormat);
- if(dt.isValid()){
+ if (dt.isValid()) {
success = true;
- {{prefix}}SerializerSettings::setDateTimeFormat(dateTimeFormat);
+ {{prefix}}SerializerSettings::setDateTimeFormatString(dateTimeFormat);
}
return success;
}
+bool setDateTimeFormat(const Qt::DateFormat &dateTimeFormat){
+ bool success = false;
+ auto dt = QDateTime::fromString(QDateTime::currentDateTime().toString(dateTimeFormat), dateTimeFormat);
+ if (dt.isValid()) {
+ success = true;
+ {{prefix}}SerializerSettings::setDateTimeFormatEnum(dateTimeFormat);
+ }
+ return success;
+}
QString toStringValue(const QString &value) {
return value;
}
QString toStringValue(const QDateTime &value) {
+ if ({{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().isStringSet) {
+ return value.toString({{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().formatString);
+ }
+
+ if ({{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().isEnumSet) {
+ return value.toString({{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().formatEnum);
+ }
+
// ISO 8601
- return {{prefix}}SerializerSettings::getInstance()->getDateTimeFormat().isEmpty()? value.toString(Qt::ISODate):value.toString({{prefix}}SerializerSettings::getInstance()->getDateTimeFormat());
+ return value.toString(Qt::ISODate);
}
QString toStringValue(const QByteArray &value) {
@@ -98,7 +134,16 @@ QJsonValue toJsonValue(const QString &value) {
}
QJsonValue toJsonValue(const QDateTime &value) {
- return QJsonValue(value.toString({{prefix}}SerializerSettings::getInstance()->getDateTimeFormat().isEmpty()?value.toString(Qt::ISODate):value.toString({{prefix}}SerializerSettings::getInstance()->getDateTimeFormat())));
+ if ({{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().isStringSet) {
+ return QJsonValue(value.toString({{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().formatString));
+ }
+
+ if ({{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().isEnumSet) {
+ return QJsonValue(value.toString({{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().formatEnum));
+ }
+
+ // ISO 8601
+ return QJsonValue(value.toString(Qt::ISODate));
}
QJsonValue toJsonValue(const QByteArray &value) {
@@ -151,7 +196,15 @@ bool fromStringValue(const QString &inStr, QDateTime &value) {
if (inStr.isEmpty()) {
return false;
} else {
- auto dateTime = {{prefix}}SerializerSettings::getInstance()->getDateTimeFormat().isEmpty()?QDateTime::fromString(inStr, Qt::ISODate) :QDateTime::fromString(inStr, {{prefix}}SerializerSettings::getInstance()->getDateTimeFormat());
+ QDateTime dateTime;
+ if ({{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().isStringSet) {
+ dateTime = QDateTime::fromString(inStr, {{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().formatString);
+ } else if ({{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().isEnumSet) {
+ dateTime = QDateTime::fromString(inStr, {{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().formatEnum);
+ } else {
+ dateTime = QDateTime::fromString(inStr, Qt::ISODate);
+ }
+
if (dateTime.isValid()) {
value.setDate(dateTime.date());
value.setTime(dateTime.time());
@@ -256,7 +309,13 @@ bool fromJsonValue(QString &value, const QJsonValue &jval) {
bool fromJsonValue(QDateTime &value, const QJsonValue &jval) {
bool ok = true;
if (!jval.isUndefined() && !jval.isNull() && jval.isString()) {
- value = {{prefix}}SerializerSettings::getInstance()->getDateTimeFormat().isEmpty()?QDateTime::fromString(jval.toString(), Qt::ISODate): QDateTime::fromString(jval.toString(), {{prefix}}SerializerSettings::getInstance()->getDateTimeFormat());
+ if ({{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().isStringSet) {
+ value = QDateTime::fromString(jval.toString(), {{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().formatString);
+ } else if ({{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().isEnumSet) {
+ value = QDateTime::fromString(jval.toString(), {{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().formatEnum);
+ } else {
+ value = QDateTime::fromString(jval.toString(), Qt::ISODate);
+ }
ok = value.isValid();
} else {
ok = false;
diff --git a/modules/openapi-generator/src/main/resources/cpp-qt5-client/helpers-header.mustache b/modules/openapi-generator/src/main/resources/cpp-qt5-client/helpers-header.mustache
index 1607aeed2e8..6b0ad489b1c 100644
--- a/modules/openapi-generator/src/main/resources/cpp-qt5-client/helpers-header.mustache
+++ b/modules/openapi-generator/src/main/resources/cpp-qt5-client/helpers-header.mustache
@@ -11,6 +11,7 @@
#include
#include
#include
+#include
#include "{{prefix}}Enum.h"
#include "{{prefix}}HttpFileElement.h"
@@ -41,7 +42,8 @@ public:
}
};
-bool setDateTimeFormat(const QString&);
+bool setDateTimeFormat(const QString &format);
+bool setDateTimeFormat(const Qt::DateFormat &format);
template
QString toStringValue(const QList &val);
diff --git a/modules/openapi-generator/src/main/resources/cpp-ue4/helpers-header.mustache b/modules/openapi-generator/src/main/resources/cpp-ue4/helpers-header.mustache
index eb178e890af..67d60535987 100644
--- a/modules/openapi-generator/src/main/resources/cpp-ue4/helpers-header.mustache
+++ b/modules/openapi-generator/src/main/resources/cpp-ue4/helpers-header.mustache
@@ -105,6 +105,11 @@ inline FStringFormatArg ToStringFormatArg(const FDateTime& Value)
return FStringFormatArg(Value.ToIso8601());
}
+inline FStringFormatArg ToStringFormatArg(const FGuid& Value)
+{
+ return FStringFormatArg(Value.ToString(EGuidFormats::DigitsWithHyphens));
+}
+
inline FStringFormatArg ToStringFormatArg(const TArray& Value)
{
return FStringFormatArg(Base64UrlEncode(Value));
@@ -220,6 +225,11 @@ inline void WriteJsonValue(JsonWriter& Writer, const FDateTime& Value)
Writer->WriteValue(Value.ToIso8601());
}
+inline void WriteJsonValue(JsonWriter& Writer, const FGuid& Value)
+{
+ Writer->WriteValue(Value.ToString(EGuidFormats::DigitsWithHyphens));
+}
+
inline void WriteJsonValue(JsonWriter& Writer, const Model& Value)
{
Value.WriteJson(Writer);
@@ -281,6 +291,17 @@ inline bool TryGetJsonValue(const TSharedPtr& JsonValue, FDateTime&
return false;
}
+inline bool TryGetJsonValue(const TSharedPtr& JsonValue, FGuid& Value)
+{
+ FString TmpValue;
+ if (JsonValue->TryGetString(TmpValue))
+ {
+ return FGuid::Parse(TmpValue, Value);
+ }
+ else
+ return false;
+}
+
inline bool TryGetJsonValue(const TSharedPtr& JsonValue, bool& Value)
{
bool TmpValue;
diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/TestProject.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/TestProject.mustache
index bab424f90f8..b1a50ae778e 100644
--- a/modules/openapi-generator/src/main/resources/csharp-netcore/TestProject.mustache
+++ b/modules/openapi-generator/src/main/resources/csharp-netcore/TestProject.mustache
@@ -17,7 +17,7 @@
Properties
{{testPackageName}}
{{testPackageName}}
- {{testTargetFramework}}
+ {{testTargetFramework}}
false
512
diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient/ApiClient.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient/ApiClient.mustache
index bdc24c21a17..619bcb6bfbb 100644
--- a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient/ApiClient.mustache
+++ b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient/ApiClient.mustache
@@ -168,9 +168,9 @@ namespace {{packageName}}.Client
{
private readonly String _baseUrl;
- private readonly HttpClientHandler _httpClientHandler;
- private readonly HttpClient _httpClient;
- private readonly bool _disposeClient;
+ private readonly HttpClientHandler _httpClientHandler;
+ private readonly HttpClient _httpClient;
+ private readonly bool _disposeClient;
///
/// Specifies the settings on a object.
@@ -192,88 +192,63 @@ namespace {{packageName}}.Client
///
/// Initializes a new instance of the , defaulting to the global configurations' base url.
///
+ [Obsolete("Constructors without HttpClient have non-trivial drawbacks and are thus considered deprecated. Check README.md for details.")]
public ApiClient() :
this({{packageName}}.Client.GlobalConfiguration.Instance.BasePath)
- {
+ {
}
-
+
///
/// Initializes a new instance of the .
///
/// The target service's base path in URL format.
///
+ [Obsolete("Constructors without HttpClient have non-trivial drawbacks and are thus considered deprecated. Check README.md for details.")]
public ApiClient(String basePath)
- {
- if (string.IsNullOrEmpty(basePath)) throw new ArgumentException("basePath cannot be empty");
+ {
+ if (string.IsNullOrEmpty(basePath)) throw new ArgumentException("basePath cannot be empty");
- _httpClientHandler = new HttpClientHandler();
- _httpClient = new HttpClient(_httpClientHandler, true);
+ _httpClientHandler = new HttpClientHandler();
+ _httpClient = new HttpClient(_httpClientHandler, true);
_disposeClient = true;
- _baseUrl = basePath;
+ _baseUrl = basePath;
}
-
+
///
/// Initializes a new instance of the , defaulting to the global configurations' base url.
///
/// An instance of HttpClient.
- ///
- ///
- /// Some configuration settings will not be applied without passing an HttpClientHandler.
+ /// An optional instance of HttpClientHandler that is used by HttpClient.
+ ///
+ ///
+ /// Some configuration settings will not be applied without passing an HttpClientHandler.
/// The features affected are: Setting and Retrieving Cookies, Client Certificates, Proxy settings.
- ///
- public ApiClient(HttpClient client) :
- this(client, {{packageName}}.Client.GlobalConfiguration.Instance.BasePath)
- {
+ ///
+ public ApiClient(HttpClient client, HttpClientHandler handler = null) :
+ this(client, {{packageName}}.Client.GlobalConfiguration.Instance.BasePath, handler)
+ {
}
-
- ///
- /// Initializes a new instance of the
- ///
- /// An instance of HttpClient.
- /// The target service's base path in URL format.
- ///
- ///
- ///
- /// Some configuration settings will not be applied without passing an HttpClientHandler.
- /// The features affected are: Setting and Retrieving Cookies, Client Certificates, Proxy settings.
- ///
- public ApiClient(HttpClient client, String basePath)
- {
- if (client == null) throw new ArgumentNullException("client cannot be null");
- if (string.IsNullOrEmpty(basePath)) throw new ArgumentException("basePath cannot be empty");
-
- _httpClient = client;
- _baseUrl = basePath;
- }
-
- ///
- /// Initializes a new instance of the , defaulting to the global configurations' base url.
- ///
- /// An instance of HttpClient.
- /// An instance of HttpClientHandler that is used by HttpClient.
- ///
- public ApiClient(HttpClient client, HttpClientHandler handler) :
- this(client, handler, {{packageName}}.Client.GlobalConfiguration.Instance.BasePath)
- {
- }
-
- ///
+
+ ///
/// Initializes a new instance of the .
///
/// An instance of HttpClient.
- /// An instance of HttpClientHandler that is used by HttpClient.
- /// The target service's base path in URL format.
- ///
- ///
- public ApiClient(HttpClient client, HttpClientHandler handler, String basePath)
- {
- if (client == null) throw new ArgumentNullException("client cannot be null");
- if (handler == null) throw new ArgumentNullException("handler cannot be null");
- if (string.IsNullOrEmpty(basePath)) throw new ArgumentException("basePath cannot be empty");
-
- _httpClientHandler = handler;
- _httpClient = client;
- _baseUrl = basePath;
+ /// The target service's base path in URL format.
+ /// An optional instance of HttpClientHandler that is used by HttpClient.
+ ///
+ ///
+ ///
+ /// Some configuration settings will not be applied without passing an HttpClientHandler.
+ /// The features affected are: Setting and Retrieving Cookies, Client Certificates, Proxy settings.
+ ///
+ public ApiClient(HttpClient client, String basePath, HttpClientHandler handler = null)
+ {
+ if (client == null) throw new ArgumentNullException("client cannot be null");
+ if (string.IsNullOrEmpty(basePath)) throw new ArgumentException("basePath cannot be empty");
+
+ _httpClientHandler = handler;
+ _httpClient = client;
+ _baseUrl = basePath;
}
///
diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient/api.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient/api.mustache
index b71ebee0f81..efa52cfbd41 100644
--- a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient/api.mustache
+++ b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient/api.mustache
@@ -108,6 +108,7 @@ namespace {{packageName}}.{{apiPackage}}
/// Initializes a new instance of the class.
///
///
+ [Obsolete("Constructors without HttpClient have non-trivial drawbacks and are thus considered deprecated. Check README.md for details.")]
public {{classname}}() : this((string)null)
{
}
@@ -116,8 +117,9 @@ namespace {{packageName}}.{{apiPackage}}
/// Initializes a new instance of the class.
///
/// The target service's base path in URL format.
- ///
+ ///
///
+ [Obsolete("Constructors without HttpClient have non-trivial drawbacks and are thus considered deprecated. Check README.md for details.")]
public {{classname}}(String basePath)
{
this.Configuration = {{packageName}}.Client.Configuration.MergeConfigurations(
@@ -138,6 +140,7 @@ namespace {{packageName}}.{{apiPackage}}
/// An instance of Configuration.
///
///
+ [Obsolete("Constructors without HttpClient have non-trivial drawbacks and are thus considered deprecated. Check README.md for details.")]
public {{classname}}({{packageName}}.Client.Configuration configuration)
{
if (configuration == null) throw new ArgumentNullException("configuration");
@@ -158,13 +161,14 @@ namespace {{packageName}}.{{apiPackage}}
/// Initializes a new instance of the class.
///
/// An instance of HttpClient.
+ /// An optional instance of HttpClientHandler that is used by HttpClient.
///
///
///
- /// Some configuration settings will not be applied without passing an HttpClientHandler.
+ /// Some configuration settings will not be applied without passing an HttpClientHandler.
/// The features affected are: Setting and Retrieving Cookies, Client Certificates, Proxy settings.
///
- public {{classname}}(HttpClient client) : this(client, (string)null)
+ public {{classname}}(HttpClient client, HttpClientHandler handler = null) : this(client, (string)null, handler)
{
}
@@ -173,14 +177,15 @@ namespace {{packageName}}.{{apiPackage}}
///
/// An instance of HttpClient.
/// The target service's base path in URL format.
+ /// An optional instance of HttpClientHandler that is used by HttpClient.
///
- ///
+ ///
///
- ///
- /// Some configuration settings will not be applied without passing an HttpClientHandler.
+ ///
+ /// Some configuration settings will not be applied without passing an HttpClientHandler.
/// The features affected are: Setting and Retrieving Cookies, Client Certificates, Proxy settings.
///
- public {{classname}}(HttpClient client, String basePath)
+ public {{classname}}(HttpClient client, String basePath, HttpClientHandler handler = null)
{
if (client == null) throw new ArgumentNullException("client");
@@ -188,7 +193,7 @@ namespace {{packageName}}.{{apiPackage}}
{{packageName}}.Client.GlobalConfiguration.Instance,
new {{packageName}}.Client.Configuration { BasePath = basePath }
);
- this.ApiClient = new {{packageName}}.Client.ApiClient(client, this.Configuration.BasePath);
+ this.ApiClient = new {{packageName}}.Client.ApiClient(client, this.Configuration.BasePath, handler);
this.Client = this.ApiClient;
{{#supportsAsync}}
this.AsynchronousClient = this.ApiClient;
@@ -201,85 +206,23 @@ namespace {{packageName}}.{{apiPackage}}
///
/// An instance of HttpClient.
/// An instance of Configuration.
+ /// An optional instance of HttpClientHandler that is used by HttpClient.
///
///
///
- /// Some configuration settings will not be applied without passing an HttpClientHandler.
+ /// Some configuration settings will not be applied without passing an HttpClientHandler.
/// The features affected are: Setting and Retrieving Cookies, Client Certificates, Proxy settings.
///
- public {{classname}}(HttpClient client, {{packageName}}.Client.Configuration configuration)
+ public {{classname}}(HttpClient client, {{packageName}}.Client.Configuration configuration, HttpClientHandler handler = null)
{
if (configuration == null) throw new ArgumentNullException("configuration");
- if (client == null) throw new ArgumentNullException("client");
-
- this.Configuration = {{packageName}}.Client.Configuration.MergeConfigurations(
- {{packageName}}.Client.GlobalConfiguration.Instance,
- configuration
- );
- this.ApiClient = new {{packageName}}.Client.ApiClient(client, this.Configuration.BasePath);
- this.Client = this.ApiClient;
- {{#supportsAsync}}
- this.AsynchronousClient = this.ApiClient;
- {{/supportsAsync}}
- ExceptionFactory = {{packageName}}.Client.Configuration.DefaultExceptionFactory;
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// An instance of HttpClient.
- /// An instance of HttpClientHandler that is used by HttpClient.
- ///
- ///
- public {{classname}}(HttpClient client, HttpClientHandler handler) : this(client, handler, (string)null)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// An instance of HttpClient.
- /// An instance of HttpClientHandler that is used by HttpClient.
- /// The target service's base path in URL format.
- ///
- ///
- ///
- public {{classname}}(HttpClient client, HttpClientHandler handler, String basePath)
- {
if (client == null) throw new ArgumentNullException("client");
- if (handler == null) throw new ArgumentNullException("handler");
-
- this.Configuration = {{packageName}}.Client.Configuration.MergeConfigurations(
- {{packageName}}.Client.GlobalConfiguration.Instance,
- new {{packageName}}.Client.Configuration { BasePath = basePath }
- );
- this.ApiClient = new {{packageName}}.Client.ApiClient(client, handler, this.Configuration.BasePath);
- this.Client = this.ApiClient;
- {{#supportsAsync}}
- this.AsynchronousClient = this.ApiClient;
- {{/supportsAsync}}
- this.ExceptionFactory = {{packageName}}.Client.Configuration.DefaultExceptionFactory;
- }
-
- ///
- /// Initializes a new instance of the class using Configuration object.
- ///
- /// An instance of HttpClient.
- /// An instance of HttpClientHandler that is used by HttpClient.
- /// An instance of Configuration.
- ///
- ///
- public {{classname}}(HttpClient client, HttpClientHandler handler, {{packageName}}.Client.Configuration configuration)
- {
- if (configuration == null) throw new ArgumentNullException("configuration");
- if (client == null) throw new ArgumentNullException("client");
- if (handler == null) throw new ArgumentNullException("handler");
this.Configuration = {{packageName}}.Client.Configuration.MergeConfigurations(
{{packageName}}.Client.GlobalConfiguration.Instance,
configuration
);
- this.ApiClient = new {{packageName}}.Client.ApiClient(client, handler, this.Configuration.BasePath);
+ this.ApiClient = new {{packageName}}.Client.ApiClient(client, this.Configuration.BasePath, handler);
this.Client = this.ApiClient;
{{#supportsAsync}}
this.AsynchronousClient = this.ApiClient;
diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/netcore_project.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/netcore_project.mustache
index cdc1b85e584..7d77d34b4d8 100644
--- a/modules/openapi-generator/src/main/resources/csharp-netcore/netcore_project.mustache
+++ b/modules/openapi-generator/src/main/resources/csharp-netcore/netcore_project.mustache
@@ -2,7 +2,7 @@
false
- {{targetFramework}}
+ {{targetFramework}}
{{packageName}}
{{packageName}}
Library
diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/netcore_testproject.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/netcore_testproject.mustache
index 48eaf5a20cc..b20a94c76c1 100644
--- a/modules/openapi-generator/src/main/resources/csharp-netcore/netcore_testproject.mustache
+++ b/modules/openapi-generator/src/main/resources/csharp-netcore/netcore_testproject.mustache
@@ -3,7 +3,7 @@
{{testPackageName}}
{{testPackageName}}
- {{testTargetFramework}}
+ {{testTargetFramework}}
false
diff --git a/modules/openapi-generator/src/main/resources/dart-dio/api.mustache b/modules/openapi-generator/src/main/resources/dart-dio/api.mustache
index 38f4deb96f8..dff1dcd4235 100644
--- a/modules/openapi-generator/src/main/resources/dart-dio/api.mustache
+++ b/modules/openapi-generator/src/main/resources/dart-dio/api.mustache
@@ -4,10 +4,8 @@ import 'package:dio/dio.dart';
import 'package:built_value/serializer.dart';
{{#operations}}
-{{#modelImports}}import 'package:{{pubName}}/model/{{.}}.dart';
-{{/modelImports}}
-{{#fullImports}}import '{{.}}';
-{{/fullImports}}
+{{#imports}}import '{{.}}';
+{{/imports}}
class {{classname}} {
diff --git a/modules/openapi-generator/src/main/resources/dart-dio/pubspec.mustache b/modules/openapi-generator/src/main/resources/dart-dio/pubspec.mustache
index 1d1a328affe..025230b7357 100644
--- a/modules/openapi-generator/src/main/resources/dart-dio/pubspec.mustache
+++ b/modules/openapi-generator/src/main/resources/dart-dio/pubspec.mustache
@@ -1,16 +1,22 @@
name: {{pubName}}
version: {{pubVersion}}
description: {{pubDescription}}
+homepage: {{pubHomepage}}
+authors:
+ - '{{{pubAuthor}}} <{{{pubAuthorEmail}}}>'
+
environment:
- sdk: '>=2.7.0 <3.0.0'
+ sdk: '>=2.7.0 <3.0.0'
+
dependencies:
- dio: '^3.0.9'
- built_value: '>=7.1.0 <8.0.0'
- built_collection: '>=4.3.2 <5.0.0'
+ dio: '^3.0.9'
+ built_value: '>=7.1.0 <8.0.0'
+ built_collection: '>=4.3.2 <5.0.0'
{{#timeMachine}}
- time_machine: '^0.9.12'
+ time_machine: '^0.9.12'
{{/timeMachine}}
+
dev_dependencies:
- built_value_generator: '>=7.1.0 <8.0.0'
- build_runner: any
- test: '>=1.3.0 <1.16.0'
+ built_value_generator: '>=7.1.0 <8.0.0'
+ build_runner: any
+ test: '>=1.3.0 <1.16.0'
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/README.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/README.mustache
index 454bd6ccdb9..3ef0679e726 100644
--- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/README.mustache
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/README.mustache
@@ -21,25 +21,32 @@ For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}})
* Dart 2.12.0 or later OR Flutter 1.26.0 or later
* Dio 4.0.0+
+{{#useDateLibTimeMachine}}
* timemachine option currently **DOES NOT** support sound null-safety and may not work
+{{/useDateLibTimeMachine}}
## Installation & Usage
-### Github
-If this Dart package is published to Github, please include the following in pubspec.yaml
-```
-name: {{pubName}}
-version: {{pubVersion}}
-description: {{pubDescription}}
+### pub.dev
+To use the package from [pub.dev](https://pub.dev), please include the following in pubspec.yaml
+```yaml
dependencies:
- {{pubName}}:
- git: https://github.com/{{gitUserId}}/{{gitRepoId}}.git
- version: 'any'
+ {{pubName}}: {{pubVersion}}
```
-### Local
-To use the package in your local drive, please include the following in pubspec.yaml
+### Github
+If this Dart package is published to Github, please include the following in pubspec.yaml
+```yaml
+dependencies:
+ {{pubName}}:
+ git:
+ url: https://github.com/{{gitUserId}}/{{gitRepoId}}.git
+ #ref: main
```
+
+### Local development
+To use the package from your local drive, please include the following in pubspec.yaml
+```yaml
dependencies:
{{pubName}}:
path: /path/to/{{pubName}}
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache
index 8deca6ce000..34cf9554991 100644
--- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache
@@ -5,10 +5,8 @@ import 'dart:async';
import 'package:dio/dio.dart';
{{#operations}}
-{{#modelImports}}import 'package:{{pubName}}/src/model/{{.}}.dart';
-{{/modelImports}}
-{{#fullImports}}import '{{.}}';
-{{/fullImports}}
+{{#imports}}import '{{.}}';
+{{/imports}}
class {{classname}} {
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/lib.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/lib.mustache
index ff543662653..32f6a54b1a6 100644
--- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/lib.mustache
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/lib.mustache
@@ -3,7 +3,8 @@ export 'package:{{pubName}}/src/api.dart';
export 'package:{{pubName}}/src/auth/api_key_auth.dart';
export 'package:{{pubName}}/src/auth/basic_auth.dart';
export 'package:{{pubName}}/src/auth/oauth.dart';
-{{#useBuiltValue}}export 'package:{{pubName}}/src/serializers.dart';{{/useBuiltValue}}
+{{#useBuiltValue}}export 'package:{{pubName}}/src/serializers.dart';
+{{#useDateLibCore}}export 'package:{{pubName}}/src/model/date.dart';{{/useDateLibCore}}{{/useBuiltValue}}
{{#apiInfo}}{{#apis}}export 'package:{{pubName}}/src/api/{{classFilename}}.dart';
{{/apis}}{{/apiInfo}}
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache
index 7e466cc87f5..b2eef72f91e 100644
--- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache
@@ -1,6 +1,9 @@
name: {{pubName}}
version: {{pubVersion}}
description: {{pubDescription}}
+homepage: {{pubHomepage}}
+authors:
+ - '{{{pubAuthor}}} <{{{pubAuthorEmail}}}>'
environment:
sdk: '>=2.12.0 <3.0.0'
@@ -8,7 +11,7 @@ environment:
dependencies:
dio: '>=4.0.0 <5.0.0'
{{#useBuiltValue}}
- built_value: '>=8.0.3 <9.0.0'
+ built_value: '>=8.0.4 <9.0.0'
built_collection: '>=5.0.0 <6.0.0'
{{/useBuiltValue}}
{{#useDateLibTimeMachine}}
@@ -17,7 +20,7 @@ dependencies:
dev_dependencies:
{{#useBuiltValue}}
- built_value_generator: '>=8.0.3 <9.0.0'
+ built_value_generator: '>=8.0.4 <9.0.0'
build_runner: any
{{/useBuiltValue}}
test: '>=1.16.0 <1.17.0'
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/date.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/date.mustache
new file mode 100644
index 00000000000..c3a87eae259
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/date.mustache
@@ -0,0 +1,69 @@
+/// A gregorian calendar date generated by
+/// OpenAPI generator to differentiate
+/// between [DateTime] and [Date] formats.
+class Date implements Comparable {
+ final int year;
+
+ /// January is 1.
+ final int month;
+
+ /// First day is 1.
+ final int day;
+
+ Date(this.year, this.month, this.day);
+
+ /// The current date
+ static Date now({bool utc = false}) {
+ var now = DateTime.now();
+ if (utc) {
+ now = now.toUtc();
+ }
+ return now.toDate();
+ }
+
+ /// Convert to a [DateTime].
+ DateTime toDateTime({bool utc = false}) {
+ if (utc) {
+ DateTime.utc(year, month, day);
+ }
+ return DateTime(year, month, day);
+ }
+
+ @override
+ int compareTo(Date other) {
+ int d = year.compareTo(other.year);
+ if (d != 0) {
+ return d;
+ }
+ d = month.compareTo(other.month);
+ if (d != 0) {
+ return d;
+ }
+ return day.compareTo(other.day);
+ }
+
+ @override
+ bool operator ==(Object other) =>
+ identical(this, other) ||
+ other is Date &&
+ runtimeType == other.runtimeType &&
+ year == other.year &&
+ month == other.month &&
+ day == other.day;
+
+ @override
+ int get hashCode => year.hashCode ^ month.hashCode ^ day.hashCode;
+
+ @override
+ String toString() {
+ final yyyy = year.toString();
+ final mm = month.toString().padLeft(2, '0');
+ final dd = day.toString().padLeft(2, '0');
+
+ return '$yyyy-$mm-$dd';
+ }
+}
+
+extension DateTimeToDate on DateTime {
+ Date toDate() => Date(year, month, day);
+}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/date_serializer.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/date_serializer.mustache
new file mode 100644
index 00000000000..b5f0ed32c22
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/date_serializer.mustache
@@ -0,0 +1,28 @@
+{{>header}}
+import 'package:built_collection/built_collection.dart';
+import 'package:built_value/serializer.dart';
+import 'package:{{pubName}}/src/model/date.dart';
+
+class DateSerializer implements PrimitiveSerializer {
+
+ const DateSerializer();
+
+ @override
+ Iterable get types => BuiltList.of([Date]);
+
+ @override
+ String get wireName => 'Date';
+
+ @override
+ Date deserialize(Serializers serializers, Object serialized,
+ {FullType specifiedType = FullType.unspecified}) {
+ final parsed = DateTime.parse(serialized as String);
+ return Date(parsed.year, parsed.month, parsed.day);
+ }
+
+ @override
+ Object serialize(Serializers serializers, Date date,
+ {FullType specifiedType = FullType.unspecified}) {
+ return date.toString();
+ }
+}
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/local_date_serializer.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/offset_date_serializer.mustache
similarity index 96%
rename from modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/local_date_serializer.mustache
rename to modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/offset_date_serializer.mustache
index 68cfd5e31c6..2698caf0f49 100644
--- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/local_date_serializer.mustache
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/offset_date_serializer.mustache
@@ -8,7 +8,7 @@ class OffsetDateSerializer implements PrimitiveSerializer {
const OffsetDateSerializer();
@override
- Iterable get types => BuiltList([OffsetDate]);
+ Iterable get types => BuiltList.of([OffsetDate]);
@override
String get wireName => 'OffsetDate';
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/serializers.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/serializers.mustache
index afca0bc138f..10925bc1112 100644
--- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/serializers.mustache
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/serializers.mustache
@@ -1,11 +1,15 @@
{{>header}}
+// ignore_for_file: unused_import
+
import 'package:built_collection/built_collection.dart';
import 'package:built_value/json_object.dart';
import 'package:built_value/serializer.dart';
import 'package:built_value/standard_json_plugin.dart';
-{{#useDateLibCore}}import 'package:built_value/iso_8601_date_time_serializer.dart';{{/useDateLibCore}}
+{{#useDateLibCore}}import 'package:built_value/iso_8601_date_time_serializer.dart';
+import 'package:{{pubName}}/src/date_serializer.dart';
+import 'package:{{pubName}}/src/model/date.dart';{{/useDateLibCore}}
{{#useDateLibTimeMachine}}import 'package:time_machine/time_machine.dart';
-import 'package:{{pubName}}/src/local_date_serializer.dart';{{/useDateLibTimeMachine}}
+import 'package:{{pubName}}/src/offset_date_serializer.dart';{{/useDateLibTimeMachine}}
{{#models}}{{#model}}import 'package:{{pubName}}/src/model/{{classFilename}}.dart';
{{/model}}{{/models}}
part 'serializers.g.dart';
@@ -25,8 +29,9 @@ Serializers serializers = (_$serializers.toBuilder(){{#apiInfo}}{{#apis}}{{#seri
{{/isMap}}
){{/serializers}}{{/apis}}{{/apiInfo}}{{#useDateLibTimeMachine}}
..add(const OffsetDateSerializer())
- ..add(const OffsetDateTimeSerializer()){{/useDateLibTimeMachine}}
- ..add(Iso8601DateTimeSerializer()))
+ ..add(const OffsetDateTimeSerializer()){{/useDateLibTimeMachine}}{{#useDateLibCore}}
+ ..add(const DateSerializer())
+ ..add(Iso8601DateTimeSerializer())){{/useDateLibCore}}
.build();
Serializers standardSerializers =
diff --git a/modules/openapi-generator/src/main/resources/go-echo-server/Dockerfile.mustache b/modules/openapi-generator/src/main/resources/go-echo-server/Dockerfile.mustache
new file mode 100644
index 00000000000..bd60366b27f
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/go-echo-server/Dockerfile.mustache
@@ -0,0 +1,11 @@
+FROM golang:1.16-alpine3.13 as build-env
+RUN apk add --no-cache git gcc
+RUN mkdir /app
+WORKDIR /app
+COPY . .
+RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o {{packageName}}
+FROM alpine:3.13
+COPY --from=build-env /app/{{packageName}} .
+EXPOSE 8080/tcp
+USER 1001
+ENTRYPOINT ["./{{packageName}}"]
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/go-echo-server/README.mustache b/modules/openapi-generator/src/main/resources/go-echo-server/README.mustache
new file mode 100644
index 00000000000..9ff2b9aeb19
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/go-echo-server/README.mustache
@@ -0,0 +1,44 @@
+# Go Echo API Server for {{packageName}}
+
+{{#appDescriptionWithNewLines}}
+{{{appDescriptionWithNewLines}}}
+{{/appDescriptionWithNewLines}}
+
+## Overview
+This server was generated by the [openapi-generator]
+(https://openapi-generator.tech) project.
+By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub.
+-
+
+To see how to make this your own, look here:
+
+[README](https://openapi-generator.tech)
+
+- API version: {{appVersion}}{{^hideGenerationTimestamp}}
+- Build date: {{generatedDate}}{{/hideGenerationTimestamp}}
+{{#infoUrl}}
+For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}})
+{{/infoUrl}}
+
+### Running the server
+
+To run the server, follow these simple steps:
+
+```
+go mod download
+go build -o app
+```
+
+To run the server in a docker container
+```
+docker build --network=host -t {{{packageName}}} .
+```
+
+Once the image is built, just run
+```
+docker run --rm -it {{{packageName}}}
+```
+
+### Known Issue
+
+TBA
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/go-echo-server/api.mustache b/modules/openapi-generator/src/main/resources/go-echo-server/api.mustache
new file mode 100644
index 00000000000..9ac9ad29838
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/go-echo-server/api.mustache
@@ -0,0 +1,15 @@
+package handlers
+{{#operations}}
+import (
+ "github.com/{{{gitUserId}}}/{{{gitRepoId}}}/models"
+ "github.com/labstack/echo/v4"
+ "net/http"
+){{#operation}}
+
+// {{nickname}} - {{{summary}}}
+func (c *Container) {{operationId}}(ctx echo.Context) error {
+ return ctx.JSON(http.StatusOK, models.HelloWorld {
+ Message: "Hello World",
+ })
+}
+{{/operation}}{{/operations}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/go-echo-server/go-mod.mustache b/modules/openapi-generator/src/main/resources/go-echo-server/go-mod.mustache
new file mode 100644
index 00000000000..4b31aa41c83
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/go-echo-server/go-mod.mustache
@@ -0,0 +1,5 @@
+module github.com/{{{gitUserId}}}/{{{gitRepoId}}}
+
+go 1.16
+
+require github.com/labstack/echo/v4 v4.2.0
diff --git a/modules/openapi-generator/src/main/resources/go-echo-server/handler-container.mustache b/modules/openapi-generator/src/main/resources/go-echo-server/handler-container.mustache
new file mode 100644
index 00000000000..330a32f5153
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/go-echo-server/handler-container.mustache
@@ -0,0 +1,11 @@
+package handlers
+
+// Container will hold all dependencies for your application.
+type Container struct {
+}
+
+// NewContainer returns an empty or an initialized container for your handlers.
+func NewContainer() (Container, error) {
+ c := Container{}
+ return c, nil
+}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/go-echo-server/hello-world.mustache b/modules/openapi-generator/src/main/resources/go-echo-server/hello-world.mustache
new file mode 100644
index 00000000000..98b4d20cb61
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/go-echo-server/hello-world.mustache
@@ -0,0 +1,6 @@
+package models
+
+// HelloWorld is a sample data structure to make sure each endpoint return something.
+type HelloWorld struct {
+ Message string `json:"message"`
+}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/go-echo-server/main.mustache b/modules/openapi-generator/src/main/resources/go-echo-server/main.mustache
new file mode 100644
index 00000000000..ef0421cdd11
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/go-echo-server/main.mustache
@@ -0,0 +1,26 @@
+package main
+
+import (
+ "github.com/{{{gitUserId}}}/{{{gitRepoId}}}/handlers"
+ "github.com/labstack/echo/v4"
+ "github.com/labstack/echo/v4/middleware"
+)
+
+func main() {
+ e := echo.New()
+
+ //todo: handle the error!
+ c, _ := handlers.NewContainer()
+
+ // Middleware
+ e.Use(middleware.Logger())
+ e.Use(middleware.Recover())
+
+{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
+ // {{nickname}} - {{{summary}}}
+ e.{{httpMethod.toUpperCase}}("{{{basePathWithoutHost}}}{{{path}}}", c.{{operationId}})
+{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
+
+ // Start server
+ e.Logger.Fatal(e.Start(":{{serverPort}}"))
+}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/go-echo-server/model.mustache b/modules/openapi-generator/src/main/resources/go-echo-server/model.mustache
new file mode 100644
index 00000000000..ef59462f11e
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/go-echo-server/model.mustache
@@ -0,0 +1,23 @@
+package models
+{{#models}}{{#imports}}
+{{#-first}}import (
+{{/-first}} "{{import}}"{{#-last}}
+)
+{{/-last}}{{/imports}}{{#model}}{{#isEnum}}{{#description}}// {{{classname}}} : {{{description}}}{{/description}}
+type {{{classname}}} {{^format}}{{dataType}}{{/format}}{{#format}}{{{format}}}{{/format}}
+
+// List of {{{classname}}}
+const (
+ {{#allowableValues}}
+ {{#enumVars}}
+ {{#enumClassPrefix}}{{{classname.toUpperCase}}}_{{/enumClassPrefix}}{{name}} {{{classname}}} = {{{value}}}
+ {{/enumVars}}
+ {{/allowableValues}}
+){{/isEnum}}{{^isEnum}}{{#description}}
+// {{classname}} - {{{description}}}{{/description}}
+type {{classname}} struct {
+{{#vars}}{{#description}}
+ // {{{description}}}{{/description}}
+ {{name}} {{#isNullable}}*{{/isNullable}}{{{dataType}}} `json:"{{baseName}}{{^required}},omitempty{{/required}}"{{#vendorExtensions.x-go-custom-tag}} {{{.}}}{{/vendorExtensions.x-go-custom-tag}}`
+{{/vars}}
+}{{/isEnum}}{{/model}}{{/models}}
diff --git a/modules/openapi-generator/src/main/resources/go-echo-server/openapi.mustache b/modules/openapi-generator/src/main/resources/go-echo-server/openapi.mustache
new file mode 100644
index 00000000000..51ebafb0187
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/go-echo-server/openapi.mustache
@@ -0,0 +1 @@
+{{{openapi-yaml}}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache b/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache
index 7d321a03efe..2c6b5da8b52 100644
--- a/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache
+++ b/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache
@@ -16,7 +16,7 @@ type {{classname}}Controller struct {
// New{{classname}}Controller creates a default api controller
func New{{classname}}Controller(s {{classname}}Servicer) Router {
- return &{{classname}}Controller{ service: s }
+ return &{{classname}}Controller{service: s}
}
// Routes returns all of the api route for the {{classname}}Controller
@@ -32,73 +32,128 @@ func (c *{{classname}}Controller) Routes() Routes {
}{{#operations}}{{#operation}}
// {{nickname}} - {{{summary}}}
-func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Request) { {{#hasFormParams}}
- err := r.ParseForm()
+func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Request) {
+ {{#hasFormParams}}
+ {{#isMultipart}}
+ if err := r.ParseMultipartForm(32 << 20); err != nil {
+ w.WriteHeader(http.StatusBadRequest)
+ return
+ }
+ {{/isMultipart}}
+ {{^isMultipart}}
+ if err := r.ParseForm(); err != nil {
+ w.WriteHeader(http.StatusBadRequest)
+ return
+ }
+ {{/isMultipart}}
+ {{/hasFormParams}}
+ {{#hasPathParams}}
+ params := mux.Vars(r)
+ {{/hasPathParams}}
+ {{#hasQueryParams}}
+ query := r.URL.Query()
+ {{/hasQueryParams}}
+ {{#allParams}}
+ {{#isPathParam}}
+ {{#isLong}}
+ {{paramName}}, err := parseInt64Parameter(params["{{baseName}}"], {{required}})
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
- {{/hasFormParams}}{{#hasPathParams}}
- params := mux.Vars(r){{/hasPathParams}}{{#hasQueryParams}}
- query := r.URL.Query(){{/hasQueryParams}}{{#allParams}}{{#isPathParam}}{{#isLong}}
- {{paramName}}, err := parseInt64Parameter(params["{{baseName}}"])
- if err != nil {
- w.WriteHeader(http.StatusBadRequest)
- return
- }{{/isLong}}{{#isInteger}}
- {{paramName}}, err := parseInt32Parameter(params["{{baseName}}"])
+ {{/isLong}}
+ {{#isInteger}}
+ {{paramName}}, err := parseInt32Parameter(params["{{baseName}}"], {{required}})
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
- {{/isInteger}}{{^isLong}}{{^isInteger}}
- {{paramName}} := params["{{baseName}}"]{{/isInteger}}{{/isLong}}{{/isPathParam}}{{#isQueryParam}}{{#isLong}}
- {{paramName}}, err := parseInt64Parameter(query.Get("{{baseName}}"))
+ {{/isInteger}}
+ {{^isLong}}
+ {{^isInteger}}
+ {{paramName}} := params["{{baseName}}"]
+ {{/isInteger}}{{/isLong}}
+ {{/isPathParam}}
+ {{#isQueryParam}}
+ {{#isLong}}
+ {{paramName}}, err := parseInt64Parameter(query.Get("{{baseName}}"), {{required}})
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
- {{/isLong}}{{#isInteger}}
- {{paramName}}, err := parseInt32Parameter(query.Get("{{baseName}}"))
+ {{/isLong}}
+ {{#isInteger}}
+ {{paramName}}, err := parseInt32Parameter(query.Get("{{baseName}}"), {{required}})
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
- {{/isInteger}}{{^isLong}}{{^isInteger}}
- {{paramName}} := {{#isArray}}strings.Split({{/isArray}}query.Get("{{baseName}}"){{#isArray}}, ","){{/isArray}}{{/isInteger}}{{/isLong}}{{/isQueryParam}}{{#isFormParam}}{{#isFile}}
- {{#isArray}}{{paramName}}, err := ReadFormFilesToTempFiles(r, "{{baseName}}"){{/isArray}}{{^isArray}}{{paramName}}, err := ReadFormFileToTempFile(r, "{{baseName}}"){{/isArray}}
+ {{/isInteger}}
+ {{#isBoolean}}
+ {{paramName}}, err := parseBoolParameter(query.Get("{{paramName}}"))
+ if err != nil {
+ w.WriteHeader(500)
+ return
+ }
+ {{/isBoolean}}
+ {{^isLong}}
+ {{^isInteger}}
+ {{^isBoolean}}
+ {{paramName}} := {{#isArray}}strings.Split({{/isArray}}query.Get("{{paramName}}"){{#isArray}}, ","){{/isArray}}
+ {{/isBoolean}}
+ {{/isInteger}}
+ {{/isLong}}
+ {{/isQueryParam}}
+ {{#isFormParam}}
+ {{#isFile}}{{#isArray}}
+ {{paramName}}, err := ReadFormFilesToTempFiles(r, "{{baseName}}"){{/isArray}}{{^isArray}}
+ {{paramName}}, err := ReadFormFileToTempFile(r, "{{baseName}}")
+ {{/isArray}}
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
- {{/isFile}}{{#isLong}}
- {{paramName}}, err := parseInt64Parameter( r.FormValue("{{baseName}}"))
+ {{/isFile}}
+ {{#isLong}}{{#isArray}}
+ {{paramName}}, err := parseInt64ArrayParameter(r.FormValue("{{baseName}}"), ",", {{required}}){{/isArray}}{{^isArray}}
+ {{paramName}}, err := parseInt64Parameter(r.FormValue("{{baseName}}"), {{required}}){{/isArray}}
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
- {{/isLong}}{{#isInteger}}
- {{paramName}}, err := parseInt32Parameter( r.FormValue("{{baseName}}"))
+ {{/isLong}}
+ {{#isInteger}}{{#isArray}}
+ {{paramName}}, err := parseInt32ArrayParameter(r.FormValue("{{baseName}}"), ",", {{required}}){{/isArray}}{{^isArray}}
+ {{paramName}}, err := parseInt32Parameter(r.FormValue("{{baseName}}"), {{required}}){{/isArray}}
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
- {{/isInteger}}{{^isFile}}{{^isLong}}
- {{paramName}} := r.FormValue("{{baseName}}"){{/isLong}}{{/isFile}}{{/isFormParam}}{{#isHeaderParam}}
- {{paramName}} := r.Header.Get("{{baseName}}"){{/isHeaderParam}}{{#isBodyParam}}
+ {{/isInteger}}
+ {{^isFile}}
+ {{^isLong}}
+ {{paramName}} := r.FormValue("{{baseName}}")
+ {{/isLong}}
+ {{/isFile}}
+ {{/isFormParam}}
+ {{#isHeaderParam}}
+ {{paramName}} := r.Header.Get("{{baseName}}")
+ {{/isHeaderParam}}
+ {{#isBodyParam}}
{{paramName}} := &{{dataType}}{}
if err := json.NewDecoder(r.Body).Decode(&{{paramName}}); err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
- {{/isBodyParam}}{{/allParams}}
+ {{/isBodyParam}}
+ {{/allParams}}
result, err := c.service.{{nickname}}(r.Context(){{#allParams}}, {{#isBodyParam}}*{{/isBodyParam}}{{paramName}}{{/allParams}})
- //If an error occured, encode the error with the status code
+ // If an error occurred, encode the error with the status code
if err != nil {
- EncodeJSONResponse(err.Error(), &result.Code, w)
+ EncodeJSONResponse(err.Error(), &result.Code,{{#addResponseHeaders}} result.Headers,{{/addResponseHeaders}} w)
return
}
- //If no error, encode the body and the result code
- EncodeJSONResponse(result.Body, &result.Code, w)
-
+ // If no error, encode the body and the result code
+ EncodeJSONResponse(result.Body, &result.Code,{{#addResponseHeaders}} result.Headers,{{/addResponseHeaders}} w)
+
}{{/operation}}{{/operations}}
diff --git a/modules/openapi-generator/src/main/resources/go-server/helpers.mustache b/modules/openapi-generator/src/main/resources/go-server/helpers.mustache
index 2441678ab3b..13115656bc0 100644
--- a/modules/openapi-generator/src/main/resources/go-server/helpers.mustache
+++ b/modules/openapi-generator/src/main/resources/go-server/helpers.mustache
@@ -3,6 +3,22 @@ package {{packageName}}
//Response return a ImplResponse struct filled
func Response(code int, body interface{}) ImplResponse {
- return ImplResponse{Code: code, Body: body}
+ return ImplResponse {
+ Code: code,
+ {{#addResponseHeaders}}
+ Headers: nil,
+ {{/addResponseHeaders}}
+ Body: body,
+ }
}
+{{#addResponseHeaders}}
+//ResponseWithHeaders return a ImplResponse struct filled, including headers
+func ResponseWithHeaders(code int, headers map[string][]string, body interface{}) ImplResponse {
+ return ImplResponse {
+ Code: code,
+ Headers: headers,
+ Body: body,
+ }
+}
+{{/addResponseHeaders}}
diff --git a/modules/openapi-generator/src/main/resources/go-server/impl.mustache b/modules/openapi-generator/src/main/resources/go-server/impl.mustache
index 3333cdecdc2..48d5a3e5e5c 100644
--- a/modules/openapi-generator/src/main/resources/go-server/impl.mustache
+++ b/modules/openapi-generator/src/main/resources/go-server/impl.mustache
@@ -4,5 +4,8 @@ package {{packageName}}
//Implementation response defines an error code with the associated body
type ImplResponse struct {
Code int
+ {{#addResponseHeaders}}
+ Headers map[string][]string
+ {{/addResponseHeaders}}
Body interface{}
-}
\ No newline at end of file
+}
diff --git a/modules/openapi-generator/src/main/resources/go-server/routers.mustache b/modules/openapi-generator/src/main/resources/go-server/routers.mustache
index 6338eecd2e5..d76397166c6 100644
--- a/modules/openapi-generator/src/main/resources/go-server/routers.mustache
+++ b/modules/openapi-generator/src/main/resources/go-server/routers.mustache
@@ -3,22 +3,24 @@ package {{packageName}}
import (
"encoding/json"
+ "errors"
+ "github.com/gorilla/mux"
+ {{#featureCORS}}
+ "github.com/gorilla/handlers"
+ {{/featureCORS}}
"io/ioutil"
"mime/multipart"
"net/http"
"os"
"strconv"
- {{#featureCORS}}
- "github.com/gorilla/handlers"
- {{/featureCORS}}
- "github.com/gorilla/mux"
+ "strings"
)
// A Route defines the parameters for an api endpoint
type Route struct {
- Name string
- Method string
- Pattern string
+ Name string
+ Method string
+ Pattern string
HandlerFunc http.HandlerFunc
}
@@ -30,6 +32,8 @@ type Router interface {
Routes() Routes
}
+const errMsgRequiredMissing = "required parameter is missing"
+
// NewRouter creates a new router for any number of api routers
func NewRouter(routers ...Router) *mux.Router {
router := mux.NewRouter().StrictSlash(true)
@@ -54,8 +58,21 @@ func NewRouter(routers ...Router) *mux.Router {
}
// EncodeJSONResponse uses the json encoder to write an interface to the http response with an optional status code
-func EncodeJSONResponse(i interface{}, status *int, w http.ResponseWriter) error {
+func EncodeJSONResponse(i interface{}, status *int,{{#addResponseHeaders}} headers map[string][]string,{{/addResponseHeaders}} w http.ResponseWriter) error {
+ {{#addResponseHeader}}
+ wHeader := w.Header()
+ if headers != nil {
+ for key, values := range headers {
+ for _, value := range values {
+ wHeader.Add(key, value)
+ }
+ }
+ }
+ wHeader.Set("Content-Type", "application/json; charset=UTF-8")
+ {{/addResponseHeader}}
+ {{^addResponseHeader}}
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
+ {{/addResponseHeader}}
if status != nil {
w.WriteHeader(*status)
} else {
@@ -121,17 +138,91 @@ func readFileHeaderToTempFile(fileHeader *multipart.FileHeader) (*os.File, error
return file, nil
}
+// parseInt64Parameter parses a string parameter to an int64.
+func parseInt64Parameter(param string, required bool) (int64, error) {
+ if param == "" {
+ if required {
+ return 0, errors.New(errMsgRequiredMissing)
+ }
+
+ return 0, nil
+ }
-// parseInt64Parameter parses a sting parameter to an int64
-func parseInt64Parameter(param string) (int64, error) {
return strconv.ParseInt(param, 10, 64)
}
-// parseInt32Parameter parses a sting parameter to an int32
-func parseInt32Parameter(param string) (int32, error) {
+// parseInt32Parameter parses a string parameter to an int32.
+func parseInt32Parameter(param string, required bool) (int32, error) {
+ if param == "" {
+ if required {
+ return 0, errors.New(errMsgRequiredMissing)
+ }
+
+ return 0, nil
+ }
+
val, err := strconv.ParseInt(param, 10, 32)
if err != nil {
return -1, err
}
+
return int32(val), nil
}
+
+// parseBoolParameter parses a string parameter to a bool
+func parseBoolParameter(param string) (bool, error) {
+ val, err := strconv.ParseBool(param)
+ if err != nil {
+ return false, err
+ }
+
+ return bool(val), nil
+}
+
+// parseInt64ArrayParameter parses a string parameter containing array of values to []int64.
+func parseInt64ArrayParameter(param, delim string, required bool) ([]int64, error) {
+ if param == "" {
+ if required {
+ return nil, errors.New(errMsgRequiredMissing)
+ }
+
+ return nil, nil
+ }
+
+ str := strings.Split(param, delim)
+ ints := make([]int64, len(str))
+
+ for i, s := range str {
+ if v, err := strconv.ParseInt(s, 10, 64); err != nil {
+ return nil, err
+ } else {
+ ints[i] = v
+ }
+ }
+
+ return ints, nil
+}
+
+// parseInt32ArrayParameter parses a string parameter containing array of values to []int32.
+func parseInt32ArrayParameter(param, delim string, required bool) ([]int32, error) {
+ if param == "" {
+ if required {
+ return nil, errors.New(errMsgRequiredMissing)
+ }
+
+ return nil, nil
+ }
+
+ str := strings.Split(param, delim)
+ ints := make([]int32, len(str))
+
+ for i, s := range str {
+ if v, err := strconv.ParseInt(s, 10, 32); err != nil {
+ return nil, err
+ } else {
+ ints[i] = int32(v)
+ }
+ }
+
+ return ints, nil
+}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/go/client.mustache b/modules/openapi-generator/src/main/resources/go/client.mustache
index a68fa9ee1dd..476a2081f88 100644
--- a/modules/openapi-generator/src/main/resources/go/client.mustache
+++ b/modules/openapi-generator/src/main/resources/go/client.mustache
@@ -112,7 +112,7 @@ func selectHeaderAccept(accepts []string) string {
return strings.Join(accepts, ",")
}
-// contains is a case insenstive match, finding needle in a haystack
+// contains is a case insensitive match, finding needle in a haystack
func contains(haystack []string, needle string) bool {
for _, a := range haystack {
if strings.ToLower(a) == strings.ToLower(needle) {
diff --git a/modules/openapi-generator/src/main/resources/go/model_enum.mustache b/modules/openapi-generator/src/main/resources/go/model_enum.mustache
index 1d3c2244c09..11dfbfc7d33 100644
--- a/modules/openapi-generator/src/main/resources/go/model_enum.mustache
+++ b/modules/openapi-generator/src/main/resources/go/model_enum.mustache
@@ -12,6 +12,14 @@ const (
{{/allowableValues}}
)
+var allowed{{{classname}}}EnumValues = []{{{classname}}}{
+ {{#allowableValues}}
+ {{#enumVars}}
+ {{{value}}},
+ {{/enumVars}}
+ {{/allowableValues}}
+}
+
func (v *{{{classname}}}) UnmarshalJSON(src []byte) error {
var value {{^format}}{{dataType}}{{/format}}{{#format}}{{{format}}}{{/format}}
err := json.Unmarshal(src, &value)
@@ -19,7 +27,7 @@ func (v *{{{classname}}}) UnmarshalJSON(src []byte) error {
return err
}
enumTypeValue := {{{classname}}}(value)
- for _, existing := range []{{classname}}{ {{#allowableValues}}{{#enumVars}}{{{value}}}, {{/enumVars}} {{/allowableValues}} } {
+ for _, existing := range allowed{{{classname}}}EnumValues {
if existing == enumTypeValue {
*v = enumTypeValue
return nil
@@ -29,6 +37,27 @@ func (v *{{{classname}}}) UnmarshalJSON(src []byte) error {
return fmt.Errorf("%+v is not a valid {{classname}}", value)
}
+// New{{{classname}}}FromValue returns a pointer to a valid {{{classname}}}
+// for the value passed as argument, or an error if the value passed is not allowed by the enum
+func New{{{classname}}}FromValue(v {{^format}}{{dataType}}{{/format}}{{#format}}{{{format}}}{{/format}}) (*{{{classname}}}, error) {
+ ev := {{{classname}}}(v)
+ if ev.IsValid() {
+ return &ev, nil
+ } else {
+ return nil, fmt.Errorf("invalid value '%v' for {{{classname}}}: valid values are %v", v, allowed{{{classname}}}EnumValues)
+ }
+}
+
+// IsValid return true if the value is valid for the enum, false otherwise
+func (v {{{classname}}}) IsValid() bool {
+ for _, existing := range allowed{{{classname}}}EnumValues {
+ if existing == v {
+ return true
+ }
+ }
+ return false
+}
+
// Ptr returns reference to {{{name}}} value
func (v {{{classname}}}) Ptr() *{{{classname}}} {
return &v
diff --git a/modules/openapi-generator/src/main/resources/go/response.mustache b/modules/openapi-generator/src/main/resources/go/response.mustache
index 1a8765bae8f..4691e8f428f 100644
--- a/modules/openapi-generator/src/main/resources/go/response.mustache
+++ b/modules/openapi-generator/src/main/resources/go/response.mustache
@@ -23,7 +23,7 @@ type APIResponse struct {
Payload []byte `json:"-"`
}
-// NewAPIResponse returns a new APIResonse object.
+// NewAPIResponse returns a new APIResponse object.
func NewAPIResponse(r *http.Response) *APIResponse {
response := &APIResponse{Response: r}
diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/build.gradle.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/build.gradle.mustache
index 415a8c25574..1f58112db53 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-client/build.gradle.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-client/build.gradle.mustache
@@ -114,3 +114,11 @@ dependencies {
{{/jvm-retrofit2}}
testCompile "io.kotlintest:kotlintest-runner-junit5:3.4.2"
}
+{{#kotlinx_serialization}}
+
+tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
+ kotlinOptions {
+ freeCompilerArgs += "-Xopt-in=kotlinx.serialization.ExperimentalSerializationApi"
+ }
+}
+{{/kotlinx_serialization}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/data_class.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/data_class.mustache
index b83b7aff952..117cdef8fd7 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-client/data_class.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-client/data_class.mustache
@@ -70,6 +70,9 @@ import java.io.Serializable
* {{{description}}}
* Values: {{#allowableValues}}{{#enumVars}}{{&name}}{{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}}
*/
+ {{#kotlinx_serialization}}
+ @KSerializable
+ {{/kotlinx_serialization}}
{{#nonPublicApi}}internal {{/nonPublicApi}}enum class {{{nameInCamelCase}}}(val value: {{^isContainer}}{{dataType}}{{/isContainer}}{{#isContainer}}kotlin.String{{/isContainer}}) {
{{#allowableValues}}
{{#enumVars}}
diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/BigDecimalAdapter.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/BigDecimalAdapter.kt.mustache
index 5efc613a20e..609d15a34d3 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/BigDecimalAdapter.kt.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/BigDecimalAdapter.kt.mustache
@@ -1,5 +1,6 @@
package {{packageName}}.infrastructure
+{{#kotlinx_serialization}}
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializer
import kotlinx.serialization.encoding.Decoder
@@ -7,13 +8,26 @@ import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.SerialDescriptor
+{{/kotlinx_serialization}}
+{{#moshi}}
+import com.squareup.moshi.FromJson
+import com.squareup.moshi.ToJson
+{{/moshi}}
import java.math.BigDecimal
-@Serializer(forClass = BigDecimal::class)
+{{#kotlinx_serialization}}@Serializer(forClass = BigDecimal::class)
object BigDecimalAdapter : KSerializer {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("BigDecimal", PrimitiveKind.STRING)
-
override fun deserialize(decoder: Decoder): BigDecimal = BigDecimal(decoder.decodeString())
-
override fun serialize(encoder: Encoder, value: BigDecimal) = encoder.encodeString(value.toPlainString())
-}
\ No newline at end of file
+}{{/kotlinx_serialization}}{{#moshi}}{{#nonPublicApi}}internal {{/nonPublicApi}}class BigDecimalAdapter {
+ @ToJson
+ fun toJson(value: BigDecimal): String {
+ return value.toPlainString()
+ }
+
+ @FromJson
+ fun fromJson(value: String): BigDecimal {
+ return BigDecimal(value)
+ }
+}{{/moshi}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/BigIntegerAdapter.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/BigIntegerAdapter.kt.mustache
index bd2b4d3c8e9..2924e8f63a2 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/BigIntegerAdapter.kt.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/BigIntegerAdapter.kt.mustache
@@ -1,5 +1,6 @@
package {{packageName}}.infrastructure
+{{#kotlinx_serialization}}
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializer
import kotlinx.serialization.encoding.Decoder
@@ -7,12 +8,16 @@ import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.SerialDescriptor
+{{/kotlinx_serialization}}
+{{#moshi}}
+import com.squareup.moshi.FromJson
+import com.squareup.moshi.ToJson
+{{/moshi}}
import java.math.BigInteger
-@Serializer(forClass = BigInteger::class)
+{{#kotlinx_serialization}}@Serializer(forClass = BigInteger::class)
object BigIntegerAdapter : KSerializer {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("BigInteger", PrimitiveKind.STRING)
-
override fun deserialize(decoder: Decoder): BigInteger {
return BigInteger(decoder.decodeString())
}
@@ -20,4 +25,14 @@ object BigIntegerAdapter : KSerializer {
override fun serialize(encoder: Encoder, value: BigInteger) {
encoder.encodeString(value.toString())
}
-}
\ No newline at end of file
+}{{/kotlinx_serialization}}{{#moshi}}{{#nonPublicApi}}internal {{/nonPublicApi}}class BigIntegerAdapter {
+ @ToJson
+ fun toJson(value: BigInteger): String {
+ return value.toString()
+ }
+
+ @FromJson
+ fun fromJson(value: String): BigInteger {
+ return BigInteger(value)
+ }
+}{{/moshi}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/Serializer.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/Serializer.kt.mustache
index e9ed019095e..beef3fc2bf3 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/Serializer.kt.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/Serializer.kt.mustache
@@ -63,6 +63,8 @@ import java.util.concurrent.atomic.AtomicLong
{{^moshiCodeGen}}
.add(KotlinJsonAdapterFactory())
{{/moshiCodeGen}}
+ .add(BigDecimalAdapter())
+ .add(BigIntegerAdapter())
@JvmStatic
val moshi: Moshi by lazy {
diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/infrastructure/ApiClient.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/infrastructure/ApiClient.kt.mustache
index 0d834b1e55c..aa5a275a9f3 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/infrastructure/ApiClient.kt.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/infrastructure/ApiClient.kt.mustache
@@ -25,7 +25,10 @@ import okhttp3.Request
import okhttp3.Headers
import okhttp3.MultipartBody
import java.io.File
+import java.io.BufferedWriter
+import java.io.FileWriter
import java.net.URLConnection
+import java.nio.file.Files
import java.util.Date
{{^threetenbp}}
import java.time.LocalDate
@@ -171,6 +174,15 @@ import org.threeten.bp.OffsetTime
if (bodyContent.isEmpty()) {
return null
}
+ if (T::class.java == File::class.java) {
+ // return tempfile
+ val f = Files.createTempFile("tmp.{{packageName}}", null).toFile()
+ f.deleteOnExit()
+ val out = BufferedWriter(FileWriter(f))
+ out.write(bodyContent)
+ out.close()
+ return f as T
+ }
return when(mediaType) {
JsonMediaType -> {{#moshi}}Serializer.moshi.adapter(T::class.java).fromJson(bodyContent){{/moshi}}{{#gson}}Serializer.gson.fromJson(bodyContent, T::class.java){{/gson}}{{#jackson}}Serializer.jacksonObjectMapper.readValue(bodyContent, T::class.java){{/jackson}}
else -> throw UnsupportedOperationException("responseBody currently only supports JSON body.")
diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/api.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/api.mustache
index 07bf4667f39..bca56e88bae 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/api.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/api.mustache
@@ -47,6 +47,12 @@ import okhttp3.MultipartBody
{{/isMultipart}}
{{/x-kotlin-multipart-import}}
+{{#operation}}
+{{#isResponseFile}}
+import okhttp3.ResponseBody
+
+{{/isResponseFile}}
+{{/operation}}
interface {{classname}} {
{{#operation}}
/**
diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/formParams.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/formParams.mustache
index d5267aa7746..041cad11529 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/formParams.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/formParams.mustache
@@ -1 +1 @@
-{{#isFormParam}}{{^isFile}}{{#isMultipart}}@Part{{/isMultipart}}{{^isMultipart}}@Field{{/isMultipart}}("{{baseName}}") {{{paramName}}}: {{{dataType}}}{{/isFile}}{{#isFile}}{{#isMultipart}}@Part{{/isMultipart}}{{^isMultipart}}@Field("{{baseName}}"){{/isMultipart}} {{{paramName}}}: MultipartBody.Part{{/isFile}}{{/isFormParam}}
\ No newline at end of file
+{{#isFormParam}}{{^isFile}}{{#isMultipart}}@Part{{/isMultipart}}{{^isMultipart}}@Field{{/isMultipart}}("{{baseName}}") {{{paramName}}}: {{{dataType}}}{{#required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{/required}}{{^required}}?{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{^defaultValue}} = null{{/defaultValue}}{{/required}}{{/isFile}}{{#isFile}}{{#isMultipart}}@Part{{/isMultipart}}{{^isMultipart}}@Field("{{baseName}}"){{/isMultipart}} {{{paramName}}}: MultipartBody.Part{{^required}}? = null{{/required}}{{/isFile}}{{/isFormParam}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/infrastructure/ApiClient.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/infrastructure/ApiClient.kt.mustache
index 66e77122a81..ea19748fbfb 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/infrastructure/ApiClient.kt.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/infrastructure/ApiClient.kt.mustache
@@ -25,6 +25,7 @@ import okhttp3.Interceptor
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import okhttp3.logging.HttpLoggingInterceptor
+import retrofit2.Converter
import retrofit2.converter.scalars.ScalarsConverterFactory
{{#useRxJava}}
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory
@@ -55,7 +56,8 @@ import okhttp3.MediaType.Companion.toMediaType
private var baseUrl: String = defaultBasePath,
private val okHttpClientBuilder: OkHttpClient.Builder? = null{{^kotlinx_serialization}},
private val serializerBuilder: {{#gson}}Gson{{/gson}}{{#moshi}}Moshi.{{/moshi}}Builder = Serializer.{{#gson}}gson{{/gson}}{{#moshi}}moshi{{/moshi}}Builder{{/kotlinx_serialization}},
- private val okHttpClient : OkHttpClient? = null
+ private val okHttpClient : OkHttpClient? = null,
+ private val converterFactory: Converter.Factory? = null,
) {
private val apiAuthorizations = mutableMapOf()
var logger: ((String) -> Unit)? = null
@@ -81,6 +83,11 @@ import okhttp3.MediaType.Companion.toMediaType
{{#kotlinx_serialization}}
.addConverterFactory(jvmJson.asConverterFactory("application/json".toMediaType()))
{{/kotlinx_serialization}}
+ .apply {
+ if (converterFactory != null) {
+ addConverterFactory(converterFactory)
+ }
+ }
}
private val clientBuilder: OkHttpClient.Builder by lazy {
diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/apiDelegate.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/apiDelegate.mustache
index d45f9f79f2e..bbf57f85b7b 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-spring/apiDelegate.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-spring/apiDelegate.mustache
@@ -8,6 +8,7 @@ import org.springframework.http.ResponseEntity
import org.springframework.web.context.request.NativeWebRequest
import org.springframework.core.io.Resource
{{#reactive}}
+import kotlinx.coroutines.flow.Flow
import org.springframework.web.server.ServerWebExchange
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
@@ -32,7 +33,7 @@ interface {{classname}}Delegate {
/**
* @see {{classname}}#{{operationId}}
*/
- fun {{operationId}}({{#allParams}}{{paramName}}: {{^isFile}}{{>optionalDataType}}{{/isFile}}{{#isFile}}Resource?{{/isFile}}{{^-last}},
+ {{#reactive}}{{^isArray}}suspend {{/isArray}}{{/reactive}}fun {{operationId}}({{#allParams}}{{paramName}}: {{^isFile}}{{>optionalDataType}}{{/isFile}}{{#isFile}}Resource?{{/isFile}}{{^-last}},
{{/-last}}{{/allParams}}): {{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {
{{>methodBody}}
}
diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/apiInterface.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/apiInterface.mustache
index bc224b50080..5e9b3888c8d 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-spring/apiInterface.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-spring/apiInterface.mustache
@@ -83,7 +83,7 @@ interface {{classname}} {
return {{>returnValue}}
{{/isDelegate}}
{{#isDelegate}}
- return getDelegate().{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}exchange{{/reactive}});
+ return getDelegate().{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
{{/isDelegate}}
}
{{/operation}}
diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/enumClass.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/enumClass.mustache
index 2f24a1de76b..bd0794c7f12 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-spring/enumClass.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-spring/enumClass.mustache
@@ -4,6 +4,6 @@
*/
enum class {{classname}}(val value: {{dataType}}) {
{{#allowableValues}}{{#enumVars}}
- {{&name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
+ @JsonProperty({{{value}}}) {{&name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
{{/enumVars}}{{/allowableValues}}
}
diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/methodBody.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/methodBody.mustache
index 69a9fd42d93..3e3b63e9ab0 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-spring/methodBody.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-spring/methodBody.mustache
@@ -1,3 +1,4 @@
+{{^reactive}}
{{#examples}}
{{#-first}}
{{#async}}
@@ -21,3 +22,7 @@ return CompletableFuture.supplyAsync(()-> {
{{^examples}}
return {{#async}}CompletableFuture.completedFuture({{/async}}ResponseEntity({{#returnSuccessCode}}HttpStatus.OK{{/returnSuccessCode}}{{^returnSuccessCode}}HttpStatus.NOT_IMPLEMENTED{{/returnSuccessCode}})
{{/examples}}
+{{/reactive}}
+{{#reactive}}
+return ResponseEntity({{#returnSuccessCode}}HttpStatus.OK{{/returnSuccessCode}}{{^returnSuccessCode}}HttpStatus.NOT_IMPLEMENTED{{/returnSuccessCode}})
+{{/reactive}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/php-symfony/model_variables.mustache b/modules/openapi-generator/src/main/resources/php-symfony/model_variables.mustache
index 3ef46d1c9b0..d79a5feb74a 100644
--- a/modules/openapi-generator/src/main/resources/php-symfony/model_variables.mustache
+++ b/modules/openapi-generator/src/main/resources/php-symfony/model_variables.mustache
@@ -7,6 +7,9 @@
* @SerializedName("{{baseName}}")
{{#required}}
* @Assert\NotNull()
+ {{^isPrimitiveType}}
+ * @Assert\Valid()
+ {{/isPrimitiveType}}
{{/required}}
{{#isEnum}}
{{#isContainer}}
diff --git a/modules/openapi-generator/src/main/resources/php/model_generic.mustache b/modules/openapi-generator/src/main/resources/php/model_generic.mustache
index 276b2bd9d8c..64bb657af16 100644
--- a/modules/openapi-generator/src/main/resources/php/model_generic.mustache
+++ b/modules/openapi-generator/src/main/resources/php/model_generic.mustache
@@ -188,12 +188,12 @@ class {{classname}} {{#parentSchema}}extends {{{parent}}}{{/parentSchema}}{{^par
*/
public function listInvalidProperties()
{
- {{#parent}}
+ {{#parentSchema}}
$invalidProperties = parent::listInvalidProperties();
- {{/parent}}
- {{^parent}}
+ {{/parentSchema}}
+ {{^parentSchema}}
$invalidProperties = [];
- {{/parent}}
+ {{/parentSchema}}
{{#vars}}
{{#required}}
diff --git a/modules/openapi-generator/src/main/resources/powershell/api_doc.mustache b/modules/openapi-generator/src/main/resources/powershell/api_doc.mustache
index c892573091e..7903ec98afe 100644
--- a/modules/openapi-generator/src/main/resources/powershell/api_doc.mustache
+++ b/modules/openapi-generator/src/main/resources/powershell/api_doc.mustache
@@ -78,8 +78,8 @@ Name | Type | Description | Notes
{{/allParams}}
### Return type
-# cmdlet returns PSCustomObject, the return object contains the properties of below type
-{{#returnType}}{{#returnTypeIsPrimitive}}**{{{returnType}}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{{returnType}}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}void (empty response body){{/returnType}}
+
+{{#returnType}}{{#returnTypeIsPrimitive}}**{{{returnType}}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{{returnType}}}**]({{returnBaseType}}.md) (PSCustomObject){{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}void (empty response body){{/returnType}}
### Authorization
diff --git a/modules/openapi-generator/src/main/resources/powershell/appveyor.mustache b/modules/openapi-generator/src/main/resources/powershell/appveyor.mustache
index bf3770e187a..d1047879e53 100644
--- a/modules/openapi-generator/src/main/resources/powershell/appveyor.mustache
+++ b/modules/openapi-generator/src/main/resources/powershell/appveyor.mustache
@@ -1,24 +1,26 @@
{{> partial_header}}
version: 1.0.{build}
image:
- - Visual Studio 2019 # PS 6.x
- #- Visual Studio 2017 # PS 5.x
- #- Ubuntu # PS 6.x
- # ref: https://www.appveyor.com/docs/build-environment/#build-worker-images
+ - Visual Studio 2019 # PWSH 7.x
+ #- Visual Studio 2017 # PS 5.x, PWSH 6.x
+ #- Ubuntu # PWSH 6.x
+ # ref: https://www.appveyor.com/docs/windows-images-software/
install:
- - ps: $PSVersionTable.PSVersion
- - ps: Install-Module Pester -Force -Scope CurrentUser
+ - pwsh: $PSVersionTable.PSVersion
+ - pwsh: Install-Module Pester -Force -Scope CurrentUser
build: off
test_script:
- - ps: |
+ - pwsh: |
+ .\Build.ps1
+ Import-Module -Name '.\src\{{{packageName}}}'
$Result = Invoke-Pester -PassThru
if ($Result.FailedCount -gt 0) {
$host.SetShouldExit($Result.FailedCount)
exit $Result.FailedCount
}
deploy_script:
- - ps: |
- if ($env:APPVEYOR_REPO_TAG -eq $true -and $env:NuGetApiKey -ne $null -and $env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019") {
+ - pwsh: |
+ if ($env:APPVEYOR_REPO_TAG -eq $true -and $env:NuGetApiKey -ne $null) {
.\Build.ps1
try {
Publish-Module -NuGetApiKey $env:NuGetApiKey -Path .\src\{{{packageName}}}\ -Confirm:$False -Verbose
diff --git a/modules/openapi-generator/src/main/resources/python/api.mustache b/modules/openapi-generator/src/main/resources/python/api.mustache
index cbad6df2c54..37339fc5115 100644
--- a/modules/openapi-generator/src/main/resources/python/api.mustache
+++ b/modules/openapi-generator/src/main/resources/python/api.mustache
@@ -230,8 +230,8 @@ class {{classname}}(object):
'min_length': {{minLength}},{{/minLength}}{{#maxItems}}
'max_items': {{maxItems}},{{/maxItems}}{{#minItems}}
'min_items': {{minItems}},{{/minItems}}{{#maximum}}
- {{#exclusiveMaximum}}'exclusive_maximum'{{/exclusiveMaximum}}'inclusive_maximum'{{^exclusiveMaximum}}{{/exclusiveMaximum}}: {{maximum}},{{/maximum}}{{#minimum}}
- {{#exclusiveMinimum}}'exclusive_minimum'{{/exclusiveMinimum}}'inclusive_minimum'{{^exclusiveMinimum}}{{/exclusiveMinimum}}: {{minimum}},{{/minimum}}{{#pattern}}
+ {{#exclusiveMaximum}}'exclusive_maximum'{{/exclusiveMaximum}}{{^exclusiveMaximum}}'inclusive_maximum'{{/exclusiveMaximum}}: {{maximum}},{{/maximum}}{{#minimum}}
+ {{#exclusiveMinimum}}'exclusive_minimum'{{/exclusiveMinimum}}{{^exclusiveMinimum}}'inclusive_minimum'{{/exclusiveMinimum}}: {{minimum}},{{/minimum}}{{#pattern}}
'regex': {
'pattern': r'{{{vendorExtensions.x-regex}}}', # noqa: E501{{#vendorExtensions.x-modifiers}}
{{#-first}}'flags': (re.{{.}}{{/-first}}{{^-first}} re.{{.}}{{/-first}}{{^-last}} | {{/-last}}{{#-last}}){{/-last}}{{/vendorExtensions.x-modifiers}}
diff --git a/modules/openapi-generator/src/main/resources/python/model_utils.mustache b/modules/openapi-generator/src/main/resources/python/model_utils.mustache
index 9b5a8dd9e81..3621a5eec51 100644
--- a/modules/openapi-generator/src/main/resources/python/model_utils.mustache
+++ b/modules/openapi-generator/src/main/resources/python/model_utils.mustache
@@ -1211,13 +1211,19 @@ def model_to_dict(model_instance, serialize=True):
# exist in attribute_map
attr = model_instance.attribute_map.get(attr, attr)
if isinstance(value, list):
- if not value or isinstance(value[0], PRIMITIVE_TYPES):
- # empty list or primitive types
- result[attr] = value
- elif isinstance(value[0], ModelSimple):
- result[attr] = [x.value for x in value]
- else:
- result[attr] = [model_to_dict(x, serialize=serialize) for x in value]
+ if not value:
+ # empty list or None
+ result[attr] = value
+ else:
+ res = []
+ for v in value:
+ if isinstance(v, PRIMITIVE_TYPES) or v is None:
+ res.append(v)
+ elif isinstance(v, ModelSimple):
+ res.append(v.value)
+ else:
+ res.append(model_to_dict(v, serialize=serialize))
+ result[attr] = res
elif isinstance(value, dict):
result[attr] = dict(map(
lambda item: (item[0],
@@ -1277,11 +1283,16 @@ def get_valid_classes_phrase(input_classes):
def convert_js_args_to_python_args(fn):
from functools import wraps
@wraps(fn)
- def wrapped_init(self, *args, **kwargs):
+ def wrapped_init(_self, *args, **kwargs):
+ """
+ An attribute named `self` received from the api will conflicts with the reserved `self`
+ parameter of a class method. During generation, `self` attributes are mapped
+ to `_self` in models. Here, we name `_self` instead of `self` to avoid conflicts.
+ """
spec_property_naming = kwargs.get('_spec_property_naming', False)
if spec_property_naming:
- kwargs = change_keys_js_to_python(kwargs, self.__class__)
- return fn(self, *args, **kwargs)
+ kwargs = change_keys_js_to_python(kwargs, _self.__class__)
+ return fn(_self, *args, **kwargs)
return wrapped_init
diff --git a/modules/openapi-generator/src/main/resources/ruby-sinatra-server/Dockerfile b/modules/openapi-generator/src/main/resources/ruby-sinatra-server/Dockerfile
new file mode 100644
index 00000000000..41be83d48ec
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/ruby-sinatra-server/Dockerfile
@@ -0,0 +1,32 @@
+## Build libraries
+FROM ruby:3.0-alpine as rubydev
+
+## for thin or falcon
+#RUN apk --no-cache add make g++ libc-dev
+## for puma
+#RUN apk --no-cache add make gcc libc-dev
+
+ADD . /app
+WORKDIR /app
+
+RUN bundle config set path lib
+RUN bundle install
+
+## Build Runtime image
+FROM ruby:3.0-alpine
+
+RUN apk --no-cache add tzdata ## ca-certificates
+
+COPY --from=rubydev /app /app
+WORKDIR /app
+
+ENV SINATRA_HOST 0.0.0.0
+ENV SINATRA_PORT 8080
+EXPOSE $SINATRA_PORT
+
+RUN addgroup sinatra
+RUN adduser -S -G sinatra sinatra
+USER sinatra
+RUN bundle config set path lib
+
+CMD bundle exec rackup --host $SINATRA_HOST -p $SINATRA_PORT
diff --git a/modules/openapi-generator/src/main/resources/ruby-sinatra-server/Gemfile b/modules/openapi-generator/src/main/resources/ruby-sinatra-server/Gemfile
index be9c3168ea6..90d7b0e3bcd 100644
--- a/modules/openapi-generator/src/main/resources/ruby-sinatra-server/Gemfile
+++ b/modules/openapi-generator/src/main/resources/ruby-sinatra-server/Gemfile
@@ -1,4 +1,5 @@
source 'https://rubygems.org'
+gem "webrick"
gem "sinatra"
-gem "sinatra-cross_origin"
\ No newline at end of file
+gem "sinatra-cross_origin"
diff --git a/modules/openapi-generator/src/main/resources/ruby-sinatra-server/README.md b/modules/openapi-generator/src/main/resources/ruby-sinatra-server/README.md
index bf132cb042a..aecb705a194 100644
--- a/modules/openapi-generator/src/main/resources/ruby-sinatra-server/README.md
+++ b/modules/openapi-generator/src/main/resources/ruby-sinatra-server/README.md
@@ -1,4 +1,4 @@
-# Swagger for Sinatra
+# OpenAPI for Sinatra
## Overview
This is a project to provide Swagger support inside the [Sinatra](http://www.sinatrarb.com/) framework. You can find
@@ -6,24 +6,60 @@ out more about both the spec and the framework at http://swagger.io. For more i
Wordnik's APIs, please visit http://developer.wordnik.com.
## Prerequisites
-You need to install ruby 1.9.3 and the following gems:
+As of ruby 3.0.0, the webrick web server library was removed.
+You need to install a rack-supported web server, such as webrick and thin.
+
+The default Gemfile is as follows.
+Update the name of the web server as your prefer.
```
-sinatra
-sinatra-cross_origin
+source 'https://rubygems.org'
+
+gem "webrick"
+gem "sinatra"
+gem "sinatra-cross_origin"
```
## Getting started
-This sample was generated with the [OpenAPI Generator](https://github.com/openapitools/openapi-generator) project.
+To generate a ruby-sinatra server for petstore.yaml, please run the following:
```
-rackup -p 4567 config.ru
+openapi-generator-cli generate \
+ -i https://raw.githubusercontent.com/openapitools/openapi-generator/master/modules/openapi-generator/src/test/resources/3_0/petstore.yaml \
+ -g ruby-sinatra -o code
```
-In your [swagger ui](https://github.com/swagger-api/swagger-ui), put in the following URL:
+To run the generated server, please run the following:
```
-http://localhost:4567/resources.json
+cd code/
+bundle config set path lib
+bundle install
+bundle exec rackup -p 8080
+```
+
+You can access the application by the following URL:
+
+```
+http://localhost:8080/v2/store/inventory
+```
+
+## Docker
+If you want to use a web server other than webrick, you need to edit the generated Dockerfile to prepare the compiler and the make command. Please check the comment of the Dockerfile.
+
+To run the code on docker, you can use the Dockerfile as follows:
+
+### Build the docker image
+The "container_name" can be changed for your preferences.
+
+```
+docker build . --tag "container_name"
+```
+
+### Run the docker image
+
+```
+docker run -it --rm -p 8080:8080 "container_name"
```
Voila!
diff --git a/modules/openapi-generator/src/main/resources/scala-akka-client/requests.mustache b/modules/openapi-generator/src/main/resources/scala-akka-client/requests.mustache
index 6dd3ab7d977..727d88f1818 100644
--- a/modules/openapi-generator/src/main/resources/scala-akka-client/requests.mustache
+++ b/modules/openapi-generator/src/main/resources/scala-akka-client/requests.mustache
@@ -3,6 +3,7 @@ package {{invokerPackage}}
import java.io.File
import java.net.URLEncoder
+import java.util.UUID
import java.time.OffsetDateTime
import scala.util.Try
@@ -181,6 +182,7 @@ object ParametersMap {
case Some(opt) => formattedParams(name, opt)
case s: Seq[Any] => formattedParams(name, ArrayValues(s))
case v: String => Seq((name, urlEncode(v)))
+ case v: UUID => formattedParams(name, v.toString)
case NumericValue(v) => Seq((name, urlEncode(v)))
case f: File => Seq((name, f))
case m: ApiModel => Seq((name, m))
diff --git a/modules/openapi-generator/src/main/resources/scala-akka-client/serializers.mustache b/modules/openapi-generator/src/main/resources/scala-akka-client/serializers.mustache
index 6fcbaa2c35e..e66999529d9 100644
--- a/modules/openapi-generator/src/main/resources/scala-akka-client/serializers.mustache
+++ b/modules/openapi-generator/src/main/resources/scala-akka-client/serializers.mustache
@@ -9,6 +9,7 @@ import org.joda.time.format.ISODateTimeFormat
import org.joda.time.{LocalDate, DateTime}
{{/joda}}
import org.json4s.{Serializer, CustomSerializer, JNull}
+import org.json4s.ext.JavaTypesSerializers
import org.json4s.JsonAST.JString
import scala.util.Try
@@ -47,6 +48,6 @@ object Serializers {
}))
{{/joda}}
- def all: Seq[Serializer[_]] = Seq[Serializer[_]]() :+ DateTimeSerializer :+ LocalDateSerializer
+ def all: Seq[Serializer[_]] = JavaTypesSerializers.all :+ DateTimeSerializer :+ LocalDateSerializer
-}
\ No newline at end of file
+}
diff --git a/modules/openapi-generator/src/main/resources/scala-akka-http-server/multipartDirectives.mustache b/modules/openapi-generator/src/main/resources/scala-akka-http-server/multipartDirectives.mustache
index 98a2186fd2e..6e802204c57 100644
--- a/modules/openapi-generator/src/main/resources/scala-akka-http-server/multipartDirectives.mustache
+++ b/modules/openapi-generator/src/main/resources/scala-akka-http-server/multipartDirectives.mustache
@@ -1,6 +1,7 @@
package {{invokerPackage}}
import java.io.File
+import java.nio.file.Files
import akka.annotation.ApiMayChange
import akka.http.scaladsl.model.Multipart.FormData
@@ -69,7 +70,7 @@ trait MultipartDirectives {
object MultipartDirectives extends MultipartDirectives with FileUploadDirectives {
val tempFileFromFileInfo: FileInfo => File = {
- file: FileInfo => File.createTempFile(file.fileName, ".tmp")
+ file: FileInfo => Files.createTempFile(file.fileName, ".tmp").toFile()
}
}
diff --git a/modules/openapi-generator/src/main/resources/swift5/Cartfile.mustache b/modules/openapi-generator/src/main/resources/swift5/Cartfile.mustache
index 3f6269c23ab..64dac06473e 100644
--- a/modules/openapi-generator/src/main/resources/swift5/Cartfile.mustache
+++ b/modules/openapi-generator/src/main/resources/swift5/Cartfile.mustache
@@ -1,3 +1,4 @@
{{#useAlamofire}}github "Alamofire/Alamofire" ~> 4.9.1{{/useAlamofire}}{{#usePromiseKit}}
github "mxcl/PromiseKit" ~> 6.13.1{{/usePromiseKit}}{{#useRxSwift}}
github "ReactiveX/RxSwift" ~> 5.1.1{{/useRxSwift}}
+github "Flight-School/AnyCodable" ~> 0.4.0
diff --git a/modules/openapi-generator/src/main/resources/swift5/Extensions.mustache b/modules/openapi-generator/src/main/resources/swift5/Extensions.mustache
index 1a23697a04b..7e6dcc1994f 100644
--- a/modules/openapi-generator/src/main/resources/swift5/Extensions.mustache
+++ b/modules/openapi-generator/src/main/resources/swift5/Extensions.mustache
@@ -4,7 +4,8 @@
// https://openapi-generator.tech
//
-import Foundation{{#usePromiseKit}}
+import Foundation
+import AnyCodable{{#usePromiseKit}}
import PromiseKit{{/usePromiseKit}}
extension Bool: JSONEncodable {
@@ -53,6 +54,12 @@ extension Array: JSONEncodable {
}
}
+extension Set: JSONEncodable {
+ func encodeToJSON() -> Any {
+ return Array(self).encodeToJSON()
+ }
+}
+
extension Dictionary: JSONEncodable {
func encodeToJSON() -> Any {
var dictionary = [AnyHashable: Any]()
@@ -193,3 +200,44 @@ extension RequestBuilder {
return deferred.promise
}
}{{/usePromiseKit}}
+
+extension AnyCodable: Hashable {
+ public func hash(into hasher: inout Hasher) {
+ switch value {
+ case let value as Bool:
+ hasher.combine(value)
+ case let value as Int:
+ hasher.combine(value)
+ case let value as Int8:
+ hasher.combine(value)
+ case let value as Int16:
+ hasher.combine(value)
+ case let value as Int32:
+ hasher.combine(value)
+ case let value as Int64:
+ hasher.combine(value)
+ case let value as UInt:
+ hasher.combine(value)
+ case let value as UInt8:
+ hasher.combine(value)
+ case let value as UInt16:
+ hasher.combine(value)
+ case let value as UInt32:
+ hasher.combine(value)
+ case let value as UInt64:
+ hasher.combine(value)
+ case let value as Float:
+ hasher.combine(value)
+ case let value as Double:
+ hasher.combine(value)
+ case let value as String:
+ hasher.combine(value)
+ case let value as [String: AnyCodable]:
+ hasher.combine(value)
+ case let value as [AnyCodable]:
+ hasher.combine(value)
+ default:
+ hasher.combine(0)
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/swift5/Package.swift.mustache b/modules/openapi-generator/src/main/resources/swift5/Package.swift.mustache
index d173f21077b..353c6e9f341 100644
--- a/modules/openapi-generator/src/main/resources/swift5/Package.swift.mustache
+++ b/modules/openapi-generator/src/main/resources/swift5/Package.swift.mustache
@@ -1,4 +1,4 @@
-// swift-tools-version:5.0
+// swift-tools-version:5.1
import PackageDescription
@@ -19,6 +19,7 @@ let package = Package(
],
dependencies: [
// Dependencies declare other packages that this package depends on.
+ .package(url: "https://github.com/Flight-School/AnyCodable", .exact("0.4.0")),
{{#useAlamofire}}
.package(url: "https://github.com/Alamofire/Alamofire.git", from: "4.9.1"),
{{/useAlamofire}}
@@ -34,8 +35,8 @@ let package = Package(
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target(
name: "{{projectName}}",
- dependencies: [{{#useAlamofire}}"Alamofire", {{/useAlamofire}}{{#usePromiseKit}}"PromiseKit", {{/usePromiseKit}}{{#useRxSwift}}"RxSwift"{{/useRxSwift}}],
- path: "{{projectName}}/Classes"
+ dependencies: ["AnyCodable", {{#useAlamofire}}"Alamofire", {{/useAlamofire}}{{#usePromiseKit}}"PromiseKit", {{/usePromiseKit}}{{#useRxSwift}}"RxSwift"{{/useRxSwift}}],
+ path: "{{#swiftPackagePath}}{{swiftPackagePath}}{{/swiftPackagePath}}{{^swiftPackagePath}}{{#useSPMFileStructure}}Sources/{{projectName}}{{/useSPMFileStructure}}{{^useSPMFileStructure}}{{projectName}}/Classes{{/useSPMFileStructure}}{{/swiftPackagePath}}"
),
]
)
diff --git a/modules/openapi-generator/src/main/resources/swift5/Podspec.mustache b/modules/openapi-generator/src/main/resources/swift5/Podspec.mustache
index c0539662ce7..09f07162c03 100644
--- a/modules/openapi-generator/src/main/resources/swift5/Podspec.mustache
+++ b/modules/openapi-generator/src/main/resources/swift5/Podspec.mustache
@@ -25,7 +25,7 @@ Pod::Spec.new do |s|
{{#podDocumentationURL}}
s.documentation_url = '{{podDocumentationURL}}'
{{/podDocumentationURL}}
- s.source_files = '{{projectName}}/Classes/**/*.swift'
+ s.source_files = '{{#swiftPackagePath}}{{swiftPackagePath}}{{/swiftPackagePath}}{{^swiftPackagePath}}{{#useSPMFileStructure}}Sources/{{projectName}}{{/useSPMFileStructure}}{{^useSPMFileStructure}}{{projectName}}/Classes{{/useSPMFileStructure}}{{/swiftPackagePath}}/**/*.swift'
{{#usePromiseKit}}
s.dependency 'PromiseKit/CorePromise', '~> 6.13.1'
{{/usePromiseKit}}
@@ -35,4 +35,5 @@ Pod::Spec.new do |s|
{{#useAlamofire}}
s.dependency 'Alamofire', '~> 4.9.1'
{{/useAlamofire}}
+ s.dependency 'AnyCodable-FlightSchool', '~> 0.4.0'
end
diff --git a/modules/openapi-generator/src/main/resources/swift5/XcodeGen.mustache b/modules/openapi-generator/src/main/resources/swift5/XcodeGen.mustache
index a81137ae138..54fbb33d468 100644
--- a/modules/openapi-generator/src/main/resources/swift5/XcodeGen.mustache
+++ b/modules/openapi-generator/src/main/resources/swift5/XcodeGen.mustache
@@ -4,7 +4,7 @@ targets:
type: framework
platform: iOS
deploymentTarget: "9.0"
- sources: [{{projectName}}]
+ sources: [{{#swiftPackagePath}}{{swiftPackagePath}}{{/swiftPackagePath}}{{^swiftPackagePath}}{{#useSPMFileStructure}}Sources{{/useSPMFileStructure}}{{^useSPMFileStructure}}{{projectName}}{{/useSPMFileStructure}}{{/swiftPackagePath}}]
info:
path: ./Info.plist
version: {{#podVersion}}{{podVersion}}{{/podVersion}}{{^podVersion}}{{#apiInfo}}{{version}}{{/apiInfo}}{{^apiInfo}}}0.0.1{{/apiInfo}}{{/podVersion}}
@@ -15,3 +15,4 @@ targets:
- carthage: Alamofire{{/useAlamofire}}{{#useRxSwift}}
- carthage: RxSwift{{/useRxSwift}}{{#usePromiseKit}}
- carthage: PromiseKit{{/usePromiseKit}}
+ - carthage: AnyCodable
diff --git a/modules/openapi-generator/src/main/resources/swift5/api.mustache b/modules/openapi-generator/src/main/resources/swift5/api.mustache
index f1e181e2524..ac3b4b3d954 100644
--- a/modules/openapi-generator/src/main/resources/swift5/api.mustache
+++ b/modules/openapi-generator/src/main/resources/swift5/api.mustache
@@ -248,13 +248,13 @@ extension {{projectName}}API {
let parameters: [String: Any]? = nil
{{/hasFormParams}}
{{/bodyParam}}{{#hasQueryParams}}
- var url = URLComponents(string: URLString)
- url?.queryItems = APIHelper.mapValuesToQueryItems([{{^queryParams}}:{{/queryParams}}
+ var urlComponents = URLComponents(string: URLString)
+ urlComponents?.queryItems = APIHelper.mapValuesToQueryItems([{{^queryParams}}:{{/queryParams}}
{{#queryParams}}
{{> _param}},
{{/queryParams}}
]){{/hasQueryParams}}{{^hasQueryParams}}
- let url = URLComponents(string: URLString){{/hasQueryParams}}
+ let urlComponents = URLComponents(string: URLString){{/hasQueryParams}}
let nillableHeaders: [String: Any?] = [{{^headerParams}}{{^hasFormParams}}
:{{/hasFormParams}}{{/headerParams}}{{#hasFormParams}}
@@ -266,7 +266,7 @@ extension {{projectName}}API {
let requestBuilder: RequestBuilder<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>.Type = {{projectName}}API.requestBuilderFactory.{{#returnType}}getBuilder(){{/returnType}}{{^returnType}}getNonDecodableBuilder(){{/returnType}}
- return requestBuilder.init(method: "{{httpMethod}}", URLString: (url?.string ?? URLString), parameters: parameters, headers: headerParameters)
+ return requestBuilder.init(method: "{{httpMethod}}", URLString: (urlComponents?.string ?? URLString), parameters: parameters, headers: headerParameters)
}
{{/operation}}
diff --git a/modules/openapi-generator/src/main/resources/swift5/model.mustache b/modules/openapi-generator/src/main/resources/swift5/model.mustache
index a5870644a60..7ea71a27f23 100644
--- a/modules/openapi-generator/src/main/resources/swift5/model.mustache
+++ b/modules/openapi-generator/src/main/resources/swift5/model.mustache
@@ -6,6 +6,7 @@
//
import Foundation
+import AnyCodable
{{#description}}
/** {{description}} */{{/description}}{{#isDeprecated}}
diff --git a/modules/openapi-generator/src/main/resources/swift5/modelObject.mustache b/modules/openapi-generator/src/main/resources/swift5/modelObject.mustache
index 661bb479b48..c119f723a2a 100644
--- a/modules/openapi-generator/src/main/resources/swift5/modelObject.mustache
+++ b/modules/openapi-generator/src/main/resources/swift5/modelObject.mustache
@@ -1,4 +1,4 @@
-{{^objcCompatible}}{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} struct {{classname}}: Codable{{#vendorExtensions.x-swift-hashable}}, Hashable{{/vendorExtensions.x-swift-hashable}} {
+{{^objcCompatible}}{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} {{#useClasses}}final class{{/useClasses}}{{^useClasses}}struct{{/useClasses}} {{classname}}: Codable, Hashable {
{{/objcCompatible}}{{#objcCompatible}}@objc {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} class {{classname}}: NSObject, Codable {
{{/objcCompatible}}
@@ -11,17 +11,17 @@
{{#isEnum}}
{{#description}}/** {{description}} */
{{/description}}{{#deprecated}}@available(*, deprecated, message: "This property is deprecated.")
- {{/deprecated}}{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} {{#readonlyProperties}}private(set) {{/readonlyProperties}}var {{name}}: {{{datatypeWithEnum}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}
+ {{/deprecated}}{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} {{#readonlyProperties}}private(set) {{/readonlyProperties}}var {{{name}}}: {{{datatypeWithEnum}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}
{{/isEnum}}
{{^isEnum}}
{{#description}}/** {{description}} */
{{/description}}{{#deprecated}}@available(*, deprecated, message: "This property is deprecated.")
- {{/deprecated}}{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} {{#readonlyProperties}}private(set) {{/readonlyProperties}}var {{name}}: {{{datatype}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}
+ {{/deprecated}}{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} {{#readonlyProperties}}private(set) {{/readonlyProperties}}var {{{name}}}: {{{datatype}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}
{{#objcCompatible}}
{{#vendorExtensions.x-swift-optional-scalar}}
- {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var {{name}}Num: NSNumber? {
+ {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var {{{name}}}Num: NSNumber? {
get {
- return {{name}} as NSNumber?
+ return {{{name}}} as NSNumber?
}
}
{{/vendorExtensions.x-swift-optional-scalar}}
@@ -30,12 +30,17 @@
{{/allVars}}
{{#hasVars}}
- {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} init({{#allVars}}{{name}}: {{{datatypeWithEnum}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}{{^required}} = nil{{/required}}{{/defaultValue}}{{^-last}}, {{/-last}}{{/allVars}}) {
+ {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} init({{#allVars}}{{{name}}}: {{{datatypeWithEnum}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}{{^required}} = nil{{/required}}{{/defaultValue}}{{^-last}}, {{/-last}}{{/allVars}}) {
{{#allVars}}
- self.{{name}} = {{name}}
+ self.{{{name}}} = {{{name}}}
{{/allVars}}
}
{{/hasVars}}
+ {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} enum CodingKeys: {{#hasVars}}String, {{/hasVars}}CodingKey, CaseIterable {
+ {{#allVars}}
+ case {{{name}}}{{#vendorExtensions.x-codegen-escaped-property-name}} = "{{{baseName}}}"{{/vendorExtensions.x-codegen-escaped-property-name}}
+ {{/allVars}}
+ }
{{#additionalPropertiesType}}
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} {{#readonlyProperties}}private(set) {{/readonlyProperties}}var additionalProperties: [String: {{{additionalPropertiesType}}}] = [:]
@@ -51,26 +56,29 @@
additionalProperties[key] = newValue
}
}
+{{/additionalPropertiesType}}
// Encodable protocol methods
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func encode(to encoder: Encoder) throws {
-
- var container = encoder.container(keyedBy: String.self)
-
+ var container = encoder.container(keyedBy: CodingKeys.self)
{{#allVars}}
- try container.encode{{#required}}{{#isNullable}}IfPresent{{/isNullable}}{{/required}}{{^required}}IfPresent{{/required}}({{{name}}}, forKey: "{{{baseName}}}")
+ try container.encode{{^required}}IfPresent{{/required}}({{{name}}}, forKey: .{{{name}}})
{{/allVars}}
- try container.encodeMap(additionalProperties)
+ {{#additionalPropertiesType}}
+ var additionalPropertiesContainer = encoder.container(keyedBy: String.self)
+ try additionalPropertiesContainer.encodeMap(additionalProperties)
+ {{/additionalPropertiesType}}
}
+{{#additionalPropertiesType}}
// Decodable protocol methods
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}}{{#objcCompatible}} required{{/objcCompatible}} init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: String.self)
{{#allVars}}
- {{name}} = try container.decode{{#required}}{{#isNullable}}IfPresent{{/isNullable}}{{/required}}{{^required}}IfPresent{{/required}}({{{datatypeWithEnum}}}.self, forKey: "{{{baseName}}}")
+ {{{name}}} = try container.decode{{#required}}{{#isNullable}}IfPresent{{/isNullable}}{{/required}}{{^required}}IfPresent{{/required}}({{{datatypeWithEnum}}}.self, forKey: "{{{baseName}}}")
{{/allVars}}
var nonAdditionalPropertyKeys = Set()
{{#allVars}}
@@ -79,11 +87,20 @@
additionalProperties = try container.decodeMap({{{additionalPropertiesType}}}.self, excludedKeys: nonAdditionalPropertyKeys)
}
{{/additionalPropertiesType}}
-{{^additionalPropertiesType}}{{#vendorExtensions.x-codegen-has-escaped-property-names}}
- {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} enum CodingKeys: String, CodingKey, CaseIterable {
+
+{{^objcCompatible}}{{#useClasses}}
+ {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static func == (lhs: {{classname}}, rhs: {{classname}}) -> Bool {
{{#allVars}}
- case {{name}}{{#vendorExtensions.x-codegen-escaped-property-name}} = "{{{baseName}}}"{{/vendorExtensions.x-codegen-escaped-property-name}}
+ lhs.{{{name}}} == rhs.{{{name}}}{{^-last}} &&{{/-last}}
{{/allVars}}
+ {{#additionalPropertiesType}}{{#hasVars}}&& {{/hasVars}}lhs.additionalProperties == rhs.additionalProperties{{/additionalPropertiesType}}
}
-{{/vendorExtensions.x-codegen-has-escaped-property-names}}{{/additionalPropertiesType}}
+
+ {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func hash(into hasher: inout Hasher) {
+ {{#allVars}}
+ hasher.combine({{{name}}}{{^required}}?{{/required}}.hashValue)
+ {{/allVars}}
+ {{#additionalPropertiesType}}hasher.combine(additionalProperties.hashValue){{/additionalPropertiesType}}
+ }
+{{/useClasses}}{{/objcCompatible}}
}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/swift5/model_doc.mustache b/modules/openapi-generator/src/main/resources/swift5/model_doc.mustache
index d3e4ecf5c76..6b68575707a 100644
--- a/modules/openapi-generator/src/main/resources/swift5/model_doc.mustache
+++ b/modules/openapi-generator/src/main/resources/swift5/model_doc.mustache
@@ -3,7 +3,7 @@
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
-{{#vars}}**{{name}}** | {{#isPrimitiveType}}**{{{dataType}}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{^isContainer}}[**{{dataType}}**]({{complexType}}.md){{/isContainer}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}}[default to {{{.}}}]{{/defaultValue}}
+{{#vars}}**{{{name}}}** | {{#isPrimitiveType}}**{{{dataType}}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{^isContainer}}[**{{dataType}}**]({{complexType}}.md){{/isContainer}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}}[default to {{{.}}}]{{/defaultValue}}
{{/vars}}
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
diff --git a/modules/openapi-generator/src/main/resources/typescript-angular/api.service.mustache b/modules/openapi-generator/src/main/resources/typescript-angular/api.service.mustache
index 718a8b88549..8f66fcf6f9e 100644
--- a/modules/openapi-generator/src/main/resources/typescript-angular/api.service.mustache
+++ b/modules/openapi-generator/src/main/resources/typescript-angular/api.service.mustache
@@ -334,9 +334,9 @@ export class {{classname}} {
{{/hasFormParams}}
{{^isResponseFile}}
- let responseType: 'text' | 'json' = 'json';
+ let responseType_: 'text' | 'json' = 'json';
if(httpHeaderAcceptSelected && httpHeaderAcceptSelected.startsWith('text')) {
- responseType = 'text';
+ responseType_ = 'text';
}
{{/isResponseFile}}
@@ -350,7 +350,7 @@ export class {{classname}} {
responseType: "blob",
{{/isResponseFile}}
{{^isResponseFile}}
- responseType: responseType,
+ responseType: responseType_,
{{/isResponseFile}}
withCredentials: this.configuration.withCredentials,
headers: headers,
diff --git a/modules/openapi-generator/src/main/resources/typescript-angular/configuration.mustache b/modules/openapi-generator/src/main/resources/typescript-angular/configuration.mustache
index e3a5e824385..40aaec67f47 100644
--- a/modules/openapi-generator/src/main/resources/typescript-angular/configuration.mustache
+++ b/modules/openapi-generator/src/main/resources/typescript-angular/configuration.mustache
@@ -64,15 +64,19 @@ export class {{configurationClassName}} {
{{#isApiKey}}
this.credentials['{{name}}'] = () => {
{{! Fallback behaviour may be removed for 5.0 release. See #5062 }}
- return this.apiKeys['{{name}}'] || this.apiKeys['{{keyParamName}}'];
+ if (this.apiKeys === null || this.apiKeys === undefined) {
+ return undefined;
+ } else {
+ return this.apiKeys['{{name}}'] || this.apiKeys['{{keyParamName}}'];
+ }
};
{{/isApiKey}}
{{#isBasic}}
{{#isBasicBasic}}
this.credentials['{{name}}'] = () => {
- if (this.username || this.password) {
- return btoa(this.username + ':' + this.password);
- }
+ return (this.username || this.password)
+ ? btoa(this.username + ':' + this.password)
+ : undefined;
};
{{/isBasicBasic}}
{{#isBasicBearer}}
diff --git a/modules/openapi-generator/src/main/resources/typescript-axios/apiInner.mustache b/modules/openapi-generator/src/main/resources/typescript-axios/apiInner.mustache
index 71981cf8fca..0550c77b4d8 100644
--- a/modules/openapi-generator/src/main/resources/typescript-axios/apiInner.mustache
+++ b/modules/openapi-generator/src/main/resources/typescript-axios/apiInner.mustache
@@ -86,10 +86,20 @@ export const {{classname}}AxiosParamCreator = function (configuration?: Configur
{{#isArray}}
if ({{paramName}}) {
{{#isCollectionFormatMulti}}
+ {{#uniqueItems}}
+ localVarQueryParameter['{{baseName}}'] = Array.from({{paramName}});
+ {{/uniqueItems}}
+ {{^uniqueItems}}
localVarQueryParameter['{{baseName}}'] = {{paramName}};
+ {{/uniqueItems}}
{{/isCollectionFormatMulti}}
{{^isCollectionFormatMulti}}
+ {{#uniqueItems}}
+ localVarQueryParameter['{{baseName}}'] = Array.from({{paramName}}).join(COLLECTION_FORMATS.{{collectionFormat}});
+ {{/uniqueItems}}
+ {{^uniqueItems}}
localVarQueryParameter['{{baseName}}'] = {{paramName}}.join(COLLECTION_FORMATS.{{collectionFormat}});
+ {{/uniqueItems}}
{{/isCollectionFormatMulti}}
}
{{/isArray}}
@@ -117,7 +127,12 @@ export const {{classname}}AxiosParamCreator = function (configuration?: Configur
{{#headerParams}}
{{#isArray}}
if ({{paramName}}) {
+ {{#uniqueItems}}
+ let mapped = Array.from({{paramName}}).map(value => ("{{{dataType}}}" !== "Set") ? JSON.stringify(value) : (value || ""));
+ {{/uniqueItems}}
+ {{^uniqueItems}}
let mapped = {{paramName}}.map(value => ("{{{dataType}}}" !== "Array") ? JSON.stringify(value) : (value || ""));
+ {{/uniqueItems}}
localVarHeaderParameter['{{baseName}}'] = mapped.join(COLLECTION_FORMATS["{{collectionFormat}}"]);
}
{{/isArray}}
@@ -143,7 +158,7 @@ export const {{classname}}AxiosParamCreator = function (configuration?: Configur
})
{{/isCollectionFormatMulti}}
{{^isCollectionFormatMulti}}
- localVarFormParams.{{#multipartFormData}}append{{/multipartFormData}}{{^multipartFormData}}set{{/multipartFormData}}({{paramName}}.join(COLLECTION_FORMATS.{{collectionFormat}}));
+ localVarFormParams.{{#multipartFormData}}append{{/multipartFormData}}{{^multipartFormData}}set{{/multipartFormData}}('{{baseName}}', {{paramName}}.join(COLLECTION_FORMATS.{{collectionFormat}}));
{{/isCollectionFormatMulti}}
}{{/isArray}}
{{^isArray}}
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java
index a21c506d5a2..e125c98a463 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java
@@ -1188,12 +1188,15 @@ public class DefaultCodegenTest {
Schema sc = openAPI.getComponents().getSchemas().get(modelName);
+ /*
+ // comment out below as we're now showing warnings instead of throwing exceptions
try {
codegen.fromModel(modelName, sc);
Assert.assertTrue(false, "A RuntimeException should have been thrown when processing "+modelName+ " but it was not");
} catch (RuntimeException re) {
Assert.assertEquals(re.getMessage(), errorMessageExpected);
}
+ */
}
}
@@ -1220,12 +1223,15 @@ public class DefaultCodegenTest {
Schema sc = openAPI.getComponents().getSchemas().get(modelName);
+ /*
+ // comment out below as we're now showing warnings instead of throwing exceptions
try {
codegen.fromModel(modelName, sc);
Assert.assertTrue(false, "A RuntimeException should have been thrown when processing "+modelName+ " but it was not");
} catch (RuntimeException re) {
Assert.assertEquals(re.getMessage(), errorMessageExpected);
}
+ */
}
}
@@ -1256,7 +1262,8 @@ public class DefaultCodegenTest {
// inline anyOf with inline anyOf model doesn't work because we have null $refs and we throw an exception
final String fmodelName = "FruitInlineInlineDisc";
final Schema fsc = openAPI.getComponents().getSchemas().get(fmodelName);
- Assert.assertThrows(() -> codegen.fromModel(fmodelName, fsc));
+ // comment out below as we're now showing warnings instead of throwing exceptions
+ //Assert.assertThrows(() -> codegen.fromModel(fmodelName, fsc));
// ref anyOf models with discriminator in properties in those models
modelName = "FruitReqDisc";
@@ -1341,7 +1348,8 @@ public class DefaultCodegenTest {
// inline oneOf with inline oneOf model doesn't work because we have null $refs and we throw an exception
final String fmodelName = "FruitInlineInlineDisc";
final Schema fsc = openAPI.getComponents().getSchemas().get(fmodelName);
- Assert.assertThrows(() -> codegen.fromModel(fmodelName, fsc));
+ // comment out below as we're now showing warnings instead of throwing exceptions
+ //Assert.assertThrows(() -> codegen.fromModel(fmodelName, fsc));
// ref oneOf models with discriminator in properties in those models
modelName = "FruitReqDisc";
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultGeneratorTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultGeneratorTest.java
index 1dee6ced301..7e6a986bb32 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultGeneratorTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultGeneratorTest.java
@@ -459,7 +459,7 @@ public class DefaultGeneratorTest {
List files = generator.opts(clientOptInput).generate();
- Assert.assertEquals(files.size(), 24);
+ Assert.assertEquals(files.size(), 26);
// Generator should report a library templated file as a generated file
TestUtils.ensureContainsFile(files, output, "src/main/kotlin/org/openapitools/client/infrastructure/Errors.kt");
@@ -501,7 +501,7 @@ public class DefaultGeneratorTest {
List files = generator.opts(clientOptInput).generate();
- Assert.assertEquals(files.size(), 24);
+ Assert.assertEquals(files.size(), 26);
// Generator should report README.md as a generated file
TestUtils.ensureContainsFile(files, output, "README.md");
@@ -566,7 +566,7 @@ public class DefaultGeneratorTest {
List files = generator.opts(clientOptInput).generate();
- Assert.assertEquals(files.size(), 24);
+ Assert.assertEquals(files.size(), 26);
// Generator should report a library templated file as a generated file
TestUtils.ensureContainsFile(files, output, "src/main/kotlin/org/openapitools/client/infrastructure/Errors.kt");
@@ -620,7 +620,7 @@ public class DefaultGeneratorTest {
List files = generator.opts(clientOptInput).generate();
- Assert.assertEquals(files.size(), 24);
+ Assert.assertEquals(files.size(), 26);
// Generator should report README.md as a generated file
TestUtils.ensureContainsFile(files, output, "README.md");
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/DartModelTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/DartModelTest.java
index 36daa8b1335..5d76dbcac8e 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/DartModelTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/DartModelTest.java
@@ -337,8 +337,8 @@ public class DartModelTest {
{"sample name", "SampleName"},
{"List", "ModelList"},
{"list", "ModelList"},
- {"File", "ModelFile"},
- {"Client", "ModelClient"},
+ {"File", "TestModelFile"},
+ {"Client", "TestModelClient"},
{"String", "ModelString"},
};
}
@@ -349,6 +349,8 @@ public class DartModelTest {
final Schema model = new Schema();
final DefaultCodegen codegen = new DartClientCodegen();
codegen.setOpenAPI(openAPI);
+ codegen.typeMapping().put("File", "TestModelFile");
+ codegen.typeMapping().put("Client", "TestModelClient");
final CodegenModel cm = codegen.fromModel(name, model);
Assert.assertEquals(cm.name, name);
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioModelTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioModelTest.java
index 95449c3edb9..d645046b2df 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioModelTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioModelTest.java
@@ -380,10 +380,8 @@ public class DartDioModelTest {
@DataProvider(name = "modelNames")
public static Object[][] modelNames() {
return new Object[][] {
- {"EnumClass", "ModelEnumClass"},
- {"JsonObject", "ModelJsonObject"},
- // OffsetDate is valid without timemachine date library
- {"OffsetDate", "OffsetDate"},
+ {"EnumClass", "TestModelEnumClass"},
+ {"JsonObject", "TestModelJsonObject"}
};
}
@@ -393,6 +391,8 @@ public class DartDioModelTest {
final Schema model = new Schema();
final DartDioClientCodegen codegen = new DartDioClientCodegen();
codegen.setOpenAPI(openAPI);
+ codegen.typeMapping().put("EnumClass", "TestModelEnumClass");
+ codegen.typeMapping().put("JsonObject", "TestModelJsonObject");
final CodegenModel cm = codegen.fromModel(name, model);
Assert.assertEquals(cm.name, name);
@@ -402,10 +402,9 @@ public class DartDioModelTest {
@DataProvider(name = "modelNamesTimemachine")
public static Object[][] modelNamesTimemachine() {
return new Object[][] {
- {"EnumClass", "ModelEnumClass"},
- {"JsonObject", "ModelJsonObject"},
- // OffsetDate is not valid with timemachine date library
- {"OffsetDate", "ModelOffsetDate"},
+ {"EnumClass", "TestModelEnumClass"},
+ {"JsonObject", "TestModelJsonObject"},
+ {"OffsetDate", "TestModelOffsetDate"},
};
}
@@ -416,6 +415,9 @@ public class DartDioModelTest {
final DartDioClientCodegen codegen = new DartDioClientCodegen();
codegen.setDateLibrary("timemachine");
codegen.processOpts();
+ codegen.typeMapping().put("EnumClass", "TestModelEnumClass");
+ codegen.typeMapping().put("JsonObject", "TestModelJsonObject");
+ codegen.typeMapping().put("OffsetDate", "TestModelOffsetDate");
codegen.setOpenAPI(openAPI);
final CodegenModel cm = codegen.fromModel(name, model);
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioNextModelTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioNextModelTest.java
index 1190240faa0..4eefae4e418 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioNextModelTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioNextModelTest.java
@@ -390,10 +390,8 @@ public class DartDioNextModelTest {
@DataProvider(name = "modelNames")
public static Object[][] modelNames() {
return new Object[][] {
- {"EnumClass", "ModelEnumClass"},
- {"JsonObject", "ModelJsonObject"},
- // OffsetDate is valid without timemachine date library
- {"OffsetDate", "OffsetDate"},
+ {"EnumClass", "TestModelEnumClass"},
+ {"JsonObject", "TestModelJsonObject"},
};
}
@@ -405,7 +403,8 @@ public class DartDioNextModelTest {
final DefaultCodegen codegen = new DartDioNextClientCodegen();
codegen.additionalProperties().put(CodegenConstants.SERIALIZATION_LIBRARY, DartDioNextClientCodegen.SERIALIZATION_LIBRARY_BUILT_VALUE);
codegen.processOpts();
-
+ codegen.typeMapping().put("EnumClass", "TestModelEnumClass");
+ codegen.typeMapping().put("JsonObject", "TestModelJsonObject");
codegen.setOpenAPI(openAPI);
final CodegenModel cm = codegen.fromModel(name, model);
@@ -417,10 +416,9 @@ public class DartDioNextModelTest {
@DataProvider(name = "modelNamesTimemachine")
public static Object[][] modelNamesTimemachine() {
return new Object[][] {
- {"EnumClass", "ModelEnumClass"},
- {"JsonObject", "ModelJsonObject"},
- // OffsetDate is not valid with timemachine date library
- {"OffsetDate", "ModelOffsetDate"},
+ {"EnumClass", "TestModelEnumClass"},
+ {"JsonObject", "TestModelJsonObject"},
+ {"OffsetDate", "TestModelOffsetDate"},
};
}
@@ -431,7 +429,11 @@ public class DartDioNextModelTest {
final DartDioNextClientCodegen codegen = new DartDioNextClientCodegen();
codegen.additionalProperties().put(DartDioNextClientCodegen.DATE_LIBRARY, DartDioNextClientCodegen.DATE_LIBRARY_TIME_MACHINE);
codegen.processOpts();
+ codegen.typeMapping().put("EnumClass", "TestModelEnumClass");
+ codegen.typeMapping().put("JsonObject", "TestModelJsonObject");
+ codegen.typeMapping().put("OffsetDate", "TestModelOffsetDate");
codegen.setOpenAPI(openAPI);
+
final CodegenModel cm = codegen.fromModel(name, model);
Assert.assertEquals(cm.name, name);
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java
index 3ead6f31f9e..3a7636d631c 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java
@@ -1028,18 +1028,18 @@ public class JavaClientCodegenTest {
Path defaultApi = Paths.get(output + "/src/main/java/xyz/abcdef/api/MultipartApi.java");
TestUtils.assertFileContains(defaultApi,
//multiple files
- "multipartArray(java.util.Collection files)",
- "multipartArrayWithHttpInfo(java.util.Collection files)",
+ "multipartArray(java.util.Collection files)",
+ "multipartArrayWithHttpInfo(java.util.Collection files)",
"formParams.addAll(\"files\", files.stream().collect(Collectors.toList()));",
//mixed
- "multipartMixed(org.springframework.core.io.Resource file, MultipartMixedMarker marker)",
- "multipartMixedWithHttpInfo(org.springframework.core.io.Resource file, MultipartMixedMarker marker)",
+ "multipartMixed(org.springframework.web.multipart.MultipartFile file, MultipartMixedMarker marker)",
+ "multipartMixedWithHttpInfo(org.springframework.web.multipart.MultipartFile file, MultipartMixedMarker marker)",
"formParams.add(\"file\", file);",
//single file
- "multipartSingle(org.springframework.core.io.Resource file)",
- "multipartSingleWithHttpInfo(org.springframework.core.io.Resource file)",
+ "multipartSingle(org.springframework.web.multipart.MultipartFile file)",
+ "multipartSingleWithHttpInfo(org.springframework.web.multipart.MultipartFile file)",
"formParams.add(\"file\", file);"
);
}
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java
index b77afc858f9..dc3bceaa435 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java
@@ -1,9 +1,14 @@
package org.openapitools.codegen.kotlin.spring;
import com.google.common.collect.testing.Helpers;
-
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.info.Info;
+import io.swagger.v3.oas.models.servers.Server;
import org.apache.commons.io.FileUtils;
-import org.openapitools.codegen.*;
+import org.openapitools.codegen.ClientOptInput;
+import org.openapitools.codegen.CodegenConstants;
+import org.openapitools.codegen.DefaultGenerator;
+import org.openapitools.codegen.TestUtils;
import org.openapitools.codegen.kotlin.KotlinTestUtils;
import org.openapitools.codegen.languages.KotlinSpringServerCodegen;
import org.testng.Assert;
@@ -11,12 +16,12 @@ import org.testng.annotations.Test;
import java.io.File;
import java.nio.file.Files;
+import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
-import io.swagger.v3.oas.models.OpenAPI;
-import io.swagger.v3.oas.models.info.Info;
-import io.swagger.v3.oas.models.servers.Server;
+import static org.openapitools.codegen.TestUtils.assertFileContains;
+import static org.openapitools.codegen.TestUtils.assertFileNotContains;
public class KotlinSpringServerCodegenTest {
@@ -203,4 +208,49 @@ public class KotlinSpringServerCodegenTest {
new File(output, "src/main/kotlin/org/openapitools/api/TestV2ApiDelegate.kt")
);
}
+
+ @Test(description = "test delegate reactive with tags")
+ public void delegateReactiveWithTags() throws Exception {
+ File output = Files.createTempDirectory("test").toFile().getCanonicalFile(); //may be move to /build
+ KotlinSpringServerCodegen codegen = new KotlinSpringServerCodegen();
+ codegen.setOutputDir(output.getAbsolutePath());
+ codegen.additionalProperties().put(KotlinSpringServerCodegen.DELEGATE_PATTERN, true);
+ codegen.additionalProperties().put(KotlinSpringServerCodegen.REACTIVE, true);
+ codegen.additionalProperties().put(KotlinSpringServerCodegen.USE_TAGS, true);
+
+ List files = new DefaultGenerator()
+ .opts(
+ new ClientOptInput()
+ .openAPI(TestUtils.parseSpec("src/test/resources/3_0/kotlin/issue7325-use-delegate-reactive-tags-kotlin.yaml"))
+ .config(codegen)
+ )
+ .generate();
+
+ Helpers.assertContainsAllOf(files,
+ new File(output, "src/main/kotlin/org/openapitools/api/TestV1Api.kt"),
+ new File(output, "src/main/kotlin/org/openapitools/api/TestV1ApiController.kt"),
+ new File(output, "src/main/kotlin/org/openapitools/api/TestV1ApiDelegate.kt"),
+ new File(output, "src/main/kotlin/org/openapitools/api/TestV2Api.kt"),
+ new File(output, "src/main/kotlin/org/openapitools/api/TestV2ApiController.kt"),
+ new File(output, "src/main/kotlin/org/openapitools/api/TestV2ApiDelegate.kt")
+ );
+
+ assertFileContains(Paths.get(output + "/src/main/kotlin/org/openapitools/api/TestV1Api.kt"),
+ "suspend fun");
+ assertFileNotContains(Paths.get(output + "/src/main/kotlin/org/openapitools/api/TestV1Api.kt"),
+ "exchange");
+ assertFileContains(Paths.get(output + "/src/main/kotlin/org/openapitools/api/TestV1ApiDelegate.kt"),
+ "suspend fun");
+ assertFileNotContains(Paths.get(output + "/src/main/kotlin/org/openapitools/api/TestV1ApiDelegate.kt"),
+ "ApiUtil");
+
+ assertFileContains(Paths.get(output + "/src/main/kotlin/org/openapitools/api/TestV2Api.kt"),
+ "import kotlinx.coroutines.flow.Flow", "ResponseEntity>");
+ assertFileNotContains(Paths.get(output + "/src/main/kotlin/org/openapitools/api/TestV2Api.kt"),
+ "exchange");
+ assertFileContains(Paths.get(output + "/src/main/kotlin/org/openapitools/api/TestV2ApiDelegate.kt"),
+ "import kotlinx.coroutines.flow.Flow");
+ assertFileNotContains(Paths.get(output + "/src/main/kotlin/org/openapitools/api/TestV2ApiDelegate.kt"),
+ "suspend fun", "ApiUtil");
+ }
}
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/Swift5OptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/Swift5OptionsProvider.java
index e432b326d1c..9e2a4a3b36f 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/Swift5OptionsProvider.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/Swift5OptionsProvider.java
@@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableMap;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.languages.Swift5ClientCodegen;
+import java.io.File;
import java.util.Map;
public class Swift5OptionsProvider implements OptionsProvider {
@@ -45,9 +46,12 @@ public class Swift5OptionsProvider implements OptionsProvider {
public static final String POD_DOCUMENTATION_URL_VALUE = "podDocumentationURL";
public static final String READONLY_PROPERTIES_VALUE = "false";
public static final String SWIFT_USE_API_NAMESPACE_VALUE = "swiftUseApiNamespace";
+ public static final String USE_BACKTICKS_ESCAPES_VALUE = "false";
public static final String ALLOW_UNICODE_IDENTIFIERS_VALUE = "false";
public static final String PREPEND_FORM_OR_BODY_PARAMETERS_VALUE = "true";
public static final String LIBRARY_VALUE = "alamofire";
+ public static final String USE_SPM_FILE_STRUCTURE_VALUE = "false";
+ public static final String SWIFT_PACKAGE_PATH_VALUE = "";
@Override
public String getLanguage() {
@@ -77,6 +81,7 @@ public class Swift5OptionsProvider implements OptionsProvider {
.put(Swift5ClientCodegen.POD_DOCUMENTATION_URL, POD_DOCUMENTATION_URL_VALUE)
.put(Swift5ClientCodegen.READONLY_PROPERTIES, READONLY_PROPERTIES_VALUE)
.put(Swift5ClientCodegen.SWIFT_USE_API_NAMESPACE, SWIFT_USE_API_NAMESPACE_VALUE)
+ .put(Swift5ClientCodegen.USE_BACKTICK_ESCAPES, USE_BACKTICKS_ESCAPES_VALUE)
.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, "true")
.put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE)
.put(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, PREPEND_FORM_OR_BODY_PARAMETERS_VALUE)
@@ -84,6 +89,8 @@ public class Swift5OptionsProvider implements OptionsProvider {
.put(CodegenConstants.LIBRARY, LIBRARY_VALUE)
.put(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR, "true")
.put(CodegenConstants.DISALLOW_ADDITIONAL_PROPERTIES_IF_NOT_PRESENT, "true")
+ .put(Swift5ClientCodegen.USE_SPM_FILE_STRUCTURE, USE_SPM_FILE_STRUCTURE_VALUE)
+ .put(Swift5ClientCodegen.SWIFT_PACKAGE_PATH, SWIFT_PACKAGE_PATH_VALUE)
.build();
}
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/ruby/RubyClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/ruby/RubyClientCodegenTest.java
index 3981f3f6078..f50f20ac135 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/ruby/RubyClientCodegenTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/ruby/RubyClientCodegenTest.java
@@ -677,4 +677,29 @@ public class RubyClientCodegenTest {
// pattern_dont_escape_backslash '/^pattern\d{3}$/i' NOTE: the double \ is to escape \ in string but is read as single \
Assert.assertEquals(op.allParams.get(2).pattern, "/^pattern\\d{3}$/i");
}
+
+ /**
+ * We want to make sure that the type mapping works as expect
+ */
+ @Test(description = "test type mapping to handle special format, e.g. string+special")
+ public void typeMappingTest() {
+ final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/type_mapping_test.yaml");
+ final RubyClientCodegen codegen = new RubyClientCodegen();
+ codegen.typeMapping().put("string+special", "VerySpecialStringInRuby");
+
+ codegen.setOpenAPI(openAPI);
+ final String path = "/animals";
+ final Operation p = openAPI.getPaths().get(path).getGet();
+ final CodegenOperation op = codegen.fromOperation(path, "get", p, null);
+ Assert.assertEquals(op.allParams.get(0).dataType, "VerySpecialStringInRuby");
+
+ final Schema schema = openAPI.getComponents().getSchemas().get("Animal");
+ codegen.setOpenAPI(openAPI);
+ CodegenModel animal = codegen.fromModel("Animal", schema);
+ Assert.assertNotNull(animal);
+ CodegenProperty cp2 = animal.getVars().get(2);
+ Assert.assertEquals(cp2.name, "mapping_test");
+ Assert.assertFalse(cp2.required);
+ Assert.assertEquals(cp2.dataType, "VerySpecialStringInRuby");
+ }
}
diff --git a/modules/openapi-generator/src/test/resources/2_0/swift/petstore-with-fake-endpoints-models-for-testing.yaml b/modules/openapi-generator/src/test/resources/2_0/swift/petstore-with-fake-endpoints-models-for-testing.yaml
index c37f4329e4e..38797a5bf10 100644
--- a/modules/openapi-generator/src/test/resources/2_0/swift/petstore-with-fake-endpoints-models-for-testing.yaml
+++ b/modules/openapi-generator/src/test/resources/2_0/swift/petstore-with-fake-endpoints-models-for-testing.yaml
@@ -1086,7 +1086,6 @@ definitions:
xml:
name: Order
Category:
- x-swift-hashable: true
type: object
required:
- name
@@ -1097,6 +1096,7 @@ definitions:
name:
type: string
default: default-name
+ x-nullable: true
xml:
name: Category
User:
diff --git a/modules/openapi-generator/src/test/resources/2_0/templates/Java/ApiClient.mustache b/modules/openapi-generator/src/test/resources/2_0/templates/Java/ApiClient.mustache
index 116f14c8650..d75e455961c 100644
--- a/modules/openapi-generator/src/test/resources/2_0/templates/Java/ApiClient.mustache
+++ b/modules/openapi-generator/src/test/resources/2_0/templates/Java/ApiClient.mustache
@@ -1,28 +1,38 @@
-//overloaded main template file to add this comment
-
{{>licenseInfo}}
package {{invokerPackage}};
+{{#threetenbp}}
+import org.threeten.bp.*;
+
+{{/threetenbp}}
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.*;
+{{#joda}}
+import com.fasterxml.jackson.datatype.joda.JodaModule;
+{{/joda}}
{{#java8}}
-import com.fasterxml.jackson.datatype.jsr310.*;
-{{/java8}}
-{{^java8}}
-import com.fasterxml.jackson.datatype.joda.*;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+{{^threetenbp}}
+import java.time.OffsetDateTime;
+{{/threetenbp}}
{{/java8}}
+{{#threetenbp}}
+import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule;
+{{/threetenbp}}
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.GenericType;
import com.sun.jersey.api.client.config.DefaultClientConfig;
+import com.sun.jersey.api.client.filter.GZIPContentEncodingFilter;
import com.sun.jersey.api.client.filter.LoggingFilter;
import com.sun.jersey.api.client.WebResource.Builder;
import com.sun.jersey.multipart.FormDataMultiPart;
import com.sun.jersey.multipart.file.FileDataBodyPart;
+import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.Response.Status.Family;
import javax.ws.rs.core.MediaType;
@@ -31,7 +41,9 @@ import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
+import java.util.Arrays;
import java.util.ArrayList;
import java.util.Date;
import java.util.TimeZone;
@@ -44,14 +56,51 @@ import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import {{invokerPackage}}.auth.Authentication;
+{{#hasHttpBasicMethods}}
import {{invokerPackage}}.auth.HttpBasicAuth;
+{{/hasHttpBasicMethods}}
+{{#hasHttpBearerMethods}}
+import {{invokerPackage}}.auth.HttpBearerAuth;
+{{/hasHttpBearerMethods}}
+{{#hasApiKeyMethods}}
import {{invokerPackage}}.auth.ApiKeyAuth;
+{{/hasApiKeyMethods}}
+{{#hasOAuthMethods}}
import {{invokerPackage}}.auth.OAuth;
+{{/hasOAuthMethods}}
{{>generatedAnnotation}}
-public class ApiClient {
+public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
private Map defaultHeaderMap = new HashMap();
- private String basePath = "{{basePath}}";
+ private Map defaultCookieMap = new HashMap();
+ private String basePath = "{{{basePath}}}";
+ protected List servers = new ArrayList({{#servers}}{{#-first}}Arrays.asList(
+{{/-first}} new ServerConfiguration(
+ "{{{url}}}",
+ "{{{description}}}{{^description}}No description provided{{/description}}",
+ new HashMap(){{#variables}}{{#-first}} {{
+{{/-first}} put("{{{name}}}", new ServerVariable(
+ "{{{description}}}{{^description}}No description provided{{/description}}",
+ "{{{defaultValue}}}",
+ new HashSet(
+ {{#enumValues}}
+ {{#-first}}
+ Arrays.asList(
+ {{/-first}}
+ "{{{.}}}"{{^-last}},{{/-last}}
+ {{#-last}}
+ )
+ {{/-last}}
+ {{/enumValues}}
+ )
+ ));
+ {{#-last}}
+ }}{{/-last}}{{/variables}}
+ ){{^-last}},{{/-last}}
+ {{#-last}}
+ ){{/-last}}{{/servers}});
+ protected Integer serverIndex = 0;
+ protected Map serverVariables = null;
private boolean debugging = false;
private int connectionTimeout = 0;
@@ -69,15 +118,23 @@ public class ApiClient {
objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
+ {{#joda}}
+ objectMapper.registerModule(new JodaModule());
+ {{/joda}}
{{#java8}}
objectMapper.registerModule(new JavaTimeModule());
{{/java8}}
- {{^java8}}
- objectMapper.registerModule(new JodaModule());
- {{/java8}}
+ {{#threetenbp}}
+ ThreeTenModule module = new ThreeTenModule();
+ module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT);
+ module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME);
+ module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME);
+ objectMapper.registerModule(module);
+ {{/threetenbp}}
objectMapper.setDateFormat(ApiClient.buildDefaultDateFormat());
dateFormat = ApiClient.buildDefaultDateFormat();
@@ -86,8 +143,9 @@ public class ApiClient {
setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}");
// Setup authentications (key: authentication name, value: authentication).
- authentications = new HashMap();{{#authMethods}}{{#isBasic}}
- authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}}
+ authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}}
+ authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}}
+ authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}}
authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}}
authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}}
// Prevent the authentications from being modified.
@@ -112,6 +170,7 @@ public class ApiClient {
DefaultClientConfig conf = new DefaultClientConfig();
conf.getSingletons().add(jsonProvider);
Client client = Client.create(conf);
+ client.addFilter(new GZIPContentEncodingFilter({{#useGzipFeature}}true{{/useGzipFeature}}{{^useGzipFeature}}false{{/useGzipFeature}}));
if (debugging) {
client.addFilter(new LoggingFilter());
}
@@ -156,6 +215,33 @@ public class ApiClient {
return this;
}
+ public List getServers() {
+ return servers;
+ }
+
+ public ApiClient setServers(List servers) {
+ this.servers = servers;
+ return this;
+ }
+
+ public Integer getServerIndex() {
+ return serverIndex;
+ }
+
+ public ApiClient setServerIndex(Integer serverIndex) {
+ this.serverIndex = serverIndex;
+ return this;
+ }
+
+ public Map getServerVariables() {
+ return serverVariables;
+ }
+
+ public ApiClient setServerVariables(Map serverVariables) {
+ this.serverVariables = serverVariables;
+ return this;
+ }
+
/**
* Gets the status code of the previous request
* @return Status code
@@ -190,6 +276,24 @@ public class ApiClient {
return authentications.get(authName);
}
+ {{#hasHttpBearerMethods}}
+ /**
+ * Helper method to set access token for the first Bearer authentication.
+ * @param bearerToken Bearer token
+ */
+ public void setBearerToken(String bearerToken) {
+ for (Authentication auth : authentications.values()) {
+ if (auth instanceof HttpBearerAuth) {
+ ((HttpBearerAuth) auth).setBearerToken(bearerToken);
+ return;
+ }
+ }
+ throw new RuntimeException("No Bearer authentication configured!");
+ }
+
+ {{/hasHttpBearerMethods}}
+
+ {{#hasHttpBasicMethods}}
/**
* Helper method to set username for the first HTTP basic authentication.
* @param username Username
@@ -218,9 +322,12 @@ public class ApiClient {
throw new RuntimeException("No HTTP basic authentication configured!");
}
+ {{/hasHttpBasicMethods}}
+
+ {{#hasApiKeyMethods}}
/**
* Helper method to set API key value for the first API key authentication.
- * @param apiKey API key
+ * @param apiKey the API key
*/
public void setApiKey(String apiKey) {
for (Authentication auth : authentications.values()) {
@@ -246,6 +353,9 @@ public class ApiClient {
throw new RuntimeException("No API key authentication configured!");
}
+ {{/hasApiKeyMethods}}
+
+ {{#hasOAuthMethods}}
/**
* Helper method to set access token for the first OAuth2 authentication.
* @param accessToken Access token
@@ -260,6 +370,8 @@ public class ApiClient {
throw new RuntimeException("No OAuth2 authentication configured!");
}
+ {{/hasOAuthMethods}}
+
/**
* Set the User-Agent header's value (by adding to the default header map).
* @param userAgent User agent
@@ -282,6 +394,18 @@ public class ApiClient {
return this;
}
+ /**
+ * Add a default cookie.
+ *
+ * @param key The cookie's key
+ * @param value The cookie's value
+ * @return API client
+ */
+ public ApiClient addDefaultCookie(String key, String value) {
+ defaultCookieMap.put(key, value);
+ return this;
+ }
+
/**
* Check that whether debugging is enabled for this API client.
* @return True if debugging is on
@@ -378,7 +502,9 @@ public class ApiClient {
return "";
} else if (param instanceof Date) {
return formatDate((Date) param);
- } else if (param instanceof Collection) {
+ } {{#jsr310}}else if (param instanceof OffsetDateTime) {
+ return formatOffsetDateTime((OffsetDateTime) param);
+ } {{/jsr310}}else if (param instanceof Collection) {
StringBuilder b = new StringBuilder();
for(Object o : (Collection>)param) {
if(b.length() > 0) {
@@ -392,62 +518,71 @@ public class ApiClient {
}
}
- /*
- * Format to {@code Pair} objects.
- * @param collectionFormat Collection format
- * @param name Name
- * @param value Value
- * @return List of pair
+ /**
+ * Formats the specified query parameter to a list containing a single {@code Pair} object.
+ *
+ * Note that {@code value} must not be a collection.
+ *
+ * @param name The name of the parameter.
+ * @param value The value of the parameter.
+ * @return A list containing a single {@code Pair} object.
*/
- public List parameterToPairs(String collectionFormat, String name, Object value){
+ public List parameterToPair(String name, Object value) {
List params = new ArrayList();
// preconditions
- if (name == null || name.isEmpty() || value == null) return params;
+ if (name == null || name.isEmpty() || value == null || value instanceof Collection) return params;
- Collection> valueCollection;
- if (value instanceof Collection>) {
- valueCollection = (Collection>) value;
- } else {
- params.add(new Pair(name, parameterToString(value)));
+ params.add(new Pair(name, parameterToString(value)));
+ return params;
+ }
+
+ /**
+ * Formats the specified collection query parameters to a list of {@code Pair} objects.
+ *
+ * Note that the values of each of the returned Pair objects are percent-encoded.
+ *
+ * @param collectionFormat The collection format of the parameter.
+ * @param name The name of the parameter.
+ * @param value The value of the parameter.
+ * @return A list of {@code Pair} objects.
+ */
+ public List parameterToPairs(String collectionFormat, String name, Collection value) {
+ List params = new ArrayList();
+
+ // preconditions
+ if (name == null || name.isEmpty() || value == null) {
return params;
}
- if (valueCollection.isEmpty()){
- return params;
- }
-
- // get the collection format
- String format = (collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat); // default: csv
-
// create the params based on the collection format
- if ("multi".equals(format)) {
- for (Object item : valueCollection) {
- params.add(new Pair(name, parameterToString(item)));
+ if ("multi".equals(collectionFormat)) {
+ for (Object item : value) {
+ params.add(new Pair(name, escapeString(parameterToString(item))));
}
-
return params;
}
+ // collectionFormat is assumed to be "csv" by default
String delimiter = ",";
- if ("csv".equals(format)) {
- delimiter = ",";
- } else if ("ssv".equals(format)) {
- delimiter = " ";
- } else if ("tsv".equals(format)) {
- delimiter = "\t";
- } else if ("pipes".equals(format)) {
- delimiter = "|";
+ // escape all delimiters except commas, which are URI reserved
+ // characters
+ if ("ssv".equals(collectionFormat)) {
+ delimiter = escapeString(" ");
+ } else if ("tsv".equals(collectionFormat)) {
+ delimiter = escapeString("\t");
+ } else if ("pipes".equals(collectionFormat)) {
+ delimiter = escapeString("|");
}
StringBuilder sb = new StringBuilder() ;
- for (Object item : valueCollection) {
+ for (Object item : value) {
sb.append(delimiter);
- sb.append(parameterToString(item));
+ sb.append(escapeString(parameterToString(item)));
}
- params.add(new Pair(name, sb.substring(1)));
+ params.add(new Pair(name, sb.substring(delimiter.length())));
return params;
}
@@ -458,11 +593,13 @@ public class ApiClient {
* application/json
* application/json; charset=UTF8
* APPLICATION/JSON
+ * application/vnd.company+json
* @param mime MIME
* @return True if MIME type is boolean
*/
public boolean isJsonMime(String mime) {
- return mime != null && mime.matches("(?i)application\\/json(;.*)?");
+ String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$";
+ return mime != null && (mime.matches(jsonMime) || mime.equals("*/*"));
}
/**
@@ -493,10 +630,10 @@ public class ApiClient {
*
* @param contentTypes The Content-Type array to select from
* @return The Content-Type header to use. If the given array is empty,
- * JSON will be used.
+ * or matches "any", JSON will be used.
*/
public String selectHeaderContentType(String[] contentTypes) {
- if (contentTypes.length == 0) {
+ if (contentTypes.length == 0 || contentTypes[0].equals("*/*")) {
return "application/json";
}
for (String contentType : contentTypes) {
@@ -561,11 +698,24 @@ public class ApiClient {
*
* @param path The sub path
* @param queryParams The query parameters
+ * @param collectionQueryParams The collection query parameters
* @return The full URL
*/
- private String buildUrl(String path, List queryParams) {
+ private String buildUrl(String path, List queryParams, List collectionQueryParams) {
+ String baseURL;
+ if (serverIndex != null) {
+ if (serverIndex < 0 || serverIndex >= servers.size()) {
+ throw new ArrayIndexOutOfBoundsException(String.format(
+ "Invalid index %d when selecting the host settings. Must be less than %d", serverIndex, servers.size()
+ ));
+ }
+ baseURL = servers.get(serverIndex).URL(serverVariables);
+ } else {
+ baseURL = basePath;
+ }
+
final StringBuilder url = new StringBuilder();
- url.append(basePath).append(path);
+ url.append(baseURL).append(path);
if (queryParams != null && !queryParams.isEmpty()) {
// support (constant) query string in `path`, e.g. "/posts?draft=1"
@@ -584,17 +734,34 @@ public class ApiClient {
}
}
+ if (collectionQueryParams != null && !collectionQueryParams.isEmpty()) {
+ String prefix = url.toString().contains("?") ? "&" : "?";
+ for (Pair param : collectionQueryParams) {
+ if (param.getValue() != null) {
+ if (prefix != null) {
+ url.append(prefix);
+ prefix = null;
+ } else {
+ url.append("&");
+ }
+ String value = parameterToString(param.getValue());
+ // collection query parameter value already escaped as part of parameterToPairs
+ url.append(escapeString(param.getName())).append("=").append(value);
+ }
+ }
+ }
+
return url.toString();
}
- private ClientResponse getAPIResponse(String path, String method, List queryParams, Object body, Map headerParams, Map formParams, String accept, String contentType, String[] authNames) throws ApiException {
+ private ClientResponse getAPIResponse(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames) throws ApiException {
if (body != null && !formParams.isEmpty()) {
throw new ApiException(500, "Cannot have body and form params");
}
- updateParamsForAuth(authNames, queryParams, headerParams);
+ updateParamsForAuth(authNames, queryParams, headerParams, cookieParams);
- final String url = buildUrl(path, queryParams);
+ final String url = buildUrl(path, queryParams, collectionQueryParams);
Builder builder;
if (accept == null) {
builder = httpClient.resource(url).getRequestBuilder();
@@ -602,12 +769,21 @@ public class ApiClient {
builder = httpClient.resource(url).accept(accept);
}
- for (String key : headerParams.keySet()) {
- builder = builder.header(key, headerParams.get(key));
+ for (Entry keyValue : headerParams.entrySet()) {
+ builder = builder.header(keyValue.getKey(), keyValue.getValue());
}
- for (String key : defaultHeaderMap.keySet()) {
- if (!headerParams.containsKey(key)) {
- builder = builder.header(key, defaultHeaderMap.get(key));
+ for (Map.Entry keyValue : defaultHeaderMap.entrySet()) {
+ if (!headerParams.containsKey(keyValue.getKey())) {
+ builder = builder.header(keyValue.getKey(), keyValue.getValue());
+ }
+ }
+
+ for (Entry keyValue : cookieParams.entrySet()) {
+ builder = builder.cookie(new Cookie(keyValue.getKey(), keyValue.getValue()));
+ }
+ for (Map.Entry keyValue : defaultCookieMap.entrySet()) {
+ if (!cookieParams.containsKey(keyValue.getKey())) {
+ builder = builder.cookie(new Cookie(keyValue.getKey(), keyValue.getValue()));
}
}
@@ -623,8 +799,9 @@ public class ApiClient {
response = builder.type(contentType).delete(ClientResponse.class, serialize(body, contentType, formParams));
} else if ("PATCH".equals(method)) {
response = builder.type(contentType).header("X-HTTP-Method-Override", "PATCH").post(ClientResponse.class, serialize(body, contentType, formParams));
- }
- else {
+ } else if ("HEAD".equals(method)) {
+ response = builder.head();
+ } else {
throw new ApiException(500, "unknown method type " + method);
}
return response;
@@ -637,8 +814,10 @@ public class ApiClient {
* @param path The sub-path of the HTTP URL
* @param method The request method, one of "GET", "POST", "PUT", and "DELETE"
* @param queryParams The query parameters
+ * @param collectionQueryParams The collection query parameters
* @param body The request body object - if it is not binary, otherwise null
* @param headerParams The header parameters
+ * @param cookieParams The cookie parameters
* @param formParams The form parameters
* @param accept The request's Accept header
* @param contentType The request's Content-Type header
@@ -647,9 +826,9 @@ public class ApiClient {
* @return The response body in type of string
* @throws ApiException API exception
*/
- public T invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException {
+ public T invokeAPI(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException {
- ClientResponse response = getAPIResponse(path, method, queryParams, body, headerParams, formParams, accept, contentType, authNames);
+ ClientResponse response = getAPIResponse(path, method, queryParams, collectionQueryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames);
statusCode = response.getStatusInfo().getStatusCode();
responseHeaders = response.getHeaders();
@@ -686,12 +865,13 @@ public class ApiClient {
* @param authNames The authentications to apply
* @param queryParams Query parameters
* @param headerParams Header parameters
+ * @param cookieParams Cookie parameters
*/
- private void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams) {
+ private void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams, Map cookieParams) {
for (String authName : authNames) {
Authentication auth = authentications.get(authName);
if (auth == null) throw new RuntimeException("Authentication undefined: " + authName);
- auth.applyToParams(queryParams, headerParams);
+ auth.applyToParams(queryParams, headerParams, cookieParams);
}
}
diff --git a/modules/openapi-generator/src/test/resources/2_0/templates/Java/libraries/jersey2/ApiClient.mustache b/modules/openapi-generator/src/test/resources/2_0/templates/Java/libraries/jersey2/ApiClient.mustache
index 52c3c06e24c..65494e8ea04 100644
--- a/modules/openapi-generator/src/test/resources/2_0/templates/Java/libraries/jersey2/ApiClient.mustache
+++ b/modules/openapi-generator/src/test/resources/2_0/templates/Java/libraries/jersey2/ApiClient.mustache
@@ -1,5 +1,3 @@
-//overloaded template file within library folder to add this comment
-
package {{invokerPackage}};
import javax.ws.rs.client.Client;
@@ -13,9 +11,12 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
+{{#hasOAuthMethods}}
+import com.github.scribejava.core.model.OAuth2AccessToken;
+{{/hasOAuthMethods}}
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.ClientProperties;
-import org.glassfish.jersey.filter.LoggingFilter;
+import org.glassfish.jersey.client.HttpUrlConnectorProvider;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
@@ -25,22 +26,38 @@ import org.glassfish.jersey.media.multipart.MultiPartFeature;
import java.io.IOException;
import java.io.InputStream;
-{{^supportJava6}}
+import java.net.URI;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import java.security.cert.X509Certificate;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
import java.nio.file.Files;
+import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
-{{/supportJava6}}
-{{#supportJava6}}
-import org.apache.commons.io.FileUtils;
-{{/supportJava6}}
+import org.glassfish.jersey.logging.LoggingFeature;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
+import java.util.Arrays;
import java.util.ArrayList;
import java.util.Date;
-import java.util.TimeZone;
+{{#jsr310}}
+{{#threetenbp}}
+import org.threeten.bp.OffsetDateTime;
+{{/threetenbp}}
+{{^threetenbp}}
+import java.time.OffsetDateTime;
+{{/threetenbp}}
+{{/jsr310}}
import java.net.URLEncoder;
@@ -53,30 +70,120 @@ import java.util.regex.Pattern;
import {{invokerPackage}}.auth.Authentication;
import {{invokerPackage}}.auth.HttpBasicAuth;
+import {{invokerPackage}}.auth.HttpBearerAuth;
+{{#hasHttpSignatureMethods}}
+import {{invokerPackage}}.auth.HttpSignatureAuth;
+{{/hasHttpSignatureMethods}}
import {{invokerPackage}}.auth.ApiKeyAuth;
+{{#hasOAuthMethods}}
import {{invokerPackage}}.auth.OAuth;
+{{/hasOAuthMethods}}
{{>generatedAnnotation}}
-public class ApiClient {
- private Map defaultHeaderMap = new HashMap();
- private String basePath = "{{{basePath}}}";
- private boolean debugging = false;
- private int connectionTimeout = 0;
+public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
+ protected Map defaultHeaderMap = new HashMap();
+ protected Map defaultCookieMap = new HashMap();
+ protected String basePath = "{{{basePath}}}";
+ protected String userAgent;
+ private static final Logger log = Logger.getLogger(ApiClient.class.getName());
- private Client httpClient;
- private JSON json;
- private String tempFolderPath = null;
+ protected List servers = new ArrayList({{#servers}}{{#-first}}Arrays.asList(
+{{/-first}} new ServerConfiguration(
+ "{{{url}}}",
+ "{{{description}}}{{^description}}No description provided{{/description}}",
+ new HashMap(){{#variables}}{{#-first}} {{
+{{/-first}} put("{{{name}}}", new ServerVariable(
+ "{{{description}}}{{^description}}No description provided{{/description}}",
+ "{{{defaultValue}}}",
+ new HashSet