diff --git a/bin/configs/java-okhttp-3.1-duplicated-operationid.yaml b/bin/configs/java-okhttp-3.1-duplicated-operationid.yaml
new file mode 100644
index 000000000000..840948f2aad0
--- /dev/null
+++ b/bin/configs/java-okhttp-3.1-duplicated-operationid.yaml
@@ -0,0 +1,12 @@
+generatorName: java
+outputDir: samples/client/petstore/java/okhttp-3.1-duplicated-operationid
+library: okhttp
+inputSpec: modules/openapi-generator/src/test/resources/3_1/java/duplicated_operationid.yaml
+templateDir: modules/openapi-generator/src/main/resources/Java
+validateSpec: false
+additionalProperties:
+ artifactId: petstore-okhttp-31-do
+ hideGenerationTimestamp: "true"
+ disallowAdditionalPropertiesIfNotPresent: false
+openapiNormalizer:
+ FIX_DUPLICATED_OPERATIONID: true
diff --git a/bin/configs/java-okhttp-3.1.yaml b/bin/configs/java-okhttp-3.1.yaml
new file mode 100644
index 000000000000..97e073fa0c34
--- /dev/null
+++ b/bin/configs/java-okhttp-3.1.yaml
@@ -0,0 +1,20 @@
+generatorName: java
+outputDir: samples/client/petstore/java/okhttp-3.1
+library: okhttp
+inputSpec: modules/openapi-generator/src/test/resources/3_1/java/petstore.yaml
+templateDir: modules/openapi-generator/src/main/resources/Java
+validateSpec: false
+nameMappings:
+ _type: underscoreType
+ type_: typeWithUnderscore
+parameterNameMappings:
+ _type: underscoreType
+ type_: typeWithUnderscore
+additionalProperties:
+ artifactId: petstore-okhttp-31
+ hideGenerationTimestamp: "true"
+ useOneOfDiscriminatorLookup: "true"
+ disallowAdditionalPropertiesIfNotPresent: false
+ enumPropertyNaming: legacy
+openapiNormalizer:
+ FIX_DUPLICATED_OPERATIONID: true
diff --git a/bin/configs/java-okhttp-awsv4signature.yaml b/bin/configs/java-okhttp-awsv4signature.yaml
new file mode 100644
index 000000000000..fb44f3572406
--- /dev/null
+++ b/bin/configs/java-okhttp-awsv4signature.yaml
@@ -0,0 +1,11 @@
+generatorName: java
+outputDir: samples/client/petstore/java/okhttp-awsv4signature
+library: okhttp
+inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
+templateDir: modules/openapi-generator/src/main/resources/Java
+additionalProperties:
+ artifactId: okhttp-awsv4signature
+ hideGenerationTimestamp: "true"
+ useOneOfDiscriminatorLookup: "true"
+ disallowAdditionalPropertiesIfNotPresent: false
+ withAWSV4Signature: true
diff --git a/bin/configs/java-okhttp-dynamicOperations.yaml b/bin/configs/java-okhttp-dynamicOperations.yaml
new file mode 100644
index 000000000000..a59bbb4fb4e2
--- /dev/null
+++ b/bin/configs/java-okhttp-dynamicOperations.yaml
@@ -0,0 +1,9 @@
+generatorName: java
+outputDir: samples/client/petstore/java/okhttp-dynamicOperations
+library: okhttp
+inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml
+templateDir: modules/openapi-generator/src/main/resources/Java
+additionalProperties:
+ artifactId: petstore-okhttp-dynamicoperations
+ hideGenerationTimestamp: "true"
+ dynamicOperations: "true"
diff --git a/bin/configs/java-okhttp-echo-api.yaml b/bin/configs/java-okhttp-echo-api.yaml
new file mode 100644
index 000000000000..ff869505ba04
--- /dev/null
+++ b/bin/configs/java-okhttp-echo-api.yaml
@@ -0,0 +1,8 @@
+generatorName: java
+outputDir: samples/client/echo_api/java/okhttp
+library: okhttp
+inputSpec: modules/openapi-generator/src/test/resources/3_0/echo_api.yaml
+templateDir: modules/openapi-generator/src/main/resources/Java
+additionalProperties:
+ artifactId: echo-api-okhttp
+ hideGenerationTimestamp: "true"
diff --git a/bin/configs/java-okhttp-group-parameter.yaml b/bin/configs/java-okhttp-group-parameter.yaml
new file mode 100644
index 000000000000..cc018e0e5fe5
--- /dev/null
+++ b/bin/configs/java-okhttp-group-parameter.yaml
@@ -0,0 +1,10 @@
+generatorName: java
+outputDir: samples/client/petstore/java/okhttp-group-parameter
+library: okhttp
+inputSpec: modules/openapi-generator/src/test/resources/3_0/java/petstore-group-parameter.yaml
+templateDir: modules/openapi-generator/src/main/resources/Java
+additionalProperties:
+ artifactId: petstore-okhttp-group-parameter
+ hideGenerationTimestamp: "true"
+ disallowAdditionalPropertiesIfNotPresent: false
+ useSingleRequestParameter: true
diff --git a/bin/configs/java-okhttp-gson-user-defined-templates.yaml b/bin/configs/java-okhttp-gson-user-defined-templates.yaml
new file mode 100644
index 000000000000..650c2dc1b195
--- /dev/null
+++ b/bin/configs/java-okhttp-gson-user-defined-templates.yaml
@@ -0,0 +1,17 @@
+generatorName: java
+outputDir: samples/client/echo_api/java/okhttp-gson-user-defined-templates
+library: okhttp-gson
+inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
+templateDir: modules/openapi-generator/src/main/resources/Java
+additionalProperties:
+ hideGenerationTimestamp: "true"
+files:
+ README.mustache:
+ destinationFilename: info.md
+ api_doc.mustache:
+ templateType: APIDocs
+ destinationFilename: Documentation.md
+ pojo.mustache:
+ templateType: Model
+ folder: modelCopy
+ destinationFilename: .java
diff --git a/bin/configs/java-okhttp-jackson.yaml b/bin/configs/java-okhttp-jackson.yaml
new file mode 100644
index 000000000000..591442357762
--- /dev/null
+++ b/bin/configs/java-okhttp-jackson.yaml
@@ -0,0 +1,26 @@
+generatorName: java
+outputDir: samples/client/petstore/java/okhttp-jackson
+library: okhttp
+inputSpec: modules/openapi-generator/src/test/resources/3_0/java/petstore-with-fake-endpoints-models-for-testing-okhttp-gson.yaml
+templateDir: modules/openapi-generator/src/main/resources/Java
+nameMappings:
+ _type: underscoreType
+ type_: typeWithUnderscore
+parameterNameMappings:
+ _type: underscoreType
+ type_: typeWithUnderscore
+additionalProperties:
+ serializationLibrary: jackson
+ defaultToEmptyContainer: "array?|array|map?"
+ artifactId: petstore-okhttp-jackson
+ hideGenerationTimestamp: true
+ useOneOfDiscriminatorLookup: true
+ disallowAdditionalPropertiesIfNotPresent: false
+ useReflectionEqualsHashCode: true
+ removeEnumValuePrefix: true
+enumNameMappings:
+ s: LOWER_CASE_S
+ S: UPPER_CASE_S
+operationIdNameMappings:
+ getArrayOfEnums: getFakeArrayofenums
+ fakeHealthGet: getFakeHealth
diff --git a/bin/configs/java-okhttp-jackson3.yaml b/bin/configs/java-okhttp-jackson3.yaml
new file mode 100644
index 000000000000..f6cfbb543d55
--- /dev/null
+++ b/bin/configs/java-okhttp-jackson3.yaml
@@ -0,0 +1,27 @@
+generatorName: java
+outputDir: samples/client/petstore/java/okhttp-jackson3
+library: okhttp
+inputSpec: modules/openapi-generator/src/test/resources/3_0/java/petstore-with-fake-endpoints-models-for-testing-okhttp-gson.yaml
+templateDir: modules/openapi-generator/src/main/resources/Java
+nameMappings:
+ _type: underscoreType
+ type_: typeWithUnderscore
+parameterNameMappings:
+ _type: underscoreType
+ type_: typeWithUnderscore
+additionalProperties:
+ serializationLibrary: jackson
+ useJackson3: true
+ defaultToEmptyContainer: "array?|array|map?"
+ artifactId: petstore-okhttp-jackson3
+ hideGenerationTimestamp: true
+ useOneOfDiscriminatorLookup: true
+ disallowAdditionalPropertiesIfNotPresent: false
+ useReflectionEqualsHashCode: true
+ removeEnumValuePrefix: true
+enumNameMappings:
+ s: LOWER_CASE_S
+ S: UPPER_CASE_S
+operationIdNameMappings:
+ getArrayOfEnums: getFakeArrayofenums
+ fakeHealthGet: getFakeHealth
diff --git a/bin/configs/java-okhttp-jsonb.yaml b/bin/configs/java-okhttp-jsonb.yaml
new file mode 100644
index 000000000000..7c09beba0903
--- /dev/null
+++ b/bin/configs/java-okhttp-jsonb.yaml
@@ -0,0 +1,27 @@
+generatorName: java
+outputDir: samples/client/petstore/java/okhttp-jsonb
+library: okhttp
+inputSpec: modules/openapi-generator/src/test/resources/3_0/java/petstore-with-fake-endpoints-models-for-testing-okhttp-gson.yaml
+templateDir: modules/openapi-generator/src/main/resources/Java
+nameMappings:
+ _type: underscoreType
+ type_: typeWithUnderscore
+parameterNameMappings:
+ _type: underscoreType
+ type_: typeWithUnderscore
+additionalProperties:
+ serializationLibrary: jsonb
+ useJakartaEe: true
+ defaultToEmptyContainer: "array?|array|map?"
+ artifactId: petstore-okhttp-jsonb
+ hideGenerationTimestamp: true
+ useOneOfDiscriminatorLookup: true
+ disallowAdditionalPropertiesIfNotPresent: false
+ useReflectionEqualsHashCode: true
+ removeEnumValuePrefix: true
+enumNameMappings:
+ s: LOWER_CASE_S
+ S: UPPER_CASE_S
+operationIdNameMappings:
+ getArrayOfEnums: getFakeArrayofenums
+ fakeHealthGet: getFakeHealth
diff --git a/bin/configs/java-okhttp-jspecify.yaml b/bin/configs/java-okhttp-jspecify.yaml
new file mode 100644
index 000000000000..65c392833045
--- /dev/null
+++ b/bin/configs/java-okhttp-jspecify.yaml
@@ -0,0 +1,13 @@
+generatorName: java
+outputDir: samples/client/petstore/java/okhttp-jspecify
+library: okhttp
+inputSpec: modules/openapi-generator/src/test/resources/3_0/java/okhttp-jspecify.yaml
+templateDir: modules/openapi-generator/src/main/resources/Java
+additionalProperties:
+ artifactId: petstore-okhttp-jspecify
+ hideGenerationTimestamp: true
+ useJspecify: true
+ containerDefaultToNull: true
+typeMappings:
+ OffsetDateTime: java.time.Instant
+ BigDecimal: java.math.BigDecimal
diff --git a/bin/configs/java-okhttp-nullable-required.yaml b/bin/configs/java-okhttp-nullable-required.yaml
new file mode 100644
index 000000000000..bcbea4844bf5
--- /dev/null
+++ b/bin/configs/java-okhttp-nullable-required.yaml
@@ -0,0 +1,10 @@
+generatorName: java
+outputDir: samples/client/petstore/java/okhttp-nullable-required
+library: okhttp
+inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-with-nullable-required.yaml
+templateDir: modules/openapi-generator/src/main/resources/Java
+additionalProperties:
+ artifactId: nullable-required-okhttp
+ hideGenerationTimestamp: "true"
+ useOneOfDiscriminatorLookup: "true"
+ disallowAdditionalPropertiesIfNotPresent: false
diff --git a/bin/configs/java-okhttp-oneOf-array.yaml b/bin/configs/java-okhttp-oneOf-array.yaml
new file mode 100644
index 000000000000..0b08167db70e
--- /dev/null
+++ b/bin/configs/java-okhttp-oneOf-array.yaml
@@ -0,0 +1,8 @@
+generatorName: java
+outputDir: samples/client/others/java/okhttp-oneOf-array
+library: okhttp
+inputSpec: modules/openapi-generator/src/test/resources/3_0/oneOf_array.yaml
+templateDir: modules/openapi-generator/src/main/resources/Java
+additionalProperties:
+ hideGenerationTimestamp: "true"
+ useBeanValidation: "true"
diff --git a/bin/configs/java-okhttp-oneOf.yaml b/bin/configs/java-okhttp-oneOf.yaml
new file mode 100644
index 000000000000..41349c2cb740
--- /dev/null
+++ b/bin/configs/java-okhttp-oneOf.yaml
@@ -0,0 +1,7 @@
+generatorName: java
+outputDir: samples/client/others/java/okhttp-oneOf
+library: okhttp
+inputSpec: modules/openapi-generator/src/test/resources/3_0/oneOf_twoPrimitives.yaml
+templateDir: modules/openapi-generator/src/main/resources/Java
+additionalProperties:
+ hideGenerationTimestamp: "true"
diff --git a/bin/configs/java-okhttp-parcelableModel.yaml b/bin/configs/java-okhttp-parcelableModel.yaml
new file mode 100644
index 000000000000..fcd784ad575b
--- /dev/null
+++ b/bin/configs/java-okhttp-parcelableModel.yaml
@@ -0,0 +1,9 @@
+generatorName: java
+outputDir: samples/client/petstore/java/okhttp-parcelableModel
+library: okhttp
+inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml
+templateDir: modules/openapi-generator/src/main/resources/Java
+additionalProperties:
+ parcelableModel: "true"
+ artifactId: petstore-okhttp-parcelableModel
+ hideGenerationTimestamp: "true"
diff --git a/bin/configs/java-okhttp-streaming.yaml b/bin/configs/java-okhttp-streaming.yaml
new file mode 100644
index 000000000000..d05edb2dfa2b
--- /dev/null
+++ b/bin/configs/java-okhttp-streaming.yaml
@@ -0,0 +1,11 @@
+generatorName: java
+outputDir: samples/client/others/java/okhttp-streaming
+library: okhttp
+inputSpec: modules/openapi-generator/src/test/resources/3_0/streaming.yaml
+templateDir: modules/openapi-generator/src/main/resources/Java
+additionalProperties:
+ artifactId: petstore-okhttp
+ hideGenerationTimestamp: "true"
+ supportStreaming: true
+ serializableModel: true
+ enumPropertyNaming: legacy
diff --git a/bin/configs/java-okhttp-swagger1.yaml b/bin/configs/java-okhttp-swagger1.yaml
new file mode 100644
index 000000000000..acc00784b891
--- /dev/null
+++ b/bin/configs/java-okhttp-swagger1.yaml
@@ -0,0 +1,13 @@
+generatorName: java
+outputDir: samples/client/petstore/java/okhttp-swagger1
+library: okhttp
+inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
+templateDir: modules/openapi-generator/src/main/resources/Java
+additionalProperties:
+ artifactId: petstore-okhttp
+ hideGenerationTimestamp: "true"
+ useOneOfDiscriminatorLookup: "true"
+ disallowAdditionalPropertiesIfNotPresent: false
+ annotationLibrary: "swagger1"
+openapiNormalizer:
+ SET_TAGS_FOR_ALL_OPERATIONS: common
diff --git a/bin/configs/java-okhttp-swagger2.yaml b/bin/configs/java-okhttp-swagger2.yaml
new file mode 100644
index 000000000000..d029804c8d4c
--- /dev/null
+++ b/bin/configs/java-okhttp-swagger2.yaml
@@ -0,0 +1,11 @@
+generatorName: java
+outputDir: samples/client/petstore/java/okhttp-swagger2
+library: okhttp
+inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
+templateDir: modules/openapi-generator/src/main/resources/Java
+additionalProperties:
+ artifactId: petstore-okhttp
+ hideGenerationTimestamp: "true"
+ useOneOfDiscriminatorLookup: "true"
+ disallowAdditionalPropertiesIfNotPresent: false
+ annotationLibrary: "swagger2"
diff --git a/bin/configs/java-okhttp.yaml b/bin/configs/java-okhttp.yaml
new file mode 100644
index 000000000000..936fbfbed3b6
--- /dev/null
+++ b/bin/configs/java-okhttp.yaml
@@ -0,0 +1,25 @@
+generatorName: java
+outputDir: samples/client/petstore/java/okhttp
+library: okhttp
+inputSpec: modules/openapi-generator/src/test/resources/3_0/java/petstore-with-fake-endpoints-models-for-testing-okhttp-gson.yaml
+templateDir: modules/openapi-generator/src/main/resources/Java
+nameMappings:
+ _type: underscoreType
+ type_: typeWithUnderscore
+parameterNameMappings:
+ _type: underscoreType
+ type_: typeWithUnderscore
+additionalProperties:
+ defaultToEmptyContainer: "array?|array|map?"
+ artifactId: petstore-okhttp
+ hideGenerationTimestamp: true
+ useOneOfDiscriminatorLookup: true
+ disallowAdditionalPropertiesIfNotPresent: false
+ useReflectionEqualsHashCode: true
+ removeEnumValuePrefix: true
+enumNameMappings:
+ s: LOWER_CASE_S
+ S: UPPER_CASE_S
+operationIdNameMappings:
+ getArrayOfEnums: getFakeArrayofenums
+ fakeHealthGet: getFakeHealth
diff --git a/docs/generators/java-microprofile.md b/docs/generators/java-microprofile.md
index 2dfaf5e0bcf4..01cbe2f9ebd2 100644
--- a/docs/generators/java-microprofile.md
+++ b/docs/generators/java-microprofile.md
@@ -32,7 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|bigDecimalAsString|Treat BigDecimal values as Strings to avoid precision loss.| |false|
|booleanGetterPrefix|Set booleanGetterPrefix| |get|
|camelCaseDollarSign|Fix camelCase when starting with $ sign. when true : $Value when false : $value| |false|
-|caseInsensitiveResponseHeaders|Make API response's headers case-insensitive. Available on okhttp-gson, jersey2 libraries| |false|
+|caseInsensitiveResponseHeaders|Make API response's headers case-insensitive. Available on okhttp-gson, jersey2, and okhttp libraries| |false|
|configKey|Config key in @RegisterRestClient. Default to none. Only `microprofile` supports this option.| |null|
|configKeyFromClassName|If true, set tag as key in @RegisterRestClient. Default to false. Only `microprofile` supports this option.| |null|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
@@ -51,7 +51,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true|
|enumPropertyNaming|Naming convention for enum properties: 'MACRO_CASE', 'legacy' and 'original'| |MACRO_CASE|
|enumUnknownDefaultCase|If the server adds new enum cases, that are unknown by an old spec/client, the client will fail to parse the network response. With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the server sends an enum case that is not known by the client/spec, they can safely fallback to this case.|
**false** No changes to the enums are made, this is the default option. **true** With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the enum case sent by the server is not known by the client/spec, can safely be decoded to this case. |false|
-|errorObjectType|Error Object type. (This option is for okhttp-gson only)| |null|
+|errorObjectType|Error Object type. (This option is for okhttp-gson and okhttp only)| |null|
|failOnUnknownProperties|Fail Jackson de-serialization on unknown properties| |false|
|generateBuilders|Whether to generate builders for models| |false|
|generateClientAsBean|For resttemplate, restclient and webclient, configure whether to create `ApiClient.java` and Apis clients as bean (with `@Component` annotation).| |false|
@@ -64,7 +64,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|implicitHeadersRegex|Skip header parameters that matches given regex in the generated API methods using @ApiImplicitParams annotation. Note: this parameter is ignored when implicitHeaders=true| |null|
|invokerPackage|root package for generated code| |org.openapitools.client|
|legacyDiscriminatorBehavior|Set to false for generators with better support for discriminators. (Python, Java, Go, PowerShell, C# have this enabled by default).|**true** The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document. **false** The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing. |true|
-|library|library template (sub-template) to use|**jersey2** HTTP client: Jersey client 2.25.1. JSON processing: Jackson 2.18.9 **jersey3** HTTP client: Jersey client 3.1.11. JSON processing: Jackson 2.x (3.x if `useJackson3=true`, requires Java 17+) **feign** HTTP client: OpenFeign 13.2.1. JSON processing: Jackson 2.18.9 or Gson 2.10.1 **feign-hc5** HTTP client: OpenFeign 13.2.1/HttpClient5 5.4.2. JSON processing: Jackson 2.18.9 or Gson 2.10.1 **okhttp-gson** [DEFAULT] HTTP client: OkHttp 4.11.0. JSON processing: Gson 2.10.1. Enable Parcelable models on Android using '-DparcelableModel=true'. Enable gzip request encoding using '-DuseGzipFeature=true'. **retrofit2** HTTP client: OkHttp 4.11.0. JSON processing: Gson 2.10.1 (Retrofit 2.5.0) or Jackson 2.18.9. Enable the RxJava adapter using '-DuseRxJava[2/3]=true'. (RxJava 1.x or 2.x or 3.x) **resttemplate** HTTP client: Spring RestTemplate 5.3.33 (6.2.x if `useJakartaEe=true`, 7.x.x if `useSpringBoot4=true`). JSON processing: Jackson 2.x (3.x if `useJackson3=true`) **webclient** HTTP client: Spring WebClient 5.1.18 (7.x.x if `useSpringBoot4=true`). JSON processing: Jackson 2.18.9 (3.x if `useJackson3=true`) **restclient** HTTP client: Spring RestClient 6.1.6 (7.x.x if `useSpringBoot4=true`). JSON processing: Jackson 2.18.9 (3.x if `useJackson3=true`) **resteasy** HTTP client: Resteasy client 4.7.6. JSON processing: Jackson 2.18.9 **vertx** HTTP client: VertX client 3.5.2. JSON processing: Jackson 2.18.9 **google-api-client** HTTP client: Google API client 2.2.0. JSON processing: Jackson 2.18.9 **rest-assured** HTTP client: rest-assured 5.3.2. JSON processing: Gson 2.10.1 or Jackson 2.18.9. Only for Java 8 **native** HTTP client: Java native HttpClient. JSON processing: Jackson 2.18.9 (3.x if `useJackson3=true`). Only for Java11+ **microprofile** HTTP client: Microprofile client 2.0 (default, set desired version via `microprofileRestClientVersion=x.x.x`). JSON processing: JSON-B 1.0.2 or Jackson 2.18.9 **apache-httpclient** HTTP client: Apache httpclient 5.2.1. JSON processing: Jackson 2.18.9 (3.x if `useJackson3=true`) |okhttp-gson|
+|library|library template (sub-template) to use|**jersey2** HTTP client: Jersey client 2.25.1. JSON processing: Jackson 2.18.9 **jersey3** HTTP client: Jersey client 3.1.11. JSON processing: Jackson 2.x (3.x if `useJackson3=true`, requires Java 17+) **feign** HTTP client: OpenFeign 13.2.1. JSON processing: Jackson 2.18.9 or Gson 2.10.1 **feign-hc5** HTTP client: OpenFeign 13.2.1/HttpClient5 5.4.2. JSON processing: Jackson 2.18.9 or Gson 2.10.1 **okhttp-gson** [DEFAULT] HTTP client: OkHttp 4.11.0. JSON processing: Gson 2.10.1. Enable Parcelable models on Android using '-DparcelableModel=true'. Enable gzip request encoding using '-DuseGzipFeature=true'. **okhttp** HTTP client: OkHttp 5.4.0. JSON processing: Gson 2.10.1, Jackson 2.x/3.x, or JSON-B. Enable Parcelable models on Android using '-DparcelableModel=true'. Enable gzip request encoding using '-DuseGzipFeature=true'. **retrofit2** HTTP client: OkHttp 4.11.0. JSON processing: Gson 2.10.1 (Retrofit 2.5.0) or Jackson 2.18.9. Enable the RxJava adapter using '-DuseRxJava[2/3]=true'. (RxJava 1.x or 2.x or 3.x) **resttemplate** HTTP client: Spring RestTemplate 5.3.33 (6.2.x if `useJakartaEe=true`, 7.x.x if `useSpringBoot4=true`). JSON processing: Jackson 2.x (3.x if `useJackson3=true`) **webclient** HTTP client: Spring WebClient 5.1.18 (7.x.x if `useSpringBoot4=true`). JSON processing: Jackson 2.18.9 (3.x if `useJackson3=true`) **restclient** HTTP client: Spring RestClient 6.1.6 (7.x.x if `useSpringBoot4=true`). JSON processing: Jackson 2.18.9 (3.x if `useJackson3=true`) **resteasy** HTTP client: Resteasy client 4.7.6. JSON processing: Jackson 2.18.9 **vertx** HTTP client: VertX client 3.5.2. JSON processing: Jackson 2.18.9 **google-api-client** HTTP client: Google API client 2.2.0. JSON processing: Jackson 2.18.9 **rest-assured** HTTP client: rest-assured 5.3.2. JSON processing: Gson 2.10.1 or Jackson 2.18.9. Only for Java 8 **native** HTTP client: Java native HttpClient. JSON processing: Jackson 2.18.9 (3.x if `useJackson3=true`). Only for Java11+ **microprofile** HTTP client: Microprofile client 2.0 (default, set desired version via `microprofileRestClientVersion=x.x.x`). JSON processing: JSON-B 1.0.2 or Jackson 2.18.9 **apache-httpclient** HTTP client: Apache httpclient 5.2.1. JSON processing: Jackson 2.18.9 (3.x if `useJackson3=true`) |okhttp-gson|
|licenseName|The name of the license| |Unlicense|
|licenseUrl|The URL of the license| |http://unlicense.org|
|microprofileFramework|Framework for microprofile. Possible values "kumuluzee"| |null|
@@ -74,7 +74,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|microprofileRestClientVersion|Version of MicroProfile Rest Client API.| |null|
|modelPackage|package for generated models| |org.openapitools.client.model|
|openApiNullable|Enable OpenAPI Jackson Nullable library. Not supported by `microprofile` library.| |true|
-|parcelableModel|Whether to generate models for Android that implement Parcelable with the okhttp-gson library.| |false|
+|parcelableModel|Whether to generate models for Android that implement Parcelable with the okhttp-gson and okhttp libraries.| |false|
|parentArtifactId|parent artifactId in generated pom N.B. parentGroupId, parentArtifactId and parentVersion must all be specified for any of them to take effect| |null|
|parentGroupId|parent groupId in generated pom N.B. parentGroupId, parentArtifactId and parentVersion must all be specified for any of them to take effect| |null|
|parentVersion|parent version in generated pom N.B. parentGroupId, parentArtifactId and parentVersion must all be specified for any of them to take effect| |null|
@@ -90,7 +90,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|sourceFolder|source folder for generated code| |src/main/java|
|supportStreaming|Support streaming endpoint (beta)| |false|
-|supportUrlQuery|Generate toUrlQueryString in POJO (default to true). Available on `native`, `apache-httpclient` libraries.| |false|
+|supportUrlQuery|Generate toUrlQueryString in POJO (default to true). Available on `native`, `apache-httpclient`, `okhttp`, `feign`, `restclient`, `resttemplate`, `webclient` libraries.| |false|
|supportVertxFuture|Also generate api methods that return a vertx Future instead of taking a callback. Only `vertx` supports this option. Requires vertx 4 or greater.| |false|
|testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi|
|useAbstractionForFiles|Use alternative types instead of java.io.File to allow passing bytes without a file on disk. Available on resttemplate, webclient, restclient, libraries| |false|
@@ -98,23 +98,23 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|useDeductionForOneOfInterfaces|Annotate discriminator-free oneOf interfaces with Jackson's @JsonTypeInfo(use = Id.DEDUCTION) and @JsonSubTypes so the concrete subtype is resolved from the JSON field set rather than a type-tag property. Has no effect when a discriminator is present (name-based resolution is used instead). Requires subtypes to have structurally distinct sets of properties.| |false|
|useEnumCaseInsensitive|Use `equalsIgnoreCase` when String for enum comparison| |false|
|useGzipFeature|Send gzip-encoded requests| |false|
-|useJackson3|Use Jackson 3 instead of Jackson 2. Supported for 'native', 'apache-httpclient', and 'jersey3' libraries (requires Java 17+) and for Spring 'resttemplate', 'webclient', and 'restclient' libraries (require useSpringBoot4=true).| |false|
+|useJackson3|Use Jackson 3 instead of Jackson 2. Supported for 'native', 'apache-httpclient', 'jersey3', and 'okhttp' libraries (requires Java 17+) and for Spring 'resttemplate', 'webclient', and 'restclient' libraries (require useSpringBoot4=true).| |false|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
-|useJspecify|Use Jspecify for null checks. Only supported for [native, restclient, resttemplate, webclient]| |false|
-|useOneOfDiscriminatorLookup|Use the discriminator's mapping in oneOf to speed up the model lookup. IMPORTANT: Validation (e.g. one and only one match in oneOf's schemas) will be skipped. Only jersey2, jersey3, native, okhttp-gson support this option.| |false|
+|useJspecify|Use Jspecify for null checks. Only supported for [native, okhttp, restclient, resttemplate, webclient]| |false|
+|useOneOfDiscriminatorLookup|Use the discriminator's mapping in oneOf to speed up the model lookup. IMPORTANT: Validation (e.g. one and only one match in oneOf's schemas) will be skipped. Only jersey2, jersey3, native, okhttp-gson, okhttp support this option.| |false|
|useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |false|
|usePlayWS|Use Play! Async HTTP client (Play WS API)| |false|
|useReflectionEqualsHashCode|Use org.apache.commons.lang3.builder for equals and hashCode in the models. WARNING: This will fail under a security manager, unless the appropriate permissions are set up correctly and also there's potential performance impact.| |false|
-|useRuntimeException|Use RuntimeException instead of Exception. Only jersey2, jersey3, okhttp-gson, vertx, microprofile support this option.| |false|
+|useRuntimeException|Use RuntimeException instead of Exception. Only jersey2, jersey3, okhttp-gson, okhttp, vertx, microprofile support this option.| |false|
|useRxJava2|Whether to use the RxJava2 adapter with the retrofit2 library. IMPORTANT: This option has been deprecated.| |false|
|useRxJava3|Whether to use the RxJava3 adapter with the retrofit2 library. IMPORTANT: This option has been deprecated.| |false|
|useSealedOneOfInterfaces|Generate the oneOf interfaces as sealed interfaces. Only supported for WebClient, RestClient and Microprofile (with Jackson).| |false|
-|useSingleRequestParameter|Setting this property to "true" will generate functions with a single argument containing all API endpoint parameters instead of one argument per parameter. ONLY native, jersey2, jersey3, okhttp-gson, microprofile, Spring RestClient, Spring WebClient support this option. Setting this property to "static" does the same as "true", but also makes the generated arguments class static with single parameter instantiation.| |false|
+|useSingleRequestParameter|Setting this property to "true" will generate functions with a single argument containing all API endpoint parameters instead of one argument per parameter. ONLY native, jersey2, jersey3, okhttp-gson, okhttp, microprofile, Spring RestClient, Spring WebClient support this option. Setting this property to "static" does the same as "true", but also makes the generated arguments class static with single parameter instantiation.| |false|
|useSpringBoot4|Generate code and provide dependencies for use with Spring Boot 4.x.| |false|
|useUnaryInterceptor|If true it will generate ResponseInterceptors using a UnaryOperator. This can be usefull for manipulating the request before it gets passed, for example doing your own decryption| |false|
|useVertx5|Whether to use Vert.x 5 syntax.| |false|
|webclientBlockingOperations|Making all WebClient operations blocking(sync). Note that if on operation 'x-webclient-blocking: false' then such operation won't be sync| |false|
-|withAWSV4Signature|whether to include AWS v4 signature support (only available for okhttp-gson library)| |false|
+|withAWSV4Signature|whether to include AWS v4 signature support (only available for okhttp-gson and okhttp libraries)| |false|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|
## SUPPORTED VENDOR EXTENSIONS
diff --git a/docs/generators/java.md b/docs/generators/java.md
index 6740780102b9..aa4f8fcb02e3 100644
--- a/docs/generators/java.md
+++ b/docs/generators/java.md
@@ -11,7 +11,7 @@ title: Documentation for the java Generator
| generator type | CLIENT | |
| generator language | Java | |
| generator default templating engine | mustache | |
-| helpTxt | Generates a Java client library (HTTP lib: Jersey (1.x, 2.x), Retrofit (2.x), OpenFeign (10.x) and more. | |
+| helpTxt | Generates a Java client library (HTTP lib: Jersey (1.x, 2.x), Retrofit (2.x), OpenFeign (10.x), OkHttp and more. | |
## CONFIG OPTIONS
These options may be applied as additional-properties (cli) or configOptions (plugins). Refer to [configuration docs](https://openapi-generator.tech/docs/configuration) for more details.
@@ -32,7 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|bigDecimalAsString|Treat BigDecimal values as Strings to avoid precision loss.| |false|
|booleanGetterPrefix|Set booleanGetterPrefix| |get|
|camelCaseDollarSign|Fix camelCase when starting with $ sign. when true : $Value when false : $value| |false|
-|caseInsensitiveResponseHeaders|Make API response's headers case-insensitive. Available on okhttp-gson, jersey2 libraries| |false|
+|caseInsensitiveResponseHeaders|Make API response's headers case-insensitive. Available on okhttp-gson, jersey2, and okhttp libraries| |false|
|configKey|Config key in @RegisterRestClient. Default to none. Only `microprofile` supports this option.| |null|
|configKeyFromClassName|If true, set tag as key in @RegisterRestClient. Default to false. Only `microprofile` supports this option.| |null|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
@@ -51,7 +51,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true|
|enumPropertyNaming|Naming convention for enum properties: 'MACRO_CASE', 'legacy' and 'original'| |MACRO_CASE|
|enumUnknownDefaultCase|If the server adds new enum cases, that are unknown by an old spec/client, the client will fail to parse the network response. With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the server sends an enum case that is not known by the client/spec, they can safely fallback to this case.|**false** No changes to the enums are made, this is the default option. **true** With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the enum case sent by the server is not known by the client/spec, can safely be decoded to this case. |false|
-|errorObjectType|Error Object type. (This option is for okhttp-gson only)| |null|
+|errorObjectType|Error Object type. (This option is for okhttp-gson and okhttp only)| |null|
|failOnUnknownProperties|Fail Jackson de-serialization on unknown properties| |false|
|generateBuilders|Whether to generate builders for models| |false|
|generateClientAsBean|For resttemplate, restclient and webclient, configure whether to create `ApiClient.java` and Apis clients as bean (with `@Component` annotation).| |false|
@@ -64,7 +64,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|implicitHeadersRegex|Skip header parameters that matches given regex in the generated API methods using @ApiImplicitParams annotation. Note: this parameter is ignored when implicitHeaders=true| |null|
|invokerPackage|root package for generated code| |org.openapitools.client|
|legacyDiscriminatorBehavior|Set to false for generators with better support for discriminators. (Python, Java, Go, PowerShell, C# have this enabled by default).|**true** The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document. **false** The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing. |true|
-|library|library template (sub-template) to use|**jersey2** HTTP client: Jersey client 2.25.1. JSON processing: Jackson 2.18.9 **jersey3** HTTP client: Jersey client 3.1.11. JSON processing: Jackson 2.x (3.x if `useJackson3=true`, requires Java 17+) **feign** HTTP client: OpenFeign 13.2.1. JSON processing: Jackson 2.18.9 or Gson 2.10.1 **feign-hc5** HTTP client: OpenFeign 13.2.1/HttpClient5 5.4.2. JSON processing: Jackson 2.18.9 or Gson 2.10.1 **okhttp-gson** [DEFAULT] HTTP client: OkHttp 4.11.0. JSON processing: Gson 2.10.1. Enable Parcelable models on Android using '-DparcelableModel=true'. Enable gzip request encoding using '-DuseGzipFeature=true'. **retrofit2** HTTP client: OkHttp 4.11.0. JSON processing: Gson 2.10.1 (Retrofit 2.5.0) or Jackson 2.18.9. Enable the RxJava adapter using '-DuseRxJava[2/3]=true'. (RxJava 1.x or 2.x or 3.x) **resttemplate** HTTP client: Spring RestTemplate 5.3.33 (6.2.x if `useJakartaEe=true`, 7.x.x if `useSpringBoot4=true`). JSON processing: Jackson 2.x (3.x if `useJackson3=true`) **webclient** HTTP client: Spring WebClient 5.1.18 (7.x.x if `useSpringBoot4=true`). JSON processing: Jackson 2.18.9 (3.x if `useJackson3=true`) **restclient** HTTP client: Spring RestClient 6.1.6 (7.x.x if `useSpringBoot4=true`). JSON processing: Jackson 2.18.9 (3.x if `useJackson3=true`) **resteasy** HTTP client: Resteasy client 4.7.6. JSON processing: Jackson 2.18.9 **vertx** HTTP client: VertX client 3.5.2. JSON processing: Jackson 2.18.9 **google-api-client** HTTP client: Google API client 2.2.0. JSON processing: Jackson 2.18.9 **rest-assured** HTTP client: rest-assured 5.3.2. JSON processing: Gson 2.10.1 or Jackson 2.18.9. Only for Java 8 **native** HTTP client: Java native HttpClient. JSON processing: Jackson 2.18.9 (3.x if `useJackson3=true`). Only for Java11+ **microprofile** HTTP client: Microprofile client 2.0 (default, set desired version via `microprofileRestClientVersion=x.x.x`). JSON processing: JSON-B 1.0.2 or Jackson 2.18.9 **apache-httpclient** HTTP client: Apache httpclient 5.2.1. JSON processing: Jackson 2.18.9 (3.x if `useJackson3=true`) |okhttp-gson|
+|library|library template (sub-template) to use|**jersey2** HTTP client: Jersey client 2.25.1. JSON processing: Jackson 2.18.9 **jersey3** HTTP client: Jersey client 3.1.11. JSON processing: Jackson 2.x (3.x if `useJackson3=true`, requires Java 17+) **feign** HTTP client: OpenFeign 13.2.1. JSON processing: Jackson 2.18.9 or Gson 2.10.1 **feign-hc5** HTTP client: OpenFeign 13.2.1/HttpClient5 5.4.2. JSON processing: Jackson 2.18.9 or Gson 2.10.1 **okhttp-gson** [DEFAULT] HTTP client: OkHttp 4.11.0. JSON processing: Gson 2.10.1. Enable Parcelable models on Android using '-DparcelableModel=true'. Enable gzip request encoding using '-DuseGzipFeature=true'. **okhttp** HTTP client: OkHttp 5.4.0. JSON processing: Gson 2.10.1, Jackson 2.x/3.x, or JSON-B. Enable Parcelable models on Android using '-DparcelableModel=true'. Enable gzip request encoding using '-DuseGzipFeature=true'. **retrofit2** HTTP client: OkHttp 4.11.0. JSON processing: Gson 2.10.1 (Retrofit 2.5.0) or Jackson 2.18.9. Enable the RxJava adapter using '-DuseRxJava[2/3]=true'. (RxJava 1.x or 2.x or 3.x) **resttemplate** HTTP client: Spring RestTemplate 5.3.33 (6.2.x if `useJakartaEe=true`, 7.x.x if `useSpringBoot4=true`). JSON processing: Jackson 2.x (3.x if `useJackson3=true`) **webclient** HTTP client: Spring WebClient 5.1.18 (7.x.x if `useSpringBoot4=true`). JSON processing: Jackson 2.18.9 (3.x if `useJackson3=true`) **restclient** HTTP client: Spring RestClient 6.1.6 (7.x.x if `useSpringBoot4=true`). JSON processing: Jackson 2.18.9 (3.x if `useJackson3=true`) **resteasy** HTTP client: Resteasy client 4.7.6. JSON processing: Jackson 2.18.9 **vertx** HTTP client: VertX client 3.5.2. JSON processing: Jackson 2.18.9 **google-api-client** HTTP client: Google API client 2.2.0. JSON processing: Jackson 2.18.9 **rest-assured** HTTP client: rest-assured 5.3.2. JSON processing: Gson 2.10.1 or Jackson 2.18.9. Only for Java 8 **native** HTTP client: Java native HttpClient. JSON processing: Jackson 2.18.9 (3.x if `useJackson3=true`). Only for Java11+ **microprofile** HTTP client: Microprofile client 2.0 (default, set desired version via `microprofileRestClientVersion=x.x.x`). JSON processing: JSON-B 1.0.2 or Jackson 2.18.9 **apache-httpclient** HTTP client: Apache httpclient 5.2.1. JSON processing: Jackson 2.18.9 (3.x if `useJackson3=true`) |okhttp-gson|
|licenseName|The name of the license| |Unlicense|
|licenseUrl|The URL of the license| |http://unlicense.org|
|microprofileFramework|Framework for microprofile. Possible values "kumuluzee"| |null|
@@ -74,7 +74,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|microprofileRestClientVersion|Version of MicroProfile Rest Client API.| |null|
|modelPackage|package for generated models| |org.openapitools.client.model|
|openApiNullable|Enable OpenAPI Jackson Nullable library. Not supported by `microprofile` library.| |true|
-|parcelableModel|Whether to generate models for Android that implement Parcelable with the okhttp-gson library.| |false|
+|parcelableModel|Whether to generate models for Android that implement Parcelable with the okhttp-gson and okhttp libraries.| |false|
|parentArtifactId|parent artifactId in generated pom N.B. parentGroupId, parentArtifactId and parentVersion must all be specified for any of them to take effect| |null|
|parentGroupId|parent groupId in generated pom N.B. parentGroupId, parentArtifactId and parentVersion must all be specified for any of them to take effect| |null|
|parentVersion|parent version in generated pom N.B. parentGroupId, parentArtifactId and parentVersion must all be specified for any of them to take effect| |null|
@@ -90,7 +90,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|sourceFolder|source folder for generated code| |src/main/java|
|supportStreaming|Support streaming endpoint (beta)| |false|
-|supportUrlQuery|Generate toUrlQueryString in POJO (default to true). Available on `native`, `apache-httpclient` libraries.| |false|
+|supportUrlQuery|Generate toUrlQueryString in POJO (default to true). Available on `native`, `apache-httpclient`, `okhttp`, `feign`, `restclient`, `resttemplate`, `webclient` libraries.| |false|
|supportVertxFuture|Also generate api methods that return a vertx Future instead of taking a callback. Only `vertx` supports this option. Requires vertx 4 or greater.| |false|
|testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi|
|useAbstractionForFiles|Use alternative types instead of java.io.File to allow passing bytes without a file on disk. Available on resttemplate, webclient, restclient, libraries| |false|
@@ -98,23 +98,23 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|useDeductionForOneOfInterfaces|Annotate discriminator-free oneOf interfaces with Jackson's @JsonTypeInfo(use = Id.DEDUCTION) and @JsonSubTypes so the concrete subtype is resolved from the JSON field set rather than a type-tag property. Has no effect when a discriminator is present (name-based resolution is used instead). Requires subtypes to have structurally distinct sets of properties.| |false|
|useEnumCaseInsensitive|Use `equalsIgnoreCase` when String for enum comparison| |false|
|useGzipFeature|Send gzip-encoded requests| |false|
-|useJackson3|Use Jackson 3 instead of Jackson 2. Supported for 'native', 'apache-httpclient', and 'jersey3' libraries (requires Java 17+) and for Spring 'resttemplate', 'webclient', and 'restclient' libraries (require useSpringBoot4=true).| |false|
+|useJackson3|Use Jackson 3 instead of Jackson 2. Supported for 'native', 'apache-httpclient', 'jersey3', and 'okhttp' libraries (requires Java 17+) and for Spring 'resttemplate', 'webclient', and 'restclient' libraries (require useSpringBoot4=true).| |false|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
-|useJspecify|Use Jspecify for null checks. Only supported for [native, restclient, resttemplate, webclient]| |false|
-|useOneOfDiscriminatorLookup|Use the discriminator's mapping in oneOf to speed up the model lookup. IMPORTANT: Validation (e.g. one and only one match in oneOf's schemas) will be skipped. Only jersey2, jersey3, native, okhttp-gson support this option.| |false|
+|useJspecify|Use Jspecify for null checks. Only supported for [native, okhttp, restclient, resttemplate, webclient]| |false|
+|useOneOfDiscriminatorLookup|Use the discriminator's mapping in oneOf to speed up the model lookup. IMPORTANT: Validation (e.g. one and only one match in oneOf's schemas) will be skipped. Only jersey2, jersey3, native, okhttp-gson, okhttp support this option.| |false|
|useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |false|
|usePlayWS|Use Play! Async HTTP client (Play WS API)| |false|
|useReflectionEqualsHashCode|Use org.apache.commons.lang3.builder for equals and hashCode in the models. WARNING: This will fail under a security manager, unless the appropriate permissions are set up correctly and also there's potential performance impact.| |false|
-|useRuntimeException|Use RuntimeException instead of Exception. Only jersey2, jersey3, okhttp-gson, vertx, microprofile support this option.| |false|
+|useRuntimeException|Use RuntimeException instead of Exception. Only jersey2, jersey3, okhttp-gson, okhttp, vertx, microprofile support this option.| |false|
|useRxJava2|Whether to use the RxJava2 adapter with the retrofit2 library. IMPORTANT: This option has been deprecated.| |false|
|useRxJava3|Whether to use the RxJava3 adapter with the retrofit2 library. IMPORTANT: This option has been deprecated.| |false|
|useSealedOneOfInterfaces|Generate the oneOf interfaces as sealed interfaces. Only supported for WebClient, RestClient and Microprofile (with Jackson).| |false|
-|useSingleRequestParameter|Setting this property to "true" will generate functions with a single argument containing all API endpoint parameters instead of one argument per parameter. ONLY native, jersey2, jersey3, okhttp-gson, microprofile, Spring RestClient, Spring WebClient support this option. Setting this property to "static" does the same as "true", but also makes the generated arguments class static with single parameter instantiation.| |false|
+|useSingleRequestParameter|Setting this property to "true" will generate functions with a single argument containing all API endpoint parameters instead of one argument per parameter. ONLY native, jersey2, jersey3, okhttp-gson, okhttp, microprofile, Spring RestClient, Spring WebClient support this option. Setting this property to "static" does the same as "true", but also makes the generated arguments class static with single parameter instantiation.| |false|
|useSpringBoot4|Generate code and provide dependencies for use with Spring Boot 4.x.| |false|
|useUnaryInterceptor|If true it will generate ResponseInterceptors using a UnaryOperator. This can be usefull for manipulating the request before it gets passed, for example doing your own decryption| |false|
|useVertx5|Whether to use Vert.x 5 syntax.| |false|
|webclientBlockingOperations|Making all WebClient operations blocking(sync). Note that if on operation 'x-webclient-blocking: false' then such operation won't be sync| |false|
-|withAWSV4Signature|whether to include AWS v4 signature support (only available for okhttp-gson library)| |false|
+|withAWSV4Signature|whether to include AWS v4 signature support (only available for okhttp-gson and okhttp libraries)| |false|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|
## SUPPORTED VENDOR EXTENSIONS
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java
index 0bcd7a12a6d3..69e47f662a89 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java
@@ -95,6 +95,7 @@ public class JavaClientCodegen extends AbstractJavaCodegen
public static final String JERSEY3 = "jersey3";
public static final String NATIVE = "native";
public static final String OKHTTP_GSON = "okhttp-gson";
+ public static final String OKHTTP = "okhttp";
public static final String RESTEASY = "resteasy";
public static final String RESTTEMPLATE = "resttemplate";
public static final String WEBCLIENT = "webclient";
@@ -184,7 +185,7 @@ public class JavaClientCodegen extends AbstractJavaCodegen
@Setter protected int maxAttemptsForRetry = 1;
@Setter protected long waitTimeMillis = 10l;
- private final Set JSPECIFY_SUPPORTED_LIBRARIES = new TreeSet<>(Arrays.asList(RESTCLIENT, WEBCLIENT, NATIVE, RESTTEMPLATE));
+ private final Set JSPECIFY_SUPPORTED_LIBRARIES = new TreeSet<>(Arrays.asList(RESTCLIENT, WEBCLIENT, NATIVE, RESTTEMPLATE, OKHTTP));
private static class MpRestClientVersion {
public final String rootPackage;
@@ -250,16 +251,16 @@ public JavaClientCodegen() {
cliOptions.add(CliOption.newBoolean(USE_RX_JAVA2, "Whether to use the RxJava2 adapter with the retrofit2 library. IMPORTANT: This option has been deprecated."));
cliOptions.add(CliOption.newBoolean(USE_RX_JAVA3, "Whether to use the RxJava3 adapter with the retrofit2 library. IMPORTANT: This option has been deprecated."));
- cliOptions.add(CliOption.newBoolean(PARCELABLE_MODEL, "Whether to generate models for Android that implement Parcelable with the okhttp-gson library."));
+ cliOptions.add(CliOption.newBoolean(PARCELABLE_MODEL, "Whether to generate models for Android that implement Parcelable with the okhttp-gson and okhttp libraries."));
cliOptions.add(CliOption.newBoolean(USE_VERTX_5, "Whether to use Vert.x 5 syntax."));
cliOptions.add(CliOption.newBoolean(USE_PLAY_WS, "Use Play! Async HTTP client (Play WS API)"));
cliOptions.add(CliOption.newBoolean(USE_BEANVALIDATION, "Use BeanValidation API annotations"));
cliOptions.add(CliOption.newBoolean(PERFORM_BEANVALIDATION, "Perform BeanValidation"));
cliOptions.add(CliOption.newBoolean(USE_GZIP_FEATURE, "Send gzip-encoded requests"));
- cliOptions.add(CliOption.newBoolean(USE_RUNTIME_EXCEPTION, "Use RuntimeException instead of Exception. Only jersey2, jersey3, okhttp-gson, vertx, microprofile support this option."));
+ cliOptions.add(CliOption.newBoolean(USE_RUNTIME_EXCEPTION, "Use RuntimeException instead of Exception. Only jersey2, jersey3, okhttp-gson, okhttp, vertx, microprofile support this option."));
cliOptions.add(CliOption.newBoolean(ASYNC_NATIVE, "If true, async handlers will be used, instead of the sync version"));
cliOptions.add(CliOption.newBoolean(USE_REFLECTION_EQUALS_HASHCODE, "Use org.apache.commons.lang3.builder for equals and hashCode in the models. WARNING: This will fail under a security manager, unless the appropriate permissions are set up correctly and also there's potential performance impact."));
- cliOptions.add(CliOption.newBoolean(CASE_INSENSITIVE_RESPONSE_HEADERS, "Make API response's headers case-insensitive. Available on " + OKHTTP_GSON + ", " + JERSEY2 + " libraries"));
+ cliOptions.add(CliOption.newBoolean(CASE_INSENSITIVE_RESPONSE_HEADERS, "Make API response's headers case-insensitive. Available on " + OKHTTP_GSON + ", " + JERSEY2 + ", and " + OKHTTP + " libraries"));
cliOptions.add(CliOption.newString(MICROPROFILE_FRAMEWORK, "Framework for microprofile. Possible values \"kumuluzee\""));
cliOptions.add(CliOption.newString(MICROPROFILE_MUTINY, "Whether to use async types for microprofile (currently only Smallrye Mutiny is supported)."));
cliOptions.add(CliOption.newString(MICROPROFILE_REGISTER_EXCEPTION_MAPPER, "Should generated API Clients be annotated with @RegisterProvider(ApiExceptionMapper.class).").defaultValue("true"));
@@ -267,20 +268,20 @@ public JavaClientCodegen() {
cliOptions.add(CliOption.newBoolean(USE_ABSTRACTION_FOR_FILES, "Use alternative types instead of java.io.File to allow passing bytes without a file on disk. Available on resttemplate, webclient, restclient, libraries"));
cliOptions.add(CliOption.newBoolean(DYNAMIC_OPERATIONS, "Generate operations dynamically at runtime from an OAS", this.dynamicOperations));
cliOptions.add(CliOption.newBoolean(SUPPORT_STREAMING, "Support streaming endpoint (beta)", this.supportStreaming));
- cliOptions.add(CliOption.newBoolean(CodegenConstants.WITH_AWSV4_SIGNATURE_COMMENT, CodegenConstants.WITH_AWSV4_SIGNATURE_COMMENT_DESC + " (only available for okhttp-gson library)", this.withAWSV4Signature));
+ cliOptions.add(CliOption.newBoolean(CodegenConstants.WITH_AWSV4_SIGNATURE_COMMENT, CodegenConstants.WITH_AWSV4_SIGNATURE_COMMENT_DESC + " (only available for okhttp-gson and okhttp libraries)", this.withAWSV4Signature));
cliOptions.add(CliOption.newString(GRADLE_PROPERTIES, "Append additional Gradle properties to the gradle.properties file"));
- cliOptions.add(CliOption.newString(ERROR_OBJECT_TYPE, "Error Object type. (This option is for okhttp-gson only)"));
+ cliOptions.add(CliOption.newString(ERROR_OBJECT_TYPE, "Error Object type. (This option is for okhttp-gson and okhttp only)"));
cliOptions.add(CliOption.newString(CONFIG_KEY, "Config key in @RegisterRestClient. Default to none. Only `microprofile` supports this option."));
cliOptions.add(CliOption.newString(CONFIG_KEY_FROM_CLASS_NAME, "If true, set tag as key in @RegisterRestClient. Default to false. Only `microprofile` supports this option."));
- cliOptions.add(CliOption.newBoolean(CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP, CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP_DESC + " Only jersey2, jersey3, native, okhttp-gson support this option."));
+ cliOptions.add(CliOption.newBoolean(CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP, CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP_DESC + " Only jersey2, jersey3, native, okhttp-gson, okhttp support this option."));
cliOptions.add(CliOption.newString(MICROPROFILE_REST_CLIENT_VERSION, "Version of MicroProfile Rest Client API."));
- cliOptions.add(CliOption.newString(CodegenConstants.USE_SINGLE_REQUEST_PARAMETER, "Setting this property to \"true\" will generate functions with a single argument containing all API endpoint parameters instead of one argument per parameter. ONLY native, jersey2, jersey3, okhttp-gson, microprofile, Spring RestClient, Spring WebClient support this option. Setting this property to \"static\" does the same as \"true\", but also makes the generated arguments class static with single parameter instantiation.").defaultValue("false"));
+ cliOptions.add(CliOption.newString(CodegenConstants.USE_SINGLE_REQUEST_PARAMETER, "Setting this property to \"true\" will generate functions with a single argument containing all API endpoint parameters instead of one argument per parameter. ONLY native, jersey2, jersey3, okhttp-gson, okhttp, microprofile, Spring RestClient, Spring WebClient support this option. Setting this property to \"static\" does the same as \"true\", but also makes the generated arguments class static with single parameter instantiation.").defaultValue("false"));
cliOptions.add(CliOption.newBoolean(WEBCLIENT_BLOCKING_OPERATIONS, "Making all WebClient operations blocking(sync). Note that if on operation 'x-webclient-blocking: false' then such operation won't be sync", this.webclientBlockingOperations));
cliOptions.add(CliOption.newBoolean(GENERATE_CLIENT_AS_BEAN, "For resttemplate, restclient and webclient, configure whether to create `ApiClient.java` and Apis clients as bean (with `@Component` annotation).", this.generateClientAsBean));
- cliOptions.add(CliOption.newBoolean(SUPPORT_URL_QUERY, "Generate toUrlQueryString in POJO (default to true). Available on `native`, `apache-httpclient` libraries."));
+ cliOptions.add(CliOption.newBoolean(SUPPORT_URL_QUERY, "Generate toUrlQueryString in POJO (default to true). Available on `native`, `apache-httpclient`, `okhttp`, `feign`, `restclient`, `resttemplate`, `webclient` libraries."));
cliOptions.add(CliOption.newBoolean(USE_ENUM_CASE_INSENSITIVE, "Use `equalsIgnoreCase` when String for enum comparison", useEnumCaseInsensitive));
cliOptions.add(CliOption.newBoolean(FAIL_ON_UNKNOWN_PROPERTIES, "Fail Jackson de-serialization on unknown properties", this.failOnUnknownProperties));
- cliOptions.add(CliOption.newBoolean(USE_JACKSON_3, "Use Jackson 3 instead of Jackson 2. Supported for 'native', 'apache-httpclient', and 'jersey3' libraries (requires Java 17+) and for Spring 'resttemplate', 'webclient', and 'restclient' libraries (require useSpringBoot4=true).", this.useJackson3));
+ cliOptions.add(CliOption.newBoolean(USE_JACKSON_3, "Use Jackson 3 instead of Jackson 2. Supported for 'native', 'apache-httpclient', 'jersey3', and 'okhttp' libraries (requires Java 17+) and for Spring 'resttemplate', 'webclient', and 'restclient' libraries (require useSpringBoot4=true).", this.useJackson3));
cliOptions.add(CliOption.newBoolean(SUPPORT_VERTX_FUTURE, "Also generate api methods that return a vertx Future instead of taking a callback. Only `vertx` supports this option. Requires vertx 4 or greater.", this.supportVertxFuture));
cliOptions.add(CliOption.newBoolean(USE_SEALED_ONE_OF_INTERFACES, "Generate the oneOf interfaces as sealed interfaces. Only supported for WebClient, RestClient and Microprofile (with Jackson).", this.useSealedOneOfInterfaces));
cliOptions.add(CliOption.newBoolean(USE_UNARY_INTERCEPTOR, "If true it will generate ResponseInterceptors using a UnaryOperator. This can be usefull for manipulating the request before it gets passed, for example doing your own decryption", this.useUnaryInterceptor));
@@ -292,6 +293,7 @@ public JavaClientCodegen() {
supportedLibraries.put(FEIGN, "HTTP client: OpenFeign 13.2.1. JSON processing: Jackson 2.18.9 or Gson 2.10.1");
supportedLibraries.put(FEIGN_HC5, "HTTP client: OpenFeign 13.2.1/HttpClient5 5.4.2. JSON processing: Jackson 2.18.9 or Gson 2.10.1");
supportedLibraries.put(OKHTTP_GSON, "[DEFAULT] HTTP client: OkHttp 4.11.0. JSON processing: Gson 2.10.1. Enable Parcelable models on Android using '-DparcelableModel=true'. Enable gzip request encoding using '-DuseGzipFeature=true'.");
+ supportedLibraries.put(OKHTTP, "HTTP client: OkHttp 5.4.0. JSON processing: Gson 2.10.1, Jackson 2.x/3.x, or JSON-B. Enable Parcelable models on Android using '-DparcelableModel=true'. Enable gzip request encoding using '-DuseGzipFeature=true'.");
supportedLibraries.put(RETROFIT_2, "HTTP client: OkHttp 4.11.0. JSON processing: Gson 2.10.1 (Retrofit 2.5.0) or Jackson 2.18.9. Enable the RxJava adapter using '-DuseRxJava[2/3]=true'. (RxJava 1.x or 2.x or 3.x)");
supportedLibraries.put(RESTTEMPLATE, "HTTP client: Spring RestTemplate 5.3.33 (6.2.x if `useJakartaEe=true`, 7.x.x if `useSpringBoot4=true`). JSON processing: Jackson 2.x (3.x if `useJackson3=true`)");
supportedLibraries.put(WEBCLIENT, "HTTP client: Spring WebClient 5.1.18 (7.x.x if `useSpringBoot4=true`). JSON processing: Jackson 2.18.9 (3.x if `useJackson3=true`)");
@@ -355,7 +357,7 @@ public String getName() {
@Override
public String getHelp() {
- return "Generates a Java client library (HTTP lib: Jersey (1.x, 2.x), Retrofit (2.x), OpenFeign (10.x) and more.";
+ return "Generates a Java client library (HTTP lib: Jersey (1.x, 2.x), Retrofit (2.x), OpenFeign (10.x), OkHttp and more.";
}
@Override
@@ -385,6 +387,7 @@ public void processOpts() {
final boolean libJersey3 = isLibrary(JERSEY3);
final boolean libMicroprofile = isLibrary(MICROPROFILE);
final boolean libNative = isLibrary(NATIVE);
+ final boolean libOkHttp = isLibrary(OKHTTP);
final boolean libOkHttpGson = isLibrary(OKHTTP_GSON) || StringUtils.isBlank(getLibrary());
final boolean libRestAssured = isLibrary(REST_ASSURED);
final boolean libRestClient = isLibrary(RESTCLIENT);
@@ -395,15 +398,30 @@ public void processOpts() {
final boolean libWebClient = isLibrary(WEBCLIENT);
// default jackson unless overridden by setSerializationLibrary
- this.jackson = !additionalProperties.containsKey(CodegenConstants.SERIALIZATION_LIBRARY) ||
- SERIALIZATION_LIBRARY_JACKSON.equals(additionalProperties.get(CodegenConstants.SERIALIZATION_LIBRARY));
+ if (additionalProperties.containsKey(CodegenConstants.SERIALIZATION_LIBRARY)) {
+ this.serializationLibrary = String.valueOf(additionalProperties.get(CodegenConstants.SERIALIZATION_LIBRARY));
+ }
+
+ if (this.serializationLibrary == null) {
+ if (libOkHttp || libOkHttpGson) {
+ this.serializationLibrary = SERIALIZATION_LIBRARY_GSON;
+ } else if (libMicroprofile) {
+ this.serializationLibrary = SERIALIZATION_LIBRARY_JSONB;
+ }
+ }
+ additionalProperties.put(CodegenConstants.SERIALIZATION_LIBRARY, serializationLibrary);
+
+ this.jackson = SERIALIZATION_LIBRARY_JACKSON.equals(serializationLibrary);
+ additionalProperties.put("isJackson", jackson);
+ additionalProperties.put("isGson", SERIALIZATION_LIBRARY_GSON.equals(serializationLibrary));
+ additionalProperties.put("isJsonb", SERIALIZATION_LIBRARY_JSONB.equals(serializationLibrary));
convertPropertyToBooleanAndWriteBack(CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP, this::setUseOneOfDiscriminatorLookup);
convertPropertyToBooleanAndWriteBack(USE_JACKSON_3, this::setUseJackson3);
convertPropertyToBooleanAndWriteBack(USE_SPRING_BOOT4, this::setUseSpringBoot4);
if (useJackson3 && (libRestClient || libRestTemplate || libWebClient) && !useSpringBoot4) {
throw new IllegalArgumentException("useJackson3 for the restclient, resttemplate, and webclient libraries requires useSpringBoot4=true");
- } else if (useJackson3 && !libNative && !libApache && !libJersey3 && !libRestClient && !libRestTemplate && !libWebClient) {
- throw new IllegalArgumentException("useJackson3 is only supported for the 'native', 'apache-httpclient', 'jersey3', 'restclient', 'resttemplate', and 'webclient' libraries. " +
+ } else if (useJackson3 && !libNative && !libApache && !libJersey3 && !libRestClient && !libRestTemplate && !libWebClient && !libOkHttp) {
+ throw new IllegalArgumentException("useJackson3 is only supported for the 'native', 'apache-httpclient', 'jersey3', 'restclient', 'resttemplate', 'webclient', and 'okhttp' libraries. " +
"The Spring libraries also require useSpringBoot4=true.");
}
@@ -567,7 +585,7 @@ public void processOpts() {
supportingFiles.add(new SupportingFile("auth/HttpBasicAuth.mustache", authFolder, "HttpBasicAuth.java"));
supportingFiles.add(new SupportingFile("auth/HttpBearerAuth.mustache", authFolder, "HttpBearerAuth.java"));
supportingFiles.add(new SupportingFile("auth/ApiKeyAuth.mustache", authFolder, "ApiKeyAuth.java"));
- if (libOkHttpGson && withAWSV4Signature) {
+ if ((libOkHttp || libOkHttpGson) && withAWSV4Signature) {
supportingFiles.add(new SupportingFile("auth/AWS4Auth.mustache", authFolder, "AWS4Auth.java"));
}
}
@@ -586,8 +604,6 @@ public void processOpts() {
"BeanValidationException.java"));
}
- convertPropertyToStringAndWriteBack(CodegenConstants.SERIALIZATION_LIBRARY, this::setSerializationLibrary);
-
//TODO: add auto-generated doc to feign
if (libFeign) {
modelDocTemplateFiles.remove("model_doc.mustache");
@@ -626,6 +642,21 @@ public void processOpts() {
}
supportingFiles.add(new SupportingFile("EncodingUtils.mustache", invokerFolder, "EncodingUtils.java"));
+ // Composed schemas can have the 'additionalProperties' keyword, as specified in JSON schema.
+ // In principle, this should be enabled by default for all code generators. However due to limitations
+ // in other code generators, support needs to be enabled on a case-by-case basis.
+ // The flag below should be set for all Java libraries, but the templates need to be ported
+ // one by one for each library.
+ supportsAdditionalPropertiesWithComposedSchema = true;
+ } else if (libOkHttp) {
+ // the "okhttp" library template requires "ApiCallback.mustache" for async call
+ supportingFiles.add(new SupportingFile("ApiCallback.mustache", invokerFolder, "ApiCallback.java"));
+ supportingFiles.add(new SupportingFile("ApiResponse.mustache", invokerFolder, "ApiResponse.java"));
+ supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java"));
+ supportingFiles.add(new SupportingFile("ProgressRequestBody.mustache", invokerFolder, "ProgressRequestBody.java"));
+ supportingFiles.add(new SupportingFile("ProgressResponseBody.mustache", invokerFolder, "ProgressResponseBody.java"));
+ supportingFiles.add(new SupportingFile("AbstractOpenApiSchema.mustache", modelsFolder, "AbstractOpenApiSchema.java"));
+
// Composed schemas can have the 'additionalProperties' keyword, as specified in JSON schema.
// In principle, this should be enabled by default for all code generators. However due to limitations
// in other code generators, support needs to be enabled on a case-by-case basis.
@@ -850,7 +881,7 @@ public void processOpts() {
additionalProperties.remove(SERIALIZATION_LIBRARY_GSON);
additionalProperties.remove(SERIALIZATION_LIBRARY_JSONB);
supportingFiles.add(new SupportingFile("RFC3339DateFormat.mustache", invokerFolder, "RFC3339DateFormat.java"));
- if (!useJackson3 || libNative || libApache || libJersey3 || libRestTemplate || libWebClient) {
+ if (!useJackson3 || libNative || libApache || libJersey3 || libRestTemplate || libWebClient || libOkHttp) {
supportingFiles.add(new SupportingFile("RFC3339InstantDeserializer.mustache", invokerFolder, "RFC3339InstantDeserializer.java"));
supportingFiles.add(new SupportingFile("RFC3339JavaTimeModule.mustache", invokerFolder, "RFC3339JavaTimeModule.java"));
}
@@ -889,8 +920,8 @@ public void processOpts() {
// authentication related files
// has OAuth defined
if (ProcessUtils.hasOAuthMethods(openAPI)) {
- // for okhttp-gson (default), check to see if OAuth is defined and included OAuth-related files accordingly
- if (libOkHttpGson) {
+ // for okhttp-gson (default) or okhttp, check to see if OAuth is defined and included OAuth-related files accordingly
+ if (libOkHttpGson || libOkHttp) {
supportingFiles.add(new SupportingFile("auth/OAuthOkHttpClient.mustache", authFolder, "OAuthOkHttpClient.java"));
supportingFiles.add(new SupportingFile("auth/RetryingOAuth.mustache", authFolder, "RetryingOAuth.java"));
}
@@ -915,7 +946,7 @@ public void processOpts() {
public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List allModels) {
super.postProcessOperationsWithModels(objs, allModels);
- if (this.getSingleRequestParameter() && (isLibrary(JERSEY2) || isLibrary(JERSEY3) || isLibrary(OKHTTP_GSON) || isLibrary(NATIVE))) {
+ if (this.getSingleRequestParameter() && (isLibrary(JERSEY2) || isLibrary(JERSEY3) || isLibrary(OKHTTP_GSON) || isLibrary(NATIVE) || isLibrary(OKHTTP))) {
// loop through operations to set x-group-parameters extension to true if useSingleRequestParameter option is enabled
OperationMap operations = objs.getOperations();
if (operations != null) {
@@ -1265,6 +1296,10 @@ public ModelsMap postProcessModels(ModelsMap objs) {
for (ModelMap mo : models) {
CodegenModel cm = mo.getModel();
+ if (supportsAdditionalPropertiesWithComposedSchema) {
+ cm.isAdditionalPropertiesTrue = true;
+ }
+
cm.getVendorExtensions().putIfAbsent(X_IMPLEMENTS, new ArrayList());
if (isLibrary(JERSEY2) || isLibrary(JERSEY3) || isLibrary(NATIVE) || isLibrary(OKHTTP_GSON)) {
if (cm.oneOf != null && !cm.oneOf.isEmpty() && cm.oneOf.contains("ModelNull")) {
@@ -1379,7 +1414,7 @@ public String toApiVarName(String name) {
@Override
public void addImportsToOneOfInterface(List> imports) {
- if (additionalProperties.containsKey(SERIALIZATION_LIBRARY_JACKSON)) {
+ if (jackson) {
for (String i : Arrays.asList("JsonSubTypes", "JsonTypeInfo", "JsonIgnoreProperties")) {
Map oneImport = new HashMap<>();
oneImport.put("import", importMapping.get(i));
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/native/modelEnum.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/native/modelEnum.mustache
index 6db13f884a38..312a3d96d856 100644
--- a/modules/openapi-generator/src/main/resources/Java/libraries/native/modelEnum.mustache
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/native/modelEnum.mustache
@@ -96,7 +96,7 @@ import java.net.URI;
@Override
public {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException {
{{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{^isNumber}}{{^isInteger}}next{{{dataType}}}(){{/isInteger}}{{/isNumber}};
- return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
+ return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new java.math.BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
}
}
{{/gson}}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache
index 499469238d2f..b5bb126f01aa 100644
--- a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache
@@ -1539,8 +1539,17 @@ public class ApiClient {
List updatedQueryParams = new ArrayList<>(queryParams);
+ String localVarPayload = requestBodyToString(reqBody);
+
// update parameters with authentication settings
- updateParamsForAuth(authNames, updatedQueryParams, headerParams, cookieParams, requestBodyToString(reqBody), method, URI.create(url));
+ for (String authName : authNames) {
+ Authentication auth = authentications.get(authName);
+ if (auth == null) {
+ throw new RuntimeException("Authentication undefined: " + authName);
+ }
+ URI currentUri = URI.create(buildUrl(baseUrl, path, updatedQueryParams, collectionQueryParams));
+ auth.applyToParams(updatedQueryParams, headerParams, cookieParams, localVarPayload, method, currentUri);
+ }
final Request.Builder reqBuilder = new Request.Builder().url(buildUrl(baseUrl, path, updatedQueryParams, collectionQueryParams));
processHeaderParams(headerParams, reqBuilder);
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/api.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/api.mustache
index 9519ce13c75e..0e03ab7d194a 100644
--- a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/api.mustache
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/api.mustache
@@ -235,7 +235,7 @@ public class {{classname}} {
{{/headerParams}}
{{/dynamicOperations}}
- String[] localVarAuthNames = new String[] { {{#withAWSV4Signature}}"AWS4Auth"{{/withAWSV4Signature}}{{#authMethods}}{{#-first}}{{#withAWSV4Signature}}, {{/withAWSV4Signature}}{{/-first}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} };
+ String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{#-last}}{{#withAWSV4Signature}}, {{/withAWSV4Signature}}{{/-last}}{{/authMethods}}{{#withAWSV4Signature}}"AWS4Auth"{{/withAWSV4Signature}} };
return localVarApiClient.buildCall(basePath, localVarPath, {{^dynamicOperations}}"{{httpMethod}}"{{/dynamicOperations}}{{#dynamicOperations}}apiOperation.getMethod(){{/dynamicOperations}}, localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback);
}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/modelEnum.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/modelEnum.mustache
index a89b1578d7bd..1a526075cf24 100644
--- a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/modelEnum.mustache
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/modelEnum.mustache
@@ -61,13 +61,13 @@ import com.google.gson.stream.JsonWriter;
@Override
public {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException {
{{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = {{#isFloat}}(float){{/isFloat}}{{#isUri}}URI.create({{/isUri}}jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{#isUri}}nextString()){{/isUri}}{{^isNumber}}{{^isInteger}}{{^isUri}}{{#isFloat}}nextDouble{{/isFloat}}{{^isFloat}}next{{{dataType}}}{{/isFloat}}(){{/isUri}}{{/isInteger}}{{/isNumber}};
- return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
+ return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new java.math.BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
}
}
public static void validateJsonElement(JsonElement jsonElement) throws IOException {
{{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = {{#isUri}}URI.create({{/isUri}}jsonElement.{{#isNumber}}getAsString(){{/isNumber}}{{#isInteger}}getAsInt(){{/isInteger}}{{#isUri}}getAsString()){{/isUri}}{{^isNumber}}{{^isInteger}}{{^isUri}}getAs{{{dataType}}}(){{/isUri}}{{/isInteger}}{{/isNumber}};
- {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
+ {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new java.math.BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
}
{{#supportUrlQuery}}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/modelInnerEnum.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/modelInnerEnum.mustache
index 1d23f2da527b..31d6281b07f6 100644
--- a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/modelInnerEnum.mustache
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/modelInnerEnum.mustache
@@ -55,12 +55,12 @@
@Override
public {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException {
{{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = {{#isFloat}}(float){{/isFloat}} {{#isUri}}URI.create({{/isUri}}jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{#isUri}}nextString()){{/isUri}}{{^isNumber}}{{^isInteger}}{{^isUri}}{{#isFloat}}nextDouble{{/isFloat}}{{^isFloat}}next{{{dataType}}}{{/isFloat}}(){{/isUri}}{{/isInteger}}{{/isNumber}};
- return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
+ return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new java.math.BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
}
}
public static void validateJsonElement(JsonElement jsonElement) throws IOException {
{{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = {{#isUri}}URI.create({{/isUri}}jsonElement.{{#isNumber}}getAsString(){{/isNumber}}{{#isInteger}}getAsInt(){{/isInteger}}{{#isUri}}getAsString()){{/isUri}}{{^isNumber}}{{^isInteger}}{{^isUri}}getAs{{{dataType}}}(){{/isUri}}{{/isInteger}}{{/isNumber}};
- {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
+ {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new java.math.BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
}
}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/pojo.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/pojo.mustache
index 349e6fc6a798..ed8ee8c481c2 100644
--- a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/pojo.mustache
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/pojo.mustache
@@ -11,6 +11,8 @@ import com.google.gson.reflect.TypeToken;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
+import com.google.gson.annotations.JsonAdapter;
+import com.google.gson.annotations.SerializedName;
import java.io.IOException;
import java.util.HashMap;
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/AbstractOpenApiSchema.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/AbstractOpenApiSchema.mustache
new file mode 100644
index 000000000000..3949e023fbb4
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/AbstractOpenApiSchema.mustache
@@ -0,0 +1,139 @@
+{{>licenseInfo}}
+
+package {{modelPackage}};
+
+import {{invokerPackage}}.ApiException;
+{{#isJackson}}
+import com.fasterxml.jackson.annotation.JsonValue;
+{{/isJackson}}
+import java.util.Objects;
+import java.lang.reflect.Type;
+import java.util.Map;
+
+/**
+ * Abstract class for oneOf,anyOf schemas defined in OpenAPI spec
+ */
+{{>generatedAnnotation}}
+
+public abstract class AbstractOpenApiSchema {
+
+ // store the actual instance of the schema/object
+ private Object instance;
+
+ // is nullable
+ private Boolean isNullable;
+
+ // schema type (e.g. oneOf, anyOf)
+ private final String schemaType;
+
+ public AbstractOpenApiSchema(String schemaType, Boolean isNullable) {
+ this.schemaType = schemaType;
+ this.isNullable = isNullable;
+ }
+
+ /**
+ * Get the list of oneOf/anyOf composed schemas allowed to be stored in this object
+ *
+ * @return an instance of the actual schema/object
+ */
+ public abstract Map> getSchemas();
+
+ /**
+ * Get the actual instance
+ *
+ * @return an instance of the actual schema/object
+ */
+ {{#isJackson}}
+ @JsonValue
+ {{/isJackson}}
+ public Object getActualInstance() {return instance;}
+
+ /**
+ * Set the actual instance
+ *
+ * @param instance the actual instance of the schema/object
+ */
+ public void setActualInstance(Object instance) {this.instance = instance;}
+
+ /**
+ * Get the instant recursively when the schemas defined in oneOf/anyof happen to be oneOf/anyOf schema as well
+ *
+ * @return an instance of the actual schema/object
+ */
+ public Object getActualInstanceRecursively() {
+ return getActualInstanceRecursively(this);
+ }
+
+ private Object getActualInstanceRecursively(AbstractOpenApiSchema object) {
+ if (object.getActualInstance() == null) {
+ return null;
+ } else if (object.getActualInstance() instanceof AbstractOpenApiSchema) {
+ return getActualInstanceRecursively((AbstractOpenApiSchema)object.getActualInstance());
+ } else {
+ return object.getActualInstance();
+ }
+ }
+
+ /**
+ * Get the schema type (e.g. anyOf, oneOf)
+ *
+ * @return the schema type
+ */
+ public String getSchemaType() {
+ return schemaType;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("class ").append(getClass()).append(" {\n");
+ sb.append(" instance: ").append(toIndentedString(instance)).append("\n");
+ sb.append(" isNullable: ").append(toIndentedString(isNullable)).append("\n");
+ sb.append(" schemaType: ").append(toIndentedString(schemaType)).append("\n");
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces
+ * (except the first line).
+ */
+ private String toIndentedString(Object o) {
+ return o == null ? "null" : o.toString().replace("\n", "\n ");
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ AbstractOpenApiSchema a = (AbstractOpenApiSchema) o;
+ return Objects.equals(this.instance, a.instance) &&
+ Objects.equals(this.isNullable, a.isNullable) &&
+ Objects.equals(this.schemaType, a.schemaType);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(instance, isNullable, schemaType);
+ }
+
+ /**
+ * Is nullable
+ *
+ * @return true if it's nullable
+ */
+ public Boolean isNullable() {
+ if (Boolean.TRUE.equals(isNullable)) {
+ return Boolean.TRUE;
+ } else {
+ return Boolean.FALSE;
+ }
+ }
+
+{{>additional_properties}}
+
+
+}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/ApiCallback.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/ApiCallback.mustache
new file mode 100644
index 000000000000..53b6a7b8e34f
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/ApiCallback.mustache
@@ -0,0 +1,51 @@
+{{>licenseInfo}}
+
+package {{invokerPackage}};
+
+import java.io.IOException;
+
+import java.util.Map;
+import java.util.List;
+
+/**
+ * Callback for asynchronous API call.
+ *
+ * @param The return type
+ */
+public interface ApiCallback {
+ /**
+ * This is called when the API call fails.
+ *
+ * @param e The exception causing the failure
+ * @param statusCode Status code of the response if available, otherwise it would be 0
+ * @param responseHeaders Headers of the response if available, otherwise it would be null
+ */
+ void onFailure(ApiException e, int statusCode, Map> responseHeaders);
+
+ /**
+ * This is called when the API call succeeded.
+ *
+ * @param result The result deserialized from response
+ * @param statusCode Status code of the response
+ * @param responseHeaders Headers of the response
+ */
+ void onSuccess(T result, int statusCode, Map> responseHeaders);
+
+ /**
+ * This is called when the API upload processing.
+ *
+ * @param bytesWritten bytes Written
+ * @param contentLength content length of request body
+ * @param done write end
+ */
+ void onUploadProgress(long bytesWritten, long contentLength, boolean done);
+
+ /**
+ * This is called when the API download processing.
+ *
+ * @param bytesRead bytes Read
+ * @param contentLength content length of the response
+ * @param done Read end
+ */
+ void onDownloadProgress(long bytesRead, long contentLength, boolean done);
+}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/ApiClient.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/ApiClient.mustache
new file mode 100644
index 000000000000..6a489eea3004
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/ApiClient.mustache
@@ -0,0 +1,1992 @@
+{{>licenseInfo}}
+
+package {{invokerPackage}};
+
+{{#dynamicOperations}}
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.Operation;
+import io.swagger.v3.oas.models.PathItem;
+import io.swagger.v3.oas.models.parameters.Parameter;
+import io.swagger.v3.oas.models.parameters.Parameter.StyleEnum;
+import io.swagger.v3.parser.OpenAPIV3Parser;
+{{/dynamicOperations}}
+import okhttp3.*;
+import okhttp3.internal.http.HttpMethod;
+import okhttp3.internal.tls.OkHostnameVerifier;
+import okhttp3.logging.HttpLoggingInterceptor;
+import okhttp3.logging.HttpLoggingInterceptor.Level;
+import okio.Buffer;
+import okio.BufferedSink;
+import okio.Okio;
+{{#joda}}
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+import org.joda.time.format.DateTimeFormatter;
+{{/joda}}
+{{#hasOAuthMethods}}
+import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder;
+import org.apache.oltu.oauth2.common.message.types.GrantType;
+{{/hasOAuthMethods}}
+
+import javax.net.ssl.*;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Type;
+import java.net.URI;
+import java.net.URLConnection;
+import java.net.URLEncoder;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.SecureRandom;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.text.DateFormat;
+{{#jsr310}}
+import java.time.LocalDate;
+import java.time.OffsetDateTime;
+import java.time.format.DateTimeFormatter;
+{{/jsr310}}
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import {{invokerPackage}}.auth.Authentication;
+import {{invokerPackage}}.auth.HttpBasicAuth;
+import {{invokerPackage}}.auth.HttpBearerAuth;
+import {{invokerPackage}}.auth.ApiKeyAuth;
+{{#hasOAuthMethods}}
+import {{invokerPackage}}.auth.OAuth;
+import {{invokerPackage}}.auth.RetryingOAuth;
+import {{invokerPackage}}.auth.OAuthFlow;
+{{/hasOAuthMethods}}
+{{#withAWSV4Signature}}
+import {{invokerPackage}}.auth.AWS4Auth;
+{{/withAWSV4Signature}}
+
+/**
+ * ApiClient class.
+ */
+public class ApiClient {
+
+ protected 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;
+ protected boolean debugging = false;
+ protected Map defaultHeaderMap = new HashMap();
+ protected Map defaultCookieMap = new HashMap();
+ protected String tempFolderPath = null;
+
+ protected Map authentications;
+
+ protected DateFormat dateFormat;
+ protected DateFormat datetimeFormat;
+ protected boolean lenientDatetimeFormat;
+ protected int dateLength;
+
+ protected InputStream sslCaCert;
+ protected boolean verifyingSsl;
+ protected KeyManager[] keyManagers;
+ protected String tlsServerName;
+
+ protected OkHttpClient httpClient;
+ protected JSON json;
+
+ protected HttpLoggingInterceptor loggingInterceptor;
+
+ {{#dynamicOperations}}
+ protected Map operationLookupMap = new HashMap<>();
+
+ {{/dynamicOperations}}
+ /**
+ * Basic constructor for ApiClient
+ */
+ public ApiClient() {
+ init();
+ initHttpClient();
+
+ // Setup authentications (key: authentication name, value: authentication).{{#authMethods}}{{#isBasic}}{{#isBasicBasic}}
+ authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{#isBasicBearer}}
+ authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBearer}}{{/isBasic}}{{#isApiKey}}
+ authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}}
+ authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}}{{#withAWSV4Signature}}
+ authentications.put("AWS4Auth", new AWS4Auth());{{/withAWSV4Signature}}
+ // Prevent the authentications from being modified.
+ authentications = Collections.unmodifiableMap(authentications);
+ }
+
+ /**
+ * Basic constructor with custom OkHttpClient
+ *
+ * @param client a {@link okhttp3.OkHttpClient} object
+ */
+ public ApiClient(OkHttpClient client) {
+ init();
+
+ httpClient = client;
+
+ // Setup authentications (key: authentication name, value: authentication).{{#authMethods}}{{#isBasic}}{{#isBasicBasic}}
+ authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{#isBasicBearer}}
+ authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBearer}}{{/isBasic}}{{#isApiKey}}
+ authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}}
+ authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}}{{#withAWSV4Signature}}
+ authentications.put("AWS4Auth", new AWS4Auth());{{/withAWSV4Signature}}
+ // Prevent the authentications from being modified.
+ authentications = Collections.unmodifiableMap(authentications);
+ }
+
+ {{#hasOAuthMethods}}
+ {{#oauthMethods}}
+ {{#-first}}
+ /**
+ * Constructor for ApiClient to support access token retry on 401/403 configured with client ID
+ *
+ * @param clientId client ID
+ */
+ public ApiClient(String clientId) {
+ this(clientId, null, null);
+ }
+
+ /**
+ * Constructor for ApiClient to support access token retry on 401/403 configured with client ID and additional parameters
+ *
+ * @param clientId client ID
+ * @param parameters a {@link java.util.Map} of parameters
+ */
+ public ApiClient(String clientId, Map parameters) {
+ this(clientId, null, parameters);
+ }
+
+ /**
+ * Constructor for ApiClient to support access token retry on 401/403 configured with client ID, secret, and additional parameters
+ *
+ * @param clientId client ID
+ * @param clientSecret client secret
+ * @param parameters a {@link java.util.Map} of parameters
+ */
+ public ApiClient(String clientId, String clientSecret, Map parameters) {
+ this(null, clientId, clientSecret, parameters);
+ }
+
+ /**
+ * Constructor for ApiClient to support access token retry on 401/403 configured with base path, client ID, secret, and additional parameters
+ *
+ * @param basePath base path
+ * @param clientId client ID
+ * @param clientSecret client secret
+ * @param parameters a {@link java.util.Map} of parameters
+ */
+ public ApiClient(String basePath, String clientId, String clientSecret, Map parameters) {
+ init();
+ if (basePath != null) {
+ this.basePath = basePath;
+ }
+
+ String tokenUrl = "{{{tokenUrl}}}";
+ if (!"".equals(tokenUrl) && !URI.create(tokenUrl).isAbsolute()) {
+ URI uri = URI.create(getBasePath());
+ tokenUrl = uri.getScheme() + ":" +
+ (uri.getAuthority() != null ? "//" + uri.getAuthority() : "") +
+ tokenUrl;
+ if (!URI.create(tokenUrl).isAbsolute()) {
+ throw new IllegalArgumentException("OAuth2 token URL must be an absolute URL");
+ }
+ }
+ RetryingOAuth retryingOAuth = new RetryingOAuth(tokenUrl, clientId, OAuthFlow.{{#lambda.uppercase}}{{#lambda.snakecase}}{{flow}}{{/lambda.snakecase}}{{/lambda.uppercase}}, clientSecret, parameters);
+ authentications.put(
+ "{{name}}",
+ retryingOAuth
+ );
+ initHttpClient(Collections.singletonList(retryingOAuth));
+ // Setup authentications (key: authentication name, value: authentication).{{#authMethods}}{{#isBasic}}{{#isBasicBasic}}
+ authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{#isBasicBearer}}
+ authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBearer}}{{/isBasic}}{{#isApiKey}}
+ authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{/authMethods}}{{#withAWSV4Signature}}
+ authentications.put("AWS4Auth", new AWS4Auth());{{/withAWSV4Signature}}
+
+ // Prevent the authentications from being modified.
+ authentications = Collections.unmodifiableMap(authentications);
+ }
+
+ {{/-first}}
+ {{/oauthMethods}}
+ {{/hasOAuthMethods}}
+ protected void initHttpClient() {
+ initHttpClient(Collections.emptyList());
+ }
+
+ protected void initHttpClient(List interceptors) {
+ OkHttpClient.Builder builder = new OkHttpClient.Builder();
+ builder.addNetworkInterceptor(getProgressInterceptor());
+ for (Interceptor interceptor: interceptors) {
+ builder.addInterceptor(interceptor);
+ }
+ {{#useGzipFeature}}
+ // Enable gzip request compression
+ builder.addInterceptor(new GzipRequestInterceptor());
+ {{/useGzipFeature}}
+
+ httpClient = builder.build();
+ }
+
+ protected void init() {
+ verifyingSsl = true;
+
+ json = new JSON();
+
+ // Set default User-Agent.
+ setUserAgent("{{{httpUserAgent}}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}");
+
+ authentications = new HashMap();
+ {{#dynamicOperations}}
+
+ OpenAPI openAPI = new OpenAPIV3Parser().read("openapi/openapi.yaml");
+ createOperationLookupMap(openAPI);
+ {{/dynamicOperations}}
+ }
+
+ /**
+ * Get base path
+ *
+ * @return Base path
+ */
+ public String getBasePath() {
+ return basePath;
+ }
+
+ /**
+ * Set base path
+ *
+ * @param basePath Base path of the URL (e.g {{{basePath}}})
+ * @return An instance of ApiClient
+ */
+ public ApiClient setBasePath(String basePath) {
+ this.basePath = basePath;
+ this.serverIndex = null;
+ 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;
+ }
+
+ /**
+ * Get HTTP client
+ *
+ * @return An instance of OkHttpClient
+ */
+ public OkHttpClient getHttpClient() {
+ return httpClient;
+ }
+
+ /**
+ * Set HTTP client, which must never be null.
+ *
+ * @param newHttpClient An instance of OkHttpClient
+ * @return ApiClient
+ * @throws java.lang.NullPointerException when newHttpClient is null
+ */
+ public ApiClient setHttpClient(OkHttpClient newHttpClient) {
+ this.httpClient = Objects.requireNonNull(newHttpClient, "HttpClient must not be null!");
+ return this;
+ }
+
+ /**
+ * Get JSON
+ *
+ * @return JSON object
+ */
+ public JSON getJSON() {
+ return json;
+ }
+
+ /**
+ * Set JSON
+ *
+ * @param json JSON object
+ * @return Api client
+ */
+ public ApiClient setJSON(JSON json) {
+ this.json = json;
+ return this;
+ }
+
+ /**
+ * True if isVerifyingSsl flag is on
+ *
+ * @return True if isVerifySsl flag is on
+ */
+ public boolean isVerifyingSsl() {
+ return verifyingSsl;
+ }
+
+ /**
+ * Configure whether to verify certificate and hostname when making https requests.
+ * Default to true.
+ * NOTE: Do NOT set to false in production code, otherwise you would face multiple types of cryptographic attacks.
+ *
+ * @param verifyingSsl True to verify TLS/SSL connection
+ * @return ApiClient
+ */
+ public ApiClient setVerifyingSsl(boolean verifyingSsl) {
+ this.verifyingSsl = verifyingSsl;
+ applySslSettings();
+ return this;
+ }
+
+ /**
+ * Get SSL CA cert.
+ *
+ * @return Input stream to the SSL CA cert
+ */
+ public InputStream getSslCaCert() {
+ return sslCaCert;
+ }
+
+ /**
+ * Configure the CA certificate to be trusted when making https requests.
+ * Use null to reset to default.
+ *
+ * @param sslCaCert input stream for SSL CA cert
+ * @return ApiClient
+ */
+ public ApiClient setSslCaCert(InputStream sslCaCert) {
+ this.sslCaCert = sslCaCert;
+ applySslSettings();
+ return this;
+ }
+
+ /**
+ * Getter for the field keyManagers.
+ *
+ * @return an array of {@link javax.net.ssl.KeyManager} objects
+ */
+ public KeyManager[] getKeyManagers() {
+ return keyManagers;
+ }
+
+ /**
+ * Configure client keys to use for authorization in an SSL session.
+ * Use null to reset to default.
+ *
+ * @param managers The KeyManagers to use
+ * @return ApiClient
+ */
+ public ApiClient setKeyManagers(KeyManager[] managers) {
+ this.keyManagers = managers;
+ applySslSettings();
+ return this;
+ }
+
+ /**
+ * Get TLS server name for SNI (Server Name Indication).
+ *
+ * @return The TLS server name
+ */
+ public String getTlsServerName() {
+ return tlsServerName;
+ }
+
+ /**
+ * Set TLS server name for SNI (Server Name Indication).
+ * This is used to verify the server certificate against a specific hostname
+ * instead of the hostname in the URL.
+ *
+ * @param tlsServerName The TLS server name to use for certificate verification
+ * @return ApiClient
+ */
+ public ApiClient setTlsServerName(String tlsServerName) {
+ this.tlsServerName = tlsServerName;
+ applySslSettings();
+ return this;
+ }
+
+ /**
+ * Getter for the field dateFormat.
+ *
+ * @return a {@link java.text.DateFormat} object
+ */
+ public DateFormat getDateFormat() {
+ return dateFormat;
+ }
+
+ /**
+ * Setter for the field dateFormat.
+ *
+ * @param dateFormat a {@link java.text.DateFormat} object
+ * @return a {@link {{invokerPackage}}.ApiClient} object
+ */
+ public ApiClient setDateFormat(DateFormat dateFormat) {
+ JSON.setDateFormat(dateFormat);
+ return this;
+ }
+
+ /**
+ * Set SqlDateFormat.
+ *
+ * @param dateFormat a {@link java.text.DateFormat} object
+ * @return a {@link {{invokerPackage}}.ApiClient} object
+ */
+ public ApiClient setSqlDateFormat(DateFormat dateFormat) {
+ JSON.setSqlDateFormat(dateFormat);
+ return this;
+ }
+
+ {{#joda}}
+ public ApiClient setDateTimeFormat(DateTimeFormatter dateFormat) {
+ JSON.setDateTimeFormat(dateFormat);
+ return this;
+ }
+
+ public ApiClient setLocalDateFormat(DateTimeFormatter dateFormat) {
+ JSON.setLocalDateFormat(dateFormat);
+ return this;
+ }
+
+ {{/joda}}
+ {{#jsr310}}
+ /**
+ * Set OffsetDateTimeFormat.
+ *
+ * @param dateFormat a {@link java.time.format.DateTimeFormatter} object
+ * @return a {@link {{invokerPackage}}.ApiClient} object
+ */
+ public ApiClient setOffsetDateTimeFormat(DateTimeFormatter dateFormat) {
+ JSON.setOffsetDateTimeFormat(dateFormat);
+ return this;
+ }
+
+ /**
+ * Set LocalDateFormat.
+ *
+ * @param dateFormat a {@link java.time.format.DateTimeFormatter} object
+ * @return a {@link {{invokerPackage}}.ApiClient} object
+ */
+ public ApiClient setLocalDateFormat(DateTimeFormatter dateFormat) {
+ JSON.setLocalDateFormat(dateFormat);
+ return this;
+ }
+
+ {{/jsr310}}
+ /**
+ * Set LenientOnJson.
+ *
+ * @param lenientOnJson a boolean
+ * @return a {@link {{invokerPackage}}.ApiClient} object
+ */
+ public ApiClient setLenientOnJson(boolean lenientOnJson) {
+ JSON.setLenientOnJson(lenientOnJson);
+ return this;
+ }
+
+ /**
+ * Get authentications (key: authentication name, value: authentication).
+ *
+ * @return Map of authentication objects
+ */
+ public Map getAuthentications() {
+ return authentications;
+ }
+
+ /**
+ * Get authentication for the given name.
+ *
+ * @param authName The authentication name
+ * @return The authentication, null if not found
+ */
+ public Authentication getAuthentication(String authName) {
+ 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) {
+ setBearerToken(() -> bearerToken);
+ }
+
+ /**
+ * Helper method to set the supplier of access tokens for Bearer authentication.
+ *
+ * @param tokenSupplier The supplier of bearer tokens
+ */
+ public void setBearerToken(Supplier tokenSupplier) {
+ for (Authentication auth : authentications.values()) {
+ if (auth instanceof HttpBearerAuth) {
+ ((HttpBearerAuth) auth).setBearerToken(tokenSupplier);
+ return;
+ }
+ }
+ throw new RuntimeException("No Bearer authentication configured!");
+ }
+ {{/hasHttpBearerMethods}}
+
+ /**
+ * Helper method to set username for the first HTTP basic authentication.
+ *
+ * @param username Username
+ */
+ public void setUsername(String username) {
+ for (Authentication auth : authentications.values()) {
+ if (auth instanceof HttpBasicAuth) {
+ ((HttpBasicAuth) auth).setUsername(username);
+ return;
+ }
+ }
+ throw new RuntimeException("No HTTP basic authentication configured!");
+ }
+
+ /**
+ * Helper method to set password for the first HTTP basic authentication.
+ *
+ * @param password Password
+ */
+ public void setPassword(String password) {
+ for (Authentication auth : authentications.values()) {
+ if (auth instanceof HttpBasicAuth) {
+ ((HttpBasicAuth) auth).setPassword(password);
+ return;
+ }
+ }
+ throw new RuntimeException("No HTTP basic authentication configured!");
+ }
+
+ /**
+ * Helper method to set API key value for the first API key authentication.
+ *
+ * @param apiKey API key
+ */
+ public void setApiKey(String apiKey) {
+ for (Authentication auth : authentications.values()) {
+ if (auth instanceof ApiKeyAuth) {
+ ((ApiKeyAuth) auth).setApiKey(apiKey);
+ return;
+ }
+ }
+ throw new RuntimeException("No API key authentication configured!");
+ }
+
+ /**
+ * Helper method to set API key prefix for the first API key authentication.
+ *
+ * @param apiKeyPrefix API key prefix
+ */
+ public void setApiKeyPrefix(String apiKeyPrefix) {
+ for (Authentication auth : authentications.values()) {
+ if (auth instanceof ApiKeyAuth) {
+ ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix);
+ return;
+ }
+ }
+ throw new RuntimeException("No API key authentication configured!");
+ }
+
+ /**
+ * Helper method to set access token for the first OAuth2 authentication.
+ *
+ * @param accessToken Access token
+ */
+ public void setAccessToken(String accessToken) {
+ {{#hasOAuthMethods}}
+ for (Authentication auth : authentications.values()) {
+ if (auth instanceof OAuth) {
+ ((OAuth) auth).setAccessToken(accessToken);
+ return;
+ }
+ }
+ {{/hasOAuthMethods}}
+ throw new RuntimeException("No OAuth2 authentication configured!");
+ }
+
+ /**
+ * Helper method to set credentials for AWSV4 Signature
+ *
+ * @param accessKey Access Key
+ * @param secretKey Secret Key
+ * @param region Region
+ * @param service Service to access to
+ */
+ public void setAWS4Configuration(String accessKey, String secretKey, String region, String service) {
+ {{#withAWSV4Signature}}
+ for (Authentication auth : authentications.values()) {
+ if (auth instanceof AWS4Auth) {
+ ((AWS4Auth) auth).setCredentials(accessKey, secretKey);
+ ((AWS4Auth) auth).setRegion(region);
+ ((AWS4Auth) auth).setService(service);
+ return;
+ }
+ }
+ {{/withAWSV4Signature}}
+ throw new RuntimeException("No AWS4 authentication configured!");
+ }
+
+ /**
+ * Helper method to set credentials for AWSV4 Signature
+ *
+ * @param accessKey Access Key
+ * @param secretKey Secret Key
+ * @param sessionToken Session Token
+ * @param region Region
+ * @param service Service to access to
+ */
+ public void setAWS4Configuration(String accessKey, String secretKey, String sessionToken, String region, String service) {
+ {{#withAWSV4Signature}}
+ for (Authentication auth : authentications.values()) {
+ if (auth instanceof AWS4Auth) {
+ ((AWS4Auth) auth).setCredentials(accessKey, secretKey, sessionToken);
+ ((AWS4Auth) auth).setRegion(region);
+ ((AWS4Auth) auth).setService(service);
+ return;
+ }
+ }
+ {{/withAWSV4Signature}}
+ throw new RuntimeException("No AWS4 authentication configured!");
+ }
+
+ /**
+ * Set the User-Agent header's value (by adding to the default header map).
+ *
+ * @param userAgent HTTP request's user agent
+ * @return ApiClient
+ */
+ public ApiClient setUserAgent(String userAgent) {
+ addDefaultHeader("User-Agent", userAgent);
+ return this;
+ }
+
+ /**
+ * Add a default header.
+ *
+ * @param key The header's key
+ * @param value The header's value
+ * @return ApiClient
+ */
+ public ApiClient addDefaultHeader(String key, String value) {
+ defaultHeaderMap.put(key, value);
+ return this;
+ }
+
+ /**
+ * Add a default cookie.
+ *
+ * @param key The cookie's key
+ * @param value The cookie's value
+ * @return ApiClient
+ */
+ 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 enabled, false otherwise.
+ */
+ public boolean isDebugging() {
+ return debugging;
+ }
+
+ /**
+ * Enable/disable debugging for this API client.
+ *
+ * @param debugging To enable (true) or disable (false) debugging
+ * @return ApiClient
+ */
+ public ApiClient setDebugging(boolean debugging) {
+ if (debugging != this.debugging) {
+ if (debugging) {
+ loggingInterceptor = new HttpLoggingInterceptor();
+ loggingInterceptor.setLevel(Level.BODY);
+ httpClient = httpClient.newBuilder().addInterceptor(loggingInterceptor).build();
+ } else {
+ final OkHttpClient.Builder builder = httpClient.newBuilder();
+ builder.interceptors().remove(loggingInterceptor);
+ httpClient = builder.build();
+ loggingInterceptor = null;
+ }
+ }
+ this.debugging = debugging;
+ return this;
+ }
+
+ /**
+ * The path of temporary folder used to store downloaded files from endpoints
+ * with file response. The default value is null, i.e. using
+ * the system's default temporary folder.
+ *
+ * @see createTempFile
+ * @return Temporary folder path
+ */
+ public String getTempFolderPath() {
+ return tempFolderPath;
+ }
+
+ /**
+ * Set the temporary folder path (for downloading files)
+ *
+ * @param tempFolderPath Temporary folder path
+ * @return ApiClient
+ */
+ public ApiClient setTempFolderPath(String tempFolderPath) {
+ this.tempFolderPath = tempFolderPath;
+ return this;
+ }
+
+ /**
+ * Get connection timeout (in milliseconds).
+ *
+ * @return Timeout in milliseconds
+ */
+ public int getConnectTimeout() {
+ return httpClient.connectTimeoutMillis();
+ }
+
+ /**
+ * Sets the connect timeout (in milliseconds).
+ * A value of 0 means no timeout, otherwise values must be between 1 and
+ * {@link java.lang.Integer#MAX_VALUE}.
+ *
+ * @param connectionTimeout connection timeout in milliseconds
+ * @return Api client
+ */
+ public ApiClient setConnectTimeout(int connectionTimeout) {
+ httpClient = httpClient.newBuilder().connectTimeout(connectionTimeout, TimeUnit.MILLISECONDS).build();
+ return this;
+ }
+
+ /**
+ * Get read timeout (in milliseconds).
+ *
+ * @return Timeout in milliseconds
+ */
+ public int getReadTimeout() {
+ return httpClient.readTimeoutMillis();
+ }
+
+ /**
+ * Sets the read timeout (in milliseconds).
+ * A value of 0 means no timeout, otherwise values must be between 1 and
+ * {@link java.lang.Integer#MAX_VALUE}.
+ *
+ * @param readTimeout read timeout in milliseconds
+ * @return Api client
+ */
+ public ApiClient setReadTimeout(int readTimeout) {
+ httpClient = httpClient.newBuilder().readTimeout(readTimeout, TimeUnit.MILLISECONDS).build();
+ return this;
+ }
+
+ /**
+ * Get write timeout (in milliseconds).
+ *
+ * @return Timeout in milliseconds
+ */
+ public int getWriteTimeout() {
+ return httpClient.writeTimeoutMillis();
+ }
+
+ /**
+ * Sets the write timeout (in milliseconds).
+ * A value of 0 means no timeout, otherwise values must be between 1 and
+ * {@link java.lang.Integer#MAX_VALUE}.
+ *
+ * @param writeTimeout connection timeout in milliseconds
+ * @return Api client
+ */
+ public ApiClient setWriteTimeout(int writeTimeout) {
+ httpClient = httpClient.newBuilder().writeTimeout(writeTimeout, TimeUnit.MILLISECONDS).build();
+ return this;
+ }
+
+ {{#hasOAuthMethods}}
+ /**
+ * Helper method to configure the token endpoint of the first oauth found in the apiAuthorizations (there should be only one)
+ *
+ * @return Token request builder
+ */
+ public TokenRequestBuilder getTokenEndPoint() {
+ for (Authentication apiAuth : authentications.values()) {
+ if (apiAuth instanceof RetryingOAuth) {
+ RetryingOAuth retryingOAuth = (RetryingOAuth) apiAuth;
+ return retryingOAuth.getTokenRequestBuilder();
+ }
+ }
+ return null;
+ }
+ {{/hasOAuthMethods}}
+
+ /**
+ * Format the given parameter object into string.
+ *
+ * @param param Parameter
+ * @return String representation of the parameter
+ */
+ public String parameterToString(Object param) {
+ if (param == null) {
+ return "";
+ } else if (param instanceof Date {{#joda}}|| param instanceof DateTime || param instanceof LocalDate{{/joda}}{{#jsr310}}|| param instanceof OffsetDateTime || param instanceof LocalDate{{/jsr310}}) {
+ //Serialize to json string and remove the " enclosing characters
+ String jsonStr = json.serialize(param);
+ return jsonStr.substring(1, jsonStr.length() - 1);
+ } else if (param instanceof Collection) {
+ StringBuilder b = new StringBuilder();
+ for (Object o : (Collection) param) {
+ if (b.length() > 0) {
+ b.append(",");
+ }
+ b.append(o);
+ }
+ return b.toString();
+ } else {
+ return String.valueOf(param);
+ }
+ }
+
+ /**
+ * 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 parameterToPair(String name, Object value) {
+ List params = new ArrayList();
+
+ // preconditions
+ if (name == null || name.isEmpty() || value == null || value instanceof Collection) {
+ return params;
+ }
+
+ params.add(new Pair(name, parameterToString(value)));
+ return params;
+ }
+
+ {{^dynamicOperations}}
+ /**
+ * 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 || value.isEmpty()) {
+ return params;
+ }
+
+ // create the params based on the collection format
+ 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 = ",";
+
+ // 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 : value) {
+ sb.append(delimiter);
+ sb.append(escapeString(parameterToString(item)));
+ }
+
+ params.add(new Pair(name, sb.substring(delimiter.length())));
+
+ return params;
+ }
+ {{/dynamicOperations}}
+ {{#dynamicOperations}}
+ public List parameterToPairs(Parameter param, Collection value) {
+ List params = new ArrayList();
+
+ // preconditions
+ if (param == null || param.getName() == null || param.getName().isEmpty() || value == null || value.isEmpty()) {
+ return params;
+ }
+
+ // create the params based on the collection format
+ if (StyleEnum.FORM.equals(param.getStyle()) && Boolean.TRUE.equals(param.getExplode())) {
+ for (Object item : value) {
+ params.add(new Pair(param.getName(), escapeString(parameterToString(item))));
+ }
+ return params;
+ }
+
+ // collectionFormat is assumed to be "csv" by default
+ String delimiter = ",";
+
+ // escape all delimiters except commas, which are URI reserved
+ // characters
+ if (StyleEnum.SPACEDELIMITED.equals(param.getStyle())) {
+ delimiter = escapeString(" ");
+ } else if (StyleEnum.PIPEDELIMITED.equals(param.getStyle())) {
+ delimiter = escapeString("|");
+ }
+
+ StringBuilder sb = new StringBuilder();
+ for (Object item : value) {
+ sb.append(delimiter);
+ sb.append(escapeString(parameterToString(item)));
+ }
+
+ params.add(new Pair(param.getName(), sb.substring(delimiter.length())));
+
+ return params;
+ }
+ {{/dynamicOperations}}
+
+ /**
+ * Formats the specified free-form query parameters to a list of {@code Pair} objects.
+ *
+ * @param value The free-form query parameters.
+ * @return A list of {@code Pair} objects.
+ */
+ public List freeFormParameterToPairs(Object value) {
+ List params = new ArrayList<>();
+
+ // preconditions
+ if (value == null || !(value instanceof Map )) {
+ return params;
+ }
+
+ @SuppressWarnings("unchecked")
+ final Map valuesMap = (Map) value;
+
+ for (Map.Entry entry : valuesMap.entrySet()) {
+ params.add(new Pair(entry.getKey(), parameterToString(entry.getValue())));
+ }
+
+ return params;
+ }
+
+
+ /**
+ * Formats the specified collection path parameter to a string value.
+ *
+ * @param collectionFormat The collection format of the parameter.
+ * @param value The value of the parameter.
+ * @return String representation of the parameter
+ */
+ public String collectionPathParameterToString(String collectionFormat, Collection value) {
+ // create the value based on the collection format
+ if ("multi".equals(collectionFormat)) {
+ // not valid for path params
+ return parameterToString(value);
+ }
+
+ // collectionFormat is assumed to be "csv" by default
+ String delimiter = ",";
+
+ if ("ssv".equals(collectionFormat)) {
+ delimiter = " ";
+ } else if ("tsv".equals(collectionFormat)) {
+ delimiter = "\t";
+ } else if ("pipes".equals(collectionFormat)) {
+ delimiter = "|";
+ }
+
+ StringBuilder sb = new StringBuilder() ;
+ for (Object item : value) {
+ sb.append(delimiter);
+ sb.append(parameterToString(item));
+ }
+
+ return sb.substring(delimiter.length());
+ }
+
+ /**
+ * Sanitize filename by removing path.
+ * e.g. ../../sun.gif becomes sun.gif
+ *
+ * @param filename The filename to be sanitized
+ * @return The sanitized filename
+ */
+ public String sanitizeFilename(String filename) {
+ return filename.replaceFirst("^.*[/\\\\]", "");
+ }
+
+ /**
+ * Check if the given MIME is a JSON MIME.
+ * JSON MIME examples:
+ * application/json
+ * application/json; charset=UTF8
+ * APPLICATION/JSON
+ * application/vnd.company+json
+ * "* / *" is also default to JSON
+ * @param mime MIME (Multipurpose Internet Mail Extensions)
+ * @return True if the given MIME is JSON, false otherwise.
+ */
+ public boolean isJsonMime(String mime) {
+ String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$";
+ return mime != null && (mime.matches(jsonMime) || mime.equals("*/*"));
+ }
+
+ /**
+ * Select the Accept header's value from the given accepts array:
+ * if JSON exists in the given array, use it;
+ * otherwise use all of them (joining into a string)
+ *
+ * @param accepts The accepts array to select from
+ * @return The Accept header to use. If the given array is empty,
+ * null will be returned (not to set the Accept header explicitly).
+ */
+ public String selectHeaderAccept(String[] accepts) {
+ if (accepts.length == 0) {
+ return null;
+ }
+ for (String accept : accepts) {
+ if (isJsonMime(accept)) {
+ return accept;
+ }
+ }
+ return StringUtil.join(accepts, ",");
+ }
+
+ /**
+ * Select the Content-Type header's value from the given array:
+ * if JSON exists in the given array, use it;
+ * otherwise use the first one of the array.
+ *
+ * @param contentTypes The Content-Type array to select from
+ * @return The Content-Type header to use. If the given array is empty,
+ * returns null. If it matches "any", JSON will be used.
+ */
+ public String selectHeaderContentType(String[] contentTypes) {
+ if (contentTypes.length == 0) {
+ return null;
+ }
+
+ if (contentTypes[0].equals("*/*")) {
+ return "application/json";
+ }
+
+ for (String contentType : contentTypes) {
+ if (isJsonMime(contentType)) {
+ return contentType;
+ }
+ }
+
+ return contentTypes[0];
+ }
+
+ /**
+ * Escape the given string to be used as URL query value.
+ *
+ * @param str String to be escaped
+ * @return Escaped string
+ */
+ public String escapeString(String str) {
+ try {
+ return URLEncoder.encode(str, "utf8").replaceAll("\\+", "%20");
+ } catch (UnsupportedEncodingException e) {
+ return str;
+ }
+ }
+
+ /**
+ * Deserialize response body to Java object, according to the return type and
+ * the Content-Type response header.
+ *
+ * @param Type
+ * @param response HTTP response
+ * @param returnType The type of the Java object
+ * @return The deserialized Java object
+ * @throws {{invokerPackage}}.ApiException If fail to deserialize response body, i.e. cannot read response body
+ * or the Content-Type of the response is not supported.
+ */
+ @SuppressWarnings("unchecked")
+ public T deserialize(Response response, Type returnType) throws ApiException {
+ if (response == null || returnType == null) {
+ return null;
+ }
+
+ if ("byte[]".equals(returnType.toString())) {
+ // Handle binary response (byte array).
+ try {
+ return (T) response.body().bytes();
+ } catch (IOException e) {
+ throw new ApiException(e);
+ }
+ } else if (returnType.equals(File.class)) {
+ // Handle file downloading.
+ return (T) downloadFileFromResponse(response);
+ }
+
+ ResponseBody respBody = response.body();
+ if (respBody == null) {
+ return null;
+ }
+
+ String contentType = response.headers().get("Content-Type");
+ if (contentType == null) {
+ // ensuring a default content type
+ contentType = "application/json";
+ }
+ try {
+ if (isJsonMime(contentType)) {
+ if (returnType.equals(String.class)) {
+ String respBodyString = respBody.string();
+ if (respBodyString.isEmpty()) {
+ return null;
+ }
+ // Use String-based deserialize for String return type with fallback
+ return json.deserialize(respBodyString, returnType);
+ } else {
+ // Use InputStream-based deserialize which supports responses > 2GB
+ return json.deserialize(respBody.byteStream(), returnType);
+ }
+ } else if (returnType.equals(String.class)) {
+ String respBodyString = respBody.string();
+ if (respBodyString.isEmpty()) {
+ return null;
+ }
+ // Expecting string, return the raw response body.
+ return (T) respBodyString;
+ } else {
+ throw new ApiException(
+ "Content type \"" + contentType + "\" is not supported for type: " + returnType,
+ response.code(),
+ response.headers().toMultimap(),
+ response.body().string());
+ }
+ } catch (IOException e) {
+ throw new ApiException(e);
+ }
+ }
+
+ /**
+ * Serialize the given Java object into request body according to the object's
+ * class and the request Content-Type.
+ *
+ * @param obj The Java object
+ * @param contentType The request Content-Type
+ * @return The serialized request body
+ * @throws {{invokerPackage}}.ApiException If fail to serialize the given object
+ */
+ public RequestBody serialize(Object obj, String contentType) throws ApiException {
+ if (obj instanceof byte[]) {
+ // Binary (byte array) body parameter support.
+ return RequestBody.create((byte[]) obj, MediaType.parse(contentType));
+ } else if (obj instanceof File) {
+ // File body parameter support.
+ return RequestBody.create((File) obj, MediaType.parse(contentType));
+ } else if ("text/plain".equals(contentType) && obj instanceof String) {
+ return RequestBody.create((String) obj, MediaType.parse(contentType));
+ } else if (isJsonMime(contentType)) {
+ String content;
+ if (obj != null) {
+ content = json.serialize(obj);
+ } else {
+ content = null;
+ }
+ return RequestBody.create(content, MediaType.parse(contentType));
+ } else if (obj instanceof String) {
+ return RequestBody.create((String) obj, MediaType.parse(contentType));
+ } else {
+ throw new ApiException("Content type \"" + contentType + "\" is not supported");
+ }
+ }
+
+ /**
+ * Download file from the given response.
+ *
+ * @param response An instance of the Response object
+ * @throws {{invokerPackage}}.ApiException If fail to read file content from response and write to disk
+ * @return Downloaded file
+ */
+ public File downloadFileFromResponse(Response response) throws ApiException {
+ try {
+ File file = prepareDownloadFile(response);
+ BufferedSink sink = Okio.buffer(Okio.sink(file));
+ sink.writeAll(response.body().source());
+ sink.close();
+ return file;
+ } catch (IOException e) {
+ throw new ApiException(e);
+ }
+ }
+
+ /**
+ * Prepare file for download
+ *
+ * @param response An instance of the Response object
+ * @return Prepared file for the download
+ * @throws java.io.IOException If fail to prepare file for download
+ */
+ public File prepareDownloadFile(Response response) throws IOException {
+ String filename = null;
+ String contentDisposition = response.header("Content-Disposition");
+ if (contentDisposition != null && !"".equals(contentDisposition)) {
+ // Get filename from the Content-Disposition header.
+ Pattern pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?");
+ Matcher matcher = pattern.matcher(contentDisposition);
+ if (matcher.find()) {
+ filename = sanitizeFilename(matcher.group(1));
+ }
+ }
+
+ String prefix = null;
+ String suffix = null;
+ if (filename == null) {
+ prefix = "download-";
+ suffix = "";
+ } else {
+ int pos = filename.lastIndexOf(".");
+ if (pos == -1) {
+ prefix = filename + "-";
+ } else {
+ prefix = filename.substring(0, pos) + "-";
+ suffix = filename.substring(pos);
+ }
+ // Files.createTempFile requires the prefix to be at least three characters long
+ if (prefix.length() < 3)
+ prefix = "download-";
+ }
+
+ if (tempFolderPath == null)
+ return Files.createTempFile(prefix, suffix).toFile();
+ else
+ return Files.createTempFile(Paths.get(tempFolderPath), prefix, suffix).toFile();
+ }
+
+ /**
+ * {@link #execute(Call, Type)}
+ *
+ * @param Type
+ * @param call An instance of the Call object
+ * @return ApiResponse<T>
+ * @throws {{invokerPackage}}.ApiException If fail to execute the call
+ */
+ public ApiResponse execute(Call call) throws ApiException {
+ return execute(call, null);
+ }
+
+ /**
+ * Execute HTTP call and deserialize the HTTP response body into the given return type.
+ *
+ * @param returnType The return type used to deserialize HTTP response body
+ * @param The return type corresponding to (same with) returnType
+ * @param call Call
+ * @return ApiResponse object containing response status, headers and
+ * data, which is a Java object deserialized from response body and would be null
+ * when returnType is null.
+ * @throws {{invokerPackage}}.ApiException If fail to execute the call
+ */
+ public ApiResponse execute(Call call, Type returnType) throws ApiException {
+ try {
+ Response response = call.execute();
+ T data = handleResponse(response, returnType);
+ return new ApiResponse(response.code(), response.headers().toMultimap(), data);
+ } catch (IOException e) {
+ throw new ApiException(e);
+ }
+ }
+
+ {{#supportStreaming}}
+ /**
+ * Execute stream.
+ *
+ * @param call a {@link okhttp3.Call} object
+ * @param returnType a {@link java.lang.reflect.Type} object
+ * @return a {@link java.io.InputStream} object
+ * @throws {{invokerPackage}}.ApiException if any.
+ */
+ public InputStream executeStream(Call call, Type returnType) throws ApiException {
+ try {
+ Response response = call.execute();
+ if (!response.isSuccessful()) {
+ throw new ApiException(response.code(), response.message(), response.headers().toMultimap(), null);
+ }
+ if (response.body() == null) {
+ return null;
+ }
+ return response.body().byteStream();
+ } catch (IOException e) {
+ throw new ApiException(e);
+ }
+ }
+
+ {{/supportStreaming}}
+ /**
+ * {@link #executeAsync(Call, Type, ApiCallback)}
+ *
+ * @param Type
+ * @param call An instance of the Call object
+ * @param callback ApiCallback<T>
+ */
+ public void executeAsync(Call call, ApiCallback callback) {
+ executeAsync(call, null, callback);
+ }
+
+ /**
+ * Execute HTTP call asynchronously.
+ *
+ * @param Type
+ * @param call The callback to be executed when the API call finishes
+ * @param returnType Return type
+ * @param callback ApiCallback
+ * @see #execute(Call, Type)
+ */
+ @SuppressWarnings("unchecked")
+ public void executeAsync(Call call, final Type returnType, final ApiCallback callback) {
+ call.enqueue(new Callback() {
+ @Override
+ public void onFailure(Call call, IOException e) {
+ callback.onFailure(new ApiException(e), 0, null);
+ }
+
+ @Override
+ public void onResponse(Call call, Response response) throws IOException {
+ T result;
+ try {
+ result = (T) handleResponse(response, returnType);
+ } catch (ApiException e) {
+ callback.onFailure(e, response.code(), response.headers().toMultimap());
+ return;
+ } catch (Exception e) {
+ callback.onFailure(new ApiException(e), response.code(), response.headers().toMultimap());
+ return;
+ }
+ callback.onSuccess(result, response.code(), response.headers().toMultimap());
+ }
+ });
+ }
+
+ /**
+ * Handle the given response, return the deserialized object when the response is successful.
+ *
+ * @param Type
+ * @param response Response
+ * @param returnType Return type
+ * @return Type
+ * @throws {{invokerPackage}}.ApiException If the response has an unsuccessful status code or
+ * fail to deserialize the response body
+ */
+ public T handleResponse(Response response, Type returnType) throws ApiException {
+ if (response.isSuccessful()) {
+ if (returnType == null || response.code() == 204) {
+ // returning null if the returnType is not defined,
+ // or the status code is 204 (No Content)
+ if (response.body() != null) {
+ try {
+ response.body().close();
+ } catch (Exception e) {
+ throw new ApiException(response.message(), e, response.code(), response.headers().toMultimap());
+ }
+ }
+ return null;
+ } else {
+ return deserialize(response, returnType);
+ }
+ } else {
+ String respBody = null;
+ if (response.body() != null) {
+ try {
+ respBody = response.body().string();
+ } catch (IOException e) {
+ throw new ApiException(response.message(), e, response.code(), response.headers().toMultimap());
+ }
+ }
+ throw new ApiException(response.message(), response.code(), response.headers().toMultimap(), respBody);
+ }
+ }
+
+ /**
+ * Build HTTP call with the given options.
+ *
+ * @param baseUrl The base URL
+ * @param path The sub-path of the HTTP URL
+ * @param method The request method, one of "GET", "HEAD", "OPTIONS", "POST", "PUT", "PATCH" and "DELETE"
+ * @param queryParams The query parameters
+ * @param collectionQueryParams The collection query parameters
+ * @param body The request body object
+ * @param headerParams The header parameters
+ * @param cookieParams The cookie parameters
+ * @param formParams The form parameters
+ * @param authNames The authentications to apply
+ * @param callback Callback for upload/download progress
+ * @return The HTTP call
+ * @throws {{invokerPackage}}.ApiException If fail to serialize the request body object
+ */
+ public Call buildCall(String baseUrl, String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String[] authNames, ApiCallback callback) throws ApiException {
+ Request request = buildRequest(baseUrl, path, method, queryParams, collectionQueryParams, body, headerParams, cookieParams, formParams, authNames, callback);
+
+ return httpClient.newCall(request);
+ }
+
+ /**
+ * Build an HTTP request with the given options.
+ *
+ * @param baseUrl The base URL
+ * @param path The sub-path of the HTTP URL
+ * @param method The request method, one of "GET", "HEAD", "OPTIONS", "POST", "PUT", "PATCH" and "DELETE"
+ * @param queryParams The query parameters
+ * @param collectionQueryParams The collection query parameters
+ * @param body The request body object
+ * @param headerParams The header parameters
+ * @param cookieParams The cookie parameters
+ * @param formParams The form parameters
+ * @param authNames The authentications to apply
+ * @param callback Callback for upload/download progress
+ * @return The HTTP request
+ * @throws {{invokerPackage}}.ApiException If fail to serialize the request body object
+ */
+ public Request buildRequest(String baseUrl, String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String[] authNames, ApiCallback callback) throws ApiException {
+ final String url = buildUrl(baseUrl, path, queryParams, collectionQueryParams);
+
+ // prepare HTTP request body
+ RequestBody reqBody;
+ String contentType = headerParams.get("Content-Type");
+ String contentTypePure = contentType;
+ if (contentTypePure != null && contentTypePure.contains(";")) {
+ contentTypePure = contentType.substring(0, contentType.indexOf(";"));
+ }
+ if (!HttpMethod.permitsRequestBody(method)) {
+ reqBody = null;
+ } else if ("application/x-www-form-urlencoded".equals(contentTypePure)) {
+ reqBody = buildRequestBodyFormEncoding(formParams);
+ } else if ("multipart/form-data".equals(contentTypePure)) {
+ reqBody = buildRequestBodyMultipart(formParams);
+ } else if (body == null) {
+ if ("DELETE".equals(method)) {
+ // allow calling DELETE without sending a request body
+ reqBody = null;
+ } else {
+ // use an empty request body (for POST, PUT and PATCH)
+ reqBody = RequestBody.create("", contentType == null ? null : MediaType.parse(contentType));
+ }
+ } else {
+ reqBody = serialize(body, contentType);
+ }
+
+ List updatedQueryParams = new ArrayList<>(queryParams);
+
+ String localVarPayload = requestBodyToString(reqBody);
+
+ // update parameters with authentication settings
+ for (String authName : authNames) {
+ Authentication auth = authentications.get(authName);
+ if (auth == null) {
+ throw new RuntimeException("Authentication undefined: " + authName);
+ }
+ URI currentUri = URI.create(buildUrl(baseUrl, path, updatedQueryParams, collectionQueryParams));
+ auth.applyToParams(updatedQueryParams, headerParams, cookieParams, localVarPayload, method, currentUri);
+ }
+
+ final Request.Builder reqBuilder = new Request.Builder().url(buildUrl(baseUrl, path, updatedQueryParams, collectionQueryParams));
+ processHeaderParams(headerParams, reqBuilder);
+ processCookieParams(cookieParams, reqBuilder);
+
+ // Associate callback with request (if not null) so interceptor can
+ // access it when creating ProgressResponseBody
+ reqBuilder.tag(callback);
+
+ Request request = null;
+
+ if (callback != null && reqBody != null) {
+ ProgressRequestBody progressRequestBody = new ProgressRequestBody(reqBody, callback);
+ request = reqBuilder.method(method, progressRequestBody).build();
+ } else {
+ request = reqBuilder.method(method, reqBody).build();
+ }
+
+ return request;
+ }
+
+ /**
+ * Build full URL by concatenating base path, the given sub path and query parameters.
+ *
+ * @param baseUrl The base URL
+ * @param path The sub path
+ * @param queryParams The query parameters
+ * @param collectionQueryParams The collection query parameters
+ * @return The full URL
+ */
+ public String buildUrl(String baseUrl, String path, List queryParams, List collectionQueryParams) {
+ final StringBuilder url = new StringBuilder();
+ if (baseUrl != null) {
+ url.append(baseUrl).append(path);
+ } else {
+ String baseURL;
+ if (serverIndex != null) {
+ if (serverIndex < 0 || serverIndex >= servers.size()) {
+ throw new ArrayIndexOutOfBoundsException(String.format(
+ java.util.Locale.ROOT,
+ "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;
+ }
+ url.append(baseURL).append(path);
+ }
+
+ if (queryParams != null && !queryParams.isEmpty()) {
+ // support (constant) query string in `path`, e.g. "/posts?draft=1"
+ String prefix = path.contains("?") ? "&" : "?";
+ for (Pair param : queryParams) {
+ if (param.getValue() != null) {
+ if (prefix != null) {
+ url.append(prefix);
+ prefix = null;
+ } else {
+ url.append("&");
+ }
+ String value = parameterToString(param.getValue());
+ url.append(escapeString(param.getName())).append("=").append(escapeString(value));
+ }
+ }
+ }
+
+ 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();
+ }
+
+ /**
+ * Set header parameters to the request builder, including default headers.
+ *
+ * @param headerParams Header parameters in the form of Map
+ * @param reqBuilder Request.Builder
+ */
+ public void processHeaderParams(Map headerParams, Request.Builder reqBuilder) {
+ for (Entry param : headerParams.entrySet()) {
+ reqBuilder.header(param.getKey(), parameterToString(param.getValue()));
+ }
+ for (Entry header : defaultHeaderMap.entrySet()) {
+ if (!headerParams.containsKey(header.getKey())) {
+ reqBuilder.header(header.getKey(), parameterToString(header.getValue()));
+ }
+ }
+ }
+
+ /**
+ * Set cookie parameters to the request builder, including default cookies.
+ *
+ * @param cookieParams Cookie parameters in the form of Map
+ * @param reqBuilder Request.Builder
+ */
+ public void processCookieParams(Map cookieParams, Request.Builder reqBuilder) {
+ for (Entry param : cookieParams.entrySet()) {
+ reqBuilder.addHeader("Cookie", String.format(java.util.Locale.ROOT, "%s=%s", param.getKey(), param.getValue()));
+ }
+ for (Entry param : defaultCookieMap.entrySet()) {
+ if (!cookieParams.containsKey(param.getKey())) {
+ reqBuilder.addHeader("Cookie", String.format(java.util.Locale.ROOT, "%s=%s", param.getKey(), param.getValue()));
+ }
+ }
+ }
+
+ /**
+ * Update query and header parameters based on authentication settings.
+ *
+ * @param authNames The authentications to apply
+ * @param queryParams List of query parameters
+ * @param headerParams Map of header parameters
+ * @param cookieParams Map of cookie parameters
+ * @param payload HTTP request body
+ * @param method HTTP method
+ * @param uri URI
+ * @throws {{invokerPackage}}.ApiException If fails to update the parameters
+ */
+ public void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams,
+ Map cookieParams, String payload, String method, URI uri) throws ApiException {
+ for (String authName : authNames) {
+ Authentication auth = authentications.get(authName);
+ if (auth == null) {
+ throw new RuntimeException("Authentication undefined: " + authName);
+ }
+ auth.applyToParams(queryParams, headerParams, cookieParams, payload, method, uri);
+ }
+ }
+
+ /**
+ * Build a form-encoding request body with the given form parameters.
+ *
+ * @param formParams Form parameters in the form of Map
+ * @return RequestBody
+ */
+ public RequestBody buildRequestBodyFormEncoding(Map formParams) {
+ okhttp3.FormBody.Builder formBuilder = new okhttp3.FormBody.Builder();
+ for (Entry param : formParams.entrySet()) {
+ formBuilder.add(param.getKey(), parameterToString(param.getValue()));
+ }
+ return formBuilder.build();
+ }
+
+ /**
+ * Build a multipart (file uploading) request body with the given form parameters,
+ * which could contain text fields and file fields.
+ *
+ * @param formParams Form parameters in the form of Map
+ * @return RequestBody
+ */
+ public RequestBody buildRequestBodyMultipart(Map formParams) {
+ MultipartBody.Builder mpBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM);
+ for (Entry param : formParams.entrySet()) {
+ if (param.getValue() instanceof File) {
+ File file = (File) param.getValue();
+ addPartToMultiPartBuilder(mpBuilder, param.getKey(), file);
+ } else if (param.getValue() instanceof List) {
+ List list = (List) param.getValue();
+ for (Object item: list) {
+ if (item instanceof File) {
+ addPartToMultiPartBuilder(mpBuilder, param.getKey(), (File) item);
+ } else {
+ addPartToMultiPartBuilder(mpBuilder, param.getKey(), param.getValue());
+ }
+ }
+ } else {
+ addPartToMultiPartBuilder(mpBuilder, param.getKey(), param.getValue());
+ }
+ }
+ return mpBuilder.build();
+ }
+
+ /**
+ * Guess Content-Type header from the given file (defaults to "application/octet-stream").
+ *
+ * @param file The given file
+ * @return The guessed Content-Type
+ */
+ public String guessContentTypeFromFile(File file) {
+ String contentType = URLConnection.guessContentTypeFromName(file.getName());
+ if (contentType == null) {
+ return "application/octet-stream";
+ } else {
+ return contentType;
+ }
+ }
+
+ /**
+ * Add a Content-Disposition Header for the given key and file to the MultipartBody Builder.
+ *
+ * @param mpBuilder MultipartBody.Builder
+ * @param key The key of the Header element
+ * @param file The file to add to the Header
+ */
+ protected void addPartToMultiPartBuilder(MultipartBody.Builder mpBuilder, String key, File file) {
+ Headers partHeaders = Headers.of("Content-Disposition", "form-data; name=\"" + key + "\"; filename=\"" + file.getName() + "\"");
+ MediaType mediaType = MediaType.parse(guessContentTypeFromFile(file));
+ mpBuilder.addPart(partHeaders, RequestBody.create(file, mediaType));
+ }
+
+ /**
+ * Add a Content-Disposition Header for the given key and complex object to the MultipartBody Builder.
+ *
+ * @param mpBuilder MultipartBody.Builder
+ * @param key The key of the Header element
+ * @param obj The complex object to add to the Header
+ */
+ protected void addPartToMultiPartBuilder(MultipartBody.Builder mpBuilder, String key, Object obj) {
+ RequestBody requestBody;
+ if (obj instanceof String) {
+ requestBody = RequestBody.create((String) obj, MediaType.parse("text/plain"));
+ } else {
+ String content;
+ if (obj != null) {
+ content = json.serialize(obj);
+ } else {
+ content = null;
+ }
+ requestBody = RequestBody.create(content, MediaType.parse("application/json"));
+ }
+
+ Headers partHeaders = Headers.of("Content-Disposition", "form-data; name=\"" + key + "\"");
+ mpBuilder.addPart(partHeaders, requestBody);
+ }
+
+ /**
+ * Get network interceptor to add it to the httpClient to track download progress for
+ * async requests.
+ */
+ protected Interceptor getProgressInterceptor() {
+ return new Interceptor() {
+ @Override
+ public Response intercept(Interceptor.Chain chain) throws IOException {
+ final Request request = chain.request();
+ final Response originalResponse = chain.proceed(request);
+ if (request.tag() instanceof ApiCallback) {
+ final ApiCallback callback = (ApiCallback) request.tag();
+ return originalResponse.newBuilder()
+ .body(new ProgressResponseBody(originalResponse.body(), callback))
+ .build();
+ }
+ return originalResponse;
+ }
+ };
+ }
+
+ /**
+ * Apply SSL related settings to httpClient according to the current values of
+ * verifyingSsl and sslCaCert.
+ */
+ protected void applySslSettings() {
+ try {
+ TrustManager[] trustManagers;
+ HostnameVerifier hostnameVerifier;
+ if (!verifyingSsl) {
+ trustManagers = new TrustManager[]{
+ new X509TrustManager() {
+ @Override
+ public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
+ }
+
+ @Override
+ public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
+ }
+
+ @Override
+ public java.security.cert.X509Certificate[] getAcceptedIssuers() {
+ return new java.security.cert.X509Certificate[]{};
+ }
+ }
+ };
+ hostnameVerifier = new HostnameVerifier() {
+ @Override
+ public boolean verify(String hostname, SSLSession session) {
+ return true;
+ }
+ };
+ } else {
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+
+ if (sslCaCert == null) {
+ trustManagerFactory.init((KeyStore) null);
+ } else {
+ char[] password = null; // Any password will work.
+ CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
+ Collection extends Certificate> certificates = certificateFactory.generateCertificates(sslCaCert);
+ if (certificates.isEmpty()) {
+ throw new IllegalArgumentException("expected non-empty set of trusted certificates");
+ }
+ KeyStore caKeyStore = newEmptyKeyStore(password);
+ int index = 0;
+ for (Certificate certificate : certificates) {
+ String certificateAlias = "ca" + (index++);
+ caKeyStore.setCertificateEntry(certificateAlias, certificate);
+ }
+ trustManagerFactory.init(caKeyStore);
+ }
+ trustManagers = trustManagerFactory.getTrustManagers();
+ if (tlsServerName != null && !tlsServerName.isEmpty()) {
+ hostnameVerifier = new HostnameVerifier() {
+ @Override
+ public boolean verify(String hostname, SSLSession session) {
+ // Verify the certificate against tlsServerName instead of the actual hostname
+ return OkHostnameVerifier.INSTANCE.verify(tlsServerName, session);
+ }
+ };
+ } else {
+ hostnameVerifier = OkHostnameVerifier.INSTANCE;
+ }
+ }
+
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+ sslContext.init(keyManagers, trustManagers, new SecureRandom());
+ httpClient = httpClient.newBuilder()
+ .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustManagers[0])
+ .hostnameVerifier(hostnameVerifier)
+ .build();
+ } catch (GeneralSecurityException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected KeyStore newEmptyKeyStore(char[] password) throws GeneralSecurityException {
+ try {
+ KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ keyStore.load(null, password);
+ return keyStore;
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ }
+ {{#dynamicOperations}}
+
+ public ApiClient createOperationLookupMap(OpenAPI openAPI) {
+ operationLookupMap = new HashMap<>();
+ for (Map.Entry pathItemEntry : openAPI.getPaths().entrySet()) {
+ String path = pathItemEntry.getKey();
+ PathItem pathItem = pathItemEntry.getValue();
+ addOperationLookupEntry(path, "GET", pathItem.getGet());
+ addOperationLookupEntry(path, "PUT", pathItem.getPut());
+ addOperationLookupEntry(path, "POST", pathItem.getPost());
+ addOperationLookupEntry(path, "DELETE", pathItem.getDelete());
+ addOperationLookupEntry(path, "OPTIONS", pathItem.getOptions());
+ addOperationLookupEntry(path, "HEAD", pathItem.getHead());
+ addOperationLookupEntry(path, "PATCH", pathItem.getPatch());
+ addOperationLookupEntry(path, "TRACE", pathItem.getTrace());
+ }
+ return this;
+ }
+
+ protected void addOperationLookupEntry(String path, String method, Operation operation) {
+ if ( operation != null && operation.getOperationId() != null) {
+ operationLookupMap.put(
+ operation.getOperationId(),
+ new ApiOperation(path, method, operation));
+ }
+ }
+
+ public Map getOperationLookupMap() {
+ return operationLookupMap;
+ }
+
+ public String fillParametersFromOperation(
+ Operation operation,
+ Map paramMap,
+ String path,
+ List queryParams,
+ List collectionQueryParams,
+ Map headerParams,
+ Map cookieParams
+ ) {
+ for (Map.Entry entry : paramMap.entrySet()) {
+ Object value = entry.getValue();
+ for (Parameter param : operation.getParameters()) {
+ if (entry.getKey().equals(param.getName())) {
+ switch (param.getIn()) {
+ case "path":
+ path = path.replace("{" + param.getName() + "}", escapeString(value.toString()));
+ break;
+ case "query":
+ if (value instanceof Collection>) {
+ collectionQueryParams.addAll(parameterToPairs(param, (Collection) value));
+ } else {
+ queryParams.addAll(parameterToPair(param.getName(), value));
+ }
+ break;
+ case "header":
+ headerParams.put(param.getName(), parameterToString(value));
+ break;
+ case "cookie":
+ cookieParams.put(param.getName(), parameterToString(value));
+ break;
+ default:
+ throw new IllegalStateException("Unexpected param in: " + param.getIn());
+ }
+
+ }
+ }
+ }
+ return path;
+ }
+ {{/dynamicOperations}}
+
+ /**
+ * Convert the HTTP request body to a string.
+ *
+ * @param requestBody The HTTP request object
+ * @return The string representation of the HTTP request body
+ * @throws {{invokerPackage}}.ApiException If fail to serialize the request body object into a string
+ */
+ protected String requestBodyToString(RequestBody requestBody) throws ApiException {
+ if (requestBody != null) {
+ try {
+ final Buffer buffer = new Buffer();
+ requestBody.writeTo(buffer);
+ return buffer.readUtf8();
+ } catch (final IOException e) {
+ throw new ApiException(e);
+ }
+ }
+
+ // empty http request body
+ return "";
+ }
+}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/ApiResponse.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/ApiResponse.mustache
new file mode 100644
index 000000000000..cecbaac1df27
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/ApiResponse.mustache
@@ -0,0 +1,75 @@
+{{>licenseInfo}}
+
+package {{invokerPackage}};
+
+import java.util.List;
+import java.util.Map;
+{{#caseInsensitiveResponseHeaders}}
+import java.util.Map.Entry;
+import java.util.TreeMap;
+{{/caseInsensitiveResponseHeaders}}
+
+/**
+ * API response returned by API call.
+ */
+public class ApiResponse {
+ final private int statusCode;
+ final private Map> headers;
+ final private T data;
+
+ /**
+ * Constructor for ApiResponse.
+ *
+ * @param statusCode The status code of HTTP response
+ * @param headers The headers of HTTP response
+ */
+ public ApiResponse(int statusCode, Map> headers) {
+ this(statusCode, headers, null);
+ }
+
+ /**
+ * Constructor for ApiResponse.
+ *
+ * @param statusCode The status code of HTTP response
+ * @param headers The headers of HTTP response
+ * @param data The object deserialized from response bod
+ */
+ public ApiResponse(int statusCode, Map> headers, T data) {
+ this.statusCode = statusCode;
+ {{#caseInsensitiveResponseHeaders}}
+ Map> responseHeaders = new TreeMap>(String.CASE_INSENSITIVE_ORDER);
+ for(Entry> entry : headers.entrySet()){
+ responseHeaders.put(entry.getKey().toLowerCase(), entry.getValue());
+ }
+ {{/caseInsensitiveResponseHeaders}}
+ this.headers = {{#caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}};
+ this.data = data;
+ }
+
+ /**
+ * Get the status code.
+ *
+ * @return the status code
+ */
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ /**
+ * Get the headers.
+ *
+ * @return a {@link java.util.Map} of headers
+ */
+ public Map> getHeaders() {
+ return headers;
+ }
+
+ /**
+ * Get the data.
+ *
+ * @return the data
+ */
+ public T getData() {
+ return data;
+ }
+}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/GzipRequestInterceptor.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/GzipRequestInterceptor.mustache
new file mode 100644
index 000000000000..b633aa8f5864
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/GzipRequestInterceptor.mustache
@@ -0,0 +1,74 @@
+{{>licenseInfo}}
+
+package {{invokerPackage}};
+
+import okhttp3.*;
+import okio.Buffer;
+import okio.BufferedSink;
+import okio.GzipSink;
+import okio.Okio;
+
+import java.io.IOException;
+
+/**
+ * Encodes request bodies using gzip.
+ *
+ * Taken from https://github.com/square/okhttp/issues/350
+ */
+class GzipRequestInterceptor implements Interceptor {
+ @Override
+ public Response intercept(Chain chain) throws IOException {
+ Request originalRequest = chain.request();
+ if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) {
+ return chain.proceed(originalRequest);
+ }
+
+ Request compressedRequest = originalRequest.newBuilder()
+ .header("Content-Encoding", "gzip")
+ .method(originalRequest.method(), forceContentLength(gzip(originalRequest.body())))
+ .build();
+ return chain.proceed(compressedRequest);
+ }
+
+ private RequestBody forceContentLength(final RequestBody requestBody) throws IOException {
+ final Buffer buffer = new Buffer();
+ requestBody.writeTo(buffer);
+ return new RequestBody() {
+ @Override
+ public MediaType contentType() {
+ return requestBody.contentType();
+ }
+
+ @Override
+ public long contentLength() {
+ return buffer.size();
+ }
+
+ @Override
+ public void writeTo(BufferedSink sink) throws IOException {
+ sink.write(buffer.snapshot());
+ }
+ };
+ }
+
+ private RequestBody gzip(final RequestBody body) {
+ return new RequestBody() {
+ @Override
+ public MediaType contentType() {
+ return body.contentType();
+ }
+
+ @Override
+ public long contentLength() {
+ return -1; // We don't know the compressed length in advance!
+ }
+
+ @Override
+ public void writeTo(BufferedSink sink) throws IOException {
+ BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
+ body.writeTo(gzipSink);
+ gzipSink.close();
+ }
+ };
+ }
+}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/JSON.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/JSON.mustache
new file mode 100644
index 000000000000..3245901a6563
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/JSON.mustache
@@ -0,0 +1,1040 @@
+{{>licenseInfo}}
+
+package {{invokerPackage}};
+
+import {{modelPackage}}.AbstractOpenApiSchema;
+
+{{#isGson}}
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonParseException;
+import com.google.gson.TypeAdapter;
+import com.google.gson.internal.bind.util.ISO8601Utils;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+import com.google.gson.JsonElement;
+import io.gsonfire.GsonFireBuilder;
+import io.gsonfire.TypeSelector;
+{{/isGson}}
+{{#isJackson}}
+import {{jacksonPackage}}.core.JsonGenerator;
+import {{jacksonPackage}}.core.JsonParser;
+import {{jacksonPackage}}.core.JsonToken;
+{{#useJackson3}}
+import {{jacksonPackage}}.core.JacksonException;
+{{/useJackson3}}
+import com.fasterxml.jackson.annotation.*;
+import {{jacksonPackage}}.databind.*;
+import {{jacksonPackage}}.databind.json.JsonMapper;
+{{^useJackson3}}
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+{{/useJackson3}}
+{{#useJackson3}}
+import {{jacksonPackage}}.databind.cfg.DateTimeFeature;
+import {{jacksonPackage}}.databind.cfg.EnumFeature;
+{{/useJackson3}}
+{{#openApiNullable}}
+import org.openapitools.jackson.nullable.{{#useJackson3}}JsonNullableJackson3Module{{/useJackson3}}{{^useJackson3}}JsonNullableModule{{/useJackson3}};
+{{/openApiNullable}}
+{{/isJackson}}
+{{#isJsonb}}
+import jakarta.json.bind.Jsonb;
+import jakarta.json.bind.JsonbBuilder;
+import jakarta.json.bind.JsonbConfig;
+{{/isJsonb}}
+
+{{#joda}}
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+{{#isGson}}
+import org.joda.time.format.DateTimeFormatter;
+import org.joda.time.format.DateTimeFormatterBuilder;
+import org.joda.time.format.ISODateTimeFormat;
+{{/isGson}}
+{{#isJackson}}
+import {{jacksonPackage}}.datatype.joda.JodaModule;
+{{/isJackson}}
+{{/joda}}
+
+import okio.ByteString;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringReader;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.nio.charset.StandardCharsets;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.ParsePosition;
+{{#jsr310}}
+import java.time.LocalDate;
+import java.time.OffsetDateTime;
+import java.time.format.DateTimeFormatter;
+{{/jsr310}}
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Locale;
+import java.util.Map;
+import java.util.HashMap;
+
+/*
+ * A JSON utility class
+ */
+public class JSON {
+ {{#isGson}}
+ private static Gson gson;
+ private static boolean isLenientOnJson = false;
+ private static DateTypeAdapter dateTypeAdapter = new DateTypeAdapter();
+ private static SqlDateTypeAdapter sqlDateTypeAdapter = new SqlDateTypeAdapter();
+ {{#joda}}
+ private static DateTimeTypeAdapter dateTimeTypeAdapter = new DateTimeTypeAdapter();
+ private static LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter();
+ {{/joda}}
+ {{#jsr310}}
+ private static OffsetDateTimeTypeAdapter offsetDateTimeTypeAdapter = new OffsetDateTimeTypeAdapter();
+ private static LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter();
+ {{/jsr310}}
+ private static ByteArrayAdapter byteArrayAdapter = new ByteArrayAdapter();
+ {{/isGson}}
+ {{#isJackson}}
+ private static ObjectMapper mapper;
+ {{/isJackson}}
+ {{#isJsonb}}
+ private static Jsonb jsonb;
+ {{/isJsonb}}
+
+ public JSON() {
+ {{#isGson}}
+ GsonFireBuilder fireBuilder = new GsonFireBuilder();
+ {{#models}}
+ {{#model}}
+ {{#discriminator}}
+ fireBuilder.registerTypeSelector({{modelPackage}}.{{classname}}.class, new TypeSelector<{{modelPackage}}.{{classname}}>() {
+ @Override
+ public Class extends {{modelPackage}}.{{classname}}> getClassForElement(JsonElement readElement) {
+ Map classByDiscriminatorValue = new HashMap();
+ {{#mappedModels}}
+ classByDiscriminatorValue.put("{{mappingName}}"{{^discriminatorCaseSensitive}}.toUpperCase(Locale.ROOT){{/discriminatorCaseSensitive}}, {{modelPackage}}.{{modelName}}.class);
+ {{/mappedModels}}
+ classByDiscriminatorValue.put("{{name}}"{{^discriminatorCaseSensitive}}.toUpperCase(Locale.ROOT){{/discriminatorCaseSensitive}}, {{modelPackage}}.{{classname}}.class);
+ return getClassByDiscriminator(classByDiscriminatorValue,
+ getDiscriminatorValue(readElement, "{{{propertyBaseName}}}"));
+ }
+ });
+ {{/discriminator}}
+ {{/model}}
+ {{/models}}
+ GsonBuilder builder = fireBuilder.createGsonBuilder();
+ {{#disableHtmlEscaping}}
+ builder.disableHtmlEscaping();
+ {{/disableHtmlEscaping}}
+ builder.registerTypeAdapter(Date.class, dateTypeAdapter);
+ builder.registerTypeAdapter(java.sql.Date.class, sqlDateTypeAdapter);
+ {{#joda}}
+ builder.registerTypeAdapter(DateTime.class, dateTimeTypeAdapter);
+ builder.registerTypeAdapter(LocalDate.class, localDateTypeAdapter);
+ {{/joda}}
+ {{#jsr310}}
+ builder.registerTypeAdapter(OffsetDateTime.class, offsetDateTimeTypeAdapter);
+ builder.registerTypeAdapter(LocalDate.class, localDateTypeAdapter);
+ {{/jsr310}}
+ builder.registerTypeAdapter(byte[].class, byteArrayAdapter);
+ {{#models}}
+ {{#model}}
+ {{^isEnum}}
+ {{^hasChildren}}
+ builder.registerTypeAdapterFactory(new {{modelPackage}}.{{{classname}}}.CustomTypeAdapterFactory());
+ {{/hasChildren}}
+ {{/isEnum}}
+ {{/model}}
+ {{/models}}
+ gson = builder.create();
+ {{/isGson}}
+ {{#isJackson}}
+ if (mapper == null) {
+ {{^useJackson3}}
+ mapper = JsonMapper.builder()
+ .serializationInclusion(JsonInclude.Include.NON_NULL)
+ .disable(MapperFeature.ALLOW_COERCION_OF_SCALARS)
+ {{#failOnUnknownProperties}}
+ .enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
+ {{/failOnUnknownProperties}}
+ {{^failOnUnknownProperties}}
+ .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
+ {{/failOnUnknownProperties}}
+ .enable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)
+ .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
+ .enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)
+ .enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING)
+ .defaultDateFormat(new RFC3339DateFormat())
+ .addModule(new JavaTimeModule())
+ .build();
+ {{#joda}}
+ mapper.registerModule(new JodaModule());
+ {{/joda}}
+ {{#openApiNullable}}
+ mapper.registerModule(new JsonNullableModule());
+ {{/openApiNullable}}
+ {{/useJackson3}}
+ {{#useJackson3}}
+ JsonMapper.Builder jsonMapperBuilder = JsonMapper.builder()
+ .changeDefaultPropertyInclusion(v -> v.withValueInclusion(JsonInclude.Include.NON_NULL))
+ {{#failOnUnknownProperties}}
+ .enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
+ {{/failOnUnknownProperties}}
+ {{^failOnUnknownProperties}}
+ .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
+ {{/failOnUnknownProperties}}
+ .enable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)
+ .disable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS)
+ .enable(EnumFeature.WRITE_ENUMS_USING_TO_STRING)
+ .enable(EnumFeature.READ_ENUMS_USING_TO_STRING)
+ .defaultDateFormat(new RFC3339DateFormat());
+ {{#joda}}
+ jsonMapperBuilder.addModule(new JodaModule());
+ {{/joda}}
+ {{#openApiNullable}}
+ jsonMapperBuilder.addModule(new JsonNullableJackson3Module());
+ {{/openApiNullable}}
+ mapper = jsonMapperBuilder.build();
+ {{/useJackson3}}
+ }
+ {{/isJackson}}
+ {{#isJsonb}}
+ if (jsonb == null) {
+ JsonbConfig config = new JsonbConfig();
+ jsonb = JsonbBuilder.create(config);
+ }
+ {{/isJsonb}}
+ }
+
+ {{#isGson}}
+ private static String getDiscriminatorValue(JsonElement readElement, String discriminatorField) {
+ JsonElement element = readElement.getAsJsonObject().get(discriminatorField);
+ if (null == element) {
+ throw new IllegalArgumentException("missing discriminator field: <" + discriminatorField + ">");
+ }
+ return element.getAsString();
+ }
+
+ private static Class getClassByDiscriminator(Map classByDiscriminatorValue, String discriminatorValue) {
+ Class clazz = (Class) classByDiscriminatorValue.get(discriminatorValue{{^discriminatorCaseSensitive}}.toUpperCase(Locale.ROOT){{/discriminatorCaseSensitive}});
+ if (null == clazz) {
+ throw new IllegalArgumentException("cannot determine model class of name: <" + discriminatorValue + ">");
+ }
+ return clazz;
+ }
+ {{/isGson}}
+ {{#isJackson}}
+ /**
+ * Returns the target model class that should be used to deserialize the input data.
+ * The discriminator mappings are used to determine the target model class.
+ *
+ * @param node The input data.
+ * @param modelClass The class that contains the discriminator mappings.
+ * @return the target model class.
+ */
+ public static Class> getClassForElement(JsonNode node, Class> modelClass) {
+ ClassDiscriminatorMapping cdm = modelDiscriminators.get(modelClass);
+ if (cdm != null) {
+ return cdm.getClassForElement(node, new HashSet>());
+ }
+ return null;
+ }
+
+ /**
+ * Helper class to register the discriminator mappings.
+ */
+ private static class ClassDiscriminatorMapping {
+ // The model class name.
+ Class> modelClass;
+ // The name of the discriminator property.
+ String discriminatorName;
+ // The discriminator mappings for a model class.
+ Map> discriminatorMappings;
+
+ // Constructs a new class discriminator.
+ ClassDiscriminatorMapping(Class> cls, String propertyName, Map> mappings) {
+ modelClass = cls;
+ discriminatorName = propertyName;
+ discriminatorMappings = new HashMap>();
+ if (mappings != null) {
+ discriminatorMappings.putAll(mappings);
+ }
+ }
+
+ // Return the name of the discriminator property for this model class.
+ String getDiscriminatorPropertyName() {
+ return discriminatorName;
+ }
+
+ // Return the discriminator value or null if the discriminator is not
+ // present in the payload.
+ String getDiscriminatorValue(JsonNode node) {
+ // Determine the value of the discriminator property in the input data.
+ if (discriminatorName != null) {
+ // Get the value of the discriminator property, if present in the input payload.
+ node = node.get(discriminatorName);
+ if (node != null && node.isValueNode()) {
+ {{^useJackson3}}
+ String discrValue = node.asText();
+ {{/useJackson3}}
+ {{#useJackson3}}
+ String discrValue = node.asString();
+ {{/useJackson3}}
+ if (discrValue != null) {
+ return discrValue;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the target model class that should be used to deserialize the input data.
+ * This function can be invoked for anyOf/oneOf composed models with discriminator mappings.
+ * The discriminator mappings are used to determine the target model class.
+ *
+ * @param node The input data.
+ * @param visitedClasses The set of classes that have already been visited.
+ * @return the target model class.
+ */
+ Class> getClassForElement(JsonNode node, Set> visitedClasses) {
+ if (visitedClasses.contains(modelClass)) {
+ // Class has already been visited.
+ return null;
+ }
+ // Determine the value of the discriminator property in the input data.
+ String discrValue = getDiscriminatorValue(node);
+ if (discrValue == null) {
+ return null;
+ }
+ Class> cls = discriminatorMappings.get(discrValue);
+ // It may not be sufficient to return this cls directly because that target class
+ // may itself be a composed schema, possibly with its own discriminator.
+ visitedClasses.add(modelClass);
+ for (Class> childClass : discriminatorMappings.values()) {
+ ClassDiscriminatorMapping childCdm = modelDiscriminators.get(childClass);
+ if (childCdm == null) {
+ continue;
+ }
+ if (!discriminatorName.equals(childCdm.discriminatorName)) {
+ discrValue = getDiscriminatorValue(node);
+ if (discrValue == null) {
+ continue;
+ }
+ }
+ if (childCdm != null) {
+ // Recursively traverse the discriminator mappings.
+ Class> childDiscr = childCdm.getClassForElement(node, visitedClasses);
+ if (childDiscr != null) {
+ return childDiscr;
+ }
+ }
+ }
+ return cls;
+ }
+ }
+
+ /**
+ * Returns true if inst is an instance of modelClass in the OpenAPI model hierarchy.
+ *
+ * The Java class hierarchy is not implemented the same way as the OpenAPI model hierarchy,
+ * so it's not possible to use the instanceof keyword.
+ *
+ * @param modelClass A OpenAPI model class.
+ * @param inst The instance object.
+ * @param visitedClasses The set of classes that have already been visited.
+ * @return true if inst is an instance of modelClass in the OpenAPI model hierarchy.
+ */
+ public static boolean isInstanceOf(Class> modelClass, Object inst, Set> visitedClasses) {
+ if (modelClass.isInstance(inst)) {
+ // This handles the 'allOf' use case with single parent inheritance.
+ return true;
+ }
+ if (visitedClasses.contains(modelClass)) {
+ // This is to prevent infinite recursion when the composed schemas have
+ // a circular dependency.
+ return false;
+ }
+ visitedClasses.add(modelClass);
+
+ // Traverse the oneOf/anyOf composed schemas.
+ Map> descendants = modelDescendants.get(modelClass);
+ if (descendants != null) {
+ for (Class> childType : descendants.values()) {
+ if (isInstanceOf(childType, inst, visitedClasses)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * A map of discriminators for all model classes.
+ */
+ private static Map, ClassDiscriminatorMapping> modelDiscriminators = new HashMap<>();
+
+ /**
+ * A map of oneOf/anyOf descendants for each model class.
+ */
+ private static Map, Map>> modelDescendants = new HashMap<>();
+
+ /**
+ * Register a model class discriminator.
+ *
+ * @param modelClass the model class
+ * @param discriminatorPropertyName the name of the discriminator property
+ * @param mappings a map with the discriminator mappings.
+ */
+ public static void registerDiscriminator(Class> modelClass, String discriminatorPropertyName, Map> mappings) {
+ ClassDiscriminatorMapping m = new ClassDiscriminatorMapping(modelClass, discriminatorPropertyName, mappings);
+ modelDiscriminators.put(modelClass, m);
+ }
+
+ /**
+ * Register the oneOf/anyOf descendants of the modelClass.
+ *
+ * @param modelClass the model class
+ * @param descendants a map of oneOf/anyOf descendants.
+ */
+ public static void registerDescendants(Class> modelClass, Map> descendants) {
+ modelDescendants.put(modelClass, descendants);
+ }
+ {{/isJackson}}
+
+ /**
+ * Get the internal serialization object.
+ *
+ * @return serialization object
+ */
+ public static Object getSerializer() {
+ {{#isGson}}
+ return gson;
+ {{/isGson}}
+ {{#isJackson}}
+ return mapper;
+ {{/isJackson}}
+ {{#isJsonb}}
+ return jsonb;
+ {{/isJsonb}}
+ }
+
+ /**
+ * Set the internal serialization object.
+ *
+ * @param serializer serialization object
+ */
+ public static void setSerializer(Object serializer) {
+ {{#isGson}}
+ JSON.gson = (Gson) serializer;
+ {{/isGson}}
+ {{#isJackson}}
+ JSON.mapper = (ObjectMapper) serializer;
+ {{/isJackson}}
+ {{#isJsonb}}
+ JSON.jsonb = (Jsonb) serializer;
+ {{/isJsonb}}
+ }
+
+ {{#isJsonb}}
+ /**
+ * Helper class to get the Type of a generic class.
+ */
+ public static class GenericType {
+ private final Type type;
+
+ protected GenericType() {
+ Type superclass = getClass().getGenericSuperclass();
+ this.type = ((ParameterizedType) superclass).getActualTypeArguments()[0];
+ }
+
+ public Type getType() {
+ return type;
+ }
+ }
+ {{/isJsonb}}
+ {{#isGson}}
+ public static Gson getGson() {
+ return gson;
+ }
+
+ public static void setGson(Gson gson) {
+ JSON.gson = gson;
+ }
+
+ public static void setLenientOnJson(boolean lenientOnJson) {
+ JSON.isLenientOnJson = lenientOnJson;
+ }
+
+ public static void setDateFormat(DateFormat dateFormat) {
+ dateTypeAdapter.setFormat(dateFormat);
+ }
+
+ public static void setSqlDateFormat(DateFormat dateFormat) {
+ sqlDateTypeAdapter.setFormat(dateFormat);
+ }
+
+ public static boolean isInstanceOf(Class> type, Object instance, Set> visited) {
+ if (instance == null) {
+ return true;
+ }
+ if (type.isInstance(instance)) {
+ return true;
+ }
+ if (instance instanceof AbstractOpenApiSchema) {
+ AbstractOpenApiSchema schema = (AbstractOpenApiSchema) instance;
+ visited.add(schema.getClass());
+ for (Class> allowedType : schema.getSchemas().values()) {
+ if (visited.contains(allowedType)) {
+ continue;
+ }
+ if (isInstanceOf(type, schema.getActualInstance(), visited)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ {{/isGson}}
+
+ {{#isJackson}}
+ public static ObjectMapper getMapper() {
+ return mapper;
+ }
+
+ public static void setMapper(ObjectMapper mapper) {
+ JSON.mapper = mapper;
+ }
+
+ public static void setDateFormat(DateFormat dateFormat) {
+ {{^useJackson3}}
+ mapper.setDateFormat(dateFormat);
+ {{/useJackson3}}
+ {{#useJackson3}}
+ mapper = ((JsonMapper) mapper).rebuild().defaultDateFormat(dateFormat).build();
+ {{/useJackson3}}
+ }
+
+ public static void setSqlDateFormat(DateFormat dateFormat) {
+ // TODO: implement for Jackson
+ }
+
+ public static void setLenientOnJson(boolean lenientOnJson) {
+ // TODO: implement for Jackson
+ }
+ {{/isJackson}}
+
+ {{#isJsonb}}
+ public static Jsonb getJsonb() {
+ return jsonb;
+ }
+
+ public static void setJsonb(Jsonb jsonb) {
+ JSON.jsonb = jsonb;
+ }
+
+ public static void setDateFormat(DateFormat dateFormat) {
+ // TODO: implement for JSON-B
+ }
+
+ public static void setSqlDateFormat(DateFormat dateFormat) {
+ // TODO: implement for JSON-B
+ }
+
+ public static void setLenientOnJson(boolean lenientOnJson) {
+ // TODO: implement for JSON-B
+ }
+
+ public static boolean isInstanceOf(Class> type, Object instance, Set> visited) {
+ if (instance == null) {
+ return true;
+ }
+ if (type.isInstance(instance)) {
+ return true;
+ }
+ if (instance instanceof AbstractOpenApiSchema) {
+ AbstractOpenApiSchema schema = (AbstractOpenApiSchema) instance;
+ visited.add(schema.getClass());
+ for (Class> allowedType : schema.getSchemas().values()) {
+ if (visited.contains(allowedType)) {
+ continue;
+ }
+ if (isInstanceOf(type, schema.getActualInstance(), visited)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ {{/isJsonb}}
+
+ {{#jsr310}}
+ {{#isGson}}
+ public static void setOffsetDateTimeFormat(DateTimeFormatter dateFormat) {
+ offsetDateTimeTypeAdapter.setFormat(dateFormat);
+ }
+
+ public static void setLocalDateFormat(DateTimeFormatter dateFormat) {
+ localDateTypeAdapter.setFormat(dateFormat);
+ }
+ {{/isGson}}
+ {{#isJackson}}
+ public static void setOffsetDateTimeFormat(DateTimeFormatter dateFormat) {
+ // TODO: implement for Jackson
+ }
+
+ public static void setLocalDateFormat(DateTimeFormatter dateFormat) {
+ // TODO: implement for Jackson
+ }
+ {{/isJackson}}
+ {{#isJsonb}}
+ public static void setOffsetDateTimeFormat(DateTimeFormatter dateFormat) {
+ // TODO: implement for JSON-B
+ }
+
+ public static void setLocalDateFormat(DateTimeFormatter dateFormat) {
+ // TODO: implement for JSON-B
+ }
+ {{/isJsonb}}
+ {{/jsr310}}
+
+ {{#joda}}
+ {{#isGson}}
+ public static void setDateTimeFormat(DateTimeFormatter dateFormat) {
+ dateTimeTypeAdapter.setFormat(dateFormat);
+ }
+
+ public static void setLocalDateFormat(DateTimeFormatter dateFormat) {
+ localDateTypeAdapter.setFormat(dateFormat);
+ }
+ {{/isGson}}
+ {{#isJackson}}
+ public static void setDateTimeFormat(DateTimeFormatter dateFormat) {
+ // TODO: implement for Jackson
+ }
+
+ public static void setLocalDateFormat(DateTimeFormatter dateFormat) {
+ // TODO: implement for Jackson
+ }
+ {{/isJackson}}
+ {{#isJsonb}}
+ public static void setDateTimeFormat(DateTimeFormatter dateFormat) {
+ // TODO: implement for JSON-B
+ }
+
+ public static void setLocalDateFormat(DateTimeFormatter dateFormat) {
+ // TODO: implement for JSON-B
+ }
+ {{/isJsonb}}
+ {{/joda}}
+
+ /**
+ * Serialize the given Java object into JSON string.
+ *
+ * @param obj Object
+ * @return String representation of the JSON
+ */
+ public String serialize(Object obj) {
+ {{#isGson}}
+ return gson.toJson(obj);
+ {{/isGson}}
+ {{#isJackson}}
+ try {
+ return mapper.writeValueAsString(obj);
+ } catch ({{#useJackson3}}JacksonException{{/useJackson3}}{{^useJackson3}}IOException{{/useJackson3}} e) {
+ throw new RuntimeException(e);
+ }
+ {{/isJackson}}
+ {{#isJsonb}}
+ return jsonb.toJson(obj);
+ {{/isJsonb}}
+ }
+
+ /**
+ * Deserialize the given JSON string to Java object.
+ *
+ * @param Type
+ * @param body The JSON string
+ * @param returnType The type to deserialize into
+ * @return The deserialized Java object
+ */
+ @SuppressWarnings("unchecked")
+ public T deserialize(String body, Type returnType) {
+ {{#isGson}}
+ try {
+ if (isLenientOnJson) {
+ JsonReader jsonReader = new JsonReader(new StringReader(body));
+ jsonReader.setLenient(true);
+ return gson.fromJson(jsonReader, returnType);
+ } else {
+ return gson.fromJson(body, returnType);
+ }
+ } catch (JsonParseException e) {
+ if (returnType.equals(String.class)) {
+ return (T) body;
+ } else {
+ throw (e);
+ }
+ }
+ {{/isGson}}
+ {{#isJackson}}
+ try {
+ JavaType type = mapper.getTypeFactory().constructType(returnType);
+ return mapper.readValue(body, type);
+ } catch ({{#useJackson3}}JacksonException{{/useJackson3}}{{^useJackson3}}IOException{{/useJackson3}} e) {
+ if (returnType.equals(String.class)) {
+ return (T) body;
+ } else {
+ throw new RuntimeException(e);
+ }
+ }
+ {{/isJackson}}
+ {{#isJsonb}}
+ return jsonb.fromJson(body, returnType);
+ {{/isJsonb}}
+ }
+
+ /**
+ * Deserialize the given JSON InputStream to a Java object.
+ *
+ * @param Type
+ * @param inputStream The JSON InputStream
+ * @param returnType The type to deserialize into
+ * @return The deserialized Java object
+ */
+ @SuppressWarnings("unchecked")
+ public T deserialize(InputStream inputStream, Type returnType) throws IOException {
+ {{#isGson}}
+ try (InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {
+ if (isLenientOnJson) {
+ JsonReader jsonReader = new JsonReader(reader);
+ jsonReader.setLenient(true);
+ return gson.fromJson(jsonReader, returnType);
+ } else {
+ return gson.fromJson(reader, returnType);
+ }
+ }
+ {{/isGson}}
+ {{#isJackson}}
+ JavaType type = mapper.getTypeFactory().constructType(returnType);
+ return mapper.readValue(inputStream, type);
+ {{/isJackson}}
+ {{#isJsonb}}
+ return jsonb.fromJson(inputStream, returnType);
+ {{/isJsonb}}
+ }
+
+ {{#isGson}}
+ /**
+ * Gson TypeAdapter for Byte Array type
+ */
+ public static class ByteArrayAdapter extends TypeAdapter {
+
+ @Override
+ public void write(JsonWriter out, byte[] value) throws IOException {
+ if (value == null) {
+ out.nullValue();
+ } else {
+ out.value(ByteString.of(value).base64());
+ }
+ }
+
+ @Override
+ public byte[] read(JsonReader in) throws IOException {
+ switch (in.peek()) {
+ case NULL:
+ in.nextNull();
+ return null;
+ default:
+ String bytesAsBase64 = in.nextString();
+ ByteString byteString = ByteString.decodeBase64(bytesAsBase64);
+ return byteString.toByteArray();
+ }
+ }
+ }
+
+ {{#joda}}
+ /**
+ * Gson TypeAdapter for Joda DateTime type
+ */
+ public static class DateTimeTypeAdapter extends TypeAdapter {
+
+ private DateTimeFormatter formatter;
+
+ public DateTimeTypeAdapter() {
+ this(new DateTimeFormatterBuilder()
+ .append(ISODateTimeFormat.dateTime().getPrinter(), ISODateTimeFormat.dateOptionalTimeParser().getParser())
+ .toFormatter());
+ }
+
+ public DateTimeTypeAdapter(DateTimeFormatter formatter) {
+ this.formatter = formatter;
+ }
+
+ public void setFormat(DateTimeFormatter dateFormat) {
+ this.formatter = dateFormat;
+ }
+
+ @Override
+ public void write(JsonWriter out, DateTime date) throws IOException {
+ if (date == null) {
+ out.nullValue();
+ } else {
+ out.value(formatter.print(date));
+ }
+ }
+
+ @Override
+ public DateTime read(JsonReader in) throws IOException {
+ switch (in.peek()) {
+ case NULL:
+ in.nextNull();
+ return null;
+ default:
+ String date = in.nextString();
+ return formatter.parseDateTime(date);
+ }
+ }
+ }
+
+ /**
+ * Gson TypeAdapter for Joda LocalDate type
+ */
+ public static class LocalDateTypeAdapter extends TypeAdapter {
+
+ private DateTimeFormatter formatter;
+
+ public LocalDateTypeAdapter() {
+ this(ISODateTimeFormat.date());
+ }
+
+ public LocalDateTypeAdapter(DateTimeFormatter formatter) {
+ this.formatter = formatter;
+ }
+
+ public void setFormat(DateTimeFormatter dateFormat) {
+ this.formatter = dateFormat;
+ }
+
+ @Override
+ public void write(JsonWriter out, LocalDate date) throws IOException {
+ if (date == null) {
+ out.nullValue();
+ } else {
+ out.value(formatter.print(date));
+ }
+ }
+
+ @Override
+ public LocalDate read(JsonReader in) throws IOException {
+ switch (in.peek()) {
+ case NULL:
+ in.nextNull();
+ return null;
+ default:
+ String date = in.nextString();
+ return formatter.parseLocalDate(date);
+ }
+ }
+ }
+ {{/joda}}
+ {{#jsr310}}
+ /**
+ * Gson TypeAdapter for JSR310 OffsetDateTime type
+ */
+ public static class OffsetDateTimeTypeAdapter extends TypeAdapter {
+
+ private DateTimeFormatter formatter;
+
+ public OffsetDateTimeTypeAdapter() {
+ this(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
+ }
+
+ public OffsetDateTimeTypeAdapter(DateTimeFormatter formatter) {
+ this.formatter = formatter;
+ }
+
+ public void setFormat(DateTimeFormatter dateFormat) {
+ this.formatter = dateFormat;
+ }
+
+ @Override
+ public void write(JsonWriter out, OffsetDateTime date) throws IOException {
+ if (date == null) {
+ out.nullValue();
+ } else {
+ out.value(formatter.format(date));
+ }
+ }
+
+ @Override
+ public OffsetDateTime read(JsonReader in) throws IOException {
+ switch (in.peek()) {
+ case NULL:
+ in.nextNull();
+ return null;
+ default:
+ String date = in.nextString();
+ if (date.endsWith("+0000")) {
+ date = date.substring(0, date.length()-5) + "Z";
+ }
+ return OffsetDateTime.parse(date, formatter);
+ }
+ }
+ }
+
+ /**
+ * Gson TypeAdapter for JSR310 LocalDate type
+ */
+ public static class LocalDateTypeAdapter extends TypeAdapter {
+
+ private DateTimeFormatter formatter;
+
+ public LocalDateTypeAdapter() {
+ this(DateTimeFormatter.ISO_LOCAL_DATE);
+ }
+
+ public LocalDateTypeAdapter(DateTimeFormatter formatter) {
+ this.formatter = formatter;
+ }
+
+ public void setFormat(DateTimeFormatter dateFormat) {
+ this.formatter = dateFormat;
+ }
+
+ @Override
+ public void write(JsonWriter out, LocalDate date) throws IOException {
+ if (date == null) {
+ out.nullValue();
+ } else {
+ out.value(formatter.format(date));
+ }
+ }
+
+ @Override
+ public LocalDate read(JsonReader in) throws IOException {
+ switch (in.peek()) {
+ case NULL:
+ in.nextNull();
+ return null;
+ default:
+ String date = in.nextString();
+ return LocalDate.parse(date, formatter);
+ }
+ }
+ }
+ {{/jsr310}}
+ /**
+ * Gson TypeAdapter for java.sql.Date type
+ */
+ public static class SqlDateTypeAdapter extends TypeAdapter {
+
+ private DateFormat dateFormat;
+
+ public SqlDateTypeAdapter() {}
+
+ public SqlDateTypeAdapter(DateFormat dateFormat) {
+ this.dateFormat = dateFormat;
+ }
+
+ public void setFormat(DateFormat dateFormat) {
+ this.dateFormat = dateFormat;
+ }
+
+ @Override
+ public void write(JsonWriter out, java.sql.Date date) throws IOException {
+ if (date == null) {
+ out.nullValue();
+ } else {
+ String value;
+ if (dateFormat != null) {
+ value = dateFormat.format(date);
+ } else {
+ value = date.toString();
+ }
+ out.value(value);
+ }
+ }
+
+ @Override
+ public java.sql.Date read(JsonReader in) throws IOException {
+ switch (in.peek()) {
+ case NULL:
+ in.nextNull();
+ return null;
+ default:
+ String date = in.nextString();
+ try {
+ if (dateFormat != null) {
+ return new java.sql.Date(dateFormat.parse(date).getTime());
+ }
+ return new java.sql.Date(ISO8601Utils.parse(date, new ParsePosition(0)).getTime());
+ } catch (ParseException e) {
+ throw new JsonParseException(e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Gson TypeAdapter for java.util.Date type
+ */
+ public static class DateTypeAdapter extends TypeAdapter {
+
+ private DateFormat dateFormat;
+
+ public DateTypeAdapter() {}
+
+ public DateTypeAdapter(DateFormat dateFormat) {
+ this.dateFormat = dateFormat;
+ }
+
+ public void setFormat(DateFormat dateFormat) {
+ this.dateFormat = dateFormat;
+ }
+
+ @Override
+ public void write(JsonWriter out, Date date) throws IOException {
+ if (date == null) {
+ out.nullValue();
+ } else {
+ String value;
+ if (dateFormat != null) {
+ value = dateFormat.format(date);
+ } else {
+ value = ISO8601Utils.format(date, true);
+ }
+ out.value(value);
+ }
+ }
+
+ @Override
+ public Date read(JsonReader in) throws IOException {
+ try {
+ switch (in.peek()) {
+ case NULL:
+ in.nextNull();
+ return null;
+ default:
+ String date = in.nextString();
+ try {
+ if (dateFormat != null) {
+ return dateFormat.parse(date);
+ }
+ return ISO8601Utils.parse(date, new ParsePosition(0));
+ } catch (ParseException e) {
+ throw new JsonParseException(e);
+ }
+ }
+ } catch (IllegalArgumentException e) {
+ throw new JsonParseException(e);
+ }
+ }
+ }
+ {{/isGson}}
+}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/ProgressRequestBody.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/ProgressRequestBody.mustache
new file mode 100644
index 000000000000..71e1e2b4cbe8
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/ProgressRequestBody.mustache
@@ -0,0 +1,62 @@
+{{>licenseInfo}}
+
+package {{invokerPackage}};
+
+import okhttp3.MediaType;
+import okhttp3.RequestBody;
+
+import java.io.IOException;
+
+import okio.Buffer;
+import okio.BufferedSink;
+import okio.ForwardingSink;
+import okio.Okio;
+import okio.Sink;
+
+public class ProgressRequestBody extends RequestBody {
+
+ private final RequestBody requestBody;
+
+ private final ApiCallback callback;
+
+ public ProgressRequestBody(RequestBody requestBody, ApiCallback callback) {
+ this.requestBody = requestBody;
+ this.callback = callback;
+ }
+
+ @Override
+ public MediaType contentType() {
+ return requestBody.contentType();
+ }
+
+ @Override
+ public long contentLength() throws IOException {
+ return requestBody.contentLength();
+ }
+
+ @Override
+ public void writeTo(BufferedSink sink) throws IOException {
+ BufferedSink bufferedSink = Okio.buffer(sink(sink));
+ requestBody.writeTo(bufferedSink);
+ bufferedSink.flush();
+ }
+
+ private Sink sink(Sink sink) {
+ return new ForwardingSink(sink) {
+
+ long bytesWritten = 0L;
+ long contentLength = 0L;
+
+ @Override
+ public void write(Buffer source, long byteCount) throws IOException {
+ super.write(source, byteCount);
+ if (contentLength == 0) {
+ contentLength = contentLength();
+ }
+
+ bytesWritten += byteCount;
+ callback.onUploadProgress(bytesWritten, contentLength, bytesWritten == contentLength);
+ }
+ };
+ }
+}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/ProgressResponseBody.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/ProgressResponseBody.mustache
new file mode 100644
index 000000000000..45115940b665
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/ProgressResponseBody.mustache
@@ -0,0 +1,59 @@
+{{>licenseInfo}}
+
+package {{invokerPackage}};
+
+import okhttp3.MediaType;
+import okhttp3.ResponseBody;
+
+import java.io.IOException;
+
+import okio.Buffer;
+import okio.BufferedSource;
+import okio.ForwardingSource;
+import okio.Okio;
+import okio.Source;
+
+public class ProgressResponseBody extends ResponseBody {
+
+ private final ResponseBody responseBody;
+ private final ApiCallback callback;
+ private BufferedSource bufferedSource;
+
+ public ProgressResponseBody(ResponseBody responseBody, ApiCallback callback) {
+ this.responseBody = responseBody;
+ this.callback = callback;
+ }
+
+ @Override
+ public MediaType contentType() {
+ return responseBody.contentType();
+ }
+
+ @Override
+ public long contentLength() {
+ return responseBody.contentLength();
+ }
+
+ @Override
+ public BufferedSource source() {
+ if (bufferedSource == null) {
+ bufferedSource = Okio.buffer(source(responseBody.source()));
+ }
+ return bufferedSource;
+ }
+
+ private Source source(Source source) {
+ return new ForwardingSource(source) {
+ long totalBytesRead = 0L;
+
+ @Override
+ public long read(Buffer sink, long byteCount) throws IOException {
+ long bytesRead = super.read(sink, byteCount);
+ // read() returns the number of bytes read, or -1 if this source is exhausted.
+ totalBytesRead += bytesRead != -1 ? bytesRead : 0;
+ callback.onDownloadProgress(totalBytesRead, responseBody.contentLength(), bytesRead == -1);
+ return bytesRead;
+ }
+ };
+ }
+}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/README.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/README.mustache
new file mode 100644
index 000000000000..de3afa6c1875
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/README.mustache
@@ -0,0 +1,195 @@
+# {{artifactId}}
+
+{{appName}}
+- API version: {{appVersion}}
+{{^hideGenerationTimestamp}}
+ - Build date: {{generatedDate}}
+{{/hideGenerationTimestamp}}
+ - Generator version: {{generatorVersion}}
+
+{{{appDescriptionWithNewLines}}}
+
+{{#infoUrl}}
+ For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}})
+{{/infoUrl}}
+
+*Automatically generated by the [OpenAPI Generator](https://openapi-generator.tech)*
+
+
+## Requirements
+
+Building the API client library requires:
+1. Java 1.8+
+2. Maven (3.8.3+)/Gradle (7.2+)
+
+## Installation
+
+To install the API client library to your local Maven repository, simply execute:
+
+```shell
+mvn clean install
+```
+
+To deploy it to a remote Maven repository instead, configure the settings of the repository and execute:
+
+```shell
+mvn clean deploy
+```
+
+Refer to the [OSSRH Guide](http://central.sonatype.org/pages/ossrh-guide.html) for more information.
+
+### Maven users
+
+Add this dependency to your project's POM:
+
+```xml
+
+ {{{groupId}}}
+ {{{artifactId}}}
+ {{{artifactVersion}}}
+ compile
+
+```
+
+### Gradle users
+
+Add this dependency to your project's build file:
+
+```groovy
+ repositories {
+ mavenCentral() // Needed if the '{{{artifactId}}}' jar has been published to maven central.
+ mavenLocal() // Needed if the '{{{artifactId}}}' jar has been published to the local maven repo.
+ }
+
+ dependencies {
+ implementation "{{{groupId}}}:{{{artifactId}}}:{{{artifactVersion}}}"
+ }
+```
+
+### Others
+
+At first generate the JAR by executing:
+
+```shell
+mvn clean package
+```
+
+Then manually install the following JARs:
+
+* `target/{{{artifactId}}}-{{{artifactVersion}}}.jar`
+* `target/lib/*.jar`
+
+## Getting Started
+
+Please follow the [installation](#installation) instruction and execute the following Java code:
+
+```java
+{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}}
+// Import classes:
+import {{{invokerPackage}}}.ApiClient;
+import {{{invokerPackage}}}.ApiException;
+import {{{invokerPackage}}}.Configuration;{{#hasAuthMethods}}
+import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}}
+import {{{modelPackage}}}.*;
+import {{{package}}}.{{{classname}}};
+
+public class Example {
+ public static void main(String[] args) {
+ ApiClient defaultClient = Configuration.getDefaultApiClient();
+ defaultClient.setBasePath("{{{basePath}}}");
+ {{#withAWSV4Signature}}
+ // Configure AWS Signature V4 authorization
+ defaultClient.setAWS4Configuration("YOUR_ACCESS_KEY", "YOUR_SECRET_KEY", "REGION", "SERVICE")
+ {{/withAWSV4Signature}}
+ {{#hasAuthMethods}}
+ {{#authMethods}}{{#isBasic}}{{#isBasicBasic}}
+ // Configure HTTP basic authorization: {{{name}}}
+ HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}");
+ {{{name}}}.setUsername("YOUR USERNAME");
+ {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasicBasic}}{{#isBasicBearer}}
+ // Configure HTTP bearer authorization: {{{name}}}
+ HttpBearerAuth {{{name}}} = (HttpBearerAuth) defaultClient.getAuthentication("{{{name}}}");
+ {{{name}}}.setBearerToken("BEARER TOKEN");{{/isBasicBearer}}{{/isBasic}}{{#isApiKey}}
+ // Configure API key authorization: {{{name}}}
+ ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}");
+ {{{name}}}.setApiKey("YOUR API KEY");
+ // Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null)
+ //{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}}
+ // Configure OAuth2 access token for authorization: {{{name}}}
+ OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}");
+ {{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}}
+ {{/authMethods}}
+ {{/hasAuthMethods}}
+
+ {{{classname}}} apiInstance = new {{{classname}}}(defaultClient);
+ {{#allParams}}
+ {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}}
+ {{/allParams}}
+ try {
+ {{#returnType}}{{{.}}} result = {{/returnType}}apiInstance.{{{operationId}}}{{^vendorExtensions.x-group-parameters}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}({{#requiredParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/requiredParams}}){{#optionalParams}}
+ .{{{paramName}}}({{{paramName}}}){{/optionalParams}}
+ .execute();{{/vendorExtensions.x-group-parameters}}{{#returnType}}
+ System.out.println(result);{{/returnType}}
+ } catch (ApiException e) {
+ System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}");
+ System.err.println("Status code: " + e.getCode());
+ System.err.println("Reason: " + e.getResponseBody());
+ System.err.println("Response headers: " + e.getResponseHeaders());
+ e.printStackTrace();
+ }
+ }
+}
+{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}}
+```
+
+## Documentation for API Endpoints
+
+All URIs are relative to *{{basePath}}*
+
+Class | Method | HTTP request | Description
+------------ | ------------- | ------------- | -------------
+{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{summary}}
+{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
+
+## Documentation for Models
+
+{{#models}}{{#model}} - [{{classname}}]({{modelDocPath}}{{classname}}.md)
+{{/model}}{{/models}}
+
+
+## Documentation for Authorization
+
+{{^authMethods}}Endpoints do not require authorization.{{/authMethods}}
+{{#hasAuthMethods}}Authentication schemes defined for the API:{{/hasAuthMethods}}
+{{#authMethods}}
+
+### {{name}}
+
+{{#isApiKey}}- **Type**: API key
+- **API key parameter name**: {{keyParamName}}
+- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}}
+{{/isApiKey}}
+{{#isBasicBasic}}- **Type**: HTTP basic authentication
+{{/isBasicBasic}}
+{{#isBasicBearer}}- **Type**: HTTP Bearer Token authentication{{#bearerFormat}} ({{{.}}}){{/bearerFormat}}
+{{/isBasicBearer}}
+{{#isHttpSignature}}- **Type**: HTTP signature authentication
+{{/isHttpSignature}}
+{{#isOAuth}}- **Type**: OAuth
+- **Flow**: {{flow}}
+- **Authorization URL**: {{authorizationUrl}}
+- **Scopes**: {{^scopes}}N/A{{/scopes}}
+{{#scopes}} - {{scope}}: {{description}}
+{{/scopes}}
+{{/isOAuth}}
+
+{{/authMethods}}
+
+## Recommendation
+
+It's recommended to create an instance of `ApiClient` per thread in a multithreaded environment to avoid any potential issues.
+
+## Author
+
+{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}}
+{{/-last}}{{/apis}}{{/apiInfo}}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/additional_properties.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/additional_properties.mustache
new file mode 100644
index 000000000000..bca54f84d575
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/additional_properties.mustache
@@ -0,0 +1,46 @@
+{{#isAdditionalPropertiesTrue}}
+ /**
+ * A container for additional, undeclared properties.
+ * This is a holder for any undeclared properties as specified with
+ * the 'additionalProperties' keyword in the OAS document.
+ */
+ private Map additionalProperties;
+
+ /**
+ * Set the additional (undeclared) property with the specified name and value.
+ * If the property does not already exist, create it otherwise replace it.
+ *
+ * @param key name of the property
+ * @param value value of the property
+ * @return the {{classname}} instance itself
+ */
+ public {{classname}} putAdditionalProperty(String key, Object value) {
+ if (this.additionalProperties == null) {
+ this.additionalProperties = new HashMap();
+ }
+ this.additionalProperties.put(key, value);
+ return this;
+ }
+
+ /**
+ * Return the additional (undeclared) property.
+ *
+ * @return a map of objects
+ */
+ public Map getAdditionalProperties() {
+ return additionalProperties;
+ }
+
+ /**
+ * Return the additional (undeclared) property with the specified name.
+ *
+ * @param key name of the property
+ * @return an object
+ */
+ public Object getAdditionalProperty(String key) {
+ if (this.additionalProperties == null) {
+ return null;
+ }
+ return this.additionalProperties.get(key);
+ }
+{{/isAdditionalPropertiesTrue}}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/anyof_model.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/anyof_model.mustache
new file mode 100644
index 000000000000..ceb1e7e0ed12
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/anyof_model.mustache
@@ -0,0 +1,632 @@
+{{#isGson}}
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonParseException;
+import com.google.gson.TypeAdapter;
+import com.google.gson.TypeAdapterFactory;
+import com.google.gson.reflect.TypeToken;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.annotations.JsonAdapter;
+import com.google.gson.annotations.SerializedName;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonArray;
+{{/isGson}}
+{{#isJackson}}
+import {{jacksonPackage}}.core.JsonGenerator;
+import {{jacksonPackage}}.core.JsonParser;
+import {{jacksonPackage}}.core.JsonToken;
+import {{jacksonPackage}}.core.type.TypeReference;
+import {{jacksonPackage}}.databind.DeserializationContext;
+{{^useJackson3}}
+import {{jacksonPackage}}.databind.JsonMappingException;
+{{/useJackson3}}
+import {{jacksonPackage}}.databind.JsonNode;
+import {{jacksonPackage}}.databind.MapperFeature;
+{{^useJackson3}}
+import {{jacksonPackage}}.databind.SerializerProvider;
+{{/useJackson3}}
+import {{jacksonPackage}}.databind.annotation.JsonDeserialize;
+import {{jacksonPackage}}.databind.annotation.JsonSerialize;
+import {{jacksonPackage}}.databind.deser.std.StdDeserializer;
+import {{jacksonPackage}}.databind.ser.std.StdSerializer;
+import {{jacksonPackage}}.databind.JavaType;
+{{#useJackson3}}
+import {{jacksonPackage}}.core.JacksonException;
+import {{jacksonPackage}}.databind.DatabindException;
+import {{jacksonPackage}}.databind.SerializationContext;
+{{/useJackson3}}
+{{/isJackson}}
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.StringJoiner;
+
+import {{invokerPackage}}.JSON;
+
+{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}}
+{{#isJackson}}
+@JsonDeserialize(using = {{classname}}.{{classname}}Deserializer.class)
+@JsonSerialize(using = {{classname}}.{{classname}}Serializer.class)
+{{/isJackson}}
+public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}} implements {{{.}}}{{^-last}}, {{/-last}}{{/vendorExtensions.x-implements}} {
+ private static final Logger log = Logger.getLogger({{classname}}.class.getName());
+
+ {{#isGson}}
+ /**
+ * Validates the JSON Element and throws an exception if issues found
+ *
+ * @param jsonElement JSON Element
+ * @throws IOException if the JSON Element is invalid with respect to {{classname}}
+ */
+ public static void validateJsonElement(JsonElement jsonElement) throws IOException {
+ List errorMessages = new ArrayList<>();
+ int matches = 0;
+
+ {{#composedSchemas}}
+ {{#anyOf}}
+ {{^vendorExtensions.x-duplicated-data-type}}
+ try {
+ // validate the JSON object to see if any exception is thrown
+ {{#isModel}}
+ {{#hasChildren}}
+ {{{dataType}}}.validateJsonElement(jsonElement);
+ {{/hasChildren}}
+ {{^hasChildren}}
+ {{#isArray}}
+ if (!jsonElement.isJsonArray()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be a array type in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isArray}}
+ {{^isArray}}
+ {{#isMap}}
+ if (!jsonElement.isJsonObject()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be a object type in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isMap}}
+ {{^isMap}}
+ {{{dataType}}}.validateJsonElement(jsonElement);
+ {{/isMap}}
+ {{/isArray}}
+ {{/hasChildren}}
+ {{/isModel}}
+ {{#isPrimitiveType}}
+ {{#isArray}}
+ if (!jsonElement.isJsonArray()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be a array type in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isArray}}
+ {{^isArray}}
+ {{#isMap}}
+ if (!jsonElement.isJsonObject()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be a object type in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isMap}}
+ {{^isMap}}
+ if (!jsonElement.isJsonPrimitive()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be a primitive type in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isMap}}
+ {{/isArray}}
+ {{/isPrimitiveType}}
+ matches++;
+ } catch (Exception e) {
+ // deserialization failed, continue
+ errorMessages.add(String.format("Deserialization for {{{dataType}}} failed with `%s`.", e.getMessage()));
+ }
+
+ {{/vendorExtensions.x-duplicated-data-type}}
+ {{/anyOf}}
+ {{/composedSchemas}}
+
+ if (matches == 0) {
+ throw new IOException(String.format("Failed deserialization for {{classname}}: no match found. %s", errorMessages));
+ }
+ }
+
+ public static class CustomTypeAdapterFactory implements TypeAdapterFactory {
+ @SuppressWarnings("unchecked")
+ @Override
+ public TypeAdapter create(Gson gson, TypeToken type) {
+ if (!{{classname}}.class.isAssignableFrom(type.getRawType())) {
+ return null; // this class only serializes '{{classname}}' and its subtypes
+ }
+ final TypeAdapter elementAdapter = gson.getAdapter(JsonElement.class);
+ {{#composedSchemas}}
+ {{#anyOf}}
+ {{^isArray}}
+ {{^vendorExtensions.x-duplicated-data-type}}
+ final TypeAdapter<{{{dataType}}}> adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}} = gson.getDelegateAdapter(this, TypeToken.get({{{dataType}}}.class));
+ {{/vendorExtensions.x-duplicated-data-type}}
+ {{/isArray}}
+ {{#isArray}}
+ final Type typeInstance{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}} = new TypeToken<{{{dataType}}}>(){}.getType();
+ final TypeAdapter<{{{dataType}}}> adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}} = (TypeAdapter<{{{dataType}}}>) gson.getDelegateAdapter(this, TypeToken.get(typeInstance));
+ {{/isArray}}
+ {{/anyOf}}
+ {{/composedSchemas}}
+
+ return (TypeAdapter) new TypeAdapter<{{classname}}>() {
+ @Override
+ public void write(JsonWriter out, {{classname}} value) throws IOException {
+ if (value == null || value.getActualInstance() == null) {
+ elementAdapter.write(out, null);
+ return;
+ }
+
+ {{#composedSchemas}}
+ {{#anyOf}}
+ {{^vendorExtensions.x-duplicated-data-type}}
+ // check if the actual instance is of the type `{{{dataType}}}`
+ if (value.getActualInstance() instanceof {{#isArray}}List>{{/isArray}}{{^isArray}}{{{dataType}}}{{/isArray}}) {
+ {{#isPrimitiveType}}
+ JsonPrimitive primitive = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.toJsonTree(({{{dataType}}})value.getActualInstance()).getAsJsonPrimitive();
+ elementAdapter.write(out, primitive);
+ return;
+ {{/isPrimitiveType}}
+ {{^isPrimitiveType}}
+ {{#isArray}}
+ List> list = (List>) value.getActualInstance();
+ if (!list.isEmpty() && list.get(0) instanceof {{{items.dataType}}}) {
+ JsonArray array = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.toJsonTree(({{{dataType}}})value.getActualInstance()).getAsJsonArray();
+ elementAdapter.write(out, array);
+ return;
+ }
+ {{/isArray}}
+ {{/isPrimitiveType}}
+ {{^isArray}}
+ {{^isPrimitiveType}}
+ JsonElement element = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.toJsonTree(({{{dataType}}})value.getActualInstance());
+ elementAdapter.write(out, element);
+ return;
+ {{/isPrimitiveType}}
+ {{/isArray}}
+ }
+ {{/vendorExtensions.x-duplicated-data-type}}
+ {{/anyOf}}
+ {{/composedSchemas}}
+ throw new IOException("Failed to serialize as the type doesn't match anyOf schemas: {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}");
+ }
+
+ @Override
+ public {{classname}} read(JsonReader in) throws IOException {
+ Object deserialized = null;
+ JsonElement jsonElement = elementAdapter.read(in);
+
+ ArrayList errorMessages = new ArrayList<>();
+ TypeAdapter actualAdapter = elementAdapter;
+
+ {{#composedSchemas}}
+ {{#anyOf}}
+ {{^vendorExtensions.x-duplicated-data-type}}
+ // deserialize {{{dataType}}}
+ try {
+ // validate the JSON object to see if any exception is thrown
+ {{#isModel}}
+ {{#hasChildren}}
+ {{{dataType}}}.validateJsonElement(jsonElement);
+ {{/hasChildren}}
+ {{^hasChildren}}
+ {{#isArray}}
+ if (!jsonElement.isJsonArray()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be a array type in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isArray}}
+ {{^isArray}}
+ {{#isMap}}
+ if (!jsonElement.isJsonObject()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be a object type in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isMap}}
+ {{^isMap}}
+ {{{dataType}}}.validateJsonElement(jsonElement);
+ {{/isMap}}
+ {{/isArray}}
+ {{/hasChildren}}
+ {{/isModel}}
+ {{#isPrimitiveType}}
+ {{#isArray}}
+ if (!jsonElement.isJsonArray()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be a array type in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isArray}}
+ {{^isArray}}
+ {{#isMap}}
+ if (!jsonElement.isJsonObject()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be a object type in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isMap}}
+ {{^isMap}}
+ if (!jsonElement.isJsonPrimitive()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be a primitive type in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isMap}}
+ {{/isArray}}
+ {{/isPrimitiveType}}
+ {{classname}} ret = new {{classname}}();
+ ret.setActualInstance(adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.fromJsonTree(jsonElement));
+ return ret;
+ } catch (Exception e) {
+ // deserialization failed, continue
+ errorMessages.add(String.format("Deserialization for {{{dataType}}} failed with `%s`.", e.getMessage()));
+ log.log(Level.FINER, "Input data does not match schema '{{{dataType}}}'", e);
+ }
+
+ {{/vendorExtensions.x-duplicated-data-type}}
+ {{/anyOf}}
+ {{/composedSchemas}}
+
+ throw new IOException(String.format("Failed deserialization for {{classname}}: no match found. %s", errorMessages));
+ }
+ };
+ }
+ }
+ {{/isGson}}
+
+ {{#isJackson}}
+ public static class {{classname}}Serializer extends StdSerializer<{{classname}}> {
+ public {{classname}}Serializer(Class<{{classname}}> t) {
+ super(t);
+ }
+
+ public {{classname}}Serializer() {
+ this(null);
+ }
+
+ @Override
+ public void serialize({{classname}} value, JsonGenerator jgen, {{^useJackson3}}SerializerProvider provider{{/useJackson3}}{{#useJackson3}}SerializationContext serializationContext{{/useJackson3}}) throws {{^useJackson3}}IOException{{/useJackson3}}{{#useJackson3}}JacksonException{{/useJackson3}} {
+ {{^useJackson3}}
+ jgen.writeObject(value.getActualInstance());
+ {{/useJackson3}}
+ {{#useJackson3}}
+ serializationContext.writeValue(jgen, value.getActualInstance());
+ {{/useJackson3}}
+ }
+ }
+
+ public static class {{classname}}Deserializer extends StdDeserializer<{{classname}}> {
+ public {{classname}}Deserializer() {
+ this({{classname}}.class);
+ }
+
+ public {{classname}}Deserializer(Class> vc) {
+ super(vc);
+ }
+
+ @Override
+ public {{classname}} deserialize(JsonParser jp, DeserializationContext ctxt) throws {{^useJackson3}}IOException{{/useJackson3}}{{#useJackson3}}JacksonException{{/useJackson3}} {
+ JsonNode tree = ctxt.readTree(jp);
+ Object deserialized = null;
+ {{#discriminator}}
+ Class> cls = JSON.getClassForElement(tree, new {{classname}}().getClass());
+ if (cls != null) {
+ {{^useJackson3}}
+ deserialized = tree.traverse(jp.getCodec()).readValueAs(cls);
+ {{/useJackson3}}
+ {{#useJackson3}}
+ deserialized = ctxt.readTreeAsValue(tree, ctxt.constructType(cls));
+ {{/useJackson3}}
+ {{classname}} ret = new {{classname}}();
+ ret.setActualInstance(deserialized);
+ return ret;
+ }
+ {{/discriminator}}
+ {{#anyOf}}
+ // deserialize {{{.}}}
+ try {
+ {{^useJackson3}}
+ deserialized = tree.traverse(jp.getCodec()).readValueAs({{{.}}}.class);
+ {{/useJackson3}}
+ {{#useJackson3}}
+ deserialized = ctxt.readTreeAsValue(tree, {{{.}}}.class);
+ {{/useJackson3}}
+ {{classname}} ret = new {{classname}}();
+ ret.setActualInstance(deserialized);
+ return ret;
+ } catch (Exception e) {
+ // deserialization failed, continue
+ log.log(Level.FINER, "Input data does not match schema '{{{.}}}'", e);
+ }
+
+ {{/anyOf}}
+ {{^useJackson3}}
+ throw new IOException(String.format(java.util.Locale.ROOT, "Failed deserialization for {{classname}}: no match found"));
+ {{/useJackson3}}
+ {{#useJackson3}}
+ throw DatabindException.from(jp, String.format(java.util.Locale.ROOT, "Failed deserialization for {{classname}}: no match found"));
+ {{/useJackson3}}
+ }
+
+ /**
+ * Handle deserialization of the 'null' value.
+ */
+ @Override
+ {{^useJackson3}}
+ public {{classname}} getNullValue(DeserializationContext ctxt) throws JsonMappingException {
+ {{/useJackson3}}
+ {{#useJackson3}}
+ public {{classname}} getNullValue(DeserializationContext ctxt) {
+ {{/useJackson3}}
+ {{#isNullable}}
+ return null;
+ {{/isNullable}}
+ {{^isNullable}}
+ {{^useJackson3}}
+ throw new JsonMappingException(ctxt.getParser(), "{{classname}} cannot be null");
+ {{/useJackson3}}
+ {{#useJackson3}}
+ throw DatabindException.from(ctxt.getParser(), "{{classname}} cannot be null");
+ {{/useJackson3}}
+ {{/isNullable}}
+ }
+ }
+ {{/isJackson}}
+
+ // store a list of schema names defined in anyOf
+ public static final Map> schemas = new HashMap<>();
+
+ public {{classname}}() {
+ super("anyOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}});
+ }
+
+ {{#anyOf}}
+ public {{classname}}({{{.}}} o) {
+ super("anyOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}});
+ setActualInstance(o);
+ }
+
+ {{/anyOf}}
+ static {
+ {{#anyOf}}
+ schemas.put("{{{.}}}", {{{.}}}.class);
+ {{/anyOf}}
+ {{#isJackson}}
+ JSON.registerDescendants({{classname}}.class, Collections.unmodifiableMap(schemas));
+ {{#discriminator}}
+ // Initialize and register the discriminator mappings.
+ Map> mappings = new HashMap>();
+ {{#mappedModels}}
+ mappings.put("{{mappingName}}", {{modelName}}.class);
+ {{/mappedModels}}
+ mappings.put("{{name}}", {{classname}}.class);
+ JSON.registerDiscriminator({{classname}}.class, "{{propertyBaseName}}", mappings);
+ {{/discriminator}}
+ {{/isJackson}}
+ }
+
+ @Override
+ public Map> getSchemas() {
+ return {{classname}}.schemas;
+ }
+
+ /**
+ * Set the instance that matches the anyOf child schema, check
+ * the instance parameter is valid against the anyOf child schemas:
+ * {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}
+ *
+ * It could be an instance of the 'anyOf' schemas.
+ * The anyOf child schemas may themselves be a composed schema (allOf, anyOf, anyOf).
+ */
+ @Override
+ public void setActualInstance(Object instance) {
+ {{#isNullable}}
+ if (instance == null) {
+ super.setActualInstance(instance);
+ return;
+ }
+
+ {{/isNullable}}
+ {{#anyOf}}
+ if (JSON.isInstanceOf({{{.}}}.class, instance, new HashSet>())) {
+ super.setActualInstance(instance);
+ return;
+ }
+
+ {{/anyOf}}
+ throw new RuntimeException("Invalid instance type. Must be {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}");
+ }
+
+ /**
+ * Get the actual instance, which can be the following:
+ * {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}
+ *
+ * @return The actual instance ({{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}})
+ */
+ @Override
+ public Object getActualInstance() {
+ return super.getActualInstance();
+ }
+
+ {{#anyOf}}
+ /**
+ * Get the actual instance of `{{{.}}}`. If the actual instance is not `{{{.}}}`,
+ * the ClassCastException will be thrown.
+ *
+ * @return The actual instance of `{{{.}}}`
+ * @throws ClassCastException if the instance is not `{{{.}}}`
+ */
+ public {{{.}}} get{{{.}}}() throws ClassCastException {
+ return ({{{.}}})super.getActualInstance();
+ }
+
+ {{/anyOf}}
+
+{{#supportUrlQuery}}
+
+ /**
+ * Convert the instance into URL query string.
+ *
+ * @return URL query string
+ */
+ public String toUrlQueryString() {
+ return toUrlQueryString(null);
+ }
+
+ /**
+ * Convert the instance into URL query string.
+ *
+ * @param prefix prefix of the query string
+ * @return URL query string
+ */
+ public String toUrlQueryString(String prefix) {
+ String suffix = "";
+ String containerSuffix = "";
+ String containerPrefix = "";
+ if (prefix == null) {
+ // style=form, explode=true, e.g. /pet?name=cat&type=manx
+ prefix = "";
+ } else {
+ // deepObject style e.g. /pet?id[name]=cat&id[type]=manx
+ prefix = prefix + "[";
+ suffix = "]";
+ containerSuffix = "]";
+ containerPrefix = "[";
+ }
+
+ StringJoiner joiner = new StringJoiner("&");
+
+ {{#composedSchemas.oneOf}}
+ {{^vendorExtensions.x-duplicated-data-type}}
+ if (getActualInstance() instanceof {{{dataType}}}) {
+ {{#isArray}}
+ {{#items.isPrimitiveType}}
+ {{#uniqueItems}}
+ if (getActualInstance() != null) {
+ int i = 0;
+ for ({{{items.dataType}}} _item : ({{{dataType}}})getActualInstance()) {
+ joiner.add(String.format(java.util.Locale.ROOT, "%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, i, containerSuffix),
+ ApiClient.urlEncode(String.valueOf(_item))));
+ }
+ i++;
+ }
+ {{/uniqueItems}}
+ {{^uniqueItems}}
+ if (getActualInstance() != null) {
+ for (int i = 0; i < (({{{dataType}}})getActualInstance()).size(); i++) {
+ joiner.add(String.format(java.util.Locale.ROOT, "%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, i, containerSuffix),
+ ApiClient.urlEncode(String.valueOf(getActualInstance().get(i)))));
+ }
+ }
+ {{/uniqueItems}}
+ {{/items.isPrimitiveType}}
+ {{^items.isPrimitiveType}}
+ {{#items.isModel}}
+ {{#uniqueItems}}
+ if (getActualInstance() != null) {
+ int i = 0;
+ for ({{{items.dataType}}} _item : ({{{dataType}}})getActualInstance()) {
+ if (_item != null) {
+ joiner.add(_item.toUrlQueryString(String.format(java.util.Locale.ROOT, "%s{{baseName}}%s%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, i, containerSuffix))));
+ }
+ }
+ i++;
+ }
+ {{/uniqueItems}}
+ {{^uniqueItems}}
+ if (getActualInstance() != null) {
+ for (int i = 0; i < (({{{dataType}}})getActualInstance()).size(); i++) {
+ if ((({{{dataType}}})getActualInstance()).get(i) != null) {
+ joiner.add((({{{items.dataType}}})getActualInstance()).get(i).toUrlQueryString(String.format(java.util.Locale.ROOT, "%s{{baseName}}%s%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, i, containerSuffix))));
+ }
+ }
+ }
+ {{/uniqueItems}}
+ {{/items.isModel}}
+ {{^items.isModel}}
+ {{#uniqueItems}}
+ if (getActualInstance() != null) {
+ int i = 0;
+ for ({{{items.dataType}}} _item : ({{{dataType}}})getActualInstance()) {
+ if (_item != null) {
+ joiner.add(String.format(java.util.Locale.ROOT, "%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, i, containerSuffix),
+ ApiClient.urlEncode(String.valueOf(_item))));
+ }
+ i++;
+ }
+ }
+ {{/uniqueItems}}
+ {{^uniqueItems}}
+ if (getActualInstance() != null) {
+ for (int i = 0; i < (({{{dataType}}})getActualInstance()).size(); i++) {
+ if (getActualInstance().get(i) != null) {
+ joiner.add(String.format(java.util.Locale.ROOT, "%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, i, containerSuffix),
+ ApiClient.urlEncode(String.valueOf((({{{dataType}}})getActualInstance()).get(i)))));
+ }
+ }
+ }
+ {{/uniqueItems}}
+ {{/items.isModel}}
+ {{/items.isPrimitiveType}}
+ {{/isArray}}
+ {{^isArray}}
+ {{#isMap}}
+ {{#items.isPrimitiveType}}
+ if (getActualInstance() != null) {
+ for (String _key : (({{{dataType}}})getActualInstance()).keySet()) {
+ joiner.add(String.format(java.util.Locale.ROOT, "%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, _key, containerSuffix),
+ getActualInstance().get(_key), ApiClient.urlEncode(String.valueOf((({{{dataType}}})getActualInstance()).get(_key)))));
+ }
+ }
+ {{/items.isPrimitiveType}}
+ {{^items.isPrimitiveType}}
+ if (getActualInstance() != null) {
+ for (String _key : (({{{dataType}}})getActualInstance()).keySet()) {
+ if ((({{{dataType}}})getActualInstance()).get(_key) != null) {
+ joiner.add((({{{items.dataType}}})getActualInstance()).get(_key).toUrlQueryString(String.format(java.util.Locale.ROOT, "%s{{baseName}}%s%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, _key, containerSuffix))));
+ }
+ }
+ }
+ {{/items.isPrimitiveType}}
+ {{/isMap}}
+ {{^isMap}}
+ {{#isPrimitiveType}}
+ if (getActualInstance() != null) {
+ joiner.add(String.format(java.util.Locale.ROOT, "%s{{{baseName}}}%s=%s", prefix, suffix, ApiClient.urlEncode(String.valueOf(getActualInstance()))));
+ }
+ {{/isPrimitiveType}}
+ {{^isPrimitiveType}}
+ {{#isModel}}
+ if (getActualInstance() != null) {
+ joiner.add((({{{dataType}}})getActualInstance()).toUrlQueryString(prefix + "{{{baseName}}}" + suffix));
+ }
+ {{/isModel}}
+ {{^isModel}}
+ if (getActualInstance() != null) {
+ joiner.add(String.format(java.util.Locale.ROOT, "%s{{{baseName}}}%s=%s", prefix, suffix, ApiClient.urlEncode(String.valueOf(getActualInstance()))));
+ }
+ {{/isModel}}
+ {{/isPrimitiveType}}
+ {{/isMap}}
+ {{/isArray}}
+ return joiner.toString();
+ }
+ {{/vendorExtensions.x-duplicated-data-type}}
+ {{/composedSchemas.oneOf}}
+ return null;
+ }
+{{/supportUrlQuery}}
+
+}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/api.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/api.mustache
new file mode 100644
index 000000000000..29e9d152a37d
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/api.mustache
@@ -0,0 +1,626 @@
+{{>licenseInfo}}
+
+package {{package}};
+
+import {{invokerPackage}}.ApiCallback;
+import {{invokerPackage}}.ApiClient;
+import {{invokerPackage}}.ApiException;
+{{#dynamicOperations}}
+import {{invokerPackage}}.ApiOperation;
+{{/dynamicOperations}}
+import {{invokerPackage}}.ApiResponse;
+import {{invokerPackage}}.JSON;
+import {{invokerPackage}}.Configuration;
+import {{invokerPackage}}.Pair;
+import {{invokerPackage}}.ProgressRequestBody;
+import {{invokerPackage}}.ProgressResponseBody;
+{{#performBeanValidation}}
+import {{invokerPackage}}.BeanValidationException;
+{{/performBeanValidation}}
+
+{{#isGson}}
+import com.google.gson.reflect.TypeToken;
+{{/isGson}}
+{{#isJackson}}
+import {{jacksonPackage}}.core.type.TypeReference;
+{{/isJackson}}
+{{#dynamicOperations}}
+import io.swagger.v3.oas.models.Operation;
+import io.swagger.v3.oas.models.parameters.Parameter;
+{{/dynamicOperations}}
+
+import java.io.IOException;
+
+{{#useBeanValidation}}
+import {{javaxPackage}}.validation.constraints.*;
+import {{javaxPackage}}.validation.Valid;
+{{/useBeanValidation}}
+{{#performBeanValidation}}
+import {{javaxPackage}}.validation.ConstraintViolation;
+import {{javaxPackage}}.validation.Validation;
+import {{javaxPackage}}.validation.ValidatorFactory;
+import {{javaxPackage}}.validation.executable.ExecutableValidator;
+import java.util.Set;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+{{/performBeanValidation}}
+
+{{#imports}}import {{import}};
+{{/imports}}
+
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+{{#supportStreaming}}
+import java.io.InputStream;
+{{/supportStreaming}}
+
+{{#operations}}
+public class {{classname}} {
+ private ApiClient localVarApiClient;
+ private int localHostIndex;
+ private String localCustomBaseUrl;
+
+ public {{classname}}() {
+ this(Configuration.getDefaultApiClient());
+ }
+
+ public {{classname}}(ApiClient apiClient) {
+ this.localVarApiClient = apiClient;
+ }
+
+ public ApiClient getApiClient() {
+ return localVarApiClient;
+ }
+
+ public void setApiClient(ApiClient apiClient) {
+ this.localVarApiClient = apiClient;
+ }
+
+ public int getHostIndex() {
+ return localHostIndex;
+ }
+
+ public void setHostIndex(int hostIndex) {
+ this.localHostIndex = hostIndex;
+ }
+
+ public String getCustomBaseUrl() {
+ return localCustomBaseUrl;
+ }
+
+ public void setCustomBaseUrl(String customBaseUrl) {
+ this.localCustomBaseUrl = customBaseUrl;
+ }
+
+ {{#operation}}
+ {{^vendorExtensions.x-group-parameters}}/**
+ * Build call for {{operationId}}{{#allParams}}
+ * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}{{/allParams}}
+ * @param _callback Callback for upload/download progress
+ * @return Call to execute
+ * @throws ApiException If fail to serialize the request body object
+ {{#responses.0}}
+ * @http.response.details
+
+ Response Details
+ Status Code Description Response Headers
+ {{#responses}}
+ {{code}} {{message}} {{#headers}} * {{baseName}} - {{description}} {{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses}}
+
+ {{/responses.0}}
+ {{#isDeprecated}}
+ * @deprecated
+ {{/isDeprecated}}
+ {{#externalDocs}}
+ * {{description}}
+ * @see {{summary}} Documentation
+ {{/externalDocs}}
+ */
+ {{#isDeprecated}}
+ @Deprecated
+ {{/isDeprecated}}
+ public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} okhttp3.Call {{operationId}}Call({{#allParams}}{{>nullableArgument}} {{paramName}}, {{/allParams}}final ApiCallback _callback) throws ApiException {
+ String basePath = null;
+ // Operation Servers
+ String[] localBasePaths = new String[] { {{#servers}}"{{{url}}}"{{^-last}}, {{/-last}}{{/servers}} };
+
+ // Determine Base Path to Use
+ if (localCustomBaseUrl != null){
+ basePath = localCustomBaseUrl;
+ } else if ( localBasePaths.length > 0 ) {
+ basePath = localBasePaths[localHostIndex];
+ } else {
+ basePath = null;
+ }
+
+ Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}};
+
+ // create path and map variables
+ {{^dynamicOperations}}
+ String localVarPath = "{{{path}}}"{{#pathParams}}
+ .replace("{" + "{{baseName}}" + "}", localVarApiClient.escapeString({{#collectionFormat}}localVarApiClient.collectionPathParameterToString("{{{collectionFormat}}}", {{{paramName}}}){{/collectionFormat}}{{^collectionFormat}}{{{paramName}}}.toString(){{/collectionFormat}})){{/pathParams}};
+ {{/dynamicOperations}}
+ {{#dynamicOperations}}
+ ApiOperation apiOperation = localVarApiClient.getOperationLookupMap().get("{{{operationId}}}");
+ if (apiOperation == null) {
+ throw new ApiException("Operation not found in OAS");
+ }
+ Operation operation = apiOperation.getOperation();
+ String localVarPath = apiOperation.getPath();
+ Map paramMap = new HashMap<>();
+ {{#allParams}}
+ {{^isFormParam}}
+ {{^isBodyParam}}
+ paramMap.put("{{baseName}}", {{paramName}});
+ {{/isBodyParam}}
+ {{/isFormParam}}
+ {{/allParams}}
+ {{/dynamicOperations}}
+
+ List localVarQueryParams = new ArrayList();
+ List localVarCollectionQueryParams = new ArrayList();
+ Map localVarHeaderParams = new HashMap();
+ Map localVarCookieParams = new HashMap();
+ Map localVarFormParams = new HashMap();
+
+ {{#formParams}}
+ if ({{paramName}} != null) {
+ localVarFormParams.put("{{baseName}}", {{paramName}});
+ }
+
+ {{/formParams}}
+ {{^dynamicOperations}}
+ {{#queryParams}}
+ if ({{paramName}} != null) {
+ {{#isFreeFormObject}}localVarQueryParams.addAll(localVarApiClient.freeFormParameterToPairs({{paramName}}));{{/isFreeFormObject}}{{^isFreeFormObject}}{{#collectionFormat}}localVarCollectionQueryParams.addAll(localVarApiClient.parameterToPairs("{{{.}}}", {{/collectionFormat}}{{^collectionFormat}}localVarQueryParams.addAll(localVarApiClient.parameterToPair({{/collectionFormat}}"{{baseName}}", {{paramName}}));{{/isFreeFormObject}}
+ }
+
+ {{/queryParams}}
+ {{#constantParams}}
+ {{#isQueryParam}}
+ // Set client side default value of Query Param "{{baseName}}".
+ localVarCollectionQueryParams.add(new Pair("{{baseName}}", {{#_enum}}"{{{.}}}"{{/_enum}}));
+
+ {{/isQueryParam}}
+ {{/constantParams}}
+ {{#constantParams}}
+ {{#isHeaderParam}}
+ // Set client side default value of Header Param "{{baseName}}".
+ localVarHeaderParams.put("{{baseName}}", {{#_enum}}"{{{.}}}"{{/_enum}});
+
+ {{/isHeaderParam}}
+ {{/constantParams}}
+ {{#cookieParams}}
+ if ({{paramName}} != null) {
+ localVarCookieParams.put("{{baseName}}", localVarApiClient.parameterToString({{paramName}}));
+ }
+
+ {{/cookieParams}}
+ {{#constantParams}}
+ {{#isCookieParam}}
+ // Set client side default value of Cookie Param "{{baseName}}".
+ localVarCookieParams.put("{{baseName}}", {{#_enum}}"{{{.}}}"{{/_enum}});
+
+ {{/isCookieParam}}
+ {{/constantParams}}
+ {{/dynamicOperations}}
+ {{#dynamicOperations}}
+ localVarPath = localVarApiClient.fillParametersFromOperation(operation, paramMap, localVarPath, localVarQueryParams, localVarCollectionQueryParams, localVarHeaderParams, localVarCookieParams);
+
+ {{/dynamicOperations}}
+ final String[] localVarAccepts = {
+ {{#produces}}
+ "{{{mediaType}}}"{{^-last}},{{/-last}}
+ {{/produces}}
+ };
+ final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts);
+ if (localVarAccept != null) {
+ localVarHeaderParams.put("Accept", localVarAccept);
+ }
+
+ final String[] localVarContentTypes = {
+ {{#consumes}}
+ "{{{mediaType}}}"{{^-last}},{{/-last}}
+ {{/consumes}}
+ };
+ final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes);
+ if (localVarContentType != null) {
+ localVarHeaderParams.put("Content-Type", localVarContentType);
+ }
+ {{^dynamicOperations}}
+ {{#headerParams}}
+
+ if ({{paramName}} != null) {
+ localVarHeaderParams.put("{{baseName}}", localVarApiClient.parameterToString({{paramName}}));
+ }
+
+ {{/headerParams}}
+ {{/dynamicOperations}}
+
+ String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{#-last}}{{#withAWSV4Signature}}, {{/withAWSV4Signature}}{{/-last}}{{/authMethods}}{{#withAWSV4Signature}}"AWS4Auth"{{/withAWSV4Signature}} };
+ return localVarApiClient.buildCall(basePath, localVarPath, {{^dynamicOperations}}"{{httpMethod}}"{{/dynamicOperations}}{{#dynamicOperations}}apiOperation.getMethod(){{/dynamicOperations}}, localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback);
+ }
+
+ {{#isDeprecated}}
+ @Deprecated
+ {{/isDeprecated}}
+ @SuppressWarnings("rawtypes")
+ private okhttp3.Call {{operationId}}ValidateBeforeCall({{#allParams}}{{>nullableArgument}} {{paramName}}, {{/allParams}}final ApiCallback _callback) throws ApiException {
+ {{^performBeanValidation}}
+ {{#allParams}}
+ {{#required}}
+ // verify the required parameter '{{paramName}}' is set
+ if ({{paramName}} == null) {
+ throw new ApiException("Missing the required parameter '{{paramName}}' when calling {{operationId}}(Async)");
+ }
+
+ {{/required}}
+ {{/allParams}}
+ return {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}_callback);
+
+ {{/performBeanValidation}}
+ {{#performBeanValidation}}
+ try {
+ ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
+ ExecutableValidator executableValidator = factory.getValidator().forExecutables();
+
+ Object[] parameterValues = { {{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}} };
+ Method method = this.getClass().getMethod("{{operationId}}WithHttpInfo"{{#allParams}}, {{#isArray}}java.util.List{{/isArray}}{{#isMap}}java.util.Map{{/isMap}}{{^isArray}}{{^isMap}}{{>nullable_var_annotations}} {{{dataType}}}{{/isMap}}{{/isArray}}.class{{/allParams}});
+ Set> violations = executableValidator.validateParameters(this, method,
+ parameterValues);
+
+ if (violations.size() == 0) {
+ return {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}_callback);
+ } else {
+ throw new BeanValidationException((Set) violations);
+ }
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ throw new ApiException(e.getMessage());
+ } catch (SecurityException e) {
+ e.printStackTrace();
+ throw new ApiException(e.getMessage());
+ }
+ {{/performBeanValidation}}
+ }
+
+ {{^vendorExtensions.x-group-parameters}}
+ /**
+ * {{summary}}
+ * {{notes}}{{#allParams}}
+ * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}{{/allParams}}{{#returnType}}
+ * @return {{.}}{{/returnType}}
+ * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body
+ {{#responses.0}}
+ * @http.response.details
+
+ Response Details
+ Status Code Description Response Headers
+ {{#responses}}
+ {{code}} {{message}} {{#headers}} * {{baseName}} - {{description}} {{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses}}
+
+ {{/responses.0}}
+ {{#isDeprecated}}
+ * @deprecated
+ {{/isDeprecated}}
+ {{#externalDocs}}
+ * {{description}}
+ * @see {{summary}} Documentation
+ {{/externalDocs}}
+ */
+ {{#isDeprecated}}
+ @Deprecated
+ {{/isDeprecated}}
+ {{#vendorExtensions.x-streaming}}
+ public {{#returnType}}InputStream {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{>nullableArgument}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException {
+ {{#returnType}}InputStream localVarResp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}}
+ return localVarResp;{{/returnType}}
+ }
+ {{/vendorExtensions.x-streaming}}
+ {{^vendorExtensions.x-streaming}}
+ public {{#returnType}}{{{.}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{>nullableArgument}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException {
+ {{#returnType}}ApiResponse<{{{.}}}> localVarResp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}}
+ return localVarResp.getData();{{/returnType}}
+ }
+ {{/vendorExtensions.x-streaming}}
+ {{/vendorExtensions.x-group-parameters}}
+
+ {{^vendorExtensions.x-group-parameters}}/**
+ * {{summary}}
+ * {{notes}}{{#allParams}}
+ * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}{{/allParams}}
+ * @return ApiResponse<{{returnType}}{{^returnType}}Void{{/returnType}}>
+ * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body
+ {{#responses.0}}
+ * @http.response.details
+
+ Response Details
+ Status Code Description Response Headers
+ {{#responses}}
+ {{code}} {{message}} {{#headers}} * {{baseName}} - {{description}} {{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses}}
+
+ {{/responses.0}}
+ {{#isDeprecated}}
+ * @deprecated
+ {{/isDeprecated}}
+ {{#externalDocs}}
+ * {{description}}
+ * @see {{summary}} Documentation
+ {{/externalDocs}}
+ */
+ {{#isDeprecated}}
+ @Deprecated
+ {{/isDeprecated}}
+ public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-streaming}} InputStream {{operationId}}WithHttpInfo({{#allParams}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{>nullable_var_annotations}} {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException {
+ okhttp3.Call localVarCall = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}null);
+ {{#returnType}}
+ {{#errorObjectType}}
+ try {
+ {{#isGson}}Type localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType();{{/isGson}}
+ {{#isJackson}}Type localVarReturnType = new TypeReference<{{{returnType}}}>(){}.getType();{{/isJackson}}
+ {{#isJsonb}}Type localVarReturnType = new JSON.GenericType<{{{returnType}}}>(){}.getType();{{/isJsonb}}
+ return localVarApiClient.executeStream(localVarCall, localVarReturnType);
+ } catch (ApiException e) {
+ {{#isGson}}e.setErrorObject(localVarApiClient.getJSON().getGson().fromJson(e.getResponseBody(), new TypeToken<{{{errorObjectType}}}>(){}.getType()));{{/isGson}}
+ {{#isJsonb}}e.setErrorObject(localVarApiClient.getJSON().deserialize(e.getResponseBody(), new JSON.GenericType<{{{errorObjectType}}}>(){}.getType()));{{/isJsonb}}
+ throw e;
+ }
+ {{/errorObjectType}}
+ {{^errorObjectType}}
+ {{#isGson}}Type localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType();{{/isGson}}
+ {{#isJackson}}Type localVarReturnType = new TypeReference<{{{returnType}}}>(){}.getType();{{/isJackson}}
+ {{#isJsonb}}Type localVarReturnType = new JSON.GenericType<{{{returnType}}}>(){}.getType();{{/isJsonb}}
+ return localVarApiClient.executeStream(localVarCall, localVarReturnType);
+ {{/errorObjectType}}
+ {{/returnType}}
+ }
+ {{/vendorExtensions.x-streaming}}{{^vendorExtensions.x-streaming}} ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{>nullableArgument}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException {
+ okhttp3.Call localVarCall = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}null);
+ {{^returnType}}
+ return localVarApiClient.execute(localVarCall);
+ {{/returnType}}
+ {{#returnType}}
+ {{#errorObjectType}}
+ try {
+ {{#isGson}}Type localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType();{{/isGson}}
+ {{#isJackson}}Type localVarReturnType = new TypeReference<{{{returnType}}}>(){}.getType();{{/isJackson}}
+ {{#isJsonb}}Type localVarReturnType = new JSON.GenericType<{{{returnType}}}>(){}.getType();{{/isJsonb}}
+ return localVarApiClient.execute(localVarCall, localVarReturnType);
+ } catch (ApiException e) {
+ {{#isGson}}e.setErrorObject(localVarApiClient.getJSON().getGson().fromJson(e.getResponseBody(), new TypeToken<{{{errorObjectType}}}>(){}.getType()));{{/isGson}}
+ {{#isJsonb}}e.setErrorObject(localVarApiClient.getJSON().deserialize(e.getResponseBody(), new JSON.GenericType<{{{errorObjectType}}}>(){}.getType()));{{/isJsonb}}
+ throw e;
+ }
+ {{/errorObjectType}}
+ {{^errorObjectType}}
+ {{#isGson}}Type localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType();{{/isGson}}
+ {{#isJackson}}Type localVarReturnType = new TypeReference<{{{returnType}}}>(){}.getType();{{/isJackson}}
+ {{#isJsonb}}Type localVarReturnType = new JSON.GenericType<{{{returnType}}}>(){}.getType();{{/isJsonb}}
+ return localVarApiClient.execute(localVarCall, localVarReturnType);
+ {{/errorObjectType}}
+ {{/returnType}}
+ }
+ {{/vendorExtensions.x-streaming}}
+
+ {{^vendorExtensions.x-group-parameters}}/**
+ * {{summary}} (asynchronously)
+ * {{notes}}{{#allParams}}
+ * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}{{/allParams}}
+ * @param _callback The callback to be executed when the API call finishes
+ * @return The request call
+ * @throws ApiException If fail to process the API call, e.g. serializing the request body object
+ {{#responses.0}}
+ * @http.response.details
+
+ Response Details
+ Status Code Description Response Headers
+ {{#responses}}
+ {{code}} {{message}} {{#headers}} * {{baseName}} - {{description}} {{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses}}
+
+ {{/responses.0}}
+ {{#isDeprecated}}
+ * @deprecated
+ {{/isDeprecated}}
+ {{#externalDocs}}
+ * {{description}}
+ * @see {{summary}} Documentation
+ {{/externalDocs}}
+ */
+ {{#isDeprecated}}
+ @Deprecated
+ {{/isDeprecated}}
+ public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} okhttp3.Call {{operationId}}Async({{#allParams}}{{>nullableArgument}} {{paramName}}, {{/allParams}}final ApiCallback<{{{returnType}}}{{^returnType}}Void{{/returnType}}> _callback) throws ApiException {
+
+ okhttp3.Call localVarCall = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}_callback);
+ {{#returnType}}{{#isGson}}Type localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType();{{/isGson}}{{#isJackson}}Type localVarReturnType = new TypeReference<{{{returnType}}}>(){}.getType();{{/isJackson}}{{#isJsonb}}Type localVarReturnType = new JSON.GenericType<{{{returnType}}}>(){}.getType();{{/isJsonb}}
+ localVarApiClient.executeAsync(localVarCall, localVarReturnType, _callback);{{/returnType}}{{^returnType}}localVarApiClient.executeAsync(localVarCall, _callback);{{/returnType}}
+ return localVarCall;
+ }
+ {{#vendorExtensions.x-group-parameters}}
+
+ public class API{{operationId}}Request {
+ {{#requiredParams}}
+ {{>nullable_var_annotations}}{{! prevent indent}}
+ private final {{#lambda.jSpecifyDatatype}}{{{dataType}}}{{/lambda.jSpecifyDatatype}} {{paramName}};
+ {{/requiredParams}}
+ {{#optionalParams}}
+ {{>nullable_var_annotations}}{{! prevent indent}}
+ private {{#lambda.jSpecifyDatatype}}{{{dataType}}}{{/lambda.jSpecifyDatatype}} {{paramName}};
+ {{/optionalParams}}
+
+ private API{{operationId}}Request({{#requiredParams}}{{>nullableArgument}} {{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}) {
+ {{#requiredParams}}
+ this.{{paramName}} = {{paramName}};
+ {{/requiredParams}}
+ }
+
+ {{#optionalParams}}
+ /**
+ * Set {{paramName}}
+ * @param {{paramName}} {{description}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}})
+ * @return API{{operationId}}Request
+ */
+ public API{{operationId}}Request {{paramName}}({{>nullableArgument}} {{paramName}}) {
+ this.{{paramName}} = {{paramName}};
+ return this;
+ }
+
+ {{/optionalParams}}
+ /**
+ * Build call for {{operationId}}
+ * @param _callback ApiCallback API callback
+ * @return Call to execute
+ * @throws ApiException If fail to serialize the request body object
+ {{#responses.0}}
+ * @http.response.details
+
+ Response Details
+ Status Code Description Response Headers
+ {{#responses}}
+ {{code}} {{message}} {{#headers}} * {{baseName}} - {{description}} {{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses}}
+
+ {{/responses.0}}
+ {{#isDeprecated}}
+ * @deprecated
+ {{/isDeprecated}}
+ */
+ {{#isDeprecated}}
+ @Deprecated
+ {{/isDeprecated}}
+ public okhttp3.Call buildCall(final ApiCallback _callback) throws ApiException {
+ return {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}_callback);
+ }
+
+ /**
+ * Execute {{operationId}} request{{#returnType}}
+ * @return {{.}}{{/returnType}}
+ * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body
+ {{#responses.0}}
+ * @http.response.details
+
+ Response Details
+ Status Code Description Response Headers
+ {{#responses}}
+ {{code}} {{message}} {{#headers}} * {{baseName}} - {{description}} {{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses}}
+
+ {{/responses.0}}
+ {{#isDeprecated}}
+ * @deprecated
+ {{/isDeprecated}}
+ */
+ {{#isDeprecated}}
+ @Deprecated
+ {{/isDeprecated}}
+ {{^vendorExtensions.x-streaming}}
+ public {{{returnType}}}{{^returnType}}void{{/returnType}} execute() throws ApiException {
+ {{#returnType}}ApiResponse<{{{.}}}> localVarResp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}}
+ return localVarResp.getData();{{/returnType}}
+ }
+ {{/vendorExtensions.x-streaming}}
+ {{#vendorExtensions.x-streaming}}
+ public InputStream execute() throws ApiException {
+ return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
+ }
+ {{/vendorExtensions.x-streaming}}
+
+ /**
+ * Execute {{operationId}} request with HTTP info returned
+ * @return ApiResponse<{{returnType}}{{^returnType}}Void{{/returnType}}>
+ * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body
+ {{#responses.0}}
+ * @http.response.details
+
+ Response Details
+ Status Code Description Response Headers
+ {{#responses}}
+ {{code}} {{message}} {{#headers}} * {{baseName}} - {{description}} {{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses}}
+
+ {{/responses.0}}
+ {{#isDeprecated}}
+ * @deprecated
+ {{/isDeprecated}}
+ */
+ {{#isDeprecated}}
+ @Deprecated
+ {{/isDeprecated}}
+ {{^vendorExtensions.x-streaming}}
+ public ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}> executeWithHttpInfo() throws ApiException {
+ return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
+ }
+ {{/vendorExtensions.x-streaming}}
+ {{#vendorExtensions.x-streaming}}
+ public InputStream executeWithHttpInfo() throws ApiException {
+ return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
+ }
+ {{/vendorExtensions.x-streaming}}
+
+ /**
+ * Execute {{operationId}} request (asynchronously)
+ * @param _callback The callback to be executed when the API call finishes
+ * @return The request call
+ * @throws ApiException If fail to process the API call, e.g. serializing the request body object
+ {{#responses.0}}
+ * @http.response.details
+
+ Response Details
+ Status Code Description Response Headers
+ {{#responses}}
+ {{code}} {{message}} {{#headers}} * {{baseName}} - {{description}} {{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses}}
+
+ {{/responses.0}}
+ {{#isDeprecated}}
+ * @deprecated
+ {{/isDeprecated}}
+ */
+ {{#isDeprecated}}
+ @Deprecated
+ {{/isDeprecated}}
+ public okhttp3.Call executeAsync(final ApiCallback<{{{returnType}}}{{^returnType}}Void{{/returnType}}> _callback) throws ApiException {
+ return {{operationId}}Async({{#allParams}}{{paramName}}, {{/allParams}}_callback);
+ }
+ }
+
+ /**
+ * {{summary}}
+ * {{notes}}{{#requiredParams}}
+ * @param {{paramName}} {{description}} (required){{/requiredParams}}
+ * @return API{{operationId}}Request
+ {{#responses.0}}
+ * @http.response.details
+
+ Response Details
+ Status Code Description Response Headers
+ {{#responses}}
+ {{code}} {{message}} {{#headers}} * {{baseName}} - {{description}} {{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses}}
+
+ {{/responses.0}}
+ {{#isDeprecated}}
+ * @deprecated
+ {{/isDeprecated}}
+ {{#externalDocs}}
+ * {{description}}
+ * @see {{summary}} Documentation
+ {{/externalDocs}}
+ */
+ {{#isDeprecated}}
+ @Deprecated
+ {{/isDeprecated}}
+ public API{{operationId}}Request {{operationId}}({{#requiredParams}}{{>nullable_var_annotations}} {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}) {
+ return new API{{operationId}}Request({{#requiredParams}}{{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}});
+ }
+ {{/vendorExtensions.x-group-parameters}}
+ {{/operation}}
+}
+{{/operations}}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/apiException.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/apiException.mustache
new file mode 100644
index 000000000000..96283bc054d3
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/apiException.mustache
@@ -0,0 +1,196 @@
+{{>licenseInfo}}
+
+package {{invokerPackage}};
+
+import java.util.Map;
+import java.util.List;
+{{#caseInsensitiveResponseHeaders}}
+import java.util.Map.Entry;
+import java.util.TreeMap;
+{{/caseInsensitiveResponseHeaders}}
+
+
+/**
+ * ApiException class.
+ */
+@SuppressWarnings("serial")
+{{>generatedAnnotation}}
+
+public class ApiException extends{{#useRuntimeException}} RuntimeException {{/useRuntimeException}}{{^useRuntimeException}} Exception {{/useRuntimeException}}{
+ private static final long serialVersionUID = 1L;
+
+ private int code = 0;
+ private Map> responseHeaders = null;
+ private String responseBody = null;
+ {{#errorObjectType}}
+ private {{{errorObjectType}}} errorObject = null;
+ {{/errorObjectType}}
+
+ /**
+ * Constructor for ApiException.
+ */
+ public ApiException() {}
+
+ /**
+ * Constructor for ApiException.
+ *
+ * @param throwable a {@link java.lang.Throwable} object
+ */
+ public ApiException(Throwable throwable) {
+ super(throwable);
+ }
+
+ /**
+ * Constructor for ApiException.
+ *
+ * @param message the error message
+ */
+ public ApiException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructor for ApiException.
+ *
+ * @param message the error message
+ * @param throwable a {@link java.lang.Throwable} object
+ * @param code HTTP status code
+ * @param responseHeaders a {@link java.util.Map} of HTTP response headers
+ * @param responseBody the response body
+ */
+ public ApiException(String message, Throwable throwable, int code, Map> responseHeaders, String responseBody) {
+ super(message, throwable);
+ this.code = code;
+ {{#caseInsensitiveResponseHeaders}}
+ Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER);
+ for(Entry> entry : responseHeaders.entrySet()){
+ headers.put(entry.getKey().toLowerCase(), entry.getValue());
+ }
+ {{/caseInsensitiveResponseHeaders}}
+ this.responseHeaders = {{#caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}};
+ this.responseBody = responseBody;
+ }
+
+ /**
+ * Constructor for ApiException.
+ *
+ * @param message the error message
+ * @param code HTTP status code
+ * @param responseHeaders a {@link java.util.Map} of HTTP response headers
+ * @param responseBody the response body
+ */
+ public ApiException(String message, int code, Map> responseHeaders, String responseBody) {
+ this(message, (Throwable) null, code, responseHeaders, responseBody);
+ }
+
+ /**
+ * Constructor for ApiException.
+ *
+ * @param message the error message
+ * @param throwable a {@link java.lang.Throwable} object
+ * @param code HTTP status code
+ * @param responseHeaders a {@link java.util.Map} of HTTP response headers
+ */
+ public ApiException(String message, Throwable throwable, int code, Map> responseHeaders) {
+ this(message, throwable, code, responseHeaders, null);
+ }
+
+ /**
+ * Constructor for ApiException.
+ *
+ * @param code HTTP status code
+ * @param responseHeaders a {@link java.util.Map} of HTTP response headers
+ * @param responseBody the response body
+ */
+ public ApiException(int code, Map> responseHeaders, String responseBody) {
+ this("Response Code: " + code + " Response Body: " + responseBody, (Throwable) null, code, responseHeaders, responseBody);
+ }
+
+ /**
+ * Constructor for ApiException.
+ *
+ * @param code HTTP status code
+ * @param message a {@link java.lang.String} object
+ */
+ public ApiException(int code, String message) {
+ super(message);
+ this.code = code;
+ }
+
+ /**
+ * Constructor for ApiException.
+ *
+ * @param code HTTP status code
+ * @param message the error message
+ * @param responseHeaders a {@link java.util.Map} of HTTP response headers
+ * @param responseBody the response body
+ */
+ public ApiException(int code, String message, Map> responseHeaders, String responseBody) {
+ this(code, message);
+ {{#caseInsensitiveResponseHeaders}}
+ Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER);
+ for(Entry> entry : responseHeaders.entrySet()){
+ headers.put(entry.getKey().toLowerCase(), entry.getValue());
+ }
+ {{/caseInsensitiveResponseHeaders}}
+ this.responseHeaders = {{#caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}};
+ this.responseBody = responseBody;
+ }
+
+ /**
+ * Get the HTTP status code.
+ *
+ * @return HTTP status code
+ */
+ public int getCode() {
+ return code;
+ }
+
+ /**
+ * Get the HTTP response headers.
+ *
+ * @return A map of list of string
+ */
+ public Map> getResponseHeaders() {
+ return responseHeaders;
+ }
+
+ /**
+ * Get the HTTP response body.
+ *
+ * @return Response body in the form of string
+ */
+ public String getResponseBody() {
+ return responseBody;
+ }
+
+ /**
+ * Get the exception message including HTTP response data.
+ *
+ * @return The exception message
+ */
+ public String getMessage() {
+ return String.format(java.util.Locale.ROOT, "Message: %s%nHTTP response code: %s%nHTTP response body: %s%nHTTP response headers: %s",
+ super.getMessage(), this.getCode(), this.getResponseBody(), this.getResponseHeaders());
+ }
+ {{#errorObjectType}}
+
+ /**
+ * Get the error object.
+ *
+ * @return Error object
+ */
+ public {{{errorObjectType}}} getErrorObject() {
+ return errorObject;
+ }
+
+ /**
+ * Get the error object.
+ *
+ * @param errorObject Error object
+ */
+ public void setErrorObject({{{errorObjectType}}} errorObject) {
+ this.errorObject = errorObject;
+ }
+ {{/errorObjectType}}
+}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/api_doc.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/api_doc.mustache
new file mode 100644
index 000000000000..dea75bd2b98e
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/api_doc.mustache
@@ -0,0 +1,110 @@
+# {{classname}}{{#description}}
+{{.}}{{/description}}
+
+All URIs are relative to *{{basePath}}*
+
+| Method | HTTP request | Description |
+|------------- | ------------- | -------------|
+{{#operations}}{{#operation}}| [**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{summary}} |
+{{/operation}}{{/operations}}
+
+{{#operations}}
+{{#operation}}
+
+# **{{operationId}}**{{^vendorExtensions.x-group-parameters}}
+> {{#returnType}}{{.}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}){{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}
+> {{#returnType}}{{.}} {{/returnType}}{{operationId}}({{#requiredParams}}{{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}){{#optionalParams}}.{{paramName}}({{paramName}}){{/optionalParams}}.execute();{{/vendorExtensions.x-group-parameters}}
+
+{{summary}}{{#notes}}
+
+{{.}}{{/notes}}
+
+### Example
+```java
+// Import classes:
+import {{{invokerPackage}}}.ApiClient;
+import {{{invokerPackage}}}.ApiException;
+import {{{invokerPackage}}}.Configuration;{{#hasAuthMethods}}
+import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}}
+import {{{invokerPackage}}}.models.*;
+import {{{package}}}.{{{classname}}};
+
+public class Example {
+ public static void main(String[] args) {
+ ApiClient defaultClient = Configuration.getDefaultApiClient();
+ defaultClient.setBasePath("{{{basePath}}}");
+ {{#withAWSV4Signature}}
+ // Configure AWS Signature V4 authorization
+ defaultClient.setAWS4Configuration("YOUR_ACCESS_KEY", "YOUR_SECRET_KEY", "REGION", "SERVICE")
+ {{/withAWSV4Signature}}
+ {{#hasAuthMethods}}
+ {{#authMethods}}{{#isBasic}}{{#isBasicBasic}}
+ // Configure HTTP basic authorization: {{{name}}}
+ HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}");
+ {{{name}}}.setUsername("YOUR USERNAME");
+ {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasicBasic}}{{#isBasicBearer}}
+ // Configure HTTP bearer authorization: {{{name}}}
+ HttpBearerAuth {{{name}}} = (HttpBearerAuth) defaultClient.getAuthentication("{{{name}}}");
+ {{{name}}}.setBearerToken("BEARER TOKEN");{{/isBasicBearer}}{{/isBasic}}{{#isApiKey}}
+ // Configure API key authorization: {{{name}}}
+ ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}");
+ {{{name}}}.setApiKey("YOUR API KEY");
+ // Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null)
+ //{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}}
+ // Configure OAuth2 access token for authorization: {{{name}}}
+ OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}");
+ {{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}}
+ {{/authMethods}}
+ {{/hasAuthMethods}}
+
+ {{{classname}}} apiInstance = new {{{classname}}}(defaultClient);
+ {{#allParams}}
+ {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}}
+ {{/allParams}}
+ try {
+ {{#returnType}}{{{.}}} result = {{/returnType}}apiInstance.{{{operationId}}}{{^vendorExtensions.x-group-parameters}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}({{#requiredParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/requiredParams}}){{#optionalParams}}
+ .{{{paramName}}}({{{paramName}}}){{/optionalParams}}
+ .execute();{{/vendorExtensions.x-group-parameters}}{{#returnType}}
+ System.out.println(result);{{/returnType}}
+ } catch (ApiException e) {
+ System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}");
+ System.err.println("Status code: " + e.getCode());
+ System.err.println("Reason: " + e.getResponseBody());
+ System.err.println("Response headers: " + e.getResponseHeaders());
+ e.printStackTrace();
+ }
+ }
+}
+```
+
+### Parameters
+{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}}
+| Name | Type | Description | Notes |
+|------------- | ------------- | ------------- | -------------|{{/-last}}{{/allParams}}
+{{#allParams}}| **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{^isContainer}}{{#defaultValue}} [default to {{.}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} |
+{{/allParams}}
+
+### Return type
+
+{{#returnType}}{{#returnTypeIsPrimitive}}**{{returnType}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{returnType}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}null (empty response body){{/returnType}}
+
+### Authorization
+
+{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{name}}](../README.md#{{name}}){{^-last}}, {{/-last}}{{/authMethods}}
+
+### HTTP request headers
+
+ - **Content-Type**: {{#consumes}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/consumes}}{{^consumes}}Not defined{{/consumes}}
+ - **Accept**: {{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}{{^produces}}Not defined{{/produces}}
+
+{{#responses.0}}
+### HTTP response details
+| Status code | Description | Response headers |
+|-------------|-------------|------------------|
+{{#responses}}
+| **{{code}}** | {{message}} | {{#headers}} * {{baseName}} - {{description}} {{/headers}}{{^headers.0}} - {{/headers.0}} |
+{{/responses}}
+{{/responses.0}}
+
+{{/operation}}
+{{/operations}}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/api_test.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/api_test.mustache
new file mode 100644
index 000000000000..b56bdf4db09b
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/api_test.mustache
@@ -0,0 +1,65 @@
+{{>licenseInfo}}
+
+package {{package}};
+
+import {{invokerPackage}}.ApiException;
+{{#imports}}import {{import}};
+{{/imports}}
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+{{#supportStreaming}}
+import java.io.InputStream;
+{{/supportStreaming}}
+
+{{#useBeanValidation}}
+import {{javaxPackage}}.validation.constraints.*;
+import {{javaxPackage}}.validation.Valid;
+
+{{/useBeanValidation}}
+/**
+ * API tests for {{classname}}
+ */
+@Disabled
+public class {{classname}}Test {
+
+ private final {{classname}} api = new {{classname}}();
+
+ {{#operations}}
+ {{#operation}}
+ /**
+ {{#summary}}
+ * {{summary}}
+ *
+ {{/summary}}
+ {{#notes}}
+ * {{notes}}
+ *
+ {{/notes}}
+ * @throws ApiException if the Api call fails
+ */
+ @Test
+ public void {{operationId}}Test() throws ApiException {
+ {{#allParams}}
+ {{{dataType}}} {{paramName}} = null;
+ {{/allParams}}
+ {{#vendorExtensions.x-streaming}}
+ InputStream response = api.{{operationId}}{{^vendorExtensions.x-group-parameters}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}({{#requiredParams}}{{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}){{#optionalParams}}
+ .{{paramName}}({{paramName}}){{/optionalParams}}
+ .execute();{{/vendorExtensions.x-group-parameters}}
+ {{/vendorExtensions.x-streaming}}
+ {{^vendorExtensions.x-streaming}}
+ {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}{{^vendorExtensions.x-group-parameters}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}({{#requiredParams}}{{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}){{#optionalParams}}
+ .{{paramName}}({{paramName}}){{/optionalParams}}
+ .execute();{{/vendorExtensions.x-group-parameters}}
+ {{/vendorExtensions.x-streaming}}
+ // TODO: test validations
+ }
+
+ {{/operation}}
+ {{/operations}}
+}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/AWS4Auth.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/AWS4Auth.mustache
new file mode 100644
index 000000000000..d3f30b77cc52
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/AWS4Auth.mustache
@@ -0,0 +1,105 @@
+{{>licenseInfo}}
+
+package {{invokerPackage}}.auth;
+
+import {{invokerPackage}}.Pair;
+import {{invokerPackage}}.ApiException;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider;
+import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
+import software.amazon.awssdk.auth.credentials.AwsSessionCredentials;
+import software.amazon.awssdk.auth.credentials.AwsCredentials;
+import software.amazon.awssdk.auth.signer.Aws4Signer;
+import software.amazon.awssdk.auth.signer.params.Aws4SignerParams;
+import software.amazon.awssdk.http.ContentStreamProvider;
+import software.amazon.awssdk.http.SdkHttpFullRequest;
+import software.amazon.awssdk.http.SdkHttpMethod;
+import software.amazon.awssdk.regions.Region;
+
+import okio.Buffer;
+
+{{>generatedAnnotation}}
+
+public class AWS4Auth implements Authentication {
+
+ private AwsCredentials credentials;
+ private String region;
+ private String service;
+
+ public AWS4Auth() {
+ this.credentials = AnonymousCredentialsProvider.create().resolveCredentials();
+ }
+
+ public void setCredentials(String accessKey, String secretKey) {
+ this.credentials = AwsBasicCredentials.create(accessKey, secretKey);
+ }
+
+ public void setCredentials(String accessKey, String secretKey, String sessionToken) {
+ this.credentials = AwsSessionCredentials.create(accessKey, secretKey, sessionToken);
+ }
+
+ public void setRegion(String region) {
+ this.region = region;
+ }
+
+ public void setService(String service) {
+ this.service = service;
+ }
+
+ @Override
+ public void applyToParams(List queryParams, Map headerParams,
+ Map cookieParams, String payload, String method, URI uri)
+ throws ApiException {
+
+ SdkHttpFullRequest.Builder requestBuilder =
+ SdkHttpFullRequest.builder().uri(uri).method(SdkHttpMethod.fromValue(method));
+
+ ContentStreamProvider provider = new ContentStreamProvider() {
+ @Override
+ public InputStream newStream() {
+ InputStream is = new ByteArrayInputStream(payload.getBytes(StandardCharsets.UTF_8));
+ return is;
+ }
+ };
+
+ requestBuilder = requestBuilder.contentStreamProvider(provider);
+
+ SdkHttpFullRequest signableRequest = sign(requestBuilder);
+
+ Map headers = signableRequest.headers().entrySet().stream()
+ .collect(Collectors.toMap(s -> s.getKey(), e -> e.getValue().get(0)));
+
+ headerParams.putAll(headers);
+ }
+
+ /**
+ * AWS Signature Version 4 signing.
+ *
+ * @param request {@link SdkHttpFullRequest.Builder}
+ * @return {@link SdkHttpFullRequest}
+ */
+ private SdkHttpFullRequest sign(final SdkHttpFullRequest.Builder request) {
+
+ SdkHttpFullRequest req = request.build();
+
+ if (this.service != null && this.region != null && this.credentials != null) {
+ Aws4SignerParams params = Aws4SignerParams.builder().signingName(this.service)
+ .signingRegion(Region.of(this.region)).awsCredentials(this.credentials).build();
+
+ Aws4Signer signer = Aws4Signer.create();
+
+ req = signer.sign(req, params);
+ }
+
+ return req;
+ }
+}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/ApiKeyAuth.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/ApiKeyAuth.mustache
new file mode 100644
index 000000000000..ee02f7cece7f
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/ApiKeyAuth.mustache
@@ -0,0 +1,70 @@
+{{>licenseInfo}}
+
+package {{invokerPackage}}.auth;
+
+import {{invokerPackage}}.ApiException;
+import {{invokerPackage}}.Pair;
+
+import java.net.URI;
+import java.util.Map;
+import java.util.List;
+
+{{>generatedAnnotation}}
+
+public class ApiKeyAuth implements Authentication {
+ private final String location;
+ private final String paramName;
+
+ private String apiKey;
+ private String apiKeyPrefix;
+
+ public ApiKeyAuth(String location, String paramName) {
+ this.location = location;
+ this.paramName = paramName;
+ }
+
+ public String getLocation() {
+ return location;
+ }
+
+ public String getParamName() {
+ return paramName;
+ }
+
+ public String getApiKey() {
+ return apiKey;
+ }
+
+ public void setApiKey(String apiKey) {
+ this.apiKey = apiKey;
+ }
+
+ public String getApiKeyPrefix() {
+ return apiKeyPrefix;
+ }
+
+ public void setApiKeyPrefix(String apiKeyPrefix) {
+ this.apiKeyPrefix = apiKeyPrefix;
+ }
+
+ @Override
+ public void applyToParams(List queryParams, Map headerParams, Map cookieParams,
+ String payload, String method, URI uri) throws ApiException {
+ if (apiKey == null) {
+ return;
+ }
+ String value;
+ if (apiKeyPrefix != null) {
+ value = apiKeyPrefix + " " + apiKey;
+ } else {
+ value = apiKey;
+ }
+ if ("query".equals(location)) {
+ queryParams.add(new Pair(paramName, value));
+ } else if ("header".equals(location)) {
+ headerParams.put(paramName, value);
+ } else if ("cookie".equals(location)) {
+ cookieParams.put(paramName, value);
+ }
+ }
+}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/Authentication.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/Authentication.mustache
new file mode 100644
index 000000000000..da1e1902cc4b
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/Authentication.mustache
@@ -0,0 +1,27 @@
+{{>licenseInfo}}
+
+package {{invokerPackage}}.auth;
+
+import {{invokerPackage}}.Pair;
+import {{invokerPackage}}.ApiException;
+
+import java.net.URI;
+import java.util.Map;
+import java.util.List;
+
+{{>generatedAnnotation}}
+
+public interface Authentication {
+ /**
+ * Apply authentication settings to header and query params.
+ *
+ * @param queryParams List of query parameters
+ * @param headerParams Map of header parameters
+ * @param cookieParams Map of cookie parameters
+ * @param payload HTTP request body
+ * @param method HTTP method
+ * @param uri URI
+ * @throws ApiException if failed to update the parameters
+ */
+ void applyToParams(List queryParams, Map headerParams, Map cookieParams, String payload, String method, URI uri) throws ApiException;
+}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/HttpBasicAuth.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/HttpBasicAuth.mustache
new file mode 100644
index 000000000000..634ec7ab54bb
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/HttpBasicAuth.mustache
@@ -0,0 +1,44 @@
+{{>licenseInfo}}
+
+package {{invokerPackage}}.auth;
+
+import {{invokerPackage}}.Pair;
+import {{invokerPackage}}.ApiException;
+
+import okhttp3.Credentials;
+
+import java.net.URI;
+import java.util.Map;
+import java.util.List;
+
+{{>generatedAnnotation}}
+
+public class HttpBasicAuth implements Authentication {
+ private String username;
+ private String password;
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ @Override
+ public void applyToParams(List queryParams, Map headerParams, Map cookieParams,
+ String payload, String method, URI uri) throws ApiException {
+ if (username == null && password == null) {
+ return;
+ }
+ headerParams.put("Authorization", Credentials.basic(username == null ? "" : username, password == null ? "" : password));
+ }
+}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/HttpBearerAuth.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/HttpBearerAuth.mustache
new file mode 100644
index 000000000000..ad6d29b8108e
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/HttpBearerAuth.mustache
@@ -0,0 +1,52 @@
+{{>licenseInfo}}
+
+package {{invokerPackage}}.auth;
+
+import {{invokerPackage}}.Pair;
+import {{invokerPackage}}.ApiException;
+
+import java.net.URI;
+import java.util.Map;
+import java.util.List;
+
+{{>generatedAnnotation}}
+
+public class HttpBearerAuth implements Authentication {
+ private final String scheme;
+ private String bearerToken;
+
+ public HttpBearerAuth(String scheme) {
+ this.scheme = scheme;
+ }
+
+ /**
+ * Gets the token, which together with the scheme, will be sent as the value of the AdditionalHeader.
+ *
+ * @return The bearer token
+ */
+ public String getBearerToken() {
+ return bearerToken;
+ }
+
+ /**
+ * Sets the token, which together with the scheme, will be sent as the value of the AdditionalHeader.
+ *
+ * @param bearerToken The bearer token
+ */
+ public void setBearerToken(String bearerToken) {
+ this.bearerToken = bearerToken;
+ }
+
+ @Override
+ public void applyToParams(List queryParams, Map headerParams, Map cookieParams,
+ String payload, String method, URI uri) throws ApiException {
+ if (bearerToken == null) {
+ return;
+ }
+ headerParams.put("Authorization", (scheme != null ? upperCaseBearer(scheme) + " " : "") + bearerToken);
+ }
+
+ private static String upperCaseBearer(String scheme) {
+ return ("bearer".equalsIgnoreCase(scheme)) ? "Bearer" : scheme;
+ }
+}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/OAuth.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/OAuth.mustache
new file mode 100644
index 000000000000..d2a8e6374c2c
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/OAuth.mustache
@@ -0,0 +1,33 @@
+{{>licenseInfo}}
+
+package {{invokerPackage}}.auth;
+
+import {{invokerPackage}}.Pair;
+import {{invokerPackage}}.ApiException;
+
+import java.net.URI;
+import java.util.Map;
+import java.util.List;
+
+{{>generatedAnnotation}}
+
+public class OAuth implements Authentication {
+ private String accessToken;
+
+ public String getAccessToken() {
+ return accessToken;
+ }
+
+ public void setAccessToken(String accessToken) {
+ this.accessToken = accessToken;
+ }
+
+ @Override
+ public void applyToParams(List queryParams, Map headerParams, Map cookieParams,
+ String payload, String method, URI uri) throws ApiException {
+ if (accessToken == null) {
+ return;
+ }
+ headerParams.put("Authorization", "Bearer " + accessToken);
+ }
+}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/OAuthOkHttpClient.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/OAuthOkHttpClient.mustache
new file mode 100644
index 000000000000..67d7f720d44b
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/OAuthOkHttpClient.mustache
@@ -0,0 +1,73 @@
+{{>licenseInfo}}
+
+{{#hasOAuthMethods}}
+package {{invokerPackage}}.auth;
+
+import okhttp3.OkHttpClient;
+import okhttp3.MediaType;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+
+import org.apache.oltu.oauth2.client.HttpClient;
+import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
+import org.apache.oltu.oauth2.client.response.OAuthClientResponse;
+import org.apache.oltu.oauth2.client.response.OAuthClientResponseFactory;
+import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
+import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Map.Entry;
+
+public class OAuthOkHttpClient implements HttpClient {
+ private OkHttpClient client;
+
+ public OAuthOkHttpClient() {
+ this.client = new OkHttpClient();
+ }
+
+ public OAuthOkHttpClient(OkHttpClient client) {
+ this.client = client;
+ }
+
+ @Override
+ public T execute(OAuthClientRequest request, Map headers,
+ String requestMethod, Class responseClass)
+ throws OAuthSystemException, OAuthProblemException {
+
+ MediaType mediaType = MediaType.parse("application/json");
+ Request.Builder requestBuilder = new Request.Builder().url(request.getLocationUri());
+
+ if(headers != null) {
+ for (Entry entry : headers.entrySet()) {
+ if (entry.getKey().equalsIgnoreCase("Content-Type")) {
+ mediaType = MediaType.parse(entry.getValue());
+ } else {
+ requestBuilder.addHeader(entry.getKey(), entry.getValue());
+ }
+ }
+ }
+
+ RequestBody body = request.getBody() != null ? RequestBody.create(request.getBody(), mediaType) : null;
+ requestBuilder.method(requestMethod, body);
+
+ try {
+ Response response = client.newCall(requestBuilder.build()).execute();
+ return OAuthClientResponseFactory.createCustomResponse(
+ response.body().string(),
+ response.body().contentType().toString(),
+ response.code(),
+ response.headers().toMultimap(),
+ responseClass);
+ } catch (IOException e) {
+ throw new OAuthSystemException(e);
+ }
+ }
+
+ @Override
+ public void shutdown() {
+ // Nothing to do here
+ }
+}
+{{/hasOAuthMethods}}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/RetryingOAuth.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/RetryingOAuth.mustache
new file mode 100644
index 000000000000..fbe73e729c98
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/RetryingOAuth.mustache
@@ -0,0 +1,214 @@
+{{>licenseInfo}}
+
+{{#hasOAuthMethods}}
+package {{invokerPackage}}.auth;
+
+import {{invokerPackage}}.ApiException;
+import {{invokerPackage}}.Pair;
+
+import okhttp3.Interceptor;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+
+import org.apache.oltu.oauth2.client.OAuthClient;
+import org.apache.oltu.oauth2.client.request.OAuthBearerClientRequest;
+import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
+import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder;
+import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse;
+import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
+import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
+import org.apache.oltu.oauth2.common.message.types.GrantType;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URI;
+import java.util.Map;
+import java.util.List;
+
+public class RetryingOAuth extends OAuth implements Interceptor {
+ private OAuthClient oAuthClient;
+
+ private TokenRequestBuilder tokenRequestBuilder;
+
+ /**
+ * @param client An OkHttp client
+ * @param tokenRequestBuilder A token request builder
+ */
+ public RetryingOAuth(OkHttpClient client, TokenRequestBuilder tokenRequestBuilder) {
+ this.oAuthClient = new OAuthClient(new OAuthOkHttpClient(client));
+ this.tokenRequestBuilder = tokenRequestBuilder;
+ }
+
+ /**
+ * @param tokenRequestBuilder A token request builder
+ */
+ public RetryingOAuth(TokenRequestBuilder tokenRequestBuilder) {
+ this(new OkHttpClient(), tokenRequestBuilder);
+ }
+
+ /**
+ * @param tokenUrl The token URL to be used for this OAuth2 flow.
+ * Applicable to the following OAuth2 flows: "password", "clientCredentials" and "authorizationCode".
+ * The value must be an absolute URL.
+ * @param clientId The OAuth2 client ID for the "clientCredentials" flow.
+ * @param flow OAuth flow.
+ * @param clientSecret The OAuth2 client secret for the "clientCredentials" flow.
+ * @param parameters A map of string.
+ */
+ public RetryingOAuth(
+ String tokenUrl,
+ String clientId,
+ OAuthFlow flow,
+ String clientSecret,
+ Map parameters
+ ) {
+ this(OAuthClientRequest.tokenLocation(tokenUrl)
+ .setClientId(clientId)
+ .setClientSecret(clientSecret));
+ setFlow(flow);
+ if (parameters != null) {
+ for (Map.Entry entry : parameters.entrySet()) {
+ tokenRequestBuilder.setParameter(entry.getKey(), entry.getValue());
+ }
+ }
+ }
+
+ /**
+ * Set the OAuth flow
+ *
+ * @param flow The OAuth flow.
+ */
+ public void setFlow(OAuthFlow flow) {
+ switch(flow) {
+ case ACCESS_CODE:
+ tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE);
+ break;
+ case IMPLICIT:
+ tokenRequestBuilder.setGrantType(GrantType.IMPLICIT);
+ break;
+ case PASSWORD:
+ tokenRequestBuilder.setGrantType(GrantType.PASSWORD);
+ break;
+ case APPLICATION:
+ tokenRequestBuilder.setGrantType(GrantType.CLIENT_CREDENTIALS);
+ break;
+ default:
+ break;
+ }
+ }
+
+ @Override
+ public Response intercept(Chain chain) throws IOException {
+ return retryingIntercept(chain, true);
+ }
+
+ private Response retryingIntercept(Chain chain, boolean updateTokenAndRetryOnAuthorizationFailure) throws IOException {
+ Request request = chain.request();
+
+ // If the request already has an authorization (e.g. Basic auth), proceed with the request as is
+ if (request.header("Authorization") != null) {
+ return chain.proceed(request);
+ }
+
+ // Get the token if it has not yet been acquired
+ if (getAccessToken() == null) {
+ updateAccessToken(null);
+ }
+
+ OAuthClientRequest oAuthRequest;
+ if (getAccessToken() != null) {
+ // Build the request
+ Request.Builder requestBuilder = request.newBuilder();
+
+ String requestAccessToken = getAccessToken();
+ try {
+ oAuthRequest =
+ new OAuthBearerClientRequest(request.url().toString()).
+ setAccessToken(requestAccessToken).
+ buildHeaderMessage();
+ } catch (OAuthSystemException e) {
+ throw new IOException(e);
+ }
+
+ Map headers = oAuthRequest.getHeaders();
+ for (Map.Entry entry : headers.entrySet()) {
+ requestBuilder.addHeader(entry.getKey(), entry.getValue());
+ }
+ requestBuilder.url(oAuthRequest.getLocationUri());
+
+ // Execute the request
+ Response response = chain.proceed(requestBuilder.build());
+
+ // 401/403 response codes most likely indicate an expired access token, unless it happens two times in a row
+ if (
+ response != null &&
+ ( response.code() == HttpURLConnection.HTTP_UNAUTHORIZED ||
+ response.code() == HttpURLConnection.HTTP_FORBIDDEN ) &&
+ updateTokenAndRetryOnAuthorizationFailure
+ ) {
+ try {
+ if (updateAccessToken(requestAccessToken)) {
+ response.body().close();
+ return retryingIntercept(chain, false);
+ }
+ } catch (Exception e) {
+ response.body().close();
+ throw e;
+ }
+ }
+ return response;
+ }
+ else {
+ return chain.proceed(chain.request());
+ }
+ }
+
+ /**
+ * Returns true if the access token has been updated
+ *
+ * @param requestAccessToken the request access token
+ * @return True if the update is successful
+ * @throws java.io.IOException If fail to update the access token
+ */
+ public synchronized boolean updateAccessToken(String requestAccessToken) throws IOException {
+ if (getAccessToken() == null || getAccessToken().equals(requestAccessToken)) {
+ try {
+ OAuthJSONAccessTokenResponse accessTokenResponse =
+ oAuthClient.accessToken(tokenRequestBuilder.buildBodyMessage());
+ if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) {
+ setAccessToken(accessTokenResponse.getAccessToken());
+ }
+ } catch (OAuthSystemException | OAuthProblemException e) {
+ throw new IOException(e);
+ }
+ }
+ return getAccessToken() == null || !getAccessToken().equals(requestAccessToken);
+ }
+
+ /**
+ * Gets the token request builder
+ *
+ * @return A token request builder
+ */
+ public TokenRequestBuilder getTokenRequestBuilder() {
+ return tokenRequestBuilder;
+ }
+
+ /**
+ * Sets the token request builder
+ *
+ * @param tokenRequestBuilder Token request builder
+ */
+ public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) {
+ this.tokenRequestBuilder = tokenRequestBuilder;
+ }
+
+ // Applying authorization to parameters is performed in the retryingIntercept method
+ @Override
+ public void applyToParams(List queryParams, Map headerParams, Map cookieParams,
+ String payload, String method, URI uri) throws ApiException {
+ // No implementation necessary
+ }
+}
+{{/hasOAuthMethods}}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/build.gradle.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/build.gradle.mustache
new file mode 100644
index 000000000000..3b41b58fedd6
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/build.gradle.mustache
@@ -0,0 +1,138 @@
+apply plugin: 'idea'
+apply plugin: 'eclipse'
+{{#sourceFolder}}
+apply plugin: 'java'
+{{/sourceFolder}}
+
+group = '{{groupId}}'
+version = '{{artifactVersion}}'
+
+repositories {
+ mavenCentral()
+}
+{{#sourceFolder}}
+sourceSets {
+ main.java.srcDirs = ['{{sourceFolder}}']
+}
+
+{{/sourceFolder}}
+
+apply plugin: 'java'
+apply plugin: 'maven-publish'
+
+sourceCompatibility = {{#java17}}JavaVersion.VERSION_17{{/java17}}{{^java17}}{{#java11}}JavaVersion.VERSION_11{{/java11}}{{^java11}}JavaVersion.VERSION_1_8{{/java11}}{{/java17}}
+targetCompatibility = {{#java17}}JavaVersion.VERSION_17{{/java17}}{{^java17}}{{#java11}}JavaVersion.VERSION_11{{/java11}}{{^java11}}JavaVersion.VERSION_1_8{{/java11}}{{/java17}}
+
+publishing {
+ publications {
+ maven(MavenPublication) {
+ artifactId = '{{artifactId}}'
+ from components.java
+ }
+ }
+}
+
+task execute(type:JavaExec) {
+ mainClass = System.getProperty('mainClass')
+ classpath = sourceSets.main.runtimeClasspath
+}
+
+ext {
+ {{#swagger1AnnotationLibrary}}
+ swagger_annotations_version = "1.6.6"
+ {{/swagger1AnnotationLibrary}}
+ {{#swagger2AnnotationLibrary}}
+ swagger_annotations_version = "2.2.15"
+ {{/swagger2AnnotationLibrary}}
+ {{#useJakartaEe}}
+ jakarta_annotation_version = "2.1.1"
+ {{#useBeanValidation}}
+ bean_validation_version = "3.0.2"
+ {{/useBeanValidation}}
+ {{/useJakartaEe}}
+ {{^useJakartaEe}}
+ jakarta_annotation_version = "1.3.5"
+ {{#useBeanValidation}}
+ bean_validation_version = "2.0.2"
+ {{/useBeanValidation}}
+ {{/useJakartaEe}}
+ {{#isJackson}}
+ {{#useJackson3}}
+ jackson_version = "3.2.1"
+ {{/useJackson3}}
+ {{^useJackson3}}
+ jackson_version = "2.17.1"
+ {{/useJackson3}}
+ {{/isJackson}}
+ okhttp_version = "5.4.0"
+}
+
+dependencies {
+ {{#swagger1AnnotationLibrary}}
+ implementation "io.swagger:swagger-annotations:$swagger_annotations_version"
+ {{/swagger1AnnotationLibrary}}
+ {{#swagger2AnnotationLibrary}}
+ implementation "io.swagger.core.v3:swagger-annotations:$swagger_annotations_version"
+ {{/swagger2AnnotationLibrary}}
+ {{^useJspecify}}
+ implementation "com.google.code.findbugs:jsr305:3.0.2"
+ {{/useJspecify}}
+ {{#useJspecify}}
+ implementation "org.jspecify:jspecify:1.0.0"
+ {{/useJspecify}}
+ implementation "com.squareup.okhttp3:okhttp:$okhttp_version"
+ implementation "com.squareup.okhttp3:logging-interceptor:$okhttp_version"
+ {{#isGson}}
+ implementation 'com.google.code.gson:gson:2.10.1'
+ implementation 'io.gsonfire:gson-fire:1.9.0'
+ {{/isGson}}
+ {{#isJackson}}
+ implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version"
+ implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version"
+ implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_version"
+ implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version"
+ {{#openApiNullable}}
+ implementation 'org.openapitools:jackson-databind-nullable:0.2.10'
+ {{/openApiNullable}}
+ {{/isJackson}}
+ {{#isJsonb}}
+ implementation 'jakarta.json.bind:jakarta.json.bind-api:3.0.1'
+ implementation 'org.eclipse:yasson:3.0.4'
+ implementation 'jakarta.json:jakarta.json-api:2.1.3'
+ implementation 'org.eclipse.parsson:parsson:1.1.7'
+ {{/isJsonb}}
+ {{#withAWSV4Signature}}
+ implementation 'software.amazon.awssdk:auth:2.20.157'
+ {{/withAWSV4Signature}}
+ {{#hasOAuthMethods}}
+ implementation group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.2'
+ {{/hasOAuthMethods}}
+ {{#useReflectionEqualsHashCode}}
+ implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.18.0'
+ {{/useReflectionEqualsHashCode}}
+ {{#joda}}
+ implementation 'joda-time:joda-time:2.12.0'
+ {{/joda}}
+ {{#dynamicOperations}}
+ implementation 'io.swagger.parser.v3:swagger-parser-v3:2.0.30'
+ {{/dynamicOperations}}
+ compileOnly "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version"
+ {{#useBeanValidation}}
+ compileOnly "jakarta.validation:jakarta.validation-api:$bean_validation_version"
+ {{/useBeanValidation}}
+ testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.3'
+ testImplementation 'org.mockito:mockito-core:3.12.4'
+ testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.10.3'
+}
+
+javadoc {
+ options.tags = [ "http.response.details:a:Http Response Details" ]
+}
+
+test {
+ useJUnitPlatform()
+ dependsOn 'cleanTest'
+ testLogging {
+ events "passed", "skipped", "failed"
+ }
+}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/model.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/model.mustache
new file mode 100644
index 000000000000..3a1cca8d7d4f
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/model.mustache
@@ -0,0 +1,35 @@
+{{>licenseInfo}}
+
+package {{package}};
+
+{{#useReflectionEqualsHashCode}}
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+{{/useReflectionEqualsHashCode}}
+import java.util.Objects;
+{{#imports}}
+import {{import}};
+{{/imports}}
+{{#serializableModel}}
+import java.io.Serializable;
+{{/serializableModel}}
+{{#withXml}}
+import {{javaxPackage}}.xml.bind.annotation.*;
+{{/withXml}}
+{{#parcelableModel}}
+import android.os.Parcelable;
+import android.os.Parcel;
+{{/parcelableModel}}
+{{#useBeanValidation}}
+import {{javaxPackage}}.validation.constraints.*;
+import {{javaxPackage}}.validation.Valid;
+{{/useBeanValidation}}
+{{#performBeanValidation}}
+import org.hibernate.validator.constraints.*;
+{{/performBeanValidation}}
+
+{{#models}}
+{{#model}}
+{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{#oneOf}}{{#-first}}{{>oneof_model}}{{/-first}}{{/oneOf}}{{^oneOf}}{{#anyOf}}{{#-first}}{{>anyof_model}}{{/-first}}{{/anyOf}}{{^anyOf}}{{>pojo}}{{/anyOf}}{{/oneOf}}{{/isEnum}}
+{{/model}}
+{{/models}}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/modelEnum.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/modelEnum.mustache
new file mode 100644
index 000000000000..bc63345aa9e6
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/modelEnum.mustache
@@ -0,0 +1,114 @@
+import java.io.IOException;
+{{#isUri}}
+import java.net.URI;
+{{/isUri}}
+{{#isGson}}
+import com.google.gson.TypeAdapter;
+import com.google.gson.JsonElement;
+import com.google.gson.annotations.JsonAdapter;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+{{/isGson}}
+{{#isJackson}}
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+{{/isJackson}}
+{{#isJsonb}}
+import jakarta.json.bind.annotation.JsonbCreator;
+import jakarta.json.bind.annotation.JsonbValue;
+{{/isJsonb}}
+
+/**
+ * {{description}}{{^description}}Gets or Sets {{{name}}}{{/description}}
+ */
+{{#isDeprecated}}
+@Deprecated
+{{/isDeprecated}}
+{{#isGson}}
+@JsonAdapter({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.Adapter.class)
+{{/isGson}}
+{{>additionalEnumTypeAnnotations}}public enum {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}{{#vendorExtensions.x-implements}}{{#-first}} implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.x-implements}} {
+ {{#allowableValues}}{{#enumVars}}
+ {{#enumDescription}}
+ /**
+ * {{.}}
+ */
+ {{/enumDescription}}
+ {{#withXml}}
+ @XmlEnumValue({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}})
+ {{/withXml}}
+ {{{name}}}({{{value}}}){{^-last}},
+ {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}}
+
+ private {{{dataType}}} value;
+
+ {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) {
+ this.value = value;
+ }
+
+ {{#isJackson}}
+ @JsonValue
+ {{/isJackson}}
+ {{#isJsonb}}
+ @JsonbValue
+ {{/isJsonb}}
+ public {{{dataType}}} getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+ {{#isJackson}}
+ @JsonCreator
+ {{/isJackson}}
+ {{#isJsonb}}
+ @JsonbCreator
+ {{/isJsonb}}
+ public static {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue({{{dataType}}} value) {
+ for ({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) {
+ if (b.value.equals{{#isString}}{{#useEnumCaseInsensitive}}IgnoreCase{{/useEnumCaseInsensitive}}{{/isString}}(value)) {
+ return b;
+ }
+ }
+ {{#isNullable}}return null;{{/isNullable}}{{^isNullable}}{{#enumUnknownDefaultCase}}{{#allowableValues}}{{#enumVars}}{{#-last}}return {{{name}}};{{/-last}}{{/enumVars}}{{/allowableValues}}{{/enumUnknownDefaultCase}}{{^enumUnknownDefaultCase}}throw new IllegalArgumentException("Unexpected value '" + value + "'");{{/enumUnknownDefaultCase}}{{/isNullable}}
+ }
+
+ {{#isGson}}
+ public static class Adapter extends TypeAdapter<{{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}> {
+ @Override
+ public void write(final JsonWriter jsonWriter, final {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} enumeration) throws IOException {
+ jsonWriter.value(enumeration.getValue(){{#isUri}}.toASCIIString(){{/isUri}});
+ }
+
+ @Override
+ public {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException {
+ {{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = {{#isFloat}}(float){{/isFloat}}{{#isUri}}URI.create({{/isUri}}jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{#isUri}}nextString()){{/isUri}}{{^isNumber}}{{^isInteger}}{{^isUri}}{{#isFloat}}nextDouble{{/isFloat}}{{^isFloat}}next{{{dataType}}}{{/isFloat}}(){{/isUri}}{{/isInteger}}{{/isNumber}};
+ return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new java.math.BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
+ }
+ }
+
+ public static void validateJsonElement(JsonElement jsonElement) throws IOException {
+ {{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = {{#isUri}}URI.create({{/isUri}}jsonElement.{{#isNumber}}getAsString(){{/isNumber}}{{#isInteger}}getAsInt(){{/isInteger}}{{#isUri}}getAsString()){{/isUri}}{{^isNumber}}{{^isInteger}}{{^isUri}}getAs{{{dataType}}}(){{/isUri}}{{/isInteger}}{{/isNumber}};
+ {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new java.math.BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
+ }
+ {{/isGson}}
+{{#supportUrlQuery}}
+
+ /**
+ * Convert the instance into URL query string.
+ *
+ * @param prefix prefix of the query string
+ * @return URL query string
+ */
+ public String toUrlQueryString(String prefix) {
+ if (prefix == null) {
+ prefix = "";
+ }
+
+ return String.format(java.util.Locale.ROOT, "%s=%s", prefix, this.toString());
+ }
+{{/supportUrlQuery}}
+}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/modelInnerEnum.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/modelInnerEnum.mustache
new file mode 100644
index 000000000000..7250b6e36cb3
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/modelInnerEnum.mustache
@@ -0,0 +1,82 @@
+ /**
+ * {{description}}{{^description}}Gets or Sets {{{name}}}{{/description}}
+ */
+ {{#isGson}}
+ @JsonAdapter({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.Adapter.class)
+ {{/isGson}}
+{{#withXml}}
+ @XmlType(name="{{datatypeWithEnum}}")
+ @XmlEnum({{dataType}}.class)
+{{/withXml}}
+ {{>additionalEnumTypeAnnotations}}public enum {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}{{#vendorExtensions.x-implements}}{{#-first}} implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.x-implements}} {
+ {{#allowableValues}}
+ {{#enumVars}}
+ {{#enumDescription}}
+ /**
+ * {{.}}
+ */
+ {{/enumDescription}}
+ {{#withXml}}
+ @XmlEnumValue({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}})
+ {{/withXml}}
+ {{{name}}}({{{value}}}){{^-last}},
+ {{/-last}}{{#-last}};{{/-last}}
+ {{/enumVars}}
+ {{/allowableValues}}
+
+ private {{{dataType}}} value;
+
+ {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}({{{dataType}}} value) {
+ this.value = value;
+ }
+
+ {{#isJackson}}
+ @JsonValue
+ {{/isJackson}}
+ {{#isJsonb}}
+ @JsonbValue
+ {{/isJsonb}}
+ public {{{dataType}}} getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+ {{#isJackson}}
+ @JsonCreator
+ {{/isJackson}}
+ {{#isJsonb}}
+ @JsonbCreator
+ {{/isJsonb}}
+ public static {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue({{{dataType}}} value) {
+ for ({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) {
+ if (b.value.equals{{#isString}}{{#useEnumCaseInsensitive}}IgnoreCase{{/useEnumCaseInsensitive}}{{/isString}}(value)) {
+ return b;
+ }
+ }
+ {{#isNullable}}return null;{{/isNullable}}{{^isNullable}}{{#enumUnknownDefaultCase}}{{#allowableValues}}{{#enumVars}}{{#-last}}return {{{name}}};{{/-last}}{{/enumVars}}{{/allowableValues}}{{/enumUnknownDefaultCase}}{{^enumUnknownDefaultCase}}throw new IllegalArgumentException("Unexpected value '" + value + "'");{{/enumUnknownDefaultCase}}{{/isNullable}}
+ }
+
+ {{#isGson}}
+ public static class Adapter extends TypeAdapter<{{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}> {
+ @Override
+ public void write(final JsonWriter jsonWriter, final {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} enumeration) throws IOException {
+ jsonWriter.value(enumeration.getValue(){{#isUri}}.toASCIIString(){{/isUri}});
+ }
+
+ @Override
+ public {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException {
+ {{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = {{#isFloat}}(float){{/isFloat}} {{#isUri}}URI.create({{/isUri}}jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{#isUri}}nextString()){{/isUri}}{{^isNumber}}{{^isInteger}}{{^isUri}}{{#isFloat}}nextDouble{{/isFloat}}{{^isFloat}}next{{{dataType}}}{{/isFloat}}(){{/isUri}}{{/isInteger}}{{/isNumber}};
+ return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new java.math.BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
+ }
+ }
+
+ public static void validateJsonElement(JsonElement jsonElement) throws IOException {
+ {{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = {{#isUri}}URI.create({{/isUri}}jsonElement.{{#isNumber}}getAsString(){{/isNumber}}{{#isInteger}}getAsInt(){{/isInteger}}{{#isUri}}getAsString()){{/isUri}}{{^isNumber}}{{^isInteger}}{{^isUri}}getAs{{{dataType}}}(){{/isUri}}{{/isInteger}}{{/isNumber}};
+ {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new java.math.BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
+ }
+ {{/isGson}}
+ }
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/model_test.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/model_test.mustache
new file mode 100644
index 000000000000..040d319bf114
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/model_test.mustache
@@ -0,0 +1,42 @@
+{{>licenseInfo}}
+
+package {{package}};
+
+{{#imports}}import {{import}};
+{{/imports}}
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Model tests for {{classname}}
+ */
+public class {{classname}}Test {
+ {{#models}}
+ {{#model}}
+ {{^vendorExtensions.x-is-one-of-interface}}
+ {{^isEnum}}
+ private final {{classname}} model = new {{classname}}();
+
+ {{/isEnum}}
+ /**
+ * Model tests for {{classname}}
+ */
+ @Test
+ public void test{{classname}}() {
+ // TODO: test {{classname}}
+ }
+
+ {{#allVars}}
+ /**
+ * Test the property '{{name}}'
+ */
+ @Test
+ public void {{name}}Test() {
+ // TODO: test {{name}}
+ }
+
+ {{/allVars}}
+ {{/vendorExtensions.x-is-one-of-interface}}
+ {{/model}}
+ {{/models}}
+}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/oneof_model.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/oneof_model.mustache
new file mode 100644
index 000000000000..0bd87d611144
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/oneof_model.mustache
@@ -0,0 +1,738 @@
+{{#isGson}}
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonParseException;
+import com.google.gson.TypeAdapter;
+import com.google.gson.TypeAdapterFactory;
+import com.google.gson.reflect.TypeToken;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.annotations.JsonAdapter;
+import com.google.gson.annotations.SerializedName;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonArray;
+{{/isGson}}
+{{#isJackson}}
+import {{jacksonPackage}}.core.JsonGenerator;
+import {{jacksonPackage}}.core.JsonParser;
+import {{jacksonPackage}}.core.JsonToken;
+import {{jacksonPackage}}.core.type.TypeReference;
+import {{jacksonPackage}}.databind.DeserializationContext;
+{{^useJackson3}}
+import {{jacksonPackage}}.databind.JsonMappingException;
+{{/useJackson3}}
+import {{jacksonPackage}}.databind.JsonNode;
+import {{jacksonPackage}}.databind.MapperFeature;
+{{^useJackson3}}
+import {{jacksonPackage}}.databind.SerializerProvider;
+{{/useJackson3}}
+import {{jacksonPackage}}.databind.annotation.JsonDeserialize;
+import {{jacksonPackage}}.databind.annotation.JsonSerialize;
+import {{jacksonPackage}}.databind.deser.std.StdDeserializer;
+import {{jacksonPackage}}.databind.ser.std.StdSerializer;
+import {{jacksonPackage}}.databind.JavaType;
+{{#useJackson3}}
+import {{jacksonPackage}}.core.JacksonException;
+import {{jacksonPackage}}.databind.DatabindException;
+import {{jacksonPackage}}.databind.SerializationContext;
+{{/useJackson3}}
+{{/isJackson}}
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.StringJoiner;
+
+import {{invokerPackage}}.JSON;
+
+{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}}
+{{#isJackson}}
+@JsonDeserialize(using = {{classname}}.{{classname}}Deserializer.class)
+@JsonSerialize(using = {{classname}}.{{classname}}Serializer.class)
+{{/isJackson}}
+public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}} implements {{{.}}}{{^-last}}, {{/-last}}{{/vendorExtensions.x-implements}} {
+ private static final Logger log = Logger.getLogger({{classname}}.class.getName());
+
+ {{#isGson}}
+ /**
+ * Validates the JSON Element and throws an exception if issues found
+ *
+ * @param jsonElement JSON Element
+ * @throws IOException if the JSON Element is invalid with respect to {{classname}}
+ */
+ public static void validateJsonElement(JsonElement jsonElement) throws IOException {
+ int matches = 0;
+ List errorMessages = new ArrayList<>();
+ {{#useOneOfDiscriminatorLookup}}
+ {{#discriminator}}
+ JsonObject jsonObject = jsonElement.getAsJsonObject();
+ if (jsonObject.get("{{{propertyBaseName}}}") == null) {
+ throw new IOException("Failed to deserialize as the discriminator field '{{{propertyBaseName}}}' is missing.");
+ }
+ String discriminatorValue = jsonObject.get("{{{propertyBaseName}}}").getAsString();
+ {{#mappedModels}}
+ if ("{{{mappingName}}}".equals(discriminatorValue)) {
+ {{{modelName}}}.validateJsonElement(jsonElement);
+ return;
+ }
+ {{/mappedModels}}
+ {{/discriminator}}
+ {{/useOneOfDiscriminatorLookup}}
+ {{#composedSchemas}}
+ {{#oneOf}}
+ {{^vendorExtensions.x-duplicated-data-type}}
+ // deserialize {{{dataType}}}
+ try {
+ // validate the JSON object to see if any exception is thrown
+ {{#isModel}}
+ {{#hasChildren}}
+ {{{dataType}}}.validateJsonElement(jsonElement);
+ {{/hasChildren}}
+ {{^hasChildren}}
+ {{#isArray}}
+ if (!jsonElement.isJsonArray()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be a array type in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isArray}}
+ {{^isArray}}
+ {{#isMap}}
+ if (!jsonElement.isJsonObject()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be a object type in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isMap}}
+ {{^isMap}}
+ {{{dataType}}}.validateJsonElement(jsonElement);
+ {{/isMap}}
+ {{/isArray}}
+ {{/hasChildren}}
+ {{/isModel}}
+ {{#isPrimitiveType}}
+ {{#isArray}}
+ if (!jsonElement.isJsonArray()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be a array type in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isArray}}
+ {{^isArray}}
+ {{#isMap}}
+ if (!jsonElement.isJsonObject()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be a object type in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isMap}}
+ {{^isMap}}
+ if (!jsonElement.isJsonPrimitive()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be a primitive type in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isMap}}
+ {{/isArray}}
+ {{/isPrimitiveType}}
+ matches++;
+ } catch (Exception e) {
+ // deserialization failed, continue
+ errorMessages.add(String.format("Deserialization for {{{dataType}}} failed with `%s`.", e.getMessage()));
+ }
+
+ {{/vendorExtensions.x-duplicated-data-type}}
+ {{/oneOf}}
+ {{/composedSchemas}}
+ if (matches != 1) {
+ throw new IOException(String.format("Failed deserialization for {{classname}}: %d classes match result, expected 1. %s", matches, errorMessages));
+ }
+ }
+
+ public static class CustomTypeAdapterFactory implements TypeAdapterFactory {
+ @SuppressWarnings("unchecked")
+ @Override
+ public TypeAdapter create(Gson gson, TypeToken type) {
+ if (!{{classname}}.class.isAssignableFrom(type.getRawType())) {
+ return null; // this class only serializes '{{classname}}' and its subtypes
+ }
+ final TypeAdapter elementAdapter = gson.getAdapter(JsonElement.class);
+ {{#composedSchemas}}
+ {{#oneOf}}
+ {{^isArray}}
+ {{^isMap}}
+ {{^vendorExtensions.x-duplicated-data-type}}
+ final TypeAdapter<{{{dataType}}}> adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}} = gson.getDelegateAdapter(this, TypeToken.get({{{dataType}}}.class));
+ {{/vendorExtensions.x-duplicated-data-type}}
+ {{/isMap}}
+ {{/isArray}}
+ {{#isArray}}
+ final Type typeInstance{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}} = new TypeToken<{{{dataType}}}>(){}.getType();
+ final TypeAdapter<{{{dataType}}}> adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}} = (TypeAdapter<{{{dataType}}}>) gson.getDelegateAdapter(this, TypeToken.get(typeInstance));
+ {{/isArray}}
+ {{#isMap}}
+ final Type typeInstance{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}} = new TypeToken<{{{dataType}}}>(){}.getType();
+ final TypeAdapter<{{{dataType}}}> adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}} = (TypeAdapter<{{{dataType}}}>) gson.getDelegateAdapter(this, TypeToken.get(typeInstance));
+ {{/isMap}}
+ {{/oneOf}}
+ {{/composedSchemas}}
+
+ return (TypeAdapter) new TypeAdapter<{{classname}}>() {
+ @Override
+ public void write(JsonWriter out, {{classname}} value) throws IOException {
+ if (value == null || value.getActualInstance() == null) {
+ elementAdapter.write(out, null);
+ return;
+ }
+
+ {{#composedSchemas}}
+ {{#oneOf}}
+ {{^vendorExtensions.x-duplicated-data-type}}
+ // check if the actual instance is of the type `{{{dataType}}}`
+ if (value.getActualInstance() instanceof {{#isArray}}List>{{/isArray}}{{#isMap}}Map, ?>{{/isMap}}{{^isMap}}{{^isArray}}{{{dataType}}}{{/isArray}}{{/isMap}}) {
+ {{#isPrimitiveType}}
+ {{^isMap}}
+ JsonPrimitive primitive = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.toJsonTree(({{{dataType}}})value.getActualInstance()).getAsJsonPrimitive();
+ elementAdapter.write(out, primitive);
+ return;
+ {{/isMap}}
+ {{#isMap}}
+ JsonObject object = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.toJsonTree(({{{dataType}}})value.getActualInstance()).getAsJsonObject();
+ elementAdapter.write(out, object);
+ return;
+ {{/isMap}}
+ {{/isPrimitiveType}}
+ {{^isPrimitiveType}}
+ {{#isArray}}
+ List> list = (List>) value.getActualInstance();
+ if (!list.isEmpty() && list.get(0) instanceof {{{items.dataType}}}) {
+ JsonArray array = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.toJsonTree(({{{dataType}}})value.getActualInstance()).getAsJsonArray();
+ elementAdapter.write(out, array);
+ return;
+ }
+ {{/isArray}}
+ {{/isPrimitiveType}}
+ {{^isMap}}
+ {{^isArray}}
+ {{^isPrimitiveType}}
+ JsonElement element = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.toJsonTree(({{{dataType}}})value.getActualInstance());
+ elementAdapter.write(out, element);
+ return;
+ {{/isPrimitiveType}}
+ {{/isArray}}
+ {{/isMap}}
+ }
+
+ {{/vendorExtensions.x-duplicated-data-type}}
+ {{/oneOf}}
+ {{/composedSchemas}}
+ throw new IOException("Failed to serialize as the type doesn't match oneOf schemas: {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}");
+ }
+
+ @Override
+ public {{classname}} read(JsonReader in) throws IOException {
+ Object deserialized = null;
+ JsonElement jsonElement = elementAdapter.read(in);
+
+ {{#useOneOfDiscriminatorLookup}}
+ {{#discriminator}}
+ JsonObject jsonObject = jsonElement.getAsJsonObject();
+ if (jsonObject.get("{{{propertyBaseName}}}") == null) {
+ throw new IOException("Failed to deserialize as the discriminator field '{{{propertyBaseName}}}' is missing.");
+ }
+ String discriminatorValue = jsonObject.get("{{{propertyBaseName}}}").getAsString();
+ {{#mappedModels}}
+ if ("{{{mappingName}}}".equals(discriminatorValue)) {
+ deserialized = adapter{{#sanitizeDataType}}{{{modelName}}}{{/sanitizeDataType}}.fromJsonTree(jsonElement);
+ {{classname}} ret = new {{classname}}();
+ ret.setActualInstance(deserialized);
+ return ret;
+ }
+ {{/mappedModels}}
+ {{/discriminator}}
+ {{/useOneOfDiscriminatorLookup}}
+
+ int match = 0;
+ ArrayList errorMessages = new ArrayList<>();
+ TypeAdapter actualAdapter = null;
+
+ {{#composedSchemas}}
+ {{#oneOf}}
+ {{^vendorExtensions.x-duplicated-data-type}}
+ // deserialize {{{dataType}}}
+ try {
+ // validate the JSON object to see if any exception is thrown
+ {{#isModel}}
+ {{#hasChildren}}
+ {{{dataType}}}.validateJsonElement(jsonElement);
+ {{/hasChildren}}
+ {{^hasChildren}}
+ {{#isArray}}
+ if (!jsonElement.isJsonArray()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be a array type in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isArray}}
+ {{^isArray}}
+ {{#isMap}}
+ if (!jsonElement.isJsonObject()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be a object type in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isMap}}
+ {{^isMap}}
+ {{{dataType}}}.validateJsonElement(jsonElement);
+ {{/isMap}}
+ {{/isArray}}
+ {{/hasChildren}}
+ {{/isModel}}
+ {{#isPrimitiveType}}
+ {{#isArray}}
+ if (!jsonElement.isJsonArray()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be a array type in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isArray}}
+ {{^isArray}}
+ {{#isMap}}
+ if (!jsonElement.isJsonObject()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be a object type in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isMap}}
+ {{^isMap}}
+ if (!jsonElement.isJsonPrimitive()) {
+ throw new IllegalArgumentException(String.format("Expected json element to be a primitive type in the JSON string but got `%s`", jsonElement.toString()));
+ }
+ {{/isMap}}
+ {{/isArray}}
+ {{/isPrimitiveType}}
+ actualAdapter = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}};
+ match++;
+ log.log(Level.FINER, "Input data matches schema '{{{dataType}}}'");
+ } catch (Exception e) {
+ // deserialization failed, continue
+ errorMessages.add(String.format("Deserialization for {{{dataType}}} failed with `%s`.", e.getMessage()));
+ log.log(Level.FINER, "Input data does not match schema '{{{dataType}}}'", e);
+ }
+
+ {{/vendorExtensions.x-duplicated-data-type}}
+ {{/oneOf}}
+ {{/composedSchemas}}
+ if (match == 1) {
+ {{classname}} ret = new {{classname}}();
+ ret.setActualInstance(actualAdapter.fromJsonTree(jsonElement));
+ return ret;
+ }
+
+ throw new IOException(String.format("Failed deserialization for {{classname}}: %d classes match result, expected 1. %s", match, errorMessages));
+ }
+ };
+ }
+ }
+ {{/isGson}}
+
+ {{#isJackson}}
+ public static class {{classname}}Serializer extends StdSerializer<{{classname}}> {
+ public {{classname}}Serializer(Class<{{classname}}> t) {
+ super(t);
+ }
+
+ public {{classname}}Serializer() {
+ this(null);
+ }
+
+ @Override
+ public void serialize({{classname}} value, JsonGenerator jgen, {{^useJackson3}}SerializerProvider provider{{/useJackson3}}{{#useJackson3}}SerializationContext serializationContext{{/useJackson3}}) throws {{^useJackson3}}IOException{{/useJackson3}}{{#useJackson3}}JacksonException{{/useJackson3}} {
+ {{^useJackson3}}
+ jgen.writeObject(value.getActualInstance());
+ {{/useJackson3}}
+ {{#useJackson3}}
+ serializationContext.writeValue(jgen, value.getActualInstance());
+ {{/useJackson3}}
+ }
+ }
+
+ public static class {{classname}}Deserializer extends StdDeserializer<{{classname}}> {
+ public {{classname}}Deserializer() {
+ this({{classname}}.class);
+ }
+
+ public {{classname}}Deserializer(Class> vc) {
+ super(vc);
+ }
+
+ @Override
+ public {{classname}} deserialize(JsonParser jp, DeserializationContext ctxt) throws {{^useJackson3}}IOException{{/useJackson3}}{{#useJackson3}}JacksonException{{/useJackson3}} {
+ JsonNode tree = ctxt.readTree(jp);
+ Object deserialized = null;
+ {{#useOneOfDiscriminatorLookup}}
+ {{#discriminator}}
+ {{classname}} new{{classname}} = new {{classname}}();
+ {{^useJackson3}}
+ Map result2 = tree.traverse(jp.getCodec()).readValueAs(new TypeReference>() {});
+ String discriminatorValue = (String)result2.get("{{{propertyBaseName}}}");
+ {{/useJackson3}}
+ {{#useJackson3}}
+ String discriminatorValue = tree.path("{{{propertyBaseName}}}").asText(null);
+ {{/useJackson3}}
+ if (discriminatorValue != null) {
+ switch (discriminatorValue) {
+ {{#mappedModels}}
+ case "{{{mappingName}}}":
+ {{^useJackson3}}
+ deserialized = tree.traverse(jp.getCodec()).readValueAs({{{modelName}}}.class);
+ {{/useJackson3}}
+ {{#useJackson3}}
+ deserialized = ctxt.readTreeAsValue(tree, {{{modelName}}}.class);
+ {{/useJackson3}}
+ new{{classname}}.setActualInstance(deserialized);
+ return new{{classname}};
+ {{/mappedModels}}
+ default:
+ log.log(Level.WARNING, String.format(java.util.Locale.ROOT, "Failed to lookup discriminator value `%s` for {{classname}}. Possible values:{{#mappedModels}} {{{mappingName}}}{{/mappedModels}}", discriminatorValue));
+ }
+ }
+
+ {{/discriminator}}
+ {{/useOneOfDiscriminatorLookup}}
+ {{^useJackson3}}
+ boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS);
+ {{/useJackson3}}
+ {{#useJackson3}}
+ boolean typeCoercion = false;
+ {{/useJackson3}}
+ int match = 0;
+ {{^useJackson3}}
+ JsonToken token = tree.traverse(jp.getCodec()).nextToken();
+ {{/useJackson3}}
+ {{#useJackson3}}
+ JsonToken token = tree.asToken();
+ {{/useJackson3}}
+ {{#oneOf}}
+ // deserialize {{{.}}}
+ try {
+ boolean attemptParsing = true;
+ // ensure that we respect type coercion as set on the client ObjectMapper
+ if ({{{.}}}.class.equals(Integer.class) || {{{.}}}.class.equals(Long.class) || {{{.}}}.class.equals(Float.class) || {{{.}}}.class.equals(Double.class) || {{{.}}}.class.equals(Boolean.class) || {{{.}}}.class.equals(String.class)) {
+ attemptParsing = typeCoercion;
+ if (!attemptParsing) {
+ attemptParsing |= (({{{.}}}.class.equals(Integer.class) || {{{.}}}.class.equals(Long.class)) && token == JsonToken.VALUE_NUMBER_INT);
+ attemptParsing |= (({{{.}}}.class.equals(Float.class) || {{{.}}}.class.equals(Double.class)) && token == JsonToken.VALUE_NUMBER_FLOAT);
+ attemptParsing |= ({{{.}}}.class.equals(Boolean.class) && (token == JsonToken.VALUE_FALSE || token == JsonToken.VALUE_TRUE));
+ attemptParsing |= ({{{.}}}.class.equals(String.class) && token == JsonToken.VALUE_STRING);
+ {{#isNullable}}
+ attemptParsing |= (token == JsonToken.VALUE_NULL);
+ {{/isNullable}}
+ }
+ }
+ if (attemptParsing) {
+ {{^useJackson3}}
+ deserialized = tree.traverse(jp.getCodec()).readValueAs({{{.}}}.class);
+ {{/useJackson3}}
+ {{#useJackson3}}
+ deserialized = ctxt.readTreeAsValue(tree, {{{.}}}.class);
+ {{/useJackson3}}
+ // TODO: there is no validation against JSON schema constraints
+ // (min, max, enum, pattern...), this does not perform a strict JSON
+ // validation, which means the 'match' count may be higher than it should be.
+ match++;
+ log.log(Level.FINER, "Input data matches schema '{{{.}}}'");
+ }
+ } catch (Exception e) {
+ // deserialization failed, continue
+ log.log(Level.FINER, "Input data does not match schema '{{{.}}}'", e);
+ }
+
+ {{/oneOf}}
+ if (match == 1) {
+ {{classname}} ret = new {{classname}}();
+ ret.setActualInstance(deserialized);
+ return ret;
+ }
+ {{^useJackson3}}
+ throw new IOException(String.format(java.util.Locale.ROOT, "Failed deserialization for {{classname}}: %d classes match result, expected 1", match));
+ {{/useJackson3}}
+ {{#useJackson3}}
+ throw DatabindException.from(jp, String.format(java.util.Locale.ROOT, "Failed deserialization for {{classname}}: %d classes match result, expected 1", match));
+ {{/useJackson3}}
+ }
+
+ /**
+ * Handle deserialization of the 'null' value.
+ */
+ @Override
+ {{^useJackson3}}
+ public {{classname}} getNullValue(DeserializationContext ctxt) throws JsonMappingException {
+ {{/useJackson3}}
+ {{#useJackson3}}
+ public {{classname}} getNullValue(DeserializationContext ctxt) {
+ {{/useJackson3}}
+ {{#isNullable}}
+ return null;
+ {{/isNullable}}
+ {{^isNullable}}
+ {{^useJackson3}}
+ throw new JsonMappingException(ctxt.getParser(), "{{classname}} cannot be null");
+ {{/useJackson3}}
+ {{#useJackson3}}
+ throw DatabindException.from(ctxt.getParser(), "{{classname}} cannot be null");
+ {{/useJackson3}}
+ {{/isNullable}}
+ }
+ }
+ {{/isJackson}}
+
+ // store a list of schema names defined in oneOf
+ public static final Map> schemas = new HashMap<>();
+
+ public {{classname}}() {
+ super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}});
+ }
+
+ {{#oneOf}}
+ public {{classname}}({{{.}}} o) {
+ super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}});
+ setActualInstance(o);
+ }
+
+ {{/oneOf}}
+ static {
+ {{#oneOf}}
+ schemas.put("{{{.}}}", {{{.}}}.class);
+ {{/oneOf}}
+ {{#isJackson}}
+ JSON.registerDescendants({{classname}}.class, Collections.unmodifiableMap(schemas));
+ {{#discriminator}}
+ // Initialize and register the discriminator mappings.
+ Map> mappings = new HashMap>();
+ {{#mappedModels}}
+ mappings.put("{{mappingName}}", {{modelName}}.class);
+ {{/mappedModels}}
+ mappings.put("{{name}}", {{classname}}.class);
+ JSON.registerDiscriminator({{classname}}.class, "{{propertyBaseName}}", mappings);
+ {{/discriminator}}
+ {{/isJackson}}
+ }
+
+ @Override
+ public Map> getSchemas() {
+ return {{classname}}.schemas;
+ }
+
+ /**
+ * Set the instance that matches the oneOf child schema, check
+ * the instance parameter is valid against the oneOf child schemas:
+ * {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}
+ *
+ * It could be an instance of the 'oneOf' schemas.
+ * The oneOf child schemas may themselves be a composed schema (allOf, anyOf, oneOf).
+ */
+ @Override
+ public void setActualInstance(Object instance) {
+ {{#isNullable}}
+ if (instance == null) {
+ super.setActualInstance(instance);
+ return;
+ }
+
+ {{/isNullable}}
+ {{#oneOf}}
+ if (JSON.isInstanceOf({{{.}}}.class, instance, new HashSet>())) {
+ super.setActualInstance(instance);
+ return;
+ }
+
+ {{/oneOf}}
+ throw new RuntimeException("Invalid instance type. Must be {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}");
+ }
+
+ /**
+ * Get the actual instance, which can be the following:
+ * {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}
+ *
+ * @return The actual instance ({{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}})
+ */
+ @Override
+ public Object getActualInstance() {
+ return super.getActualInstance();
+ }
+
+ {{#oneOf}}
+ /**
+ * Get the actual instance of `{{{.}}}`. If the actual instance is not `{{{.}}}`,
+ * the ClassCastException will be thrown.
+ *
+ * @return The actual instance of `{{{.}}}`
+ * @throws ClassCastException if the instance is not `{{{.}}}`
+ */
+ public {{{.}}} get{{{.}}}() throws ClassCastException {
+ return ({{{.}}})super.getActualInstance();
+ }
+
+ {{/oneOf}}
+
+{{#supportUrlQuery}}
+
+ /**
+ * Convert the instance into URL query string.
+ *
+ * @return URL query string
+ */
+ public String toUrlQueryString() {
+ return toUrlQueryString(null);
+ }
+
+ /**
+ * Convert the instance into URL query string.
+ *
+ * @param prefix prefix of the query string
+ * @return URL query string
+ */
+ public String toUrlQueryString(String prefix) {
+ String suffix = "";
+ String containerSuffix = "";
+ String containerPrefix = "";
+ if (prefix == null) {
+ // style=form, explode=true, e.g. /pet?name=cat&type=manx
+ prefix = "";
+ } else {
+ // deepObject style e.g. /pet?id[name]=cat&id[type]=manx
+ prefix = prefix + "[";
+ suffix = "]";
+ containerSuffix = "]";
+ containerPrefix = "[";
+ }
+
+ StringJoiner joiner = new StringJoiner("&");
+
+ {{#composedSchemas.oneOf}}
+ {{^vendorExtensions.x-duplicated-data-type}}
+ if (getActualInstance() instanceof {{{dataType}}}) {
+ {{#isArray}}
+ {{#items.isPrimitiveType}}
+ {{#uniqueItems}}
+ if (getActualInstance() != null) {
+ int i = 0;
+ for ({{{items.dataType}}} _item : ({{{dataType}}})getActualInstance()) {
+ joiner.add(String.format(java.util.Locale.ROOT, "%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, i, containerSuffix),
+ ApiClient.urlEncode(String.valueOf(_item))));
+ }
+ i++;
+ }
+ {{/uniqueItems}}
+ {{^uniqueItems}}
+ if (getActualInstance() != null) {
+ for (int i = 0; i < (({{{dataType}}})getActualInstance()).size(); i++) {
+ joiner.add(String.format(java.util.Locale.ROOT, "%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, i, containerSuffix),
+ ApiClient.urlEncode(String.valueOf(getActualInstance().get(i)))));
+ }
+ }
+ {{/uniqueItems}}
+ {{/items.isPrimitiveType}}
+ {{^items.isPrimitiveType}}
+ {{#items.isModel}}
+ {{#uniqueItems}}
+ if (getActualInstance() != null) {
+ int i = 0;
+ for ({{{items.dataType}}} _item : ({{{dataType}}})getActualInstance()) {
+ if (_item != null) {
+ joiner.add(_item.toUrlQueryString(String.format(java.util.Locale.ROOT, "%s{{baseName}}%s%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, i, containerSuffix))));
+ }
+ }
+ i++;
+ }
+ {{/uniqueItems}}
+ {{^uniqueItems}}
+ if (getActualInstance() != null) {
+ for (int i = 0; i < (({{{dataType}}})getActualInstance()).size(); i++) {
+ if ((({{{dataType}}})getActualInstance()).get(i) != null) {
+ joiner.add((({{{items.dataType}}})getActualInstance()).get(i).toUrlQueryString(String.format(java.util.Locale.ROOT, "%s{{baseName}}%s%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, i, containerSuffix))));
+ }
+ }
+ }
+ {{/uniqueItems}}
+ {{/items.isModel}}
+ {{^items.isModel}}
+ {{#uniqueItems}}
+ if (getActualInstance() != null) {
+ int i = 0;
+ for ({{{items.dataType}}} _item : ({{{dataType}}})getActualInstance()) {
+ if (_item != null) {
+ joiner.add(String.format(java.util.Locale.ROOT, "%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, i, containerSuffix),
+ ApiClient.urlEncode(String.valueOf(_item))));
+ }
+ i++;
+ }
+ }
+ {{/uniqueItems}}
+ {{^uniqueItems}}
+ if (getActualInstance() != null) {
+ for (int i = 0; i < (({{{dataType}}})getActualInstance()).size(); i++) {
+ if (getActualInstance().get(i) != null) {
+ joiner.add(String.format(java.util.Locale.ROOT, "%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, i, containerSuffix),
+ ApiClient.urlEncode(String.valueOf((({{{dataType}}})getActualInstance()).get(i)))));
+ }
+ }
+ }
+ {{/uniqueItems}}
+ {{/items.isModel}}
+ {{/items.isPrimitiveType}}
+ {{/isArray}}
+ {{^isArray}}
+ {{#isMap}}
+ {{#items.isPrimitiveType}}
+ if (getActualInstance() != null) {
+ for (String _key : (({{{dataType}}})getActualInstance()).keySet()) {
+ joiner.add(String.format(java.util.Locale.ROOT, "%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, _key, containerSuffix),
+ getActualInstance().get(_key), ApiClient.urlEncode(String.valueOf((({{{dataType}}})getActualInstance()).get(_key)))));
+ }
+ }
+ {{/items.isPrimitiveType}}
+ {{^items.isPrimitiveType}}
+ if (getActualInstance() != null) {
+ for (String _key : (({{{dataType}}})getActualInstance()).keySet()) {
+ if ((({{{dataType}}})getActualInstance()).get(_key) != null) {
+ joiner.add((({{{items.dataType}}})getActualInstance()).get(_key).toUrlQueryString(String.format(java.util.Locale.ROOT, "%s{{baseName}}%s%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, _key, containerSuffix))));
+ }
+ }
+ }
+ {{/items.isPrimitiveType}}
+ {{/isMap}}
+ {{^isMap}}
+ {{#isPrimitiveType}}
+ if (getActualInstance() != null) {
+ joiner.add(String.format(java.util.Locale.ROOT, "%s{{{baseName}}}%s=%s", prefix, suffix, ApiClient.urlEncode(String.valueOf(getActualInstance()))));
+ }
+ {{/isPrimitiveType}}
+ {{^isPrimitiveType}}
+ {{#isModel}}
+ if (getActualInstance() != null) {
+ joiner.add((({{{dataType}}})getActualInstance()).toUrlQueryString(prefix + "{{{baseName}}}" + suffix));
+ }
+ {{/isModel}}
+ {{^isModel}}
+ if (getActualInstance() != null) {
+ joiner.add(String.format(java.util.Locale.ROOT, "%s{{{baseName}}}%s=%s", prefix, suffix, ApiClient.urlEncode(String.valueOf(getActualInstance()))));
+ }
+ {{/isModel}}
+ {{/isPrimitiveType}}
+ {{/isMap}}
+ {{/isArray}}
+ return joiner.toString();
+ }
+ {{/vendorExtensions.x-duplicated-data-type}}
+ {{/composedSchemas.oneOf}}
+ return null;
+ }
+{{/supportUrlQuery}}
+
+}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/pojo.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/pojo.mustache
new file mode 100644
index 000000000000..745cd050ab0a
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/pojo.mustache
@@ -0,0 +1,672 @@
+{{#isGson}}
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import com.google.gson.TypeAdapterFactory;
+import com.google.gson.reflect.TypeToken;
+import com.google.gson.TypeAdapter;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+import com.google.gson.annotations.JsonAdapter;
+import com.google.gson.annotations.SerializedName;
+{{/isGson}}
+{{#isJackson}}
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonValue;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+{{/isJackson}}
+{{#isJsonb}}
+import jakarta.json.bind.annotation.JsonbProperty;
+import jakarta.json.bind.annotation.JsonbCreator;
+import jakarta.json.bind.annotation.JsonbValue;
+{{/isJsonb}}
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import {{invokerPackage}}.JSON;
+
+/**
+ * {{description}}{{^description}}{{classname}}{{/description}}{{#isDeprecated}}
+ * @deprecated{{/isDeprecated}}
+ */{{#isDeprecated}}
+@Deprecated{{/isDeprecated}}
+{{#swagger1AnnotationLibrary}}
+{{#description}}
+@ApiModel(description = "{{{.}}}")
+{{/description}}
+{{/swagger1AnnotationLibrary}}
+{{#swagger2AnnotationLibrary}}
+{{#description}}
+@Schema(description = "{{{.}}}")
+{{/description}}
+{{/swagger2AnnotationLibrary}}
+{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}}
+{{#vendorExtensions.x-class-extra-annotation}}
+{{{.}}}
+{{/vendorExtensions.x-class-extra-annotation}}
+{{#isJackson}}
+@JsonPropertyOrder({
+{{#vars}}
+ {{classname}}.JSON_PROPERTY_{{nameInSnakeCase}}{{^-last}},{{/-last}}
+{{/vars}}
+})
+{{#jacksonPackageName}}
+@tools.jackson.annotation.JsonTypeName("{{name}}")
+{{/jacksonPackageName}}
+{{^jacksonPackageName}}
+@JsonTypeName("{{name}}")
+{{/jacksonPackageName}}
+{{/isJackson}}
+public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{
+{{#serializableModel}}
+ private static final long serialVersionUID = 1L;
+
+{{/serializableModel}}
+ {{#vars}}
+ {{#isEnum}}
+ {{^isContainer}}
+{{>modelInnerEnum}}
+
+ {{/isContainer}}
+ {{#isContainer}}
+ {{#mostInnerItems}}
+{{>modelInnerEnum}}
+
+ {{/mostInnerItems}}
+ {{/isContainer}}
+ {{/isEnum}}
+ {{#isGson}}
+ public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}";
+ {{/isGson}}
+ {{#isJackson}}
+ public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}";
+ {{/isJackson}}
+ {{#isJsonb}}
+ public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}";
+ {{/isJsonb}}
+ {{#withXml}}
+ @Xml{{#isXmlAttribute}}Attribute{{/isXmlAttribute}}{{^isXmlAttribute}}Element{{/isXmlAttribute}}(name = "{{items.xmlName}}{{^items.xmlName}}{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}{{/items.xmlName}}"{{#xmlNamespace}}, namespace = "{{.}}"{{/xmlNamespace}})
+ {{#isXmlWrapped}}
+ @XmlElementWrapper(name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}"{{#xmlNamespace}}, namespace = "{{.}}"{{/xmlNamespace}})
+ {{/isXmlWrapped}}
+ {{/withXml}}
+ {{#deprecated}}
+ @Deprecated
+ {{/deprecated}}
+ {{#isGson}}
+ @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}})
+ {{/isGson}}
+ {{#isJackson}}
+ @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}})
+ {{#includeIfNull}}
+ @JsonInclude(value = JsonInclude.Include.ALWAYS)
+ {{/includeIfNull}}
+ {{#isReadOnly}}
+ @JsonProperty(access = JsonProperty.Access.READ_ONLY)
+ {{/isReadOnly}}
+ {{#isWriteOnly}}
+ @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
+ {{/isWriteOnly}}
+ {{/isJackson}}
+ {{#isJsonb}}
+ @JsonbProperty(SERIALIZED_NAME_{{nameInSnakeCase}})
+ {{/isJsonb}}
+ {{#vendorExtensions.x-field-extra-annotation}}
+ {{{.}}}
+ {{/vendorExtensions.x-field-extra-annotation}}
+ {{>nullable_var_annotations}}{{! prevent indent}}
+ {{#isDiscriminator}}protected{{/isDiscriminator}}{{^isDiscriminator}}private{{/isDiscriminator}} {{>nullableDatatypeWithEnum}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
+
+ {{/vars}}
+ public {{classname}}() {
+ {{#parent}}
+ {{#parcelableModel}}
+ super();
+ {{/parcelableModel}}
+ {{/parent}}
+ {{#discriminator}}
+ {{#discriminator.isEnum}}
+{{#readWriteVars}}{{#isDiscriminator}}{{#defaultValue}}
+ this.{{name}} = {{defaultValue}};
+{{/defaultValue}}{{/isDiscriminator}}{{/readWriteVars}}
+ {{/discriminator.isEnum}}
+ {{^discriminator.isEnum}}
+ this.{{{discriminatorName}}} = this.getClass().getSimpleName();
+ {{/discriminator.isEnum}}
+ {{/discriminator}}
+ }
+ {{#vendorExtensions.x-has-readonly-properties}}
+ {{^withXml}}
+
+ public {{classname}}(
+ {{#readOnlyVars}}
+ {{{datatypeWithEnum}}} {{name}}{{^-last}}, {{/-last}}
+ {{/readOnlyVars}}
+ ) {
+ this();
+ {{#readOnlyVars}}
+ this.{{name}} = {{name}};
+ {{/readOnlyVars}}
+ }
+ {{/withXml}}
+ {{/vendorExtensions.x-has-readonly-properties}}
+ {{#vars}}
+
+ {{^isReadOnly}}
+ {{#deprecated}}
+ @Deprecated
+ {{/deprecated}}
+ public {{classname}} {{name}}({{>nullableArgumentWithEnum}} {{name}}) {
+ this.{{name}} = {{name}};
+ return this;
+ }
+ {{#isArray}}
+
+ public {{classname}} add{{nameInPascalCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) {
+ if (this.{{name}} == null) {
+ this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new {{#uniqueItems}}LinkedHashSet{{/uniqueItems}}{{^uniqueItems}}ArrayList{{/uniqueItems}}<>(){{/defaultValue}};
+ }
+ this.{{name}}.add({{name}}Item);
+ return this;
+ }
+ {{/isArray}}
+ {{#isMap}}
+
+ public {{classname}} put{{nameInPascalCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) {
+ if (this.{{name}} == null) {
+ this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new HashMap<>(){{/defaultValue}};
+ }
+ this.{{name}}.put(key, {{name}}Item);
+ return this;
+ }
+ {{/isMap}}
+
+ {{/isReadOnly}}
+ /**
+ {{#description}}
+ * {{.}}
+ {{/description}}
+ {{^description}}
+ * Get {{name}}
+ {{/description}}
+ {{#minimum}}
+ * minimum: {{.}}
+ {{/minimum}}
+ {{#maximum}}
+ * maximum: {{.}}
+ {{/maximum}}
+ * @return {{name}}
+ {{#deprecated}}
+ * @deprecated
+ {{/deprecated}}
+ */
+{{#deprecated}}
+ @Deprecated
+{{/deprecated}}
+ {{>nullable_var_annotations}}{{! prevent indent}}
+{{#useBeanValidation}}
+{{>beanValidation}}
+
+{{/useBeanValidation}}
+{{#swagger1AnnotationLibrary}}
+ @ApiModelProperty({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}")
+{{/swagger1AnnotationLibrary}}
+{{#swagger2AnnotationLibrary}}
+ @Schema({{#example}}example = "{{{.}}}", {{/example}}requiredMode = {{#required}}Schema.RequiredMode.REQUIRED{{/required}}{{^required}}Schema.RequiredMode.NOT_REQUIRED{{/required}}, description = "{{{description}}}")
+{{/swagger2AnnotationLibrary}}
+{{#vendorExtensions.x-extra-annotation}}
+ {{{vendorExtensions.x-extra-annotation}}}
+{{/vendorExtensions.x-extra-annotation}}
+{{#jackson}}{{> jackson_annotations}}{{/jackson}}
+ public {{>nullableDatatypeWithEnum}} {{getter}}() {
+ return {{name}};
+ }
+
+ {{^isReadOnly}}
+{{#vendorExtensions.x-setter-extra-annotation}} {{{vendorExtensions.x-setter-extra-annotation}}}
+{{/vendorExtensions.x-setter-extra-annotation}}{{#deprecated}} @Deprecated
+{{/deprecated}}{{#jackson}}{{> jackson_annotations}}{{/jackson}} public void {{setter}}({{>nullableArgumentWithEnum}} {{name}}) {
+ this.{{name}} = {{name}};
+ }
+ {{/isReadOnly}}
+
+ {{/vars}}
+{{>additional_properties}}
+
+
+ @Override
+ public boolean equals(Object o) {
+ {{#useReflectionEqualsHashCode}}
+ return EqualsBuilder.reflectionEquals(this, o, false, null, true);
+ {{/useReflectionEqualsHashCode}}
+ {{^useReflectionEqualsHashCode}}
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }{{#hasVars}}
+ {{classname}} {{classVarName}} = ({{classname}}) o;
+ return {{#vars}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{^-last}} &&
+ {{/-last}}{{/vars}}{{#isAdditionalPropertiesTrue}}&&
+ Objects.equals(this.additionalProperties, {{classVarName}}.additionalProperties){{/isAdditionalPropertiesTrue}}{{#parent}} &&
+ super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}}
+ return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}}
+ {{/useReflectionEqualsHashCode}}
+ }{{#vendorExtensions.x-jackson-optional-nullable-helpers}}
+
+ private static boolean equalsNullable(JsonNullable a, JsonNullable b) {
+ return a == b || (a != null && b != null && a.isPresent() && b.isPresent() && Objects.deepEquals(a.get(), b.get()));
+ }{{/vendorExtensions.x-jackson-optional-nullable-helpers}}
+
+ @Override
+ public int hashCode() {
+ {{#useReflectionEqualsHashCode}}
+ return HashCodeBuilder.reflectionHashCode(this);
+ {{/useReflectionEqualsHashCode}}
+ {{^useReflectionEqualsHashCode}}
+ return Objects.hash({{#vars}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}{{#isAdditionalPropertiesTrue}}{{#hasVars}}, {{/hasVars}}{{^hasVars}}{{#parent}}, {{/parent}}{{/hasVars}}additionalProperties{{/isAdditionalPropertiesTrue}});
+ {{/useReflectionEqualsHashCode}}
+ }{{#vendorExtensions.x-jackson-optional-nullable-helpers}}
+
+ private static int hashCodeNullable(JsonNullable a) {
+ if (a == null) {
+ return 1;
+ }
+ return a.isPresent() ? Arrays.deepHashCode(new Object[]{a.get()}) : 31;
+ }{{/vendorExtensions.x-jackson-optional-nullable-helpers}}
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("class {{classname}} {\n");
+ {{#parent}}
+ sb.append(" ").append(toIndentedString(super.toString())).append("\n");
+ {{/parent}}
+ {{#vars}}
+ sb.append(" {{name}}: ").append({{#isPassword}}"*"{{/isPassword}}{{^isPassword}}toIndentedString({{name}}){{/isPassword}}).append("\n");
+ {{/vars}}
+{{#isAdditionalPropertiesTrue}}
+ sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n");
+{{/isAdditionalPropertiesTrue}}
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces
+ * (except the first line).
+ */
+ private String toIndentedString(Object o) {
+ return o == null ? "null" : o.toString().replace("\n", "\n ");
+ }
+
+{{#parcelableModel}}
+
+ public void writeToParcel(Parcel out, int flags) {
+{{#model}}
+{{#isArray}}
+ out.writeList(this);
+{{/isArray}}
+{{^isArray}}
+{{#parent}}
+ super.writeToParcel(out, flags);
+{{/parent}}
+{{#vars}}
+ out.writeValue({{name}});
+{{/vars}}
+{{/isArray}}
+{{/model}}
+ }
+
+ {{classname}}(Parcel in) {
+{{#isArray}}
+ in.readTypedList(this, {{arrayModelType}}.CREATOR);
+{{/isArray}}
+{{^isArray}}
+{{#parent}}
+ super(in);
+{{/parent}}
+{{#vars}}
+{{#isPrimitiveType}}
+ {{name}} = ({{{datatypeWithEnum}}})in.readValue(null);
+{{/isPrimitiveType}}
+{{^isPrimitiveType}}
+ {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader());
+{{/isPrimitiveType}}
+{{/vars}}
+{{/isArray}}
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() {
+ public {{classname}} createFromParcel(Parcel in) {
+{{#model}}
+{{#isArray}}
+ {{classname}} result = new {{classname}}();
+ result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader()));
+ return result;
+{{/isArray}}
+{{^isArray}}
+ return new {{classname}}(in);
+{{/isArray}}
+{{/model}}
+ }
+ public {{classname}}[] newArray(int size) {
+ return new {{classname}}[size];
+ }
+ };
+{{/parcelableModel}}
+
+ public static HashSet openapiFields;
+ public static HashSet openapiRequiredFields;
+
+ static {
+ // a set of all properties/fields (JSON key names)
+ {{#hasVars}}
+ openapiFields = new HashSet(Arrays.asList({{#allVars}}"{{baseName}}"{{^-last}}, {{/-last}}{{/allVars}}));
+ {{/hasVars}}
+ {{^hasVars}}
+ openapiFields = new HashSet(0);
+ {{/hasVars}}
+
+ // a set of required properties/fields (JSON key names)
+ {{#hasRequired}}
+ openapiRequiredFields = new HashSet(Arrays.asList({{#requiredVars}}"{{baseName}}"{{^-last}}, {{/-last}}{{/requiredVars}}));
+ {{/hasRequired}}
+ {{^hasRequired}}
+ openapiRequiredFields = new HashSet(0);
+ {{/hasRequired}}
+ }
+
+{{#isGson}}
+ /**
+ * Validates the JSON Element and throws an exception if issues found
+ *
+ * @param jsonElement JSON Element
+ * @throws IOException if the JSON Element is invalid with respect to {{classname}}
+ */
+ public static void validateJsonElement(JsonElement jsonElement) throws IOException {
+ if (jsonElement == null) {
+ if (!{{classname}}.openapiRequiredFields.isEmpty()) { // has required fields but JSON element is null
+ throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "The required field(s) %s in {{{classname}}} is not found in the empty JSON string", {{classname}}.openapiRequiredFields.toString()));
+ }
+ }
+ {{^hasChildren}}
+ {{^isAdditionalPropertiesTrue}}
+
+ Set> entries = jsonElement.getAsJsonObject().entrySet();
+ // check to see if the JSON string contains additional fields
+ for (Map.Entry entry : entries) {
+ if (!{{classname}}.openapiFields.contains(entry.getKey())) {
+ throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "The field `%s` in the JSON string is not defined in the `{{classname}}` properties. JSON: %s", entry.getKey(), jsonElement.toString()));
+ }
+ }
+ {{/isAdditionalPropertiesTrue}}
+ {{#requiredVars}}
+ {{#-first}}
+
+ // check to make sure all required properties/fields are present in the JSON string
+ for (String requiredField : {{classname}}.openapiRequiredFields) {
+ if (jsonElement.getAsJsonObject().get(requiredField) == null) {
+ throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "The required field `%s` is not found in the JSON string: %s", requiredField, jsonElement.toString()));
+ }
+ }
+ {{/-first}}
+ {{/requiredVars}}
+ {{/hasChildren}}
+ {{^discriminator}}
+ {{#hasVars}}
+ JsonObject jsonObj = jsonElement.getAsJsonObject();
+ {{/hasVars}}
+ {{#vars}}
+ {{#isArray}}
+ {{#items.isModel}}
+ {{#required}}
+ if (jsonObj.get("{{{baseName}}}") != null{{#isNullable}} && !jsonObj.get("{{{baseName}}}").isJsonNull(){{/isNullable}}) {
+ if (!jsonObj.get("{{{baseName}}}").isJsonArray()) {
+ throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj.get("{{{baseName}}}").toString()));
+ }
+ JsonArray jsonArray{{name}} = jsonObj.getAsJsonArray("{{{baseName}}}");
+ // validate the required field `{{{baseName}}}` (array)
+ for (int i = 0; i < jsonArray{{name}}.size(); i++) {
+ {{{items.dataType}}}.validateJsonElement(jsonArray{{name}}.get(i));
+ }
+ }
+ {{/required}}
+ {{^required}}
+ if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) {
+ JsonArray jsonArray{{name}} = jsonObj.getAsJsonArray("{{{baseName}}}");
+ if (jsonArray{{name}} != null) {
+ // ensure the json data is an array
+ if (!jsonObj.get("{{{baseName}}}").isJsonArray()) {
+ throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj.get("{{{baseName}}}").toString()));
+ }
+
+ // validate the optional field `{{{baseName}}}` (array)
+ for (int i = 0; i < jsonArray{{name}}.size(); i++) {
+ {{{items.dataType}}}.validateJsonElement(jsonArray{{name}}.get(i));
+ };
+ }
+ }
+ {{/required}}
+ {{/items.isModel}}
+ {{^items.isModel}}
+ {{^required}}
+ // ensure the optional json data is an array if present
+ if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull() && !jsonObj.get("{{{baseName}}}").isJsonArray()) {
+ throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj.get("{{{baseName}}}").toString()));
+ }
+ {{/required}}
+ {{#required}}
+ // ensure the required json array is present
+ if (jsonObj.get("{{{baseName}}}") == null) {
+ throw new IllegalArgumentException("Expected the field `linkedContent` to be an array in the JSON string but got `null`");
+ } else if (!jsonObj.get("{{{baseName}}}").isJsonArray(){{#isNullable}} && !jsonObj.get("{{baseName}}").isJsonNull(){{/isNullable}}) {
+ throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj.get("{{{baseName}}}").toString()));
+ }
+ {{/required}}
+ {{/items.isModel}}
+ {{/isArray}}
+ {{^isContainer}}
+ {{#isString}}
+ if ({{#notRequiredOrIsNullable}}(jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) && {{/notRequiredOrIsNullable}}!jsonObj.get("{{{baseName}}}").isJsonPrimitive()) {
+ throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `{{{baseName}}}` to be a primitive type in the JSON string but got `%s`", jsonObj.get("{{{baseName}}}").toString()));
+ }
+ {{/isString}}
+ {{#isModel}}
+ {{^isEnum}}
+ {{#required}}
+ {{#isNullable}}
+ if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) {
+ {{/isNullable}}
+ // validate the required field `{{{baseName}}}`
+ {{{dataType}}}.validateJsonElement(jsonObj.get("{{{baseName}}}"));
+ {{#isNullable}}
+ }
+ {{/isNullable}}
+ {{/required}}
+ {{^required}}
+ // validate the optional field `{{{baseName}}}`
+ if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) {
+ {{{dataType}}}.validateJsonElement(jsonObj.get("{{{baseName}}}"));
+ }
+ {{/required}}
+ {{/isEnum}}
+ {{/isModel}}
+ {{#isEnum}}
+ {{#required}}
+ {{#isNullable}}
+ if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) {
+ {{/isNullable}}
+ // validate the required field `{{{baseName}}}`
+ {{{datatypeWithEnum}}}.validateJsonElement(jsonObj.get("{{{baseName}}}"));
+ {{#isNullable}}
+ }
+ {{/isNullable}}
+ {{/required}}
+ {{^required}}
+ // validate the optional field `{{{baseName}}}`
+ if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) {
+ {{{datatypeWithEnum}}}.validateJsonElement(jsonObj.get("{{{baseName}}}"));
+ }
+ {{/required}}
+ {{/isEnum}}
+ {{#isEnumRef}}
+ {{#required}}
+ {{#isNullable}}
+ if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) {
+ {{/isNullable}}
+ // validate the required field `{{{baseName}}}`
+ {{{dataType}}}.validateJsonElement(jsonObj.get("{{{baseName}}}"));
+ {{#isNullable}}
+ }
+ {{/isNullable}}
+ {{/required}}
+ {{^required}}
+ // validate the optional field `{{{baseName}}}`
+ if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) {
+ {{{dataType}}}.validateJsonElement(jsonObj.get("{{{baseName}}}"));
+ }
+ {{/required}}
+ {{/isEnumRef}}
+ {{/isContainer}}
+ {{/vars}}
+ {{/discriminator}}
+ {{#hasChildren}}
+ {{#discriminator}}
+
+ String discriminatorValue = jsonElement.getAsJsonObject().get("{{{propertyBaseName}}}").getAsString();
+ switch (discriminatorValue) {
+ {{#mappedModels}}
+ case "{{mappingName}}":
+ {{modelName}}.validateJsonElement(jsonElement);
+ break;
+ {{/mappedModels}}
+ default:
+ throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "The value of the `{{{propertyBaseName}}}` field `%s` does not match any key defined in the discriminator's mapping.", discriminatorValue));
+ }
+ {{/discriminator}}
+ {{/hasChildren}}
+ }
+
+{{^hasChildren}}
+ public static class CustomTypeAdapterFactory implements TypeAdapterFactory {
+ @SuppressWarnings("unchecked")
+ @Override
+ public TypeAdapter create(Gson gson, TypeToken type) {
+ if (!{{classname}}.class.isAssignableFrom(type.getRawType())) {
+ return null; // this class only serializes '{{classname}}' and its subtypes
+ }
+ final TypeAdapter elementAdapter = gson.getAdapter(JsonElement.class);
+ final TypeAdapter<{{classname}}> thisAdapter
+ = gson.getDelegateAdapter(this, TypeToken.get({{classname}}.class));
+
+ return (TypeAdapter) new TypeAdapter<{{classname}}>() {
+ @Override
+ public void write(JsonWriter out, {{classname}} value) throws IOException {
+ JsonObject obj = thisAdapter.toJsonTree(value).getAsJsonObject();
+ {{#isAdditionalPropertiesTrue}}
+ obj.remove("additionalProperties");
+ // serialize additional properties
+ if (value.getAdditionalProperties() != null) {
+ for (Map.Entry entry : value.getAdditionalProperties().entrySet()) {
+ if (entry.getValue() instanceof String)
+ obj.addProperty(entry.getKey(), (String) entry.getValue());
+ else if (entry.getValue() instanceof Number)
+ obj.addProperty(entry.getKey(), (Number) entry.getValue());
+ else if (entry.getValue() instanceof Boolean)
+ obj.addProperty(entry.getKey(), (Boolean) entry.getValue());
+ else if (entry.getValue() instanceof Character)
+ obj.addProperty(entry.getKey(), (Character) entry.getValue());
+ else {
+ JsonElement jsonElement = gson.toJsonTree(entry.getValue());
+ if (jsonElement.isJsonArray()) {
+ obj.add(entry.getKey(), jsonElement.getAsJsonArray());
+ } else {
+ obj.add(entry.getKey(), jsonElement.getAsJsonObject());
+ }
+ }
+ }
+ }
+ {{/isAdditionalPropertiesTrue}}
+ elementAdapter.write(out, obj);
+ }
+
+ @Override
+ public {{classname}} read(JsonReader in) throws IOException {
+ JsonElement jsonElement = elementAdapter.read(in);
+ validateJsonElement(jsonElement);
+ {{#isAdditionalPropertiesTrue}}
+ JsonObject jsonObj = jsonElement.getAsJsonObject();
+ // store additional fields in the deserialized instance
+ {{classname}} instance = thisAdapter.fromJsonTree(jsonObj);
+ for (Map.Entry entry : jsonObj.entrySet()) {
+ if (!openapiFields.contains(entry.getKey())) {
+ if (entry.getValue().isJsonPrimitive()) { // primitive type
+ if (entry.getValue().getAsJsonPrimitive().isString())
+ instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsString());
+ else if (entry.getValue().getAsJsonPrimitive().isNumber())
+ instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsNumber());
+ else if (entry.getValue().getAsJsonPrimitive().isBoolean())
+ instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsBoolean());
+ else
+ throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "The field `%s` has unknown primitive type. Value: %s", entry.getKey(), entry.getValue().toString()));
+ } else if (entry.getValue().isJsonArray()) {
+ instance.putAdditionalProperty(entry.getKey(), gson.fromJson(entry.getValue(), List.class));
+ } else { // JSON object
+ instance.putAdditionalProperty(entry.getKey(), gson.fromJson(entry.getValue(), HashMap.class));
+ }
+ }
+ }
+ return instance;
+ {{/isAdditionalPropertiesTrue}}
+ {{^isAdditionalPropertiesTrue}}
+ return thisAdapter.fromJsonTree(jsonElement);
+ {{/isAdditionalPropertiesTrue}}
+ }
+
+ }.nullSafe();
+ }
+ }
+{{/hasChildren}}
+{{/isGson}}
+
+{{#isGson}}
+ /**
+ * Create an instance of {{classname}} given an JSON string
+ *
+ * @param jsonString JSON string
+ * @return An instance of {{classname}}
+ * @throws IOException if the JSON string is invalid with respect to {{classname}}
+ */
+ public static {{{classname}}} fromJson(String jsonString) throws IOException {
+ return JSON.getGson().fromJson(jsonString, {{{classname}}}.class);
+ }
+
+ /**
+ * Convert an instance of {{classname}} to an JSON string
+ *
+ * @return JSON string
+ */
+ public String toJson() {
+ return JSON.getGson().toJson(this);
+ }
+{{/isGson}}
+}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/pom.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/pom.mustache
new file mode 100644
index 000000000000..66bd1b18e9ea
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp/pom.mustache
@@ -0,0 +1,466 @@
+
+ 4.0.0
+ {{groupId}}
+ {{artifactId}}
+ jar
+ {{artifactId}}
+ {{artifactVersion}}
+ {{artifactUrl}}
+ {{artifactDescription}}
+
+ {{scmConnection}}
+ {{scmDeveloperConnection}}
+ {{scmUrl}}
+
+{{#parentOverridden}}
+
+ {{{parentGroupId}}}
+ {{{parentArtifactId}}}
+ {{{parentVersion}}}
+
+{{/parentOverridden}}
+
+
+
+ {{licenseName}}
+ {{licenseUrl}}
+ repo
+
+
+
+
+
+ {{developerName}}
+ {{developerEmail}}
+ {{developerOrganization}}
+ {{developerOrganizationUrl}}
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+ {{#useJackson3}}
+ 17
+ 17
+ {{/useJackson3}}
+ {{^useJackson3}}
+ 1.8
+ 1.8
+ {{/useJackson3}}
+ true
+ 128m
+ 512m
+
+ -Xlint:all
+ -J-Xss4m
+
+
+
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+ 3.4.1
+
+
+ enforce-maven
+
+ enforce
+
+
+
+
+ 2.2.0
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.22.2
+
+
+
+ loggerPath
+ conf/log4j.properties
+
+
+ -Xms512m -Xmx1500m
+ methods
+ 10
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ ${junit-version}
+
+
+
+
+ maven-dependency-plugin
+ 3.6.1
+
+
+ package
+
+ copy-dependencies
+
+
+ ${project.build.directory}/lib
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.3.0
+
+
+
+ test-jar
+
+
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ 3.5.0
+
+
+ add_sources
+ generate-sources
+
+ add-source
+
+
+
+ {{{sourceFolder}}}
+
+
+
+
+ add_test_sources
+ generate-test-sources
+
+ add-test-source
+
+
+
+ src/test/java
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.6.3
+
+
+ attach-javadocs
+
+ jar
+
+
+
+
+ none
+
+
+ http.response.details
+ a
+ Http Response Details:
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 3.3.0
+
+
+ attach-sources
+
+ jar-no-fork
+
+
+
+
+
+
+
+
+
+ sign-artifacts
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ 3.2.1
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+
+
+
+
+
+
+
+
+ {{#swagger1AnnotationLibrary}}
+
+ io.swagger
+ swagger-annotations
+ ${swagger-annotations-version}
+
+ {{/swagger1AnnotationLibrary}}
+ {{#swagger2AnnotationLibrary}}
+
+ io.swagger.core.v3
+ swagger-annotations
+ ${swagger-annotations-version}
+
+ {{/swagger2AnnotationLibrary}}
+ {{^useJspecify}}
+
+
+ com.google.code.findbugs
+ jsr305
+ 3.0.2
+
+ {{/useJspecify}}
+ {{#useJspecify}}
+
+ org.jspecify
+ jspecify
+ 1.0.0
+
+ {{/useJspecify}}
+
+ com.squareup.okhttp3
+ okhttp
+ ${okhttp-version}
+
+
+ com.squareup.okhttp3
+ logging-interceptor
+ ${okhttp-version}
+
+ {{#isGson}}
+
+ com.google.code.gson
+ gson
+ ${gson-version}
+
+
+ io.gsonfire
+ gson-fire
+ ${gson-fire-version}
+
+ {{/isGson}}
+ {{#isJackson}}
+
+ {{jacksonPackage}}.core
+ jackson-core
+ ${jackson-version}
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+ ${jackson-annotations-version}
+
+
+ {{jacksonPackage}}.core
+ jackson-databind
+ ${jackson-version}
+
+ {{^useJackson3}}
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+ ${jackson-version}
+
+ {{/useJackson3}}
+ {{#openApiNullable}}
+
+ org.openapitools
+ jackson-databind-nullable
+ ${jackson-databind-nullable-version}
+
+ {{/openApiNullable}}
+ {{/isJackson}}
+ {{#isJsonb}}
+
+ jakarta.json.bind
+ jakarta.json.bind-api
+ ${jsonb-api-version}
+
+
+ org.eclipse
+ yasson
+ ${yasson-version}
+
+
+ jakarta.json
+ jakarta.json-api
+ 2.1.3
+
+
+ org.eclipse.parsson
+ parsson
+ 1.1.7
+
+ {{/isJsonb}}
+ {{#hasOAuthMethods}}
+
+ org.apache.oltu.oauth2
+ org.apache.oltu.oauth2.client
+ 1.0.2
+
+ {{/hasOAuthMethods}}
+ {{#useReflectionEqualsHashCode}}
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3-version}
+
+ {{/useReflectionEqualsHashCode}}
+ {{#joda}}
+
+ joda-time
+ joda-time
+ ${jodatime-version}
+
+ {{/joda}}
+ {{#useBeanValidation}}
+
+
+ jakarta.validation
+ jakarta.validation-api
+ ${beanvalidation-version}
+ provided
+
+ {{/useBeanValidation}}
+ {{#performBeanValidation}}
+
+
+ org.hibernate.validator
+ hibernate-validator
+ 8.0.3.Final
+
+
+ jakarta.el
+ jakarta.el-api
+ ${jakarta.el-version}
+
+ {{/performBeanValidation}}
+
+ jakarta.annotation
+ jakarta.annotation-api
+ ${jakarta-annotation-version}
+ provided
+
+ {{#withAWSV4Signature}}
+
+ software.amazon.awssdk
+ auth
+ 2.20.157
+
+ {{/withAWSV4Signature}}
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ ${junit-version}
+ test
+
+
+ org.junit.platform
+ junit-platform-runner
+ ${junit-platform-runner.version}
+ test
+
+
+
+ {{#java17}}17{{/java17}}{{^java17}}{{#java11}}11{{/java11}}{{^java11}}1.8{{/java11}}{{/java17}}
+ ${java.version}
+ ${java.version}
+ 1.9.0
+ {{#swagger1AnnotationLibrary}}
+ 1.6.6
+ {{/swagger1AnnotationLibrary}}
+ {{#swagger2AnnotationLibrary}}
+ 2.2.15
+ {{/swagger2AnnotationLibrary}}
+ 5.4.0
+ {{#isGson}}
+ 2.10.1
+ {{/isGson}}
+ {{#isJackson}}
+ {{#useJackson3}}
+ 3.2.1
+ {{/useJackson3}}
+ {{^useJackson3}}
+ 2.17.1
+ {{/useJackson3}}
+ 2.21
+ {{/isJackson}}
+ {{#isJsonb}}
+ 3.0.1
+ 3.0.4
+ {{/isJsonb}}
+ {{#useReflectionEqualsHashCode}}
+ 3.18.0
+ {{/useReflectionEqualsHashCode}}
+ {{#isJackson}}
+ {{#openApiNullable}}
+ 0.2.10
+ {{/openApiNullable}}
+ {{/isJackson}}
+ {{#joda}}
+ 2.12.0
+ {{/joda}}
+ {{#useJakartaEe}}
+ 2.1.1
+ {{#useBeanValidation}}
+ 3.0.2
+ {{/useBeanValidation}}
+ {{/useJakartaEe}}
+ {{^useJakartaEe}}
+ 1.3.5
+ {{#useBeanValidation}}
+ 2.0.2
+ {{/useBeanValidation}}
+ {{/useJakartaEe}}
+ {{#performBeanValidation}}
+ 3.0.3
+ {{/performBeanValidation}}
+ 5.10.3
+ 1.10.0
+ UTF-8
+
+
diff --git a/modules/openapi-generator/src/main/resources/Java/modelEnum.mustache b/modules/openapi-generator/src/main/resources/Java/modelEnum.mustache
index 6738ef9edc16..b8570851d99a 100644
--- a/modules/openapi-generator/src/main/resources/Java/modelEnum.mustache
+++ b/modules/openapi-generator/src/main/resources/Java/modelEnum.mustache
@@ -79,7 +79,7 @@ import java.net.URI;
@Override
public {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException {
{{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = {{#isFloat}}(float){{/isFloat}}{{#isUri}}URI.create({{/isUri}}jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{#isUri}}nextString()){{/isUri}}{{^isNumber}}{{^isInteger}}{{^isUri}}{{#isFloat}}nextDouble{{/isFloat}}{{^isFloat}}next{{{dataType}}}{{/isFloat}}(){{/isUri}}{{/isInteger}}{{/isNumber}};
- return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
+ return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new java.math.BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
}
}
{{/gson}}
diff --git a/modules/openapi-generator/src/main/resources/Java/modelInnerEnum.mustache b/modules/openapi-generator/src/main/resources/Java/modelInnerEnum.mustache
index 9a50912fc780..fa1d3a610530 100644
--- a/modules/openapi-generator/src/main/resources/Java/modelInnerEnum.mustache
+++ b/modules/openapi-generator/src/main/resources/Java/modelInnerEnum.mustache
@@ -68,7 +68,7 @@
@Override
public {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException {
{{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = {{#isFloat}}(float){{/isFloat}} {{#isUri}}URI.create({{/isUri}}jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{#isUri}}nextString()){{/isUri}}{{^isNumber}}{{^isInteger}}{{^isUri}}{{#isFloat}}nextDouble{{/isFloat}}{{^isFloat}}next{{{dataType}}}{{/isFloat}}(){{/isUri}}{{/isInteger}}{{/isNumber}};
- return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
+ return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new java.math.BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
}
}
{{/gson}}
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 0e4d9033c831..5e85717a992a 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
@@ -89,6 +89,7 @@ enum Library {
MICROPROFILE("microprofile", Serializer.JSONB, Set.of(Serializer.JACKSON)),
NATIVE("native", Serializer.JACKSON),
OKHTTP("okhttp-gson", Serializer.GSON),
+ OKHTTP_GENERIC("okhttp", Serializer.GSON, Set.of(Serializer.JACKSON, Serializer.JSONB)),
REST_ASSURED("rest-assured", Serializer.GSON, Set.of(Serializer.JACKSON)),
RESTEASY("resteasy", Serializer.JACKSON),
REST_CLIENT("restclient", Serializer.JACKSON),
@@ -230,6 +231,53 @@ public void testParametersAreCorrectlyOrderedWhenUsingRetrofit() {
Assertions.assertEquals(Arrays.asList(pathParam1, pathParam2, queryParamRequired, queryParamOptional), codegenOperation.allParams);
}
+ @Test
+ public void testOkHttp() {
+ final JavaClientCodegen codegen = new JavaClientCodegen();
+ codegen.setLibrary(JavaClientCodegen.OKHTTP);
+ codegen.processOpts();
+
+ assertEquals(JavaClientCodegen.OKHTTP, codegen.getLibrary());
+ assertTrue((Boolean) codegen.additionalProperties().get("isGson"));
+ }
+
+ @Test
+ public void testOkHttpWithJackson() {
+ final JavaClientCodegen codegen = new JavaClientCodegen();
+ codegen.setLibrary(JavaClientCodegen.OKHTTP);
+ codegen.additionalProperties().put(CodegenConstants.SERIALIZATION_LIBRARY, JavaClientCodegen.SERIALIZATION_LIBRARY_JACKSON);
+ codegen.processOpts();
+
+ assertEquals(JavaClientCodegen.OKHTTP, codegen.getLibrary());
+ assertTrue((Boolean) codegen.additionalProperties().get("isJackson"));
+ assertEquals(JavaClientCodegen.SERIALIZATION_LIBRARY_JACKSON, codegen.additionalProperties().get(CodegenConstants.SERIALIZATION_LIBRARY));
+ }
+
+ @Test
+ public void testOkHttpWithJackson3() {
+ final JavaClientCodegen codegen = new JavaClientCodegen();
+ codegen.setLibrary(JavaClientCodegen.OKHTTP);
+ codegen.additionalProperties().put(CodegenConstants.SERIALIZATION_LIBRARY, JavaClientCodegen.SERIALIZATION_LIBRARY_JACKSON);
+ codegen.additionalProperties().put(JavaClientCodegen.USE_JACKSON_3, true);
+ codegen.processOpts();
+
+ assertEquals(JavaClientCodegen.OKHTTP, codegen.getLibrary());
+ assertTrue((Boolean) codegen.additionalProperties().get("isJackson"));
+ assertTrue((Boolean) codegen.additionalProperties().get(JavaClientCodegen.USE_JACKSON_3));
+ }
+
+ @Test
+ public void testOkHttpWithJsonb() {
+ final JavaClientCodegen codegen = new JavaClientCodegen();
+ codegen.setLibrary(JavaClientCodegen.OKHTTP);
+ codegen.additionalProperties().put(CodegenConstants.SERIALIZATION_LIBRARY, JavaClientCodegen.SERIALIZATION_LIBRARY_JSONB);
+ codegen.processOpts();
+
+ assertEquals(codegen.getLibrary(), JavaClientCodegen.OKHTTP);
+ assertTrue((Boolean) codegen.additionalProperties().get("isJsonb"));
+ assertEquals(codegen.additionalProperties().get(CodegenConstants.SERIALIZATION_LIBRARY), JavaClientCodegen.SERIALIZATION_LIBRARY_JSONB);
+ }
+
@Test
public void testInitialConfigValues() throws Exception {
final JavaClientCodegen codegen = new JavaClientCodegen();
@@ -4625,7 +4673,8 @@ public Object[][] jspecifyLibraries() {
{"webclient", true, false},
{"resttemplate", false, true},
{"resttemplate", true, true},
- {"native", false, true}
+ {"native", false, true},
+ {"okhttp", false, true}
};
}
@@ -4685,6 +4734,31 @@ public void testJspecify(String library, boolean useSpringBoot4, boolean hasJspe
}
+ @Test
+ public void testJspecifyOkHttpSingleRequestParameter() throws IOException {
+ final Map files = generateFromContract("src/test/resources/3_0/java/jspecify.yaml", "okhttp",
+ Map.of(USE_JSPECIFY, true,
+ "containerDefaultToNull", true,
+ CodegenConstants.USE_SINGLE_REQUEST_PARAMETER, "true"
+ ),
+ codegenConfigurator ->
+ codegenConfigurator
+ .setValidateSpec(false)
+ .addTypeMapping("OffsetDateTime", "java.time.Instant")
+ .addTypeMapping("BigDecimal", "java.math.BigDecimal"));
+
+ JavaFileAssert.assertThat(files.get("DefaultApi.java"))
+ .fileContains(
+ "import org.jspecify.annotations.Nullable;",
+ "public class APIfooDtParamGetRequest {",
+ "private java.time.@Nullable Instant dtParam;",
+ "private java.time.@Nullable Instant dtQuery;",
+ "private java.time.@Nullable Instant dtCookie;",
+ "public APIfooDtParamGetRequest dtParam(java.time.@Nullable Instant dtParam) {",
+ "private APIfooDtParamGetRequest() {"
+ );
+ }
+
@DataProvider(name = "replaceOneOf")
public Object[][] replaceOneOf() {
return new Object[][]{
@@ -4798,6 +4872,107 @@ public void processOptsConvertsConfiguredSupportUrlQuery() {
.containsEntry(SUPPORT_URL_QUERY, false);
}
+ @Test
+ public void testOkHttpDependencyVersions() throws IOException {
+ final Path output = newTempFolder();
+ final CodegenConfigurator configurator = new CodegenConfigurator()
+ .setGeneratorName(JAVA_GENERATOR)
+ .setLibrary(JavaClientCodegen.OKHTTP)
+ .setInputSpec("src/test/resources/3_0/ping.yaml")
+ .setOutputDir(output.toString().replace("\\", "/"));
+
+ new DefaultGenerator().opts(configurator.toClientOptInput()).generate();
+
+ assertThat(output.resolve("pom.xml")).content()
+ .contains("5.4.0 ")
+ .contains("2.10.1 ");
+
+ assertThat(output.resolve("build.gradle")).content()
+ .contains("okhttp_version = \"5.4.0\"")
+ .contains("implementation 'com.google.code.gson:gson:2.10.1'");
+ }
+
+ @Test
+ public void testOkHttpComposedSchemaAdditionalProperties() throws IOException {
+ final Path output = newTempFolder();
+ final CodegenConfigurator configurator = new CodegenConfigurator()
+ .setGeneratorName(JAVA_GENERATOR)
+ .setLibrary(JavaClientCodegen.OKHTTP)
+ .setInputSpec("src/test/resources/3_0/composed-schemas.yaml")
+ .setOutputDir(output.toString().replace("\\", "/"));
+
+ new DefaultGenerator().opts(configurator.toClientOptInput()).generate();
+
+ // Dog is a composed schema (allOf). Since we enabled supportsAdditionalPropertiesWithComposedSchema,
+ // it should have the additionalProperties field.
+ assertThat(output.resolve("src/main/java/org/openapitools/client/model/Dog.java")).content()
+ .contains("private Map additionalProperties;");
+ }
+
+ @Test
+ public void testOkHttpWithJackson2DependencyVersions() throws IOException {
+ final Path output = newTempFolder();
+ final CodegenConfigurator configurator = new CodegenConfigurator()
+ .setGeneratorName(JAVA_GENERATOR)
+ .setLibrary(JavaClientCodegen.OKHTTP)
+ .addAdditionalProperty(CodegenConstants.SERIALIZATION_LIBRARY, JavaClientCodegen.SERIALIZATION_LIBRARY_JACKSON)
+ .setInputSpec("src/test/resources/3_0/ping.yaml")
+ .setOutputDir(output.toString().replace("\\", "/"));
+
+ new DefaultGenerator().opts(configurator.toClientOptInput()).generate();
+
+ assertThat(output.resolve("pom.xml")).content()
+ .contains("5.4.0 ")
+ .contains("2.17.1 ");
+
+ assertThat(output.resolve("build.gradle")).content()
+ .contains("okhttp_version = \"5.4.0\"")
+ .contains("jackson_version = \"2.17.1\"");
+ }
+
+ @Test
+ public void testOkHttpWithJackson3DependencyVersions() throws IOException {
+ final Path output = newTempFolder();
+ final CodegenConfigurator configurator = new CodegenConfigurator()
+ .setGeneratorName(JAVA_GENERATOR)
+ .setLibrary(JavaClientCodegen.OKHTTP)
+ .addAdditionalProperty(CodegenConstants.SERIALIZATION_LIBRARY, JavaClientCodegen.SERIALIZATION_LIBRARY_JACKSON)
+ .addAdditionalProperty(JavaClientCodegen.USE_JACKSON_3, true)
+ .setInputSpec("src/test/resources/3_0/ping.yaml")
+ .setOutputDir(output.toString().replace("\\", "/"));
+
+ new DefaultGenerator().opts(configurator.toClientOptInput()).generate();
+
+ assertThat(output.resolve("pom.xml")).content()
+ .contains("5.4.0 ")
+ .contains("3.2.1 ");
+
+ assertThat(output.resolve("build.gradle")).content()
+ .contains("okhttp_version = \"5.4.0\"")
+ .contains("jackson_version = \"3.2.1\"");
+ }
+
+ @Test
+ public void testOkHttpWithJsonbDependencyVersions() throws IOException {
+ final Path output = newTempFolder();
+ final CodegenConfigurator configurator = new CodegenConfigurator()
+ .setGeneratorName(JAVA_GENERATOR)
+ .setLibrary(JavaClientCodegen.OKHTTP)
+ .addAdditionalProperty(CodegenConstants.SERIALIZATION_LIBRARY, JavaClientCodegen.SERIALIZATION_LIBRARY_JSONB)
+ .setInputSpec("src/test/resources/3_0/ping.yaml")
+ .setOutputDir(output.toString().replace("\\", "/"));
+
+ new DefaultGenerator().opts(configurator.toClientOptInput()).generate();
+
+ assertThat(output.resolve("pom.xml")).content()
+ .contains("5.4.0 ")
+ .contains("3.0.1 ");
+
+ assertThat(output.resolve("build.gradle")).content()
+ .contains("okhttp_version = \"5.4.0\"")
+ .contains("implementation 'jakarta.json.bind:jakarta.json.bind-api:3.0.1'");
+ }
+
private static JavaClientCodegen newRetrofit2Codegen(Map properties) {
JavaClientCodegen codegen = new JavaClientCodegen();
codegen.setLibrary(JavaClientCodegen.RETROFIT_2);
diff --git a/modules/openapi-generator/src/test/resources/3_0/java/okhttp-jspecify.yaml b/modules/openapi-generator/src/test/resources/3_0/java/okhttp-jspecify.yaml
new file mode 100644
index 000000000000..a110f078d0c4
--- /dev/null
+++ b/modules/openapi-generator/src/test/resources/3_0/java/okhttp-jspecify.yaml
@@ -0,0 +1,88 @@
+openapi: 3.0.0
+info:
+ description: test fully qualified name and jspecify
+ title: jspecify
+ version: 1.0.0
+paths:
+ /foo/{dtParam}:
+ get:
+ parameters:
+ - in: path
+ name: dtParam
+ required: true
+ schema:
+ type: string
+ format: date-time
+ - in: query
+ name: dtQuery
+ schema:
+ type: string
+ format: date-time
+ - in: cookie
+ name: dtCookie
+ schema:
+ type: string
+ format: date-time
+ responses:
+ default:
+ description: response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Foo'
+ /upload:
+ post:
+ requestBody:
+ description: file
+ content:
+ multipart/form-data:
+ schema:
+ type: object
+ properties:
+ file:
+ type: string
+ format: binary
+ responses:
+ default:
+ description: ok
+
+ /file/{id}:
+ get:
+ parameters:
+ - in: path
+ name: id
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: ok
+
+components:
+ schemas:
+ Foo:
+ required:
+ - requiredDt
+ properties:
+ dt:
+ type: string
+ format: date-time
+ binary:
+ type: string
+ format: binary
+ listOfDt:
+ type: array
+ items:
+ type: string
+ format: date-time
+ listMinIntems:
+ type: array
+ minItems: 1
+ items:
+ type: string
+ format: date-time
+ requiredDt:
+ type: string
+ format: date-time
+ number:
+ type: number
diff --git a/samples/client/echo_api/java/okhttp-gson-user-defined-templates/src/main/java/org/openapitools/client/model/Category.java b/samples/client/echo_api/java/okhttp-gson-user-defined-templates/src/main/java/org/openapitools/client/model/Category.java
index bc61756944c8..05e64b83f721 100644
--- a/samples/client/echo_api/java/okhttp-gson-user-defined-templates/src/main/java/org/openapitools/client/model/Category.java
+++ b/samples/client/echo_api/java/okhttp-gson-user-defined-templates/src/main/java/org/openapitools/client/model/Category.java
@@ -100,6 +100,50 @@ public void setName(@javax.annotation.Nullable String name) {
this.name = name;
}
+ /**
+ * A container for additional, undeclared properties.
+ * This is a holder for any undeclared properties as specified with
+ * the 'additionalProperties' keyword in the OAS document.
+ */
+ private Map additionalProperties;
+
+ /**
+ * Set the additional (undeclared) property with the specified name and value.
+ * If the property does not already exist, create it otherwise replace it.
+ *
+ * @param key name of the property
+ * @param value value of the property
+ * @return the Category instance itself
+ */
+ public Category putAdditionalProperty(String key, Object value) {
+ if (this.additionalProperties == null) {
+ this.additionalProperties = new HashMap();
+ }
+ this.additionalProperties.put(key, value);
+ return this;
+ }
+
+ /**
+ * Return the additional (undeclared) property.
+ *
+ * @return a map of objects
+ */
+ public Map getAdditionalProperties() {
+ return additionalProperties;
+ }
+
+ /**
+ * Return the additional (undeclared) property with the specified name.
+ *
+ * @param key name of the property
+ * @return an object
+ */
+ public Object getAdditionalProperty(String key) {
+ if (this.additionalProperties == null) {
+ return null;
+ }
+ return this.additionalProperties.get(key);
+ }
@Override
@@ -112,12 +156,13 @@ public boolean equals(Object o) {
}
Category category = (Category) o;
return Objects.equals(this.id, category.id) &&
- Objects.equals(this.name, category.name);
+ Objects.equals(this.name, category.name)&&
+ Objects.equals(this.additionalProperties, category.additionalProperties);
}
@Override
public int hashCode() {
- return Objects.hash(id, name);
+ return Objects.hash(id, name, additionalProperties);
}
@Override
@@ -126,6 +171,7 @@ public String toString() {
sb.append("class Category {\n");
sb.append(" id: ").append(toIndentedString(id)).append("\n");
sb.append(" name: ").append(toIndentedString(name)).append("\n");
+ sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n");
sb.append("}");
return sb.toString();
}
@@ -162,14 +208,6 @@ public static void validateJsonElement(JsonElement jsonElement) throws IOExcepti
throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "The required field(s) %s in Category is not found in the empty JSON string", Category.openapiRequiredFields.toString()));
}
}
-
- Set> entries = jsonElement.getAsJsonObject().entrySet();
- // check to see if the JSON string contains additional fields
- for (Map.Entry entry : entries) {
- if (!Category.openapiFields.contains(entry.getKey())) {
- throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "The field `%s` in the JSON string is not defined in the `Category` properties. JSON: %s", entry.getKey(), jsonElement.toString()));
- }
- }
JsonObject jsonObj = jsonElement.getAsJsonObject();
if ((jsonObj.get("name") != null && !jsonObj.get("name").isJsonNull()) && !jsonObj.get("name").isJsonPrimitive()) {
throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `name` to be a primitive type in the JSON string but got `%s`", jsonObj.get("name").toString()));
@@ -191,6 +229,28 @@ public TypeAdapter create(Gson gson, TypeToken type) {
@Override
public void write(JsonWriter out, Category value) throws IOException {
JsonObject obj = thisAdapter.toJsonTree(value).getAsJsonObject();
+ obj.remove("additionalProperties");
+ // serialize additional properties
+ if (value.getAdditionalProperties() != null) {
+ for (Map.Entry entry : value.getAdditionalProperties().entrySet()) {
+ if (entry.getValue() instanceof String)
+ obj.addProperty(entry.getKey(), (String) entry.getValue());
+ else if (entry.getValue() instanceof Number)
+ obj.addProperty(entry.getKey(), (Number) entry.getValue());
+ else if (entry.getValue() instanceof Boolean)
+ obj.addProperty(entry.getKey(), (Boolean) entry.getValue());
+ else if (entry.getValue() instanceof Character)
+ obj.addProperty(entry.getKey(), (Character) entry.getValue());
+ else {
+ JsonElement jsonElement = gson.toJsonTree(entry.getValue());
+ if (jsonElement.isJsonArray()) {
+ obj.add(entry.getKey(), jsonElement.getAsJsonArray());
+ } else {
+ obj.add(entry.getKey(), jsonElement.getAsJsonObject());
+ }
+ }
+ }
+ }
elementAdapter.write(out, obj);
}
@@ -198,7 +258,28 @@ public void write(JsonWriter out, Category value) throws IOException {
public Category read(JsonReader in) throws IOException {
JsonElement jsonElement = elementAdapter.read(in);
validateJsonElement(jsonElement);
- return thisAdapter.fromJsonTree(jsonElement);
+ JsonObject jsonObj = jsonElement.getAsJsonObject();
+ // store additional fields in the deserialized instance
+ Category instance = thisAdapter.fromJsonTree(jsonObj);
+ for (Map.Entry