From 4fbc26ee60adf7274c916a927533e545282571c9 Mon Sep 17 00:00:00 2001 From: "api-clients-generation-pipeline[bot]" <54105614+api-clients-generation-pipeline[bot]@users.noreply.github.com> Date: Tue, 23 Mar 2021 15:32:53 +0100 Subject: [PATCH] Move templates in clients (#709) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [java][client][jax-rs] Add a constant for Jackson @JsonProperty (#3560) * Add test cases to cover different collection formats (#3640) * add test cases to cover different collection format * add space params to retrofit 1.x * add space params to retrofit 2.x * rename url to localVarUrl * fix exception in haskell servant * Use javax.annotation.processing.Generated for Java 11 native client (#3637) Before Java 9, the `Generated` annotation was part of JEE and in the `javax.annotation` package. Starting with Java 9, it is now part of the standard SDK, under the new `javax.annotation.processing` package. This change creates a custom Generated annotation template for the native clientlib, since it is guaranteed to be run in Java 11+. * [java-client] set collection to null when not required (#3615) * [java][model] set collection to null when not required * Fix tests * Fix trailing whitespace * generate samples * Restore 'de.thetaphi' plugin in pom.xml * [java-client][jersey2][resteasy] add support for TRACE method (#3653) * [Java][client] make it possible to send explicit nulls for nullable fields (#3474) * [Java][client] make it possible to send explicit nulls for nullable fields * Regenerate samples * [java-client][jersey2][resteasy] add support for OPTIONS method (#3677) * [java-client][jersey2][resteasy] add support for OPTIONS method * Update samples * [java-client][resteasy] support bearer authentication (#3706) * [java-client][resteasy][jersey2][google-api-client][okhttp-json] several fixes to make sent requests more accurate (#3703) * [BUG] Https protocol schema is not handled correctly in java 11 native code #3729 (#3730) * added getter for schema * Two tiny fixes for Java Vertx client (#3683) * two tiny fixes: 1.) ApiClient already defines and configures an objectMapper to not fail on unknown properties, but it is not used when parsing the response. The fix uses the pre-configured object mapper instead of the vertx default one 2.) When an operation has no response (or just ones without content), the accept array passed to ApiClient is emtpy. This makes the null check in ApiClient useless, as it still tries to set a null Accept header, which is refused with an NPE. Amend the check with .length > 0 to catch this case. * update generated client as required by contributor guidelines * [java-client][java-jaxrs-server][jackson] Add @JsonPropertyOrder to models (#3778) * [java-client][rest-assured] add jackson support in addition to gson (#3795) * [java] add jackson-databind-nullable dependency to the gradle.build file (#3793) * Add jackson-databind-nullable * Update samples * Support custom git repository (#3757) * add gitHost param to GeneratorSettings and related * parameterize gitHost in READMEs * parameterize gitHost in go.mod * parameterize gitHost in git_push * update petstore samples * run ./bin/utils/export_docs_generators.sh * run meta-codehen.sh * Revert "run meta-codehen.sh" This reverts commit d6d579f6159186531257cdfdd73b9caf9e9ffeba. * Revert "run ./bin/utils/export_docs_generators.sh" This reverts commit 1b81538198d4319fd1b4e97447303e3cc0e8dc99. * Revert "update petstore samples" This reverts commit f513add88396707f6991ae2e4920359583ec88f1. * run ensure-up-to-date * [Java][okhttp-gson] fix failure to deserialize floats (#3846) * fixed bug where nullApi.java would be generated. Instead, generated DefaultApi.java to match the default path /{pathParam} * fix to bug #3157 * update samples * updated google-api-client version from 1.23.0 to 1.30.2. Bugfix #3625 (#3882) * Fix jackson-databind security issue (#3945) * fix jackson security issue * update groovy petstore sample * Fix issue3635 (#3948) * fixed Feign template * regenerated Feign example * update java feign petstore sample * [java] Don't import oltu when not necessary (#3950) * [java][client] Fix regression in Java XML serialization. Fixes #4014 (#4023) * Fix regression in Java XML serialization. Fixes #4014 * Also move JSON_PROPERTY_* declaration * Fix readonly with isReadOnly (#4102) * fix readonly * update samples * Make Resttemplate thread safe by using the withHttpInfo pattern used by many other generated clients (#4049) * Added new discriminator RawName property to preserve declared discriminator for @JsonTypeInfo annotations (#3320) * Rename property name from propertyRawName to propertyBaseName (#4124) * rename property in codegen discriminator * better code format * [Java] fix jackson-databind-nullable version variable due to Gradle Incompatibility (Template Update) (#4148) * Replaced dashes with underscores in build.gradle files. * Updated mustache template files * Update to jackson-datatype-threetenbp 2.9.10 (#4176) * Update to jackson-datatype-threetenbp 2.9.10 * Update to ThreeTen BP 1.4.0 * Fix import and usage of org.threeten.bp.DateTimeUtils * Refresh samples * [Java] Support cookie-based security schemas in Java clients (#4155) * Adding cookie support and cookie-based AuthKeys to Java clients * Fix indentation * Revert accidental change * Updating samples * Fixing tests and regenerating samples * [java][client] Don't include nullable attributes twice in serialized JSON (#3923) * [java][client] Don't include nullable attributes twice in serialized JSON * Get rid of the extra added whitespace * Regenerate samples * okhttp-gson: fix SSL settings with okhttp3 (#4226) The old code used to work with older okhttp (< 3), but will throw NullPointerExceptions with okhttp3. * Add bearer token authentication documentation to template (#4278) * add bearer token authenticationdocumentation to template * Use correct method * Add the get parameter back * feat(documentation): Adding model documentation (#4308) * Do not HTML escaped the description in the doc (#4321) * html escaped the description in the doc * update python oas3 sample * fix security alerts reported by github (#4344) * Fix Jackson databind security issue (#4370) * fix jackson databind security issue * update groovy sample * fix groovy dep version * [Java]: Client resttemplate and webclient: array parameters of type integer in path badly generated (#4379) * 4375: Client resttemplate and webclient: array parameters of type integer in path badly generated * 4375: Fix samples * 4375: Fix samples * 4375: Fix samples * [Java] Refactor webClient generator to use URI templates to capture correct metrics (#4314) * Fixing URI templating for webclients to support Spring metric collection * Revert accidental change to test * Re-interrupt the thread in the generated code (#4382) * Re-interrupt the thread in the generated code, otherwise the client has to check for the type of the cause of the thrown exception. * update samples * recursive equal on reflection (#4475) * [BUG] [Java] Client resttemplate and webclient. Form Params are badly added when they are lists (#4461) * 4383: Client resttemplate and webclient. Form Params are badly added when they are lists * 4383: Force redeploy * 4383: Fix test * 4383: Fix map * 4383: revert change * 4383: Fix test resttemplate-withXml * [JAVA] Update Gradle in generated Java projects from 2.14.1 to 6.0.1 (#4536) * Update Gradle in generated Java projects from 2.14.1 to 6.0.1 * Upgrade Java 11 native Gradle from 5.5 to 6.0.1 When Java 11 native client library was introduced it was introduced with an overridden version of the Gradle wrapper (5.5 instead of 2.14.1). From looking at that PR, there doesn't appear to be any specific reason for the versions to differ. This removes the only override of the Gradle wrapper so all the Java projects are up to date and shares the same version. * [java][client][restassured] add getAllOperations() (#4631) * [java][client][restassured] add getAllOperations() * Update samples * [#4025] custom java annotations (#4026) * custom java annotations * Error in the reactive client when the path variables are a list (#4687) (#4689) * Error in the reactive client when the path variables are a list (#4687) * Update samples (#4687) * [REQ] Java Microprofile REST Client Template (#4713) * Add a Java Library called microprofile. * Fix formatting * [java] Update jackson_databind_nullable_version to 0.2.1 (#4839) * [java] Update jackson_databind_nullable_version to 0.2.1 * Update samples * FIx typo * [java] Jersey2 and resttemplate do not correctly send defaultCookies (#4821) * Java/Jersey2 sends defaultCookies * Send cookie value instead of [value] (resttemplate) * Improve the javadoc string * [Java] Fix serialized name of discriminator in JSON.mustache (#4672) * Use propertyBaseName instead of propertyName for discriminator * Revert "Use propertyBaseName instead of propertyName for discriminator" This reverts commit 389c5471ba0a71a8ba558c2859e64f08a5186f00. * Use propertyBaseName instead of propertyName for discriminator * fix java feign parameter request name (#4883) * upgrade to JUnit 4.13 (#4899) * [kotlin][client] make Request date converter toJson as default (#4884) * Fix for Issue #2205 Because when we have tags on OpenAPI Specification, there can be more than 1 Feign Beans being generated and the title field is share by all the clients. This makes the code to stop working in runtime. Here is a PR which uses the classVarName instead, which follows the standards and should be enough to solve this issue. For more info please refer to: https://github.com/OpenAPITools/openapi-generator/issues/2205 * fix java feign parameter request name (#4883) * update sprign cloud feign sample * [JAVA][SPRING][2195] added missing getter for enum value (#2346) * [2195] added missing getter for enum value * updated samples * re-generate spring samples * Removed @JsonValue from toString and regenerated samples * re-generate spring samples Co-authored-by: Esteban Gehring * update samples * [kotlin][client] make Request date converter toJson as default * [kotlin][client] update windows scripts * [kotlin][client] update docs * [kotlin][client] update scripts * [kotlin][client] update scripts Co-authored-by: Filipe Manuel Couto Pinheiro Co-authored-by: William Cheng Co-authored-by: Lukáš Vasek Co-authored-by: Esteban Gehring * [java][client] jackson update (#4907) * [java][client] update jackson-databind-version to 2.10.1 * [java][client] update jackson-version to 2.10.1 * Update samples * [google-api-client] add missing generic parameter to fix compile error * Update samples * [Java][jersey2] Use builder pattern for requests (#4666) * Use builder pattern for requests * petstore * Add @throws annotation * regenerate jersey2 test files * Also group bodyParam in builder class * petstore java6 * regenerate java8 * ensure up to date * Escape query params before invoking api (#5023) * Escape query params before invoking api * Update petstore file * Update remaining petstore examples * better code format in java jersey doc (#5031) * Evaluating https issues in CircleCI (on top of CiscoM31-maven-h… (#5034) * replace http with https. Replace http://central.maven.org with https://repo1.maven.org * replace http://www.apache.org/licenses/LICENSE-2.0 with https://www.apache.org/licenses/LICENSE-2.0 * Force HTTPS for mavenCentral gradle DSL Co-authored-by: Sebastien Rosset * [gradle] consistent use of maven url in gradle files (#5045) * wrap maven url with uri function * consistent use of maven url in gradle files * Bump spring-webflux from 5.0.8.RELEASE to 5.1.0.RELEASE in /samples/client/petstore/java/webclient (#5071) * Bump spring-webflux in /samples/client/petstore/java/webclient Bumps [spring-webflux](https://github.com/spring-projects/spring-framework) from 5.0.8.RELEASE to 5.1.0.RELEASE. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v5.0.8.RELEASE...v5.1.0.RELEASE) Signed-off-by: dependabot[bot] * Bump spring-webflux version from 5.0.8 to 5.0.16 ref https://pivotal.io/security/cve-2020-5398 Co-authored-by: Akihito Nakano * [java][client] oneOf support for jackson clients (#5120) * Switch to predominant use of appDescriptionWithNewLines in README.mustache (#5109) Descriptions tend to get lengthy and can include multiple lines. New lines are important to markdown formatting/syntax and can't just be ignored. Resolves https://github.com/OpenAPITools/openapi-generator/issues/3704 * [java-jersey2] Fix empty body when form parameters supplied (#5169) * [Java] update feign form dependency version (#5179) * [Java-Feign-issue 5173] - update feign form dependency version * [Java-Feign-issue 5173] - updated feign versions in sample project * [Java-Feign-issue 5173] - fix OAuth in Feign10 sample * [Java-Feign-issue 5173] - updated OAuth Feign template * update feign samples Co-authored-by: William Cheng * [go-experimental] Add oneOf support (#5150) * [go-experimental] Add oneOf support * Fix docs for the oneOf models * isOneOfInterface => x-is-one-of-interface * Add proper warnings when inline models are used in oneOf choices * Add a convenience method to oneOf implementing structs to cast them as the oneOf interface * Update modules/openapi-generator/src/main/resources/go-experimental/model.mustache Co-Authored-By: Jiri Kuncar * Fix retrieving data from additionalDataMap * Add basic tests Co-authored-by: Jiri Kuncar * [Java][okhttp-gson] Use builder api of OkHttpClient to avoid UnsupportedOperationEx (#5177) * 3432 Use builder api of OkHttpClient to avoid UnsupportedOperationEx The reason for the UnsupportedOperationException was an invalid access to the interceptors list of OkHttpClient. That list is unmodifiable as stated by the JavaDoc. Instead accessing the list directly, the interceptors should always be passed when building the client by the builder api. * 3432 Use builder api of OkHttpClient to avoid UnsupportedOperationEx The reason for the UnsupportedOperationException was an invalid access to the interceptors list of OkHttpClient. That list is unmodifiable as stated by the JavaDoc. Instead accessing the list directly, the interceptors should always be passed when building the client by the builder api. * 3432 Follow-up fix to make samples compile again * 3432 Updated sample implementation for okHttp-Gson-ParcelableModel * [Java] mark Feign 10.x (instead of 9.x) as the default (#5310) * set feign 10x as default, mark 9x as deprecated * update doc * [templates] Update templates vendor ext standards (#5295) * [templates] Update to vendor extension standard keys * Fix missed value in Java template, also implements=>x-implements. Evaluate Haskell Client changes * Fix missing accept/content-type update for vendor extension format * [java] Support templated servers (#4998) * [java] Support templated servers * Deprecate old signature of invokeAPI method * throw ArrayIndexOutOfBoundsException * Update modules/openapi-generator/src/main/resources/Java/ServerConfiguration.mustache * [java] Regenerate samples Co-authored-by: Jim Schubert * Update maven-javadoc-plugin for Java 11 support (#5361) * Resolves `An error has occurred in Javadoc report generation: [ERROR] Exit code: 1 - javadoc: error - The code being documented uses modules but the packages defined in https://docs.oracle.com/javase/8/docs/api/ are in the unnamed module` error that happens when using Java 11 * Resolves `An error has occurred in Javadoc report generation: [ERROR] Exit code: 1 - javadoc: error - The code being documented uses modules but the packages defined in https://docs.oracle.com/javase/8/docs/api/ are in the unnamed module` error that happens when using Java 11 * Fix duplicate configuration entries * Fix okhttp poms * Remove letter that shouldn't be there * Removal of Encoding in the Query-Params in order to prevent double Encoding. (#5255) This way letting WebClient do its Job in encoding the URL. * [Java][WebClient] better code format (#5433) * better code format for java webclient * prefix local varaible with localVar * [java] Support aliasing of API keys (#4966) * [java] Support aliasing of API keys * Rebuild Java Jersey2 sample client * x-lookup to x-auth-id-alias * Regenerated * update jackson dependency to newer version (#5527) * [Java] Fix exception when OAuth2 token URL is a relative URL (#5535) * Add support for case when OAuth2 token URL is a relative URL * Add support for case when OAuth2 token URL is a relative URL * run scripts under bin * [Java] fix runtime exception when there are multiple auth methods (#5530) * fix runtime exception when there are multiple auth methods * Refactor a bit so that it does not cause conflict with relative url token branch * Adding Response Interceptor (#5500) * added Response interceptor for native clients * added Response interceptor for native clients * [Java] Update version of maven-surefire-plugin (#5509) * use more recent version of maven-surefire-plugin * use more recent version of maven-surefire-plugin * higher debug level for troubleshooting ci issue * temporarily increase debug log to help troubleshoot * Use local instance of pet store service for unit test purpose * Add more logging to troubleshoot unit test failures * Add more logging to troubleshoot unit test failures * Add more logging to troubleshoot unit test failures * Add more logging to troubleshoot unit test failures * Add more logging to troubleshoot unit test failures * use random ID for Java unit test instead of fixed id * add code comments and specify URL for java unit test * reenable quiet argument * fix java unit test issues * fix java unit test issues * Revert "fix java unit test issues" This reverts commit e8508416ff0f2aeb568e3f916b013dc967390f74. * fix java unit test issues * Add openapi.yaml file to Java clients (#5765) * Add openapi.yaml file to Java client * Move supporting template file to Java root * Update petstore clients * [Java-client] Add maven-compiler-plugin in pom.xml and enable linter checks by default (#5866) * Add maven-compiler-plugin plugin in Java pom.xml and enable linter checks by default * Add maven-compiler-plugin plugin in Java pom.xml and enable linter checks by default * Update generated build files for REST Assured (#5873) * REST Assured 4.3.0 * Jackson 2.10.3 * Gson 2.8.6, GSON-Fire 1.8.4 * Okio 1.17.5 * Joda-Time 2.10.5 * ThreeTenBP 1.4.3 * Added missing dependencies for Bean Validation * Added missing dependencies for `@Generated` annotation * Refresh REST Assured sample project * [Java][Feign] Bug fix in @Param annotation (#5250) * FIX-5249 fix @Param annotation for Feign-client code generation Use paramName instead of baseName in order to make mapping in @Headers section fit the param-value. * update samples * FIX-5249 fix @Param annotation for Feign-client code generation Use paramName instead of baseName in order to make mapping in @Headers section fit the param-value. Co-authored-by: Christoph Preißner Co-authored-by: William Cheng * [Java] Increase java compiler stack size to handle large files (#5901) * increase java compiler stack size to handle large files * increase java compiler stack size to handle large files * [Java] Discriminator lookup should not be case insensitive by default (#5894) * Add 'discriminatorCaseSensitive' property * Discriminator value lookup should not be case insensitive * fix typo * run scripts * execute ./bin/utils/export_docs_generators.sh * fix discriminator mapping, add code comments * [Java] Fix inclusive max validation (#5908) Co-authored-by: erikmolin * update dependency for java client (#5926) * [Java][Client] Fix Gradle and SBT builds for REST Assured generator (#5990) * Fix Gradle and SBT builds for Java REST Assured generator * Add missing jackson-databind-nullable dependency to SBT build * Update rest-assured sample * Add sample for Java client with REST Assured and Jackson * Add new REST Assured sample as Maven sub-module * Sync master to 5.0.x (#5968) * Change the Model template (#5222) * Add a link to Xero blog post (#5426) * Removal of Encoding in the Query-Params in order to prevent double Encoding. (#5255) This way letting WebClient do its Job in encoding the URL. * update java webclient sample * [kotlin][client] Add Jackson as serialization library (#5236) * [kotlin][client] Add Jackson as serialization library * [kotlin][client] Add kotlin-client-jackson.sh to kotlin-client-all.sh * update kotlin client samples * update doc Co-authored-by: William Cheng * include kotlin jackson in CI tests (#5438) * [Ruby] Add error output (#5428) * Add error output to the log so that we can make sure why the error occurred * Fix forbidden method invocation using default charsets * Update usage.md (#5443) * fix NPE for enum (#5445) * [Java][WebClient] better code format (#5433) * better code format for java webclient * prefix local varaible with localVar * fix issue with online service (#5461) * Support for additionalProperties in the C generator "Client: C" solves #5395 (#5440) * Support for additionalProperties in the C generator. * Support for additionalProperties in the C generator. * [docs] Enable Algolia search (#5472) * Fix #5420 add headers from configuration object (#5422) * Fix #5420 add headers from configuration object * Add baseOptions undefined checking #5420 * Update the samples and replace array to object #5420 * Update sample * [typescript] Clean up modelPropertyNaming across generators (#5427) * [typescript] Clean up modelPropertyNaming across generators Fixes https://github.com/OpenAPITools/openapi-generator/issues/2976 Generators without runtime models conversion use "original" property naming by default. It's still possible to change it via cli options Generators with runtime conversion keep using "camelCase" * Refactoring: use enum instead of string for modelPropertyNaming * Restore the original camelCase for var names, decouple it from property names * Swap toParamName and toVarName logic (looks like I've mistaken them) * Regenerate docs * Remove a no longer used private method * Added support for msvc builds in cpp-qt5-client generator (#5468) * Added support for msvc builds Moved GCC-specific compile flags to non msvc builds, and added equivalent flags for msvc. * CMakeLists condition cleanup * [all] Move feature set setter (#5460) When I originally implemented the feature set code, I added the getter/setter on DefaultCodegen and CodegenConfig as well as on GeneratorMetadata. GeneratorMetadata also includes the library variation features. When I went to add library-specific features, I realized the discrepancy. This removes the public setter from DefaultCodegen/CodegenConfig, and adds a protected modifyFeatureSet which accepts a lambda and hides the builder logic away in the method. This will be a breaking change for anyone who's created a custom generator in 4.2.3, so the impact is very limited. * [Swift5] small improvements to Objc compatibility (#5410) * [swift] make some small improvements * [swift][client] revert model to use allVars * PostProcessModelProperty with allVars * PostProcessModelProperty with vars * [swift] improve objc interoperability * [swift] fix swift4 for CI to pass * [swift] improve objc interoperability * [swift] improve objc interoperability * Swift - try to fix build * [swift] remove pods from git * [scala] [template] scala sttp client (#5429) * scala-sttp-client template * invoker for sttp fixed and tests added * clean up pet api test from redunant comments * docs updated * fix artefact name, model comments and redunant generic * code optimization * cross scala versions 2.11 2.12 2.13 * date serializers extracted and joda enabled as default * basic and bearer authorization added, apikey in query supported * [Ruby] Fix obsolete configuration of Rubocop and Rubocop's warns (#5417) (#5474) * fix obsolute configuration in generated .rubocop.yml * fix style of `expect` with block in generated ruby client's test code * update sample of ruby client * [scala] strip model class name for all scala generators (#5439) * stripped parameter enabled for all scala based generators * scala samples updated * docs generators updated * fix scalatra. regenerated by openapi3 script. manually removed enum default value from scalatra example due bug in schema extraction * [Scala][sttp] various improvements (#5475) * various improvements to scala sttp * update ScalaSttpClientCodegen.java * add windows batch file * test scala sttp in jdk8 * fix tempalte directory * Use the dataType if the baseType is not set (#5372) * Use the dataType if the baseType is not set * add tests for passing enum as parameter * updated requirements file in samples * Update spec to explicitly name objects and prevent `inline_object` * use the correct scripts to generate samples (`bin/openapi3/python-flask*`) * [python] Adds python oneOf/anyOf models + tests (#5341) * Adds oneOf + anyOf schemas, models and tests to python-experimental * Adds setUpClass and tearDownClass * Removes newline in method_init_shared.mustache * Regenerated v3 spec sample for python-experimental * Fxes test for discard_unknown_keys * Moves new models into existing spec, regen python-exp and go-exp * Also fix python-exp windows file * fix CVE-2020-8130 (#5483) * [go] Add Ptr method to const enum values (#5257) * fix rubocop warns in Ruby client's custom spec (#5488) * [C-libcurl] The name in API parameter should not be escaped even though it includes a C key word. (#5487) * [go-experimental] Support aliasing of API keys (#4940) * [go-experimental] Support aliasing of API keys * Use {{.}} inside condition * Use name instead of keyParamName for lookup * x-lookup to x-auth-id-alias * [java] Support aliasing of API keys (#4966) * [java] Support aliasing of API keys * Rebuild Java Jersey2 sample client * x-lookup to x-auth-id-alias * Regenerated * [cli][gradle] Validate now uses parseOptions w/setResolve (#5471) * [cli] Validate now uses parseOptions w/setResolve The validate command now uses ParseOptions#setResolve(true) to match how we parse in CodegenConfigurator and online's Generate. Without this option, the OpenAPI 3 parser skips the "resolve" block, which made lead to validations in the command not matching validations during generation. * [gradle] Validate now uses parseOptions w/setResolve The Graldle validate command now uses ParseOptions#setResolve(true) to match how we parse in CodegenConfigurator and online's Generate. Without this option, the OpenAPI 3 parser skips the "resolve" block, which made lead to validations in the command not matching validations during generation. * [kotlin]Fix ktor doesn't generate nullable types (#5258) * If not required, need `? = null` * run ./bin/kotlin-server-petstore.sh * Added `?` when value is `required` and `isNullable` * Rerun ./bin/kotlin-server-petstore.sh. But No differences * [C++] Add an option to allow having lowercase variables in models, Pistache: allow using reservedWords in models (#5434) * [C++][Pistache] Use reserved words to replace incorrect names discard old decision to truncate reservedWords * [C++][Pistache] Update struct model to use name instead of baseName * [C++][Pistache] Update Petstore sample * [C++] Add option to have lowercase variables * [C++] Update generated docs * [BUG] [JAVA | Spring] Cookie in parameter is not correctly generated (#5393) * Cookie in parameter is not correctly generated * gh-5386: Fix cookie parameter in * gh-5386: Fix cookie parameter in * gh-5386: Update test file * gh-5386: Fix cookie parameter in * gh-5386: Fix cookie parameter in * gh-5386: Regenerate samples * gh-5386: Fix test * Added Spring CookieValue tests Co-authored-by: Gonzalo * Add missing `@Generated` annotation. (#5384) The annotation is present on other generated files when using jaxrs-spec, but it missing on model classes. * [scala] [template] scala model property style (#5486) * Model property naming style generic for scala * scala templates based on abstractScala regererated * docs generators updated * property format tests * add Agoda as the user (#5494) * Hide timestamp in Scala Play server samples (#5495) * hide timestamp in scala play server output * add chameleon82 to scala tech committee * Add a link to tech blog tech.medpeer.co.jp (#5498) * Add links to blog posts about OpenAPI Generator (#5508) * Typescript array alias array (#4981) * Add failing tests for typescript type declaration * Refactor array and map child type string fallback * Add unaliasSchema to typescript getTypeDeclaration * TypeScriptRxjs: Use Blob as file type declaration This was inadvertantly changed in https://github.com/OpenAPITools/openapi-generator/pull/5266 * [core] Sanitize/underscore/camelize cache expiry (#5484) The helper methods for sanitize/underscore/camelize were recently updated to cache values in static maps. This would lead to a memory leak in hosted environments as the maps had no cleanup/expiry. This moves those cached entries to Caffeine caches with expiry based on last access to allow the edge-case performance improvement gains on very large documents, without the memory leak in hosted or embedded environments. * Update README.md * Add a link to the conference paper (#5510) * Add a link to the conference paper * fix author list * [Slim4] Add Data Mocker middleware (#4978) * [Slim4] Store response schemas * [Slim4] Add Data Mocker middleware * [Slim4] Enhance Slim router * [Slim4] Enhance config * [Slim4] Fix data format key in object mocking * [Slim4] Add tests for Data Mocker middleware * [Slim4] Add Mock feature documentation * [Slim4] Refresh samples * [Java][Spring][Spring-Cloud] Fix #5144 - Use conditional package declaration to avoid unnecessary dependencies (#5145) * FIX: Use conditional package declaration to avoid unnecessary dependencies * DEV: Adjusted sample ClientConfiguration.java for async spring-cloud * fix(php): no need to serialize collections, Guzzle does that, fix #2292 (#3984) * fix(php): only serialize collections if !explode, Guzzle handles the rest, fix #2292 * fix(php): update petstore samples Co-authored-by: Mahdi Dibaiee * [php] replace $collectionFormat with $style (#5517) * php - remove $collectionFormat * update php openapi3 petstore sample * [BUG][scala][template] scala generate java.math.BigDecimal instead of scala type (#5514) * [BUG] scala generate java.math.BigDecimal instead of scala type * update docs/generators * [PHP] complete support for form style (#5519) * [BUG][PHP] Parameter property style not fully implemented (related to comment on PR #3984) * [AUTOGENERATED][PHP] Sample Files * update jackson dependency to newer version (#5527) * Fix Swift4 CI tests (#5540) * comment out swift 4 order tests * comment out store tests * Test Dart petstore client in CircleCI (#5544) * test dart2 in circle ci (jdk7) * fix tests * update package * fix dart installation * Add serialization of ModelComposed (#5551) * Fixes kwargs typos, removes E501s (#5552) * Update generic model to support nullable properties (#5568) * [DOC] Add link to integration test wiki in CONTRIBUTING.md (#5570) * Add link to integration test wiki * Add link to integration test wiki * [Kotlin][client] fix file upload (#5548) * [kotlin] fix file upload * [kotlin] fix file upload * [kotlin] fix file upload * [kotlin][client] fix jackson integration * [kotlin] fix file upload * [kotlin] fix file upload * update doc * [Java] Fix exception when OAuth2 token URL is a relative URL (#5535) * Add support for case when OAuth2 token URL is a relative URL * Add support for case when OAuth2 token URL is a relative URL * run scripts under bin * [Java] fix runtime exception when there are multiple auth methods (#5530) * fix runtime exception when there are multiple auth methods * Refactor a bit so that it does not cause conflict with relative url token branch * [markdown] Fix broken links when generating markdown (#5569) * [markdown] Fix broken links when generating markdown The `api.mustache` file generates links to the markdown model files. These links were previously brokeen. Additionally, the defaultPackage for markdown is "/Models", so this looked pretty in the heading for model files. So this prefix has been stripped from the header in `model.mustache`. * Re-generate Petstore samples for markdown * typescript-angular: fix zone-js version for angular 8 (#5585) * Add a link to the slide (#5590) * [Swift] fix URLSession file upload (#5546) * [swift5] - fix URLSession file upload * [swift5] - fix URLSession file upload * [swift5] fix file upload * [swift5] - fix URLSession file upload * [swift] add unit tests for file upload * [swift] update samples copyright * [swift] add option for API prefix (#5567) * [swift] add option for API prefix * [swift] update docs * [haskell-http-client] update stack; exclude problem time versions (#5589) * [go-experimental] Do not generate HTTP signature unit test for every generated SDK (#5588) * Do not generate HTTP signature unit test for every generated SDK * Add golang 1.14 to CI environment * fix unit test issues * remove script commands that were commented out * add support for ed25519 private keys * PR to solve 2 open issues on enums: #5091 and #4293 (#5477) * PR to solve 2 open issues on enums: Issue 5091 needs to generate enums also when the enum is directly in a param to a API call, instead than in a model. I did that by copying and adapting enum code from *model* to *api* Issue 4293 needs to decorate enums, for when enum names or enum values are repeated over the yaml definition. * PR to solve 2 open issues on enums: Issue 5091 needs to generate enums also when the enum is directly in a param to a API call, instead than in a model. I did that by copying and adapting enum code from *model* to *api* Issue 4293 needs to decorate enums, for when enum names or enum values are repeated over the yaml definition. * Enums decorated: with {{projectName}}_{{classVarName}}_{{enumName}}_ in the models, with {{projectName}}_{{classVarName}}_{{enumName}}_ in the operations. * Changes to the c client: - Removed white space. - Removed ToJSON and FromJSON function for the enums, since they are not used - Sanitized project name in the .java file. For example, this solves a problem with the issue #2338, where the yaml file had title: "Skycoin REST API." * Changes to the c client: - Removed white space. - Removed ToJSON and FromJSON function for the enums, since they are not used - Sanitized project name in the .java file. For example, this solves a problem with the issue #2338, where the yaml file had title: "Skycoin REST API." * Adds parseFlattenSpec (#5526) * Adds parseFlattenSpec, updates tests and helper functions * Adds parseSPec invocation inside parseFlattenSpec * Scala-Akka: Add missing body to PATCH requests (#5605) * NodeJS - Adds missing keyword (#5606) * [jaxrs-cxf-cdi] Support PATCH httpMethod (#5574) Update the required CXF version to 3.1.2 since PATCH support appeared with this version. Add the cxf PATCH annotation to the imports so that the generated code when defining a PATCH api compiles. * fix default value for abstract scala and scalatra server impl (#5578) * [Java] Generated API class has wrong dataType and does not compile Issue (#5331) * add unit test assertion * add check for composed schema * add support for x-allOf-name * change x-allOf-name to x-all-of-name * Add more troubleshooting information * Add more troubleshooting information * Add more troubleshooting information * Add more troubleshooting information * [swift5] stop hiding network error (#5603) * [swift5] stop hiding network error * [swift5] stop hiding network error * [scala][templates] java 8 dates support (#5291) * [scala][akka-http-client] java8 dates support * scala-akka readme doc updated * DateSerializers renamed * rename serializers * move date-library option to abstractScala * generators docs updated * enum defined for date libraries * Backport to scala-http-client * fix scala-akka-client date serializers * fix typo in docs * switch scala templates to java8 (jsr-310) date library by default * update scala samples with java8 date library * update scala generators docs with java8 default date library * fix scala-play-server generator cli options as only java8 dateLibrary supported * fix scalaz DateTimeCodecs template to support java8 * scalaz ci test againt java7 removed as it generate scala 2.11.8 client which is java8 based * update doc * Adding Response Interceptor (#5500) * added Response interceptor for native clients * added Response interceptor for native clients * [k6] Add blog post about using the k6 generator (#5608) * [Kotlin] Remove kotlin-reflect dependency when not needed (#5502) * Remove kotlin-reflect dependency when using CodeGen * Update Kotlin tests * Regenerated unit test samples * Remove newline in generated build.gradle files * [typescript-fetch] add interfaces, withInterfaces (#5612) * typescript-fetch: interfaces, first draft * fix name in description * [scala] Regenerate akka sample (#5622) * scala-version 2.11.12 (#5618) * micheleISEP->michelealbano (#5625) * [Powershell] refactor the client generator (#5629) * add api client * add local variables * add configuration * add header/query/form parameter support * add partial header * add auth, fix parameters type * fix accept, content type * url query string * fix path, header * remove dep on C# client * fix method naming with package name * fix object * convert result from json * better response handling * remove tostring method * fix model doc * fix default module * generate api test files * better api, model tests * fix add pet * add appveyor * fix accept, content type * add petstore tests * fix form parameters * test delete * better file handling (upload) * better code sample * add package version, better doc * delete unused files * fix header parameters * clean up api client * update samples * support query parameter * better method and parameter naming * minor formatting change * better doc, fix cookie parameter * better doc * add api prefix support * better api nam prefix option * fix configuration * throw errors for required parameter * fix authentication * add try catch block to sample code * rename model * use debug, clean up comment * revise code * move bin script * update doc * add new file * better map support * [PowerShell] minor improvements and bug fixes (#5635) * add output type, minor format fix * minor test improvement * Port client updates to server (#5634) * Revert "scala-version 2.11.12 (#5618)" This reverts commit 6b984a926a0f99120a4ad80cef73bee19f8614cd. * update release date * Handle negative response from the server (#5649) * Fix integration tests (Travis, CircleCI) (#5672) * fix php tests * fix scala tests * update ts angular v6 rest * fix user create test * fix spring cloud test * comment out user delete * fix angular v7 tests * fix user test * fix tests * fix go exp tests * commented out delete user tests * comment out delete user tests in go openapi 3 * fix clojure tests * [PowerShell] Fixes typo (#5648) * Solving issue #5623 and supporting bools for C client label:"Client: C" (#5624) * Removed stray "printf"s in modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CLibcurlClientCodegen.java * Support for booleans in C client * Update README.md * Change to C API mustache files to solve issue #5623 * Debugging of C's modle-body.mustache, as suggested by ityuhui * Final changes suggested by ityuhui * [PowerShell] Fix map type (#5638) * fix map type * remove output type, fix appveyor * test macos * comment out failing scala test * fix typo: configuration * Revert "comment out failing scala test" This reverts commit 1dcf84ffcbb7ab520938ae7c75d60a8329f71478. * [powershell-experimental] Protects against stackoverflow when OAS spec has circular references (#5646) * protects against stackoverflow when OAS spec has circular references * protects against stackoverflow when OAS spec has circular references * Adds configuration option to skip certificate check. Fixes a typo. Fixes an issue which was restricting from cookie to get consumed (#5657) * [k6] bugfixes to improve the output script (#5614) * [k6] Skip appDescription escaping * [k6] Fix variable identifier in output * [k6] Fix bug with reserved words handling * [C][Client] Check the pointer before deleting operation to avoid core dump label:"Client C" (#5626) * [C-libcurl] Check the pointer before deleting operation to avoid core dump * [C-libcurl] Check the pointer before deleting operation, update sample * [kotlin][client] Add Jackson to interface properties and remove extra line feed (#5459) * [kotlin][client] Ensure Jackson annotations are consistent with interface vars * [kotlin][client] Rebuild samples * [kotlin][client] Some kotlin client enhancements - Don't use JsonFormat for Date objects, this should be controlled via a custom serializer/deserializer or a turning on and off serialization features of Jackson. I've updated the jacksonObjectMapper config to write the dates as strings, which I think was intended in the original commit. https://fasterxml.github.io/jackson-databind/javadoc/2.6/com/fasterxml/jackson/databind/SerializationFeature.html#WRITE_DATES_AS_TIMESTAMPS https://fasterxml.github.io/jackson-databind/javadoc/2.6/com/fasterxml/jackson/databind/cfg/MapperConfig.html#getDateFormat-- - Dont' use @JsonFormat(shape = JsonFormat.Shape.OBJECT) for enums. This causes Enums to be formatted as objects with an internal "value" field. In reality, OpenAPI enums are just strings without properties and should be treated as a string. https://www.baeldung.com/jackson-serialize-enums#2-enum-as-json-object - Add's Kotlin use site annotation @get: to JsonProperty for parent interface properties. Otherwise Kotlin will warn: "This annotation is not applicable to target 'member property without backing field or delegate'" - Add's JsonTypeInfo annotations to interfaces for inheritance. This was copied verbatim from the kotlin-spring generator. https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/resources/kotlin-spring/typeInfoAnnotation.mustache * [kotlin][client] Rebuild kotlin samples * Remove scala version in parent pom (#5647) * [asciidoc] Allow the inclusion of additional documentation to t… (#5260) * [asccidoc] Allow the inclusion of additional documentation to the asccidoc generated Resolves #5228 * [jaxrs-reasteasy-eap] Fix invalid Bean Validation annotations for Longs (#5659) * fix issue #5658 * update samples * [PowerShell] Test powershell petstore client in Appveyor (#5674) * remove scala version in parent pom * test ps petstore in appveyor * fix command * build and import * fix import module * fix import * skip module import * run multiple commands * move to test script * test ps exit * fix exit * check last status code * clean tests * exit last code * add import * change dir * skip build failure * fix check * trigger build failure * fail fast * restore c# test * new line comment * add powershell exp to ensure up to date script * [PowerShell][Experimental] Better docstring (#5688) * add docstring to powershell module * add doc string * Nodejs express js packages update (#5675) * Updated to new nodejs packages, depending heavily on express-openapi-validator. Requires quite a change in code. Updated the business-logic in the controllers/Controller.js file. Logger now records also timestamp of events. Files are uploaded according to definition in config.js file * Removed commented-out code; Changed openApi document extensions to suit new express-openapi-validator definition; multipart and file uploading is supported now; Automatic response returns the values the were sent in the request * fixed README documentation, fixed a mistage in package.json/mustache * added generated files that were created when running the ./bin/test file * [go-experimental] Fix nullable support (#5414) * Fix nullable support in go-experimental client * Fix support for models with parents and container fields * Make sure that oneOf interfaces serialize properly even if they're required (non-pointers) on other models * Spaces => tabs * Regenerate samples * Make some methods of nullables pointer-receivers, add tests * Improve the Get/Set logic to make usage more convenient * Address review * [kotlin][client] make base path globally configurable (#5450) * [kotlin][client] make base path configurable * [kotlin][client] update pet project * [kotlin][client] set default base path * [kotlin][client] set default base path * [kotlin][client] set default base path * Add michelealbano to C technical committee (#5692) * [Go][Experimental] Rename extensions from x-basetype to x-go-base-type (#5691) * rename go vendor extension * update go exp petstore samples oas3 * comment out powershell petstore in uptodate script * remove processing of http_signature_test.mustache (#5696) * Fix generation of oneOf interfaces for oneOf usage in properties (#5400) * Fix generation of oneOf interfaces for oneOf usage in properties * Only generate oneOf interface models when oneOf is defined * use basic parsing (#5702) * [python/asyncio] explicitly close client session via async context manager (#5621) * [gradle] Include engine option for handlebars generation (#5686) * [codegen][Go] Fix compilation error of generated go code when schema is free form object (#5391) * Fix code generation for free-form objects in go-experimental * Execute scripts in bin directory * Add more use cases for open-ended types * Add more use cases for open-ended types * Add more use cases for open-ended types * add code comments * Better name for test properties * handle scenario when type is arbitrary * handle interface{} scenario * handle interface{} scenario * add helper function isAnyType * isAnyType function * implementation of isAnyType function * fix javadoc issue * handle interface{} scenario * use equals comparison instead of == * merge from master * Add code documentation * add code comments, remove unused min/max attribute, fix equals method * Handle 'anytype' use case * add code comments * override postProcessModelProperty to set vendor extension * Use vendorExtensions.x-golang-is-container * fix compilation error of generated code * fix compilation error of generated code * fix compilation error of generated code * [Java] Update version of maven-surefire-plugin (#5509) * use more recent version of maven-surefire-plugin * use more recent version of maven-surefire-plugin * higher debug level for troubleshooting ci issue * temporarily increase debug log to help troubleshoot * Use local instance of pet store service for unit test purpose * Add more logging to troubleshoot unit test failures * Add more logging to troubleshoot unit test failures * Add more logging to troubleshoot unit test failures * Add more logging to troubleshoot unit test failures * Add more logging to troubleshoot unit test failures * use random ID for Java unit test instead of fixed id * add code comments and specify URL for java unit test * reenable quiet argument * fix java unit test issues * fix java unit test issues * Revert "fix java unit test issues" This reverts commit e8508416ff0f2aeb568e3f916b013dc967390f74. * fix java unit test issues * Generator for JavaScript/Apollo Client (#5645) Co-authored-by: William Cheng * Add yutaka0m to Kotlin Technical Committee (#5716) * Add Scala client scripts to ensure-uptodate process (#5712) * add scala client to ensure-upto-date * new scala-akka petstore oas3 folder * regenerate scala akka oas2 petstore * remove script * Minor improvments to JS apollo generator (#5714) * minor improvments to js apollo generator * comment out apollo * [Rust Server] Handle text/xml correctly (#5660) * [Rust Server] Handle text/xml correctly Treat application/xml the same as text/xml as per RFC 7303 * [Rust Server] Add test for text/xml * Update samples * 4.3.0 release (#5721) * update samples (#5722) * 5211 - Use allVars instead of vars for Kotlin client (#5396) * [C++] [Qt5] fixed cpp-client-qt5 HttpRequestWorker requests crashing on timeout... (#5651) * - fixed cpp-client-qt5 HttpRequestWorker requests crashing on timeout when they have actually NOT timed out (were calling back into a deleted struct). * #minor fixes after review * Regenerate changed files Co-authored-by: valentin Bisson Co-authored-by: etherealjoy * Fix SSL setting in checkout script (#5725) * fix ssl setting in checkout script * add check for sbt-openapi-generator * [C] fix decode funtion (#5642) * fix function names and add parameter to return decoded bytes length from base64decode function * format base64decode function to avoid unnecessary malloc and fix wrong length assigning * update the pointer assigning for some reason var++ / *var++ cannot be done on int *var, hence making a local variable which is incremented and at the end it is assigned to the pointer. * Update bump.sh to go SNAPSHOT to version (#5727) * Fix CI failures (#5734) * update ci to use petstore 1.0.4 * comment out test * comment out test * comment out update user test * comment out more tests * use latest petstore * comment out updatePetWithForm * comment out update pet test * fix file path in release_version_update_docs (#5724) * better appveyor test (#5739) * better readme, type mapping, new option (#5740) * Remove warning for unused camel case vendor extension for Qt5 client and server (#5731) * [PS][Experimental] Add multiple server support (#5741) * code comment * add get host setting * add multiple server support * add default headers support (#5746) * [C][Client] Support SSL client authentication for the c client (#5719) * [C][Client] Support SSL client authentication * [C][Client] Support SSL client authentication, update sample * [kotlin] Fix #5247 incorrect enum parameter type for arrays (#5435) * [Erlang-Server] security definition context changes don't propagate to handler (#5751) * Map Merge Context & Params handler requires context and params to be merged before returned to user defined request_handler. * post build & shell script * Delete VERSION * [PS][PowerShell] fix passthru, use switch instead of bool (#5768) * fix passthru, use switch * remove line * comment out kotlin vertx server test (#5767) * add support for common verbs (#5771) * fix request.on_complete message when tempfile is nil (#5745) * fix request.on_complete message when tempfile is nil * update faraday client sample * add openapi3 client samples * use prepare instead of new (#5773) * use Initialize instead of prepare (#5777) * add map example (#5778) * [PS][Experimental] Better common verb handling (#5783) * better common verb handling * better debugging * add option to customize common verb * [cli][docker] Better expose version/sha information of builds (#5736) * [cli] Some CLI improvements… * Introduce --version * Introduce --help * Add --sha to version command for short SHA display * Output Version and SHA details * In new --version output, display repo and doc site Additional cleanup to suppress warnings and code quality. * [docker] Adds labels for metadata This adds image labels to store metadata on the online and cli docker images, using standard labels: * org.opencontainers.image.created * org.opencontainers.image.revision * org.opencontainers.image.title * org.opencontainers.image.version These can be inspected via 'docker inspect IMAGE_NAME' and may be useful in tooling/automation or bug reports submitted by users. For more details on these labels, see: https://github.com/opencontainers/image-spec/blob/master/annotations.md * Include version --full for equiv to --version * [cli] Add --global-property for -D replacement (#5687) -D option has been deprecated as it was previously used to: * Pass "system properties" * Pass additional properties This was confusing because we already have --additional-properties and because Java System Properties are passed as -D before program arguments. Confusion around the -D option had existed for some time, but when we introduced the thread-safe GlobalSettings to avoid overwriting Java System Properties, we created a hard break from Java System Properties in the generator. This also disconnected the previous "system properties" from accepting additional properties. Once these newly deprecated methods are removed, we will have a clear separation of concerns between: * Java System Properties * Global generator properties (used as workflow context) * Additional properties (used as generator options) This commit marks multiple places for cleanup in 5.0. These will be breaking changes, and lower effort to break in 5.0 with deprecation warnings now rather than adding sibling properties throughout the code and potentially introducing logic errors. * [dart-dio] Fixes --model-name-suffix having no effect (#5669) Fixes #5409 * [go-experimental][go][client] Remove unreachable code in go client API methods (#5611) * [go-experimental][go][client] Remove unreachable code in go client API methods * Properly regenerate all samples * please add openVALIDATION Project to readme (#5534) * added openVALIDATION Project to readme * Update README.md Co-Authored-By: Akihito Nakano Co-authored-by: Akihito Nakano * [Csharp-client] Complex form parameters are not serialized as application/json (#5787) * [csharp-client] Complex form parameters are now correctly serialized as json. Reference: http://spec.openapis.org/oas/v3.0.3#special-considerations-for-multipart-content * Updated bin/windows csharp sample generation scripts to point to the correct directories * Updated csharp samples Co-authored-by: Olivier Leonard * fix scala-akka java8 serializers (#5742) * fix scala-akka java8 serializers * regenerate samples for akka-http * [typescript-axios][client] Unnecessary imports occurs when using withSeparateModelsAndApi (#5797) * add ts-ignore * add petstore sample * use write verbose in auth, better api doc (#5804) * [PS][Experimental] add withHttpInfo support, fix "null" return (#5811) * add with http support * use full name in tests * using full name in test * skip type check * [PS][Experimental] Add tests for array of object in response (#5814) * debugging array response * fix find pet tests * better tests to ignore order * [codegen] Use once(LOGGER) to reduce amount of identical warning messages (#5808) * Warn once instead of many times when the log statement does not have contextual information * Warn once instead of many times when the log statement does not have contextual information * make name cache configurabl (#5775) * [codegen] Cachesize config seconds (#5816) * make name cache configurable * Address review comments * [Python-experimental] Documentation enhancement for oneOf schema and minor err msg improvement (#5791) * Add documentation to generated code * Improve error message * Improve documentation * Improve documentation * Improve documentation * Improve documentation * Improve documentation * Improve documentation * Run sample scripts * Address review comments * Address review comments * Fix problem in python error message * rename hostsetting, validate base url (#5821) * fix array return (#5822) * Scala akka-http server (#5758) * Scala akka-http server base implementation * [scala-akka-http-server] petStore samples * Improved the formatting of generated files * Updated scala-akka-http server samples * [scala-akka-http-server] the groupId, artifactId and artifactVersion default value are used as intended. * Fixed the default operation not being correctly generated on parameterless operations * Added build.sbt.mustache supporting file * Updated scala-akka-http server samples * ScalaAkkaHttpServer: Fixed a String.format call to use Locale.ROOT for locale * [scala-akka-http-server] Fixed defaultValue being escaped during generation * Added scala-akka-http.md * Replaced all "⇒" character with "=>" to retain compatibility with scala 2.13 * [scala-akka-http] Added a config option akkaHttpVersion It's set in the generated build.sbt. * Updated scala-akka-http server samples * [scala-akka-http] More accurate akkaHttpVersion parsing * Updated scala-akka-http.md * [scala-akka-http] Changed the akka-http version check to fix the generation of StringDirectives * Updated scala-akka-http samples * updated scala-akka-http.md Co-authored-by: Olivier Leonard * Minor improvements to scala akka server (#5823) * minor improvements to scala akka server * add samples * update doc * Update swagger parser to 2.0.19 (#5413) * update swagger parser to 2.0.18 * fix online server exception * Revert "fix online server exception" This reverts commit fe3cb5221f362c00b176fa81411eaf368f0e446d. * update parser to 2.0.19 * [jaxrs-cxf-cdi] fix allOf equals and hashCode (#5756) When generating model that use allOf, the equals and hashCode methods must take the parent class into account. * [BUG] [KOTLIN] Fix default value generation for Kotlin Strings (#5776) * fix default value generation for kotlin * add updated pet templates * Revert "add updated pet templates" This reverts commit 7e8168ad * regen pet store projects code * tests for models for C-libcurl generator (#5699) * First try to generate unit tests for the models of the C-libcurl client. Models into models are not supported yet. * Added unit tests for the modules of the C-libcurl client to the git repository. * Support for objects having other objects as properties, for the C-libcurl client generator * Proper formatting of generated code * use allVars to cover all properties (#5835) * support enum in parameters (#5838) * [C++] [Qt5] [Client] fixed cpp-client-qt5 HttpRequestWorker contentCompression variables initialization (#5834) When contentCompression is not enabled, the variables isRequestCompressionEnabled and isResponseCompressionEnabled in HttpRequestWorker are not being initialized. Without initialization the compress function could be called and the request content could be an empty QByteArray instead of original request body. * minor fix to http basic auth (#5839) * Scala akka http server - normalization of some vendor extensions (#5829) * [scala-akka-http-server] Normalized vendor extension "paths" to "x-paths" * [scala-akka-http-server] Normalized vendor extension "hasDefaultValue", "isDefault", "specificMarshallers", "fileParams", "nonFileParams" Co-authored-by: Olivier Leonard * Add Bouill to the Scala technical committee (#5843) * C client generator improvements to support petstore. Solves #5836 (#5837) * C client generator improvement to support: openapi-generator/modules/openapi-generator/src/test/resources/3_0/petstore.yaml * Improvements to the C client generator: - moved base64* from apiClient.c to binary.h/binary.c - changed CR/LF to LF in binary.h/binary.c * C client generator: better support for base64encode / base64decode * Add openapi.yaml file to Java clients (#5765) * Add openapi.yaml file to Java client * Move supporting template file to Java root * Update petstore clients * [codegen] Fix 'super.HashCode' for oneOf and allOf Implementations (retry) (#5830) * Added hasVars after completion of all model post-processing (#5587) * Post ensure-up-to-date * Update to check the size of vars and not assume non-null * update mysql samples * Add default case to handle response code (#5825) * add default case to handle response code * fix default response code * add test for isDefault * fix user id in scala tc * Fix for Issue #4840 [BUG][JAVA][spring-mvc] Generated Code for Map of Maps Return Type does not compile (#5240) * add parent for allOf only (#5851) * Add pythonSrcRoot option to python servers (aiohttp/flask/blueplanet) to support src/ layout projects [and reenable/fix all python server tests] (#5423) * python server: Add pythonSrcRoot option This will allow the python project to be in a subdirectory (as specified in pythonSrcRoot). That could mean following the src layout with sources under src/ or lib/. Multi-language projects might use a sub directory like python/, or whatever makes sense for the project. By default, the pythonSrcRoot is "", meaning the existing behavior is the default. * python server: update template files to support pythonSrcRoot * python server: update docs to add pythonSrcRoot option * python server: add pythonSrcRoot sample script * python server: build sample srclayout project * [Python] copy test files preserving history * [Python] Make a conflict to preserve file copy history * [Python] customize pom.xml for src layout tests * [Python] add python-aiohttp-srclayout tests * [Python] Fix server tests by updating requirements Reverts the PR that disabled python2 server tests: https://github.com/OpenAPITools/openapi-generator/pull/4949 Reverts commits that disabled python3 server tests: 9adfedbfbb45c7059e64b3d9a285710bded4fb62 17ee990baaa80585242c7a07d64e2be4888fcfd0 Issue about the python 3 tests: https://github.com/OpenAPITools/openapi-generator/issues/5235 I couldn't find an issue about the python2 tests being disabled. I'm guessing build errors like the following were the trigger: https://travis-ci.org/github/OpenAPITools/openapi-generator/builds/634238181 Let's see what breaks! * [Python] Copy setup.py to python-aiohttp * [Python] Save history while copying setup.py to python-aiohttp * [Python] Add aiohttp server setup.py * [Python] Fix python server tests with src layout * [Python] bump Flask-Testing version * [Python] Pin pyyaml for py2.7 flask server * [Python] simplify flask server requirements * consolidate server tests * [Python] rebuild python server samples * [Python] Fix python server requirements for older pythons Documented minimum python version for our aiohttp server is 3.5. Documented minimum python version for our flask server is 3.4. Connexion 2.3 is the last version to support python 3.4 and 3.5, so fix the version pinning to correctly select <=2.3 for these EOL python versions. Newer pythons should get the latest if possible as there many relevant bug fixes. Werkzeug also needs to be pinned for these old versions in the aiohttp server just like for the flask server. 3.4 and 3.5 are EOL. We really should increase the minimum supported version, but that is for another PR to do. * stop error globally (#5858) * [PS][Experimental] Add validations to model (#5842) * add validations to model * better error message * improve validation * Updates to allow the setting of the dateTime format string (#5763) * [PS] Select Content-Type in the response (#5872) * better return type handling * update tempalte * better documentation * fix greater than * various enhancement to ps exp generator (#5875) * [C#] dependency upgrade (#5870) * Updating packages version (#5313) * Add support to RestSharp version 106.10.1 Restsharp 106.10.1 needs the Content Lenght as a parameter to AddFile method * Updating RestSharp Version Updating RestSharp Version * Update netcore_project.mustache * Update netcore_testproject.mustache * Update Project.mustache * Updating packages version Updating packages version * Updating packages version Updating packages version * Updating packages version Updating packages version * Updating packages version Updating packages version * Updating packages version Updating packages version * Updating packages version Updating packages version * Execute task async obsolete Use ExecuteAsync instead * update csharp samples Co-authored-by: William Cheng * [csharp] Library upgrade fix (#5848) * On .net45 framework, Restsharp version is updated to 106.10.1 Otherwise, it stays on version 105.1.0 * Added additionalProperties for library versions and target frameworks * Removed unused properties * Added an additional property to test for a specific version of RestSharp * Updated csharp samples * Fixed nuspec.mustache to use library specific additional properties * Updated csharp samples * Updating CI/samples.ci csharp petstore test project file. * Updated csharp.md Co-authored-by: Olivier Leonard * [csharp-client] Restored tests on csharp samples (#5879) * Restored tests on csharp samples * Restored a reference to the file used to test file uploads Co-authored-by: Olivier Leonard * update samples Co-authored-by: Igor Quirino Co-authored-by: Bouillie <34162532+Bouillie@users.noreply.github.com> Co-authored-by: Olivier Leonard * [Csharp-client] Complex form parameters are not serialized as application/json (#5849) * [csharp-client] Complex form parameters are now correctly serialized as json. * Updated csharp samples Co-authored-by: Olivier Leonard * docs: removes Nico from technical committee (#5883) * [PS] better handle special variables (#5885) * add variable * fix reserved words * update ps doc * [PS] add file post-processing to the PowerShell generator (#5864) * add post process to ps generator * add import * fix merge issue * consolidate header selection functions (#5889) * [Java-client] Add maven-compiler-plugin in pom.xml and enable linter checks by default (#5866) * Add maven-compiler-plugin plugin in Java pom.xml and enable linter checks by default * Add maven-compiler-plugin plugin in Java pom.xml and enable linter checks by default * Update enum.mustache (#5793) https://github.com/OpenAPITools/openapi-generator/issues/5792 * Update modelGeneric.mustache (#5378) * Update modelGeneric.mustache If maxlength is specified for a property type enum it there should be .ToString() appended before length check * ran the csharp petstore bar and updated the file Co-authored-by: Shweta Shukla * Fix Scala sttp generator packages (#5890) * Fix Scala sttp generator packages * Change package to parameterised * [Dart] Fix "basic" auth method and Add Bearer token support (#5743) * added auth check and lint * fixed basic auth condition * Added bearer auth * updated samples * update dart petstore samples Co-authored-by: William Cheng * Add date time format annotation on pojo for model query parameters (#5437) * Add date time format annotation on pojo for model query parameters * Regenetare samples * update spring samples Co-authored-by: William Cheng * [mysql] Add basic SQL queries (#5757) * Add basic SQL queries template * Add namedParametersEnabled option * Move model related SQLs into Model folder * Update README template * Refresh samples * [enhancement] [jaxrs-spec] Add builders to models (#4930) * Update formatting in jaxrs-spec POJOs * Add generateBuilders option * Update formatting in jaxrs-spec POJOs * Disable the builders generation by default * Ensure samples are up-to-date * Revert newline change * Run ensure-up-to-date * update doc * fix merge conflicts Co-authored-by: Artem Shubovych Co-authored-by: William Cheng * Update generated build files for REST Assured (#5873) * REST Assured 4.3.0 * Jackson 2.10.3 * Gson 2.8.6, GSON-Fire 1.8.4 * Okio 1.17.5 * Joda-Time 2.10.5 * ThreeTenBP 1.4.3 * Added missing dependencies for Bean Validation * Added missing dependencies for `@Generated` annotation * Refresh REST Assured sample project * [Java][Feign] Bug fix in @Param annotation (#5250) * FIX-5249 fix @Param annotation for Feign-client code generation Use paramName instead of baseName in order to make mapping in @Headers section fit the param-value. * update samples * FIX-5249 fix @Param annotation for Feign-client code generation Use paramName instead of baseName in order to make mapping in @Headers section fit the param-value. Co-authored-by: Christoph Preißner Co-authored-by: William Cheng * [Java] Increase java compiler stack size to handle large files (#5901) * increase java compiler stack size to handle large files * increase java compiler stack size to handle large files * Added emineo to list of companies on website (#5905) * add emineo to the list * [swift5] fix warning (#5900) * update bitwise config (#5904) * [Java] Discriminator lookup should not be case insensitive by default (#5894) * Add 'discriminatorCaseSensitive' property * Discriminator value lookup should not be case insensitive * fix typo * run scripts * execute ./bin/utils/export_docs_generators.sh * fix discriminator mapping, add code comments * minor fix to users.yml * Add a link to optim blog post (#5922) * [Java] Fix inclusive max validation (#5908) Co-authored-by: erikmolin * add bearer auth support to csharp netcore (#5921) * [Python][aiohttp] create venv as rule (#5913) * create venv as rule * create venv as rule II * Fix for Result Model Name collision (#5923) * Fix for Result Model Name collision * Run Scripts Co-authored-by: Sebastian Ohm * [Dart] Remove content type from header when content type is not specified (#5752) * accept empty content type * fixed test * updated samples * additional comment out * update dependency for java client (#5926) * Update axios dependency to the new minor version 0.19.0 (#5867) * Update axios dependency to 0.19.0 Axios (version 0.18.0) used by typescript-axios generator is more than two years old (released in Feb 2018). Axios 0.19.2 released earlier this year contains a lot of fixes and functionality, I recommend updating to 0.19.2. * Ran ./bin/typescript-axios-petstore-all.sh to update package.json in ./samples Co-authored-by: Chandra Yalangi * fixed README/doc of bearer auth support for csharp-netcore (#5931) * fix duplicated semi-colon in c# model (#5934) * [Python-experimental] Use DER encoding for ECDSA signatures, add parameter to configure hash algorithm (#5924) * Use DER encoding for ECDSA signatures * Use DER encoding for ECDSA signatures * Use DER encoding for ECDSA signatures * Use DER encoding for ECDSA signatures * fix python unit tests for http message signature * Fix error message * format python code * format python code * [Python-experimental] Fix TypeError: unhashable type: 'list' (#5810) * handle scenario when value is a list, fix TypeError: unhashable type: 'list' * Add __hash__ function * use list instead of set * use list instead of set * use list instead of set * use list instead of set * use list instead of set * use list instead of set * [python/asyncio] fix passing proxy parameters to aiohttp (#5943) * [C][Client]Fix data lost when libcurl write-data callback function is called multiple times (#5828) * [C][Client]Fix the defect of data lost when libcurl write-data callback function (configured by CURLOPT_WRITEFUNCTION) is called multiple times. * [C][Client]Fix data lost when libcurl write-data callback function is called multiple times (Reset count) * [typescript-axios][client] Allow apiKey type Promise. (#5953) * change apiKey type * recreate sample * Add YITU Technology to the user list (#5967) * add yitu to the user list * use yitu technology * Use model as body param for generateAliasAsModel (#4569) * generateAliasAsModel: Use model name as body param * Update samples * resolve merge conflicts in the core generator files * fix merge conflicts in pom.xml * Resolve Elm merge conflicts * [Rust Server] Fix up merge conflicts * Update samples * [Rust Server] Add debug log for rust-server-petstore.sh * update samples * update more samples * fix dart openapi-generator version * remove deprecated c# files * update meta codegen * fix port in pom.xml * fix port in sample * update jaxrs cxf version Co-authored-by: sunn <33183834+etherealjoy@users.noreply.github.com> Co-authored-by: dwlabcube <46682038+dwlabcube@users.noreply.github.com> Co-authored-by: Herve DARRITCHON Co-authored-by: Akihito Nakano Co-authored-by: Johnny Peck Co-authored-by: Michele Albano Co-authored-by: Jim Schubert Co-authored-by: Nikita Co-authored-by: Alexey Makhrov Co-authored-by: val Co-authored-by: Bruno Coelho <4brunu@users.noreply.github.com> Co-authored-by: Aleksandr Nekrasov Co-authored-by: Akira Tanimura Co-authored-by: Justin Co-authored-by: Justin Black Co-authored-by: Jiri Kuncar Co-authored-by: Hui Yu Co-authored-by: Yutaka Miyamae <48900426+yutaka0m@users.noreply.github.com> Co-authored-by: Mateusz Szychowski (Muttley) Co-authored-by: Jorge Rodriguez Co-authored-by: Gonzalo Co-authored-by: ChristianCiach Co-authored-by: Bodo Graumann Co-authored-by: Yuriy Belenko Co-authored-by: Daniel Klessing Co-authored-by: copypasta-g <53397163+copypasta-g@users.noreply.github.com> Co-authored-by: Mahdi Dibaiee Co-authored-by: Sebastien Rosset Co-authored-by: siada Co-authored-by: Samuel Hoffstaetter Co-authored-by: Esteban Gehring Co-authored-by: Jon Schoning Co-authored-by: Marcin Kubala Co-authored-by: anoohya-n <51289018+anoohya-n@users.noreply.github.com> Co-authored-by: Antoine Reilles Co-authored-by: Clemens Angermann Co-authored-by: Mostafa Moradian Co-authored-by: Adam Co-authored-by: Lars Hvam Co-authored-by: sullis Co-authored-by: Vikrant Balyan Co-authored-by: Matt Traynham Co-authored-by: LEZIER-S2 <60382243+LEZIER-S2@users.noreply.github.com> Co-authored-by: Thomas Enderle Co-authored-by: YishTish Co-authored-by: Slavek Kabrda Co-authored-by: Tomasz Prus Co-authored-by: Erica Kastner Co-authored-by: Richard Whitehouse Co-authored-by: valentin Bisson Co-authored-by: etherealjoy Co-authored-by: Hemant Zope <42613258+zhemant@users.noreply.github.com> Co-authored-by: Even André Fiskvik Co-authored-by: ehansen31 Co-authored-by: Timur Platonov Co-authored-by: Josh Burton Co-authored-by: Ilja leyberman <7ilya@gmx.de> Co-authored-by: Bouillie <34162532+Bouillie@users.noreply.github.com> Co-authored-by: Olivier Leonard Co-authored-by: tanmen Co-authored-by: Alex Buchkovsky Co-authored-by: Natan Laverde Co-authored-by: Nicholas Muesch Co-authored-by: jburgess <11861789+jburgess@users.noreply.github.com> Co-authored-by: emileonhardt <40421857+emileonhardt@users.noreply.github.com> Co-authored-by: Jacob Floyd Co-authored-by: Igor Quirino Co-authored-by: Nico König Co-authored-by: https://gitlab.com/selankon Co-authored-by: Shweta Shukla <25539662+shwetashukla@users.noreply.github.com> Co-authored-by: Shweta Shukla Co-authored-by: Bartek Kowalik Co-authored-by: Shinya Sugmoto <34866626+gasugesu@users.noreply.github.com> Co-authored-by: Artem Shubovych Co-authored-by: Artem Shubovych Co-authored-by: Jochen Schalanda Co-authored-by: Chr1st0ph Co-authored-by: Christoph Preißner Co-authored-by: Erikmolin Co-authored-by: erikmolin Co-authored-by: Nicolas Homble Co-authored-by: Sebastian <63457660+sebohdev@users.noreply.github.com> Co-authored-by: Sebastian Ohm Co-authored-by: chandra-gh <63366477+chandra-gh@users.noreply.github.com> Co-authored-by: Chandra Yalangi Co-authored-by: Fabian Freund Co-authored-by: Erik Timmers * Revert "Sync master to 5.0.x (#5968)" This reverts commit 90dd7a03418ff4554ae8351b325eb86ee5794e92. * Change access updateParamsForAuth to protected (#5940) So that it can be overridden with a custom behaviour. * Add jersey2-experimental to Java client generator (#6024) * add jersey2 experimental * add new files * add abstract one of class * read the stream multiple times * rename to getActualInstance * update petstore * fix jackon check * test new java petstore in ci * fix broken tests * remove todo * better exception message, primitive type handling * add anyof support * update samples * add new files * update all java client samples * update doc, fix pom * better null check for allOf * add primitive types support in oneof, anyof * better validation * update python exp samples * remove primitive type support in allOf * [CORE] Fixes composed schema discriminator map (#4906) * Adds addComposedMappedModels and testComposedSchemaOneOfDiscriminatorMap * Requires that discriminators be required properties * Strengthens discriminaotr validation, adds better error messages, adds schema oneof samples * Adds oneOf and anyOf invalidDiscriminator tests * Updates incorrect addOneOfInterfaceModel invocation * Runs ensure-up-to-date * Adds updates from Sebastien Rosset * Removes newlines * Uses df.isString * Fixes tests be correctly setting df.isString * Updates discriminatorExplicitMappingVerbose description per PR feedback * Adds description of how mappedModels is populated * Adds the suggestion exception raising when a MappedModel mappingName is null * Actually resolves merge conflicts * Switches two methods to package private because they are needed for testing * Allow nulls in MappedModel.getMappingName * Updates CLI flag name to legacyDiscriminatorBehavior, default=true Co-authored-by: William Cheng * Update Java (feign) client dependency (#6068) * update feign dependency * update feign samples * Add HTTP signature authentication support to Java (jersey2-experimental) (#6058) * add fmt-maven-plugin to jersey2 exp * update samples * add http signature auth template * minor fix * fix http beaer auth, update sample * fix http signature auth * fix http signature auth * header support * add query string to path * undo changes in default codegen * ignore fake test * add serialize to string method * add serialzie to string method * add get mapper * auto format java source code * remove plugin * update pom.xml * change back AbstractOpenApiSchema to T * skip mvn code formatter in bin script * undo changes to spec * update samples * add back HttpSignatureAuth.java * better docstring for jersey2 client (#6104) * [Java] Enhancements for HTTP message signature (#6090) * Add code comments * Change 'setup' method to setPrivateKey * Add support for configuring digest algorithm * run script in bin directory * format generated code * Revert "format generated code" This reverts commit 3b527784375bcf86cacf75bd0142f63b91c96ff8. * Add async native Java Client (#4721) * Add async native Java Client * UPDATE: Reformat the samples * test java native async in drone.io * update test count Co-authored-by: William Cheng * Fix #6157: Updated native template to fix null async return (#6168) * Fix #6157: Updated native template to fix null async return Should fix issue: https://github.com/OpenAPITools/openapi-generator/issues/6157 * fixed uncaught json exception in java native api gen * cleaning up Co-authored-by: Luis Ballabeni * Add full OAuth2 support to jersey2-experimental codegen (#6183) * Add full Oauth2 support to Jersey client * Regenerate jersey2-experimental sample * Regenerate all java clients * [Java][jersey2] replace jersey2 with jersey2-experimental (#6251) * replace jersey2 with jersey2-experimental * better handling of oauth * add jersey2 java8 samples * add dependency to test pom * fix test, update doc * add null type support to oneof/anyof java jersey2 (#6269) * Mustache template should use invokerPackage tag to generate import (#6277) * [Java] update jackson databind versions (#6328) * update databind version * update gradle build * fix gradle in some java clients (#6339) * [Java][jersey2] Allow setting serverIndex to null (#6321) * [Java] Upgrade http signature library to version 1.4 (#6370) * Mustache template should use invokerPackage tag to generate import * upgrade to http signature library version 1.4 * Use updated HTTP signature library * Run sample scripts * Add code samples in README file for HTTP signature * fix java imports * Update http-signature version * Use webclient exceptions in java webclient client (#6304) * Add helper methods to determine if the spec has certain authentication defined (#6347) * better import, add security methods * add helper method to determine auth type when adding supporting files * better docstrings * fix boolean return * update tests * Revert "update tests" This reverts commit 29cfc8ad663234ee20c73ac7be9c4dd2235ac34f. * add test in shippable * rename variables * check if auth files are needed * update tests * revert check * set java8 to true * fix auth check * better npe handling * reoder methods * undo changes to shippable.yml * [Java-jersey2] Add new ApiClient constructor with auth objects (#6393) * Mustache template should use invokerPackage tag to generate import * Add new constructor for Java ApiClient * Add constructor with auth map * [Java] Fix mustache tag in pom template for HTTP signature (#6404) * Mustache template should use invokerPackage tag to generate import * Fix tag for http signature in pom.xml * [Java] Generate valid code if no Authentication implementations present (#5788) * generate valid code if no Authentication implementations present resurrects https://github.com/OpenAPITools/openapi-generator/pull/2861 * remove what I assume are human generated test cases * need to iterate over authMethods in order to pull out name * fix another test * update more tests * rename hasTokenAuthMethods to hasApiKeyAuthMethods * remove duplicate methods, fix hasHttpBearerMethods check * update templates * update windows java-petstore files * update windows java-petstore files * re-generate * re-generate * restore samples.ci tests * restore samples.ci tests * [java-jersey2] Conditionally include http signature mustache template (#6413) * [Java][jersey2] Make (de)serialization work for oneOf models, add convenience and comparison methods (#6323) * [Java][jersey2] minor improvement to jersey2 tests (#6418) * minor improvement to jersey2 test, remove script/bat * remove tests for java7 jersey2 * remove log from abstrct java class * undo change to jaxrs path * java jersey2 enhance anyOf (#6420) * [Java][jersey2] Improve http signature code comments (#6463) * Mustache template should use invokerPackage tag to generate import * fix typo and improve code comments * [Java][jersey2] Fix RuntimeException when HTTP signature parameters are not configured (#6457) * Mustache template should use invokerPackage tag to generate import * fix runtime exception when HttpSignatureAuth is not set * fix runtime exception when HttpSignatureAuth is not set * [Java][Jersey2] Fix typo and script, Log enhancements, HTTP signature, deserialization (#6476) * Mustache template should use invokerPackage tag to generate import * fix typo, fix script issue, add log statement for troubleshooting * Add java jersey2 samples with OpenAPI doc that has HTTP signature security scheme * Add sample for Java jersey2 and HTTP signature scheme * Add unit test for oneOf schema deserialization * Add unit test for oneOf schema deserialization * Add log statements * Add profile for jersey2 * Temporarily disable unit test * Temporarily disable unit test * fix typo in pom.xml * fix duplicate jersey2 samples * fix duplicate jersey2 samples * fix duplicate artifact id * fix duplicate jersey2 samples * run samples scripts * [Java][Jersey2] various improvements (#6518) * [java][jersey2] Add support for discriminator, fix nullable typo and nullable deserialization (#6495) * Mustache template should use invokerPackage tag to generate import * fix typo, fix script issue, add log statement for troubleshooting * Add java jersey2 samples with OpenAPI doc that has HTTP signature security scheme * Add sample for Java jersey2 and HTTP signature scheme * Add unit test for oneOf schema deserialization * Add unit test for oneOf schema deserialization * Add log statements * Add profile for jersey2 * Temporarily disable unit test * Temporarily disable unit test * support for discriminator in jersey2 * fix typo in pom.xml * disable unit test because jersey2 deserialization is broken * disable unit test because jersey2 deserialization is broken * fix duplicate jersey2 samples * fix duplicate jersey2 samples * Add code comments * fix duplicate artifact id * fix duplicate jersey2 samples * run samples scripts * resolve merge conflicts * Add unit tests * fix unit tests * continue implementation of discriminator lookup * throw deserialization exception when value is null and schema does not allow null value * continue implementation of compose schema * continue implementation of compose schema * continue implementation of compose schema * Add more unit tests * Add unit tests for anyOf * Add unit tests Co-authored-by: Vikrant Balyan (vvb) * update samples * add tests to oas3 java jersey2 petstore * comment out jersey2 ensure uptodate * Jersey2 supports additional properties with composed schema (#6523) * Mustache template should use invokerPackage tag to generate import * fix typo, fix script issue, add log statement for troubleshooting * Add java jersey2 samples with OpenAPI doc that has HTTP signature security scheme * Add sample for Java jersey2 and HTTP signature scheme * Add unit test for oneOf schema deserialization * Add unit test for oneOf schema deserialization * Add log statements * Add profile for jersey2 * Temporarily disable unit test * Temporarily disable unit test * support for discriminator in jersey2 * fix typo in pom.xml * disable unit test because jersey2 deserialization is broken * disable unit test because jersey2 deserialization is broken * fix duplicate jersey2 samples * fix duplicate jersey2 samples * Add code comments * fix duplicate artifact id * fix duplicate jersey2 samples * run samples scripts * resolve merge conflicts * Add unit tests * fix unit tests * continue implementation of discriminator lookup * throw deserialization exception when value is null and schema does not allow null value * continue implementation of compose schema * continue implementation of compose schema * continue implementation of compose schema * Add more unit tests * Add unit tests for anyOf * Add unit tests * Set supportsAdditionalPropertiesWithComposedSchema to true for Java jersey2 * Support additional properties as nested field * Support additional properties as nested field * add code comments * add customer deserializer * Fix 'method too big' error with generated code * resolve merge conflicts Co-authored-by: Vikrant Balyan (vvb) * [Jersey2] Fix code generation of 'registerDiscriminator' method for large models (#6535) * Mustache template should use invokerPackage tag to generate import * fix typo, fix script issue, add log statement for troubleshooting * Add java jersey2 samples with OpenAPI doc that has HTTP signature security scheme * Add sample for Java jersey2 and HTTP signature scheme * Add unit test for oneOf schema deserialization * Add unit test for oneOf schema deserialization * Add log statements * Add profile for jersey2 * Temporarily disable unit test * Temporarily disable unit test * support for discriminator in jersey2 * fix typo in pom.xml * disable unit test because jersey2 deserialization is broken * disable unit test because jersey2 deserialization is broken * fix duplicate jersey2 samples * fix duplicate jersey2 samples * Add code comments * fix duplicate artifact id * fix duplicate jersey2 samples * run samples scripts * resolve merge conflicts * Add unit tests * fix unit tests * continue implementation of discriminator lookup * throw deserialization exception when value is null and schema does not allow null value * continue implementation of compose schema * continue implementation of compose schema * continue implementation of compose schema * Add more unit tests * Add unit tests for anyOf * Add unit tests * Fix 'method too big' error with generated code * resolve merge conflicts Co-authored-by: Vikrant Balyan (vvb) * update samples * comment out tests * support additional properties in serialize and deserialize * add discriminator lookup * remove oneof/anyof logic in apilcient * add serializer to mammal.java * add serialize to oneOf model * add serializer to anyof model * comment out test cases that are subject to further discussion * add back files * update configs, samples Co-authored-by: Sebastien Rosset Co-authored-by: Vikrant Balyan (vvb) * fix import of JSON class (#6606) * [Java][jersey2] Fix Java compiler warnings (#6605) * Mustache template should use invokerPackage tag to generate import * fix typo, fix script issue, add log statement for troubleshooting * Add java jersey2 samples with OpenAPI doc that has HTTP signature security scheme * Add sample for Java jersey2 and HTTP signature scheme * Add unit test for oneOf schema deserialization * Add unit test for oneOf schema deserialization * Add log statements * Add profile for jersey2 * Temporarily disable unit test * Temporarily disable unit test * support for discriminator in jersey2 * fix typo in pom.xml * disable unit test because jersey2 deserialization is broken * disable unit test because jersey2 deserialization is broken * fix duplicate jersey2 samples * fix duplicate jersey2 samples * Add code comments * fix duplicate artifact id * fix duplicate jersey2 samples * run samples scripts * resolve merge conflicts * Add unit tests * fix unit tests * continue implementation of discriminator lookup * throw deserialization exception when value is null and schema does not allow null value * continue implementation of compose schema * continue implementation of compose schema * continue implementation of compose schema * Add more unit tests * Add unit tests for anyOf * Add unit tests * [java][jersey2] Add support for discriminator, fix nullable typo and nullable deserialization (#6495) * Mustache template should use invokerPackage tag to generate import * fix typo, fix script issue, add log statement for troubleshooting * Add java jersey2 samples with OpenAPI doc that has HTTP signature security scheme * Add sample for Java jersey2 and HTTP signature scheme * Add unit test for oneOf schema deserialization * Add unit test for oneOf schema deserialization * Add log statements * Add profile for jersey2 * Temporarily disable unit test * Temporarily disable unit test * support for discriminator in jersey2 * fix typo in pom.xml * disable unit test because jersey2 deserialization is broken * disable unit test because jersey2 deserialization is broken * fix duplicate jersey2 samples * fix duplicate jersey2 samples * Add code comments * fix duplicate artifact id * fix duplicate jersey2 samples * run samples scripts * resolve merge conflicts * Add unit tests * fix unit tests * continue implementation of discriminator lookup * throw deserialization exception when value is null and schema does not allow null value * continue implementation of compose schema * continue implementation of compose schema * continue implementation of compose schema * Add more unit tests * Add unit tests for anyOf * Add unit tests Co-authored-by: Vikrant Balyan (vvb) * update samples * add tests to oas3 java jersey2 petstore * Fix 'method too big' error with generated code * resolve merge conflicts * comment out jersey2 ensure uptodate * fix compiler warnings * Jersey2 supports additional properties with composed schema (#6523) * Mustache template should use invokerPackage tag to generate import * fix typo, fix script issue, add log statement for troubleshooting * Add java jersey2 samples with OpenAPI doc that has HTTP signature security scheme * Add sample for Java jersey2 and HTTP signature scheme * Add unit test for oneOf schema deserialization * Add unit test for oneOf schema deserialization * Add log statements * Add profile for jersey2 * Temporarily disable unit test * Temporarily disable unit test * support for discriminator in jersey2 * fix typo in pom.xml * disable unit test because jersey2 deserialization is broken * disable unit test because jersey2 deserialization is broken * fix duplicate jersey2 samples * fix duplicate jersey2 samples * Add code comments * fix duplicate artifact id * fix duplicate jersey2 samples * run samples scripts * resolve merge conflicts * Add unit tests * fix unit tests * continue implementation of discriminator lookup * throw deserialization exception when value is null and schema does not allow null value * continue implementation of compose schema * continue implementation of compose schema * continue implementation of compose schema * Add more unit tests * Add unit tests for anyOf * Add unit tests * Set supportsAdditionalPropertiesWithComposedSchema to true for Java jersey2 * Support additional properties as nested field * Support additional properties as nested field * add code comments * add customer deserializer * Fix 'method too big' error with generated code * resolve merge conflicts Co-authored-by: Vikrant Balyan (vvb) * [Jersey2] Fix code generation of 'registerDiscriminator' method for large models (#6535) * Mustache template should use invokerPackage tag to generate import * fix typo, fix script issue, add log statement for troubleshooting * Add java jersey2 samples with OpenAPI doc that has HTTP signature security scheme * Add sample for Java jersey2 and HTTP signature scheme * Add unit test for oneOf schema deserialization * Add unit test for oneOf schema deserialization * Add log statements * Add profile for jersey2 * Temporarily disable unit test * Temporarily disable unit test * support for discriminator in jersey2 * fix typo in pom.xml * disable unit test because jersey2 deserialization is broken * disable unit test because jersey2 deserialization is broken * fix duplicate jersey2 samples * fix duplicate jersey2 samples * Add code comments * fix duplicate artifact id * fix duplicate jersey2 samples * run samples scripts * resolve merge conflicts * Add unit tests * fix unit tests * continue implementation of discriminator lookup * throw deserialization exception when value is null and schema does not allow null value * continue implementation of compose schema * continue implementation of compose schema * continue implementation of compose schema * Add more unit tests * Add unit tests for anyOf * Add unit tests * Fix 'method too big' error with generated code * resolve merge conflicts Co-authored-by: Vikrant Balyan (vvb) * Add unit test for date time * Add unit test for date time * update samples * comment out tests * support additional properties in serialize and deserialize * add discriminator lookup * remove oneof/anyof logic in apilcient * add serializer to mammal.java * add serialize to oneOf model * add serializer to anyof model * comment out test cases that are subject to further discussion * add back files * update configs, samples * resolve merge conflicts Co-authored-by: Vikrant Balyan (vvb) Co-authored-by: William Cheng * remove localVariablePrefix (#6588) * Use builder pattern for requests (#5961) * [JAVA] RxJava3 support (#6622) * rx3 support * ran the shell script ./bin/generate-samples.sht * added missing rx3 migration, removed tabs * Fix URL encoding problem for HTTP signatures (#6637) * [java][jersey2] Add hook to customize SSL context, trust manager and host verifier (#6633) * Add hook to customize SSL context, trust manager and host verifier * run sample scripts * [Java][Retrofit2] deprecate RxJava 1.x (#6641) * deprecate rxjava1.x * update samples * Fix usage of javax.annotation (#6645) * Fix usage of javax.annotation:javax.annotation-api * Regenerate samples ``` bin/generate-samples.sh bin/configs/java-* bin/configs/jaxrs-* bin/configs/spring-* bin/configs/kotlin-* bin/configs/other/java-* bin/configs/other/jaxrs-* bin/configs/other/kotlin-* bin/configs/other/openapi3/jaxrs-cxf-client.yaml bin/configs/other/openapi3/kotlin-* ``` * [Java] Add add constructor to BYO OkHttpClient (#6401) * [Java] Add add constructor to BYO OkHttpClient * client example * this client changed too * [java] Specify Java version for maven-javadoc-plugin (fixes Java 11 error) (#6679) * Add jersey2-experimental to petstore build script on-behalf-of: @nqminds * [java] Add to javadoc in pom.mustache We add the following tag to the of maven-javadoc-plugin for most pom.mustache files that use it. This tells javadoc which version of java the compiler used. This fixes the following error when running Java 11: [ERROR] Exit code: 1 - javadoc: error - The code being documented uses modules but the packages defined in https://docs.oracle.com/javase/8/docs/api/ are in the unnamed module Additionally, we also add maven-compiler-plugin to jersey2/pom.mustache to specify that the source code is Java 6/7/8. on-behalf-of: @nqminds * [java-jersey2-java6] Update failing old tests Pull-request #4666 changed jersey generation, but didn't update the test samples Tests now succeed. on-behalf-of: @nqminds * [java-retrofit2-play24] Fix integration-tests Running mvn integration-test failed in samples/client/petstore/java/retrofit2-play24 This merges pull requests #1735 and #5527 into retrofit2-play24. Also removes the jackson-databind-version field, since it should always be the same as jackson-version, and updates build.gradle/build.sbt on-behalf-of: @nqminds Co-authored-by: Alois Klink * [Java][MicroProfile] Use jsonb imports for serializing and deserializing enum (#6064) * Use jsonb imports for serializing and deserializing pojo * Fix: Exclude jsonbProperty class when withXml=true Co-authored-by: Ravisankar Challa * add getActualInstanceRecursively (#6636) * [java][jersey2] Fix processing of additional, undeclared properties (#6647) * Add unit tests for additional properties * add unit tests * Add unit tests and fix processing of additionalProperties * fix deserialization issue with additional properties * [Java][Microprofile] JSON enum processing fix (#6700) * When withXml=false we shouldn't add the jaxb imports When users are just dealing with json and set withXml=false jaxb (Java Api XML binding) imports are not needed. * Updated the microprodile-rest-client samples * Removed cxf-rt-rs-extension-providers dependency * Fix processing of enum values * Remove unwanted changes * Remove spaces * java-native added WithHttpInfo (#6704) remove /t * [Java][jersey2] fix oneOf, anyOf documentation (#6695) * fix oneOf doc in Java jersey2 * fix sample code * add new files * minor tweat to the doc * [Java][jersey2] Add debugging to OAuth (#6757) * add debugging to oauth * use fine instead * [java][jersey2] Add support for (expires) and (created) fields in HTTP signature (#6632) * Add support for (expires) and (created) fields in HTTP signature * Add support for (expires) and (created) fields in HTTP signature * [Java][jersey2] Add nullable body support (#6784) * add nullable body support * update serializeToString with nullable body * add nullable support to body parameter * minor code format change * Revert "minor code format change" This reverts commit 3af1838a9bf421e633165dbd8e62bb7740b539ef. * code format fix * [Java][client][native][Gradle] Add missing jackson-databind-nullable (#6802) * Add missing jackson-databind-nullable to java-native Gradle build Closes #6801 * Regenerate java-native samples * update samples Co-authored-by: William Cheng * [Java] Deprecate feignVersion option (#6824) * deprecate feign option * update doc * udpate samples * [Java][jersey2] Add a getter for the User-Agent header value (#6831) * [Java][jersey2] Add a getter for the User-Agent header value * generate samples * Make ApiClient in retrofit2 be able to use own OkHttpClient (#6699) * set adapterBuilder.client() only if okBuilder was used in retrofit2 * updated the samples * added field okHttpClient and updated samples * bug fixed, added exception if okBuilder is null * added semicolon * added space, changed Exception to RuntimeException and changed its message * updated the samples * [Java][WebClient]remove the dead code from java ApiClient.mustache (#6556) * remove the dead code Remove the dead code from ApiClient The code is not used and it contains vulnerability of Log Forgery when it writes unvalidated http header to the log. An attacker could take advantage of this behaviour to forge log entries or inject malicious content into the log. * update Petstore samples * whitespace * [BUG] [JAVA] Fix multiple files upload (#4803) (#6808) * gh-4803: Fix bug java client multiple files upload * gh-4803: Fix bug java client multiple files upload * gh-4803: Fix bug java client multiple files upload * gh-4803: Fix bug java client multiple files upload * gh-4803: Fix bug java client multiple files upload * [Java][Client][vert.x] Support per-call authentication and JsonNullable in client request bodies, fix path parameter encoding (#5732) * Support per-call authentication and JsonNullable in client request bodies Extensions ---------- Since vertx is an asynchronous/reactive toolkit usage of mutable fields of `ApiClient` to store authentication prohibits delegation of authentication from incoming call without recreating the client everytime (which is prohibitively expensive due to instantiation of objectmapper). This commit adds a per call authentication override which takes precedence over the mutable fields so a single client can be safely reused. To ease usage a simple builder-style auxiliary `AuthInfo` object is provided providing methods for each specified authentication. A new configuration option for `ApiClient` has been added: `timeout`. It gets applied as timeout for the vertx http request. Fixes ----- Request bodies have been wrongly serialized using vert.x built-in objectmapper instead of the embedded instance thus usage of beans with `JsonNullable` wrapped fields in request bodies led to bad requests. * update vertx samples * Client Java Vertx: Add url encode for path parameters. * update vertx samples * minor fix to sample code (java jersey2) (#6921) * fix typo (#6928) * [Java][jersey2] Fix format of Date header in HTTP signature (#6925) * Use RFC 1123 date format for Date header in HTTP signature * Use RFC 1123 date format for Date header in HTTP signature * fix null payload in java jersey2 (#6933) * [Java][Native] added WithHttpInfo method for async-native (#6903) * [java-asyncNative] add withHttpInfo * update api template for async-native * [Java][Jersey2] Add JsonTypeName annotation (#6551) * Mustache template should use invokerPackage tag to generate import * add JsonSubTypes annotation to handle scenario when OAS name has special characters * add JsonSubTypes annotation to handle scenario when OAS name has special characters. Add unit test * run sample scripts * fix unit test * run sample scripts * add minimal openapi document to show issue with special characters and discriminators * Add 'isClassnameSanitized' tag * Add 'isClassnameSanitized' tag * Add 'isClassnameSanitized' tag * Add 'isClassnameSanitized' tag * Add 'isClassnameSanitized' tag * Add 'isClassnameSanitized' tag * Add unit tests for unmarshaling of discriminators with special characters * Add unit tests for unmarshaling of discriminators with special characters * use JsonTypeName Co-authored-by: Vikrant Balyan (vvb) Co-authored-by: William Cheng * [Java][RestTemplate] Use abstraction for files (#6912) * Fix dir path in PR request template * Add "useAbstractionForFiles" config option for Java/RestTemplate to allow flexible options in generated client when a file is needed (#6715) * Add "useAbstractionForFiles" config option for Java/RestTemplate to allow flexible options in generated client when a file is needed (#6715) * Add "useAbstractionForFiles" config option for Java/RestTemplate to allow flexible options in generated client when a file is needed (#6715) * #6715 - Add "useAbstractionForFiles" config option for Java/RestTemplate to allow flexible options in generated client when a file is needed. * add JsonTypeName (#6995) * rollback feign version to 10.11 (#7012) * [Java][jersey2] Fix `serializeToString` (#6956) * fix empty get body in serializeToString, add tests * add new file * fix serialize to better handle null string * update test comments * [java][jersey2-client] Disable coercion of scalars (#6811) * [java][jersey2-client] Disable coercion of scalars * Respect the coercion objectmapper setting in deserializers * Update jackson in maven plugin to get version that has ALLOW_COERCION_OF_SCALARS * Add property additionalModelTypeAnnotations on the top of pojo class (#6037) * [Java][jersey2] fix query parameters in applyToParams (#7028) * fix query parameters in applyToParams * update samples * #6715 - Use Resource interface instead of AbstractResource when useAbstractionForFiles=true. (#7051) * [Java][okhttp-gson] prevent UnsupportedOperationException by removal from ImmutableList on setDebugging(false) (#7024) * fix https://github.com/OpenAPITools/openapi-generator/issues/6934 * fix https://github.com/OpenAPITools/openapi-generator/issues/6934 * update samples Co-authored-by: William Cheng * [Java][jersey2]Fix gradle HttpSignatureAuth dependencies (#7096) * Corrects tag for including HttpSignatureAuth in gradle builds * Updates version of org.tomitribe:tomitribe-http-signatures in gradle template to match version from maven template * Updates samples * fix http signaure auth in build.sbt (#7110) * ISSUE-4222: Prevent conflicts with accept(s) local variables in generated Java RestTemplate ApiClient (#7101) * ISSUE-4222: Change accept(s) to localVarAccept(s) in Java/resttemplate/api.mustache * ISSUE-4222: Regenerate samples * [BUG][JAVA] Fix error handling in okhttp-gson async api client (#7089) * Fix error handling in okhttp-gson async api client * update samples Co-authored-by: William Cheng * [Java][jersey2] Add helper methods for oneOf Java classes (#7115) * add helper methods for oneOf java class * better test comment * add helper methods to anyOf in java models (#7130) * [Java] Update templates not to add @Pattern on byte array property (#7153) * Update Java templates to skip generating @Pattern on byte array properties * Revert separator changes * Revert separator changes * [Java] parameterize formParams (#5784) * parameterize formParams fixes #5782 * sync generated code * update to latest version of spring, replace MultiValueMap#put with #addAll, remove unused imports * restore java.util.HashMap import * update spring version in pom/gradle templates * re-generate resttemplate samples * fix test * fix test * parameterize an additional usage of LinkedMultiValueMap * re-generate resttemplate samples * re-generate webclient samples * manually edit FILES to replace \ with / * [REQ][Java] Additional annotations with String params (#7117) * Additional annotations with String params * Additional annotations with String params. Missed sample update * Additional annotations with String params. Use Jackson annotations * insert unescaped content * fix imports * fix imports * Support for KumuluzEE microprofile runtime (#5944) * Added library and edited generator to support server stub generation with Kumuluzee framework. * Trimmed and tweaked pom.xml template and removed unnecessary template files from generator and library. * minor edits * Added new library to Java client codegen (microprofile-kumuluzee). A functional KumuluzEE REST client can now be generated. * Edited README for microprofile-kumuluzee * Edited docs to include new KumuluzEE library options. * Updated kee-rest-client client POM dependency version to latest * fixed pom, edited REAMDE * Trimmed redundant dependencies from KEE client pom * Removed unnecessary DefaultGenerator edit, modified config template accordingly. * Made mp framework an additional property for microprofile instead of being another library option, removed now redundant library files. * Updated documentation with microprofile framework * Fixed errors caused by removed functions and variables * update doc Co-authored-by: Chuckledog Co-authored-by: Jan Meznaric Co-authored-by: William Cheng * [Java][jersey2] Add jersey injection dependencies (#7240) * Adds the jersey injection dependency to gradle and sbt to match the maven dependency. * Update jersey version in sbt * [Java][clients] remove java.lang prefix from Object (#6806) * [Java][jersey2]Support enum discriminator value in child objects (#7267) * support enum discriminator value in child (java jersey2) * update samples * add tests, use public * [Java] remove deprecated jackson classes (#7304) * [java/resttemplate] Generate valid code if no Authentication implementations present Take the logic used to decide which instances to add to the authentications map and re-use to not import classes or offer non-functional util methods * parameterize formParams fixes #5782 * replace use of ISO8601DateFormat and ISO8601Utils with StdDateFormat fixes #5779 * add constructor to intialise calendar * Revert "[java/resttemplate] Generate valid code if no Authentication implementations present" This reverts commit 6e450907bae1d831a4a8c9b66f6b707424f0a39a. * Revert "parameterize formParams" This reverts commit 7a26ce5dd21ce147ed33728cd0091a29175367a4. * also override single arg parse method to avoid throwing exception * also override single arg parse method to avoid throwing exception * update samples * update samples * fix jersey1 tests * fix jersey2 test * update resteasy dependencies * fix java jersey2 oas3 tests * use java8 in springboot-beanvalidation Co-authored-by: Jon Freedman * [java] Intro openApiNullable property to enable/disable OpenAPI Jackson Nullable library (#6154) * Add option to prevent usage of jackson-nullable (#2901) Add a option for all java client and server to prevent usage of third party library (jackson-databind-nullable) which may be forbidden in some company Add samples for Vertx, Spring MVC, Spring Cloud, Feign and Play Upgrade dependencies for org.openapitools:jackson-databind-nullable * Samples - Remove dependency org.openapitools:jackson-databind-nullable (#2901) * Fix generation of gradle file for vertx (#2901) * Regenerate samples (#2901) * Fix documentation and up to date (#2901) * Fix forgotten regeneration of vertx after dependency integration (#2901) * Regenerate template after rebase (#2901) * Use yaml config files introduce in #6509 to manage samples (#2901) * Regenerate template using the config (#2901) * Fix bad version during testing generated samples (#2901) * Regenerate template after fix bad version (#2901) * Fix merge, allow for set importing on codegen model Co-authored-by: Jim Schubert * [Java][Client] Use java8 OffsetDateTime for clients (#7190) * use java8 OffsetDateTime for clients * use java8 OffsetDateTime for clients * fix javadoc * add javadoc to JavaTimeFormatter.mustache * add javadoc to JavaTimeFormatter.mustache * add javadoc to JavaTimeFormatter.mustache * Remove duplicate jackson-datatype-jsr310 dependency (#7338) * [TYPO] [WEBCLIENT] Issue 7425: Fixed comments that referred to RestTemplate. (#7445) * Issue 7425: Fixed comments that referred to RestTemplate. * Ran genreate-samples.sh * Re-ran generate-samples.sh against all configs. * update samples Co-authored-by: William Cheng * [java] jaxrs (all) add usetags option (#6130) * Adds "useTags" option to all jaxrs code generators (AbstractJAXRSServerCodegen): - jaxrs-jersey - jaxrs-spec - jaxrs-cxf-cdi - jaxrs-resteasy - jaxrs-cxf - jaxrs-cxf-extended - java-msf4j - jaxrs-resteasy-eap * jaxrs-spec - Changed handling of root paths: e.g "/:", "/{id}:" to simplify code and create a more consistent behaviour -- old: use tag for classname -- new: use tag only if useTags is enabled, use "DefaultApi" if not * @path class level annotation - for all generators above and the microprofile generator (uses same jaxrs postprocessing) - extended the "commonPath" to contain more than only the root path if possible - e.g. "/group1/subgroup1/op1" -> "/group1/subgroup1" is moved to class level annotation * update microprofile default license info file (#7550) * replace tab with spaces (#7625) * java jersey2: remove trailing whitespaces (#7632) * Unifies naming for isMap in Schema class properties (#7640) * Updates isMapModel + isMapContainer -> isMap * Removes git conflict characters * Update junit to newer version (4.13.1) (#7690) * update junit to newer version * update junit to newer version * [Java][Native] Support oneOf/anyOf schemas (#7263) * Java-native add models of oneOf/anyOf * Java-native refresh samples * Java-native add a sample project for openapi3 * Changes lingering isMapContainer to isMap (#7747) * Changes lingering isMapContainer to isMap * Adds ensure up to date updates * Unifies naming for isArray in Schema class properties (#7691) * Updates key java files * Adds all lingering isArray fixes * Adds two files * Reverts two cs files * Fixes lingering isListContainer + isArrayModel references * Some ensure up to date updates * [java][jersey2] add proxy support (#7752) * add client config getter and setter * update gradle, sbt config * update client config * update samples * add code sample to set proxy * [Java][webclient] fix missing dependencies in build.gradle (#7777) * fix build.gradle in java webclient * update junit version in samples * Removes secondaryParam and hasMore (#7882) * Removes secondaryParam and hasMore * Fixes tests * Only uses bodyParam in groovy template * fix additional properties without variables (#7978) * Remove links to basic types in java API docs (#7989) * Remove links to basic types in java API docs This removes (most) wrong links to basic types in Java API docs. * Regenerate some more samples * remove default ContentType for java webclient (#7945) * Improve generated Java examples (#8012) * Add basic types imports to generated examples This adds an extension to include basic types imports to generated Java examples. * Make some fixes to example generation * Generate OffsetDatetime correctly * Create a useful sample for enums, regenerate samples * Fix BigDecimal as well * Bump Gradle in generated Java projects to 6.7.1 (#8079) * Bump Gradle in Java projects from 6.0.1 to 6.7.1 Regular maintenance, 6.0.1 was released November 18th, 2019 and the latest release (November 16th, 2020) is 6.7.1. This updates all the wrapper templatesto the latest version. * Updated generated Java samples Generated via `./bin/generate-samples.sh bin/configs/java-*` * update samples Co-authored-by: William Cheng * [Java/okhttp] Add dynamic operations option (#7916) * Add dynamicOperations option to okhttp gen * Add tests * Add apiclient tests * Fix apiclient template * Add dependencies in gradle and sbt * [java] Generate "static final" instead "final static" (#8158) * Generate java code with "static final" instead "final static" * Regenerate code with "static final" * feat(#8038): add url encode feature to WebClient (#8171) * [java] Add setBearerToken method in okhttp-gson (#8200) * Add setBearerToken method in okhttp-gson * Update generated files * Use Map interface for configureApiKeys (#7982) * 7141: filter out problem+json mime type from JSON mime types fast tra… (#7976) * 7141: filter out problem+json mime type from JSON mime types fast tracked into the Accept header (resttemplate) * 7141: ran ensure-up-to-date * 7141: minimize changes with master (keep using isJsonMime for MediaType) * Migrate off deprecate Gradle configurations (#8436) A bunch of gradle configurations have been deprecated, with drop in replacements. Relevant to this project: compile -> implementation testCompile -> testImplementation They're visible by executing e.g. ./gradlew build --warning-mode all with supporting documentation here: https://docs.gradle.org/6.6.1/userguide/upgrading_version_5.html#dependencies_should_no_longer_be_declared_using_the_compile_and_runtime_configurations * [JAVA][Feign] Replace Apache oltu with scribejava (#8318) * - Replace apache oltu with scribejava - Implement the following authentication methods - ApiKey header - HTTP basic authentication - Oauth client credentials flow - Oauth Implicit flow - Oauth Pasword (deprecated) * Create class hierarchy for Oauth flows implementation * Add instructions of how to use the ApiClient to Readme.md * Update samples * Remove support for java 6 and 7 * Remove java 6 and 7 support from gradle * Format pom.xml * Remove empty line * Update samples * Remove oltu dependency from build.gradle and build.sbt. Replace oltu with ScribeJava Update samples * Update samples * Update samples * [JAVA][FEIGN]Implement unit tests for java-feign client (#8484) * Implement unit tests for feign client Implement tests Migrate to junit 5 * Default feign client does not support PATCH verb Default feign client does not support PATCH verb * Remove test for GET endpoint with request body * Configure junit in gradle build * Configure logback for unit tests * Add missing dependencies to sbt * Fix gradle dependency * Add logback to gradle unit test * Regenerate samples * Make junit test classes package private * Make junit test classes package private * Update samples * Organize imports * Organize imports * Implement useAbstractionForFiles for webclient library (#7567) * implement useAbstractionForFiles for webclient library * update doc Co-authored-by: William Cheng * remove supportJava6 option (#8514) * Fix #8492 - Use Vertx reference instead of static class (#8501) * [Java] fix generation for JavaTimeFormatter (#8348) * [Java] fix generation for JavaTimeFormatter * [Java] fix generation for JavaTimeFormatter * [Java] fix generation for JavaTimeFormatter * [Java] fix generation for JavaTimeFormatter * [Java] fix generation for JavaTimeFormatter * [Java] fix generation for JavaTimeFormatter * [Java] fix generation for JavaTimeFormatter * [Java] fix generation for JavaTimeFormatter * [Java] fix generation for JavaTimeFormatter * Upgraded dependency versions in okhttp generator. (#8604) Co-authored-by: Jens Oberender * FIX #8583 [BUG][JAVA] AbstractOpenApiSchema package (#8635) Fixed package declaration in AbstractOpenApiSchema.mustache template * Do not use context timezone. (#8614) * Fixed serialization of date-time query parameters. (#8616) * [JAVA][native] - Fix #8027 - import the auto generated supporting JSON class only when discriminator is needed (#8554) * Fix #8027 - import the auto generated supporting JSON class only when generateSupportingFiles is true * Fix #8027 - import the auto generated supporting JSON class only when generateSupportingFiles is true * Fix #8027 - import the auto generated supporting JSON class only when generateSupportingFiles is true * Revert "Fix #8027 - import the auto generated supporting JSON class only when generateSupportingFiles is true" This reverts commit 56e2b1fb * Revert "Fix #8027 - import the auto generated supporting JSON class only when generateSupportingFiles is true" This reverts commit 335c304d * Fix #8027 - import the auto generated supporting JSON class only when generateSupportingFiles is true * Fix #8027 - import the auto generated supporting JSON class only when discriminator is needed * Fix #8027 - import the auto generated supporting JSON class only when discriminator is needed * Fix #8027 - import the auto generated supporting JSON class only when discriminator is needed * [java native][dotnetcore] Implement QueryParameter deepObject style for client generators java native and dotnetcore. (#8563) * [Java][native] extend native ApiClient (#8557) * update jackson dependencies to address security issues (#8778) * update jackson to 2.12.1 (#8783) * [Java] use Files.createTempFile instead (#8787) * use Files.createTempFile * fix import * add missing import * FIX: Error in mustache.api (#8800) When a GET/PUT/POST operations includes queryParams, then the feign generator wrongly generates the Basename instead of the paramName. That leads to a java.illegalstateException ("Body parameters cannot be used with form parameters") in Feign Contract when attempting to invoke the Method. i.e: a generated feign client: public interface PersonClientTest extends RestApi { @RequestLine("GET /personen/{kundenNummer}?mitUnterstruktur={mitUnterstruktur}") @Headers({ "Accept: application/json", "If-None-Match: {ifNoneMatch}" }) PersonOut getPersonByKundenNummer(@Param(value="kundenNummer", expander=ParamExpander.class) String kundenNummer, @Param(value="If-None-Match", expander=ParamExpander.class) String ifNoneMatch, @Param(value="mitUnterstruktur", expander=ParamExpander.class) Boolean mitUnterstruktur); } in the headers: "If-None-Match: {ifNoneMatch}" but in the method: @Param(value="If-None-Match", expander=ParamExpander.class) String ifNoneMatch the value should be ifNoneMatch instead of "If-None-Match" * [Java][Client] JSON-B serialization support (#8729) * Added JSON-B support. * Mention jsonb in docs * [Java] Additional enum type annotations (#8389) * [Java] Additional enum type annotations * [Java] Additional enum type annotations * Add whitespace to SDK documentation where necessary (#8919) * Add a space between table title and the line above it to resolve issues when translating markdown to asciidoc * Regenerate Samples Co-authored-by: Tyler Ballast Co-authored-by: tballast * [Java][webclient] Fix deprecation warning: BodyInserters.fromObject (#8963) * Fix deprecation warning: BodyInserters.fromObject See for more information #8553 * [Java][webclient] Upgrade to spring 5.2.13 * fix deprecation warnings (#8969) * [Java][Server] fix default value (#8577) * [Java][Server] fix default value * [Java][Server] fix default value * fix: remove double URL encoding (#8660) DefaultWebClient() already encodes URL query parameters. * [Java] Update WebClient dependencies (#8972) * update webclient dependencies * update build.gradle * Apply template-patches/java-0002-custom-license-header.patch * Apply template-patches/java-0004-unescaped-descriptions.patch * Apply template-patches/java-0005-unstable-operations.patch * Apply template-patches/java-0007-operation-id-header.patch * Apply template-patches/java-0008-user-agent.patch * Apply template-patches/java-0009-document-auth.patch * Apply template-patches/java-0011-allow-unknown-properties.patch * Apply template-patches/java-0014-fix-multipart-requests.patch * Apply template-patches/java-0015-readme-links.patch * Apply template-patches/java-0016-remove-download-files.patch * Regenerate client from commit 7e667f1 of spec repo Co-authored-by: Jérémie Bresson Co-authored-by: William Cheng Co-authored-by: Benjamin Douglas Co-authored-by: Slavek Kabrda Co-authored-by: thecrazzymouse Co-authored-by: FlorianBruckner Co-authored-by: Quim Muntal Co-authored-by: Benjamin Simpson Co-authored-by: Davide Maestroni Co-authored-by: Michael Walser Co-authored-by: Thomas Joeissient Co-authored-by: gurumeditator Co-authored-by: Jochen Schalanda Co-authored-by: atsharp Co-authored-by: Fabio Kung Co-authored-by: Addy Naik <48064952+addynaik@users.noreply.github.com> Co-authored-by: Sai Giridhar P Co-authored-by: Jorge Rodriguez Co-authored-by: Eric Feliksik Co-authored-by: Min Kim <291271447@qq.com> Co-authored-by: Toby Murray Co-authored-by: Oleh Kurpiak Co-authored-by: Paul Gooderham Co-authored-by: Ties de Kock Co-authored-by: Sebastien Rosset Co-authored-by: sullis Co-authored-by: Bruno Coelho <4brunu@users.noreply.github.com> Co-authored-by: Filipe Manuel Couto Pinheiro Co-authored-by: Lukáš Vasek Co-authored-by: Esteban Gehring Co-authored-by: Hippolyte HENRY Co-authored-by: Nicholas Muesch Co-authored-by: Jim Schubert Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Akihito Nakano Co-authored-by: LoveIsGrief Co-authored-by: Ben Cox <1038350+ind1go@users.noreply.github.com> Co-authored-by: gaetPax <47664574+gaetPax@users.noreply.github.com> Co-authored-by: Jiri Kuncar Co-authored-by: Timo Rohrberg Co-authored-by: Igor Savin Co-authored-by: dwlabcube <46682038+dwlabcube@users.noreply.github.com> Co-authored-by: Clemens Angermann Co-authored-by: Chr1st0ph Co-authored-by: Christoph Preißner Co-authored-by: Erikmolin Co-authored-by: erikmolin Co-authored-by: sunn <33183834+etherealjoy@users.noreply.github.com> Co-authored-by: Herve DARRITCHON Co-authored-by: Johnny Peck Co-authored-by: Michele Albano Co-authored-by: Nikita Co-authored-by: Alexey Makhrov Co-authored-by: val Co-authored-by: Aleksandr Nekrasov Co-authored-by: Akira Tanimura Co-authored-by: Justin Co-authored-by: Justin Black Co-authored-by: Hui Yu Co-authored-by: Yutaka Miyamae <48900426+yutaka0m@users.noreply.github.com> Co-authored-by: Mateusz Szychowski (Muttley) Co-authored-by: Gonzalo Co-authored-by: ChristianCiach Co-authored-by: Bodo Graumann Co-authored-by: Yuriy Belenko Co-authored-by: Daniel Klessing Co-authored-by: copypasta-g <53397163+copypasta-g@users.noreply.github.com> Co-authored-by: Mahdi Dibaiee Co-authored-by: siada Co-authored-by: Samuel Hoffstaetter Co-authored-by: Esteban Gehring Co-authored-by: Jon Schoning Co-authored-by: Marcin Kubala Co-authored-by: anoohya-n <51289018+anoohya-n@users.noreply.github.com> Co-authored-by: Antoine Reilles Co-authored-by: Mostafa Moradian Co-authored-by: Adam Co-authored-by: Lars Hvam Co-authored-by: Vikrant Balyan Co-authored-by: Matt Traynham Co-authored-by: LEZIER-S2 <60382243+LEZIER-S2@users.noreply.github.com> Co-authored-by: Thomas Enderle Co-authored-by: YishTish Co-authored-by: Tomasz Prus Co-authored-by: Erica Kastner Co-authored-by: Richard Whitehouse Co-authored-by: valentin Bisson Co-authored-by: etherealjoy Co-authored-by: Hemant Zope <42613258+zhemant@users.noreply.github.com> Co-authored-by: Even André Fiskvik Co-authored-by: ehansen31 Co-authored-by: Timur Platonov Co-authored-by: Josh Burton Co-authored-by: Ilja leyberman <7ilya@gmx.de> Co-authored-by: Bouillie <34162532+Bouillie@users.noreply.github.com> Co-authored-by: Olivier Leonard Co-authored-by: tanmen Co-authored-by: Alex Buchkovsky Co-authored-by: Natan Laverde Co-authored-by: jburgess <11861789+jburgess@users.noreply.github.com> Co-authored-by: emileonhardt <40421857+emileonhardt@users.noreply.github.com> Co-authored-by: Jacob Floyd Co-authored-by: Igor Quirino Co-authored-by: Nico König Co-authored-by: https://gitlab.com/selankon Co-authored-by: Shweta Shukla <25539662+shwetashukla@users.noreply.github.com> Co-authored-by: Shweta Shukla Co-authored-by: Bartek Kowalik Co-authored-by: Shinya Sugmoto <34866626+gasugesu@users.noreply.github.com> Co-authored-by: Artem Shubovych Co-authored-by: Artem Shubovych Co-authored-by: Nicolas Homble Co-authored-by: Sebastian <63457660+sebohdev@users.noreply.github.com> Co-authored-by: Sebastian Ohm Co-authored-by: chandra-gh <63366477+chandra-gh@users.noreply.github.com> Co-authored-by: Chandra Yalangi Co-authored-by: Fabian Freund Co-authored-by: Erik Timmers Co-authored-by: Francisco A. Lozano Co-authored-by: Ukonn Ra <16066720+UkonnRa@users.noreply.github.com> Co-authored-by: Luis Ballabeni Co-authored-by: Luis Ballabeni Co-authored-by: Christophe Bornet Co-authored-by: Diogo Nunes Co-authored-by: Jon Freedman Co-authored-by: Vikrant Balyan (vvb) Co-authored-by: bgong-mdsol Co-authored-by: tgerth <39165556+tgerth@users.noreply.github.com> Co-authored-by: Jonathan Goldman Co-authored-by: Alois Klink Co-authored-by: Ravisankar-Challa Co-authored-by: Ravisankar Challa Co-authored-by: grzegorz-moto <60603738+grzegorz-moto@users.noreply.github.com> Co-authored-by: jekkel Co-authored-by: Moshe Elisha Co-authored-by: Benjamin Seiller Co-authored-by: TIm Clark Co-authored-by: mikesaurus <64160787+mikesaurus@users.noreply.github.com> Co-authored-by: Dmitry Mavrichev <68993831+dmavrichev@users.noreply.github.com> Co-authored-by: beytun Co-authored-by: Aljaž Pavišič Co-authored-by: Chuckledog Co-authored-by: Jan Meznaric Co-authored-by: Niels Pardon Co-authored-by: Patouche Co-authored-by: Robin Eggenkamp Co-authored-by: dtiller <3858971+dtiller@users.noreply.github.com> Co-authored-by: Philipp Paris Co-authored-by: Thomas Hervé Co-authored-by: David Ruppelt <44848632+druppelt@users.noreply.github.com> Co-authored-by: Toby Murray Co-authored-by: agilob Co-authored-by: Tivadar Bocz Co-authored-by: Arnaud Jeansen Co-authored-by: Hugo Alves Co-authored-by: iyzana <16743652+iyzana@users.noreply.github.com> Co-authored-by: Ricardo Zanini <1538000+ricardozanini@users.noreply.github.com> Co-authored-by: Jens Oberender <1905126+burberius@users.noreply.github.com> Co-authored-by: Jens Oberender Co-authored-by: Benjamin Klatt Co-authored-by: Reinhard-PTV <77726540+Reinhard-PTV@users.noreply.github.com> Co-authored-by: nitschy Co-authored-by: Dheeraj Nalluri Co-authored-by: Tyler Ballast Co-authored-by: Tyler Ballast Co-authored-by: tballast Co-authored-by: Backfighter Co-authored-by: David Gerber Co-authored-by: api-clients-generation-pipeline[bot] <54105614+api-clients-generation-pipeline[bot]@users.noreply.github.com> Co-authored-by: ci.datadog-api-spec --- .apigentools-info | 8 +- .generator/templates/ApiClient.mustache | 905 +++++++++ .../BeanValidationException.mustache | 27 + .generator/templates/Configuration.mustache | 28 + .../CustomInstantDeserializer.mustache | 232 +++ .generator/templates/JSON.mustache | 539 ++++++ .../templates/JavaTimeFormatter.mustache | 60 + .generator/templates/Pair.mustache | 50 + .generator/templates/README.mustache | 50 + .../templates/RFC3339DateFormat.mustache | 44 + .../templates/ServerConfiguration.mustache | 58 + .generator/templates/ServerVariable.mustache | 23 + .generator/templates/StringUtil.mustache | 72 + .../additionalEnumTypeAnnotations.mustache | 2 + .../additionalModelTypeAnnotations.mustache | 2 + .generator/templates/api.mustache | 122 ++ .generator/templates/apiException.mustache | 80 + .generator/templates/apiOperation.mustache | 28 + .generator/templates/api_doc.mustache | 108 ++ .generator/templates/api_test.mustache | 51 + .generator/templates/auth/ApiKeyAuth.mustache | 66 + .../templates/auth/Authentication.mustache | 19 + .../templates/auth/HttpBasicAuth.mustache | 60 + .../templates/auth/HttpBearerAuth.mustache | 49 + .generator/templates/auth/OAuth.mustache | 28 + .generator/templates/auth/OAuthFlow.mustache | 11 + .generator/templates/beanValidation.mustache | 16 + .../templates/beanValidationCore.mustache | 20 + .../beanValidationQueryParams.mustache | 1 + .generator/templates/build.gradle.mustache | 167 ++ .generator/templates/build.sbt.mustache | 1 + .generator/templates/enum_outer_doc.mustache | 7 + .../templates/generatedAnnotation.mustache | 1 + .generator/templates/git_push.sh.mustache | 58 + .generator/templates/gitignore.mustache | 21 + .generator/templates/gradle-wrapper.jar | Bin 0 -> 59203 bytes .../gradle-wrapper.properties.mustache | 5 + .../templates/gradle.properties.mustache | 2 + .generator/templates/gradlew.bat.mustache | 89 + .generator/templates/gradlew.mustache | 185 ++ .../templates/jackson_annotations.mustache | 19 + .../libraries/feign/ApiClient.mustache | 338 ++++ .../libraries/feign/EncodingUtils.mustache | 86 + .../libraries/feign/ParamExpander.mustache | 22 + .../templates/libraries/feign/README.mustache | 77 + .../templates/libraries/feign/api.mustache | 105 ++ .../libraries/feign/api_test.mustache | 70 + .../libraries/feign/auth/ApiKeyAuth.mustache | 43 + .../feign/auth/DefaultApi20Impl.mustache | 47 + .../feign/auth/HttpBasicAuth.mustache | 41 + .../feign/auth/HttpBearerAuth.mustache | 43 + .../libraries/feign/auth/OAuth.mustache | 81 + .../auth/OauthClientCredentialsGrant.mustache | 39 + .../feign/auth/OauthPasswordGrant.mustache | 48 + .../libraries/feign/build.gradle.mustache | 151 ++ .../libraries/feign/build.sbt.mustache | 34 + .../libraries/feign/model_test.mustache | 48 + .../templates/libraries/feign/pom.mustache | 379 ++++ .../google-api-client/ApiClient.mustache | 116 ++ .../libraries/google-api-client/api.mustache | 190 ++ .../google-api-client/api_test.mustache | 45 + .../google-api-client/build.gradle.mustache | 152 ++ .../google-api-client/build.sbt.mustache | 34 + .../libraries/google-api-client/pom.mustache | 335 ++++ .../jersey2/AbstractOpenApiSchema.mustache | 138 ++ .../libraries/jersey2/ApiClient.mustache | 1375 ++++++++++++++ .../libraries/jersey2/ApiResponse.mustache | 73 + .../templates/libraries/jersey2/JSON.mustache | 277 +++ .../jersey2/additional_properties.mustache | 39 + .../libraries/jersey2/anyof_model.mustache | 202 ++ .../templates/libraries/jersey2/api.mustache | 273 +++ .../libraries/jersey2/apiException.mustache | 99 + .../libraries/jersey2/api_doc.mustache | 122 ++ .../libraries/jersey2/api_test.mustache | 56 + .../jersey2/auth/ApiKeyAuth.mustache | 68 + .../jersey2/auth/Authentication.mustache | 22 + .../jersey2/auth/HttpBasicAuth.mustache | 62 + .../jersey2/auth/HttpBearerAuth.mustache | 51 + .../jersey2/auth/HttpSignatureAuth.mustache | 269 +++ .../libraries/jersey2/auth/OAuth.mustache | 182 ++ .../libraries/jersey2/auth/OAuthFlow.mustache | 7 + .../libraries/jersey2/build.gradle.mustache | 166 ++ .../libraries/jersey2/build.sbt.mustache | 43 + .../libraries/jersey2/model.mustache | 61 + .../jersey2/model_anyof_doc.mustache | 38 + .../libraries/jersey2/model_doc.mustache | 19 + .../jersey2/model_oneof_doc.mustache | 38 + .../libraries/jersey2/oneof_model.mustache | 235 +++ .../templates/libraries/jersey2/pojo.mustache | 386 ++++ .../templates/libraries/jersey2/pom.mustache | 391 ++++ .../libraries/microprofile/README.mustache | 10 + .../libraries/microprofile/api.mustache | 61 + .../microprofile/api_exception.mustache | 23 + .../api_exception_mapper.mustache | 22 + .../libraries/microprofile/api_test.mustache | 75 + .../microprofile/beanValidation.mustache | 4 + .../microprofile/beanValidationCore.mustache | 20 + .../beanValidationHeaderParams.mustache | 1 + .../beanValidationPathParams.mustache | 1 + .../beanValidationQueryParams.mustache | 1 + .../microprofile/bodyParams.mustache | 1 + .../microprofile/bodyParamsImpl.mustache | 1 + .../libraries/microprofile/enumClass.mustache | 66 + .../microprofile/enumOuterClass.mustache | 48 + .../microprofile/formParams.mustache | 1 + .../microprofile/formParamsImpl.mustache | 1 + .../microprofile/generatedAnnotation.mustache | 1 + .../microprofile/headerParams.mustache | 1 + .../microprofile/headerParamsImpl.mustache | 1 + .../microprofile/kumuluzee.beans.xml.mustache | 5 + .../kumuluzee.config.yaml.mustache | 10 + .../microprofile/kumuluzee.pom.mustache | 98 + .../microprofile/licenseInfo.mustache | 11 + .../libraries/microprofile/model.mustache | 23 + .../microprofile/pathParams.mustache | 1 + .../microprofile/pathParamsImpl.mustache | 1 + .../libraries/microprofile/pojo.mustache | 147 ++ .../libraries/microprofile/pom.mustache | 183 ++ .../microprofile/queryParams.mustache | 1 + .../microprofile/queryParamsImpl.mustache | 1 + .../microprofile/returnTypes.mustache | 4 + .../native/AbstractOpenApiSchema.mustache | 138 ++ .../libraries/native/ApiClient.mustache | 389 ++++ .../libraries/native/ApiResponse.mustache | 58 + .../templates/libraries/native/JSON.mustache | 276 +++ .../libraries/native/README.mustache | 178 ++ .../native/additional_properties.mustache | 39 + .../libraries/native/anyof_model.mustache | 202 ++ .../templates/libraries/native/api.mustache | 392 ++++ .../libraries/native/apiException.mustache | 79 + .../libraries/native/api_doc.mustache | 280 +++ .../libraries/native/api_test.mustache | 59 + .../libraries/native/build.gradle.mustache | 76 + .../native/generatedAnnotation.mustache | 1 + .../native/gradle.properties.mustache | 0 .../templates/libraries/native/model.mustache | 60 + .../libraries/native/model_anyof_doc.mustache | 38 + .../libraries/native/model_doc.mustache | 19 + .../libraries/native/model_oneof_doc.mustache | 38 + .../libraries/native/oneof_model.mustache | 235 +++ .../templates/libraries/native/pojo.mustache | 389 ++++ .../templates/libraries/native/pom.mustache | 247 +++ .../libraries/native/travis.mustache | 16 + .../okhttp-gson/ApiCallback.mustache | 51 + .../libraries/okhttp-gson/ApiClient.mustache | 1617 +++++++++++++++++ .../okhttp-gson/ApiResponse.mustache | 58 + .../GzipRequestInterceptor.mustache | 74 + .../okhttp-gson/ProgressRequestBody.mustache | 62 + .../okhttp-gson/ProgressResponseBody.mustache | 61 + .../libraries/okhttp-gson/README.mustache | 176 ++ .../libraries/okhttp-gson/api.mustache | 481 +++++ .../okhttp-gson/apiException.mustache | 96 + .../libraries/okhttp-gson/api_doc.mustache | 106 ++ .../libraries/okhttp-gson/api_test.mustache | 47 + .../okhttp-gson/auth/HttpBasicAuth.mustache | 43 + .../auth/OAuthOkHttpClient.mustache | 70 + .../okhttp-gson/auth/RetryingOAuth.mustache | 183 ++ .../okhttp-gson/build.gradle.mustache | 142 ++ .../libraries/okhttp-gson/build.sbt.mustache | 36 + .../libraries/okhttp-gson/pom.mustache | 348 ++++ .../libraries/rest-assured/ApiClient.mustache | 62 + .../rest-assured/GsonObjectMapper.mustache | 30 + .../rest-assured/JacksonObjectMapper.mustache | 68 + .../libraries/rest-assured/Oper.mustache | 13 + .../libraries/rest-assured/README.mustache | 43 + .../ResponseSpecBuilders.mustache | 31 + .../libraries/rest-assured/api.mustache | 266 +++ .../libraries/rest-assured/api_doc.mustache | 62 + .../libraries/rest-assured/api_test.mustache | 66 + .../rest-assured/build.gradle.mustache | 168 ++ .../libraries/rest-assured/build.sbt.mustache | 57 + .../libraries/rest-assured/pom.mustache | 370 ++++ .../libraries/resteasy/ApiClient.mustache | 767 ++++++++ .../libraries/resteasy/JSON.mustache | 56 + .../templates/libraries/resteasy/api.mustache | 114 ++ .../libraries/resteasy/build.gradle.mustache | 146 ++ .../libraries/resteasy/build.sbt.mustache | 32 + .../templates/libraries/resteasy/pom.mustache | 299 +++ .../libraries/resttemplate/ApiClient.mustache | 816 +++++++++ .../libraries/resttemplate/api.mustache | 151 ++ .../libraries/resttemplate/api_test.mustache | 44 + .../resttemplate/auth/ApiKeyAuth.mustache | 62 + .../resttemplate/auth/Authentication.mustache | 14 + .../resttemplate/auth/HttpBasicAuth.mustache | 39 + .../resttemplate/auth/HttpBearerAuth.mustache | 38 + .../resttemplate/auth/OAuth.mustache | 24 + .../resttemplate/auth/OAuthFlow.mustache | 5 + .../resttemplate/build.gradle.mustache | 151 ++ .../libraries/resttemplate/pom.mustache | 333 ++++ .../libraries/retrofit/ApiClient.mustache | 448 +++++ .../retrofit/CollectionFormats.mustache | 99 + .../libraries/retrofit/README.mustache | 43 + .../templates/libraries/retrofit/api.mustache | 62 + .../libraries/retrofit/api_test.mustache | 44 + .../retrofit/auth/ApiKeyAuth.mustache | 72 + .../retrofit/auth/HttpBasicAuth.mustache | 49 + .../retrofit/auth/HttpBearerAuth.mustache | 42 + .../libraries/retrofit/auth/OAuth.mustache | 185 ++ .../retrofit/auth/OAuthOkHttpClient.mustache | 69 + .../libraries/retrofit/bodyParams.mustache | 1 + .../libraries/retrofit/build.gradle.mustache | 127 ++ .../libraries/retrofit/build.sbt.mustache | 24 + .../libraries/retrofit/formParams.mustache | 1 + .../libraries/retrofit/headerParams.mustache | 1 + .../libraries/retrofit/pathParams.mustache | 1 + .../templates/libraries/retrofit/pom.mustache | 295 +++ .../libraries/retrofit/queryParams.mustache | 1 + .../libraries/retrofit2/ApiClient.mustache | 467 +++++ .../retrofit2/CollectionFormats.mustache | 99 + .../libraries/retrofit2/JSON.mustache | 448 +++++ .../libraries/retrofit2/README.mustache | 39 + .../libraries/retrofit2/api.mustache | 83 + .../libraries/retrofit2/api_test.mustache | 46 + .../retrofit2/auth/ApiKeyAuth.mustache | 72 + .../retrofit2/auth/HttpBasicAuth.mustache | 50 + .../retrofit2/auth/HttpBearerAuth.mustache | 42 + .../libraries/retrofit2/auth/OAuth.mustache | 185 ++ .../retrofit2/auth/OAuthOkHttpClient.mustache | 72 + .../libraries/retrofit2/bodyParams.mustache | 1 + .../libraries/retrofit2/build.gradle.mustache | 195 ++ .../libraries/retrofit2/build.sbt.mustache | 58 + .../libraries/retrofit2/formParams.mustache | 1 + .../retrofit2/formParams.mustache.save | 1 + .../libraries/retrofit2/headerParams.mustache | 1 + .../libraries/retrofit2/pathParams.mustache | 1 + .../play-common/auth/ApiKeyAuth.mustache | 69 + .../retrofit2/play24/ApiClient.mustache | 146 ++ .../play24/Play24CallAdapterFactory.mustache | 100 + .../play24/Play24CallFactory.mustache | 254 +++ .../libraries/retrofit2/play24/api.mustache | 59 + .../retrofit2/play25/ApiClient.mustache | 145 ++ .../play25/Play25CallAdapterFactory.mustache | 117 ++ .../play25/Play25CallFactory.mustache | 264 +++ .../libraries/retrofit2/play25/api.mustache | 59 + .../retrofit2/play26/ApiClient.mustache | 214 +++ .../play26/Play26CallAdapterFactory.mustache | 116 ++ .../play26/Play26CallFactory.mustache | 294 +++ .../libraries/retrofit2/play26/api.mustache | 59 + .../libraries/retrofit2/pom.mustache | 446 +++++ .../libraries/retrofit2/queryParams.mustache | 1 + .../libraries/vertx/ApiClient.mustache | 739 ++++++++ .../libraries/vertx/Configuration.mustache | 42 + .../templates/libraries/vertx/api.mustache | 22 + .../libraries/vertx/apiException.mustache | 110 ++ .../libraries/vertx/apiImpl.mustache | 121 ++ .../libraries/vertx/api_test.mustache | 70 + .../libraries/vertx/auth/ApiKeyAuth.mustache | 66 + .../vertx/auth/Authentication.mustache | 19 + .../vertx/auth/HttpBasicAuth.mustache | 40 + .../vertx/auth/HttpBearerAuth.mustache | 39 + .../libraries/vertx/auth/OAuth.mustache | 28 + .../libraries/vertx/auth/OAuthFlow.mustache | 7 + .../libraries/vertx/build.gradle.mustache | 66 + .../templates/libraries/vertx/pom.mustache | 315 ++++ .../libraries/vertx/rxApiImpl.mustache | 87 + .../libraries/webclient/ApiClient.mustache | 664 +++++++ .../libraries/webclient/api.mustache | 132 ++ .../libraries/webclient/api_test.mustache | 41 + .../webclient/auth/ApiKeyAuth.mustache | 62 + .../webclient/auth/Authentication.mustache | 14 + .../webclient/auth/HttpBasicAuth.mustache | 39 + .../webclient/auth/HttpBearerAuth.mustache | 39 + .../libraries/webclient/auth/OAuth.mustache | 24 + .../webclient/auth/OAuthFlow.mustache | 5 + .../libraries/webclient/build.gradle.mustache | 165 ++ .../libraries/webclient/pom.mustache | 166 ++ .generator/templates/licenseInfo.mustache | 9 + .generator/templates/manifest.mustache | 3 + .generator/templates/model.mustache | 54 + .generator/templates/modelEnum.mustache | 100 + .generator/templates/modelInnerEnum.mustache | 95 + .generator/templates/model_doc.mustache | 4 + .generator/templates/model_test.mustache | 50 + .generator/templates/oneof_interface.mustache | 6 + .generator/templates/openapi.mustache | 1 + .generator/templates/pojo.mustache | 348 ++++ .generator/templates/pojo_doc.mustache | 37 + .generator/templates/pom.mustache | 373 ++++ .generator/templates/settings.gradle.mustache | 1 + .generator/templates/travis.mustache | 22 + .../templates/typeInfoAnnotation.mustache | 16 + .generator/templates/xmlAnnotation.mustache | 6 + api_docs/v1/APIErrorResponse.md | 1 + api_docs/v1/AWSAccount.md | 1 + api_docs/v1/AWSAccountAndLambdaRequest.md | 1 + api_docs/v1/AWSAccountCreateResponse.md | 1 + api_docs/v1/AWSAccountListResponse.md | 1 + api_docs/v1/AWSLogsAsyncError.md | 1 + api_docs/v1/AWSLogsAsyncResponse.md | 1 + api_docs/v1/AWSLogsLambda.md | 1 + api_docs/v1/AWSLogsListResponse.md | 1 + api_docs/v1/AWSLogsListServicesResponse.md | 1 + api_docs/v1/AWSLogsServicesRequest.md | 1 + api_docs/v1/AWSTagFilter.md | 1 + api_docs/v1/AWSTagFilterCreateRequest.md | 1 + api_docs/v1/AWSTagFilterDeleteRequest.md | 1 + api_docs/v1/AWSTagFilterListResponse.md | 1 + api_docs/v1/AlertGraphWidgetDefinition.md | 1 + api_docs/v1/AlertValueWidgetDefinition.md | 1 + api_docs/v1/ApiKey.md | 1 + api_docs/v1/ApiKeyListResponse.md | 1 + api_docs/v1/ApiKeyResponse.md | 1 + api_docs/v1/ApmStatsQueryColumnType.md | 1 + api_docs/v1/ApmStatsQueryDefinition.md | 1 + api_docs/v1/ApplicationKey.md | 1 + api_docs/v1/ApplicationKeyListResponse.md | 1 + api_docs/v1/ApplicationKeyResponse.md | 1 + .../v1/AuthenticationValidationResponse.md | 1 + api_docs/v1/AzureAccount.md | 1 + api_docs/v1/CancelDowntimesByScopeRequest.md | 1 + api_docs/v1/CanceledDowntimesIds.md | 1 + api_docs/v1/ChangeWidgetDefinition.md | 1 + api_docs/v1/ChangeWidgetRequest.md | 1 + api_docs/v1/CheckCanDeleteMonitorResponse.md | 1 + .../v1/CheckCanDeleteMonitorResponseData.md | 1 + api_docs/v1/CheckCanDeleteSLOResponse.md | 1 + api_docs/v1/CheckCanDeleteSLOResponseData.md | 1 + api_docs/v1/CheckStatusWidgetDefinition.md | 1 + api_docs/v1/Creator.md | 1 + api_docs/v1/Dashboard.md | 1 + api_docs/v1/DashboardDeleteResponse.md | 1 + api_docs/v1/DashboardList.md | 1 + api_docs/v1/DashboardListDeleteResponse.md | 1 + api_docs/v1/DashboardListListResponse.md | 1 + api_docs/v1/DashboardSummary.md | 1 + api_docs/v1/DashboardSummaryDefinition.md | 1 + api_docs/v1/DashboardTemplateVariable.md | 1 + .../v1/DashboardTemplateVariablePreset.md | 1 + .../DashboardTemplateVariablePresetValue.md | 1 + api_docs/v1/DeletedMonitor.md | 1 + api_docs/v1/DistributionWidgetDefinition.md | 1 + api_docs/v1/DistributionWidgetRequest.md | 1 + api_docs/v1/Downtime.md | 1 + api_docs/v1/DowntimeRecurrence.md | 1 + api_docs/v1/Event.md | 1 + api_docs/v1/EventListResponse.md | 1 + api_docs/v1/EventQueryDefinition.md | 1 + api_docs/v1/EventResponse.md | 1 + api_docs/v1/EventStreamWidgetDefinition.md | 1 + api_docs/v1/EventTimelineWidgetDefinition.md | 1 + .../FormulaAndFunctionEventQueryDefinition.md | 1 + ...aAndFunctionEventQueryDefinitionCompute.md | 1 + ...laAndFunctionEventQueryDefinitionSearch.md | 1 + .../v1/FormulaAndFunctionEventQueryGroupBy.md | 1 + ...FormulaAndFunctionEventQueryGroupBySort.md | 1 + ...FormulaAndFunctionMetricQueryDefinition.md | 1 + ...ormulaAndFunctionProcessQueryDefinition.md | 1 + api_docs/v1/FreeTextWidgetDefinition.md | 1 + api_docs/v1/GCPAccount.md | 1 + api_docs/v1/GeomapWidgetDefinition.md | 1 + api_docs/v1/GeomapWidgetDefinitionStyle.md | 1 + api_docs/v1/GeomapWidgetDefinitionView.md | 1 + api_docs/v1/GeomapWidgetRequest.md | 1 + api_docs/v1/GraphSnapshot.md | 1 + api_docs/v1/GroupWidgetDefinition.md | 1 + api_docs/v1/HeatMapWidgetDefinition.md | 1 + api_docs/v1/HeatMapWidgetRequest.md | 1 + api_docs/v1/Host.md | 1 + api_docs/v1/HostListResponse.md | 1 + api_docs/v1/HostMapRequest.md | 1 + api_docs/v1/HostMapWidgetDefinition.md | 1 + .../v1/HostMapWidgetDefinitionRequests.md | 1 + api_docs/v1/HostMapWidgetDefinitionStyle.md | 1 + api_docs/v1/HostMeta.md | 1 + api_docs/v1/HostMetrics.md | 1 + api_docs/v1/HostMuteResponse.md | 1 + api_docs/v1/HostMuteSettings.md | 1 + api_docs/v1/HostTags.md | 1 + api_docs/v1/HostTotals.md | 1 + api_docs/v1/IFrameWidgetDefinition.md | 1 + api_docs/v1/IPPrefixesAPI.md | 1 + api_docs/v1/IPPrefixesAPM.md | 1 + api_docs/v1/IPPrefixesAgents.md | 1 + api_docs/v1/IPPrefixesLogs.md | 1 + api_docs/v1/IPPrefixesProcess.md | 1 + api_docs/v1/IPPrefixesSynthetics.md | 1 + api_docs/v1/IPPrefixesWebhooks.md | 1 + api_docs/v1/IPRanges.md | 1 + api_docs/v1/IdpFormData.md | 1 + api_docs/v1/IdpResponse.md | 1 + api_docs/v1/ImageWidgetDefinition.md | 1 + api_docs/v1/Log.md | 1 + api_docs/v1/LogContent.md | 1 + api_docs/v1/LogQueryDefinition.md | 1 + api_docs/v1/LogQueryDefinitionGroupBy.md | 1 + api_docs/v1/LogQueryDefinitionGroupBySort.md | 1 + api_docs/v1/LogQueryDefinitionSearch.md | 1 + api_docs/v1/LogStreamWidgetDefinition.md | 1 + api_docs/v1/LogsAPIError.md | 1 + api_docs/v1/LogsAPIErrorResponse.md | 1 + api_docs/v1/LogsArithmeticProcessor.md | 1 + api_docs/v1/LogsAttributeRemapper.md | 1 + api_docs/v1/LogsCategoryProcessor.md | 1 + api_docs/v1/LogsCategoryProcessorCategory.md | 1 + api_docs/v1/LogsDateRemapper.md | 1 + api_docs/v1/LogsExclusion.md | 1 + api_docs/v1/LogsExclusionFilter.md | 1 + api_docs/v1/LogsFilter.md | 1 + api_docs/v1/LogsGeoIPParser.md | 1 + api_docs/v1/LogsGrokParser.md | 1 + api_docs/v1/LogsGrokParserRules.md | 1 + api_docs/v1/LogsIndex.md | 1 + api_docs/v1/LogsIndexListResponse.md | 1 + api_docs/v1/LogsIndexUpdateRequest.md | 1 + api_docs/v1/LogsIndexesOrder.md | 1 + api_docs/v1/LogsListRequest.md | 1 + api_docs/v1/LogsListRequestTime.md | 1 + api_docs/v1/LogsListResponse.md | 1 + api_docs/v1/LogsLookupProcessor.md | 1 + api_docs/v1/LogsMessageRemapper.md | 1 + api_docs/v1/LogsPipeline.md | 1 + api_docs/v1/LogsPipelineProcessor.md | 1 + api_docs/v1/LogsPipelinesOrder.md | 1 + api_docs/v1/LogsQueryCompute.md | 1 + api_docs/v1/LogsServiceRemapper.md | 1 + api_docs/v1/LogsStatusRemapper.md | 1 + api_docs/v1/LogsStringBuilderProcessor.md | 1 + api_docs/v1/LogsTraceRemapper.md | 1 + api_docs/v1/LogsURLParser.md | 1 + api_docs/v1/LogsUserAgentParser.md | 1 + api_docs/v1/MetricMetadata.md | 1 + api_docs/v1/MetricSearchResponse.md | 1 + api_docs/v1/MetricSearchResponseResults.md | 1 + api_docs/v1/MetricsListResponse.md | 1 + api_docs/v1/MetricsQueryMetadata.md | 1 + api_docs/v1/MetricsQueryResponse.md | 1 + api_docs/v1/MetricsQueryUnit.md | 1 + api_docs/v1/Monitor.md | 1 + api_docs/v1/MonitorOptions.md | 1 + api_docs/v1/MonitorOptionsAggregation.md | 1 + api_docs/v1/MonitorState.md | 1 + api_docs/v1/MonitorStateGroup.md | 1 + api_docs/v1/MonitorSummaryWidgetDefinition.md | 1 + api_docs/v1/MonitorThresholdWindowOptions.md | 1 + api_docs/v1/MonitorThresholds.md | 1 + api_docs/v1/MonitorUpdateRequest.md | 1 + api_docs/v1/NoteWidgetDefinition.md | 1 + api_docs/v1/Organization.md | 1 + api_docs/v1/OrganizationBilling.md | 1 + api_docs/v1/OrganizationCreateBody.md | 1 + api_docs/v1/OrganizationCreateResponse.md | 1 + api_docs/v1/OrganizationListResponse.md | 1 + api_docs/v1/OrganizationResponse.md | 1 + api_docs/v1/OrganizationSettings.md | 1 + api_docs/v1/OrganizationSettingsSaml.md | 1 + ...ationSettingsSamlAutocreateUsersDomains.md | 1 + ...ganizationSettingsSamlIdpInitiatedLogin.md | 1 + .../v1/OrganizationSettingsSamlStrictMode.md | 1 + api_docs/v1/OrganizationSubscription.md | 1 + api_docs/v1/PagerDutyService.md | 1 + api_docs/v1/PagerDutyServiceKey.md | 1 + api_docs/v1/PagerDutyServiceName.md | 1 + api_docs/v1/ProcessQueryDefinition.md | 1 + api_docs/v1/QueryValueWidgetDefinition.md | 1 + api_docs/v1/QueryValueWidgetRequest.md | 1 + api_docs/v1/SLOBulkDeleteError.md | 1 + api_docs/v1/SLOBulkDeleteResponse.md | 1 + api_docs/v1/SLOBulkDeleteResponseData.md | 1 + api_docs/v1/SLOCorrection.md | 1 + api_docs/v1/SLOCorrectionCreateData.md | 1 + api_docs/v1/SLOCorrectionCreateRequest.md | 1 + .../SLOCorrectionCreateRequestAttributes.md | 1 + api_docs/v1/SLOCorrectionListResponse.md | 1 + api_docs/v1/SLOCorrectionResponse.md | 1 + .../v1/SLOCorrectionResponseAttributes.md | 1 + api_docs/v1/SLOCorrectionUpdateData.md | 1 + api_docs/v1/SLOCorrectionUpdateRequest.md | 1 + .../SLOCorrectionUpdateRequestAttributes.md | 1 + api_docs/v1/SLODeleteResponse.md | 1 + api_docs/v1/SLOHistoryMetrics.md | 1 + api_docs/v1/SLOHistoryMetricsSeries.md | 1 + .../v1/SLOHistoryMetricsSeriesMetadata.md | 1 + .../v1/SLOHistoryMetricsSeriesMetadataUnit.md | 1 + api_docs/v1/SLOHistoryResponse.md | 1 + api_docs/v1/SLOHistoryResponseData.md | 1 + api_docs/v1/SLOHistoryResponseError.md | 1 + api_docs/v1/SLOHistorySLIData.md | 1 + api_docs/v1/SLOListResponse.md | 1 + api_docs/v1/SLOResponse.md | 1 + api_docs/v1/SLOThreshold.md | 1 + api_docs/v1/SLOWidgetDefinition.md | 1 + api_docs/v1/ScatterPlotRequest.md | 1 + api_docs/v1/ScatterPlotWidgetDefinition.md | 1 + .../v1/ScatterPlotWidgetDefinitionRequests.md | 1 + api_docs/v1/ServiceLevelObjective.md | 1 + api_docs/v1/ServiceLevelObjectiveQuery.md | 1 + api_docs/v1/ServiceLevelObjectiveRequest.md | 1 + api_docs/v1/ServiceMapWidgetDefinition.md | 1 + api_docs/v1/ServiceSummaryWidgetDefinition.md | 1 + api_docs/v1/SlackIntegrationChannel.md | 1 + api_docs/v1/SlackIntegrationChannelDisplay.md | 1 + api_docs/v1/SyntheticsAPIStep.md | 1 + api_docs/v1/SyntheticsAPITest.md | 1 + api_docs/v1/SyntheticsAPITestConfig.md | 1 + api_docs/v1/SyntheticsAPITestResultData.md | 1 + api_docs/v1/SyntheticsAPITestResultFull.md | 1 + .../v1/SyntheticsAPITestResultFullCheck.md | 1 + api_docs/v1/SyntheticsAPITestResultShort.md | 1 + .../v1/SyntheticsAPITestResultShortResult.md | 1 + .../v1/SyntheticsAssertionJSONPathTarget.md | 1 + ...SyntheticsAssertionJSONPathTargetTarget.md | 1 + api_docs/v1/SyntheticsAssertionTarget.md | 1 + api_docs/v1/SyntheticsBasicAuth.md | 1 + api_docs/v1/SyntheticsBrowserError.md | 1 + api_docs/v1/SyntheticsBrowserTest.md | 1 + api_docs/v1/SyntheticsBrowserTestConfig.md | 1 + .../v1/SyntheticsBrowserTestResultData.md | 1 + .../v1/SyntheticsBrowserTestResultFull.md | 1 + .../SyntheticsBrowserTestResultFullCheck.md | 1 + .../v1/SyntheticsBrowserTestResultShort.md | 1 + .../SyntheticsBrowserTestResultShortResult.md | 1 + api_docs/v1/SyntheticsBrowserVariable.md | 1 + api_docs/v1/SyntheticsCITest.md | 1 + api_docs/v1/SyntheticsCITestBody.md | 1 + api_docs/v1/SyntheticsCITestMetadata.md | 1 + api_docs/v1/SyntheticsCITestMetadataCi.md | 1 + api_docs/v1/SyntheticsCITestMetadataGit.md | 1 + api_docs/v1/SyntheticsConfigVariable.md | 1 + api_docs/v1/SyntheticsCoreWebVitals.md | 1 + api_docs/v1/SyntheticsDeleteTestsPayload.md | 1 + api_docs/v1/SyntheticsDeleteTestsResponse.md | 1 + api_docs/v1/SyntheticsDeletedTest.md | 1 + api_docs/v1/SyntheticsDevice.md | 1 + ...ntheticsGetAPITestLatestResultsResponse.md | 1 + ...ticsGetBrowserTestLatestResultsResponse.md | 1 + api_docs/v1/SyntheticsGlobalVariable.md | 1 + ...yntheticsGlobalVariableParseTestOptions.md | 1 + api_docs/v1/SyntheticsGlobalVariableValue.md | 1 + api_docs/v1/SyntheticsListTestsResponse.md | 1 + api_docs/v1/SyntheticsLocation.md | 1 + api_docs/v1/SyntheticsLocations.md | 1 + api_docs/v1/SyntheticsParsingOptions.md | 1 + api_docs/v1/SyntheticsPrivateLocation.md | 1 + ...ntheticsPrivateLocationCreationResponse.md | 1 + ...ocationCreationResponseResultEncryption.md | 1 + .../v1/SyntheticsPrivateLocationSecrets.md | 1 + ...icsPrivateLocationSecretsAuthentication.md | 1 + ...sPrivateLocationSecretsConfigDecryption.md | 1 + api_docs/v1/SyntheticsSSLCertificate.md | 1 + api_docs/v1/SyntheticsSSLCertificateIssuer.md | 1 + .../v1/SyntheticsSSLCertificateSubject.md | 1 + api_docs/v1/SyntheticsStep.md | 1 + api_docs/v1/SyntheticsStepDetail.md | 1 + api_docs/v1/SyntheticsStepDetailWarning.md | 1 + api_docs/v1/SyntheticsTestConfig.md | 1 + api_docs/v1/SyntheticsTestDetails.md | 1 + api_docs/v1/SyntheticsTestOptions.md | 1 + .../v1/SyntheticsTestOptionsMonitorOptions.md | 1 + api_docs/v1/SyntheticsTestOptionsRetry.md | 1 + api_docs/v1/SyntheticsTestRequest.md | 1 + .../v1/SyntheticsTestRequestCertificate.md | 1 + .../SyntheticsTestRequestCertificateItem.md | 1 + api_docs/v1/SyntheticsTiming.md | 1 + .../v1/SyntheticsTriggerCITestLocation.md | 1 + .../v1/SyntheticsTriggerCITestRunResult.md | 1 + .../v1/SyntheticsTriggerCITestsResponse.md | 1 + .../SyntheticsUpdateTestPauseStatusPayload.md | 1 + api_docs/v1/SyntheticsVariableParser.md | 1 + api_docs/v1/TableWidgetDefinition.md | 1 + api_docs/v1/TableWidgetRequest.md | 1 + api_docs/v1/TagToHosts.md | 1 + api_docs/v1/TimeseriesWidgetDefinition.md | 1 + .../v1/TimeseriesWidgetExpressionAlias.md | 1 + api_docs/v1/TimeseriesWidgetRequest.md | 1 + api_docs/v1/ToplistWidgetDefinition.md | 1 + api_docs/v1/ToplistWidgetRequest.md | 1 + api_docs/v1/UsageAnalyzedLogsHour.md | 1 + api_docs/v1/UsageAnalyzedLogsResponse.md | 1 + api_docs/v1/UsageAttributionAggregatesBody.md | 1 + api_docs/v1/UsageAttributionBody.md | 1 + api_docs/v1/UsageAttributionMetadata.md | 1 + api_docs/v1/UsageAttributionPagination.md | 1 + api_docs/v1/UsageAttributionResponse.md | 1 + api_docs/v1/UsageAttributionValues.md | 1 + api_docs/v1/UsageBillableSummaryBody.md | 1 + api_docs/v1/UsageBillableSummaryHour.md | 1 + api_docs/v1/UsageBillableSummaryKeys.md | 1 + api_docs/v1/UsageBillableSummaryResponse.md | 1 + api_docs/v1/UsageCustomReportsAttributes.md | 1 + api_docs/v1/UsageCustomReportsData.md | 1 + api_docs/v1/UsageCustomReportsMeta.md | 1 + api_docs/v1/UsageCustomReportsPage.md | 1 + api_docs/v1/UsageCustomReportsResponse.md | 1 + api_docs/v1/UsageFargateHour.md | 1 + api_docs/v1/UsageFargateResponse.md | 1 + api_docs/v1/UsageHostHour.md | 1 + api_docs/v1/UsageHostsResponse.md | 1 + api_docs/v1/UsageIncidentManagementHour.md | 1 + .../v1/UsageIncidentManagementResponse.md | 1 + api_docs/v1/UsageIndexedSpansHour.md | 1 + api_docs/v1/UsageIndexedSpansResponse.md | 1 + api_docs/v1/UsageIngestedSpansHour.md | 1 + api_docs/v1/UsageIngestedSpansResponse.md | 1 + api_docs/v1/UsageIoTHour.md | 1 + api_docs/v1/UsageIoTResponse.md | 1 + api_docs/v1/UsageLambdaHour.md | 1 + api_docs/v1/UsageLambdaResponse.md | 1 + api_docs/v1/UsageLogsByIndexHour.md | 1 + api_docs/v1/UsageLogsByIndexResponse.md | 1 + api_docs/v1/UsageLogsHour.md | 1 + api_docs/v1/UsageLogsResponse.md | 1 + api_docs/v1/UsageNetworkFlowsHour.md | 1 + api_docs/v1/UsageNetworkFlowsResponse.md | 1 + api_docs/v1/UsageNetworkHostsHour.md | 1 + api_docs/v1/UsageNetworkHostsResponse.md | 1 + api_docs/v1/UsageProfilingHour.md | 1 + api_docs/v1/UsageProfilingResponse.md | 1 + api_docs/v1/UsageRumSessionsHour.md | 1 + api_docs/v1/UsageRumSessionsResponse.md | 1 + api_docs/v1/UsageSNMPHour.md | 1 + api_docs/v1/UsageSNMPResponse.md | 1 + .../UsageSpecifiedCustomReportsAttributes.md | 1 + .../v1/UsageSpecifiedCustomReportsData.md | 1 + .../v1/UsageSpecifiedCustomReportsMeta.md | 1 + .../v1/UsageSpecifiedCustomReportsPage.md | 1 + .../v1/UsageSpecifiedCustomReportsResponse.md | 1 + api_docs/v1/UsageSummaryDate.md | 1 + api_docs/v1/UsageSummaryDateOrg.md | 1 + api_docs/v1/UsageSummaryResponse.md | 1 + api_docs/v1/UsageSyntheticsAPIHour.md | 1 + api_docs/v1/UsageSyntheticsAPIResponse.md | 1 + api_docs/v1/UsageSyntheticsBrowserHour.md | 1 + api_docs/v1/UsageSyntheticsBrowserResponse.md | 1 + api_docs/v1/UsageSyntheticsHour.md | 1 + api_docs/v1/UsageSyntheticsResponse.md | 1 + api_docs/v1/UsageTimeseriesHour.md | 1 + api_docs/v1/UsageTimeseriesResponse.md | 1 + api_docs/v1/UsageTopAvgMetricsHour.md | 1 + api_docs/v1/UsageTopAvgMetricsResponse.md | 1 + api_docs/v1/UsageTraceHour.md | 1 + api_docs/v1/UsageTraceResponse.md | 1 + api_docs/v1/UsageTracingWithoutLimitsHour.md | 1 + .../v1/UsageTracingWithoutLimitsResponse.md | 1 + api_docs/v1/User.md | 1 + api_docs/v1/UserDisableResponse.md | 1 + api_docs/v1/UserListResponse.md | 1 + api_docs/v1/UserResponse.md | 1 + api_docs/v1/Widget.md | 1 + api_docs/v1/WidgetAxis.md | 1 + api_docs/v1/WidgetConditionalFormat.md | 1 + api_docs/v1/WidgetCustomLink.md | 1 + api_docs/v1/WidgetEvent.md | 1 + api_docs/v1/WidgetFieldSort.md | 1 + api_docs/v1/WidgetFormula.md | 1 + api_docs/v1/WidgetFormulaLimit.md | 1 + api_docs/v1/WidgetLayout.md | 1 + api_docs/v1/WidgetMarker.md | 1 + api_docs/v1/WidgetRequestStyle.md | 1 + api_docs/v1/WidgetStyle.md | 1 + api_docs/v1/WidgetTime.md | 1 + api_docs/v2/APIErrorResponse.md | 1 + api_docs/v2/APIKeyCreateAttributes.md | 1 + api_docs/v2/APIKeyCreateData.md | 1 + api_docs/v2/APIKeyCreateRequest.md | 1 + api_docs/v2/APIKeyRelationships.md | 1 + api_docs/v2/APIKeyResponse.md | 1 + api_docs/v2/APIKeyUpdateAttributes.md | 1 + api_docs/v2/APIKeyUpdateData.md | 1 + api_docs/v2/APIKeyUpdateRequest.md | 1 + api_docs/v2/APIKeysResponse.md | 1 + api_docs/v2/ApplicationKeyCreateAttributes.md | 1 + api_docs/v2/ApplicationKeyCreateData.md | 1 + api_docs/v2/ApplicationKeyCreateRequest.md | 1 + api_docs/v2/ApplicationKeyRelationships.md | 1 + api_docs/v2/ApplicationKeyResponse.md | 1 + api_docs/v2/ApplicationKeyUpdateAttributes.md | 1 + api_docs/v2/ApplicationKeyUpdateData.md | 1 + api_docs/v2/ApplicationKeyUpdateRequest.md | 1 + api_docs/v2/Creator.md | 1 + api_docs/v2/DashboardListAddItemsRequest.md | 1 + api_docs/v2/DashboardListAddItemsResponse.md | 1 + .../v2/DashboardListDeleteItemsRequest.md | 1 + .../v2/DashboardListDeleteItemsResponse.md | 1 + api_docs/v2/DashboardListItem.md | 1 + api_docs/v2/DashboardListItemRequest.md | 1 + api_docs/v2/DashboardListItemResponse.md | 1 + api_docs/v2/DashboardListItems.md | 1 + .../v2/DashboardListUpdateItemsRequest.md | 1 + .../v2/DashboardListUpdateItemsResponse.md | 1 + api_docs/v2/FullAPIKey.md | 1 + api_docs/v2/FullAPIKeyAttributes.md | 1 + api_docs/v2/FullApplicationKey.md | 1 + api_docs/v2/FullApplicationKeyAttributes.md | 1 + api_docs/v2/IncidentCreateAttributes.md | 1 + api_docs/v2/IncidentCreateData.md | 1 + api_docs/v2/IncidentCreateRelationships.md | 1 + api_docs/v2/IncidentCreateRequest.md | 1 + .../IncidentFieldAttributesMultipleValue.md | 1 + .../v2/IncidentFieldAttributesSingleValue.md | 1 + api_docs/v2/IncidentResponse.md | 1 + api_docs/v2/IncidentResponseAttributes.md | 1 + api_docs/v2/IncidentResponseData.md | 1 + api_docs/v2/IncidentResponseRelationships.md | 1 + .../v2/IncidentServiceCreateAttributes.md | 1 + api_docs/v2/IncidentServiceCreateData.md | 1 + api_docs/v2/IncidentServiceCreateRequest.md | 1 + api_docs/v2/IncidentServiceRelationships.md | 1 + api_docs/v2/IncidentServiceResponse.md | 1 + .../v2/IncidentServiceResponseAttributes.md | 1 + api_docs/v2/IncidentServiceResponseData.md | 1 + .../v2/IncidentServiceUpdateAttributes.md | 1 + api_docs/v2/IncidentServiceUpdateData.md | 1 + api_docs/v2/IncidentServiceUpdateRequest.md | 1 + api_docs/v2/IncidentServicesResponse.md | 1 + api_docs/v2/IncidentServicesResponseMeta.md | 1 + .../IncidentServicesResponseMetaPagination.md | 1 + api_docs/v2/IncidentTeamCreateAttributes.md | 1 + api_docs/v2/IncidentTeamCreateData.md | 1 + api_docs/v2/IncidentTeamCreateRequest.md | 1 + api_docs/v2/IncidentTeamRelationships.md | 1 + api_docs/v2/IncidentTeamResponse.md | 1 + api_docs/v2/IncidentTeamResponseAttributes.md | 1 + api_docs/v2/IncidentTeamResponseData.md | 1 + api_docs/v2/IncidentTeamUpdateAttributes.md | 1 + api_docs/v2/IncidentTeamUpdateData.md | 1 + api_docs/v2/IncidentTeamUpdateRequest.md | 1 + api_docs/v2/IncidentTeamsResponse.md | 1 + ...entTimelineCellMarkdownCreateAttributes.md | 1 + ...lineCellMarkdownCreateAttributesContent.md | 1 + api_docs/v2/IncidentUpdateAttributes.md | 1 + api_docs/v2/IncidentUpdateData.md | 1 + api_docs/v2/IncidentUpdateRelationships.md | 1 + api_docs/v2/IncidentUpdateRequest.md | 1 + api_docs/v2/IncidentsResponse.md | 1 + api_docs/v2/ListApplicationKeysResponse.md | 1 + api_docs/v2/Log.md | 1 + api_docs/v2/LogAttributes.md | 1 + api_docs/v2/LogsAggregateBucket.md | 1 + .../v2/LogsAggregateBucketValueTimeseries.md | 1 + ...LogsAggregateBucketValueTimeseriesPoint.md | 1 + api_docs/v2/LogsAggregateRequest.md | 1 + api_docs/v2/LogsAggregateRequestPage.md | 1 + api_docs/v2/LogsAggregateResponse.md | 1 + api_docs/v2/LogsAggregateResponseData.md | 1 + api_docs/v2/LogsAggregateSort.md | 1 + api_docs/v2/LogsArchive.md | 1 + api_docs/v2/LogsArchiveAttributes.md | 1 + api_docs/v2/LogsArchiveCreateRequest.md | 1 + .../v2/LogsArchiveCreateRequestAttributes.md | 1 + .../v2/LogsArchiveCreateRequestDefinition.md | 1 + api_docs/v2/LogsArchiveDefinition.md | 1 + api_docs/v2/LogsArchiveDestinationAzure.md | 1 + api_docs/v2/LogsArchiveDestinationGCS.md | 1 + api_docs/v2/LogsArchiveDestinationS3.md | 1 + api_docs/v2/LogsArchiveIntegrationAzure.md | 1 + api_docs/v2/LogsArchiveIntegrationGCS.md | 1 + api_docs/v2/LogsArchiveIntegrationS3.md | 1 + api_docs/v2/LogsArchiveOrder.md | 1 + api_docs/v2/LogsArchiveOrderAttributes.md | 1 + api_docs/v2/LogsArchiveOrderDefinition.md | 1 + api_docs/v2/LogsArchives.md | 1 + api_docs/v2/LogsCompute.md | 1 + api_docs/v2/LogsGroupBy.md | 1 + api_docs/v2/LogsGroupByHistogram.md | 1 + api_docs/v2/LogsListRequest.md | 1 + api_docs/v2/LogsListRequestPage.md | 1 + api_docs/v2/LogsListResponse.md | 1 + api_docs/v2/LogsListResponseLinks.md | 1 + api_docs/v2/LogsMetricCompute.md | 1 + api_docs/v2/LogsMetricCreateAttributes.md | 1 + api_docs/v2/LogsMetricCreateData.md | 1 + api_docs/v2/LogsMetricCreateRequest.md | 1 + api_docs/v2/LogsMetricFilter.md | 1 + api_docs/v2/LogsMetricGroupBy.md | 1 + api_docs/v2/LogsMetricResponse.md | 1 + api_docs/v2/LogsMetricResponseAttributes.md | 1 + api_docs/v2/LogsMetricResponseCompute.md | 1 + api_docs/v2/LogsMetricResponseData.md | 1 + api_docs/v2/LogsMetricResponseFilter.md | 1 + api_docs/v2/LogsMetricResponseGroupBy.md | 1 + api_docs/v2/LogsMetricUpdateAttributes.md | 1 + api_docs/v2/LogsMetricUpdateData.md | 1 + api_docs/v2/LogsMetricUpdateRequest.md | 1 + api_docs/v2/LogsMetricsResponse.md | 1 + api_docs/v2/LogsQueryFilter.md | 1 + api_docs/v2/LogsQueryOptions.md | 1 + api_docs/v2/LogsResponseMetadata.md | 1 + api_docs/v2/LogsResponseMetadataPage.md | 1 + api_docs/v2/LogsWarning.md | 1 + api_docs/v2/Metric.md | 1 + api_docs/v2/MetricAllTags.md | 1 + api_docs/v2/MetricAllTagsAttributes.md | 1 + api_docs/v2/MetricAllTagsResponse.md | 1 + api_docs/v2/MetricDistinctVolume.md | 1 + api_docs/v2/MetricDistinctVolumeAttributes.md | 1 + api_docs/v2/MetricIngestedIndexedVolume.md | 1 + .../MetricIngestedIndexedVolumeAttributes.md | 1 + api_docs/v2/MetricTagConfiguration.md | 1 + .../v2/MetricTagConfigurationAttributes.md | 1 + .../MetricTagConfigurationCreateAttributes.md | 1 + .../v2/MetricTagConfigurationCreateData.md | 1 + .../v2/MetricTagConfigurationCreateRequest.md | 1 + api_docs/v2/MetricTagConfigurationResponse.md | 1 + .../MetricTagConfigurationUpdateAttributes.md | 1 + .../v2/MetricTagConfigurationUpdateData.md | 1 + .../v2/MetricTagConfigurationUpdateRequest.md | 1 + api_docs/v2/MetricVolumesResponse.md | 1 + ...tricsAndMetricTagConfigurationsResponse.md | 1 + api_docs/v2/Organization.md | 1 + api_docs/v2/OrganizationAttributes.md | 1 + api_docs/v2/Pagination.md | 1 + api_docs/v2/PartialAPIKey.md | 1 + api_docs/v2/PartialAPIKeyAttributes.md | 1 + api_docs/v2/PartialApplicationKey.md | 1 + .../v2/PartialApplicationKeyAttributes.md | 1 + api_docs/v2/Permission.md | 1 + api_docs/v2/PermissionAttributes.md | 1 + api_docs/v2/PermissionsResponse.md | 1 + api_docs/v2/ProcessSummariesMeta.md | 1 + api_docs/v2/ProcessSummariesMetaPage.md | 1 + api_docs/v2/ProcessSummariesResponse.md | 1 + api_docs/v2/ProcessSummary.md | 1 + api_docs/v2/ProcessSummaryAttributes.md | 1 + ...onshipToIncidentIntegrationMetadataData.md | 1 + ...ationshipToIncidentIntegrationMetadatas.md | 1 + .../v2/RelationshipToIncidentPostmortem.md | 1 + .../RelationshipToIncidentPostmortemData.md | 1 + api_docs/v2/RelationshipToOrganization.md | 1 + api_docs/v2/RelationshipToOrganizationData.md | 1 + api_docs/v2/RelationshipToOrganizations.md | 1 + api_docs/v2/RelationshipToPermission.md | 1 + api_docs/v2/RelationshipToPermissionData.md | 1 + api_docs/v2/RelationshipToPermissions.md | 1 + api_docs/v2/RelationshipToRole.md | 1 + api_docs/v2/RelationshipToRoleData.md | 1 + api_docs/v2/RelationshipToRoles.md | 1 + api_docs/v2/RelationshipToUser.md | 1 + api_docs/v2/RelationshipToUserData.md | 1 + api_docs/v2/RelationshipToUsers.md | 1 + api_docs/v2/ResponseMetaAttributes.md | 1 + api_docs/v2/Role.md | 1 + api_docs/v2/RoleAttributes.md | 1 + api_docs/v2/RoleCreateAttributes.md | 1 + api_docs/v2/RoleCreateData.md | 1 + api_docs/v2/RoleCreateRequest.md | 1 + api_docs/v2/RoleCreateResponse.md | 1 + api_docs/v2/RoleCreateResponseData.md | 1 + api_docs/v2/RoleRelationships.md | 1 + api_docs/v2/RoleResponse.md | 1 + api_docs/v2/RoleResponseRelationships.md | 1 + api_docs/v2/RoleUpdateAttributes.md | 1 + api_docs/v2/RoleUpdateData.md | 1 + api_docs/v2/RoleUpdateRequest.md | 1 + api_docs/v2/RoleUpdateResponse.md | 1 + api_docs/v2/RoleUpdateResponseData.md | 1 + api_docs/v2/RolesResponse.md | 1 + api_docs/v2/SecurityMonitoringFilter.md | 1 + .../v2/SecurityMonitoringListRulesResponse.md | 1 + api_docs/v2/SecurityMonitoringRuleCase.md | 1 + .../v2/SecurityMonitoringRuleCaseCreate.md | 1 + .../v2/SecurityMonitoringRuleCreatePayload.md | 1 + .../SecurityMonitoringRuleNewValueOptions.md | 1 + api_docs/v2/SecurityMonitoringRuleOptions.md | 1 + api_docs/v2/SecurityMonitoringRuleQuery.md | 1 + .../v2/SecurityMonitoringRuleQueryCreate.md | 1 + api_docs/v2/SecurityMonitoringRuleResponse.md | 1 + .../v2/SecurityMonitoringRuleUpdatePayload.md | 1 + api_docs/v2/SecurityMonitoringSignal.md | 1 + .../v2/SecurityMonitoringSignalAttributes.md | 1 + .../v2/SecurityMonitoringSignalListRequest.md | 1 + ...curityMonitoringSignalListRequestFilter.md | 1 + ...SecurityMonitoringSignalListRequestPage.md | 1 + .../SecurityMonitoringSignalsListResponse.md | 1 + ...urityMonitoringSignalsListResponseLinks.md | 1 + ...curityMonitoringSignalsListResponseMeta.md | 1 + ...tyMonitoringSignalsListResponseMetaPage.md | 1 + api_docs/v2/User.md | 1 + api_docs/v2/UserAttributes.md | 1 + api_docs/v2/UserCreateAttributes.md | 1 + api_docs/v2/UserCreateData.md | 1 + api_docs/v2/UserCreateRequest.md | 1 + api_docs/v2/UserInvitationData.md | 1 + api_docs/v2/UserInvitationDataAttributes.md | 1 + api_docs/v2/UserInvitationRelationships.md | 1 + api_docs/v2/UserInvitationResponse.md | 1 + api_docs/v2/UserInvitationResponseData.md | 1 + api_docs/v2/UserInvitationsRequest.md | 1 + api_docs/v2/UserInvitationsResponse.md | 1 + api_docs/v2/UserRelationships.md | 1 + api_docs/v2/UserResponse.md | 1 + api_docs/v2/UserResponseRelationships.md | 1 + api_docs/v2/UserUpdateAttributes.md | 1 + api_docs/v2/UserUpdateData.md | 1 + api_docs/v2/UserUpdateRequest.md | 1 + api_docs/v2/UsersResponse.md | 1 + 885 files changed, 33155 insertions(+), 4 deletions(-) create mode 100644 .generator/templates/ApiClient.mustache create mode 100644 .generator/templates/BeanValidationException.mustache create mode 100644 .generator/templates/Configuration.mustache create mode 100644 .generator/templates/CustomInstantDeserializer.mustache create mode 100644 .generator/templates/JSON.mustache create mode 100644 .generator/templates/JavaTimeFormatter.mustache create mode 100644 .generator/templates/Pair.mustache create mode 100644 .generator/templates/README.mustache create mode 100644 .generator/templates/RFC3339DateFormat.mustache create mode 100644 .generator/templates/ServerConfiguration.mustache create mode 100644 .generator/templates/ServerVariable.mustache create mode 100644 .generator/templates/StringUtil.mustache create mode 100644 .generator/templates/additionalEnumTypeAnnotations.mustache create mode 100644 .generator/templates/additionalModelTypeAnnotations.mustache create mode 100644 .generator/templates/api.mustache create mode 100644 .generator/templates/apiException.mustache create mode 100644 .generator/templates/apiOperation.mustache create mode 100644 .generator/templates/api_doc.mustache create mode 100644 .generator/templates/api_test.mustache create mode 100644 .generator/templates/auth/ApiKeyAuth.mustache create mode 100644 .generator/templates/auth/Authentication.mustache create mode 100644 .generator/templates/auth/HttpBasicAuth.mustache create mode 100644 .generator/templates/auth/HttpBearerAuth.mustache create mode 100644 .generator/templates/auth/OAuth.mustache create mode 100644 .generator/templates/auth/OAuthFlow.mustache create mode 100644 .generator/templates/beanValidation.mustache create mode 100644 .generator/templates/beanValidationCore.mustache create mode 100644 .generator/templates/beanValidationQueryParams.mustache create mode 100644 .generator/templates/build.gradle.mustache create mode 100644 .generator/templates/build.sbt.mustache create mode 100644 .generator/templates/enum_outer_doc.mustache create mode 100644 .generator/templates/generatedAnnotation.mustache create mode 100755 .generator/templates/git_push.sh.mustache create mode 100644 .generator/templates/gitignore.mustache create mode 100644 .generator/templates/gradle-wrapper.jar create mode 100644 .generator/templates/gradle-wrapper.properties.mustache create mode 100644 .generator/templates/gradle.properties.mustache create mode 100644 .generator/templates/gradlew.bat.mustache create mode 100755 .generator/templates/gradlew.mustache create mode 100644 .generator/templates/jackson_annotations.mustache create mode 100644 .generator/templates/libraries/feign/ApiClient.mustache create mode 100644 .generator/templates/libraries/feign/EncodingUtils.mustache create mode 100644 .generator/templates/libraries/feign/ParamExpander.mustache create mode 100644 .generator/templates/libraries/feign/README.mustache create mode 100644 .generator/templates/libraries/feign/api.mustache create mode 100644 .generator/templates/libraries/feign/api_test.mustache create mode 100644 .generator/templates/libraries/feign/auth/ApiKeyAuth.mustache create mode 100644 .generator/templates/libraries/feign/auth/DefaultApi20Impl.mustache create mode 100644 .generator/templates/libraries/feign/auth/HttpBasicAuth.mustache create mode 100644 .generator/templates/libraries/feign/auth/HttpBearerAuth.mustache create mode 100644 .generator/templates/libraries/feign/auth/OAuth.mustache create mode 100644 .generator/templates/libraries/feign/auth/OauthClientCredentialsGrant.mustache create mode 100644 .generator/templates/libraries/feign/auth/OauthPasswordGrant.mustache create mode 100644 .generator/templates/libraries/feign/build.gradle.mustache create mode 100644 .generator/templates/libraries/feign/build.sbt.mustache create mode 100644 .generator/templates/libraries/feign/model_test.mustache create mode 100644 .generator/templates/libraries/feign/pom.mustache create mode 100644 .generator/templates/libraries/google-api-client/ApiClient.mustache create mode 100644 .generator/templates/libraries/google-api-client/api.mustache create mode 100644 .generator/templates/libraries/google-api-client/api_test.mustache create mode 100644 .generator/templates/libraries/google-api-client/build.gradle.mustache create mode 100644 .generator/templates/libraries/google-api-client/build.sbt.mustache create mode 100644 .generator/templates/libraries/google-api-client/pom.mustache create mode 100644 .generator/templates/libraries/jersey2/AbstractOpenApiSchema.mustache create mode 100644 .generator/templates/libraries/jersey2/ApiClient.mustache create mode 100644 .generator/templates/libraries/jersey2/ApiResponse.mustache create mode 100644 .generator/templates/libraries/jersey2/JSON.mustache create mode 100644 .generator/templates/libraries/jersey2/additional_properties.mustache create mode 100644 .generator/templates/libraries/jersey2/anyof_model.mustache create mode 100644 .generator/templates/libraries/jersey2/api.mustache create mode 100644 .generator/templates/libraries/jersey2/apiException.mustache create mode 100644 .generator/templates/libraries/jersey2/api_doc.mustache create mode 100644 .generator/templates/libraries/jersey2/api_test.mustache create mode 100644 .generator/templates/libraries/jersey2/auth/ApiKeyAuth.mustache create mode 100644 .generator/templates/libraries/jersey2/auth/Authentication.mustache create mode 100644 .generator/templates/libraries/jersey2/auth/HttpBasicAuth.mustache create mode 100644 .generator/templates/libraries/jersey2/auth/HttpBearerAuth.mustache create mode 100644 .generator/templates/libraries/jersey2/auth/HttpSignatureAuth.mustache create mode 100644 .generator/templates/libraries/jersey2/auth/OAuth.mustache create mode 100644 .generator/templates/libraries/jersey2/auth/OAuthFlow.mustache create mode 100644 .generator/templates/libraries/jersey2/build.gradle.mustache create mode 100644 .generator/templates/libraries/jersey2/build.sbt.mustache create mode 100644 .generator/templates/libraries/jersey2/model.mustache create mode 100644 .generator/templates/libraries/jersey2/model_anyof_doc.mustache create mode 100644 .generator/templates/libraries/jersey2/model_doc.mustache create mode 100644 .generator/templates/libraries/jersey2/model_oneof_doc.mustache create mode 100644 .generator/templates/libraries/jersey2/oneof_model.mustache create mode 100644 .generator/templates/libraries/jersey2/pojo.mustache create mode 100644 .generator/templates/libraries/jersey2/pom.mustache create mode 100644 .generator/templates/libraries/microprofile/README.mustache create mode 100644 .generator/templates/libraries/microprofile/api.mustache create mode 100644 .generator/templates/libraries/microprofile/api_exception.mustache create mode 100644 .generator/templates/libraries/microprofile/api_exception_mapper.mustache create mode 100644 .generator/templates/libraries/microprofile/api_test.mustache create mode 100644 .generator/templates/libraries/microprofile/beanValidation.mustache create mode 100644 .generator/templates/libraries/microprofile/beanValidationCore.mustache create mode 100644 .generator/templates/libraries/microprofile/beanValidationHeaderParams.mustache create mode 100644 .generator/templates/libraries/microprofile/beanValidationPathParams.mustache create mode 100644 .generator/templates/libraries/microprofile/beanValidationQueryParams.mustache create mode 100644 .generator/templates/libraries/microprofile/bodyParams.mustache create mode 100644 .generator/templates/libraries/microprofile/bodyParamsImpl.mustache create mode 100644 .generator/templates/libraries/microprofile/enumClass.mustache create mode 100644 .generator/templates/libraries/microprofile/enumOuterClass.mustache create mode 100644 .generator/templates/libraries/microprofile/formParams.mustache create mode 100644 .generator/templates/libraries/microprofile/formParamsImpl.mustache create mode 100644 .generator/templates/libraries/microprofile/generatedAnnotation.mustache create mode 100644 .generator/templates/libraries/microprofile/headerParams.mustache create mode 100644 .generator/templates/libraries/microprofile/headerParamsImpl.mustache create mode 100644 .generator/templates/libraries/microprofile/kumuluzee.beans.xml.mustache create mode 100644 .generator/templates/libraries/microprofile/kumuluzee.config.yaml.mustache create mode 100644 .generator/templates/libraries/microprofile/kumuluzee.pom.mustache create mode 100644 .generator/templates/libraries/microprofile/licenseInfo.mustache create mode 100644 .generator/templates/libraries/microprofile/model.mustache create mode 100644 .generator/templates/libraries/microprofile/pathParams.mustache create mode 100644 .generator/templates/libraries/microprofile/pathParamsImpl.mustache create mode 100644 .generator/templates/libraries/microprofile/pojo.mustache create mode 100644 .generator/templates/libraries/microprofile/pom.mustache create mode 100644 .generator/templates/libraries/microprofile/queryParams.mustache create mode 100644 .generator/templates/libraries/microprofile/queryParamsImpl.mustache create mode 100644 .generator/templates/libraries/microprofile/returnTypes.mustache create mode 100644 .generator/templates/libraries/native/AbstractOpenApiSchema.mustache create mode 100644 .generator/templates/libraries/native/ApiClient.mustache create mode 100644 .generator/templates/libraries/native/ApiResponse.mustache create mode 100644 .generator/templates/libraries/native/JSON.mustache create mode 100644 .generator/templates/libraries/native/README.mustache create mode 100644 .generator/templates/libraries/native/additional_properties.mustache create mode 100644 .generator/templates/libraries/native/anyof_model.mustache create mode 100644 .generator/templates/libraries/native/api.mustache create mode 100644 .generator/templates/libraries/native/apiException.mustache create mode 100644 .generator/templates/libraries/native/api_doc.mustache create mode 100644 .generator/templates/libraries/native/api_test.mustache create mode 100644 .generator/templates/libraries/native/build.gradle.mustache create mode 100644 .generator/templates/libraries/native/generatedAnnotation.mustache create mode 100644 .generator/templates/libraries/native/gradle.properties.mustache create mode 100644 .generator/templates/libraries/native/model.mustache create mode 100644 .generator/templates/libraries/native/model_anyof_doc.mustache create mode 100644 .generator/templates/libraries/native/model_doc.mustache create mode 100644 .generator/templates/libraries/native/model_oneof_doc.mustache create mode 100644 .generator/templates/libraries/native/oneof_model.mustache create mode 100644 .generator/templates/libraries/native/pojo.mustache create mode 100644 .generator/templates/libraries/native/pom.mustache create mode 100644 .generator/templates/libraries/native/travis.mustache create mode 100644 .generator/templates/libraries/okhttp-gson/ApiCallback.mustache create mode 100644 .generator/templates/libraries/okhttp-gson/ApiClient.mustache create mode 100644 .generator/templates/libraries/okhttp-gson/ApiResponse.mustache create mode 100644 .generator/templates/libraries/okhttp-gson/GzipRequestInterceptor.mustache create mode 100644 .generator/templates/libraries/okhttp-gson/ProgressRequestBody.mustache create mode 100644 .generator/templates/libraries/okhttp-gson/ProgressResponseBody.mustache create mode 100644 .generator/templates/libraries/okhttp-gson/README.mustache create mode 100644 .generator/templates/libraries/okhttp-gson/api.mustache create mode 100644 .generator/templates/libraries/okhttp-gson/apiException.mustache create mode 100644 .generator/templates/libraries/okhttp-gson/api_doc.mustache create mode 100644 .generator/templates/libraries/okhttp-gson/api_test.mustache create mode 100644 .generator/templates/libraries/okhttp-gson/auth/HttpBasicAuth.mustache create mode 100644 .generator/templates/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache create mode 100644 .generator/templates/libraries/okhttp-gson/auth/RetryingOAuth.mustache create mode 100644 .generator/templates/libraries/okhttp-gson/build.gradle.mustache create mode 100644 .generator/templates/libraries/okhttp-gson/build.sbt.mustache create mode 100644 .generator/templates/libraries/okhttp-gson/pom.mustache create mode 100644 .generator/templates/libraries/rest-assured/ApiClient.mustache create mode 100644 .generator/templates/libraries/rest-assured/GsonObjectMapper.mustache create mode 100644 .generator/templates/libraries/rest-assured/JacksonObjectMapper.mustache create mode 100644 .generator/templates/libraries/rest-assured/Oper.mustache create mode 100644 .generator/templates/libraries/rest-assured/README.mustache create mode 100644 .generator/templates/libraries/rest-assured/ResponseSpecBuilders.mustache create mode 100644 .generator/templates/libraries/rest-assured/api.mustache create mode 100644 .generator/templates/libraries/rest-assured/api_doc.mustache create mode 100644 .generator/templates/libraries/rest-assured/api_test.mustache create mode 100644 .generator/templates/libraries/rest-assured/build.gradle.mustache create mode 100644 .generator/templates/libraries/rest-assured/build.sbt.mustache create mode 100644 .generator/templates/libraries/rest-assured/pom.mustache create mode 100644 .generator/templates/libraries/resteasy/ApiClient.mustache create mode 100644 .generator/templates/libraries/resteasy/JSON.mustache create mode 100644 .generator/templates/libraries/resteasy/api.mustache create mode 100644 .generator/templates/libraries/resteasy/build.gradle.mustache create mode 100644 .generator/templates/libraries/resteasy/build.sbt.mustache create mode 100644 .generator/templates/libraries/resteasy/pom.mustache create mode 100644 .generator/templates/libraries/resttemplate/ApiClient.mustache create mode 100644 .generator/templates/libraries/resttemplate/api.mustache create mode 100644 .generator/templates/libraries/resttemplate/api_test.mustache create mode 100644 .generator/templates/libraries/resttemplate/auth/ApiKeyAuth.mustache create mode 100644 .generator/templates/libraries/resttemplate/auth/Authentication.mustache create mode 100644 .generator/templates/libraries/resttemplate/auth/HttpBasicAuth.mustache create mode 100644 .generator/templates/libraries/resttemplate/auth/HttpBearerAuth.mustache create mode 100644 .generator/templates/libraries/resttemplate/auth/OAuth.mustache create mode 100644 .generator/templates/libraries/resttemplate/auth/OAuthFlow.mustache create mode 100644 .generator/templates/libraries/resttemplate/build.gradle.mustache create mode 100644 .generator/templates/libraries/resttemplate/pom.mustache create mode 100644 .generator/templates/libraries/retrofit/ApiClient.mustache create mode 100644 .generator/templates/libraries/retrofit/CollectionFormats.mustache create mode 100644 .generator/templates/libraries/retrofit/README.mustache create mode 100644 .generator/templates/libraries/retrofit/api.mustache create mode 100644 .generator/templates/libraries/retrofit/api_test.mustache create mode 100644 .generator/templates/libraries/retrofit/auth/ApiKeyAuth.mustache create mode 100644 .generator/templates/libraries/retrofit/auth/HttpBasicAuth.mustache create mode 100644 .generator/templates/libraries/retrofit/auth/HttpBearerAuth.mustache create mode 100644 .generator/templates/libraries/retrofit/auth/OAuth.mustache create mode 100644 .generator/templates/libraries/retrofit/auth/OAuthOkHttpClient.mustache create mode 100644 .generator/templates/libraries/retrofit/bodyParams.mustache create mode 100644 .generator/templates/libraries/retrofit/build.gradle.mustache create mode 100644 .generator/templates/libraries/retrofit/build.sbt.mustache create mode 100644 .generator/templates/libraries/retrofit/formParams.mustache create mode 100644 .generator/templates/libraries/retrofit/headerParams.mustache create mode 100644 .generator/templates/libraries/retrofit/pathParams.mustache create mode 100644 .generator/templates/libraries/retrofit/pom.mustache create mode 100644 .generator/templates/libraries/retrofit/queryParams.mustache create mode 100644 .generator/templates/libraries/retrofit2/ApiClient.mustache create mode 100644 .generator/templates/libraries/retrofit2/CollectionFormats.mustache create mode 100644 .generator/templates/libraries/retrofit2/JSON.mustache create mode 100644 .generator/templates/libraries/retrofit2/README.mustache create mode 100644 .generator/templates/libraries/retrofit2/api.mustache create mode 100644 .generator/templates/libraries/retrofit2/api_test.mustache create mode 100644 .generator/templates/libraries/retrofit2/auth/ApiKeyAuth.mustache create mode 100644 .generator/templates/libraries/retrofit2/auth/HttpBasicAuth.mustache create mode 100644 .generator/templates/libraries/retrofit2/auth/HttpBearerAuth.mustache create mode 100644 .generator/templates/libraries/retrofit2/auth/OAuth.mustache create mode 100644 .generator/templates/libraries/retrofit2/auth/OAuthOkHttpClient.mustache create mode 100644 .generator/templates/libraries/retrofit2/bodyParams.mustache create mode 100644 .generator/templates/libraries/retrofit2/build.gradle.mustache create mode 100644 .generator/templates/libraries/retrofit2/build.sbt.mustache create mode 100644 .generator/templates/libraries/retrofit2/formParams.mustache create mode 100644 .generator/templates/libraries/retrofit2/formParams.mustache.save create mode 100644 .generator/templates/libraries/retrofit2/headerParams.mustache create mode 100644 .generator/templates/libraries/retrofit2/pathParams.mustache create mode 100644 .generator/templates/libraries/retrofit2/play-common/auth/ApiKeyAuth.mustache create mode 100644 .generator/templates/libraries/retrofit2/play24/ApiClient.mustache create mode 100644 .generator/templates/libraries/retrofit2/play24/Play24CallAdapterFactory.mustache create mode 100644 .generator/templates/libraries/retrofit2/play24/Play24CallFactory.mustache create mode 100644 .generator/templates/libraries/retrofit2/play24/api.mustache create mode 100644 .generator/templates/libraries/retrofit2/play25/ApiClient.mustache create mode 100644 .generator/templates/libraries/retrofit2/play25/Play25CallAdapterFactory.mustache create mode 100644 .generator/templates/libraries/retrofit2/play25/Play25CallFactory.mustache create mode 100644 .generator/templates/libraries/retrofit2/play25/api.mustache create mode 100644 .generator/templates/libraries/retrofit2/play26/ApiClient.mustache create mode 100644 .generator/templates/libraries/retrofit2/play26/Play26CallAdapterFactory.mustache create mode 100644 .generator/templates/libraries/retrofit2/play26/Play26CallFactory.mustache create mode 100644 .generator/templates/libraries/retrofit2/play26/api.mustache create mode 100644 .generator/templates/libraries/retrofit2/pom.mustache create mode 100644 .generator/templates/libraries/retrofit2/queryParams.mustache create mode 100644 .generator/templates/libraries/vertx/ApiClient.mustache create mode 100644 .generator/templates/libraries/vertx/Configuration.mustache create mode 100644 .generator/templates/libraries/vertx/api.mustache create mode 100644 .generator/templates/libraries/vertx/apiException.mustache create mode 100644 .generator/templates/libraries/vertx/apiImpl.mustache create mode 100644 .generator/templates/libraries/vertx/api_test.mustache create mode 100644 .generator/templates/libraries/vertx/auth/ApiKeyAuth.mustache create mode 100644 .generator/templates/libraries/vertx/auth/Authentication.mustache create mode 100644 .generator/templates/libraries/vertx/auth/HttpBasicAuth.mustache create mode 100644 .generator/templates/libraries/vertx/auth/HttpBearerAuth.mustache create mode 100644 .generator/templates/libraries/vertx/auth/OAuth.mustache create mode 100644 .generator/templates/libraries/vertx/auth/OAuthFlow.mustache create mode 100644 .generator/templates/libraries/vertx/build.gradle.mustache create mode 100644 .generator/templates/libraries/vertx/pom.mustache create mode 100644 .generator/templates/libraries/vertx/rxApiImpl.mustache create mode 100644 .generator/templates/libraries/webclient/ApiClient.mustache create mode 100644 .generator/templates/libraries/webclient/api.mustache create mode 100644 .generator/templates/libraries/webclient/api_test.mustache create mode 100644 .generator/templates/libraries/webclient/auth/ApiKeyAuth.mustache create mode 100644 .generator/templates/libraries/webclient/auth/Authentication.mustache create mode 100644 .generator/templates/libraries/webclient/auth/HttpBasicAuth.mustache create mode 100644 .generator/templates/libraries/webclient/auth/HttpBearerAuth.mustache create mode 100644 .generator/templates/libraries/webclient/auth/OAuth.mustache create mode 100644 .generator/templates/libraries/webclient/auth/OAuthFlow.mustache create mode 100644 .generator/templates/libraries/webclient/build.gradle.mustache create mode 100644 .generator/templates/libraries/webclient/pom.mustache create mode 100644 .generator/templates/licenseInfo.mustache create mode 100644 .generator/templates/manifest.mustache create mode 100644 .generator/templates/model.mustache create mode 100644 .generator/templates/modelEnum.mustache create mode 100644 .generator/templates/modelInnerEnum.mustache create mode 100644 .generator/templates/model_doc.mustache create mode 100644 .generator/templates/model_test.mustache create mode 100644 .generator/templates/oneof_interface.mustache create mode 100644 .generator/templates/openapi.mustache create mode 100644 .generator/templates/pojo.mustache create mode 100644 .generator/templates/pojo_doc.mustache create mode 100644 .generator/templates/pom.mustache create mode 100644 .generator/templates/settings.gradle.mustache create mode 100644 .generator/templates/travis.mustache create mode 100644 .generator/templates/typeInfoAnnotation.mustache create mode 100644 .generator/templates/xmlAnnotation.mustache diff --git a/.apigentools-info b/.apigentools-info index 74505b8097a..770e445bdc3 100644 --- a/.apigentools-info +++ b/.apigentools-info @@ -4,13 +4,13 @@ "spec_versions": { "v1": { "apigentools_version": "1.4.1.dev6", - "regenerated": "2021-03-23 10:52:32.731196", - "spec_repo_commit": "34cf37f" + "regenerated": "2021-03-23 14:02:16.829328", + "spec_repo_commit": "7e667f1" }, "v2": { "apigentools_version": "1.4.1.dev6", - "regenerated": "2021-03-23 10:53:17.035331", - "spec_repo_commit": "34cf37f" + "regenerated": "2021-03-23 14:03:03.589201", + "spec_repo_commit": "7e667f1" } } } \ No newline at end of file diff --git a/.generator/templates/ApiClient.mustache b/.generator/templates/ApiClient.mustache new file mode 100644 index 00000000000..d75e455961c --- /dev/null +++ b/.generator/templates/ApiClient.mustache @@ -0,0 +1,905 @@ +{{>licenseInfo}} +package {{invokerPackage}}; + +{{#threetenbp}} +import org.threeten.bp.*; + +{{/threetenbp}} +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.*; +{{#joda}} +import com.fasterxml.jackson.datatype.joda.JodaModule; +{{/joda}} +{{#java8}} +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{^threetenbp}} +import java.time.OffsetDateTime; +{{/threetenbp}} +{{/java8}} +{{#threetenbp}} +import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; +{{/threetenbp}} +import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; + +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.GenericType; +import com.sun.jersey.api.client.config.DefaultClientConfig; +import com.sun.jersey.api.client.filter.GZIPContentEncodingFilter; +import com.sun.jersey.api.client.filter.LoggingFilter; +import com.sun.jersey.api.client.WebResource.Builder; + +import com.sun.jersey.multipart.FormDataMultiPart; +import com.sun.jersey.multipart.file.FileDataBodyPart; + +import javax.ws.rs.core.Cookie; +import javax.ws.rs.core.Response.Status.Family; +import javax.ws.rs.core.MediaType; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Map.Entry; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Date; +import java.util.TimeZone; + +import java.net.URLEncoder; + +import java.io.File; +import java.io.UnsupportedEncodingException; + +import java.text.DateFormat; + +import {{invokerPackage}}.auth.Authentication; +{{#hasHttpBasicMethods}} +import {{invokerPackage}}.auth.HttpBasicAuth; +{{/hasHttpBasicMethods}} +{{#hasHttpBearerMethods}} +import {{invokerPackage}}.auth.HttpBearerAuth; +{{/hasHttpBearerMethods}} +{{#hasApiKeyMethods}} +import {{invokerPackage}}.auth.ApiKeyAuth; +{{/hasApiKeyMethods}} +{{#hasOAuthMethods}} +import {{invokerPackage}}.auth.OAuth; +{{/hasOAuthMethods}} + +{{>generatedAnnotation}} +public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { + private Map defaultHeaderMap = new HashMap(); + private Map defaultCookieMap = new HashMap(); + private String basePath = "{{{basePath}}}"; + protected List servers = new ArrayList({{#servers}}{{#-first}}Arrays.asList( +{{/-first}} new ServerConfiguration( + "{{{url}}}", + "{{{description}}}{{^description}}No description provided{{/description}}", + new HashMap(){{#variables}}{{#-first}} {{ +{{/-first}} put("{{{name}}}", new ServerVariable( + "{{{description}}}{{^description}}No description provided{{/description}}", + "{{{defaultValue}}}", + new HashSet( + {{#enumValues}} + {{#-first}} + Arrays.asList( + {{/-first}} + "{{{.}}}"{{^-last}},{{/-last}} + {{#-last}} + ) + {{/-last}} + {{/enumValues}} + ) + )); + {{#-last}} + }}{{/-last}}{{/variables}} + ){{^-last}},{{/-last}} + {{#-last}} + ){{/-last}}{{/servers}}); + protected Integer serverIndex = 0; + protected Map serverVariables = null; + private boolean debugging = false; + private int connectionTimeout = 0; + + private Client httpClient; + private ObjectMapper objectMapper; + + private Map authentications; + + private int statusCode; + private Map> responseHeaders; + + private DateFormat dateFormat; + + public ApiClient() { + objectMapper = new ObjectMapper(); + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + {{#joda}} + objectMapper.registerModule(new JodaModule()); + {{/joda}} + {{#java8}} + objectMapper.registerModule(new JavaTimeModule()); + {{/java8}} + {{#threetenbp}} + ThreeTenModule module = new ThreeTenModule(); + module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); + module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); + module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); + objectMapper.registerModule(module); + {{/threetenbp}} + objectMapper.setDateFormat(ApiClient.buildDefaultDateFormat()); + + dateFormat = ApiClient.buildDefaultDateFormat(); + + // Set default User-Agent. + setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + + rebuildHttpClient(); + } + + public static DateFormat buildDefaultDateFormat() { + return new RFC3339DateFormat(); + } + + /** + * Build the Client used to make HTTP requests with the latest settings, + * i.e. objectMapper and debugging. + * TODO: better to use the Builder Pattern? + * @return API client + */ + public ApiClient rebuildHttpClient() { + // Add the JSON serialization support to Jersey + JacksonJsonProvider jsonProvider = new JacksonJsonProvider(objectMapper); + DefaultClientConfig conf = new DefaultClientConfig(); + conf.getSingletons().add(jsonProvider); + Client client = Client.create(conf); + client.addFilter(new GZIPContentEncodingFilter({{#useGzipFeature}}true{{/useGzipFeature}}{{^useGzipFeature}}false{{/useGzipFeature}})); + if (debugging) { + client.addFilter(new LoggingFilter()); + } + this.httpClient = client; + return this; + } + + /** + * Returns the current object mapper used for JSON serialization/deserialization. + *

+ * Note: If you make changes to the object mapper, remember to set it back via + * setObjectMapper in order to trigger HTTP client rebuilding. + *

+ * @return Object mapper + */ + public ObjectMapper getObjectMapper() { + return objectMapper; + } + + public ApiClient setObjectMapper(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + // Need to rebuild the Client as it depends on object mapper. + rebuildHttpClient(); + return this; + } + + public Client getHttpClient() { + return httpClient; + } + + public ApiClient setHttpClient(Client httpClient) { + this.httpClient = httpClient; + return this; + } + + public String getBasePath() { + return basePath; + } + + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + public List getServers() { + return servers; + } + + public ApiClient setServers(List servers) { + this.servers = servers; + return this; + } + + public Integer getServerIndex() { + return serverIndex; + } + + public ApiClient setServerIndex(Integer serverIndex) { + this.serverIndex = serverIndex; + return this; + } + + public Map getServerVariables() { + return serverVariables; + } + + public ApiClient setServerVariables(Map serverVariables) { + this.serverVariables = serverVariables; + return this; + } + + /** + * Gets the status code of the previous request + * @return Status code + */ + public int getStatusCode() { + return statusCode; + } + + /** + * Gets the response headers of the previous request + * @return Response headers + */ + public Map> getResponseHeaders() { + return responseHeaders; + } + + /** + * Get authentications (key: authentication name, value: authentication). + * @return Map of authentication + */ + 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) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBearerAuth) { + ((HttpBearerAuth) auth).setBearerToken(bearerToken); + return; + } + } + throw new RuntimeException("No Bearer authentication configured!"); + } + + {{/hasHttpBearerMethods}} + + {{#hasHttpBasicMethods}} + /** + * Helper method to set username for the first HTTP basic authentication. + * @param username Username + */ + 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!"); + } + + {{/hasHttpBasicMethods}} + + {{#hasApiKeyMethods}} + /** + * Helper method to set API key value for the first API key authentication. + * @param apiKey the 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!"); + } + + {{/hasApiKeyMethods}} + + {{#hasOAuthMethods}} + /** + * Helper method to set access token for the first OAuth2 authentication. + * @param accessToken Access token + */ + public void setAccessToken(String accessToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setAccessToken(accessToken); + return; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + {{/hasOAuthMethods}} + + /** + * Set the User-Agent header's value (by adding to the default header map). + * @param userAgent User agent + * @return API client + */ + 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 API client + */ + 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 API client + */ + public ApiClient addDefaultCookie(String key, String value) { + defaultCookieMap.put(key, value); + return this; + } + + /** + * Check that whether debugging is enabled for this API client. + * @return True if debugging is on + */ + public boolean isDebugging() { + return debugging; + } + + /** + * Enable/disable debugging for this API client. + * + * @param debugging To enable (true) or disable (false) debugging + * @return API client + */ + public ApiClient setDebugging(boolean debugging) { + this.debugging = debugging; + // Need to rebuild the Client as it depends on the value of debugging. + rebuildHttpClient(); + return this; + } + + /** + * Connect timeout (in milliseconds). + * @return Connection timeout + */ + public int getConnectTimeout() { + return connectionTimeout; + } + + /** + * Set the connect timeout (in milliseconds). + * A value of 0 means no timeout, otherwise values must be between 1 and + * {@link Integer#MAX_VALUE}. + * @param connectionTimeout Connection timeout in milliseconds + * @return API client + */ + public ApiClient setConnectTimeout(int connectionTimeout) { + this.connectionTimeout = connectionTimeout; + httpClient.setConnectTimeout(connectionTimeout); + return this; + } + + /** + * Get the date format used to parse/format date parameters. + * @return Date format + */ + public DateFormat getDateFormat() { + return dateFormat; + } + + /** + * Set the date format used to parse/format date parameters. + * @param dateFormat Date format + * @return API client + */ + public ApiClient setDateFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + // Also set the date format for model (de)serialization with Date properties. + this.objectMapper.setDateFormat((DateFormat) dateFormat.clone()); + // Need to rebuild the Client as objectMapper changes. + rebuildHttpClient(); + return this; + } + + /** + * Parse the given string into Date object. + * @param str String + * @return Date + */ + public Date parseDate(String str) { + try { + return dateFormat.parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(e); + } + } + + /** + * Format the given Date object into string. + * @param date Date + * @return Date in string format + */ + public String formatDate(Date date) { + return dateFormat.format(date); + } + + /** + * Format the given parameter object into string. + * @param param Object + * @return Object in string format + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date) { + return formatDate((Date) param); + } {{#jsr310}}else if (param instanceof OffsetDateTime) { + return formatOffsetDateTime((OffsetDateTime) param); + } {{/jsr310}}else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for(Object o : (Collection)param) { + if(b.length() > 0) { + b.append(','); + } + b.append(String.valueOf(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; + } + + /** + * Formats the specified collection query parameters to a list of {@code Pair} objects. + * + * Note that the values of each of the returned Pair objects are percent-encoded. + * + * @param collectionFormat The collection format of the parameter. + * @param name The name of the parameter. + * @param value The value of the parameter. + * @return A list of {@code Pair} objects. + */ + public List parameterToPairs(String collectionFormat, String name, Collection value) { + List params = new ArrayList(); + + // preconditions + if (name == null || name.isEmpty() || value == null) { + return params; + } + + // 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; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * application/vnd.company+json + * @param mime MIME + * @return True if MIME type is boolean + */ + public boolean isJsonMime(String mime) { + 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, + * or matches "any", JSON will be used. + */ + public String selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0 || 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 + * @return Escaped string + */ + public String escapeString(String str) { + try { + return URLEncoder.encode(str, "utf8").replaceAll("\\+", "%20"); + } catch (UnsupportedEncodingException e) { + return str; + } + } + + /** + * Serialize the given Java object into string according the given + * Content-Type (only JSON is supported for now). + * @param obj Object + * @param contentType Content type + * @param formParams Form parameters + * @return Object + * @throws ApiException API exception + */ + public Object serialize(Object obj, String contentType, Map formParams) throws ApiException { + if (contentType.startsWith("multipart/form-data")) { + FormDataMultiPart mp = new FormDataMultiPart(); + for (Entry param: formParams.entrySet()) { + if( param.getValue() instanceof List && !( ( List ) param.getValue() ).isEmpty() + && ( ( List ) param.getValue() ).get( 0 ) instanceof File ) { + @SuppressWarnings( "unchecked" ) + List files = ( List ) param.getValue(); + for( File file : files ) { + mp.bodyPart( new FileDataBodyPart( param.getKey(), file, MediaType.APPLICATION_OCTET_STREAM_TYPE ) ); + } + } else if (param.getValue() instanceof File) { + File file = (File) param.getValue(); + mp.bodyPart(new FileDataBodyPart(param.getKey(), file, MediaType.APPLICATION_OCTET_STREAM_TYPE)); + } else { + mp.field(param.getKey(), parameterToString(param.getValue()), MediaType.MULTIPART_FORM_DATA_TYPE); + } + } + return mp; + } else if (contentType.startsWith("application/x-www-form-urlencoded")) { + return this.getXWWWFormUrlencodedParams(formParams); + } else { + // We let Jersey attempt to serialize the body + return obj; + } + } + + /** + * Build full URL by concatenating base path, the given sub path and query parameters. + * + * @param path The sub path + * @param queryParams The query parameters + * @param collectionQueryParams The collection query parameters + * @return The full URL + */ + private String buildUrl(String path, List queryParams, List collectionQueryParams) { + String baseURL; + if (serverIndex != null) { + if (serverIndex < 0 || serverIndex >= servers.size()) { + throw new ArrayIndexOutOfBoundsException(String.format( + "Invalid index %d when selecting the host settings. Must be less than %d", serverIndex, servers.size() + )); + } + baseURL = servers.get(serverIndex).URL(serverVariables); + } else { + baseURL = basePath; + } + + final StringBuilder url = new StringBuilder(); + url.append(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(); + } + + private ClientResponse getAPIResponse(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames) throws ApiException { + if (body != null && !formParams.isEmpty()) { + throw new ApiException(500, "Cannot have body and form params"); + } + + updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); + + final String url = buildUrl(path, queryParams, collectionQueryParams); + Builder builder; + if (accept == null) { + builder = httpClient.resource(url).getRequestBuilder(); + } else { + builder = httpClient.resource(url).accept(accept); + } + + for (Entry keyValue : headerParams.entrySet()) { + builder = builder.header(keyValue.getKey(), keyValue.getValue()); + } + for (Map.Entry keyValue : defaultHeaderMap.entrySet()) { + if (!headerParams.containsKey(keyValue.getKey())) { + builder = builder.header(keyValue.getKey(), keyValue.getValue()); + } + } + + for (Entry keyValue : cookieParams.entrySet()) { + builder = builder.cookie(new Cookie(keyValue.getKey(), keyValue.getValue())); + } + for (Map.Entry keyValue : defaultCookieMap.entrySet()) { + if (!cookieParams.containsKey(keyValue.getKey())) { + builder = builder.cookie(new Cookie(keyValue.getKey(), keyValue.getValue())); + } + } + + ClientResponse response = null; + + if ("GET".equals(method)) { + response = (ClientResponse) builder.get(ClientResponse.class); + } else if ("POST".equals(method)) { + response = builder.type(contentType).post(ClientResponse.class, serialize(body, contentType, formParams)); + } else if ("PUT".equals(method)) { + response = builder.type(contentType).put(ClientResponse.class, serialize(body, contentType, formParams)); + } else if ("DELETE".equals(method)) { + response = builder.type(contentType).delete(ClientResponse.class, serialize(body, contentType, formParams)); + } else if ("PATCH".equals(method)) { + response = builder.type(contentType).header("X-HTTP-Method-Override", "PATCH").post(ClientResponse.class, serialize(body, contentType, formParams)); + } else if ("HEAD".equals(method)) { + response = builder.head(); + } else { + throw new ApiException(500, "unknown method type " + method); + } + return response; + } + + /** + * Invoke API by sending HTTP request with the given options. + * + * @param Type + * @param path The sub-path of the HTTP URL + * @param method The request method, one of "GET", "POST", "PUT", and "DELETE" + * @param queryParams The query parameters + * @param collectionQueryParams The collection query parameters + * @param body The request body object - if it is not binary, otherwise null + * @param headerParams The header parameters + * @param cookieParams The cookie parameters + * @param formParams The form parameters + * @param accept The request's Accept header + * @param contentType The request's Content-Type header + * @param authNames The authentications to apply + * @param returnType Return type + * @return The response body in type of string + * @throws ApiException API exception + */ + public T invokeAPI(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { + + ClientResponse response = getAPIResponse(path, method, queryParams, collectionQueryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames); + + statusCode = response.getStatusInfo().getStatusCode(); + responseHeaders = response.getHeaders(); + + if(response.getStatusInfo().getStatusCode() == ClientResponse.Status.NO_CONTENT.getStatusCode()) { + return null; + } else if (response.getStatusInfo().getFamily() == Family.SUCCESSFUL) { + if (returnType == null) + return null; + else + return response.getEntity(returnType); + } else { + String message = "error"; + String respBody = null; + if (response.hasEntity()) { + try { + respBody = response.getEntity(String.class); + message = respBody; + } catch (RuntimeException e) { + // e.printStackTrace(); + } + } + throw new ApiException( + response.getStatusInfo().getStatusCode(), + message, + response.getHeaders(), + respBody); + } + } + + /** + * Update query and header parameters based on authentication settings. + * + * @param authNames The authentications to apply + * @param queryParams Query parameters + * @param headerParams Header parameters + * @param cookieParams Cookie parameters + */ + private void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams, Map cookieParams) { + for (String authName : authNames) { + Authentication auth = authentications.get(authName); + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + auth.applyToParams(queryParams, headerParams, cookieParams); + } + } + + /** + * Encode the given form parameters as request body. + * @param formParams Form parameters + * @return HTTP form encoded parameters + */ + private String getXWWWFormUrlencodedParams(Map formParams) { + StringBuilder formParamBuilder = new StringBuilder(); + + for (Entry param : formParams.entrySet()) { + String valueStr = parameterToString(param.getValue()); + try { + formParamBuilder.append(URLEncoder.encode(param.getKey(), "utf8")) + .append("=") + .append(URLEncoder.encode(valueStr, "utf8")); + formParamBuilder.append("&"); + } catch (UnsupportedEncodingException e) { + // move on to next + } + } + + String encodedFormParams = formParamBuilder.toString(); + if (encodedFormParams.endsWith("&")) { + encodedFormParams = encodedFormParams.substring(0, encodedFormParams.length() - 1); + } + + return encodedFormParams; + } +} diff --git a/.generator/templates/BeanValidationException.mustache b/.generator/templates/BeanValidationException.mustache new file mode 100644 index 00000000000..ab8ef30b69b --- /dev/null +++ b/.generator/templates/BeanValidationException.mustache @@ -0,0 +1,27 @@ +package {{invokerPackage}}; + +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.ValidationException; + +public class BeanValidationException extends ValidationException { + /** + * + */ + private static final long serialVersionUID = -5294733947409491364L; + Set> violations; + + public BeanValidationException(Set> violations) { + this.violations = violations; + } + + public Set> getViolations() { + return violations; + } + + public void setViolations(Set> violations) { + this.violations = violations; + } + +} diff --git a/.generator/templates/Configuration.mustache b/.generator/templates/Configuration.mustache new file mode 100644 index 00000000000..cb425df3563 --- /dev/null +++ b/.generator/templates/Configuration.mustache @@ -0,0 +1,28 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +{{>generatedAnnotation}} +public class Configuration { + private static ApiClient defaultApiClient = new ApiClient(); + + /** + * Get the default API client, which would be used when creating API + * instances without providing an API client. + * + * @return Default API client + */ + public static ApiClient getDefaultApiClient() { + return defaultApiClient; + } + + /** + * Set the default API client, which would be used when creating API + * instances without providing an API client. + * + * @param apiClient API client + */ + public static void setDefaultApiClient(ApiClient apiClient) { + defaultApiClient = apiClient; + } +} diff --git a/.generator/templates/CustomInstantDeserializer.mustache b/.generator/templates/CustomInstantDeserializer.mustache new file mode 100644 index 00000000000..5ebea810e1d --- /dev/null +++ b/.generator/templates/CustomInstantDeserializer.mustache @@ -0,0 +1,232 @@ +package {{invokerPackage}}; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonTokenId; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.datatype.threetenbp.DecimalUtils; +import com.fasterxml.jackson.datatype.threetenbp.deser.ThreeTenDateTimeDeserializerBase; +import com.fasterxml.jackson.datatype.threetenbp.function.BiFunction; +import com.fasterxml.jackson.datatype.threetenbp.function.Function; +import org.threeten.bp.DateTimeException; +import org.threeten.bp.DateTimeUtils; +import org.threeten.bp.Instant; +import org.threeten.bp.OffsetDateTime; +import org.threeten.bp.ZoneId; +import org.threeten.bp.ZonedDateTime; +import org.threeten.bp.format.DateTimeFormatter; +import org.threeten.bp.temporal.Temporal; +import org.threeten.bp.temporal.TemporalAccessor; + +import java.io.IOException; +import java.math.BigDecimal; + +/** + * Deserializer for ThreeTen temporal {@link Instant}s, {@link OffsetDateTime}, and {@link ZonedDateTime}s. + * Adapted from the jackson threetenbp InstantDeserializer to add support for deserializing rfc822 format. + * + * @author Nick Williams + */ +public class CustomInstantDeserializer + extends ThreeTenDateTimeDeserializerBase { + private static final long serialVersionUID = 1L; + + public static final CustomInstantDeserializer INSTANT = new CustomInstantDeserializer( + Instant.class, DateTimeFormatter.ISO_INSTANT, + new Function() { + @Override + public Instant apply(TemporalAccessor temporalAccessor) { + return Instant.from(temporalAccessor); + } + }, + new Function() { + @Override + public Instant apply(FromIntegerArguments a) { + return Instant.ofEpochMilli(a.value); + } + }, + new Function() { + @Override + public Instant apply(FromDecimalArguments a) { + return Instant.ofEpochSecond(a.integer, a.fraction); + } + }, + null + ); + + public static final CustomInstantDeserializer OFFSET_DATE_TIME = new CustomInstantDeserializer( + OffsetDateTime.class, DateTimeFormatter.ISO_OFFSET_DATE_TIME, + new Function() { + @Override + public OffsetDateTime apply(TemporalAccessor temporalAccessor) { + return OffsetDateTime.from(temporalAccessor); + } + }, + new Function() { + @Override + public OffsetDateTime apply(FromIntegerArguments a) { + return OffsetDateTime.ofInstant(Instant.ofEpochMilli(a.value), a.zoneId); + } + }, + new Function() { + @Override + public OffsetDateTime apply(FromDecimalArguments a) { + return OffsetDateTime.ofInstant(Instant.ofEpochSecond(a.integer, a.fraction), a.zoneId); + } + }, + new BiFunction() { + @Override + public OffsetDateTime apply(OffsetDateTime d, ZoneId z) { + return d.withOffsetSameInstant(z.getRules().getOffset(d.toLocalDateTime())); + } + } + ); + + public static final CustomInstantDeserializer ZONED_DATE_TIME = new CustomInstantDeserializer( + ZonedDateTime.class, DateTimeFormatter.ISO_ZONED_DATE_TIME, + new Function() { + @Override + public ZonedDateTime apply(TemporalAccessor temporalAccessor) { + return ZonedDateTime.from(temporalAccessor); + } + }, + new Function() { + @Override + public ZonedDateTime apply(FromIntegerArguments a) { + return ZonedDateTime.ofInstant(Instant.ofEpochMilli(a.value), a.zoneId); + } + }, + new Function() { + @Override + public ZonedDateTime apply(FromDecimalArguments a) { + return ZonedDateTime.ofInstant(Instant.ofEpochSecond(a.integer, a.fraction), a.zoneId); + } + }, + new BiFunction() { + @Override + public ZonedDateTime apply(ZonedDateTime zonedDateTime, ZoneId zoneId) { + return zonedDateTime.withZoneSameInstant(zoneId); + } + } + ); + + protected final Function fromMilliseconds; + + protected final Function fromNanoseconds; + + protected final Function parsedToValue; + + protected final BiFunction adjust; + + protected CustomInstantDeserializer(Class supportedType, + DateTimeFormatter parser, + Function parsedToValue, + Function fromMilliseconds, + Function fromNanoseconds, + BiFunction adjust) { + super(supportedType, parser); + this.parsedToValue = parsedToValue; + this.fromMilliseconds = fromMilliseconds; + this.fromNanoseconds = fromNanoseconds; + this.adjust = adjust == null ? new BiFunction() { + @Override + public T apply(T t, ZoneId zoneId) { + return t; + } + } : adjust; + } + + @SuppressWarnings("unchecked") + protected CustomInstantDeserializer(CustomInstantDeserializer base, DateTimeFormatter f) { + super((Class) base.handledType(), f); + parsedToValue = base.parsedToValue; + fromMilliseconds = base.fromMilliseconds; + fromNanoseconds = base.fromNanoseconds; + adjust = base.adjust; + } + + @Override + protected JsonDeserializer withDateFormat(DateTimeFormatter dtf) { + if (dtf == _formatter) { + return this; + } + return new CustomInstantDeserializer(this, dtf); + } + + @Override + public T deserialize(JsonParser parser, DeserializationContext context) throws IOException { + //NOTE: Timestamps contain no timezone info, and are always in configured TZ. Only + //string values have to be adjusted to the configured TZ. + switch (parser.getCurrentTokenId()) { + case JsonTokenId.ID_NUMBER_FLOAT: { + BigDecimal value = parser.getDecimalValue(); + long seconds = value.longValue(); + int nanoseconds = DecimalUtils.extractNanosecondDecimal(value, seconds); + return fromNanoseconds.apply(new FromDecimalArguments( + seconds, nanoseconds, getZone(context))); + } + + case JsonTokenId.ID_NUMBER_INT: { + long timestamp = parser.getLongValue(); + if (context.isEnabled(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS)) { + return this.fromNanoseconds.apply(new FromDecimalArguments( + timestamp, 0, this.getZone(context) + )); + } + return this.fromMilliseconds.apply(new FromIntegerArguments( + timestamp, this.getZone(context) + )); + } + + case JsonTokenId.ID_STRING: { + String string = parser.getText().trim(); + if (string.length() == 0) { + return null; + } + if (string.endsWith("+0000")) { + string = string.substring(0, string.length() - 5) + "Z"; + } + T value; + try { + TemporalAccessor acc = _formatter.parse(string); + value = parsedToValue.apply(acc); + if (context.isEnabled(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)) { + return adjust.apply(value, this.getZone(context)); + } + } catch (DateTimeException e) { + throw _peelDTE(e); + } + return value; + } + } + throw context.mappingException("Expected type float, integer, or string."); + } + + private ZoneId getZone(DeserializationContext context) { + // Instants are always in UTC, so don't waste compute cycles + return (_valueClass == Instant.class) ? null : DateTimeUtils.toZoneId(context.getTimeZone()); + } + + private static class FromIntegerArguments { + public final long value; + public final ZoneId zoneId; + + private FromIntegerArguments(long value, ZoneId zoneId) { + this.value = value; + this.zoneId = zoneId; + } + } + + private static class FromDecimalArguments { + public final long integer; + public final int fraction; + public final ZoneId zoneId; + + private FromDecimalArguments(long integer, int fraction, ZoneId zoneId) { + this.integer = integer; + this.fraction = fraction; + this.zoneId = zoneId; + } + } +} diff --git a/.generator/templates/JSON.mustache b/.generator/templates/JSON.mustache new file mode 100644 index 00000000000..77b72ddc7fc --- /dev/null +++ b/.generator/templates/JSON.mustache @@ -0,0 +1,539 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +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; +{{#joda}} +import org.joda.time.DateTime; +import org.joda.time.LocalDate; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.DateTimeFormatterBuilder; +import org.joda.time.format.ISODateTimeFormat; +{{/joda}} +{{#threetenbp}} +import org.threeten.bp.LocalDate; +import org.threeten.bp.OffsetDateTime; +import org.threeten.bp.format.DateTimeFormatter; +{{/threetenbp}} + +{{#models.0}} +import {{modelPackage}}.*; +{{/models.0}} +import okio.ByteString; + +import java.io.IOException; +import java.io.StringReader; +import java.lang.reflect.Type; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.ParsePosition; +{{#java8}} +import java.time.LocalDate; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +{{/java8}} +import java.util.Date; +import java.util.Locale; +import java.util.Map; +import java.util.HashMap; + +public class JSON { + private Gson gson; + private boolean isLenientOnJson = false; + private DateTypeAdapter dateTypeAdapter = new DateTypeAdapter(); + private SqlDateTypeAdapter sqlDateTypeAdapter = new SqlDateTypeAdapter(); + {{#joda}} + private DateTimeTypeAdapter dateTimeTypeAdapter = new DateTimeTypeAdapter(); + private LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter(); + {{/joda}} + {{#jsr310}} + private OffsetDateTimeTypeAdapter offsetDateTimeTypeAdapter = new OffsetDateTimeTypeAdapter(); + private LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter(); + {{/jsr310}} + private ByteArrayAdapter byteArrayAdapter = new ByteArrayAdapter(); + + @SuppressWarnings("unchecked") + public static GsonBuilder createGson() { + GsonFireBuilder fireBuilder = new GsonFireBuilder() + {{#models}} + {{#model}} + {{#discriminator}} + .registerTypeSelector({{classname}}.class, new TypeSelector<{{classname}}>() { + @Override + public Class getClassForElement(JsonElement readElement) { + Map classByDiscriminatorValue = new HashMap(); + {{#mappedModels}} + classByDiscriminatorValue.put("{{mappingName}}"{{^discriminatorCaseSensitive}}.toUpperCase(Locale.ROOT){{/discriminatorCaseSensitive}}, {{modelName}}.class); + {{/mappedModels}} + classByDiscriminatorValue.put("{{name}}"{{^discriminatorCaseSensitive}}.toUpperCase(Locale.ROOT){{/discriminatorCaseSensitive}}, {{classname}}.class); + return getClassByDiscriminator(classByDiscriminatorValue, + getDiscriminatorValue(readElement, "{{{propertyBaseName}}}")); + } + }) + {{/discriminator}} + {{/model}} + {{/models}} + ; + GsonBuilder builder = fireBuilder.createGsonBuilder(); + {{#disableHtmlEscaping}} + builder.disableHtmlEscaping(); + {{/disableHtmlEscaping}} + return builder; + } + + 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(); + } + + /** + * Returns the Java class that implements the OpenAPI schema for the specified discriminator value. + * + * @param classByDiscriminatorValue The map of discriminator values to Java classes. + * @param discriminatorValue The value of the OpenAPI discriminator in the input data. + * @return The Java class that implements the OpenAPI schema + */ + 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; + } + + public JSON() { + gson = createGson() + .registerTypeAdapter(Date.class, dateTypeAdapter) + .registerTypeAdapter(java.sql.Date.class, sqlDateTypeAdapter) + {{#joda}} + .registerTypeAdapter(DateTime.class, dateTimeTypeAdapter) + .registerTypeAdapter(LocalDate.class, localDateTypeAdapter) + {{/joda}} + {{#jsr310}} + .registerTypeAdapter(OffsetDateTime.class, offsetDateTimeTypeAdapter) + .registerTypeAdapter(LocalDate.class, localDateTypeAdapter) + {{/jsr310}} + .registerTypeAdapter(byte[].class, byteArrayAdapter) + .create(); + } + + /** + * Get Gson. + * + * @return Gson + */ + public Gson getGson() { + return gson; + } + + /** + * Set Gson. + * + * @param gson Gson + * @return JSON + */ + public JSON setGson(Gson gson) { + this.gson = gson; + return this; + } + + public JSON setLenientOnJson(boolean lenientOnJson) { + isLenientOnJson = lenientOnJson; + return this; + } + + /** + * Serialize the given Java object into JSON string. + * + * @param obj Object + * @return String representation of the JSON + */ + public String serialize(Object obj) { + return gson.toJson(obj); + } + + /** + * 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) { + try { + if (isLenientOnJson) { + JsonReader jsonReader = new JsonReader(new StringReader(body)); + // see https://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/stream/JsonReader.html#setLenient(boolean) + jsonReader.setLenient(true); + return gson.fromJson(jsonReader, returnType); + } else { + return gson.fromJson(body, returnType); + } + } catch (JsonParseException e) { + // Fallback processing when failed to parse JSON form response body: + // return the response body string directly for the String return type; + if (returnType.equals(String.class)) { + return (T) body; + } else { + throw (e); + } + } + } + + /** + * Gson TypeAdapter for Byte Array type + */ + public 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 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); + } + } + } + + public JSON setDateTimeFormat(DateTimeFormatter dateFormat) { + dateTimeTypeAdapter.setFormat(dateFormat); + return this; + } + + public JSON setLocalDateFormat(DateTimeFormatter dateFormat) { + localDateTypeAdapter.setFormat(dateFormat); + return this; + } + + {{/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 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); + } + } + } + + public JSON setOffsetDateTimeFormat(DateTimeFormatter dateFormat) { + offsetDateTimeTypeAdapter.setFormat(dateFormat); + return this; + } + + public JSON setLocalDateFormat(DateTimeFormatter dateFormat) { + localDateTypeAdapter.setFormat(dateFormat); + return this; + } + + {{/jsr310}} + /** + * Gson TypeAdapter for java.sql.Date type + * If the dateFormat is null, a simple "yyyy-MM-dd" format will be used + * (more efficient than SimpleDateFormat). + */ + 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 + * If the dateFormat is null, ISO8601Utils will be used. + */ + 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); + } + } + } + + public JSON setDateFormat(DateFormat dateFormat) { + dateTypeAdapter.setFormat(dateFormat); + return this; + } + + public JSON setSqlDateFormat(DateFormat dateFormat) { + sqlDateTypeAdapter.setFormat(dateFormat); + return this; + } + +} diff --git a/.generator/templates/JavaTimeFormatter.mustache b/.generator/templates/JavaTimeFormatter.mustache new file mode 100644 index 00000000000..07d0eb6ce72 --- /dev/null +++ b/.generator/templates/JavaTimeFormatter.mustache @@ -0,0 +1,60 @@ +{{>licenseInfo}} +package {{invokerPackage}}; + +{{^threetenbp}} +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +{{/threetenbp}} +{{#threetenbp}} +import org.threeten.bp.OffsetDateTime; +import org.threeten.bp.format.DateTimeFormatter; +import org.threeten.bp.format.DateTimeParseException; +{{/threetenbp}} + +/** + * Class that add parsing/formatting support for Java 8+ {@code OffsetDateTime} class. + * It's generated for java clients when {@code AbstractJavaCodegen#dateLibrary} specified as {@code java8}. + */ +{{>generatedAnnotation}} +public class JavaTimeFormatter { + + private DateTimeFormatter offsetDateTimeFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME; + + /** + * Get the date format used to parse/format {@code OffsetDateTime} parameters. + * @return DateTimeFormatter + */ + public DateTimeFormatter getOffsetDateTimeFormatter() { + return offsetDateTimeFormatter; + } + + /** + * Set the date format used to parse/format {@code OffsetDateTime} parameters. + * @param offsetDateTimeFormatter {@code DateTimeFormatter} + */ + public void setOffsetDateTimeFormatter(DateTimeFormatter offsetDateTimeFormatter) { + this.offsetDateTimeFormatter = offsetDateTimeFormatter; + } + + /** + * Parse the given string into {@code OffsetDateTime} object. + * @param str String + * @return {@code OffsetDateTime} + */ + public OffsetDateTime parseOffsetDateTime(String str) { + try { + return OffsetDateTime.parse(str, offsetDateTimeFormatter); + } catch (DateTimeParseException e) { + throw new RuntimeException(e); + } + } + /** + * Format the given {@code OffsetDateTime} object into string. + * @param offsetDateTime {@code OffsetDateTime} + * @return {@code OffsetDateTime} in string format + */ + public String formatOffsetDateTime(OffsetDateTime offsetDateTime) { + return offsetDateTimeFormatter.format(offsetDateTime); + } +} diff --git a/.generator/templates/Pair.mustache b/.generator/templates/Pair.mustache new file mode 100644 index 00000000000..ff9e06b20d4 --- /dev/null +++ b/.generator/templates/Pair.mustache @@ -0,0 +1,50 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +{{>generatedAnnotation}} +public class Pair { + private String name = ""; + private String value = ""; + + public Pair (String name, String value) { + setName(name); + setValue(value); + } + + private void setName(String name) { + if (!isValidString(name)) { + return; + } + + this.name = name; + } + + private void setValue(String value) { + if (!isValidString(value)) { + return; + } + + this.value = value; + } + + public String getName() { + return this.name; + } + + public String getValue() { + return this.value; + } + + private boolean isValidString(String arg) { + if (arg == null) { + return false; + } + + if (arg.trim().isEmpty()) { + return false; + } + + return true; + } +} diff --git a/.generator/templates/README.mustache b/.generator/templates/README.mustache new file mode 100644 index 00000000000..a5b66abc2e2 --- /dev/null +++ b/.generator/templates/README.mustache @@ -0,0 +1,50 @@ +## Documentation for API Endpoints + +All URIs are relative to *{{basePath}}* + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{commonPath}}{{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} + +## Documentation for Models + +{{#models}}{{#model}} - [{{classname}}]({{classname}}.md) +{{/model}}{{/models}} + +## Documentation for Authorization + +{{^authMethods}}All endpoints do not require authorization. +{{/authMethods}}Authentication schemes defined for the API: +{{#authMethods}}### {{name}} + +{{#isApiKey}} + +- **Type**: API key +- **API key parameter name**: {{keyParamName}} +- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}} +{{/isApiKey}} +{{#isBasic}} + +- **Type**: HTTP basic authentication +{{/isBasic}} +{{#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/.generator/templates/RFC3339DateFormat.mustache b/.generator/templates/RFC3339DateFormat.mustache new file mode 100644 index 00000000000..cacd793e738 --- /dev/null +++ b/.generator/templates/RFC3339DateFormat.mustache @@ -0,0 +1,44 @@ +{{>licenseInfo}} +package {{invokerPackage}}; + +import com.fasterxml.jackson.databind.util.StdDateFormat; + +import java.text.DateFormat; +import java.text.FieldPosition; +import java.text.ParsePosition; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.TimeZone; + +public class RFC3339DateFormat extends DateFormat { + private static final long serialVersionUID = 1L; + private static final TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC"); + + private final StdDateFormat fmt = new StdDateFormat() + .withTimeZone(TIMEZONE_Z) + .withColonInTimeZone(true); + + public RFC3339DateFormat() { + this.calendar = new GregorianCalendar(); + } + + @Override + public Date parse(String source) { + return parse(source, new ParsePosition(0)); + } + + @Override + public Date parse(String source, ParsePosition pos) { + return fmt.parse(source, pos); + } + + @Override + public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { + return fmt.format(date, toAppendTo, fieldPosition); + } + + @Override + public Object clone() { + return this; + } +} \ No newline at end of file diff --git a/.generator/templates/ServerConfiguration.mustache b/.generator/templates/ServerConfiguration.mustache new file mode 100644 index 00000000000..f976c542b19 --- /dev/null +++ b/.generator/templates/ServerConfiguration.mustache @@ -0,0 +1,58 @@ +package {{invokerPackage}}; + +import java.util.Map; + +/** + * Representing a Server configuration. + */ +public class ServerConfiguration { + public String URL; + public String description; + public Map variables; + + /** + * @param URL A URL to the target host. + * @param description A describtion of the host designated by the URL. + * @param variables A map between a variable name and its value. The value is used for substitution in the server's URL template. + */ + public ServerConfiguration(String URL, String description, Map variables) { + this.URL = URL; + this.description = description; + this.variables = variables; + } + + /** + * Format URL template using given variables. + * + * @param variables A map between a variable name and its value. + * @return Formatted URL. + */ + public String URL(Map variables) { + String url = this.URL; + + // go through variables and replace placeholders + for (Map.Entry variable: this.variables.entrySet()) { + String name = variable.getKey(); + ServerVariable serverVariable = variable.getValue(); + String value = serverVariable.defaultValue; + + if (variables != null && variables.containsKey(name)) { + value = variables.get(name); + if (serverVariable.enumValues.size() > 0 && !serverVariable.enumValues.contains(value)) { + throw new RuntimeException("The variable " + name + " in the server URL has invalid value " + value + "."); + } + } + url = url.replaceAll("\\{" + name + "\\}", value); + } + return url; + } + + /** + * Format URL template using default server variables. + * + * @return Formatted URL. + */ + public String URL() { + return URL(null); + } +} diff --git a/.generator/templates/ServerVariable.mustache b/.generator/templates/ServerVariable.mustache new file mode 100644 index 00000000000..1978b1eb95e --- /dev/null +++ b/.generator/templates/ServerVariable.mustache @@ -0,0 +1,23 @@ +package {{invokerPackage}}; + +import java.util.HashSet; + +/** + * Representing a Server Variable for server URL template substitution. + */ +public class ServerVariable { + public String description; + public String defaultValue; + public HashSet enumValues = null; + + /** + * @param description A description for the server variable. + * @param defaultValue The default value to use for substitution. + * @param enumValues An enumeration of string values to be used if the substitution options are from a limited set. + */ + public ServerVariable(String description, String defaultValue, HashSet enumValues) { + this.description = description; + this.defaultValue = defaultValue; + this.enumValues = enumValues; + } +} diff --git a/.generator/templates/StringUtil.mustache b/.generator/templates/StringUtil.mustache new file mode 100644 index 00000000000..e3d5d6e9088 --- /dev/null +++ b/.generator/templates/StringUtil.mustache @@ -0,0 +1,72 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import java.util.Collection; +import java.util.Iterator; + +{{>generatedAnnotation}} +public class StringUtil { + /** + * Check if the given array contains the given value (with case-insensitive comparison). + * + * @param array The array + * @param value The value to search + * @return true if the array contains the value + */ + public static boolean containsIgnoreCase(String[] array, String value) { + for (String str : array) { + if (value == null && str == null) { + return true; + } + if (value != null && value.equalsIgnoreCase(str)) { + return true; + } + } + return false; + } + + /** + * Join an array of strings with the given separator. + *

+ * Note: This might be replaced by utility method from commons-lang or guava someday + * if one of those libraries is added as dependency. + *

+ * + * @param array The array of strings + * @param separator The separator + * @return the resulting string + */ + public static String join(String[] array, String separator) { + int len = array.length; + if (len == 0) { + return ""; + } + + StringBuilder out = new StringBuilder(); + out.append(array[0]); + for (int i = 1; i < len; i++) { + out.append(separator).append(array[i]); + } + return out.toString(); + } + + /** + * Join a list of strings with the given separator. + * + * @param list The list of strings + * @param separator The separator + * @return the resulting string + */ + public static String join(Collection list, String separator) { + Iterator iterator = list.iterator(); + StringBuilder out = new StringBuilder(); + if (iterator.hasNext()) { + out.append(iterator.next()); + } + while (iterator.hasNext()) { + out.append(separator).append(iterator.next()); + } + return out.toString(); + } +} diff --git a/.generator/templates/additionalEnumTypeAnnotations.mustache b/.generator/templates/additionalEnumTypeAnnotations.mustache new file mode 100644 index 00000000000..aa524798b42 --- /dev/null +++ b/.generator/templates/additionalEnumTypeAnnotations.mustache @@ -0,0 +1,2 @@ +{{#additionalEnumTypeAnnotations}}{{{.}}} +{{/additionalEnumTypeAnnotations}} \ No newline at end of file diff --git a/.generator/templates/additionalModelTypeAnnotations.mustache b/.generator/templates/additionalModelTypeAnnotations.mustache new file mode 100644 index 00000000000..f4871c02cc2 --- /dev/null +++ b/.generator/templates/additionalModelTypeAnnotations.mustache @@ -0,0 +1,2 @@ +{{#additionalModelTypeAnnotations}}{{{.}}} +{{/additionalModelTypeAnnotations}} \ No newline at end of file diff --git a/.generator/templates/api.mustache b/.generator/templates/api.mustache new file mode 100644 index 00000000000..894cb011239 --- /dev/null +++ b/.generator/templates/api.mustache @@ -0,0 +1,122 @@ +{{>licenseInfo}} +package {{package}}; + +import com.sun.jersey.api.client.GenericType; + +import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.Configuration; +import {{modelPackage}}.*; +import {{invokerPackage}}.Pair; + +{{#imports}}import {{import}}; +{{/imports}} + + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}} { + private ApiClient apiClient; + + public {{classname}}() { + this(Configuration.getDefaultApiClient()); + } + + public {{classname}}(ApiClient apiClient) { + this.apiClient = apiClient; + } + + public ApiClient getApiClient() { + return apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.apiClient = apiClient; + } + + {{#operation}} + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}{{/required}} + {{/allParams}} + {{#returnType}} + * @return {{returnType}} + {{/returnType}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + } + {{/required}}{{/allParams}} + // create path and map variables + String localVarPath = "{{{path}}}"{{#pathParams}} + .replaceAll("\\{" + "{{baseName}}" + "\\}", apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; + + // query params + {{javaUtilPrefix}}List localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}List localVarCollectionQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}Map localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarCookieParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap(); + + {{#queryParams}} + {{#collectionFormat}}localVarCollectionQueryParams.addAll(apiClient.parameterToPairs("{{{collectionFormat}}}", {{/collectionFormat}}{{^collectionFormat}}localVarQueryParams.addAll(apiClient.parameterToPair({{/collectionFormat}}"{{baseName}}", {{paramName}})); + {{/queryParams}} + + {{#headerParams}}if ({{paramName}} != null) + localVarHeaderParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); + {{/headerParams}} + + {{#cookieParams}}if ({{paramName}} != null) + localVarCookieParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); + {{/cookieParams}} + + {{#formParams}}if ({{paramName}} != null) + localVarFormParams.put("{{baseName}}", {{paramName}}); + {{/formParams}} + + final String[] localVarAccepts = { + {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} + }; + final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); + + final String[] localVarContentTypes = { + {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} + }; + final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); + + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; + + {{#returnType}} + GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {}; + return apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); + {{/returnType}}{{^returnType}} + apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, null); + {{/returnType}} + } + {{/operation}} +} +{{/operations}} diff --git a/.generator/templates/apiException.mustache b/.generator/templates/apiException.mustache new file mode 100644 index 00000000000..5b450c9ba62 --- /dev/null +++ b/.generator/templates/apiException.mustache @@ -0,0 +1,80 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import java.util.Map; +import java.util.List; + +{{>generatedAnnotation}} +public class ApiException extends{{#useRuntimeException}} RuntimeException {{/useRuntimeException}}{{^useRuntimeException}} Exception {{/useRuntimeException}}{ + private int code = 0; + private Map> responseHeaders = null; + private String responseBody = null; + + public ApiException() {} + + public ApiException(Throwable throwable) { + super(throwable); + } + + public ApiException(String message) { + super(message); + } + + public ApiException(String message, Throwable throwable, int code, Map> responseHeaders, String responseBody) { + super(message, throwable); + this.code = code; + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + + public ApiException(String message, int code, Map> responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(String message, Throwable throwable, int code, Map> responseHeaders) { + this(message, throwable, code, responseHeaders, null); + } + + public ApiException(int code, Map> responseHeaders, String responseBody) { + this((String) null, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(int code, String message) { + super(message); + this.code = code; + } + + public ApiException(int code, String message, Map> responseHeaders, String responseBody) { + this(code, message); + this.responseHeaders = responseHeaders; + 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; + } +} diff --git a/.generator/templates/apiOperation.mustache b/.generator/templates/apiOperation.mustache new file mode 100644 index 00000000000..97adb0ea285 --- /dev/null +++ b/.generator/templates/apiOperation.mustache @@ -0,0 +1,28 @@ +{{>licenseInfo}} +package {{invokerPackage}}; + +import io.swagger.v3.oas.models.Operation; + +public class ApiOperation { + private final String path; + private final String method; + private final Operation operation; + + public ApiOperation(String path, String method, Operation operation) { + this.path = path; + this.method = method; + this.operation = operation; + } + + public Operation getOperation() { + return operation; + } + + public String getPath() { + return path; + } + + public String getMethod() { + return method; + } +} diff --git a/.generator/templates/api_doc.mustache b/.generator/templates/api_doc.mustache new file mode 100644 index 00000000000..cd7ecc6aefb --- /dev/null +++ b/.generator/templates/api_doc.mustache @@ -0,0 +1,108 @@ +# {{classname}}{{#description}} + +{{description}}{{/description}} + +All URIs are relative to *{{basePath}}* + +Method | HTTP request | Description +------------- | ------------- | ------------- +{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{commonPath}}{{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}} + +{{#operations}} +{{#operation}} + +## {{operationId}} + +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}) + +{{summary}}{{#notes}} + +{{{unescapedNotes}}}{{/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}}}"); + {{#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}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}});{{#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}}]{{/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/.generator/templates/api_test.mustache b/.generator/templates/api_test.mustache new file mode 100644 index 00000000000..38c58efb711 --- /dev/null +++ b/.generator/templates/api_test.mustache @@ -0,0 +1,51 @@ +{{>licenseInfo}} + +package {{package}}; + +import {{invokerPackage}}.ApiException; +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Test; +import org.junit.Ignore; +import org.junit.Assert; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +{{/fullJavaUtil}} +/** + * API tests for {{classname}} + */ +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}} + //{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + + // TODO: test validations + } + {{/operation}} + {{/operations}} +} diff --git a/.generator/templates/auth/ApiKeyAuth.mustache b/.generator/templates/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..991ae235003 --- /dev/null +++ b/.generator/templates/auth/ApiKeyAuth.mustache @@ -0,0 +1,66 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; + +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) { + 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/.generator/templates/auth/Authentication.mustache b/.generator/templates/auth/Authentication.mustache new file mode 100644 index 00000000000..033de98d562 --- /dev/null +++ b/.generator/templates/auth/Authentication.mustache @@ -0,0 +1,19 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; + +import java.util.Map; +import java.util.List; + +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 + */ + void applyToParams(List queryParams, Map headerParams, Map cookieParams); +} diff --git a/.generator/templates/auth/HttpBasicAuth.mustache b/.generator/templates/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..4d362cbaf54 --- /dev/null +++ b/.generator/templates/auth/HttpBasicAuth.mustache @@ -0,0 +1,60 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; + +{{^java8}} +import com.migcomponents.migbase64.Base64; +{{/java8}} +{{#java8}} +import java.util.Base64; +import java.nio.charset.StandardCharsets; +{{/java8}} + +import java.util.Map; +import java.util.List; + +{{^java8}} +import java.io.UnsupportedEncodingException; +{{/java8}} + +{{>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) { + if (username == null && password == null) { + return; + } + String str = (username == null ? "" : username) + ":" + (password == null ? "" : password); +{{^java8}} + try { + headerParams.put("Authorization", "Basic " + Base64.encodeToString(str.getBytes("UTF-8"), false)); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } +{{/java8}} +{{#java8}} + headerParams.put("Authorization", "Basic " + Base64.getEncoder().encodeToString(str.getBytes(StandardCharsets.UTF_8))); +{{/java8}} + } +} diff --git a/.generator/templates/auth/HttpBearerAuth.mustache b/.generator/templates/auth/HttpBearerAuth.mustache new file mode 100644 index 00000000000..322281f8716 --- /dev/null +++ b/.generator/templates/auth/HttpBearerAuth.mustache @@ -0,0 +1,49 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; + +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 Authorization header. + * + * @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 Authorization header. + * + * @param bearerToken The bearer token to send in the Authorization header + */ + public void setBearerToken(String bearerToken) { + this.bearerToken = bearerToken; + } + + @Override + public void applyToParams(List queryParams, Map headerParams, Map cookieParams) { + 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/.generator/templates/auth/OAuth.mustache b/.generator/templates/auth/OAuth.mustache new file mode 100644 index 00000000000..5cb98e7cb3b --- /dev/null +++ b/.generator/templates/auth/OAuth.mustache @@ -0,0 +1,28 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; + +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) { + if (accessToken != null) { + headerParams.put("Authorization", "Bearer " + accessToken); + } + } +} diff --git a/.generator/templates/auth/OAuthFlow.mustache b/.generator/templates/auth/OAuthFlow.mustache new file mode 100644 index 00000000000..07b7f3aa673 --- /dev/null +++ b/.generator/templates/auth/OAuthFlow.mustache @@ -0,0 +1,11 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +{{>generatedAnnotation}} +public enum OAuthFlow { + accessCode, //called authorizationCode in OpenAPI 3.0 + implicit, + password, + application //called clientCredentials in OpenAPI 3.0 +} diff --git a/.generator/templates/beanValidation.mustache b/.generator/templates/beanValidation.mustache new file mode 100644 index 00000000000..1bc9afa8f68 --- /dev/null +++ b/.generator/templates/beanValidation.mustache @@ -0,0 +1,16 @@ +{{#required}} + @NotNull +{{/required}} +{{#isContainer}} +{{^isPrimitiveType}} +{{^isEnum}} + @Valid +{{/isEnum}} +{{/isPrimitiveType}} +{{/isContainer}} +{{^isContainer}} +{{^isPrimitiveType}} + @Valid +{{/isPrimitiveType}} +{{/isContainer}} +{{>beanValidationCore}} \ No newline at end of file diff --git a/.generator/templates/beanValidationCore.mustache b/.generator/templates/beanValidationCore.mustache new file mode 100644 index 00000000000..1f9f43e7b86 --- /dev/null +++ b/.generator/templates/beanValidationCore.mustache @@ -0,0 +1,20 @@ +{{#pattern}}{{^isByteArray}} @Pattern(regexp="{{{pattern}}}"){{/isByteArray}}{{/pattern}}{{! +minLength && maxLength set +}}{{#minLength}}{{#maxLength}} @Size(min={{minLength}},max={{maxLength}}){{/maxLength}}{{/minLength}}{{! +minLength set, maxLength not +}}{{#minLength}}{{^maxLength}} @Size(min={{minLength}}){{/maxLength}}{{/minLength}}{{! +minLength not set, maxLength set +}}{{^minLength}}{{#maxLength}} @Size(max={{maxLength}}){{/maxLength}}{{/minLength}}{{! +@Size: minItems && maxItems set +}}{{#minItems}}{{#maxItems}} @Size(min={{minItems}},max={{maxItems}}){{/maxItems}}{{/minItems}}{{! +@Size: minItems set, maxItems not +}}{{#minItems}}{{^maxItems}} @Size(min={{minItems}}){{/maxItems}}{{/minItems}}{{! +@Size: minItems not set && maxItems set +}}{{^minItems}}{{#maxItems}} @Size(max={{maxItems}}){{/maxItems}}{{/minItems}}{{! +check for integer or long / all others=decimal type with @Decimal* +isInteger set +}}{{#isInteger}}{{#minimum}} @Min({{minimum}}){{/minimum}}{{#maximum}} @Max({{maximum}}){{/maximum}}{{/isInteger}}{{! +isLong set +}}{{#isLong}}{{#minimum}} @Min({{minimum}}L){{/minimum}}{{#maximum}} @Max({{maximum}}L){{/maximum}}{{/isLong}}{{! +Not Integer, not Long => we have a decimal value! +}}{{^isInteger}}{{^isLong}}{{#minimum}} @DecimalMin({{#exclusiveMinimum}}value={{/exclusiveMinimum}}"{{minimum}}"{{#exclusiveMinimum}},inclusive=false{{/exclusiveMinimum}}){{/minimum}}{{#maximum}} @DecimalMax({{#exclusiveMaximum}}value={{/exclusiveMaximum}}"{{maximum}}"{{#exclusiveMaximum}},inclusive=false{{/exclusiveMaximum}}){{/maximum}}{{/isLong}}{{/isInteger}} \ No newline at end of file diff --git a/.generator/templates/beanValidationQueryParams.mustache b/.generator/templates/beanValidationQueryParams.mustache new file mode 100644 index 00000000000..f8eef8f94c7 --- /dev/null +++ b/.generator/templates/beanValidationQueryParams.mustache @@ -0,0 +1 @@ +{{#required}} @NotNull{{/required}}{{>beanValidationCore}} \ No newline at end of file diff --git a/.generator/templates/build.gradle.mustache b/.generator/templates/build.gradle.mustache new file mode 100644 index 00000000000..95fc41cbf42 --- /dev/null +++ b/.generator/templates/build.gradle.mustache @@ -0,0 +1,167 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + maven { url "https://repo1.maven.org/maven2" } + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +repositories { + maven { url "https://repo1.maven.org/maven2" } + jcenter() +} + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + } + + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + {{#java8}} + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + {{/java8}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } + + task sourcesJar(type: Jar, dependsOn: classes) { + classifier = 'sources' + from sourceSets.main.allSource + } + + task javadocJar(type: Jar, dependsOn: javadoc) { + classifier = 'javadoc' + from javadoc.destinationDir + } + + artifacts { + archives sourcesJar + archives javadocJar + } +} + +ext { + swagger_annotations_version = "1.5.22" + jackson_version = "2.12.1" + jackson_databind_version = "2.10.5.1" + {{#openApiNullable}} + jackson_databind_nullable_version = "0.2.1" + {{/openApiNullable}} + {{#threetenbp}} + jackson_threetenbp_version = "2.9.10" + {{/threetenbp}} + jersey_version = "1.19.4" + jodatime_version = "2.9.9" + junit_version = "4.13.1" +} + +dependencies { + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "com.sun.jersey:jersey-client:$jersey_version" + implementation "com.sun.jersey.contribs:jersey-multipart:$jersey_version" + 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_databind_version" + implementation "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + {{#openApiNullable}} + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} + {{#joda}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + {{/joda}} + {{#java8}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{/java8}} + {{#threetenbp}} + implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threetenbp_version" + {{/threetenbp}} + {{^java8}} + implementation "com.brsanthu:migbase64:2.2" + {{/java8}} + implementation 'javax.annotation:javax.annotation-api:1.3.2' + testImplementation "junit:junit:$junit_version" +} + diff --git a/.generator/templates/build.sbt.mustache b/.generator/templates/build.sbt.mustache new file mode 100644 index 00000000000..464090415c4 --- /dev/null +++ b/.generator/templates/build.sbt.mustache @@ -0,0 +1 @@ +# TODO diff --git a/.generator/templates/enum_outer_doc.mustache b/.generator/templates/enum_outer_doc.mustache new file mode 100644 index 00000000000..20c512aaeae --- /dev/null +++ b/.generator/templates/enum_outer_doc.mustache @@ -0,0 +1,7 @@ +# {{classname}} + +## Enum + +{{#allowableValues}}{{#enumVars}} +* `{{name}}` (value: `{{{value}}}`) +{{/enumVars}}{{/allowableValues}} diff --git a/.generator/templates/generatedAnnotation.mustache b/.generator/templates/generatedAnnotation.mustache new file mode 100644 index 00000000000..875d7b97afe --- /dev/null +++ b/.generator/templates/generatedAnnotation.mustache @@ -0,0 +1 @@ +@javax.annotation.Generated(value = "{{generatorClass}}"{{^hideGenerationTimestamp}}, date = "{{generatedDate}}"{{/hideGenerationTimestamp}}) \ No newline at end of file diff --git a/.generator/templates/git_push.sh.mustache b/.generator/templates/git_push.sh.mustache new file mode 100755 index 00000000000..8b3f689c912 --- /dev/null +++ b/.generator/templates/git_push.sh.mustache @@ -0,0 +1,58 @@ +#!/bin/sh +# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ +# +# Usage example: /bin/sh ./git_push.sh wing328 openapi-pestore-perl "minor update" "gitlab.com" + +git_user_id=$1 +git_repo_id=$2 +release_note=$3 +git_host=$4 + +if [ "$git_host" = "" ]; then + git_host="{{{gitHost}}}" + echo "[INFO] No command line input provided. Set \$git_host to $git_host" +fi + +if [ "$git_user_id" = "" ]; then + git_user_id="{{{gitUserId}}}" + echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id" +fi + +if [ "$git_repo_id" = "" ]; then + git_repo_id="{{{gitRepoId}}}" + echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id" +fi + +if [ "$release_note" = "" ]; then + release_note="{{{releaseNote}}}" + echo "[INFO] No command line input provided. Set \$release_note to $release_note" +fi + +# Initialize the local directory as a Git repository +git init + +# Adds the files in the local repository and stages them for commit. +git add . + +# Commits the tracked changes and prepares them to be pushed to a remote repository. +git commit -m "$release_note" + +# Sets the new remote +git_remote=`git remote` +if [ "$git_remote" = "" ]; then # git remote not defined + + if [ "$GIT_TOKEN" = "" ]; then + echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment." + git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git + else + git remote add origin https://${git_user_id}:${GIT_TOKEN}@${git_host}/${git_user_id}/${git_repo_id}.git + fi + +fi + +git pull origin master + +# Pushes (Forces) the changes in the local repository up to the remote repository +echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git" +git push origin master 2>&1 | grep -v 'To https' + diff --git a/.generator/templates/gitignore.mustache b/.generator/templates/gitignore.mustache new file mode 100644 index 00000000000..a530464afa1 --- /dev/null +++ b/.generator/templates/gitignore.mustache @@ -0,0 +1,21 @@ +*.class + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear + +# exclude jar for gradle wrapper +!gradle/wrapper/*.jar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +# build files +**/target +target +.gradle +build diff --git a/.generator/templates/gradle-wrapper.jar b/.generator/templates/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f GIT binary patch literal 59203 zcma&O1CT9Y(k9%tZQHhO+qUh#ZQHhO+qmuS+qP|E@9xZO?0h@l{(r>DQ>P;GjjD{w zH}lENr;dU&FbEU?00aa80D$0M0RRB{U*7-#kbjS|qAG&4l5%47zyJ#WrfA#1$1Ctx zf&Z_d{GW=lf^w2#qRJ|CvSJUi(^E3iv~=^Z(zH}F)3Z%V3`@+rNB7gTVU{Bb~90p|f+0(v;nz01EG7yDMX9@S~__vVgv%rS$+?IH+oZ03D5zYrv|^ zC1J)SruYHmCki$jLBlTaE5&dFG9-kq3!^i>^UQL`%gn6)jz54$WDmeYdsBE9;PqZ_ zoGd=P4+|(-u4U1dbAVQrFWoNgNd;0nrghPFbQrJctO>nwDdI`Q^i0XJDUYm|T|RWc zZ3^Qgo_Qk$%Fvjj-G}1NB#ZJqIkh;kX%V{THPqOyiq)d)0+(r9o(qKlSp*hmK#iIY zA^)Vr$-Hz<#SF=0@tL@;dCQsm`V9s1vYNq}K1B)!XSK?=I1)tX+bUV52$YQu*0%fnWEukW>mxkz+%3-S!oguE8u#MGzST8_Dy^#U?fA@S#K$S@9msUiX!gd_ow>08w5)nX{-KxqMOo7d?k2&?Vf z&diGDtZr(0cwPe9z9FAUSD9KC)7(n^lMWuayCfxzy8EZsns%OEblHFSzP=cL6}?J| z0U$H!4S_TVjj<`6dy^2j`V`)mC;cB%* z8{>_%E1^FH!*{>4a7*C1v>~1*@TMcLK{7nEQ!_igZC}ikJ$*<$yHy>7)oy79A~#xE zWavoJOIOC$5b6*q*F_qN1>2#MY)AXVyr$6x4b=$x^*aqF*L?vmj>Mgv+|ITnw_BoW zO?jwHvNy^prH{9$rrik1#fhyU^MpFqF2fYEt(;4`Q&XWOGDH8k6M=%@fics4ajI;st# zCU^r1CK&|jzUhRMv;+W~6N;u<;#DI6cCw-otsc@IsN3MoSD^O`eNflIoR~l4*&-%RBYk@gb^|-JXs&~KuSEmMxB}xSb z@K76cXD=Y|=I&SNC2E+>Zg?R6E%DGCH5J1nU!A|@eX9oS(WPaMm==k2s_ueCqdZw| z&hqHp)47`c{BgwgvY2{xz%OIkY1xDwkw!<0veB#yF4ZKJyabhyyVS`gZepcFIk%e2 zTcrmt2@-8`7i-@5Nz>oQWFuMC_KlroCl(PLSodswHqJ3fn<;gxg9=}~3x_L3P`9Sn zChIf}8vCHvTriz~T2~FamRi?rh?>3bX1j}%bLH+uFX+p&+^aXbOK7clZxdU~6Uxgy z8R=obwO4dL%pmVo*Ktf=lH6hnlz_5k3cG;m8lgaPp~?eD!Yn2kf)tU6PF{kLyn|oI@eQ`F z3IF7~Blqg8-uwUuWZScRKn%c2_}dXB6Dx_&xR*n9M9LXasJhtZdr$vBY!rP{c@=)& z#!?L$2UrkvClwQO>U*fSMs67oSj2mxiJ$t;E|>q%Kh_GzzWWO&3;ufU%2z%ucBU8H z3WIwr$n)cfCXR&>tyB7BcSInK>=ByZA%;cVEJhcg<#6N{aZC4>K41XF>ZgjG`z_u& zGY?;Ad?-sgiOnI`oppF1o1Gurqbi*;#x2>+SSV6|1^G@ooVy@fg?wyf@0Y!UZ4!}nGuLeC^l)6pwkh|oRY`s1Pm$>zZ3u-83T|9 zGaKJIV3_x+u1>cRibsaJpJqhcm%?0-L;2 zitBrdRxNmb0OO2J%Y&Ym(6*`_P3&&5Bw157{o7LFguvxC$4&zTy#U=W*l&(Q2MNO} zfaUwYm{XtILD$3864IA_nn34oVa_g^FRuHL5wdUd)+W-p-iWCKe8m_cMHk+=? zeKX)M?Dt(|{r5t7IenkAXo%&EXIb-i^w+0CX0D=xApC=|Xy(`xy+QG^UyFe z+#J6h_&T5i#sV)hj3D4WN%z;2+jJcZxcI3*CHXGmOF3^)JD5j&wfX)e?-|V0GPuA+ zQFot%aEqGNJJHn$!_}#PaAvQ^{3-Ye7b}rWwrUmX53(|~i0v{}G_sI9uDch_brX&6 zWl5Ndj-AYg(W9CGfQf<6!YmY>Ey)+uYd_JNXH=>|`OH-CDCmcH(0%iD_aLlNHKH z7bcW-^5+QV$jK?R*)wZ>r9t}loM@XN&M-Pw=F#xn(;u3!(3SXXY^@=aoj70;_=QE9 zGghsG3ekq#N||u{4We_25U=y#T*S{4I{++Ku)> zQ!DZW;pVcn>b;&g2;YE#+V`v*Bl&Y-i@X6D*OpNA{G@JAXho&aOk(_j^weW{#3X5Y z%$q_wpb07EYPdmyH(1^09i$ca{O<}7) zRWncXdSPgBE%BM#by!E>tdnc$8RwUJg1*x($6$}ae$e9Knj8gvVZe#bLi!<+&BkFj zg@nOpDneyc+hU9P-;jmOSMN|*H#>^Ez#?;%C3hg_65leSUm;iz)UkW)jX#p)e&S&M z1|a?wDzV5NVnlhRBCd_;F87wp>6c<&nkgvC+!@KGiIqWY4l}=&1w7|r6{oBN8xyzh zG$b#2=RJp_iq6)#t5%yLkKx(0@D=C3w+oiXtSuaQ%I1WIb-eiE$d~!)b@|4XLy!CZ z9p=t=%3ad@Ep+<9003D2KZ5VyP~_n$=;~r&YUg5UZ0KVD&tR1DHy9x)qWtKJp#Kq# zP*8p#W(8JJ_*h_3W}FlvRam?<4Z+-H77^$Lvi+#vmhL9J zJ<1SV45xi;SrO2f=-OB(7#iNA5)x1uNC-yNxUw|!00vcW2PufRm>e~toH;M0Q85MQLWd?3O{i8H+5VkR@l9Dg-ma ze2fZ%>G(u5(k9EHj2L6!;(KZ8%8|*-1V|B#EagbF(rc+5iL_5;Eu)L4Z-V;0HfK4d z*{utLse_rvHZeQ>V5H=f78M3Ntg1BPxFCVD{HbNA6?9*^YIq;B-DJd{Ca2L#)qWP? zvX^NhFmX?CTWw&Ns}lgs;r3i+Bq@y}Ul+U%pzOS0Fcv9~aB(0!>GT0)NO?p=25LjN z2bh>6RhgqD7bQj#k-KOm@JLgMa6>%-ok1WpOe)FS^XOU{c?d5shG(lIn3GiVBxmg`u%-j=)^v&pX1JecJics3&jvPI)mDut52? z3jEA)DM%}BYbxxKrizVYwq?(P&19EXlwD9^-6J+4!}9{ywR9Gk42jjAURAF&EO|~N z)?s>$Da@ikI4|^z0e{r`J8zIs>SpM~Vn^{3fArRu;?+43>lD+^XtUcY1HidJwnR6+ z!;oG2=B6Z_=M%*{z-RaHc(n|1RTKQdNjjV!Pn9lFt^4w|AeN06*j}ZyhqZ^!-=cyGP_ShV1rGxkx8t zB;8`h!S{LD%ot``700d0@Grql(DTt4Awgmi+Yr0@#jbe=2#UkK%rv=OLqF)9D7D1j z!~McAwMYkeaL$~kI~90)5vBhBzWYc3Cj1WI0RS`z000R8-@ET0dA~*r(gSiCJmQMN&4%1D zyVNf0?}sBH8zNbBLn>~(W{d3%@kL_eQ6jEcR{l>C|JK z(R-fA!z|TTRG40|zv}7E@PqCAXP3n`;%|SCQ|ZS%ym$I{`}t3KPL&^l5`3>yah4*6 zifO#{VNz3)?ZL$be;NEaAk9b#{tV?V7 zP|wf5YA*1;s<)9A4~l3BHzG&HH`1xNr#%){4xZ!jq%o=7nN*wMuXlFV{HaiQLJ`5G zBhDi#D(m`Q1pLh@Tq+L;OwuC52RdW7b8}~60WCOK5iYMUad9}7aWBuILb({5=z~YF zt?*Jr5NG+WadM{mDL>GyiByCuR)hd zA=HM?J6l1Xv0Dl+LW@w$OTcEoOda^nFCw*Sy^I@$sSuneMl{4ys)|RY#9&NxW4S)9 zq|%83IpslTLoz~&vTo!Ga@?rj_kw{|k{nv+w&Ku?fyk4Ki4I?);M|5Axm)t+BaE)D zm(`AQ#k^DWrjbuXoJf2{Aj^KT zFb1zMSqxq|vceV+Mf-)$oPflsO$@*A0n0Z!R{&(xh8s}=;t(lIy zv$S8x>m;vQNHuRzoaOo?eiWFe{0;$s`Bc+Osz~}Van${u;g(su`3lJ^TEfo~nERfP z)?aFzpDgnLYiERsKPu|0tq4l2wT)Atr6Qb%m-AUn6HnCue*yWICp7TjW$@sO zm5rm4aTcPQ(rfi7a`xP7cKCFrJD}*&_~xgLyr^-bmsL}y;A5P|al8J3WUoBSjqu%v zxC;mK!g(7r6RRJ852Z~feoC&sD3(6}^5-uLK8o)9{8L_%%rItZK9C){UxB|;G>JbP zsRRtS4-3B*5c+K2kvmgZK8472%l>3cntWUOVHxB|{Ay~aOg5RN;{PJgeVD*H%ac+y!h#wi%o2bF2Ca8IyMyH{>4#{E_8u^@+l-+n=V}Sq?$O z{091@v%Bd*3pk0^2UtiF9Z+(a@wy6 zUdw8J*ze$K#=$48IBi1U%;hmhO>lu!uU;+RS}p&6@rQila7WftH->*A4=5W|Fmtze z)7E}jh@cbmr9iup^i%*(uF%LG&!+Fyl@LFA-}Ca#bxRfDJAiR2dt6644TaYw1Ma79 zt8&DYj31j^5WPNf5P&{)J?WlCe@<3u^78wnd(Ja4^a>{^Tw}W>|Cjt^If|7l^l)^Q zbz|7~CF(k_9~n|h;ysZ+jHzkXf(*O*@5m zLzUmbHp=x!Q|!9NVXyipZ3)^GuIG$k;D)EK!a5=8MFLI_lpf`HPKl=-Ww%z8H_0$j ztJ||IfFG1lE9nmQ0+jPQy zCBdKkjArH@K7jVcMNz);Q(Q^R{d5G?-kk;Uu_IXSyWB)~KGIizZL(^&qF;|1PI7!E zTP`%l)gpX|OFn&)M%txpQ2F!hdA~hX1Cm5)IrdljqzRg!f{mN%G~H1&oqe`5eJCIF zHdD7O;AX-{XEV(a`gBFJ9ews#CVS2y!&>Cm_dm3C8*n3MA*e67(WC?uP@8TXuMroq z{#w$%z@CBIkRM7?}Xib+>hRjy?%G!fiw8! z8(gB+8J~KOU}yO7UGm&1g_MDJ$IXS!`+*b*QW2x)9>K~Y*E&bYMnjl6h!{17_8d!%&9D`a7r&LKZjC<&XOvTRaKJ1 zUY@hl5^R&kZl3lU3njk`3dPzxj$2foOL26r(9zsVF3n_F#v)s5vv3@dgs|lP#eylq62{<-vczqP!RpVBTgI>@O6&sU>W|do17+#OzQ7o5A$ICH z?GqwqnK^n2%LR;$^oZM;)+>$X3s2n}2jZ7CdWIW0lnGK-b#EG01)P@aU`pg}th&J-TrU`tIpb5t((0eu|!u zQz+3ZiOQ^?RxxK4;zs=l8q!-n7X{@jSwK(iqNFiRColuEOg}!7cyZi`iBX4g1pNBj zAPzL?P^Ljhn;1$r8?bc=#n|Ed7wB&oHcw()&*k#SS#h}jO?ZB246EGItsz*;^&tzp zu^YJ0=lwsi`eP_pU8}6JA7MS;9pfD;DsSsLo~ogzMNP70@@;Fm8f0^;>$Z>~}GWRw!W5J3tNX*^2+1f3hz{~rIzJo z6W%J(H!g-eI_J1>0juX$X4Cl6i+3wbc~k146UIX&G22}WE>0ga#WLsn9tY(&29zBvH1$`iWtTe zG2jYl@P!P)eb<5DsR72BdI7-zP&cZNI{7q3e@?N8IKc4DE#UVr->|-ryuJXk^u^>4 z$3wE~=q390;XuOQP~TNoDR?#|NSPJ%sTMInA6*rJ%go|=YjGe!B>z6u$IhgQSwoV* zjy3F2#I>uK{42{&IqP59)Y(1*Z>>#W8rCf4_eVsH)`v!P#^;BgzKDR`ARGEZzkNX+ zJUQu=*-ol=Xqqt5=`=pA@BIn@6a9G8C{c&`i^(i+BxQO9?YZ3iu%$$da&Kb?2kCCo zo7t$UpSFWqmydXf@l3bVJ=%K?SSw)|?srhJ-1ZdFu*5QhL$~-IQS!K1s@XzAtv6*Y zl8@(5BlWYLt1yAWy?rMD&bwze8bC3-GfNH=p zynNFCdxyX?K&G(ZZ)afguQ2|r;XoV^=^(;Cku#qYn4Lus`UeKt6rAlFo_rU`|Rq z&G?~iWMBio<78of-2X(ZYHx~=U0Vz4btyXkctMKdc9UM!vYr~B-(>)(Hc|D zMzkN4!PBg%tZoh+=Gba!0++d193gbMk2&krfDgcbx0jI92cq?FFESVg0D$>F+bil} zY~$)|>1HZsX=5sAZ2WgPB5P=8X#TI+NQ(M~GqyVB53c6IdX=k>Wu@A0Svf5#?uHaF zsYn|koIi3$(%GZ2+G+7Fv^lHTb#5b8sAHSTnL^qWZLM<(1|9|QFw9pnRU{svj}_Al zL)b9>fN{QiA($8peNEJyy`(a{&uh-T4_kdZFIVsKKVM(?05}76EEz?#W za^fiZOAd14IJ4zLX-n7Lq0qlQ^lW8Cvz4UKkV9~P}>sq0?xD3vg+$4vLm~C(+ zM{-3Z#qnZ09bJ>}j?6ry^h+@PfaD7*jZxBEY4)UG&daWb??6)TP+|3#Z&?GL?1i+280CFsE|vIXQbm| zM}Pk!U`U5NsNbyKzkrul-DzwB{X?n3E6?TUHr{M&+R*2%yOiXdW-_2Yd6?38M9Vy^ z*lE%gA{wwoSR~vN0=no}tP2Ul5Gk5M(Xq`$nw#ndFk`tcpd5A=Idue`XZ!FS>Q zG^0w#>P4pPG+*NC9gLP4x2m=cKP}YuS!l^?sHSFftZy{4CoQrb_ z^20(NnG`wAhMI=eq)SsIE~&Gp9Ne0nD4%Xiu|0Fj1UFk?6avDqjdXz{O1nKao*46y zT8~iA%Exu=G#{x=KD;_C&M+Zx4+n`sHT>^>=-1YM;H<72k>$py1?F3#T1*ef9mLZw z5naLQr?n7K;2l+{_uIw*_1nsTn~I|kkCgrn;|G~##hM;9l7Jy$yJfmk+&}W@JeKcF zx@@Woiz8qdi|D%aH3XTx5*wDlbs?dC1_nrFpm^QbG@wM=i2?Zg;$VK!c^Dp8<}BTI zyRhAq@#%2pGV49*Y5_mV4+OICP|%I(dQ7x=6Ob}>EjnB_-_18*xrY?b%-yEDT(wrO z9RY2QT0`_OpGfMObKHV;QLVnrK%mc?$WAdIT`kJQT^n%GuzE7|9@k3ci5fYOh(287 zuIbg!GB3xLg$YN=n)^pHGB0jH+_iIiC=nUcD;G6LuJsjn2VI1cyZx=a?ShCsF==QK z;q~*m&}L<-cb+mDDXzvvrRsybcgQ;Vg21P(uLv5I+eGc7o7tc6`;OA9{soHFOz zT~2?>Ts}gprIX$wRBb4yE>ot<8+*Bv`qbSDv*VtRi|cyWS>)Fjs>fkNOH-+PX&4(~ z&)T8Zam2L6puQl?;5zg9h<}k4#|yH9czHw;1jw-pwBM*O2hUR6yvHATrI%^mvs9q_ z&ccT0>f#eDG<^WG^q@oVqlJrhxH)dcq2cty@l3~|5#UDdExyXUmLQ}f4#;6fI{f^t zDCsgIJ~0`af%YR%Ma5VQq-p21k`vaBu6WE?66+5=XUd%Ay%D$irN>5LhluRWt7 zov-=f>QbMk*G##&DTQyou$s7UqjjW@k6=!I@!k+S{pP8R(2=e@io;N8E`EOB;OGoI zw6Q+{X1_I{OO0HPpBz!X!@`5YQ2)t{+!?M_iH25X(d~-Zx~cXnS9z>u?+If|iNJbx zyFU2d1!ITX64D|lE0Z{dLRqL1Ajj=CCMfC4lD3&mYR_R_VZ>_7_~|<^o*%_&jevU+ zQ4|qzci=0}Jydw|LXLCrOl1_P6Xf@c0$ieK2^7@A9UbF{@V_0p%lqW|L?5k>bVM8|p5v&2g;~r>B8uo<4N+`B zH{J)h;SYiIVx@#jI&p-v3dwL5QNV1oxPr8J%ooezTnLW>i*3Isb49%5i!&ac_dEXv zvXmVUck^QHmyrF8>CGXijC_R-y(Qr{3Zt~EmW)-nC!tiH`wlw5D*W7Pip;T?&j%kX z6DkZX4&}iw>hE(boLyjOoupf6JpvBG8}jIh!!VhnD0>}KSMMo{1#uU6kiFcA04~|7 zVO8eI&x1`g4CZ<2cYUI(n#wz2MtVFHx47yE5eL~8bot~>EHbevSt}LLMQX?odD{Ux zJMnam{d)W4da{l7&y-JrgiU~qY3$~}_F#G7|MxT)e;G{U`In&?`j<5D->}cb{}{T(4DF0BOk-=1195KB-E*o@c?`>y#4=dMtYtSY=&L{!TAjFVcq0y@AH`vH! z$41+u!Ld&}F^COPgL(EE{0X7LY&%D7-(?!kjFF7=qw<;`V{nwWBq<)1QiGJgUc^Vz ztMUlq1bZqKn17|6x6iAHbWc~l1HcmAxr%$Puv!znW)!JiukwIrqQ00|H$Z)OmGG@= zv%A8*4cq}(?qn4rN6o`$Y))(MyXr8R<2S^J+v(wmFmtac!%VOfN?&(8Nr!T@kV`N; z*Q33V3t`^rN&aBiHet)18wy{*wi1=W!B%B-Q6}SCrUl$~Hl{@!95ydml@FK8P=u4s z4e*7gV2s=YxEvskw2Ju!2%{8h01rx-3`NCPc(O zH&J0VH5etNB2KY6k4R@2Wvl^Ck$MoR3=)|SEclT2ccJ!RI9Nuter7u9@;sWf-%um;GfI!=eEIQ2l2p_YWUd{|6EG ze{yO6;lMc>;2tPrsNdi@&1K6(1;|$xe8vLgiouj%QD%gYk`4p{Ktv9|j+!OF-P?@p z;}SV|oIK)iwlBs+`ROXkhd&NK zzo__r!B>tOXpBJMDcv!Mq54P+n4(@dijL^EpO1wdg~q+!DT3lB<>9AANSe!T1XgC=J^)IP0XEZ()_vpu!!3HQyJhwh?r`Ae%Yr~b% zO*NY9t9#qWa@GCPYOF9aron7thfWT`eujS4`t2uG6)~JRTI;f(ZuoRQwjZjp5Pg34 z)rp$)Kr?R+KdJ;IO;pM{$6|2y=k_siqvp%)2||cHTe|b5Ht8&A{wazGNca zX$Ol?H)E_R@SDi~4{d-|8nGFhZPW;Cts1;08TwUvLLv&_2$O6Vt=M)X;g%HUr$&06 zISZb(6)Q3%?;3r~*3~USIg=HcJhFtHhIV(siOwV&QkQe#J%H9&E21!C*d@ln3E@J* zVqRO^<)V^ky-R|%{(9`l-(JXq9J)1r$`uQ8a}$vr9E^nNiI*thK8=&UZ0dsFN_eSl z(q~lnD?EymWLsNa3|1{CRPW60>DSkY9YQ;$4o3W7Ms&@&lv9eH!tk~N&dhqX&>K@} zi1g~GqglxkZ5pEFkllJ)Ta1I^c&Bt6#r(QLQ02yHTaJB~- zCcE=5tmi`UA>@P=1LBfBiqk)HB4t8D?02;9eXj~kVPwv?m{5&!&TFYhu>3=_ zsGmYZ^mo*-j69-42y&Jj0cBLLEulNRZ9vXE)8~mt9C#;tZs;=#M=1*hebkS;7(aGf zcs7zH(I8Eui9UU4L--))yy`&d&$In&VA2?DAEss4LAPCLd>-$i?lpXvn!gu^JJ$(DoUlc6wE98VLZ*z`QGQov5l4Fm_h?V-;mHLYDVOwKz7>e4+%AzeO>P6v}ndPW| zM>m#6Tnp7K?0mbK=>gV}=@k*0Mr_PVAgGMu$j+pWxzq4MAa&jpCDU&-5eH27Iz>m^ zax1?*HhG%pJ((tkR(V(O(L%7v7L%!_X->IjS3H5kuXQT2!ow(;%FDE>16&3r){!ex zhf==oJ!}YU89C9@mfDq!P3S4yx$aGB?rbtVH?sHpg?J5C->!_FHM%Hl3#D4eplxzQ zRA+<@LD%LKSkTk2NyWCg7u=$%F#;SIL44~S_OGR}JqX}X+=bc@swpiClB`Zbz|f!4 z7Ysah7OkR8liXfI`}IIwtEoL}(URrGe;IM8%{>b1SsqXh)~w}P>yiFRaE>}rEnNkT z!HXZUtxUp1NmFm)Dm@-{FI^aRQqpSkz}ZSyKR%Y}YHNzBk)ZIp} zMtS=aMvkgWKm9&oTcU0?S|L~CDqA+sHpOxwnswF-fEG)cXCzUR?ps@tZa$=O)=L+5 zf%m58cq8g_o}3?Bhh+c!w4(7AjxwQ3>WnVi<{{38g7yFboo>q|+7qs<$8CPXUFAN< zG&}BHbbyQ5n|qqSr?U~GY{@GJ{(Jny{bMaOG{|IkUj7tj^9pa9|FB_<+KHLxSxR;@ zHpS$4V)PP+tx}22fWx(Ku9y+}Ap;VZqD0AZW4gCDTPCG=zgJmF{|x;(rvdM|2|9a}cex6xrMkERnkE;}jvU-kmzd%_J50$M`lIPCKf+^*zL=@LW`1SaEc%=m zQ+lT06Gw+wVwvQ9fZ~#qd430v2HndFsBa9WjD0P}K(rZYdAt^5WQIvb%D^Q|pkVE^ zte$&#~zmULFACGfS#g=2OLOnIf2Of-k!(BIHjs77nr!5Q1*I9 z1%?=~#Oss!rV~?-6Gm~BWJiA4mJ5TY&iPm_$)H1_rTltuU1F3I(qTQ^U$S>%$l z)Wx1}R?ij0idp@8w-p!Oz{&*W;v*IA;JFHA9%nUvVDy7Q8woheC#|8QuDZb-L_5@R zOqHwrh|mVL9b=+$nJxM`3eE{O$sCt$UK^2@L$R(r^-_+z?lOo+me-VW=Zw z-Bn>$4ovfWd%SPY`ab-u9{INc*k2h+yH%toDHIyqQ zO68=u`N}RIIs7lsn1D){)~%>ByF<>i@qFb<-axvu(Z+6t7v<^z&gm9McRB~BIaDn$ z#xSGT!rzgad8o>~kyj#h1?7g96tOcCJniQ+*#=b7wPio>|6a1Z?_(TS{)KrPe}(8j z!#&A=k(&Pj^F;r)CI=Z{LVu>uj!_W1q4b`N1}E(i%;BWjbEcnD=mv$FL$l?zS6bW!{$7j1GR5ocn94P2u{ z70tAAcpqtQo<@cXw~@i-@6B23;317|l~S>CB?hR5qJ%J3EFgyBdJd^fHZu7AzHF(BQ!tyAz^L0`X z23S4Fe{2X$W0$zu9gm%rg~A>ijaE#GlYlrF9$ds^QtaszE#4M(OLVP2O-;XdT(XIC zatwzF*)1c+t~c{L=fMG8Z=k5lv>U0;C{caN1NItnuSMp)6G3mbahu>E#sj&oy94KC zpH}8oEw{G@N3pvHhp{^-YaZeH;K+T_1AUv;IKD<=mv^&Ueegrb!yf`4VlRl$M?wsl zZyFol(2|_QM`e_2lYSABpKR{{NlxlDSYQNkS;J66aT#MSiTx~;tUmvs-b*CrR4w=f z8+0;*th6kfZ3|5!Icx3RV11sp=?`0Jy3Fs0N4GZQMN=8HmT6%x9@{Dza)k}UwL6JT zHRDh;%!XwXr6yuuy`4;Xsn0zlR$k%r%9abS1;_v?`HX_hI|+EibVnlyE@3aL5vhQq zlIG?tN^w@0(v9M*&L+{_+RQZw=o|&BRPGB>e5=ys7H`nc8nx)|-g;s7mRc7hg{GJC zAe^vCIJhajmm7C6g! zL&!WAQ~5d_5)00?w_*|*H>3$loHrvFbitw#WvLB!JASO?#5Ig5$Ys10n>e4|3d;tS zELJ0|R4n3Az(Fl3-r^QiV_C;)lQ1_CW{5bKS15U|E9?ZgLec@%kXr84>5jV2a5v=w z?pB1GPdxD$IQL4)G||B_lI+A=08MUFFR4MxfGOu07vfIm+j=z9tp~5i_6jb`tR>qV z$#`=BQ*jpCjm$F0+F)L%xRlnS%#&gro6PiRfu^l!EVan|r3y}AHJQOORGx4~ z&<)3=K-tx518DZyp%|!EqpU!+X3Et7n2AaC5(AtrkW>_57i}$eqs$rupubg0a1+WO zGHZKLN2L0D;ab%{_S1Plm|hx8R?O14*w*f&2&bB050n!R2by zw!@XOQx$SqZ5I<(Qu$V6g>o#A!JVwErWv#(Pjx=KeS0@hxr4?13zj#oWwPS(7Ro|v z>Mp@Kmxo79q|}!5qtX2-O@U&&@6s~!I&)1WQIl?lTnh6UdKT_1R640S4~f=_xoN3- zI+O)$R@RjV$F=>Ti7BlnG1-cFKCC(t|Qjm{SalS~V-tX#+2ekRhwmN zZr`8{QF6y~Z!D|{=1*2D-JUa<(1Z=;!Ei!KiRNH?o{p5o3crFF=_pX9O-YyJchr$~ zRC`+G+8kx~fD2k*ZIiiIGR<8r&M@3H?%JVOfE>)})7ScOd&?OjgAGT@WVNSCZ8N(p zuQG~76GE3%(%h1*vUXg$vH{ua0b`sQ4f0*y=u~lgyb^!#CcPJa2mkSEHGLsnO^kb$ zru5_l#nu=Y{rSMWiYx?nO{8I!gH+?wEj~UM?IrG}E|bRIBUM>UlY<`T1EHpRr36vv zBi&dG8oxS|J$!zoaq{+JpJy+O^W(nt*|#g32bd&K^w-t>!Vu9N!k9eA8r!Xc{utY> zg9aZ(D2E0gL#W0MdjwES-7~Wa8iubPrd?8-$C4BP?*wok&O8+ykOx{P=Izx+G~hM8 z*9?BYz!T8~dzcZr#ux8kS7u7r@A#DogBH8km8Ry4slyie^n|GrTbO|cLhpqgMdsjX zJ_LdmM#I&4LqqsOUIXK8gW;V0B(7^$y#h3h>J0k^WJfAMeYek%Y-Dcb_+0zPJez!GM zAmJ1u;*rK=FNM0Nf}Y!!P9c4)HIkMnq^b;JFd!S3?_Qi2G#LIQ)TF|iHl~WKK6JmK zbv7rPE6VkYr_%_BT}CK8h=?%pk@3cz(UrZ{@h40%XgThP*-Oeo`T0eq9 zA8BnWZKzCy5e&&_GEsU4*;_k}(8l_&al5K-V*BFM=O~;MgRkYsOs%9eOY6s6AtE*<7GQAR2ulC3RAJrG_P1iQK5Z~&B z&f8X<>yJV6)oDGIlS$Y*D^Rj(cszTy5c81a5IwBr`BtnC6_e`ArI8CaTX_%rx7;cn zR-0?J_LFg*?(#n~G8cXut(1nVF0Oka$A$1FGcERU<^ggx;p@CZc?3UB41RY+wLS`LWFNSs~YP zuw1@DNN3lTd|jDL7gjBsd9}wIw}4xT2+8dBQzI00m<@?c2L%>}QLfK5%r!a-iII`p zX@`VEUH)uj^$;7jVUYdADQ2k*!1O3WdfgF?OMtUXNpQ1}QINamBTKDuv19^{$`8A1 zeq%q*O0mi@(%sZU>Xdb0Ru96CFqk9-L3pzLVsMQ`Xpa~N6CR{9Rm2)A|CI21L(%GW zh&)Y$BNHa=FD+=mBw3{qTgw)j0b!Eahs!rZnpu)z!!E$*eXE~##yaXz`KE5(nQM`s zD!$vW9XH)iMxu9R>r$VlLk9oIR%HxpUiW=BK@4U)|1WNQ=mz9a z^!KkO=>GaJ!GBXm{KJj^;kh-MkUlEQ%lza`-G&}C5y1>La1sR6hT=d*NeCnuK%_LV zOXt$}iP6(YJKc9j-Fxq~*ItVUqljQ8?oaysB-EYtFQp9oxZ|5m0^Hq(qV!S+hq#g( z?|i*H2MIr^Kxgz+3vIljQ*Feejy6S4v~jKEPTF~Qhq!(ms5>NGtRgO5vfPPc4Z^AM zTj!`5xEreIN)vaNxa|q6qWdg>+T`Ol0Uz)ckXBXEGvPNEL3R8hB3=C5`@=SYgAju1 z!)UBr{2~=~xa{b8>x2@C7weRAEuatC)3pkRhT#pMPTpSbA|tan%U7NGMvzmF?c!V8 z=pEWxbdXbTAGtWTyI?Fml%lEr-^AE}w#l(<7OIw;ctw}imYax&vR4UYNJZK6P7ZOd zP87XfhnUHxCUHhM@b*NbTi#(-8|wcv%3BGNs#zRCVV(W?1Qj6^PPQa<{yaBwZ`+<`w|;rqUY_C z&AeyKwwf*q#OW-F()lir=T^<^wjK65Lif$puuU5+tk$;e_EJ;Lu+pH>=-8=PDhkBg z8cWt%@$Sc#C6F$Vd+0507;{OOyT7Hs%nKS88q-W!$f~9*WGBpHGgNp}=C*7!RiZ5s zn1L_DbKF@B8kwhDiLKRB@lsXVVLK|ph=w%_`#owlf@s@V(pa`GY$8h%;-#h@TsO|Y8V=n@*!Rog7<7Cid%apR|x zOjhHCyfbIt%+*PCveTEcuiDi%Wx;O;+K=W?OFUV%)%~6;gl?<0%)?snDDqIvkHF{ zyI02)+lI9ov42^hL>ZRrh*HhjF9B$A@=H94iaBESBF=eC_KT$8A@uB^6$~o?3Wm5t1OIaqF^~><2?4e3c&)@wKn9bD? zoeCs;H>b8DL^F&>Xw-xjZEUFFTv>JD^O#1E#)CMBaG4DX9bD(Wtc8Rzq}9soQ8`jf zeSnHOL}<+WVSKp4kkq&?SbETjq6yr@4%SAqOG=9E(3YeLG9dtV+8vmzq+6PFPk{L; z(&d++iu=^F%b+ea$i2UeTC{R*0Isk;vFK!no<;L+(`y`3&H-~VTdKROkdyowo1iqR zbVW(3`+(PQ2>TKY>N!jGmGo7oeoB8O|P_!Ic@ zZ^;3dnuXo;WJ?S+)%P>{Hcg!Jz#2SI(s&dY4QAy_vRlmOh)QHvs_7c&zkJCmJGVvV zX;Mtb>QE+xp`KyciG$Cn*0?AK%-a|=o!+7x&&yzHQOS>8=B*R=niSnta^Pxp1`=md z#;$pS$4WCT?mbiCYU?FcHGZ#)kHVJTTBt^%XE(Q};aaO=Zik0UgLcc0I(tUpt(>|& zcxB_|fxCF7>&~5eJ=Dpn&5Aj{A^cV^^}(7w#p;HG&Q)EaN~~EqrE1qKrMAc&WXIE;>@<&)5;gD2?={Xf@Mvn@OJKw=8Mgn z!JUFMwD+s==JpjhroT&d{$kQAy%+d`a*XxDEVxy3`NHzmITrE`o!;5ClXNPb4t*8P zzAivdr{j_v!=9!^?T3y?gzmqDWX6mkzhIzJ-3S{T5bcCFMr&RPDryMcdwbBuZbsgN zGrp@^i?rcfN7v0NKGzDPGE#4yszxu=I_`MI%Z|10nFjU-UjQXXA?k8Pk|OE<(?ae) zE%vG#eZAlj*E7_3dx#Zz4kMLj>H^;}33UAankJiDy5ZvEhrjr`!9eMD8COp}U*hP+ zF}KIYx@pkccIgyxFm#LNw~G&`;o&5)2`5aogs`1~7cMZQ7zj!%L4E`2yzlQN6REX20&O<9 zKV6fyr)TScJPPzNTC2gL+0x#=u>(({{D7j)c-%tvqls3#Y?Z1m zV5WUE)zdJ{$p>yX;^P!UcXP?UD~YM;IRa#Rs5~l+*$&nO(;Ers`G=0D!twR(0GF@c zHl9E5DQI}Oz74n zfKP>&$q0($T4y$6w(p=ERAFh+>n%iaeRA%!T%<^+pg?M)@ucY<&59$x9M#n+V&>}=nO9wCV{O~lg&v#+jcUj(tQ z`0u1YH)-`U$15a{pBkGyPL0THv1P|4e@pf@3IBZS4dVJPo#H>pWq%Lr0YS-SeWash z8R7=jb28KPMI|_lo#GEO|5B?N_e``H*23{~a!AmUJ+fb4HX-%QI@lSEUxKlGV7z7Q zSKw@-TR>@1RL%w{x}dW#k1NgW+q4yt2Xf1J62Bx*O^WG8OJ|FqI4&@d3_o8Id@*)4 zYrk=>@!wv~mh7YWv*bZhxqSmFh2Xq)o=m;%n$I?GSz49l1$xRpPu_^N(vZ>*>Z<04 z2+rP70oM=NDysd!@fQdM2OcyT?3T^Eb@lIC-UG=Bw{BjQ&P`KCv$AcJ;?`vdZ4){d z&gkoUK{$!$$K`3*O-jyM1~p-7T*qb)Ys>Myt^;#1&a%O@x8A+E>! zY8=eD`ZG)LVagDLBeHg>=atOG?Kr%h4B%E6m@J^C+U|y)XX@f z8oyJDW|9g=<#f<{JRr{y#~euMnv)`7j=%cHWLc}ngjq~7k**6%4u>Px&W%4D94(r* z+akunK}O0DC2A%Xo9jyF;DobX?!1I(7%}@7F>i%&nk*LMO)bMGg2N+1iqtg+r(70q zF5{Msgsm5GS7DT`kBsjMvOrkx&|EU!{{~gL4d2MWrAT=KBQ-^zQCUq{5PD1orxlIL zq;CvlWx#f1NWvh`hg011I%?T_s!e38l*lWVt|~z-PO4~~1g)SrJ|>*tXh=QfXT)%( z+ex+inPvD&O4Ur;JGz>$sUOnWdpSLcm1X%aQDw4{dB!cnj`^muI$CJ2%p&-kULVCE z>$eMR36kN$wCPR+OFDM3-U(VOrp9k3)lI&YVFqd;Kpz~K)@Fa&FRw}L(SoD z9B4a+hQzZT-BnVltst&=kq6Y(f^S4hIGNKYBgMxGJ^;2yrO}P3;r)(-I-CZ)26Y6? z&rzHI_1GCvGkgy-t1E;r^3Le30|%$ebDRu2+gdLG)r=A~Qz`}~&L@aGJ{}vVs_GE* zVUjFnzHiXfKQbpv&bR&}l2bzIjAooB)=-XNcYmrGmBh(&iu@o!^hn0^#}m2yZZUK8 zufVm7Gq0y`Mj;9b>`c?&PZkU0j4>IL=UL&-Lp3j&47B5pAW4JceG{!XCA)kT<%2nqCxj<)uy6XR_uws~>_MEKPOpAQ!H zkn>FKh)<9DwwS*|Y(q?$^N!6(51O0 z^JM~Ax{AI1Oj$fs-S5d4T7Z_i1?{%0SsIuQ&r8#(JA=2iLcTN+?>wOL532%&dMYkT z*T5xepC+V6zxhS@vNbMoi|i)=rpli@R9~P!39tWbSSb904ekv7D#quKbgFEMTb48P zuq(VJ+&L8aWU(_FCD$3^uD!YM%O^K(dvy~Wm2hUuh6bD|#(I39Xt>N1Y{ZqXL`Fg6 zKQ?T2htHN!(Bx;tV2bfTtIj7e)liN-29s1kew>v(D^@)#v;}C4-G=7x#;-dM4yRWm zyY`cS21ulzMK{PoaQ6xChEZ}o_#}X-o}<&0)$1#3we?+QeLt;aVCjeA)hn!}UaKt< zat1fHEx13y-rXNMvpUUmCVzocPmN~-Y4(YJvQ#db)4|%B!rBsgAe+*yor~}FrNH08 z3V!97S}D7d$zbSD{$z;@IYMxM6aHdypIuS*pr_U6;#Y!_?0i|&yU*@16l z*dcMqDQgfNBf}?quiu4e>H)yTVfsp#f+Du0@=Kc41QockXkCkvu>FBd6Q+@FL!(Yx z2`YuX#eMEiLEDhp+9uFqME_E^faV&~9qjBHJkIp~%$x^bN=N)K@kvSVEMdDuzA0sn z88CBG?`RX1@#hQNd`o^V{37)!w|nA)QfiYBE^m=yQKv-fQF+UCMcuEe1d4BH7$?>b zJl-r9@0^Ie=)guO1vOd=i$_4sz>y3x^R7n4ED!5oXL3@5**h(xr%Hv)_gILarO46q+MaDOF%ChaymKoI6JU5Pg;7#2n9-18|S1;AK+ zgsn6;k6-%!QD>D?cFy}8F;r@z8H9xN1jsOBw2vQONVqBVEbkiNUqgw~*!^##ht>w0 zUOykwH=$LwX2j&nLy=@{hr)2O&-wm-NyjW7n~Zs9UlH;P7iP3 zI}S(r0YFVYacnKH(+{*)Tbw)@;6>%=&Th=+Z6NHo_tR|JCI8TJiXv2N7ei7M^Q+RM z?9o`meH$5Yi;@9XaNR#jIK^&{N|DYNNbtdb)XW1Lv2k{E>;?F`#Pq|&_;gm~&~Zc9 zf+6ZE%{x4|{YdtE?a^gKyzr}dA>OxQv+pq|@IXL%WS0CiX!V zm$fCePA%lU{%pTKD7|5NJHeXg=I0jL@$tOF@K*MI$)f?om)D63K*M|r`gb9edD1~Y zc|w7N)Y%do7=0{RC|AziW7#am$)9jciRJ?IWl9PE{G3U+$%FcyKs_0Cgq`=K3@ttV z9g;M!3z~f_?P%y3-ph%vBMeS@p7P&Ea8M@97+%XEj*(1E6vHj==d zjsoviB>j^$_^OI_DEPvFkVo(BGRo%cJeD){6Uckei=~1}>sp299|IRjhXe)%?uP0I zF5+>?0#Ye}T^Y$u_rc4=lPcq4K^D(TZG-w30-YiEM=dcK+4#o*>lJ8&JLi+3UcpZk z!^?95S^C0ja^jwP`|{<+3cBVog$(mRdQmadS+Vh~z zS@|P}=|z3P6uS+&@QsMp0no9Od&27O&14zHXGAOEy zh~OKpymK5C%;LLb467@KgIiVwYbYd6wFxI{0-~MOGfTq$nBTB!{SrWmL9Hs}C&l&l#m?s*{tA?BHS4mVKHAVMqm63H<|c5n0~k)-kbg zXidai&9ZUy0~WFYYKT;oe~rytRk?)r8bptITsWj(@HLI;@=v5|XUnSls7$uaxFRL+ zRVMGuL3w}NbV1`^=Pw*0?>bm8+xfeY(1PikW*PB>>Tq(FR`91N0c2&>lL2sZo5=VD zQY{>7dh_TX98L2)n{2OV=T10~*YzX27i2Q7W86M4$?gZIXZaBq#sA*{PH8){|GUi;oM>e?ua7eF4WFuFYZSG| zze?srg|5Ti8Og{O zeFxuw9!U+zhyk?@w zjsA6(oKD=Ka;A>Ca)oPORxK+kxH#O@zhC!!XS4@=swnuMk>t+JmLmFiE^1aX3f<)D@`%K0FGK^gg1a1j>zi z2KhV>sjU7AX3F$SEqrXSC}fRx64GDoc%!u2Yag68Lw@w9v;xOONf@o)Lc|Uh3<21ctTYu-mFZuHk*+R{GjXHIGq3p)tFtQp%TYqD=j1&y)>@zxoxUJ!G@ zgI0XKmP6MNzw>nRxK$-Gbzs}dyfFzt>#5;f6oR27ql!%+{tr+(`(>%51|k`ML} zY4eE)Lxq|JMas(;JibNQds1bUB&r}ydMQXBY4x(^&fY_&LlQC)3hylc$~8&~|06-D z#T+%66rYbHX%^KuqJED_wuGB+=h`nWA!>1n0)3wZrBG3%`b^Ozv6__dNa@%V14|!D zQ?o$z5u0^8`giv%qE!BzZ!3j;BlDlJDk)h@9{nSQeEk!z9RGW) z${RSF3phEM*ce*>Xdp}585vj$|40=&S{S-GTiE?Op*vY&Lvr9}BO$XWy80IF+6@%n z5*2ueT_g@ofP#u5pxb7n*fv^Xtt7&?SRc{*2Ka-*!BuOpf}neHGCiHy$@Ka1^Dint z;DkmIL$-e)rj4o2WQV%Gy;Xg(_Bh#qeOsTM2f@KEe~4kJ8kNLQ+;(!j^bgJMcNhvklP5Z6I+9Fq@c&D~8Fb-4rmDT!MB5QC{Dsb;BharP*O;SF4& zc$wj-7Oep7#$WZN!1nznc@Vb<_Dn%ga-O#J(l=OGB`dy=Sy&$(5-n3zzu%d7E#^8`T@}V+5B;PP8J14#4cCPw-SQTdGa2gWL0*zKM z#DfSXs_iWOMt)0*+Y>Lkd=LlyoHjublNLefhKBv@JoC>P7N1_#> zv=mLWe96%EY;!ZGSQDbZWb#;tzqAGgx~uk+-$+2_8U`!ypbwXl z^2E-FkM1?lY@yt8=J3%QK+xaZ6ok=-y%=KXCD^0r!5vUneW>95PzCkOPO*t}p$;-> ze5j-BLT_;)cZQzR2CEsm@rU7GZfFtdp*a|g4wDr%8?2QkIGasRfDWT-Dvy*U{?IHT z*}wGnzdlSptl#ZF^sf)KT|BJs&kLG91^A6ls{CzFprZ6-Y!V0Xysh%9p%iMd7HLsS zN+^Un$tDV)T@i!v?3o0Fsx2qI(AX_$dDkBzQ@fRM%n zRXk6hb9Py#JXUs+7)w@eo;g%QQ95Yq!K_d=z{0dGS+pToEI6=Bo8+{k$7&Z zo4>PH(`ce8E-Ps&uv`NQ;U$%t;w~|@E3WVOCi~R4oj5wP?%<*1C%}Jq%a^q~T7u>K zML5AKfQDv6>PuT`{SrKHRAF+^&edg6+5R_#H?Lz3iGoWo#PCEd0DS;)2U({{X#zU^ zw_xv{4x7|t!S)>44J;KfA|DC?;uQ($l+5Vp7oeqf7{GBF9356nx|&B~gs+@N^gSdd zvb*>&W)|u#F{Z_b`f#GVtQ`pYv3#||N{xj1NgB<#=Odt6{eB%#9RLt5v zIi|0u70`#ai}9fJjKv7dE!9ZrOIX!3{$z_K5FBd-Kp-&e4(J$LD-)NMTp^_pB`RT; zftVVlK2g@+1Ahv2$D){@Y#cL#dUj9*&%#6 zd2m9{1NYp>)6=oAvqdCn5#cx{AJ%S8skUgMglu2*IAtd+z1>B&`MuEAS(D(<6X#Lj z?f4CFx$)M&$=7*>9v1ER4b6!SIz-m0e{o0BfkySREchp?WdVPpQCh!q$t>?rL!&Jg zd#heM;&~A}VEm8Dvy&P|J*eAV&w!&Nx6HFV&B8jJFVTmgLaswn!cx$&%JbTsloz!3 zMEz1d`k==`Ueub_JAy_&`!ogbwx27^ZXgFNAbx=g_I~5nO^r)}&myw~+yY*cJl4$I znNJ32M&K=0(2Dj_>@39`3=FX!v3nZHno_@q^!y}%(yw0PqOo=);6Y@&ylVe>nMOZ~ zd>j#QQSBn3oaWd;qy$&5(5H$Ayi)0haAYO6TH>FR?rhqHmNOO+(})NB zLI@B@v0)eq!ug`>G<@htRlp3n!EpU|n+G+AvXFrWSUsLMBfL*ZB`CRsIVHNTR&b?K zxBgsN0BjfB>UVcJ|x%=-zb%OV7lmZc& zxiupadZVF7)6QuhoY;;FK2b*qL0J-Rn-8!X4ZY$-ZSUXV5DFd7`T41c(#lAeLMoeT z4%g655v@7AqT!i@)Edt5JMbN(=Q-6{=L4iG8RA%}w;&pKmtWvI4?G9pVRp|RTw`g0 zD5c12B&A2&P6Ng~8WM2eIW=wxd?r7A*N+&!Be7PX3s|7~z=APxm=A?5 zt>xB4WG|*Td@VX{Rs)PV0|yK`oI3^xn(4c_j&vgxk_Y3o(-`_5o`V zRTghg6%l@(qodXN;dB#+OKJEEvhfcnc#BeO2|E(5df-!fKDZ!%9!^BJ_4)9P+9Dq5 zK1=(v?KmIp34r?z{NEWnLB3Px{XYwy-akun4F7xTRr2^zeYW{gcK9)>aJDdU5;w5@ zak=<+-PLH-|04pelTb%ULpuuuJC7DgyT@D|p{!V!0v3KpDnRjANN12q6SUR3mb9<- z>2r~IApQGhstZ!3*?5V z8#)hJ0TdZg0M-BK#nGFP>$i=qk82DO z7h;Ft!D5E15OgW)&%lej*?^1~2=*Z5$2VX>V{x8SC+{i10BbtUk9@I#Vi&hX)q
Q!LwySI{Bnv%Sm)yh{^sSVJ8&h_D-BJ_YZe5eCaAWU9b$O2c z$T|{vWVRtOL!xC0DTc(Qbe`ItNtt5hr<)VijD0{U;T#bUEp381_y`%ZIav?kuYG{iyYdEBPW=*xNSc;Rlt6~F4M`5G+VtOjc z*0qGzCb@gME5udTjJA-9O<&TWd~}ysBd(eVT1-H82-doyH9RST)|+Pb{o*;$j9Tjs zhU!IlsPsj8=(x3bAKJTopW3^6AKROHR^7wZ185wJGVhA~hEc|LP;k7NEz-@4p5o}F z`AD6naG3(n=NF9HTH81=F+Q|JOz$7wm9I<+#BSmB@o_cLt2GkW9|?7mM;r!JZp89l zbo!Hp8=n!XH1{GwaDU+k)pGp`C|cXkCU5%vcH)+v@0eK>%7gWxmuMu9YLlChA|_D@ zi#5zovN_!a-0?~pUV-Rj*1P)KwdU-LguR>YM&*Nen+ln8Q$?WFCJg%DY%K}2!!1FE zDv-A%Cbwo^p(lzac&_TZ-l#9kq`mhLcY3h9ZTUVCM(Ad&=EriQY5{jJv<5K&g|*Lk zgV%ILnf1%8V2B0E&;Sp4sYbYOvvMebLwYwzkRQ#F8GpTQq#uv=J`uaSJ34OWITeSGo6+-8Xw znCk*n{kdDEi)Hi&u^)~cs@iyCkFWB2SWZU|Uc%^43ZIZQ-vWNExCCtDWjqHs;;tWf$v{}0{p0Rvxkq``)*>+Akq%|Na zA`@~-Vfe|+(AIlqru+7Ceh4nsVmO9p9jc8}HX^W&ViBDXT+uXbT#R#idPn&L>+#b6 zflC-4C5-X;kUnR~L>PSLh*gvL68}RBsu#2l`s_9KjUWRhiqF`j)`y`2`YU(>3bdBj z?>iyjEhe-~$^I5!nn%B6Wh+I`FvLNvauve~eX<+Ipl&04 zT}};W&1a3%W?dJ2=N#0t?e+aK+%t}5q%jSLvp3jZ%?&F}nOOWr>+{GFIa%wO_2`et z=JzoRR~}iKuuR+azPI8;Gf9)z3kyA4EIOSl!sRR$DlW}0>&?GbgPojmjmnln;cTqCt=ADbE zZ8GAnoM+S1(5$i8^O4t`ue;vO4i}z0wz-QEIVe5_u03;}-!G1NyY8;h^}y;tzY}i5 zqQr#Ur3Fy8sSa$Q0ys+f`!`+>9WbvU_I`Sj;$4{S>O3?#inLHCrtLy~!s#WXV=oVP zeE93*Nc`PBi4q@%Ao$x4lw9vLHM!6mn3-b_cebF|n-2vt-zYVF_&sDE--J-P;2WHo z+@n2areE0o$LjvjlV2X7ZU@j+`{*8zq`JR3gKF#EW|#+{nMyo-a>nFFTg&vhyT=b} zDa8+v0(Dgx0yRL@ZXOYIlVSZ0|MFizy0VPW8;AfA5|pe!#j zX}Py^8fl5SyS4g1WSKKtnyP+_PoOwMMwu`(i@Z)diJp~U54*-miOchy7Z35eL>^M z4p<-aIxH4VUZgS783@H%M7P9hX>t{|RU7$n4T(brCG#h9e9p! z+o`i;EGGq3&pF;~5V~eBD}lC)>if$w%Vf}AFxGqO88|ApfHf&Bvu+xdG)@vuF}Yvk z)o;~k-%+0K0g+L`Wala!$=ZV|z$e%>f0%XoLib%)!R^RoS+{!#X?h-6uu zF&&KxORdZU&EwQFITIRLo(7TA3W}y6X{?Y%y2j0It!ekU#<)$qghZtpcS>L3uh`Uj z7GY;6f$9qKynP#oS3$$a{p^{D+0oJQ71`1?OAn_m8)UGZmj3l*ZI)`V-a>MKGGFG< z&^jg#Ok%(hhm>hSrZ5;Qga4u(?^i>GiW_j9%_7M>j(^|Om$#{k+^*ULnEgzW_1gCICtAD^WpC`A z{9&DXkG#01Xo)U$OC(L5Y$DQ|Q4C6CjUKk1UkPj$nXH##J{c8e#K|&{mA*;b$r0E4 zUNo0jthwA(c&N1l=PEe8Rw_8cEl|-eya9z&H3#n`B$t#+aJ03RFMzrV@gowbe8v(c zIFM60^0&lCFO10NU4w@|61xiZ4CVXeaKjd;d?sv52XM*lS8XiVjgWpRB;&U_C0g+`6B5V&w|O6B*_q zsATxL!M}+$He)1eOWECce#eS@2n^xhlB4<_Nn?yCVEQWDs(r`|@2GqLe<#(|&P0U? z$7V5IgpWf09uIf_RazRwC?qEqRaHyL?iiS05UiGesJy%^>-C{{ypTBI&B0-iUYhk> zIk<5xpsuV@g|z(AZD+C-;A!fTG=df1=<%nxy(a(IS+U{ME4ZbDEBtcD_3V=icT6*_ z)>|J?>&6%nvHhZERBtjK+s4xnut*@>GAmA5m*OTp$!^CHTr}vM4n(X1Q*;{e-Rd2BCF-u@1ZGm z!S8hJ6L=Gl4T_SDa7Xx|-{4mxveJg=ctf`BJ*fy!yF6Dz&?w(Q_6B}WQVtNI!BVBC zKfX<>7vd6C96}XAQmF-Jd?1Q4eTfRB3q7hCh0f!(JkdWT5<{iAE#dKy*Jxq&3a1@~ z8C||Dn2mFNyrUV|<-)C^_y7@8c2Fz+2jrae9deBDu;U}tJ{^xAdxCD248(k;dCJ%o z`y3sADe>U%suxwwv~8A1+R$VB=Q?%U?4joI$um;aH+eCrBqpn- z%79D_7rb;R-;-9RTrwi9dPlg8&@tfWhhZ(Vx&1PQ+6(huX`;M9x~LrW~~#3{j0Bh2kDU$}@!fFQej4VGkJv?M4rU^x!RU zEwhu$!CA_iDjFjrJa`aocySDX16?~;+wgav;}Zut6Mg%C4>}8FL?8)Kgwc(Qlj{@#2Pt0?G`$h7P#M+qoXtlV@d}%c&OzO+QYKK`kyXaK{U(O^2DyIXCZlNQjt0^8~8JzNGrIxhj}}M z&~QZlbx%t;MJ(Vux;2tgNKGlAqphLq%pd}JG9uoVHUo?|hN{pLQ6Em%r*+7t^<);X zm~6=qChlNAVXNN*Sow->*4;}T;l;D1I-5T{Bif@4_}=>l`tK;qqDdt5zvisCKhMAH z#r}`)7VW?LZqfdmXQ%zo5bJ00{Xb9^YKrk0Nf|oIW*K@(=`o2Vndz}ZDyk{!u}PVx zzd--+_WC*U{~DH3{?GI64IB+@On&@9X>EUAo&L+G{L^dozaI4C3G#2wr~hseW@K&g zKWs{uHu-9Je!3;4pE>eBltKUXb^*hG8I&413)$J&{D4N%7PcloU6bn%jPxJyQL?g* z9g+YFFEDiE`8rW^laCNzQmi7CTnPfwyg3VDHRAl>h=In6jeaVOP@!-CP60j3+#vpL zEYmh_oP0{-gTe7Or`L6x)6w?77QVi~jD8lWN@3RHcm80iV%M1A!+Y6iHM)05iC64tb$X2lV_%Txk@0l^hZqi^%Z?#- zE;LE0uFx)R08_S-#(wC=dS&}vj6P4>5ZWjhthP=*Hht&TdLtKDR;rXEX4*z0h74FA zMCINqrh3Vq;s%3MC1YL`{WjIAPkVL#3rj^9Pj9Ss7>7duy!9H0vYF%>1jh)EPqvlr6h%R%CxDsk| z!BACz7E%j?bm=pH6Eaw{+suniuY7C9Ut~1cWfOX9KW9=H><&kQlinPV3h9R>3nJvK z4L9(DRM=x;R&d#a@oFY7mB|m8h4692U5eYfcw|QKwqRsshN(q^v$4$)HgPpAJDJ`I zkqjq(8Cd!K!+wCd=d@w%~e$=gdUgD&wj$LQ1r>-E=O@c ze+Z$x{>6(JA-fNVr)X;*)40Eym1TtUZI1Pwwx1hUi+G1Jlk~vCYeXMNYtr)1?qwyg zsX_e*$h?380O00ou?0R@7-Fc59o$UvyVs4cUbujHUA>sH!}L54>`e` zHUx#Q+Hn&Og#YVOuo*niy*GU3rH;%f``nk#NN5-xrZ34NeH$l`4@t);4(+0|Z#I>Y z)~Kzs#exIAaf--65L0UHT_SvV8O2WYeD>Mq^Y6L!Xu8%vnpofG@w!}R7M28?i1*T&zp3X4^OMCY6(Dg<-! zXmcGQrRgHXGYre7GfTJ)rhl|rs%abKT_Nt24_Q``XH{88NVPW+`x4ZdrMuO0iZ0g` z%p}y};~T5gbb9SeL8BSc`SO#ixC$@QhXxZ=B}L`tP}&k?1oSPS=4%{UOHe0<_XWln zwbl5cn(j-qK`)vGHY5B5C|QZd5)W7c@{bNVXqJ!!n$^ufc?N9C-BF2QK1(kv++h!>$QbAjq)_b$$PcJdV+F7hz0Hu@ zqj+}m0qn{t^tD3DfBb~0B36|Q`bs*xs|$i^G4uNUEBl4g;op-;Wl~iThgga?+dL7s zUP(8lMO?g{GcYpDS{NM!UA8Hco?#}eNEioRBHy4`mq!Pd-9@-97|k$hpEX>xoX+dY zDr$wfm^P&}Wu{!%?)U_(%Mn79$(ywvu*kJ9r4u|MyYLI_67U7%6Gd_vb##Nerf@>& z8W11z$$~xEZt$dPG}+*IZky+os5Ju2eRi;1=rUEeIn>t-AzC_IGM-IXWK3^6QNU+2pe=MBn4I*R@A%-iLDCOHTE-O^wo$sL_h{dcPl=^muAQb`_BRm};=cy{qSkui;`WSsj9%c^+bIDQ z0`_?KX0<-=o!t{u(Ln)v>%VGL z0pC=GB7*AQ?N7N{ut*a%MH-tdtNmNC+Yf$|KS)BW(gQJ*z$d{+{j?(e&hgTy^2|AR9vx1Xre2fagGv0YXWqtNkg*v%40v?BJBt|f9wX5 z{QTlCM}b-0{mV?IG>TW_BdviUKhtosrBqdfq&Frdz>cF~yK{P@(w{Vr7z2qKFwLhc zQuogKO@~YwyS9%+d-zD7mJG~@?EFJLSn!a&mhE5$_4xBl&6QHMzL?CdzEnC~C3$X@ zvY!{_GR06ep5;<#cKCSJ%srxX=+pn?ywDwtJ2{TV;0DKBO2t++B(tIO4)Wh`rD13P z4fE$#%zkd=UzOB74gi=-*CuID&Z3zI^-`4U^S?dHxK8fP*;fE|a(KYMgMUo`THIS1f!*6dOI2 zFjC3O=-AL`6=9pp;`CYPTdVX z8(*?V&%QoipuH0>WKlL8A*zTKckD!paN@~hh zmXzm~qZhMGVdQGd=AG8&20HW0RGV8X{$9LldFZYm zE?}`Q3i?xJRz43S?VFMmqRyvWaS#(~Lempg9nTM$EFDP(Gzx#$r)W&lpFKqcAoJh-AxEw$-bjW>`_+gEi z2w`99#UbFZGiQjS8kj~@PGqpsPX`T{YOj`CaEqTFag;$jY z8_{Wzz>HXx&G*Dx<5skhpETxIdhKH?DtY@b9l8$l?UkM#J-Snmts7bd7xayKTFJ(u zyAT&@6cAYcs{PBfpqZa%sxhJ5nSZBPji?Zlf&}#L?t)vC4X5VLp%~fz2Sx<*oN<7` z?ge=k<=X7r<~F7Tvp9#HB{!mA!QWBOf%EiSJ6KIF8QZNjg&x~-%e*tflL(ji_S^sO ztmib1rp09uon}RcsFi#k)oLs@$?vs(i>5k3YN%$T(5Or(TZ5JW9mA6mIMD08=749$ z!d+l*iu{Il7^Yu}H;lgw=En1sJpCKPSqTCHy4(f&NPelr31^*l%KHq^QE>z>Ks_bH zjbD?({~8Din7IvZeJ>8Ey=e;I?thpzD=zE5UHeO|neioJwG;IyLk?xOz(yO&0DTU~ z^#)xcs|s>Flgmp;SmYJ4g(|HMu3v7#;c*Aa8iF#UZo7CvDq4>8#qLJ|YdZ!AsH%^_7N1IQjCro

K7UpUK$>l@ zw`1S}(D?mUXu_C{wupRS-jiX~w=Uqqhf|Vb3Cm9L=T+w91Cu^ z*&Ty%sN?x*h~mJc4g~k{xD4ZmF%FXZNC;oVDwLZ_WvrnzY|{v8hc1nmx4^}Z;yriXsAf+Lp+OFLbR!&Ox?xABwl zu8w&|5pCxmu#$?Cv2_-Vghl2LZ6m7}VLEfR5o2Ou$x02uA-%QB2$c(c1rH3R9hesc zfpn#oqpbKuVsdfV#cv@5pV4^f_!WS+F>SV6N0JQ9E!T90EX((_{bSSFv9ld%I0&}9 zH&Jd4MEX1e0iqDtq~h?DBrxQX1iI0lIs<|kB$Yrh&cpeK0-^K%=FBsCBT46@h#yi!AyDq1V(#V}^;{{V*@T4WJ&U-NTq43w=|K>z8%pr_nC>%C(Wa_l78Ufib$r8Od)IIN=u>417 z`Hl{9A$mI5A(;+-Q&$F&h-@;NR>Z<2U;Y21>>Z;s@0V@SbkMQQj%_;~+qTuQ?c|AV zcWm3XZQHhP&R%QWarS%mJ!9R^&!_)*s(v+VR@I#QrAT}`17Y+l<`b-nvmDNW`De%y zrwTZ9EJrj1AFA>B`1jYDow}~*dfPs}IZMO3=a{Fy#IOILc8F0;JS4x(k-NSpbN@qM z`@aE_e}5{!$v3+qVs7u?sOV(y@1Os*Fgu`fCW9=G@F_#VQ%xf$hj0~wnnP0$hFI+@ zkQj~v#V>xn)u??YutKsX>pxKCl^p!C-o?+9;!Nug^ z{rP!|+KsP5%uF;ZCa5F;O^9TGac=M|=V z_H(PfkV1rz4jl?gJ(ArXMyWT4y(86d3`$iI4^l9`vLdZkzpznSd5Ikfrs8qcSy&>z zTIZgWZGXw0n9ibQxYWE@gI0(3#KA-dAdPcsL_|hg2@~C!VZDM}5;v_Nykfq!*@*Zf zE_wVgx82GMDryKO{U{D>vSzSc%B~|cjDQrt5BN=Ugpsf8H8f1lR4SGo#hCuXPL;QQ z#~b?C4MoepT3X`qdW2dNn& zo8)K}%Lpu>0tQei+{>*VGErz|qjbK#9 zvtd8rcHplw%YyQCKR{kyo6fgg!)6tHUYT(L>B7er5)41iG`j$qe*kSh$fY!PehLcD zWeKZHn<492B34*JUQh=CY1R~jT9Jt=k=jCU2=SL&&y5QI2uAG2?L8qd2U(^AW#{(x zThSy=C#>k+QMo^7caQcpU?Qn}j-`s?1vXuzG#j8(A+RUAY})F@=r&F(8nI&HspAy4 z4>(M>hI9c7?DCW8rw6|23?qQMSq?*Vx?v30U%luBo)B-k2mkL)Ljk5xUha3pK>EEj z@(;tH|M@xkuN?gsz;*bygizwYR!6=(Xgcg^>WlGtRYCozY<rFX2E>kaZo)O<^J7a`MX8Pf`gBd4vrtD|qKn&B)C&wp0O-x*@-|m*0egT=-t@%dD zgP2D+#WPptnc;_ugD6%zN}Z+X4=c61XNLb7L1gWd8;NHrBXwJ7s0ce#lWnnFUMTR& z1_R9Fin4!d17d4jpKcfh?MKRxxQk$@)*hradH2$3)nyXep5Z;B z?yX+-Bd=TqO2!11?MDtG0n(*T^!CIiF@ZQymqq1wPM_X$Iu9-P=^}v7npvvPBu!d$ z7K?@CsA8H38+zjA@{;{kG)#AHME>Ix<711_iQ@WWMObXyVO)a&^qE1GqpP47Q|_AG zP`(AD&r!V^MXQ^e+*n5~Lp9!B+#y3#f8J^5!iC@3Y@P`;FoUH{G*pj*q7MVV)29+j z>BC`a|1@U_v%%o9VH_HsSnM`jZ-&CDvbiqDg)tQEnV>b%Ptm)T|1?TrpIl)Y$LnG_ zzKi5j2Fx^K^PG1=*?GhK;$(UCF-tM~^=Z*+Wp{FSuy7iHt9#4n(sUuHK??@v+6*|10Csdnyg9hAsC5_OrSL;jVkLlf zHXIPukLqbhs~-*oa^gqgvtpgTk_7GypwH><53riYYL*M=Q@F-yEPLqQ&1Sc zZB%w}T~RO|#jFjMWcKMZccxm-SL)s_ig?OC?y_~gLFj{n8D$J_Kw%{r0oB8?@dWzn zB528d-wUBQzrrSSLq?fR!K%59Zv9J4yCQhhDGwhptpA5O5U?Hjqt>8nOD zi{)0CI|&Gu%zunGI*XFZh(ix)q${jT8wnnzbBMPYVJc4HX*9d^mz|21$=R$J$(y7V zo0dxdbX3N#=F$zjstTf*t8vL)2*{XH!+<2IJ1VVFa67|{?LP&P41h$2i2;?N~RA30LV`BsUcj zfO9#Pg1$t}7zpv#&)8`mis3~o+P(DxOMgz-V*(?wWaxi?R=NhtW}<#^Z?(BhSwyar zG|A#Q7wh4OfK<|DAcl9THc-W4*>J4nTevsD%dkj`U~wSUCh15?_N@uMdF^Kw+{agk zJ`im^wDqj`Ev)W3k3stasP`88-M0ZBs7;B6{-tSm3>I@_e-QfT?7|n0D~0RRqDb^G zyHb=is;IwuQ&ITzL4KsP@Z`b$d%B0Wuhioo1CWttW8yhsER1ZUZzA{F*K=wmi-sb#Ju+j z-l@In^IKnb{bQG}Ps>+Vu_W#grNKNGto+yjA)?>0?~X`4I3T@5G1)RqGUZuP^NJCq&^HykuYtMDD8qq+l8RcZNJsvN(10{ zQ1$XcGt}QH-U^WU!-wRR1d--{B$%vY{JLWIV%P4-KQuxxDeJaF#{eu&&r!3Qu{w}0f--8^H|KwE>)ORrcR+2Qf zb})DRcH>k0zWK8@{RX}NYvTF;E~phK{+F;MkIP$)T$93Ba2R2TvKc>`D??#mv9wg$ zd~|-`Qx5LwwsZ2hb*Rt4S9dsF%Cny5<1fscy~)d;0m2r$f=83<->c~!GNyb!U)PA; zq^!`@@)UaG)Ew(9V?5ZBq#c%dCWZrplmuM`o~TyHjAIMh0*#1{B>K4po-dx$Tk-Cq z=WZDkP5x2W&Os`N8KiYHRH#UY*n|nvd(U>yO=MFI-2BEp?x@=N<~CbLJBf6P)}vLS?xJXYJ2^<3KJUdrwKnJnTp{ zjIi|R=L7rn9b*D#Xxr4*R<3T5AuOS+#U8hNlfo&^9JO{VbH!v9^JbK=TCGR-5EWR@ zN8T-_I|&@A}(hKeL4_*eb!1G8p~&_Im8|wc>Cdir+gg90n1dw?QaXcx6Op_W1r=axRw>4;rM*UOpT#Eb9xU1IiWo@h?|5uP zka>-XW0Ikp@dIe;MN8B01a7+5V@h3WN{J=HJ*pe0uwQ3S&MyWFni47X32Q7SyCTNQ z+sR!_9IZa5!>f&V$`q!%H8ci!a|RMx5}5MA_kr+bhtQy{-^)(hCVa@I!^TV4RBi zAFa!Nsi3y37I5EK;0cqu|9MRj<^r&h1lF}u0KpKQD^5Y+LvFEwM zLU@@v4_Na#Axy6tn3P%sD^5P#<7F;sd$f4a7LBMk zGU^RZHBcxSA%kCx*eH&wgA?Qwazm8>9SCSz_!;MqY-QX<1@p$*T8lc?@`ikEqJ>#w zcG``^CoFMAhdEXT9qt47g0IZkaU)4R7wkGs^Ax}usqJ5HfDYAV$!=6?>J6+Ha1I<5 z|6=9soU4>E))tW$<#>F ziZ$6>KJf0bPfbx_)7-}tMINlc=}|H+$uX)mhC6-Hz+XZxsKd^b?RFB6et}O#+>Wmw9Ec9) z{q}XFWp{3@qmyK*Jvzpyqv57LIR;hPXKsrh{G?&dRjF%Zt5&m20Ll?OyfUYC3WRn{cgQ?^V~UAv+5 z&_m#&nIwffgX1*Z2#5^Kl4DbE#NrD&Hi4|7SPqZ}(>_+JMz=s|k77aEL}<=0Zfb)a z%F(*L3zCA<=xO)2U3B|pcTqDbBoFp>QyAEU(jMu8(jLA61-H!ucI804+B!$E^cQQa z)_ERrW3g!B9iLb3nn3dlkvD7KsY?sRvls3QC0qPi>o<)GHx%4Xb$5a3GBTJ(k@`e@ z$RUa^%S15^1oLEmA=sayrP5;9qtf!Z1*?e$ORVPsXpL{jL<6E)0sj&swP3}NPmR%FM?O>SQgN5XfHE< zo(4#Cv11(%Nnw_{_Ro}r6=gKd{k?NebJ~<~Kv0r(r0qe4n3LFx$5%x(BKvrz$m?LG zjLIc;hbj0FMdb9aH9Lpsof#yG$(0sG2%RL;d(n>;#jb!R_+dad+K;Ccw!|RY?uS(a zj~?=&M!4C(5LnlH6k%aYvz@7?xRa^2gml%vn&eKl$R_lJ+e|xsNfXzr#xuh(>`}9g zLHSyiFwK^-p!;p$yt7$F|3*IfO3Mlu9e>Dpx8O`37?fA`cj`C0B-m9uRhJjs^mRp# zWB;Aj6|G^1V6`jg7#7V9UFvnB4((nIwG?k%c7h`?0tS8J3Bn0t#pb#SA}N-|45$-j z$R>%7cc2ebAClXc(&0UtHX<>pd)akR3Kx_cK+n<}FhzmTx!8e9^u2e4%x{>T6pQ`6 zO182bh$-W5A3^wos0SV_TgPmF4WUP-+D25KjbC{y_6W_9I2_vNKwU(^qSdn&>^=*t z&uvp*@c8#2*paD!ZMCi3;K{Na;I4Q35zw$YrW5U@Kk~)&rw;G?d7Q&c9|x<Hg|CNMsxovmfth*|E*GHezPTWa^Hd^F4!B3sF;)? z(NaPyAhocu1jUe(!5Cy|dh|W2=!@fNmuNOzxi^tE_jAtzNJ0JR-avc_H|ve#KO}#S z#a(8secu|^Tx553d4r@3#6^MHbH)vmiBpn0X^29xEv!Vuh1n(Sr5I0V&`jA2;WS|Y zbf0e}X|)wA-Pf5gBZ>r4YX3Mav1kKY(ulAJ0Q*jB)YhviHK)w!TJsi3^dMa$L@^{` z_De`fF4;M87vM3Ph9SzCoCi$#Fsd38u!^0#*sPful^p5oI(xGU?yeYjn;Hq1!wzFk zG&2w}W3`AX4bxoVm03y>ts{KaDf!}b&7$(P4KAMP=vK5?1In^-YYNtx1f#}+2QK@h zeSeAI@E6Z8a?)>sZ`fbq9_snl6LCu6g>o)rO;ijp3|$vig+4t} zylEo7$SEW<_U+qgVcaVhk+4k+C9THI5V10qV*dOV6pPtAI$)QN{!JRBKh-D zk2^{j@bZ}yqW?<#VVuI_27*cI-V~sJiqQv&m07+10XF+#ZnIJdr8t`9s_EE;T2V;B z4UnQUH9EdX%zwh-5&wflY#ve!IWt0UE-My3?L#^Bh%kcgP1q{&26eXLn zTkjJ*w+(|_>Pq0v8{%nX$QZbf)tbJaLY$03;MO=Ic-uqYUmUCuXD>J>o6BCRF=xa% z3R4SK9#t1!K4I_d>tZgE>&+kZ?Q}1qo4&h%U$GfY058s%*=!kac{0Z+4Hwm!)pFLR zJ+5*OpgWUrm0FPI2ib4NPJ+Sk07j(`diti^i#kh&f}i>P4~|d?RFb#!JN)~D@)beox}bw?4VCf^y*`2{4`-@%SFTry2h z>9VBc9#JxEs1+0i2^LR@B1J`B9Ac=#FW=(?2;5;#U$0E0UNag_!jY$&2diQk_n)bT zl5Me_SUvqUjwCqmVcyb`igygB_4YUB*m$h5oeKv3uIF0sk}~es!{D>4r%PC*F~FN3owq5e0|YeUTSG#Vq%&Gk7uwW z0lDo#_wvflqHeRm*}l?}o;EILszBt|EW*zNPmq#?4A+&i0xx^?9obLyY4xx=Y9&^G;xYXYPxG)DOpPg!i_Ccl#3L}6xAAZzNhPK1XaC_~ z!A|mlo?Be*8Nn=a+FhgpOj@G7yYs(Qk(8&|h@_>w8Y^r&5nCqe0V60rRz?b5%J;GYeBqSAjo|K692GxD4` zRZyM2FdI+-jK2}WAZTZ()w_)V{n5tEb@>+JYluDozCb$fA4H)$bzg(Ux{*hXurjO^ zwAxc+UXu=&JV*E59}h3kzQPG4M)X8E*}#_&}w*KEgtX)cU{vm9b$atHa;s>| z+L6&cn8xUL*OSjx4YGjf6{Eq+Q3{!ZyhrL&^6Vz@jGbI%cAM9GkmFlamTbcQGvOlL zmJ?(FI)c86=JEs|*;?h~o)88>12nXlpMR4@yh%qdwFNpct;vMlc=;{FSo*apJ;p}! zAX~t;3tb~VuP|ZW;z$=IHf->F@Ml)&-&Bnb{iQyE#;GZ@C$PzEf6~q}4D>9jic@mTO5x76ulDz@+XAcm35!VSu zT*Gs>;f0b2TNpjU_BjHZ&S6Sqk6V1370+!eppV2H+FY!q*n=GHQ!9Rn6MjY!Jc77A zG7Y!lFp8?TIHN!LXO?gCnsYM-gQxsm=Ek**VmZu7vnuufD7K~GIxfxbsQ@qv2T zPa`tvHB$fFCyZl>3oYg?_wW)C>^_iDOc^B7klnTOoytQH18WkOk)L2BSD0r%xgRSW zQS9elF^?O=_@|58zKLK;(f77l-Zzu}4{fXed2saq!5k#UZAoDBqYQS{sn@j@Vtp|$ zG%gnZ$U|9@u#w1@11Sjl8ze^Co=)7yS(}=;68a3~g;NDe_X^}yJj;~s8xq9ahQ5_r zxAlTMnep*)w1e(TG%tWsjo3RR;yVGPEO4V{Zp?=a_0R#=V^ioQu4YL=BO4r0$$XTX zZfnw#_$V}sDAIDrezGQ+h?q24St0QNug_?{s-pI(^jg`#JRxM1YBV;a@@JQvH8*>> zIJvku74E0NlXkYe_624>znU0J@L<-c=G#F3k4A_)*;ky!C(^uZfj%WB3-*{*B$?9+ zDm$WFp=0(xnt6`vDQV3Jl5f&R(Mp};;q8d3I%Kn>Kx=^;uSVCw0L=gw53%Bp==8Sw zxtx=cs!^-_+i{2OK`Q;913+AXc_&Z5$@z3<)So0CU3;JAv=H?@Zpi~riQ{z-zLtVL z!oF<}@IgJp)Iyz1zVJ42!SPHSkjYNS4%ulVVIXdRuiZ@5Mx8LJS}J#qD^Zi_xQ@>DKDr-_e#>5h3dtje*NcwH_h;i{Sx7}dkdpuW z(yUCjckQsagv*QGMSi9u1`Z|V^}Wjf7B@q%j2DQXyd0nOyqg%m{CK_lAoKlJ7#8M} z%IvR?Vh$6aDWK2W!=i?*<77q&B8O&3?zP(Cs@kapc)&p7En?J;t-TX9abGT#H?TW? ztO5(lPKRuC7fs}zwcUKbRh=7E8wzTsa#Z{a`WR}?UZ%!HohN}d&xJ=JQhpO1PI#>X zHkb>pW04pU%Bj_mf~U}1F1=wxdBZu1790>3Dm44bQ#F=T4V3&HlOLsGH)+AK$cHk6 zia$=$kog?)07HCL*PI6}DRhpM^*%I*kHM<#1Se+AQ!!xyhcy6j7`iDX7Z-2i73_n# zas*?7LkxS-XSqv;YBa zW_n*32D(HTYQ0$feV_Fru1ZxW0g&iwqixPX3=9t4o)o|kOo79V$?$uh?#8Q8e>4e)V6;_(x&ViUVxma+i25qea;d-oK7ouuDsB^ab{ zu1qjQ%`n56VtxBE#0qAzb7lph`Eb-}TYpXB!H-}3Ykqyp`otprp7{VEuW*^IR2n$Fb99*nAtqT&oOFIf z@w*6>YvOGw@Ja?Pp1=whZqydzx@9X4n^2!n83C5{C?G@|E?&$?p*g68)kNvUTJ)I6 z1Q|(#UuP6pj78GUxq11m-GSszc+)X{C2eo-?8ud9sB=3(D47v?`JAa{V(IF zPZQ_0AY*9M97>Jf<o%#O_%Wq}8>YM=q0|tGY+hlXcpE=Z4Od z`NT7Hu2hnvRoqOw@g1f=bv`+nba{GwA$Ak0INlqI1k<9!x_!sL()h?hEWoWrdU3w` zZ%%)VR+Bc@_v!C#koM1p-3v_^L6)_Ktj4HE>aUh%2XZE@JFMOn)J~c`_7VWNb9c-N z2b|SZMR4Z@E7j&q&9(6H3yjEu6HV7{2!1t0lgizD;mZ9$r(r7W5G$ky@w(T_dFnOD z*p#+z$@pKE+>o@%eT(2-p_C}wbQ5s(%Sn_{$HDN@MB+Ev?t@3dPy`%TZ!z}AThZSu zN<1i$siJhXFdjV zP*y|V<`V8t=h#XTRUR~5`c`Z9^-`*BZf?WAehGdg)E2Je)hqFa!k{V(u+(hTf^Yq& zoruUh2(^3pe)2{bvt4&4Y9CY3js)PUHtd4rVG57}uFJL)D(JfSIo^{P=7liFXG zq5yqgof0V8paQcP!gy+;^pp-DA5pj=gbMN0eW=-eY+N8~y+G>t+x}oa!5r>tW$xhI zPQSv=pi;~653Gvf6~*JcQ%t1xOrH2l3Zy@8AoJ+wz@daW@m7?%LXkr!bw9GY@ns3e zSfuWF_gkWnesv?s3I`@}NgE2xwgs&rj?kH-FEy82=O8`+szN ziHch`vvS`zNfap14!&#i9H@wF7}yIPm=UB%(o(}F{wsZ(wA0nJ2aD^@B41>>o-_U6 zUqD~vdo48S8~FTb^+%#zcbQiiYoDKYcj&$#^;Smmb+Ljp(L=1Kt_J!;0s%1|JK}Wi z;={~oL!foo5n8=}rs6MmUW~R&;SIJO3TL4Ky?kh+b2rT9B1Jl4>#Uh-Bec z`Hsp<==#UEW6pGPhNk8H!!DUQR~#F9jEMI6T*OWfN^Ze&X(4nV$wa8QUJ>oTkruH# zm~O<`J7Wxseo@FqaZMl#Y(mrFW9AHM9Kb|XBMqaZ2a)DvJgYipkDD_VUF_PKd~dT7 z#02}bBfPn9a!X!O#83=lbJSK#E}K&yx-HI#T6ua)6o0{|={*HFusCkHzs|Fn&|C3H zBck1cmfcWVUN&i>X$YU^Sn6k2H;r3zuXbJFz)r5~3$d$tUj(l1?o={MM){kjgqXRO zc5R*#{;V7AQh|G|)jLM@wGAK&rm2~@{Pewv#06pHbKn#wL0P6F1!^qw9g&cW3Z=9} zj)POhOlwsh@eF=>z?#sIs*C-Nl(yU!#DaiaxhEs#iJqQ8w%(?+6lU02MYSeDkr!B- zPjMv+on6OLXgGnAtl(ao>|X2Y8*Hb}GRW5}-IzXnoo-d0!m4Vy$GS!XOLy>3_+UGs z2D|YcQx@M#M|}TDOetGi{9lGo9m-=0-^+nKE^*?$^uHkxZh}I{#UTQd;X!L+W@jm( zDg@N4+lUqI92o_rNk{3P>1gxAL=&O;x)ZT=q1mk0kLlE$WeWuY_$0`0jY-Kkt zP*|m3AF}Ubd=`<>(Xg0har*_@x2YH}bn0Wk*OZz3*e5;Zc;2uBdnl8?&XjupbkOeNZsNh6pvsq_ydmJI+*z**{I{0K)-;p1~k8cpJXL$^t!-`E}=*4G^-E8>H!LjTPxSx zcF+cS`ommfKMhNSbas^@YbTpH1*RFrBuATUR zt{oFWSk^$xU&kbFQ;MCX22RAN5F6eq9UfR$ut`Jw--p2YX)A*J69m^!oYfj2y7NYcH6&r+0~_sH^c^nzeN1AU4Ga7=FlR{S|Mm~MpzY0$Z+p2W(a={b-pR9EO1Rs zB%KY|@wLcAA@)KXi!d2_BxrkhDn`DT1=Dec}V!okd{$+wK z4E{n8R*xKyci1(CnNdhf$Dp2(Jpof0-0%-38X=Dd9PQgT+w%Lshx9+loPS~MOm%ZT zt%2B2iL_KU_ita%N>xjB!#71_3=3c}o zgeW~^U_ZTJQ2!PqXulQd=3b=XOQhwATK$y(9$#1jOQ4}4?~l#&nek)H(04f(Sr=s| zWv7Lu1=%WGk4FSw^;;!8&YPM)pQDCY9DhU`hMty1@sq1=Tj7bFsOOBZOFlpR`W>-J$-(kezWJj;`?x-v>ev{*8V z8p|KXJPV$HyQr1A(9LVrM47u-XpcrIyO`yWvx1pVYc&?154aneRpLqgx)EMvRaa#|9?Wwqs2+W8n5~79G z(}iCiLk;?enn}ew`HzhG+tu+Ru@T+K5juvZN)wY;x6HjvqD!&!)$$;1VAh~7fg0K| zEha#aN=Yv|3^~YFH}cc38ovVb%L|g@9W6fo(JtT6$fa?zf@Ct88e}m?i)b*Jgc{fl zExfdvw-BYDmH6>(4QMt#p0;FUIQqkhD}aH?a7)_%JtA~soqj{ppP_82yi9kaxuK>~ ze_)Zt>1?q=ZH*kF{1iq9sr*tVuy=u>Zev}!gEZx@O6-fjyu9X00gpIl-fS_pzjpqJ z1yqBmf9NF!jaF<+YxgH6oXBdK)sH(>VZ)1siyA$P<#KDt;8NT*l_0{xit~5j1P)FN zI8hhYKhQ)i z37^aP13B~u65?sg+_@2Kr^iWHN=U;EDSZ@2W2!5ALhGNWXnFBY%7W?1 z=HI9JzQ-pLKZDYTv<0-lt|6c-RwhxZ)mU2Os{bsX_i^@*fKUj8*aDO5pks=qn3Dv6 zwggpKLuyRCTVPwmw1r}B#AS}?X7b837UlXwp~E2|PJw2SGVueL7){Y&z!jL!XN=0i zU^Eig`S2`{+gU$68aRdWx?BZ{sU_f=8sn~>s~M?GU~`fH5kCc; z8ICp+INM3(3{#k32RZdv6b9MQYdZXNuk7ed8;G?S2nT+NZBG=Tar^KFl2SvhW$bGW#kdWL-I)s_IqVnCDDM9fm8g;P;8 z7t4yZn3^*NQfx7SwmkzP$=fwdC}bafQSEF@pd&P8@H#`swGy_rz;Z?Ty5mkS%>m#% zp_!m9e<()sfKiY(nF<1zBz&&`ZlJf6QLvLhl`_``%RW&{+O>Xhp;lwSsyRqGf=RWd zpftiR`={2(siiPAS|p}@q=NhVc0ELprt%=fMXO3B)4ryC2LT(o=sLM7hJC!}T1@)E zA3^J$3&1*M6Xq>03FX`R&w*NkrZE?FwU+Muut;>qNhj@bX17ZJxnOlPSZ=Zeiz~T_ zOu#yc3t6ONHB;?|r4w+pI)~KGN;HOGC)txxiUN8#mexj+W(cz%9a4sx|IRG=}ia zuEBuba3AHsV2feqw-3MvuL`I+2|`Ud4~7ZkN=JZ;L20|Oxna5vx1qbIh#k2O4$RQF zo`tL()zxaqibg^GbB+BS5#U{@K;WWQj~GcB1zb}zJkPwH|5hZ9iH2308!>_;%msji zJHSL~s)YHBR=Koa1mLEOHos*`gp=s8KA-C zu0aE+W!#iJ*0xqKm3A`fUGy#O+X+5W36myS>Uh2!R*s$aCU^`K&KKLCCDkejX2p=5 z%o7-fl03x`gaSNyr?3_JLv?2RLS3F*8ub>Jd@^Cc17)v8vYEK4aqo?OS@W9mt%ITJ z9=S2%R8M){CugT@k~~0x`}Vl!svYqX=E)c_oU6o}#Hb^%G1l3BudxA{F*tbjG;W_>=xV73pKY53v%>I)@D36I_@&p$h|Aw zonQS`07z_F#@T-%@-Tb|)7;;anoD_WH>9ewFy(ZcEOM$#Y)8>qi7rCnsH9GO-_7zF zu*C87{Df1P4TEOsnzZ@H%&lvV(3V@;Q!%+OYRp`g05PjY^gL$^$-t0Y>H*CDDs?FZly*oZ&dxvsxaUWF!{em4{A>n@vpXg$dwvt@_rgmHF z-MER`ABa8R-t_H*kv>}CzOpz;!>p^^9ztHMsHL|SRnS<-y5Z*r(_}c4=fXF`l^-i}>e7v!qs_jv zqvWhX^F=2sDNWA9c@P0?lUlr6ecrTKM%pNQ^?*Lq?p-0~?_j50xV%^(+H>sMul#Tw zeciF*1=?a7cI(}352%>LO96pD+?9!fNyl^9v3^v&Y4L)mNGK0FN43&Xf8jUlxW1Bw zyiu2;qW-aGNhs=zbuoxnxiwZ3{PFZM#Kw)9H@(hgX23h(`Wm~m4&TvoZoYp{plb^> z_#?vXcxd>r7K+1HKJvhed>gtK`TAbJUazUWQY6T~t2af%#<+Veyr%7-#*A#@&*;@g58{i|E%6yC_InGXCOd{L0;$)z#?n7M`re zh!kO{6=>7I?*}czyF7_frt#)s1CFJ_XE&VrDA?Dp3XbvF{qsEJgb&OLSNz_5g?HpK z9)8rsr4JN!Af3G9!#Qn(6zaUDqLN(g2g8*M)Djap?WMK9NKlkC)E2|-g|#-rp%!Gz zAHd%`iq|81efi93m3yTBw3g0j#;Yb2X{mhRAI?&KDmbGqou(2xiRNb^sV}%%Wu0?< z?($L>(#BO*)^)rSgyNRni$i`R4v;GhlCZ8$@e^ROX(p=2_v6Y!%^As zu022)fHdv_-~Yu_H6WVPLpHQx!W%^6j)cBhS`O3QBW#x(eX54d&I22op(N59b*&$v zFiSRY6rOc^(dgSV1>a7-5C;(5S5MvKcM2Jm-LD9TGqDpP097%52V+0>Xqq!! zq4e3vj53SE6i8J`XcQB|MZPP8j;PAOnpGnllH6#Ku~vS42xP*Nz@~y%db7Xi8s09P z1)e%8ys6&M8D=Dt6&t`iKG_4X=!kgRQoh%Z`dc&mlOUqXk-k`jKv9@(a^2-Upw>?< zt5*^DV~6Zedbec4NVl($2T{&b)zA@b#dUyd>`2JC0=xa_fIm8{5um zr-!ApXZhC8@=vC2WyxO|!@0Km)h8ep*`^he92$@YwP>VcdoS5OC^s38e#7RPsg4j+ zbVGG}WRSET&ZfrcR(x~k8n1rTP%CnfUNKUonD$P?FtNFF#cn!wEIab-;jU=B1dHK@ z(;(yAQJ`O$sMn>h;pf^8{JISW%d+@v6@CnXh9n5TXGC}?FI9i-D0OMaIg&mAg=0Kn zNJ7oz5*ReJukD55fUsMuaP+H4tDN&V9zfqF@ zr=#ecUk9wu{0;!+gl;3Bw=Vn^)z$ahVhhw)io!na&9}LmWurLb0zubxK=UEnU*{5P z+SP}&*(iBKSO4{alBHaY^)5Q=mZ+2OwIooJ7*Q5XJ+2|q`9#f?6myq!&oz?klihLq z4C)$XP!BNS0G_Z1&TM>?Jk{S~{F3n83ioli=IO6f%wkvCl(RFFw~j0tb{GvXTx>*sB0McY0s&SNvj4+^h`9nJ_wM>F!Uc>X}9PifQekn0sKI2SAJP!a4h z5cyGTuCj3ZBM^&{dRelIlT^9zcfaAuL5Y~bl!ppSf`wZbK$z#6U~rdclk``e+!qhe z6Qspo*%<)eu6?C;Bp<^VuW6JI|Ncvyn+LlSl;Mp22Bl7ARQ0Xc24%29(ZrdsIPw&-=yHQ7_Vle|5h>AST0 zUGX2Zk34vp?U~IHT|;$U86T+UUHl_NE4m|}>E~6q``7hccCaT^#y+?wD##Q%HwPd8 zV3x4L4|qqu`B$4(LXqDJngNy-{&@aFBvVsywt@X^}iH7P%>bR?ciC$I^U-4Foa`YKI^qDyGK7k%E%c_P=yzAi`YnxGA%DeNd++j3*h^ z=rn>oBd0|~lZ<6YvmkKY*ZJlJ;Im0tqgWu&E92eqt;+NYdxx`eS(4Hw_Jb5|yVvBg z*tbdY^!AN;luEyN4VRhS@-_DC{({ziH{&Z}iGElSV~qvT>L-8G%+yEL zX#MFOhj{InyKG=mvW-<1B@c-}x$vA(nU?>S>0*eN#!SLzQ)Ex7fvQ)S4D<8|I#N$3 zT5Ei`Z?cxBODHX8(Xp73v`IsAYC@9b;t}z0wxVuQSY1J^GRwDPN@qbM-ZF48T$GZ< z8WU+;Pqo?{ghI-KZ-i*ydXu`Ep0Xw^McH_KE9J0S7G;x8Fe`DVG?j3Pv=0YzJ}yZR z%2=oqHiUjvuk0~Ca>Kol4CFi0_xQT~;_F?=u+!kIDl-9g`#ZNZ9HCy17Ga1v^Jv9# z{T4Kb1-AzUxq*MutfOWWZgD*HnFfyYg0&e9f(5tZ>krPF6{VikNeHoc{linPPt#Si z&*g>(c54V8rT_AX!J&bNm-!umPvOR}vDai#`CX___J#=zeB*{4<&2WpaDncZsOkp* zsg<%@@rbrMkR_ux9?LsQxzoBa1s%$BBn6vk#{&&zUwcfzeCBJUwFYSF$08qDsB;gWQN*g!p8pxjofWbqNSZOEKOaTx@+* zwdt5*Q47@EOZ~EZL9s?1o?A%9TJT=Ob_13yyugvPg*e&ZU(r6^k4=2+D-@n=Hv5vu zSXG|hM(>h9^zn=eQ=$6`JO&70&2|%V5Lsx>)(%#;pcOfu>*nk_3HB_BNaH$`jM<^S zcSftDU1?nL;jy)+sfonQN}(}gUW?d_ikr*3=^{G)=tjBtEPe>TO|0ddVB zTklrSHiW+!#26frPXQQ(YN8DG$PZo?(po(QUCCf_OJC`pw*uey00%gmH!`WJkrKXj2!#6?`T25mTu9OJp2L8z3! z=arrL$ZqxuE{%yV)14Kd>k}j7pxZ6#$Dz8$@WV5p8kTqN<-7W)Q7Gt2{KoOPK_tZ| zf2WG~O5@{qPI+W<4f_;reuFVdO^5`ADC1!JQE|N`s3cq@(0WB!n0uh@*c{=LAd;~} zyGK@hbF-Oo+!nN)@i*O(`@FA#u?o=~e{`4O#5}z&=UkU*50fOrzi11D^&FOqe>wii z?*k+2|EcUs;Gx{!@KBT~>PAwLrIDT7Th=Utu?~?np@t^gFs?zgX=D${RwOY^WGh-+ z+#4$066ISh8eYW#FXWp~S`<*%O^ZuItL1Tyqt8#tZ zY120E;^VG`!lZn&3sPd$RkdHpU#|w+bYV)pJC|SH9g%|5IkxVTQcBA4CL0}$&}ef@ zW^Vtj%M;;_1xxP9x#ex17&4N*{ksO*_4O}xYu(p*JkL#yr}@7b)t5X?%CY<+s5_MJ zuiqt+N_;A(_)%lumoyRFixWa-M7qK_9s6<1X?JDa9fP!+_6u~~M$5L=ipB=7(j#f< zZ34J%=bs549%~_mA(|={uZNs_0?o7;-LBP(ZRnkd{-^|2|=4vUTmtByHL8 zEph`(LSEzQj68a+`d$V<45J7cyv^#|^|%fD#si1Nx!4NW*`l*{->HEWNh6-|g>-=r zXmQ|-i}Ku$ndUeHQ^&ieT!Lf}vf6GaqW9$DJ2NWrqwPY%%4nip$@vK$nRp*_C-v<| zuKz~ZyN&<%!NS26&x?jhy+@awJipMQ-8(X4#Ae5??U<1QMt1l9R=w9fAnEF}NYu$2 z>6}Vkc zIb*A?G*z8^IvibmBKn_u^5&T_1oey0gZS2~obf(#xk=erZGTEdQnt3DMGM+0oPwss zj5zXD;(oWhB_T@~Ig#9@v)AKtXu3>Inmgf@A|-lD-1U>cNyl3h?ADD9)GG4}zUGPk zZzaXe!~Kf?<~@$G?Uql3t8jy9{2!doq4=J}j9ktTxss{p6!9UdjyDERlA*xZ!=Q)KDs5O)phz>Vq3BNGoM(H|=1*Q4$^2fTZw z(%nq1P|5Rt81}SYJpEEzMPl5VJsV5&4e)ZWKDyoZ>1EwpkHx-AQVQc8%JMz;{H~p{=FXV>jIxvm4X*qv52e?Y-f%DJ zxEA165GikEASQ^fH6K#d!Tpu2HP{sFs%E=e$gYd$aj$+xue6N+Wc(rAz~wUsk2`(b z8Kvmyz%bKQxpP}~baG-rwYcYCvkHOi zlkR<=>ZBTU*8RF_d#Bl@zZsRIhx<%~Z@Z=ik z>adw3!DK(8R|q$vy{FTxw%#xliD~6qXmY^7_9kthVPTF~Xy1CfBqbU~?1QmxmU=+k z(ggxvEuA;0e&+ci-zQR{-f7aO{O(Pz_OsEjLh_K>MbvoZ4nxtk5u{g@nPv)cgW_R} z9}EA4K4@z0?7ue}Z(o~R(X&FjejUI2g~08PH1E4w>9o{)S(?1>Z0XMvTb|;&EuyOE zGvWNpYX)Nv<8|a^;1>bh#&znEcl-r!T#pn= z4$?Yudha6F%4b>*8@=BdtXXY4N+`U4Dmx$}>HeVJk-QdTG@t!tVT#0(LeV0gvqyyw z2sEp^9eY0N`u10Tm4n8No&A=)IeEC|gnmEXoNSzu!1<4R<%-9kY_8~5Ej?zRegMn78wuMs#;i&eUA0Zk_RXQ3b&TT} z;SCI=7-FUB@*&;8|n>(_g^HGf3@QODE3LpmX~ELnymQm{Sx9xrKS zK29p~?v@R$0=v6Dr5aW>-!{+h@?Q58|Kz8{{W`%J+lDAdb&M5VHrX_mDY;1-JLnf)ezmPau$)1;=`-FU=-r-83tX=C`S#}GZufju zQ>sXNT0Ny=k@nc%cFnvA_i4SC)?_ORXHq8B4D%el1uPX`c~uG#S1M7C+*MMqLw78E zhY2dI8@+N^qrMI1+;TUda(vGqGSRyU{Fnm`aqrr7bz42c5xsOO-~oZpkzorD1g}Y<6rk&3>PsSGy}W?MtqFky@A(X# zIuNZK0cK?^=;PUAu>j0#HtjbHCV*6?jzA&OoE$*Jlga*}LF`SF?WLhv1O|zqC<>*> zYB;#lsYKx0&kH@BFpW8n*yDcc6?;_zaJs<-jPSkCsSX-!aV=P5kUgF@Nu<{a%#K*F z134Q{9|YX7X(v$62_cY3^G%t~rD>Q0z@)1|zs)vjJ6Jq9;7#Ki`w+eS**En?7;n&7 zu==V3T&eFboN3ZiMx3D8qYc;VjFUk_H-WWCau(VFXSQf~viH0L$gwD$UfFHqNcgN`x}M+YQ6RnN<+@t>JUp#)9YOkqst-Ga?{FsDpEeX0(5v{0J~SEbWiL zXC2}M4?UH@u&|;%0y`eb33ldo4~z-x8zY!oVmV=c+f$m?RfDC35mdQ2E>Pze7KWP- z>!Bh<&57I+O_^s}9Tg^k)h7{xx@0a0IA~GAOt2yy!X%Q$1rt~LbTB6@Du!_0%HV>N zlf)QI1&gvERKwso23mJ!Ou6ZS#zCS5W`gxE5T>C#E|{i<1D35C222I33?Njaz`On7 zi<+VWFP6D{e-{yiN#M|Jgk<44u1TiMI78S5W`Sdb5f+{zu34s{CfWN7a3Cf^@L%!& zN$?|!!9j2c)j$~+R6n#891w-z8(!oBpL2K=+%a$r2|~8-(vQj5_XT`<0Ksf;oP+tz z9CObS!0m)Tgg`K#xBM8B(|Z)Wb&DYL{WTYv`;A=q6~Nnx2+!lTIXtj8J7dZE!P_{z z#f8w6F}^!?^KE#+ZDv+xd5O&3EmomZzsv?>E-~ygGum45fk!SBN&|eo1rKw^?aZJ4 E2O(~oYXATM literal 0 HcmV?d00001 diff --git a/.generator/templates/gradle-wrapper.properties.mustache b/.generator/templates/gradle-wrapper.properties.mustache new file mode 100644 index 00000000000..4d9ca164914 --- /dev/null +++ b/.generator/templates/gradle-wrapper.properties.mustache @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/.generator/templates/gradle.properties.mustache b/.generator/templates/gradle.properties.mustache new file mode 100644 index 00000000000..05644f0754a --- /dev/null +++ b/.generator/templates/gradle.properties.mustache @@ -0,0 +1,2 @@ +# Uncomment to build for Android +#target = android \ No newline at end of file diff --git a/.generator/templates/gradlew.bat.mustache b/.generator/templates/gradlew.bat.mustache new file mode 100644 index 00000000000..107acd32c4e --- /dev/null +++ b/.generator/templates/gradlew.bat.mustache @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/.generator/templates/gradlew.mustache b/.generator/templates/gradlew.mustache new file mode 100755 index 00000000000..4f906e0c811 --- /dev/null +++ b/.generator/templates/gradlew.mustache @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/.generator/templates/jackson_annotations.mustache b/.generator/templates/jackson_annotations.mustache new file mode 100644 index 00000000000..3819d3d2dd2 --- /dev/null +++ b/.generator/templates/jackson_annotations.mustache @@ -0,0 +1,19 @@ +{{! + If this is map and items are nullable, make sure that nulls are included. + To determine what JsonInclude.Include method to use, consider the following: + * If the field is required, always include it, even if it is null. + * Else use custom behaviour, IOW use whatever is defined on the object mapper + }} + @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) + @JsonInclude({{#isMap}}{{#items.isNullable}}content = JsonInclude.Include.ALWAYS, {{/items.isNullable}}{{/isMap}}value = JsonInclude.Include.{{#required}}ALWAYS{{/required}}{{^required}}USE_DEFAULTS{{/required}}) + {{#withXml}} + {{^isContainer}} + @JacksonXmlProperty({{#isXmlAttribute}}isAttribute = true, {{/isXmlAttribute}}{{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}localName = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isContainer}} + {{#isContainer}} + {{#isXmlWrapped}} + // items.xmlName={{items.xmlName}} + @JacksonXmlElementWrapper(useWrapping = {{isXmlWrapped}}, {{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}localName = "{{#items.xmlName}}{{items.xmlName}}{{/items.xmlName}}{{^items.xmlName}}{{items.baseName}}{{/items.xmlName}}") + {{/isXmlWrapped}} + {{/isContainer}} + {{/withXml}} \ No newline at end of file diff --git a/.generator/templates/libraries/feign/ApiClient.mustache b/.generator/templates/libraries/feign/ApiClient.mustache new file mode 100644 index 00000000000..4e094dfccbe --- /dev/null +++ b/.generator/templates/libraries/feign/ApiClient.mustache @@ -0,0 +1,338 @@ +package {{invokerPackage}}; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +{{#threetenbp}} +import org.threeten.bp.*; +{{/threetenbp}} +import feign.okhttp.OkHttpClient; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +{{#openApiNullable}} +import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} +{{#joda}} +import com.fasterxml.jackson.datatype.joda.JodaModule; +{{/joda}} +{{#java8}} +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{/java8}} +{{#threetenbp}} +import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; +{{/threetenbp}} + +import feign.Feign; +import feign.RequestInterceptor; +import feign.form.FormEncoder; +import feign.jackson.JacksonDecoder; +import feign.jackson.JacksonEncoder; +import feign.slf4j.Slf4jLogger; +import {{invokerPackage}}.auth.*; +{{#hasOAuthMethods}} +import {{invokerPackage}}.auth.OAuth.AccessTokenListener; +{{/hasOAuthMethods}} + +{{>generatedAnnotation}} +public class ApiClient { + private static final Logger log = Logger.getLogger(ApiClient.class.getName()); + + public interface Api {} + + protected ObjectMapper objectMapper; + private String basePath = "{{{basePath}}}"; + private Map apiAuthorizations; + private Feign.Builder feignBuilder; + + public ApiClient() { + objectMapper = createObjectMapper(); + apiAuthorizations = new LinkedHashMap(); + feignBuilder = Feign.builder() + .client(new OkHttpClient()) + .encoder(new FormEncoder(new JacksonEncoder(objectMapper))) + .decoder(new JacksonDecoder(objectMapper)) + .logger(new Slf4jLogger()); + } + + public ApiClient(String[] authNames) { + this(); + for(String authName : authNames) { + log.log(Level.FINE, "Creating authentication {0}", authName); + {{#hasAuthMethods}} + RequestInterceptor auth; + {{#authMethods}}if ("{{name}}".equals(authName)) { + {{#isBasic}} + {{#isBasicBasic}} + auth = new HttpBasicAuth(); + {{/isBasicBasic}} + {{^isBasicBasic}} + auth = new HttpBearerAuth("{{scheme}}"); + {{/isBasicBasic}} + {{/isBasic}} + {{#isApiKey}} + auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"); + {{/isApiKey}} + {{#isOAuth}} + auth = buildOauthRequestInterceptor(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{^-last}}, {{/-last}}{{/scopes}}"); + {{/isOAuth}} + } else {{/authMethods}}{ + throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); + } + addAuthorization(authName, auth); + {{/hasAuthMethods}} + {{^hasAuthMethods}} + throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); + {{/hasAuthMethods}} + } + } + + /** + * Basic constructor for single auth name + * @param authName + */ + public ApiClient(String authName) { + this(new String[]{authName}); + } + + /** + * Helper constructor for single api key + * @param authName + * @param apiKey + */ + public ApiClient(String authName, String apiKey) { + this(authName); + this.setApiKey(apiKey); + } + + public String getBasePath() { + return basePath; + } + + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + public Map getApiAuthorizations() { + return apiAuthorizations; + } + + public void setApiAuthorizations(Map apiAuthorizations) { + this.apiAuthorizations = apiAuthorizations; + } + + public Feign.Builder getFeignBuilder() { + return feignBuilder; + } + + public ApiClient setFeignBuilder(Feign.Builder feignBuilder) { + this.feignBuilder = feignBuilder; + return this; + } + + private ObjectMapper createObjectMapper() { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + objectMapper.disable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE); + objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + objectMapper.setDateFormat(new RFC3339DateFormat()); + {{#joda}} + objectMapper.registerModule(new JodaModule()); + {{/joda}} + {{#java8}} + objectMapper.registerModule(new JavaTimeModule()); + {{/java8}} + {{#threetenbp}} + ThreeTenModule module = new ThreeTenModule(); + module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); + module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); + module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); + objectMapper.registerModule(module); + {{/threetenbp}} + {{#openApiNullable}} + JsonNullableModule jnm = new JsonNullableModule(); + objectMapper.registerModule(jnm); + {{/openApiNullable}} + return objectMapper; + } + + private RequestInterceptor buildOauthRequestInterceptor(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { + switch (flow) { + case password: + return new OauthPasswordGrant(tokenUrl, scopes); + case application: + return new OauthClientCredentialsGrant(authorizationUrl, tokenUrl, scopes); + default: + throw new RuntimeException("Oauth flow \"" + flow + "\" is not implemented"); + } + } + + public ObjectMapper getObjectMapper(){ + return objectMapper; + } + + public void setObjectMapper(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + /** + * Creates a feign client for given API interface. + * + * Usage: + * ApiClient apiClient = new ApiClient(); + * apiClient.setBasePath("http://localhost:8080"); + * XYZApi api = apiClient.buildClient(XYZApi.class); + * XYZResponse response = api.someMethod(...); + * @param Type + * @param clientClass Client class + * @return The Client + */ + public T buildClient(Class clientClass) { + return feignBuilder.target(clientClass, basePath); + } + + /** + * 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; + if (StringUtil.containsIgnoreCase(accepts, "application/json")) return "application/json"; + 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, + * JSON will be used. + */ + public String selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0) return "application/json"; + if (StringUtil.containsIgnoreCase(contentTypes, "application/json")) return "application/json"; + return contentTypes[0]; + } + + /** + * Helper method to configure the bearer token. + * @param bearerToken the bearer token. + */ + public void setBearerToken(String bearerToken) { + HttpBearerAuth apiAuthorization = getAuthorization(HttpBearerAuth.class); + apiAuthorization.setBearerToken(bearerToken); + } + + /** + * Helper method to configure the first api key found + * @param apiKey API key + */ + public void setApiKey(String apiKey) { + ApiKeyAuth apiAuthorization = getAuthorization(ApiKeyAuth.class); + apiAuthorization.setApiKey(apiKey); + } + + /** + * Helper method to configure the username/password for basic auth + * @param username Username + * @param password Password + */ + public void setCredentials(String username, String password) { + HttpBasicAuth apiAuthorization = getAuthorization(HttpBasicAuth.class); + apiAuthorization.setCredentials(username, password); + } + + {{#hasOAuthMethods}} + /** + * Helper method to configure the client credentials for Oauth + * @param username Username + * @param password Password + */ + public void setClientCredentials(String clientId, String clientSecret) { + OauthClientCredentialsGrant authorization = getAuthorization(OauthClientCredentialsGrant.class); + authorization.configure(clientId, clientSecret); + } + + /** + * Helper method to configure the username/password for Oauth password grant + * @param username Username + * @param password Password + */ + public void setOauthPassword(String username, String password, String clientId, String clientSecret) { + OauthPasswordGrant apiAuthorization = getAuthorization(OauthPasswordGrant.class); + apiAuthorization.configure(username, password, clientId, clientSecret); + } + + /** + * Helper method to pre-set the oauth access token of the first oauth found in the apiAuthorizations (there should be only one) + * @param accessToken Access Token + * @param expiresIn Validity period in seconds + */ + public void setAccessToken(String accessToken, Integer expiresIn) { + OAuth apiAuthorization = getAuthorization(OAuth.class); + apiAuthorization.setAccessToken(accessToken, expiresIn); + } + + /** + * Helper method to configure the oauth accessCode/implicit flow parameters + * @param clientId Client ID + * @param clientSecret Client secret + * @param redirectURI Redirect URI + */ + public void configureAuthorizationFlow(String clientId, String clientSecret, String redirectURI) { + throw new RuntimeException("Not implemented"); + } + + /** + * Configures a listener which is notified when a new access token is received. + * @param accessTokenListener Acesss token listener + */ + public void registerAccessTokenListener(AccessTokenListener accessTokenListener) { + OAuth apiAuthorization = getAuthorization(OAuth.class); + apiAuthorization.registerAccessTokenListener(accessTokenListener); + } + + {{/hasOAuthMethods}} + /** + * Gets request interceptor based on authentication name + * @param authName Authentiation name + * @return Request Interceptor + */ + public RequestInterceptor getAuthorization(String authName) { + return apiAuthorizations.get(authName); + } + + /** + * Adds an authorization to be used by the client + * @param authName Authentication name + * @param authorization Request interceptor + */ + public void addAuthorization(String authName, RequestInterceptor authorization) { + if (apiAuthorizations.containsKey(authName)) { + throw new RuntimeException("auth name \"" + authName + "\" already in api authorizations"); + } + apiAuthorizations.put(authName, authorization); + feignBuilder.requestInterceptor(authorization); + } + + private T getAuthorization(Class type) { + return (T) apiAuthorizations.values() + .stream() + .filter(requestInterceptor -> type.isAssignableFrom(requestInterceptor.getClass())) + .findFirst() + .orElseThrow(() -> new RuntimeException("No Oauth authentication or OAuth configured!")); + } +} diff --git a/.generator/templates/libraries/feign/EncodingUtils.mustache b/.generator/templates/libraries/feign/EncodingUtils.mustache new file mode 100644 index 00000000000..705eb6aa9d3 --- /dev/null +++ b/.generator/templates/libraries/feign/EncodingUtils.mustache @@ -0,0 +1,86 @@ +package {{invokerPackage}}; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** +* Utilities to support Swagger encoding formats in Feign. +*/ +public final class EncodingUtils { + + /** + * Private constructor. Do not construct this class. + */ + private EncodingUtils() {} + + /** + *

Encodes a collection of query parameters according to the Swagger + * collection format.

+ * + *

Of the various collection formats defined by Swagger ("csv", "tsv", + * etc), Feign only natively supports "multi". This utility generates the + * other format types so it will be properly processed by Feign.

+ * + *

Note, as part of reformatting, it URL encodes the parameters as + * well.

+ * @param parameters The collection object to be formatted. This object will + * not be changed. + * @param collectionFormat The Swagger collection format (eg, "csv", "tsv", + * "pipes"). See the + * + * OpenAPI Spec for more details. + * @return An object that will be correctly formatted by Feign. + */ + public static Object encodeCollection(Collection parameters, + String collectionFormat) { + if (parameters == null) { + return parameters; + } + List stringValues = new ArrayList<>(parameters.size()); + for (Object parameter : parameters) { + // ignore null values (same behavior as Feign) + if (parameter != null) { + stringValues.add(encode(parameter)); + } + } + // Feign natively handles single-element lists and the "multi" format. + if (stringValues.size() < 2 || "multi".equals(collectionFormat)) { + return stringValues; + } + // Otherwise return a formatted String + String[] stringArray = stringValues.toArray(new String[0]); + switch (collectionFormat) { + case "csv": + default: + return StringUtil.join(stringArray, ","); + case "ssv": + return StringUtil.join(stringArray, " "); + case "tsv": + return StringUtil.join(stringArray, "\t"); + case "pipes": + return StringUtil.join(stringArray, "|"); + } + } + + /** + * URL encode a single query parameter. + * @param parameter The query parameter to encode. This object will not be + * changed. + * @return The URL encoded string representation of the parameter. If the + * parameter is null, returns null. + */ + public static String encode(Object parameter) { + if (parameter == null) { + return null; + } + try { + return URLEncoder.encode(parameter.toString(), "UTF-8").replaceAll("\\+", "%20"); + } catch (UnsupportedEncodingException e) { + // Should never happen, UTF-8 is always supported + throw new RuntimeException(e); + } + } +} diff --git a/.generator/templates/libraries/feign/ParamExpander.mustache b/.generator/templates/libraries/feign/ParamExpander.mustache new file mode 100644 index 00000000000..2f5095d00f0 --- /dev/null +++ b/.generator/templates/libraries/feign/ParamExpander.mustache @@ -0,0 +1,22 @@ +package {{invokerPackage}}; + +import feign.Param; + +import java.text.DateFormat; +import java.util.Date; + +/** + * Param Expander to convert {@link Date} to RFC3339 + */ +public class ParamExpander implements Param.Expander { + + private static final DateFormat dateformat = new RFC3339DateFormat(); + + @Override + public String expand(Object value) { + if (value instanceof Date) { + return dateformat.format(value); + } + return value.toString(); + } +} diff --git a/.generator/templates/libraries/feign/README.mustache b/.generator/templates/libraries/feign/README.mustache new file mode 100644 index 00000000000..acab659406d --- /dev/null +++ b/.generator/templates/libraries/feign/README.mustache @@ -0,0 +1,77 @@ +# {{artifactId}} + +## Requirements + +Building the API client library requires [Maven](https://maven.apache.org/) to be installed. + +## Installation & Usage + +To install the API client library to your local Maven repository, simply execute: + +```shell +mvn install +``` + +To deploy it to a remote Maven repository instead, configure the settings of the repository and execute: + +```shell +mvn deploy +``` + +Refer to the [official documentation](https://maven.apache.org/plugins/maven-deploy-plugin/usage.html) for more information. + +After the client library is installed/deployed, you can use it in your Maven project by adding the following to your *pom.xml*: + +```xml + + {{groupId}} + {{artifactId}} + {{artifactVersion}} + compile + + +``` + +And to use the api you can follow the examples bellow: + +```java + + //Set bearer token manually + ApiClient apiClient = new ApiClient("petstore_auth_client"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + apiClient.setAccessToken("TOKEN", 10000); + + //Use api key + ApiClient apiClient = new ApiClient("api_key", "API KEY"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + + //Use http basic authentication + ApiClient apiClient = new ApiClient("basicAuth"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + apiClient.setCredentials("username", "password"); + + //Oauth password + ApiClient apiClient = new ApiClient("oauth_password"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + apiClient.setOauthPassword("username", "password", "client_id", "client_secret"); + + //Oauth client credentials flow + ApiClient apiClient = new ApiClient("oauth_client_credentials"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + apiClient.setClientCredentials("client_id", "client_secret"); + + PetApi petApi = apiClient.buildClient(PetApi.class); + Pet petById = petApi.getPetById(12345L); + + System.out.println(petById); + } +``` + +## 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/.generator/templates/libraries/feign/api.mustache b/.generator/templates/libraries/feign/api.mustache new file mode 100644 index 00000000000..df70b712737 --- /dev/null +++ b/.generator/templates/libraries/feign/api.mustache @@ -0,0 +1,105 @@ +package {{package}}; + +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.EncodingUtils; +{{#legacyDates}} +import {{invokerPackage}}.ParamExpander; +{{/legacyDates}} + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} +import feign.*; + +{{>generatedAnnotation}} +public interface {{classname}} extends ApiClient.Api { + +{{#operations}}{{#operation}} + /** + * {{summary}} + * {{notes}} +{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}} +{{/allParams}} +{{#returnType}} + * @return {{returnType}} +{{/returnType}} +{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation +{{/externalDocs}} + */ + @RequestLine("{{httpMethod}} {{{path}}}{{#hasQueryParams}}?{{/hasQueryParams}}{{#queryParams}}{{baseName}}={{=<% %>=}}{<%paramName%>}<%={{ }}=%>{{^-last}}&{{/-last}}{{/queryParams}}") + @Headers({ +{{#vendorExtensions.x-contentType}} "Content-Type: {{vendorExtensions.x-contentType}}", +{{/vendorExtensions.x-contentType}} "Accept: {{vendorExtensions.x-accepts}}",{{#headerParams}} + "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{^-last}}, + {{/-last}}{{/headerParams}} + }) + {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + {{#hasQueryParams}} + + /** + * {{summary}} + * {{notes}} + * Note, this is equivalent to the other {{operationId}} method, + * but with the query parameters collected into a single Map parameter. This + * is convenient for services with optional query parameters, especially when + * used with the {@link {{operationIdCamelCase}}QueryParams} class that allows for + * building up this map in a fluent style. + {{#allParams}} + {{^isQueryParam}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}} + {{/isQueryParam}} + {{/allParams}} + * @param queryParams Map of query parameters as name-value pairs + *

The following elements may be specified in the query map:

+ *
    + {{#queryParams}} + *
  • {{paramName}} - {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}
  • + {{/queryParams}} + *
+ {{#returnType}} + * @return {{returnType}} + {{/returnType}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + @RequestLine("{{httpMethod}} {{{path}}}?{{#queryParams}}{{baseName}}={{=<% %>=}}{<%paramName%>}<%={{ }}=%>{{^-last}}&{{/-last}}{{/queryParams}}") + @Headers({ +{{#vendorExtensions.x-contentType}} "Content-Type: {{vendorExtensions.x-contentType}}", +{{/vendorExtensions.x-contentType}} "Accept: {{vendorExtensions.x-accepts}}",{{#headerParams}} + "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{^-last}}, + {{/-last}}{{/headerParams}} + }) + {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isQueryParam}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}, {{/isQueryParam}}{{/allParams}}@QueryMap(encoded=true) Map queryParams); + + /** + * A convenience class for generating query parameters for the + * {{operationId}} method in a fluent style. + */ + public static class {{operationIdCamelCase}}QueryParams extends HashMap { + {{#queryParams}} + public {{operationIdCamelCase}}QueryParams {{paramName}}(final {{{dataType}}} value) { + {{#collectionFormat}} + put("{{baseName}}", EncodingUtils.encodeCollection(value, "{{collectionFormat}}")); + {{/collectionFormat}} + {{^collectionFormat}} + put("{{baseName}}", EncodingUtils.encode(value)); + {{/collectionFormat}} + return this; + } + {{/queryParams}} + } + {{/hasQueryParams}} + {{/operation}} +{{/operations}} +} diff --git a/.generator/templates/libraries/feign/api_test.mustache b/.generator/templates/libraries/feign/api_test.mustache new file mode 100644 index 00000000000..e9f9d055e02 --- /dev/null +++ b/.generator/templates/libraries/feign/api_test.mustache @@ -0,0 +1,70 @@ +package {{package}}; + +import {{invokerPackage}}.ApiClient; +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +class {{classname}}Test { + + private {{classname}} api; + + @BeforeEach + public void setup() { + api = new ApiClient().buildClient({{classname}}.class); + } + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + */ + @Test + void {{operationId}}Test() { + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + // {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + + // TODO: test validations + } + + {{#hasQueryParams}} + /** + * {{summary}} + * + * {{notes}} + * + * This tests the overload of the method that uses a Map for query parameters instead of + * listing them out individually. + */ + @Test + void {{operationId}}TestQueryMap() { + {{#allParams}} + {{^isQueryParam}} + {{{dataType}}} {{paramName}} = null; + {{/isQueryParam}} + {{/allParams}} + {{classname}}.{{operationIdCamelCase}}QueryParams queryParams = new {{classname}}.{{operationIdCamelCase}}QueryParams() + {{#queryParams}} + .{{paramName}}(null){{#-last}};{{/-last}} + {{/queryParams}} + // {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{^isQueryParam}}{{paramName}}, {{/isQueryParam}}{{/allParams}}queryParams); + + // TODO: test validations + } + {{/hasQueryParams}} + {{/operation}}{{/operations}} +} diff --git a/.generator/templates/libraries/feign/auth/ApiKeyAuth.mustache b/.generator/templates/libraries/feign/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..c03fe5c0bc0 --- /dev/null +++ b/.generator/templates/libraries/feign/auth/ApiKeyAuth.mustache @@ -0,0 +1,43 @@ +package {{invokerPackage}}.auth; + +import feign.RequestInterceptor; +import feign.RequestTemplate; + +public class ApiKeyAuth implements RequestInterceptor { + private final String location; + private final String paramName; + + private String apiKey; + + 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; + } + + @Override + public void apply(RequestTemplate template) { + if ("query".equals(location)) { + template.query(paramName, apiKey); + } else if ("header".equals(location)) { + template.header(paramName, apiKey); + } else if ("cookie".equals(location)) { + template.header("Cookie", String.format("%s=%s", paramName, apiKey)); + } + } +} diff --git a/.generator/templates/libraries/feign/auth/DefaultApi20Impl.mustache b/.generator/templates/libraries/feign/auth/DefaultApi20Impl.mustache new file mode 100644 index 00000000000..72b0a00495e --- /dev/null +++ b/.generator/templates/libraries/feign/auth/DefaultApi20Impl.mustache @@ -0,0 +1,47 @@ +package {{invokerPackage}}.auth; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor; +import com.github.scribejava.core.extractors.TokenExtractor; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignatureURIQueryParameter; +import com.github.scribejava.core.oauth2.clientauthentication.ClientAuthentication; +import com.github.scribejava.core.oauth2.clientauthentication.RequestBodyAuthenticationScheme; + +{{>generatedAnnotation}} +public class DefaultApi20Impl extends DefaultApi20 { + + private final String accessTokenEndpoint; + private final String authorizationBaseUrl; + + protected DefaultApi20Impl(String authorizationBaseUrl, String accessTokenEndpoint) { + this.authorizationBaseUrl = authorizationBaseUrl; + this.accessTokenEndpoint = accessTokenEndpoint; + } + + @Override + public String getAccessTokenEndpoint() { + return accessTokenEndpoint; + } + + @Override + protected String getAuthorizationBaseUrl() { + return authorizationBaseUrl; + } + + @Override + public BearerSignature getBearerSignature() { + return BearerSignatureURIQueryParameter.instance(); + } + + @Override + public ClientAuthentication getClientAuthentication() { + return RequestBodyAuthenticationScheme.instance(); + } + + @Override + public TokenExtractor getAccessTokenExtractor() { + return OAuth2AccessTokenJsonExtractor.instance(); + } +} \ No newline at end of file diff --git a/.generator/templates/libraries/feign/auth/HttpBasicAuth.mustache b/.generator/templates/libraries/feign/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..2b1acb8ff74 --- /dev/null +++ b/.generator/templates/libraries/feign/auth/HttpBasicAuth.mustache @@ -0,0 +1,41 @@ +package {{invokerPackage}}.auth; + +import feign.RequestInterceptor; +import feign.RequestTemplate; +import feign.auth.BasicAuthRequestInterceptor; + +/** + * An interceptor that adds the request header needed to use HTTP basic authentication. + */ +public class HttpBasicAuth implements RequestInterceptor { + + 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; + } + + public void setCredentials(String username, String password) { + this.username = username; + this.password = password; + } + + @Override + public void apply(RequestTemplate template) { + RequestInterceptor requestInterceptor = new BasicAuthRequestInterceptor(username, password); + requestInterceptor.apply(template); + } +} diff --git a/.generator/templates/libraries/feign/auth/HttpBearerAuth.mustache b/.generator/templates/libraries/feign/auth/HttpBearerAuth.mustache new file mode 100644 index 00000000000..2240a5518b5 --- /dev/null +++ b/.generator/templates/libraries/feign/auth/HttpBearerAuth.mustache @@ -0,0 +1,43 @@ +package {{invokerPackage}}.auth; + +import feign.RequestInterceptor; +import feign.RequestTemplate; + +/** + * An interceptor that adds the request header needed to use HTTP bearer authentication. + */ +public class HttpBearerAuth implements RequestInterceptor { + 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 Authorization header. + */ + public String getBearerToken() { + return bearerToken; + } + + /** + * Sets the token, which together with the scheme, will be sent as the value of the Authorization header. + */ + public void setBearerToken(String bearerToken) { + this.bearerToken = bearerToken; + } + + @Override + public void apply(RequestTemplate template) { + if(bearerToken == null) { + return; + } + + template.header("Authorization", (scheme != null ? upperCaseBearer(scheme) + " " : "") + bearerToken); + } + + private static String upperCaseBearer(String scheme) { + return ("bearer".equalsIgnoreCase(scheme)) ? "Bearer" : scheme; + } +} diff --git a/.generator/templates/libraries/feign/auth/OAuth.mustache b/.generator/templates/libraries/feign/auth/OAuth.mustache new file mode 100644 index 00000000000..864ee3fe3a5 --- /dev/null +++ b/.generator/templates/libraries/feign/auth/OAuth.mustache @@ -0,0 +1,81 @@ +package {{invokerPackage}}.auth; + +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth.OAuth20Service; +import feign.Request.HttpMethod; +import feign.RequestInterceptor; +import feign.RequestTemplate; +import feign.RetryableException; + +{{>generatedAnnotation}} +public abstract class OAuth implements RequestInterceptor { + + static final int MILLIS_PER_SECOND = 1000; + + public interface AccessTokenListener { + void notify(OAuth2AccessToken token); + } + + private volatile String accessToken; + private Long expirationTimeMillis; + private AccessTokenListener accessTokenListener; + + protected OAuth20Service service; + protected String scopes; + protected String authorizationUrl; + protected String tokenUrl; + + public OAuth(String authorizationUrl, String tokenUrl, String scopes) { + this.scopes = scopes; + this.authorizationUrl = authorizationUrl; + this.tokenUrl = tokenUrl; + } + + @Override + public void apply(RequestTemplate template) { + // If the request already have an authorization (eg. Basic auth), do nothing + if (template.headers().containsKey("Authorization")) { + return; + } + // If first time, get the token + if (expirationTimeMillis == null || System.currentTimeMillis() >= expirationTimeMillis) { + updateAccessToken(template); + } + if (getAccessToken() != null) { + template.header("Authorization", "Bearer " + getAccessToken()); + } + } + + private synchronized void updateAccessToken(RequestTemplate template) { + OAuth2AccessToken accessTokenResponse; + try { + accessTokenResponse = getOAuth2AccessToken(); + } catch (Exception e) { + throw new RetryableException(0, e.getMessage(), HttpMethod.POST, e, null, template.request()); + } + if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { + setAccessToken(accessTokenResponse.getAccessToken(), accessTokenResponse.getExpiresIn()); + if (accessTokenListener != null) { + accessTokenListener.notify(accessTokenResponse); + } + } + } + + abstract OAuth2AccessToken getOAuth2AccessToken(); + + abstract OAuthFlow getFlow(); + + public synchronized void registerAccessTokenListener(AccessTokenListener accessTokenListener) { + this.accessTokenListener = accessTokenListener; + } + + public synchronized String getAccessToken() { + return accessToken; + } + + public synchronized void setAccessToken(String accessToken, Integer expiresIn) { + this.accessToken = accessToken; + this.expirationTimeMillis = expiresIn == null ? null : System.currentTimeMillis() + expiresIn * MILLIS_PER_SECOND; + } + +} \ No newline at end of file diff --git a/.generator/templates/libraries/feign/auth/OauthClientCredentialsGrant.mustache b/.generator/templates/libraries/feign/auth/OauthClientCredentialsGrant.mustache new file mode 100644 index 00000000000..ef22c211637 --- /dev/null +++ b/.generator/templates/libraries/feign/auth/OauthClientCredentialsGrant.mustache @@ -0,0 +1,39 @@ +package {{invokerPackage}}.auth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; + +{{>generatedAnnotation}} +public class OauthClientCredentialsGrant extends OAuth { + + public OauthClientCredentialsGrant(String authorizationUrl, String tokenUrl, String scopes) { + super(authorizationUrl, tokenUrl, scopes); + } + + @Override + protected OAuth2AccessToken getOAuth2AccessToken() { + try { + return service.getAccessTokenClientCredentialsGrant(scopes); + } catch (Exception e) { + throw new RuntimeException("Failed to get oauth token", e); + } + } + + @Override + protected OAuthFlow getFlow() { + return OAuthFlow.application; + } + + /** + * Configures the client credentials flow + * + * @param clientId + * @param clientSecret + */ + public void configure(String clientId, String clientSecret) { + service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope(scopes) + .build(new DefaultApi20Impl(authorizationUrl, tokenUrl)); + } +} diff --git a/.generator/templates/libraries/feign/auth/OauthPasswordGrant.mustache b/.generator/templates/libraries/feign/auth/OauthPasswordGrant.mustache new file mode 100644 index 00000000000..870c3755a8b --- /dev/null +++ b/.generator/templates/libraries/feign/auth/OauthPasswordGrant.mustache @@ -0,0 +1,48 @@ +package {{invokerPackage}}.auth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; + +{{>generatedAnnotation}} +public class OauthPasswordGrant extends OAuth { + + private String username; + private String password; + + public OauthPasswordGrant(String tokenUrl, String scopes) { + super(null, tokenUrl, scopes); + } + + @Override + protected OAuth2AccessToken getOAuth2AccessToken() { + try { + return service.getAccessTokenPasswordGrant(username, password); + } catch (Exception e) { + throw new RuntimeException("Failed to get oauth token", e); + } + } + + @Override + protected OAuthFlow getFlow() { + return OAuthFlow.password; + } + + /** + * Configures Oauth password grant flow + * Note: this flow is deprecated. + * + * @param username + * @param password + * @param clientId + * @param clientSecret + */ + public void configure(String username, String password, String clientId, String clientSecret) { + this.username = username; + this.password = password; + //TODO the clientId and secret are optional according with the RFC + service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope(scopes) + .build(new DefaultApi20Impl(authorizationUrl, tokenUrl)); + } +} \ No newline at end of file diff --git a/.generator/templates/libraries/feign/build.gradle.mustache b/.generator/templates/libraries/feign/build.gradle.mustache new file mode 100644 index 00000000000..eda36125e37 --- /dev/null +++ b/.generator/templates/libraries/feign/build.gradle.mustache @@ -0,0 +1,151 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + maven { url "https://repo1.maven.org/maven2" } + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +test { + useJUnitPlatform() +} + +ext { + swagger_annotations_version = "1.5.24" + jackson_version = "2.10.3" + jackson_databind_version = "2.10.3" + {{#openApiNullable}} + jackson_databind_nullable_version = "0.2.1" + {{/openApiNullable}} + {{#threetenbp}} + jackson_threetenbp_version = "2.9.10" + {{/threetenbp}} + feign_version = "10.11" + feign_form_version = "3.8.0" + junit_version = "5.7.0" + scribejava_version = "8.0.0" +} + +dependencies { + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "io.github.openfeign:feign-core:$feign_version" + implementation "io.github.openfeign:feign-jackson:$feign_version" + implementation "io.github.openfeign:feign-slf4j:$feign_version" + implementation "io.github.openfeign:feign-okhttp:$feign_version" + implementation "io.github.openfeign.form:feign-form:$feign_form_version" + 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_databind_version" + {{#openApiNullable}} + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} + {{#joda}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + {{/joda}} + {{#java8}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{/java8}} + {{#threetenbp}} + implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threetenbp_version" + {{/threetenbp}} + implementation "com.brsanthu:migbase64:2.2" + implementation "com.github.scribejava:scribejava-core:$scribejava_version" + implementation "com.brsanthu:migbase64:2.2" + implementation 'javax.annotation:javax.annotation-api:1.3.2' + testImplementation "org.junit.jupiter:junit-jupiter:$junit_version" + testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit_version" + testImplementation "org.junit.jupiter:junit-jupiter-params:$junit_version" + testImplementation "com.github.tomakehurst:wiremock-jre8:2.27.2" + testImplementation "org.hamcrest:hamcrest:2.2" + testImplementation "commons-io:commons-io:2.8.0" + testImplementation "ch.qos.logback:logback-classic:1.2.3" +} diff --git a/.generator/templates/libraries/feign/build.sbt.mustache b/.generator/templates/libraries/feign/build.sbt.mustache new file mode 100644 index 00000000000..95745cdad26 --- /dev/null +++ b/.generator/templates/libraries/feign/build.sbt.mustache @@ -0,0 +1,34 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "io.swagger" % "swagger-annotations" % "1.5.24" % "compile", + "com.google.code.findbugs" % "jsr305" % "3.0.2" % "compile", + "io.github.openfeign" % "feign-core" % "10.11" % "compile", + "io.github.openfeign" % "feign-jackson" % "10.11" % "compile", + "io.github.openfeign" % "feign-slf4j" % "10.11" % "compile", + "io.github.openfeign.form" % "feign-form" % "3.8.0" % "compile", + "io.github.openfeign" % "feign-okhttp" % "10.11" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}" % "2.9.10" % "compile", + "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", + "com.github.scribejava" % "scribejava-core" % "8.0.0" % "compile", + "com.brsanthu" % "migbase64" % "2.2" % "compile", + "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", + "org.junit.jupiter" % "junit-jupiter" % "5.7.0" % "test", + "org.junit.jupiter" % "junit-jupiter-params" % "5.7.0" % "test", + "com.github.tomakehurst" % "wiremock-jre8" % "2.27.2" % "test", + "org.hamcrest" % "hamcrest" % "2.2" % "test", + "commons-io" % "commons-io" % "2.8.0" % "test", + "com.novocode" % "junit-interface" % "0.10" % "test" + ) + ) diff --git a/.generator/templates/libraries/feign/model_test.mustache b/.generator/templates/libraries/feign/model_test.mustache new file mode 100644 index 00000000000..0d75e120b09 --- /dev/null +++ b/.generator/templates/libraries/feign/model_test.mustache @@ -0,0 +1,48 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.jupiter.api.Test; + +{{#fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * Model tests for {{classname}} + */ +class {{classname}}Test { + {{#models}} + {{#model}} + {{^vendorExtensions.x-is-one-of-interface}} + {{^isEnum}} + private final {{classname}} model = new {{classname}}(); + + {{/isEnum}} + /** + * Model tests for {{classname}} + */ + @Test + void test{{classname}}() { + // TODO: test {{classname}} + } + + {{#allVars}} + /** + * Test the property '{{name}}' + */ + @Test + void {{name}}Test() { + // TODO: test {{name}} + } + + {{/allVars}} + {{/vendorExtensions.x-is-one-of-interface}} + {{/model}} + {{/models}} +} diff --git a/.generator/templates/libraries/feign/pom.mustache b/.generator/templates/libraries/feign/pom.mustache new file mode 100644 index 00000000000..65b3cc3c214 --- /dev/null +++ b/.generator/templates/libraries/feign/pom.mustache @@ -0,0 +1,379 @@ + + 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-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M4 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + 10 + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + true + 128m + 512m + + -Xlint:all + -J-Xss4m + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.1 + + none + 1.8 + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + + + io.github.openfeign + feign-core + ${feign-version} + + + io.github.openfeign + feign-jackson + ${feign-version} + + + io.github.openfeign + feign-slf4j + ${feign-version} + + + io.github.openfeign.form + feign-form + ${feign-form-version} + + + io.github.openfeign + feign-okhttp + ${feign-version} + + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-databind-version} + + {{#openApiNullable}} + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + + {{/openApiNullable}} + {{#withXml}} + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson-version} + + {{/withXml}} + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + {{/joda}} + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{/java8}} + {{#threetenbp}} + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-threetenbp-version} + + {{/threetenbp}} + + com.github.scribejava + scribejava-core + ${scribejava-version} + + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + + + + + ch.qos.logback + logback-classic + 1.2.3 + test + + + org.junit.jupiter + junit-jupiter + ${junit-version} + test + + + org.junit.jupiter + junit-jupiter-params + ${junit-version} + test + + + org.hamcrest + hamcrest + 2.2 + test + + + com.github.tomakehurst + wiremock-jre8 + 2.27.2 + test + + + commons-io + commons-io + 2.8.0 + test + + + + UTF-8 + 1.8 + ${java.version} + ${java.version} + 1.5.24 + 10.11 + 3.8.0 + 2.10.3 + {{#openApiNullable}} + 0.2.1 + {{/openApiNullable}} + 2.10.3 + {{#threetenbp}} + 2.9.10 + {{/threetenbp}} + 1.3.2 + 5.7.0 + 1.0.0 + 8.0.0 + + diff --git a/.generator/templates/libraries/google-api-client/ApiClient.mustache b/.generator/templates/libraries/google-api-client/ApiClient.mustache new file mode 100644 index 00000000000..aa91362ba13 --- /dev/null +++ b/.generator/templates/libraries/google-api-client/ApiClient.mustache @@ -0,0 +1,116 @@ +package {{invokerPackage}}; + +import {{apiPackage}}.*; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +{{#openApiNullable}} +import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} +{{#joda}} +import com.fasterxml.jackson.datatype.joda.JodaModule; +{{/joda}} +{{#java8}} +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{/java8}} +{{#threetenbp}} +import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; +{{/threetenbp}} +{{#threetenbp}} +import org.threeten.bp.*; +{{/threetenbp}} +import com.google.api.client.googleapis.util.Utils; +import com.google.api.client.http.AbstractHttpContent; +import com.google.api.client.http.HttpRequestFactory; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.HttpTransport; +import com.google.api.client.json.Json; + +import java.io.IOException; +import java.io.OutputStream; + +{{>generatedAnnotation}} +public class ApiClient { + private final String basePath; + private final HttpRequestFactory httpRequestFactory; + private final ObjectMapper objectMapper; + + private static final String defaultBasePath = "{{basePath}}"; + + // A reasonable default object mapper. Client can pass in a chosen ObjectMapper anyway, this is just for reasonable defaults. + private static ObjectMapper createDefaultObjectMapper() { + ObjectMapper objectMapper = new ObjectMapper() + .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) + .setDateFormat(new RFC3339DateFormat()); + {{#joda}} + objectMapper.registerModule(new JodaModule()); + {{/joda}} + {{#java8}} + objectMapper.registerModule(new JavaTimeModule()); + {{/java8}} + {{#threetenbp}} + ThreeTenModule module = new ThreeTenModule(); + module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); + module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); + module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); + objectMapper.registerModule(module); + {{/threetenbp}} + {{#openApiNullable}} + JsonNullableModule jnm = new JsonNullableModule(); + objectMapper.registerModule(jnm); + {{/openApiNullable}} + return objectMapper; + } + + public ApiClient() { + this(null, null, null, null); + } + + public ApiClient( + String basePath, + HttpTransport httpTransport, + HttpRequestInitializer initializer, + ObjectMapper objectMapper + ) { + this.basePath = basePath == null ? defaultBasePath : ( + basePath.endsWith("/") ? basePath.substring(0, basePath.length() - 1) : basePath + ); + this.httpRequestFactory = (httpTransport == null ? Utils.getDefaultTransport() : httpTransport).createRequestFactory(initializer); + this.objectMapper = (objectMapper == null ? createDefaultObjectMapper() : objectMapper); + } + + public HttpRequestFactory getHttpRequestFactory() { + return httpRequestFactory; + } + + public String getBasePath() { + return basePath; + } + + public ObjectMapper getObjectMapper() { + return objectMapper; + } + + public class JacksonJsonHttpContent extends AbstractHttpContent { + /* A POJO that can be serialized with a com.fasterxml Jackson ObjectMapper */ + private final Object data; + + public JacksonJsonHttpContent(Object data) { + super(Json.MEDIA_TYPE); + this.data = data; + } + + @Override + public void writeTo(OutputStream out) throws IOException { + objectMapper.writeValue(out, data); + } + } + + // Builder pattern to get API instances for this client. + {{#apiInfo}}{{#apis}} + public {{classname}} {{classVarName}}Api() { + return new {{classname}}(this); + } + {{/apis}}{{/apiInfo}} +} diff --git a/.generator/templates/libraries/google-api-client/api.mustache b/.generator/templates/libraries/google-api-client/api.mustache new file mode 100644 index 00000000000..2cd0f49badd --- /dev/null +++ b/.generator/templates/libraries/google-api-client/api.mustache @@ -0,0 +1,190 @@ +package {{package}}; + +import {{invokerPackage}}.ApiClient; + +{{#imports}}import {{import}}; +{{/imports}} + +import com.fasterxml.jackson.core.type.TypeReference; +import com.google.api.client.http.EmptyContent; +import com.google.api.client.http.GenericUrl; +import com.google.api.client.http.HttpContent; +import com.google.api.client.http.InputStreamContent; +import com.google.api.client.http.HttpMethods; +import com.google.api.client.http.HttpResponse; +import com.google.api.client.json.Json; + +import javax.ws.rs.core.UriBuilder; +import java.io.IOException; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.List; +import java.util.ArrayList; + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}} { + private ApiClient apiClient; + + public {{classname}}() { + this(new ApiClient()); + } + + public {{classname}}(ApiClient apiClient) { + this.apiClient = apiClient; + } + + public ApiClient getApiClient() { + return apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.apiClient = apiClient; + } + + {{#operation}} + /**{{#summary}} + * {{summary}}{{/summary}}{{#notes}} + * {{notes}}{{/notes}}{{#responses}} + *

{{code}}{{#message}} - {{message}}{{/message}}{{/responses}}{{#allParams}} + * @param {{paramName}} {{description}}{{^description}}The {{paramName}} parameter{{/description}}{{/allParams}}{{#returnType}} + * @return {{returnType}}{{/returnType}} + * @throws IOException if an error occurs while attempting to invoke the API{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + + **/ + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws IOException { + {{#returnType}}HttpResponse response = {{/returnType}}{{operationId}}ForHttpResponse({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}} + TypeReference<{{{returnType}}}> typeRef = new TypeReference<{{{returnType}}}>() {}; + return apiClient.getObjectMapper().readValue(response.getContent(), typeRef);{{/returnType}} + } + + /**{{#summary}} + * {{summary}}{{/summary}}{{#notes}} + * {{notes}}{{/notes}}{{#responses}} + *

{{code}}{{#message}} - {{message}}{{/message}}{{/responses}}{{#requiredParams}} + * @param {{paramName}} {{description}}{{^description}}The {{paramName}} parameter{{/description}}{{/requiredParams}} + * @param params Map of query params. A collection will be interpreted as passing in multiple instances of the same query param.{{#returnType}} + * @return {{returnType}}{{/returnType}} + * @throws IOException if an error occurs while attempting to invoke the API{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + + **/ + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#bodyParam}}{{^required}}{{{dataType}}} {{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}Map params) throws IOException { + {{#returnType}}HttpResponse response = {{/returnType}}{{operationId}}ForHttpResponse({{#bodyParam}}{{^required}}{{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}params);{{#returnType}} + TypeReference<{{{returnType}}}> typeRef = new TypeReference<{{{returnType}}}>() {}; + return apiClient.getObjectMapper().readValue(response.getContent(), typeRef);{{/returnType}} + } + + public HttpResponse {{operationId}}ForHttpResponse({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws IOException { + {{#allParams}}{{#required}}// verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new IllegalArgumentException("Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + }{{/required}}{{/allParams}} + {{#hasPathParams}} + // create a map of path variables + final Map uriVariables = new HashMap();{{#pathParams}} + uriVariables.put("{{baseName}}", {{{paramName}}});{{/pathParams}} + {{/hasPathParams}} + UriBuilder uriBuilder = UriBuilder.fromUri(apiClient.getBasePath() + "{{{path}}}");{{#hasQueryParams}} + {{#queryParams}} + if ({{paramName}} != null) { + String key = "{{baseName}}"; + Object value = {{paramName}}; + if (value instanceof Collection) { + uriBuilder = uriBuilder.queryParam(key, ((Collection) value).toArray()); + } else if (value instanceof Object[]) { + uriBuilder = uriBuilder.queryParam(key, (Object[]) value); + } else { + uriBuilder = uriBuilder.queryParam(key, value); + } + }{{/queryParams}}{{/hasQueryParams}} + + String localVarUrl = uriBuilder{{#hasPathParams}}.buildFromMap(uriVariables).toString();{{/hasPathParams}}{{^hasPathParams}}.build().toString();{{/hasPathParams}} + GenericUrl genericUrl = new GenericUrl(localVarUrl); + + HttpContent content = {{#isBodyAllowed}}{{#bodyParam}}apiClient.new JacksonJsonHttpContent({{paramName}}){{/bodyParam}}{{^bodyParam}}new EmptyContent(){{/bodyParam}}{{/isBodyAllowed}}{{^isBodyAllowed}}null{{/isBodyAllowed}}; + return apiClient.getHttpRequestFactory().buildRequest(HttpMethods.{{httpMethod}}, genericUrl, content).execute(); + }{{#bodyParam}} + + public HttpResponse {{operationId}}ForHttpResponse({{#allParams}}{{#isBodyParam}}java.io.InputStream {{paramName}}{{/isBodyParam}}{{^isBodyParam}}{{{dataType}}} {{paramName}}{{/isBodyParam}}{{^-last}}, {{/-last}}{{/allParams}}, String mediaType) throws IOException { + {{#allParams}}{{#required}}// verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new IllegalArgumentException("Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + }{{/required}}{{/allParams}} + {{#hasPathParams}} + // create a map of path variables + final Map uriVariables = new HashMap();{{#pathParams}} + uriVariables.put("{{baseName}}", {{{paramName}}});{{/pathParams}} + {{/hasPathParams}} + UriBuilder uriBuilder = UriBuilder.fromUri(apiClient.getBasePath() + "{{{path}}}");{{#hasQueryParams}} + {{#queryParams}} + if ({{paramName}} != null) { + String key = "{{baseName}}"; + Object value = {{paramName}}; + if (value instanceof Collection) { + uriBuilder = uriBuilder.queryParam(key, ((Collection) value).toArray()); + } else if (value instanceof Object[]) { + uriBuilder = uriBuilder.queryParam(key, (Object[]) value); + } else { + uriBuilder = uriBuilder.queryParam(key, value); + } + }{{/queryParams}}{{/hasQueryParams}} + + String localVarUrl = uriBuilder{{#hasPathParams}}.buildFromMap(uriVariables).toString();{{/hasPathParams}}{{^hasPathParams}}.build().toString();{{/hasPathParams}} + GenericUrl genericUrl = new GenericUrl(localVarUrl); + + HttpContent content = {{#bodyParam}}{{paramName}} == null ? + apiClient.new JacksonJsonHttpContent(null) : + new InputStreamContent(mediaType == null ? Json.MEDIA_TYPE : mediaType, {{paramName}}){{/bodyParam}}; + return apiClient.getHttpRequestFactory().buildRequest(HttpMethods.{{httpMethod}}, genericUrl, content).execute(); + }{{/bodyParam}} + + public HttpResponse {{operationId}}ForHttpResponse({{#bodyParam}}{{^required}}{{{dataType}}} {{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}Map params) throws IOException { + {{#allParams}}{{#required}}// verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new IllegalArgumentException("Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + }{{/required}}{{/allParams}} + {{#hasPathParams}} + // create a map of path variables + final Map uriVariables = new HashMap();{{#pathParams}} + uriVariables.put("{{baseName}}", {{{paramName}}});{{/pathParams}} + {{/hasPathParams}} + UriBuilder uriBuilder = UriBuilder.fromUri(apiClient.getBasePath() + "{{{path}}}"); + + // Copy the params argument if present, to allow passing in immutable maps + Map allParams = params == null ? new HashMap() : new HashMap(params);{{#queryParams}}{{#required}} + // Add the required query param '{{paramName}}' to the map of query params + allParams.put("{{paramName}}", {{paramName}});{{/required}}{{/queryParams}} + + for (Map.Entry entry: allParams.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + + if (key != null && value != null) { + if (value instanceof Collection) { + uriBuilder = uriBuilder.queryParam(key, ((Collection) value).toArray()); + } else if (value instanceof Object[]) { + uriBuilder = uriBuilder.queryParam(key, (Object[]) value); + } else { + uriBuilder = uriBuilder.queryParam(key, value); + } + } + } + + String localVarUrl = uriBuilder{{#hasPathParams}}.buildFromMap(uriVariables).toString();{{/hasPathParams}}{{^hasPathParams}}.build().toString();{{/hasPathParams}} + GenericUrl genericUrl = new GenericUrl(localVarUrl); + + HttpContent content = {{#isBodyAllowed}}{{#bodyParam}}apiClient.new JacksonJsonHttpContent({{paramName}}){{/bodyParam}}{{^bodyParam}}new EmptyContent(){{/bodyParam}}{{/isBodyAllowed}}{{^isBodyAllowed}}null{{/isBodyAllowed}}; + return apiClient.getHttpRequestFactory().buildRequest(HttpMethods.{{httpMethod}}, genericUrl, content).execute(); + } + + + {{/operation}} +} +{{/operations}} diff --git a/.generator/templates/libraries/google-api-client/api_test.mustache b/.generator/templates/libraries/google-api-client/api_test.mustache new file mode 100644 index 00000000000..56b7c1897d1 --- /dev/null +++ b/.generator/templates/libraries/google-api-client/api_test.mustache @@ -0,0 +1,45 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Test; +import org.junit.Ignore; + +import java.io.IOException; +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +@Ignore +public class {{classname}}Test { + + private final {{classname}} api = new {{classname}}(); + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + * + * @throws IOException + * if the Api call fails + */ + @Test + public void {{operationId}}Test() throws IOException { + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + + // TODO: test validations + } + {{/operation}}{{/operations}} +} diff --git a/.generator/templates/libraries/google-api-client/build.gradle.mustache b/.generator/templates/libraries/google-api-client/build.gradle.mustache new file mode 100644 index 00000000000..6be8600c7da --- /dev/null +++ b/.generator/templates/libraries/google-api-client/build.gradle.mustache @@ -0,0 +1,152 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + maven { url "https://repo1.maven.org/maven2" } + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.5.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 23 + buildToolsVersion '23.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 22 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + {{#java8}} + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + {{/java8}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + swagger_annotations_version = "1.5.22" + jackson_version = "2.12.1" + jackson_databind_version = "2.10.5.1" + {{#openApiNullable}} + jackson_databind_nullable_version = "0.2.1" + {{/openApiNullable}} + google_api_client_version = "1.23.0" + jersey_common_version = "2.25.1" + jodatime_version = "2.9.9" + junit_version = "4.13.1" + {{#threetenbp}} + jackson_threeten_version = "2.9.10" + {{/threetenbp}} +} + +dependencies { + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "com.google.api-client:google-api-client:${google_api_client_version}" + implementation "org.glassfish.jersey.core:jersey-common:${jersey_common_version}" + 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_databind_version" + implementation "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + {{#openApiNullable}} + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} + {{#java8}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{/java8}} + {{#joda}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + implementation "joda-time:joda-time:$jodatime_version" + {{/joda}} + {{#threetenbp}} + implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threeten_version" + {{/threetenbp}} + {{#withXml}} + implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version" + {{/withXml}} + implementation 'javax.annotation:javax.annotation-api:1.3.2' + testImplementation "junit:junit:$junit_version" +} diff --git a/.generator/templates/libraries/google-api-client/build.sbt.mustache b/.generator/templates/libraries/google-api-client/build.sbt.mustache new file mode 100644 index 00000000000..be30ae48caf --- /dev/null +++ b/.generator/templates/libraries/google-api-client/build.sbt.mustache @@ -0,0 +1,34 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "io.swagger" % "swagger-annotations" % "1.5.22", + "com.google.api-client" % "google-api-client" % "1.23.0", + "org.glassfish.jersey.core" % "jersey-common" % "2.25.1", + "com.fasterxml.jackson.core" % "jackson-core" % "2.12.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.5.1" % "compile", + {{#withXml}} + "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.9.10" % "compile", + {{/withXml}} + {{#joda}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile", + {{/joda}} + {{#java8}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile", + {{/java8}} + {{#threetenbp}} + "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", + {{/threetenbp}} + "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", + "junit" % "junit" % "4.13.1" % "test", + "com.novocode" % "junit-interface" % "0.10" % "test" + ) + ) diff --git a/.generator/templates/libraries/google-api-client/pom.mustache b/.generator/templates/libraries/google-api-client/pom.mustache new file mode 100644 index 00000000000..fdcb6953faf --- /dev/null +++ b/.generator/templates/libraries/google-api-client/pom.mustache @@ -0,0 +1,335 @@ + + 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-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + {{#java8}} + 1.8 + 1.8 + {{/java8}} + {{^java8}} + 1.7 + 1.7 + {{/java8}} + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.1 + + none + {{#java8}} + 1.8 + {{/java8}} + {{^java8}} + 1.7 + {{/java8}} + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + + com.google.api-client + google-api-client + ${google-api-client-version} + + + + org.glassfish.jersey.core + jersey-common + ${jersey-common-version} + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + {{#openApiNullable}} + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + + {{/openApiNullable}} + {{#withXml}} + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson-version} + + {{/withXml}} + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{/java8}} + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + + joda-time + joda-time + ${jodatime-version} + + {{/joda}} + {{#threetenbp}} + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-threetenbp-version} + + {{/threetenbp}} + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + + + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.5.22 + 1.30.2 + 2.25.1 + 2.12.1 + 2.10.4 + {{#openApiNullable}} + 0.2.1 + {{/openApiNullable}} + {{#joda}} + 2.9.9 + {{/joda}} + {{#threetenbp}} + 2.9.10 + {{/threetenbp}} + 1.3.2 + 1.0.0 + 4.13.1 + + diff --git a/.generator/templates/libraries/jersey2/AbstractOpenApiSchema.mustache b/.generator/templates/libraries/jersey2/AbstractOpenApiSchema.mustache new file mode 100644 index 00000000000..6eb87a90b9b --- /dev/null +++ b/.generator/templates/libraries/jersey2/AbstractOpenApiSchema.mustache @@ -0,0 +1,138 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.model; + +import {{invokerPackage}}.ApiException; +import java.util.Objects; +import java.lang.reflect.Type; +import java.util.Map; +import javax.ws.rs.core.GenericType; + +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Abstract class for oneOf,anyOf schemas defined in OpenAPI spec + */ +{{>additionalModelTypeAnnotations}}{{>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 + */ + @JsonValue + 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) { + if (o == null) { + return "null"; + } + return 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 nullalble + * + * @return true if it's nullable + */ + public Boolean isNullable() { + if (Boolean.TRUE.equals(isNullable)) { + return Boolean.TRUE; + } else { + return Boolean.FALSE; + } + } + +{{>libraries/jersey2/additional_properties}} + +} diff --git a/.generator/templates/libraries/jersey2/ApiClient.mustache b/.generator/templates/libraries/jersey2/ApiClient.mustache new file mode 100644 index 00000000000..5c3f0de8fa3 --- /dev/null +++ b/.generator/templates/libraries/jersey2/ApiClient.mustache @@ -0,0 +1,1375 @@ +package {{invokerPackage}}; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.Form; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +{{#hasOAuthMethods}} +import com.github.scribejava.core.model.OAuth2AccessToken; +{{/hasOAuthMethods}} +import org.glassfish.jersey.client.ClientConfig; +import org.glassfish.jersey.client.ClientProperties; +import org.glassfish.jersey.client.HttpUrlConnectorProvider; +import org.glassfish.jersey.jackson.JacksonFeature; +import org.glassfish.jersey.media.multipart.FormDataBodyPart; +import org.glassfish.jersey.media.multipart.FormDataContentDisposition; +import org.glassfish.jersey.media.multipart.MultiPart; +import org.glassfish.jersey.media.multipart.MultiPartFeature; + +import java.io.IOException; +import java.io.InputStream; + +import java.net.URI; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.security.cert.X509Certificate; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import org.glassfish.jersey.logging.LoggingFeature; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Map.Entry; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Set; +import java.util.Date; +import java.util.Properties; +{{#jsr310}} +{{#threetenbp}} +import org.threeten.bp.OffsetDateTime; +{{/threetenbp}} +{{^threetenbp}} +import java.time.OffsetDateTime; +{{/threetenbp}} +{{/jsr310}} + +import java.net.URLEncoder; + +import java.io.File; +import java.io.UnsupportedEncodingException; + +import java.text.DateFormat; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import {{invokerPackage}}.auth.Authentication; +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.HttpBearerAuth; +{{#hasHttpSignatureMethods}} +import {{invokerPackage}}.auth.HttpSignatureAuth; +{{/hasHttpSignatureMethods}} +import {{invokerPackage}}.auth.ApiKeyAuth; +{{#hasOAuthMethods}} +import {{invokerPackage}}.auth.OAuth; +{{/hasOAuthMethods}} + +{{>generatedAnnotation}} +public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { + protected Map defaultHeaderMap = new HashMap(); + protected Map defaultCookieMap = new HashMap(); + protected String basePath = "{{{basePath}}}"; + protected String userAgent; + private static final Logger log = Logger.getLogger(ApiClient.class.getName()); + + 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 Map> operationServers = new HashMap>() {{ + {{#apiInfo}} + {{#apis}} + {{#operations}} + {{#operation}} + {{#servers}} + {{#-first}} + put("{{{classname}}}.{{{operationId}}}", new ArrayList(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}} + {{/operation}} + {{/operations}} + {{/apis}} + {{/apiInfo}} + }}; + protected Map operationServerIndex = new HashMap(); + protected Map> operationServerVariables = new HashMap>(); + protected boolean debugging = false; + protected ClientConfig clientConfig; + protected int connectionTimeout = 0; + private int readTimeout = 0; + + protected Client httpClient; + protected JSON json; + protected String tempFolderPath = null; + + protected Map authentications; + protected Map authenticationLookup; + + protected DateFormat dateFormat; + protected final Map unstableOperations = new HashMap() {{ + {{#apiInfo}} + {{#apis}} + {{#operations}} + {{#operation}} + {{#vendorExtensions.x-unstable}} + put("{{operationId}}", false); + {{/vendorExtensions.x-unstable}} + {{/operation}} + {{/operations}} + {{/apis}} + {{/apiInfo}} + }}; + protected static final java.util.logging.Logger logger = java.util.logging.Logger.getLogger(ApiClient.class.getName()); + + /** + * Constructs a new ApiClient with default parameters. + */ + public ApiClient() { + this(null); + } + + /** + * Constructs a new ApiClient with the specified authentication parameters. + * + * @param authMap A hash map containing authentication parameters. + */ + public ApiClient(Map authMap) { + json = new JSON(); + httpClient = buildHttpClient(); + + this.dateFormat = new RFC3339DateFormat(); + + // Set default User-Agent. + setUserAgent(); + + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap(); + Authentication auth = null; + {{#authMethods}} + if (authMap != null) { + auth = authMap.get("{{name}}"); + } + {{#isBasic}} + {{#isBasicBasic}} + if (auth instanceof HttpBasicAuth) { + authentications.put("{{name}}", auth); + } else { + authentications.put("{{name}}", new HttpBasicAuth()); + } + {{/isBasicBasic}} + {{#isBasicBearer}} + if (auth instanceof HttpBearerAuth) { + authentications.put("{{name}}", auth); + } else { + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}")); + } + {{/isBasicBearer}} + {{#isHttpSignature}} + if (auth instanceof HttpSignatureAuth) { + authentications.put("{{name}}", auth); + } + {{/isHttpSignature}} + {{/isBasic}} + {{#isApiKey}} + if (auth instanceof ApiKeyAuth) { + authentications.put("{{name}}", auth); + } else { + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}")); + } + {{/isApiKey}} + {{#isOAuth}} + if (auth instanceof OAuth) { + authentications.put("{{name}}", auth); + } else { + authentications.put("{{name}}", new OAuth(basePath, "{{tokenUrl}}")); + } + {{/isOAuth}} + {{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + + // Setup authentication lookup (key: authentication alias, value: authentication name) + authenticationLookup = new HashMap();{{#authMethods}}{{#vendorExtensions.x-auth-id-alias}} + authenticationLookup.put("{{name}}", "{{.}}");{{/vendorExtensions.x-auth-id-alias}}{{/authMethods}} + } + + /** + * Gets the JSON instance to do JSON serialization and deserialization. + * + * @return JSON + */ + public JSON getJSON() { + return json; + } + + public Client getHttpClient() { + return httpClient; + } + + public ApiClient setHttpClient(Client httpClient) { + this.httpClient = httpClient; + return this; + } + + /** + * Returns the base URL to the location where the OpenAPI document is being served. + * + * @return The base URL to the target host. + */ + public String getBasePath() { + return basePath; + } + + /** + * Sets the base URL to the location where the OpenAPI document is being served. + * + * @param basePath The base URL to the target host. + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + {{#hasOAuthMethods}} + setOauthBasePath(basePath); + {{/hasOAuthMethods}} + return this; + } + + public List getServers() { + return servers; + } + + public ApiClient setServers(List servers) { + this.servers = servers; + updateBasePath(); + return this; + } + + public Integer getServerIndex() { + return serverIndex; + } + + public ApiClient setServerIndex(Integer serverIndex) { + this.serverIndex = serverIndex; + updateBasePath(); + return this; + } + + public Map getServerVariables() { + return serverVariables; + } + + public ApiClient setServerVariables(Map serverVariables) { + this.serverVariables = serverVariables; + updateBasePath(); + return this; + } + + private void updateBasePath() { + if (serverIndex != null) { + setBasePath(servers.get(serverIndex).URL(serverVariables)); + } + } + + {{#hasOAuthMethods}} + private void setOauthBasePath(String basePath) { + for(Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setBasePath(basePath); + } + } + } + + {{/hasOAuthMethods}} + /** + * Get authentications (key: authentication name, value: authentication). + * + * @return Map of authentication object + */ + 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); + } + + /** + * Helper method to set username for the first HTTP basic authentication. + * + * @param username Username + */ + public ApiClient setUsername(String username) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setUsername(username); + return this; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set password for the first HTTP basic authentication. + * + * @param password Password + */ + public ApiClient setPassword(String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setPassword(password); + return this; + } + } + 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 ApiClient setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return this; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to configure authentications which respects aliases of API keys. + * + * @param secrets Hash map from authentication name to its secret. + */ + public ApiClient configureApiKeys(Map secrets) { + for (Map.Entry authEntry : authentications.entrySet()) { + Authentication auth = authEntry.getValue(); + if (auth instanceof ApiKeyAuth) { + String name = authEntry.getKey(); + // respect x-auth-id-alias property + name = authenticationLookup.containsKey(name) ? authenticationLookup.get(name) : name; + if (secrets.containsKey(name)) { + ((ApiKeyAuth) auth).setApiKey(secrets.get(name)); + } + } + } + return this; + } + + /** + * Helper method to set API key prefix for the first API key authentication. + * + * @param apiKeyPrefix API key prefix + */ + public ApiClient setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return this; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set bearer token for the first Bearer authentication. + * + * @param bearerToken Bearer token + */ + public ApiClient setBearerToken(String bearerToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBearerAuth) { + ((HttpBearerAuth) auth).setBearerToken(bearerToken); + return this; + } + } + throw new RuntimeException("No Bearer authentication configured!"); + } + + + {{#hasOAuthMethods}} + /** + * Helper method to set access token for the first OAuth2 authentication. + * @param accessToken Access token + */ + public ApiClient setAccessToken(String accessToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setAccessToken(accessToken); + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Helper method to set the credentials for the first OAuth2 authentication. + * + * @param clientId the client ID + * @param clientSecret the client secret + */ + public ApiClient setOauthCredentials(String clientId, String clientSecret) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setCredentials(clientId, clientSecret, isDebugging()); + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Helper method to set the password flow for the first OAuth2 authentication. + * + * @param username the user name + * @param password the user password + */ + public ApiClient setOauthPasswordFlow(String username, String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).usePasswordFlow(username, password); + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Helper method to set the authorization code flow for the first OAuth2 authentication. + * + * @param code the authorization code + */ + public ApiClient setOauthAuthorizationCodeFlow(String code) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).useAuthorizationCodeFlow(code); + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Helper method to set the scopes for the first OAuth2 authentication. + * + * @param scope the oauth scope + */ + public ApiClient setOauthScope(String scope) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setScope(scope); + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + {{/hasOAuthMethods}} + /** + * Set the User-Agent header's value (by adding to the default header map). + * @param userAgent Http user agent + * @return API client + */ + public ApiClient setUserAgent(String userAgent) { + userAgent = userAgent; + addDefaultHeader("User-Agent", userAgent); + return this; + } + + /** + * Get the User-Agent header's value. + * @return User-Agent string + */ + public String getUserAgent(){ + return userAgent; + } + + /** + * Set the default User-Agent header's value with telemetry information (by adding to the default header map). + * @return API client + */ + public ApiClient setUserAgent() { + final Properties properties = new Properties(); + try { + properties.load(getClass().getClassLoader().getResourceAsStream("com/datadog/api/project.properties")); + } catch (IOException e) { + logger.severe("Could not load client version: " + e.toString()); + } + + String userAgent = "datadog-api-client-java/" + properties.getProperty("version") + + " (" + + "java " + System.getProperty("java.version") + "; " + + "java_vendor " + System.getProperty("java.vendor") + "; " + + "os " + System.getProperty("os.name") + "; " + + "os_version " + System.getProperty("os.version") + "; " + + "arch " + System.getProperty("os.arch") + + ")"; + addDefaultHeader("User-Agent", userAgent); + this.userAgent = userAgent; + return this; + } + + /** + * Add a default header. + * + * @param key The header's key + * @param value The header's value + * @return API client + */ + 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 API client + */ + public ApiClient addDefaultCookie(String key, String value) { + defaultCookieMap.put(key, value); + return this; + } + + /** + * Gets the client config. + * @return Client config + */ + public ClientConfig getClientConfig() { + return clientConfig; + } + + /** + * Set the client config. + * + * @param clientConfig Set the client config + * @return API client + */ + public ApiClient setClientConfig(ClientConfig clientConfig) { + this.clientConfig = clientConfig; + // Rebuild HTTP Client according to the new "clientConfig" value. + this.httpClient = buildHttpClient(); + return this; + } + + /** + * Check that whether debugging is enabled for this API client. + * @return True if debugging is switched on + */ + public boolean isDebugging() { + return debugging; + } + + /** + * Enable/disable debugging for this API client. + * + * @param debugging To enable (true) or disable (false) debugging + * @return API client + */ + public ApiClient setDebugging(boolean debugging) { + this.debugging = debugging; + // Rebuild HTTP Client according to the new "debugging" value. + this.httpClient = buildHttpClient(); + return this; + } + + /** + * Set temp folder path + * @param tempFolderPath Temp folder path + * @return API client + */ + public ApiClient setTempFolderPath(String tempFolderPath) { + this.tempFolderPath = tempFolderPath; + return this; + } + + /** + * Connect timeout (in milliseconds). + * @return Connection timeout + */ + public int getConnectTimeout() { + return connectionTimeout; + } + + /** + * Set the connect timeout (in milliseconds). + * A value of 0 means no timeout, otherwise values must be between 1 and + * {@link Integer#MAX_VALUE}. + * @param connectionTimeout Connection timeout in milliseconds + * @return API client + */ + public ApiClient setConnectTimeout(int connectionTimeout) { + this.connectionTimeout = connectionTimeout; + httpClient.property(ClientProperties.CONNECT_TIMEOUT, connectionTimeout); + return this; + } + + /** + * read timeout (in milliseconds). + * @return Read timeout + */ + public int getReadTimeout() { + return readTimeout; + } + + /** + * Set the read timeout (in milliseconds). + * A value of 0 means no timeout, otherwise values must be between 1 and + * {@link Integer#MAX_VALUE}. + * @param readTimeout Read timeout in milliseconds + * @return API client + */ + public ApiClient setReadTimeout(int readTimeout) { + this.readTimeout = readTimeout; + httpClient.property(ClientProperties.READ_TIMEOUT, readTimeout); + return this; + } + + /** + * Get the date format used to parse/format date parameters. + * @return Date format + */ + public DateFormat getDateFormat() { + return dateFormat; + } + + /** + * Set the date format used to parse/format date parameters. + * @param dateFormat Date format + * @return API client + */ + public ApiClient setDateFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + // also set the date format for model (de)serialization with Date properties + this.json.setDateFormat((DateFormat) dateFormat.clone()); + return this; + } + + /** + * Get list of all unstable operations + * @return set of all unstable operations Ids + */ + public Set getUnstableOperations() { + return unstableOperations.keySet(); + } + + /** + * Mark an unstable operation as enabled/disabled. + * @param operation operation Id - this is the name of the method on the API class, e.g. "createFoo" + * @param enabled whether to mark the operation as enabled (true) or disabled (false) + * @return true if the operation is marked as unstable and thus was enabled/disabled, false otherwise + */ + public boolean setUnstableOperationEnabled(String operation, boolean enabled) { + if (unstableOperations.containsKey(operation)) { + unstableOperations.put(operation, enabled); + return true; + } + logger.warning(String.format("'%s' is not an unstable operation, can't enable/disable", operation)); + return false; + } + + /** + * Determine whether an operation is an unstable operation. + * @param operation operation Id - this is the name of the method on the API class, e.g. "createFoo" + * @return true if the operation is an unstable operation, false otherwise + */ + public boolean isUnstableOperation(String operation) { + return unstableOperations.containsKey(operation); + } + + /** + * Determine whether an unstable operation is enabled. + * @param operation operation Id - this is the name of the method on the API class, e.g. "createFoo" + * @return true if the operation is unstable and it is enabled, false otherwise + */ + public boolean isUnstableOperationEnabled(String operation) { + if (unstableOperations.containsKey(operation)) { + return unstableOperations.get(operation); + } else { + logger.warning(String.format("'%s' is not an unstable operation, is always enabled", operation)); + return true; + } + } + + /** + * Get the ApiClient logger + * @return ApiClient logger + */ + public java.util.logging.Logger getLogger() { + return logger; + } + + /** + * Parse the given string into Date object. + * @param str String + * @return Date + */ + public Date parseDate(String str) { + try { + return dateFormat.parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(e); + } + } + + /** + * Format the given Date object into string. + * @param date Date + * @return Date in string format + */ + public String formatDate(Date date) { + return dateFormat.format(date); + } + + /** + * Format the given parameter object into string. + * @param param Object + * @return Object in string format + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date) { + return formatDate((Date) param); + } {{#jsr310}}else if (param instanceof OffsetDateTime) { + return formatOffsetDateTime((OffsetDateTime) param); + } {{/jsr310}}else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for(Object o : (Collection)param) { + if(b.length() > 0) { + b.append(','); + } + b.append(String.valueOf(o)); + } + return b.toString(); + } else { + return String.valueOf(param); + } + } + + /* + * Format to {@code Pair} objects. + * @param collectionFormat Collection format + * @param name Name + * @param value Value + * @return List of pairs + */ + public List parameterToPairs(String collectionFormat, String name, Object value){ + List params = new ArrayList(); + + // preconditions + if (name == null || name.isEmpty() || value == null) return params; + + Collection valueCollection; + if (value instanceof Collection) { + valueCollection = (Collection) value; + } else { + params.add(new Pair(name, parameterToString(value))); + return params; + } + + if (valueCollection.isEmpty()){ + return params; + } + + // get the collection format (default: csv) + String format = (collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat); + + // create the params based on the collection format + if ("multi".equals(format)) { + for (Object item : valueCollection) { + params.add(new Pair(name, parameterToString(item))); + } + + return params; + } + + String delimiter = ","; + + if ("csv".equals(format)) { + delimiter = ","; + } else if ("ssv".equals(format)) { + delimiter = " "; + } else if ("tsv".equals(format)) { + delimiter = "\t"; + } else if ("pipes".equals(format)) { + delimiter = "|"; + } + + StringBuilder sb = new StringBuilder() ; + for (Object item : valueCollection) { + sb.append(delimiter); + sb.append(parameterToString(item)); + } + + params.add(new Pair(name, sb.substring(1))); + + return params; + } + + /** + * 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 + * @return True if the MIME type is JSON + */ + 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, + * JSON will be used. + */ + public String selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0) { + 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 + * @return Escaped string + */ + public String escapeString(String str) { + try { + return URLEncoder.encode(str, "utf8").replaceAll("\\+", "%20"); + } catch (UnsupportedEncodingException e) { + return str; + } + } + + /** + * Serialize the given Java object into string entity according the given + * Content-Type (only JSON is supported for now). + * @param obj Object + * @param formParams Form parameters + * @param contentType Context type + * @return Entity + * @throws ApiException API exception + */ + public Entity serialize(Object obj, Map formParams, String contentType, boolean isBodyNullable) throws ApiException { + Entity entity; + if (contentType.startsWith("multipart/form-data")) { + MultiPart multiPart = new MultiPart(); + for (Entry param: formParams.entrySet()) { + if (param.getValue() instanceof File) { + File file = (File) param.getValue(); + FormDataContentDisposition contentDisp = FormDataContentDisposition.name(param.getKey()) + .fileName(file.getName()).size(file.length()).build(); + multiPart.bodyPart(new FormDataBodyPart(contentDisp, file, MediaType.APPLICATION_OCTET_STREAM_TYPE)); + } else { + FormDataContentDisposition contentDisp = FormDataContentDisposition.name(param.getKey()).build(); + multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(param.getValue()))); + } + } + entity = Entity.entity(multiPart, MediaType.MULTIPART_FORM_DATA_TYPE); + } else if (contentType.startsWith("application/x-www-form-urlencoded")) { + Form form = new Form(); + for (Entry param: formParams.entrySet()) { + form.param(param.getKey(), parameterToString(param.getValue())); + } + entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE); + } else { + // We let jersey handle the serialization + if (isBodyNullable) { // payload is nullable + if (obj instanceof String) { + entity = Entity.entity(obj == null ? "null" : "\"" + ((String)obj).replaceAll("\"", Matcher.quoteReplacement("\\\"")) + "\"", contentType); + } else { + entity = Entity.entity(obj == null ? "null" : obj, contentType); + } + } else { + if (obj instanceof String) { + entity = Entity.entity(obj == null ? "" : "\"" + ((String)obj).replaceAll("\"", Matcher.quoteReplacement("\\\"")) + "\"", contentType); + } else { + entity = Entity.entity(obj == null ? "" : obj, contentType); + } + } + } + return entity; + } + + /** + * Serialize the given Java object into string according the given + * Content-Type (only JSON, HTTP form is supported for now). + * @param obj Object + * @param formParams Form parameters + * @param contentType Context type + * @param isBodyNullable True if the body is nullable + * @return String + * @throws ApiException API exception + */ + public String serializeToString(Object obj, Map formParams, String contentType, boolean isBodyNullable) throws ApiException { + try { + if (contentType.startsWith("multipart/form-data")) { + throw new ApiException("multipart/form-data not yet supported for serializeToString (http signature authentication)"); + } else if (contentType.startsWith("application/x-www-form-urlencoded")) { + String formString = ""; + for (Entry param : formParams.entrySet()) { + formString = param.getKey() + "=" + URLEncoder.encode(parameterToString(param.getValue()), "UTF-8") + "&"; + } + + if (formString.length() == 0) { // empty string + return formString; + } else { + return formString.substring(0, formString.length() - 1); + } + } else { + if (isBodyNullable) { + return obj == null ? "null" : json.getMapper().writeValueAsString(obj); + } else { + return obj == null ? "" : json.getMapper().writeValueAsString(obj); + } + } + } catch (Exception ex) { + throw new ApiException("Failed to perform serializeToString: " + ex.toString()); + } + } + + /** + * Deserialize response body to Java object according to the Content-Type. + * @param Type + * @param response Response + * @param returnType Return type + * @return Deserialize object + * @throws ApiException API exception + */ + @SuppressWarnings("unchecked") + public T deserialize(Response response, GenericType returnType) throws ApiException { + if (response == null || returnType == null) { + return null; + } + + if ("byte[]".equals(returnType.toString())) { + // Handle binary response (byte array). + return (T) response.readEntity(byte[].class); + } + + String contentType = null; + List contentTypes = response.getHeaders().get("Content-Type"); + if (contentTypes != null && !contentTypes.isEmpty()) + contentType = String.valueOf(contentTypes.get(0)); + + // read the entity stream multiple times + response.bufferEntity(); + + return response.readEntity(returnType); + } + + /** + * Invoke API by sending HTTP request with the given options. + * + * @param Type + * @param operation The qualified name of the operation + * @param path The sub-path of the HTTP URL + * @param method The request method, one of "GET", "POST", "PUT", "HEAD" and "DELETE" + * @param queryParams The query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param cookieParams The cookie parameters + * @param formParams The form parameters + * @param accept The request's Accept header + * @param contentType The request's Content-Type header + * @param authNames The authentications to apply + * @param returnType The return type into which to deserialize the response + * @param isBodyNullable True if the body is nullable + * @return The response body in type of string + * @throws ApiException API exception + */ + public ApiResponse invokeAPI( + String operation, + String path, + String method, + List queryParams, + Object body, + Map headerParams, + Map cookieParams, + Map formParams, + String accept, + String contentType, + String[] authNames, + GenericType returnType, + boolean isBodyNullable) + throws ApiException { + + // Not using `.target(targetURL).path(path)` below, + // to support (constant) query string in `path`, e.g. "/posts?draft=1" + String targetURL; + if (serverIndex != null && operationServers.containsKey(operation)) { + Integer index = operationServerIndex.containsKey(operation) ? operationServerIndex.get(operation) : serverIndex; + Map variables = operationServerVariables.containsKey(operation) ? + operationServerVariables.get(operation) : serverVariables; + List serverConfigurations = operationServers.get(operation); + if (index < 0 || index >= serverConfigurations.size()) { + throw new ArrayIndexOutOfBoundsException( + String.format( + "Invalid index %d when selecting the host settings. Must be less than %d", + index, serverConfigurations.size())); + } + targetURL = serverConfigurations.get(index).URL(variables) + path; + } else { + targetURL = this.basePath + path; + } + WebTarget target = httpClient.target(targetURL); + + if (queryParams != null) { + for (Pair queryParam : queryParams) { + if (queryParam.getValue() != null) { + target = target.queryParam(queryParam.getName(), escapeString(queryParam.getValue())); + } + } + } + + Invocation.Builder invocationBuilder = target.request().accept(accept); + + for (Entry entry : cookieParams.entrySet()) { + String value = entry.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.cookie(entry.getKey(), value); + } + } + + for (Entry entry : defaultCookieMap.entrySet()) { + String value = entry.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.cookie(entry.getKey(), value); + } + } + + Entity entity = serialize(body, formParams, contentType, isBodyNullable); + + // put all headers in one place + Map allHeaderParams = new HashMap<>(defaultHeaderMap); + allHeaderParams.putAll(headerParams); + + // update different parameters (e.g. headers) for authentication + updateParamsForAuth( + authNames, + queryParams, + allHeaderParams, + cookieParams, + // NOTE: this is not used in ApiKeyAuthentication anyway, so we comment it out to enable multipart requests + "", // serializeToString(body, formParams, contentType, isBodyNullable), + method, + target.getUri()); + + for (Entry entry : allHeaderParams.entrySet()) { + String value = entry.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.header(entry.getKey(), value); + } + } + + Response response = null; + + try { + response = sendRequest(method, invocationBuilder, entity); + + {{#hasOAuthMethods}} + // If OAuth is used and a status 401 is received, renew the access token and retry the request + if (response.getStatusInfo() == Status.UNAUTHORIZED) { + for (String authName : authNames) { + Authentication authentication = authentications.get(authName); + if (authentication instanceof OAuth) { + OAuth2AccessToken accessToken = ((OAuth) authentication).renewAccessToken(); + if (accessToken != null) { + invocationBuilder.header("Authorization", null); + invocationBuilder.header("Authorization", "Bearer " + accessToken.getAccessToken()); + response = sendRequest(method, invocationBuilder, entity); + } + break; + } + } + } + + {{/hasOAuthMethods}} + int statusCode = response.getStatusInfo().getStatusCode(); + Map> responseHeaders = buildResponseHeaders(response); + + if (response.getStatusInfo() == Status.NO_CONTENT) { + return new ApiResponse(statusCode, responseHeaders); + } else if (response.getStatusInfo().getFamily() == Status.Family.SUCCESSFUL) { + if (returnType == null) { + return new ApiResponse(statusCode, responseHeaders); + } else { + return new ApiResponse(statusCode, responseHeaders, deserialize(response, returnType)); + } + } else { + String message = "error"; + String respBody = null; + if (response.hasEntity()) { + try { + respBody = String.valueOf(response.readEntity(String.class)); + message = respBody; + } catch (RuntimeException e) { + // e.printStackTrace(); + } + } + throw new ApiException( + response.getStatus(), message, buildResponseHeaders(response), respBody); + } + } finally { + try { + response.close(); + } catch (Exception e) { + // it's not critical, since the response object is local in method invokeAPI; that's fine, + // just continue + } + } + } + + private Response sendRequest(String method, Invocation.Builder invocationBuilder, Entity entity) { + Response response; + if ("POST".equals(method)) { + response = invocationBuilder.post(entity); + } else if ("PUT".equals(method)) { + response = invocationBuilder.put(entity); + } else if ("DELETE".equals(method)) { + response = invocationBuilder.method("DELETE", entity); + } else if ("PATCH".equals(method)) { + response = invocationBuilder.method("PATCH", entity); + } else { + response = invocationBuilder.method(method); + } + return response; + } + + /** + * @deprecated Add qualified name of the operation as a first parameter. + */ + @Deprecated + public ApiResponse invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType, boolean isBodyNullable) throws ApiException { + return invokeAPI(null, path, method, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType, isBodyNullable); + } + + /** + * Build the Client used to make HTTP requests. + * @return Client + */ + protected Client buildHttpClient() { + // use the default client config if not yet initialized + if (clientConfig == null) { + clientConfig = getDefaultClientConfig(); + } + + ClientBuilder clientBuilder = ClientBuilder.newBuilder(); + customizeClientBuilder(clientBuilder); + clientBuilder = clientBuilder.withConfig(clientConfig); + return clientBuilder.build(); + } + + /** + * Get the default client config. + * @return Client config + */ + public ClientConfig getDefaultClientConfig() { + ClientConfig clientConfig = new ClientConfig(); + clientConfig.register(MultiPartFeature.class); + clientConfig.register(json); + clientConfig.register(JacksonFeature.class); + clientConfig.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true); + // turn off compliance validation to be able to send payloads with DELETE calls + clientConfig.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true); + if (debugging) { + clientConfig.register(new LoggingFeature(java.util.logging.Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME), java.util.logging.Level.INFO, LoggingFeature.Verbosity.PAYLOAD_ANY, 1024*50 /* Log payloads up to 50K */)); + clientConfig.property(LoggingFeature.LOGGING_FEATURE_VERBOSITY, LoggingFeature.Verbosity.PAYLOAD_ANY); + // Set logger to ALL + java.util.logging.Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME).setLevel(java.util.logging.Level.ALL); + } else { + // suppress warnings for payloads with DELETE calls: + java.util.logging.Logger.getLogger("org.glassfish.jersey.client").setLevel(java.util.logging.Level.SEVERE); + } + + return clientConfig; + } + + /** + * Customize the client builder. + * + * This method can be overriden to customize the API client. For example, this can be used to: + * 1. Set the hostname verifier to be used by the client to verify the endpoint's hostname + * against its identification information. + * 2. Set the client-side key store. + * 3. Set the SSL context that will be used when creating secured transport connections to + * server endpoints from web targets created by the client instance that is using this SSL context. + * 4. Set the client-side trust store. + * + * To completely disable certificate validation (at your own risk), you can + * override this method and invoke disableCertificateValidation(clientBuilder). + */ + protected void customizeClientBuilder(ClientBuilder clientBuilder) { + // No-op extension point + } + + /** + * Disable X.509 certificate validation in TLS connections. + * + * Please note that trusting all certificates is extremely risky. + * This may be useful in a development environment with self-signed certificates. + */ + protected void disableCertificateValidation(ClientBuilder clientBuilder) throws KeyManagementException, NoSuchAlgorithmException { + TrustManager[] trustAllCerts = new X509TrustManager[] { + new X509TrustManager() { + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + @Override + public void checkClientTrusted(X509Certificate[] certs, String authType) { + } + @Override + public void checkServerTrusted(X509Certificate[] certs, String authType) { + } + } + }; + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, trustAllCerts, new SecureRandom()); + clientBuilder.sslContext(sslContext); + } + + protected Map> buildResponseHeaders(Response response) { + Map> responseHeaders = new HashMap>(); + for (Entry> entry: response.getHeaders().entrySet()) { + List values = entry.getValue(); + List headers = new ArrayList(); + for (Object o : values) { + headers.add(String.valueOf(o)); + } + responseHeaders.put(entry.getKey(), headers); + } + return responseHeaders; + } + + /** + * 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 method HTTP method (e.g. POST) + * @param uri HTTP URI + */ + protected 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) { + continue; + } + auth.applyToParams(queryParams, headerParams, cookieParams, payload, method, uri); + } + } +} diff --git a/.generator/templates/libraries/jersey2/ApiResponse.mustache b/.generator/templates/libraries/jersey2/ApiResponse.mustache new file mode 100644 index 00000000000..86c889b0f67 --- /dev/null +++ b/.generator/templates/libraries/jersey2/ApiResponse.mustache @@ -0,0 +1,73 @@ +{{>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. + * + * @param The type of data that is deserialized from response body + */ +public class ApiResponse { + private final int statusCode; + private final Map> headers; + private final T data; + + /** + * @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); + } + + /** + * @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 status code + */ + public int getStatusCode() { + return statusCode; + } + + /** + * Get the headers + * + * @return map of headers + */ + public Map> getHeaders() { + return headers; + } + + /** + * Get the data + * + * @return data + */ + public T getData() { + return data; + } +} diff --git a/.generator/templates/libraries/jersey2/JSON.mustache b/.generator/templates/libraries/jersey2/JSON.mustache new file mode 100644 index 00000000000..aed16b34010 --- /dev/null +++ b/.generator/templates/libraries/jersey2/JSON.mustache @@ -0,0 +1,277 @@ +package {{invokerPackage}}; + +{{#threetenbp}} +import org.threeten.bp.*; +{{/threetenbp}} +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.*; +{{#openApiNullable}} +import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} +{{#java8}} +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{/java8}} +{{#joda}} +import com.fasterxml.jackson.datatype.joda.JodaModule; +{{/joda}} +{{#threetenbp}} +import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; +{{/threetenbp}} +{{#models.0}} +import {{modelPackage}}.*; +{{/models.0}} + +import java.text.DateFormat; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.ext.ContextResolver; + +{{>generatedAnnotation}} +public class JSON implements ContextResolver { + private ObjectMapper mapper; + + public JSON() { + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.setDateFormat(new RFC3339DateFormat()); + {{#java8}} + mapper.registerModule(new JavaTimeModule()); + {{/java8}} + {{#joda}} + mapper.registerModule(new JodaModule()); + {{/joda}} + {{#threetenbp}} + ThreeTenModule module = new ThreeTenModule(); + module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); + module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); + module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); + mapper.registerModule(module); + {{/threetenbp}} + {{#openApiNullable}} + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); + {{/openApiNullable}} + } + + /** + * Set the date format for JSON (de)serialization with Date properties. + * @param dateFormat Date format + */ + public void setDateFormat(DateFormat dateFormat) { + mapper.setDateFormat(dateFormat); + } + + @Override + public ObjectMapper getContext(Class type) { + return mapper; + } + + /** + * Get the object mapper + * + * @return object mapper + */ + public ObjectMapper getMapper() { return mapper; } + + /** + * 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. + */ + 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()) { + String discrValue = node.asText(); + 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. + */ + 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. + */ + 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 (GenericType childType : descendants.values()) { + if (isInstanceOf(childType.getRawType(), inst, visitedClasses)) { + return true; + } + } + } + return false; + } + + /** + * A map of discriminators for all model classes. + */ + private static Map, ClassDiscriminatorMapping> modelDiscriminators = new HashMap, ClassDiscriminatorMapping>(); + + /** + * A map of oneOf/anyOf descendants for each model class. + */ + private static Map, Map> modelDescendants = new HashMap, Map>(); + + /** + * 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); + } + + private static JSON json; + + static + { + json = new JSON(); + } + + /** + * Get the default JSON instance. + * + * @return the default JSON instance + */ + public static JSON getDefault() { + return json; + } + + /** + * Set the default JSON instance. + * + * @param json JSON instance to be used + */ + public static void setDefault(JSON json) { + JSON.json = json; + } +} diff --git a/.generator/templates/libraries/jersey2/additional_properties.mustache b/.generator/templates/libraries/jersey2/additional_properties.mustache new file mode 100644 index 00000000000..61973dc24fa --- /dev/null +++ b/.generator/templates/libraries/jersey2/additional_properties.mustache @@ -0,0 +1,39 @@ +{{#additionalPropertiesType}} + /** + * 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. + */ + @JsonAnySetter + public {{classname}} putAdditionalProperty(String key, {{{.}}} value) { + if (this.additionalProperties == null) { + this.additionalProperties = new HashMap(); + } + this.additionalProperties.put(key, value); + return this; + } + + /** + * Return the additional (undeclared) property. + */ + @JsonAnyGetter + public Map getAdditionalProperties() { + return additionalProperties; + } + + /** + * Return the additional (undeclared) property with the specified name. + */ + public {{{.}}} getAdditionalProperty(String key) { + if (this.additionalProperties == null) { + return null; + } + return this.additionalProperties.get(key); + } +{{/additionalPropertiesType}} diff --git a/.generator/templates/libraries/jersey2/anyof_model.mustache b/.generator/templates/libraries/jersey2/anyof_model.mustache new file mode 100644 index 00000000000..8d236677b00 --- /dev/null +++ b/.generator/templates/libraries/jersey2/anyof_model.mustache @@ -0,0 +1,202 @@ +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.Response; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import {{invokerPackage}}.JSON; + +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} +@JsonDeserialize(using={{classname}}.{{classname}}Deserializer.class) +@JsonSerialize(using = {{classname}}.{{classname}}Serializer.class) +public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} { + private static final Logger log = Logger.getLogger({{classname}}.class.getName()); + + 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, SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeObject(value.getActualInstance()); + } + } + + 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 IOException, JsonProcessingException { + JsonNode tree = jp.readValueAsTree(); + + Object deserialized = null; + {{#discriminator}} + Class cls = JSON.getClassForElement(tree, {{classname}}.class); + if (cls != null) { + // When the OAS schema includes a discriminator, use the discriminator value to + // discriminate the anyOf schemas. + // Get the discriminator mapping value to get the class. + deserialized = tree.traverse(jp.getCodec()).readValueAs(cls); + {{classname}} ret = new {{classname}}(); + ret.setActualInstance(deserialized); + return ret; + } + {{/discriminator}} + {{#anyOf}} + // deserialzie {{{.}}} + try { + deserialized = tree.traverse(jp.getCodec()).readValueAs({{{.}}}.class); + {{classname}} ret = new {{classname}}(); + ret.setActualInstance(deserialized); + return ret; + } catch (Exception e) { + // deserialization failed, continue, log to help debugging + log.log(Level.FINER, "Input data does not match '{{classname}}'", e); + } + + {{/anyOf}} + throw new IOException(String.format("Failed deserialization for {{classname}}: no match found")); + } + + /** + * Handle deserialization of the 'null' value. + */ + @Override + public {{classname}} getNullValue(DeserializationContext ctxt) throws JsonMappingException { + {{#isNullable}} + return null; + {{/isNullable}} + {{^isNullable}} + throw new JsonMappingException(ctxt.getParser(), "{{classname}} cannot be null"); + {{/isNullable}} + } + } + + // 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}}); + } +{{> libraries/jersey2/additional_properties }} + {{#additionalPropertiesType}} + /** + * Return true if this {{name}} object is equal to o. + */ + @Override + public boolean equals(Object o) { + return super.equals(o) && Objects.equals(this.additionalProperties, (({{classname}})o).additionalProperties); + } + + @Override + public int hashCode() { + return Objects.hash(getActualInstance(), isNullable(), getSchemaType(), additionalProperties); + } + {{/additionalPropertiesType}} + {{#anyOf}} + public {{classname}}({{{.}}} o) { + super("anyOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + setActualInstance(o); + } + + {{/anyOf}} + static { + {{#anyOf}} + schemas.put("{{{.}}}", new GenericType<{{{.}}}>() { + }); + {{/anyOf}} + 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}} + } + + @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 instanct 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}} +} diff --git a/.generator/templates/libraries/jersey2/api.mustache b/.generator/templates/libraries/jersey2/api.mustache new file mode 100644 index 00000000000..809694a6dfc --- /dev/null +++ b/.generator/templates/libraries/jersey2/api.mustache @@ -0,0 +1,273 @@ +package {{package}}; + +import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.ApiResponse; +import {{invokerPackage}}.Configuration; +import {{invokerPackage}}.Pair; + +import javax.ws.rs.core.GenericType; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +{{/fullJavaUtil}} +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}} { + private ApiClient apiClient; + + public {{classname}}() { + this(Configuration.getDefaultApiClient()); + } + + public {{classname}}(ApiClient apiClient) { + this.apiClient = apiClient; + } + + /** + * Get the API cilent + * + * @return API client + */ + public ApiClient getApiClient() { + return apiClient; + } + + /** + * Set the API cilent + * + * @param apiClient an instance of API client + */ + public void setApiClient(ApiClient apiClient) { + this.apiClient = apiClient; + } + + {{#operation}} + {{^vendorExtensions.x-group-parameters}} + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + {{#returnType}} + * @return {{returnType}} + {{/returnType}} + * @throws ApiException if fails to make API call + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + {{#returnType}}return {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}){{#returnType}}.getData(){{/returnType}}; + } + {{/vendorExtensions.x-group-parameters}} + + {{^vendorExtensions.x-group-parameters}} + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @return ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + * @throws ApiException if fails to make API call + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/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}} ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + } + {{/required}}{{/allParams}} + // create path and map variables + String localVarPath = "{{{path}}}"{{#pathParams}} + .replaceAll("\\{" + "{{baseName}}" + "\\}", apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; + + // query params + {{javaUtilPrefix}}List localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}Map localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarCookieParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap(); + + {{#queryParams}} + localVarQueryParams.addAll(apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); + {{/queryParams}} + + // Set Operation-ID header for telemetry + localVarHeaderParams.put("DD-OPERATION-ID", "{{operationId}}"); + + {{#headerParams}}if ({{paramName}} != null) + localVarHeaderParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); + {{/headerParams}} + + {{#cookieParams}}if ({{paramName}} != null) + localVarCookieParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); + {{/cookieParams}} + + {{#formParams}}if ({{paramName}} != null) + localVarFormParams.put("{{baseName}}", {{paramName}}); + {{/formParams}} + + final String[] localVarAccepts = { + {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} + }; + final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); + + final String[] localVarContentTypes = { + {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} + }; + final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); + + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; + + {{#returnType}} + GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {}; + + {{/returnType}} + return apiClient.invokeAPI("{{classname}}.{{operationId}}", localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, + localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, + localVarAuthNames, {{#returnType}}localVarReturnType{{/returnType}}{{^returnType}}null{{/returnType}}, {{#bodyParam}}{{#isNullable}}true{{/isNullable}}{{^isNullable}}false{{/isNullable}}{{/bodyParam}}{{^bodyParam}}false{{/bodyParam}}); + } + {{#vendorExtensions.x-group-parameters}} + + public class API{{operationId}}Request { + {{#allParams}} + private {{#isRequired}}final {{/isRequired}}{{{dataType}}} {{paramName}}; + {{/allParams}} + + private API{{operationId}}Request({{#pathParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}) { + {{#pathParams}} + this.{{paramName}} = {{paramName}}; + {{/pathParams}} + } + {{#allParams}} + {{^isPathParam}} + + /** + * Set {{paramName}} + * @param {{paramName}} {{description}} ({{^required}}optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}{{/required}}{{#required}}required{{/required}}) + * @return API{{operationId}}Request + */ + public API{{operationId}}Request {{paramName}}({{{dataType}}} {{paramName}}) { + this.{{paramName}} = {{paramName}}; + return this; + } + {{/isPathParam}} + {{/allParams}} + + /** + * Execute {{operationId}} request + {{#returnType}}* @return {{.}}{{/returnType}} + * @throws ApiException if fails to make API call + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} + {{#isDeprecated}}* @deprecated{{/isDeprecated}} + */ + {{#isDeprecated}}@Deprecated{{/isDeprecated}} + public {{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}void{{/returnType}} execute() throws ApiException { + {{#returnType}}return {{/returnType}}this.executeWithHttpInfo().getData(); + } + + /** + * Execute {{operationId}} request with HTTP info returned + * @return ApiResponse<{{#returnType}}{{.}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + * @throws ApiException if fails to make API call + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} + {{#isDeprecated}} + * @deprecated{{/isDeprecated}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public ApiResponse<{{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> executeWithHttpInfo() throws ApiException { + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + } + } + + /** + * {{summary}} + * {{notes}}{{#pathParams}} + * @param {{paramName}} {{description}} (required){{/pathParams}} + * @return {{operationId}}Request + * @throws ApiException if fails to make API call + {{#isDeprecated}}* @deprecated{{/isDeprecated}} + {{#externalDocs}}* {{description}} + * @see {{summary}} Documentation{{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public API{{operationId}}Request {{operationId}}({{#pathParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}) throws ApiException { + {{#vendorExtensions.x-unstable}} + String operationId = "{{operationId}}"; + if (apiClient.isUnstableOperationEnabled(operationId)) { + apiClient.getLogger().warning(String.format("Using unstable operation '%s'", operationId)); + } else { + throw new ApiException(0, String.format("Unstable operation '%s' is disabled", operationId)); + } + {{/vendorExtensions.x-unstable}} + return new API{{operationId}}Request({{#pathParams}}{{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}); + } + {{/vendorExtensions.x-group-parameters}} + {{/operation}} +} +{{/operations}} diff --git a/.generator/templates/libraries/jersey2/apiException.mustache b/.generator/templates/libraries/jersey2/apiException.mustache new file mode 100644 index 00000000000..74a419aacf1 --- /dev/null +++ b/.generator/templates/libraries/jersey2/apiException.mustache @@ -0,0 +1,99 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import java.util.Map; +import java.util.List; +{{#caseInsensitiveResponseHeaders}} +import java.util.Map.Entry; +import java.util.TreeMap; +{{/caseInsensitiveResponseHeaders}} + +/** + * API Exception + */ +{{>generatedAnnotation}} +public class ApiException extends{{#useRuntimeException}} RuntimeException {{/useRuntimeException}}{{^useRuntimeException}} Exception {{/useRuntimeException}}{ + private int code = 0; + private Map> responseHeaders = null; + private String responseBody = null; + + public ApiException() {} + + public ApiException(Throwable throwable) { + super(throwable); + } + + public ApiException(String message) { + super(message); + } + + 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; + } + + public ApiException(String message, int code, Map> responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(String message, Throwable throwable, int code, Map> responseHeaders) { + this(message, throwable, code, responseHeaders, null); + } + + public ApiException(int code, Map> responseHeaders, String responseBody) { + this((String) null, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(int code, String message) { + super(message); + this.code = code; + } + + 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; + } +} diff --git a/.generator/templates/libraries/jersey2/api_doc.mustache b/.generator/templates/libraries/jersey2/api_doc.mustache new file mode 100644 index 00000000000..eaf50994059 --- /dev/null +++ b/.generator/templates/libraries/jersey2/api_doc.mustache @@ -0,0 +1,122 @@ +# {{classname}}{{#description}} + +{{description}}{{/description}} + +All URIs are relative to *{{basePath}}* + +Method | HTTP request | Description +------------- | ------------- | ------------- +{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}} + +{{#operations}} +{{#operation}} + +## {{operationId}} + +{{^vendorExtensions.x-group-parameters}} +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) +{{/vendorExtensions.x-group-parameters}} +{{#vendorExtensions.x-group-parameters}} +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#pathParams}}{{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}){{#allParams}}{{^isPathParam}}.{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}}.execute(); +{{/vendorExtensions.x-group-parameters}} + +{{summary}}{{#notes}} + +{{{unescapedNotes}}}{{/notes}} + +### Example + +```java +{{#vendorExtensions.x-java-import}} +import {{.}}; +{{/vendorExtensions.x-java-import}} +// Import classes: +import java.util.*; +import {{{invokerPackage}}}.ApiClient; +import {{{invokerPackage}}}.ApiException; +import {{{invokerPackage}}}.Configuration;{{#hasAuthMethods}} +import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}} +import {{{invokerPackage}}}.model.*; +import {{{package}}}.{{{classname}}}; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + // Configure the Datadog site to send API calls to + HashMap serverVariables = new HashMap(); + String site = System.getenv("DD_SITE"); + if (site != null) { + serverVariables.put("site", site); + defaultClient.setServerVariables(serverVariables); + } + // Configure API key authorization: {{{name}}} + HashMap secrets = new HashMap(); + {{#hasAuthMethods}} + {{#authMethods}} + {{#isApiKey}} + secrets.put("{{{name}}}", System.getenv("{{{vendorExtensions.x-env-name}}}")); + {{/isApiKey}} + {{/authMethods}} + {{/hasAuthMethods}} + defaultClient.configureApiKeys(secrets); + + {{{classname}}} apiInstance = new {{{classname}}}(defaultClient); + {{#allParams}} + {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} + {{/allParams}} + try { + {{^vendorExtensions.x-group-parameters}} + {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}); + {{/vendorExtensions.x-group-parameters}} + {{#vendorExtensions.x-group-parameters}} + {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{operationId}}({{#pathParams}}{{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}){{#allParams}}{{^isPathParam}} + .{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}} + .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}}** | {{#isContainer}}{{#isArray}}{{#items}}{{#isModel}}{{^isFile}}[{{/isFile}}{{/isModel}}**List<{{dataType}}>**{{#isModel}}{{^isFile}}]({{^baseType}}{{dataType}}{{/baseType}}{{#baseType}}{{baseType}}{{/baseType}}.md){{/isFile}}{{/isModel}}{{/items}}{{/isArray}}{{#isMap}}{{#items}}{{#isModel}}{{^isFile}}[{{/isFile}}{{/isModel}}**Map<String,{{dataType}}>**{{#isModel}}{{^isFile}}]({{^baseType}}{{dataType}}{{/baseType}}{{#baseType}}{{baseType}}{{/baseType}}.md){{/isFile}}{{/isModel}}{{/items}}{{/isMap}}{{/isContainer}}{{^isContainer}}{{#isModel}}{{^isFile}}[{{/isFile}}{{/isModel}}**{{dataType}}**{{#isModel}}{{^isFile}}]({{^baseType}}{{dataType}}{{/baseType}}{{#baseType}}{{baseType}}{{/baseType}}.md){{/isFile}}{{/isModel}}{{/isContainer}}| {{description}} |{{^required}} [optional]{{/required}}{{^isContainer}}{{#defaultValue}} [default to {{defaultValue}}]{{/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/.generator/templates/libraries/jersey2/api_test.mustache b/.generator/templates/libraries/jersey2/api_test.mustache new file mode 100644 index 00000000000..b6ea89f6154 --- /dev/null +++ b/.generator/templates/libraries/jersey2/api_test.mustache @@ -0,0 +1,56 @@ +{{>licenseInfo}} + +package {{package}}; + +import {{invokerPackage}}.*; +import {{invokerPackage}}.auth.*; +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +public class {{classname}}Test { + + private final {{classname}} api = new {{classname}}(); + + {{#operations}} + {{#operation}} + /** + * {{summary}} + * + * {{notes}} + * + * @throws ApiException + * if the Api call fails + */ + @Test + public void {{operationId}}Test() throws ApiException { + {{#allParams}} + //{{{dataType}}} {{paramName}} = null; + {{/allParams}} + {{^vendorExtensions.x-group-parameters}} + //{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + {{/vendorExtensions.x-group-parameters}} + {{#vendorExtensions.x-group-parameters}} + //{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#pathParams}}{{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}){{#allParams}}{{^isPathParam}} + // .{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}} + // .execute(); + {{/vendorExtensions.x-group-parameters}} + // TODO: test validations + } + + {{/operation}} + {{/operations}} +} diff --git a/.generator/templates/libraries/jersey2/auth/ApiKeyAuth.mustache b/.generator/templates/libraries/jersey2/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..1731f936fb8 --- /dev/null +++ b/.generator/templates/libraries/jersey2/auth/ApiKeyAuth.mustache @@ -0,0 +1,68 @@ +{{>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 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/.generator/templates/libraries/jersey2/auth/Authentication.mustache b/.generator/templates/libraries/jersey2/auth/Authentication.mustache new file mode 100644 index 00000000000..46d9c1ab6ac --- /dev/null +++ b/.generator/templates/libraries/jersey2/auth/Authentication.mustache @@ -0,0 +1,22 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import {{invokerPackage}}.ApiException; + +import java.net.URI; +import java.util.Map; +import java.util.List; + +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 + */ + void applyToParams(List queryParams, Map headerParams, Map cookieParams, String payload, String method, URI uri) throws ApiException; + +} diff --git a/.generator/templates/libraries/jersey2/auth/HttpBasicAuth.mustache b/.generator/templates/libraries/jersey2/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..898bb97ee78 --- /dev/null +++ b/.generator/templates/libraries/jersey2/auth/HttpBasicAuth.mustache @@ -0,0 +1,62 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import {{invokerPackage}}.ApiException; + +{{^java8}} +import com.migcomponents.migbase64.Base64; +{{/java8}} +{{#java8}} +import java.util.Base64; +import java.nio.charset.StandardCharsets; +{{/java8}} + +import java.net.URI; +import java.util.Map; +import java.util.List; + +{{^java8}} +import java.io.UnsupportedEncodingException; +{{/java8}} + +{{>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; + } + String str = (username == null ? "" : username) + ":" + (password == null ? "" : password); +{{^java8}} + try { + headerParams.put("Authorization", "Basic " + Base64.encodeToString(str.getBytes("UTF-8"), false)); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } +{{/java8}} +{{#java8}} + headerParams.put("Authorization", "Basic " + Base64.getEncoder().encodeToString(str.getBytes(StandardCharsets.UTF_8))); +{{/java8}} + } +} diff --git a/.generator/templates/libraries/jersey2/auth/HttpBearerAuth.mustache b/.generator/templates/libraries/jersey2/auth/HttpBearerAuth.mustache new file mode 100644 index 00000000000..110a11ea779 --- /dev/null +++ b/.generator/templates/libraries/jersey2/auth/HttpBearerAuth.mustache @@ -0,0 +1,51 @@ +{{>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 Authorization header. + * + * @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 Authorization header. + * + * @param bearerToken The bearer token to send in the Authorization header + */ + 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/.generator/templates/libraries/jersey2/auth/HttpSignatureAuth.mustache b/.generator/templates/libraries/jersey2/auth/HttpSignatureAuth.mustache new file mode 100644 index 00000000000..ac0a77db8ac --- /dev/null +++ b/.generator/templates/libraries/jersey2/auth/HttpSignatureAuth.mustache @@ -0,0 +1,269 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import {{invokerPackage}}.ApiException; + +import java.net.URI; +import java.net.URLEncoder; +import java.security.MessageDigest; +import java.security.Key; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Base64; +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; +import java.util.Map; +import java.util.List; +import java.util.TimeZone; +import java.security.spec.AlgorithmParameterSpec; +import java.security.InvalidKeyException; + +import org.tomitribe.auth.signatures.Algorithm; +import org.tomitribe.auth.signatures.Signer; +import org.tomitribe.auth.signatures.Signature; +import org.tomitribe.auth.signatures.SigningAlgorithm; + +/** + * A Configuration object for the HTTP message signature security scheme. + */ +public class HttpSignatureAuth implements Authentication { + + private Signer signer; + + // An opaque string that the server can use to look up the component they need to validate the signature. + private String keyId; + + // The HTTP signature algorithm. + private SigningAlgorithm signingAlgorithm; + + // The HTTP cryptographic algorithm. + private Algorithm algorithm; + + // The cryptographic parameters. + private AlgorithmParameterSpec parameterSpec; + + // The list of HTTP headers that should be included in the HTTP signature. + private List headers; + + // The digest algorithm which is used to calculate a cryptographic digest of the HTTP request body. + private String digestAlgorithm; + + // The maximum validity duration of the HTTP signature. + private Long maxSignatureValidity; + + /** + * Construct a new HTTP signature auth configuration object. + * + * @param keyId An opaque string that the server can use to look up the component they need to validate the signature. + * @param signingAlgorithm The signature algorithm. + * @param algorithm The cryptographic algorithm. + * @param digestAlgorithm The digest algorithm. + * @param headers The list of HTTP headers that should be included in the HTTP signature. + * @param maxSignatureValidity The maximum validity duration of the HTTP signature. + * Used to set the '(expires)' field in the HTTP signature. + */ + public HttpSignatureAuth(String keyId, + SigningAlgorithm signingAlgorithm, + Algorithm algorithm, + String digestAlgorithm, + AlgorithmParameterSpec parameterSpec, + List headers, + Long maxSignatureValidity) { + this.keyId = keyId; + this.signingAlgorithm = signingAlgorithm; + this.algorithm = algorithm; + this.parameterSpec = parameterSpec; + this.digestAlgorithm = digestAlgorithm; + this.headers = headers; + this.maxSignatureValidity = maxSignatureValidity; + } + + /** + * Returns the opaque string that the server can use to look up the component they need to validate the signature. + * + * @return The keyId. + */ + public String getKeyId() { + return keyId; + } + + /** + * Set the HTTP signature key id. + * + * @param keyId An opaque string that the server can use to look up the component they need to validate the signature. + */ + public void setKeyId(String keyId) { + this.keyId = keyId; + } + + /** + * Returns the HTTP signature algorithm which is used to sign HTTP requests. + */ + public SigningAlgorithm getSigningAlgorithm() { + return signingAlgorithm; + } + + /** + * Sets the HTTP signature algorithm which is used to sign HTTP requests. + * + * @param signingAlgorithm The HTTP signature algorithm. + */ + public void setSigningAlgorithm(SigningAlgorithm signingAlgorithm) { + this.signingAlgorithm = signingAlgorithm; + } + + /** + * Returns the HTTP cryptographic algorithm which is used to sign HTTP requests. + */ + public Algorithm getAlgorithm() { + return algorithm; + } + + /** + * Sets the HTTP cryptographic algorithm which is used to sign HTTP requests. + * + * @param algorithm The HTTP signature algorithm. + */ + public void setAlgorithm(Algorithm algorithm) { + this.algorithm = algorithm; + } + + /** + * Returns the cryptographic parameters which are used to sign HTTP requests. + */ + public AlgorithmParameterSpec getAlgorithmParameterSpec() { + return parameterSpec; + } + + /** + * Sets the cryptographic parameters which are used to sign HTTP requests. + * + * @param parameterSpec The cryptographic parameters. + */ + public void setAlgorithmParameterSpec(AlgorithmParameterSpec parameterSpec) { + this.parameterSpec = parameterSpec; + } + + /** + * Returns the digest algorithm which is used to calculate a cryptographic digest of the HTTP request body. + * + * @see java.security.MessageDigest + */ + public String getDigestAlgorithm() { + return digestAlgorithm; + } + + /** + * Sets the digest algorithm which is used to calculate a cryptographic digest of the HTTP request body. + * + * The exact list of supported digest algorithms depends on the installed security providers. + * Every implementation of the Java platform is required to support "MD5", "SHA-1" and "SHA-256". + * Do not use "MD5" and "SHA-1", they are vulnerable to multiple known attacks. + * By default, "SHA-256" is used. + * + * @param digestAlgorithm The digest algorithm. + * + * @see java.security.MessageDigest + */ + public void setDigestAlgorithm(String digestAlgorithm) { + this.digestAlgorithm = digestAlgorithm; + } + + /** + * Returns the list of HTTP headers that should be included in the HTTP signature. + */ + public List getHeaders() { + return headers; + } + + /** + * Sets the list of HTTP headers that should be included in the HTTP signature. + * + * @param headers The HTTP headers. + */ + public void setHeaders(List headers) { + this.headers = headers; + } + + /** + * Returns the maximum validity duration of the HTTP signature. + * @return The maximum validity duration of the HTTP signature. + */ + public Long getMaxSignatureValidity() { + return maxSignatureValidity; + } + + /** + * Returns the signer instance used to sign HTTP messages. + * + * @return the signer instance. + */ + public Signer getSigner() { + return signer; + } + + /** + * Sets the signer instance used to sign HTTP messages. + * + * @param signer The signer instance to set. + */ + public void setSigner(Signer signer) { + this.signer = signer; + } + + /** + * Set the private key used to sign HTTP requests using the HTTP signature scheme. + * + * @param key The private key. + * + * @throws InvalidKeyException Unable to parse the key, or the security provider for this key + * is not installed. + */ + public void setPrivateKey(Key key) throws InvalidKeyException, ApiException { + if (key == null) { + throw new ApiException("Private key (java.security.Key) cannot be null"); + } + signer = new Signer(key, new Signature(keyId, signingAlgorithm, algorithm, parameterSpec, null, headers, maxSignatureValidity)); + } + + @Override + public void applyToParams(List queryParams, Map headerParams, Map cookieParams, + String payload, String method, URI uri) throws ApiException { + try { + if (headers.contains("host")) { + headerParams.put("host", uri.getHost()); + } + + if (headers.contains("date")) { + SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); + dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); + headerParams.put("date", dateFormat.format(Calendar.getInstance().getTime())); + } + + if (headers.contains("digest")) { + headerParams.put("digest", + this.digestAlgorithm + "=" + + new String(Base64.getEncoder().encode(MessageDigest.getInstance(this.digestAlgorithm).digest(payload.getBytes())))); + } + + if (signer == null) { + throw new ApiException("Signer cannot be null. Please call the method `setPrivateKey` to set it up correctly"); + } + + // construct the path with the URL-encoded path and query. + // Calling getRawPath and getRawQuery ensures the path is URL-encoded as it will be serialized + // on the wire. The HTTP signature must use the encode URL as it is sent on the wire. + String path = uri.getRawPath(); + if (uri.getRawQuery() != null && !"".equals(uri.getRawQuery())) { + path += "?" + uri.getRawQuery(); + } + + headerParams.put("Authorization", signer.sign(method, path, headerParams).toString()); + } catch (Exception ex) { + throw new ApiException("Failed to create signature in the HTTP request header: " + ex.toString()); + } + } +} diff --git a/.generator/templates/libraries/jersey2/auth/OAuth.mustache b/.generator/templates/libraries/jersey2/auth/OAuth.mustache new file mode 100644 index 00000000000..62b573a66c0 --- /dev/null +++ b/.generator/templates/libraries/jersey2/auth/OAuth.mustache @@ -0,0 +1,182 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import {{invokerPackage}}.ApiException; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.exceptions.OAuthException; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth.OAuth20Service; + +import javax.ws.rs.core.UriBuilder; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.logging.Level; +import java.util.logging.Logger; + +{{>generatedAnnotation}} +public class OAuth implements Authentication { + private static final Logger log = Logger.getLogger(OAuth.class.getName()); + + private String tokenUrl; + private String absoluteTokenUrl; + private OAuthFlow flow = OAuthFlow.application; + private OAuth20Service service; + private DefaultApi20 authApi; + private String scope; + private String username; + private String password; + private String code; + private volatile OAuth2AccessToken accessToken; + + public OAuth(String basePath, String tokenUrl) { + this.tokenUrl = tokenUrl; + this.absoluteTokenUrl = createAbsoluteTokenUrl(basePath, tokenUrl); + authApi = new DefaultApi20() { + @Override + public String getAccessTokenEndpoint() { + return absoluteTokenUrl; + } + + @Override + protected String getAuthorizationBaseUrl() { + throw new UnsupportedOperationException("Shouldn't get there !"); + } + }; + } + + private static String createAbsoluteTokenUrl(String basePath, String tokenUrl) { + if (!URI.create(tokenUrl).isAbsolute()) { + try { + return UriBuilder.fromPath(basePath).path(tokenUrl).build().toURL().toString(); + } catch (MalformedURLException e) { + log.log(Level.SEVERE, "Couldn't create absolute token URL", e); + } + } + return tokenUrl; + } + + @Override + public void applyToParams( + List queryParams, + Map headerParams, + Map cookieParams, + String payload, + String method, + URI uri) + throws ApiException { + + if (accessToken == null) { + obtainAccessToken(null); + } + if (accessToken != null) { + headerParams.put("Authorization", "Bearer " + accessToken.getAccessToken()); + } + } + + public OAuth2AccessToken renewAccessToken() throws ApiException { + String refreshToken = null; + if (accessToken != null) { + refreshToken = accessToken.getRefreshToken(); + accessToken = null; + } + return obtainAccessToken(refreshToken); + } + + public synchronized OAuth2AccessToken obtainAccessToken(String refreshToken) throws ApiException { + if (service == null) { + log.log(Level.FINE, "service is null in obtainAccessToken."); + return null; + } + try { + if (refreshToken != null) { + return service.refreshAccessToken(refreshToken); + } + } catch (OAuthException | InterruptedException | ExecutionException | IOException e) { + log.log(Level.FINE, "Refreshing the access token using the refresh token failed", e); + } + try { + switch (flow) { + case password: + if (username != null && password != null) { + accessToken = service.getAccessTokenPasswordGrant(username, password, scope); + } + break; + case accessCode: + if (code != null) { + accessToken = service.getAccessToken(code); + code = null; + } + break; + case application: + accessToken = service.getAccessTokenClientCredentialsGrant(scope); + break; + default: + log.log(Level.SEVERE, "Invalid flow in obtainAccessToken: " + flow); + } + } catch (OAuthException | InterruptedException | ExecutionException | IOException e) { + throw new ApiException(e); + } + return accessToken; + } + + public OAuth2AccessToken getAccessToken() { + return accessToken; + } + + public OAuth setAccessToken(OAuth2AccessToken accessToken) { + this.accessToken = accessToken; + return this; + } + + public OAuth setAccessToken(String accessToken) { + this.accessToken = new OAuth2AccessToken(accessToken); + return this; + } + + public OAuth setScope(String scope) { + this.scope = scope; + return this; + } + + public OAuth setCredentials(String clientId, String clientSecret, Boolean debug) { + if (Boolean.TRUE.equals(debug)) { + service = new ServiceBuilder(clientId) + .apiSecret(clientSecret).debug() + .build(authApi); + } else { + service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .build(authApi); + } + return this; + } + + public OAuth usePasswordFlow(String username, String password) { + this.flow = OAuthFlow.password; + this.username = username; + this.password = password; + return this; + } + + public OAuth useAuthorizationCodeFlow(String code) { + this.flow = OAuthFlow.accessCode; + this.code = code; + return this; + } + + public OAuth setFlow(OAuthFlow flow) { + this.flow = flow; + return this; + } + + public void setBasePath(String basePath) { + this.absoluteTokenUrl = createAbsoluteTokenUrl(basePath, tokenUrl); + } +} diff --git a/.generator/templates/libraries/jersey2/auth/OAuthFlow.mustache b/.generator/templates/libraries/jersey2/auth/OAuthFlow.mustache new file mode 100644 index 00000000000..002e9572f33 --- /dev/null +++ b/.generator/templates/libraries/jersey2/auth/OAuthFlow.mustache @@ -0,0 +1,7 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +public enum OAuthFlow { + accessCode, implicit, password, application +} diff --git a/.generator/templates/libraries/jersey2/build.gradle.mustache b/.generator/templates/libraries/jersey2/build.gradle.mustache new file mode 100644 index 00000000000..378de9fb1e1 --- /dev/null +++ b/.generator/templates/libraries/jersey2/build.gradle.mustache @@ -0,0 +1,166 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + maven { url "https://repo1.maven.org/maven2" } + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + {{#java8}} + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + {{/java8}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + swagger_annotations_version = "1.5.22" + jackson_version = "2.10.5" + jackson_databind_version = "2.10.5.1" + {{#openApiNullable}} + jackson_databind_nullable_version = "0.2.1" + {{/openApiNullable}} + jersey_version = "2.27" + junit_version = "4.13.1" + {{#threetenbp}} + threetenbp_version = "2.9.10" + {{/threetenbp}} + {{#hasOAuthMethods}} + scribejava_apis_version = "6.9.0" + {{/hasOAuthMethods}} + {{#hasHttpSignatureMethods}} + tomitribe_http_signatures_version = "1.5" + {{/hasHttpSignatureMethods}} +} + +dependencies { + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "org.glassfish.jersey.core:jersey-client:$jersey_version" + implementation "org.glassfish.jersey.inject:jersey-hk2:$jersey_version" + implementation "org.glassfish.jersey.media:jersey-media-multipart:$jersey_version" + implementation "org.glassfish.jersey.media:jersey-media-json-jackson:$jersey_version" + implementation "org.glassfish.jersey.connectors:jersey-apache-connector:$jersey_version" + 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_databind_version" + {{#openApiNullable}} + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} + {{#joda}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + {{/joda}} + {{#java8}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{/java8}} + {{#hasOAuthMethods}} + implementation "com.github.scribejava:scribejava-apis:$scribejava_apis_version" + {{/hasOAuthMethods}} + {{#hasHttpSignatureMethods}} + implementation "org.tomitribe:tomitribe-http-signatures:$tomitribe_http_signatures_version" + {{/hasHttpSignatureMethods}} + {{#threetenbp}} + implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:$threetenbp_version" + {{/threetenbp}} + {{^java8}} + implementation "com.brsanthu:migbase64:2.2" + {{/java8}} + implementation 'javax.annotation:javax.annotation-api:1.3.2' + testImplementation "junit:junit:$junit_version" +} + +javadoc { + options.tags = [ "http.response.details:a:Http Response Details" ] +} diff --git a/.generator/templates/libraries/jersey2/build.sbt.mustache b/.generator/templates/libraries/jersey2/build.sbt.mustache new file mode 100644 index 00000000000..9823c3c657e --- /dev/null +++ b/.generator/templates/libraries/jersey2/build.sbt.mustache @@ -0,0 +1,43 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "io.swagger" % "swagger-annotations" % "1.5.22", + "org.glassfish.jersey.core" % "jersey-client" % "2.27", + "org.glassfish.jersey.inject" % "jersey-hk2" % "2.27", + "org.glassfish.jersey.media" % "jersey-media-multipart" % "2.27", + "org.glassfish.jersey.media" % "jersey-media-json-jackson" % "2.27", + "org.glassfish.jersey.connectors" % "jersey-apache-connector" % "2.27", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.5" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.5.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.5.1" % "compile", + {{#joda}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile", + {{/joda}} + {{#java8}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile", + {{/java8}} + {{#threetenbp}} + "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", + {{/threetenbp}} + {{#hasOAuthMethods}} + "com.github.scribejava" % "scribejava-apis" % "6.9.0" % "compile", + {{/hasOAuthMethods}} + {{#hasHttpSignatureMethods}} + "org.tomitribe" % "tomitribe-http-signatures" % "1.5" % "compile", + {{/hasHttpSignatureMethods}} + {{^java8}} + "com.brsanthu" % "migbase64" % "2.2", + {{/java8}} + "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", + "junit" % "junit" % "4.13.1" % "test", + "com.novocode" % "junit-interface" % "0.10" % "test" + ) + ) diff --git a/.generator/templates/libraries/jersey2/model.mustache b/.generator/templates/libraries/jersey2/model.mustache new file mode 100644 index 00000000000..18ee1211785 --- /dev/null +++ b/.generator/templates/libraries/jersey2/model.mustache @@ -0,0 +1,61 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#useReflectionEqualsHashCode}} +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +{{/useReflectionEqualsHashCode}} +{{#models}} +{{#model}} +{{#additionalPropertiesType}} +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +{{/additionalPropertiesType}} +{{/model}} +{{/models}} +import java.util.Objects; +import java.util.Arrays; +import java.util.Map; +import java.util.HashMap; +{{#imports}} +import {{import}}; +{{/imports}} +{{#serializableModel}} +import java.io.Serializable; +{{/serializableModel}} +{{#jackson}} +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +{{#withXml}} +import com.fasterxml.jackson.dataformat.xml.annotation.*; +{{/withXml}} +{{/jackson}} +{{#withXml}} +import javax.xml.bind.annotation.*; +{{/withXml}} +{{#parcelableModel}} +import android.os.Parcelable; +import android.os.Parcel; +{{/parcelableModel}} +{{#useBeanValidation}} +import javax.validation.constraints.*; +import javax.validation.Valid; +{{/useBeanValidation}} +{{#performBeanValidation}} +import org.hibernate.validator.constraints.*; +{{/performBeanValidation}} +import {{invokerPackage}}.JSON; + +{{#models}} +{{#model}} +{{#oneOf}} +{{#-first}} +import com.fasterxml.jackson.core.type.TypeReference; +{{/-first}} +{{/oneOf}} + +{{#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/.generator/templates/libraries/jersey2/model_anyof_doc.mustache b/.generator/templates/libraries/jersey2/model_anyof_doc.mustache new file mode 100644 index 00000000000..e360aa56e6c --- /dev/null +++ b/.generator/templates/libraries/jersey2/model_anyof_doc.mustache @@ -0,0 +1,38 @@ +# {{classname}} + +{{#description}} +{{&description}} + +{{/description}} +## anyOf schemas +{{#anyOf}} +* [{{{.}}}]({{{.}}}.md) +{{/anyOf}} + +{{#isNullable}} +NOTE: this class is nullable. + +{{/isNullable}} +## Example +```java +// Import classes: +import {{{package}}}.{{{classname}}}; +{{#anyOf}} +import {{{package}}}.{{{.}}}; +{{/anyOf}} + +public class Example { + public static void main(String[] args) { + {{classname}} example{{classname}} = new {{classname}}(); + {{#anyOf}} + + // create a new {{{.}}} + {{{.}}} example{{{.}}} = new {{{.}}}(); + // set {{{classname}}} to {{{.}}} + example{{classname}}.setActualInstance(example{{{.}}}); + // to get back the {{{.}}} set earlier + {{{.}}} test{{{.}}} = ({{{.}}}) example{{classname}}.getActualInstance(); + {{/anyOf}} + } +} +``` diff --git a/.generator/templates/libraries/jersey2/model_doc.mustache b/.generator/templates/libraries/jersey2/model_doc.mustache new file mode 100644 index 00000000000..be1aedcf2f3 --- /dev/null +++ b/.generator/templates/libraries/jersey2/model_doc.mustache @@ -0,0 +1,19 @@ +{{#models}}{{#model}} + +{{#isEnum}} +{{>enum_outer_doc}} +{{/isEnum}} +{{^isEnum}} +{{^oneOf.isEmpty}} +{{>model_oneof_doc}} +{{/oneOf.isEmpty}} +{{^anyOf.isEmpty}} +{{>model_anyof_doc}} +{{/anyOf.isEmpty}} +{{^anyOf}} +{{^oneOf}} +{{>pojo_doc}} +{{/oneOf}} +{{/anyOf}} +{{/isEnum}} +{{/model}}{{/models}} diff --git a/.generator/templates/libraries/jersey2/model_oneof_doc.mustache b/.generator/templates/libraries/jersey2/model_oneof_doc.mustache new file mode 100644 index 00000000000..5fff76c9efa --- /dev/null +++ b/.generator/templates/libraries/jersey2/model_oneof_doc.mustache @@ -0,0 +1,38 @@ +# {{classname}} + +{{#description}} +{{&description}} + +{{/description}} +## oneOf schemas +{{#oneOf}} +* [{{{.}}}]({{{.}}}.md) +{{/oneOf}} + +{{#isNullable}} +NOTE: this class is nullable. + +{{/isNullable}} +## Example +```java +// Import classes: +import {{{package}}}.{{{classname}}}; +{{#oneOf}} +import {{{package}}}.{{{.}}}; +{{/oneOf}} + +public class Example { + public static void main(String[] args) { + {{classname}} example{{classname}} = new {{classname}}(); + {{#oneOf}} + + // create a new {{{.}}} + {{{.}}} example{{{.}}} = new {{{.}}}(); + // set {{{classname}}} to {{{.}}} + example{{classname}}.setActualInstance(example{{{.}}}); + // to get back the {{{.}}} set earlier + {{{.}}} test{{{.}}} = ({{{.}}}) example{{classname}}.getActualInstance(); + {{/oneOf}} + } +} +``` diff --git a/.generator/templates/libraries/jersey2/oneof_model.mustache b/.generator/templates/libraries/jersey2/oneof_model.mustache new file mode 100644 index 00000000000..eb47106559d --- /dev/null +++ b/.generator/templates/libraries/jersey2/oneof_model.mustache @@ -0,0 +1,235 @@ +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.Response; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import {{invokerPackage}}.JSON; + +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} +@JsonDeserialize(using = {{classname}}.{{classname}}Deserializer.class) +@JsonSerialize(using = {{classname}}.{{classname}}Serializer.class) +public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} { + private static final Logger log = Logger.getLogger({{classname}}.class.getName()); + + 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, SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeObject(value.getActualInstance()); + } + } + + 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 IOException, JsonProcessingException { + JsonNode tree = jp.readValueAsTree(); + Object deserialized = null; + {{#useOneOfDiscriminatorLookup}} + {{#discriminator}} + {{classname}} new{{classname}} = new {{classname}}(); + Map result2 = tree.traverse(jp.getCodec()).readValueAs(new TypeReference>() {}); + String discriminatorValue = (String)result2.get("{{{propertyBaseName}}}"); + switch (discriminatorValue) { + {{#mappedModels}} + case "{{{mappingName}}}": + deserialized = tree.traverse(jp.getCodec()).readValueAs({{{modelName}}}.class); + new{{classname}}.setActualInstance(deserialized); + return new{{classname}}; + {{/mappedModels}} + default: + log.log(Level.WARNING, String.format("Failed to lookup discriminator value `%s` for {{classname}}. Possible values:{{#mappedModels}} {{{mappingName}}}{{/mappedModels}}", discriminatorValue)); + } + + {{/discriminator}} + {{/useOneOfDiscriminatorLookup}} + boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS); + int match = 0; + JsonToken token = tree.traverse(jp.getCodec()).nextToken(); + {{#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) { + deserialized = tree.traverse(jp.getCodec()).readValueAs({{{.}}}.class); + // 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; + } + throw new IOException(String.format("Failed deserialization for {{classname}}: %d classes match result, expected 1", match)); + } + + /** + * Handle deserialization of the 'null' value. + */ + @Override + public {{classname}} getNullValue(DeserializationContext ctxt) throws JsonMappingException { + {{#isNullable}} + return null; + {{/isNullable}} + {{^isNullable}} + throw new JsonMappingException(ctxt.getParser(), "{{classname}} cannot be null"); + {{/isNullable}} + } + } + + // 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}}); + } +{{> libraries/jersey2/additional_properties }} + {{#additionalPropertiesType}} + /** + * Return true if this {{name}} object is equal to o. + */ + @Override + public boolean equals(Object o) { + return super.equals(o) && Objects.equals(this.additionalProperties, (({{classname}})o).additionalProperties); + } + + @Override + public int hashCode() { + return Objects.hash(getActualInstance(), isNullable(), getSchemaType(), additionalProperties); + } + {{/additionalPropertiesType}} + {{#oneOf}} + public {{classname}}({{{.}}} o) { + super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + setActualInstance(o); + } + + {{/oneOf}} + static { + {{#oneOf}} + schemas.put("{{{.}}}", new GenericType<{{{.}}}>() { + }); + {{/oneOf}} + 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}} + } + + @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 instanct 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}} +} diff --git a/.generator/templates/libraries/jersey2/pojo.mustache b/.generator/templates/libraries/jersey2/pojo.mustache new file mode 100644 index 00000000000..70fadd299bc --- /dev/null +++ b/.generator/templates/libraries/jersey2/pojo.mustache @@ -0,0 +1,386 @@ +/** + * {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}} + */{{#description}} +@ApiModel(description = "{{{description}}}"){{/description}} +{{#jackson}} +@JsonPropertyOrder({ +{{#vars}} + {{classname}}.JSON_PROPERTY_{{nameInSnakeCase}}{{^-last}},{{/-last}} +{{/vars}} +}) +{{/jackson}} +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} +public class {{classname}} {{#parent}}extends {{{parent}}} {{/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}} + {{^vendorExtensions.x-enum-as-string}} +{{>modelInnerEnum}} + {{/vendorExtensions.x-enum-as-string}} + {{/isContainer}} + {{#isContainer}} + {{#mostInnerItems}} +{{>modelInnerEnum}} + {{/mostInnerItems}} + {{/isContainer}} + {{/isEnum}} + {{#gson}} + public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}"; + {{/gson}} + {{#jackson}} + public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}"; + {{/jackson}} + {{#withXml}} + {{#isXmlAttribute}} + @XmlAttribute(name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlAttribute}} + {{^isXmlAttribute}} + {{^isContainer}} + @XmlElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isContainer}} + {{#isContainer}} + // Is a container wrapped={{isXmlWrapped}} + {{#items}} + // items.name={{name}} items.baseName={{baseName}} items.xmlName={{xmlName}} items.xmlNamespace={{xmlNamespace}} + // items.example={{example}} items.type={{dataType}} + @XmlElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/items}} + {{#isXmlWrapped}} + @XmlElementWrapper({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlWrapped}} + {{/isContainer}} + {{/isXmlAttribute}} + {{/withXml}} + {{#gson}} + @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}}) + {{/gson}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#isContainer}} + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined(); + {{/isContainer}} + {{^isContainer}} + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + {{/isContainer}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{#isContainer}} + private {{{datatypeWithEnum}}} {{name}}{{#required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/required}}{{^required}} = null{{/required}}; + {{/isContainer}} + {{^isContainer}} + private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; + {{/isContainer}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + + {{/vars}} + {{#parcelableModel}} + public {{classname}}() { + {{#parent}} + super(); + {{/parent}} + {{#gson}} + {{#discriminator}} + this.{{{discriminatorName}}} = this.getClass().getSimpleName(); + {{/discriminator}} + {{/gson}} + } + {{/parcelableModel}} + {{^parcelableModel}} + {{#gson}} + {{#discriminator}} + public {{classname}}() { + this.{{{discriminatorName}}} = this.getClass().getSimpleName(); + } + {{/discriminator}} + {{/gson}} + {{/parcelableModel}} + {{#vars}} + + {{^isReadOnly}} + {{#vendorExtensions.x-enum-as-string}} + public static final Set {{{nameInSnakeCase}}}_VALUES = new HashSet<>(Arrays.asList( + {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}} + )); + + {{/vendorExtensions.x-enum-as-string}} + public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-enum-as-string}} + if (!{{{nameInSnakeCase}}}_VALUES.contains({{name}})) { + throw new IllegalArgumentException({{name}} + " is invalid. Possible values for {{name}}: " + String.join(", ", {{{nameInSnakeCase}}}_VALUES)); + } + + {{/vendorExtensions.x-enum-as-string}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + return this; + } + {{#isArray}} + + public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null || !this.{{name}}.isPresent()) { + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); + } + try { + this.{{name}}.get().add({{name}}Item); + } catch (java.util.NoSuchElementException e) { + // this can never happen, as we make sure above that the value is present + } + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.add({{name}}Item); + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isArray}} + {{#isMap}} + + public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null || !this.{{name}}.isPresent()) { + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); + } + try { + this.{{name}}.get().put(key, {{name}}Item); + } catch (java.util.NoSuchElementException e) { + // this can never happen, as we make sure above that the value is present + } + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.put(key, {{name}}Item); + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isMap}} + + {{/isReadOnly}} + /** + {{#description}} + * {{description}} + {{/description}} + {{^description}} + * Get {{name}} + {{/description}} + {{#minimum}} + * minimum: {{minimum}} + {{/minimum}} + {{#maximum}} + * maximum: {{maximum}} + {{/maximum}} + * @return {{name}} + **/ +{{#required}} +{{#isNullable}} + @javax.annotation.Nullable +{{/isNullable}} +{{/required}} +{{^required}} + @javax.annotation.Nullable +{{/required}} +{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} @ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") +{{#vendorExtensions.x-extra-annotation}} + {{{vendorExtensions.x-extra-annotation}}} +{{/vendorExtensions.x-extra-annotation}} +{{#vendorExtensions.x-is-jackson-optional-nullable}} + {{!unannotated, Jackson would pick this up automatically and add it *in addition* to the _JsonNullable getter field}} + @JsonIgnore +{{/vendorExtensions.x-is-jackson-optional-nullable}} +{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#jackson}}{{> jackson_annotations}}{{/jackson}}{{/vendorExtensions.x-is-jackson-optional-nullable}} + public {{{datatypeWithEnum}}} {{getter}}() { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#isReadOnly}}{{! A readonly attribute doesn't have setter => jackson will set null directly if explicitly returned by API, so make sure we have an empty JsonNullable}} + if ({{name}} == null) { + {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + } + {{/isReadOnly}} + return {{name}}.orElse(null); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + return {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + + {{#vendorExtensions.x-is-jackson-optional-nullable}} +{{> jackson_annotations}} + public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}_JsonNullable() { + return {{name}}; + } + {{/vendorExtensions.x-is-jackson-optional-nullable}}{{#vendorExtensions.x-is-jackson-optional-nullable}} + @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) + {{#isReadOnly}}private{{/isReadOnly}}{{^isReadOnly}}public{{/isReadOnly}} void {{setter}}_JsonNullable(JsonNullable<{{{datatypeWithEnum}}}> {{name}}) { + {{! For getters/setters that have name differing from attribute name, we must include setter (albeit private) for jackson to be able to set the attribute}} + this.{{name}} = {{name}}; + } + {{/vendorExtensions.x-is-jackson-optional-nullable}} + + {{^isReadOnly}} + public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-enum-as-string}} + if (!{{{nameInSnakeCase}}}_VALUES.contains({{name}})) { + throw new IllegalArgumentException({{name}} + " is invalid. Possible values for {{name}}: " + String.join(", ", {{{nameInSnakeCase}}}_VALUES)); + } + + {{/vendorExtensions.x-enum-as-string}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isReadOnly}} + + {{/vars}} +{{>libraries/jersey2/additional_properties}} + /** + * Return true if this {{name}} object is equal to o. + */ + @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}}{{#additionalPropertiesType}}&& + Objects.equals(this.additionalProperties, {{classVarName}}.additionalProperties){{/additionalPropertiesType}}{{#parent}} && + super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} + return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}} + {{/useReflectionEqualsHashCode}} + } + + @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}}{{#additionalPropertiesType}}{{#hasVars}}, {{/hasVars}}{{^hasVars}}{{#parent}}, {{/parent}}{{/hasVars}}additionalProperties{{/additionalPropertiesType}}); + {{/useReflectionEqualsHashCode}} + } + + @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(toIndentedString({{name}})).append("\n"); + {{/vars}} + {{#additionalPropertiesType}} + sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n"); + {{/additionalPropertiesType}} + 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) { + if (o == null) { + return "null"; + } + return 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}} +{{#discriminator}} +static { + // 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}} +} diff --git a/.generator/templates/libraries/jersey2/pom.mustache b/.generator/templates/libraries/jersey2/pom.mustache new file mode 100644 index 00000000000..f36f0cd8817 --- /dev/null +++ b/.generator/templates/libraries/jersey2/pom.mustache @@ -0,0 +1,391 @@ + + 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-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M4 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + 10 + false + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.6 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + {{#java8}} + 1.8 + 1.8 + {{/java8}} + {{^java8}} + 1.7 + 1.7 + {{/java8}} + true + 128m + 512m + + -Xlint:all + -J-Xss4m + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.1 + + + attach-javadocs + + jar + + + + + none + {{#java8}} + 1.8 + {{/java8}} + {{^java8}} + 1.7 + {{/java8}} + + + http.response.details + a + Http Response Details: + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + + + org.glassfish.jersey.core + jersey-client + ${jersey-version} + + + org.glassfish.jersey.inject + jersey-hk2 + ${jersey-version} + + + org.glassfish.jersey.media + jersey-media-multipart + ${jersey-version} + + + org.glassfish.jersey.media + jersey-media-json-jackson + ${jersey-version} + + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-databind-version} + + {{#openApiNullable}} + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + + {{/openApiNullable}} + {{#withXml}} + + + org.glassfish.jersey.media + jersey-media-jaxb + ${jersey-version} + + {{/withXml}} + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + {{/joda}} + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{/java8}} + {{#threetenbp}} + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${threetenbp-version} + + {{/threetenbp}} + {{^java8}} + + + com.brsanthu + migbase64 + 2.2 + + {{/java8}} + {{#hasHttpSignatureMethods}} + + org.tomitribe + tomitribe-http-signatures + ${http-signature-version} + + {{/hasHttpSignatureMethods}} + {{#hasOAuthMethods}} + + com.github.scribejava + scribejava-apis + ${scribejava-apis-version} + + {{/hasOAuthMethods}} + {{#useBeanValidation}} + + + javax.validation + validation-api + 1.1.0.Final + provided + + {{/useBeanValidation}} + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + + + org.glassfish.jersey.connectors + jersey-apache-connector + ${jersey-version} + + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.6.1 + 2.30.1 + 2.10.5 + 2.10.5.1 + 0.2.1 + {{#threetenbp}} + 2.9.10 + {{/threetenbp}} + 1.3.2 + 4.13.1 + {{#hasHttpSignatureMethods}} + 1.5 + {{/hasHttpSignatureMethods}} + {{#hasOAuthMethods}} + 6.9.0 + {{/hasOAuthMethods}} + + diff --git a/.generator/templates/libraries/microprofile/README.mustache b/.generator/templates/libraries/microprofile/README.mustache new file mode 100644 index 00000000000..8d126ada313 --- /dev/null +++ b/.generator/templates/libraries/microprofile/README.mustache @@ -0,0 +1,10 @@ +# {{appName}} - MicroProfile Rest Client + +{{#appDescriptionWithNewLines}} +{{{appDescriptionWithNewLines}}} + +{{/appDescriptionWithNewLines}} +## Overview +This API client was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. +[MicroProfile Rest Client](https://github.com/eclipse/microprofile-rest-client) is a type-safe way of calling +REST services. The generated client contains an interface which acts as the client, you can inject it into dependent classes. diff --git a/.generator/templates/libraries/microprofile/api.mustache b/.generator/templates/libraries/microprofile/api.mustache new file mode 100644 index 00000000000..b9e8dad8cef --- /dev/null +++ b/.generator/templates/libraries/microprofile/api.mustache @@ -0,0 +1,61 @@ +{{>licenseInfo}} +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} + +import java.io.InputStream; +import java.io.OutputStream; +import java.util.List; +import java.util.Map; +import javax.ws.rs.*; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.MediaType; +{{^disableMultipart}} +import org.apache.cxf.jaxrs.ext.multipart.*; +{{/disableMultipart}} + +import org.eclipse.microprofile.rest.client.annotation.RegisterProvider; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +{{#appName}} +/** + * {{{appName}}} + * + {{#appDescription}} + *

{{{appDescription}}} + * + {{/appDescription}} + */ +{{/appName}} + +@RegisterRestClient +@RegisterProvider(ApiExceptionMapper.class) +@Path("{{#useAnnotatedBasePath}}{{contextPath}}{{/useAnnotatedBasePath}}{{commonPath}}") +public interface {{classname}} { +{{#operations}} +{{#operation}} + + {{#summary}} + /** + * {{summary}} + * + {{#notes}} + * {{notes}} + * + {{/notes}} + */ + {{/summary}} + @{{httpMethod}} + {{#subresourceOperation}}@Path("{{{path}}}"){{/subresourceOperation}} +{{#hasConsumes}} + @Consumes({ {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} }) +{{/hasConsumes}} +{{#hasProduces}} + @Produces({ {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} }) +{{/hasProduces}} + public {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{nickname}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException, ProcessingException; +{{/operation}} +} +{{/operations}} + diff --git a/.generator/templates/libraries/microprofile/api_exception.mustache b/.generator/templates/libraries/microprofile/api_exception.mustache new file mode 100644 index 00000000000..fc5c5e5000a --- /dev/null +++ b/.generator/templates/libraries/microprofile/api_exception.mustache @@ -0,0 +1,23 @@ +{{>licenseInfo}} +package {{apiPackage}}; + +import javax.ws.rs.core.Response; + +public class ApiException extends Exception { + + private static final long serialVersionUID = 1L; + private Response response; + + public ApiException() { + super(); + } + + public ApiException(Response response) { + super("Api response has status code " + response.getStatus()); + this.response = response; + } + + public Response getResponse() { + return this.response; + } +} diff --git a/.generator/templates/libraries/microprofile/api_exception_mapper.mustache b/.generator/templates/libraries/microprofile/api_exception_mapper.mustache new file mode 100644 index 00000000000..9c5988414cd --- /dev/null +++ b/.generator/templates/libraries/microprofile/api_exception_mapper.mustache @@ -0,0 +1,22 @@ +{{>licenseInfo}} +package {{apiPackage}}; + +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.Provider; +import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper; + +@Provider +public class ApiExceptionMapper + implements ResponseExceptionMapper { + + @Override + public boolean handles(int status, MultivaluedMap headers) { + return status >= 400; + } + + @Override + public ApiException toThrowable(Response response) { + return new ApiException(response); + } +} diff --git a/.generator/templates/libraries/microprofile/api_test.mustache b/.generator/templates/libraries/microprofile/api_test.mustache new file mode 100644 index 00000000000..e0ed40ef88b --- /dev/null +++ b/.generator/templates/libraries/microprofile/api_test.mustache @@ -0,0 +1,75 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Test; +import org.junit.Before; +import static org.junit.Assert.*; + +import org.eclipse.microprofile.rest.client.RestClientBuilder; + +import java.net.URL; +import java.net.MalformedURLException; +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + + + +/** + {{#appName}} + * {{{appName}}} Test + * + {{/appName}} + * API tests for {{classname}} + */ +{{#generateSpringBootApplication}} +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = SpringBootApplication.class) +@WebAppConfiguration +@IntegrationTest("server.port=0") +{{/generateSpringBootApplication}} +public class {{classname}}Test { + + private {{classname}} client; + private String baseUrl = "http://localhost:9080"; + + @Before + public void setup() throws MalformedURLException { + client = RestClientBuilder.newBuilder() + .baseUrl(new URL(baseUrl)) + .register(ApiException.class) + .build({{classname}}.class); + } + + {{#operations}}{{#operation}} + /** + {{#summary}} + * {{summary}} + * + {{#notes}} + * {{notes}} + * + {{/notes}} + {{/summary}} + * @throws ApiException + * if the Api call fails + */ + @Test + public void {{operationId}}Test() { + // TODO: test validations + {{#allParams}} + {{^isFile}}{{{dataType}}} {{paramName}} = null;{{/isFile}}{{#isFile}}org.apache.cxf.jaxrs.ext.multipart.Attachment {{paramName}} = null;{{/isFile}} + {{/allParams}} + //{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + //{{#returnType}}assertNotNull(response);{{/returnType}} + + + } + {{/operation}}{{/operations}} +} diff --git a/.generator/templates/libraries/microprofile/beanValidation.mustache b/.generator/templates/libraries/microprofile/beanValidation.mustache new file mode 100644 index 00000000000..c8c6946fef6 --- /dev/null +++ b/.generator/templates/libraries/microprofile/beanValidation.mustache @@ -0,0 +1,4 @@ +{{#required}} + @NotNull +{{/required}} +{{>beanValidationCore}} \ No newline at end of file diff --git a/.generator/templates/libraries/microprofile/beanValidationCore.mustache b/.generator/templates/libraries/microprofile/beanValidationCore.mustache new file mode 100644 index 00000000000..8bcdce3df16 --- /dev/null +++ b/.generator/templates/libraries/microprofile/beanValidationCore.mustache @@ -0,0 +1,20 @@ +{{#pattern}} @Pattern(regexp="{{{pattern}}}"){{/pattern}}{{! +minLength && maxLength set +}}{{#minLength}}{{#maxLength}} @Size(min={{minLength}},max={{maxLength}}){{/maxLength}}{{/minLength}}{{! +minLength set, maxLength not +}}{{#minLength}}{{^maxLength}} @Size(min={{minLength}}){{/maxLength}}{{/minLength}}{{! +minLength not set, maxLength set +}}{{^minLength}}{{#maxLength}} @Size(max={{maxLength}}){{/maxLength}}{{/minLength}}{{! +@Size: minItems && maxItems set +}}{{#minItems}}{{#maxItems}} @Size(min={{minItems}},max={{maxItems}}){{/maxItems}}{{/minItems}}{{! +@Size: minItems set, maxItems not +}}{{#minItems}}{{^maxItems}} @Size(min={{minItems}}){{/maxItems}}{{/minItems}}{{! +@Size: minItems not set && maxItems set +}}{{^minItems}}{{#maxItems}} @Size(max={{maxItems}}){{/maxItems}}{{/minItems}}{{! +check for integer or long / all others=decimal type with @Decimal* +isInteger set +}}{{#isInteger}}{{#minimum}} @Min({{minimum}}){{/minimum}}{{#maximum}} @Max({{maximum}}){{/maximum}}{{/isInteger}}{{! +isLong set +}}{{#isLong}}{{#minimum}} @Min({{minimum}}L){{/minimum}}{{#maximum}} @Max({{maximum}}L){{/maximum}}{{/isLong}}{{! +Not Integer, not Long => we have a decimal value! +}}{{^isInteger}}{{^isLong}}{{#minimum}} @DecimalMin("{{minimum}}"){{/minimum}}{{#maximum}} @DecimalMax("{{maximum}}"){{/maximum}}{{/isLong}}{{/isInteger}} \ No newline at end of file diff --git a/.generator/templates/libraries/microprofile/beanValidationHeaderParams.mustache b/.generator/templates/libraries/microprofile/beanValidationHeaderParams.mustache new file mode 100644 index 00000000000..f8eef8f94c7 --- /dev/null +++ b/.generator/templates/libraries/microprofile/beanValidationHeaderParams.mustache @@ -0,0 +1 @@ +{{#required}} @NotNull{{/required}}{{>beanValidationCore}} \ No newline at end of file diff --git a/.generator/templates/libraries/microprofile/beanValidationPathParams.mustache b/.generator/templates/libraries/microprofile/beanValidationPathParams.mustache new file mode 100644 index 00000000000..051bd53c0a5 --- /dev/null +++ b/.generator/templates/libraries/microprofile/beanValidationPathParams.mustache @@ -0,0 +1 @@ +{{! PathParam is always required, no @NotNull necessary }}{{>beanValidationCore}} \ No newline at end of file diff --git a/.generator/templates/libraries/microprofile/beanValidationQueryParams.mustache b/.generator/templates/libraries/microprofile/beanValidationQueryParams.mustache new file mode 100644 index 00000000000..f8eef8f94c7 --- /dev/null +++ b/.generator/templates/libraries/microprofile/beanValidationQueryParams.mustache @@ -0,0 +1 @@ +{{#required}} @NotNull{{/required}}{{>beanValidationCore}} \ No newline at end of file diff --git a/.generator/templates/libraries/microprofile/bodyParams.mustache b/.generator/templates/libraries/microprofile/bodyParams.mustache new file mode 100644 index 00000000000..be56da7535b --- /dev/null +++ b/.generator/templates/libraries/microprofile/bodyParams.mustache @@ -0,0 +1 @@ +{{#isBodyParam}}{{#useBeanValidation}}@Valid {{/useBeanValidation}}{{{dataType}}} {{paramName}}{{/isBodyParam}} \ No newline at end of file diff --git a/.generator/templates/libraries/microprofile/bodyParamsImpl.mustache b/.generator/templates/libraries/microprofile/bodyParamsImpl.mustache new file mode 100644 index 00000000000..c7d1abfe527 --- /dev/null +++ b/.generator/templates/libraries/microprofile/bodyParamsImpl.mustache @@ -0,0 +1 @@ +{{#isBodyParam}}{{{dataType}}} {{paramName}}{{/isBodyParam}} \ No newline at end of file diff --git a/.generator/templates/libraries/microprofile/enumClass.mustache b/.generator/templates/libraries/microprofile/enumClass.mustache new file mode 100644 index 00000000000..87d5ee699a5 --- /dev/null +++ b/.generator/templates/libraries/microprofile/enumClass.mustache @@ -0,0 +1,66 @@ +{{#withXml}} +@XmlType(name="{{datatypeWithEnum}}") +@XmlEnum({{dataType}}.class) +{{/withXml}} +{{^withXml}} + @JsonbTypeSerializer({{datatypeWithEnum}}.Serializer.class) + @JsonbTypeDeserializer({{datatypeWithEnum}}.Deserializer.class) +{{/withXml}} + {{>additionalEnumTypeAnnotations}}public enum {{datatypeWithEnum}} { + + {{#allowableValues}} + {{#withXml}} + {{#enumVars}}@XmlEnumValue({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) {{name}}({{dataType}}.valueOf({{{value}}})){{^-last}}, {{/-last}}{{#-last}};{{/-last}}{{/enumVars}} + {{/withXml}} + {{^withXml}} + {{#enumVars}}{{name}}({{dataType}}.valueOf({{{value}}})){{^-last}}, {{/-last}}{{#-last}};{{/-last}}{{/enumVars}} + {{/withXml}} + {{/allowableValues}} + + + {{dataType}} value; + + {{datatypeWithEnum}} ({{dataType}} v) { + value = v; + } + + public {{dataType}} value() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + + {{#withXml}} + public static {{datatypeWithEnum}} fromValue(String v) { + for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + if (String.valueOf(b.value).equals(v)) { + return b; + } + } + {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + v + "'");{{/useNullForUnknownEnumValue}} + } + {{/withXml}} + {{^withXml}} + public static final class Deserializer implements JsonbDeserializer<{{datatypeWithEnum}}> { + @Override + public {{datatypeWithEnum}} deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) { + for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + if (String.valueOf(b.value).equals(parser.getString())) { + return b; + } + } + {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + parser.getString() + "'");{{/useNullForUnknownEnumValue}} + } + } + + public static final class Serializer implements JsonbSerializer<{{datatypeWithEnum}}> { + @Override + public void serialize({{datatypeWithEnum}} obj, JsonGenerator generator, SerializationContext ctx) { + generator.write(obj.value); + } + } + {{/withXml}} + } diff --git a/.generator/templates/libraries/microprofile/enumOuterClass.mustache b/.generator/templates/libraries/microprofile/enumOuterClass.mustache new file mode 100644 index 00000000000..c56eca64b1e --- /dev/null +++ b/.generator/templates/libraries/microprofile/enumOuterClass.mustache @@ -0,0 +1,48 @@ +{{#jackson}} +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +{{/jackson}} + +/** + * {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}} + */ +{{>additionalEnumTypeAnnotations}}public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} { + {{#gson}} + {{#allowableValues}}{{#enumVars}} + @SerializedName({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) + {{{name}}}({{{value}}}){{^-last}}, + {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}} + {{/gson}} + {{^gson}} + {{#allowableValues}}{{#enumVars}} + {{{name}}}({{{value}}}){{^-last}}, + {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}} + {{/gson}} + + private {{{dataType}}} value; + + {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) { + this.value = value; + } + + @Override +{{#jackson}} + @JsonValue +{{/jackson}} + public String toString() { + return String.valueOf(value); + } + +{{#jackson}} + @JsonCreator +{{/jackson}} + public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue(String text) { + for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + if (String.valueOf(b.value).equals(text)) { + return b; + } + } + {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + text + "'");{{/useNullForUnknownEnumValue}} + } + +} diff --git a/.generator/templates/libraries/microprofile/formParams.mustache b/.generator/templates/libraries/microprofile/formParams.mustache new file mode 100644 index 00000000000..97216dc1806 --- /dev/null +++ b/.generator/templates/libraries/microprofile/formParams.mustache @@ -0,0 +1 @@ +{{#isFormParam}}{{^isFile}}@Multipart(value = "{{baseName}}"{{^required}}, required = false{{/required}}) {{{dataType}}} {{paramName}}{{/isFile}}{{#isFile}} @Multipart(value = "{{baseName}}" {{^required}}, required = false{{/required}}) Attachment {{paramName}}Detail{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/.generator/templates/libraries/microprofile/formParamsImpl.mustache b/.generator/templates/libraries/microprofile/formParamsImpl.mustache new file mode 100644 index 00000000000..2be40e1ddd3 --- /dev/null +++ b/.generator/templates/libraries/microprofile/formParamsImpl.mustache @@ -0,0 +1 @@ +{{#isFormParam}}{{^isFile}}{{{dataType}}} {{paramName}}{{/isFile}}{{#isFile}} Attachment {{paramName}}Detail{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/.generator/templates/libraries/microprofile/generatedAnnotation.mustache b/.generator/templates/libraries/microprofile/generatedAnnotation.mustache new file mode 100644 index 00000000000..875d7b97afe --- /dev/null +++ b/.generator/templates/libraries/microprofile/generatedAnnotation.mustache @@ -0,0 +1 @@ +@javax.annotation.Generated(value = "{{generatorClass}}"{{^hideGenerationTimestamp}}, date = "{{generatedDate}}"{{/hideGenerationTimestamp}}) \ No newline at end of file diff --git a/.generator/templates/libraries/microprofile/headerParams.mustache b/.generator/templates/libraries/microprofile/headerParams.mustache new file mode 100644 index 00000000000..4a9009e76a2 --- /dev/null +++ b/.generator/templates/libraries/microprofile/headerParams.mustache @@ -0,0 +1 @@ +{{#isHeaderParam}}@HeaderParam("{{baseName}}") {{#useBeanValidation}}{{>beanValidationHeaderParams}}{{/useBeanValidation}} {{{dataType}}} {{paramName}}{{/isHeaderParam}} \ No newline at end of file diff --git a/.generator/templates/libraries/microprofile/headerParamsImpl.mustache b/.generator/templates/libraries/microprofile/headerParamsImpl.mustache new file mode 100644 index 00000000000..bd03573d196 --- /dev/null +++ b/.generator/templates/libraries/microprofile/headerParamsImpl.mustache @@ -0,0 +1 @@ +{{#isHeaderParam}}{{{dataType}}} {{paramName}}{{/isHeaderParam}} \ No newline at end of file diff --git a/.generator/templates/libraries/microprofile/kumuluzee.beans.xml.mustache b/.generator/templates/libraries/microprofile/kumuluzee.beans.xml.mustache new file mode 100644 index 00000000000..29549d01d2c --- /dev/null +++ b/.generator/templates/libraries/microprofile/kumuluzee.beans.xml.mustache @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/.generator/templates/libraries/microprofile/kumuluzee.config.yaml.mustache b/.generator/templates/libraries/microprofile/kumuluzee.config.yaml.mustache new file mode 100644 index 00000000000..90f5237eb99 --- /dev/null +++ b/.generator/templates/libraries/microprofile/kumuluzee.config.yaml.mustache @@ -0,0 +1,10 @@ +kumuluzee: + server: + http: + port: 8081 + + rest-client: + registrations: + {{#apiInfo}}{{#apis}}{{#operations}}- class: {{{invokerPackage}}}.{{{classname}}} + url: http://localhost:8080/v2 + {{/operations}}{{/apis}}{{/apiInfo}} \ No newline at end of file diff --git a/.generator/templates/libraries/microprofile/kumuluzee.pom.mustache b/.generator/templates/libraries/microprofile/kumuluzee.pom.mustache new file mode 100644 index 00000000000..ac235b7edf5 --- /dev/null +++ b/.generator/templates/libraries/microprofile/kumuluzee.pom.mustache @@ -0,0 +1,98 @@ + + 4.0.0 + + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + 1.0.0-SNAPSHOT + + + 1.8 + 1.8 + UTF-8 + + 3.9.0 + 1.2.3 + 1.4.1 + 3.2.6 + 4.13 + 2.28 + + + + + + com.kumuluz.ee + kumuluzee-bom + ${kumuluzee.version} + pom + import + + + + + + + com.kumuluz.ee + kumuluzee-core + + + com.kumuluz.ee + kumuluzee-servlet-jetty + + + com.kumuluz.ee + kumuluzee-jax-rs-jersey + + + com.kumuluz.ee + kumuluzee-cdi-weld + + + com.kumuluz.ee + kumuluzee-json-p-jsonp + + + com.kumuluz.ee + kumuluzee-json-b-yasson + + + com.kumuluz.ee.rest-client + kumuluzee-rest-client + ${kumuluzee-rest-client.version} + + + org.apache.cxf + cxf-rt-rs-extension-providers + ${cxf-rt-rs-extension-providers.version} + + + junit + junit + ${junit-version} + test + + + + + + + com.kumuluz.ee + kumuluzee-maven-plugin + ${kumuluzee.version} + + + package + + repackage + + + + + + + + \ No newline at end of file diff --git a/.generator/templates/libraries/microprofile/licenseInfo.mustache b/.generator/templates/libraries/microprofile/licenseInfo.mustache new file mode 100644 index 00000000000..9866f297a4d --- /dev/null +++ b/.generator/templates/libraries/microprofile/licenseInfo.mustache @@ -0,0 +1,11 @@ +/** + * {{{appName}}} + * {{{appDescription}}} + * + * {{#version}}The version of the OpenAPI document: {{{version}}}{{/version}} + * {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}} + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ diff --git a/.generator/templates/libraries/microprofile/model.mustache b/.generator/templates/libraries/microprofile/model.mustache new file mode 100644 index 00000000000..5272ff09487 --- /dev/null +++ b/.generator/templates/libraries/microprofile/model.mustache @@ -0,0 +1,23 @@ +{{>licenseInfo}} +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +{{#serializableModel}} +import java.io.Serializable; +{{/serializableModel}} +{{#useBeanValidation}} +import javax.validation.constraints.*; +import javax.validation.Valid; +{{/useBeanValidation}} + +{{#models}} +{{#model}} +{{#isEnum}} +{{>enumOuterClass}} +{{/isEnum}} +{{^isEnum}} +{{>pojo}} +{{/isEnum}} +{{/model}} +{{/models}} diff --git a/.generator/templates/libraries/microprofile/pathParams.mustache b/.generator/templates/libraries/microprofile/pathParams.mustache new file mode 100644 index 00000000000..9e8455d5ac7 --- /dev/null +++ b/.generator/templates/libraries/microprofile/pathParams.mustache @@ -0,0 +1 @@ +{{#isPathParam}}@PathParam("{{baseName}}"){{#useBeanValidation}}{{>beanValidationPathParams}}{{/useBeanValidation}} {{{dataType}}} {{paramName}}{{/isPathParam}} \ No newline at end of file diff --git a/.generator/templates/libraries/microprofile/pathParamsImpl.mustache b/.generator/templates/libraries/microprofile/pathParamsImpl.mustache new file mode 100644 index 00000000000..6829cf8c7a6 --- /dev/null +++ b/.generator/templates/libraries/microprofile/pathParamsImpl.mustache @@ -0,0 +1 @@ +{{#isPathParam}}{{{dataType}}} {{paramName}}{{/isPathParam}} \ No newline at end of file diff --git a/.generator/templates/libraries/microprofile/pojo.mustache b/.generator/templates/libraries/microprofile/pojo.mustache new file mode 100644 index 00000000000..24e6e7e7d05 --- /dev/null +++ b/.generator/templates/libraries/microprofile/pojo.mustache @@ -0,0 +1,147 @@ +{{#withXml}} +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlEnumValue; +{{/withXml}} +{{^withXml}} +import java.lang.reflect.Type; +import javax.json.bind.annotation.JsonbTypeDeserializer; +import javax.json.bind.annotation.JsonbTypeSerializer; +import javax.json.bind.serializer.DeserializationContext; +import javax.json.bind.serializer.JsonbDeserializer; +import javax.json.bind.serializer.JsonbSerializer; +import javax.json.bind.serializer.SerializationContext; +import javax.json.stream.JsonGenerator; +import javax.json.stream.JsonParser; +import javax.json.bind.annotation.JsonbProperty; +{{/withXml}} + +{{#withXml}} +@XmlAccessorType(XmlAccessType.FIELD) +{{#hasVars}} @XmlType(name = "{{classname}}", propOrder = + { {{#vars}}"{{name}}"{{^-last}}, {{/-last}}{{/vars}} +}){{/hasVars}} +{{^hasVars}}@XmlType(name = "{{classname}}"){{/hasVars}} +{{^parent}}@XmlRootElement(name="{{classname}}"){{/parent}} +{{/withXml}} +{{#description}} +/** + * {{{description}}} + **/ +{{/description}} +{{>additionalModelTypeAnnotations}} +public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}}{{#serializableModel}} implements Serializable{{/serializableModel}} { + {{#vars}}{{#isEnum}}{{^isContainer}} +{{>enumClass}}{{/isContainer}}{{#isContainer}}{{#mostInnerItems}} +{{>enumClass}}{{/mostInnerItems}}{{/isContainer}}{{/isEnum}} +{{#withXml}} + @XmlElement(name="{{baseName}}"{{#required}}, required = {{required}}{{/required}}) +{{/withXml}} +{{#description}} + /** + * {{{description}}} + **/ +{{/description}} +{{#isContainer}} + private {{{datatypeWithEnum}}} {{name}}{{#required}} = {{{defaultValue}}}{{/required}}{{^required}} = null{{/required}}; +{{/isContainer}} +{{^isContainer}} + private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; +{{/isContainer}} + {{/vars}} + + {{#vars}} + /** + {{#description}} + * {{description}} + {{/description}} + {{^description}} + * Get {{name}} + {{/description}} + {{#minimum}} + * minimum: {{minimum}} + {{/minimum}} + {{#maximum}} + * maximum: {{maximum}} + {{/maximum}} + * @return {{name}} + **/ + {{^withXml}} + @JsonbProperty("{{baseName}}") + {{/withXml}} +{{#vendorExtensions.x-extra-annotation}} + {{{vendorExtensions.x-extra-annotation}}} +{{/vendorExtensions.x-extra-annotation}} +{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} {{#withXml}}{{#isEnum}}{{^isArray}}{{^isMap}}public {{dataType}} {{getter}}() { + if ({{name}} == null) { + return null; + } + return {{name}}.value(); + }{{/isMap}}{{/isArray}}{{/isEnum}}{{/withXml}}{{^withXml}}{{#isEnum}}{{^isArray}}{{^isMap}}public {{datatypeWithEnum}} {{getter}}() { + return {{name}}; + }{{/isMap}}{{/isArray}}{{/isEnum}}{{/withXml}}{{#isEnum}}{{#isArray}}public {{{datatypeWithEnum}}} {{getter}}() { + return {{name}}; + }{{/isArray}}{{/isEnum}}{{#isEnum}}{{#isMap}}public {{{datatypeWithEnum}}} {{getter}}() { + return {{name}}; + }{{/isMap}}{{/isEnum}}{{^isEnum}}public {{{datatypeWithEnum}}} {{getter}}() { + return {{name}}; + }{{/isEnum}} + + {{^isReadOnly}} + /** + * Set {{name}} + **/ + public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { + this.{{name}} = {{name}}; + } + + public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { + this.{{name}} = {{name}}; + return this; + } + {{#isArray}} + + public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { + this.{{name}}.add({{name}}Item); + return this; + } + {{/isArray}} + {{#isMap}} + + public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { + this.{{name}}.put(key, {{name}}Item); + return this; + } + {{/isMap}} + {{/isReadOnly}} + + {{/vars}} + + /** + * Create a string representation of this pojo. + **/ + @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(toIndentedString({{name}})).append("\n"); + {{/vars}}sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private static String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/.generator/templates/libraries/microprofile/pom.mustache b/.generator/templates/libraries/microprofile/pom.mustache new file mode 100644 index 00000000000..63321ae28bb --- /dev/null +++ b/.generator/templates/libraries/microprofile/pom.mustache @@ -0,0 +1,183 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{#appDescription}} + {{appDescription}} + {{/appDescription}} + {{artifactVersion}} + + src/main/java + + + maven-failsafe-plugin + 2.6 + + + + integration-test + verify + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.9.1 + + + add-source + generate-sources + + add-source + + + + src/gen/java + + + + + + + + + + junit + junit + ${junit-version} + test + +{{#useBeanValidation}} + + + javax.validation + validation-api + ${beanvalidation-version} + provided + +{{/useBeanValidation}} + + + org.eclipse.microprofile.rest.client + microprofile-rest-client-api + 1.2.1 + + + + + javax.ws.rs + javax.ws.rs-api + 2.1.1 + provided + + + + io.smallrye + smallrye-rest-client + 1.2.1 + test + + + + io.smallrye + smallrye-config + 1.3.5 + test + + {{^disableMultipart}} + + org.apache.cxf + cxf-rt-rs-extension-providers + 3.2.6 + + {{/disableMultipart}} + + javax.json.bind + javax.json.bind-api + 1.0 + + + javax.json + javax.json-api + 1.1.4 + + + javax.xml.bind + jaxb-api + 2.2.11 + + + com.sun.xml.bind + jaxb-core + 2.2.11 + + + com.sun.xml.bind + jaxb-impl + 2.2.11 + + + javax.activation + activation + 1.1.1 + + +{{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-jaxrs-version} + +{{/java8}} +{{^java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-jaxrs-version} + +{{/java8}} +{{#useBeanValidationFeature}} + + org.hibernate + hibernate-validator + 5.2.2.Final + +{{/useBeanValidationFeature}} + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + + + + + sonatype-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + true + + + + + 1.8 + ${java.version} + ${java.version} + 1.5.18 + 9.2.9.v20150224 + 4.13.1 + 1.1.7 + 2.5 +{{#useBeanValidation}} + 1.1.0.Final +{{/useBeanValidation}} + 3.2.7 + 2.9.7 + 1.3.2 + UTF-8 + + diff --git a/.generator/templates/libraries/microprofile/queryParams.mustache b/.generator/templates/libraries/microprofile/queryParams.mustache new file mode 100644 index 00000000000..f89529fdb5d --- /dev/null +++ b/.generator/templates/libraries/microprofile/queryParams.mustache @@ -0,0 +1 @@ +{{#isQueryParam}}@QueryParam("{{baseName}}"){{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}} {{^isContainer}}{{#defaultValue}}@DefaultValue("{{{defaultValue}}}") {{/defaultValue}}{{/isContainer}}{{{dataType}}} {{paramName}}{{/isQueryParam}} \ No newline at end of file diff --git a/.generator/templates/libraries/microprofile/queryParamsImpl.mustache b/.generator/templates/libraries/microprofile/queryParamsImpl.mustache new file mode 100644 index 00000000000..ff79730471d --- /dev/null +++ b/.generator/templates/libraries/microprofile/queryParamsImpl.mustache @@ -0,0 +1 @@ +{{#isQueryParam}}{{{dataType}}} {{paramName}}{{/isQueryParam}} \ No newline at end of file diff --git a/.generator/templates/libraries/microprofile/returnTypes.mustache b/.generator/templates/libraries/microprofile/returnTypes.mustache new file mode 100644 index 00000000000..6af86ffe4e4 --- /dev/null +++ b/.generator/templates/libraries/microprofile/returnTypes.mustache @@ -0,0 +1,4 @@ +{{#useGenericResponse}}Response{{/useGenericResponse}}{{! non-generic response: +}}{{^useGenericResponse}}{{! +}}{{{returnType}}}{{! +}}{{/useGenericResponse}} \ No newline at end of file diff --git a/.generator/templates/libraries/native/AbstractOpenApiSchema.mustache b/.generator/templates/libraries/native/AbstractOpenApiSchema.mustache new file mode 100644 index 00000000000..d7d9ee9e740 --- /dev/null +++ b/.generator/templates/libraries/native/AbstractOpenApiSchema.mustache @@ -0,0 +1,138 @@ +{{>licenseInfo}} + +package {{modelPackage}}; + +import {{invokerPackage}}.ApiException; +import java.util.Objects; +import java.lang.reflect.Type; +import java.util.Map; +import javax.ws.rs.core.GenericType; + +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Abstract class for oneOf,anyOf schemas defined in OpenAPI spec + */ +{{>additionalModelTypeAnnotations}}{{>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 + */ + @JsonValue + 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) { + if (o == null) { + return "null"; + } + return 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 nullalble + * + * @return true if it's nullable + */ + public Boolean isNullable() { + if (Boolean.TRUE.equals(isNullable)) { + return Boolean.TRUE; + } else { + return Boolean.FALSE; + } + } + +{{>libraries/native/additional_properties}} + +} diff --git a/.generator/templates/libraries/native/ApiClient.mustache b/.generator/templates/libraries/native/ApiClient.mustache new file mode 100644 index 00000000000..4c915fb3f38 --- /dev/null +++ b/.generator/templates/libraries/native/ApiClient.mustache @@ -0,0 +1,389 @@ +{{>licenseInfo}} +package {{invokerPackage}}; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{#openApiNullable}} +import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} + +import java.io.InputStream; +import java.net.URI; +import java.net.URLEncoder; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.charset.Charset; +import java.time.Duration; +{{#java8}} +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +{{/java8}} +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.StringJoiner; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +/** + * Configuration and utility class for API clients. + * + *

This class can be constructed and modified, then used to instantiate the + * various API classes. The API classes use the settings in this class to + * configure themselves, but otherwise do not store a link to this class.

+ * + *

This class is mutable and not synchronized, so it is not thread-safe. + * The API classes generated from this are immutable and thread-safe.

+ * + *

The setter methods of this class return the current object to facilitate + * a fluent style of configuration.

+ */ +{{>generatedAnnotation}} +public class ApiClient { + + private static final Charset UTF_8 = Charset.forName("UTF-8"); + + private HttpClient.Builder builder; + private ObjectMapper mapper; + private String scheme; + private String host; + private int port; + private String basePath; + private Consumer interceptor; + private Consumer> responseInterceptor; + private Duration readTimeout; + + private static String valueToString(Object value) { + if (value == null) { + return ""; + } + {{#java8}} + if (value instanceof OffsetDateTime) { + return ((OffsetDateTime) value).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); + } + {{/java8}} + return value.toString(); + } + + /** + * URL encode a string in the UTF-8 encoding. + * + * @param s String to encode. + * @return URL-encoded representation of the input string. + */ + public static String urlEncode(String s) { + return URLEncoder.encode(s, UTF_8); + } + + /** + * Convert a URL query name/value parameter to a list of encoded {@link Pair} + * objects. + * + *

The value can be null, in which case an empty list is returned.

+ * + * @param name The query name parameter. + * @param value The query value, which may not be a collection but may be + * null. + * @return A singleton list of the {@link Pair} objects representing the input + * parameters, which is encoded for use in a URL. If the value is null, an + * empty list is returned. + */ + public static List parameterToPairs(String name, Object value) { + if (name == null || name.isEmpty() || value == null) { + return Collections.emptyList(); + } + return Collections.singletonList(new Pair(urlEncode(name), urlEncode(valueToString(value)))); + } + + /** + * Convert a URL query name/collection parameter to a list of encoded + * {@link Pair} objects. + * + * @param collectionFormat The swagger collectionFormat string (csv, tsv, etc). + * @param name The query name parameter. + * @param values A collection of values for the given query name, which may be + * null. + * @return A list of {@link Pair} objects representing the input parameters, + * which is encoded for use in a URL. If the values collection is null, an + * empty list is returned. + */ + public static List parameterToPairs( + String collectionFormat, String name, Collection values) { + if (name == null || name.isEmpty() || values == null || values.isEmpty()) { + return Collections.emptyList(); + } + + // get the collection format (default: csv) + String format = collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat; + + // create the params based on the collection format + if ("multi".equals(format)) { + return values.stream() + .map(value -> new Pair(urlEncode(name), urlEncode(valueToString(value)))) + .collect(Collectors.toList()); + } + + String delimiter; + switch(format) { + case "csv": + delimiter = urlEncode(","); + break; + case "ssv": + delimiter = urlEncode(" "); + break; + case "tsv": + delimiter = urlEncode("\t"); + break; + case "pipes": + delimiter = urlEncode("|"); + break; + default: + throw new IllegalArgumentException("Illegal collection format: " + collectionFormat); + } + + StringJoiner joiner = new StringJoiner(delimiter); + for (Object value : values) { + joiner.add(urlEncode(valueToString(value))); + } + + return Collections.singletonList(new Pair(urlEncode(name), joiner.toString())); + } + + /** + * Ctor. + */ + public ApiClient() { + this.builder = createDefaultHttpClientBuilder(); + this.mapper = createDefaultObjectMapper(); + updateBaseUri(getDefaultBaseUri()); + interceptor = null; + readTimeout = null; + responseInterceptor = null; + } + + /** + * Ctor. + */ + public ApiClient(HttpClient.Builder builder, ObjectMapper mapper, String baseUri) { + this.builder = builder; + this.mapper = mapper; + updateBaseUri(baseUri); + interceptor = null; + readTimeout = null; + responseInterceptor = null; + } + + protected ObjectMapper createDefaultObjectMapper() { + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); + mapper.registerModule(new JavaTimeModule()); + {{#openApiNullable}} + mapper.registerModule(new JsonNullableModule()); + {{/openApiNullable}} + return mapper; + } + + protected String getDefaultBaseUri() { + return "{{{basePath}}}"; + } + + protected HttpClient.Builder createDefaultHttpClientBuilder() { + return HttpClient.newBuilder(); + } + + public void updateBaseUri(String baseUri) { + URI uri = URI.create(baseUri); + scheme = uri.getScheme(); + host = uri.getHost(); + port = uri.getPort(); + basePath = uri.getRawPath(); + } + + /** + * Set a custom {@link HttpClient.Builder} object to use when creating the + * {@link HttpClient} that is used by the API client. + * + * @param builder Custom client builder. + * @return This object. + */ + public ApiClient setHttpClientBuilder(HttpClient.Builder builder) { + this.builder = builder; + return this; + } + + /** + * Get an {@link HttpClient} based on the current {@link HttpClient.Builder}. + * + *

The returned object is immutable and thread-safe.

+ * + * @return The HTTP client. + */ + public HttpClient getHttpClient() { + return builder.build(); + } + + /** + * Set a custom {@link ObjectMapper} to serialize and deserialize the request + * and response bodies. + * + * @param mapper Custom object mapper. + * @return This object. + */ + public ApiClient setObjectMapper(ObjectMapper mapper) { + this.mapper = mapper; + return this; + } + + /** + * Get a copy of the current {@link ObjectMapper}. + * + * @return A copy of the current object mapper. + */ + public ObjectMapper getObjectMapper() { + return mapper.copy(); + } + + /** + * Set a custom host name for the target service. + * + * @param host The host name of the target service. + * @return This object. + */ + public ApiClient setHost(String host) { + this.host = host; + return this; + } + + /** + * Set a custom port number for the target service. + * + * @param port The port of the target service. Set this to -1 to reset the + * value to the default for the scheme. + * @return This object. + */ + public ApiClient setPort(int port) { + this.port = port; + return this; + } + + /** + * Set a custom base path for the target service, for example '/v2'. + * + * @param basePath The base path against which the rest of the path is + * resolved. + * @return This object. + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get the base URI to resolve the endpoint paths against. + * + * @return The complete base URI that the rest of the API parameters are + * resolved against. + */ + public String getBaseUri() { + return scheme + "://" + host + (port == -1 ? "" : ":" + port) + basePath; + } + + /** + * Set a custom scheme for the target service, for example 'https'. + * + * @param scheme The scheme of the target service + * @return This object. + */ + public ApiClient setScheme(String scheme){ + this.scheme = scheme; + return this; + } + + /** + * Set a custom request interceptor. + * + *

A request interceptor is a mechanism for altering each request before it + * is sent. After the request has been fully configured but not yet built, the + * request builder is passed into this function for further modification, + * after which it is sent out.

+ * + *

This is useful for altering the requests in a custom manner, such as + * adding headers. It could also be used for logging and monitoring.

+ * + * @param interceptor A function invoked before creating each request. A value + * of null resets the interceptor to a no-op. + * @return This object. + */ + public ApiClient setRequestInterceptor(Consumer interceptor) { + this.interceptor = interceptor; + return this; + } + + /** + * Get the custom interceptor. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer getRequestInterceptor() { + return interceptor; + } + + /** + * Set a custom response interceptor. + * + *

This is useful for logging, monitoring or extraction of header variables

+ * + * @param interceptor A function invoked before creating each request. A value + * of null resets the interceptor to a no-op. + * @return This object. + */ + public ApiClient setResponseInterceptor(Consumer> interceptor) { + this.responseInterceptor = interceptor; + return this; + } + + /** + * Get the custom response interceptor. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer> getResponseInterceptor() { + return responseInterceptor; + } + + /** + * Set the read timeout for the http client. + * + *

This is the value used by default for each request, though it can be + * overridden on a per-request basis with a request interceptor.

+ * + * @param readTimeout The read timeout used by default by the http client. + * Setting this value to null resets the timeout to an + * effectively infinite value. + * @return This object. + */ + public ApiClient setReadTimeout(Duration readTimeout) { + this.readTimeout = readTimeout; + return this; + } + + /** + * Get the read timeout that was set. + * + * @return The read timeout, or null if no timeout was set. Null represents + * an infinite wait time. + */ + public Duration getReadTimeout() { + return readTimeout; + } +} diff --git a/.generator/templates/libraries/native/ApiResponse.mustache b/.generator/templates/libraries/native/ApiResponse.mustache new file mode 100644 index 00000000000..1f3f3a31981 --- /dev/null +++ b/.generator/templates/libraries/native/ApiResponse.mustache @@ -0,0 +1,58 @@ +{{>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. + * + * @param The type of data that is deserialized from response body + */ +public class ApiResponse { + final private int statusCode; + final private Map> headers; + final private T data; + + /** + * @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); + } + + /** + * @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; + } + + public int getStatusCode() { + return statusCode; + } + + public Map> getHeaders() { + return headers; + } + + public T getData() { + return data; + } +} diff --git a/.generator/templates/libraries/native/JSON.mustache b/.generator/templates/libraries/native/JSON.mustache new file mode 100644 index 00000000000..16aa21e1403 --- /dev/null +++ b/.generator/templates/libraries/native/JSON.mustache @@ -0,0 +1,276 @@ +package {{invokerPackage}}; + +{{#threetenbp}} +import org.threeten.bp.*; +{{/threetenbp}} +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.*; +{{#openApiNullable}} +import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} +{{#java8}} +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{/java8}} +{{#joda}} +import com.fasterxml.jackson.datatype.joda.JodaModule; +{{/joda}} +{{#threetenbp}} +import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; +{{/threetenbp}} +{{#models.0}} +import {{modelPackage}}.*; +{{/models.0}} + +import java.text.DateFormat; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.ext.ContextResolver; + +{{>generatedAnnotation}} +public class JSON implements ContextResolver { + private ObjectMapper mapper; + + public JSON() { + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.setDateFormat(new RFC3339DateFormat()); + {{#java8}} + mapper.registerModule(new JavaTimeModule()); + {{/java8}} + {{#joda}} + mapper.registerModule(new JodaModule()); + {{/joda}} + {{#threetenbp}} + ThreeTenModule module = new ThreeTenModule(); + module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); + module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); + module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); + mapper.registerModule(module); + {{/threetenbp}} + {{#openApiNullable}} + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); + {{/openApiNullable}} + } + + /** + * Set the date format for JSON (de)serialization with Date properties. + * @param dateFormat Date format + */ + public void setDateFormat(DateFormat dateFormat) { + mapper.setDateFormat(dateFormat); + } + + @Override + public ObjectMapper getContext(Class type) { + return mapper; + } + + /** + * Get the object mapper + * + * @return object mapper + */ + public ObjectMapper getMapper() { return mapper; } + + /** + * 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. + */ + 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()) { + String discrValue = node.asText(); + 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. + */ + 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. + */ + 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 (GenericType childType : descendants.values()) { + if (isInstanceOf(childType.getRawType(), inst, visitedClasses)) { + return true; + } + } + } + return false; + } + + /** + * A map of discriminators for all model classes. + */ + private static Map, ClassDiscriminatorMapping> modelDiscriminators = new HashMap, ClassDiscriminatorMapping>(); + + /** + * A map of oneOf/anyOf descendants for each model class. + */ + private static Map, Map> modelDescendants = new HashMap, Map>(); + + /** + * 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); + } + + private static JSON json; + + static { + json = new JSON(); + } + + /** + * Get the default JSON instance. + * + * @return the default JSON instance + */ + public static JSON getDefault() { + return json; + } + + /** + * Set the default JSON instance. + * + * @param json JSON instance to be used + */ + public static void setDefault(JSON json) { + JSON.json = json; + } +} diff --git a/.generator/templates/libraries/native/README.mustache b/.generator/templates/libraries/native/README.mustache new file mode 100644 index 00000000000..0f6d46a460b --- /dev/null +++ b/.generator/templates/libraries/native/README.mustache @@ -0,0 +1,178 @@ +# {{artifactId}} + +{{appName}} + +- API version: {{appVersion}} +{{^hideGenerationTimestamp}} + +- Build date: {{generatedDate}} +{{/hideGenerationTimestamp}} + +{{#appDescriptionWithNewLines}}{{{appDescriptionWithNewLines}}}{{/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 11+ +2. Maven/Gradle + +## 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 +compile "{{{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 {{{invokerPackage}}}.*; +import {{{modelPackage}}}.*; +import {{{package}}}.{{{classname}}};{{#vendorExtensions.x-group-parameters}} +import {{{package}}}.{{{classname}}}.*;{{/vendorExtensions.x-group-parameters}} +{{#asyncNative}} +import java.util.concurrent.CompletableFuture; +{{/asyncNative}} + +public class {{{classname}}}Example { + + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + // Configure clients using the `defaultClient` object, such as + // overriding the host and port, timeout, etc. + {{{classname}}} apiInstance = new {{{classname}}}(defaultClient); + {{#allParams}} + {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} + {{/allParams}} + try { + {{^vendorExtensions.x-group-parameters}} + {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}); + {{/vendorExtensions.x-group-parameters}} + {{#vendorExtensions.x-group-parameters}} + {{#hasParams}} + API{{operationId}}Request request = API{{operationId}}Request.newBuilder(){{#allParams}} + .{{paramName}}({{paramName}}){{/allParams}} + .build(); + {{/hasParams}} + {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{operationId}}({{#hasParams}}request{{/hasParams}}); + {{/vendorExtensions.x-group-parameters}} + {{#returnType}} + System.out.println(result{{#asyncNative}}.get(){{/asyncNative}}); + {{/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}}{{summary}}{{/summary}} +*{{classname}}* | [**{{operationId}}WithHttpInfo**]({{apiDocPath}}{{classname}}.md#{{operationId}}WithHttpInfo) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} + +## Documentation for Models + +{{#models}}{{#model}} - [{{classname}}]({{modelDocPath}}{{classname}}.md) +{{/model}}{{/models}} + +## Documentation for Authorization + +{{^authMethods}}All endpoints do not require authorization. +{{/authMethods}}Authentication schemes defined for the API: +{{#authMethods}}### {{name}} + +{{#isApiKey}} + +- **Type**: API key +- **API key parameter name**: {{keyParamName}} +- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}} +{{/isApiKey}} +{{#isBasic}} + +- **Type**: HTTP basic authentication +{{/isBasic}} +{{#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. +However, the instances of the api clients created from the `ApiClient` are thread-safe and can be re-used. + +## Author + +{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}} +{{/-last}}{{/apis}}{{/apiInfo}} diff --git a/.generator/templates/libraries/native/additional_properties.mustache b/.generator/templates/libraries/native/additional_properties.mustache new file mode 100644 index 00000000000..61973dc24fa --- /dev/null +++ b/.generator/templates/libraries/native/additional_properties.mustache @@ -0,0 +1,39 @@ +{{#additionalPropertiesType}} + /** + * 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. + */ + @JsonAnySetter + public {{classname}} putAdditionalProperty(String key, {{{.}}} value) { + if (this.additionalProperties == null) { + this.additionalProperties = new HashMap(); + } + this.additionalProperties.put(key, value); + return this; + } + + /** + * Return the additional (undeclared) property. + */ + @JsonAnyGetter + public Map getAdditionalProperties() { + return additionalProperties; + } + + /** + * Return the additional (undeclared) property with the specified name. + */ + public {{{.}}} getAdditionalProperty(String key) { + if (this.additionalProperties == null) { + return null; + } + return this.additionalProperties.get(key); + } +{{/additionalPropertiesType}} diff --git a/.generator/templates/libraries/native/anyof_model.mustache b/.generator/templates/libraries/native/anyof_model.mustache new file mode 100644 index 00000000000..456f8309c09 --- /dev/null +++ b/.generator/templates/libraries/native/anyof_model.mustache @@ -0,0 +1,202 @@ +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.Response; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import {{invokerPackage}}.JSON; + +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} +@JsonDeserialize(using={{classname}}.{{classname}}Deserializer.class) +@JsonSerialize(using = {{classname}}.{{classname}}Serializer.class) +public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} { + private static final Logger log = Logger.getLogger({{classname}}.class.getName()); + + 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, SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeObject(value.getActualInstance()); + } + } + + 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 IOException, JsonProcessingException { + JsonNode tree = jp.readValueAsTree(); + + Object deserialized = null; + {{#discriminator}} + Class cls = JSON.getClassForElement(tree, {{classname}}.class); + if (cls != null) { + // When the OAS schema includes a discriminator, use the discriminator value to + // discriminate the anyOf schemas. + // Get the discriminator mapping value to get the class. + deserialized = tree.traverse(jp.getCodec()).readValueAs(cls); + {{classname}} ret = new {{classname}}(); + ret.setActualInstance(deserialized); + return ret; + } + {{/discriminator}} + {{#anyOf}} + // deserialize {{{.}}} + try { + deserialized = tree.traverse(jp.getCodec()).readValueAs({{{.}}}.class); + {{classname}} ret = new {{classname}}(); + ret.setActualInstance(deserialized); + return ret; + } catch (Exception e) { + // deserialization failed, continue, log to help debugging + log.log(Level.FINER, "Input data does not match '{{classname}}'", e); + } + + {{/anyOf}} + throw new IOException(String.format("Failed deserialization for {{classname}}: no match found")); + } + + /** + * Handle deserialization of the 'null' value. + */ + @Override + public {{classname}} getNullValue(DeserializationContext ctxt) throws JsonMappingException { + {{#isNullable}} + return null; + {{/isNullable}} + {{^isNullable}} + throw new JsonMappingException(ctxt.getParser(), "{{classname}} cannot be null"); + {{/isNullable}} + } + } + + // 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}}); + } +{{> libraries/native/additional_properties }} + {{#additionalPropertiesType}} + /** + * Return true if this {{name}} object is equal to o. + */ + @Override + public boolean equals(Object o) { + return super.equals(o) && Objects.equals(this.additionalProperties, (({{classname}})o).additionalProperties); + } + + @Override + public int hashCode() { + return Objects.hash(getActualInstance(), isNullable(), getSchemaType(), additionalProperties); + } + {{/additionalPropertiesType}} + {{#anyOf}} + public {{classname}}({{{.}}} o) { + super("anyOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + setActualInstance(o); + } + + {{/anyOf}} + static { + {{#anyOf}} + schemas.put("{{{.}}}", new GenericType<{{{.}}}>() { + }); + {{/anyOf}} + 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}} + } + + @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 instanct 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}} +} diff --git a/.generator/templates/libraries/native/api.mustache b/.generator/templates/libraries/native/api.mustache new file mode 100644 index 00000000000..2adef3a6b0e --- /dev/null +++ b/.generator/templates/libraries/native/api.mustache @@ -0,0 +1,392 @@ +{{>licenseInfo}} +package {{package}}; + +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.ApiResponse; +import {{invokerPackage}}.Pair; + +{{#imports}} +import {{import}}; +{{/imports}} + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.util.function.Consumer; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.StringJoiner; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} +{{#asyncNative}} + +import java.util.concurrent.CompletableFuture; +{{/asyncNative}} + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}} { + private final HttpClient memberVarHttpClient; + private final ObjectMapper memberVarObjectMapper; + private final String memberVarBaseUri; + private final Consumer memberVarInterceptor; + private final Duration memberVarReadTimeout; + private final Consumer> memberVarResponseInterceptor; + + public {{classname}}() { + this(new ApiClient()); + } + + public {{classname}}(ApiClient apiClient) { + memberVarHttpClient = apiClient.getHttpClient(); + memberVarObjectMapper = apiClient.getObjectMapper(); + memberVarBaseUri = apiClient.getBaseUri(); + memberVarInterceptor = apiClient.getRequestInterceptor(); + memberVarReadTimeout = apiClient.getReadTimeout(); + memberVarResponseInterceptor = apiClient.getResponseInterceptor(); + } + {{#asyncNative}} + + private ApiException getApiException(String operationId, HttpResponselocalVarResponse) { + return new ApiException(localVarResponse.statusCode(), + operationId + " call received non-success response", + localVarResponse.headers(), + localVarResponse.body()); + } + {{/asyncNative}} + + {{#operation}} + {{#vendorExtensions.x-group-parameters}} + {{#hasParams}} + /** + * {{summary}} + * {{notes}} + * @param apiRequest {@link API{{operationId}}Request} + {{#returnType}} + * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}{{returnType}}{{#asyncNative}}>{{/asyncNative}} + {{/returnType}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}(API{{operationId}}Request apiRequest) throws ApiException { + {{#allParams}} + {{{dataType}}} {{paramName}} = apiRequest.{{paramName}}(); + {{/allParams}} + {{#returnType}}return {{/returnType}}{{^returnType}}{{#asyncNative}}return {{/asyncNative}}{{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + } + + /** + * {{summary}} + * {{notes}} + * @param apiRequest {@link API{{operationId}}Request} + * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}}WithHttpInfo(API{{operationId}}Request apiRequest) throws ApiException { + {{#allParams}} + {{{dataType}}} {{paramName}} = apiRequest.{{paramName}}(); + {{/allParams}} + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + } + + {{/hasParams}} + {{/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 {{#asyncNative}}CompletableFuture<{{/asyncNative}}{{returnType}}{{#asyncNative}}>{{/asyncNative}} + {{/returnType}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + {{^asyncNative}} + {{#returnType}}ApiResponse<{{{returnType}}}> localVarResponse = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + {{#returnType}} + return localVarResponse.getData(); + {{/returnType}} + {{/asyncNative}} + {{#asyncNative}} + try { + HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + return memberVarHttpClient.sendAsync( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofString()).thenComposeAsync(localVarResponse -> { + if (localVarResponse.statusCode()/ 100 != 2) { + return CompletableFuture.failedFuture(getApiException("{{operationId}}", localVarResponse)); + } + {{#returnType}} + try { + return CompletableFuture.completedFuture( + memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<{{{returnType}}}>() {}) + ); + } catch (IOException e) { + return CompletableFuture.failedFuture(new ApiException(e)); + } + {{/returnType}} + {{^returnType}} + return CompletableFuture.completedFuture(null); + {{/returnType}} + }); + } + catch (ApiException e) { + return CompletableFuture.failedFuture(e); + } + {{/asyncNative}} + } + + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}{{/required}} + {{/allParams}} + * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + {{^asyncNative}} + HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + try { + HttpResponse localVarResponse = memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + if (localVarResponse.statusCode()/ 100 != 2) { + throw new ApiException(localVarResponse.statusCode(), + "{{operationId}} call received non-success response", + localVarResponse.headers(), + localVarResponse.body() == null ? null : new String(localVarResponse.body().readAllBytes())); + } + return new ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + {{#returnType}}memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<{{{returnType}}}>() {}){{/returnType}}{{^returnType}}null{{/returnType}} + ); + } catch (IOException e) { + throw new ApiException(e); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + {{/asyncNative}} + {{#asyncNative}} + try { + HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + return memberVarHttpClient.sendAsync( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofString()).thenComposeAsync(localVarResponse -> { + if (localVarResponse.statusCode()/ 100 != 2) { + return CompletableFuture.failedFuture(getApiException("{{operationId}}", localVarResponse)); + } + {{#returnType}} + try { + return CompletableFuture.completedFuture( + new ApiResponse<{{{returnType}}}>( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<{{{returnType}}}>() {})) + ); + } catch (IOException e) { + return CompletableFuture.failedFuture(new ApiException(e)); + } + {{/returnType}} + {{^returnType}} + return CompletableFuture.completedFuture( + new ApiResponse(localVarResponse.statusCode(), localVarResponse.headers().map(), null) + ); + {{/returnType}} + } + ); + } + catch (ApiException e) { + return CompletableFuture.failedFuture(e); + } + {{/asyncNative}} + } + + private HttpRequest.Builder {{operationId}}RequestBuilder({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + {{#allParams}} + {{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + } + {{/required}} + {{/allParams}} + + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + + {{! Switch delimiters for baseName so we can write constants like "{query}" }} + String localVarPath = "{{{path}}}"{{#pathParams}} + .replace({{=<% %>=}}"{<%baseName%>}"<%={{ }}=%>, ApiClient.urlEncode({{{paramName}}}.toString())){{/pathParams}}; + + {{#hasQueryParams}} + {{javaUtilPrefix}}List localVarQueryParams = new {{javaUtilPrefix}}ArrayList<>(); + {{#queryParams}} + {{#collectionFormat}} + localVarQueryParams.addAll(ApiClient.parameterToPairs("{{{collectionFormat}}}", "{{baseName}}", {{paramName}})); + {{/collectionFormat}} + {{^collectionFormat}} + {{#isDeepObject}} + if ({{paramName}} != null) { + {{#items.vars}} + localVarQueryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}}.{{getter}}())); + {{/items.vars}} + } + {{/isDeepObject}} + {{^isDeepObject}} + localVarQueryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}})); + {{/isDeepObject}} + {{/collectionFormat}} + {{/queryParams}} + + if (!localVarQueryParams.isEmpty()) { + {{javaUtilPrefix}}StringJoiner queryJoiner = new StringJoiner("&"); + localVarQueryParams.forEach(p -> queryJoiner.add(p.getName() + '=' + p.getValue())); + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath + '?' + queryJoiner.toString())); + } else { + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + } + {{/hasQueryParams}} + {{^hasQueryParams}} + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + {{/hasQueryParams}} + + {{#headerParams}} + if ({{paramName}} != null) { + localVarRequestBuilder.header("{{baseName}}", {{paramName}}.toString()); + } + {{/headerParams}} + {{#bodyParam}} + localVarRequestBuilder.header("Content-Type", "application/json"); + {{/bodyParam}} + localVarRequestBuilder.header("Accept", "application/json"); + + {{#bodyParam}} + try { + byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes({{paramName}}); + localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody)); + } catch (IOException e) { + throw new ApiException(e); + } + {{/bodyParam}} + {{^bodyParam}} + localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.noBody()); + {{/bodyParam}} + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); + } + return localVarRequestBuilder; + } + {{#vendorExtensions.x-group-parameters}} + {{#hasParams}} + + public static final class API{{operationId}}Request { + {{#requiredParams}} + private {{{dataType}}} {{paramName}}; // {{description}} (required) + {{/requiredParams}} + {{#optionalParams}} + private {{{dataType}}} {{paramName}}; // {{description}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}} + {{/optionalParams}} + + private API{{operationId}}Request(Builder builder) { + {{#requiredParams}} + this.{{paramName}} = builder.{{paramName}}; + {{/requiredParams}} + {{#optionalParams}} + this.{{paramName}} = builder.{{paramName}}; + {{/optionalParams}} + } + {{#allParams}} + public {{{dataType}}} {{paramName}}() { + return {{paramName}}; + } + {{/allParams}} + public static Builder newBuilder() { + return new Builder(); + } + + public static class Builder { + {{#requiredParams}} + private {{{dataType}}} {{paramName}}; + {{/requiredParams}} + {{#optionalParams}} + private {{{dataType}}} {{paramName}}; + {{/optionalParams}} + + {{#allParams}} + public Builder {{paramName}}({{{dataType}}} {{paramName}}) { + this.{{paramName}} = {{paramName}}; + return this; + } + {{/allParams}} + public API{{operationId}}Request build() { + return new API{{operationId}}Request(this); + } + } + } + + {{/hasParams}} + {{/vendorExtensions.x-group-parameters}} + {{/operation}} +} +{{/operations}} diff --git a/.generator/templates/libraries/native/apiException.mustache b/.generator/templates/libraries/native/apiException.mustache new file mode 100644 index 00000000000..3d0eee4bf9c --- /dev/null +++ b/.generator/templates/libraries/native/apiException.mustache @@ -0,0 +1,79 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import java.net.http.HttpHeaders; + +{{>generatedAnnotation}} +public class ApiException extends{{#useRuntimeException}} RuntimeException {{/useRuntimeException}}{{^useRuntimeException}} Exception {{/useRuntimeException}}{ + private int code = 0; + private HttpHeaders responseHeaders = null; + private String responseBody = null; + + public ApiException() {} + + public ApiException(Throwable throwable) { + super(throwable); + } + + public ApiException(String message) { + super(message); + } + + public ApiException(String message, Throwable throwable, int code, HttpHeaders responseHeaders, String responseBody) { + super(message, throwable); + this.code = code; + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + + public ApiException(String message, int code, HttpHeaders responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(String message, Throwable throwable, int code, HttpHeaders responseHeaders) { + this(message, throwable, code, responseHeaders, null); + } + + public ApiException(int code, HttpHeaders responseHeaders, String responseBody) { + this((String) null, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(int code, String message) { + super(message); + this.code = code; + } + + public ApiException(int code, String message, HttpHeaders responseHeaders, String responseBody) { + this(code, message); + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + + /** + * Get the HTTP status code. + * + * @return HTTP status code + */ + public int getCode() { + return code; + } + + /** + * Get the HTTP response headers. + * + * @return Headers as an HttpHeaders object + */ + public HttpHeaders getResponseHeaders() { + return responseHeaders; + } + + /** + * Get the HTTP response body. + * + * @return Response body in the form of string + */ + public String getResponseBody() { + return responseBody; + } +} diff --git a/.generator/templates/libraries/native/api_doc.mustache b/.generator/templates/libraries/native/api_doc.mustache new file mode 100644 index 00000000000..23473757c36 --- /dev/null +++ b/.generator/templates/libraries/native/api_doc.mustache @@ -0,0 +1,280 @@ +# {{classname}}{{#description}} + +{{description}}{{/description}} + +All URIs are relative to *{{basePath}}* + +Method | HTTP request | Description +------------- | ------------- | ------------- +{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +[**{{operationId}}WithHttpInfo**]({{classname}}.md#{{operationId}}WithHttpInfo) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}} + +{{#operations}} +{{#operation}} + +## {{operationId}} + +{{^vendorExtensions.x-group-parameters}} +> {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}) +{{/vendorExtensions.x-group-parameters}} +{{#vendorExtensions.x-group-parameters}} +> {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}({{#hasParams}}{{operationId}}Request{{/hasParams}}) +{{/vendorExtensions.x-group-parameters}} + +{{summary}}{{#notes}} + +{{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}}};{{#vendorExtensions.x-group-parameters}} +import {{{package}}}.{{{classname}}}.*;{{/vendorExtensions.x-group-parameters}} +{{#asyncNative}} +import java.util.concurrent.CompletableFuture; +{{/asyncNative}} + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("{{{basePath}}}"); + {{#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 { + {{^vendorExtensions.x-group-parameters}} + {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}); + {{/vendorExtensions.x-group-parameters}} + {{#vendorExtensions.x-group-parameters}} + {{#hasParams}} + API{{operationId}}Request request = API{{operationId}}Request.newBuilder(){{#allParams}} + .{{paramName}}({{paramName}}){{/allParams}} + .build(); + {{/hasParams}} + {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{operationId}}({{#hasParams}}request{{/hasParams}}); + {{/vendorExtensions.x-group-parameters}} + {{#returnType}} + System.out.println(result{{#asyncNative}}.get(){{/asyncNative}}); + {{/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}}{{^vendorExtensions.x-group-parameters}}{{#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}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} +{{/allParams}} +{{/vendorExtensions.x-group-parameters}} +{{#vendorExtensions.x-group-parameters}} +{{#hasParams}} +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------| +| {{operationId}}Request | [**API{{operationId}}Request**]({{classname}}.md#API{{operationId}}Request)|-|-|{{/hasParams}} +{{/vendorExtensions.x-group-parameters}} + +### Return type + +{{#returnType}}{{#asyncNative}}CompletableFuture<{{/asyncNative}}{{#returnTypeIsPrimitive}}**{{returnType}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{returnType}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}{{#asyncNative}}>{{/asyncNative}}{{/returnType}} +{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}null{{/asyncNative}} (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}} + +## {{operationId}}WithHttpInfo + +{{^vendorExtensions.x-group-parameters}} +> {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}} {{operationId}}WithHttpInfo({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}) +{{/vendorExtensions.x-group-parameters}} +{{#vendorExtensions.x-group-parameters}} +> {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}} {{operationId}}WithHttpInfo({{#hasParams}}{{operationId}}Request{{/hasParams}}) +{{/vendorExtensions.x-group-parameters}} + +{{summary}}{{#notes}} + +{{notes}}{{/notes}} + +### Example + +```java +// Import classes: +import {{{invokerPackage}}}.ApiClient; +import {{{invokerPackage}}}.ApiException; +import {{{invokerPackage}}}.ApiResponse; +import {{{invokerPackage}}}.Configuration;{{#hasAuthMethods}} +import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}} +import {{{invokerPackage}}}.models.*; +import {{{package}}}.{{{classname}}};{{#vendorExtensions.x-group-parameters}} +import {{{package}}}.{{{classname}}}.*;{{/vendorExtensions.x-group-parameters}} +{{#asyncNative}} +import java.util.concurrent.CompletableFuture; +{{/asyncNative}} + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("{{{basePath}}}"); + {{#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 { + {{^vendorExtensions.x-group-parameters}} + {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} response = apiInstance.{{{operationId}}}WithHttpInfo({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}); + {{/vendorExtensions.x-group-parameters}} + {{#vendorExtensions.x-group-parameters}} + {{#hasParams}} + API{{operationId}}Request request = API{{operationId}}Request.newBuilder(){{#allParams}} + .{{paramName}}({{paramName}}){{/allParams}} + .build(); + {{/hasParams}} + {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} response = apiInstance.{{{operationId}}}WithHttpInfo({{#hasParams}}request{{/hasParams}}); + {{/vendorExtensions.x-group-parameters}} + System.out.println("Status code: " + response{{#asyncNative}}.get(){{/asyncNative}}.getStatusCode()); + System.out.println("Response headers: " + response{{#asyncNative}}.get(){{/asyncNative}}.getHeaders()); + {{#returnType}} + System.out.println("Response body: " + response{{#asyncNative}}.get(){{/asyncNative}}.getData()); + {{/returnType}} + {{#asyncNative}} + } catch (InterruptedException | ExecutionException e) { + ApiException apiException = (ApiException)e.getCause(); + System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); + System.err.println("Status code: " + apiException.getCode()); + System.err.println("Response headers: " + apiException.getResponseHeaders()); + System.err.println("Reason: " + apiException.getResponseBody()); + e.printStackTrace(); + {{/asyncNative}} + } catch (ApiException e) { + System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Response headers: " + e.getResponseHeaders()); + System.err.println("Reason: " + e.getResponseBody()); + e.printStackTrace(); + } + } +} +``` + +### Parameters + +{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{^vendorExtensions.x-group-parameters}}{{#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}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} +{{/allParams}} +{{/vendorExtensions.x-group-parameters}} +{{#vendorExtensions.x-group-parameters}} +{{#hasParams}} +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------| +| {{operationId}}Request | [**API{{operationId}}Request**]({{classname}}.md#API{{operationId}}Request)|-|-|{{/hasParams}} +{{/vendorExtensions.x-group-parameters}} + +### Return type + +{{#returnType}}{{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnTypeIsPrimitive}}**{{returnType}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{returnType}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}>{{#asyncNative}}>{{/asyncNative}}{{/returnType}} +{{^returnType}}{{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse{{#asyncNative}}>{{/asyncNative}}{{/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}} +{{#vendorExtensions.x-group-parameters}}{{#hasParams}} + + +## API{{operationId}}Request +### Properties +{{#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}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} +{{/allParams}} + +{{/hasParams}}{{/vendorExtensions.x-group-parameters}} +{{/operation}} +{{/operations}} diff --git a/.generator/templates/libraries/native/api_test.mustache b/.generator/templates/libraries/native/api_test.mustache new file mode 100644 index 00000000000..2f5ffae22c4 --- /dev/null +++ b/.generator/templates/libraries/native/api_test.mustache @@ -0,0 +1,59 @@ +{{>licenseInfo}} + +package {{package}}; + +import {{invokerPackage}}.ApiException; +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Test; +import org.junit.Ignore; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +{{#asyncNative}} +import java.util.concurrent.CompletableFuture; +{{/asyncNative}} + +/** + * API tests for {{classname}} + */ +@Ignore +public class {{classname}}Test { + + private final {{classname}} api = new {{classname}}(); + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + * + * @throws ApiException + * if the Api call fails + */ + @Test + public void {{operationId}}Test() throws ApiException { + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + {{^vendorExtensions.x-group-parameters}} + {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} response = {{/returnType}} + {{^returnType}}{{#asyncNative}}CompletableFuture response = {{/asyncNative}}{{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + {{/vendorExtensions.x-group-parameters}} + {{#vendorExtensions.x-group-parameters}}{{#hasParams}} + {{classname}}.API{{operationId}}Request request = {{classname}}.API{{operationId}}Request.newBuilder(){{#allParams}} + .{{paramName}}({{paramName}}){{/allParams}} + .build();{{/hasParams}} + {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} response = {{/returnType}} + {{^returnType}}{{#asyncNative}}CompletableFuture response = {{/asyncNative}}{{/returnType}}api.{{operationId}}({{#hasParams}}request{{/hasParams}}); + {{/vendorExtensions.x-group-parameters}} + + // TODO: test validations + } + {{/operation}}{{/operations}} +} diff --git a/.generator/templates/libraries/native/build.gradle.mustache b/.generator/templates/libraries/native/build.gradle.mustache new file mode 100644 index 00000000000..e1967261a11 --- /dev/null +++ b/.generator/templates/libraries/native/build.gradle.mustache @@ -0,0 +1,76 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + maven { url "https://repo1.maven.org/maven2" } + jcenter() + } +} + +repositories { + maven { url "https://repo1.maven.org/maven2" } + jcenter() +} + +apply plugin: 'java' +apply plugin: 'maven' + +sourceCompatibility = JavaVersion.VERSION_11 +targetCompatibility = JavaVersion.VERSION_11 + +install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } +} + +task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath +} + +task sourcesJar(type: Jar, dependsOn: classes) { + classifier = 'sources' + from sourceSets.main.allSource +} + +task javadocJar(type: Jar, dependsOn: javadoc) { + classifier = 'javadoc' + from javadoc.destinationDir +} + +artifacts { + archives sourcesJar + archives javadocJar +} + + +ext { + swagger_annotations_version = "1.5.22" + jackson_version = "2.10.4" + junit_version = "4.13.1" + ws_rs_version = "2.1.1" + {{#threetenbp}} + threetenbp_version = "2.9.10" + {{/threetenbp}} +} + +dependencies { + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + 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" + implementation "org.openapitools:jackson-databind-nullable:0.2.1" + implementation 'javax.annotation:javax.annotation-api:1.3.2' + implementation "javax.ws.rs:javax.ws.rs-api:$ws_rs_version" + {{#threetenbp}} + implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:$threetenbp_version" + {{/threetenbp}} + testImplementation "junit:junit:$junit_version" +} diff --git a/.generator/templates/libraries/native/generatedAnnotation.mustache b/.generator/templates/libraries/native/generatedAnnotation.mustache new file mode 100644 index 00000000000..baf5ff08b49 --- /dev/null +++ b/.generator/templates/libraries/native/generatedAnnotation.mustache @@ -0,0 +1 @@ +@javax.annotation.processing.Generated(value = "{{generatorClass}}"{{^hideGenerationTimestamp}}, date = "{{generatedDate}}"{{/hideGenerationTimestamp}}) \ No newline at end of file diff --git a/.generator/templates/libraries/native/gradle.properties.mustache b/.generator/templates/libraries/native/gradle.properties.mustache new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.generator/templates/libraries/native/model.mustache b/.generator/templates/libraries/native/model.mustache new file mode 100644 index 00000000000..db4fbfd9fbc --- /dev/null +++ b/.generator/templates/libraries/native/model.mustache @@ -0,0 +1,60 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#useReflectionEqualsHashCode}} +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +{{/useReflectionEqualsHashCode}} +{{#models}} +{{#model}} +{{#additionalPropertiesType}} +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +{{/additionalPropertiesType}} +{{/model}} +{{/models}} +import java.util.Objects; +import java.util.Arrays; +import java.util.Map; +import java.util.HashMap; +{{#imports}} +import {{import}}; +{{/imports}} +{{#serializableModel}} +import java.io.Serializable; +{{/serializableModel}} +{{#jackson}} +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +{{#withXml}} +import com.fasterxml.jackson.dataformat.xml.annotation.*; +{{/withXml}} +{{/jackson}} +{{#withXml}} +import javax.xml.bind.annotation.*; +{{/withXml}} +{{#parcelableModel}} +import android.os.Parcelable; +import android.os.Parcel; +{{/parcelableModel}} +{{#useBeanValidation}} +import javax.validation.constraints.*; +import javax.validation.Valid; +{{/useBeanValidation}} +{{#performBeanValidation}} +import org.hibernate.validator.constraints.*; +{{/performBeanValidation}} + +{{#models}} +{{#model}} +{{#oneOf}} +{{#-first}} +import com.fasterxml.jackson.core.type.TypeReference; +{{/-first}} +{{/oneOf}} + +{{#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/.generator/templates/libraries/native/model_anyof_doc.mustache b/.generator/templates/libraries/native/model_anyof_doc.mustache new file mode 100644 index 00000000000..e360aa56e6c --- /dev/null +++ b/.generator/templates/libraries/native/model_anyof_doc.mustache @@ -0,0 +1,38 @@ +# {{classname}} + +{{#description}} +{{&description}} + +{{/description}} +## anyOf schemas +{{#anyOf}} +* [{{{.}}}]({{{.}}}.md) +{{/anyOf}} + +{{#isNullable}} +NOTE: this class is nullable. + +{{/isNullable}} +## Example +```java +// Import classes: +import {{{package}}}.{{{classname}}}; +{{#anyOf}} +import {{{package}}}.{{{.}}}; +{{/anyOf}} + +public class Example { + public static void main(String[] args) { + {{classname}} example{{classname}} = new {{classname}}(); + {{#anyOf}} + + // create a new {{{.}}} + {{{.}}} example{{{.}}} = new {{{.}}}(); + // set {{{classname}}} to {{{.}}} + example{{classname}}.setActualInstance(example{{{.}}}); + // to get back the {{{.}}} set earlier + {{{.}}} test{{{.}}} = ({{{.}}}) example{{classname}}.getActualInstance(); + {{/anyOf}} + } +} +``` diff --git a/.generator/templates/libraries/native/model_doc.mustache b/.generator/templates/libraries/native/model_doc.mustache new file mode 100644 index 00000000000..be1aedcf2f3 --- /dev/null +++ b/.generator/templates/libraries/native/model_doc.mustache @@ -0,0 +1,19 @@ +{{#models}}{{#model}} + +{{#isEnum}} +{{>enum_outer_doc}} +{{/isEnum}} +{{^isEnum}} +{{^oneOf.isEmpty}} +{{>model_oneof_doc}} +{{/oneOf.isEmpty}} +{{^anyOf.isEmpty}} +{{>model_anyof_doc}} +{{/anyOf.isEmpty}} +{{^anyOf}} +{{^oneOf}} +{{>pojo_doc}} +{{/oneOf}} +{{/anyOf}} +{{/isEnum}} +{{/model}}{{/models}} diff --git a/.generator/templates/libraries/native/model_oneof_doc.mustache b/.generator/templates/libraries/native/model_oneof_doc.mustache new file mode 100644 index 00000000000..5fff76c9efa --- /dev/null +++ b/.generator/templates/libraries/native/model_oneof_doc.mustache @@ -0,0 +1,38 @@ +# {{classname}} + +{{#description}} +{{&description}} + +{{/description}} +## oneOf schemas +{{#oneOf}} +* [{{{.}}}]({{{.}}}.md) +{{/oneOf}} + +{{#isNullable}} +NOTE: this class is nullable. + +{{/isNullable}} +## Example +```java +// Import classes: +import {{{package}}}.{{{classname}}}; +{{#oneOf}} +import {{{package}}}.{{{.}}}; +{{/oneOf}} + +public class Example { + public static void main(String[] args) { + {{classname}} example{{classname}} = new {{classname}}(); + {{#oneOf}} + + // create a new {{{.}}} + {{{.}}} example{{{.}}} = new {{{.}}}(); + // set {{{classname}}} to {{{.}}} + example{{classname}}.setActualInstance(example{{{.}}}); + // to get back the {{{.}}} set earlier + {{{.}}} test{{{.}}} = ({{{.}}}) example{{classname}}.getActualInstance(); + {{/oneOf}} + } +} +``` diff --git a/.generator/templates/libraries/native/oneof_model.mustache b/.generator/templates/libraries/native/oneof_model.mustache new file mode 100644 index 00000000000..f2345ab33be --- /dev/null +++ b/.generator/templates/libraries/native/oneof_model.mustache @@ -0,0 +1,235 @@ +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.Response; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import {{invokerPackage}}.JSON; + +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} +@JsonDeserialize(using = {{classname}}.{{classname}}Deserializer.class) +@JsonSerialize(using = {{classname}}.{{classname}}Serializer.class) +public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} { + private static final Logger log = Logger.getLogger({{classname}}.class.getName()); + + 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, SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeObject(value.getActualInstance()); + } + } + + 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 IOException, JsonProcessingException { + JsonNode tree = jp.readValueAsTree(); + Object deserialized = null; + {{#useOneOfDiscriminatorLookup}} + {{#discriminator}} + {{classname}} new{{classname}} = new {{classname}}(); + Map result2 = tree.traverse(jp.getCodec()).readValueAs(new TypeReference>() {}); + String discriminatorValue = (String)result2.get("{{{propertyBaseName}}}"); + switch (discriminatorValue) { + {{#mappedModels}} + case "{{{mappingName}}}": + deserialized = tree.traverse(jp.getCodec()).readValueAs({{{modelName}}}.class); + new{{classname}}.setActualInstance(deserialized); + return new{{classname}}; + {{/mappedModels}} + default: + log.log(Level.WARNING, String.format("Failed to lookup discriminator value `%s` for {{classname}}. Possible values:{{#mappedModels}} {{{mappingName}}}{{/mappedModels}}", discriminatorValue)); + } + + {{/discriminator}} + {{/useOneOfDiscriminatorLookup}} + boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS); + int match = 0; + JsonToken token = tree.traverse(jp.getCodec()).nextToken(); + {{#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) { + deserialized = tree.traverse(jp.getCodec()).readValueAs({{{.}}}.class); + // 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; + } + throw new IOException(String.format("Failed deserialization for {{classname}}: %d classes match result, expected 1", match)); + } + + /** + * Handle deserialization of the 'null' value. + */ + @Override + public {{classname}} getNullValue(DeserializationContext ctxt) throws JsonMappingException { + {{#isNullable}} + return null; + {{/isNullable}} + {{^isNullable}} + throw new JsonMappingException(ctxt.getParser(), "{{classname}} cannot be null"); + {{/isNullable}} + } + } + + // 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}}); + } +{{> libraries/native/additional_properties }} + {{#additionalPropertiesType}} + /** + * Return true if this {{name}} object is equal to o. + */ + @Override + public boolean equals(Object o) { + return super.equals(o) && Objects.equals(this.additionalProperties, (({{classname}})o).additionalProperties); + } + + @Override + public int hashCode() { + return Objects.hash(getActualInstance(), isNullable(), getSchemaType(), additionalProperties); + } + {{/additionalPropertiesType}} + {{#oneOf}} + public {{classname}}({{{.}}} o) { + super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + setActualInstance(o); + } + + {{/oneOf}} + static { + {{#oneOf}} + schemas.put("{{{.}}}", new GenericType<{{{.}}}>() { + }); + {{/oneOf}} + 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}} + } + + @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 instanct 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}} +} diff --git a/.generator/templates/libraries/native/pojo.mustache b/.generator/templates/libraries/native/pojo.mustache new file mode 100644 index 00000000000..b2a919dea3f --- /dev/null +++ b/.generator/templates/libraries/native/pojo.mustache @@ -0,0 +1,389 @@ +{{#discriminator}} +import {{invokerPackage}}.JSON; +{{/discriminator}} +/** + * {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}} + */{{#description}} +@ApiModel(description = "{{{description}}}"){{/description}} +{{#jackson}} +@JsonPropertyOrder({ +{{#vars}} + {{classname}}.JSON_PROPERTY_{{nameInSnakeCase}}{{^-last}},{{/-last}} +{{/vars}} +}) +{{/jackson}} +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} +public class {{classname}} {{#parent}}extends {{{parent}}} {{/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}} + {{^vendorExtensions.x-enum-as-string}} +{{>modelInnerEnum}} + {{/vendorExtensions.x-enum-as-string}} + {{/isContainer}} + {{#isContainer}} + {{#mostInnerItems}} +{{>modelInnerEnum}} + {{/mostInnerItems}} + {{/isContainer}} + {{/isEnum}} + {{#gson}} + public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}"; + {{/gson}} + {{#jackson}} + public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}"; + {{/jackson}} + {{#withXml}} + {{#isXmlAttribute}} + @XmlAttribute(name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlAttribute}} + {{^isXmlAttribute}} + {{^isContainer}} + @XmlElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isContainer}} + {{#isContainer}} + // Is a container wrapped={{isXmlWrapped}} + {{#items}} + // items.name={{name}} items.baseName={{baseName}} items.xmlName={{xmlName}} items.xmlNamespace={{xmlNamespace}} + // items.example={{example}} items.type={{dataType}} + @XmlElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/items}} + {{#isXmlWrapped}} + @XmlElementWrapper({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlWrapped}} + {{/isContainer}} + {{/isXmlAttribute}} + {{/withXml}} + {{#gson}} + @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}}) + {{/gson}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#isContainer}} + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined(); + {{/isContainer}} + {{^isContainer}} + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + {{/isContainer}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{#isContainer}} + private {{{datatypeWithEnum}}} {{name}}{{#required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/required}}{{^required}} = null{{/required}}; + {{/isContainer}} + {{^isContainer}} + private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; + {{/isContainer}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + + {{/vars}} + {{#parcelableModel}} + public {{classname}}() { + {{#parent}} + super(); + {{/parent}} + {{#gson}} + {{#discriminator}} + this.{{{discriminatorName}}} = this.getClass().getSimpleName(); + {{/discriminator}} + {{/gson}} + } + {{/parcelableModel}} + {{^parcelableModel}} + {{#gson}} + {{#discriminator}} + public {{classname}}() { + this.{{{discriminatorName}}} = this.getClass().getSimpleName(); + } + {{/discriminator}} + {{/gson}} + {{/parcelableModel}} + {{#vars}} + + {{^isReadOnly}} + {{#vendorExtensions.x-enum-as-string}} + public static final Set {{{nameInSnakeCase}}}_VALUES = new HashSet<>(Arrays.asList( + {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}} + )); + + {{/vendorExtensions.x-enum-as-string}} + public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-enum-as-string}} + if (!{{{nameInSnakeCase}}}_VALUES.contains({{name}})) { + throw new IllegalArgumentException({{name}} + " is invalid. Possible values for {{name}}: " + String.join(", ", {{{nameInSnakeCase}}}_VALUES)); + } + + {{/vendorExtensions.x-enum-as-string}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + return this; + } + {{#isArray}} + + public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null || !this.{{name}}.isPresent()) { + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); + } + try { + this.{{name}}.get().add({{name}}Item); + } catch (java.util.NoSuchElementException e) { + // this can never happen, as we make sure above that the value is present + } + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.add({{name}}Item); + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isArray}} + {{#isMap}} + + public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null || !this.{{name}}.isPresent()) { + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); + } + try { + this.{{name}}.get().put(key, {{name}}Item); + } catch (java.util.NoSuchElementException e) { + // this can never happen, as we make sure above that the value is present + } + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.put(key, {{name}}Item); + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isMap}} + + {{/isReadOnly}} + /** + {{#description}} + * {{description}} + {{/description}} + {{^description}} + * Get {{name}} + {{/description}} + {{#minimum}} + * minimum: {{minimum}} + {{/minimum}} + {{#maximum}} + * maximum: {{maximum}} + {{/maximum}} + * @return {{name}} + **/ +{{#required}} +{{#isNullable}} + @javax.annotation.Nullable +{{/isNullable}} +{{/required}} +{{^required}} + @javax.annotation.Nullable +{{/required}} +{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} @ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") +{{#vendorExtensions.x-extra-annotation}} + {{{vendorExtensions.x-extra-annotation}}} +{{/vendorExtensions.x-extra-annotation}} +{{#vendorExtensions.x-is-jackson-optional-nullable}} + {{!unannotated, Jackson would pick this up automatically and add it *in addition* to the _JsonNullable getter field}} + @JsonIgnore +{{/vendorExtensions.x-is-jackson-optional-nullable}} +{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#jackson}}{{> jackson_annotations}}{{/jackson}}{{/vendorExtensions.x-is-jackson-optional-nullable}} + public {{{datatypeWithEnum}}} {{getter}}() { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#isReadOnly}}{{! A readonly attribute doesn't have setter => jackson will set null directly if explicitly returned by API, so make sure we have an empty JsonNullable}} + if ({{name}} == null) { + {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + } + {{/isReadOnly}} + return {{name}}.orElse(null); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + return {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + + {{#vendorExtensions.x-is-jackson-optional-nullable}} +{{> jackson_annotations}} + public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}_JsonNullable() { + return {{name}}; + } + {{/vendorExtensions.x-is-jackson-optional-nullable}}{{#vendorExtensions.x-is-jackson-optional-nullable}} + @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) + {{#isReadOnly}}private{{/isReadOnly}}{{^isReadOnly}}public{{/isReadOnly}} void {{setter}}_JsonNullable(JsonNullable<{{{datatypeWithEnum}}}> {{name}}) { + {{! For getters/setters that have name differing from attribute name, we must include setter (albeit private) for jackson to be able to set the attribute}} + this.{{name}} = {{name}}; + } + {{/vendorExtensions.x-is-jackson-optional-nullable}} + + {{^isReadOnly}} + public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-enum-as-string}} + if (!{{{nameInSnakeCase}}}_VALUES.contains({{name}})) { + throw new IllegalArgumentException({{name}} + " is invalid. Possible values for {{name}}: " + String.join(", ", {{{nameInSnakeCase}}}_VALUES)); + } + + {{/vendorExtensions.x-enum-as-string}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isReadOnly}} + + {{/vars}} +{{>libraries/native/additional_properties}} + /** + * Return true if this {{name}} object is equal to o. + */ + @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}}{{#additionalPropertiesType}}&& + Objects.equals(this.additionalProperties, {{classVarName}}.additionalProperties){{/additionalPropertiesType}}{{#parent}} && + super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} + return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}} + {{/useReflectionEqualsHashCode}} + } + + @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}}{{#additionalPropertiesType}}, additionalProperties{{/additionalPropertiesType}}); + {{/useReflectionEqualsHashCode}} + } + + @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(toIndentedString({{name}})).append("\n"); + {{/vars}} + {{#additionalPropertiesType}} + sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n"); + {{/additionalPropertiesType}} + 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) { + if (o == null) { + return "null"; + } + return 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}} +{{#discriminator}} +static { + // 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}} +} diff --git a/.generator/templates/libraries/native/pom.mustache b/.generator/templates/libraries/native/pom.mustache new file mode 100644 index 00000000000..a6445406227 --- /dev/null +++ b/.generator/templates/libraries/native/pom.mustache @@ -0,0 +1,247 @@ + + 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}} + + + + + + + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 3 + + + 11 + + + + + + + + maven-surefire-plugin + 3.0.0-M3 + + + conf/log4j.properties + + -Xms512m -Xmx1500m + methods + 10 + + + + maven-dependency-plugin + 3.1.1 + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.2 + + + + test-jar + + + + + + + + maven-compiler-plugin + 3.8.1 + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.0 + + + attach-javadocs + + jar + + + + + + maven-source-plugin + 3.1.0 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + maven-gpg-plugin + 1.6 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + + {{#threetenbp}} + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${threetenbp-version} + + {{/threetenbp}} + + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + + + + + javax.ws.rs + javax.ws.rs-api + ${javax-ws-rs-api-version} + + + + + junit + junit + ${junit-version} + test + + + + + UTF-8 + 1.5.22 + 11 + 11 + 2.10.4 + 0.2.1 + 1.3.2 + 2.1.1 + {{#threetenbp}} + 2.9.10 + {{/threetenbp}} + 4.13.1 + + diff --git a/.generator/templates/libraries/native/travis.mustache b/.generator/templates/libraries/native/travis.mustache new file mode 100644 index 00000000000..d489da682e9 --- /dev/null +++ b/.generator/templates/libraries/native/travis.mustache @@ -0,0 +1,16 @@ +# +# Generated by: https://openapi-generator.tech +# +language: java +jdk: + - oraclejdk11 +before_install: + # ensure gradlew has proper permission + - chmod a+x ./gradlew +script: + # test using maven + - mvn test + # uncomment below to test using gradle + # - gradle test + # uncomment below to test using sbt + # - sbt test diff --git a/.generator/templates/libraries/okhttp-gson/ApiCallback.mustache b/.generator/templates/libraries/okhttp-gson/ApiCallback.mustache new file mode 100644 index 00000000000..4cc99a76ec3 --- /dev/null +++ b/.generator/templates/libraries/okhttp-gson/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 downlond processing. + * + * @param bytesRead bytes Read + * @param contentLength content lenngth of the response + * @param done Read end + */ + void onDownloadProgress(long bytesRead, long contentLength, boolean done); +} diff --git a/.generator/templates/libraries/okhttp-gson/ApiClient.mustache b/.generator/templates/libraries/okhttp-gson/ApiClient.mustache new file mode 100644 index 00000000000..37ebae04830 --- /dev/null +++ b/.generator/templates/libraries/okhttp-gson/ApiClient.mustache @@ -0,0 +1,1617 @@ +{{>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.BufferedSink; +import okio.Okio; +{{#joda}} +import org.joda.time.DateTime; +import org.joda.time.LocalDate; +import org.joda.time.format.DateTimeFormatter; +{{/joda}} +{{#threetenbp}} +import org.threeten.bp.LocalDate; +import org.threeten.bp.OffsetDateTime; +import org.threeten.bp.format.DateTimeFormatter; +{{/threetenbp}} +{{#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; +{{#java8}} +import java.time.LocalDate; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +{{/java8}} +import java.util.*; +import java.util.Map.Entry; +import java.util.concurrent.TimeUnit; +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}} + +public class ApiClient { + + private String basePath = "{{{basePath}}}"; + private boolean debugging = false; + private Map defaultHeaderMap = new HashMap(); + private Map defaultCookieMap = new HashMap(); + private String tempFolderPath = null; + + private Map authentications; + + private DateFormat dateFormat; + private DateFormat datetimeFormat; + private boolean lenientDatetimeFormat; + private int dateLength; + + private InputStream sslCaCert; + private boolean verifyingSsl; + private KeyManager[] keyManagers; + + private OkHttpClient httpClient; + private JSON json; + + private HttpLoggingInterceptor loggingInterceptor; + + {{#dynamicOperations}} + private 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}}{{^isBasicBasic}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/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}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + } + + /* + * Basic constructor with custom OkHttpClient + */ + public ApiClient(OkHttpClient client) { + init(); + + httpClient = client; + + // Setup authentications (key: authentication name, value: authentication).{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // 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 + */ + 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 + */ + 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 + */ + 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 + */ + public ApiClient(String basePath, String clientId, String clientSecret, Map parameters) { + init(); + if (basePath != null) { + this.basePath = basePath; + } + +{{#hasOAuthMethods}} + 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.{{flow}}, clientSecret, parameters); + authentications.put( + "{{name}}", + retryingOAuth + ); + initHttpClient(Collections.singletonList(retryingOAuth)); +{{/hasOAuthMethods}} + // Setup authentications (key: authentication name, value: authentication).{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{/authMethods}} + + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + } + + {{/-first}} + {{/oauthMethods}} + {{/hasOAuthMethods}} + private void initHttpClient() { + initHttpClient(Collections.emptyList()); + } + + private 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(); + } + + private void init() { + verifyingSsl = true; + + json = new JSON(); + + // Set default User-Agent. + setUserAgent("{{#httpUserAgent}}{{{.}}}{{/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 OkHttpClient + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + 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 Api Client + * @throws 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; + } + + 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; + } + + public DateFormat getDateFormat() { + return dateFormat; + } + + public ApiClient setDateFormat(DateFormat dateFormat) { + this.json.setDateFormat(dateFormat); + return this; + } + + public ApiClient setSqlDateFormat(DateFormat dateFormat) { + this.json.setSqlDateFormat(dateFormat); + return this; + } + + {{#joda}} + public ApiClient setDateTimeFormat(DateTimeFormatter dateFormat) { + this.json.setDateTimeFormat(dateFormat); + return this; + } + + public ApiClient setLocalDateFormat(DateTimeFormatter dateFormat) { + this.json.setLocalDateFormat(dateFormat); + return this; + } + + {{/joda}} + {{#jsr310}} + public ApiClient setOffsetDateTimeFormat(DateTimeFormatter dateFormat) { + this.json.setOffsetDateTimeFormat(dateFormat); + return this; + } + + public ApiClient setLocalDateFormat(DateTimeFormatter dateFormat) { + this.json.setLocalDateFormat(dateFormat); + return this; + } + + {{/jsr310}} + public ApiClient setLenientOnJson(boolean lenientOnJson) { + this.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) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBearerAuth) { + ((HttpBearerAuth) auth).setBearerToken(bearerToken); + 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!"); + } + + /** + * 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 tempopary 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 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 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 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(String.valueOf(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) { + 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 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.replaceAll(".*[/\\\\]", ""); + } + + /** + * 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, + * or matches "any", JSON will be used. + */ + public String selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0 || 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 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); + } + + String respBody; + try { + if (response.body() != null) + respBody = response.body().string(); + else + respBody = null; + } catch (IOException e) { + throw new ApiException(e); + } + + if (respBody == null || "".equals(respBody)) { + return null; + } + + String contentType = response.headers().get("Content-Type"); + if (contentType == null) { + // ensuring a default content type + contentType = "application/json"; + } + if (isJsonMime(contentType)) { + return json.deserialize(respBody, returnType); + } else if (returnType.equals(String.class)) { + // Expecting string, return the raw response body. + return (T) respBody; + } else { + throw new ApiException( + "Content type \"" + contentType + "\" is not supported for type: " + returnType, + response.code(), + response.headers().toMultimap(), + respBody); + } + } + + /** + * 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 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 (isJsonMime(contentType)) { + String content; + if (obj != null) { + content = json.serialize(obj); + } else { + content = null; + } + return RequestBody.create(content, 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 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 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 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 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); + } + } + + /** + * {@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 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 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 ApiException If fail to serialize the request body object + */ + public Call buildCall(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(path, method, queryParams, collectionQueryParams, body, headerParams, cookieParams, formParams, authNames, callback); + + return httpClient.newCall(request); + } + + /** + * Build an HTTP request with the given options. + * + * @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 ApiException If fail to serialize the request body object + */ + public Request buildRequest(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String[] authNames, ApiCallback callback) throws ApiException { + updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); + + final String url = buildUrl(path, queryParams, collectionQueryParams); + final Request.Builder reqBuilder = new Request.Builder().url(url); + processHeaderParams(headerParams, reqBuilder); + processCookieParams(cookieParams, reqBuilder); + + String contentType = (String) headerParams.get("Content-Type"); + // ensuring a default content type + if (contentType == null) { + contentType = "application/json"; + } + + RequestBody reqBody; + if (!HttpMethod.permitsRequestBody(method)) { + reqBody = null; + } else if ("application/x-www-form-urlencoded".equals(contentType)) { + reqBody = buildRequestBodyFormEncoding(formParams); + } else if ("multipart/form-data".equals(contentType)) { + 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("", MediaType.parse(contentType)); + } + } else { + reqBody = serialize(body, contentType); + } + + // 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 path The sub path + * @param queryParams The query parameters + * @param collectionQueryParams The collection query parameters + * @return The full URL + */ + public String buildUrl(String path, List queryParams, List collectionQueryParams) { + final StringBuilder url = new StringBuilder(); + url.append(basePath).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("%s=%s", param.getKey(), param.getValue())); + } + for (Entry param : defaultCookieMap.entrySet()) { + if (!cookieParams.containsKey(param.getKey())) { + reqBuilder.addHeader("Cookie", String.format("%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 + */ + public void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams, Map cookieParams) { + for (String authName : authNames) { + Authentication auth = authentications.get(authName); + if (auth == null) { + throw new RuntimeException("Authentication undefined: " + authName); + } + auth.applyToParams(queryParams, headerParams, cookieParams); + } + } + + /** + * 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(); + Headers partHeaders = Headers.of("Content-Disposition", "form-data; name=\"" + param.getKey() + "\"; filename=\"" + file.getName() + "\""); + MediaType mediaType = MediaType.parse(guessContentTypeFromFile(file)); + mpBuilder.addPart(partHeaders, RequestBody.create(file, mediaType)); + } else { + Headers partHeaders = Headers.of("Content-Disposition", "form-data; name=\"" + param.getKey() + "\""); + mpBuilder.addPart(partHeaders, RequestBody.create(parameterToString(param.getValue()), null)); + } + } + 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; + } + } + + /** + * Get network interceptor to add it to the httpClient to track download progress for + * async requests. + */ + private 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. + */ + private 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 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" + Integer.toString(index++); + caKeyStore.setCertificateEntry(certificateAlias, certificate); + } + trustManagerFactory.init(caKeyStore); + } + trustManagers = trustManagerFactory.getTrustManagers(); + 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); + } + } + + private 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; + } + + private 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.replaceAll("\\{" + 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}} +} diff --git a/.generator/templates/libraries/okhttp-gson/ApiResponse.mustache b/.generator/templates/libraries/okhttp-gson/ApiResponse.mustache new file mode 100644 index 00000000000..1e277319a93 --- /dev/null +++ b/.generator/templates/libraries/okhttp-gson/ApiResponse.mustache @@ -0,0 +1,58 @@ +{{>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. + * + * @param The type of data that is deserialized from response body + */ +public class ApiResponse { + final private int statusCode; + final private Map> headers; + final private T data; + + /** + * @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); + } + + /** + * @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; + } + + public int getStatusCode() { + return statusCode; + } + + public Map> getHeaders() { + return headers; + } + + public T getData() { + return data; + } +} diff --git a/.generator/templates/libraries/okhttp-gson/GzipRequestInterceptor.mustache b/.generator/templates/libraries/okhttp-gson/GzipRequestInterceptor.mustache new file mode 100644 index 00000000000..b633aa8f586 --- /dev/null +++ b/.generator/templates/libraries/okhttp-gson/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/.generator/templates/libraries/okhttp-gson/ProgressRequestBody.mustache b/.generator/templates/libraries/okhttp-gson/ProgressRequestBody.mustache new file mode 100644 index 00000000000..71e1e2b4cbe --- /dev/null +++ b/.generator/templates/libraries/okhttp-gson/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/.generator/templates/libraries/okhttp-gson/ProgressResponseBody.mustache b/.generator/templates/libraries/okhttp-gson/ProgressResponseBody.mustache new file mode 100644 index 00000000000..50f2eba395a --- /dev/null +++ b/.generator/templates/libraries/okhttp-gson/ProgressResponseBody.mustache @@ -0,0 +1,61 @@ +{{>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/.generator/templates/libraries/okhttp-gson/README.mustache b/.generator/templates/libraries/okhttp-gson/README.mustache new file mode 100644 index 00000000000..5b4ff7e38f5 --- /dev/null +++ b/.generator/templates/libraries/okhttp-gson/README.mustache @@ -0,0 +1,176 @@ +# {{artifactId}} + +{{appName}} +- API version: {{appVersion}} +{{^hideGenerationTimestamp}} + - Build date: {{generatedDate}} +{{/hideGenerationTimestamp}} + +{{#appDescriptionWithNewLines}}{{{appDescriptionWithNewLines}}}{{/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 {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}+ +2. Maven/Gradle + +## 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 +compile "{{{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 {{{invokerPackage}}}.models.*; +import {{{package}}}.{{{classname}}}; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("{{{basePath}}}"); + {{#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}}{{{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}}{{summary}}{{/summary}} +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} + +## Documentation for Models + +{{#models}}{{#model}} - [{{classname}}]({{modelDocPath}}{{classname}}.md) +{{/model}}{{/models}} + +## Documentation for Authorization + +{{^authMethods}}All endpoints do not require authorization. +{{/authMethods}}Authentication schemes defined for the API: +{{#authMethods}}### {{name}} + +{{#isApiKey}}- **Type**: API key +- **API key parameter name**: {{keyParamName}} +- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}} +{{/isApiKey}} +{{#isBasic}}- **Type**: HTTP basic authentication +{{/isBasic}} +{{#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/.generator/templates/libraries/okhttp-gson/api.mustache b/.generator/templates/libraries/okhttp-gson/api.mustache new file mode 100644 index 00000000000..6f71a36cd97 --- /dev/null +++ b/.generator/templates/libraries/okhttp-gson/api.mustache @@ -0,0 +1,481 @@ +{{>licenseInfo}} + +package {{package}}; + +import {{invokerPackage}}.ApiCallback; +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.ApiException; +{{#dynamicOperations}} +import {{invokerPackage}}.ApiOperation; +{{/dynamicOperations}} +import {{invokerPackage}}.ApiResponse; +import {{invokerPackage}}.Configuration; +import {{invokerPackage}}.Pair; +import {{invokerPackage}}.ProgressRequestBody; +import {{invokerPackage}}.ProgressResponseBody; +{{#performBeanValidation}} +import {{invokerPackage}}.BeanValidationException; +{{/performBeanValidation}} + +import com.google.gson.reflect.TypeToken; +{{#dynamicOperations}} +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.parameters.Parameter; +{{/dynamicOperations}} + +import java.io.IOException; + +{{#useBeanValidation}} +import javax.validation.constraints.*; +{{/useBeanValidation}} +{{#performBeanValidation}} +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.ValidatorFactory; +import javax.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; +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +{{#operations}} +public class {{classname}} { + private ApiClient localVarApiClient; + + 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; + } + + {{#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 + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/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}}{{{dataType}}} {{paramName}}, {{/allParams}}final ApiCallback _callback) throws ApiException { + Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + + // create path and map variables + {{^dynamicOperations}} + String localVarPath = "{{{path}}}"{{#pathParams}} + .replaceAll("\\{" + "{{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}} + + {{javaUtilPrefix}}List localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}List localVarCollectionQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}Map localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarCookieParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap(); + + {{#formParams}} + if ({{paramName}} != null) { + localVarFormParams.put("{{baseName}}", {{paramName}}); + } + + {{/formParams}} + {{^dynamicOperations}} + {{#queryParams}} + if ({{paramName}} != null) { + {{#collectionFormat}}localVarCollectionQueryParams.addAll(localVarApiClient.parameterToPairs("{{{collectionFormat}}}", {{/collectionFormat}}{{^collectionFormat}}localVarQueryParams.addAll(localVarApiClient.parameterToPair({{/collectionFormat}}"{{baseName}}", {{paramName}})); + } + + {{/queryParams}} + {{#headerParams}} + if ({{paramName}} != null) { + localVarHeaderParams.put("{{baseName}}", localVarApiClient.parameterToString({{paramName}})); + } + + {{/headerParams}} + {{#cookieParams}} + if ({{paramName}} != null) { + localVarCookieParams.put("{{baseName}}", localVarApiClient.parameterToString({{paramName}})); + } + + {{/cookieParams}} + {{/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); + localVarHeaderParams.put("Content-Type", localVarContentType); + + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; + return localVarApiClient.buildCall(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}}{{{dataType}}} {{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}} + + okhttp3.Call localVarCall = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}_callback); + return localVarCall; + + {{/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}}{{{dataType}}}{{/isMap}}{{/isArray}}.class{{/allParams}}); + Set> violations = executableValidator.validateParameters(this, method, + parameterValues); + + if (violations.size() == 0) { + okhttp3.Call localVarCall = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}_callback); + return localVarCall; + + } 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}}{{/returnType}} + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + {{#returnType}}ApiResponse<{{{returnType}}}> localVarResp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}} + return localVarResp.getData();{{/returnType}} + } + {{/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}}{{/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 + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/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}} ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + okhttp3.Call localVarCall = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}null); + {{#returnType}}Type localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); + return localVarApiClient.execute(localVarCall, localVarReturnType);{{/returnType}}{{^returnType}}return localVarApiClient.execute(localVarCall);{{/returnType}} + } + + {{^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 + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/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}}{{{dataType}}} {{paramName}}, {{/allParams}}final ApiCallback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> _callback) throws ApiException { + + okhttp3.Call localVarCall = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}_callback); + {{#returnType}}Type localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); + localVarApiClient.executeAsync(localVarCall, localVarReturnType, _callback);{{/returnType}}{{^returnType}}localVarApiClient.executeAsync(localVarCall, _callback);{{/returnType}} + return localVarCall; + } + {{#vendorExtensions.x-group-parameters}} + + public class API{{operationId}}Request { + {{#requiredParams}} + private final {{{dataType}}} {{paramName}}; + {{/requiredParams}} + {{#optionalParams}} + private {{{dataType}}} {{paramName}}; + {{/optionalParams}} + + private API{{operationId}}Request({{#requiredParams}}{{{dataType}}} {{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}}({{{dataType}}} {{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 + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/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}}{{/returnType}} + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} execute() throws ApiException { + {{#returnType}}ApiResponse<{{{returnType}}}> localVarResp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}} + return localVarResp.getData();{{/returnType}} + } + + /** + * Execute {{operationId}} request with HTTP info returned + * @return ApiResponse<{{#returnType}}{{returnType}}{{/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 + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> executeWithHttpInfo() throws ApiException { + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + } + + /** + * 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 + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public okhttp3.Call executeAsync(final ApiCallback<{{#returnType}}{{{returnType}}}{{/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 + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public API{{operationId}}Request {{operationId}}({{#requiredParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}) { + return new API{{operationId}}Request({{#requiredParams}}{{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}); + } + {{/vendorExtensions.x-group-parameters}} + {{/operation}} +} +{{/operations}} diff --git a/.generator/templates/libraries/okhttp-gson/apiException.mustache b/.generator/templates/libraries/okhttp-gson/apiException.mustache new file mode 100644 index 00000000000..d28b1bd9630 --- /dev/null +++ b/.generator/templates/libraries/okhttp-gson/apiException.mustache @@ -0,0 +1,96 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import java.util.Map; +import java.util.List; +{{#caseInsensitiveResponseHeaders}} +import java.util.Map.Entry; +import java.util.TreeMap; +{{/caseInsensitiveResponseHeaders}} + +{{>generatedAnnotation}} +public class ApiException extends{{#useRuntimeException}} RuntimeException {{/useRuntimeException}}{{^useRuntimeException}} Exception {{/useRuntimeException}}{ + private int code = 0; + private Map> responseHeaders = null; + private String responseBody = null; + + public ApiException() {} + + public ApiException(Throwable throwable) { + super(throwable); + } + + public ApiException(String message) { + super(message); + } + + 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; + } + + public ApiException(String message, int code, Map> responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(String message, Throwable throwable, int code, Map> responseHeaders) { + this(message, throwable, code, responseHeaders, null); + } + + public ApiException(int code, Map> responseHeaders, String responseBody) { + this((String) null, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(int code, String message) { + super(message); + this.code = code; + } + + 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; + } +} diff --git a/.generator/templates/libraries/okhttp-gson/api_doc.mustache b/.generator/templates/libraries/okhttp-gson/api_doc.mustache new file mode 100644 index 00000000000..332088661a9 --- /dev/null +++ b/.generator/templates/libraries/okhttp-gson/api_doc.mustache @@ -0,0 +1,106 @@ +# {{classname}}{{#description}} +{{description}}{{/description}} + +All URIs are relative to *{{basePath}}* + +Method | HTTP request | Description +------------- | ------------- | ------------- +{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}} + +{{#operations}} +{{#operation}} + +# **{{operationId}}**{{^vendorExtensions.x-group-parameters}} +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}){{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}} +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#requiredParams}}{{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}){{#optionalParams}}.{{paramName}}({{paramName}}){{/optionalParams}}.execute();{{/vendorExtensions.x-group-parameters}} + +{{summary}}{{#notes}} + +{{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}}}"); + {{#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}}{{{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}}]{{/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/.generator/templates/libraries/okhttp-gson/api_test.mustache b/.generator/templates/libraries/okhttp-gson/api_test.mustache new file mode 100644 index 00000000000..050bf8617d6 --- /dev/null +++ b/.generator/templates/libraries/okhttp-gson/api_test.mustache @@ -0,0 +1,47 @@ +{{>licenseInfo}} + +package {{package}}; + +import {{invokerPackage}}.ApiException; +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Test; +import org.junit.Ignore; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +@Ignore +public class {{classname}}Test { + + private final {{classname}} api = new {{classname}}(); + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + * + * @throws ApiException + * if the Api call fails + */ + @Test + public void {{operationId}}Test() throws ApiException { + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + {{#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}} + + // TODO: test validations + } + {{/operation}}{{/operations}} +} diff --git a/.generator/templates/libraries/okhttp-gson/auth/HttpBasicAuth.mustache b/.generator/templates/libraries/okhttp-gson/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..9cff50a7475 --- /dev/null +++ b/.generator/templates/libraries/okhttp-gson/auth/HttpBasicAuth.mustache @@ -0,0 +1,43 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; + +import okhttp3.Credentials; + +import java.util.Map; +import java.util.List; + +import java.io.UnsupportedEncodingException; + +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) { + if (username == null && password == null) { + return; + } + headerParams.put("Authorization", Credentials.basic( + username == null ? "" : username, + password == null ? "" : password)); + } +} diff --git a/.generator/templates/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache b/.generator/templates/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache new file mode 100644 index 00000000000..cb0e8250550 --- /dev/null +++ b/.generator/templates/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache @@ -0,0 +1,70 @@ +{{#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(), + responseClass); + } catch (IOException e) { + throw new OAuthSystemException(e); + } + } + + @Override + public void shutdown() { + // Nothing to do here + } +} +{{/hasOAuthMethods}} diff --git a/.generator/templates/libraries/okhttp-gson/auth/RetryingOAuth.mustache b/.generator/templates/libraries/okhttp-gson/auth/RetryingOAuth.mustache new file mode 100644 index 00000000000..3ddacedb70e --- /dev/null +++ b/.generator/templates/libraries/okhttp-gson/auth/RetryingOAuth.mustache @@ -0,0 +1,183 @@ +{{#hasOAuthMethods}} +package {{invokerPackage}}.auth; + +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.util.Map; +import java.util.List; + +public class RetryingOAuth extends OAuth implements Interceptor { + private OAuthClient oAuthClient; + + private TokenRequestBuilder tokenRequestBuilder; + + public RetryingOAuth(OkHttpClient client, TokenRequestBuilder tokenRequestBuilder) { + this.oAuthClient = new OAuthClient(new OAuthOkHttpClient(client)); + this.tokenRequestBuilder = tokenRequestBuilder; + } + + 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 clientSecret The OAuth2 client secret for the "clientCredentials" flow. + */ + 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 (String paramName : parameters.keySet()) { + tokenRequestBuilder.setParameter(paramName, parameters.get(paramName)); + } + } + } + + public void setFlow(OAuthFlow flow) { + switch(flow) { + case accessCode: + 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 (String headerName : headers.keySet()) { + requestBuilder.addHeader(headerName, headers.get(headerName)); + } + 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 + */ + 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()); + return !getAccessToken().equals(requestAccessToken); + } + } catch (OAuthSystemException | OAuthProblemException e) { + throw new IOException(e); + } + } + + return false; + } + + public TokenRequestBuilder getTokenRequestBuilder() { + return tokenRequestBuilder; + } + + 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) { + // No implementation necessary + } +} +{{/hasOAuthMethods}} diff --git a/.generator/templates/libraries/okhttp-gson/build.gradle.mustache b/.generator/templates/libraries/okhttp-gson/build.gradle.mustache new file mode 100644 index 00000000000..c027064edd4 --- /dev/null +++ b/.generator/templates/libraries/okhttp-gson/build.gradle.mustache @@ -0,0 +1,142 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' +{{#sourceFolder}} +apply plugin: 'java' +{{/sourceFolder}} + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + maven { url "https://repo1.maven.org/maven2" } + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +repositories { + jcenter() +} +{{#sourceFolder}} +sourceSets { + main.java.srcDirs = ['{{sourceFolder}}'] +} + +{{/sourceFolder}} +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:javax.annotation-api:1.3.2' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + {{#java8}} + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + {{/java8}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +dependencies { + implementation 'io.swagger:swagger-annotations:1.5.24' + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation 'com.squareup.okhttp3:okhttp:3.14.7' + implementation 'com.squareup.okhttp3:logging-interceptor:3.14.7' + implementation 'com.google.code.gson:gson:2.8.6' + implementation 'io.gsonfire:gson-fire:1.8.4' + {{#hasOAuthMethods}} + implementation group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.1' + {{/hasOAuthMethods}} + implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.10' + {{#joda}} + implementation 'joda-time:joda-time:2.9.9' + {{/joda}} + {{#threetenbp}} + implementation 'org.threeten:threetenbp:1.4.3' + {{/threetenbp}} + {{#dynamicOperations}} + implementation 'io.swagger.parser.v3:swagger-parser-v3:2.0.23' + {{/dynamicOperations}} + implementation 'javax.annotation:javax.annotation-api:1.3.2' + testImplementation 'junit:junit:4.13.1' +} + +javadoc { + options.tags = [ "http.response.details:a:Http Response Details" ] +} diff --git a/.generator/templates/libraries/okhttp-gson/build.sbt.mustache b/.generator/templates/libraries/okhttp-gson/build.sbt.mustache new file mode 100644 index 00000000000..a14047e7998 --- /dev/null +++ b/.generator/templates/libraries/okhttp-gson/build.sbt.mustache @@ -0,0 +1,36 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "io.swagger" % "swagger-annotations" % "1.5.24", + "com.squareup.okhttp3" % "okhttp" % "3.14.7", + "com.squareup.okhttp3" % "logging-interceptor" % "3.14.7", + "com.google.code.gson" % "gson" % "2.8.6", + "org.apache.commons" % "commons-lang3" % "3.10", + {{#hasOAuthMethods}} + "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1", + {{/hasOAuthMethods}} + {{#joda}} + "joda-time" % "joda-time" % "2.9.9" % "compile", + {{/joda}} + {{#threetenbp}} + "org.threeten" % "threetenbp" % "1.4.3" % "compile", + {{/threetenbp}} + {{#dynamicOperations}} + "io.swagger.parser.v3" % "swagger-parser-v3" "2.0.23" % "compile" + {{/dynamicOperations}} + "io.gsonfire" % "gson-fire" % "1.8.3" % "compile", + "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", + "com.google.code.findbugs" % "jsr305" % "3.0.2" % "compile", + "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", + "junit" % "junit" % "4.13.1" % "test", + "com.novocode" % "junit-interface" % "0.10" % "test" + ) + ) diff --git a/.generator/templates/libraries/okhttp-gson/pom.mustache b/.generator/templates/libraries/okhttp-gson/pom.mustache new file mode 100644 index 00000000000..74a1b796dcd --- /dev/null +++ b/.generator/templates/libraries/okhttp-gson/pom.mustache @@ -0,0 +1,348 @@ + + 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 + + true + 128m + 512m + + -Xlint:all + -J-Xss4m + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M4 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + 10 + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + 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.1.1 + + + attach-javadocs + + jar + + + + + none + + + http.response.details + a + Http Response Details: + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-core-version} + + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + com.squareup.okhttp3 + okhttp + ${okhttp-version} + + + com.squareup.okhttp3 + logging-interceptor + ${okhttp-version} + + + com.google.code.gson + gson + ${gson-version} + + + io.gsonfire + gson-fire + ${gson-fire-version} + + {{#hasOAuthMethods}} + + org.apache.oltu.oauth2 + org.apache.oltu.oauth2.client + 1.0.1 + + {{/hasOAuthMethods}} + + org.apache.commons + commons-lang3 + ${commons-lang3-version} + + {{#joda}} + + joda-time + joda-time + ${jodatime-version} + + {{/joda}} + {{#threetenbp}} + + org.threeten + threetenbp + ${threetenbp-version} + + {{/threetenbp}} + {{#dynamicOperations}} + + io.swagger.parser.v3 + swagger-parser-v3 + 2.0.23 + + {{/dynamicOperations}} + {{#useBeanValidation}} + + + javax.validation + validation-api + 1.1.0.Final + provided + + {{/useBeanValidation}} + {{#performBeanValidation}} + + + org.hibernate + hibernate-validator + 5.4.1.Final + + + javax.el + el-api + 2.2 + + {{/performBeanValidation}} + {{#parcelableModel}} + + + com.google.android + android + 4.1.1.4 + provided + + {{/parcelableModel}} + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + + + + junit + junit + ${junit-version} + test + + + + {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}} + ${java.version} + ${java.version} + 1.8.5 + 1.6.2 + 4.9.1 + 2.8.6 + 3.11 + {{#joda}} + 2.10.9 + {{/joda}} + {{#threetenbp}} + 1.5.0 + {{/threetenbp}} + 1.3.2 + 4.13.1 + UTF-8 + + diff --git a/.generator/templates/libraries/rest-assured/ApiClient.mustache b/.generator/templates/libraries/rest-assured/ApiClient.mustache new file mode 100644 index 00000000000..1a691ea9482 --- /dev/null +++ b/.generator/templates/libraries/rest-assured/ApiClient.mustache @@ -0,0 +1,62 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import {{apiPackage}}.*; + +{{#imports}}import {{import}}; +{{/imports}} +{{^fullJavaUtil}} +import io.restassured.builder.RequestSpecBuilder; +import java.util.function.Consumer; +import java.util.function.Supplier; + +import static io.restassured.config.ObjectMapperConfig.objectMapperConfig; +import static io.restassured.config.RestAssuredConfig.config; +import static {{invokerPackage}}.{{#gson}}GsonObjectMapper.gson{{/gson}}{{#jackson}}JacksonObjectMapper.jackson{{/jackson}}; + +{{/fullJavaUtil}} + +public class ApiClient { + {{#basePath}} + public static final String BASE_URI = "{{basePath}}"; + {{/basePath}} + + private final Config config; + + private ApiClient(Config config) { + this.config = config; + } + + public static ApiClient api(Config config) { + return new ApiClient(config); + } + + {{#apiInfo}} + {{#apis}} + public {{classname}} {{classVarName}}() { + return {{classname}}.{{classVarName}}(config.reqSpecSupplier); + } + {{/apis}} + {{/apiInfo}} + + public static class Config { + private Supplier reqSpecSupplier = () -> new RequestSpecBuilder() + {{#basePath}}.setBaseUri(BASE_URI){{/basePath}} + .setConfig(config().objectMapperConfig(objectMapperConfig().defaultObjectMapper({{#gson}}gson(){{/gson}}{{#jackson}}jackson(){{/jackson}}))); + + /** + * Use common specification for all operations + * @param supplier supplier + * @return configuration + */ + public Config reqSpecSupplier(Supplier supplier) { + this.reqSpecSupplier = supplier; + return this; + } + + public static Config apiConfig() { + return new Config(); + } + } +} \ No newline at end of file diff --git a/.generator/templates/libraries/rest-assured/GsonObjectMapper.mustache b/.generator/templates/libraries/rest-assured/GsonObjectMapper.mustache new file mode 100644 index 00000000000..320d8141f95 --- /dev/null +++ b/.generator/templates/libraries/rest-assured/GsonObjectMapper.mustache @@ -0,0 +1,30 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import io.restassured.mapper.ObjectMapper; +import io.restassured.mapper.ObjectMapperDeserializationContext; +import io.restassured.mapper.ObjectMapperSerializationContext; + +public class GsonObjectMapper implements ObjectMapper { + + private JSON json; + + private GsonObjectMapper() { + this.json = new JSON(); + } + + public static GsonObjectMapper gson() { + return new GsonObjectMapper(); + } + + @Override + public Object deserialize(ObjectMapperDeserializationContext context) { + return json.deserialize(context.getDataToDeserialize().asString(), context.getType()); + } + + @Override + public Object serialize(ObjectMapperSerializationContext context) { + return json.serialize(context.getObjectToSerialize()); + } +} \ No newline at end of file diff --git a/.generator/templates/libraries/rest-assured/JacksonObjectMapper.mustache b/.generator/templates/libraries/rest-assured/JacksonObjectMapper.mustache new file mode 100644 index 00000000000..6af705a9d9d --- /dev/null +++ b/.generator/templates/libraries/rest-assured/JacksonObjectMapper.mustache @@ -0,0 +1,68 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +{{#threetenbp}} +import org.threeten.bp.*; +{{/threetenbp}} +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.*; +{{#openApiNullable}} +import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} +{{#java8}} +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{/java8}} +{{#joda}} +import com.fasterxml.jackson.datatype.joda.JodaModule; +{{/joda}} +{{#threetenbp}} +import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; +{{/threetenbp}} + +import io.restassured.internal.mapping.Jackson2Mapper; +import io.restassured.path.json.mapper.factory.Jackson2ObjectMapperFactory; + + +public class JacksonObjectMapper extends Jackson2Mapper { + + private JacksonObjectMapper() { + super(createFactory()); + } + + private static Jackson2ObjectMapperFactory createFactory() { + return (cls, charset) -> { + ObjectMapper mapper = new ObjectMapper(); + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.setDateFormat(new RFC3339DateFormat()); + {{#java8}} + mapper.registerModule(new JavaTimeModule()); + {{/java8}} + {{#joda}} + mapper.registerModule(new JodaModule()); + {{/joda}} + {{#threetenbp}} + ThreeTenModule module = new ThreeTenModule(); + module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); + module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); + module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); + mapper.registerModule(module); + {{/threetenbp}} + {{#openApiNullable}} + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); + {{/openApiNullable}} + return mapper; + }; + } + + public static JacksonObjectMapper jackson() { + return new JacksonObjectMapper(); + } +} \ No newline at end of file diff --git a/.generator/templates/libraries/rest-assured/Oper.mustache b/.generator/templates/libraries/rest-assured/Oper.mustache new file mode 100644 index 00000000000..b8684665b56 --- /dev/null +++ b/.generator/templates/libraries/rest-assured/Oper.mustache @@ -0,0 +1,13 @@ +{{>licenseInfo}} + +package {{apiPackage}}; + +import io.restassured.response.Response; + +import java.util.function.Function; + +public interface Oper { + + T execute(Function handler); + +} diff --git a/.generator/templates/libraries/rest-assured/README.mustache b/.generator/templates/libraries/rest-assured/README.mustache new file mode 100644 index 00000000000..a0fac9d41df --- /dev/null +++ b/.generator/templates/libraries/rest-assured/README.mustache @@ -0,0 +1,43 @@ +# {{artifactId}} + +## Requirements + +Building the API client library requires [Maven](https://maven.apache.org/) to be installed. + +## Installation & Usage + +To install the API client library to your local Maven repository, simply execute: + +```shell +mvn install +``` + +To deploy it to a remote Maven repository instead, configure the settings of the repository and execute: + +```shell +mvn deploy +``` + +Refer to the [official documentation](https://maven.apache.org/plugins/maven-deploy-plugin/usage.html) for more information. + +After the client library is installed/deployed, you can use it in your Maven project by adding the following to your *pom.xml*: + +```xml + + {{groupId}} + {{artifactId}} + {{artifactVersion}} + compile + + +``` + +## 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/.generator/templates/libraries/rest-assured/ResponseSpecBuilders.mustache b/.generator/templates/libraries/rest-assured/ResponseSpecBuilders.mustache new file mode 100644 index 00000000000..af7e7ac960f --- /dev/null +++ b/.generator/templates/libraries/rest-assured/ResponseSpecBuilders.mustache @@ -0,0 +1,31 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import io.restassured.builder.ResponseSpecBuilder; +import io.restassured.response.Response; +import io.restassured.specification.ResponseSpecification; + +import java.util.function.Function; + +public class ResponseSpecBuilders { + + private ResponseSpecBuilders() { + } + + public static Function validatedWith(ResponseSpecification respSpec) { + return response -> response.then().spec(respSpec).extract().response(); + } + + public static Function validatedWith(ResponseSpecBuilder respSpec) { + return validatedWith(respSpec.build()); + } + + /** + * @param code expected status code + * @return ResponseSpecBuilder + */ + public static ResponseSpecBuilder shouldBeCode(int code) { + return new ResponseSpecBuilder().expectStatusCode(code); + } +} \ No newline at end of file diff --git a/.generator/templates/libraries/rest-assured/api.mustache b/.generator/templates/libraries/rest-assured/api.mustache new file mode 100644 index 00000000000..dea1217125e --- /dev/null +++ b/.generator/templates/libraries/rest-assured/api.mustache @@ -0,0 +1,266 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#gson}} +import com.google.gson.reflect.TypeToken; +{{/gson}} +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import io.restassured.RestAssured; +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.builder.ResponseSpecBuilder; +{{#jackson}} +import io.restassured.common.mapper.TypeRef; +{{/jackson}} +import io.restassured.http.Method; +import io.restassured.response.Response; +import io.swagger.annotations.*; + +import java.lang.reflect.Type; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; +{{/fullJavaUtil}} +{{#gson}} +import {{invokerPackage}}.JSON; +{{/gson}} +import static io.restassured.http.Method.*; + +@Api(value = "{{{baseName}}}") +public class {{classname}} { + + private Supplier reqSpecSupplier; + private Consumer reqSpecCustomizer; + + private {{classname}}(Supplier reqSpecSupplier) { + this.reqSpecSupplier = reqSpecSupplier; + } + + public static {{classname}} {{classVarName}}(Supplier reqSpecSupplier) { + return new {{classname}}(reqSpecSupplier); + } + + private RequestSpecBuilder createReqSpec() { + RequestSpecBuilder reqSpec = reqSpecSupplier.get(); + if(reqSpecCustomizer != null) { + reqSpecCustomizer.accept(reqSpec); + } + return reqSpec; + } + + public List getAllOperations() { + return Arrays.asList( +{{#operations}} +{{#operation}} + {{operationId}}(){{^-last}},{{/-last}} +{{/operation}} +{{/operations}} + ); + } +{{#operations}} +{{#operation}} + + @ApiOperation(value = "{{{summary}}}", + notes = "{{{notes}}}", + nickname = "{{{operationId}}}", + tags = { {{#tags}}{{#name}}"{{{name}}}"{{/name}}{{^-last}}, {{/-last}}{{/tags}} }) + @ApiResponses(value = { {{#responses}} + @ApiResponse(code = {{{code}}}, message = "{{{message}}}") {{^-last}},{{/-last}}{{/responses}} }) + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{operationIdCamelCase}}Oper {{operationId}}() { + return new {{operationIdCamelCase}}Oper(createReqSpec()); + } +{{/operation}} +{{/operations}} + + /** + * Customize request specification + * @param reqSpecCustomizer consumer to modify the RequestSpecBuilder + * @return api + */ + public {{classname}} reqSpec(Consumer reqSpecCustomizer) { + this.reqSpecCustomizer = reqSpecCustomizer; + return this; + } + + {{#operations}} + {{#operation}} + /** + * {{summary}} + * {{notes}} + * + {{#allParams}} + * @see #{{#isPathParam}}{{paramName}}Path{{/isPathParam}}{{#isQueryParam}}{{paramName}}Query{{/isQueryParam}}{{#isFormParam}}{{^isFile}}{{paramName}}Form{{/isFile}}{{#isFile}}{{paramName}}MultiPart{{/isFile}}{{/isFormParam}}{{#isHeaderParam}}{{paramName}}Header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + {{#returnType}} + * return {{returnType}} + {{/returnType}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public static class {{operationIdCamelCase}}Oper implements Oper { + + public static final Method REQ_METHOD = {{httpMethod}}; + public static final String REQ_URI = "{{path}}"; + + private RequestSpecBuilder reqSpec; + private ResponseSpecBuilder respSpec; + + public {{operationIdCamelCase}}Oper(RequestSpecBuilder reqSpec) { + this.reqSpec = reqSpec; + {{#vendorExtensions}} + {{#x-contentType}} + reqSpec.setContentType("{{x-contentType}}"); + {{/x-contentType}} + {{#x-accepts}} + reqSpec.setAccept("{{x-accepts}}"); + {{/x-accepts}} + {{/vendorExtensions}} + this.respSpec = new ResponseSpecBuilder(); + } + + /** + * {{httpMethod}} {{path}} + * @param handler handler + * @param type + * @return type + */ + @Override + public T execute(Function handler) { + return handler.apply(RestAssured.given().spec(reqSpec.build()).expect().spec(respSpec.build()).when().request(REQ_METHOD, REQ_URI)); + } + {{#returnType}} + + /** + * {{httpMethod}} {{path}} + * @param handler handler + * @return {{returnType}} + */ + public {{{returnType}}} executeAs(Function handler) { + {{#gson}}Type type = new TypeToken<{{{returnType}}}>(){}.getType(); + {{/gson}}{{#jackson}}TypeRef<{{{returnType}}}> type = new TypeRef<{{{returnType}}}>(){}; + {{/jackson}}return execute(handler).as(type); + } + {{/returnType}} + {{#bodyParams}} + + /** + * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @return operation + */ + public {{operationIdCamelCase}}Oper body({{{dataType}}} {{paramName}}) { + reqSpec.setBody({{paramName}}); + return this; + } + {{/bodyParams}} + {{#headerParams}} + + public static final String {{#convert}}{{paramName}}{{/convert}}_HEADER = "{{baseName}}"; + + /** + * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @return operation + */ + public {{operationIdCamelCase}}Oper {{paramName}}Header(String {{paramName}}) { + reqSpec.addHeader({{#convert}}{{paramName}}{{/convert}}_HEADER, {{paramName}}); + return this; + } + {{/headerParams}} + {{#pathParams}} + + public static final String {{#convert}}{{paramName}}{{/convert}}_PATH = "{{baseName}}"; + + /** + * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @return operation + */ + public {{operationIdCamelCase}}Oper {{paramName}}Path(Object {{paramName}}) { + reqSpec.addPathParam({{#convert}}{{paramName}}{{/convert}}_PATH, {{paramName}}); + return this; + } + {{/pathParams}} + {{#queryParams}} + + public static final String {{#convert}}{{paramName}}{{/convert}}_QUERY = "{{baseName}}"; + + /** + * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @return operation + */ + public {{operationIdCamelCase}}Oper {{paramName}}Query(Object... {{paramName}}) { + reqSpec.addQueryParam({{#convert}}{{paramName}}{{/convert}}_QUERY, {{paramName}}); + return this; + } + {{/queryParams}} + {{#formParams}} + {{^isFile}} + + public static final String {{#convert}}{{paramName}}{{/convert}}_FORM = "{{baseName}}"; + + /** + * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @return operation + */ + public {{operationIdCamelCase}}Oper {{paramName}}Form(Object... {{paramName}}) { + reqSpec.addFormParam({{#convert}}{{paramName}}{{/convert}}_FORM, {{paramName}}); + return this; + } + {{/isFile}} + {{/formParams}} + {{#formParams}} + {{#isFile}} + + /** + * It will assume that the control name is file and the <content-type> is <application/octet-stream> + * @see #reqSpec for customise + * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @return operation + */ + public {{operationIdCamelCase}}Oper {{paramName}}MultiPart({{{dataType}}} {{paramName}}) { + reqSpec.addMultiPart({{paramName}}); + return this; + } + {{/isFile}} + {{/formParams}} + + /** + * Customize request specification + * @param reqSpecCustomizer consumer to modify the RequestSpecBuilder + * @return operation + */ + public {{operationIdCamelCase}}Oper reqSpec(Consumer reqSpecCustomizer) { + reqSpecCustomizer.accept(reqSpec); + return this; + } + + /** + * Customize response specification + * @param respSpecCustomizer consumer to modify the ResponseSpecBuilder + * @return operation + */ + public {{operationIdCamelCase}}Oper respSpec(Consumer respSpecCustomizer) { + respSpecCustomizer.accept(respSpec); + return this; + } + } +{{/operation}} +{{/operations}} +} diff --git a/.generator/templates/libraries/rest-assured/api_doc.mustache b/.generator/templates/libraries/rest-assured/api_doc.mustache new file mode 100644 index 00000000000..f173a89016e --- /dev/null +++ b/.generator/templates/libraries/rest-assured/api_doc.mustache @@ -0,0 +1,62 @@ +# {{classname}}{{#description}} +{{description}}{{/description}} + +All URIs are relative to *{{basePath}}* + +Method | HTTP request | Description +------------- | ------------- | ------------- +{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}} + +{{#operations}} +{{#operation}} + +# **{{operationId}}** +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}) + +{{summary}}{{#notes}} + +{{notes}}{{/notes}} + +### Example +```java +// Import classes: +//import {{invokerPackage}}.ApiClient; +//import io.restassured.builder.RequestSpecBuilder; +//import io.restassured.filter.log.ErrorLoggingFilter; + +{{classname}} api = ApiClient.api(ApiClient.Config.apiConfig().withReqSpecSupplier( + () -> new RequestSpecBuilder() + .setBaseUri("{{basePath}}"))).{{classVarName}}(); + +api.{{operationId}}(){{#allParams}}{{#required}}{{#isPathParam}} + .{{paramName}}Path({{paramName}}){{/isPathParam}}{{#isQueryParam}} + .{{paramName}}Query({{paramName}}){{/isQueryParam}}{{#isFormParam}}{{^isFile}} + .{{paramName}}Form({{paramName}}){{/isFile}}{{/isFormParam}}{{#isFormParam}}{{#isFile}} + .{{paramName}}MultiPart({{paramName}}){{/isFile}}{{/isFormParam}}{{#isHeaderParam}} + .{{paramName}}Header({{paramName}}){{/isHeaderParam}}{{#isBodyParam}} + .body({{paramName}}){{/isBodyParam}}{{/required}}{{/allParams}}.execute(r -> r.prettyPeek()); +``` + +### 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}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{#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}} + +{{/operation}} +{{/operations}} diff --git a/.generator/templates/libraries/rest-assured/api_test.mustache b/.generator/templates/libraries/rest-assured/api_test.mustache new file mode 100644 index 00000000000..74a1c9f7e8c --- /dev/null +++ b/.generator/templates/libraries/rest-assured/api_test.mustache @@ -0,0 +1,66 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +import {{invokerPackage}}.ApiClient; +import {{apiPackage}}.{{classname}}; +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.filter.log.ErrorLoggingFilter; +import org.junit.Before; +import org.junit.Test; +import org.junit.Ignore; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} +import static io.restassured.config.ObjectMapperConfig.objectMapperConfig; +import static io.restassured.config.RestAssuredConfig.config; +import static {{invokerPackage}}.{{#gson}}GsonObjectMapper.gson{{/gson}}{{#jackson}}JacksonObjectMapper.jackson{{/jackson}}; + +/** + * API tests for {{classname}} + */ +@Ignore +public class {{classname}}Test { + + private {{classname}} api; + + @Before + public void createApi() { + api = ApiClient.api(ApiClient.Config.apiConfig().reqSpecSupplier( + () -> new RequestSpecBuilder() + .setConfig(config().objectMapperConfig(objectMapperConfig().defaultObjectMapper({{#gson}}gson(){{/gson}}{{#jackson}}jackson(){{/jackson}}))) + .addFilter(new ErrorLoggingFilter()) + .setBaseUri("{{{basePath}}}"))).{{classVarName}}(); + } +{{#operations}} +{{#operation}} + + {{#responses}} + /** + * {{message}} + */ + @Test + public void shouldSee{{code}}After{{operationIdCamelCase}}() { + {{#allParams}} + {{#isHeaderParam}}String {{paramName}} = null;{{/isHeaderParam}}{{^isHeaderParam}}{{{dataType}}} {{paramName}} = null;{{/isHeaderParam}} + {{/allParams}} + api.{{operationId}}(){{#allParams}}{{#required}}{{#isPathParam}} + .{{paramName}}Path({{paramName}}){{/isPathParam}}{{#isQueryParam}} + .{{paramName}}Query({{paramName}}){{/isQueryParam}}{{#isFormParam}}{{^isFile}} + .{{paramName}}Form({{paramName}}){{/isFile}}{{/isFormParam}}{{#isFormParam}}{{#isFile}} + .{{paramName}}MultiPart({{paramName}}){{/isFile}}{{/isFormParam}}{{#isHeaderParam}} + .{{paramName}}Header({{paramName}}){{/isHeaderParam}}{{#isBodyParam}} + .body({{paramName}}){{/isBodyParam}}{{/required}}{{/allParams}}.execute(r -> r.prettyPeek()); + // TODO: test validations + } + + {{/responses}} +{{/operation}} +{{/operations}} +} \ No newline at end of file diff --git a/.generator/templates/libraries/rest-assured/build.gradle.mustache b/.generator/templates/libraries/rest-assured/build.gradle.mustache new file mode 100644 index 00000000000..28c213b41b7 --- /dev/null +++ b/.generator/templates/libraries/rest-assured/build.gradle.mustache @@ -0,0 +1,168 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + maven { url "https://repo1.maven.org/maven2" } + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.5.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 23 + buildToolsVersion '23.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 22 + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + swagger_annotations_version = "1.5.21" + rest_assured_version = "4.3.0" + junit_version = "4.13.1" +{{#jackson}} + jackson_version = "2.10.3" + jackson_databind_version = "2.10.3" + {{#openApiNullable}} + jackson_databind_nullable_version = "0.2.1" + {{/openApiNullable}} + {{#threetenbp}} + jackson_threetenbp_version = "2.10.0" + {{/threetenbp}} +{{/jackson}} +{{#gson}} + gson_version = "2.8.6" + gson_fire_version = "1.8.4" +{{/gson}} +{{#joda}} + jodatime_version = "2.10.5" +{{/joda}} +{{#threetenbp}} + threetenbp_version = "1.4.3" +{{/threetenbp}} + okio_version = "1.17.5" +} + +dependencies { + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "io.rest-assured:rest-assured:$rest_assured_version" +{{#jackson}} + 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_databind_version" + implementation "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + {{#openApiNullable}} + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} + {{#withXml}} + implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version" + {{/withXml}} + {{#joda}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + {{/joda}} + {{#java8}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{/java8}} + {{#threetenbp}} + implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threetenbp_version" + {{/threetenbp}} +{{/jackson}} +{{#gson}} + implementation "io.gsonfire:gson-fire:$gson_fire_version" + implementation 'com.google.code.gson:gson:$gson_version' +{{/gson}} +{{#joda}} + implementation "joda-time:joda-time:$jodatime_version" +{{/joda}} +{{#threetenbp}} + implementation "org.threeten:threetenbp:$threetenbp_version" +{{/threetenbp}} + implementation "com.squareup.okio:okio:$okio_version" +{{#useBeanValidation}} + implementation "javax.validation:validation-api:2.0.1.Final" +{{/useBeanValidation}} +{{#performBeanValidation}} + implementation "org.hibernate:hibernate-validator:6.0.19.Final" +{{/performBeanValidation}} + implementation 'javax.annotation:javax.annotation-api:1.3.2' + testImplementation "junit:junit:$junit_version" +} diff --git a/.generator/templates/libraries/rest-assured/build.sbt.mustache b/.generator/templates/libraries/rest-assured/build.sbt.mustache new file mode 100644 index 00000000000..48a8c8dfcb7 --- /dev/null +++ b/.generator/templates/libraries/rest-assured/build.sbt.mustache @@ -0,0 +1,57 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "io.swagger" % "swagger-annotations" % "1.5.21", + "io.rest-assured" % "rest-assured" % "4.3.0", + "io.rest-assured" % "scala-support" % "4.3.0", + "com.google.code.findbugs" % "jsr305" % "3.0.2", +{{#jackson}} + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3", + {{#openApiNullable}} + "org.openapitools" % "jackson-databind-nullable" % "0.2.1", + {{/openApiNullable}} + {{#withXml}} + "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.10.3", + {{/withXml}} + {{#joda}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.10.3", + {{/joda}} + {{#java8}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.10.3", + {{/java8}} + {{#threetenbp}} + "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.10.0", + {{/threetenbp}} +{{/jackson}} +{{#gson}} + "com.google.code.gson" % "gson" % "2.8.6", + "io.gsonfire" % "gson-fire" % "1.8.4" % "compile", +{{/gson}} +{{#joda}} + "joda-time" % "joda-time" % "2.10.5" % "compile", +{{/joda}} +{{#threetenbp}} + "org.threeten" % "threetenbp" % "1.4.3" % "compile", +{{/threetenbp}} + "com.squareup.okio" % "okio" % "1.17.5" % "compile", +{{#useBeanValidation}} + "javax.validation" % "validation-api" % "2.0.1.Final" % "compile", +{{/useBeanValidation}} +{{#performBeanValidation}} + "org.hibernate" % "hibernate-validator" % "6.0.19.Final" % "compile", +{{/performBeanValidation}} + "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", + "junit" % "junit" % "4.13.1" % "test", + "com.novocode" % "junit-interface" % "0.10" % "test" + ) + ) diff --git a/.generator/templates/libraries/rest-assured/pom.mustache b/.generator/templates/libraries/rest-assured/pom.mustache new file mode 100644 index 00000000000..57d94de93ef --- /dev/null +++ b/.generator/templates/libraries/rest-assured/pom.mustache @@ -0,0 +1,370 @@ + + 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-enforcer-plugin + 3.0.0-M3 + + + enforce-maven + + enforce + + + + + 3.0.5 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + + + loggerPath + conf/log4j.properties + + + false + 1C + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.1.0 + + + add_sources + generate-sources + + add-source + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + none + 1.8 + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.0 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + sign-artifacts + verify + + sign + + + + + + + + + + {{#jackson}} + + + + com.fasterxml.jackson + jackson-bom + ${jackson-version} + pom + import + + + + {{/jackson}} + + + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + + + io.rest-assured + rest-assured + ${rest-assured.version} + + {{#gson}} + + com.google.code.gson + gson + ${gson-version} + + {{/gson}} + {{#joda}} + + joda-time + joda-time + ${jodatime-version} + + {{/joda}} + {{#threetenbp}} + + org.threeten + threetenbp + ${threetenbp-version} + + {{/threetenbp}} + {{#gson}} + + io.gsonfire + gson-fire + ${gson-fire-version} + + {{/gson}} + {{#jackson}} + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-annotations + + + com.fasterxml.jackson.core + jackson-databind + + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + + {{#withXml}} + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + + {{/withXml}} + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + + {{/joda}} + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + {{/java8}} + {{#threetenbp}} + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-threetenbp-version} + + {{/threetenbp}} + {{/jackson}} + + com.squareup.okio + okio + ${okio-version} + + {{#useBeanValidation}} + + + javax.validation + validation-api + 2.0.1.Final + provided + + {{/useBeanValidation}} + {{#performBeanValidation}} + + + org.hibernate + hibernate-validator + 6.0.19.Final + + {{/performBeanValidation}} + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.5.21 + 4.3.0 + 2.8.6 + 1.8.4 + {{#joda}} + 2.10.5 + {{/joda}} + {{#threetenbp}} + 1.4.3 + {{/threetenbp}} + {{#jackson}} + 2.10.3 + 0.2.1 + {{#threetenbp}} + 2.10.0 + {{/threetenbp}} + {{/jackson}} + 1.3.2 + 1.17.5 + 4.13.1 + + diff --git a/.generator/templates/libraries/resteasy/ApiClient.mustache b/.generator/templates/libraries/resteasy/ApiClient.mustache new file mode 100644 index 00000000000..775e0efea40 --- /dev/null +++ b/.generator/templates/libraries/resteasy/ApiClient.mustache @@ -0,0 +1,767 @@ +package {{invokerPackage}}; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TimeZone; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +{{#jsr310}} +{{#threetenbp}} +import org.threeten.bp.OffsetDateTime; +{{/threetenbp}} +{{^threetenbp}} +import java.time.OffsetDateTime; +{{/threetenbp}} +{{/jsr310}} + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.Form; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.jboss.logging.Logger; +import org.jboss.resteasy.client.jaxrs.internal.ClientConfiguration; +import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput; +import org.jboss.resteasy.spi.ResteasyProviderFactory; + +import {{invokerPackage}}.auth.Authentication; +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.HttpBearerAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +{{#hasOAuthMethods}} +import {{invokerPackage}}.auth.OAuth; +{{/hasOAuthMethods}} + +{{>generatedAnnotation}} +public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { + private Map defaultHeaderMap = new HashMap(); + private Map defaultCookieMap = new HashMap(); + private String basePath = "{{{basePath}}}"; + private boolean debugging = false; + + private Client httpClient; + private JSON json; + private String tempFolderPath = null; + + private Map authentications; + + private int statusCode; + private Map> responseHeaders; + + private DateFormat dateFormat; + + public ApiClient() { + json = new JSON(); + httpClient = buildHttpClient(debugging); + + this.dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ROOT); + + // Use UTC as the default time zone. + this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + + this.json.setDateFormat((DateFormat) dateFormat.clone()); + + // Set default User-Agent. + setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + } + + /** + * Gets the JSON instance to do JSON serialization and deserialization. + * @return the JSON utility class + */ + public JSON getJSON() { + return json; + } + + public Client getHttpClient() { + return httpClient; + } + + public ApiClient setHttpClient(Client httpClient) { + this.httpClient = httpClient; + return this; + } + + public String getBasePath() { + return basePath; + } + + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Gets the status code of the previous request + * @return the status code of the previous request + */ + public int getStatusCode() { + return statusCode; + } + + /** + * Gets the response headers of the previous request + * @return the response headers of the previous request + */ + public Map> getResponseHeaders() { + return responseHeaders; + } + + /** + * Get authentications (key: authentication name, value: authentication). + * @return the authentications + */ + 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); + } + + /** + * Helper method to set username for the first HTTP basic authentication. + * @param username the 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 the 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 the 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 the 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!"); + } + + {{#hasOAuthMethods}} + /** + * Helper method to set access token for the first OAuth2 authentication. + * @param accessToken the access token + */ + public void setAccessToken(String accessToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setAccessToken(accessToken); + return; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + {{/hasOAuthMethods}} + /** + * Set the User-Agent header's value (by adding to the default header map). + * @param userAgent the User-Agent header value + * @return this {@code 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 this {@code ApiClient} + */ + public ApiClient addDefaultHeader(String key, String value) { + defaultHeaderMap.put(key, value); + return this; + } + + /** + * Check that whether debugging is enabled for this API client. + * @return {@code true} if debugging is enabled for this API client + */ + public boolean isDebugging() { + return debugging; + } + + /** + * Enable/disable debugging for this API client. + * + * @param debugging To enable (true) or disable (false) debugging + * @return this {@code ApiClient} + */ + public ApiClient setDebugging(boolean debugging) { + this.debugging = debugging; + // Rebuild HTTP Client according to the new "debugging" value. + this.httpClient = buildHttpClient(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 tempopary folder. + * + * @return the temporary folder path + * @see createTempFile + */ + public String getTempFolderPath() { + return tempFolderPath; + } + + public ApiClient setTempFolderPath(String tempFolderPath) { + this.tempFolderPath = tempFolderPath; + return this; + } + + /** + * Get the date format used to parse/format date parameters. + * @return the date format used to parse/format date parameters + */ + public DateFormat getDateFormat() { + return dateFormat; + } + + /** + * Set the date format used to parse/format date parameters. + * @param dateFormat a date format used to parse/format date parameters + * @return this {@code ApiClient} + */ + public ApiClient setDateFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + // also set the date format for model (de)serialization with Date properties + this.json.setDateFormat((DateFormat) dateFormat.clone()); + return this; + } + + /** + * Parse the given string into Date object. + * @param str a string to parse + * @return a {@code Date} object + */ + public Date parseDate(String str) { + try { + return dateFormat.parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(e); + } + } + + /** + * Format the given Date object into string. + * @param date a {@code Date} object to format + * @return the {@code String} version of the {@code Date} object + */ + public String formatDate(Date date) { + return dateFormat.format(date); + } + + /** + * Format the given parameter object into string. + * @param param an object to format + * @return the {@code String} version of the object + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date) { + return formatDate((Date) param); + } {{#jsr310}}else if (param instanceof OffsetDateTime) { + return formatOffsetDateTime((OffsetDateTime) param); + } {{/jsr310}}else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for(Object o : (Collection)param) { + if(b.length() > 0) { + b.append(","); + } + b.append(String.valueOf(o)); + } + return b.toString(); + } else { + return String.valueOf(param); + } + } + + /* + Format to {@code Pair} objects. + */ + public List parameterToPairs(String collectionFormat, String name, Object value){ + List params = new ArrayList(); + + // preconditions + if (name == null || name.isEmpty() || value == null) return params; + + Collection valueCollection = null; + if (value instanceof Collection) { + valueCollection = (Collection) value; + } else { + params.add(new Pair(name, parameterToString(value))); + return params; + } + + if (valueCollection.isEmpty()){ + return params; + } + + // get the collection format + collectionFormat = (collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat); // default: csv + + // create the params based on the collection format + if (collectionFormat.equals("multi")) { + for (Object item : valueCollection) { + params.add(new Pair(name, parameterToString(item))); + } + + return params; + } + + String delimiter = ","; + + if (collectionFormat.equals("csv")) { + delimiter = ","; + } else if (collectionFormat.equals("ssv")) { + delimiter = " "; + } else if (collectionFormat.equals("tsv")) { + delimiter = "\t"; + } else if (collectionFormat.equals("pipes")) { + delimiter = "|"; + } + + StringBuilder sb = new StringBuilder() ; + for (Object item : valueCollection) { + sb.append(delimiter); + sb.append(parameterToString(item)); + } + + params.add(new Pair(name, sb.substring(1))); + + return params; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * application/vnd.company+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, + * JSON will be used. + */ + public String selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0) { + 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 a {@code String} to escape + * @return the escaped version of the {@code String} + */ + public String escapeString(String str) { + try { + return URLEncoder.encode(str, "utf8").replaceAll("\\+", "%20"); + } catch (UnsupportedEncodingException e) { + return str; + } + } + + /** + * Serialize the given Java object into string entity according the given + * Content-Type (only JSON is supported for now). + * @param obj the object to serialize + * @param formParams the form parameters + * @param contentType the content type + * @return an {@code Entity} + * @throws ApiException on failure to serialize + */ + public Entity serialize(Object obj, Map formParams, String contentType) throws ApiException { + Entity entity = null; + if (contentType.startsWith("multipart/form-data")) { + MultipartFormDataOutput multipart = new MultipartFormDataOutput(); + //MultiPart multiPart = new MultiPart(); + for (Entry param: formParams.entrySet()) { + if (param.getValue() instanceof File) { + File file = (File) param.getValue(); + try { + multipart.addFormData(param.getValue().toString(),new FileInputStream(file),MediaType.APPLICATION_OCTET_STREAM_TYPE); + } catch (FileNotFoundException e) { + throw new ApiException("Could not serialize multipart/form-data "+e.getMessage()); + } + } else { + multipart.addFormData(param.getValue().toString(),param.getValue().toString(),MediaType.APPLICATION_OCTET_STREAM_TYPE); + } + } + entity = Entity.entity(multipart.getFormData(), MediaType.MULTIPART_FORM_DATA_TYPE); + } else if (contentType.startsWith("application/x-www-form-urlencoded")) { + Form form = new Form(); + for (Entry param: formParams.entrySet()) { + form.param(param.getKey(), parameterToString(param.getValue())); + } + entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE); + } else { + // We let jersey handle the serialization + entity = Entity.entity(obj, contentType); + } + return entity; + } + + /** + * Deserialize response body to Java object according to the Content-Type. + * @param a Java type parameter + * @param response the response body to deserialize + * @param returnType a Java type to deserialize into + * @return a deserialized Java object + * @throws ApiException on failure to deserialize + */ + public T deserialize(Response response, GenericType returnType) throws ApiException { + if (response == null || returnType == null) { + return null; + } + + if ("byte[]".equals(returnType.toString())) { + // Handle binary response (byte array). + return (T) response.readEntity(byte[].class); + } else if (returnType.equals(File.class)) { + // Handle file downloading. + @SuppressWarnings("unchecked") + T file = (T) downloadFileFromResponse(response); + return file; + } + + String contentType = null; + List contentTypes = response.getHeaders().get("Content-Type"); + if (contentTypes != null && !contentTypes.isEmpty()) + contentType = String.valueOf(contentTypes.get(0)); + if (contentType == null) + throw new ApiException(500, "missing Content-Type in response"); + + return response.readEntity(returnType); + } + + /** + * Download file from the given response. + * @param response a response + * @return a file from the given response + * @throws ApiException If fail to read file content from response and write to disk + */ + public File downloadFileFromResponse(Response response) throws ApiException { + try { + File file = prepareDownloadFile(response); + Files.copy(response.readEntity(InputStream.class), file.toPath()); + return file; + } catch (IOException e) { + throw new ApiException(e); + } + } + + public File prepareDownloadFile(Response response) throws IOException { + String filename = null; + String contentDisposition = (String) response.getHeaders().getFirst("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 = 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(); + } + + /** + * Invoke API by sending HTTP request with the given options. + * + * @param a Java type parameter + * @param path The sub-path of the HTTP URL + * @param method The request method, one of "GET", "POST", "PUT", "HEAD" and "DELETE" + * @param queryParams The query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param cookieParams The cookie parameters + * @param formParams The form parameters + * @param accept The request's Accept header + * @param contentType The request's Content-Type header + * @param authNames The authentications to apply + * @param returnType The return type into which to deserialize the response + * @return The response body in type of string + * @throws ApiException if the invocation failed + */ + public T invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { + updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); + + // Not using `.target(this.basePath).path(path)` below, + // to support (constant) query string in `path`, e.g. "/posts?draft=1" + WebTarget target = httpClient.target(this.basePath + path); + + if (queryParams != null) { + for (Pair queryParam : queryParams) { + if (queryParam.getValue() != null) { + target = target.queryParam(queryParam.getName(), queryParam.getValue()); + } + } + } + + Invocation.Builder invocationBuilder = target.request().accept(accept); + + for (Entry headerParamsEnrty : headerParams.entrySet()) { + String value = headerParamsEnrty.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.header(headerParamsEnrty.getKey(), value); + } + } + + for (Entry defaultHeaderEnrty: defaultHeaderMap.entrySet()) { + if (!headerParams.containsKey(defaultHeaderEnrty.getKey())) { + String value = defaultHeaderEnrty.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.header(defaultHeaderEnrty.getKey(), value); + } + } + } + + for (Entry cookieParamsEntry : cookieParams.entrySet()) { + String value = cookieParamsEntry.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.cookie(cookieParamsEntry.getKey(), value); + } + } + + for (Entry defaultCookieEntry: defaultHeaderMap.entrySet()) { + if (!cookieParams.containsKey(defaultCookieEntry.getKey())) { + String value = defaultCookieEntry.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.cookie(defaultCookieEntry.getKey(), value); + } + } + } + + Entity entity = serialize(body, formParams, contentType); + + Response response = null; + + if ("GET".equals(method)) { + response = invocationBuilder.get(); + } else if ("POST".equals(method)) { + response = invocationBuilder.post(entity); + } else if ("PUT".equals(method)) { + response = invocationBuilder.put(entity); + } else if ("DELETE".equals(method)) { + response = invocationBuilder.method("DELETE", entity); + } else if ("PATCH".equals(method)) { + response = invocationBuilder.method("PATCH", entity); + } else if ("HEAD".equals(method)) { + response = invocationBuilder.head(); + } else if ("OPTIONS".equals(method)) { + response = invocationBuilder.options(); + } else if ("TRACE".equals(method)) { + response = invocationBuilder.trace(); + } else { + throw new ApiException(500, "unknown method type " + method); + } + + statusCode = response.getStatusInfo().getStatusCode(); + responseHeaders = buildResponseHeaders(response); + + if (response.getStatus() == Status.NO_CONTENT.getStatusCode()) { + return null; + } else if (response.getStatusInfo().getFamily().equals(Status.Family.SUCCESSFUL)) { + if (returnType == null) + return null; + else + return deserialize(response, returnType); + } else { + String message = "error"; + String respBody = null; + if (response.hasEntity()) { + try { + respBody = String.valueOf(response.readEntity(String.class)); + message = respBody; + } catch (RuntimeException e) { + // e.printStackTrace(); + } + } + throw new ApiException( + response.getStatus(), + message, + buildResponseHeaders(response), + respBody); + } + } + + /** + * Build the Client used to make HTTP requests. + */ + private Client buildHttpClient(boolean debugging) { + final ClientConfiguration clientConfig = new ClientConfiguration(ResteasyProviderFactory.getInstance()); + clientConfig.register(json); + if(debugging){ + clientConfig.register(Logger.class); + } + return ClientBuilder.newClient(clientConfig); + } + private Map> buildResponseHeaders(Response response) { + Map> responseHeaders = new HashMap>(); + for (Entry> entry: response.getHeaders().entrySet()) { + List values = entry.getValue(); + List headers = new ArrayList(); + for (Object o : values) { + headers.add(String.valueOf(o)); + } + responseHeaders.put(entry.getKey(), headers); + } + return responseHeaders; + } + + /** + * Update query and header parameters based on authentication settings. + * + * @param authNames The authentications to apply + */ + private void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams, Map cookieParams) { + for (String authName : authNames) { + Authentication auth = authentications.get(authName); + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + auth.applyToParams(queryParams, headerParams, cookieParams); + } + } +} diff --git a/.generator/templates/libraries/resteasy/JSON.mustache b/.generator/templates/libraries/resteasy/JSON.mustache new file mode 100644 index 00000000000..338d0455d14 --- /dev/null +++ b/.generator/templates/libraries/resteasy/JSON.mustache @@ -0,0 +1,56 @@ +package {{invokerPackage}}; + +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.*; +{{#openApiNullable}} +import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} +{{#java8}} +import com.fasterxml.jackson.datatype.jsr310.*; +{{/java8}} +{{^java8}} +import com.fasterxml.jackson.datatype.joda.*; +{{/java8}} + +import java.text.DateFormat; + +import javax.ws.rs.ext.ContextResolver; + +{{>generatedAnnotation}} +public class JSON implements ContextResolver { + private ObjectMapper mapper; + + public JSON() { + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.setDateFormat(new RFC3339DateFormat()); + {{#openApiNullable}} + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); + {{/openApiNullable}} + {{#java8}} + mapper.registerModule(new JavaTimeModule()); + {{/java8}} + {{^java8}} + mapper.registerModule(new JodaModule()); + {{/java8}} + } + + /** + * Set the date format for JSON (de)serialization with Date properties. + * @param dateFormat the date format to set + */ + public void setDateFormat(DateFormat dateFormat) { + mapper.setDateFormat(dateFormat); + } + + @Override + public ObjectMapper getContext(Class type) { + return mapper; + } +} diff --git a/.generator/templates/libraries/resteasy/api.mustache b/.generator/templates/libraries/resteasy/api.mustache new file mode 100644 index 00000000000..85891614c0e --- /dev/null +++ b/.generator/templates/libraries/resteasy/api.mustache @@ -0,0 +1,114 @@ +package {{package}}; + +import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.Configuration; +import {{invokerPackage}}.Pair; + +import javax.ws.rs.core.GenericType; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}} { + private ApiClient apiClient; + + public {{classname}}() { + this(Configuration.getDefaultApiClient()); + } + + public {{classname}}(ApiClient apiClient) { + this.apiClient = apiClient; + } + + public ApiClient getApiClient() { + return apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.apiClient = apiClient; + } + + {{#operation}} + /** + * {{summary}} + * {{notes}}{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{/allParams}}{{#returnType}} + * @return a {@code {{{returnType}}}}{{/returnType}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + } + {{/required}}{{/allParams}} + // create path and map variables + String localVarPath = "{{{path}}}".replaceAll("\\{format\\}","json"){{#pathParams}} + .replaceAll("\\{" + "{{baseName}}" + "\\}", apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; + + // query params + {{javaUtilPrefix}}List localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}Map localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarCookieParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap(); + + {{#queryParams}} + localVarQueryParams.addAll(apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); + {{/queryParams}} + + {{#headerParams}}if ({{paramName}} != null) + localVarHeaderParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); + {{/headerParams}} + + {{#cookieParams}}if ({{paramName}} != null) + localVarCookieParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); + {{/cookieParams}} + + {{#formParams}}if ({{paramName}} != null) + localVarFormParams.put("{{baseName}}", {{paramName}}); + {{/formParams}} + + final String[] localVarAccepts = { + {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} + }; + final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); + + final String[] localVarContentTypes = { + {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} + }; + final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); + + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; + + {{#returnType}} + GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {}; + return apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); + {{/returnType}}{{^returnType}} + apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, null); + {{/returnType}} + } + {{/operation}} +} +{{/operations}} diff --git a/.generator/templates/libraries/resteasy/build.gradle.mustache b/.generator/templates/libraries/resteasy/build.gradle.mustache new file mode 100644 index 00000000000..fe6c7b1f8d0 --- /dev/null +++ b/.generator/templates/libraries/resteasy/build.gradle.mustache @@ -0,0 +1,146 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + maven { url "https://repo1.maven.org/maven2" } + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.5.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 23 + buildToolsVersion '23.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 23 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + {{#java8}} + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + {{/java8}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + swagger_annotations_version = "1.5.22" + jackson_version = "2.10.5" + jackson_databind_version = "2.10.5.1" + {{#openApiNullable}} + jackson_databind_nullable_version = "0.2.1" + {{/openApiNullable}} + threetenbp_version = "2.9.10" + resteasy_version = "3.1.3.Final" + {{^java8}} + jodatime_version = "2.9.9" + {{/java8}} + junit_version = "4.13" +} + +dependencies { + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "org.jboss.resteasy:resteasy-client:$resteasy_version" + implementation "org.jboss.resteasy:resteasy-multipart-provider:$resteasy_version" + implementation "org.jboss.resteasy:resteasy-jackson2-provider:$resteasy_version" + 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_databind_version" + implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:$threetenbp_version" + {{#openApiNullable}} + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} + {{#java8}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{/java8}} + {{^java8}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + implementation "joda-time:joda-time:$jodatime_version" + implementation "com.brsanthu:migbase64:2.2" + {{/java8}} + implementation 'javax.annotation:javax.annotation-api:1.3.2' + testImplementation "junit:junit:$junit_version" +} diff --git a/.generator/templates/libraries/resteasy/build.sbt.mustache b/.generator/templates/libraries/resteasy/build.sbt.mustache new file mode 100644 index 00000000000..c2dfff284b0 --- /dev/null +++ b/.generator/templates/libraries/resteasy/build.sbt.mustache @@ -0,0 +1,32 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "io.swagger" % "swagger-annotations" % "1.5.22" % "compile", + "org.jboss.resteasy" % "resteasy-client" % "3.1.3.Final" % "compile", + "org.jboss.resteasy" % "resteasy-multipart-provider" % "3.1.3.Final" % "compile", + "org.jboss.resteasy" % "resteasy-jackson2-provider" % "3.1.3.Final" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.5" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.5" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.5.1" % "compile", + "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", + {{#java8}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile", + {{/java8}} + {{^java8}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile", + "joda-time" % "joda-time" % "2.9.9" % "compile", + "com.brsanthu" % "migbase64" % "2.2" % "compile", + {{/java8}} + "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", + "junit" % "junit" % "4.13" % "test", + "com.novocode" % "junit-interface" % "0.10" % "test" + ) + ) diff --git a/.generator/templates/libraries/resteasy/pom.mustache b/.generator/templates/libraries/resteasy/pom.mustache new file mode 100644 index 00000000000..084f42df9bd --- /dev/null +++ b/.generator/templates/libraries/resteasy/pom.mustache @@ -0,0 +1,299 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + +{{#parentOverridden}} + + {{{parentGroupId}}} + {{{parentArtifactId}}} + {{{parentVersion}}} + +{{/parentOverridden}} + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.6 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.5.1 + + {{#java8}} + 1.8 + 1.8 + {{/java8}} + {{^java8}} + 1.7 + 1.7 + {{/java8}} + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.1 + + none + {{#java8}} + 1.8 + {{/java8}} + {{^java8}} + 1.7 + {{/java8}} + + + + attach-javadocs + + jar + + + + + + + + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + + org.jboss.resteasy + resteasy-client + ${resteasy-version} + + + org.jboss.resteasy + resteasy-multipart-provider + ${resteasy-version} + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-databind-version} + + {{#openApiNullable}} + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + + {{/openApiNullable}} + {{#withXml}} + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson-version} + + + {{/withXml}} + {{^java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + + joda-time + joda-time + ${jodatime-version} + + + + + com.brsanthu + migbase64 + 2.2 + + {{/java8}} + + + org.jboss.resteasy + resteasy-jackson2-provider + 3.1.3.Final + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${threetenbp-version} + + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.5.22 + 3.1.3.Final + 2.10.5 + 2.10.5.1 + 0.2.1 + 1.3.2 + 2.9.10 + {{^java8}} + 2.9.9 + {{/java8}} + 1.0.0 + 4.13 + + diff --git a/.generator/templates/libraries/resttemplate/ApiClient.mustache b/.generator/templates/libraries/resttemplate/ApiClient.mustache new file mode 100644 index 00000000000..150f3d3ebbb --- /dev/null +++ b/.generator/templates/libraries/resttemplate/ApiClient.mustache @@ -0,0 +1,816 @@ +package {{invokerPackage}}; + +{{#withXml}} +import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; +{{/withXml}} +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpRequest; +import org.springframework.http.HttpStatus; +import org.springframework.http.InvalidMediaTypeException; +import org.springframework.http.MediaType; +import org.springframework.http.RequestEntity; +import org.springframework.http.RequestEntity.BodyBuilder; +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.BufferingClientHttpRequestFactory; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.client.ClientHttpResponse; +{{#withXml}} +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter; +{{/withXml}} +import org.springframework.stereotype.Component; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.util.StringUtils; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; +{{#threetenbp}} +import org.threeten.bp.*; +import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter; +import com.fasterxml.jackson.databind.ObjectMapper; +{{#openApiNullable}} +import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} +{{/threetenbp}} + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.text.DateFormat; +import java.text.ParseException; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TimeZone; +{{#jsr310}}{{^threetenbp}} +import java.time.OffsetDateTime; +{{/threetenbp}}{{/jsr310}} + +import {{invokerPackage}}.auth.Authentication; +{{#hasHttpBasicMethods}} +import {{invokerPackage}}.auth.HttpBasicAuth; +{{/hasHttpBasicMethods}} +{{#hasHttpBearerMethods}} +import {{invokerPackage}}.auth.HttpBearerAuth; +{{/hasHttpBearerMethods}} +{{#hasApiKeyMethods}} +import {{invokerPackage}}.auth.ApiKeyAuth; +{{/hasApiKeyMethods}} +{{#hasOAuthMethods}} +import {{invokerPackage}}.auth.OAuth; +{{/hasOAuthMethods}} + +{{>generatedAnnotation}} +@Component("{{invokerPackage}}.ApiClient") +public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { + public enum CollectionFormat { + CSV(","), TSV("\t"), SSV(" "), PIPES("|"), MULTI(null); + + private final String separator; + private CollectionFormat(String separator) { + this.separator = separator; + } + + private String collectionToString(Collection collection) { + return StringUtils.collectionToDelimitedString(collection, separator); + } + } + + private boolean debugging = false; + + private HttpHeaders defaultHeaders = new HttpHeaders(); + private MultiValueMap defaultCookies = new LinkedMultiValueMap(); + + private String basePath = "{{basePath}}"; + + private RestTemplate restTemplate; + + private Map authentications; + + private DateFormat dateFormat; + + public ApiClient() { + this.restTemplate = buildRestTemplate(); + init(); + } + + @Autowired + public ApiClient(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + init(); + } + + protected void init() { + // Use RFC3339 format for date and datetime. + // See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14 + this.dateFormat = new RFC3339DateFormat(); + + // Use UTC as the default time zone. + this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + + // Set default User-Agent. + setUserAgent("Java-SDK"); + + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + } + + /** + * Get the current base path + * @return String the base path + */ + public String getBasePath() { + return basePath; + } + + /** + * Set the base path, which should include the host + * @param basePath the base path + * @return ApiClient this client + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get authentications (key: authentication name, value: authentication). + * @return Map the currently configured authentication types + */ + 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 token for HTTP bearer authentication. + * @param bearerToken the token + */ + public void setBearerToken(String bearerToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBearerAuth) { + ((HttpBearerAuth) auth).setBearerToken(bearerToken); + return; + } + } + throw new RuntimeException("No Bearer authentication configured!"); + } + + {{/hasHttpBearerMethods}} + + {{#hasHttpBasicMethods}} + /** + * Helper method to set username for the first HTTP basic authentication. + * @param username Username + */ + 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!"); + } + + {{/hasHttpBasicMethods}} + + {{#hasApiKeyMethods}} + /** + * Helper method to set API key value for the first API key authentication. + * @param apiKey the 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!"); + } + + {{/hasApiKeyMethods}} + + {{#hasOAuthMethods}} + /** + * Helper method to set access token for the first OAuth2 authentication. + * @param accessToken Access token + */ + public void setAccessToken(String accessToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setAccessToken(accessToken); + return; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + {{/hasOAuthMethods}} + + /** + * Set the User-Agent header's value (by adding to the default header map). + * @param userAgent the user agent string + * @return ApiClient this client + */ + public ApiClient setUserAgent(String userAgent) { + addDefaultHeader("User-Agent", userAgent); + return this; + } + + /** + * Add a default header. + * + * @param name The header's name + * @param value The header's value + * @return ApiClient this client + */ + public ApiClient addDefaultHeader(String name, String value) { + if (defaultHeaders.containsKey(name)) { + defaultHeaders.remove(name); + } + defaultHeaders.add(name, value); + return this; + } + + /** + * Add a default cookie. + * + * @param name The cookie's name + * @param value The cookie's value + * @return ApiClient this client + */ + public ApiClient addDefaultCookie(String name, String value) { + if (defaultCookies.containsKey(name)) { + defaultCookies.remove(name); + } + defaultCookies.add(name, value); + return this; + } + + public void setDebugging(boolean debugging) { + List currentInterceptors = this.restTemplate.getInterceptors(); + if(debugging) { + if (currentInterceptors == null) { + currentInterceptors = new ArrayList(); + } + ClientHttpRequestInterceptor interceptor = new ApiClientHttpRequestInterceptor(); + currentInterceptors.add(interceptor); + this.restTemplate.setInterceptors(currentInterceptors); + } else { + if (currentInterceptors != null && !currentInterceptors.isEmpty()) { + Iterator iter = currentInterceptors.iterator(); + while (iter.hasNext()) { + ClientHttpRequestInterceptor interceptor = iter.next(); + if (interceptor instanceof ApiClientHttpRequestInterceptor) { + iter.remove(); + } + } + this.restTemplate.setInterceptors(currentInterceptors); + } + } + this.debugging = debugging; + } + + /** + * Check that whether debugging is enabled for this API client. + * @return boolean true if this client is enabled for debugging, false otherwise + */ + public boolean isDebugging() { + return debugging; + } + + /** + * Get the date format used to parse/format date parameters. + * @return DateFormat format + */ + public DateFormat getDateFormat() { + return dateFormat; + } + + /** + * Set the date format used to parse/format date parameters. + * @param dateFormat Date format + * @return API client + */ + public ApiClient setDateFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + {{#threetenbp}} + for(HttpMessageConverter converter:restTemplate.getMessageConverters()){ + if(converter instanceof AbstractJackson2HttpMessageConverter){ + ObjectMapper mapper = ((AbstractJackson2HttpMessageConverter)converter).getObjectMapper(); + mapper.setDateFormat(dateFormat); + } + } + {{/threetenbp}} + return this; + } + + /** + * Parse the given string into Date object. + * @param str the string to parse + * @return the Date parsed from the string + */ + public Date parseDate(String str) { + try { + return dateFormat.parse(str); + } catch (ParseException e) { + throw new RuntimeException(e); + } + } + + /** + * Format the given Date object into string. + * @param date the date to format + * @return the formatted date as string + */ + public String formatDate(Date date) { + return dateFormat.format(date); + } + + /** + * Format the given parameter object into string. + * @param param the object to convert + * @return String the parameter represented as a String + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date) { + return formatDate( (Date) param); + } {{#jsr310}}else if (param instanceof OffsetDateTime) { + return formatOffsetDateTime((OffsetDateTime) param); + } {{/jsr310}}else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for(Object o : (Collection) param) { + if(b.length() > 0) { + b.append(","); + } + b.append(String.valueOf(o)); + } + return b.toString(); + } else { + return String.valueOf(param); + } + } + + /** + * Formats the specified collection path parameter to a string value. + * + * @param collectionFormat The collection format of the parameter. + * @param values The values of the parameter. + * @return String representation of the parameter + */ + public String collectionPathParameterToString(CollectionFormat collectionFormat, Collection values) { + // create the value based on the collection format + if (CollectionFormat.MULTI.equals(collectionFormat)) { + // not valid for path params + return parameterToString(values); + } + + // collectionFormat is assumed to be "csv" by default + if(collectionFormat == null) { + collectionFormat = CollectionFormat.CSV; + } + + return collectionFormat.collectionToString(values); + } + + /** + * Converts a parameter to a {@link MultiValueMap} for use in REST requests + * @param collectionFormat The format to convert to + * @param name The name of the parameter + * @param value The parameter's value + * @return a Map containing the String value(s) of the input parameter + */ + public MultiValueMap parameterToMultiValueMap(CollectionFormat collectionFormat, String name, Object value) { + final MultiValueMap params = new LinkedMultiValueMap(); + + if (name == null || name.isEmpty() || value == null) { + return params; + } + + if(collectionFormat == null) { + collectionFormat = CollectionFormat.CSV; + } + + Collection valueCollection = null; + if (value instanceof Collection) { + valueCollection = (Collection) value; + } else { + params.add(name, parameterToString(value)); + return params; + } + + if (valueCollection.isEmpty()){ + return params; + } + + if (collectionFormat.equals(CollectionFormat.MULTI)) { + for (Object item : valueCollection) { + params.add(name, parameterToString(item)); + } + return params; + } + + List values = new ArrayList(); + for(Object o : valueCollection) { + values.add(parameterToString(o)); + } + params.add(name, collectionFormat.collectionToString(values)); + + return params; + } + + /** + * Check if the given {@code String} is a JSON MIME. + * @param mediaType the input MediaType + * @return boolean true if the MediaType represents JSON, false otherwise + */ + public boolean isJsonMime(String mediaType) { + // "* / *" is default to JSON + if ("*/*".equals(mediaType)) { + return true; + } + + try { + return isJsonMime(MediaType.parseMediaType(mediaType)); + } catch (InvalidMediaTypeException e) { + } + return false; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * @param mediaType the input MediaType + * @return boolean true if the MediaType represents JSON, false otherwise + */ + public boolean isJsonMime(MediaType mediaType) { + return mediaType != null && (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType) || mediaType.getSubtype().matches("^.*\\+json[;]?\\s*$")); + } + + /** + * Check if the given {@code String} is a Problem JSON MIME (RFC-7807). + * @param mediaType the input MediaType + * @return boolean true if the MediaType represents Problem JSON, false otherwise + */ + public boolean isProblemJsonMime(String mediaType) { + return "application/problem+json".equalsIgnoreCase(mediaType); + } + + /** + * 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 List The list of MediaTypes to use for the Accept header + */ + public List selectHeaderAccept(String[] accepts) { + if (accepts.length == 0) { + return null; + } + for (String accept : accepts) { + MediaType mediaType = MediaType.parseMediaType(accept); + if (isJsonMime(mediaType) && !isProblemJsonMime(accept)) { + return Collections.singletonList(mediaType); + } + } + return MediaType.parseMediaTypes(StringUtils.arrayToCommaDelimitedString(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 MediaType The Content-Type header to use. If the given array is empty, JSON will be used. + */ + public MediaType selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0) { + return MediaType.APPLICATION_JSON; + } + for (String contentType : contentTypes) { + MediaType mediaType = MediaType.parseMediaType(contentType); + if (isJsonMime(mediaType)) { + return mediaType; + } + } + return MediaType.parseMediaType(contentTypes[0]); + } + + /** + * Select the body to use for the request + * @param obj the body object + * @param formParams the form parameters + * @param contentType the content type of the request + * @return Object the selected body + */ + protected Object selectBody(Object obj, MultiValueMap formParams, MediaType contentType) { + boolean isForm = MediaType.MULTIPART_FORM_DATA.isCompatibleWith(contentType) || MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType); + return isForm ? formParams : obj; + } + + /** + * Expand path template with variables + * @param pathTemplate path template with placeholders + * @param variables variables to replace + * @return path with placeholders replaced by variables + */ + public String expandPath(String pathTemplate, Map variables) { + return restTemplate.getUriTemplateHandler().expand(pathTemplate, variables).toString(); + } + + /** + * Invoke API by sending HTTP request with the given options. + * + * @param the return type to use + * @param path The sub-path of the HTTP URL + * @param method The request method + * @param queryParams The query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param cookieParams The cookie parameters + * @param formParams The form parameters + * @param accept The request's Accept header + * @param contentType The request's Content-Type header + * @param authNames The authentications to apply + * @param returnType The return type into which to deserialize the response + * @return ResponseEntity<T> The response of the chosen type + */ + public ResponseEntity invokeAPI(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap cookieParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { + updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); + + final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(path); + if (queryParams != null) { + //encode the query parameters in case they contain unsafe characters + for (List values : queryParams.values()) { + if (values != null) { + for (int i = 0; i < values.size(); i++) { + try { + values.set(i, URLEncoder.encode(values.get(i), "utf8")); + } catch (UnsupportedEncodingException e) { + + } + } + } + } + builder.queryParams(queryParams); + } + + URI uri; + try { + uri = new URI(builder.build().toUriString()); + } catch(URISyntaxException ex) { + throw new RestClientException("Could not build URL: " + builder.toUriString(), ex); + } + + final BodyBuilder requestBuilder = RequestEntity.method(method, uri); + if(accept != null) { + requestBuilder.accept(accept.toArray(new MediaType[accept.size()])); + } + if(contentType != null) { + requestBuilder.contentType(contentType); + } + + addHeadersToRequest(headerParams, requestBuilder); + addHeadersToRequest(defaultHeaders, requestBuilder); + addCookiesToRequest(cookieParams, requestBuilder); + addCookiesToRequest(defaultCookies, requestBuilder); + + RequestEntity requestEntity = requestBuilder.body(selectBody(body, formParams, contentType)); + + ResponseEntity responseEntity = restTemplate.exchange(requestEntity, returnType); + + if (responseEntity.getStatusCode().is2xxSuccessful()) { + return responseEntity; + } else { + // The error handler built into the RestTemplate should handle 400 and 500 series errors. + throw new RestClientException("API returned " + responseEntity.getStatusCode() + " and it wasn't handled by the RestTemplate error handler"); + } + } + + /** + * Add headers to the request that is being built + * @param headers The headers to add + * @param requestBuilder The current request + */ + protected void addHeadersToRequest(HttpHeaders headers, BodyBuilder requestBuilder) { + for (Entry> entry : headers.entrySet()) { + List values = entry.getValue(); + for(String value : values) { + if (value != null) { + requestBuilder.header(entry.getKey(), value); + } + } + } + } + + /** + * Add cookies to the request that is being built + * @param cookies The cookies to add + * @param requestBuilder The current request + */ + protected void addCookiesToRequest(MultiValueMap cookies, BodyBuilder requestBuilder) { + if (!cookies.isEmpty()) { + requestBuilder.header("Cookie", buildCookieHeader(cookies)); + } + } + + /** + * Build cookie header. Keeps a single value per cookie (as per + * RFC6265 section 5.3). + * + * @param cookies map all cookies + * @return header string for cookies. + */ + private String buildCookieHeader(MultiValueMap cookies) { + final StringBuilder cookieValue = new StringBuilder(); + String delimiter = ""; + for (final Map.Entry> entry : cookies.entrySet()) { + final String value = entry.getValue().get(entry.getValue().size() - 1); + cookieValue.append(String.format("%s%s=%s", delimiter, entry.getKey(), value)); + delimiter = "; "; + } + return cookieValue.toString(); + } + + /** + * Build the RestTemplate used to make HTTP requests. + * @return RestTemplate + */ + protected RestTemplate buildRestTemplate() { + {{#withXml}}List> messageConverters = new ArrayList>(); + messageConverters.add(new MappingJackson2HttpMessageConverter()); + XmlMapper xmlMapper = new XmlMapper(); + xmlMapper.configure(ToXmlGenerator.Feature.WRITE_XML_DECLARATION, true); + {{#openApiNullable}} + xmlMapper.registerModule(new JsonNullableModule()); + {{/openApiNullable}} + messageConverters.add(new MappingJackson2XmlHttpMessageConverter(xmlMapper)); + + RestTemplate restTemplate = new RestTemplate(messageConverters); + {{/withXml}}{{^withXml}}RestTemplate restTemplate = new RestTemplate();{{/withXml}} + {{#threetenbp}} + for(HttpMessageConverter converter:restTemplate.getMessageConverters()){ + if(converter instanceof AbstractJackson2HttpMessageConverter){ + ObjectMapper mapper = ((AbstractJackson2HttpMessageConverter)converter).getObjectMapper(); + ThreeTenModule module = new ThreeTenModule(); + module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); + module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); + module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); + mapper.registerModule(module); + {{#openApiNullable}} + mapper.registerModule(new JsonNullableModule()); + {{/openApiNullable}} + } + } + {{/threetenbp}} + // This allows us to read the response more than once - Necessary for debugging. + restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(restTemplate.getRequestFactory())); + return restTemplate; + } + + /** + * Update query and header parameters based on authentication settings. + * + * @param authNames The authentications to apply + * @param queryParams The query parameters + * @param headerParams The header parameters + */ + protected void updateParamsForAuth(String[] authNames, MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { + for (String authName : authNames) { + Authentication auth = authentications.get(authName); + if (auth == null) { + throw new RestClientException("Authentication undefined: " + authName); + } + auth.applyToParams(queryParams, headerParams, cookieParams); + } + } + + private class ApiClientHttpRequestInterceptor implements ClientHttpRequestInterceptor { + private final Log log = LogFactory.getLog(ApiClientHttpRequestInterceptor.class); + + @Override + public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { + logRequest(request, body); + ClientHttpResponse response = execution.execute(request, body); + logResponse(response); + return response; + } + + private void logRequest(HttpRequest request, byte[] body) throws UnsupportedEncodingException { + log.info("URI: " + request.getURI()); + log.info("HTTP Method: " + request.getMethod()); + log.info("HTTP Headers: " + headersToString(request.getHeaders())); + log.info("Request Body: " + new String(body, StandardCharsets.UTF_8)); + } + + private void logResponse(ClientHttpResponse response) throws IOException { + log.info("HTTP Status Code: " + response.getRawStatusCode()); + log.info("Status Text: " + response.getStatusText()); + log.info("HTTP Headers: " + headersToString(response.getHeaders())); + log.info("Response Body: " + bodyToString(response.getBody())); + } + + private String headersToString(HttpHeaders headers) { + StringBuilder builder = new StringBuilder(); + for(Entry> entry : headers.entrySet()) { + builder.append(entry.getKey()).append("=["); + for(String value : entry.getValue()) { + builder.append(value).append(","); + } + builder.setLength(builder.length() - 1); // Get rid of trailing comma + builder.append("],"); + } + builder.setLength(builder.length() - 1); // Get rid of trailing comma + return builder.toString(); + } + + private String bodyToString(InputStream body) throws IOException { + StringBuilder builder = new StringBuilder(); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(body, StandardCharsets.UTF_8)); + String line = bufferedReader.readLine(); + while (line != null) { + builder.append(line).append(System.lineSeparator()); + line = bufferedReader.readLine(); + } + bufferedReader.close(); + return builder.toString(); + } + } +} diff --git a/.generator/templates/libraries/resttemplate/api.mustache b/.generator/templates/libraries/resttemplate/api.mustache new file mode 100644 index 00000000000..006e6cf8f93 --- /dev/null +++ b/.generator/templates/libraries/resttemplate/api.mustache @@ -0,0 +1,151 @@ +package {{package}}; + +import {{invokerPackage}}.ApiClient; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}}import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.stream.Collectors;{{/fullJavaUtil}} + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.core.io.FileSystemResource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; + +{{>generatedAnnotation}} +@Component("{{package}}.{{classname}}") +{{#operations}} +public class {{classname}} { + private ApiClient apiClient; + + public {{classname}}() { + this(new ApiClient()); + } + + @Autowired + public {{classname}}(ApiClient apiClient) { + this.apiClient = apiClient; + } + + public ApiClient getApiClient() { + return apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.apiClient = apiClient; + } + + {{#operation}} + /** + * {{summary}} + * {{notes}} + {{#responses}} + *

{{code}}{{#message}} - {{message}}{{/message}} + {{/responses}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + {{#returnType}} + * @return {{returnType}} + {{/returnType}} + * @throws RestClientException if an error occurs while attempting to invoke the API + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws RestClientException { + {{#returnType}} + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).getBody(); + {{/returnType}} + {{^returnType}} + {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + {{/returnType}} + } + + /** + * {{summary}} + * {{notes}} + {{#responses}} + *

{{code}}{{#message}} - {{message}}{{/message}} + {{/responses}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @return ResponseEntity<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + * @throws RestClientException if an error occurs while attempting to invoke the API + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public ResponseEntity<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws RestClientException { + Object postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + } + {{/required}}{{/allParams}}{{#hasPathParams}} + // create path and map variables + final Map uriVariables = new HashMap();{{#pathParams}} + uriVariables.put("{{baseName}}", {{#collectionFormat}}apiClient.collectionPathParameterToString(ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase()), {{{paramName}}}){{/collectionFormat}}{{^collectionFormat}}{{{paramName}}}{{/collectionFormat}});{{/pathParams}}{{/hasPathParams}} + String path = apiClient.expandPath("{{{path}}}", {{#hasPathParams}}uriVariables{{/hasPathParams}}{{^hasPathParams}}Collections.emptyMap(){{/hasPathParams}}); + + final MultiValueMap queryParams = new LinkedMultiValueMap(); + final HttpHeaders headerParams = new HttpHeaders(); + final MultiValueMap cookieParams = new LinkedMultiValueMap(); + final MultiValueMap formParams = new LinkedMultiValueMap();{{#hasQueryParams}} + + {{#queryParams}}queryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{^-last}} + {{/-last}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}} + + {{#headerParams}}if ({{paramName}} != null) + headerParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{^-last}} + {{/-last}}{{/headerParams}}{{/hasHeaderParams}}{{#hasCookieParams}} + + {{#cookieParams}}if ({{paramName}} != null) + cookieParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{^-last}} + {{/-last}}{{/cookieParams}}{{/hasCookieParams}}{{#hasFormParams}} + + {{#formParams}}if ({{paramName}} != null) + formParams.{{^collectionFormat}}add{{/collectionFormat}}{{#collectionFormat}}addAll{{/collectionFormat}}("{{baseName}}", {{#isFile}}{{^collectionFormat}}{{#useAbstractionForFiles}}{{paramName}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}new FileSystemResource({{paramName}}){{/useAbstractionForFiles}}{{/collectionFormat}}{{/isFile}}{{#isFile}}{{#collectionFormat}}{{paramName}}.stream(){{^useAbstractionForFiles}}.map(FileSystemResource::new){{/useAbstractionForFiles}}.collect(Collectors.toList()){{/collectionFormat}}{{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{^-last}} + {{/-last}}{{/formParams}}{{/hasFormParams}} + + final String[] localVarAccepts = { {{#hasProduces}} + {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} + {{/hasProduces}} }; + final List localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); + final String[] contentTypes = { {{#hasConsumes}} + {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} + {{/hasConsumes}} }; + final MediaType contentType = apiClient.selectHeaderContentType(contentTypes); + + String[] authNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; + + {{#returnType}}ParameterizedTypeReference<{{{returnType}}}> returnType = new ParameterizedTypeReference<{{{returnType}}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference returnType = new ParameterizedTypeReference() {};{{/returnType}} + return apiClient.invokeAPI(path, HttpMethod.{{httpMethod}}, queryParams, postBody, headerParams, cookieParams, formParams, localVarAccept, contentType, authNames, returnType); + } + {{/operation}} +} +{{/operations}} diff --git a/.generator/templates/libraries/resttemplate/api_test.mustache b/.generator/templates/libraries/resttemplate/api_test.mustache new file mode 100644 index 00000000000..119194543c3 --- /dev/null +++ b/.generator/templates/libraries/resttemplate/api_test.mustache @@ -0,0 +1,44 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Test; +import org.junit.Ignore; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +@Ignore +public class {{classname}}Test { + + private final {{classname}} api = new {{classname}}(); + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + * + * @throws ApiException + * if the Api call fails + */ + @Test + public void {{operationId}}Test() { + {{#allParams}} + {{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}} = null; + {{/allParams}} + {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + + // TODO: test validations + } + {{/operation}}{{/operations}} +} diff --git a/.generator/templates/libraries/resttemplate/auth/ApiKeyAuth.mustache b/.generator/templates/libraries/resttemplate/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..857403b27cf --- /dev/null +++ b/.generator/templates/libraries/resttemplate/auth/ApiKeyAuth.mustache @@ -0,0 +1,62 @@ +package {{invokerPackage}}.auth; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.MultiValueMap; + +{{>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(MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { + if (apiKey == null) { + return; + } + String value; + if (apiKeyPrefix != null) { + value = apiKeyPrefix + " " + apiKey; + } else { + value = apiKey; + } + if (location.equals("query")) { + queryParams.add(paramName, value); + } else if (location.equals("header")) { + headerParams.add(paramName, value); + } else if (location.equals("cookie")) { + cookieParams.add(paramName, value); + } + } +} diff --git a/.generator/templates/libraries/resttemplate/auth/Authentication.mustache b/.generator/templates/libraries/resttemplate/auth/Authentication.mustache new file mode 100644 index 00000000000..8e53c2ba08e --- /dev/null +++ b/.generator/templates/libraries/resttemplate/auth/Authentication.mustache @@ -0,0 +1,14 @@ +package {{invokerPackage}}.auth; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.MultiValueMap; + +public interface Authentication { + /** + * Apply authentication settings to header and / or query parameters. + * @param queryParams The query parameters for the request + * @param headerParams The header parameters for the request + * @param cookieParams The cookie parameters for the request + */ + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams); +} diff --git a/.generator/templates/libraries/resttemplate/auth/HttpBasicAuth.mustache b/.generator/templates/libraries/resttemplate/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..5b07cb907bb --- /dev/null +++ b/.generator/templates/libraries/resttemplate/auth/HttpBasicAuth.mustache @@ -0,0 +1,39 @@ +package {{invokerPackage}}.auth; + +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.Base64Utils; +import org.springframework.util.MultiValueMap; + +{{>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(MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { + if (username == null && password == null) { + return; + } + String str = (username == null ? "" : username) + ":" + (password == null ? "" : password); + headerParams.add(HttpHeaders.AUTHORIZATION, "Basic " + Base64Utils.encodeToString(str.getBytes(StandardCharsets.UTF_8))); + } +} diff --git a/.generator/templates/libraries/resttemplate/auth/HttpBearerAuth.mustache b/.generator/templates/libraries/resttemplate/auth/HttpBearerAuth.mustache new file mode 100644 index 00000000000..1d1610c61c4 --- /dev/null +++ b/.generator/templates/libraries/resttemplate/auth/HttpBearerAuth.mustache @@ -0,0 +1,38 @@ +package {{invokerPackage}}.auth; + +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.Base64Utils; +import org.springframework.util.MultiValueMap; + +{{>generatedAnnotation}} +public class HttpBearerAuth implements Authentication { + private final String scheme; + private String bearerToken; + + public HttpBearerAuth(String scheme) { + this.scheme = scheme; + } + + public String getBearerToken() { + return bearerToken; + } + + public void setBearerToken(String bearerToken) { + this.bearerToken = bearerToken; + } + + @Override + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { + if (bearerToken == null) { + return; + } + headerParams.add(HttpHeaders.AUTHORIZATION, (scheme != null ? upperCaseBearer(scheme) + " " : "") + bearerToken); + } + + private static String upperCaseBearer(String scheme) { + return ("bearer".equalsIgnoreCase(scheme)) ? "Bearer" : scheme; + } +} diff --git a/.generator/templates/libraries/resttemplate/auth/OAuth.mustache b/.generator/templates/libraries/resttemplate/auth/OAuth.mustache new file mode 100644 index 00000000000..7889f1582de --- /dev/null +++ b/.generator/templates/libraries/resttemplate/auth/OAuth.mustache @@ -0,0 +1,24 @@ +package {{invokerPackage}}.auth; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.MultiValueMap; + +{{>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(MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { + if (accessToken != null) { + headerParams.add(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken); + } + } +} diff --git a/.generator/templates/libraries/resttemplate/auth/OAuthFlow.mustache b/.generator/templates/libraries/resttemplate/auth/OAuthFlow.mustache new file mode 100644 index 00000000000..7ab35f6d890 --- /dev/null +++ b/.generator/templates/libraries/resttemplate/auth/OAuthFlow.mustache @@ -0,0 +1,5 @@ +package {{invokerPackage}}.auth; + +public enum OAuthFlow { + accessCode, implicit, password, application +} \ No newline at end of file diff --git a/.generator/templates/libraries/resttemplate/build.gradle.mustache b/.generator/templates/libraries/resttemplate/build.gradle.mustache new file mode 100644 index 00000000000..433d396baf4 --- /dev/null +++ b/.generator/templates/libraries/resttemplate/build.gradle.mustache @@ -0,0 +1,151 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + maven { url "https://repo1.maven.org/maven2" } + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.5.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 23 + buildToolsVersion '23.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 22 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + {{#java8}} + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + {{/java8}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + swagger_annotations_version = "1.5.22" + jackson_version = "2.10.5" + jackson_databind_version = "2.10.5.1" + {{#openApiNullable}} + jackson_databind_nullable_version = "0.2.1" + {{/openApiNullable}} + spring_web_version = "5.2.5.RELEASE" + jodatime_version = "2.9.9" + junit_version = "4.13.1" + {{#threetenbp}} + jackson_threeten_version = "2.9.10" + {{/threetenbp}} +} + +dependencies { + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "org.springframework:spring-web:$spring_web_version" + implementation "org.springframework:spring-context:$spring_web_version" + 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_databind_version" + implementation "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + {{#openApiNullable}} + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} + {{#java8}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{/java8}} + {{#joda}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + implementation "joda-time:joda-time:$jodatime_version" + {{/joda}} + {{#threetenbp}} + implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threeten_version" + {{/threetenbp}} + {{#withXml}} + implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version" + {{/withXml}} + implementation 'javax.annotation:javax.annotation-api:1.3.2' + testImplementation "junit:junit:$junit_version" +} diff --git a/.generator/templates/libraries/resttemplate/pom.mustache b/.generator/templates/libraries/resttemplate/pom.mustache new file mode 100644 index 00000000000..17dd7024edd --- /dev/null +++ b/.generator/templates/libraries/resttemplate/pom.mustache @@ -0,0 +1,333 @@ + + 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-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + {{#java8}} + 1.8 + 1.8 + {{/java8}} + {{^java8}} + 1.7 + 1.7 + {{/java8}} + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.1 + + none + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + + + org.springframework + spring-web + ${spring-web-version} + + + org.springframework + spring-context + ${spring-web-version} + + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-databind-version} + + + com.fasterxml.jackson.jaxrs + jackson-jaxrs-json-provider + ${jackson-version} + + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + + {{#withXml}} + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson-version} + + + {{/withXml}} + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{/java8}} + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + + joda-time + joda-time + ${jodatime-version} + + {{/joda}} + {{#threetenbp}} + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-threetenbp-version} + + {{/threetenbp}} + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + + + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.5.22 + 5.2.5.RELEASE + 2.10.5 + 2.10.5.1 + 0.2.1 + 1.3.2 + {{#joda}} + 2.9.9 + {{/joda}} + {{#threetenbp}} + 2.9.10 + {{/threetenbp}} + 1.0.0 + 4.13.1 + + diff --git a/.generator/templates/libraries/retrofit/ApiClient.mustache b/.generator/templates/libraries/retrofit/ApiClient.mustache new file mode 100644 index 00000000000..ad3057e9c3d --- /dev/null +++ b/.generator/templates/libraries/retrofit/ApiClient.mustache @@ -0,0 +1,448 @@ +package {{invokerPackage}}; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Type; +import java.util.LinkedHashMap; +import java.util.Map; + +{{#hasOAuthMethods}} +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; +{{/hasOAuthMethods}} + +import org.joda.time.DateTime; +import org.joda.time.LocalDate; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.ISODateTimeFormat; + +import retrofit.RestAdapter; +import retrofit.client.OkClient; +import retrofit.converter.ConversionException; +import retrofit.converter.Converter; +import retrofit.converter.GsonConverter; +import retrofit.mime.TypedByteArray; +import retrofit.mime.TypedInput; +import retrofit.mime.TypedOutput; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonParseException; +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import com.squareup.okhttp.Interceptor; +import com.squareup.okhttp.OkHttpClient; + +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.HttpBearerAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +{{#hasOAuthMethods}} +import {{invokerPackage}}.auth.OAuth; +import {{invokerPackage}}.auth.OAuth.AccessTokenListener; +import {{invokerPackage}}.auth.OAuthFlow; +{{/hasOAuthMethods}} + +public class ApiClient { + + private Map apiAuthorizations; + private OkHttpClient okClient; + private RestAdapter.Builder adapterBuilder; + + public ApiClient() { + apiAuthorizations = new LinkedHashMap(); + createDefaultAdapter(); + } + + public ApiClient(String[] authNames) { + this(); + for(String authName : authNames) { + {{#hasAuthMethods}} + Interceptor auth; + {{#authMethods}}if ("{{name}}".equals(authName)) { + {{#isBasic}} + {{#isBasicBasic}} + auth = new HttpBasicAuth(); + {{/isBasicBasic}} + {{^isBasicBasic}} + auth = new HttpBearerAuth("{{scheme}}"); + {{/isBasicBasic}} + {{/isBasic}} + {{#isApiKey}} + auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"); + {{/isApiKey}} + {{#isOAuth}} + auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{^-last}}, {{/-last}}{{/scopes}}"); + {{/isOAuth}} + } else {{/authMethods}}{ + throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); + } + addAuthorization(authName, auth); + {{/hasAuthMethods}} + {{^hasAuthMethods}} + throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); + {{/hasAuthMethods}} + } + } + + /** + * Basic constructor for single auth name + * @param authName Authentication name + */ + public ApiClient(String authName) { + this(new String[]{authName}); + } + + /** + * Helper constructor for single api key + * @param authName Authentication name + * @param apiKey API key + */ + public ApiClient(String authName, String apiKey) { + this(authName); + this.setApiKey(apiKey); + } + + /** + * Helper constructor for single basic auth or password oauth2 + * @param authName Authentication name + * @param username Username + * @param password Password + */ + public ApiClient(String authName, String username, String password) { + this(authName); + this.setCredentials(username, password); + } + + {{#hasOAuthMethods}} + /** + * Helper constructor for single password oauth2 + * @param authName Authentication name + * @param clientId Client ID + * @param secret Client secret + * @param username Username + * @param password Password + */ + public ApiClient(String authName, String clientId, String secret, String username, String password) { + this(authName); + this.getTokenEndPoint() + .setClientId(clientId) + .setClientSecret(secret) + .setUsername(username) + .setPassword(password); + } + + {{/hasOAuthMethods}} + public void createDefaultAdapter() { + Gson gson = new GsonBuilder() + .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ") + .registerTypeAdapter(DateTime.class, new DateTimeTypeAdapter()) + .registerTypeAdapter(LocalDate.class, new LocalDateTypeAdapter()) + .create(); + + okClient = new OkHttpClient(); + + adapterBuilder = new RestAdapter + .Builder() + .setEndpoint("{{{basePath}}}") + .setClient(new OkClient(okClient)) + .setConverter(new GsonConverterWrapper(gson)); + } + + public S createService(Class serviceClass) { + return adapterBuilder.build().create(serviceClass); + + } + + /** + * Helper method to configure the first api key found + * @param apiKey API key + */ + private void setApiKey(String apiKey) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof ApiKeyAuth) { + ApiKeyAuth keyAuth = (ApiKeyAuth) apiAuthorization; + keyAuth.setApiKey(apiKey); + return; + } + } + } + + /** + * Helper method to set token for the first Http Bearer authentication found. + * @param bearerToken Bearer token + */ + public void setBearerToken(String bearerToken) { + for (Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof HttpBearerAuth) { + ((HttpBearerAuth) apiAuthorization).setBearerToken(bearerToken); + return; + } + } + } + + /** + * Helper method to configure the username/password for basic auth or password oauth + * @param username Username + * @param password Password + */ + private void setCredentials(String username, String password) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof HttpBasicAuth) { + HttpBasicAuth basicAuth = (HttpBasicAuth) apiAuthorization; + basicAuth.setCredentials(username, password); + return; + } + {{#hasOAuthMethods}} + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.getTokenRequestBuilder().setUsername(username).setPassword(password); + return; + } + {{/hasOAuthMethods}} + } + } + + {{#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(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + return oauth.getTokenRequestBuilder(); + } + } + return null; + } + + /** + * Helper method to configure authorization endpoint of the first oauth found in the apiAuthorizations (there should be only one) + * @return Authentication request builder + */ + public AuthenticationRequestBuilder getAuthorizationEndPoint() { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + return oauth.getAuthenticationRequestBuilder(); + } + } + return null; + } + + /** + * Helper method to pre-set the oauth access token of the first oauth found in the apiAuthorizations (there should be only one) + * @param accessToken Access token + */ + public void setAccessToken(String accessToken) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.setAccessToken(accessToken); + return; + } + } + } + + /** + * Helper method to configure the oauth accessCode/implicit flow parameters + * @param clientId Client ID + * @param clientSecret Client secret + * @param redirectURI Redirect URI + */ + public void configureAuthorizationFlow(String clientId, String clientSecret, String redirectURI) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.getTokenRequestBuilder() + .setClientId(clientId) + .setClientSecret(clientSecret) + .setRedirectURI(redirectURI); + oauth.getAuthenticationRequestBuilder() + .setClientId(clientId) + .setRedirectURI(redirectURI); + return; + } + } + } + + /** + * Configures a listener which is notified when a new access token is received. + * @param accessTokenListener Access token listener + */ + public void registerAccessTokenListener(AccessTokenListener accessTokenListener) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.registerAccessTokenListener(accessTokenListener); + return; + } + } + } + {{/hasOAuthMethods}} + + /** + * Adds an authorization to be used by the client + * @param authName Authentication name + * @param authorization Authorization + */ + public void addAuthorization(String authName, Interceptor authorization) { + if (apiAuthorizations.containsKey(authName)) { + throw new RuntimeException("auth name \"" + authName + "\" already in api authorizations"); + } + apiAuthorizations.put(authName, authorization); + okClient.interceptors().add(authorization); + } + + public Map getApiAuthorizations() { + return apiAuthorizations; + } + + public void setApiAuthorizations(Map apiAuthorizations) { + this.apiAuthorizations = apiAuthorizations; + } + + public RestAdapter.Builder getAdapterBuilder() { + return adapterBuilder; + } + + public void setAdapterBuilder(RestAdapter.Builder adapterBuilder) { + this.adapterBuilder = adapterBuilder; + } + + public OkHttpClient getOkClient() { + return okClient; + } + + public void addAuthsToOkClient(OkHttpClient okClient) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + okClient.interceptors().add(apiAuthorization); + } + } + + /** + * Clones the okClient given in parameter, adds the auth interceptors and uses it to configure the RestAdapter + * @param okClient OkHttp client + */ + public void configureFromOkclient(OkHttpClient okClient) { + OkHttpClient clone = okClient.clone(); + addAuthsToOkClient(clone); + adapterBuilder.setClient(new OkClient(clone)); + } +} + +/** + * This wrapper is to take care of this case: + * when the deserialization fails due to JsonParseException and the + * expected type is String, then just return the body string. + */ +class GsonConverterWrapper implements Converter { + private GsonConverter converter; + + public GsonConverterWrapper(Gson gson) { + converter = new GsonConverter(gson); + } + + @Override public Object fromBody(TypedInput body, Type type) throws ConversionException { + byte[] bodyBytes = readInBytes(body); + TypedByteArray newBody = new TypedByteArray(body.mimeType(), bodyBytes); + try { + return converter.fromBody(newBody, type); + } catch (ConversionException e) { + if (e.getCause() instanceof JsonParseException && type.equals(String.class)) { + return new String(bodyBytes); + } else { + throw e; + } + } + } + + @Override public TypedOutput toBody(Object object) { + return converter.toBody(object); + } + + private byte[] readInBytes(TypedInput body) throws ConversionException { + InputStream in = null; + try { + in = body.in(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + byte[] buffer = new byte[0xFFFF]; + for (int len; (len = in.read(buffer)) != -1;) + os.write(buffer, 0, len); + os.flush(); + return os.toByteArray(); + } catch (IOException e) { + throw new ConversionException(e); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException ignored) { + } + } + } + + } +} + +/** + * Gson TypeAdapter for Joda DateTime type + */ +class DateTimeTypeAdapter extends TypeAdapter { + + private final DateTimeFormatter parseFormatter = ISODateTimeFormat.dateOptionalTimeParser(); + private final DateTimeFormatter printFormatter = ISODateTimeFormat.dateTime(); + + @Override + public void write(JsonWriter out, DateTime date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(printFormatter.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 parseFormatter.parseDateTime(date); + } + } +} + +/** + * Gson TypeAdapter for Joda DateTime type + */ +class LocalDateTypeAdapter extends TypeAdapter { + + private final DateTimeFormatter formatter = ISODateTimeFormat.date(); + + @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); + } + } +} diff --git a/.generator/templates/libraries/retrofit/CollectionFormats.mustache b/.generator/templates/libraries/retrofit/CollectionFormats.mustache new file mode 100644 index 00000000000..33331adb026 --- /dev/null +++ b/.generator/templates/libraries/retrofit/CollectionFormats.mustache @@ -0,0 +1,99 @@ +package {{invokerPackage}}; + +import java.util.Arrays; +import java.util.List; + +public class CollectionFormats { + + public static class CSVParams { + + protected List params; + + public CSVParams() { + } + + public CSVParams(List params) { + this.params = params; + } + + public CSVParams(String... params) { + this.params = Arrays.asList(params); + } + + public List getParams() { + return params; + } + + public void setParams(List params) { + this.params = params; + } + + @Override + public String toString() { + return StringUtil.join(params.toArray(new String[0]), ","); + } + + } + + public static class SPACEParams extends SSVParams { + + } + + public static class SSVParams extends CSVParams { + + public SSVParams() { + } + + public SSVParams(List params) { + super(params); + } + + public SSVParams(String... params) { + super(params); + } + + @Override + public String toString() { + return StringUtil.join(params.toArray(new String[0]), " "); + } + } + + public static class TSVParams extends CSVParams { + + public TSVParams() { + } + + public TSVParams(List params) { + super(params); + } + + public TSVParams(String... params) { + super(params); + } + + @Override + public String toString() { + return StringUtil.join( params.toArray(new String[0]), "\t"); + } + } + + public static class PIPESParams extends CSVParams { + + public PIPESParams() { + } + + public PIPESParams(List params) { + super(params); + } + + public PIPESParams(String... params) { + super(params); + } + + @Override + public String toString() { + return StringUtil.join(params.toArray(new String[0]), "|"); + } + } + +} diff --git a/.generator/templates/libraries/retrofit/README.mustache b/.generator/templates/libraries/retrofit/README.mustache new file mode 100644 index 00000000000..a0fac9d41df --- /dev/null +++ b/.generator/templates/libraries/retrofit/README.mustache @@ -0,0 +1,43 @@ +# {{artifactId}} + +## Requirements + +Building the API client library requires [Maven](https://maven.apache.org/) to be installed. + +## Installation & Usage + +To install the API client library to your local Maven repository, simply execute: + +```shell +mvn install +``` + +To deploy it to a remote Maven repository instead, configure the settings of the repository and execute: + +```shell +mvn deploy +``` + +Refer to the [official documentation](https://maven.apache.org/plugins/maven-deploy-plugin/usage.html) for more information. + +After the client library is installed/deployed, you can use it in your Maven project by adding the following to your *pom.xml*: + +```xml + + {{groupId}} + {{artifactId}} + {{artifactVersion}} + compile + + +``` + +## 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/.generator/templates/libraries/retrofit/api.mustache b/.generator/templates/libraries/retrofit/api.mustache new file mode 100644 index 00000000000..99b7f4f796a --- /dev/null +++ b/.generator/templates/libraries/retrofit/api.mustache @@ -0,0 +1,62 @@ +package {{package}}; + +import {{invokerPackage}}.CollectionFormats.*; + +import retrofit.Callback; +import retrofit.http.*; +import retrofit.mime.*; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +{{#operations}} +public interface {{classname}} { + {{#operation}} + /** + * {{summary}} + * Sync method + * {{notes}} +{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} +{{/allParams}} + * @return {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}} +{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation +{{/externalDocs}} + */ + {{#formParams}}{{#-first}} + {{#isMultipart}}@retrofit.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit.http.FormUrlEncoded{{/isMultipart}}{{/-first}}{{/formParams}} + @{{httpMethod}}("{{{path}}}") + {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}} {{operationId}}({{^allParams}});{{/allParams}} + {{#allParams}}{{>libraries/retrofit/queryParams}}{{>libraries/retrofit/pathParams}}{{>libraries/retrofit/headerParams}}{{>libraries/retrofit/bodyParams}}{{>libraries/retrofit/formParams}}{{^-last}}, {{/-last}}{{#-last}} + );{{/-last}}{{/allParams}} + + /** + * {{summary}} + * Async method +{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} +{{/allParams}} + * @param cb callback method +{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation +{{/externalDocs}} + */ + {{#formParams}}{{#-first}} + {{#isMultipart}}@retrofit.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit.http.FormUrlEncoded{{/isMultipart}}{{/-first}}{{/formParams}} + @{{httpMethod}}("{{{path}}}") + void {{operationId}}( + {{#allParams}}{{>libraries/retrofit/queryParams}}{{>libraries/retrofit/pathParams}}{{>libraries/retrofit/headerParams}}{{>libraries/retrofit/bodyParams}}{{>libraries/retrofit/formParams}}, {{/allParams}}Callback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> cb + ); + {{/operation}} +} +{{/operations}} diff --git a/.generator/templates/libraries/retrofit/api_test.mustache b/.generator/templates/libraries/retrofit/api_test.mustache new file mode 100644 index 00000000000..db07fb825c9 --- /dev/null +++ b/.generator/templates/libraries/retrofit/api_test.mustache @@ -0,0 +1,44 @@ +package {{package}}; + +import {{invokerPackage}}.ApiClient; +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Before; +import org.junit.Test; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +public class {{classname}}Test { + + private {{classname}} api; + + @Before + public void setup() { + api = new ApiClient().createService({{classname}}.class); + } + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + */ + @Test + public void {{operationId}}Test() { + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + // {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + + // TODO: test validations + } + {{/operation}}{{/operations}} +} diff --git a/.generator/templates/libraries/retrofit/auth/ApiKeyAuth.mustache b/.generator/templates/libraries/retrofit/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..69205bb2083 --- /dev/null +++ b/.generator/templates/libraries/retrofit/auth/ApiKeyAuth.mustache @@ -0,0 +1,72 @@ +package {{invokerPackage}}.auth; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import com.squareup.okhttp.Interceptor; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; + +public class ApiKeyAuth implements Interceptor { + private final String location; + private final String paramName; + + private String apiKey; + + 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; + } + + @Override + public Response intercept(Chain chain) throws IOException { + String paramValue; + Request request = chain.request(); + + if ("query".equals(location)) { + String newQuery = request.uri().getQuery(); + paramValue = paramName + "=" + apiKey; + if (newQuery == null) { + newQuery = paramValue; + } else { + newQuery += "&" + paramValue; + } + + URI newUri; + try { + newUri = new URI(request.uri().getScheme(), request.uri().getAuthority(), + request.uri().getPath(), newQuery, request.uri().getFragment()); + } catch (URISyntaxException e) { + throw new IOException(e); + } + + request = request.newBuilder().url(newUri.toURL()).build(); + } else if ("header".equals(location)) { + request = request.newBuilder() + .addHeader(paramName, apiKey) + .build(); + } else if ("cookie".equals(location)) { + request = request.newBuilder() + .addHeader("Cookie", String.format("%s=%s", paramName, apiKey)) + .build(); + } + return chain.proceed(request); + } +} diff --git a/.generator/templates/libraries/retrofit/auth/HttpBasicAuth.mustache b/.generator/templates/libraries/retrofit/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..394592f64d9 --- /dev/null +++ b/.generator/templates/libraries/retrofit/auth/HttpBasicAuth.mustache @@ -0,0 +1,49 @@ +package {{invokerPackage}}.auth; + +import java.io.IOException; + +import com.squareup.okhttp.Credentials; +import com.squareup.okhttp.Interceptor; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; + +public class HttpBasicAuth implements Interceptor { + + 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; + } + + public void setCredentials(String username, String password) { + this.username = username; + this.password = password; + } + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + + // If the request already have an authorization (eg. Basic auth), do nothing + if (request.header("Authorization") == null) { + String credentials = Credentials.basic(username, password); + request = request.newBuilder() + .addHeader("Authorization", credentials) + .build(); + } + return chain.proceed(request); + } +} diff --git a/.generator/templates/libraries/retrofit/auth/HttpBearerAuth.mustache b/.generator/templates/libraries/retrofit/auth/HttpBearerAuth.mustache new file mode 100644 index 00000000000..9b910c461cb --- /dev/null +++ b/.generator/templates/libraries/retrofit/auth/HttpBearerAuth.mustache @@ -0,0 +1,42 @@ +package {{invokerPackage}}.auth; + +import java.io.IOException; + +import com.squareup.okhttp.Interceptor; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; + +public class HttpBearerAuth implements Interceptor { + private final String scheme; + private String bearerToken; + + public HttpBearerAuth(String scheme) { + this.scheme = scheme; + } + + public String getBearerToken() { + return bearerToken; + } + + public void setBearerToken(String bearerToken) { + this.bearerToken = bearerToken; + } + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + + // If the request already have an authorization (eg. Basic auth), do nothing + if (request.header("Authorization") == null && bearerToken != null) { + request = request.newBuilder() + .addHeader("Authorization", (scheme != null ? upperCaseBearer(scheme) + " " : "") + bearerToken) + .build(); + } + return chain.proceed(request); + } + + private static String upperCaseBearer(String scheme) { + return ("bearer".equalsIgnoreCase(scheme)) ? "Bearer" : scheme; + } + +} diff --git a/.generator/templates/libraries/retrofit/auth/OAuth.mustache b/.generator/templates/libraries/retrofit/auth/OAuth.mustache new file mode 100644 index 00000000000..4c39f4e629e --- /dev/null +++ b/.generator/templates/libraries/retrofit/auth/OAuth.mustache @@ -0,0 +1,185 @@ +package {{invokerPackage}}.auth; + +import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; +import static java.net.HttpURLConnection.HTTP_FORBIDDEN; + +import java.io.IOException; +import java.util.Map; + +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.AuthenticationRequestBuilder; +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 org.apache.oltu.oauth2.common.token.BasicOAuthToken; + +import com.squareup.okhttp.Interceptor; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Request.Builder; +import com.squareup.okhttp.Response; + +public class OAuth implements Interceptor { + + public interface AccessTokenListener { + public void notify(BasicOAuthToken token); + } + + private volatile String accessToken; + private OAuthClient oauthClient; + + private TokenRequestBuilder tokenRequestBuilder; + private AuthenticationRequestBuilder authenticationRequestBuilder; + + private AccessTokenListener accessTokenListener; + + public OAuth( OkHttpClient client, TokenRequestBuilder requestBuilder ) { + this.oauthClient = new OAuthClient(new OAuthOkHttpClient(client)); + this.tokenRequestBuilder = requestBuilder; + } + + public OAuth(TokenRequestBuilder requestBuilder ) { + this(new OkHttpClient(), requestBuilder); + } + + public OAuth(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { + this(OAuthClientRequest.tokenLocation(tokenUrl).setScope(scopes)); + setFlow(flow); + authenticationRequestBuilder = OAuthClientRequest.authorizationLocation(authorizationUrl); + } + + public void setFlow(OAuthFlow flow) { + switch(flow) { + case accessCode: + case implicit: + tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE); + 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 have an authorization (eg. Basic auth), do nothing + if (request.header("Authorization") != null) { + return chain.proceed(request); + } + + // If first time, get the token + OAuthClientRequest oAuthRequest; + if (getAccessToken() == null) { + updateAccessToken(null); + } + + if (getAccessToken() != null) { + // Build the request + Builder rb = request.newBuilder(); + + String requestAccessToken = new String(getAccessToken()); + try { + oAuthRequest = new OAuthBearerClientRequest(request.urlString()) + .setAccessToken(requestAccessToken) + .buildHeaderMessage(); + } catch (OAuthSystemException e) { + throw new IOException(e); + } + + for ( Map.Entry header : oAuthRequest.getHeaders().entrySet() ) { + rb.addHeader(header.getKey(), header.getValue()); + } + rb.url( oAuthRequest.getLocationUri()); + + //Execute the request + Response response = chain.proceed(rb.build()); + + // 401/403 most likely indicates that access token has expired. Unless it happens two times in a row. + if ( response != null && (response.code() == HTTP_UNAUTHORIZED || response.code() == 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 + */ + public synchronized boolean updateAccessToken(String requestAccessToken) throws IOException { + if (getAccessToken() == null || getAccessToken().equals(requestAccessToken)) { + try { + OAuthJSONAccessTokenResponse accessTokenResponse = oauthClient.accessToken(this.tokenRequestBuilder.buildBodyMessage()); + if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { + setAccessToken(accessTokenResponse.getAccessToken()); + if (accessTokenListener != null) { + accessTokenListener.notify((BasicOAuthToken) accessTokenResponse.getOAuthToken()); + } + return !getAccessToken().equals(requestAccessToken); + } else { + return false; + } + } catch (OAuthSystemException e) { + throw new IOException(e); + } catch (OAuthProblemException e) { + throw new IOException(e); + } + } + return true; + } + + public void registerAccessTokenListener(AccessTokenListener accessTokenListener) { + this.accessTokenListener = accessTokenListener; + } + + public synchronized String getAccessToken() { + return accessToken; + } + + public synchronized void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + public TokenRequestBuilder getTokenRequestBuilder() { + return tokenRequestBuilder; + } + + public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) { + this.tokenRequestBuilder = tokenRequestBuilder; + } + + public AuthenticationRequestBuilder getAuthenticationRequestBuilder() { + return authenticationRequestBuilder; + } + + public void setAuthenticationRequestBuilder(AuthenticationRequestBuilder authenticationRequestBuilder) { + this.authenticationRequestBuilder = authenticationRequestBuilder; + } + +} diff --git a/.generator/templates/libraries/retrofit/auth/OAuthOkHttpClient.mustache b/.generator/templates/libraries/retrofit/auth/OAuthOkHttpClient.mustache new file mode 100644 index 00000000000..ea195f7df04 --- /dev/null +++ b/.generator/templates/libraries/retrofit/auth/OAuthOkHttpClient.mustache @@ -0,0 +1,69 @@ +package {{invokerPackage}}.auth; + +import java.io.IOException; +import java.util.Map; +import java.util.Map.Entry; + +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 com.squareup.okhttp.MediaType; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.RequestBody; +import com.squareup.okhttp.Response; + + +public class OAuthOkHttpClient implements HttpClient { + + private OkHttpClient client; + + public OAuthOkHttpClient() { + this.client = new OkHttpClient(); + } + + public OAuthOkHttpClient(OkHttpClient client) { + this.client = client; + } + + 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(mediaType, request.getBody()) : 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(), + responseClass); + } catch (IOException e) { + throw new OAuthSystemException(e); + } + } + + public void shutdown() { + // Nothing to do here + } + +} diff --git a/.generator/templates/libraries/retrofit/bodyParams.mustache b/.generator/templates/libraries/retrofit/bodyParams.mustache new file mode 100644 index 00000000000..81de324b691 --- /dev/null +++ b/.generator/templates/libraries/retrofit/bodyParams.mustache @@ -0,0 +1 @@ +{{#isBodyParam}}@retrofit.http.Body {{{dataType}}} {{paramName}}{{/isBodyParam}} \ No newline at end of file diff --git a/.generator/templates/libraries/retrofit/build.gradle.mustache b/.generator/templates/libraries/retrofit/build.gradle.mustache new file mode 100644 index 00000000000..ec85f6ec71b --- /dev/null +++ b/.generator/templates/libraries/retrofit/build.gradle.mustache @@ -0,0 +1,127 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + maven { url "https://repo1.maven.org/maven2" } + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + okhttp_version = "2.7.5" + oltu_version = "1.0.1" + retrofit_version = "1.9.0" + swagger_annotations_version = "1.5.21" + junit_version = "4.13.1" + jodatime_version = "2.9.3" + {{#threetenbp}} + threetenbp_version = "1.4.0" + {{/threetenbp}} +} + +dependencies { + implementation "com.squareup.okhttp:okhttp:$okhttp_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "com.squareup.retrofit:retrofit:$retrofit_version" + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version" + implementation "joda-time:joda-time:$jodatime_version" + {{#threetenbp}} + implementation "org.threeten:threetenbp:$threetenbp_version" + {{/threetenbp}} + implementation 'javax.annotation:javax.annotation-api:1.3.2' + testImplementation "junit:junit:$junit_version" +} diff --git a/.generator/templates/libraries/retrofit/build.sbt.mustache b/.generator/templates/libraries/retrofit/build.sbt.mustache new file mode 100644 index 00000000000..cef4b1c048d --- /dev/null +++ b/.generator/templates/libraries/retrofit/build.sbt.mustache @@ -0,0 +1,24 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "com.squareup.okhttp" % "okhttp" % "2.7.5" % "compile", + "com.squareup.retrofit" % "retrofit" % "1.9.0" % "compile", + "io.swagger" % "swagger-annotations" % "1.5.21" % "compile", + "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", + "joda-time" % "joda-time" % "2.9.3" % "compile", + {{#threetenbp}} + "org.threeten" % "threetenbp" % "1.4.0" % "compile", + {{/threetenbp}} + "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", + "junit" % "junit" % "4.13.1" % "test", + "com.novocode" % "junit-interface" % "0.10" % "test" + ) + ) diff --git a/.generator/templates/libraries/retrofit/formParams.mustache b/.generator/templates/libraries/retrofit/formParams.mustache new file mode 100644 index 00000000000..851072b3f65 --- /dev/null +++ b/.generator/templates/libraries/retrofit/formParams.mustache @@ -0,0 +1 @@ +{{#isFormParam}}{{^isFile}}{{#isMultipart}}@retrofit.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit.http.Field{{/isMultipart}}("{{baseName}}") {{{dataType}}} {{paramName}}{{/isFile}}{{#isFile}}{{#isMultipart}}@retrofit.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit.http.Field{{/isMultipart}}("{{baseName}}") TypedFile {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/.generator/templates/libraries/retrofit/headerParams.mustache b/.generator/templates/libraries/retrofit/headerParams.mustache new file mode 100644 index 00000000000..5d6da4a9437 --- /dev/null +++ b/.generator/templates/libraries/retrofit/headerParams.mustache @@ -0,0 +1 @@ +{{#isHeaderParam}}@retrofit.http.Header("{{baseName}}") {{{dataType}}} {{paramName}}{{/isHeaderParam}} \ No newline at end of file diff --git a/.generator/templates/libraries/retrofit/pathParams.mustache b/.generator/templates/libraries/retrofit/pathParams.mustache new file mode 100644 index 00000000000..7b8be8442e0 --- /dev/null +++ b/.generator/templates/libraries/retrofit/pathParams.mustache @@ -0,0 +1 @@ +{{#isPathParam}}@retrofit.http.Path("{{baseName}}") {{{dataType}}} {{paramName}}{{/isPathParam}} \ No newline at end of file diff --git a/.generator/templates/libraries/retrofit/pom.mustache b/.generator/templates/libraries/retrofit/pom.mustache new file mode 100644 index 00000000000..b495864db77 --- /dev/null +++ b/.generator/templates/libraries/retrofit/pom.mustache @@ -0,0 +1,295 @@ + + 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-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + {{#java8}} + 1.8 + 1.8 + {{/java8}} + {{^java8}} + 1.7 + 1.7 + {{/java8}} + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.1 + + none + {{#java8}} + 1.8 + {{/java8}} + {{^java8}} + 1.7 + {{/java8}} + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + com.squareup.retrofit + retrofit + ${retrofit-version} + + + org.apache.oltu.oauth2 + org.apache.oltu.oauth2.client + ${oltu-version} + + + com.squareup.okhttp + okhttp + ${okhttp-version} + + + joda-time + joda-time + ${jodatime-version} + + {{#threetenbp}} + + org.threeten + threetenbp + ${threetenbp-version} + + {{/threetenbp}} + {{#parcelableModel}} + + + com.google.android + android + 4.1.1.4 + provided + + {{/parcelableModel}} + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.5.21 + 1.9.0 + 2.7.5 + 2.9.9 + {{#threetenbp}} + 1.4.0 + {{/threetenbp}} + 1.0.1 + 1.3.2 + 1.0.0 + 4.13.1 + + diff --git a/.generator/templates/libraries/retrofit/queryParams.mustache b/.generator/templates/libraries/retrofit/queryParams.mustache new file mode 100644 index 00000000000..2a580ab34ec --- /dev/null +++ b/.generator/templates/libraries/retrofit/queryParams.mustache @@ -0,0 +1 @@ +{{#isQueryParam}}@retrofit.http.Query("{{baseName}}") {{#collectionFormat}}{{#isCollectionFormatMulti}}{{{dataType}}}{{/isCollectionFormatMulti}}{{^isCollectionFormatMulti}}{{{collectionFormat.toUpperCase}}}Params{{/isCollectionFormatMulti}}{{/collectionFormat}}{{^collectionFormat}}{{{dataType}}}{{/collectionFormat}} {{paramName}}{{/isQueryParam}} \ No newline at end of file diff --git a/.generator/templates/libraries/retrofit2/ApiClient.mustache b/.generator/templates/libraries/retrofit2/ApiClient.mustache new file mode 100644 index 00000000000..de40d727587 --- /dev/null +++ b/.generator/templates/libraries/retrofit2/ApiClient.mustache @@ -0,0 +1,467 @@ +package {{invokerPackage}}; + +import com.google.gson.Gson; +import com.google.gson.JsonParseException; +import com.google.gson.JsonElement; +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.RequestBody; +import okhttp3.ResponseBody; +{{#hasOAuthMethods}} +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; +{{/hasOAuthMethods}} +{{#joda}} +import org.joda.time.format.DateTimeFormatter; +{{/joda}} +{{#threetenbp}} +import org.threeten.bp.format.DateTimeFormatter; +{{/threetenbp}} +import retrofit2.Converter; +import retrofit2.Retrofit; +{{#useRxJava}} +import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; +{{/useRxJava}} +{{#useRxJava2}} +import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; +{{/useRxJava2}} +{{#useRxJava3}} +import hu.akarnokd.rxjava3.retrofit.RxJava3CallAdapterFactory; +{{/useRxJava3}} +import retrofit2.converter.gson.GsonConverterFactory; +import retrofit2.converter.scalars.ScalarsConverterFactory; +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.HttpBearerAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +{{#hasOAuthMethods}} +import {{invokerPackage}}.auth.OAuth; +import {{invokerPackage}}.auth.OAuth.AccessTokenListener; +import {{invokerPackage}}.auth.OAuthFlow; +{{/hasOAuthMethods}} + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.text.DateFormat; +{{#java8}} +import java.time.format.DateTimeFormatter; +{{/java8}} +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.HashMap; + +public class ApiClient { + + private Map apiAuthorizations; + private OkHttpClient.Builder okBuilder; + private Retrofit.Builder adapterBuilder; + private JSON json; + private OkHttpClient okHttpClient; + + public ApiClient() { + apiAuthorizations = new LinkedHashMap(); + createDefaultAdapter(); + okBuilder = new OkHttpClient.Builder(); + } + + public ApiClient(OkHttpClient client){ + apiAuthorizations = new LinkedHashMap(); + createDefaultAdapter(); + okHttpClient = client; + } + + public ApiClient(String[] authNames) { + this(); + for(String authName : authNames) { + {{#hasAuthMethods}} + Interceptor auth; + {{#authMethods}}if ("{{name}}".equals(authName)) { + {{#isBasic}}{{#isBasicBasic}} + auth = new HttpBasicAuth(); + {{/isBasicBasic}}{{^isBasicBasic}} + auth = new HttpBearerAuth("{{scheme}}"); + {{/isBasicBasic}}{{/isBasic}} + {{#isApiKey}} + auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"); + {{/isApiKey}} + {{#isOAuth}} + auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{^-last}}, {{/-last}}{{/scopes}}"); + {{/isOAuth}} + } else {{/authMethods}}{ + throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); + } + + addAuthorization(authName, auth); + {{/hasAuthMethods}} + {{^hasAuthMethods}} + throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); + {{/hasAuthMethods}} + } + } + + /** + * Basic constructor for single auth name + * @param authName Authentication name + */ + public ApiClient(String authName) { + this(new String[]{authName}); + } + + /** + * Helper constructor for single api key + * @param authName Authentication name + * @param apiKey API key + */ + public ApiClient(String authName, String apiKey) { + this(authName); + this.setApiKey(apiKey); + } + + /** + * Helper constructor for single basic auth or password oauth2 + * @param authName Authentication name + * @param username Username + * @param password Password + */ + public ApiClient(String authName, String username, String password) { + this(authName); + this.setCredentials(username, password); + } + + {{#hasOAuthMethods}} + /** + * Helper constructor for single password oauth2 + * @param authName Authentication name + * @param clientId Client ID + * @param secret Client Secret + * @param username Username + * @param password Password + */ + public ApiClient(String authName, String clientId, String secret, String username, String password) { + this(authName); + this.getTokenEndPoint() + .setClientId(clientId) + .setClientSecret(secret) + .setUsername(username) + .setPassword(password); + } + + {{/hasOAuthMethods}} + public void createDefaultAdapter() { + json = new JSON(); + + String baseUrl = "{{{basePath}}}"; + if (!baseUrl.endsWith("/")) + baseUrl = baseUrl + "/"; + + adapterBuilder = new Retrofit + .Builder() + .baseUrl(baseUrl) + {{#useRxJava}} + .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) + {{/useRxJava}} + {{#useRxJava2}} + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) + {{/useRxJava2}} + {{#useRxJava3}} + .addCallAdapterFactory(RxJava3CallAdapterFactory.create()) + {{/useRxJava3}} + .addConverterFactory(ScalarsConverterFactory.create()) + .addConverterFactory(GsonCustomConverterFactory.create(json.getGson())); + } + + public S createService(Class serviceClass) { + if (okHttpClient != null) { + return adapterBuilder.client(okHttpClient).build().create(serviceClass); + } else { + return adapterBuilder.client(okBuilder.build()).build().create(serviceClass); + } + } + + public ApiClient setDateFormat(DateFormat dateFormat) { + this.json.setDateFormat(dateFormat); + return this; + } + + public ApiClient setSqlDateFormat(DateFormat dateFormat) { + this.json.setSqlDateFormat(dateFormat); + return this; + } + + {{#joda}} + public ApiClient setDateTimeFormat(DateTimeFormatter dateFormat) { + this.json.setDateTimeFormat(dateFormat); + return this; + } + + public ApiClient setLocalDateFormat(DateTimeFormatter dateFormat) { + this.json.setLocalDateFormat(dateFormat); + return this; + } + + {{/joda}} + {{#jsr310}} + public ApiClient setOffsetDateTimeFormat(DateTimeFormatter dateFormat) { + this.json.setOffsetDateTimeFormat(dateFormat); + return this; + } + + public ApiClient setLocalDateFormat(DateTimeFormatter dateFormat) { + this.json.setLocalDateFormat(dateFormat); + return this; + } + + {{/jsr310}} + + /** + * Helper method to configure the first api key found + * @param apiKey API key + * @return ApiClient + */ + public ApiClient setApiKey(String apiKey) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof ApiKeyAuth) { + ApiKeyAuth keyAuth = (ApiKeyAuth) apiAuthorization; + keyAuth.setApiKey(apiKey); + return this; + } + } + return this; + } + + /** + * Helper method to set token for the first Http Bearer authentication found. + * @param bearerToken Bearer token + * @return ApiClient + */ + public ApiClient setBearerToken(String bearerToken) { + for (Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof HttpBearerAuth) { + ((HttpBearerAuth) apiAuthorization).setBearerToken(bearerToken); + return this; + } + } + return this; + } + + /** + * Helper method to configure the username/password for basic auth or password oauth + * @param username Username + * @param password Password + * @return ApiClient + */ + public ApiClient setCredentials(String username, String password) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof HttpBasicAuth) { + HttpBasicAuth basicAuth = (HttpBasicAuth) apiAuthorization; + basicAuth.setCredentials(username, password); + return this; + } + {{#hasOAuthMethods}} + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.getTokenRequestBuilder().setUsername(username).setPassword(password); + return this; + } + {{/hasOAuthMethods}} + } + 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(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + return oauth.getTokenRequestBuilder(); + } + } + return null; + } + + /** + * Helper method to configure authorization endpoint of the first oauth found in the apiAuthorizations (there should be only one) + * @return Authentication request builder + */ + public AuthenticationRequestBuilder getAuthorizationEndPoint() { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + return oauth.getAuthenticationRequestBuilder(); + } + } + return null; + } + + /** + * Helper method to pre-set the oauth access token of the first oauth found in the apiAuthorizations (there should be only one) + * @param accessToken Access token + * @return ApiClient + */ + public ApiClient setAccessToken(String accessToken) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.setAccessToken(accessToken); + return this; + } + } + return this; + } + + /** + * Helper method to configure the oauth accessCode/implicit flow parameters + * @param clientId Client ID + * @param clientSecret Client secret + * @param redirectURI Redirect URI + * @return ApiClient + */ + public ApiClient configureAuthorizationFlow(String clientId, String clientSecret, String redirectURI) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.getTokenRequestBuilder() + .setClientId(clientId) + .setClientSecret(clientSecret) + .setRedirectURI(redirectURI); + oauth.getAuthenticationRequestBuilder() + .setClientId(clientId) + .setRedirectURI(redirectURI); + return this; + } + } + return this; + } + + /** + * Configures a listener which is notified when a new access token is received. + * @param accessTokenListener Access token listener + * @return ApiClient + */ + public ApiClient registerAccessTokenListener(AccessTokenListener accessTokenListener) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.registerAccessTokenListener(accessTokenListener); + return this; + } + } + return this; + } + {{/hasOAuthMethods}} + + /** + * Adds an authorization to be used by the client + * @param authName Authentication name + * @param authorization Authorization interceptor + * @return ApiClient + */ + public ApiClient addAuthorization(String authName, Interceptor authorization) { + if (apiAuthorizations.containsKey(authName)) { + throw new RuntimeException("auth name \"" + authName + "\" already in api authorizations"); + } + apiAuthorizations.put(authName, authorization); + if(okBuilder == null){ + throw new RuntimeException("The ApiClient was created with a built OkHttpClient so it's not possible to add an authorization interceptor to it"); + } + okBuilder.addInterceptor(authorization); + + return this; + } + + public Map getApiAuthorizations() { + return apiAuthorizations; + } + + public ApiClient setApiAuthorizations(Map apiAuthorizations) { + this.apiAuthorizations = apiAuthorizations; + return this; + } + + public Retrofit.Builder getAdapterBuilder() { + return adapterBuilder; + } + + public ApiClient setAdapterBuilder(Retrofit.Builder adapterBuilder) { + this.adapterBuilder = adapterBuilder; + return this; + } + + public OkHttpClient.Builder getOkBuilder() { + return okBuilder; + } + + public void addAuthsToOkBuilder(OkHttpClient.Builder okBuilder) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + okBuilder.addInterceptor(apiAuthorization); + } + } + + /** + * Clones the okBuilder given in parameter, adds the auth interceptors and uses it to configure the Retrofit + * @param okClient An instance of OK HTTP client + */ + public void configureFromOkclient(OkHttpClient okClient) { + this.okBuilder = okClient.newBuilder(); + addAuthsToOkBuilder(this.okBuilder); + } +} + +/** + * This wrapper is to take care of this case: + * when the deserialization fails due to JsonParseException and the + * expected type is String, then just return the body string. + */ +class GsonResponseBodyConverterToString implements Converter { + private final Gson gson; + private final Type type; + + GsonResponseBodyConverterToString(Gson gson, Type type) { + this.gson = gson; + this.type = type; + } + + @Override public T convert(ResponseBody value) throws IOException { + String returned = value.string(); + try { + return gson.fromJson(returned, type); + } + catch (JsonParseException e) { + return (T) returned; + } + } +} + +class GsonCustomConverterFactory extends Converter.Factory +{ + private final Gson gson; + private final GsonConverterFactory gsonConverterFactory; + + public static GsonCustomConverterFactory create(Gson gson) { + return new GsonCustomConverterFactory(gson); + } + + private GsonCustomConverterFactory(Gson gson) { + if (gson == null) + throw new NullPointerException("gson == null"); + this.gson = gson; + this.gsonConverterFactory = GsonConverterFactory.create(gson); + } + + @Override + public Converter responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { + if (type.equals(String.class)) + return new GsonResponseBodyConverterToString(gson, type); + else + return gsonConverterFactory.responseBodyConverter(type, annotations, retrofit); + } + + @Override + public Converter requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { + return gsonConverterFactory.requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit); + } +} diff --git a/.generator/templates/libraries/retrofit2/CollectionFormats.mustache b/.generator/templates/libraries/retrofit2/CollectionFormats.mustache new file mode 100644 index 00000000000..dbfa4ae767b --- /dev/null +++ b/.generator/templates/libraries/retrofit2/CollectionFormats.mustache @@ -0,0 +1,99 @@ +package {{invokerPackage}}; + +import java.util.Arrays; +import java.util.List; + +public class CollectionFormats { + + public static class CSVParams { + + protected List params; + + public CSVParams() { + } + + public CSVParams(List params) { + this.params = params; + } + + public CSVParams(String... params) { + this.params = Arrays.asList(params); + } + + public List getParams() { + return params; + } + + public void setParams(List params) { + this.params = params; + } + + @Override + public String toString() { + return StringUtil.join(params.toArray(new String[0]), ","); + } + + } + + public static class SPACEParams extends SSVParams { + + } + + public static class SSVParams extends CSVParams { + + public SSVParams() { + } + + public SSVParams(List params) { + super(params); + } + + public SSVParams(String... params) { + super(params); + } + + @Override + public String toString() { + return StringUtil.join(params.toArray(new String[0]), " "); + } + } + + public static class TSVParams extends CSVParams { + + public TSVParams() { + } + + public TSVParams(List params) { + super(params); + } + + public TSVParams(String... params) { + super(params); + } + + @Override + public String toString() { + return StringUtil.join( params.toArray(new String[0]), "\t"); + } + } + + public static class PIPESParams extends CSVParams { + + public PIPESParams() { + } + + public PIPESParams(List params) { + super(params); + } + + public PIPESParams(String... params) { + super(params); + } + + @Override + public String toString() { + return StringUtil.join(params.toArray(new String[0]), "|"); + } + } + +} diff --git a/.generator/templates/libraries/retrofit2/JSON.mustache b/.generator/templates/libraries/retrofit2/JSON.mustache new file mode 100644 index 00000000000..9ba7567bffe --- /dev/null +++ b/.generator/templates/libraries/retrofit2/JSON.mustache @@ -0,0 +1,448 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +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; +{{#joda}} +import org.joda.time.DateTime; +import org.joda.time.LocalDate; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.DateTimeFormatterBuilder; +import org.joda.time.format.ISODateTimeFormat; +{{/joda}} +{{#threetenbp}} +import org.threeten.bp.LocalDate; +import org.threeten.bp.OffsetDateTime; +import org.threeten.bp.format.DateTimeFormatter; +{{/threetenbp}} + +{{#models.0}} +import {{modelPackage}}.*; +{{/models.0}} + +import java.io.IOException; +import java.io.StringReader; +import java.lang.reflect.Type; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.ParsePosition; +{{#java8}} +import java.time.LocalDate; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +{{/java8}} +import java.util.Date; +import java.util.Locale; +import java.util.Map; +import java.util.HashMap; + +public class JSON { + private Gson gson; + private DateTypeAdapter dateTypeAdapter = new DateTypeAdapter(); + private SqlDateTypeAdapter sqlDateTypeAdapter = new SqlDateTypeAdapter(); + {{#joda}} + private DateTimeTypeAdapter dateTimeTypeAdapter = new DateTimeTypeAdapter(); + private LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter(); + {{/joda}} + {{#jsr310}} + private OffsetDateTimeTypeAdapter offsetDateTimeTypeAdapter = new OffsetDateTimeTypeAdapter(); + private LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter(); + {{/jsr310}} + + public static GsonBuilder createGson() { + GsonFireBuilder fireBuilder = new GsonFireBuilder() + {{#models}}{{#model}}{{#discriminator}} .registerTypeSelector({{classname}}.class, new TypeSelector() { + @Override + public Class getClassForElement(JsonElement readElement) { + Map classByDiscriminatorValue = new HashMap(); + {{#mappedModels}} + classByDiscriminatorValue.put("{{mappingName}}".toUpperCase(Locale.ROOT), {{modelName}}.class); + {{/mappedModels}} + classByDiscriminatorValue.put("{{classname}}".toUpperCase(Locale.ROOT), {{classname}}.class); + return getClassByDiscriminator( + classByDiscriminatorValue, + getDiscriminatorValue(readElement, "{{{propertyName}}}")); + } + }) + {{/discriminator}}{{/model}}{{/models}} + ; + return fireBuilder.createGsonBuilder(); + } + + 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.toUpperCase(Locale.ROOT)); + if(null == clazz) { + throw new IllegalArgumentException("cannot determine model class of name: <" + discriminatorValue + ">"); + } + return clazz; + } + + public JSON() { + gson = createGson() + .registerTypeAdapter(Date.class, dateTypeAdapter) + .registerTypeAdapter(java.sql.Date.class, sqlDateTypeAdapter) + {{#joda}} + .registerTypeAdapter(DateTime.class, dateTimeTypeAdapter) + .registerTypeAdapter(LocalDate.class, localDateTypeAdapter) + {{/joda}} + {{#jsr310}} + .registerTypeAdapter(OffsetDateTime.class, offsetDateTimeTypeAdapter) + .registerTypeAdapter(LocalDate.class, localDateTypeAdapter) + {{/jsr310}} + .create(); + } + + /** + * Get Gson. + * + * @return Gson + */ + public Gson getGson() { + return gson; + } + + /** + * Set Gson. + * + * @param gson Gson + * @return JSON + */ + public JSON setGson(Gson gson) { + this.gson = gson; + return this; + } + + {{#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 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); + } + } + } + + public JSON setDateTimeFormat(DateTimeFormatter dateFormat) { + dateTimeTypeAdapter.setFormat(dateFormat); + return this; + } + + public JSON setLocalDateFormat(DateTimeFormatter dateFormat) { + localDateTypeAdapter.setFormat(dateFormat); + return this; + } + + {{/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 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); + } + } + } + + public JSON setOffsetDateTimeFormat(DateTimeFormatter dateFormat) { + offsetDateTimeTypeAdapter.setFormat(dateFormat); + return this; + } + + public JSON setLocalDateFormat(DateTimeFormatter dateFormat) { + localDateTypeAdapter.setFormat(dateFormat); + return this; + } + + {{/jsr310}} + /** + * Gson TypeAdapter for java.sql.Date type + * If the dateFormat is null, a simple "yyyy-MM-dd" format will be used + * (more efficient than SimpleDateFormat). + */ + 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 + * If the dateFormat is null, ISO8601Utils will be used. + */ + 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); + } + } + } + + public JSON setDateFormat(DateFormat dateFormat) { + dateTypeAdapter.setFormat(dateFormat); + return this; + } + + public JSON setSqlDateFormat(DateFormat dateFormat) { + sqlDateTypeAdapter.setFormat(dateFormat); + return this; + } + +} diff --git a/.generator/templates/libraries/retrofit2/README.mustache b/.generator/templates/libraries/retrofit2/README.mustache new file mode 100644 index 00000000000..847b9d5a2a1 --- /dev/null +++ b/.generator/templates/libraries/retrofit2/README.mustache @@ -0,0 +1,39 @@ +# {{artifactId}} + +## Requirements + +Building the API client library requires [Maven](https://maven.apache.org/) to be installed. + +## Installation & Usage + +To install the API client library to your local Maven repository, simply execute: + +```shell +mvn install +``` + +To deploy it to a remote Maven repository instead, configure the settings of the repository and execute: + +```shell +mvn deploy +``` + +Refer to the [official documentation](https://maven.apache.org/plugins/maven-deploy-plugin/usage.html) for more information. + +After the client library is installed/deployed, you can use it in your Maven project by adding the following to your *pom.xml*: + +```xml + + {{groupId}} + {{artifactId}} + {{artifactVersion}} + compile + + +``` + +## Author + +{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}} +{{/-last}}{{/apis}}{{/apiInfo}} + diff --git a/.generator/templates/libraries/retrofit2/api.mustache b/.generator/templates/libraries/retrofit2/api.mustache new file mode 100644 index 00000000000..baa89192cd7 --- /dev/null +++ b/.generator/templates/libraries/retrofit2/api.mustache @@ -0,0 +1,83 @@ +package {{package}}; + +import {{invokerPackage}}.CollectionFormats.*; + +{{#useRxJava}} +import rx.Observable; +{{/useRxJava}} +{{#useRxJava2}} +import io.reactivex.Observable; +{{/useRxJava2}} +{{#useRxJava3}} +import io.reactivex.rxjava3.core.Observable; +{{/useRxJava3}} +{{^returnType}} +{{#useRxJava2}} +import io.reactivex.Completable; +{{/useRxJava2}} +{{#useRxJava3}} +import io.reactivex.rxjava3.core.Completable; +{{/useRxJava3}} +{{/returnType}} +{{#doNotUseRx}} +import retrofit2.Call; +{{/doNotUseRx}} +import retrofit2.http.*; + +import okhttp3.RequestBody; +import okhttp3.ResponseBody; +import okhttp3.MultipartBody; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +{{#operations}} +public interface {{classname}} { + {{#operation}} + /** + * {{summary}} + * {{notes}} +{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} +{{/allParams}} + * @return {{^doNotUseRx}}{{#useRxJava}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/useRxJava}}{{#useRxJava2}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{returnType}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{#useRxJava3}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{returnType}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava3}}{{/doNotUseRx}}{{#doNotUseRx}}Call<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/doNotUseRx}} +{{#isDeprecated}} + * @deprecated +{{/isDeprecated}} +{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation +{{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + {{#formParams}} + {{#-first}} + {{#isMultipart}}@retrofit2.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit2.http.FormUrlEncoded{{/isMultipart}} + {{/-first}} + {{/formParams}} + {{^formParams}} + {{#prioritizedContentTypes}} + {{#-first}} + @Headers({ + "Content-Type:{{{mediaType}}}" + }) + {{/-first}} + {{/prioritizedContentTypes}} + {{/formParams}} + @{{httpMethod}}("{{{path}}}") + {{^doNotUseRx}}{{#useRxJava}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/useRxJava}}{{#useRxJava2}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{#useRxJava3}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava3}}{{/doNotUseRx}}{{#doNotUseRx}}Call<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/doNotUseRx}} {{operationId}}({{^allParams}});{{/allParams}} + {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{^-last}}, {{/-last}}{{#-last}} + );{{/-last}}{{/allParams}} + + {{/operation}} +} +{{/operations}} diff --git a/.generator/templates/libraries/retrofit2/api_test.mustache b/.generator/templates/libraries/retrofit2/api_test.mustache new file mode 100644 index 00000000000..d214d97724c --- /dev/null +++ b/.generator/templates/libraries/retrofit2/api_test.mustache @@ -0,0 +1,46 @@ +package {{package}}; + +import {{invokerPackage}}.ApiClient; +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Before; +import org.junit.Test; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +public class {{classname}}Test { + + private {{classname}} api; + + @Before + public void setup() { + api = new ApiClient().createService({{classname}}.class); + } + + {{#operations}} + {{#operation}} + /** + * {{summary}} + * + * {{notes}} + */ + @Test + public void {{operationId}}Test() { + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + // {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + + // TODO: test validations + } + {{/operation}} + {{/operations}} +} diff --git a/.generator/templates/libraries/retrofit2/auth/ApiKeyAuth.mustache b/.generator/templates/libraries/retrofit2/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..bcc62b284a5 --- /dev/null +++ b/.generator/templates/libraries/retrofit2/auth/ApiKeyAuth.mustache @@ -0,0 +1,72 @@ +package {{invokerPackage}}.auth; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +public class ApiKeyAuth implements Interceptor { + private final String location; + private final String paramName; + + private String apiKey; + + 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; + } + + @Override + public Response intercept(Chain chain) throws IOException { + String paramValue; + Request request = chain.request(); + + if ("query".equals(location)) { + String newQuery = request.url().uri().getQuery(); + paramValue = paramName + "=" + apiKey; + if (newQuery == null) { + newQuery = paramValue; + } else { + newQuery += "&" + paramValue; + } + + URI newUri; + try { + newUri = new URI(request.url().uri().getScheme(), request.url().uri().getAuthority(), + request.url().uri().getPath(), newQuery, request.url().uri().getFragment()); + } catch (URISyntaxException e) { + throw new IOException(e); + } + + request = request.newBuilder().url(newUri.toURL()).build(); + } else if ("header".equals(location)) { + request = request.newBuilder() + .addHeader(paramName, apiKey) + .build(); + } else if ("cookie".equals(location)) { + request = request.newBuilder() + .addHeader("Cookie", String.format("%s=%s", paramName, apiKey)) + .build(); + } + return chain.proceed(request); + } +} diff --git a/.generator/templates/libraries/retrofit2/auth/HttpBasicAuth.mustache b/.generator/templates/libraries/retrofit2/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..d4588426662 --- /dev/null +++ b/.generator/templates/libraries/retrofit2/auth/HttpBasicAuth.mustache @@ -0,0 +1,50 @@ +package {{invokerPackage}}.auth; + +import java.io.IOException; + +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.Credentials; + +public class HttpBasicAuth implements Interceptor { + + 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; + } + + public void setCredentials(String username, String password) { + this.username = username; + this.password = password; + } + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + + // If the request already have an authorization (eg. Basic auth), do nothing + if (request.header("Authorization") == null) { + String credentials = Credentials.basic(username, password); + request = request.newBuilder() + .addHeader("Authorization", credentials) + .build(); + } + return chain.proceed(request); + } +} diff --git a/.generator/templates/libraries/retrofit2/auth/HttpBearerAuth.mustache b/.generator/templates/libraries/retrofit2/auth/HttpBearerAuth.mustache new file mode 100644 index 00000000000..da1bef57a52 --- /dev/null +++ b/.generator/templates/libraries/retrofit2/auth/HttpBearerAuth.mustache @@ -0,0 +1,42 @@ +package {{invokerPackage}}.auth; + +import java.io.IOException; + +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +public class HttpBearerAuth implements Interceptor { + private final String scheme; + private String bearerToken; + + public HttpBearerAuth(String scheme) { + this.scheme = scheme; + } + + public String getBearerToken() { + return bearerToken; + } + + public void setBearerToken(String bearerToken) { + this.bearerToken = bearerToken; + } + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + + // If the request already have an authorization (eg. Basic auth), do nothing + if (request.header("Authorization") == null && bearerToken != null) { + request = request.newBuilder() + .addHeader("Authorization", (scheme != null ? upperCaseBearer(scheme) + " " : "") + bearerToken) + .build(); + } + return chain.proceed(request); + } + + private static String upperCaseBearer(String scheme) { + return ("bearer".equalsIgnoreCase(scheme)) ? "Bearer" : scheme; + } + +} diff --git a/.generator/templates/libraries/retrofit2/auth/OAuth.mustache b/.generator/templates/libraries/retrofit2/auth/OAuth.mustache new file mode 100644 index 00000000000..80ec7b3946c --- /dev/null +++ b/.generator/templates/libraries/retrofit2/auth/OAuth.mustache @@ -0,0 +1,185 @@ +package {{invokerPackage}}.auth; + +import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; +import static java.net.HttpURLConnection.HTTP_FORBIDDEN; + +import java.io.IOException; +import java.util.Map; + +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.AuthenticationRequestBuilder; +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 org.apache.oltu.oauth2.common.token.BasicOAuthToken; + +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Request.Builder; +import okhttp3.Response; + +public class OAuth implements Interceptor { + + public interface AccessTokenListener { + public void notify(BasicOAuthToken token); + } + + private volatile String accessToken; + private OAuthClient oauthClient; + + private TokenRequestBuilder tokenRequestBuilder; + private AuthenticationRequestBuilder authenticationRequestBuilder; + + private AccessTokenListener accessTokenListener; + + public OAuth( OkHttpClient client, TokenRequestBuilder requestBuilder ) { + this.oauthClient = new OAuthClient(new OAuthOkHttpClient(client)); + this.tokenRequestBuilder = requestBuilder; + } + + public OAuth(TokenRequestBuilder requestBuilder ) { + this(new OkHttpClient(), requestBuilder); + } + + public OAuth(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { + this(OAuthClientRequest.tokenLocation(tokenUrl).setScope(scopes)); + setFlow(flow); + authenticationRequestBuilder = OAuthClientRequest.authorizationLocation(authorizationUrl); + } + + public void setFlow(OAuthFlow flow) { + switch(flow) { + case accessCode: + case implicit: + tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE); + 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 have an authorization (eg. Basic auth), do nothing + if (request.header("Authorization") != null) { + return chain.proceed(request); + } + + // If first time, get the token + OAuthClientRequest oAuthRequest; + if (getAccessToken() == null) { + updateAccessToken(null); + } + + if (getAccessToken() != null) { + // Build the request + Builder rb = request.newBuilder(); + + String requestAccessToken = new String(getAccessToken()); + try { + oAuthRequest = new OAuthBearerClientRequest(request.url().toString()) + .setAccessToken(requestAccessToken) + .buildHeaderMessage(); + } catch (OAuthSystemException e) { + throw new IOException(e); + } + + for ( Map.Entry header : oAuthRequest.getHeaders().entrySet() ) { + rb.addHeader(header.getKey(), header.getValue()); + } + rb.url( oAuthRequest.getLocationUri()); + + //Execute the request + Response response = chain.proceed(rb.build()); + + // 401/403 most likely indicates that access token has expired. Unless it happens two times in a row. + if ( response != null && (response.code() == HTTP_UNAUTHORIZED || response.code() == 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 + */ + public synchronized boolean updateAccessToken(String requestAccessToken) throws IOException { + if (getAccessToken() == null || getAccessToken().equals(requestAccessToken)) { + try { + OAuthJSONAccessTokenResponse accessTokenResponse = oauthClient.accessToken(this.tokenRequestBuilder.buildBodyMessage()); + if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { + setAccessToken(accessTokenResponse.getAccessToken()); + if (accessTokenListener != null) { + accessTokenListener.notify((BasicOAuthToken) accessTokenResponse.getOAuthToken()); + } + return !getAccessToken().equals(requestAccessToken); + } else { + return false; + } + } catch (OAuthSystemException e) { + throw new IOException(e); + } catch (OAuthProblemException e) { + throw new IOException(e); + } + } + return true; + } + + public void registerAccessTokenListener(AccessTokenListener accessTokenListener) { + this.accessTokenListener = accessTokenListener; + } + + public synchronized String getAccessToken() { + return accessToken; + } + + public synchronized void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + public TokenRequestBuilder getTokenRequestBuilder() { + return tokenRequestBuilder; + } + + public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) { + this.tokenRequestBuilder = tokenRequestBuilder; + } + + public AuthenticationRequestBuilder getAuthenticationRequestBuilder() { + return authenticationRequestBuilder; + } + + public void setAuthenticationRequestBuilder(AuthenticationRequestBuilder authenticationRequestBuilder) { + this.authenticationRequestBuilder = authenticationRequestBuilder; + } + +} diff --git a/.generator/templates/libraries/retrofit2/auth/OAuthOkHttpClient.mustache b/.generator/templates/libraries/retrofit2/auth/OAuthOkHttpClient.mustache new file mode 100644 index 00000000000..423fa1ba0e5 --- /dev/null +++ b/.generator/templates/libraries/retrofit2/auth/OAuthOkHttpClient.mustache @@ -0,0 +1,72 @@ +package {{invokerPackage}}.auth; + +import java.io.IOException; +import java.util.Map; +import java.util.Map.Entry; + +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 okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Request.Builder; +import okhttp3.Response; +import okhttp3.MediaType; +import okhttp3.RequestBody; + + +public class OAuthOkHttpClient implements HttpClient { + + private OkHttpClient client; + + public OAuthOkHttpClient() { + this.client = new OkHttpClient(); + } + + public OAuthOkHttpClient(OkHttpClient client) { + this.client = client; + } + + 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(mediaType, request.getBody()) : 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(), + responseClass); + } catch (IOException e) { + throw new OAuthSystemException(e); + } + } + + public void shutdown() { + // Nothing to do here + } + +} diff --git a/.generator/templates/libraries/retrofit2/bodyParams.mustache b/.generator/templates/libraries/retrofit2/bodyParams.mustache new file mode 100644 index 00000000000..97b03fcb717 --- /dev/null +++ b/.generator/templates/libraries/retrofit2/bodyParams.mustache @@ -0,0 +1 @@ +{{#isBodyParam}}@retrofit2.http.Body {{{dataType}}} {{paramName}}{{/isBodyParam}} \ No newline at end of file diff --git a/.generator/templates/libraries/retrofit2/build.gradle.mustache b/.generator/templates/libraries/retrofit2/build.gradle.mustache new file mode 100644 index 00000000000..090eefa3383 --- /dev/null +++ b/.generator/templates/libraries/retrofit2/build.gradle.mustache @@ -0,0 +1,195 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + maven { url "https://repo1.maven.org/maven2" } + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + {{#java8}} + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + {{/java8}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + oltu_version = "1.0.1" + retrofit_version = "2.3.0" + {{#usePlayWS}} + jackson_version = "2.10.5" + jackson_databind_version = "2.10.5.1" + {{#openApiNullable}} + jackson_databind_nullable_version = "0.2.1" + {{/openApiNullable}} + {{#play24}} + play_version = "2.4.11" + {{/play24}} + {{#play25}} + play_version = "2.5.14" + {{/play25}} + {{#play26}} + play_version = "2.6.7" + {{/play26}} + {{/usePlayWS}} + swagger_annotations_version = "1.5.22" + junit_version = "4.13.1" + {{#useRxJava}} + rx_java_version = "1.3.0" + {{/useRxJava}} + {{#useRxJava2}} + rx_java_version = "2.1.1" + {{/useRxJava2}} + {{#useRxJava3}} + rx_java_version = "3.0.4" + {{/useRxJava3}} + {{#joda}} + jodatime_version = "2.9.9" + {{/joda}} + {{#threetenbp}} + threetenbp_version = "1.4.0" + {{/threetenbp}} + json_fire_version = "1.8.0" +} + +dependencies { + implementation "com.squareup.retrofit2:retrofit:$retrofit_version" + implementation "com.squareup.retrofit2:converter-scalars:$retrofit_version" + implementation "com.squareup.retrofit2:converter-gson:$retrofit_version" + {{#useRxJava}} + implementation "com.squareup.retrofit2:adapter-rxjava:$retrofit_version" + implementation "io.reactivex:rxjava:$rx_java_version" + {{/useRxJava}} + {{#useRxJava2}} + implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' + implementation "io.reactivex.rxjava2:rxjava:$rx_java_version" + {{/useRxJava2}} + {{#useRxJava3}} + implementation 'com.github.akarnokd:rxjava3-retrofit-adapter:3.0.0' + implementation "io.reactivex.rxjava3:rxjava:$rx_java_version" + {{/useRxJava3}} + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation ("org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version"){ + exclude group:'org.apache.oltu.oauth2' , module: 'org.apache.oltu.oauth2.common' + } + implementation "io.gsonfire:gson-fire:$json_fire_version" + {{#joda}} + implementation "joda-time:joda-time:$jodatime_version" + {{/joda}} + {{#threetenbp}} + implementation "org.threeten:threetenbp:$threetenbp_version" + {{/threetenbp}} + {{#usePlayWS}} + {{#play26}} + implementation "com.typesafe.play:play-ahc-ws_2.12:$play_version" + implementation "javax.validation:validation-api:1.1.0.Final" + {{/play26}} + {{^play26}} + implementation "com.typesafe.play:play-java-ws_2.11:$play_version" + {{/play26}} + implementation "com.squareup.retrofit2:converter-jackson:$retrofit_version" + 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_databind_version" + {{#openApiNullable}} + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}:$jackson_version" + {{/usePlayWS}} + implementation 'javax.annotation:javax.annotation-api:1.3.2' + testImplementation "junit:junit:$junit_version" +} diff --git a/.generator/templates/libraries/retrofit2/build.sbt.mustache b/.generator/templates/libraries/retrofit2/build.sbt.mustache new file mode 100644 index 00000000000..a9301f736a4 --- /dev/null +++ b/.generator/templates/libraries/retrofit2/build.sbt.mustache @@ -0,0 +1,58 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "com.squareup.retrofit2" % "retrofit" % "2.3.0" % "compile", + "com.squareup.retrofit2" % "converter-scalars" % "2.3.0" % "compile", + {{^usePlayWS}} + "com.squareup.retrofit2" % "converter-gson" % "2.3.0" % "compile", + {{/usePlayWS}} + {{#usePlayWS}} + {{#play24}} + "com.typesafe.play" % "play-java-ws_2.11" % "2.4.11" % "compile", + {{/play24}} + {{#play25}} + "com.typesafe.play" % "play-java-ws_2.11" % "2.5.15" % "compile", + {{/play25}} + {{#play26}} + "com.typesafe.play" % "play-ahc-ws_2.12" % "2.6.7" % "compile", + "javax.validation" % "validation-api" % "1.1.0.Final" % "compile", + {{/play26}} + "com.squareup.retrofit2" % "converter-jackson" % "2.3.0" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.5" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.5" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.5.1" % "compile", + {{/usePlayWS}} + {{#useRxJava}} + "com.squareup.retrofit2" % "adapter-rxjava" % "2.3.0" % "compile", + "io.reactivex" % "rxjava" % "1.3.0" % "compile", + {{/useRxJava}} + {{#useRxJava2}} + "com.squareup.retrofit2" % "adapter-rxjava2" % "2.3.0" % "compile", + "io.reactivex.rxjava2" % "rxjava" % "2.1.1" % "compile", + {{/useRxJava2}} + {{#useRxJava3}} + "com.github.akarnokd" % "rxjava3-retrofit-adapter" % "3.0.0" % "compile", + "io.reactivex.rxjava3" % "rxjava" % "3.0.4" % "compile", + {{/useRxJava3}} + "io.swagger" % "swagger-annotations" % "1.5.21" % "compile", + "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", + {{#joda}} + "joda-time" % "joda-time" % "2.9.9" % "compile", + {{/joda}} + {{#threetenbp}} + "org.threeten" % "threetenbp" % "1.4.0" % "compile", + {{/threetenbp}} + "io.gsonfire" % "gson-fire" % "1.8.0" % "compile", + "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", + "junit" % "junit" % "4.13.1" % "test", + "com.novocode" % "junit-interface" % "0.11" % "test" + ) + ) diff --git a/.generator/templates/libraries/retrofit2/formParams.mustache b/.generator/templates/libraries/retrofit2/formParams.mustache new file mode 100644 index 00000000000..0456f44947e --- /dev/null +++ b/.generator/templates/libraries/retrofit2/formParams.mustache @@ -0,0 +1 @@ +{{#isFormParam}}{{^isFile}}{{#isMultipart}}@retrofit2.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit2.http.Field{{/isMultipart}}("{{baseName}}") {{{dataType}}} {{paramName}}{{/isFile}}{{#isFile}}{{#isMultipart}}@retrofit2.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit2.http.Field("{{baseName}}"){{/isMultipart}} MultipartBody.Part {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/.generator/templates/libraries/retrofit2/formParams.mustache.save b/.generator/templates/libraries/retrofit2/formParams.mustache.save new file mode 100644 index 00000000000..a3a3c16f1c0 --- /dev/null +++ b/.generator/templates/libraries/retrofit2/formParams.mustache.save @@ -0,0 +1 @@ +{{#isFormParam}}{{^isFile}}{{#isMultipart}}retrofit.http@retrofit2.http.Part{{/isMultipart}}{{^isMultipart}}@Field{{/isMultipart}}("{{baseName}}") {{{dataType}}} {{paramName}}{{/isFile}}{{#isFile}}{{#isMultipart}}@Part{{/isMultipart}}{{^isMultipart}}@Field{{/isMultipart}} okhttp3.MultipartBody.Part {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/.generator/templates/libraries/retrofit2/headerParams.mustache b/.generator/templates/libraries/retrofit2/headerParams.mustache new file mode 100644 index 00000000000..c7748f3bf27 --- /dev/null +++ b/.generator/templates/libraries/retrofit2/headerParams.mustache @@ -0,0 +1 @@ +{{#isHeaderParam}}@retrofit2.http.Header("{{baseName}}") {{{dataType}}} {{paramName}}{{/isHeaderParam}} \ No newline at end of file diff --git a/.generator/templates/libraries/retrofit2/pathParams.mustache b/.generator/templates/libraries/retrofit2/pathParams.mustache new file mode 100644 index 00000000000..8fe7c380c41 --- /dev/null +++ b/.generator/templates/libraries/retrofit2/pathParams.mustache @@ -0,0 +1 @@ +{{#isPathParam}}@retrofit2.http.Path("{{baseName}}") {{{dataType}}} {{paramName}}{{/isPathParam}} \ No newline at end of file diff --git a/.generator/templates/libraries/retrofit2/play-common/auth/ApiKeyAuth.mustache b/.generator/templates/libraries/retrofit2/play-common/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..220d896533c --- /dev/null +++ b/.generator/templates/libraries/retrofit2/play-common/auth/ApiKeyAuth.mustache @@ -0,0 +1,69 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; + +import java.util.Map; +import java.util.List; + +/** + * Holds ApiKey auth info + */ +{{>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) { + 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/.generator/templates/libraries/retrofit2/play24/ApiClient.mustache b/.generator/templates/libraries/retrofit2/play24/ApiClient.mustache new file mode 100644 index 00000000000..c43f800a42c --- /dev/null +++ b/.generator/templates/libraries/retrofit2/play24/ApiClient.mustache @@ -0,0 +1,146 @@ +package {{invokerPackage}}; + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.*; + +import retrofit2.Retrofit; +import retrofit2.converter.scalars.ScalarsConverterFactory; +import retrofit2.converter.jackson.JacksonConverterFactory; +import com.fasterxml.jackson.databind.ObjectMapper; +{{#openApiNullable}} +import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} + +import play.libs.Json; +import play.libs.ws.WSClient; + +import {{invokerPackage}}.Play24CallAdapterFactory; +import {{invokerPackage}}.Play24CallFactory; + +import okhttp3.Interceptor; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.Authentication; + +/** + * API client + */ +public class ApiClient { + + /** Underlying HTTP-client */ + private WSClient wsClient; + + /** Supported auths */ + private Map authentications; + + /** API base path */ + private String basePath = "{{{basePath}}}"; + + public ApiClient(WSClient wsClient) { + this(); + this.wsClient = wsClient; + } + + public ApiClient() { + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap<>();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + // authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + // authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + // authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + + } + + /** + * Creates a retrofit2 client for given API interface + */ + public S createService(Class serviceClass) { + if(!basePath.endsWith("/")) { + basePath = basePath + "/"; + } + + Map extraHeaders = new HashMap<>(); + Map extraCookies = new HashMap<>(); + List extraQueryParams = new ArrayList<>(); + + for (String authName : authentications.keySet()) { + Authentication auth = authentications.get(authName); + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + + auth.applyToParams(extraQueryParams, extraHeaders, extraCookies); + } + + ObjectMapper mapper = Json.mapper(); + {{#openApiNullable}} + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); + {{/openApiNullable}} + + return new Retrofit.Builder() + .baseUrl(basePath) + .addConverterFactory(ScalarsConverterFactory.create()) + .addConverterFactory(JacksonConverterFactory.create(mapper)) + .callFactory(new Play24CallFactory(wsClient, extraHeaders, extraCookies, extraQueryParams)) + .addCallAdapterFactory(new Play24CallAdapterFactory()) + .build() + .create(serviceClass); + } + + /** + * Helper method to set API base path + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get authentications (key: authentication name, value: authentication). + */ + 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); + } + + /** + * Helper method to set API key value for the first API key authentication. + */ + public ApiClient setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return this; + } + } + + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + */ + public ApiClient setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return this; + } + } + + throw new RuntimeException("No API key authentication configured!"); + } + + +} diff --git a/.generator/templates/libraries/retrofit2/play24/Play24CallAdapterFactory.mustache b/.generator/templates/libraries/retrofit2/play24/Play24CallAdapterFactory.mustache new file mode 100644 index 00000000000..be7cac4a0d5 --- /dev/null +++ b/.generator/templates/libraries/retrofit2/play24/Play24CallAdapterFactory.mustache @@ -0,0 +1,100 @@ +package {{invokerPackage}}; + +import play.libs.F; +import retrofit2.*; + +import java.lang.annotation.Annotation; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.WildcardType; + +/** + * Creates {@link CallAdapter} instances that convert {@link Call} into {@link play.libs.F.Promise} + */ +public class Play24CallAdapterFactory extends CallAdapter.Factory { + + @Override + public CallAdapter get(Type returnType, Annotation[] annotations, Retrofit retrofit) { + if (!(returnType instanceof ParameterizedType)) { + return null; + } + + ParameterizedType type = (ParameterizedType) returnType; + if (type.getRawType() != F.Promise.class) { + return null; + } + + return createAdapter((ParameterizedType) returnType); + } + + private CallAdapter> createAdapter(ParameterizedType returnType) { + Type[] types = returnType.getActualTypeArguments(); + if (types.length != 1) { + throw new IllegalStateException("Must be exactly one type parameter"); + } + + Type resultType = types[0]; + Class rawTypeParam = getRawType(resultType); + + boolean includeResponse = false; + if (rawTypeParam == Response.class) { + if (!(resultType instanceof ParameterizedType)) { + throw new IllegalStateException("Response must be parameterized" + + " as Response"); + } + resultType = ((ParameterizedType) resultType).getActualTypeArguments()[0]; + includeResponse = true; + } + + return new ValueAdapter(resultType, includeResponse); + } + + /** + * Adapter that coverts values returned by API interface into CompletionStage + */ + private static final class ValueAdapter implements CallAdapter> { + + private final Type responseType; + private final boolean includeResponse; + + ValueAdapter(Type responseType, boolean includeResponse) { + this.responseType = responseType; + this.includeResponse = includeResponse; + } + + @Override + public Type responseType() { + return responseType; + } + + @Override + public F.Promise adapt(final Call call) { + final F.RedeemablePromise promise = F.RedeemablePromise.empty(); + + call.enqueue(new Callback() { + + @Override + public void onResponse(Call call, Response response) { + if (response.isSuccessful()) { + if (includeResponse) { + promise.success((R) response); + } else { + promise.success(response.body()); + } + } else { + promise.failure(new HttpException(response)); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + promise.failure(t); + } + + }); + + return promise; + } + } + +} diff --git a/.generator/templates/libraries/retrofit2/play24/Play24CallFactory.mustache b/.generator/templates/libraries/retrofit2/play24/Play24CallFactory.mustache new file mode 100644 index 00000000000..b17ac641564 --- /dev/null +++ b/.generator/templates/libraries/retrofit2/play24/Play24CallFactory.mustache @@ -0,0 +1,254 @@ +package {{invokerPackage}}; + +import okhttp3.*; +import okio.AsyncTimeout; +import okio.Buffer; +import okio.BufferedSource; +import okio.Timeout; +import play.libs.F; +import play.libs.ws.WSClient; +import play.libs.ws.WSRequest; +import play.libs.ws.WSResponse; +import play.libs.ws.WSCookie; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * Creates {@link Call} instances that invoke underlying {@link WSClient} + */ +public class Play24CallFactory implements okhttp3.Call.Factory { + + /** PlayWS http client */ + private final WSClient wsClient; + + /** Extra headers to add to request */ + private Map extraHeaders = new HashMap<>(); + + /** Extra cookies to add to request */ + private Map extraCookies = new HashMap<>(); + + /** Extra query parameters to add to request */ + private List extraQueryParams = new ArrayList<>(); + + public Play24CallFactory(WSClient wsClient) { + this.wsClient = wsClient; + } + + public Play24CallFactory(WSClient wsClient, Map extraHeaders, + Map extraCookies, + List extraQueryParams) { + this.wsClient = wsClient; + + this.extraHeaders.putAll(extraHeaders); + this.extraCookies.putAll(extraCookies); + this.extraQueryParams.addAll(extraQueryParams); + } + + @Override + public Call newCall(Request request) { + // add extra headers + Request.Builder rb = request.newBuilder(); + for (Map.Entry header : this.extraHeaders.entrySet()) { + rb.addHeader(header.getKey(), header.getValue()); + } + for (Map.Entry cookie : this.extraCookies.entrySet()) { + rb.addHeader("Cookie", String.format("%s=%s", cookie.getKey(), cookie.getValue())); + } + + // add extra query params + if (!this.extraQueryParams.isEmpty()) { + String newQuery = request.url().uri().getQuery(); + for (Pair queryParam : this.extraQueryParams) { + String param = String.format("%s=%s", queryParam.getName(), queryParam.getValue()); + if (newQuery == null) { + newQuery = param; + } else { + newQuery += "&" + param; + } + } + + URI newUri; + try { + newUri = new URI(request.url().uri().getScheme(), request.url().uri().getAuthority(), + request.url().uri().getPath(), newQuery, request.url().uri().getFragment()); + rb.url(newUri.toURL()); + } catch (MalformedURLException | URISyntaxException e) { + throw new RuntimeException("Error while updating an url", e); + } + } + + return new PlayWSCall(wsClient, rb.build()); + } + + /** + * Call implementation that delegates to Play WS Client + */ + static class PlayWSCall implements Call { + + private final WSClient wsClient; + private WSRequest wsRequest; + + private final Request request; + private final AsyncTimeout timeout; + + public PlayWSCall(WSClient wsClient, Request request) { + this.wsClient = wsClient; + this.request = request; + this.timeout = new AsyncTimeout(); + } + + @Override + public Request request() { + return request; + } + + @Override + public Timeout timeout() { + return timeout; + } + + @Override + public void enqueue(final okhttp3.Callback responseCallback) { + final Call call = this; + final F.Promise promise = executeAsync(); + + promise.onRedeem(new F.Callback() { + + @Override + public void invoke(WSResponse wsResponse) throws Throwable { + responseCallback.onResponse(call, PlayWSCall.this.toWSResponse(wsResponse)); + } + + }); + + promise.onFailure(new F.Callback() { + + @Override + public void invoke(Throwable throwable) throws Throwable { + if (throwable instanceof IOException) { + responseCallback.onFailure(call, (IOException) throwable); + } else { + responseCallback.onFailure(call, new IOException(throwable)); + } + } + + }); + + } + + F.Promise executeAsync() { + try { + wsRequest = wsClient.url(request.url().uri().toString()); + addHeaders(wsRequest); + addCookies(wsRequest); + if (request.body() != null) { + addBody(wsRequest); + } + + return wsRequest.execute(request.method()); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + private void addHeaders(WSRequest wsRequest) { + for(Map.Entry> entry : request.headers().toMultimap().entrySet()) { + List values = entry.getValue(); + for (String value : values) { + wsRequest.setHeader(entry.getKey(), value); + } + } + } + + private void addCookies(WSRequest wsRequest) { + final List cookies = request.headers("Cookie"); + if (!cookies.isEmpty()) { + String delimiter = ""; + final StringBuilder cookieHeader = new StringBuilder(); + for (final String cookie : cookies) { + cookieHeader.append(String.format("%s%s", delimiter, cookie)); + delimiter = "; "; + } + wsRequest.setHeader("Cookie", cookieHeader.toString()); + } + } + + private void addBody(WSRequest wsRequest) throws IOException { + Buffer buffer = new Buffer(); + request.body().writeTo(buffer); + wsRequest.setBody(buffer.inputStream()); + wsRequest.setContentType(request.body().contentType().toString()); + } + + private Response toWSResponse(final WSResponse r) { + final Response.Builder builder = new Response.Builder(); + builder.request(request) + .code(r.getStatus()) + .body(new ResponseBody() { + + @Override + public MediaType contentType() { + return Optional.ofNullable(r.getHeader("Content-Type")) + .map(MediaType::parse) + .orElse(null); + } + + @Override + public long contentLength() { + return r.asByteArray().length; + } + + @Override + public BufferedSource source() { + return new Buffer().write(r.asByteArray()); + } + + }); + + for (Map.Entry> entry : r.getAllHeaders().entrySet()) { + for (String value : entry.getValue()) { + builder.addHeader(entry.getKey(), value); + } + } + for (final WSCookie cookie : r.getCookies()) { + builder.addHeader("Cookie", String.format("%s=%s", cookie.getName(), cookie.getValue())); + } + + builder.protocol(Protocol.HTTP_1_1); + return builder.build(); + } + + @Override + public Response execute() throws IOException { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public void cancel() { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public PlayWSCall clone() { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public boolean isExecuted() { + return false; + } + + @Override + public boolean isCanceled() { + return false; + } + } +} diff --git a/.generator/templates/libraries/retrofit2/play24/api.mustache b/.generator/templates/libraries/retrofit2/play24/api.mustache new file mode 100644 index 00000000000..42cc9347d68 --- /dev/null +++ b/.generator/templates/libraries/retrofit2/play24/api.mustache @@ -0,0 +1,59 @@ +package {{package}}; + +import {{invokerPackage}}.CollectionFormats.*; + +{{#useRxJava}}import rx.Observable;{{/useRxJava}} +{{#useRxJava2}}import io.reactivex.Observable;{{/useRxJava2}} +{{#doNotUseRx}}import retrofit2.Call;{{/doNotUseRx}} +import retrofit2.http.*; + +import okhttp3.RequestBody; +import okhttp3.ResponseBody; +import okhttp3.MultipartBody; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +import play.libs.F; +import retrofit2.Response; + +{{#operations}} +public interface {{classname}} { + {{#operation}} + /** + * {{summary}} + * {{notes}} +{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} +{{/allParams}} + * @return Call<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + */ + {{#formParams}} + {{#-first}} + {{#isMultipart}}@retrofit2.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit2.http.FormUrlEncoded{{/isMultipart}} + {{/-first}} + {{/formParams}} + {{^formParams}} + {{#prioritizedContentTypes}} + {{#-first}} + @Headers({ + "Content-Type:{{{mediaType}}}" + }) + {{/-first}} + {{/prioritizedContentTypes}} + {{/formParams}} + @{{httpMethod}}("{{{path}}}") + F.Promise> {{operationId}}({{^allParams}});{{/allParams}} + {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{^-last}}, {{/-last}}{{#-last}} + );{{/-last}}{{/allParams}} + + {{/operation}} +} +{{/operations}} diff --git a/.generator/templates/libraries/retrofit2/play25/ApiClient.mustache b/.generator/templates/libraries/retrofit2/play25/ApiClient.mustache new file mode 100644 index 00000000000..849e0665e8c --- /dev/null +++ b/.generator/templates/libraries/retrofit2/play25/ApiClient.mustache @@ -0,0 +1,145 @@ +package {{invokerPackage}}; + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.*; + +import retrofit2.Retrofit; +import retrofit2.converter.scalars.ScalarsConverterFactory; +import retrofit2.converter.jackson.JacksonConverterFactory; +import com.fasterxml.jackson.databind.ObjectMapper; +{{#openApiNullable}} +import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} + +import play.libs.Json; +import play.libs.ws.WSClient; + +import {{invokerPackage}}.Play25CallAdapterFactory; +import {{invokerPackage}}.Play25CallFactory; + +import okhttp3.Interceptor; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.Authentication; + +/** + * API client + */ +public class ApiClient { + + /** Underlying HTTP-client */ + private WSClient wsClient; + + /** Supported auths */ + private Map authentications; + + /** API base path */ + private String basePath = "{{{basePath}}}"; + + public ApiClient(WSClient wsClient) { + this(); + this.wsClient = wsClient; + } + + public ApiClient() { + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap<>();{{#authMethods}}{{#isBasic}} + // authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"query"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + // authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + + } + + /** + * Creates a retrofit2 client for given API interface + */ + public S createService(Class serviceClass) { + if(!basePath.endsWith("/")) { + basePath = basePath + "/"; + } + + Map extraHeaders = new HashMap<>(); + Map extraCookies = new HashMap<>(); + List extraQueryParams = new ArrayList<>(); + + for (String authName : authentications.keySet()) { + Authentication auth = authentications.get(authName); + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + + auth.applyToParams(extraQueryParams, extraHeaders, extraCookies); + } + + ObjectMapper mapper = Json.mapper(); + {{#openApiNullable}} + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); + {{/openApiNullable}} + + return new Retrofit.Builder() + .baseUrl(basePath) + .addConverterFactory(ScalarsConverterFactory.create()) + .addConverterFactory(JacksonConverterFactory.create(mapper)) + .callFactory(new Play25CallFactory(wsClient, extraHeaders, extraCookies, extraQueryParams)) + .addCallAdapterFactory(new Play25CallAdapterFactory()) + .build() + .create(serviceClass); + } + + /** + * Helper method to set API base path + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get authentications (key: authentication name, value: authentication). + */ + 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); + } + + /** + * Helper method to set API key value for the first API key authentication. + */ + public ApiClient setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return this; + } + } + + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + */ + public ApiClient setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return this; + } + } + + throw new RuntimeException("No API key authentication configured!"); + } + + +} diff --git a/.generator/templates/libraries/retrofit2/play25/Play25CallAdapterFactory.mustache b/.generator/templates/libraries/retrofit2/play25/Play25CallAdapterFactory.mustache new file mode 100644 index 00000000000..088c10b160a --- /dev/null +++ b/.generator/templates/libraries/retrofit2/play25/Play25CallAdapterFactory.mustache @@ -0,0 +1,117 @@ +package {{invokerPackage}}; + +import java.util.concurrent.CompletionStage; +import retrofit2.*; + +import java.lang.annotation.Annotation; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.WildcardType; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.function.Function; + +/** + * Creates {@link CallAdapter} instances that convert {@link Call} into {@link java.util.concurrent.CompletionStage} + */ +public class Play25CallAdapterFactory extends CallAdapter.Factory { + + private Function exceptionConverter = Function.identity(); + + public Play25CallAdapterFactory() { + } + + public Play25CallAdapterFactory( + Function exceptionConverter) { + this.exceptionConverter = exceptionConverter; + } + + @Override + public CallAdapter get(Type returnType, Annotation[] annotations, Retrofit retrofit) { + if (!(returnType instanceof ParameterizedType)) { + return null; + } + + ParameterizedType type = (ParameterizedType) returnType; + if (type.getRawType() != CompletionStage.class) { + return null; + } + + return createAdapter((ParameterizedType) returnType); + } + + private CallAdapter> createAdapter(ParameterizedType returnType) { + // Get CompletionStage type argument + Type[] types = returnType.getActualTypeArguments(); + if (types.length != 1) { + throw new IllegalStateException("Must be exactly one type parameter"); + } + + Type resultType = types[0]; + Class rawTypeParam = getRawType(resultType); + + boolean includeResponse = false; + if (rawTypeParam == Response.class) { + if (!(resultType instanceof ParameterizedType)) { + throw new IllegalStateException("Response must be parameterized" + + " as Response"); + } + resultType = ((ParameterizedType) resultType).getActualTypeArguments()[0]; + includeResponse = true; + } + + return new ValueAdapter(resultType, includeResponse, exceptionConverter); + } + + /** + * Adapter that coverts values returned by API interface into CompletionStage + */ + private static final class ValueAdapter implements CallAdapter> { + + private final Type responseType; + private final boolean includeResponse; + private Function exceptionConverter; + + ValueAdapter(Type responseType, boolean includeResponse, + Function exceptionConverter) { + this.responseType = responseType; + this.includeResponse = includeResponse; + this.exceptionConverter = exceptionConverter; + } + + @Override + public Type responseType() { + return responseType; + } + + @Override + public CompletionStage adapt(final Call call) { + final CompletableFuture promise = new CompletableFuture(); + + call.enqueue(new Callback() { + + @Override + public void onResponse(Call call, Response response) { + if (response.isSuccessful()) { + if (includeResponse) { + promise.complete((R) response); + } else { + promise.complete(response.body()); + } + } else { + promise.completeExceptionally(exceptionConverter.apply(new HttpException(response))); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + promise.completeExceptionally(t); + } + + }); + + return promise; + } + } +} + diff --git a/.generator/templates/libraries/retrofit2/play25/Play25CallFactory.mustache b/.generator/templates/libraries/retrofit2/play25/Play25CallFactory.mustache new file mode 100644 index 00000000000..a9f19474f67 --- /dev/null +++ b/.generator/templates/libraries/retrofit2/play25/Play25CallFactory.mustache @@ -0,0 +1,264 @@ +package {{invokerPackage}}; + +import okhttp3.*; +import okio.AsyncTimeout; +import okio.Buffer; +import okio.BufferedSource; +import okio.Timeout; +import play.libs.ws.WSClient; +import play.libs.ws.WSRequest; +import play.libs.ws.WSResponse; +import play.libs.ws.WSRequestFilter; +import play.libs.ws.WSCookie; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.CompletionStage; + +/** + * Creates {@link Call} instances that invoke underlying {@link WSClient} + */ +public class Play25CallFactory implements okhttp3.Call.Factory { + + /** PlayWS http client */ + private final WSClient wsClient; + + /** Extra headers to add to request */ + private Map extraHeaders = new HashMap<>(); + + /** Extra cookies to add to request */ + private Map extraCookies = new HashMap<>(); + + /** Extra query parameters to add to request */ + private List extraQueryParams = new ArrayList<>(); + + /** Filters (interceptors) */ + private List filters = new ArrayList<>(); + + public Play25CallFactory(WSClient wsClient) { + this.wsClient = wsClient; + } + + public Play25CallFactory(WSClient wsClient, List filters) { + this.wsClient = wsClient; + this.filters.addAll(filters); + } + + public Play25CallFactory(WSClient wsClient, Map extraHeaders, + Map extraCookies, + List extraQueryParams) { + this.wsClient = wsClient; + + this.extraHeaders.putAll(extraHeaders); + this.extraCookies.putAll(extraCookies); + this.extraQueryParams.addAll(extraQueryParams); + } + + @Override + public Call newCall(Request request) { + // add extra headers + Request.Builder rb = request.newBuilder(); + for (Map.Entry header : this.extraHeaders.entrySet()) { + rb.addHeader(header.getKey(), header.getValue()); + } + for (Map.Entry cookie : this.extraCookies.entrySet()) { + rb.addHeader("Cookie", String.format("%s=%s", cookie.getKey(), cookie.getValue())); + } + + // add extra query params + if (!this.extraQueryParams.isEmpty()) { + String newQuery = request.url().uri().getQuery(); + for (Pair queryParam : this.extraQueryParams) { + String param = String.format("%s=%s", queryParam.getName(), queryParam.getValue()); + if (newQuery == null) { + newQuery = param; + } else { + newQuery += "&" + param; + } + } + + URI newUri; + try { + newUri = new URI(request.url().uri().getScheme(), request.url().uri().getAuthority(), + request.url().uri().getPath(), newQuery, request.url().uri().getFragment()); + rb.url(newUri.toURL()); + } catch (MalformedURLException | URISyntaxException e) { + throw new RuntimeException("Error while updating an url", e); + } + } + + return new PlayWSCall(wsClient, this.filters, rb.build()); + } + + /** + * Call implementation that delegates to Play WS Client + */ + static class PlayWSCall implements Call { + + private final WSClient wsClient; + private WSRequest wsRequest; + private List filters; + + private final Request request; + private final AsyncTimeout timeout; + + public PlayWSCall(WSClient wsClient, List filters, Request request) { + this.wsClient = wsClient; + this.request = request; + this.filters = filters; + this.timeout = new AsyncTimeout(); + } + + @Override + public Request request() { + return request; + } + + @Override + public Timeout timeout() { + return timeout; + } + + @Override + public void enqueue(final okhttp3.Callback responseCallback) { + final Call call = this; + final CompletionStage promise = executeAsync(); + + promise.whenCompleteAsync((v, t) -> { + if (t != null) { + if (t instanceof IOException) { + responseCallback.onFailure(call, (IOException) t); + } else { + responseCallback.onFailure(call, new IOException(t)); + } + } else { + try { + responseCallback.onResponse(call, PlayWSCall.this.toWSResponse(v)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }, play.libs.concurrent.HttpExecution.defaultContext()); + } + + CompletionStage executeAsync() { + try { + wsRequest = wsClient.url(request.url().uri().toString()); + addHeaders(wsRequest); + addCookies(wsRequest); + if (request.body() != null) { + addBody(wsRequest); + } + filters.stream().forEach(f -> wsRequest.withRequestFilter(f)); + + return wsRequest.execute(request.method()); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + private void addHeaders(WSRequest wsRequest) { + for(Map.Entry> entry : request.headers().toMultimap().entrySet()) { + List values = entry.getValue(); + for (String value : values) { + wsRequest.setHeader(entry.getKey(), value); + } + } + } + + private void addCookies(WSRequest wsRequest) { + final List cookies = request.headers("Cookie"); + if (!cookies.isEmpty()) { + String delimiter = ""; + final StringBuilder cookieHeader = new StringBuilder(); + for (final String cookie : cookies) { + cookieHeader.append(String.format("%s%s", delimiter, cookie)); + delimiter = "; "; + } + wsRequest.setHeader("Cookie", cookieHeader.toString()); + } + } + + private void addBody(WSRequest wsRequest) throws IOException { + Buffer buffer = new Buffer(); + request.body().writeTo(buffer); + wsRequest.setBody(buffer.inputStream()); + + MediaType mediaType = request.body().contentType(); + if (mediaType != null) { + wsRequest.setContentType(mediaType.toString()); + } + } + + private Response toWSResponse(final WSResponse r) { + final Response.Builder builder = new Response.Builder(); + builder.request(request) + .code(r.getStatus()) + .body(new ResponseBody() { + + @Override + public MediaType contentType() { + return Optional.ofNullable(r.getHeader("Content-Type")) + .map(MediaType::parse) + .orElse(null); + } + + @Override + public long contentLength() { + return r.asByteArray().length; + } + + @Override + public BufferedSource source() { + return new Buffer().write(r.asByteArray()); + } + + }); + + for (Map.Entry> entry : r.getAllHeaders().entrySet()) { + for (String value : entry.getValue()) { + builder.addHeader(entry.getKey(), value); + } + } + for (final WSCookie cookie : r.getCookies()) { + builder.addHeader("Cookie", String.format("%s=%s", cookie.getName(), cookie.getValue())); + } + + + builder.protocol(Protocol.HTTP_1_1); + return builder.build(); + } + + @Override + public Response execute() throws IOException { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public void cancel() { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public PlayWSCall clone() { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public boolean isExecuted() { + return false; + } + + @Override + public boolean isCanceled() { + return false; + } + } +} diff --git a/.generator/templates/libraries/retrofit2/play25/api.mustache b/.generator/templates/libraries/retrofit2/play25/api.mustache new file mode 100644 index 00000000000..8f9dc16cea1 --- /dev/null +++ b/.generator/templates/libraries/retrofit2/play25/api.mustache @@ -0,0 +1,59 @@ +package {{package}}; + +import {{invokerPackage}}.CollectionFormats.*; + +{{#useRxJava}}import rx.Observable;{{/useRxJava}} +{{#useRxJava2}}import io.reactivex.Observable;{{/useRxJava2}} +{{#doNotUseRx}}import retrofit2.Call;{{/doNotUseRx}} +import retrofit2.http.*; + +import okhttp3.RequestBody; +import okhttp3.ResponseBody; +import okhttp3.MultipartBody; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +import java.util.concurrent.*; +import retrofit2.Response; + +{{#operations}} +public interface {{classname}} { + {{#operation}} + /** + * {{summary}} + * {{notes}} +{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} +{{/allParams}} + * @return Call<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + */ + {{#formParams}} + {{#-first}} + {{#isMultipart}}@retrofit2.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit2.http.FormUrlEncoded{{/isMultipart}} + {{/-first}} + {{/formParams}} + {{^formParams}} + {{#prioritizedContentTypes}} + {{#-first}} + @Headers({ + "Content-Type:{{{mediaType}}}" + }) + {{/-first}} + {{/prioritizedContentTypes}} + {{/formParams}} + @{{httpMethod}}("{{{path}}}") + CompletionStage> {{operationId}}({{^allParams}});{{/allParams}} + {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{^-last}}, {{/-last}}{{#-last}} + );{{/-last}}{{/allParams}} + + {{/operation}} +} +{{/operations}} diff --git a/.generator/templates/libraries/retrofit2/play26/ApiClient.mustache b/.generator/templates/libraries/retrofit2/play26/ApiClient.mustache new file mode 100644 index 00000000000..b752b433d05 --- /dev/null +++ b/.generator/templates/libraries/retrofit2/play26/ApiClient.mustache @@ -0,0 +1,214 @@ +package {{invokerPackage}}; + +import java.io.File; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; + +import com.fasterxml.jackson.databind.ObjectMapper; +import retrofit2.Converter; +import retrofit2.Retrofit; +import retrofit2.converter.scalars.ScalarsConverterFactory; +import retrofit2.converter.jackson.JacksonConverterFactory; +{{#openApiNullable}} +import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} + +import play.libs.Json; +import play.libs.ws.WSClient; + +import {{invokerPackage}}.Play26CallAdapterFactory; +import {{invokerPackage}}.Play26CallFactory; + +import okhttp3.Interceptor; +import okhttp3.ResponseBody; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.Authentication; + +/** + * API client + */ +public class ApiClient { + + /** Underlying HTTP-client */ + private WSClient wsClient; + + /** Creates HTTP call instances */ + private Play26CallFactory callFactory; + + /** Create {@link java.util.concurrent.CompletionStage} instances from HTTP calls */ + private Play26CallAdapterFactory callAdapterFactory; + + /** Supported auths */ + private Map authentications; + + /** API base path */ + private String basePath = "{{{basePath}}}"; + + /** Default ObjectMapper */ + private ObjectMapper defaultMapper; + + public ApiClient(WSClient wsClient) { + this(); + this.wsClient = wsClient; + } + + public ApiClient() { + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap<>();{{#authMethods}}{{#isBasic}} + // authentications.put("{{name}}", new HttpBasicAuth());{{/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}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + } + + /** + * Creates a retrofit2 client for given API interface + */ + public S createService(Class serviceClass) { + if(!basePath.endsWith("/")) { + basePath = basePath + "/"; + } + + Map extraHeaders = new HashMap<>(); + Map extraCookies = new HashMap<>(); + List extraQueryParams = new ArrayList<>(); + + for (String authName : authentications.keySet()) { + Authentication auth = authentications.get(authName); + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + + auth.applyToParams(extraQueryParams, extraHeaders, extraCookies); + } + + if (callFactory == null) { + callFactory = new Play26CallFactory(wsClient, extraHeaders, extraCookies, extraQueryParams); + } + if (callAdapterFactory == null) { + callAdapterFactory = new Play26CallAdapterFactory(); + } + if (defaultMapper == null) { + defaultMapper = Json.mapper(); + {{#openApiNullable}} + JsonNullableModule jnm = new JsonNullableModule(); + defaultMapper.registerModule(jnm); + {{/openApiNullable}} + } + + return new Retrofit.Builder() + .baseUrl(basePath) + .addConverterFactory(new FileConverter()) + .addConverterFactory(ScalarsConverterFactory.create()) + .addConverterFactory(JacksonConverterFactory.create(defaultMapper)) + .callFactory(callFactory) + .addCallAdapterFactory(callAdapterFactory) + .build() + .create(serviceClass); + } + + /** + * Helper method to set API base path + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get authentications (key: authentication name, value: authentication). + */ + 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); + } + + /** + * Helper method to set API key value for the first API key authentication. + */ + public ApiClient setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return this; + } + } + + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + */ + public ApiClient setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return this; + } + } + + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set HTTP call instances factory + */ + public ApiClient setCallFactory(Play26CallFactory callFactory) { + this.callFactory = callFactory; + return this; + } + + /** + * Helper method to set {@link java.util.concurrent.CompletionStage} instances factory + */ + public ApiClient setCallAdapterFactory(Play26CallAdapterFactory callAdapterFactory) { + this.callAdapterFactory = callAdapterFactory; + return this; + } + + /** + * Helper method to set Jackson's {@link ObjectMapper} + */ + public ApiClient setObjectMapper(ObjectMapper mapper) { + this.defaultMapper = mapper; + return this; + } + + static class FileConverter extends Converter.Factory { + + @Override + public Converter responseBodyConverter(Type type, + Annotation[] annotations, Retrofit retrofit) { + + if (!File.class.getTypeName().equals(type.getTypeName())) { + return null; + } + + return new Converter() { + + @Override + public File convert(ResponseBody value) throws IOException { + + Path path = Files.createTempFile("retrofit-file", ".tmp"); + Files.write(path, value.bytes()); + return path.toFile(); + } + }; + } + } + +} diff --git a/.generator/templates/libraries/retrofit2/play26/Play26CallAdapterFactory.mustache b/.generator/templates/libraries/retrofit2/play26/Play26CallAdapterFactory.mustache new file mode 100644 index 00000000000..efbc0ac298b --- /dev/null +++ b/.generator/templates/libraries/retrofit2/play26/Play26CallAdapterFactory.mustache @@ -0,0 +1,116 @@ +package {{invokerPackage}}; + +import java.util.concurrent.CompletionStage; +import retrofit2.*; + +import java.lang.annotation.Annotation; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.WildcardType; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.function.Function; + +/** + * Creates {@link CallAdapter} instances that convert {@link Call} into {@link java.util.concurrent.CompletionStage} + */ +public class Play26CallAdapterFactory extends CallAdapter.Factory { + + private Function exceptionConverter = Function.identity(); + + public Play26CallAdapterFactory() { + } + + public Play26CallAdapterFactory( + Function exceptionConverter) { + this.exceptionConverter = exceptionConverter; + } + + @Override + public CallAdapter get(Type returnType, Annotation[] annotations, Retrofit retrofit) { + if (!(returnType instanceof ParameterizedType)) { + return null; + } + + ParameterizedType type = (ParameterizedType) returnType; + if (type.getRawType() != CompletionStage.class) { + return null; + } + + return createAdapter((ParameterizedType) returnType); + } + + private CallAdapter> createAdapter(ParameterizedType returnType) { + // Get CompletionStage type argument + Type[] types = returnType.getActualTypeArguments(); + if (types.length != 1) { + throw new IllegalStateException("Must be exactly one type parameter"); + } + + Type resultType = types[0]; + Class rawTypeParam = getRawType(resultType); + + boolean includeResponse = false; + if (rawTypeParam == Response.class) { + if (!(resultType instanceof ParameterizedType)) { + throw new IllegalStateException("Response must be parameterized" + + " as Response"); + } + resultType = ((ParameterizedType) resultType).getActualTypeArguments()[0]; + includeResponse = true; + } + + return new ValueAdapter(resultType, includeResponse, exceptionConverter); + } + + /** + * Adpater that coverts values returned by API interface into CompletionStage + */ + private static final class ValueAdapter implements CallAdapter> { + + private final Type responseType; + private final boolean includeResponse; + private Function exceptionConverter; + + ValueAdapter(Type responseType, boolean includeResponse, + Function exceptionConverter) { + this.responseType = responseType; + this.includeResponse = includeResponse; + this.exceptionConverter = exceptionConverter; + } + + @Override + public Type responseType() { + return responseType; + } + + @Override + public CompletionStage adapt(final Call call) { + final CompletableFuture promise = new CompletableFuture(); + + call.enqueue(new Callback() { + + @Override + public void onResponse(Call call, Response response) { + if (response.isSuccessful()) { + if (includeResponse) { + promise.complete((R) response); + } else { + promise.complete(response.body()); + } + } else { + promise.completeExceptionally(exceptionConverter.apply(new HttpException(response))); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + promise.completeExceptionally(t); + } + + }); + + return promise; + } + } +} diff --git a/.generator/templates/libraries/retrofit2/play26/Play26CallFactory.mustache b/.generator/templates/libraries/retrofit2/play26/Play26CallFactory.mustache new file mode 100644 index 00000000000..f65c921a752 --- /dev/null +++ b/.generator/templates/libraries/retrofit2/play26/Play26CallFactory.mustache @@ -0,0 +1,294 @@ +package {{invokerPackage}}; + +import okhttp3.*; +import okio.AsyncTimeout; +import okio.Buffer; +import okio.BufferedSource; +import okio.Timeout; +import play.libs.ws.WSClient; +import play.libs.ws.WSRequest; +import play.libs.ws.WSResponse; +import play.libs.ws.WSRequestFilter; +import play.libs.ws.WSCookie; +import play.libs.ws.WSCookieBuilder; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.Executor; + +/** + * Creates {@link Call} instances that invoke underlying {@link WSClient} + */ +public class Play26CallFactory implements okhttp3.Call.Factory { + + /** PlayWS http client */ + private final WSClient wsClient; + + /** Extra headers to add to request */ + private Map extraHeaders = new HashMap<>(); + + /** Extra cookies to add to request */ + private Map extraCookies = new HashMap<>(); + + /** Extra query parameters to add to request */ + private List extraQueryParams = new ArrayList<>(); + + /** Filters (interceptors) */ + private List filters = new ArrayList<>(); + + /** Executor for WSClient */ + private Executor executor; + + public Play26CallFactory(WSClient wsClient) { + this.wsClient = wsClient; + } + + public Play26CallFactory(WSClient wsClient, List filters) { + this.wsClient = wsClient; + this.filters.addAll(filters); + } + + public Play26CallFactory(WSClient wsClient, Map extraHeaders, + Map extraCookies, + List extraQueryParams) { + this.wsClient = wsClient; + + this.extraHeaders.putAll(extraHeaders); + this.extraCookies.putAll(extraCookies); + this.extraQueryParams.addAll(extraQueryParams); + } + + public Play26CallFactory withExecutor(Executor executor) { + this.executor = executor; + return this; + } + + @Override + public Call newCall(Request request) { + // add extra headers + Request.Builder rb = request.newBuilder(); + for (Map.Entry header : this.extraHeaders.entrySet()) { + rb.addHeader(header.getKey(), header.getValue()); + } + for (Map.Entry cookie : this.extraCookies.entrySet()) { + rb.addHeader("Cookie", String.format("%s=%s", cookie.getKey(), cookie.getValue())); + } + + // add extra query params + if (!this.extraQueryParams.isEmpty()) { + String newQuery = request.url().uri().getQuery(); + for (Pair queryParam : this.extraQueryParams) { + String param = String.format("%s=%s", queryParam.getName(), queryParam.getValue()); + if (newQuery == null) { + newQuery = param; + } else { + newQuery += "&" + param; + } + } + + URI newUri; + try { + newUri = new URI(request.url().uri().getScheme(), request.url().uri().getAuthority(), + request.url().uri().getPath(), newQuery, request.url().uri().getFragment()); + rb.url(newUri.toURL()); + } catch (MalformedURLException | URISyntaxException e) { + throw new RuntimeException("Error while updating an url", e); + } + } + + return new PlayWSCall(wsClient, this.executor, this.filters, rb.build()); + } + + /** + * Call implementation that delegates to Play WS Client + */ + static class PlayWSCall implements Call { + + private final WSClient wsClient; + private WSRequest wsRequest; + private List filters; + private Executor executor = java.util.concurrent.ForkJoinPool.commonPool(); + + private final Request request; + private final AsyncTimeout timeout; + + public PlayWSCall(WSClient wsClient, Executor executor, List filters, Request request) { + this.wsClient = wsClient; + this.request = request; + this.filters = filters; + this.timeout = new AsyncTimeout(); + + if (executor != null) { + this.executor = executor; + } + } + + @Override + public Request request() { + return request; + } + + @Override + public Timeout timeout() { + return timeout; + } + + @Override + public void enqueue(final okhttp3.Callback responseCallback) { + final Call call = this; + final CompletionStage promise = executeAsync(); + + promise.whenCompleteAsync((v, t) -> { + if (t != null) { + if (t instanceof IOException) { + responseCallback.onFailure(call, (IOException) t); + } else { + responseCallback.onFailure(call, new IOException(t)); + } + } else { + try { + responseCallback.onResponse(call, PlayWSCall.this.toWSResponse(v)); + } catch (Exception e) { + responseCallback.onFailure(call, new IOException(e)); + } + } + }, this.executor); + } + + CompletionStage executeAsync() { + try { + HttpUrl url = request.url(); + wsRequest = wsClient.url(url.scheme()+ "://" + url.host() + ":" + url.port() + url.encodedPath()); + url.queryParameterNames().forEach(queryParam -> { + wsRequest.addQueryParameter(queryParam, url.queryParameter(queryParam)); + }); + addHeaders(wsRequest); + addCookies(wsRequest); + if (request.body() != null) { + addBody(wsRequest); + } + filters.stream().forEach(f -> wsRequest.setRequestFilter(f)); + + return wsRequest.execute(request.method()); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + private void addHeaders(WSRequest wsRequest) { + for(Map.Entry> entry : request.headers().toMultimap().entrySet()) { + List values = entry.getValue(); + for (String value : values) { + wsRequest.setHeader(entry.getKey(), value); + } + } + } + + private void addCookies(WSRequest wsRequest) { + for (final WSCookie cookie : getCookies()) { + wsRequest.addCookie(cookie); + } + } + + List getCookies() { + final List cookies = new ArrayList<>(); + for (final String cookieString : request.headers("Cookie")) { + for (String cookie : cookieString.split(";")) { + cookie = cookie.trim(); + final String[] nameAndValue = cookie.split("="); + if (nameAndValue.length != 2) { + continue; + } + cookies.add( + new WSCookieBuilder() + .setName(nameAndValue[0]) + .setValue(nameAndValue[1]) + .build() + ); + } + } + return cookies; + } + + private void addBody(WSRequest wsRequest) throws IOException { + MediaType mediaType = request.body().contentType(); + if (mediaType != null) { + wsRequest.setContentType(mediaType.toString()); + } + + Buffer buffer = new Buffer(); + request.body().writeTo(buffer); + wsRequest.setBody(buffer.inputStream()); + } + + private Response toWSResponse(final WSResponse r) { + final Response.Builder builder = new Response.Builder(); + builder.request(request) + .code(r.getStatus()) + .body(new ResponseBody() { + + @Override + public MediaType contentType() { + return r.getSingleHeader("Content-Type") + .map(MediaType::parse) + .orElse(null); + } + + @Override + public long contentLength() { + return r.asByteArray().length; + } + + @Override + public BufferedSource source() { + return new Buffer().write(r.asByteArray()); + } + }); + + for (Map.Entry> entry : r.getAllHeaders().entrySet()) { + for (String value : entry.getValue()) { + builder.addHeader(entry.getKey(), value); + } + } + for (final WSCookie cookie : r.getCookies()) { + builder.addHeader("Cookie", String.format("%s=%s", cookie.getName(), cookie.getValue())); + } + + builder.message(r.getStatusText()); + builder.protocol(Protocol.HTTP_1_1); + return builder.build(); + } + + @Override + public Response execute() throws IOException { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public void cancel() { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public PlayWSCall clone() { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public boolean isExecuted() { + return false; + } + + @Override + public boolean isCanceled() { + return false; + } + } +} diff --git a/.generator/templates/libraries/retrofit2/play26/api.mustache b/.generator/templates/libraries/retrofit2/play26/api.mustache new file mode 100644 index 00000000000..8f9dc16cea1 --- /dev/null +++ b/.generator/templates/libraries/retrofit2/play26/api.mustache @@ -0,0 +1,59 @@ +package {{package}}; + +import {{invokerPackage}}.CollectionFormats.*; + +{{#useRxJava}}import rx.Observable;{{/useRxJava}} +{{#useRxJava2}}import io.reactivex.Observable;{{/useRxJava2}} +{{#doNotUseRx}}import retrofit2.Call;{{/doNotUseRx}} +import retrofit2.http.*; + +import okhttp3.RequestBody; +import okhttp3.ResponseBody; +import okhttp3.MultipartBody; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +import java.util.concurrent.*; +import retrofit2.Response; + +{{#operations}} +public interface {{classname}} { + {{#operation}} + /** + * {{summary}} + * {{notes}} +{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} +{{/allParams}} + * @return Call<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + */ + {{#formParams}} + {{#-first}} + {{#isMultipart}}@retrofit2.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit2.http.FormUrlEncoded{{/isMultipart}} + {{/-first}} + {{/formParams}} + {{^formParams}} + {{#prioritizedContentTypes}} + {{#-first}} + @Headers({ + "Content-Type:{{{mediaType}}}" + }) + {{/-first}} + {{/prioritizedContentTypes}} + {{/formParams}} + @{{httpMethod}}("{{{path}}}") + CompletionStage> {{operationId}}({{^allParams}});{{/allParams}} + {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{^-last}}, {{/-last}}{{#-last}} + );{{/-last}}{{/allParams}} + + {{/operation}} +} +{{/operations}} diff --git a/.generator/templates/libraries/retrofit2/pom.mustache b/.generator/templates/libraries/retrofit2/pom.mustache new file mode 100644 index 00000000000..b8b3d5dcb28 --- /dev/null +++ b/.generator/templates/libraries/retrofit2/pom.mustache @@ -0,0 +1,446 @@ + + 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-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + {{#java8}} + 1.8 + 1.8 + {{/java8}} + {{^java8}} + 1.7 + 1.7 + {{/java8}} + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.1 + + none + {{#java8}} + 1.8 + {{/java8}} + {{^java8}} + 1.7 + {{/java8}} + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + com.squareup.retrofit2 + converter-gson + ${retrofit-version} + + + com.squareup.retrofit2 + retrofit + ${retrofit-version} + + + com.squareup.retrofit2 + converter-scalars + ${retrofit-version} + + + org.apache.oltu.oauth2 + org.apache.oltu.oauth2.client + ${oltu-version} + + + org.apache.oltu.oauth2 + common + + + + + io.gsonfire + gson-fire + ${gson-fire-version} + + {{#joda}} + + joda-time + joda-time + ${jodatime-version} + + {{/joda}} + {{#threetenbp}} + + org.threeten + threetenbp + ${threetenbp-version} + + {{/threetenbp}} + {{#useRxJava}} + + io.reactivex + rxjava + ${rxjava-version} + + + com.squareup.retrofit2 + adapter-rxjava + ${retrofit-version} + + {{/useRxJava}} + {{#useRxJava2}} + + io.reactivex.rxjava2 + rxjava + ${rxjava-version} + + + com.squareup.retrofit2 + adapter-rxjava2 + ${retrofit-version} + + {{/useRxJava2}} + {{#useRxJava3}} + + io.reactivex.rxjava3 + rxjava + ${rxjava-version} + + + com.github.akarnokd + rxjava3-retrofit-adapter + 3.0.0 + + {{/useRxJava3}} + {{#usePlayWS}} + + + com.squareup.retrofit2 + converter-jackson + ${retrofit-version} + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + {{#openApiNullable}} + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + + {{/openApiNullable}} + + com.fasterxml.jackson.datatype + jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}} + ${jackson-version} + + {{#withXml}} + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson-version} + + {{/withXml}} + {{#play24}} + + com.typesafe.play + play-java-ws_2.11 + ${play-version} + + {{/play24}} + {{#play25}} + + com.typesafe.play + play-java-ws_2.11 + ${play-version} + + {{/play25}} + {{#play26}} + + com.typesafe.play + play-ahc-ws_2.12 + ${play-version} + + + javax.validation + validation-api + 1.1.0.Final + + {{/play26}} + {{/usePlayWS}} + {{#parcelableModel}} + + + com.google.android + android + 4.1.1.4 + provided + + {{/parcelableModel}} + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + + + + junit + junit + ${junit-version} + test + + + + UTF-8 + {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}} + ${java.version} + ${java.version} + 1.8.3 + 1.5.22 + {{#usePlayWS}} + 2.12.1 + {{#play24}} + 2.4.11 + {{/play24}} + {{#play25}} + 2.5.15 + {{/play25}} + {{#play26}} + 2.6.7 + {{/play26}} + {{#openApiNullable}} + 0.2.1 + {{/openApiNullable}} + {{/usePlayWS}} + 2.5.0 + {{#useRxJava}} + 1.3.0 + {{/useRxJava}} + {{#useRxJava2}} + 2.1.1 + {{/useRxJava2}} + {{#useRxJava3}} + 3.0.4 + {{/useRxJava3}} + {{#joda}} + 2.9.9 + {{/joda}} + {{#threetenbp}} + 1.4.0 + {{/threetenbp}} + 1.3.2 + 1.0.1 + 4.13.1 + + diff --git a/.generator/templates/libraries/retrofit2/queryParams.mustache b/.generator/templates/libraries/retrofit2/queryParams.mustache new file mode 100644 index 00000000000..abb87510ecf --- /dev/null +++ b/.generator/templates/libraries/retrofit2/queryParams.mustache @@ -0,0 +1 @@ +{{#isQueryParam}}@retrofit2.http.Query("{{baseName}}") {{#collectionFormat}}{{#isCollectionFormatMulti}}{{{dataType}}}{{/isCollectionFormatMulti}}{{^isCollectionFormatMulti}}{{{collectionFormat.toUpperCase}}}Params{{/isCollectionFormatMulti}}{{/collectionFormat}}{{^collectionFormat}}{{{dataType}}}{{/collectionFormat}} {{paramName}}{{/isQueryParam}} \ No newline at end of file diff --git a/.generator/templates/libraries/vertx/ApiClient.mustache b/.generator/templates/libraries/vertx/ApiClient.mustache new file mode 100644 index 00000000000..95951e3c06a --- /dev/null +++ b/.generator/templates/libraries/vertx/ApiClient.mustache @@ -0,0 +1,739 @@ +package {{invokerPackage}}; + +import {{invokerPackage}}.auth.Authentication; +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.HttpBearerAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +{{#hasOAuthMethods}} +import {{invokerPackage}}.auth.OAuth; +{{/hasOAuthMethods}} + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{#openApiNullable}} +import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} +import io.vertx.core.*; +import io.vertx.core.buffer.Buffer; +import io.vertx.core.file.AsyncFile; +import io.vertx.core.file.FileSystem; +import io.vertx.core.file.OpenOptions; +import io.vertx.core.http.HttpHeaders; +import io.vertx.core.http.HttpMethod; +import io.vertx.core.json.DecodeException; +import io.vertx.core.json.Json; +import io.vertx.core.json.JsonObject; +import io.vertx.ext.web.client.HttpRequest; +import io.vertx.ext.web.client.HttpResponse; +import io.vertx.ext.web.client.WebClient; +import io.vertx.ext.web.client.WebClientOptions; + +{{#jsr310}} +{{#threetenbp}} +import org.threeten.bp.OffsetDateTime; +{{/threetenbp}} +{{^threetenbp}} +import java.time.OffsetDateTime; +{{/threetenbp}} +{{/jsr310}} +import java.text.DateFormat; +import java.util.*; +import java.util.function.Consumer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static java.util.stream.Collectors.toMap; + +{{>generatedAnnotation}} +public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { + + private static final Pattern CONTENT_DISPOSITION_PATTERN = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?"); + private static final OpenOptions FILE_DOWNLOAD_OPTIONS = new OpenOptions().setCreate(true).setTruncateExisting(true); + + private final Vertx vertx; + private final JsonObject config; + private final String identifier; + + private MultiMap defaultHeaders = MultiMap.caseInsensitiveMultiMap(); + private MultiMap defaultCookies = MultiMap.caseInsensitiveMultiMap(); + private Map authentications; + private String basePath = "{{{basePath}}}"; + private DateFormat dateFormat; + private ObjectMapper objectMapper; + private String downloadsDir = ""; + private int timeout = -1; + + public ApiClient(Vertx vertx, JsonObject config) { + Objects.requireNonNull(vertx, "Vertx must not be null"); + Objects.requireNonNull(config, "Config must not be null"); + + this.vertx = vertx; + + // Use RFC3339 format for date and datetime. + // See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14 + this.dateFormat = new RFC3339DateFormat(); + + // Use UTC as the default time zone. + this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + + // Build object mapper + this.objectMapper = new ObjectMapper(); + this.objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + this.objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + this.objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + this.objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + this.objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + this.objectMapper.registerModule(new JavaTimeModule()); + this.objectMapper.setDateFormat(dateFormat); + {{#openApiNullable}} + JsonNullableModule jnm = new JsonNullableModule(); + this.objectMapper.registerModule(jnm); + {{/openApiNullable}} + + // Setup authentications (key: authentication name, value: authentication). + this.authentications = new HashMap<>();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + this.authentications = Collections.unmodifiableMap(authentications); + + // Configurations + this.basePath = config.getString("basePath", this.basePath); + this.downloadsDir = config.getString("downloadsDir", this.downloadsDir); + this.config = config; + this.identifier = UUID.randomUUID().toString(); + this.timeout = config.getInteger("timeout", -1); + } + + public Vertx getVertx() { + return vertx; + } + + public ObjectMapper getObjectMapper() { + return objectMapper; + } + + public ApiClient setObjectMapper(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + return this; + } + + public synchronized WebClient getWebClient() { + String webClientIdentifier = "web-client-" + identifier; + WebClient webClient = this.vertx.getOrCreateContext().get(webClientIdentifier); + if (webClient == null) { + webClient = buildWebClient(vertx, config); + this.vertx.getOrCreateContext().put(webClientIdentifier, webClient); + } + return webClient; + } + + public String getBasePath() { + return basePath; + } + + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + public String getDownloadsDir() { + return downloadsDir; + } + + public ApiClient setDownloadsDir(String downloadsDir) { + this.downloadsDir = downloadsDir; + return this; + } + + public MultiMap getDefaultHeaders() { + return defaultHeaders; + } + + public ApiClient addDefaultHeader(String key, String value) { + defaultHeaders.add(key, value); + return this; + } + + public MultiMap getDefaultCookies() { + return defaultHeaders; + } + + public ApiClient addDefaultCookie(String key, String value) { + defaultCookies.add(key, value); + return this; + } + + /** + * Get authentications (key: authentication name, value: authentication). + * + * @return Map of authentication object + */ + 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); + } + + /** + * Helper method to set access token for the first Bearer authentication. + * @param bearerToken Bearer token + */ + public ApiClient setBearerToken(String bearerToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBearerAuth) { + ((HttpBearerAuth) auth).setBearerToken(bearerToken); + return this; + } + } + throw new RuntimeException("No Bearer authentication configured!"); + } + + /** + * Helper method to set username for the first HTTP basic authentication. + * + * @param username Username + */ + public ApiClient setUsername(String username) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setUsername(username); + return this; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set password for the first HTTP basic authentication. + * + * @param password Password + */ + public ApiClient setPassword(String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setPassword(password); + return this; + } + } + 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 ApiClient setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return this; + } + } + 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 ApiClient setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return this; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + {{#hasOAuthMethods}} + /** + * Helper method to set access token for the first OAuth2 authentication. + * + * @param accessToken Access token + */ + public ApiClient setAccessToken(String accessToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setAccessToken(accessToken); + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + {{/hasOAuthMethods}} + /** + * Format the given Date object into string. + * + * @param date Date + * @return Date in string format + */ + public String formatDate(Date date) { + return dateFormat.format(date); + } + + /** + * Format the given parameter object into string. + * + * @param param Object + * @return Object in string format + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date) { + return formatDate((Date) param); + } {{#jsr310}}else if (param instanceof OffsetDateTime) { + return formatOffsetDateTime((OffsetDateTime) param); + } {{/jsr310}}else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for (Object o : (Collection) param) { + if (b.length() > 0) { + b.append(','); + } + b.append(String.valueOf(o)); + } + return b.toString(); + } else { + return String.valueOf(param); + } + } + + /* + * Format to {@code Pair} objects. + * @param collectionFormat Collection format + * @param name Name + * @param value Value + * @return List of pairs + */ + public List parameterToPairs(String collectionFormat, String name, Object value) { + List params = new ArrayList(); + + // preconditions + if (name == null || name.isEmpty() || value == null) return params; + + Collection valueCollection; + if (value instanceof Collection) { + valueCollection = (Collection) value; + } else { + params.add(new Pair(name, parameterToString(value))); + return params; + } + + if (valueCollection.isEmpty()) { + return params; + } + + // get the collection format (default: csv) + String format = (collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat); + + // create the params based on the collection format + if ("multi".equals(format)) { + for (Object item : valueCollection) { + params.add(new Pair(name, parameterToString(item))); + } + return params; + } + + String delimiter = ","; + if ("csv".equals(format)) { + delimiter = ","; + } else if ("ssv".equals(format)) { + delimiter = " "; + } else if ("tsv".equals(format)) { + delimiter = "\t"; + } else if ("pipes".equals(format)) { + delimiter = "|"; + } + + StringBuilder sb = new StringBuilder(); + for (Object item : valueCollection) { + sb.append(delimiter); + sb.append(parameterToString(item)); + } + + params.add(new Pair(name, sb.substring(1))); + + return params; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * application/vnd.company+json + * + * @param mime MIME + * @return True if the MIME type is JSON + */ + private boolean isJsonMime(String mime) { + String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$"; + return mime != null && (mime.matches(jsonMime) || mime.equalsIgnoreCase("application/json-patch+json")); + } + + /** + * 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). + */ + protected 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, + * JSON will be used. + */ + protected String selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0) { + return "application/json"; + } + for (String contentType : contentTypes) { + if (isJsonMime(contentType)) { + return contentType; + } + } + return contentTypes[0]; + } + + public void sendBody(HttpRequest request, + Handler>> responseHandler, + Object body) { + if (body instanceof byte[]) { + Buffer buffer = Buffer.buffer((byte[]) body); + request.sendBuffer(buffer, responseHandler); + } else if (body instanceof AsyncFile) { + AsyncFile file = (AsyncFile) body; + request.sendStream(file, responseHandler); + } else { + try { + request.sendBuffer(Buffer.buffer(this.objectMapper.writeValueAsBytes(body)), responseHandler); + } catch (JsonProcessingException jsonProcessingException) { + responseHandler.handle(Future.failedFuture(jsonProcessingException)); + } + } + } + + /** + * Invoke API by sending HTTP request with the given options. + * + * @param Type + * @param path The sub-path of the HTTP URL + * @param method The request method, one of "GET", "POST", "PUT", "HEAD" and "DELETE" + * @param queryParams The query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param cookieParams The cookie parameters + * @param formParams The form parameters + * @param accepts The request's Accept headers + * @param contentTypes The request's Content-Type headers + * @param authNames The authentications to apply + * @param authInfo The call specific auth override + * @param returnType The return type into which to deserialize the response + * @param resultHandler The asynchronous response handler + */ + public void invokeAPI(String path, String method, List queryParams, Object body, MultiMap headerParams, + MultiMap cookieParams, Map formParams, String[] accepts, String[] contentTypes, String[] authNames, AuthInfo authInfo, + TypeReference returnType, Handler> resultHandler) { + + updateParamsForAuth(authNames, authInfo, queryParams, headerParams, cookieParams); + + if (accepts != null && accepts.length > 0) { + headerParams.add(HttpHeaders.ACCEPT, selectHeaderAccept(accepts)); + } + + if (contentTypes != null) { + headerParams.add(HttpHeaders.CONTENT_TYPE, selectHeaderContentType(contentTypes)); + } + + HttpMethod httpMethod = HttpMethod.valueOf(method); + HttpRequest request = getWebClient().requestAbs(httpMethod, basePath + path); + request.timeout(this.timeout); + + if (httpMethod == HttpMethod.PATCH) { + request.putHeader("X-HTTP-Method-Override", "PATCH"); + } + + queryParams.forEach(entry -> { + if (entry.getValue() != null) { + request.addQueryParam(entry.getName(), entry.getValue()); + } + }); + + headerParams.forEach(entry -> { + if (entry.getValue() != null) { + request.putHeader(entry.getKey(), entry.getValue()); + } + }); + + defaultHeaders.forEach(entry -> { + if (entry.getValue() != null) { + request.putHeader(entry.getKey(), entry.getValue()); + } + }); + + final MultiMap cookies = MultiMap.caseInsensitiveMultiMap().addAll(cookieParams).addAll(defaultCookies); + request.putHeader("Cookie", buildCookieHeader(cookies)); + + Handler>> responseHandler = buildResponseHandler(returnType, resultHandler); + if (body != null) { + sendBody(request, responseHandler, body); + } else if (formParams != null && !formParams.isEmpty()) { + Map formMap = formParams.entrySet().stream().collect(toMap(Map.Entry::getKey, entry -> parameterToString(entry.getValue()))); + MultiMap form = MultiMap.caseInsensitiveMultiMap().addAll(formMap); + request.sendForm(form, responseHandler); + } else { + request.send(responseHandler); + } + } + + private String buildCookieHeader(MultiMap cookies) { + final StringBuilder cookieValue = new StringBuilder(); + String delimiter = ""; + for (final Map.Entry entry : cookies.entries()) { + if (entry.getValue() != null) { + cookieValue.append(String.format("%s%s=%s", delimiter, entry.getKey(), entry.getValue())); + delimiter = "; "; + } + } + return cookieValue.toString(); + } + + /** + * Sanitize filename by removing path. + * e.g. ../../sun.gif becomes sun.gif + * + * @param filename The filename to be sanitized + * @return The sanitized filename + */ + protected String sanitizeFilename(String filename) { + return filename.replaceAll(".*[/\\\\]", ""); + } + + /** + * Create a filename from the given headers. + * When the headers have no "Content-Disposition" information, a random UUID name is generated. + * + * @param headers The HTTP response headers + * @return The filename + */ + protected String generateFilename(MultiMap headers) { + String filename = UUID.randomUUID().toString(); + String contentDisposition = headers.get("Content-Disposition"); + if (contentDisposition != null && !contentDisposition.isEmpty()) { + Matcher matcher = CONTENT_DISPOSITION_PATTERN.matcher(contentDisposition); + if (matcher.find()) { + filename = sanitizeFilename(matcher.group(1)); + } + } + return filename; + } + + /** + * File Download handling. + * + * @param response The HTTP response + * @param handler The response handler + */ + protected void handleFileDownload(HttpResponse response, Handler> handler) { + FileSystem fs = getVertx().fileSystem(); + + String filename = generateFilename(response.headers()); + Consumer fileHandler = directory -> { + fs.open(directory + filename, FILE_DOWNLOAD_OPTIONS, asyncFileResult -> { + if (asyncFileResult.succeeded()) { + AsyncFile asyncFile = asyncFileResult.result(); + asyncFile.write(response.bodyAsBuffer()); + //noinspection unchecked + handler.handle(Future.succeededFuture((T) asyncFile)); + } else { + handler.handle(ApiException.fail(asyncFileResult.cause())); + } + }); + }; + + String dir = getDownloadsDir(); + if (dir != null && !dir.isEmpty()) { + fs.mkdirs(dir, mkdirResult -> { + String sanitizedFolder = dir.endsWith("/") ? dir : dir + "/"; + fileHandler.accept(sanitizedFolder); + }); + } else { + fileHandler.accept(""); + } + } + + /** + * Build a response handler for the HttpResponse. + * + * @param returnType The return type + * @param handler The response handler + * @return The HTTP response handler + */ + protected Handler>> buildResponseHandler(TypeReference returnType, + Handler> handler) { + return response -> { + AsyncResult result; + if (response.succeeded()) { + HttpResponse httpResponse = response.result(); + if (httpResponse.statusCode() / 100 == 2) { + if (httpResponse.statusCode() == 204 || returnType == null) { + result = Future.succeededFuture(null); + } else { + T resultContent = null; + if ("byte[]".equals(returnType.getType().toString())) { + resultContent = (T) httpResponse.body().getBytes(); + result = Future.succeededFuture(resultContent); + } else if (AsyncFile.class.equals(returnType.getType())) { + handleFileDownload(httpResponse, handler); + return; + } else { + try { + resultContent = this.objectMapper.readValue(httpResponse.bodyAsString(), returnType); + result = Future.succeededFuture(resultContent); + } catch (Exception e) { + result = ApiException.fail(new DecodeException("Failed to decode:" + e.getMessage(), e)); + } + } + } + } else { + result = ApiException.fail(httpResponse.statusMessage(), httpResponse.statusCode(), httpResponse.headers(), httpResponse.bodyAsString()); + } + } else if (response.cause() instanceof ApiException) { + result = Future.failedFuture(response.cause()); + } else { + result = ApiException.fail(500, response.cause() != null ? response.cause().getMessage() : null); + } + handler.handle(result); + }; + } + + /** + * Build the WebClient used to make HTTP requests. + * + * @param vertx Vertx + * @return WebClient + */ + protected WebClient buildWebClient(Vertx vertx, JsonObject config) { + + if (!config.containsKey("userAgent")) { + config.put("userAgent", "{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + } + + return WebClient.create(vertx, new WebClientOptions(config)); + } + + + /** + * Update query and header parameters based on authentication settings. + * + * @param authNames The authentications to apply + */ + protected void updateParamsForAuth(String[] authNames, AuthInfo authInfo, List queryParams, MultiMap headerParams, MultiMap cookieParams) { + for (String authName : authNames) { + Authentication auth; + if (authInfo != null && authInfo.authentications.containsKey(authName)) { + auth = authInfo.authentications.get(authName); + } else { + auth = authentications.get(authName); + } + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + auth.applyToParams(queryParams, headerParams, cookieParams); + } + } + + public static class AuthInfo { + + private final Map authentications = new LinkedHashMap<>();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + + public void add{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(String username, String password) { + HttpBasicAuth auth = new HttpBasicAuth(); + auth.setUsername(username); + auth.setPassword(password); + authentications.put("{{name}}", auth); + }{{/isBasicBasic}}{{^isBasicBasic}} + + public void add{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(String bearerToken) { + HttpBearerAuth auth = new + HttpBearerAuth("{{scheme}}"); + auth.setBearerToken(bearerToken); + authentications.put("{{name}}", auth); + }{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + + public void add{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(String apikey, String apiKeyPrefix) { + ApiKeyAuth auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}},"{{keyParamName}}"); + auth.setApiKey(apikey); + auth.setApiKeyPrefix(apiKeyPrefix); + authentications.put("{{name}}", auth); + }{{/isApiKey}}{{#isOAuth}} + + public void add{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(String accessToken) { + OAuth auth = new OAuth(); + auth.setAccessToken(accessToken); + authentications.put("{{name}}", auth); + }{{/isOAuth}}{{/authMethods}}{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + + public static AuthInfo for{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}(String username, String password) { + AuthInfo authInfo = new AuthInfo(); + authInfo.add{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(username, password); + return authInfo; + }{{/isBasicBasic}}{{^isBasicBasic}} + + public static AuthInfo for{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(String bearerToken) { + AuthInfo authInfo = new AuthInfo(); + authInfo.add{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(bearerToken); + return authInfo; + }{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + + public static AuthInfo for{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(String apikey, String apiKeyPrefix) { + AuthInfo authInfo = new AuthInfo(); + authInfo.add{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(apikey, apiKeyPrefix); + return authInfo; + }{{/isApiKey}}{{#isOAuth}} + + public static AuthInfo for{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(String accessToken) { + AuthInfo authInfo = new AuthInfo(); + authInfo.add{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(accessToken); + return authInfo; + }{{/isOAuth}}{{/authMethods}} + } +} diff --git a/.generator/templates/libraries/vertx/Configuration.mustache b/.generator/templates/libraries/vertx/Configuration.mustache new file mode 100644 index 00000000000..17710ae1600 --- /dev/null +++ b/.generator/templates/libraries/vertx/Configuration.mustache @@ -0,0 +1,42 @@ +package {{invokerPackage}}; + +import io.vertx.core.Vertx; +import io.vertx.core.json.JsonObject; + +import java.util.Objects; + +public class Configuration { + + private static ApiClient defaultApiClient = null; + + /** + * Setup the default API client. + * Will be used by API instances when a client is not provided. + * + * @return Default API client + */ + public synchronized static ApiClient setupDefaultApiClient(Vertx vertx, JsonObject config) { + defaultApiClient = new ApiClient(vertx, config); + return defaultApiClient; + } + + /** + * Get the default API client, which would be used when creating API + * instances without providing an API client. + * + * @return Default API client + */ + public synchronized static ApiClient getDefaultApiClient() { + return defaultApiClient; + } + + /** + * Set the default API client, which would be used when creating API + * instances without providing an API client. + * + * @param apiClient API client + */ + public synchronized static void setDefaultApiClient(ApiClient apiClient) { + defaultApiClient = apiClient; + } +} diff --git a/.generator/templates/libraries/vertx/api.mustache b/.generator/templates/libraries/vertx/api.mustache new file mode 100644 index 00000000000..8cb5bd95373 --- /dev/null +++ b/.generator/templates/libraries/vertx/api.mustache @@ -0,0 +1,22 @@ +package {{package}}; + +import {{invokerPackage}}.ApiClient; +{{#imports}}import {{import}}; +{{/imports}} +import io.vertx.core.AsyncResult; +import io.vertx.core.Handler; +import io.vertx.core.json.JsonObject; + +import java.util.*; + +public interface {{classname}} { + + {{#operations}} + {{#operation}} + void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}Handler> handler); + + void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}ApiClient.AuthInfo authInfo, Handler> handler); + + {{/operation}} + {{/operations}} +} diff --git a/.generator/templates/libraries/vertx/apiException.mustache b/.generator/templates/libraries/vertx/apiException.mustache new file mode 100644 index 00000000000..6e9bbdbb88d --- /dev/null +++ b/.generator/templates/libraries/vertx/apiException.mustache @@ -0,0 +1,110 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import io.vertx.core.AsyncResult; +import io.vertx.core.Future; +import io.vertx.core.MultiMap; + +{{>generatedAnnotation}} +public class ApiException extends{{#useRuntimeException}} RuntimeException {{/useRuntimeException}}{{^useRuntimeException}} Exception {{/useRuntimeException}}{ + private int code = 0; + private MultiMap responseHeaders = null; + private String responseBody = null; + + + public static AsyncResult fail(int failureCode, String message) { + return Future.failedFuture(new ApiException(failureCode, message)); + } + + public static AsyncResult fail(Throwable throwable) { + return Future.failedFuture(new ApiException(throwable)); + } + + public static AsyncResult fail(String message) { + return Future.failedFuture(new ApiException(message)); + } + + public static AsyncResult fail(String message, Throwable throwable, int code, MultiMap responseHeaders) { + return Future.failedFuture(new ApiException(message, throwable, code, responseHeaders, null)); + } + + public static AsyncResult fail(String message, Throwable throwable, int code, MultiMap responseHeaders, String responseBody) { + return Future.failedFuture(new ApiException(message, throwable, code, responseHeaders, responseBody)); + } + + public static AsyncResult fail(String message, int code, MultiMap responseHeaders, String responseBody) { + return Future.failedFuture(new ApiException(message, (Throwable) null, code, responseHeaders, responseBody)); + } + + public static AsyncResult fail(int code, MultiMap responseHeaders, String responseBody) { + return Future.failedFuture(new ApiException((String) null, (Throwable) null, code, responseHeaders, responseBody)); + } + + public ApiException() {} + + public ApiException(Throwable throwable) { + super(throwable); + } + + public ApiException(String message) { + super(message); + } + + public ApiException(String message, Throwable throwable, int code, MultiMap responseHeaders, String responseBody) { + super(message, throwable); + this.code = code; + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + + public ApiException(String message, int code, MultiMap responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(String message, Throwable throwable, int code, MultiMap responseHeaders) { + this(message, throwable, code, responseHeaders, null); + } + + public ApiException(int code, MultiMap responseHeaders, String responseBody) { + this((String) null, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(int code, String message) { + super(message); + this.code = code; + } + + public ApiException(int code, String message, MultiMap responseHeaders, String responseBody) { + this(code, message); + this.responseHeaders = responseHeaders; + 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 MultiMap getResponseHeaders() { + return responseHeaders; + } + + /** + * Get the HTTP response body. + * + * @return Response body in the form of string + */ + public String getResponseBody() { + return responseBody; + } +} diff --git a/.generator/templates/libraries/vertx/apiImpl.mustache b/.generator/templates/libraries/vertx/apiImpl.mustache new file mode 100644 index 00000000000..e9e9a2fe7de --- /dev/null +++ b/.generator/templates/libraries/vertx/apiImpl.mustache @@ -0,0 +1,121 @@ +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} + +import io.vertx.core.AsyncResult; +import io.vertx.core.Handler; +import io.vertx.core.MultiMap; +import io.vertx.core.json.JsonObject; + +import com.fasterxml.jackson.core.type.TypeReference; + +import java.util.*; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.Configuration; +import {{invokerPackage}}.Pair; + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}}Impl implements {{classname}} { + + private ApiClient apiClient; + + public {{classname}}Impl() { + this(null); + } + + public {{classname}}Impl(ApiClient apiClient) { + this.apiClient = apiClient != null ? apiClient : Configuration.getDefaultApiClient(); + } + + public ApiClient getApiClient() { + return apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.apiClient = apiClient; + } + + {{#operation}} + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @param resultHandler Asynchronous result handler + */ + public void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}Handler> resultHandler) { + {{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}null, resultHandler); + } + + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @param authInfo per call authentication override. + * @param resultHandler Asynchronous result handler + */ + public void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}ApiClient.AuthInfo authInfo, Handler> resultHandler) { + Object localVarBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + resultHandler.handle(ApiException.fail(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}")); + return; + } + {{/required}}{{/allParams}} + // create path and map variables + String localVarPath = "{{{path}}}"{{#pathParams}}.replaceAll("\\{" + "{{baseName}}" + "\\}", encodeParameter({{{paramName}}}.toString())){{/pathParams}}; + + // query params + List localVarQueryParams = new ArrayList<>(); + {{#queryParams}} + localVarQueryParams.addAll(apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); + {{/queryParams}} + + // header params + MultiMap localVarHeaderParams = MultiMap.caseInsensitiveMultiMap(); + {{#headerParams}}if ({{paramName}} != null) + localVarHeaderParams.add("{{baseName}}", apiClient.parameterToString({{paramName}})); + {{/headerParams}} + + // cookie params + MultiMap localVarCookieParams = MultiMap.caseInsensitiveMultiMap(); + {{#cookieParams}}if ({{paramName}} != null) + localVarCookieParams.add("{{baseName}}", apiClient.parameterToString({{paramName}})); + {{/cookieParams}} + + // form params + // TODO: sending files within multipart/form-data is not supported yet (because of vertx web-client) + Map localVarFormParams = new HashMap<>(); + {{#formParams}}if ({{paramName}} != null) localVarFormParams.put("{{baseName}}", {{paramName}}); + {{/formParams}} + + String[] localVarAccepts = { {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} }; + String[] localVarContentTypes = { {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} }; + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; + {{#returnType}} + TypeReference<{{{returnType}}}> localVarReturnType = new TypeReference<{{{returnType}}}>() {}; + apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccepts, localVarContentTypes, localVarAuthNames, authInfo, localVarReturnType, resultHandler);{{/returnType}}{{^returnType}} + apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccepts, localVarContentTypes, localVarAuthNames, authInfo, null, resultHandler);{{/returnType}} + } + {{/operation}} + + private String encodeParameter(String parameter) { + try { + return URLEncoder.encode(parameter, StandardCharsets.UTF_8.name()); + } catch (UnsupportedEncodingException e) { + return parameter; + } + } +} +{{/operations}} diff --git a/.generator/templates/libraries/vertx/api_test.mustache b/.generator/templates/libraries/vertx/api_test.mustache new file mode 100644 index 00000000000..5eb2ec7276a --- /dev/null +++ b/.generator/templates/libraries/vertx/api_test.mustache @@ -0,0 +1,70 @@ +{{>licenseInfo}} +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} + +import {{invokerPackage}}.Configuration; + +import org.junit.Test; +import org.junit.Ignore; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.runner.RunWith; + +import io.vertx.core.AsyncResult; +import io.vertx.core.Handler; +import io.vertx.core.json.JsonObject; +import io.vertx.core.Vertx; +import io.vertx.ext.unit.junit.VertxUnitRunner; +import io.vertx.ext.unit.junit.RunTestOnContext; +import io.vertx.ext.unit.TestContext; +import io.vertx.ext.unit.Async; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +@RunWith(VertxUnitRunner.class) +@Ignore +public class {{classname}}Test { + + private {{classname}} api; + + @Rule + public RunTestOnContext rule = new RunTestOnContext(); + + @BeforeClass + public void setupApiClient() { + JsonObject config = new JsonObject(); + Vertx vertx = rule.vertx(); + Configuration.setupDefaultApiClient(vertx, config); + + api = new {{classname}}Impl(); + } + {{#operations}}{{#operation}} + /** + * {{summary}} + * {{notes}} + * + * @param context Vertx test context for doing assertions + */ + @Test + public void {{operationId}}Test(TestContext testContext) { + Async async = testContext.async(); + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + api.{{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}result -> { + // TODO: test validations + async.complete(); + }); + } + {{/operation}}{{/operations}} +} diff --git a/.generator/templates/libraries/vertx/auth/ApiKeyAuth.mustache b/.generator/templates/libraries/vertx/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..fadbd33e565 --- /dev/null +++ b/.generator/templates/libraries/vertx/auth/ApiKeyAuth.mustache @@ -0,0 +1,66 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import io.vertx.core.MultiMap; + +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, MultiMap headerParams, MultiMap cookieParams) { + 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.add(paramName, value); + } else if ("cookie".equals(location)) { + cookieParams.add(paramName, value); + } + } +} diff --git a/.generator/templates/libraries/vertx/auth/Authentication.mustache b/.generator/templates/libraries/vertx/auth/Authentication.mustache new file mode 100644 index 00000000000..9d546c30058 --- /dev/null +++ b/.generator/templates/libraries/vertx/auth/Authentication.mustache @@ -0,0 +1,19 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import io.vertx.core.MultiMap; + +import java.util.List; + +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 + */ + void applyToParams(List queryParams, MultiMap headerParams, MultiMap cookieParams); +} diff --git a/.generator/templates/libraries/vertx/auth/HttpBasicAuth.mustache b/.generator/templates/libraries/vertx/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..9bca5090a99 --- /dev/null +++ b/.generator/templates/libraries/vertx/auth/HttpBasicAuth.mustache @@ -0,0 +1,40 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import io.vertx.core.MultiMap; +import java.util.Base64; +import java.nio.charset.StandardCharsets; +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, MultiMap headerParams, MultiMap cookieParams) { + if (username == null && password == null) { + return; + } + String str = (username == null ? "" : username) + ":" + (password == null ? "" : password); + headerParams.add("Authorization", "Basic " + Base64.getEncoder().encodeToString(str.getBytes(StandardCharsets.UTF_8))); + } +} diff --git a/.generator/templates/libraries/vertx/auth/HttpBearerAuth.mustache b/.generator/templates/libraries/vertx/auth/HttpBearerAuth.mustache new file mode 100644 index 00000000000..208eedb7122 --- /dev/null +++ b/.generator/templates/libraries/vertx/auth/HttpBearerAuth.mustache @@ -0,0 +1,39 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import io.vertx.core.MultiMap; +import java.util.Base64; +import java.nio.charset.StandardCharsets; +import java.util.List; + +{{>generatedAnnotation}} +public class HttpBearerAuth implements Authentication { + private final String scheme; + private String bearerToken; + + public HttpBearerAuth(String scheme) { + this.scheme = scheme; + } + + public String getBearerToken() { + return bearerToken; + } + + public void setBearerToken(String bearerToken) { + this.bearerToken = bearerToken; + } + + @Override + public void applyToParams(List queryParams, MultiMap headerParams, MultiMap cookieParams) { + if (bearerToken == null) { + return; + } + headerParams.add("Authorization", (scheme != null ? upperCaseBearer(scheme) + " " : "") + bearerToken); + } + + private static String upperCaseBearer(String scheme) { + return ("bearer".equalsIgnoreCase(scheme)) ? "Bearer" : scheme; + } +} diff --git a/.generator/templates/libraries/vertx/auth/OAuth.mustache b/.generator/templates/libraries/vertx/auth/OAuth.mustache new file mode 100644 index 00000000000..5bebabf90a7 --- /dev/null +++ b/.generator/templates/libraries/vertx/auth/OAuth.mustache @@ -0,0 +1,28 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import io.vertx.core.MultiMap; + +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, MultiMap headerParams, MultiMap cookieParams) { + if (accessToken != null) { + headerParams.add("Authorization", "Bearer " + accessToken); + } + } +} diff --git a/.generator/templates/libraries/vertx/auth/OAuthFlow.mustache b/.generator/templates/libraries/vertx/auth/OAuthFlow.mustache new file mode 100644 index 00000000000..002e9572f33 --- /dev/null +++ b/.generator/templates/libraries/vertx/auth/OAuthFlow.mustache @@ -0,0 +1,7 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +public enum OAuthFlow { + accessCode, implicit, password, application +} diff --git a/.generator/templates/libraries/vertx/build.gradle.mustache b/.generator/templates/libraries/vertx/build.gradle.mustache new file mode 100644 index 00000000000..143a1936217 --- /dev/null +++ b/.generator/templates/libraries/vertx/build.gradle.mustache @@ -0,0 +1,66 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +repositories { + maven { url "https://repo1.maven.org/maven2" } + jcenter() +} + +apply plugin: 'java' +apply plugin: 'maven' + +sourceCompatibility = JavaVersion.VERSION_1_8 +targetCompatibility = JavaVersion.VERSION_1_8 + +install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } +} + +task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath +} + +ext { + swagger_annotations_version = "1.5.21" + jackson_version = "2.10.5" + jackson_databind_version = "2.10.5.1" + vertx_version = "3.4.2" + junit_version = "4.13.1" + {{#openApiNullable}} + jackson_databind_nullable_version = "0.2.1" + {{/openApiNullable}} + {{#threetenbp}} + jackson_threeten_version = "2.9.10" + {{/threetenbp}} +} + +dependencies { + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "io.vertx:vertx-web-client:$vertx_version" + implementation "io.vertx:vertx-rx-java:$vertx_version" + 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_databind_version" + {{#joda}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + {{/joda}} + {{#java8}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{/java8}} + {{#threetenbp}} + implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:jackson_threeten_version" + {{/threetenbp}} + {{#openApiNullable}} + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} + implementation 'javax.annotation:javax.annotation-api:1.3.2' + testImplementation "junit:junit:$junit_version" + testImplementation "io.vertx:vertx-unit:$vertx_version" +} diff --git a/.generator/templates/libraries/vertx/pom.mustache b/.generator/templates/libraries/vertx/pom.mustache new file mode 100644 index 00000000000..cbd5d580b12 --- /dev/null +++ b/.generator/templates/libraries/vertx/pom.mustache @@ -0,0 +1,315 @@ + + 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-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.6 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.0.0 + + + add_sources + generate-sources + + add-source + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.1 + + none + {{#java8}} + 1.8 + {{/java8}} + {{^java8}} + 1.7 + {{/java8}} + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + + + io.vertx + vertx-rx-java + ${vertx-version} + + + io.vertx + vertx-web-client + ${vertx-version} + + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-databind} + + {{#openApiNullable}} + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + + {{/openApiNullable}} + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + {{/joda}} + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{/java8}} + {{#threetenbp}} + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-version} + + {{/threetenbp}} + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + + + + + junit + junit + ${junit-version} + test + + + io.vertx + vertx-unit + ${vertx-version} + test + + + + + UTF-8 + 3.4.2 + 1.5.22 + 2.10.5 + 2.10.5.1 + 0.2.1 + 1.3.2 + 4.13.1 + + diff --git a/.generator/templates/libraries/vertx/rxApiImpl.mustache b/.generator/templates/libraries/vertx/rxApiImpl.mustache new file mode 100644 index 00000000000..f1f5d0323f5 --- /dev/null +++ b/.generator/templates/libraries/vertx/rxApiImpl.mustache @@ -0,0 +1,87 @@ +package {{package}}.rxjava; + +{{#imports}}import {{import}}; +{{/imports}} +import {{invokerPackage}}.ApiClient; + +import java.util.*; + +import rx.Single; +import io.vertx.core.AsyncResult; +import io.vertx.core.Handler; + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}} { + + private final {{package}}.{{classname}} delegate; + + public {{classname}}({{package}}.{{classname}} delegate) { + this.delegate = delegate; + } + + public {{package}}.{{classname}} getDelegate() { + return delegate; + } + + {{#operation}} + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @param resultHandler Asynchronous result handler + */ + public void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}Handler> resultHandler) { + delegate.{{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}resultHandler); + } + + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @param authInfo call specific auth overrides + * @param resultHandler Asynchronous result handler + */ + public void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}ApiClient.AuthInfo authInfo, Handler> resultHandler) { + delegate.{{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}authInfo, resultHandler); + } + + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @return Asynchronous result handler (RxJava Single) + */ + public Single<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> rx{{operationIdCamelCase}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) { + return Single.create(new io.vertx.rx.java.SingleOnSubscribeAdapter<>(fut -> + delegate.{{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}fut) + )); + } + + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @param authInfo call specific auth overrides + * @return Asynchronous result handler (RxJava Single) + */ + public Single<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> rx{{operationIdCamelCase}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}ApiClient.AuthInfo authInfo) { + return Single.create(new io.vertx.rx.java.SingleOnSubscribeAdapter<>(fut -> + delegate.{{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}authInfo, fut) + )); + } + {{/operation}} + + public static {{classname}} newInstance({{package}}.{{classname}} arg) { + return arg != null ? new {{classname}}(arg) : null; + } +} +{{/operations}} diff --git a/.generator/templates/libraries/webclient/ApiClient.mustache b/.generator/templates/libraries/webclient/ApiClient.mustache new file mode 100644 index 00000000000..0fe89ccb026 --- /dev/null +++ b/.generator/templates/libraries/webclient/ApiClient.mustache @@ -0,0 +1,664 @@ +package {{invokerPackage}}; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{#openApiNullable}} +import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpRequest; +import org.springframework.http.HttpStatus; +import org.springframework.http.InvalidMediaTypeException; +import org.springframework.http.MediaType; +import org.springframework.http.RequestEntity; +import org.springframework.http.RequestEntity.BodyBuilder; +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.BufferingClientHttpRequestFactory; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.http.codec.json.Jackson2JsonDecoder; +import org.springframework.http.codec.json.Jackson2JsonEncoder; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.util.StringUtils; +import org.springframework.http.client.reactive.ClientHttpRequest; +import org.springframework.web.client.RestClientException; +import org.springframework.web.util.UriComponentsBuilder; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.ClientResponse; +import org.springframework.web.reactive.function.BodyInserter; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.ExchangeStrategies; +import reactor.core.publisher.Mono; +import reactor.core.publisher.Flux; +import java.util.Optional; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.text.DateFormat; +import java.text.ParseException; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TimeZone; +{{#jsr310}} +{{#threetenbp}} +import org.threeten.bp.OffsetDateTime; +{{/threetenbp}} +{{^threetenbp}} +import java.time.OffsetDateTime; +{{/threetenbp}} +{{/jsr310}} + +import {{invokerPackage}}.auth.Authentication; +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.HttpBearerAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +{{#hasOAuthMethods}} +import {{invokerPackage}}.auth.OAuth; +{{/hasOAuthMethods}} + +{{>generatedAnnotation}} +public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { + public enum CollectionFormat { + CSV(","), TSV("\t"), SSV(" "), PIPES("|"), MULTI(null); + + private final String separator; + private CollectionFormat(String separator) { + this.separator = separator; + } + + private String collectionToString(Collection collection) { + return StringUtils.collectionToDelimitedString(collection, separator); + } + } + + private HttpHeaders defaultHeaders = new HttpHeaders(); + private MultiValueMap defaultCookies = new LinkedMultiValueMap(); + + private String basePath = "{{basePath}}"; + + private final WebClient webClient; + private final DateFormat dateFormat; + + private Map authentications; + + + public ApiClient() { + this.dateFormat = createDefaultDateFormat(); + ObjectMapper mapper = new ObjectMapper(); + mapper.setDateFormat(dateFormat); + mapper.registerModule(new JavaTimeModule()); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + {{#openApiNullable}} + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); + {{/openApiNullable}} + + this.webClient = buildWebClient(mapper); + this.init(); + } + + public ApiClient(ObjectMapper mapper, DateFormat format) { + this(buildWebClient(mapper.copy()), format); + } + + public ApiClient(WebClient webClient, ObjectMapper mapper, DateFormat format) { + this(Optional.ofNullable(webClient).orElseGet(() ->buildWebClient(mapper.copy())), format); + } + + private ApiClient(WebClient webClient, DateFormat format) { + this.webClient = webClient; + this.dateFormat = format; + this.init(); + } + + public DateFormat createDefaultDateFormat() { + DateFormat dateFormat = new RFC3339DateFormat(); + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + return dateFormat; + } + + protected void init() { + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + } + + /** + * Build the WebClient used to make HTTP requests. + * @return WebClient + */ + public static WebClient buildWebClient(ObjectMapper mapper) { + ExchangeStrategies strategies = ExchangeStrategies + .builder() + .codecs(clientDefaultCodecsConfigurer -> { + clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonEncoder(new Jackson2JsonEncoder(mapper, MediaType.APPLICATION_JSON)); + clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(mapper, MediaType.APPLICATION_JSON)); + }).build(); + WebClient.Builder webClient = WebClient.builder().exchangeStrategies(strategies); + return webClient.build(); + } + + + /** + * Get the current base path + * @return String the base path + */ + public String getBasePath() { + return basePath; + } + + /** + * Set the base path, which should include the host + * @param basePath the base path + * @return ApiClient this client + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get authentications (key: authentication name, value: authentication). + * @return Map the currently configured authentication types + */ + 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); + } + + /** + * Helper method to set access token for the first Bearer authentication. + * @param bearerToken Bearer token + */ + public void setBearerToken(String bearerToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBearerAuth) { + ((HttpBearerAuth) auth).setBearerToken(bearerToken); + return; + } + } + throw new RuntimeException("No Bearer authentication configured!"); + } + + /** + * Helper method to set username for the first HTTP basic authentication. + * @param username the 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 the 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 the 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 the 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!"); + } + + {{#hasOAuthMethods}} + /** + * Helper method to set access token for the first OAuth2 authentication. + * @param accessToken the access token + */ + public void setAccessToken(String accessToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setAccessToken(accessToken); + return; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + {{/hasOAuthMethods}} + /** + * Set the User-Agent header's value (by adding to the default header map). + * @param userAgent the user agent string + * @return ApiClient this client + */ + public ApiClient setUserAgent(String userAgent) { + addDefaultHeader("User-Agent", userAgent); + return this; + } + + /** + * Add a default header. + * + * @param name The header's name + * @param value The header's value + * @return ApiClient this client + */ + public ApiClient addDefaultHeader(String name, String value) { + if (defaultHeaders.containsKey(name)) { + defaultHeaders.remove(name); + } + defaultHeaders.add(name, value); + return this; + } + + /** + * Add a default cookie. + * + * @param name The cookie's name + * @param value The cookie's value + * @return ApiClient this client + */ + public ApiClient addDefaultCookie(String name, String value) { + if (defaultCookies.containsKey(name)) { + defaultCookies.remove(name); + } + defaultCookies.add(name, value); + return this; + } + + /** + * Get the date format used to parse/format date parameters. + * @return DateFormat format + */ + public DateFormat getDateFormat() { + return dateFormat; + } + + /** + * Parse the given string into Date object. + */ + public Date parseDate(String str) { + try { + return dateFormat.parse(str); + } catch (ParseException e) { + throw new RuntimeException(e); + } + } + + /** + * Format the given Date object into string. + */ + public String formatDate(Date date) { + return dateFormat.format(date); + } + + /** + * Format the given parameter object into string. + * @param param the object to convert + * @return String the parameter represented as a String + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date) { + return formatDate( (Date) param); + } {{#jsr310}}else if (param instanceof OffsetDateTime) { + return formatOffsetDateTime((OffsetDateTime) param); + } {{/jsr310}}else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for(Object o : (Collection) param) { + if(b.length() > 0) { + b.append(","); + } + b.append(String.valueOf(o)); + } + return b.toString(); + } else { + return String.valueOf(param); + } + } + + /** + * Converts a parameter to a {@link MultiValueMap} for use in REST requests + * @param collectionFormat The format to convert to + * @param name The name of the parameter + * @param value The parameter's value + * @return a Map containing the String value(s) of the input parameter + */ + public MultiValueMap parameterToMultiValueMap(CollectionFormat collectionFormat, String name, Object value) { + final MultiValueMap params = new LinkedMultiValueMap(); + + if (name == null || name.isEmpty() || value == null) { + return params; + } + + if(collectionFormat == null) { + collectionFormat = CollectionFormat.CSV; + } + + Collection valueCollection = null; + if (value instanceof Collection) { + valueCollection = (Collection) value; + } else { + params.add(name, parameterToString(value)); + return params; + } + + if (valueCollection.isEmpty()){ + return params; + } + + if (collectionFormat.equals(CollectionFormat.MULTI)) { + for (Object item : valueCollection) { + params.add(name, parameterToString(item)); + } + return params; + } + + List values = new ArrayList(); + for(Object o : valueCollection) { + values.add(parameterToString(o)); + } + params.add(name, collectionFormat.collectionToString(values)); + + return params; + } + + /** + * Check if the given {@code String} is a JSON MIME. + * @param mediaType the input MediaType + * @return boolean true if the MediaType represents JSON, false otherwise + */ + public boolean isJsonMime(String mediaType) { + // "* / *" is default to JSON + if ("*/*".equals(mediaType)) { + return true; + } + + try { + return isJsonMime(MediaType.parseMediaType(mediaType)); + } catch (InvalidMediaTypeException e) { + } + return false; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * @param mediaType the input MediaType + * @return boolean true if the MediaType represents JSON, false otherwise + */ + public boolean isJsonMime(MediaType mediaType) { + return mediaType != null && (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType) || mediaType.getSubtype().matches("^.*\\+json[;]?\\s*$")); + } + + /** + * 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 List The list of MediaTypes to use for the Accept header + */ + public List selectHeaderAccept(String[] accepts) { + if (accepts.length == 0) { + return null; + } + for (String accept : accepts) { + MediaType mediaType = MediaType.parseMediaType(accept); + if (isJsonMime(mediaType)) { + return Collections.singletonList(mediaType); + } + } + return MediaType.parseMediaTypes(StringUtils.arrayToCommaDelimitedString(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 MediaType The Content-Type header to use. If the given array is empty, null will be returned. + */ + public MediaType selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0) { + return null; + } + for (String contentType : contentTypes) { + MediaType mediaType = MediaType.parseMediaType(contentType); + if (isJsonMime(mediaType)) { + return mediaType; + } + } + return MediaType.parseMediaType(contentTypes[0]); + } + + /** + * Select the body to use for the request + * @param obj the body object + * @param formParams the form parameters + * @param contentType the content type of the request + * @return Object the selected body + */ + protected BodyInserter selectBody(Object obj, MultiValueMap formParams, MediaType contentType) { + if(MediaType.APPLICATION_FORM_URLENCODED.equals(contentType)) { + MultiValueMap map = new LinkedMultiValueMap<>(); + + formParams + .toSingleValueMap() + .entrySet() + .forEach(es -> map.add(es.getKey(), String.valueOf(es.getValue()))); + + return BodyInserters.fromFormData(map); + } else if(MediaType.MULTIPART_FORM_DATA.equals(contentType)) { + return BodyInserters.fromMultipartData(formParams); + } else { + return obj != null ? BodyInserters.fromValue(obj) : null; + } + } + + /** + * Invoke API by sending HTTP request with the given options. + * + * @param the return type to use + * @param path The sub-path of the HTTP URL + * @param method The request method + * @param pathParams The path parameters + * @param queryParams The query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param formParams The form parameters + * @param accept The request's Accept header + * @param contentType The request's Content-Type header + * @param authNames The authentications to apply + * @param returnType The return type into which to deserialize the response + * @return The response body in chosen type + */ + public Mono invokeAPI(String path, HttpMethod method, Map pathParams, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap cookieParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { + final WebClient.RequestBodySpec requestBuilder = prepareRequest(path, method, pathParams, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames); + return requestBuilder.retrieve().bodyToMono(returnType); + } + + /** + * Invoke API by sending HTTP request with the given options. + * + * @param the return type to use + * @param path The sub-path of the HTTP URL + * @param method The request method + * @param pathParams The path parameters + * @param queryParams The query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param formParams The form parameters + * @param accept The request's Accept header + * @param contentType The request's Content-Type header + * @param authNames The authentications to apply + * @param returnType The return type into which to deserialize the response + * @return The response body in chosen type + */ + public Flux invokeFluxAPI(String path, HttpMethod method, Map pathParams, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap cookieParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { + final WebClient.RequestBodySpec requestBuilder = prepareRequest(path, method, pathParams, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames); + return requestBuilder.retrieve().bodyToFlux(returnType); + } + + private WebClient.RequestBodySpec prepareRequest(String path, HttpMethod method, Map pathParams, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap cookieParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames) { + updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); + + final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(path); + if (queryParams != null) { + builder.queryParams(queryParams); + } + + final WebClient.RequestBodySpec requestBuilder = webClient.method(method).uri(builder.build(false).toUriString(), pathParams); + if(accept != null) { + requestBuilder.accept(accept.toArray(new MediaType[accept.size()])); + } + if(contentType != null) { + requestBuilder.contentType(contentType); + } + + addHeadersToRequest(headerParams, requestBuilder); + addHeadersToRequest(defaultHeaders, requestBuilder); + addCookiesToRequest(cookieParams, requestBuilder); + addCookiesToRequest(defaultCookies, requestBuilder); + + requestBuilder.body(selectBody(body, formParams, contentType)); + return requestBuilder; + } + + /** + * Add headers to the request that is being built + * @param headers The headers to add + * @param requestBuilder The current request + */ + protected void addHeadersToRequest(HttpHeaders headers, WebClient.RequestBodySpec requestBuilder) { + for (Entry> entry : headers.entrySet()) { + List values = entry.getValue(); + for(String value : values) { + if (value != null) { + requestBuilder.header(entry.getKey(), value); + } + } + } + } + + /** + * Add cookies to the request that is being built + * @param cookies The cookies to add + * @param requestBuilder The current request + */ + protected void addCookiesToRequest(MultiValueMap cookies, WebClient.RequestBodySpec requestBuilder) { + for (Entry> entry : cookies.entrySet()) { + List values = entry.getValue(); + for(String value : values) { + if (value != null) { + requestBuilder.cookie(entry.getKey(), value); + } + } + } + } + + /** + * Update query and header parameters based on authentication settings. + * + * @param authNames The authentications to apply + * @param queryParams The query parameters + * @param headerParams The header parameters + * @param cookieParams the cookie parameters + */ + private void updateParamsForAuth(String[] authNames, MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { + for (String authName : authNames) { + Authentication auth = authentications.get(authName); + if (auth == null) { + throw new RestClientException("Authentication undefined: " + authName); + } + auth.applyToParams(queryParams, headerParams, cookieParams); + } + } + + /** + * Formats the specified collection path parameter to a string value. + * + * @param collectionFormat The collection format of the parameter. + * @param values The values of the parameter. + * @return String representation of the parameter + */ + public String collectionPathParameterToString(CollectionFormat collectionFormat, Collection values) { + // create the value based on the collection format + if (CollectionFormat.MULTI.equals(collectionFormat)) { + // not valid for path params + return parameterToString(values); + } + + // collectionFormat is assumed to be "csv" by default + if(collectionFormat == null) { + collectionFormat = CollectionFormat.CSV; + } + + return collectionFormat.collectionToString(values); + } +} diff --git a/.generator/templates/libraries/webclient/api.mustache b/.generator/templates/libraries/webclient/api.mustache new file mode 100644 index 00000000000..5fbef45db81 --- /dev/null +++ b/.generator/templates/libraries/webclient/api.mustache @@ -0,0 +1,132 @@ +package {{package}}; + +import {{invokerPackage}}.ApiClient; + +{{#imports}}import {{import}}; +{{/imports}} +{{^fullJavaUtil}} + +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.stream.Collectors; +{{/fullJavaUtil}} + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.util.UriComponentsBuilder; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.web.reactive.function.client.WebClientResponseException; +import org.springframework.core.io.FileSystemResource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import reactor.core.publisher.Mono; +import reactor.core.publisher.Flux; + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}} { + private ApiClient apiClient; + + public {{classname}}() { + this(new ApiClient()); + } + + @Autowired + public {{classname}}(ApiClient apiClient) { + this.apiClient = apiClient; + } + + public ApiClient getApiClient() { + return apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.apiClient = apiClient; + } + + {{#operation}} + /** + * {{summary}} + * {{notes}} +{{#responses}} *

{{code}}{{#message}} - {{message}}{{/message}} +{{/responses}}{{#allParams}} * @param {{paramName}} {{description}}{{^description}}The {{paramName}} parameter{{/description}} +{{/allParams}}{{#returnType}} * @return {{returnType}} +{{/returnType}} * @throws WebClientResponseException if an error occurs while attempting to invoke the API +{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation +{{/externalDocs}} + */ + public {{#returnType}}{{#isArray}}Flux<{{{returnBaseType}}}>{{/isArray}}{{^isArray}}Mono<{{{returnType}}}>{{/isArray}} {{/returnType}}{{^returnType}}Mono {{/returnType}}{{operationId}}({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.AbstractResource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws WebClientResponseException { + Object postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + {{#allParams}} + {{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new WebClientResponseException("Missing the required parameter '{{paramName}}' when calling {{operationId}}", HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.getReasonPhrase(), null, null, null); + } + {{/required}} + {{/allParams}} + // create path and map variables + final Map pathParams = new HashMap(); + {{#hasPathParams}} + + {{#pathParams}} + pathParams.put("{{baseName}}", {{#collectionFormat}}apiClient.collectionPathParameterToString(ApiClient.CollectionFormat.valueOf("csv".toUpperCase()), {{/collectionFormat}}{{{paramName}}}{{#collectionFormat}}){{/collectionFormat}}); + {{/pathParams}} + {{/hasPathParams}} + + final MultiValueMap queryParams = new LinkedMultiValueMap(); + final HttpHeaders headerParams = new HttpHeaders(); + final MultiValueMap cookieParams = new LinkedMultiValueMap(); + final MultiValueMap formParams = new LinkedMultiValueMap(); + {{#hasQueryParams}} + + {{#queryParams}} + queryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}})); + {{/queryParams}} + {{/hasQueryParams}} + {{#hasHeaderParams}} + + {{#headerParams}} + if ({{paramName}} != null) + headerParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{^-last}} + {{/-last}} + {{/headerParams}} + {{/hasHeaderParams}} + {{#hasCookieParams}} + + {{#cookieParams}} + cookieParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}})); + {{/cookieParams}} + {{/hasCookieParams}} + {{#hasFormParams}} + + {{#formParams}} + if ({{paramName}} != null) + formParams.add{{#collectionFormat}}All{{/collectionFormat}}("{{baseName}}", {{#isFile}}{{^collectionFormat}}{{#useAbstractionForFiles}}{{paramName}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}new FileSystemResource({{paramName}}){{/useAbstractionForFiles}}{{/collectionFormat}}{{/isFile}}{{#isFile}}{{#collectionFormat}}{{paramName}}.stream(){{^useAbstractionForFiles}}.map(FileSystemResource::new){{/useAbstractionForFiles}}.collect(Collectors.toList()){{/collectionFormat}}{{/isFile}}{{^isFile}}{{paramName}}{{/isFile}}); + {{/formParams}} + {{/hasFormParams}} + + final String[] localVarAccepts = { {{#hasProduces}} + {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} + {{/hasProduces}}}; + final List localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); + final String[] localVarContentTypes = { {{#hasConsumes}} + {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} + {{/hasConsumes}}}; + final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); + + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; + + {{#returnType}}ParameterizedTypeReference<{{#isArray}}{{{returnBaseType}}}{{/isArray}}{{^isArray}}{{{returnType}}}{{/isArray}}> localVarReturnType = new ParameterizedTypeReference<{{#isArray}}{{{returnBaseType}}}{{/isArray}}{{^isArray}}{{{returnType}}}{{/isArray}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference localVarReturnType = new ParameterizedTypeReference() {};{{/returnType}} + return apiClient.{{#isArray}}invokeFluxAPI{{/isArray}}{{^isArray}}invokeAPI{{/isArray}}("{{{path}}}", HttpMethod.{{httpMethod}}, pathParams, queryParams, postBody, headerParams, cookieParams, formParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); + } + {{/operation}} +} +{{/operations}} diff --git a/.generator/templates/libraries/webclient/api_test.mustache b/.generator/templates/libraries/webclient/api_test.mustache new file mode 100644 index 00000000000..c2b491aedc1 --- /dev/null +++ b/.generator/templates/libraries/webclient/api_test.mustache @@ -0,0 +1,41 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Test; +import org.junit.Ignore; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +@Ignore +public class {{classname}}Test { + + private final {{classname}} api = new {{classname}}(); + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + */ + @Test + public void {{operationId}}Test() { + {{#allParams}} + {{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.AbstractResource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}} = null; + {{/allParams}} + {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}){{#isArray}}.collectList().block(){{/isArray}}{{^isArray}}.block(){{/isArray}}; + + // TODO: test validations + } + {{/operation}}{{/operations}} +} diff --git a/.generator/templates/libraries/webclient/auth/ApiKeyAuth.mustache b/.generator/templates/libraries/webclient/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..857403b27cf --- /dev/null +++ b/.generator/templates/libraries/webclient/auth/ApiKeyAuth.mustache @@ -0,0 +1,62 @@ +package {{invokerPackage}}.auth; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.MultiValueMap; + +{{>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(MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { + if (apiKey == null) { + return; + } + String value; + if (apiKeyPrefix != null) { + value = apiKeyPrefix + " " + apiKey; + } else { + value = apiKey; + } + if (location.equals("query")) { + queryParams.add(paramName, value); + } else if (location.equals("header")) { + headerParams.add(paramName, value); + } else if (location.equals("cookie")) { + cookieParams.add(paramName, value); + } + } +} diff --git a/.generator/templates/libraries/webclient/auth/Authentication.mustache b/.generator/templates/libraries/webclient/auth/Authentication.mustache new file mode 100644 index 00000000000..8e53c2ba08e --- /dev/null +++ b/.generator/templates/libraries/webclient/auth/Authentication.mustache @@ -0,0 +1,14 @@ +package {{invokerPackage}}.auth; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.MultiValueMap; + +public interface Authentication { + /** + * Apply authentication settings to header and / or query parameters. + * @param queryParams The query parameters for the request + * @param headerParams The header parameters for the request + * @param cookieParams The cookie parameters for the request + */ + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams); +} diff --git a/.generator/templates/libraries/webclient/auth/HttpBasicAuth.mustache b/.generator/templates/libraries/webclient/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..5b07cb907bb --- /dev/null +++ b/.generator/templates/libraries/webclient/auth/HttpBasicAuth.mustache @@ -0,0 +1,39 @@ +package {{invokerPackage}}.auth; + +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.Base64Utils; +import org.springframework.util.MultiValueMap; + +{{>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(MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { + if (username == null && password == null) { + return; + } + String str = (username == null ? "" : username) + ":" + (password == null ? "" : password); + headerParams.add(HttpHeaders.AUTHORIZATION, "Basic " + Base64Utils.encodeToString(str.getBytes(StandardCharsets.UTF_8))); + } +} diff --git a/.generator/templates/libraries/webclient/auth/HttpBearerAuth.mustache b/.generator/templates/libraries/webclient/auth/HttpBearerAuth.mustache new file mode 100644 index 00000000000..027c128f474 --- /dev/null +++ b/.generator/templates/libraries/webclient/auth/HttpBearerAuth.mustache @@ -0,0 +1,39 @@ +package {{invokerPackage}}.auth; + +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.Base64Utils; +import org.springframework.util.MultiValueMap; + +{{>generatedAnnotation}} +public class HttpBearerAuth implements Authentication { + private final String scheme; + private String bearerToken; + + public HttpBearerAuth(String scheme) { + this.scheme = scheme; + } + + public String getBearerToken() { + return bearerToken; + } + + public void setBearerToken(String bearerToken) { + this.bearerToken = bearerToken; + } + + @Override + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { + if (bearerToken == null) { + return; + } + headerParams.add(HttpHeaders.AUTHORIZATION, (scheme != null ? upperCaseBearer(scheme) + " " : "") + bearerToken); + } + + private static String upperCaseBearer(String scheme) { + return ("bearer".equalsIgnoreCase(scheme)) ? "Bearer" : scheme; + } + +} diff --git a/.generator/templates/libraries/webclient/auth/OAuth.mustache b/.generator/templates/libraries/webclient/auth/OAuth.mustache new file mode 100644 index 00000000000..7889f1582de --- /dev/null +++ b/.generator/templates/libraries/webclient/auth/OAuth.mustache @@ -0,0 +1,24 @@ +package {{invokerPackage}}.auth; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.MultiValueMap; + +{{>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(MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { + if (accessToken != null) { + headerParams.add(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken); + } + } +} diff --git a/.generator/templates/libraries/webclient/auth/OAuthFlow.mustache b/.generator/templates/libraries/webclient/auth/OAuthFlow.mustache new file mode 100644 index 00000000000..7ab35f6d890 --- /dev/null +++ b/.generator/templates/libraries/webclient/auth/OAuthFlow.mustache @@ -0,0 +1,5 @@ +package {{invokerPackage}}.auth; + +public enum OAuthFlow { + accessCode, implicit, password, application +} \ No newline at end of file diff --git a/.generator/templates/libraries/webclient/build.gradle.mustache b/.generator/templates/libraries/webclient/build.gradle.mustache new file mode 100644 index 00000000000..c335e7ad441 --- /dev/null +++ b/.generator/templates/libraries/webclient/build.gradle.mustache @@ -0,0 +1,165 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + maven { url "https://repo1.maven.org/maven2" } + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +repositories { + maven { url "https://repo1.maven.org/maven2" } + jcenter() +} + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + } + + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + {{#java8}} + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + {{/java8}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } + + task sourcesJar(type: Jar, dependsOn: classes) { + classifier = 'sources' + from sourceSets.main.allSource + } + + task javadocJar(type: Jar, dependsOn: javadoc) { + classifier = 'javadoc' + from javadoc.destinationDir + } + + artifacts { + archives sourcesJar + archives javadocJar + } +} + +ext { + swagger_annotations_version = "1.6.2" + spring_web_version = "2.4.3" + jackson_version = "2.11.3" + jackson_databind_version = "2.11.3" + {{#openApiNullable}} + jackson_databind_nullable_version = "0.2.1" + {{/openApiNullable}} + javax_annotation_version = "1.3.2" + reactor_version = "3.4.3" + reactor_netty_version = "0.7.15.RELEASE" + jodatime_version = "2.9.9" + junit_version = "4.13.1" +} + +dependencies { + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "io.projectreactor:reactor-core:$reactor_version" + implementation "org.springframework.boot:spring-boot-starter-webflux:$spring_web_version" + implementation "io.projectreactor.ipc:reactor-netty:$reactor_netty_version" + 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_databind_version" + implementation "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + {{#openApiNullable}} + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} + {{#joda}} + implementation "joda-time:joda-time:$jodatime_version" + {{/joda}} + {{#java8}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{/java8}} + {{^java8}} + implementation "com.brsanthu:migbase64:2.2" + {{/java8}} + implementation "javax.annotation:javax.annotation-api:$javax_annotation_version" + testImplementation "junit:junit:$junit_version" +} + diff --git a/.generator/templates/libraries/webclient/pom.mustache b/.generator/templates/libraries/webclient/pom.mustache new file mode 100644 index 00000000000..67a888863b4 --- /dev/null +++ b/.generator/templates/libraries/webclient/pom.mustache @@ -0,0 +1,166 @@ + + 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.6.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + + io.projectreactor + reactor-core + ${reactor-version} + + + + + org.springframework.boot + spring-boot-starter-webflux + ${spring-web-version} + + + + io.projectreactor.ipc + reactor-netty + ${reactor-netty-version} + + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-databind-version} + + {{#openApiNullable}} + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + + {{/openApiNullable}} + + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{/java8}} + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + + joda-time + joda-time + ${jodatime-version} + + {{/joda}} + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + + + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.6.2 + 2.4.3 + 2.11.3 + 2.11.3 + {{#openApiNullable}} + 0.2.1 + {{/openApiNullable}} + 1.3.2 + 4.13.1 + 3.4.3 + 0.7.15.RELEASE + {{#joda}} + 2.9.9 + {{/joda}} + + diff --git a/.generator/templates/licenseInfo.mustache b/.generator/templates/licenseInfo.mustache new file mode 100644 index 00000000000..764d7f952d8 --- /dev/null +++ b/.generator/templates/licenseInfo.mustache @@ -0,0 +1,9 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2019-Present Datadog, Inc. + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ diff --git a/.generator/templates/manifest.mustache b/.generator/templates/manifest.mustache new file mode 100644 index 00000000000..f44bd07d0a0 --- /dev/null +++ b/.generator/templates/manifest.mustache @@ -0,0 +1,3 @@ + + + diff --git a/.generator/templates/model.mustache b/.generator/templates/model.mustache new file mode 100644 index 00000000000..8fd078eb3d6 --- /dev/null +++ b/.generator/templates/model.mustache @@ -0,0 +1,54 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#useReflectionEqualsHashCode}} +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +{{/useReflectionEqualsHashCode}} +import java.util.Objects; +import java.util.Arrays; +{{#imports}} +import {{import}}; +{{/imports}} +{{#serializableModel}} +import java.io.Serializable; +{{/serializableModel}} +{{#jackson}} +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +{{#withXml}} +import com.fasterxml.jackson.dataformat.xml.annotation.*; +{{/withXml}} +{{/jackson}} +{{#withXml}} +import javax.xml.bind.annotation.*; +{{/withXml}} +{{#jsonb}} +import java.lang.reflect.Type; +import javax.json.bind.annotation.JsonbTypeDeserializer; +import javax.json.bind.annotation.JsonbTypeSerializer; +import javax.json.bind.serializer.DeserializationContext; +import javax.json.bind.serializer.JsonbDeserializer; +import javax.json.bind.serializer.JsonbSerializer; +import javax.json.bind.serializer.SerializationContext; +import javax.json.stream.JsonGenerator; +import javax.json.stream.JsonParser; +import javax.json.bind.annotation.JsonbProperty; +{{/jsonb}} +{{#parcelableModel}} +import android.os.Parcelable; +import android.os.Parcel; +{{/parcelableModel}} +{{#useBeanValidation}} +import javax.validation.constraints.*; +import javax.validation.Valid; +{{/useBeanValidation}} +{{#performBeanValidation}} +import org.hibernate.validator.constraints.*; +{{/performBeanValidation}} + +{{#models}} +{{#model}} +{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{#vendorExtensions.x-is-one-of-interface}}{{>oneof_interface}}{{/vendorExtensions.x-is-one-of-interface}}{{^vendorExtensions.x-is-one-of-interface}}{{>pojo}}{{/vendorExtensions.x-is-one-of-interface}}{{/isEnum}} +{{/model}} +{{/models}} diff --git a/.generator/templates/modelEnum.mustache b/.generator/templates/modelEnum.mustache new file mode 100644 index 00000000000..207a937ebde --- /dev/null +++ b/.generator/templates/modelEnum.mustache @@ -0,0 +1,100 @@ +{{#jackson}} +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +{{/jackson}} +{{#gson}} +import java.io.IOException; +import com.google.gson.TypeAdapter; +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +{{/gson}} + +/** + * {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}} + */ +{{#gson}} +@JsonAdapter({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.Adapter.class) +{{/gson}} +{{#jsonb}} +@JsonbTypeSerializer({{datatypeWithEnum}}.Serializer.class) +@JsonbTypeDeserializer({{datatypeWithEnum}}.Deserializer.class) +{{/jsonb}} +{{>additionalEnumTypeAnnotations}}public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} { + {{#allowableValues}}{{#enumVars}} + {{#enumDescription}} + /** + * {{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}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) { + this.value = value; + } + +{{#jackson}} + @JsonValue +{{/jackson}} + public {{{dataType}}} getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + +{{#jackson}} + @JsonCreator +{{/jackson}} + public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue({{{dataType}}} value) { + for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + if (b.value.equals(value)) { + return b; + } + } + {{#isNullable}}return null;{{/isNullable}}{{^isNullable}}throw new IllegalArgumentException("Unexpected value '" + value + "'");{{/isNullable}} + } +{{#gson}} + + public static class Adapter extends TypeAdapter<{{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}> { + @Override + public void write(final JsonWriter jsonWriter, final {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} enumeration) throws IOException { + jsonWriter.value(enumeration.getValue()); + } + + @Override + public {{#datatypeWithEnum}}{{{.}}}{{/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}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}}); + } + } +{{/gson}} +{{#jsonb}} + public static final class Deserializer implements JsonbDeserializer<{{datatypeWithEnum}}> { + @Override + public {{datatypeWithEnum}} deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) { + for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + if (String.valueOf(b.value).equals(parser.getString())) { + return b; + } + } + {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + parser.getString() + "'");{{/useNullForUnknownEnumValue}} + } + } + + public static final class Serializer implements JsonbSerializer<{{datatypeWithEnum}}> { + @Override + public void serialize({{datatypeWithEnum}} obj, JsonGenerator generator, SerializationContext ctx) { + generator.write(obj.value); + } + } +{{/jsonb}} +} diff --git a/.generator/templates/modelInnerEnum.mustache b/.generator/templates/modelInnerEnum.mustache new file mode 100644 index 00000000000..e0a194d6ba6 --- /dev/null +++ b/.generator/templates/modelInnerEnum.mustache @@ -0,0 +1,95 @@ + /** + * {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}} + */ +{{#gson}} + @JsonAdapter({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.Adapter.class) +{{/gson}} +{{#jsonb}} + @JsonbTypeSerializer({{datatypeWithEnum}}.Serializer.class) + @JsonbTypeDeserializer({{datatypeWithEnum}}.Deserializer.class) +{{/jsonb}} +{{#withXml}} + @XmlType(name="{{datatypeWithEnum}}") + @XmlEnum({{dataType}}.class) +{{/withXml}} + {{>additionalEnumTypeAnnotations}}public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} { + {{#allowableValues}} + {{#enumVars}} + {{#enumDescription}} + /** + * {{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}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}({{{dataType}}} value) { + this.value = value; + } + +{{#jackson}} + @JsonValue +{{/jackson}} + public {{{dataType}}} getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + +{{#jackson}} + @JsonCreator +{{/jackson}} + public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue({{{dataType}}} value) { + for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + if (b.value.equals(value)) { + return b; + } + } + {{#isNullable}}return null;{{/isNullable}}{{^isNullable}}throw new IllegalArgumentException("Unexpected value '" + value + "'");{{/isNullable}} + } +{{#gson}} + + public static class Adapter extends TypeAdapter<{{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}> { + @Override + public void write(final JsonWriter jsonWriter, final {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} enumeration) throws IOException { + jsonWriter.value(enumeration.getValue()); + } + + @Override + public {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException { + {{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = {{#isFloat}}(float){{/isFloat}} jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{^isNumber}}{{^isInteger}}{{#isFloat}}nextDouble{{/isFloat}}{{^isFloat}}next{{{dataType}}}{{/isFloat}}(){{/isInteger}}{{/isNumber}}; + return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}}); + } + } +{{/gson}} +{{#jsonb}} + public static final class Deserializer implements JsonbDeserializer<{{datatypeWithEnum}}> { + @Override + public {{datatypeWithEnum}} deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) { + for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + if (String.valueOf(b.value).equals(parser.getString())) { + return b; + } + } + {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + parser.getString() + "'");{{/useNullForUnknownEnumValue}} + } + } + + public static final class Serializer implements JsonbSerializer<{{datatypeWithEnum}}> { + @Override + public void serialize({{datatypeWithEnum}} obj, JsonGenerator generator, SerializationContext ctx) { + generator.write(obj.value); + } + } +{{/jsonb}} + } diff --git a/.generator/templates/model_doc.mustache b/.generator/templates/model_doc.mustache new file mode 100644 index 00000000000..9a7fe146a4e --- /dev/null +++ b/.generator/templates/model_doc.mustache @@ -0,0 +1,4 @@ +{{#models}}{{#model}} + +{{#isEnum}}{{>enum_outer_doc}}{{/isEnum}}{{^isEnum}}{{>pojo_doc}}{{/isEnum}} +{{/model}}{{/models}} diff --git a/.generator/templates/model_test.mustache b/.generator/templates/model_test.mustache new file mode 100644 index 00000000000..07468db5657 --- /dev/null +++ b/.generator/templates/model_test.mustache @@ -0,0 +1,50 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +{{#fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * 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/.generator/templates/oneof_interface.mustache b/.generator/templates/oneof_interface.mustache new file mode 100644 index 00000000000..02deb483d5f --- /dev/null +++ b/.generator/templates/oneof_interface.mustache @@ -0,0 +1,6 @@ +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>typeInfoAnnotation}}{{>xmlAnnotation}} +public interface {{classname}} {{#vendorExtensions.x-implements}}{{#-first}}extends {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.x-implements}} { + {{#discriminator}} + public {{propertyType}} {{propertyGetter}}(); + {{/discriminator}} +} diff --git a/.generator/templates/openapi.mustache b/.generator/templates/openapi.mustache new file mode 100644 index 00000000000..34fbb53f331 --- /dev/null +++ b/.generator/templates/openapi.mustache @@ -0,0 +1 @@ +{{{openapi-yaml}}} diff --git a/.generator/templates/pojo.mustache b/.generator/templates/pojo.mustache new file mode 100644 index 00000000000..30454970acf --- /dev/null +++ b/.generator/templates/pojo.mustache @@ -0,0 +1,348 @@ +/** + * {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}} + */{{#description}} +@ApiModel(description = "{{{description}}}"){{/description}} +{{#jackson}} +@JsonPropertyOrder({ +{{#vars}} + {{classname}}.JSON_PROPERTY_{{nameInSnakeCase}}{{^-last}},{{/-last}} +{{/vars}} +}) +@JsonTypeName("{{name}}") +{{/jackson}} +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} +public class {{classname}} {{#parent}}extends {{{parent}}} {{/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}} + {{#gson}} + public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}"; + {{/gson}} + {{#jackson}} + public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}"; + {{/jackson}} + {{#withXml}} + {{#isXmlAttribute}} + @XmlAttribute(name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlAttribute}} + {{^isXmlAttribute}} + {{^isContainer}} + @XmlElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isContainer}} + {{#isContainer}} + // Is a container wrapped={{isXmlWrapped}} + {{#items}} + // items.name={{name}} items.baseName={{baseName}} items.xmlName={{xmlName}} items.xmlNamespace={{xmlNamespace}} + // items.example={{example}} items.type={{dataType}} + @XmlElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/items}} + {{#isXmlWrapped}} + @XmlElementWrapper({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlWrapped}} + {{/isContainer}} + {{/isXmlAttribute}} + {{/withXml}} + {{#gson}} + @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}}) + {{/gson}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#isContainer}} + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined(); + {{/isContainer}} + {{^isContainer}} + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + {{/isContainer}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{#isContainer}} + private {{{datatypeWithEnum}}} {{name}}{{#required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/required}}{{^required}} = null{{/required}}; + {{/isContainer}} + {{^isContainer}} + {{#isDiscriminator}}protected{{/isDiscriminator}}{{^isDiscriminator}}private{{/isDiscriminator}} {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; + {{/isContainer}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + + {{/vars}} + {{#parcelableModel}} + public {{classname}}() { + {{#parent}} + super(); + {{/parent}} + {{#gson}} + {{#discriminator}} + this.{{{discriminatorName}}} = this.getClass().getSimpleName(); + {{/discriminator}} + {{/gson}} + } + {{/parcelableModel}} + {{^parcelableModel}} + {{#gson}} + {{#discriminator}} + public {{classname}}() { + this.{{{discriminatorName}}} = this.getClass().getSimpleName(); + } + {{/discriminator}} + {{/gson}} + {{/parcelableModel}} + {{#vars}} + + {{^isReadOnly}} + public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});{{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = {{name}};{{/vendorExtensions.x-is-jackson-optional-nullable}} + return this; + } + {{#isArray}} + + public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null || !this.{{name}}.isPresent()) { + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); + } + try { + this.{{name}}.get().add({{name}}Item); + } catch (java.util.NoSuchElementException e) { + // this can never happen, as we make sure above that the value is present + } + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.add({{name}}Item); + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isArray}} + {{#isMap}} + + public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null || !this.{{name}}.isPresent()) { + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); + } + try { + this.{{name}}.get().put(key, {{name}}Item); + } catch (java.util.NoSuchElementException e) { + // this can never happen, as we make sure above that the value is present + } + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.put(key, {{name}}Item); + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isMap}} + + {{/isReadOnly}} + /** + {{#description}} + * {{description}} + {{/description}} + {{^description}} + * Get {{name}} + {{/description}} + {{#minimum}} + * minimum: {{minimum}} + {{/minimum}} + {{#maximum}} + * maximum: {{maximum}} + {{/maximum}} + * @return {{name}} + **/ +{{#required}} +{{#isNullable}} + @javax.annotation.Nullable +{{/isNullable}} +{{/required}} +{{^required}} + @javax.annotation.Nullable +{{/required}} +{{#jsonb}} + @JsonbProperty("{{baseName}}") +{{/jsonb}} +{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} @ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") +{{#vendorExtensions.x-extra-annotation}} + {{{vendorExtensions.x-extra-annotation}}} +{{/vendorExtensions.x-extra-annotation}} +{{#vendorExtensions.x-is-jackson-optional-nullable}} + {{!unannotated, Jackson would pick this up automatically and add it *in addition* to the _JsonNullable getter field}} + @JsonIgnore +{{/vendorExtensions.x-is-jackson-optional-nullable}} +{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#jackson}}{{> jackson_annotations}}{{/jackson}}{{/vendorExtensions.x-is-jackson-optional-nullable}} + public {{{datatypeWithEnum}}} {{getter}}() { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#isReadOnly}}{{! A readonly attribute doesn't have setter => jackson will set null directly if explicitly returned by API, so make sure we have an empty JsonNullable}} + if ({{name}} == null) { + {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + } + {{/isReadOnly}} + return {{name}}.orElse(null); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + return {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + + {{#vendorExtensions.x-is-jackson-optional-nullable}} +{{> jackson_annotations}} + public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}_JsonNullable() { + return {{name}}; + } + {{/vendorExtensions.x-is-jackson-optional-nullable}}{{#vendorExtensions.x-is-jackson-optional-nullable}} + @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) + {{#isReadOnly}}private{{/isReadOnly}}{{^isReadOnly}}public{{/isReadOnly}} void {{setter}}_JsonNullable(JsonNullable<{{{datatypeWithEnum}}}> {{name}}) { + {{! For getters/setters that have name differing from attribute name, we must include setter (albeit private) for jackson to be able to set the attribute}} + this.{{name}} = {{name}}; + } + {{/vendorExtensions.x-is-jackson-optional-nullable}} + + {{^isReadOnly}} + public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isReadOnly}} + + {{/vars}} + + @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}}{{#parent}} && + super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} + return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}} + {{/useReflectionEqualsHashCode}} + } + + @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}}); + {{/useReflectionEqualsHashCode}} + } + + @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(toIndentedString({{name}})).append("\n"); + {{/vars}} + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private{{#jsonb}} static{{/jsonb}} String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return 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}} +} diff --git a/.generator/templates/pojo_doc.mustache b/.generator/templates/pojo_doc.mustache new file mode 100644 index 00000000000..f5643754465 --- /dev/null +++ b/.generator/templates/pojo_doc.mustache @@ -0,0 +1,37 @@ +# {{#vendorExtensions.x-is-one-of-interface}}Interface {{/vendorExtensions.x-is-one-of-interface}}{{classname}} + +{{#description}}{{&description}} +{{/description}} +{{^vendorExtensions.x-is-one-of-interface}} + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +{{#vars}}**{{name}}** | {{#isEnum}}[**{{datatypeWithEnum}}**](#{{datatypeWithEnum}}){{/isEnum}}{{^isEnum}}{{#isContainer}}{{#isArray}}{{#items}}{{#isModel}}[{{/isModel}}{{/items}}**{{baseType}}{{#items}}<{{dataType}}>**{{#isModel}}]({{^baseType}}{{dataType}}{{/baseType}}{{#baseType}}{{baseType}}{{/baseType}}.md){{/isModel}}{{/items}}{{/isArray}}{{#isMap}}{{#items}}{{#isModel}}[{{/isModel}}**Map<String, {{dataType}}>**{{#isModel}}]({{^baseType}}{{dataType}}{{/baseType}}{{#baseType}}{{baseType}}{{/baseType}}.md){{/isModel}}{{/items}}{{/isMap}}{{/isContainer}}{{^isContainer}}{{#isModel}}[{{/isModel}}**{{dataType}}**{{#isModel}}]({{^baseType}}{{dataType}}{{/baseType}}{{#baseType}}{{baseType}}{{/baseType}}.md){{/isModel}}{{/isContainer}}{{/isEnum}} | {{description}} | {{^required}} [optional]{{/required}}{{#isReadOnly}} [readonly]{{/isReadOnly}} +{{/vars}} +{{#vars}}{{#isEnum}} + + +## Enum: {{datatypeWithEnum}} + +Name | Value +---- | -----{{#allowableValues}}{{#enumVars}} +{{name}} | {{value}}{{/enumVars}}{{/allowableValues}} +{{/isEnum}}{{/vars}} +{{#vendorExtensions.x-implements.0}} + +## Implemented Interfaces + +{{#vendorExtensions.x-implements}} +* {{{.}}} +{{/vendorExtensions.x-implements}} +{{/vendorExtensions.x-implements.0}} +{{/vendorExtensions.x-is-one-of-interface}} +{{#vendorExtensions.x-is-one-of-interface}} +## Implementing Classes + +{{#oneOf}} +* {{{.}}} +{{/oneOf}} +{{/vendorExtensions.x-is-one-of-interface}} diff --git a/.generator/templates/pom.mustache b/.generator/templates/pom.mustache new file mode 100644 index 00000000000..20b602c5421 --- /dev/null +++ b/.generator/templates/pom.mustache @@ -0,0 +1,373 @@ + + 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 + + true + 128m + 512m + + -Xlint:all + -J-Xss4m + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + {{#java8}} + 1.8 + 1.8 + {{/java8}} + {{^java8}} + 1.7 + 1.7 + {{/java8}} + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.1 + + none + {{#java8}} + 1.8 + {{/java8}} + {{^java8}} + 1.7 + {{/java8}} + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + + + + com.sun.jersey + jersey-client + ${jersey-version} + + + com.sun.jersey.contribs + jersey-multipart + ${jersey-version} + + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + + com.fasterxml.jackson.jaxrs + jackson-jaxrs-json-provider + ${jackson-version} + + {{#withXml}} + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson-version} + + + {{/withXml}} + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + {{/joda}} + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{/java8}} + {{#threetenbp}} + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-threetenbp-version} + + {{/threetenbp}} + {{^java8}} + + + com.brsanthu + migbase64 + 2.2 + + {{/java8}} + {{#useBeanValidation}} + + + javax.validation + validation-api + 1.1.0.Final + provided + + {{/useBeanValidation}} + {{#performBeanValidation}} + + + org.hibernate + hibernate-validator + 5.4.1.Final + + {{/performBeanValidation}} + {{#parcelableModel}} + + + com.google.android + android + 4.1.1.4 + provided + + {{/parcelableModel}} + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.5.21 + 1.19.4 + 2.12.1 + {{#threetenbp}} + 2.9.10 + {{/threetenbp}} + 1.3.2 + 1.0.0 + 4.13.1 + + diff --git a/.generator/templates/settings.gradle.mustache b/.generator/templates/settings.gradle.mustache new file mode 100644 index 00000000000..b8fd6c4c41f --- /dev/null +++ b/.generator/templates/settings.gradle.mustache @@ -0,0 +1 @@ +rootProject.name = "{{artifactId}}" \ No newline at end of file diff --git a/.generator/templates/travis.mustache b/.generator/templates/travis.mustache new file mode 100644 index 00000000000..1b6741c083c --- /dev/null +++ b/.generator/templates/travis.mustache @@ -0,0 +1,22 @@ +# +# Generated by OpenAPI Generator: https://openapi-generator.tech +# +# Ref: https://docs.travis-ci.com/user/languages/java/ +# +language: java +jdk: + - openjdk12 + - openjdk11 + - openjdk10 + - openjdk9 + - openjdk8 +before_install: + # ensure gradlew has proper permission + - chmod a+x ./gradlew +script: + # test using maven + #- mvn test + # test using gradle + - gradle test + # test using sbt + # - sbt test diff --git a/.generator/templates/typeInfoAnnotation.mustache b/.generator/templates/typeInfoAnnotation.mustache new file mode 100644 index 00000000000..63eb42ea500 --- /dev/null +++ b/.generator/templates/typeInfoAnnotation.mustache @@ -0,0 +1,16 @@ +{{#jackson}} + +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "{{{discriminator.propertyBaseName}}}", visible = true) +{{#discriminator.mappedModels}} +{{#-first}} +@JsonSubTypes({ +{{/-first}} + @JsonSubTypes.Type(value = {{modelName}}.class, name = "{{^vendorExtensions.x-discriminator-value}}{{mappingName}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}"), +{{#-last}} +}) +{{/-last}} +{{/discriminator.mappedModels}} +{{#isClassnameSanitized}} +@JsonTypeName("{{name}}") +{{/isClassnameSanitized}} +{{/jackson}} diff --git a/.generator/templates/xmlAnnotation.mustache b/.generator/templates/xmlAnnotation.mustache new file mode 100644 index 00000000000..04566fa1167 --- /dev/null +++ b/.generator/templates/xmlAnnotation.mustache @@ -0,0 +1,6 @@ +{{#withXml}} + +@XmlRootElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{classname}}{{/xmlName}}") +@XmlAccessorType(XmlAccessType.FIELD) +{{#jackson}} +@JacksonXmlRootElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}localName = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{classname}}{{/xmlName}}"){{/jackson}}{{/withXml}} \ No newline at end of file diff --git a/api_docs/v1/APIErrorResponse.md b/api_docs/v1/APIErrorResponse.md index 11e6de06b3a..a4a6f95c369 100644 --- a/api_docs/v1/APIErrorResponse.md +++ b/api_docs/v1/APIErrorResponse.md @@ -3,6 +3,7 @@ # APIErrorResponse Error response object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSAccount.md b/api_docs/v1/AWSAccount.md index 54b4d7dd151..fda8ab041fd 100644 --- a/api_docs/v1/AWSAccount.md +++ b/api_docs/v1/AWSAccount.md @@ -3,6 +3,7 @@ # AWSAccount Returns the AWS account associated with this integration. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSAccountAndLambdaRequest.md b/api_docs/v1/AWSAccountAndLambdaRequest.md index eef09b09859..c4419d941c8 100644 --- a/api_docs/v1/AWSAccountAndLambdaRequest.md +++ b/api_docs/v1/AWSAccountAndLambdaRequest.md @@ -3,6 +3,7 @@ # AWSAccountAndLambdaRequest AWS account ID and Lambda ARN. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSAccountCreateResponse.md b/api_docs/v1/AWSAccountCreateResponse.md index 0f0c6d805ee..c5c3031ce42 100644 --- a/api_docs/v1/AWSAccountCreateResponse.md +++ b/api_docs/v1/AWSAccountCreateResponse.md @@ -3,6 +3,7 @@ # AWSAccountCreateResponse The Response returned by the AWS Create Account call. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSAccountListResponse.md b/api_docs/v1/AWSAccountListResponse.md index 3e38bdf337a..ccac6c22bcd 100644 --- a/api_docs/v1/AWSAccountListResponse.md +++ b/api_docs/v1/AWSAccountListResponse.md @@ -3,6 +3,7 @@ # AWSAccountListResponse List of enabled AWS accounts. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSLogsAsyncError.md b/api_docs/v1/AWSLogsAsyncError.md index eb674141062..74c24f27b21 100644 --- a/api_docs/v1/AWSLogsAsyncError.md +++ b/api_docs/v1/AWSLogsAsyncError.md @@ -3,6 +3,7 @@ # AWSLogsAsyncError Description of errors. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSLogsAsyncResponse.md b/api_docs/v1/AWSLogsAsyncResponse.md index 11c17275b85..e148335a2dd 100644 --- a/api_docs/v1/AWSLogsAsyncResponse.md +++ b/api_docs/v1/AWSLogsAsyncResponse.md @@ -3,6 +3,7 @@ # AWSLogsAsyncResponse A list of all Datadog-AWS logs integrations available in your Datadog organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSLogsLambda.md b/api_docs/v1/AWSLogsLambda.md index 26ed1ef4fd2..73d9e89d1a6 100644 --- a/api_docs/v1/AWSLogsLambda.md +++ b/api_docs/v1/AWSLogsLambda.md @@ -3,6 +3,7 @@ # AWSLogsLambda Description of the Lambdas. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSLogsListResponse.md b/api_docs/v1/AWSLogsListResponse.md index 471087b48e7..e1604f73650 100644 --- a/api_docs/v1/AWSLogsListResponse.md +++ b/api_docs/v1/AWSLogsListResponse.md @@ -3,6 +3,7 @@ # AWSLogsListResponse A list of all Datadog-AWS logs integrations available in your Datadog organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSLogsListServicesResponse.md b/api_docs/v1/AWSLogsListServicesResponse.md index b55a2041ab0..0fc15ad74e0 100644 --- a/api_docs/v1/AWSLogsListServicesResponse.md +++ b/api_docs/v1/AWSLogsListServicesResponse.md @@ -3,6 +3,7 @@ # AWSLogsListServicesResponse The list of current AWS services for which Datadog offers automatic log collection. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSLogsServicesRequest.md b/api_docs/v1/AWSLogsServicesRequest.md index 6bf08fe8e1e..12df66ec6a3 100644 --- a/api_docs/v1/AWSLogsServicesRequest.md +++ b/api_docs/v1/AWSLogsServicesRequest.md @@ -3,6 +3,7 @@ # AWSLogsServicesRequest A list of current AWS services for which Datadog offers automatic log collection. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSTagFilter.md b/api_docs/v1/AWSTagFilter.md index ab441b3d5dd..5d2297d3050 100644 --- a/api_docs/v1/AWSTagFilter.md +++ b/api_docs/v1/AWSTagFilter.md @@ -3,6 +3,7 @@ # AWSTagFilter A tag filter. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSTagFilterCreateRequest.md b/api_docs/v1/AWSTagFilterCreateRequest.md index 3a67077cf96..ea924645741 100644 --- a/api_docs/v1/AWSTagFilterCreateRequest.md +++ b/api_docs/v1/AWSTagFilterCreateRequest.md @@ -3,6 +3,7 @@ # AWSTagFilterCreateRequest The objects used to set an AWS tag filter. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSTagFilterDeleteRequest.md b/api_docs/v1/AWSTagFilterDeleteRequest.md index f43dd2119d7..752c2a04ba4 100644 --- a/api_docs/v1/AWSTagFilterDeleteRequest.md +++ b/api_docs/v1/AWSTagFilterDeleteRequest.md @@ -3,6 +3,7 @@ # AWSTagFilterDeleteRequest The objects used to delete an AWS tag filter entry. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSTagFilterListResponse.md b/api_docs/v1/AWSTagFilterListResponse.md index ac9691eb137..afeb2143135 100644 --- a/api_docs/v1/AWSTagFilterListResponse.md +++ b/api_docs/v1/AWSTagFilterListResponse.md @@ -3,6 +3,7 @@ # AWSTagFilterListResponse An array of tag filter rules by `namespace` and tag filter string. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AlertGraphWidgetDefinition.md b/api_docs/v1/AlertGraphWidgetDefinition.md index 225abb8d5eb..8d0e70dba36 100644 --- a/api_docs/v1/AlertGraphWidgetDefinition.md +++ b/api_docs/v1/AlertGraphWidgetDefinition.md @@ -3,6 +3,7 @@ # AlertGraphWidgetDefinition Alert graphs are timeseries graphs showing the current status of any monitor defined on your system. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AlertValueWidgetDefinition.md b/api_docs/v1/AlertValueWidgetDefinition.md index e2f6e189d0a..a66b98d627e 100644 --- a/api_docs/v1/AlertValueWidgetDefinition.md +++ b/api_docs/v1/AlertValueWidgetDefinition.md @@ -3,6 +3,7 @@ # AlertValueWidgetDefinition Alert values are query values showing the current value of the metric in any monitor defined on your system. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ApiKey.md b/api_docs/v1/ApiKey.md index b432827df47..68392005f34 100644 --- a/api_docs/v1/ApiKey.md +++ b/api_docs/v1/ApiKey.md @@ -3,6 +3,7 @@ # ApiKey Datadog API key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ApiKeyListResponse.md b/api_docs/v1/ApiKeyListResponse.md index 81ac36c12ab..a0f68042470 100644 --- a/api_docs/v1/ApiKeyListResponse.md +++ b/api_docs/v1/ApiKeyListResponse.md @@ -3,6 +3,7 @@ # ApiKeyListResponse List of API and application keys available for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ApiKeyResponse.md b/api_docs/v1/ApiKeyResponse.md index ab1fde513a4..253efeab018 100644 --- a/api_docs/v1/ApiKeyResponse.md +++ b/api_docs/v1/ApiKeyResponse.md @@ -3,6 +3,7 @@ # ApiKeyResponse An API key with its associated metadata. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ApmStatsQueryColumnType.md b/api_docs/v1/ApmStatsQueryColumnType.md index 5869084bfbf..af498078d25 100644 --- a/api_docs/v1/ApmStatsQueryColumnType.md +++ b/api_docs/v1/ApmStatsQueryColumnType.md @@ -3,6 +3,7 @@ # ApmStatsQueryColumnType Column properties. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ApmStatsQueryDefinition.md b/api_docs/v1/ApmStatsQueryDefinition.md index 52c191988a8..58f88e39d56 100644 --- a/api_docs/v1/ApmStatsQueryDefinition.md +++ b/api_docs/v1/ApmStatsQueryDefinition.md @@ -3,6 +3,7 @@ # ApmStatsQueryDefinition The APM stats query for table and distributions widgets. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ApplicationKey.md b/api_docs/v1/ApplicationKey.md index b48fbf6a6a4..abbd7268cf6 100644 --- a/api_docs/v1/ApplicationKey.md +++ b/api_docs/v1/ApplicationKey.md @@ -3,6 +3,7 @@ # ApplicationKey An application key with its associated metadata. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ApplicationKeyListResponse.md b/api_docs/v1/ApplicationKeyListResponse.md index 4b6d161299d..52e697d357a 100644 --- a/api_docs/v1/ApplicationKeyListResponse.md +++ b/api_docs/v1/ApplicationKeyListResponse.md @@ -3,6 +3,7 @@ # ApplicationKeyListResponse An application key response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ApplicationKeyResponse.md b/api_docs/v1/ApplicationKeyResponse.md index 665bf6cb341..89cf2edeb0e 100644 --- a/api_docs/v1/ApplicationKeyResponse.md +++ b/api_docs/v1/ApplicationKeyResponse.md @@ -3,6 +3,7 @@ # ApplicationKeyResponse An application key response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AuthenticationValidationResponse.md b/api_docs/v1/AuthenticationValidationResponse.md index 7706c0f8675..a153072a550 100644 --- a/api_docs/v1/AuthenticationValidationResponse.md +++ b/api_docs/v1/AuthenticationValidationResponse.md @@ -3,6 +3,7 @@ # AuthenticationValidationResponse Represent validation endpoint responses. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AzureAccount.md b/api_docs/v1/AzureAccount.md index b6d745aef74..a8a5c4cdb68 100644 --- a/api_docs/v1/AzureAccount.md +++ b/api_docs/v1/AzureAccount.md @@ -3,6 +3,7 @@ # AzureAccount Datadog-Azure integrations configured for your organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/CancelDowntimesByScopeRequest.md b/api_docs/v1/CancelDowntimesByScopeRequest.md index 660956c32d6..15cc7749f75 100644 --- a/api_docs/v1/CancelDowntimesByScopeRequest.md +++ b/api_docs/v1/CancelDowntimesByScopeRequest.md @@ -3,6 +3,7 @@ # CancelDowntimesByScopeRequest Cancel downtimes according to scope. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/CanceledDowntimesIds.md b/api_docs/v1/CanceledDowntimesIds.md index fa8a36a49aa..b723591e2ba 100644 --- a/api_docs/v1/CanceledDowntimesIds.md +++ b/api_docs/v1/CanceledDowntimesIds.md @@ -3,6 +3,7 @@ # CanceledDowntimesIds Object containing array of IDs of canceled downtimes. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ChangeWidgetDefinition.md b/api_docs/v1/ChangeWidgetDefinition.md index 7f7ea38029b..dabd3029e0f 100644 --- a/api_docs/v1/ChangeWidgetDefinition.md +++ b/api_docs/v1/ChangeWidgetDefinition.md @@ -3,6 +3,7 @@ # ChangeWidgetDefinition The Change graph shows you the change in a value over the time period chosen. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ChangeWidgetRequest.md b/api_docs/v1/ChangeWidgetRequest.md index 1a49bf31d7f..673228f7a11 100644 --- a/api_docs/v1/ChangeWidgetRequest.md +++ b/api_docs/v1/ChangeWidgetRequest.md @@ -3,6 +3,7 @@ # ChangeWidgetRequest Updated change widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/CheckCanDeleteMonitorResponse.md b/api_docs/v1/CheckCanDeleteMonitorResponse.md index 5e621e06fd4..df7cebed16b 100644 --- a/api_docs/v1/CheckCanDeleteMonitorResponse.md +++ b/api_docs/v1/CheckCanDeleteMonitorResponse.md @@ -3,6 +3,7 @@ # CheckCanDeleteMonitorResponse Response of monitor IDs that can or can't be safely deleted. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/CheckCanDeleteMonitorResponseData.md b/api_docs/v1/CheckCanDeleteMonitorResponseData.md index 8407492da6f..b7959d744a9 100644 --- a/api_docs/v1/CheckCanDeleteMonitorResponseData.md +++ b/api_docs/v1/CheckCanDeleteMonitorResponseData.md @@ -3,6 +3,7 @@ # CheckCanDeleteMonitorResponseData Wrapper object with the list of monitor IDs. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/CheckCanDeleteSLOResponse.md b/api_docs/v1/CheckCanDeleteSLOResponse.md index d632d5e7c65..0e63de22b74 100644 --- a/api_docs/v1/CheckCanDeleteSLOResponse.md +++ b/api_docs/v1/CheckCanDeleteSLOResponse.md @@ -3,6 +3,7 @@ # CheckCanDeleteSLOResponse A service level objective response containing the requested object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/CheckCanDeleteSLOResponseData.md b/api_docs/v1/CheckCanDeleteSLOResponseData.md index 8f91fb5ebb6..15686c59f51 100644 --- a/api_docs/v1/CheckCanDeleteSLOResponseData.md +++ b/api_docs/v1/CheckCanDeleteSLOResponseData.md @@ -3,6 +3,7 @@ # CheckCanDeleteSLOResponseData An array of service level objective objects. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/CheckStatusWidgetDefinition.md b/api_docs/v1/CheckStatusWidgetDefinition.md index 5942e93ecc8..28448bf785d 100644 --- a/api_docs/v1/CheckStatusWidgetDefinition.md +++ b/api_docs/v1/CheckStatusWidgetDefinition.md @@ -3,6 +3,7 @@ # CheckStatusWidgetDefinition Check status shows the current status or number of results for any check performed. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/Creator.md b/api_docs/v1/Creator.md index 6b3678871e5..5fcddcb80fc 100644 --- a/api_docs/v1/Creator.md +++ b/api_docs/v1/Creator.md @@ -3,6 +3,7 @@ # Creator Object describing the creator of the shared element. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/Dashboard.md b/api_docs/v1/Dashboard.md index d000bcd5771..7ada7bee3be 100644 --- a/api_docs/v1/Dashboard.md +++ b/api_docs/v1/Dashboard.md @@ -3,6 +3,7 @@ # Dashboard A dashboard is Datadog’s tool for visually tracking, analyzing, and displaying key performance metrics, which enable you to monitor the health of your infrastructure. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DashboardDeleteResponse.md b/api_docs/v1/DashboardDeleteResponse.md index 1a497cde87a..8a56dd00c28 100644 --- a/api_docs/v1/DashboardDeleteResponse.md +++ b/api_docs/v1/DashboardDeleteResponse.md @@ -3,6 +3,7 @@ # DashboardDeleteResponse Response from the delete dashboard call. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DashboardList.md b/api_docs/v1/DashboardList.md index efe681816a9..d97304453ef 100644 --- a/api_docs/v1/DashboardList.md +++ b/api_docs/v1/DashboardList.md @@ -3,6 +3,7 @@ # DashboardList Your Datadog Dashboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DashboardListDeleteResponse.md b/api_docs/v1/DashboardListDeleteResponse.md index ab74c5f49c6..dd6bea28451 100644 --- a/api_docs/v1/DashboardListDeleteResponse.md +++ b/api_docs/v1/DashboardListDeleteResponse.md @@ -3,6 +3,7 @@ # DashboardListDeleteResponse Deleted dashboard details. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DashboardListListResponse.md b/api_docs/v1/DashboardListListResponse.md index 62b3c10c8ca..57478be4191 100644 --- a/api_docs/v1/DashboardListListResponse.md +++ b/api_docs/v1/DashboardListListResponse.md @@ -3,6 +3,7 @@ # DashboardListListResponse Information on your dashboard lists. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DashboardSummary.md b/api_docs/v1/DashboardSummary.md index 1e4c27d52a4..b6a26e44746 100644 --- a/api_docs/v1/DashboardSummary.md +++ b/api_docs/v1/DashboardSummary.md @@ -3,6 +3,7 @@ # DashboardSummary Dashboard summary response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DashboardSummaryDefinition.md b/api_docs/v1/DashboardSummaryDefinition.md index 1c2c018d343..e55943393b1 100644 --- a/api_docs/v1/DashboardSummaryDefinition.md +++ b/api_docs/v1/DashboardSummaryDefinition.md @@ -3,6 +3,7 @@ # DashboardSummaryDefinition Dashboard definition. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DashboardTemplateVariable.md b/api_docs/v1/DashboardTemplateVariable.md index 5cf4e0376fa..894f6197be1 100644 --- a/api_docs/v1/DashboardTemplateVariable.md +++ b/api_docs/v1/DashboardTemplateVariable.md @@ -3,6 +3,7 @@ # DashboardTemplateVariable Template variable. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DashboardTemplateVariablePreset.md b/api_docs/v1/DashboardTemplateVariablePreset.md index 0e758b9c3bc..7094fe63562 100644 --- a/api_docs/v1/DashboardTemplateVariablePreset.md +++ b/api_docs/v1/DashboardTemplateVariablePreset.md @@ -3,6 +3,7 @@ # DashboardTemplateVariablePreset Template variables saved views. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DashboardTemplateVariablePresetValue.md b/api_docs/v1/DashboardTemplateVariablePresetValue.md index d22b045ea03..b5978357c0f 100644 --- a/api_docs/v1/DashboardTemplateVariablePresetValue.md +++ b/api_docs/v1/DashboardTemplateVariablePresetValue.md @@ -3,6 +3,7 @@ # DashboardTemplateVariablePresetValue Template variables saved views. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DeletedMonitor.md b/api_docs/v1/DeletedMonitor.md index c5c494f32fb..88721bf78f4 100644 --- a/api_docs/v1/DeletedMonitor.md +++ b/api_docs/v1/DeletedMonitor.md @@ -3,6 +3,7 @@ # DeletedMonitor Response from the delete monitor call. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DistributionWidgetDefinition.md b/api_docs/v1/DistributionWidgetDefinition.md index a5441f5e04c..2d8abdcdb20 100644 --- a/api_docs/v1/DistributionWidgetDefinition.md +++ b/api_docs/v1/DistributionWidgetDefinition.md @@ -3,6 +3,7 @@ # DistributionWidgetDefinition The Distribution visualization is another way of showing metrics aggregated across one or several tags, such as hosts. Unlike the heat map, a distribution graph’s x-axis is quantity rather than time. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DistributionWidgetRequest.md b/api_docs/v1/DistributionWidgetRequest.md index 6c50d9d4dd5..57f92ef37a8 100644 --- a/api_docs/v1/DistributionWidgetRequest.md +++ b/api_docs/v1/DistributionWidgetRequest.md @@ -3,6 +3,7 @@ # DistributionWidgetRequest Updated distribution widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/Downtime.md b/api_docs/v1/Downtime.md index 70dd36c8fb7..0ab93d282ae 100644 --- a/api_docs/v1/Downtime.md +++ b/api_docs/v1/Downtime.md @@ -3,6 +3,7 @@ # Downtime Downtiming gives you greater control over monitor notifications by allowing you to globally exclude scopes from alerting. Downtime settings, which can be scheduled with start and end times, prevent all alerting related to specified Datadog tags. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DowntimeRecurrence.md b/api_docs/v1/DowntimeRecurrence.md index 0ece4edfcd6..bf34de88257 100644 --- a/api_docs/v1/DowntimeRecurrence.md +++ b/api_docs/v1/DowntimeRecurrence.md @@ -3,6 +3,7 @@ # DowntimeRecurrence An object defining the recurrence of the downtime. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/Event.md b/api_docs/v1/Event.md index ec4e78ec490..04b48b640c7 100644 --- a/api_docs/v1/Event.md +++ b/api_docs/v1/Event.md @@ -3,6 +3,7 @@ # Event Object representing an event. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/EventListResponse.md b/api_docs/v1/EventListResponse.md index 72af834ce1d..cfa305391c9 100644 --- a/api_docs/v1/EventListResponse.md +++ b/api_docs/v1/EventListResponse.md @@ -3,6 +3,7 @@ # EventListResponse An event list response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/EventQueryDefinition.md b/api_docs/v1/EventQueryDefinition.md index 7ad884308ee..fa69fb4978f 100644 --- a/api_docs/v1/EventQueryDefinition.md +++ b/api_docs/v1/EventQueryDefinition.md @@ -3,6 +3,7 @@ # EventQueryDefinition The event query. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/EventResponse.md b/api_docs/v1/EventResponse.md index db8a622c417..bac5f5c59af 100644 --- a/api_docs/v1/EventResponse.md +++ b/api_docs/v1/EventResponse.md @@ -3,6 +3,7 @@ # EventResponse Object containing an event response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/EventStreamWidgetDefinition.md b/api_docs/v1/EventStreamWidgetDefinition.md index d86bae3802c..000fb7216a6 100644 --- a/api_docs/v1/EventStreamWidgetDefinition.md +++ b/api_docs/v1/EventStreamWidgetDefinition.md @@ -3,6 +3,7 @@ # EventStreamWidgetDefinition The event stream is a widget version of the stream of events on the Event Stream view. Only available on FREE layout dashboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/EventTimelineWidgetDefinition.md b/api_docs/v1/EventTimelineWidgetDefinition.md index 337b7318cbc..17cfd271a91 100644 --- a/api_docs/v1/EventTimelineWidgetDefinition.md +++ b/api_docs/v1/EventTimelineWidgetDefinition.md @@ -3,6 +3,7 @@ # EventTimelineWidgetDefinition The event timeline is a widget version of the timeline that appears at the top of the Event Stream view. Only available on FREE layout dashboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/FormulaAndFunctionEventQueryDefinition.md b/api_docs/v1/FormulaAndFunctionEventQueryDefinition.md index 47a84c56426..fbf537f5020 100644 --- a/api_docs/v1/FormulaAndFunctionEventQueryDefinition.md +++ b/api_docs/v1/FormulaAndFunctionEventQueryDefinition.md @@ -3,6 +3,7 @@ # FormulaAndFunctionEventQueryDefinition A formula and functions events query. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/FormulaAndFunctionEventQueryDefinitionCompute.md b/api_docs/v1/FormulaAndFunctionEventQueryDefinitionCompute.md index b90ae5eac4b..b1da3439075 100644 --- a/api_docs/v1/FormulaAndFunctionEventQueryDefinitionCompute.md +++ b/api_docs/v1/FormulaAndFunctionEventQueryDefinitionCompute.md @@ -3,6 +3,7 @@ # FormulaAndFunctionEventQueryDefinitionCompute Compute options. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/FormulaAndFunctionEventQueryDefinitionSearch.md b/api_docs/v1/FormulaAndFunctionEventQueryDefinitionSearch.md index 6ce4d53fb23..c9edcb23a77 100644 --- a/api_docs/v1/FormulaAndFunctionEventQueryDefinitionSearch.md +++ b/api_docs/v1/FormulaAndFunctionEventQueryDefinitionSearch.md @@ -3,6 +3,7 @@ # FormulaAndFunctionEventQueryDefinitionSearch Search options. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/FormulaAndFunctionEventQueryGroupBy.md b/api_docs/v1/FormulaAndFunctionEventQueryGroupBy.md index b232a8fe84f..42222719d53 100644 --- a/api_docs/v1/FormulaAndFunctionEventQueryGroupBy.md +++ b/api_docs/v1/FormulaAndFunctionEventQueryGroupBy.md @@ -3,6 +3,7 @@ # FormulaAndFunctionEventQueryGroupBy List of objects used to group by. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/FormulaAndFunctionEventQueryGroupBySort.md b/api_docs/v1/FormulaAndFunctionEventQueryGroupBySort.md index e3ea039d3ba..ce6e3d7c6db 100644 --- a/api_docs/v1/FormulaAndFunctionEventQueryGroupBySort.md +++ b/api_docs/v1/FormulaAndFunctionEventQueryGroupBySort.md @@ -3,6 +3,7 @@ # FormulaAndFunctionEventQueryGroupBySort Options for sorting group by results. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/FormulaAndFunctionMetricQueryDefinition.md b/api_docs/v1/FormulaAndFunctionMetricQueryDefinition.md index a6a0d24794b..b2eaf47b05e 100644 --- a/api_docs/v1/FormulaAndFunctionMetricQueryDefinition.md +++ b/api_docs/v1/FormulaAndFunctionMetricQueryDefinition.md @@ -3,6 +3,7 @@ # FormulaAndFunctionMetricQueryDefinition A formula and functions metrics query. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/FormulaAndFunctionProcessQueryDefinition.md b/api_docs/v1/FormulaAndFunctionProcessQueryDefinition.md index bcab31e627a..609ee5be855 100644 --- a/api_docs/v1/FormulaAndFunctionProcessQueryDefinition.md +++ b/api_docs/v1/FormulaAndFunctionProcessQueryDefinition.md @@ -3,6 +3,7 @@ # FormulaAndFunctionProcessQueryDefinition Process query using formulas and functions. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/FreeTextWidgetDefinition.md b/api_docs/v1/FreeTextWidgetDefinition.md index 3aa72a94312..5aab4166105 100644 --- a/api_docs/v1/FreeTextWidgetDefinition.md +++ b/api_docs/v1/FreeTextWidgetDefinition.md @@ -3,6 +3,7 @@ # FreeTextWidgetDefinition Free text is a widget that allows you to add headings to your screenboard. Commonly used to state the overall purpose of the dashboard. Only available on FREE layout dashboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/GCPAccount.md b/api_docs/v1/GCPAccount.md index 0388346626e..860fdd4ccd0 100644 --- a/api_docs/v1/GCPAccount.md +++ b/api_docs/v1/GCPAccount.md @@ -3,6 +3,7 @@ # GCPAccount Your Google Cloud Platform Account. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/GeomapWidgetDefinition.md b/api_docs/v1/GeomapWidgetDefinition.md index 2ddd9bfadd9..c23fb9abeb3 100644 --- a/api_docs/v1/GeomapWidgetDefinition.md +++ b/api_docs/v1/GeomapWidgetDefinition.md @@ -3,6 +3,7 @@ # GeomapWidgetDefinition This visualization displays a series of values by country on a world map. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/GeomapWidgetDefinitionStyle.md b/api_docs/v1/GeomapWidgetDefinitionStyle.md index f80416bcca8..a01f562e01e 100644 --- a/api_docs/v1/GeomapWidgetDefinitionStyle.md +++ b/api_docs/v1/GeomapWidgetDefinitionStyle.md @@ -3,6 +3,7 @@ # GeomapWidgetDefinitionStyle The style to apply to the widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/GeomapWidgetDefinitionView.md b/api_docs/v1/GeomapWidgetDefinitionView.md index e02920fca48..552685b21e1 100644 --- a/api_docs/v1/GeomapWidgetDefinitionView.md +++ b/api_docs/v1/GeomapWidgetDefinitionView.md @@ -3,6 +3,7 @@ # GeomapWidgetDefinitionView The view of the world that the map should render. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/GeomapWidgetRequest.md b/api_docs/v1/GeomapWidgetRequest.md index de6effc990e..903ade2f8b1 100644 --- a/api_docs/v1/GeomapWidgetRequest.md +++ b/api_docs/v1/GeomapWidgetRequest.md @@ -3,6 +3,7 @@ # GeomapWidgetRequest An updated geomap widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/GraphSnapshot.md b/api_docs/v1/GraphSnapshot.md index d941280a0e1..919f57ce866 100644 --- a/api_docs/v1/GraphSnapshot.md +++ b/api_docs/v1/GraphSnapshot.md @@ -3,6 +3,7 @@ # GraphSnapshot Object representing a graph snapshot. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/GroupWidgetDefinition.md b/api_docs/v1/GroupWidgetDefinition.md index c3e5372197d..6c47f59d785 100644 --- a/api_docs/v1/GroupWidgetDefinition.md +++ b/api_docs/v1/GroupWidgetDefinition.md @@ -3,6 +3,7 @@ # GroupWidgetDefinition The groups widget allows you to keep similar graphs together on your timeboard. Each group has a custom header, can hold one to many graphs, and is collapsible. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HeatMapWidgetDefinition.md b/api_docs/v1/HeatMapWidgetDefinition.md index e7dcc523b06..cc6d7e44dec 100644 --- a/api_docs/v1/HeatMapWidgetDefinition.md +++ b/api_docs/v1/HeatMapWidgetDefinition.md @@ -3,6 +3,7 @@ # HeatMapWidgetDefinition The heat map visualization shows metrics aggregated across many tags, such as hosts. The more hosts that have a particular value, the darker that square is. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HeatMapWidgetRequest.md b/api_docs/v1/HeatMapWidgetRequest.md index 3b408b90d8e..4a7f07d2e5e 100644 --- a/api_docs/v1/HeatMapWidgetRequest.md +++ b/api_docs/v1/HeatMapWidgetRequest.md @@ -3,6 +3,7 @@ # HeatMapWidgetRequest Updated heat map widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/Host.md b/api_docs/v1/Host.md index 741fd9a0477..8dfe1b21acf 100644 --- a/api_docs/v1/Host.md +++ b/api_docs/v1/Host.md @@ -3,6 +3,7 @@ # Host Object representing a host. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HostListResponse.md b/api_docs/v1/HostListResponse.md index 6ae60a5d96b..e3484c17cb5 100644 --- a/api_docs/v1/HostListResponse.md +++ b/api_docs/v1/HostListResponse.md @@ -3,6 +3,7 @@ # HostListResponse Response with Host information from Datadog. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HostMapRequest.md b/api_docs/v1/HostMapRequest.md index 65ad4f294d7..6a02c2467e3 100644 --- a/api_docs/v1/HostMapRequest.md +++ b/api_docs/v1/HostMapRequest.md @@ -3,6 +3,7 @@ # HostMapRequest Updated host map. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HostMapWidgetDefinition.md b/api_docs/v1/HostMapWidgetDefinition.md index 4f02849c67b..e4f372c6aa1 100644 --- a/api_docs/v1/HostMapWidgetDefinition.md +++ b/api_docs/v1/HostMapWidgetDefinition.md @@ -3,6 +3,7 @@ # HostMapWidgetDefinition The host map widget graphs any metric across your hosts using the same visualization available from the main Host Map page. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HostMapWidgetDefinitionRequests.md b/api_docs/v1/HostMapWidgetDefinitionRequests.md index 2f3d3de3dff..e97afd8d2d0 100644 --- a/api_docs/v1/HostMapWidgetDefinitionRequests.md +++ b/api_docs/v1/HostMapWidgetDefinitionRequests.md @@ -3,6 +3,7 @@ # HostMapWidgetDefinitionRequests List of definitions. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HostMapWidgetDefinitionStyle.md b/api_docs/v1/HostMapWidgetDefinitionStyle.md index b84fd8c2cb1..e9f27e2f88b 100644 --- a/api_docs/v1/HostMapWidgetDefinitionStyle.md +++ b/api_docs/v1/HostMapWidgetDefinitionStyle.md @@ -3,6 +3,7 @@ # HostMapWidgetDefinitionStyle The style to apply to the widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HostMeta.md b/api_docs/v1/HostMeta.md index 249c3883dba..7aa4458d4d9 100644 --- a/api_docs/v1/HostMeta.md +++ b/api_docs/v1/HostMeta.md @@ -3,6 +3,7 @@ # HostMeta Metadata associated with your host. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HostMetrics.md b/api_docs/v1/HostMetrics.md index 4d002bbe2f6..ceb57a3e1aa 100644 --- a/api_docs/v1/HostMetrics.md +++ b/api_docs/v1/HostMetrics.md @@ -3,6 +3,7 @@ # HostMetrics Host Metrics collected. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HostMuteResponse.md b/api_docs/v1/HostMuteResponse.md index 55e6b002386..19c4e085dd1 100644 --- a/api_docs/v1/HostMuteResponse.md +++ b/api_docs/v1/HostMuteResponse.md @@ -3,6 +3,7 @@ # HostMuteResponse Response with the list of muted host for your organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HostMuteSettings.md b/api_docs/v1/HostMuteSettings.md index 1a8ace227bb..993c63a30ad 100644 --- a/api_docs/v1/HostMuteSettings.md +++ b/api_docs/v1/HostMuteSettings.md @@ -3,6 +3,7 @@ # HostMuteSettings Combination of settings to mute a host. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HostTags.md b/api_docs/v1/HostTags.md index cfa226c2cdd..4269849b570 100644 --- a/api_docs/v1/HostTags.md +++ b/api_docs/v1/HostTags.md @@ -3,6 +3,7 @@ # HostTags Set of tags to associate with your host. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HostTotals.md b/api_docs/v1/HostTotals.md index c58ddbf19c9..3c6766767a5 100644 --- a/api_docs/v1/HostTotals.md +++ b/api_docs/v1/HostTotals.md @@ -3,6 +3,7 @@ # HostTotals Total number of host currently monitored by Datadog. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/IFrameWidgetDefinition.md b/api_docs/v1/IFrameWidgetDefinition.md index 43322480078..5cfb4803326 100644 --- a/api_docs/v1/IFrameWidgetDefinition.md +++ b/api_docs/v1/IFrameWidgetDefinition.md @@ -3,6 +3,7 @@ # IFrameWidgetDefinition The iframe widget allows you to embed a portion of any other web page on your dashboard. Only available on FREE layout dashboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/IPPrefixesAPI.md b/api_docs/v1/IPPrefixesAPI.md index 7b530d7f252..e050138046e 100644 --- a/api_docs/v1/IPPrefixesAPI.md +++ b/api_docs/v1/IPPrefixesAPI.md @@ -3,6 +3,7 @@ # IPPrefixesAPI Available prefix information for the API endpoints. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/IPPrefixesAPM.md b/api_docs/v1/IPPrefixesAPM.md index c057d57febf..5d3e3461635 100644 --- a/api_docs/v1/IPPrefixesAPM.md +++ b/api_docs/v1/IPPrefixesAPM.md @@ -3,6 +3,7 @@ # IPPrefixesAPM Available prefix information for the APM endpoints. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/IPPrefixesAgents.md b/api_docs/v1/IPPrefixesAgents.md index 70aeda162bf..bcd444408e7 100644 --- a/api_docs/v1/IPPrefixesAgents.md +++ b/api_docs/v1/IPPrefixesAgents.md @@ -3,6 +3,7 @@ # IPPrefixesAgents Available prefix information for the Agent endpoints. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/IPPrefixesLogs.md b/api_docs/v1/IPPrefixesLogs.md index c2ad0402f6b..d6f9da973c8 100644 --- a/api_docs/v1/IPPrefixesLogs.md +++ b/api_docs/v1/IPPrefixesLogs.md @@ -3,6 +3,7 @@ # IPPrefixesLogs Available prefix information for the Logs endpoints. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/IPPrefixesProcess.md b/api_docs/v1/IPPrefixesProcess.md index 63ffd712e3d..d027390e601 100644 --- a/api_docs/v1/IPPrefixesProcess.md +++ b/api_docs/v1/IPPrefixesProcess.md @@ -3,6 +3,7 @@ # IPPrefixesProcess Available prefix information for the Process endpoints. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/IPPrefixesSynthetics.md b/api_docs/v1/IPPrefixesSynthetics.md index 5fd570a8f5a..8e6f69390d0 100644 --- a/api_docs/v1/IPPrefixesSynthetics.md +++ b/api_docs/v1/IPPrefixesSynthetics.md @@ -3,6 +3,7 @@ # IPPrefixesSynthetics Available prefix information for the Synthetics endpoints. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/IPPrefixesWebhooks.md b/api_docs/v1/IPPrefixesWebhooks.md index 239b5b85a3a..f670bc6fb35 100644 --- a/api_docs/v1/IPPrefixesWebhooks.md +++ b/api_docs/v1/IPPrefixesWebhooks.md @@ -3,6 +3,7 @@ # IPPrefixesWebhooks Available prefix information for the Webhook endpoints. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/IPRanges.md b/api_docs/v1/IPRanges.md index 26ed8e10eb5..5c5603cee85 100644 --- a/api_docs/v1/IPRanges.md +++ b/api_docs/v1/IPRanges.md @@ -3,6 +3,7 @@ # IPRanges IP ranges. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/IdpFormData.md b/api_docs/v1/IdpFormData.md index f3709b29cd4..e05407bbf92 100644 --- a/api_docs/v1/IdpFormData.md +++ b/api_docs/v1/IdpFormData.md @@ -3,6 +3,7 @@ # IdpFormData Object describing the IdP configuration. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/IdpResponse.md b/api_docs/v1/IdpResponse.md index d83b3e9d2fd..c6408fcae71 100644 --- a/api_docs/v1/IdpResponse.md +++ b/api_docs/v1/IdpResponse.md @@ -3,6 +3,7 @@ # IdpResponse The IdP response object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ImageWidgetDefinition.md b/api_docs/v1/ImageWidgetDefinition.md index f05493fa8cd..696548a0732 100644 --- a/api_docs/v1/ImageWidgetDefinition.md +++ b/api_docs/v1/ImageWidgetDefinition.md @@ -3,6 +3,7 @@ # ImageWidgetDefinition The image widget allows you to embed an image on your dashboard. An image can be a PNG, JPG, or animated GIF. Only available on FREE layout dashboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/Log.md b/api_docs/v1/Log.md index 631497cb1e1..a57e44e3aa4 100644 --- a/api_docs/v1/Log.md +++ b/api_docs/v1/Log.md @@ -3,6 +3,7 @@ # Log Object describing a log after being processed and stored by Datadog. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogContent.md b/api_docs/v1/LogContent.md index 2b2ab7f5537..3dde2a06f7f 100644 --- a/api_docs/v1/LogContent.md +++ b/api_docs/v1/LogContent.md @@ -3,6 +3,7 @@ # LogContent JSON object containing all log attributes and their associated values. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogQueryDefinition.md b/api_docs/v1/LogQueryDefinition.md index 4125a51b32f..1a1095dc071 100644 --- a/api_docs/v1/LogQueryDefinition.md +++ b/api_docs/v1/LogQueryDefinition.md @@ -3,6 +3,7 @@ # LogQueryDefinition The log query. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogQueryDefinitionGroupBy.md b/api_docs/v1/LogQueryDefinitionGroupBy.md index 7aaf757a612..803ac50f181 100644 --- a/api_docs/v1/LogQueryDefinitionGroupBy.md +++ b/api_docs/v1/LogQueryDefinitionGroupBy.md @@ -3,6 +3,7 @@ # LogQueryDefinitionGroupBy Defined items in the group. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogQueryDefinitionGroupBySort.md b/api_docs/v1/LogQueryDefinitionGroupBySort.md index 5bdfc63238e..f89f49693e2 100644 --- a/api_docs/v1/LogQueryDefinitionGroupBySort.md +++ b/api_docs/v1/LogQueryDefinitionGroupBySort.md @@ -3,6 +3,7 @@ # LogQueryDefinitionGroupBySort Define a sorting method. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogQueryDefinitionSearch.md b/api_docs/v1/LogQueryDefinitionSearch.md index ffbaf40fe29..3769bf054b1 100644 --- a/api_docs/v1/LogQueryDefinitionSearch.md +++ b/api_docs/v1/LogQueryDefinitionSearch.md @@ -3,6 +3,7 @@ # LogQueryDefinitionSearch The query being made on the logs. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogStreamWidgetDefinition.md b/api_docs/v1/LogStreamWidgetDefinition.md index bbaab18adfb..a17c785e2a5 100644 --- a/api_docs/v1/LogStreamWidgetDefinition.md +++ b/api_docs/v1/LogStreamWidgetDefinition.md @@ -3,6 +3,7 @@ # LogStreamWidgetDefinition The Log Stream displays a log flow matching the defined query. Only available on FREE layout dashboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsAPIError.md b/api_docs/v1/LogsAPIError.md index 1dd3c2c1d00..f63e14e9b52 100644 --- a/api_docs/v1/LogsAPIError.md +++ b/api_docs/v1/LogsAPIError.md @@ -3,6 +3,7 @@ # LogsAPIError Error returned by the Logs API + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsAPIErrorResponse.md b/api_docs/v1/LogsAPIErrorResponse.md index e78676f1222..7082a252133 100644 --- a/api_docs/v1/LogsAPIErrorResponse.md +++ b/api_docs/v1/LogsAPIErrorResponse.md @@ -3,6 +3,7 @@ # LogsAPIErrorResponse Response returned by the Logs API when errors occur. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsArithmeticProcessor.md b/api_docs/v1/LogsArithmeticProcessor.md index d9c8a229c6b..107d23388a5 100644 --- a/api_docs/v1/LogsArithmeticProcessor.md +++ b/api_docs/v1/LogsArithmeticProcessor.md @@ -3,6 +3,7 @@ # LogsArithmeticProcessor Use the Arithmetic Processor to add a new attribute (without spaces or special characters in the new attribute name) to a log with the result of the provided formula. This enables you to remap different time attributes with different units into a single attribute, or to compute operations on attributes within the same log. The formula can use parentheses and the basic arithmetic operators `-`, `+`, `*`, `/`. By default, the calculation is skipped if an attribute is missing. Select “Replace missing attribute by 0” to automatically populate missing attribute values with 0 to ensure that the calculation is done. An attribute is missing if it is not found in the log attributes, or if it cannot be converted to a number. *Notes*: - The operator `-` needs to be space split in the formula as it can also be contained in attribute names. - If the target attribute already exists, it is overwritten by the result of the formula. - Results are rounded up to the 9th decimal. For example, if the result of the formula is `0.1234567891`, the actual value stored for the attribute is `0.123456789`. - If you need to scale a unit of measure, see [Scale Filter](https://docs.datadoghq.com/logs/processing/parsing/?tab=filter#matcher-and-filter). + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsAttributeRemapper.md b/api_docs/v1/LogsAttributeRemapper.md index cc5c151e341..fb1b96433db 100644 --- a/api_docs/v1/LogsAttributeRemapper.md +++ b/api_docs/v1/LogsAttributeRemapper.md @@ -3,6 +3,7 @@ # LogsAttributeRemapper The remapper processor remaps any source attribute(s) or tag to another target attribute or tag. Constraints on the tag/attribute name are explained in the [Tag Best Practice documentation](https://docs.datadoghq.com/logs/guide/log-parsing-best-practice). Some additional constraints are applied as `:` or `,` are not allowed in the target tag/attribute name. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsCategoryProcessor.md b/api_docs/v1/LogsCategoryProcessor.md index 0a16c2f6c04..d0e7b37730a 100644 --- a/api_docs/v1/LogsCategoryProcessor.md +++ b/api_docs/v1/LogsCategoryProcessor.md @@ -3,6 +3,7 @@ # LogsCategoryProcessor Use the Category Processor to add a new attribute (without spaces or special characters in the new attribute name) to a log matching a provided search query. Use categories to create groups for an analytical view. For example, URL groups, machine groups, environments, and response time buckets. **Notes**: - The syntax of the query is the one of Logs Explorer search bar. The query can be done on any log attribute or tag, whether it is a facet or not. Wildcards can also be used inside your query. - Once the log has matched one of the Processor queries, it stops. Make sure they are properly ordered in case a log could match several queries. - The names of the categories must be unique. - Once defined in the Category Processor, you can map categories to log status using the Log Status Remapper. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsCategoryProcessorCategory.md b/api_docs/v1/LogsCategoryProcessorCategory.md index 978d8acb3a3..fb1483ff036 100644 --- a/api_docs/v1/LogsCategoryProcessorCategory.md +++ b/api_docs/v1/LogsCategoryProcessorCategory.md @@ -3,6 +3,7 @@ # LogsCategoryProcessorCategory Object describing the logs filter. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsDateRemapper.md b/api_docs/v1/LogsDateRemapper.md index 04611a3aea0..ff18263471c 100644 --- a/api_docs/v1/LogsDateRemapper.md +++ b/api_docs/v1/LogsDateRemapper.md @@ -3,6 +3,7 @@ # LogsDateRemapper As Datadog receives logs, it timestamps them using the value(s) from any of these default attributes. - `timestamp` - `date` - `_timestamp` - `Timestamp` - `eventTime` - `published_date` If your logs put their dates in an attribute not in this list, use the log date Remapper Processor to define their date attribute as the official log timestamp. The recognized date formats are ISO8601, UNIX (the milliseconds EPOCH format), and RFC3164. **Note:** If your logs don’t contain any of the default attributes and you haven’t defined your own date attribute, Datadog timestamps the logs with the date it received them. If multiple log date remapper processors can be applied to a given log, only the first one (according to the pipelines order) is taken into account. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsExclusion.md b/api_docs/v1/LogsExclusion.md index b58abbd939a..6a6c5bb8aae 100644 --- a/api_docs/v1/LogsExclusion.md +++ b/api_docs/v1/LogsExclusion.md @@ -3,6 +3,7 @@ # LogsExclusion Represents the index exclusion filter object from configuration API. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsExclusionFilter.md b/api_docs/v1/LogsExclusionFilter.md index 5d17d667335..0a2b7c52e27 100644 --- a/api_docs/v1/LogsExclusionFilter.md +++ b/api_docs/v1/LogsExclusionFilter.md @@ -3,6 +3,7 @@ # LogsExclusionFilter Exclusion filter is defined by a query, a sampling rule, and a active/inactive toggle. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsFilter.md b/api_docs/v1/LogsFilter.md index ca733d73e09..3c384c93e4b 100644 --- a/api_docs/v1/LogsFilter.md +++ b/api_docs/v1/LogsFilter.md @@ -3,6 +3,7 @@ # LogsFilter Filter for logs. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsGeoIPParser.md b/api_docs/v1/LogsGeoIPParser.md index c673ca57070..baf55997720 100644 --- a/api_docs/v1/LogsGeoIPParser.md +++ b/api_docs/v1/LogsGeoIPParser.md @@ -3,6 +3,7 @@ # LogsGeoIPParser The GeoIP parser takes an IP address attribute and extracts if available the Continent, Country, Subdivision, and City information in the target attribute path. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsGrokParser.md b/api_docs/v1/LogsGrokParser.md index 329de061676..9916ed946c5 100644 --- a/api_docs/v1/LogsGrokParser.md +++ b/api_docs/v1/LogsGrokParser.md @@ -3,6 +3,7 @@ # LogsGrokParser Create custom grok rules to parse the full message or [a specific attribute of your raw event](https://docs.datadoghq.com/logs/processing/parsing/#advanced-settings). For more information, see the [parsing section](https://docs.datadoghq.com/logs/processing/parsing). + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsGrokParserRules.md b/api_docs/v1/LogsGrokParserRules.md index 1a5eb6ea76d..f0d06046be4 100644 --- a/api_docs/v1/LogsGrokParserRules.md +++ b/api_docs/v1/LogsGrokParserRules.md @@ -3,6 +3,7 @@ # LogsGrokParserRules Set of rules for the grok parser. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsIndex.md b/api_docs/v1/LogsIndex.md index 390c69a7ae3..a71f38c9022 100644 --- a/api_docs/v1/LogsIndex.md +++ b/api_docs/v1/LogsIndex.md @@ -3,6 +3,7 @@ # LogsIndex Object describing a Datadog Log index. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsIndexListResponse.md b/api_docs/v1/LogsIndexListResponse.md index 3175263df99..3f1041e7a71 100644 --- a/api_docs/v1/LogsIndexListResponse.md +++ b/api_docs/v1/LogsIndexListResponse.md @@ -3,6 +3,7 @@ # LogsIndexListResponse Object with all Index configurations for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsIndexUpdateRequest.md b/api_docs/v1/LogsIndexUpdateRequest.md index 09074fa4962..4ed902da0e9 100644 --- a/api_docs/v1/LogsIndexUpdateRequest.md +++ b/api_docs/v1/LogsIndexUpdateRequest.md @@ -3,6 +3,7 @@ # LogsIndexUpdateRequest Object for updating a Datadog Log index. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsIndexesOrder.md b/api_docs/v1/LogsIndexesOrder.md index 95d23cf0f53..f53770f3198 100644 --- a/api_docs/v1/LogsIndexesOrder.md +++ b/api_docs/v1/LogsIndexesOrder.md @@ -3,6 +3,7 @@ # LogsIndexesOrder Object containing the ordered list of log index names. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsListRequest.md b/api_docs/v1/LogsListRequest.md index 2af5c8a46e8..8c791354a17 100644 --- a/api_docs/v1/LogsListRequest.md +++ b/api_docs/v1/LogsListRequest.md @@ -3,6 +3,7 @@ # LogsListRequest Object to send with the request to retrieve a list of logs from your Organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsListRequestTime.md b/api_docs/v1/LogsListRequestTime.md index 8012844b9fb..b8a0a266b0b 100644 --- a/api_docs/v1/LogsListRequestTime.md +++ b/api_docs/v1/LogsListRequestTime.md @@ -3,6 +3,7 @@ # LogsListRequestTime Timeframe to retrieve the log from. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsListResponse.md b/api_docs/v1/LogsListResponse.md index b17542d6d14..a76a5aee6a7 100644 --- a/api_docs/v1/LogsListResponse.md +++ b/api_docs/v1/LogsListResponse.md @@ -3,6 +3,7 @@ # LogsListResponse Response object with all logs matching the request and pagination information. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsLookupProcessor.md b/api_docs/v1/LogsLookupProcessor.md index cd8faadee3a..c42cf4493a1 100644 --- a/api_docs/v1/LogsLookupProcessor.md +++ b/api_docs/v1/LogsLookupProcessor.md @@ -3,6 +3,7 @@ # LogsLookupProcessor Use the Lookup Processor to define a mapping between a log attribute and a human readable value saved in the processors mapping table. For example, you can use the Lookup Processor to map an internal service ID into a human readable service name. Alternatively, you could also use it to check if the MAC address that just attempted to connect to the production environment belongs to your list of stolen machines. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsMessageRemapper.md b/api_docs/v1/LogsMessageRemapper.md index a8aefff6f63..ad6ef93a6d6 100644 --- a/api_docs/v1/LogsMessageRemapper.md +++ b/api_docs/v1/LogsMessageRemapper.md @@ -3,6 +3,7 @@ # LogsMessageRemapper The message is a key attribute in Datadog. It is displayed in the message column of the Log Explorer and you can do full string search on it. Use this Processor to define one or more attributes as the official log message. **Note:** If multiple log message remapper processors can be applied to a given log, only the first one (according to the pipeline order) is taken into account. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsPipeline.md b/api_docs/v1/LogsPipeline.md index 07322c20618..0b3b9a42d95 100644 --- a/api_docs/v1/LogsPipeline.md +++ b/api_docs/v1/LogsPipeline.md @@ -3,6 +3,7 @@ # LogsPipeline Pipelines and processors operate on incoming logs, parsing and transforming them into structured attributes for easier querying. **Note**: These endpoints are only available for admin users. Make sure to use an application key created by an admin. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsPipelineProcessor.md b/api_docs/v1/LogsPipelineProcessor.md index 998522dd570..0295e7e662c 100644 --- a/api_docs/v1/LogsPipelineProcessor.md +++ b/api_docs/v1/LogsPipelineProcessor.md @@ -3,6 +3,7 @@ # LogsPipelineProcessor Nested Pipelines are pipelines within a pipeline. Use Nested Pipelines to split the processing into two steps. For example, first use a high-level filtering such as team and then a second level of filtering based on the integration, service, or any other tag or attribute. A pipeline can contain Nested Pipelines and Processors whereas a Nested Pipeline can only contain Processors. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsPipelinesOrder.md b/api_docs/v1/LogsPipelinesOrder.md index 94e4576b069..54b49edb273 100644 --- a/api_docs/v1/LogsPipelinesOrder.md +++ b/api_docs/v1/LogsPipelinesOrder.md @@ -3,6 +3,7 @@ # LogsPipelinesOrder Object containing the ordered list of pipeline IDs. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsQueryCompute.md b/api_docs/v1/LogsQueryCompute.md index 53157828c3d..aa2e310c942 100644 --- a/api_docs/v1/LogsQueryCompute.md +++ b/api_docs/v1/LogsQueryCompute.md @@ -3,6 +3,7 @@ # LogsQueryCompute Define computation for a log query. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsServiceRemapper.md b/api_docs/v1/LogsServiceRemapper.md index 82f6b2221d5..4e41f3888de 100644 --- a/api_docs/v1/LogsServiceRemapper.md +++ b/api_docs/v1/LogsServiceRemapper.md @@ -3,6 +3,7 @@ # LogsServiceRemapper Use this processor if you want to assign one or more attributes as the official service. **Note:** If multiple service remapper processors can be applied to a given log, only the first one (according to the pipeline order) is taken into account. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsStatusRemapper.md b/api_docs/v1/LogsStatusRemapper.md index e84d4fee9c9..2633c5ff996 100644 --- a/api_docs/v1/LogsStatusRemapper.md +++ b/api_docs/v1/LogsStatusRemapper.md @@ -3,6 +3,7 @@ # LogsStatusRemapper Use this Processor if you want to assign some attributes as the official status. Each incoming status value is mapped as follows. - Integers from 0 to 7 map to the Syslog severity standards - Strings beginning with `emerg` or f (case-insensitive) map to `emerg` (0) - Strings beginning with `a` (case-insensitive) map to `alert` (1) - Strings beginning with `c` (case-insensitive) map to `critical` (2) - Strings beginning with `err` (case-insensitive) map to `error` (3) - Strings beginning with `w` (case-insensitive) map to `warning` (4) - Strings beginning with `n` (case-insensitive) map to `notice` (5) - Strings beginning with `i` (case-insensitive) map to `info` (6) - Strings beginning with `d`, `trace` or `verbose` (case-insensitive) map to `debug` (7) - Strings beginning with `o` or matching `OK` or `Success` (case-insensitive) map to OK - All others map to `info` (6) **Note:** If multiple log status remapper processors can be applied to a given log, only the first one (according to the pipelines order) is taken into account. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsStringBuilderProcessor.md b/api_docs/v1/LogsStringBuilderProcessor.md index e2d95bc3145..18884d95ad6 100644 --- a/api_docs/v1/LogsStringBuilderProcessor.md +++ b/api_docs/v1/LogsStringBuilderProcessor.md @@ -3,6 +3,7 @@ # LogsStringBuilderProcessor Use the string builder processor to add a new attribute (without spaces or special characters) to a log with the result of the provided template. This enables aggregation of different attributes or raw strings into a single attribute. The template is defined by both raw text and blocks with the syntax `%{attribute_path}`. **Notes**: - The processor only accepts attributes with values or an array of values in the blocks. - If an attribute cannot be used (object or array of object), it is replaced by an empty string or the entire operation is skipped depending on your selection. - If the target attribute already exists, it is overwritten by the result of the template. - Results of the template cannot exceed 256 characters. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsTraceRemapper.md b/api_docs/v1/LogsTraceRemapper.md index efb6beb37c8..1ac427f9205 100644 --- a/api_docs/v1/LogsTraceRemapper.md +++ b/api_docs/v1/LogsTraceRemapper.md @@ -3,6 +3,7 @@ # LogsTraceRemapper There are two ways to improve correlation between application traces and logs. 1. Follow the documentation on [how to inject a trace ID in the application logs](https://docs.datadoghq.com/tracing/connect_logs_and_traces) and by default log integrations take care of all the rest of the setup. 2. Use the Trace remapper processor to define a log attribute as its associated trace ID. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsURLParser.md b/api_docs/v1/LogsURLParser.md index 2008799fe6f..0ead37c9d39 100644 --- a/api_docs/v1/LogsURLParser.md +++ b/api_docs/v1/LogsURLParser.md @@ -3,6 +3,7 @@ # LogsURLParser This processor extracts query parameters and other important parameters from a URL. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsUserAgentParser.md b/api_docs/v1/LogsUserAgentParser.md index 207e7723bb9..3159dd39c07 100644 --- a/api_docs/v1/LogsUserAgentParser.md +++ b/api_docs/v1/LogsUserAgentParser.md @@ -3,6 +3,7 @@ # LogsUserAgentParser The User-Agent parser takes a User-Agent attribute and extracts the OS, browser, device, and other user data. It recognizes major bots like the Google Bot, Yahoo Slurp, and Bing. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MetricMetadata.md b/api_docs/v1/MetricMetadata.md index 10ccc8911e0..61a6b8080f8 100644 --- a/api_docs/v1/MetricMetadata.md +++ b/api_docs/v1/MetricMetadata.md @@ -3,6 +3,7 @@ # MetricMetadata Object with all metric related metadata. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MetricSearchResponse.md b/api_docs/v1/MetricSearchResponse.md index ccde4dc52e4..b7680dce742 100644 --- a/api_docs/v1/MetricSearchResponse.md +++ b/api_docs/v1/MetricSearchResponse.md @@ -3,6 +3,7 @@ # MetricSearchResponse Object containing the list of metrics matching the search query. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MetricSearchResponseResults.md b/api_docs/v1/MetricSearchResponseResults.md index 9cdd82dbd8e..09e138f2e07 100644 --- a/api_docs/v1/MetricSearchResponseResults.md +++ b/api_docs/v1/MetricSearchResponseResults.md @@ -3,6 +3,7 @@ # MetricSearchResponseResults Search result. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MetricsListResponse.md b/api_docs/v1/MetricsListResponse.md index b9acb80ea32..47b63b9e7e8 100644 --- a/api_docs/v1/MetricsListResponse.md +++ b/api_docs/v1/MetricsListResponse.md @@ -3,6 +3,7 @@ # MetricsListResponse Object listing all metric names stored by Datadog since a given time. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MetricsQueryMetadata.md b/api_docs/v1/MetricsQueryMetadata.md index e1bfd9edc28..bed355e0589 100644 --- a/api_docs/v1/MetricsQueryMetadata.md +++ b/api_docs/v1/MetricsQueryMetadata.md @@ -3,6 +3,7 @@ # MetricsQueryMetadata Object containing all metric names returned and their associated metadata. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MetricsQueryResponse.md b/api_docs/v1/MetricsQueryResponse.md index 964e90d37af..fa6d0874f5a 100644 --- a/api_docs/v1/MetricsQueryResponse.md +++ b/api_docs/v1/MetricsQueryResponse.md @@ -3,6 +3,7 @@ # MetricsQueryResponse Response Object that includes your query and the list of metrics retrieved. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MetricsQueryUnit.md b/api_docs/v1/MetricsQueryUnit.md index c5b21d1abcb..c60898cbc51 100644 --- a/api_docs/v1/MetricsQueryUnit.md +++ b/api_docs/v1/MetricsQueryUnit.md @@ -3,6 +3,7 @@ # MetricsQueryUnit Object containing the metric unit family, scale factor, name, and short name. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/Monitor.md b/api_docs/v1/Monitor.md index d873154a5b2..4c5571fcdb1 100644 --- a/api_docs/v1/Monitor.md +++ b/api_docs/v1/Monitor.md @@ -3,6 +3,7 @@ # Monitor Object describing a monitor. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MonitorOptions.md b/api_docs/v1/MonitorOptions.md index 30f162fcdba..59172d50874 100644 --- a/api_docs/v1/MonitorOptions.md +++ b/api_docs/v1/MonitorOptions.md @@ -3,6 +3,7 @@ # MonitorOptions List of options associated with your monitor. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MonitorOptionsAggregation.md b/api_docs/v1/MonitorOptionsAggregation.md index 85c8926c69d..c7a08b487c3 100644 --- a/api_docs/v1/MonitorOptionsAggregation.md +++ b/api_docs/v1/MonitorOptionsAggregation.md @@ -3,6 +3,7 @@ # MonitorOptionsAggregation Type of aggregation performed in the monitor query. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MonitorState.md b/api_docs/v1/MonitorState.md index af18728b96b..1f494bddb78 100644 --- a/api_docs/v1/MonitorState.md +++ b/api_docs/v1/MonitorState.md @@ -3,6 +3,7 @@ # MonitorState Wrapper object with the different monitor states. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MonitorStateGroup.md b/api_docs/v1/MonitorStateGroup.md index b167f9dffdc..0ef8c1cfa11 100644 --- a/api_docs/v1/MonitorStateGroup.md +++ b/api_docs/v1/MonitorStateGroup.md @@ -3,6 +3,7 @@ # MonitorStateGroup Monitor state for a single group. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MonitorSummaryWidgetDefinition.md b/api_docs/v1/MonitorSummaryWidgetDefinition.md index 528cda09bbc..f066959ccf9 100644 --- a/api_docs/v1/MonitorSummaryWidgetDefinition.md +++ b/api_docs/v1/MonitorSummaryWidgetDefinition.md @@ -3,6 +3,7 @@ # MonitorSummaryWidgetDefinition The monitor summary widget displays a summary view of all your Datadog monitors, or a subset based on a query. Only available on FREE layout dashboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MonitorThresholdWindowOptions.md b/api_docs/v1/MonitorThresholdWindowOptions.md index f283ea7a9c8..e88a6d52ea6 100644 --- a/api_docs/v1/MonitorThresholdWindowOptions.md +++ b/api_docs/v1/MonitorThresholdWindowOptions.md @@ -3,6 +3,7 @@ # MonitorThresholdWindowOptions Alerting time window options. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MonitorThresholds.md b/api_docs/v1/MonitorThresholds.md index de71e034a3e..5d6d9820a39 100644 --- a/api_docs/v1/MonitorThresholds.md +++ b/api_docs/v1/MonitorThresholds.md @@ -3,6 +3,7 @@ # MonitorThresholds List of the different monitor threshold available. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MonitorUpdateRequest.md b/api_docs/v1/MonitorUpdateRequest.md index 6f1362524f8..1e57e0487bc 100644 --- a/api_docs/v1/MonitorUpdateRequest.md +++ b/api_docs/v1/MonitorUpdateRequest.md @@ -3,6 +3,7 @@ # MonitorUpdateRequest Object describing a monitor update request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/NoteWidgetDefinition.md b/api_docs/v1/NoteWidgetDefinition.md index 14e2f0bd9d6..7aa3eb44a7f 100644 --- a/api_docs/v1/NoteWidgetDefinition.md +++ b/api_docs/v1/NoteWidgetDefinition.md @@ -3,6 +3,7 @@ # NoteWidgetDefinition The notes and links widget is similar to free text widget, but allows for more formatting options. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/Organization.md b/api_docs/v1/Organization.md index a200dbbc679..81c22b0a2e4 100644 --- a/api_docs/v1/Organization.md +++ b/api_docs/v1/Organization.md @@ -3,6 +3,7 @@ # Organization Create, edit, and manage organizations. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/OrganizationBilling.md b/api_docs/v1/OrganizationBilling.md index 21d9ba05593..d31317a59f0 100644 --- a/api_docs/v1/OrganizationBilling.md +++ b/api_docs/v1/OrganizationBilling.md @@ -3,6 +3,7 @@ # OrganizationBilling A JSON array of billing type. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/OrganizationCreateBody.md b/api_docs/v1/OrganizationCreateBody.md index bcfb477ba77..2fd5f374881 100644 --- a/api_docs/v1/OrganizationCreateBody.md +++ b/api_docs/v1/OrganizationCreateBody.md @@ -3,6 +3,7 @@ # OrganizationCreateBody Object describing an organization to create. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/OrganizationCreateResponse.md b/api_docs/v1/OrganizationCreateResponse.md index 53e20cf675a..4314b2f6c2a 100644 --- a/api_docs/v1/OrganizationCreateResponse.md +++ b/api_docs/v1/OrganizationCreateResponse.md @@ -3,6 +3,7 @@ # OrganizationCreateResponse Response object for an organization creation. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/OrganizationListResponse.md b/api_docs/v1/OrganizationListResponse.md index eba51c07bab..fc246b9187e 100644 --- a/api_docs/v1/OrganizationListResponse.md +++ b/api_docs/v1/OrganizationListResponse.md @@ -3,6 +3,7 @@ # OrganizationListResponse Response with the list of organizations. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/OrganizationResponse.md b/api_docs/v1/OrganizationResponse.md index e1236141cff..8d63bab5e7b 100644 --- a/api_docs/v1/OrganizationResponse.md +++ b/api_docs/v1/OrganizationResponse.md @@ -3,6 +3,7 @@ # OrganizationResponse Response with an organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/OrganizationSettings.md b/api_docs/v1/OrganizationSettings.md index fd5a6e0195a..8ef701f3339 100644 --- a/api_docs/v1/OrganizationSettings.md +++ b/api_docs/v1/OrganizationSettings.md @@ -3,6 +3,7 @@ # OrganizationSettings A JSON array of settings. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/OrganizationSettingsSaml.md b/api_docs/v1/OrganizationSettingsSaml.md index 73da4e87384..5520545a4c7 100644 --- a/api_docs/v1/OrganizationSettingsSaml.md +++ b/api_docs/v1/OrganizationSettingsSaml.md @@ -3,6 +3,7 @@ # OrganizationSettingsSaml Set the boolean property enabled to enable or disable single sign on with SAML. See the SAML documentation for more information about all SAML settings. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/OrganizationSettingsSamlAutocreateUsersDomains.md b/api_docs/v1/OrganizationSettingsSamlAutocreateUsersDomains.md index 47cf9235883..ae55953b67f 100644 --- a/api_docs/v1/OrganizationSettingsSamlAutocreateUsersDomains.md +++ b/api_docs/v1/OrganizationSettingsSamlAutocreateUsersDomains.md @@ -3,6 +3,7 @@ # OrganizationSettingsSamlAutocreateUsersDomains Has two properties, `enabled` (boolean) and `domains`, which is a list of domains without the @ symbol. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/OrganizationSettingsSamlIdpInitiatedLogin.md b/api_docs/v1/OrganizationSettingsSamlIdpInitiatedLogin.md index 4c40af16f1f..684ca33893b 100644 --- a/api_docs/v1/OrganizationSettingsSamlIdpInitiatedLogin.md +++ b/api_docs/v1/OrganizationSettingsSamlIdpInitiatedLogin.md @@ -3,6 +3,7 @@ # OrganizationSettingsSamlIdpInitiatedLogin Has one property enabled (boolean). + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/OrganizationSettingsSamlStrictMode.md b/api_docs/v1/OrganizationSettingsSamlStrictMode.md index 9cf9a1d3998..561f05d039e 100644 --- a/api_docs/v1/OrganizationSettingsSamlStrictMode.md +++ b/api_docs/v1/OrganizationSettingsSamlStrictMode.md @@ -3,6 +3,7 @@ # OrganizationSettingsSamlStrictMode Has one property enabled (boolean). + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/OrganizationSubscription.md b/api_docs/v1/OrganizationSubscription.md index 832b4a83515..e30264edf26 100644 --- a/api_docs/v1/OrganizationSubscription.md +++ b/api_docs/v1/OrganizationSubscription.md @@ -3,6 +3,7 @@ # OrganizationSubscription Subscription definition. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/PagerDutyService.md b/api_docs/v1/PagerDutyService.md index 01aa59f64a3..fed8aec255e 100644 --- a/api_docs/v1/PagerDutyService.md +++ b/api_docs/v1/PagerDutyService.md @@ -3,6 +3,7 @@ # PagerDutyService The PagerDuty service that is available for integration with Datadog. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/PagerDutyServiceKey.md b/api_docs/v1/PagerDutyServiceKey.md index fa82c8033b5..b10c8fe2d4c 100644 --- a/api_docs/v1/PagerDutyServiceKey.md +++ b/api_docs/v1/PagerDutyServiceKey.md @@ -3,6 +3,7 @@ # PagerDutyServiceKey PagerDuty service object key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/PagerDutyServiceName.md b/api_docs/v1/PagerDutyServiceName.md index f1dd19ad999..a01f00e05ef 100644 --- a/api_docs/v1/PagerDutyServiceName.md +++ b/api_docs/v1/PagerDutyServiceName.md @@ -3,6 +3,7 @@ # PagerDutyServiceName PagerDuty service object name. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ProcessQueryDefinition.md b/api_docs/v1/ProcessQueryDefinition.md index 2824e3a6b3e..2e395b0df93 100644 --- a/api_docs/v1/ProcessQueryDefinition.md +++ b/api_docs/v1/ProcessQueryDefinition.md @@ -3,6 +3,7 @@ # ProcessQueryDefinition The process query to use in the widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/QueryValueWidgetDefinition.md b/api_docs/v1/QueryValueWidgetDefinition.md index 5b2371fba5f..8cdcd9c7bba 100644 --- a/api_docs/v1/QueryValueWidgetDefinition.md +++ b/api_docs/v1/QueryValueWidgetDefinition.md @@ -3,6 +3,7 @@ # QueryValueWidgetDefinition Query values display the current value of a given metric, APM, or log query. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/QueryValueWidgetRequest.md b/api_docs/v1/QueryValueWidgetRequest.md index e7118a47697..802533dbca7 100644 --- a/api_docs/v1/QueryValueWidgetRequest.md +++ b/api_docs/v1/QueryValueWidgetRequest.md @@ -3,6 +3,7 @@ # QueryValueWidgetRequest Updated query value widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOBulkDeleteError.md b/api_docs/v1/SLOBulkDeleteError.md index 363eb4cf79d..23696818d22 100644 --- a/api_docs/v1/SLOBulkDeleteError.md +++ b/api_docs/v1/SLOBulkDeleteError.md @@ -3,6 +3,7 @@ # SLOBulkDeleteError Object describing the error. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOBulkDeleteResponse.md b/api_docs/v1/SLOBulkDeleteResponse.md index 827e82d82df..7545b98b81f 100644 --- a/api_docs/v1/SLOBulkDeleteResponse.md +++ b/api_docs/v1/SLOBulkDeleteResponse.md @@ -3,6 +3,7 @@ # SLOBulkDeleteResponse The bulk partial delete service level objective object endpoint response. This endpoint operates on multiple service level objective objects, so it may be partially successful. In such cases, the \"data\" and \"error\" fields in this response indicate which deletions succeeded and failed. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOBulkDeleteResponseData.md b/api_docs/v1/SLOBulkDeleteResponseData.md index c57e162e3d7..e37c2247508 100644 --- a/api_docs/v1/SLOBulkDeleteResponseData.md +++ b/api_docs/v1/SLOBulkDeleteResponseData.md @@ -3,6 +3,7 @@ # SLOBulkDeleteResponseData An array of service level objective objects. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOCorrection.md b/api_docs/v1/SLOCorrection.md index cdf89600851..af4289ee98b 100644 --- a/api_docs/v1/SLOCorrection.md +++ b/api_docs/v1/SLOCorrection.md @@ -3,6 +3,7 @@ # SLOCorrection The response object of a list of SLO corrections + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOCorrectionCreateData.md b/api_docs/v1/SLOCorrectionCreateData.md index deaa00cfdc7..3f6a93db9eb 100644 --- a/api_docs/v1/SLOCorrectionCreateData.md +++ b/api_docs/v1/SLOCorrectionCreateData.md @@ -3,6 +3,7 @@ # SLOCorrectionCreateData The data object associated with the SLO correction to be created + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOCorrectionCreateRequest.md b/api_docs/v1/SLOCorrectionCreateRequest.md index 5f15c1ae61e..4cab40a629b 100644 --- a/api_docs/v1/SLOCorrectionCreateRequest.md +++ b/api_docs/v1/SLOCorrectionCreateRequest.md @@ -3,6 +3,7 @@ # SLOCorrectionCreateRequest An object that defines a correction to be applied to an SLO + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOCorrectionCreateRequestAttributes.md b/api_docs/v1/SLOCorrectionCreateRequestAttributes.md index 9adaabba9c4..435584cf174 100644 --- a/api_docs/v1/SLOCorrectionCreateRequestAttributes.md +++ b/api_docs/v1/SLOCorrectionCreateRequestAttributes.md @@ -3,6 +3,7 @@ # SLOCorrectionCreateRequestAttributes The attribute object associated with the SLO correction to be created + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOCorrectionListResponse.md b/api_docs/v1/SLOCorrectionListResponse.md index 0a88d1837eb..804db15fdc0 100644 --- a/api_docs/v1/SLOCorrectionListResponse.md +++ b/api_docs/v1/SLOCorrectionListResponse.md @@ -3,6 +3,7 @@ # SLOCorrectionListResponse A list of SLO correction objects + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOCorrectionResponse.md b/api_docs/v1/SLOCorrectionResponse.md index 74c929cd317..48c3824e720 100644 --- a/api_docs/v1/SLOCorrectionResponse.md +++ b/api_docs/v1/SLOCorrectionResponse.md @@ -3,6 +3,7 @@ # SLOCorrectionResponse The response object of an SLO correction + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOCorrectionResponseAttributes.md b/api_docs/v1/SLOCorrectionResponseAttributes.md index e5aabfc797c..24a711e6eb8 100644 --- a/api_docs/v1/SLOCorrectionResponseAttributes.md +++ b/api_docs/v1/SLOCorrectionResponseAttributes.md @@ -3,6 +3,7 @@ # SLOCorrectionResponseAttributes The attribute object associated with the SLO correction + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOCorrectionUpdateData.md b/api_docs/v1/SLOCorrectionUpdateData.md index a2b3d8e445e..0a182b9837e 100644 --- a/api_docs/v1/SLOCorrectionUpdateData.md +++ b/api_docs/v1/SLOCorrectionUpdateData.md @@ -3,6 +3,7 @@ # SLOCorrectionUpdateData The data object associated with the SLO correction to be updated + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOCorrectionUpdateRequest.md b/api_docs/v1/SLOCorrectionUpdateRequest.md index 4391f2c7600..144112eede9 100644 --- a/api_docs/v1/SLOCorrectionUpdateRequest.md +++ b/api_docs/v1/SLOCorrectionUpdateRequest.md @@ -3,6 +3,7 @@ # SLOCorrectionUpdateRequest An object that defines a correction to be applied to an SLO + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOCorrectionUpdateRequestAttributes.md b/api_docs/v1/SLOCorrectionUpdateRequestAttributes.md index 591551dc46a..d52afc4f611 100644 --- a/api_docs/v1/SLOCorrectionUpdateRequestAttributes.md +++ b/api_docs/v1/SLOCorrectionUpdateRequestAttributes.md @@ -3,6 +3,7 @@ # SLOCorrectionUpdateRequestAttributes The attribute object associated with the SLO correction to be updated + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLODeleteResponse.md b/api_docs/v1/SLODeleteResponse.md index f80323b16d4..61d2936f9f0 100644 --- a/api_docs/v1/SLODeleteResponse.md +++ b/api_docs/v1/SLODeleteResponse.md @@ -3,6 +3,7 @@ # SLODeleteResponse A response list of all service level objective deleted. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOHistoryMetrics.md b/api_docs/v1/SLOHistoryMetrics.md index 7dd373a2819..6ce4db8f207 100644 --- a/api_docs/v1/SLOHistoryMetrics.md +++ b/api_docs/v1/SLOHistoryMetrics.md @@ -3,6 +3,7 @@ # SLOHistoryMetrics A `metric` based SLO history response. This is not included in responses for `monitor` based SLOs. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOHistoryMetricsSeries.md b/api_docs/v1/SLOHistoryMetricsSeries.md index d0035dfa0de..67ad0daa1f0 100644 --- a/api_docs/v1/SLOHistoryMetricsSeries.md +++ b/api_docs/v1/SLOHistoryMetricsSeries.md @@ -3,6 +3,7 @@ # SLOHistoryMetricsSeries A representation of `metric` based SLO time series for the provided queries. This is the same response type from `batch_query` endpoint. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOHistoryMetricsSeriesMetadata.md b/api_docs/v1/SLOHistoryMetricsSeriesMetadata.md index 4c99cec9294..8e3eddb1a38 100644 --- a/api_docs/v1/SLOHistoryMetricsSeriesMetadata.md +++ b/api_docs/v1/SLOHistoryMetricsSeriesMetadata.md @@ -3,6 +3,7 @@ # SLOHistoryMetricsSeriesMetadata Query metadata. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOHistoryMetricsSeriesMetadataUnit.md b/api_docs/v1/SLOHistoryMetricsSeriesMetadataUnit.md index d11744b5813..eb9bcc2bd38 100644 --- a/api_docs/v1/SLOHistoryMetricsSeriesMetadataUnit.md +++ b/api_docs/v1/SLOHistoryMetricsSeriesMetadataUnit.md @@ -3,6 +3,7 @@ # SLOHistoryMetricsSeriesMetadataUnit An Object of metric units. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOHistoryResponse.md b/api_docs/v1/SLOHistoryResponse.md index 7b8da4cf522..aeef34101e7 100644 --- a/api_docs/v1/SLOHistoryResponse.md +++ b/api_docs/v1/SLOHistoryResponse.md @@ -3,6 +3,7 @@ # SLOHistoryResponse A service level objective history response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOHistoryResponseData.md b/api_docs/v1/SLOHistoryResponseData.md index b934fa0b0f8..9da6dbb24ad 100644 --- a/api_docs/v1/SLOHistoryResponseData.md +++ b/api_docs/v1/SLOHistoryResponseData.md @@ -3,6 +3,7 @@ # SLOHistoryResponseData An array of service level objective objects. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOHistoryResponseError.md b/api_docs/v1/SLOHistoryResponseError.md index c5e4184b21f..1b797dc0eb0 100644 --- a/api_docs/v1/SLOHistoryResponseError.md +++ b/api_docs/v1/SLOHistoryResponseError.md @@ -3,6 +3,7 @@ # SLOHistoryResponseError A service level objective response containing the requested history. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOHistorySLIData.md b/api_docs/v1/SLOHistorySLIData.md index da0851e0111..abd092acc37 100644 --- a/api_docs/v1/SLOHistorySLIData.md +++ b/api_docs/v1/SLOHistorySLIData.md @@ -3,6 +3,7 @@ # SLOHistorySLIData An object that holds an SLI value and its associated data. It can represent an SLO's overall SLI value. This can also represent the SLI value for a specific monitor in multi-monitor SLOs, or a group in grouped SLOs. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOListResponse.md b/api_docs/v1/SLOListResponse.md index 9bc8900c295..cd9a89de7b0 100644 --- a/api_docs/v1/SLOListResponse.md +++ b/api_docs/v1/SLOListResponse.md @@ -3,6 +3,7 @@ # SLOListResponse A response with one or more service level objective. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOResponse.md b/api_docs/v1/SLOResponse.md index 979b611e8bb..489bf084f6b 100644 --- a/api_docs/v1/SLOResponse.md +++ b/api_docs/v1/SLOResponse.md @@ -3,6 +3,7 @@ # SLOResponse A service level objective response containing a single service level objective. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOThreshold.md b/api_docs/v1/SLOThreshold.md index 12c7f9e0027..71c0e9db0cb 100644 --- a/api_docs/v1/SLOThreshold.md +++ b/api_docs/v1/SLOThreshold.md @@ -3,6 +3,7 @@ # SLOThreshold SLO thresholds (target and optionally warning) for a single time window. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOWidgetDefinition.md b/api_docs/v1/SLOWidgetDefinition.md index 050d9e32686..a3ab74178a2 100644 --- a/api_docs/v1/SLOWidgetDefinition.md +++ b/api_docs/v1/SLOWidgetDefinition.md @@ -3,6 +3,7 @@ # SLOWidgetDefinition Use the SLO and uptime widget to track your SLOs (Service Level Objectives) and uptime on screenboards and timeboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ScatterPlotRequest.md b/api_docs/v1/ScatterPlotRequest.md index e7daf79761f..c01a22c58aa 100644 --- a/api_docs/v1/ScatterPlotRequest.md +++ b/api_docs/v1/ScatterPlotRequest.md @@ -3,6 +3,7 @@ # ScatterPlotRequest Updated scatter plot. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ScatterPlotWidgetDefinition.md b/api_docs/v1/ScatterPlotWidgetDefinition.md index 72434a3c6e5..b2a6ddbf2c0 100644 --- a/api_docs/v1/ScatterPlotWidgetDefinition.md +++ b/api_docs/v1/ScatterPlotWidgetDefinition.md @@ -3,6 +3,7 @@ # ScatterPlotWidgetDefinition The scatter plot visualization allows you to graph a chosen scope over two different metrics with their respective aggregation. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ScatterPlotWidgetDefinitionRequests.md b/api_docs/v1/ScatterPlotWidgetDefinitionRequests.md index 895c0742ac3..1d7c205122c 100644 --- a/api_docs/v1/ScatterPlotWidgetDefinitionRequests.md +++ b/api_docs/v1/ScatterPlotWidgetDefinitionRequests.md @@ -3,6 +3,7 @@ # ScatterPlotWidgetDefinitionRequests Widget definition. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ServiceLevelObjective.md b/api_docs/v1/ServiceLevelObjective.md index f5ac024ef28..3a12c8e1634 100644 --- a/api_docs/v1/ServiceLevelObjective.md +++ b/api_docs/v1/ServiceLevelObjective.md @@ -3,6 +3,7 @@ # ServiceLevelObjective A service level objective object includes a service level indicator, thresholds for one or more timeframes, and metadata (`name`, `description`, `tags`, etc.). + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ServiceLevelObjectiveQuery.md b/api_docs/v1/ServiceLevelObjectiveQuery.md index 0b646128382..aa51a87db4d 100644 --- a/api_docs/v1/ServiceLevelObjectiveQuery.md +++ b/api_docs/v1/ServiceLevelObjectiveQuery.md @@ -3,6 +3,7 @@ # ServiceLevelObjectiveQuery A metric SLI query. **Required if type is `metric`**. Note that Datadog only allows the sum by aggregator to be used because this will sum up all request counts instead of averaging them, or taking the max or min of all of those requests. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ServiceLevelObjectiveRequest.md b/api_docs/v1/ServiceLevelObjectiveRequest.md index c5f2e460f1d..64dc3324100 100644 --- a/api_docs/v1/ServiceLevelObjectiveRequest.md +++ b/api_docs/v1/ServiceLevelObjectiveRequest.md @@ -3,6 +3,7 @@ # ServiceLevelObjectiveRequest A service level objective object includes a service level indicator, thresholds for one or more timeframes, and metadata (`name`, `description`, `tags`, etc.). + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ServiceMapWidgetDefinition.md b/api_docs/v1/ServiceMapWidgetDefinition.md index 7a3d45ea65d..d87917f72ef 100644 --- a/api_docs/v1/ServiceMapWidgetDefinition.md +++ b/api_docs/v1/ServiceMapWidgetDefinition.md @@ -3,6 +3,7 @@ # ServiceMapWidgetDefinition This widget displays a map of a service to all of the services that call it, and all of the services that it calls. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ServiceSummaryWidgetDefinition.md b/api_docs/v1/ServiceSummaryWidgetDefinition.md index 26dfe9d0d8b..9eeab40acd8 100644 --- a/api_docs/v1/ServiceSummaryWidgetDefinition.md +++ b/api_docs/v1/ServiceSummaryWidgetDefinition.md @@ -3,6 +3,7 @@ # ServiceSummaryWidgetDefinition The service summary displays the graphs of a chosen service in your screenboard. Only available on FREE layout dashboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SlackIntegrationChannel.md b/api_docs/v1/SlackIntegrationChannel.md index f1346f90db0..94fb1d59129 100644 --- a/api_docs/v1/SlackIntegrationChannel.md +++ b/api_docs/v1/SlackIntegrationChannel.md @@ -3,6 +3,7 @@ # SlackIntegrationChannel The Slack channel configuration. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SlackIntegrationChannelDisplay.md b/api_docs/v1/SlackIntegrationChannelDisplay.md index 1fb153f5425..8e2c12b1ba8 100644 --- a/api_docs/v1/SlackIntegrationChannelDisplay.md +++ b/api_docs/v1/SlackIntegrationChannelDisplay.md @@ -3,6 +3,7 @@ # SlackIntegrationChannelDisplay Configuration options for what is shown in an alert event message. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsAPIStep.md b/api_docs/v1/SyntheticsAPIStep.md index bb5878ff1f7..c7ecf766900 100644 --- a/api_docs/v1/SyntheticsAPIStep.md +++ b/api_docs/v1/SyntheticsAPIStep.md @@ -3,6 +3,7 @@ # SyntheticsAPIStep The steps used in a Synthetics multistep API test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsAPITest.md b/api_docs/v1/SyntheticsAPITest.md index a6eaed2461d..3aca4ef9837 100644 --- a/api_docs/v1/SyntheticsAPITest.md +++ b/api_docs/v1/SyntheticsAPITest.md @@ -3,6 +3,7 @@ # SyntheticsAPITest Object containing details about a Synthetic API test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsAPITestConfig.md b/api_docs/v1/SyntheticsAPITestConfig.md index 959fbcef660..4873319b49a 100644 --- a/api_docs/v1/SyntheticsAPITestConfig.md +++ b/api_docs/v1/SyntheticsAPITestConfig.md @@ -3,6 +3,7 @@ # SyntheticsAPITestConfig Configuration object for a Synthetic API test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsAPITestResultData.md b/api_docs/v1/SyntheticsAPITestResultData.md index 2f3c6a485c1..2c235a381e0 100644 --- a/api_docs/v1/SyntheticsAPITestResultData.md +++ b/api_docs/v1/SyntheticsAPITestResultData.md @@ -3,6 +3,7 @@ # SyntheticsAPITestResultData Object containing results for your Synthetic API test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsAPITestResultFull.md b/api_docs/v1/SyntheticsAPITestResultFull.md index 438536b0d5d..5de8778b897 100644 --- a/api_docs/v1/SyntheticsAPITestResultFull.md +++ b/api_docs/v1/SyntheticsAPITestResultFull.md @@ -3,6 +3,7 @@ # SyntheticsAPITestResultFull Object returned describing a API test result. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsAPITestResultFullCheck.md b/api_docs/v1/SyntheticsAPITestResultFullCheck.md index 3579b129662..a8a5341db68 100644 --- a/api_docs/v1/SyntheticsAPITestResultFullCheck.md +++ b/api_docs/v1/SyntheticsAPITestResultFullCheck.md @@ -3,6 +3,7 @@ # SyntheticsAPITestResultFullCheck Object describing the API test configuration. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsAPITestResultShort.md b/api_docs/v1/SyntheticsAPITestResultShort.md index fda828b3d2d..077047a920d 100644 --- a/api_docs/v1/SyntheticsAPITestResultShort.md +++ b/api_docs/v1/SyntheticsAPITestResultShort.md @@ -3,6 +3,7 @@ # SyntheticsAPITestResultShort Object with the results of a single Synthetic API test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsAPITestResultShortResult.md b/api_docs/v1/SyntheticsAPITestResultShortResult.md index bd1b6ffd030..f2e359f1af8 100644 --- a/api_docs/v1/SyntheticsAPITestResultShortResult.md +++ b/api_docs/v1/SyntheticsAPITestResultShortResult.md @@ -3,6 +3,7 @@ # SyntheticsAPITestResultShortResult Result of the last API test run. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsAssertionJSONPathTarget.md b/api_docs/v1/SyntheticsAssertionJSONPathTarget.md index 904abaebf59..919cc85e6f0 100644 --- a/api_docs/v1/SyntheticsAssertionJSONPathTarget.md +++ b/api_docs/v1/SyntheticsAssertionJSONPathTarget.md @@ -3,6 +3,7 @@ # SyntheticsAssertionJSONPathTarget An assertion for the `validatesJSONPath` operator. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsAssertionJSONPathTargetTarget.md b/api_docs/v1/SyntheticsAssertionJSONPathTargetTarget.md index 73831d88dce..8cd1eaab5d8 100644 --- a/api_docs/v1/SyntheticsAssertionJSONPathTargetTarget.md +++ b/api_docs/v1/SyntheticsAssertionJSONPathTargetTarget.md @@ -3,6 +3,7 @@ # SyntheticsAssertionJSONPathTargetTarget Composed target for `validatesJSONPath` operator. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsAssertionTarget.md b/api_docs/v1/SyntheticsAssertionTarget.md index f80d75ac39e..0cb7fc61a8b 100644 --- a/api_docs/v1/SyntheticsAssertionTarget.md +++ b/api_docs/v1/SyntheticsAssertionTarget.md @@ -3,6 +3,7 @@ # SyntheticsAssertionTarget An assertion which uses a simple target. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsBasicAuth.md b/api_docs/v1/SyntheticsBasicAuth.md index e50c39457f2..1a7c3fec19c 100644 --- a/api_docs/v1/SyntheticsBasicAuth.md +++ b/api_docs/v1/SyntheticsBasicAuth.md @@ -3,6 +3,7 @@ # SyntheticsBasicAuth Object to handle basic authentication when performing the test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsBrowserError.md b/api_docs/v1/SyntheticsBrowserError.md index 51d0db687ad..ff92b42e9f6 100644 --- a/api_docs/v1/SyntheticsBrowserError.md +++ b/api_docs/v1/SyntheticsBrowserError.md @@ -3,6 +3,7 @@ # SyntheticsBrowserError Error response object for a browser test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsBrowserTest.md b/api_docs/v1/SyntheticsBrowserTest.md index 7357163f188..899418b37e2 100644 --- a/api_docs/v1/SyntheticsBrowserTest.md +++ b/api_docs/v1/SyntheticsBrowserTest.md @@ -3,6 +3,7 @@ # SyntheticsBrowserTest Object containing details about a Synthetic browser test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsBrowserTestConfig.md b/api_docs/v1/SyntheticsBrowserTestConfig.md index 08627481b9b..d3c1cc4f5cb 100644 --- a/api_docs/v1/SyntheticsBrowserTestConfig.md +++ b/api_docs/v1/SyntheticsBrowserTestConfig.md @@ -3,6 +3,7 @@ # SyntheticsBrowserTestConfig Configuration object for a Synthetic browser test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsBrowserTestResultData.md b/api_docs/v1/SyntheticsBrowserTestResultData.md index 86274388bc5..1afd3610cb4 100644 --- a/api_docs/v1/SyntheticsBrowserTestResultData.md +++ b/api_docs/v1/SyntheticsBrowserTestResultData.md @@ -3,6 +3,7 @@ # SyntheticsBrowserTestResultData Object containing results for your Synthetic browser test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsBrowserTestResultFull.md b/api_docs/v1/SyntheticsBrowserTestResultFull.md index 6fbc6044db9..138fb325a27 100644 --- a/api_docs/v1/SyntheticsBrowserTestResultFull.md +++ b/api_docs/v1/SyntheticsBrowserTestResultFull.md @@ -3,6 +3,7 @@ # SyntheticsBrowserTestResultFull Object returned describing a browser test result. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsBrowserTestResultFullCheck.md b/api_docs/v1/SyntheticsBrowserTestResultFullCheck.md index 13bf1aaebe7..7fe39a913f4 100644 --- a/api_docs/v1/SyntheticsBrowserTestResultFullCheck.md +++ b/api_docs/v1/SyntheticsBrowserTestResultFullCheck.md @@ -3,6 +3,7 @@ # SyntheticsBrowserTestResultFullCheck Object describing the browser test configuration. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsBrowserTestResultShort.md b/api_docs/v1/SyntheticsBrowserTestResultShort.md index 7a0d6dff4d7..da0c9c2fc16 100644 --- a/api_docs/v1/SyntheticsBrowserTestResultShort.md +++ b/api_docs/v1/SyntheticsBrowserTestResultShort.md @@ -3,6 +3,7 @@ # SyntheticsBrowserTestResultShort Object with the results of a single Synthetic browser test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsBrowserTestResultShortResult.md b/api_docs/v1/SyntheticsBrowserTestResultShortResult.md index 8d13bd2d425..2a3542ff24c 100644 --- a/api_docs/v1/SyntheticsBrowserTestResultShortResult.md +++ b/api_docs/v1/SyntheticsBrowserTestResultShortResult.md @@ -3,6 +3,7 @@ # SyntheticsBrowserTestResultShortResult Object with the result of the last browser test run. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsBrowserVariable.md b/api_docs/v1/SyntheticsBrowserVariable.md index e667af65c3f..75d84d6f6df 100644 --- a/api_docs/v1/SyntheticsBrowserVariable.md +++ b/api_docs/v1/SyntheticsBrowserVariable.md @@ -3,6 +3,7 @@ # SyntheticsBrowserVariable Object defining a variable that can be used in your browser test. Learn more in the [Browser test Actions documentation](https://docs.datadoghq.com/synthetics/browser_tests/actions#variable). + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsCITest.md b/api_docs/v1/SyntheticsCITest.md index 9a75f3fd123..af1b78f3962 100644 --- a/api_docs/v1/SyntheticsCITest.md +++ b/api_docs/v1/SyntheticsCITest.md @@ -3,6 +3,7 @@ # SyntheticsCITest Test configuration for Synthetics CI + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsCITestBody.md b/api_docs/v1/SyntheticsCITestBody.md index dc81475542c..c371032b979 100644 --- a/api_docs/v1/SyntheticsCITestBody.md +++ b/api_docs/v1/SyntheticsCITestBody.md @@ -3,6 +3,7 @@ # SyntheticsCITestBody Object describing the synthetics tests to trigger. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsCITestMetadata.md b/api_docs/v1/SyntheticsCITestMetadata.md index e2410027aba..a74411be638 100644 --- a/api_docs/v1/SyntheticsCITestMetadata.md +++ b/api_docs/v1/SyntheticsCITestMetadata.md @@ -3,6 +3,7 @@ # SyntheticsCITestMetadata Metadata for the Synthetics tests run + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsCITestMetadataCi.md b/api_docs/v1/SyntheticsCITestMetadataCi.md index 92a6d2fd91d..8b357fdea2f 100644 --- a/api_docs/v1/SyntheticsCITestMetadataCi.md +++ b/api_docs/v1/SyntheticsCITestMetadataCi.md @@ -3,6 +3,7 @@ # SyntheticsCITestMetadataCi Describe CI provider. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsCITestMetadataGit.md b/api_docs/v1/SyntheticsCITestMetadataGit.md index c000d21275a..e3e22712284 100644 --- a/api_docs/v1/SyntheticsCITestMetadataGit.md +++ b/api_docs/v1/SyntheticsCITestMetadataGit.md @@ -3,6 +3,7 @@ # SyntheticsCITestMetadataGit Git information. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsConfigVariable.md b/api_docs/v1/SyntheticsConfigVariable.md index c2269508270..816d2d8e2d5 100644 --- a/api_docs/v1/SyntheticsConfigVariable.md +++ b/api_docs/v1/SyntheticsConfigVariable.md @@ -3,6 +3,7 @@ # SyntheticsConfigVariable Object defining a variable that can be used in your test configuration. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsCoreWebVitals.md b/api_docs/v1/SyntheticsCoreWebVitals.md index 90953a84c98..ab11bace7c3 100644 --- a/api_docs/v1/SyntheticsCoreWebVitals.md +++ b/api_docs/v1/SyntheticsCoreWebVitals.md @@ -3,6 +3,7 @@ # SyntheticsCoreWebVitals Core Web Vitals attached to a browser test step. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsDeleteTestsPayload.md b/api_docs/v1/SyntheticsDeleteTestsPayload.md index f155b428457..88edbefe049 100644 --- a/api_docs/v1/SyntheticsDeleteTestsPayload.md +++ b/api_docs/v1/SyntheticsDeleteTestsPayload.md @@ -3,6 +3,7 @@ # SyntheticsDeleteTestsPayload A JSON list of the ID or IDs of the Synthetic tests that you want to delete. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsDeleteTestsResponse.md b/api_docs/v1/SyntheticsDeleteTestsResponse.md index 9f19b82d694..a92b80383af 100644 --- a/api_docs/v1/SyntheticsDeleteTestsResponse.md +++ b/api_docs/v1/SyntheticsDeleteTestsResponse.md @@ -3,6 +3,7 @@ # SyntheticsDeleteTestsResponse Response object for deleting Synthetic tests. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsDeletedTest.md b/api_docs/v1/SyntheticsDeletedTest.md index 6b9c48b216c..31271765b3a 100644 --- a/api_docs/v1/SyntheticsDeletedTest.md +++ b/api_docs/v1/SyntheticsDeletedTest.md @@ -3,6 +3,7 @@ # SyntheticsDeletedTest Object containing a deleted Synthetic test ID with the associated deletion timestamp. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsDevice.md b/api_docs/v1/SyntheticsDevice.md index aec5d6ba47e..4c76c6df7c2 100644 --- a/api_docs/v1/SyntheticsDevice.md +++ b/api_docs/v1/SyntheticsDevice.md @@ -3,6 +3,7 @@ # SyntheticsDevice Object describing the device used to perform the Synthetic test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsGetAPITestLatestResultsResponse.md b/api_docs/v1/SyntheticsGetAPITestLatestResultsResponse.md index c9c062d1f76..03660876ba7 100644 --- a/api_docs/v1/SyntheticsGetAPITestLatestResultsResponse.md +++ b/api_docs/v1/SyntheticsGetAPITestLatestResultsResponse.md @@ -3,6 +3,7 @@ # SyntheticsGetAPITestLatestResultsResponse Object with the latest Synthetic API test run. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsGetBrowserTestLatestResultsResponse.md b/api_docs/v1/SyntheticsGetBrowserTestLatestResultsResponse.md index 02d0b9c7d53..391a9b9cc7f 100644 --- a/api_docs/v1/SyntheticsGetBrowserTestLatestResultsResponse.md +++ b/api_docs/v1/SyntheticsGetBrowserTestLatestResultsResponse.md @@ -3,6 +3,7 @@ # SyntheticsGetBrowserTestLatestResultsResponse Object with the latest Synthetic browser test run. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsGlobalVariable.md b/api_docs/v1/SyntheticsGlobalVariable.md index a41bbdf63e8..ce714fc3c9b 100644 --- a/api_docs/v1/SyntheticsGlobalVariable.md +++ b/api_docs/v1/SyntheticsGlobalVariable.md @@ -3,6 +3,7 @@ # SyntheticsGlobalVariable Synthetics global variable. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsGlobalVariableParseTestOptions.md b/api_docs/v1/SyntheticsGlobalVariableParseTestOptions.md index a8d0e62086b..fe7e410b497 100644 --- a/api_docs/v1/SyntheticsGlobalVariableParseTestOptions.md +++ b/api_docs/v1/SyntheticsGlobalVariableParseTestOptions.md @@ -3,6 +3,7 @@ # SyntheticsGlobalVariableParseTestOptions Parser options to use for retrieving a Synthetics global variable from a Synthetics Test. Used in conjunction with `parse_test_public_id`. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsGlobalVariableValue.md b/api_docs/v1/SyntheticsGlobalVariableValue.md index ad669ef9f94..c2a98a80bc9 100644 --- a/api_docs/v1/SyntheticsGlobalVariableValue.md +++ b/api_docs/v1/SyntheticsGlobalVariableValue.md @@ -3,6 +3,7 @@ # SyntheticsGlobalVariableValue Value of the global variable. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsListTestsResponse.md b/api_docs/v1/SyntheticsListTestsResponse.md index 2fb4cd82cc3..b53d87aa6f3 100644 --- a/api_docs/v1/SyntheticsListTestsResponse.md +++ b/api_docs/v1/SyntheticsListTestsResponse.md @@ -3,6 +3,7 @@ # SyntheticsListTestsResponse Object containing an array of Synthetic tests configuration. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsLocation.md b/api_docs/v1/SyntheticsLocation.md index edfcbcd213e..75ab591bdc2 100644 --- a/api_docs/v1/SyntheticsLocation.md +++ b/api_docs/v1/SyntheticsLocation.md @@ -3,6 +3,7 @@ # SyntheticsLocation Synthetic location that can be used when creating or editing a test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsLocations.md b/api_docs/v1/SyntheticsLocations.md index 323313deb3d..75af006469e 100644 --- a/api_docs/v1/SyntheticsLocations.md +++ b/api_docs/v1/SyntheticsLocations.md @@ -3,6 +3,7 @@ # SyntheticsLocations List of Synthetics locations. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsParsingOptions.md b/api_docs/v1/SyntheticsParsingOptions.md index 9246d3af04f..c94711a3fbb 100644 --- a/api_docs/v1/SyntheticsParsingOptions.md +++ b/api_docs/v1/SyntheticsParsingOptions.md @@ -3,6 +3,7 @@ # SyntheticsParsingOptions Parsing options for variables to extract. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsPrivateLocation.md b/api_docs/v1/SyntheticsPrivateLocation.md index 682b4b2e764..44b66705ef5 100644 --- a/api_docs/v1/SyntheticsPrivateLocation.md +++ b/api_docs/v1/SyntheticsPrivateLocation.md @@ -3,6 +3,7 @@ # SyntheticsPrivateLocation Object containing information about the private location to create. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsPrivateLocationCreationResponse.md b/api_docs/v1/SyntheticsPrivateLocationCreationResponse.md index e9892ab7682..52a4a1a6786 100644 --- a/api_docs/v1/SyntheticsPrivateLocationCreationResponse.md +++ b/api_docs/v1/SyntheticsPrivateLocationCreationResponse.md @@ -3,6 +3,7 @@ # SyntheticsPrivateLocationCreationResponse Object that contains the new private location, the public key for result encryption, and the configuration skeleton. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsPrivateLocationCreationResponseResultEncryption.md b/api_docs/v1/SyntheticsPrivateLocationCreationResponseResultEncryption.md index 2e2bd73a5b6..51532a06873 100644 --- a/api_docs/v1/SyntheticsPrivateLocationCreationResponseResultEncryption.md +++ b/api_docs/v1/SyntheticsPrivateLocationCreationResponseResultEncryption.md @@ -3,6 +3,7 @@ # SyntheticsPrivateLocationCreationResponseResultEncryption Public key for the result encryption. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsPrivateLocationSecrets.md b/api_docs/v1/SyntheticsPrivateLocationSecrets.md index a914611ebda..1a4cdf78751 100644 --- a/api_docs/v1/SyntheticsPrivateLocationSecrets.md +++ b/api_docs/v1/SyntheticsPrivateLocationSecrets.md @@ -3,6 +3,7 @@ # SyntheticsPrivateLocationSecrets Secrets for the private location. Only present in the response when creating the private location. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsPrivateLocationSecretsAuthentication.md b/api_docs/v1/SyntheticsPrivateLocationSecretsAuthentication.md index f7b0729ca20..a3e9f6776c5 100644 --- a/api_docs/v1/SyntheticsPrivateLocationSecretsAuthentication.md +++ b/api_docs/v1/SyntheticsPrivateLocationSecretsAuthentication.md @@ -3,6 +3,7 @@ # SyntheticsPrivateLocationSecretsAuthentication Authentication part of the secrets. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsPrivateLocationSecretsConfigDecryption.md b/api_docs/v1/SyntheticsPrivateLocationSecretsConfigDecryption.md index 1f44c0e28e9..aa5bf5dcd38 100644 --- a/api_docs/v1/SyntheticsPrivateLocationSecretsConfigDecryption.md +++ b/api_docs/v1/SyntheticsPrivateLocationSecretsConfigDecryption.md @@ -3,6 +3,7 @@ # SyntheticsPrivateLocationSecretsConfigDecryption Private key for the private location. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsSSLCertificate.md b/api_docs/v1/SyntheticsSSLCertificate.md index e9db98fa34a..4c13f8e1440 100644 --- a/api_docs/v1/SyntheticsSSLCertificate.md +++ b/api_docs/v1/SyntheticsSSLCertificate.md @@ -3,6 +3,7 @@ # SyntheticsSSLCertificate Object describing the SSL certificate used for a Synthetic test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsSSLCertificateIssuer.md b/api_docs/v1/SyntheticsSSLCertificateIssuer.md index 2e244e20e5b..9eeaba8f8cd 100644 --- a/api_docs/v1/SyntheticsSSLCertificateIssuer.md +++ b/api_docs/v1/SyntheticsSSLCertificateIssuer.md @@ -3,6 +3,7 @@ # SyntheticsSSLCertificateIssuer Object describing the issuer of a SSL certificate. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsSSLCertificateSubject.md b/api_docs/v1/SyntheticsSSLCertificateSubject.md index 28fedde25ee..4f6baca119b 100644 --- a/api_docs/v1/SyntheticsSSLCertificateSubject.md +++ b/api_docs/v1/SyntheticsSSLCertificateSubject.md @@ -3,6 +3,7 @@ # SyntheticsSSLCertificateSubject Object describing the SSL certificate used for the test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsStep.md b/api_docs/v1/SyntheticsStep.md index eecd9a629e8..9b286138df7 100644 --- a/api_docs/v1/SyntheticsStep.md +++ b/api_docs/v1/SyntheticsStep.md @@ -3,6 +3,7 @@ # SyntheticsStep The steps used in a Synthetics browser test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsStepDetail.md b/api_docs/v1/SyntheticsStepDetail.md index 46fdc79d81c..ce795adf3b4 100644 --- a/api_docs/v1/SyntheticsStepDetail.md +++ b/api_docs/v1/SyntheticsStepDetail.md @@ -3,6 +3,7 @@ # SyntheticsStepDetail Object describing a step for a Synthetic test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsStepDetailWarning.md b/api_docs/v1/SyntheticsStepDetailWarning.md index 35f2647213a..3f164f8956d 100644 --- a/api_docs/v1/SyntheticsStepDetailWarning.md +++ b/api_docs/v1/SyntheticsStepDetailWarning.md @@ -3,6 +3,7 @@ # SyntheticsStepDetailWarning Object collecting warnings for a given step. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsTestConfig.md b/api_docs/v1/SyntheticsTestConfig.md index cbdda1d3b86..e39debb89be 100644 --- a/api_docs/v1/SyntheticsTestConfig.md +++ b/api_docs/v1/SyntheticsTestConfig.md @@ -3,6 +3,7 @@ # SyntheticsTestConfig Configuration object for a Synthetic test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsTestDetails.md b/api_docs/v1/SyntheticsTestDetails.md index a0e4a83504e..0a7db15672a 100644 --- a/api_docs/v1/SyntheticsTestDetails.md +++ b/api_docs/v1/SyntheticsTestDetails.md @@ -3,6 +3,7 @@ # SyntheticsTestDetails Object containing details about your Synthetic test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsTestOptions.md b/api_docs/v1/SyntheticsTestOptions.md index b8d73a0b06b..46ed71b7de7 100644 --- a/api_docs/v1/SyntheticsTestOptions.md +++ b/api_docs/v1/SyntheticsTestOptions.md @@ -3,6 +3,7 @@ # SyntheticsTestOptions Object describing the extra options for a Synthetic test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsTestOptionsMonitorOptions.md b/api_docs/v1/SyntheticsTestOptionsMonitorOptions.md index 4f585abe60d..93efa5e876a 100644 --- a/api_docs/v1/SyntheticsTestOptionsMonitorOptions.md +++ b/api_docs/v1/SyntheticsTestOptionsMonitorOptions.md @@ -3,6 +3,7 @@ # SyntheticsTestOptionsMonitorOptions Object containing the options for a Synthetic test as a monitor (for example, renotification). + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsTestOptionsRetry.md b/api_docs/v1/SyntheticsTestOptionsRetry.md index f2090f49b20..1cf43a19304 100644 --- a/api_docs/v1/SyntheticsTestOptionsRetry.md +++ b/api_docs/v1/SyntheticsTestOptionsRetry.md @@ -3,6 +3,7 @@ # SyntheticsTestOptionsRetry Object describing the retry strategy to apply to a Synthetic test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsTestRequest.md b/api_docs/v1/SyntheticsTestRequest.md index 99554e769f3..85f8c0fa899 100644 --- a/api_docs/v1/SyntheticsTestRequest.md +++ b/api_docs/v1/SyntheticsTestRequest.md @@ -3,6 +3,7 @@ # SyntheticsTestRequest Object describing the Synthetic test request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsTestRequestCertificate.md b/api_docs/v1/SyntheticsTestRequestCertificate.md index b2c2febea6c..fb0368e00be 100644 --- a/api_docs/v1/SyntheticsTestRequestCertificate.md +++ b/api_docs/v1/SyntheticsTestRequestCertificate.md @@ -3,6 +3,7 @@ # SyntheticsTestRequestCertificate Client certificate to use when performing the test request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsTestRequestCertificateItem.md b/api_docs/v1/SyntheticsTestRequestCertificateItem.md index f9a31912b2e..16902ca627f 100644 --- a/api_docs/v1/SyntheticsTestRequestCertificateItem.md +++ b/api_docs/v1/SyntheticsTestRequestCertificateItem.md @@ -3,6 +3,7 @@ # SyntheticsTestRequestCertificateItem Define a request certificate. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsTiming.md b/api_docs/v1/SyntheticsTiming.md index f3f134b5bdf..6532a297e2c 100644 --- a/api_docs/v1/SyntheticsTiming.md +++ b/api_docs/v1/SyntheticsTiming.md @@ -3,6 +3,7 @@ # SyntheticsTiming Object containing all metrics and their values collected for a Synthetic API test. Learn more about those metrics in [Synthetics documentation](https://docs.datadoghq.com/synthetics/#metrics). + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsTriggerCITestLocation.md b/api_docs/v1/SyntheticsTriggerCITestLocation.md index 6700f8cfe9b..af63f86f565 100644 --- a/api_docs/v1/SyntheticsTriggerCITestLocation.md +++ b/api_docs/v1/SyntheticsTriggerCITestLocation.md @@ -3,6 +3,7 @@ # SyntheticsTriggerCITestLocation Synthetics location. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsTriggerCITestRunResult.md b/api_docs/v1/SyntheticsTriggerCITestRunResult.md index a05c4c9f94a..f8ccc27ffe0 100644 --- a/api_docs/v1/SyntheticsTriggerCITestRunResult.md +++ b/api_docs/v1/SyntheticsTriggerCITestRunResult.md @@ -3,6 +3,7 @@ # SyntheticsTriggerCITestRunResult Information about a single test run. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsTriggerCITestsResponse.md b/api_docs/v1/SyntheticsTriggerCITestsResponse.md index ea6bf24aecf..d4362a382bd 100644 --- a/api_docs/v1/SyntheticsTriggerCITestsResponse.md +++ b/api_docs/v1/SyntheticsTriggerCITestsResponse.md @@ -3,6 +3,7 @@ # SyntheticsTriggerCITestsResponse Object containing information about the tests triggered. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsUpdateTestPauseStatusPayload.md b/api_docs/v1/SyntheticsUpdateTestPauseStatusPayload.md index b434dcdf13b..ad24ffc491a 100644 --- a/api_docs/v1/SyntheticsUpdateTestPauseStatusPayload.md +++ b/api_docs/v1/SyntheticsUpdateTestPauseStatusPayload.md @@ -3,6 +3,7 @@ # SyntheticsUpdateTestPauseStatusPayload Object to start or pause an existing Synthetic test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsVariableParser.md b/api_docs/v1/SyntheticsVariableParser.md index dca0cb12d50..56b930e871b 100644 --- a/api_docs/v1/SyntheticsVariableParser.md +++ b/api_docs/v1/SyntheticsVariableParser.md @@ -3,6 +3,7 @@ # SyntheticsVariableParser Details of the parser to use for the global variable. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/TableWidgetDefinition.md b/api_docs/v1/TableWidgetDefinition.md index 4da9ada5400..333a89dd743 100644 --- a/api_docs/v1/TableWidgetDefinition.md +++ b/api_docs/v1/TableWidgetDefinition.md @@ -3,6 +3,7 @@ # TableWidgetDefinition The table visualization is available on timeboards and screenboards. It displays columns of metrics grouped by tag key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/TableWidgetRequest.md b/api_docs/v1/TableWidgetRequest.md index b5f2486b5e0..3e14c1312e9 100644 --- a/api_docs/v1/TableWidgetRequest.md +++ b/api_docs/v1/TableWidgetRequest.md @@ -3,6 +3,7 @@ # TableWidgetRequest Updated table widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/TagToHosts.md b/api_docs/v1/TagToHosts.md index 7aa1c3b7e78..e1d8d05bf16 100644 --- a/api_docs/v1/TagToHosts.md +++ b/api_docs/v1/TagToHosts.md @@ -3,6 +3,7 @@ # TagToHosts In this object, the key is the tag, the value is a list of host names that are reporting that tag. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/TimeseriesWidgetDefinition.md b/api_docs/v1/TimeseriesWidgetDefinition.md index 5ff5fa3894f..41ffeb2159c 100644 --- a/api_docs/v1/TimeseriesWidgetDefinition.md +++ b/api_docs/v1/TimeseriesWidgetDefinition.md @@ -3,6 +3,7 @@ # TimeseriesWidgetDefinition The timeseries visualization allows you to display the evolution of one or more metrics, log events, or Indexed Spans over time. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/TimeseriesWidgetExpressionAlias.md b/api_docs/v1/TimeseriesWidgetExpressionAlias.md index c0096d41546..2fae9287a13 100644 --- a/api_docs/v1/TimeseriesWidgetExpressionAlias.md +++ b/api_docs/v1/TimeseriesWidgetExpressionAlias.md @@ -3,6 +3,7 @@ # TimeseriesWidgetExpressionAlias Define an expression alias. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/TimeseriesWidgetRequest.md b/api_docs/v1/TimeseriesWidgetRequest.md index 60bd4ab8c9f..440a34a8835 100644 --- a/api_docs/v1/TimeseriesWidgetRequest.md +++ b/api_docs/v1/TimeseriesWidgetRequest.md @@ -3,6 +3,7 @@ # TimeseriesWidgetRequest Updated timeseries widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ToplistWidgetDefinition.md b/api_docs/v1/ToplistWidgetDefinition.md index d85aecc38d7..0d97a95cd83 100644 --- a/api_docs/v1/ToplistWidgetDefinition.md +++ b/api_docs/v1/ToplistWidgetDefinition.md @@ -3,6 +3,7 @@ # ToplistWidgetDefinition The top list visualization enables you to display a list of Tag value like hostname or service with the most or least of any metric value, such as highest consumers of CPU, hosts with the least disk space, etc. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ToplistWidgetRequest.md b/api_docs/v1/ToplistWidgetRequest.md index 99acc3c938b..89b7ae742be 100644 --- a/api_docs/v1/ToplistWidgetRequest.md +++ b/api_docs/v1/ToplistWidgetRequest.md @@ -3,6 +3,7 @@ # ToplistWidgetRequest Updated top list widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageAnalyzedLogsHour.md b/api_docs/v1/UsageAnalyzedLogsHour.md index a0bbdb7dc5b..1f8bfd30d04 100644 --- a/api_docs/v1/UsageAnalyzedLogsHour.md +++ b/api_docs/v1/UsageAnalyzedLogsHour.md @@ -3,6 +3,7 @@ # UsageAnalyzedLogsHour The number of analyzed logs for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageAnalyzedLogsResponse.md b/api_docs/v1/UsageAnalyzedLogsResponse.md index a03a887f9c7..bd7e69b2f05 100644 --- a/api_docs/v1/UsageAnalyzedLogsResponse.md +++ b/api_docs/v1/UsageAnalyzedLogsResponse.md @@ -3,6 +3,7 @@ # UsageAnalyzedLogsResponse A response containing the number of analyzed logs for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageAttributionAggregatesBody.md b/api_docs/v1/UsageAttributionAggregatesBody.md index 05fecbbf736..7a42139066e 100644 --- a/api_docs/v1/UsageAttributionAggregatesBody.md +++ b/api_docs/v1/UsageAttributionAggregatesBody.md @@ -3,6 +3,7 @@ # UsageAttributionAggregatesBody The object containing the aggregates. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageAttributionBody.md b/api_docs/v1/UsageAttributionBody.md index 746157094ba..f6c54482dc6 100644 --- a/api_docs/v1/UsageAttributionBody.md +++ b/api_docs/v1/UsageAttributionBody.md @@ -3,6 +3,7 @@ # UsageAttributionBody Usage Summary by tag for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageAttributionMetadata.md b/api_docs/v1/UsageAttributionMetadata.md index 925cbf0da72..1a5cb631273 100644 --- a/api_docs/v1/UsageAttributionMetadata.md +++ b/api_docs/v1/UsageAttributionMetadata.md @@ -3,6 +3,7 @@ # UsageAttributionMetadata The object containing document metadata. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageAttributionPagination.md b/api_docs/v1/UsageAttributionPagination.md index 79bb5c650ef..2668289f55c 100644 --- a/api_docs/v1/UsageAttributionPagination.md +++ b/api_docs/v1/UsageAttributionPagination.md @@ -3,6 +3,7 @@ # UsageAttributionPagination The page count for the current pagination. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageAttributionResponse.md b/api_docs/v1/UsageAttributionResponse.md index 1cb056e11c5..9d21b07bc0a 100644 --- a/api_docs/v1/UsageAttributionResponse.md +++ b/api_docs/v1/UsageAttributionResponse.md @@ -3,6 +3,7 @@ # UsageAttributionResponse Response containing the Usage Summary by tag(s). + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageAttributionValues.md b/api_docs/v1/UsageAttributionValues.md index 970ddf8b1de..56de19d5973 100644 --- a/api_docs/v1/UsageAttributionValues.md +++ b/api_docs/v1/UsageAttributionValues.md @@ -3,6 +3,7 @@ # UsageAttributionValues Fields in Usage Summary by tag(s). + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageBillableSummaryBody.md b/api_docs/v1/UsageBillableSummaryBody.md index fda1685216c..cd6f73b9bfa 100644 --- a/api_docs/v1/UsageBillableSummaryBody.md +++ b/api_docs/v1/UsageBillableSummaryBody.md @@ -3,6 +3,7 @@ # UsageBillableSummaryBody Response with properties for each aggregated usage type. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageBillableSummaryHour.md b/api_docs/v1/UsageBillableSummaryHour.md index 03db8eccf0a..bbf6948c5f4 100644 --- a/api_docs/v1/UsageBillableSummaryHour.md +++ b/api_docs/v1/UsageBillableSummaryHour.md @@ -3,6 +3,7 @@ # UsageBillableSummaryHour Response with monthly summary of data billed by Datadog. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageBillableSummaryKeys.md b/api_docs/v1/UsageBillableSummaryKeys.md index 54d33d2269e..9a666b74a4f 100644 --- a/api_docs/v1/UsageBillableSummaryKeys.md +++ b/api_docs/v1/UsageBillableSummaryKeys.md @@ -3,6 +3,7 @@ # UsageBillableSummaryKeys Response with aggregated usage types. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageBillableSummaryResponse.md b/api_docs/v1/UsageBillableSummaryResponse.md index f6f3fc2291b..6b2affcca07 100644 --- a/api_docs/v1/UsageBillableSummaryResponse.md +++ b/api_docs/v1/UsageBillableSummaryResponse.md @@ -3,6 +3,7 @@ # UsageBillableSummaryResponse Response with monthly summary of data billed by Datadog. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageCustomReportsAttributes.md b/api_docs/v1/UsageCustomReportsAttributes.md index 3e87dd852ec..5b57b032739 100644 --- a/api_docs/v1/UsageCustomReportsAttributes.md +++ b/api_docs/v1/UsageCustomReportsAttributes.md @@ -3,6 +3,7 @@ # UsageCustomReportsAttributes The response containing attributes for custom reports. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageCustomReportsData.md b/api_docs/v1/UsageCustomReportsData.md index d3d8717b885..ef48a24451e 100644 --- a/api_docs/v1/UsageCustomReportsData.md +++ b/api_docs/v1/UsageCustomReportsData.md @@ -3,6 +3,7 @@ # UsageCustomReportsData The response containing the date and type for custom reports. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageCustomReportsMeta.md b/api_docs/v1/UsageCustomReportsMeta.md index 6a8dec0f624..f3303369c0a 100644 --- a/api_docs/v1/UsageCustomReportsMeta.md +++ b/api_docs/v1/UsageCustomReportsMeta.md @@ -3,6 +3,7 @@ # UsageCustomReportsMeta The object containing document metadata. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageCustomReportsPage.md b/api_docs/v1/UsageCustomReportsPage.md index 656589011f6..6f30a15c5ac 100644 --- a/api_docs/v1/UsageCustomReportsPage.md +++ b/api_docs/v1/UsageCustomReportsPage.md @@ -3,6 +3,7 @@ # UsageCustomReportsPage The object containing page total count. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageCustomReportsResponse.md b/api_docs/v1/UsageCustomReportsResponse.md index e63aafc0124..7626a3304d5 100644 --- a/api_docs/v1/UsageCustomReportsResponse.md +++ b/api_docs/v1/UsageCustomReportsResponse.md @@ -3,6 +3,7 @@ # UsageCustomReportsResponse Response containing available custom reports. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageFargateHour.md b/api_docs/v1/UsageFargateHour.md index 8d54b7f82cd..21a6a7eb508 100644 --- a/api_docs/v1/UsageFargateHour.md +++ b/api_docs/v1/UsageFargateHour.md @@ -3,6 +3,7 @@ # UsageFargateHour Number of Fargate tasks run and hourly usage. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageFargateResponse.md b/api_docs/v1/UsageFargateResponse.md index ca5e5c13d15..b24d347247f 100644 --- a/api_docs/v1/UsageFargateResponse.md +++ b/api_docs/v1/UsageFargateResponse.md @@ -3,6 +3,7 @@ # UsageFargateResponse Response containing the number of Fargate tasks run and hourly usage. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageHostHour.md b/api_docs/v1/UsageHostHour.md index 4002df1219e..35279f0c32c 100644 --- a/api_docs/v1/UsageHostHour.md +++ b/api_docs/v1/UsageHostHour.md @@ -3,6 +3,7 @@ # UsageHostHour Number of hosts/containers recorded for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageHostsResponse.md b/api_docs/v1/UsageHostsResponse.md index 1e6e16ffaa9..7d188a97927 100644 --- a/api_docs/v1/UsageHostsResponse.md +++ b/api_docs/v1/UsageHostsResponse.md @@ -3,6 +3,7 @@ # UsageHostsResponse Host usage response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageIncidentManagementHour.md b/api_docs/v1/UsageIncidentManagementHour.md index 14fba7ddc9e..3bfec1e1989 100644 --- a/api_docs/v1/UsageIncidentManagementHour.md +++ b/api_docs/v1/UsageIncidentManagementHour.md @@ -3,6 +3,7 @@ # UsageIncidentManagementHour Incident management usage for a given organization for a given hour. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageIncidentManagementResponse.md b/api_docs/v1/UsageIncidentManagementResponse.md index 8c58504c7eb..842eaf73c36 100644 --- a/api_docs/v1/UsageIncidentManagementResponse.md +++ b/api_docs/v1/UsageIncidentManagementResponse.md @@ -3,6 +3,7 @@ # UsageIncidentManagementResponse Response containing the incident management usage for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageIndexedSpansHour.md b/api_docs/v1/UsageIndexedSpansHour.md index 9407594b256..9e1ea20ac2b 100644 --- a/api_docs/v1/UsageIndexedSpansHour.md +++ b/api_docs/v1/UsageIndexedSpansHour.md @@ -3,6 +3,7 @@ # UsageIndexedSpansHour The hours of indexed spans usage. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageIndexedSpansResponse.md b/api_docs/v1/UsageIndexedSpansResponse.md index 0a34c38ebe1..e54f3a81f13 100644 --- a/api_docs/v1/UsageIndexedSpansResponse.md +++ b/api_docs/v1/UsageIndexedSpansResponse.md @@ -3,6 +3,7 @@ # UsageIndexedSpansResponse A response containing indexed spans usage. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageIngestedSpansHour.md b/api_docs/v1/UsageIngestedSpansHour.md index 5a0cbf81875..8b81b52ac9b 100644 --- a/api_docs/v1/UsageIngestedSpansHour.md +++ b/api_docs/v1/UsageIngestedSpansHour.md @@ -3,6 +3,7 @@ # UsageIngestedSpansHour Ingested spans usage for a given organization for a given hour. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageIngestedSpansResponse.md b/api_docs/v1/UsageIngestedSpansResponse.md index 14e274c7926..103f8aeee5d 100644 --- a/api_docs/v1/UsageIngestedSpansResponse.md +++ b/api_docs/v1/UsageIngestedSpansResponse.md @@ -3,6 +3,7 @@ # UsageIngestedSpansResponse Response containing the ingested spans usage for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageIoTHour.md b/api_docs/v1/UsageIoTHour.md index d8fedfda577..a4d8534986f 100644 --- a/api_docs/v1/UsageIoTHour.md +++ b/api_docs/v1/UsageIoTHour.md @@ -3,6 +3,7 @@ # UsageIoTHour IoT usage for a given organization for a given hour. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageIoTResponse.md b/api_docs/v1/UsageIoTResponse.md index 0d8db181568..9120ec9400d 100644 --- a/api_docs/v1/UsageIoTResponse.md +++ b/api_docs/v1/UsageIoTResponse.md @@ -3,6 +3,7 @@ # UsageIoTResponse Response containing the IoT usage for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageLambdaHour.md b/api_docs/v1/UsageLambdaHour.md index 11cbc126d8b..06cb8e7aa32 100644 --- a/api_docs/v1/UsageLambdaHour.md +++ b/api_docs/v1/UsageLambdaHour.md @@ -3,6 +3,7 @@ # UsageLambdaHour Number of lambda functions and sum of the invocations of all lambda functions for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageLambdaResponse.md b/api_docs/v1/UsageLambdaResponse.md index 4b452e6d1d1..7f32918440e 100644 --- a/api_docs/v1/UsageLambdaResponse.md +++ b/api_docs/v1/UsageLambdaResponse.md @@ -3,6 +3,7 @@ # UsageLambdaResponse Response containing the number of lambda functions and sum of the invocations of all lambda functions for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageLogsByIndexHour.md b/api_docs/v1/UsageLogsByIndexHour.md index e7978449201..7c0b33e862d 100644 --- a/api_docs/v1/UsageLogsByIndexHour.md +++ b/api_docs/v1/UsageLogsByIndexHour.md @@ -3,6 +3,7 @@ # UsageLogsByIndexHour Number of indexed logs for each hour and index for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageLogsByIndexResponse.md b/api_docs/v1/UsageLogsByIndexResponse.md index 785a91c5748..4890c74a61f 100644 --- a/api_docs/v1/UsageLogsByIndexResponse.md +++ b/api_docs/v1/UsageLogsByIndexResponse.md @@ -3,6 +3,7 @@ # UsageLogsByIndexResponse Response containing the number of indexed logs for each hour and index for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageLogsHour.md b/api_docs/v1/UsageLogsHour.md index eb788cbcb6b..82171a5aa16 100644 --- a/api_docs/v1/UsageLogsHour.md +++ b/api_docs/v1/UsageLogsHour.md @@ -3,6 +3,7 @@ # UsageLogsHour Hour usage for logs. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageLogsResponse.md b/api_docs/v1/UsageLogsResponse.md index 83e78ed1f39..137bff33a7e 100644 --- a/api_docs/v1/UsageLogsResponse.md +++ b/api_docs/v1/UsageLogsResponse.md @@ -3,6 +3,7 @@ # UsageLogsResponse Response containing the number of logs for each hour. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageNetworkFlowsHour.md b/api_docs/v1/UsageNetworkFlowsHour.md index 00dea5c19b2..c0446764df8 100644 --- a/api_docs/v1/UsageNetworkFlowsHour.md +++ b/api_docs/v1/UsageNetworkFlowsHour.md @@ -3,6 +3,7 @@ # UsageNetworkFlowsHour Number of netflow events indexed for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageNetworkFlowsResponse.md b/api_docs/v1/UsageNetworkFlowsResponse.md index 05a9f25306b..4352ebb4b1b 100644 --- a/api_docs/v1/UsageNetworkFlowsResponse.md +++ b/api_docs/v1/UsageNetworkFlowsResponse.md @@ -3,6 +3,7 @@ # UsageNetworkFlowsResponse Response containing the number of netflow events indexed for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageNetworkHostsHour.md b/api_docs/v1/UsageNetworkHostsHour.md index cc05f524502..154d6d2fbe6 100644 --- a/api_docs/v1/UsageNetworkHostsHour.md +++ b/api_docs/v1/UsageNetworkHostsHour.md @@ -3,6 +3,7 @@ # UsageNetworkHostsHour Number of active NPM hosts for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageNetworkHostsResponse.md b/api_docs/v1/UsageNetworkHostsResponse.md index 5c3e8309a8e..1ee36b21e57 100644 --- a/api_docs/v1/UsageNetworkHostsResponse.md +++ b/api_docs/v1/UsageNetworkHostsResponse.md @@ -3,6 +3,7 @@ # UsageNetworkHostsResponse Response containing the number of active NPM hosts for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageProfilingHour.md b/api_docs/v1/UsageProfilingHour.md index 9cce8f50250..9b1680ae697 100644 --- a/api_docs/v1/UsageProfilingHour.md +++ b/api_docs/v1/UsageProfilingHour.md @@ -3,6 +3,7 @@ # UsageProfilingHour The number of profiled hosts for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageProfilingResponse.md b/api_docs/v1/UsageProfilingResponse.md index f161e8a379c..fe4d090d087 100644 --- a/api_docs/v1/UsageProfilingResponse.md +++ b/api_docs/v1/UsageProfilingResponse.md @@ -3,6 +3,7 @@ # UsageProfilingResponse Response containing the number of profiled hosts for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageRumSessionsHour.md b/api_docs/v1/UsageRumSessionsHour.md index aabd279d762..ddc0742adfa 100644 --- a/api_docs/v1/UsageRumSessionsHour.md +++ b/api_docs/v1/UsageRumSessionsHour.md @@ -3,6 +3,7 @@ # UsageRumSessionsHour Number of RUM Sessions recorded for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageRumSessionsResponse.md b/api_docs/v1/UsageRumSessionsResponse.md index 0fe5a90ce25..7b46400babc 100644 --- a/api_docs/v1/UsageRumSessionsResponse.md +++ b/api_docs/v1/UsageRumSessionsResponse.md @@ -3,6 +3,7 @@ # UsageRumSessionsResponse Response containing the number of RUM Sessions for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSNMPHour.md b/api_docs/v1/UsageSNMPHour.md index 2a7fada862e..a6225f4f741 100644 --- a/api_docs/v1/UsageSNMPHour.md +++ b/api_docs/v1/UsageSNMPHour.md @@ -3,6 +3,7 @@ # UsageSNMPHour The number of SNMP devices for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSNMPResponse.md b/api_docs/v1/UsageSNMPResponse.md index bf3adeed414..761bf2ac7c1 100644 --- a/api_docs/v1/UsageSNMPResponse.md +++ b/api_docs/v1/UsageSNMPResponse.md @@ -3,6 +3,7 @@ # UsageSNMPResponse Response containing the number of SNMP devices for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSpecifiedCustomReportsAttributes.md b/api_docs/v1/UsageSpecifiedCustomReportsAttributes.md index 2ac1ff10005..e0e828562fb 100644 --- a/api_docs/v1/UsageSpecifiedCustomReportsAttributes.md +++ b/api_docs/v1/UsageSpecifiedCustomReportsAttributes.md @@ -3,6 +3,7 @@ # UsageSpecifiedCustomReportsAttributes The response containing attributes for specified custom reports. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSpecifiedCustomReportsData.md b/api_docs/v1/UsageSpecifiedCustomReportsData.md index 2905e5c945f..f4d4a7b416f 100644 --- a/api_docs/v1/UsageSpecifiedCustomReportsData.md +++ b/api_docs/v1/UsageSpecifiedCustomReportsData.md @@ -3,6 +3,7 @@ # UsageSpecifiedCustomReportsData Response containing date and type for specified custom reports. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSpecifiedCustomReportsMeta.md b/api_docs/v1/UsageSpecifiedCustomReportsMeta.md index 89717525dc4..d9fbfd8931b 100644 --- a/api_docs/v1/UsageSpecifiedCustomReportsMeta.md +++ b/api_docs/v1/UsageSpecifiedCustomReportsMeta.md @@ -3,6 +3,7 @@ # UsageSpecifiedCustomReportsMeta The object containing document metadata. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSpecifiedCustomReportsPage.md b/api_docs/v1/UsageSpecifiedCustomReportsPage.md index eaac0d17f2f..611d1d7fea9 100644 --- a/api_docs/v1/UsageSpecifiedCustomReportsPage.md +++ b/api_docs/v1/UsageSpecifiedCustomReportsPage.md @@ -3,6 +3,7 @@ # UsageSpecifiedCustomReportsPage The object containing page total count for specified ID. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSpecifiedCustomReportsResponse.md b/api_docs/v1/UsageSpecifiedCustomReportsResponse.md index 47d06766577..88ff88b789c 100644 --- a/api_docs/v1/UsageSpecifiedCustomReportsResponse.md +++ b/api_docs/v1/UsageSpecifiedCustomReportsResponse.md @@ -3,6 +3,7 @@ # UsageSpecifiedCustomReportsResponse Returns available specified custom reports. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSummaryDate.md b/api_docs/v1/UsageSummaryDate.md index 99a15a39960..79bd7198208 100644 --- a/api_docs/v1/UsageSummaryDate.md +++ b/api_docs/v1/UsageSummaryDate.md @@ -3,6 +3,7 @@ # UsageSummaryDate Response with hourly report of all data billed by Datadog all organizations. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSummaryDateOrg.md b/api_docs/v1/UsageSummaryDateOrg.md index af45df51712..7f415225e00 100644 --- a/api_docs/v1/UsageSummaryDateOrg.md +++ b/api_docs/v1/UsageSummaryDateOrg.md @@ -3,6 +3,7 @@ # UsageSummaryDateOrg Global hourly report of all data billed by Datadog for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSummaryResponse.md b/api_docs/v1/UsageSummaryResponse.md index 0437d80fc02..c82f0ff4c08 100644 --- a/api_docs/v1/UsageSummaryResponse.md +++ b/api_docs/v1/UsageSummaryResponse.md @@ -3,6 +3,7 @@ # UsageSummaryResponse Response with hourly report of all data billed by Datadog all organizations. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSyntheticsAPIHour.md b/api_docs/v1/UsageSyntheticsAPIHour.md index c25fccbf867..fb7519e376d 100644 --- a/api_docs/v1/UsageSyntheticsAPIHour.md +++ b/api_docs/v1/UsageSyntheticsAPIHour.md @@ -3,6 +3,7 @@ # UsageSyntheticsAPIHour Number of Synthetics API tests run for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSyntheticsAPIResponse.md b/api_docs/v1/UsageSyntheticsAPIResponse.md index 7cb7eed378d..5084f431366 100644 --- a/api_docs/v1/UsageSyntheticsAPIResponse.md +++ b/api_docs/v1/UsageSyntheticsAPIResponse.md @@ -3,6 +3,7 @@ # UsageSyntheticsAPIResponse Response containing the number of Synthetics API tests run for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSyntheticsBrowserHour.md b/api_docs/v1/UsageSyntheticsBrowserHour.md index e19c2611257..87cea0abd1e 100644 --- a/api_docs/v1/UsageSyntheticsBrowserHour.md +++ b/api_docs/v1/UsageSyntheticsBrowserHour.md @@ -3,6 +3,7 @@ # UsageSyntheticsBrowserHour Number of Synthetics Browser tests run for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSyntheticsBrowserResponse.md b/api_docs/v1/UsageSyntheticsBrowserResponse.md index 70ae460b7e5..241f297f729 100644 --- a/api_docs/v1/UsageSyntheticsBrowserResponse.md +++ b/api_docs/v1/UsageSyntheticsBrowserResponse.md @@ -3,6 +3,7 @@ # UsageSyntheticsBrowserResponse Response containing the number of Synthetics Browser tests run for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSyntheticsHour.md b/api_docs/v1/UsageSyntheticsHour.md index 39a0cb27fa1..efddfe2b174 100644 --- a/api_docs/v1/UsageSyntheticsHour.md +++ b/api_docs/v1/UsageSyntheticsHour.md @@ -3,6 +3,7 @@ # UsageSyntheticsHour The number of synthetics tests run for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSyntheticsResponse.md b/api_docs/v1/UsageSyntheticsResponse.md index d6a4e7cb144..2112096d826 100644 --- a/api_docs/v1/UsageSyntheticsResponse.md +++ b/api_docs/v1/UsageSyntheticsResponse.md @@ -3,6 +3,7 @@ # UsageSyntheticsResponse Response containing the number of Synthetics API tests run for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageTimeseriesHour.md b/api_docs/v1/UsageTimeseriesHour.md index 2dca8e2f6fd..ff57b2e01fe 100644 --- a/api_docs/v1/UsageTimeseriesHour.md +++ b/api_docs/v1/UsageTimeseriesHour.md @@ -3,6 +3,7 @@ # UsageTimeseriesHour The hourly usage of timeseries. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageTimeseriesResponse.md b/api_docs/v1/UsageTimeseriesResponse.md index 5a9827d54b3..4cb393e1190 100644 --- a/api_docs/v1/UsageTimeseriesResponse.md +++ b/api_docs/v1/UsageTimeseriesResponse.md @@ -3,6 +3,7 @@ # UsageTimeseriesResponse Response containing hourly usage of timeseries. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageTopAvgMetricsHour.md b/api_docs/v1/UsageTopAvgMetricsHour.md index ec094b6736f..56f37c7554b 100644 --- a/api_docs/v1/UsageTopAvgMetricsHour.md +++ b/api_docs/v1/UsageTopAvgMetricsHour.md @@ -3,6 +3,7 @@ # UsageTopAvgMetricsHour Number of hourly recorded custom metrics for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageTopAvgMetricsResponse.md b/api_docs/v1/UsageTopAvgMetricsResponse.md index 3800798a28f..b6e9815f4c8 100644 --- a/api_docs/v1/UsageTopAvgMetricsResponse.md +++ b/api_docs/v1/UsageTopAvgMetricsResponse.md @@ -3,6 +3,7 @@ # UsageTopAvgMetricsResponse Response containing the number of hourly recorded custom metrics for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageTraceHour.md b/api_docs/v1/UsageTraceHour.md index 313e2d39af2..4512d96df49 100644 --- a/api_docs/v1/UsageTraceHour.md +++ b/api_docs/v1/UsageTraceHour.md @@ -3,6 +3,7 @@ # UsageTraceHour The hours of trace usage. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageTraceResponse.md b/api_docs/v1/UsageTraceResponse.md index f43ed2bf9c9..c490032fd73 100644 --- a/api_docs/v1/UsageTraceResponse.md +++ b/api_docs/v1/UsageTraceResponse.md @@ -3,6 +3,7 @@ # UsageTraceResponse A response containing trace usage. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageTracingWithoutLimitsHour.md b/api_docs/v1/UsageTracingWithoutLimitsHour.md index 0b5bb939da9..b049c924358 100644 --- a/api_docs/v1/UsageTracingWithoutLimitsHour.md +++ b/api_docs/v1/UsageTracingWithoutLimitsHour.md @@ -3,6 +3,7 @@ # UsageTracingWithoutLimitsHour Tracing without limits usage for a given organization for a given hour. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageTracingWithoutLimitsResponse.md b/api_docs/v1/UsageTracingWithoutLimitsResponse.md index 0785a04fa69..4a94b379af0 100644 --- a/api_docs/v1/UsageTracingWithoutLimitsResponse.md +++ b/api_docs/v1/UsageTracingWithoutLimitsResponse.md @@ -3,6 +3,7 @@ # UsageTracingWithoutLimitsResponse Response containing the tracing without limits usage for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/User.md b/api_docs/v1/User.md index 725aa78e99c..a37022b880c 100644 --- a/api_docs/v1/User.md +++ b/api_docs/v1/User.md @@ -3,6 +3,7 @@ # User Create, edit, and disable users. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UserDisableResponse.md b/api_docs/v1/UserDisableResponse.md index a116a8f5dd3..c38668fe7be 100644 --- a/api_docs/v1/UserDisableResponse.md +++ b/api_docs/v1/UserDisableResponse.md @@ -3,6 +3,7 @@ # UserDisableResponse Array of user disabled for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UserListResponse.md b/api_docs/v1/UserListResponse.md index 84359198a31..b8802cfc09d 100644 --- a/api_docs/v1/UserListResponse.md +++ b/api_docs/v1/UserListResponse.md @@ -3,6 +3,7 @@ # UserListResponse Array of Datadog users for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UserResponse.md b/api_docs/v1/UserResponse.md index eb0105a8091..081d46cdeb8 100644 --- a/api_docs/v1/UserResponse.md +++ b/api_docs/v1/UserResponse.md @@ -3,6 +3,7 @@ # UserResponse A Datadog User. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/Widget.md b/api_docs/v1/Widget.md index a14b8c5e965..dbafcc2daba 100644 --- a/api_docs/v1/Widget.md +++ b/api_docs/v1/Widget.md @@ -3,6 +3,7 @@ # Widget Information about widget. Note: The `layout` property is required for widgets in dashboards with `free` `layout_type` only. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/WidgetAxis.md b/api_docs/v1/WidgetAxis.md index c38bcfab0c6..e1a00bcc76c 100644 --- a/api_docs/v1/WidgetAxis.md +++ b/api_docs/v1/WidgetAxis.md @@ -3,6 +3,7 @@ # WidgetAxis Axis controls for the widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/WidgetConditionalFormat.md b/api_docs/v1/WidgetConditionalFormat.md index 17c465c0b2a..49a72d877b2 100644 --- a/api_docs/v1/WidgetConditionalFormat.md +++ b/api_docs/v1/WidgetConditionalFormat.md @@ -3,6 +3,7 @@ # WidgetConditionalFormat Define a conditional format for the widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/WidgetCustomLink.md b/api_docs/v1/WidgetCustomLink.md index fac5876ffd6..0471667581e 100644 --- a/api_docs/v1/WidgetCustomLink.md +++ b/api_docs/v1/WidgetCustomLink.md @@ -3,6 +3,7 @@ # WidgetCustomLink Custom links help you connect a data value to a URL, like a Datadog page or your AWS console. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/WidgetEvent.md b/api_docs/v1/WidgetEvent.md index f199451c4d1..0710e879674 100644 --- a/api_docs/v1/WidgetEvent.md +++ b/api_docs/v1/WidgetEvent.md @@ -3,6 +3,7 @@ # WidgetEvent Event overlay control options. See the dedicated [Events JSON schema documentation](https://docs.datadoghq.com/dashboards/graphing_json/widget_json/#events-schema) to learn how to build the ``. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/WidgetFieldSort.md b/api_docs/v1/WidgetFieldSort.md index 7e9150aac38..f5666b5579e 100644 --- a/api_docs/v1/WidgetFieldSort.md +++ b/api_docs/v1/WidgetFieldSort.md @@ -3,6 +3,7 @@ # WidgetFieldSort Which column and order to sort by + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/WidgetFormula.md b/api_docs/v1/WidgetFormula.md index bc0d8a24d09..f56e5d64cb8 100644 --- a/api_docs/v1/WidgetFormula.md +++ b/api_docs/v1/WidgetFormula.md @@ -3,6 +3,7 @@ # WidgetFormula Formula to be used in a widget query. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/WidgetFormulaLimit.md b/api_docs/v1/WidgetFormulaLimit.md index 64b248eb9bb..1dc94501c91 100644 --- a/api_docs/v1/WidgetFormulaLimit.md +++ b/api_docs/v1/WidgetFormulaLimit.md @@ -3,6 +3,7 @@ # WidgetFormulaLimit Options for limiting results returned. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/WidgetLayout.md b/api_docs/v1/WidgetLayout.md index 288624aefec..53b733a5822 100644 --- a/api_docs/v1/WidgetLayout.md +++ b/api_docs/v1/WidgetLayout.md @@ -3,6 +3,7 @@ # WidgetLayout The layout for a widget on a free dashboard. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/WidgetMarker.md b/api_docs/v1/WidgetMarker.md index 0d140a0aea5..12c9be5dea4 100644 --- a/api_docs/v1/WidgetMarker.md +++ b/api_docs/v1/WidgetMarker.md @@ -3,6 +3,7 @@ # WidgetMarker Markers allow you to add visual conditional formatting for your graphs. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/WidgetRequestStyle.md b/api_docs/v1/WidgetRequestStyle.md index 6079d01bd08..c08d865cf64 100644 --- a/api_docs/v1/WidgetRequestStyle.md +++ b/api_docs/v1/WidgetRequestStyle.md @@ -3,6 +3,7 @@ # WidgetRequestStyle Define request widget style. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/WidgetStyle.md b/api_docs/v1/WidgetStyle.md index efbdc836281..3dea9a57847 100644 --- a/api_docs/v1/WidgetStyle.md +++ b/api_docs/v1/WidgetStyle.md @@ -3,6 +3,7 @@ # WidgetStyle Widget style definition. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/WidgetTime.md b/api_docs/v1/WidgetTime.md index d7450524203..4f5c2b143c0 100644 --- a/api_docs/v1/WidgetTime.md +++ b/api_docs/v1/WidgetTime.md @@ -3,6 +3,7 @@ # WidgetTime Time setting for the widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/APIErrorResponse.md b/api_docs/v2/APIErrorResponse.md index 762d5496c67..9b3ff1beee4 100644 --- a/api_docs/v2/APIErrorResponse.md +++ b/api_docs/v2/APIErrorResponse.md @@ -3,6 +3,7 @@ # APIErrorResponse API error response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/APIKeyCreateAttributes.md b/api_docs/v2/APIKeyCreateAttributes.md index efcbfe3d29e..7c7bbbd73b2 100644 --- a/api_docs/v2/APIKeyCreateAttributes.md +++ b/api_docs/v2/APIKeyCreateAttributes.md @@ -3,6 +3,7 @@ # APIKeyCreateAttributes Attributes used to create an API Key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/APIKeyCreateData.md b/api_docs/v2/APIKeyCreateData.md index 563eff6daf8..bcd32c2e542 100644 --- a/api_docs/v2/APIKeyCreateData.md +++ b/api_docs/v2/APIKeyCreateData.md @@ -3,6 +3,7 @@ # APIKeyCreateData Object used to create an API key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/APIKeyCreateRequest.md b/api_docs/v2/APIKeyCreateRequest.md index aee4437861f..dca0f144001 100644 --- a/api_docs/v2/APIKeyCreateRequest.md +++ b/api_docs/v2/APIKeyCreateRequest.md @@ -3,6 +3,7 @@ # APIKeyCreateRequest Request used to create an API key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/APIKeyRelationships.md b/api_docs/v2/APIKeyRelationships.md index 4f197721408..8d4bf21f0aa 100644 --- a/api_docs/v2/APIKeyRelationships.md +++ b/api_docs/v2/APIKeyRelationships.md @@ -3,6 +3,7 @@ # APIKeyRelationships Resources related to the API key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/APIKeyResponse.md b/api_docs/v2/APIKeyResponse.md index f73e0cb2c26..4d62d72bfd7 100644 --- a/api_docs/v2/APIKeyResponse.md +++ b/api_docs/v2/APIKeyResponse.md @@ -3,6 +3,7 @@ # APIKeyResponse Response for retrieving an API key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/APIKeyUpdateAttributes.md b/api_docs/v2/APIKeyUpdateAttributes.md index 9543fe5c215..d4867bf68e5 100644 --- a/api_docs/v2/APIKeyUpdateAttributes.md +++ b/api_docs/v2/APIKeyUpdateAttributes.md @@ -3,6 +3,7 @@ # APIKeyUpdateAttributes Attributes used to update an API Key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/APIKeyUpdateData.md b/api_docs/v2/APIKeyUpdateData.md index 7f9fe375969..0b36ad99fa9 100644 --- a/api_docs/v2/APIKeyUpdateData.md +++ b/api_docs/v2/APIKeyUpdateData.md @@ -3,6 +3,7 @@ # APIKeyUpdateData Object used to update an API key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/APIKeyUpdateRequest.md b/api_docs/v2/APIKeyUpdateRequest.md index 0423daf88e1..35bb4d5138c 100644 --- a/api_docs/v2/APIKeyUpdateRequest.md +++ b/api_docs/v2/APIKeyUpdateRequest.md @@ -3,6 +3,7 @@ # APIKeyUpdateRequest Request used to update an API key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/APIKeysResponse.md b/api_docs/v2/APIKeysResponse.md index c05c8c2ef20..9dbc86a16d2 100644 --- a/api_docs/v2/APIKeysResponse.md +++ b/api_docs/v2/APIKeysResponse.md @@ -3,6 +3,7 @@ # APIKeysResponse Response for a list of API keys. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ApplicationKeyCreateAttributes.md b/api_docs/v2/ApplicationKeyCreateAttributes.md index b13b17ffd01..b8a284c21a9 100644 --- a/api_docs/v2/ApplicationKeyCreateAttributes.md +++ b/api_docs/v2/ApplicationKeyCreateAttributes.md @@ -3,6 +3,7 @@ # ApplicationKeyCreateAttributes Attributes used to create an application Key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ApplicationKeyCreateData.md b/api_docs/v2/ApplicationKeyCreateData.md index 9c6ffe1ad58..890ffefefea 100644 --- a/api_docs/v2/ApplicationKeyCreateData.md +++ b/api_docs/v2/ApplicationKeyCreateData.md @@ -3,6 +3,7 @@ # ApplicationKeyCreateData Object used to create an application key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ApplicationKeyCreateRequest.md b/api_docs/v2/ApplicationKeyCreateRequest.md index fdc458321c4..4fbca11e7bc 100644 --- a/api_docs/v2/ApplicationKeyCreateRequest.md +++ b/api_docs/v2/ApplicationKeyCreateRequest.md @@ -3,6 +3,7 @@ # ApplicationKeyCreateRequest Request used to create an application key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ApplicationKeyRelationships.md b/api_docs/v2/ApplicationKeyRelationships.md index 1c5ad131334..9336fe74769 100644 --- a/api_docs/v2/ApplicationKeyRelationships.md +++ b/api_docs/v2/ApplicationKeyRelationships.md @@ -3,6 +3,7 @@ # ApplicationKeyRelationships Resources related to the application key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ApplicationKeyResponse.md b/api_docs/v2/ApplicationKeyResponse.md index 1712ffb8684..9a5dfedaca8 100644 --- a/api_docs/v2/ApplicationKeyResponse.md +++ b/api_docs/v2/ApplicationKeyResponse.md @@ -3,6 +3,7 @@ # ApplicationKeyResponse Response for retrieving an application key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ApplicationKeyUpdateAttributes.md b/api_docs/v2/ApplicationKeyUpdateAttributes.md index fe28f6845ec..0f0879a4943 100644 --- a/api_docs/v2/ApplicationKeyUpdateAttributes.md +++ b/api_docs/v2/ApplicationKeyUpdateAttributes.md @@ -3,6 +3,7 @@ # ApplicationKeyUpdateAttributes Attributes used to update an application Key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ApplicationKeyUpdateData.md b/api_docs/v2/ApplicationKeyUpdateData.md index d64f3656c84..d00d9ed4a21 100644 --- a/api_docs/v2/ApplicationKeyUpdateData.md +++ b/api_docs/v2/ApplicationKeyUpdateData.md @@ -3,6 +3,7 @@ # ApplicationKeyUpdateData Object used to update an application key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ApplicationKeyUpdateRequest.md b/api_docs/v2/ApplicationKeyUpdateRequest.md index 170a8d1e694..c249ed71b17 100644 --- a/api_docs/v2/ApplicationKeyUpdateRequest.md +++ b/api_docs/v2/ApplicationKeyUpdateRequest.md @@ -3,6 +3,7 @@ # ApplicationKeyUpdateRequest Request used to update an application key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/Creator.md b/api_docs/v2/Creator.md index c2e7cf2fcb0..7a606571319 100644 --- a/api_docs/v2/Creator.md +++ b/api_docs/v2/Creator.md @@ -3,6 +3,7 @@ # Creator Creator of the object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/DashboardListAddItemsRequest.md b/api_docs/v2/DashboardListAddItemsRequest.md index 772bd4cafc1..47214dc008a 100644 --- a/api_docs/v2/DashboardListAddItemsRequest.md +++ b/api_docs/v2/DashboardListAddItemsRequest.md @@ -3,6 +3,7 @@ # DashboardListAddItemsRequest Request containing a list of dashboards to add. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/DashboardListAddItemsResponse.md b/api_docs/v2/DashboardListAddItemsResponse.md index a592abd6432..6060be28cd5 100644 --- a/api_docs/v2/DashboardListAddItemsResponse.md +++ b/api_docs/v2/DashboardListAddItemsResponse.md @@ -3,6 +3,7 @@ # DashboardListAddItemsResponse Response containing a list of added dashboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/DashboardListDeleteItemsRequest.md b/api_docs/v2/DashboardListDeleteItemsRequest.md index 0bfe26ca5f7..2f65457eaec 100644 --- a/api_docs/v2/DashboardListDeleteItemsRequest.md +++ b/api_docs/v2/DashboardListDeleteItemsRequest.md @@ -3,6 +3,7 @@ # DashboardListDeleteItemsRequest Request containing a list of dashboards to delete. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/DashboardListDeleteItemsResponse.md b/api_docs/v2/DashboardListDeleteItemsResponse.md index 3dcf9238a72..8db2b289237 100644 --- a/api_docs/v2/DashboardListDeleteItemsResponse.md +++ b/api_docs/v2/DashboardListDeleteItemsResponse.md @@ -3,6 +3,7 @@ # DashboardListDeleteItemsResponse Response containing a list of deleted dashboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/DashboardListItem.md b/api_docs/v2/DashboardListItem.md index bb3a8a6082f..dcb89acd083 100644 --- a/api_docs/v2/DashboardListItem.md +++ b/api_docs/v2/DashboardListItem.md @@ -3,6 +3,7 @@ # DashboardListItem A dashboard within a list. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/DashboardListItemRequest.md b/api_docs/v2/DashboardListItemRequest.md index f5d6978bd92..c1c78542f9e 100644 --- a/api_docs/v2/DashboardListItemRequest.md +++ b/api_docs/v2/DashboardListItemRequest.md @@ -3,6 +3,7 @@ # DashboardListItemRequest A dashboard within a list. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/DashboardListItemResponse.md b/api_docs/v2/DashboardListItemResponse.md index d54ecd16431..df9af44cf92 100644 --- a/api_docs/v2/DashboardListItemResponse.md +++ b/api_docs/v2/DashboardListItemResponse.md @@ -3,6 +3,7 @@ # DashboardListItemResponse A dashboard within a list. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/DashboardListItems.md b/api_docs/v2/DashboardListItems.md index a4bd827c04c..a2406e81d3d 100644 --- a/api_docs/v2/DashboardListItems.md +++ b/api_docs/v2/DashboardListItems.md @@ -3,6 +3,7 @@ # DashboardListItems Dashboards within a list. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/DashboardListUpdateItemsRequest.md b/api_docs/v2/DashboardListUpdateItemsRequest.md index 4c772c319e0..a4213aedd3a 100644 --- a/api_docs/v2/DashboardListUpdateItemsRequest.md +++ b/api_docs/v2/DashboardListUpdateItemsRequest.md @@ -3,6 +3,7 @@ # DashboardListUpdateItemsRequest Request containing the list of dashboards to update to. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/DashboardListUpdateItemsResponse.md b/api_docs/v2/DashboardListUpdateItemsResponse.md index d1778080763..41a5cfc6196 100644 --- a/api_docs/v2/DashboardListUpdateItemsResponse.md +++ b/api_docs/v2/DashboardListUpdateItemsResponse.md @@ -3,6 +3,7 @@ # DashboardListUpdateItemsResponse Response containing a list of updated dashboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/FullAPIKey.md b/api_docs/v2/FullAPIKey.md index e43e5b7aa96..7383fe32f3b 100644 --- a/api_docs/v2/FullAPIKey.md +++ b/api_docs/v2/FullAPIKey.md @@ -3,6 +3,7 @@ # FullAPIKey Datadog API key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/FullAPIKeyAttributes.md b/api_docs/v2/FullAPIKeyAttributes.md index e7b2d16eac3..beca5fe229c 100644 --- a/api_docs/v2/FullAPIKeyAttributes.md +++ b/api_docs/v2/FullAPIKeyAttributes.md @@ -3,6 +3,7 @@ # FullAPIKeyAttributes Attributes of a full API key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/FullApplicationKey.md b/api_docs/v2/FullApplicationKey.md index 9ac8d597e4c..5f12243f900 100644 --- a/api_docs/v2/FullApplicationKey.md +++ b/api_docs/v2/FullApplicationKey.md @@ -3,6 +3,7 @@ # FullApplicationKey Datadog application key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/FullApplicationKeyAttributes.md b/api_docs/v2/FullApplicationKeyAttributes.md index 6ef0bbc1c29..3c8ef4c59f6 100644 --- a/api_docs/v2/FullApplicationKeyAttributes.md +++ b/api_docs/v2/FullApplicationKeyAttributes.md @@ -3,6 +3,7 @@ # FullApplicationKeyAttributes Attributes of a full application key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentCreateAttributes.md b/api_docs/v2/IncidentCreateAttributes.md index 7b3e09cce9b..0086d7b8b44 100644 --- a/api_docs/v2/IncidentCreateAttributes.md +++ b/api_docs/v2/IncidentCreateAttributes.md @@ -3,6 +3,7 @@ # IncidentCreateAttributes The incident's attributes for a create request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentCreateData.md b/api_docs/v2/IncidentCreateData.md index d942a9f8cad..81605977f66 100644 --- a/api_docs/v2/IncidentCreateData.md +++ b/api_docs/v2/IncidentCreateData.md @@ -3,6 +3,7 @@ # IncidentCreateData Incident data for a create request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentCreateRelationships.md b/api_docs/v2/IncidentCreateRelationships.md index 28960a6fef6..41959d0bc23 100644 --- a/api_docs/v2/IncidentCreateRelationships.md +++ b/api_docs/v2/IncidentCreateRelationships.md @@ -3,6 +3,7 @@ # IncidentCreateRelationships The relationships the incident will have with other resources once created. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentCreateRequest.md b/api_docs/v2/IncidentCreateRequest.md index e72d1871e06..e0ae0063489 100644 --- a/api_docs/v2/IncidentCreateRequest.md +++ b/api_docs/v2/IncidentCreateRequest.md @@ -3,6 +3,7 @@ # IncidentCreateRequest Create request for an incident. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentFieldAttributesMultipleValue.md b/api_docs/v2/IncidentFieldAttributesMultipleValue.md index f3d110e043c..3a89efaa264 100644 --- a/api_docs/v2/IncidentFieldAttributesMultipleValue.md +++ b/api_docs/v2/IncidentFieldAttributesMultipleValue.md @@ -3,6 +3,7 @@ # IncidentFieldAttributesMultipleValue A field with potentially multiple values selected. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentFieldAttributesSingleValue.md b/api_docs/v2/IncidentFieldAttributesSingleValue.md index c43841ea61c..78189011575 100644 --- a/api_docs/v2/IncidentFieldAttributesSingleValue.md +++ b/api_docs/v2/IncidentFieldAttributesSingleValue.md @@ -3,6 +3,7 @@ # IncidentFieldAttributesSingleValue A field with a single value selected. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentResponse.md b/api_docs/v2/IncidentResponse.md index 8ff0428ef34..daa611b211c 100644 --- a/api_docs/v2/IncidentResponse.md +++ b/api_docs/v2/IncidentResponse.md @@ -3,6 +3,7 @@ # IncidentResponse Response with an incident. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentResponseAttributes.md b/api_docs/v2/IncidentResponseAttributes.md index 092d6d462a7..982a62b38b5 100644 --- a/api_docs/v2/IncidentResponseAttributes.md +++ b/api_docs/v2/IncidentResponseAttributes.md @@ -3,6 +3,7 @@ # IncidentResponseAttributes The incident's attributes from a response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentResponseData.md b/api_docs/v2/IncidentResponseData.md index d1539f2d818..dd32515cd1c 100644 --- a/api_docs/v2/IncidentResponseData.md +++ b/api_docs/v2/IncidentResponseData.md @@ -3,6 +3,7 @@ # IncidentResponseData Incident data from a response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentResponseRelationships.md b/api_docs/v2/IncidentResponseRelationships.md index 0a4e081b801..fd7ef87bbc0 100644 --- a/api_docs/v2/IncidentResponseRelationships.md +++ b/api_docs/v2/IncidentResponseRelationships.md @@ -3,6 +3,7 @@ # IncidentResponseRelationships The incident's relationships from a response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServiceCreateAttributes.md b/api_docs/v2/IncidentServiceCreateAttributes.md index ae9b8197d29..dcc6be7e1b5 100644 --- a/api_docs/v2/IncidentServiceCreateAttributes.md +++ b/api_docs/v2/IncidentServiceCreateAttributes.md @@ -3,6 +3,7 @@ # IncidentServiceCreateAttributes The incident service's attributes for a create request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServiceCreateData.md b/api_docs/v2/IncidentServiceCreateData.md index 375bf6b1026..f61e9dea5b4 100644 --- a/api_docs/v2/IncidentServiceCreateData.md +++ b/api_docs/v2/IncidentServiceCreateData.md @@ -3,6 +3,7 @@ # IncidentServiceCreateData Incident Service payload for create requests. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServiceCreateRequest.md b/api_docs/v2/IncidentServiceCreateRequest.md index 62438fdcf38..f7126fec045 100644 --- a/api_docs/v2/IncidentServiceCreateRequest.md +++ b/api_docs/v2/IncidentServiceCreateRequest.md @@ -3,6 +3,7 @@ # IncidentServiceCreateRequest Create request with an incident service payload. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServiceRelationships.md b/api_docs/v2/IncidentServiceRelationships.md index 29c274ea8bb..4647065cf72 100644 --- a/api_docs/v2/IncidentServiceRelationships.md +++ b/api_docs/v2/IncidentServiceRelationships.md @@ -3,6 +3,7 @@ # IncidentServiceRelationships The incident service's relationships. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServiceResponse.md b/api_docs/v2/IncidentServiceResponse.md index e5667482bc4..bcabf57fa8b 100644 --- a/api_docs/v2/IncidentServiceResponse.md +++ b/api_docs/v2/IncidentServiceResponse.md @@ -3,6 +3,7 @@ # IncidentServiceResponse Response with an incident service payload. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServiceResponseAttributes.md b/api_docs/v2/IncidentServiceResponseAttributes.md index eabc1497c81..c45aed0bf3e 100644 --- a/api_docs/v2/IncidentServiceResponseAttributes.md +++ b/api_docs/v2/IncidentServiceResponseAttributes.md @@ -3,6 +3,7 @@ # IncidentServiceResponseAttributes The incident service's attributes from a response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServiceResponseData.md b/api_docs/v2/IncidentServiceResponseData.md index b65381456d5..f9a58c52bde 100644 --- a/api_docs/v2/IncidentServiceResponseData.md +++ b/api_docs/v2/IncidentServiceResponseData.md @@ -3,6 +3,7 @@ # IncidentServiceResponseData Incident Service data from responses. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServiceUpdateAttributes.md b/api_docs/v2/IncidentServiceUpdateAttributes.md index d5859ed5a56..9f1f260fc57 100644 --- a/api_docs/v2/IncidentServiceUpdateAttributes.md +++ b/api_docs/v2/IncidentServiceUpdateAttributes.md @@ -3,6 +3,7 @@ # IncidentServiceUpdateAttributes The incident service's attributes for an update request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServiceUpdateData.md b/api_docs/v2/IncidentServiceUpdateData.md index 1128c2e2baf..58af2016f50 100644 --- a/api_docs/v2/IncidentServiceUpdateData.md +++ b/api_docs/v2/IncidentServiceUpdateData.md @@ -3,6 +3,7 @@ # IncidentServiceUpdateData Incident Service payload for update requests. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServiceUpdateRequest.md b/api_docs/v2/IncidentServiceUpdateRequest.md index aede8001c1a..797c67650bc 100644 --- a/api_docs/v2/IncidentServiceUpdateRequest.md +++ b/api_docs/v2/IncidentServiceUpdateRequest.md @@ -3,6 +3,7 @@ # IncidentServiceUpdateRequest Update request with an incident service payload. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServicesResponse.md b/api_docs/v2/IncidentServicesResponse.md index 514c36810f6..c0f6db251b0 100644 --- a/api_docs/v2/IncidentServicesResponse.md +++ b/api_docs/v2/IncidentServicesResponse.md @@ -3,6 +3,7 @@ # IncidentServicesResponse Response with a list of incident service payloads. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServicesResponseMeta.md b/api_docs/v2/IncidentServicesResponseMeta.md index 6f3ddddcfac..b58f00ca87c 100644 --- a/api_docs/v2/IncidentServicesResponseMeta.md +++ b/api_docs/v2/IncidentServicesResponseMeta.md @@ -3,6 +3,7 @@ # IncidentServicesResponseMeta The metadata object containing pagination metadata. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServicesResponseMetaPagination.md b/api_docs/v2/IncidentServicesResponseMetaPagination.md index 6a5740f2c3a..b4e07ae1c1a 100644 --- a/api_docs/v2/IncidentServicesResponseMetaPagination.md +++ b/api_docs/v2/IncidentServicesResponseMetaPagination.md @@ -3,6 +3,7 @@ # IncidentServicesResponseMetaPagination Pagination properties. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTeamCreateAttributes.md b/api_docs/v2/IncidentTeamCreateAttributes.md index 2c668e6017b..a00a0617eeb 100644 --- a/api_docs/v2/IncidentTeamCreateAttributes.md +++ b/api_docs/v2/IncidentTeamCreateAttributes.md @@ -3,6 +3,7 @@ # IncidentTeamCreateAttributes The incident team's attributes for a create request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTeamCreateData.md b/api_docs/v2/IncidentTeamCreateData.md index a1e47eae4bf..13963d7b494 100644 --- a/api_docs/v2/IncidentTeamCreateData.md +++ b/api_docs/v2/IncidentTeamCreateData.md @@ -3,6 +3,7 @@ # IncidentTeamCreateData Incident Team data for a create request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTeamCreateRequest.md b/api_docs/v2/IncidentTeamCreateRequest.md index 058638720ab..6d50a68034f 100644 --- a/api_docs/v2/IncidentTeamCreateRequest.md +++ b/api_docs/v2/IncidentTeamCreateRequest.md @@ -3,6 +3,7 @@ # IncidentTeamCreateRequest Create request with an incident team payload. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTeamRelationships.md b/api_docs/v2/IncidentTeamRelationships.md index e9721640ea7..5db344cc26b 100644 --- a/api_docs/v2/IncidentTeamRelationships.md +++ b/api_docs/v2/IncidentTeamRelationships.md @@ -3,6 +3,7 @@ # IncidentTeamRelationships The incident team's relationships. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTeamResponse.md b/api_docs/v2/IncidentTeamResponse.md index 05332b3f682..3ebdee8228f 100644 --- a/api_docs/v2/IncidentTeamResponse.md +++ b/api_docs/v2/IncidentTeamResponse.md @@ -3,6 +3,7 @@ # IncidentTeamResponse Response with an incident team payload. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTeamResponseAttributes.md b/api_docs/v2/IncidentTeamResponseAttributes.md index efcebe91772..5549a7fc8fd 100644 --- a/api_docs/v2/IncidentTeamResponseAttributes.md +++ b/api_docs/v2/IncidentTeamResponseAttributes.md @@ -3,6 +3,7 @@ # IncidentTeamResponseAttributes The incident team's attributes from a response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTeamResponseData.md b/api_docs/v2/IncidentTeamResponseData.md index f2a604821b5..c0a57846dc1 100644 --- a/api_docs/v2/IncidentTeamResponseData.md +++ b/api_docs/v2/IncidentTeamResponseData.md @@ -3,6 +3,7 @@ # IncidentTeamResponseData Incident Team data from a response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTeamUpdateAttributes.md b/api_docs/v2/IncidentTeamUpdateAttributes.md index debd79341e8..0f26facf7fd 100644 --- a/api_docs/v2/IncidentTeamUpdateAttributes.md +++ b/api_docs/v2/IncidentTeamUpdateAttributes.md @@ -3,6 +3,7 @@ # IncidentTeamUpdateAttributes The incident team's attributes for an update request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTeamUpdateData.md b/api_docs/v2/IncidentTeamUpdateData.md index 42e51147d80..108c569bb77 100644 --- a/api_docs/v2/IncidentTeamUpdateData.md +++ b/api_docs/v2/IncidentTeamUpdateData.md @@ -3,6 +3,7 @@ # IncidentTeamUpdateData Incident Team data for an update request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTeamUpdateRequest.md b/api_docs/v2/IncidentTeamUpdateRequest.md index 3af168c8743..01c79f32478 100644 --- a/api_docs/v2/IncidentTeamUpdateRequest.md +++ b/api_docs/v2/IncidentTeamUpdateRequest.md @@ -3,6 +3,7 @@ # IncidentTeamUpdateRequest Update request with an incident team payload. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTeamsResponse.md b/api_docs/v2/IncidentTeamsResponse.md index 7a0f296760b..41486806e66 100644 --- a/api_docs/v2/IncidentTeamsResponse.md +++ b/api_docs/v2/IncidentTeamsResponse.md @@ -3,6 +3,7 @@ # IncidentTeamsResponse Response with a list of incident team payloads. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTimelineCellMarkdownCreateAttributes.md b/api_docs/v2/IncidentTimelineCellMarkdownCreateAttributes.md index 629499f2ba1..4c91f2329ae 100644 --- a/api_docs/v2/IncidentTimelineCellMarkdownCreateAttributes.md +++ b/api_docs/v2/IncidentTimelineCellMarkdownCreateAttributes.md @@ -3,6 +3,7 @@ # IncidentTimelineCellMarkdownCreateAttributes Timeline cell data for Markdown timeline cells for a create request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTimelineCellMarkdownCreateAttributesContent.md b/api_docs/v2/IncidentTimelineCellMarkdownCreateAttributesContent.md index 4b40695f993..d4d63f9ad07 100644 --- a/api_docs/v2/IncidentTimelineCellMarkdownCreateAttributesContent.md +++ b/api_docs/v2/IncidentTimelineCellMarkdownCreateAttributesContent.md @@ -3,6 +3,7 @@ # IncidentTimelineCellMarkdownCreateAttributesContent The Markdown timeline cell contents. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentUpdateAttributes.md b/api_docs/v2/IncidentUpdateAttributes.md index 142f424153a..3833d185536 100644 --- a/api_docs/v2/IncidentUpdateAttributes.md +++ b/api_docs/v2/IncidentUpdateAttributes.md @@ -3,6 +3,7 @@ # IncidentUpdateAttributes The incident's attributes for an update request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentUpdateData.md b/api_docs/v2/IncidentUpdateData.md index e2d83a3d366..4073f1cb626 100644 --- a/api_docs/v2/IncidentUpdateData.md +++ b/api_docs/v2/IncidentUpdateData.md @@ -3,6 +3,7 @@ # IncidentUpdateData Incident data for an update request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentUpdateRelationships.md b/api_docs/v2/IncidentUpdateRelationships.md index 3409ed9d7e0..27b06a260b0 100644 --- a/api_docs/v2/IncidentUpdateRelationships.md +++ b/api_docs/v2/IncidentUpdateRelationships.md @@ -3,6 +3,7 @@ # IncidentUpdateRelationships The incident's relationships for an update request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentUpdateRequest.md b/api_docs/v2/IncidentUpdateRequest.md index 72d9add0f47..25be3c636c6 100644 --- a/api_docs/v2/IncidentUpdateRequest.md +++ b/api_docs/v2/IncidentUpdateRequest.md @@ -3,6 +3,7 @@ # IncidentUpdateRequest Update request for an incident. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentsResponse.md b/api_docs/v2/IncidentsResponse.md index 089ce2b5c28..c1ca10dd4ff 100644 --- a/api_docs/v2/IncidentsResponse.md +++ b/api_docs/v2/IncidentsResponse.md @@ -3,6 +3,7 @@ # IncidentsResponse Response with a list of incidents. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ListApplicationKeysResponse.md b/api_docs/v2/ListApplicationKeysResponse.md index 26ae8071cea..c246e031076 100644 --- a/api_docs/v2/ListApplicationKeysResponse.md +++ b/api_docs/v2/ListApplicationKeysResponse.md @@ -3,6 +3,7 @@ # ListApplicationKeysResponse Response for a list of application keys. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/Log.md b/api_docs/v2/Log.md index 287ca8e0c82..119e330218c 100644 --- a/api_docs/v2/Log.md +++ b/api_docs/v2/Log.md @@ -3,6 +3,7 @@ # Log Object description of a log after being processed and stored by Datadog. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogAttributes.md b/api_docs/v2/LogAttributes.md index ab93516b172..f4f88d76798 100644 --- a/api_docs/v2/LogAttributes.md +++ b/api_docs/v2/LogAttributes.md @@ -3,6 +3,7 @@ # LogAttributes JSON object containing all log attributes and their associated values. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsAggregateBucket.md b/api_docs/v2/LogsAggregateBucket.md index cd1dc5ab66c..31407e7b595 100644 --- a/api_docs/v2/LogsAggregateBucket.md +++ b/api_docs/v2/LogsAggregateBucket.md @@ -3,6 +3,7 @@ # LogsAggregateBucket A bucket values + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsAggregateBucketValueTimeseries.md b/api_docs/v2/LogsAggregateBucketValueTimeseries.md index ad8547063e6..6eae4fd6e96 100644 --- a/api_docs/v2/LogsAggregateBucketValueTimeseries.md +++ b/api_docs/v2/LogsAggregateBucketValueTimeseries.md @@ -3,6 +3,7 @@ # LogsAggregateBucketValueTimeseries A timeseries array + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsAggregateBucketValueTimeseriesPoint.md b/api_docs/v2/LogsAggregateBucketValueTimeseriesPoint.md index f927b3c35d3..48bd076a99d 100644 --- a/api_docs/v2/LogsAggregateBucketValueTimeseriesPoint.md +++ b/api_docs/v2/LogsAggregateBucketValueTimeseriesPoint.md @@ -3,6 +3,7 @@ # LogsAggregateBucketValueTimeseriesPoint A timeseries point + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsAggregateRequest.md b/api_docs/v2/LogsAggregateRequest.md index f3a61d816d1..9f1c68765d6 100644 --- a/api_docs/v2/LogsAggregateRequest.md +++ b/api_docs/v2/LogsAggregateRequest.md @@ -3,6 +3,7 @@ # LogsAggregateRequest The object sent with the request to retrieve a list of logs from your organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsAggregateRequestPage.md b/api_docs/v2/LogsAggregateRequestPage.md index 49fc449a4e8..1f7339b2730 100644 --- a/api_docs/v2/LogsAggregateRequestPage.md +++ b/api_docs/v2/LogsAggregateRequestPage.md @@ -3,6 +3,7 @@ # LogsAggregateRequestPage Paging settings + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsAggregateResponse.md b/api_docs/v2/LogsAggregateResponse.md index 2df078d50b5..250556db1e9 100644 --- a/api_docs/v2/LogsAggregateResponse.md +++ b/api_docs/v2/LogsAggregateResponse.md @@ -3,6 +3,7 @@ # LogsAggregateResponse The response object for the logs aggregate API endpoint + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsAggregateResponseData.md b/api_docs/v2/LogsAggregateResponseData.md index b58cab7b71f..65494dd2f6a 100644 --- a/api_docs/v2/LogsAggregateResponseData.md +++ b/api_docs/v2/LogsAggregateResponseData.md @@ -3,6 +3,7 @@ # LogsAggregateResponseData The query results + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsAggregateSort.md b/api_docs/v2/LogsAggregateSort.md index ae39ff63de3..91319ee88da 100644 --- a/api_docs/v2/LogsAggregateSort.md +++ b/api_docs/v2/LogsAggregateSort.md @@ -3,6 +3,7 @@ # LogsAggregateSort A sort rule + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchive.md b/api_docs/v2/LogsArchive.md index 2f1a4cb5e34..78ef488f771 100644 --- a/api_docs/v2/LogsArchive.md +++ b/api_docs/v2/LogsArchive.md @@ -3,6 +3,7 @@ # LogsArchive The logs archive. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveAttributes.md b/api_docs/v2/LogsArchiveAttributes.md index 27fab1d0bd6..aef7b6f027f 100644 --- a/api_docs/v2/LogsArchiveAttributes.md +++ b/api_docs/v2/LogsArchiveAttributes.md @@ -3,6 +3,7 @@ # LogsArchiveAttributes The attributes associated with the archive. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveCreateRequest.md b/api_docs/v2/LogsArchiveCreateRequest.md index c337229c76d..93930bddaff 100644 --- a/api_docs/v2/LogsArchiveCreateRequest.md +++ b/api_docs/v2/LogsArchiveCreateRequest.md @@ -3,6 +3,7 @@ # LogsArchiveCreateRequest The logs archive. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveCreateRequestAttributes.md b/api_docs/v2/LogsArchiveCreateRequestAttributes.md index 0e8a13eaa4d..fc88bfc7676 100644 --- a/api_docs/v2/LogsArchiveCreateRequestAttributes.md +++ b/api_docs/v2/LogsArchiveCreateRequestAttributes.md @@ -3,6 +3,7 @@ # LogsArchiveCreateRequestAttributes The attributes associated with the archive. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveCreateRequestDefinition.md b/api_docs/v2/LogsArchiveCreateRequestDefinition.md index 1e8816ebdb6..129ab6f4c61 100644 --- a/api_docs/v2/LogsArchiveCreateRequestDefinition.md +++ b/api_docs/v2/LogsArchiveCreateRequestDefinition.md @@ -3,6 +3,7 @@ # LogsArchiveCreateRequestDefinition The definition of an archive. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveDefinition.md b/api_docs/v2/LogsArchiveDefinition.md index d9f3d2ec45e..85fc8b0ddd1 100644 --- a/api_docs/v2/LogsArchiveDefinition.md +++ b/api_docs/v2/LogsArchiveDefinition.md @@ -3,6 +3,7 @@ # LogsArchiveDefinition The definition of an archive. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveDestinationAzure.md b/api_docs/v2/LogsArchiveDestinationAzure.md index cd4a2bdc9cc..7f8adbe38bb 100644 --- a/api_docs/v2/LogsArchiveDestinationAzure.md +++ b/api_docs/v2/LogsArchiveDestinationAzure.md @@ -3,6 +3,7 @@ # LogsArchiveDestinationAzure The Azure archive destination. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveDestinationGCS.md b/api_docs/v2/LogsArchiveDestinationGCS.md index 12c637a8494..40fc552bea4 100644 --- a/api_docs/v2/LogsArchiveDestinationGCS.md +++ b/api_docs/v2/LogsArchiveDestinationGCS.md @@ -3,6 +3,7 @@ # LogsArchiveDestinationGCS The GCS archive destination. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveDestinationS3.md b/api_docs/v2/LogsArchiveDestinationS3.md index 1f1fa613447..4139308924f 100644 --- a/api_docs/v2/LogsArchiveDestinationS3.md +++ b/api_docs/v2/LogsArchiveDestinationS3.md @@ -3,6 +3,7 @@ # LogsArchiveDestinationS3 The S3 archive destination. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveIntegrationAzure.md b/api_docs/v2/LogsArchiveIntegrationAzure.md index e98ec2e9414..6d82de2dd87 100644 --- a/api_docs/v2/LogsArchiveIntegrationAzure.md +++ b/api_docs/v2/LogsArchiveIntegrationAzure.md @@ -3,6 +3,7 @@ # LogsArchiveIntegrationAzure The Azure archive's integration destination. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveIntegrationGCS.md b/api_docs/v2/LogsArchiveIntegrationGCS.md index 595beba7d4c..9dadc8c252f 100644 --- a/api_docs/v2/LogsArchiveIntegrationGCS.md +++ b/api_docs/v2/LogsArchiveIntegrationGCS.md @@ -3,6 +3,7 @@ # LogsArchiveIntegrationGCS The GCS archive's integration destination. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveIntegrationS3.md b/api_docs/v2/LogsArchiveIntegrationS3.md index b9c34655ba1..703bcd0450e 100644 --- a/api_docs/v2/LogsArchiveIntegrationS3.md +++ b/api_docs/v2/LogsArchiveIntegrationS3.md @@ -3,6 +3,7 @@ # LogsArchiveIntegrationS3 The S3 Archive's integration destination. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveOrder.md b/api_docs/v2/LogsArchiveOrder.md index f773cd12ece..ee1f21a948d 100644 --- a/api_docs/v2/LogsArchiveOrder.md +++ b/api_docs/v2/LogsArchiveOrder.md @@ -3,6 +3,7 @@ # LogsArchiveOrder A ordered list of archive IDs. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveOrderAttributes.md b/api_docs/v2/LogsArchiveOrderAttributes.md index d36a2939430..e52daf02870 100644 --- a/api_docs/v2/LogsArchiveOrderAttributes.md +++ b/api_docs/v2/LogsArchiveOrderAttributes.md @@ -3,6 +3,7 @@ # LogsArchiveOrderAttributes The attributes associated with the archive order. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveOrderDefinition.md b/api_docs/v2/LogsArchiveOrderDefinition.md index a50c0f3c74e..be52667a6b5 100644 --- a/api_docs/v2/LogsArchiveOrderDefinition.md +++ b/api_docs/v2/LogsArchiveOrderDefinition.md @@ -3,6 +3,7 @@ # LogsArchiveOrderDefinition The definition of an archive order. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchives.md b/api_docs/v2/LogsArchives.md index c8baa13c627..96d1735995b 100644 --- a/api_docs/v2/LogsArchives.md +++ b/api_docs/v2/LogsArchives.md @@ -3,6 +3,7 @@ # LogsArchives The available archives. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsCompute.md b/api_docs/v2/LogsCompute.md index 1a9475093a5..9e6f5fec84a 100644 --- a/api_docs/v2/LogsCompute.md +++ b/api_docs/v2/LogsCompute.md @@ -3,6 +3,7 @@ # LogsCompute A compute rule to compute metrics or timeseries + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsGroupBy.md b/api_docs/v2/LogsGroupBy.md index a398aad6f56..02897ce83aa 100644 --- a/api_docs/v2/LogsGroupBy.md +++ b/api_docs/v2/LogsGroupBy.md @@ -3,6 +3,7 @@ # LogsGroupBy A group by rule + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsGroupByHistogram.md b/api_docs/v2/LogsGroupByHistogram.md index a72ec16ad69..f18374e983a 100644 --- a/api_docs/v2/LogsGroupByHistogram.md +++ b/api_docs/v2/LogsGroupByHistogram.md @@ -3,6 +3,7 @@ # LogsGroupByHistogram Used to perform a histogram computation (only for measure facets). Note: At most 100 buckets are allowed, the number of buckets is (max - min)/interval. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsListRequest.md b/api_docs/v2/LogsListRequest.md index af231d71ac8..0723a848e6e 100644 --- a/api_docs/v2/LogsListRequest.md +++ b/api_docs/v2/LogsListRequest.md @@ -3,6 +3,7 @@ # LogsListRequest The request for a logs list. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsListRequestPage.md b/api_docs/v2/LogsListRequestPage.md index ed030a14dc9..e01f781c804 100644 --- a/api_docs/v2/LogsListRequestPage.md +++ b/api_docs/v2/LogsListRequestPage.md @@ -3,6 +3,7 @@ # LogsListRequestPage Paging attributes for listing logs. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsListResponse.md b/api_docs/v2/LogsListResponse.md index 93b02989bf1..f24c3eec548 100644 --- a/api_docs/v2/LogsListResponse.md +++ b/api_docs/v2/LogsListResponse.md @@ -3,6 +3,7 @@ # LogsListResponse Response object with all logs matching the request and pagination information. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsListResponseLinks.md b/api_docs/v2/LogsListResponseLinks.md index f04caa6f705..736282cea6b 100644 --- a/api_docs/v2/LogsListResponseLinks.md +++ b/api_docs/v2/LogsListResponseLinks.md @@ -3,6 +3,7 @@ # LogsListResponseLinks Links attributes. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricCompute.md b/api_docs/v2/LogsMetricCompute.md index 58eff948a9e..9c4698affc0 100644 --- a/api_docs/v2/LogsMetricCompute.md +++ b/api_docs/v2/LogsMetricCompute.md @@ -3,6 +3,7 @@ # LogsMetricCompute The compute rule to compute the log-based metric. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricCreateAttributes.md b/api_docs/v2/LogsMetricCreateAttributes.md index 952129034aa..4e5a5e3062a 100644 --- a/api_docs/v2/LogsMetricCreateAttributes.md +++ b/api_docs/v2/LogsMetricCreateAttributes.md @@ -3,6 +3,7 @@ # LogsMetricCreateAttributes The object describing the Datadog log-based metric to create. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricCreateData.md b/api_docs/v2/LogsMetricCreateData.md index 9c61f774b22..b0e09a0dfc9 100644 --- a/api_docs/v2/LogsMetricCreateData.md +++ b/api_docs/v2/LogsMetricCreateData.md @@ -3,6 +3,7 @@ # LogsMetricCreateData The new log-based metric properties. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricCreateRequest.md b/api_docs/v2/LogsMetricCreateRequest.md index 8a4db445e1f..d1253a0ba99 100644 --- a/api_docs/v2/LogsMetricCreateRequest.md +++ b/api_docs/v2/LogsMetricCreateRequest.md @@ -3,6 +3,7 @@ # LogsMetricCreateRequest The new log-based metric body. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricFilter.md b/api_docs/v2/LogsMetricFilter.md index f384f3350c9..ccd3ed9ad84 100644 --- a/api_docs/v2/LogsMetricFilter.md +++ b/api_docs/v2/LogsMetricFilter.md @@ -3,6 +3,7 @@ # LogsMetricFilter The log-based metric filter. Logs matching this filter will be aggregated in this metric. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricGroupBy.md b/api_docs/v2/LogsMetricGroupBy.md index 906ff144d19..ea4240802ce 100644 --- a/api_docs/v2/LogsMetricGroupBy.md +++ b/api_docs/v2/LogsMetricGroupBy.md @@ -3,6 +3,7 @@ # LogsMetricGroupBy A group by rule. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricResponse.md b/api_docs/v2/LogsMetricResponse.md index 13fe6393e36..8bd16279386 100644 --- a/api_docs/v2/LogsMetricResponse.md +++ b/api_docs/v2/LogsMetricResponse.md @@ -3,6 +3,7 @@ # LogsMetricResponse The log-based metric object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricResponseAttributes.md b/api_docs/v2/LogsMetricResponseAttributes.md index c944d2dd310..07edee98851 100644 --- a/api_docs/v2/LogsMetricResponseAttributes.md +++ b/api_docs/v2/LogsMetricResponseAttributes.md @@ -3,6 +3,7 @@ # LogsMetricResponseAttributes The object describing a Datadog log-based metric. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricResponseCompute.md b/api_docs/v2/LogsMetricResponseCompute.md index b7f3d6c5d7c..c638e600cce 100644 --- a/api_docs/v2/LogsMetricResponseCompute.md +++ b/api_docs/v2/LogsMetricResponseCompute.md @@ -3,6 +3,7 @@ # LogsMetricResponseCompute The compute rule to compute the log-based metric. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricResponseData.md b/api_docs/v2/LogsMetricResponseData.md index 4e7455ccac7..bacd80f89a7 100644 --- a/api_docs/v2/LogsMetricResponseData.md +++ b/api_docs/v2/LogsMetricResponseData.md @@ -3,6 +3,7 @@ # LogsMetricResponseData The log-based metric properties. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricResponseFilter.md b/api_docs/v2/LogsMetricResponseFilter.md index 024d6173974..b4e797b0898 100644 --- a/api_docs/v2/LogsMetricResponseFilter.md +++ b/api_docs/v2/LogsMetricResponseFilter.md @@ -3,6 +3,7 @@ # LogsMetricResponseFilter The log-based metric filter. Logs matching this filter will be aggregated in this metric. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricResponseGroupBy.md b/api_docs/v2/LogsMetricResponseGroupBy.md index 78ec6afede1..35e7512b450 100644 --- a/api_docs/v2/LogsMetricResponseGroupBy.md +++ b/api_docs/v2/LogsMetricResponseGroupBy.md @@ -3,6 +3,7 @@ # LogsMetricResponseGroupBy A group by rule. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricUpdateAttributes.md b/api_docs/v2/LogsMetricUpdateAttributes.md index f16f5576490..7e756cfe92f 100644 --- a/api_docs/v2/LogsMetricUpdateAttributes.md +++ b/api_docs/v2/LogsMetricUpdateAttributes.md @@ -3,6 +3,7 @@ # LogsMetricUpdateAttributes The log-based metric properties that will be updated. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricUpdateData.md b/api_docs/v2/LogsMetricUpdateData.md index e6470d0c878..d8961d73409 100644 --- a/api_docs/v2/LogsMetricUpdateData.md +++ b/api_docs/v2/LogsMetricUpdateData.md @@ -3,6 +3,7 @@ # LogsMetricUpdateData The new log-based metric properties. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricUpdateRequest.md b/api_docs/v2/LogsMetricUpdateRequest.md index 88197b54c0e..6e3731167c6 100644 --- a/api_docs/v2/LogsMetricUpdateRequest.md +++ b/api_docs/v2/LogsMetricUpdateRequest.md @@ -3,6 +3,7 @@ # LogsMetricUpdateRequest The new log-based metric body. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricsResponse.md b/api_docs/v2/LogsMetricsResponse.md index 85b0fc6ff99..316926cabe1 100644 --- a/api_docs/v2/LogsMetricsResponse.md +++ b/api_docs/v2/LogsMetricsResponse.md @@ -3,6 +3,7 @@ # LogsMetricsResponse All the available log-based metric objects. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsQueryFilter.md b/api_docs/v2/LogsQueryFilter.md index 79f342de444..1b25d7397e2 100644 --- a/api_docs/v2/LogsQueryFilter.md +++ b/api_docs/v2/LogsQueryFilter.md @@ -3,6 +3,7 @@ # LogsQueryFilter The search and filter query settings + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsQueryOptions.md b/api_docs/v2/LogsQueryOptions.md index 112e903ed33..0f85cae1ff2 100644 --- a/api_docs/v2/LogsQueryOptions.md +++ b/api_docs/v2/LogsQueryOptions.md @@ -3,6 +3,7 @@ # LogsQueryOptions Global query options that are used during the query. Note: You should only supply timezone or time offset but not both otherwise the query will fail. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsResponseMetadata.md b/api_docs/v2/LogsResponseMetadata.md index ca30e3e6e20..37b8e2ffdc1 100644 --- a/api_docs/v2/LogsResponseMetadata.md +++ b/api_docs/v2/LogsResponseMetadata.md @@ -3,6 +3,7 @@ # LogsResponseMetadata The metadata associated with a request + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsResponseMetadataPage.md b/api_docs/v2/LogsResponseMetadataPage.md index 1758099fdb9..ee5cbfe9bb3 100644 --- a/api_docs/v2/LogsResponseMetadataPage.md +++ b/api_docs/v2/LogsResponseMetadataPage.md @@ -3,6 +3,7 @@ # LogsResponseMetadataPage Paging attributes. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsWarning.md b/api_docs/v2/LogsWarning.md index dbd9fdf503b..1c4c965a18a 100644 --- a/api_docs/v2/LogsWarning.md +++ b/api_docs/v2/LogsWarning.md @@ -3,6 +3,7 @@ # LogsWarning A warning message indicating something that went wrong with the query + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/Metric.md b/api_docs/v2/Metric.md index ed27801821e..31098c445bf 100644 --- a/api_docs/v2/Metric.md +++ b/api_docs/v2/Metric.md @@ -3,6 +3,7 @@ # Metric Object for a single metric tag configuration. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricAllTags.md b/api_docs/v2/MetricAllTags.md index 8f127b51327..f0d1ea130dc 100644 --- a/api_docs/v2/MetricAllTags.md +++ b/api_docs/v2/MetricAllTags.md @@ -3,6 +3,7 @@ # MetricAllTags Object for a single metric's indexed tags. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricAllTagsAttributes.md b/api_docs/v2/MetricAllTagsAttributes.md index 44e8e8d5cd1..4d0e76954f0 100644 --- a/api_docs/v2/MetricAllTagsAttributes.md +++ b/api_docs/v2/MetricAllTagsAttributes.md @@ -3,6 +3,7 @@ # MetricAllTagsAttributes Object containing the definition of a metric's tags. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricAllTagsResponse.md b/api_docs/v2/MetricAllTagsResponse.md index 9adaa810c7a..7457f2f0b03 100644 --- a/api_docs/v2/MetricAllTagsResponse.md +++ b/api_docs/v2/MetricAllTagsResponse.md @@ -3,6 +3,7 @@ # MetricAllTagsResponse Response object that includes a single metric's indexed tags. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricDistinctVolume.md b/api_docs/v2/MetricDistinctVolume.md index f2b0fa94125..051dae55533 100644 --- a/api_docs/v2/MetricDistinctVolume.md +++ b/api_docs/v2/MetricDistinctVolume.md @@ -3,6 +3,7 @@ # MetricDistinctVolume Object for a single metric's distinct volume. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricDistinctVolumeAttributes.md b/api_docs/v2/MetricDistinctVolumeAttributes.md index 3c3efb82ac7..f80d335047c 100644 --- a/api_docs/v2/MetricDistinctVolumeAttributes.md +++ b/api_docs/v2/MetricDistinctVolumeAttributes.md @@ -3,6 +3,7 @@ # MetricDistinctVolumeAttributes Object containing the definition of a metric's distinct volume. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricIngestedIndexedVolume.md b/api_docs/v2/MetricIngestedIndexedVolume.md index 4dacad785d8..2cf4d0d04d4 100644 --- a/api_docs/v2/MetricIngestedIndexedVolume.md +++ b/api_docs/v2/MetricIngestedIndexedVolume.md @@ -3,6 +3,7 @@ # MetricIngestedIndexedVolume Object for a single metric's ingested and indexed volume. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricIngestedIndexedVolumeAttributes.md b/api_docs/v2/MetricIngestedIndexedVolumeAttributes.md index b63d2066372..1249aa79d80 100644 --- a/api_docs/v2/MetricIngestedIndexedVolumeAttributes.md +++ b/api_docs/v2/MetricIngestedIndexedVolumeAttributes.md @@ -3,6 +3,7 @@ # MetricIngestedIndexedVolumeAttributes Object containing the definition of a metric's ingested and indexed volume. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricTagConfiguration.md b/api_docs/v2/MetricTagConfiguration.md index 057f219feb2..240806883fe 100644 --- a/api_docs/v2/MetricTagConfiguration.md +++ b/api_docs/v2/MetricTagConfiguration.md @@ -3,6 +3,7 @@ # MetricTagConfiguration Object for a single metric tag configuration. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricTagConfigurationAttributes.md b/api_docs/v2/MetricTagConfigurationAttributes.md index 0e3fc361de7..64a27c00d7f 100644 --- a/api_docs/v2/MetricTagConfigurationAttributes.md +++ b/api_docs/v2/MetricTagConfigurationAttributes.md @@ -3,6 +3,7 @@ # MetricTagConfigurationAttributes Object containing the definition of a metric tag configuration attributes. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricTagConfigurationCreateAttributes.md b/api_docs/v2/MetricTagConfigurationCreateAttributes.md index 2db6e808e0f..2b973184ea0 100644 --- a/api_docs/v2/MetricTagConfigurationCreateAttributes.md +++ b/api_docs/v2/MetricTagConfigurationCreateAttributes.md @@ -3,6 +3,7 @@ # MetricTagConfigurationCreateAttributes Object containing the definition of a metric tag configuration to be created. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricTagConfigurationCreateData.md b/api_docs/v2/MetricTagConfigurationCreateData.md index 6fe88887bcc..5bd55eff3fc 100644 --- a/api_docs/v2/MetricTagConfigurationCreateData.md +++ b/api_docs/v2/MetricTagConfigurationCreateData.md @@ -3,6 +3,7 @@ # MetricTagConfigurationCreateData Object for a single metric to be configure tags on. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricTagConfigurationCreateRequest.md b/api_docs/v2/MetricTagConfigurationCreateRequest.md index a887ce99307..3428cf99d79 100644 --- a/api_docs/v2/MetricTagConfigurationCreateRequest.md +++ b/api_docs/v2/MetricTagConfigurationCreateRequest.md @@ -3,6 +3,7 @@ # MetricTagConfigurationCreateRequest Request object that includes the metric that you would like to configure tags for. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricTagConfigurationResponse.md b/api_docs/v2/MetricTagConfigurationResponse.md index 1838910b861..3487918ffaa 100644 --- a/api_docs/v2/MetricTagConfigurationResponse.md +++ b/api_docs/v2/MetricTagConfigurationResponse.md @@ -3,6 +3,7 @@ # MetricTagConfigurationResponse Response object which includes a single metric's tag configuration. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricTagConfigurationUpdateAttributes.md b/api_docs/v2/MetricTagConfigurationUpdateAttributes.md index 9dd3c0d781b..2481e6cb5c7 100644 --- a/api_docs/v2/MetricTagConfigurationUpdateAttributes.md +++ b/api_docs/v2/MetricTagConfigurationUpdateAttributes.md @@ -3,6 +3,7 @@ # MetricTagConfigurationUpdateAttributes Object containing the definition of a metric tag configuration to be updated. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricTagConfigurationUpdateData.md b/api_docs/v2/MetricTagConfigurationUpdateData.md index db9bfb353e2..e84514e89ec 100644 --- a/api_docs/v2/MetricTagConfigurationUpdateData.md +++ b/api_docs/v2/MetricTagConfigurationUpdateData.md @@ -3,6 +3,7 @@ # MetricTagConfigurationUpdateData Object for a single tag configuration to be edited. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricTagConfigurationUpdateRequest.md b/api_docs/v2/MetricTagConfigurationUpdateRequest.md index 70299faa487..bb6aa90a709 100644 --- a/api_docs/v2/MetricTagConfigurationUpdateRequest.md +++ b/api_docs/v2/MetricTagConfigurationUpdateRequest.md @@ -3,6 +3,7 @@ # MetricTagConfigurationUpdateRequest Request object that includes the metric that you would like to edit the tag configuration on. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricVolumesResponse.md b/api_docs/v2/MetricVolumesResponse.md index 4381fda3512..ab8ef6d1c65 100644 --- a/api_docs/v2/MetricVolumesResponse.md +++ b/api_docs/v2/MetricVolumesResponse.md @@ -3,6 +3,7 @@ # MetricVolumesResponse Response object which includes a single metric's volume. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricsAndMetricTagConfigurationsResponse.md b/api_docs/v2/MetricsAndMetricTagConfigurationsResponse.md index a5bafdf8fd9..108364fa9b4 100644 --- a/api_docs/v2/MetricsAndMetricTagConfigurationsResponse.md +++ b/api_docs/v2/MetricsAndMetricTagConfigurationsResponse.md @@ -3,6 +3,7 @@ # MetricsAndMetricTagConfigurationsResponse Response object that includes metrics and metric tag configurations. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/Organization.md b/api_docs/v2/Organization.md index 1fc96cba632..9cef57893d3 100644 --- a/api_docs/v2/Organization.md +++ b/api_docs/v2/Organization.md @@ -3,6 +3,7 @@ # Organization Organization object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/OrganizationAttributes.md b/api_docs/v2/OrganizationAttributes.md index 870d633c983..859602142ce 100644 --- a/api_docs/v2/OrganizationAttributes.md +++ b/api_docs/v2/OrganizationAttributes.md @@ -3,6 +3,7 @@ # OrganizationAttributes Attributes of the organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/Pagination.md b/api_docs/v2/Pagination.md index ca940b448b7..ba03b9dc3b0 100644 --- a/api_docs/v2/Pagination.md +++ b/api_docs/v2/Pagination.md @@ -3,6 +3,7 @@ # Pagination Pagination object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/PartialAPIKey.md b/api_docs/v2/PartialAPIKey.md index 24fc25f9607..50be9dc0f64 100644 --- a/api_docs/v2/PartialAPIKey.md +++ b/api_docs/v2/PartialAPIKey.md @@ -3,6 +3,7 @@ # PartialAPIKey Partial Datadog API key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/PartialAPIKeyAttributes.md b/api_docs/v2/PartialAPIKeyAttributes.md index 5382ec41e3d..b762f30a35f 100644 --- a/api_docs/v2/PartialAPIKeyAttributes.md +++ b/api_docs/v2/PartialAPIKeyAttributes.md @@ -3,6 +3,7 @@ # PartialAPIKeyAttributes Attributes of a partial API key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/PartialApplicationKey.md b/api_docs/v2/PartialApplicationKey.md index 0bf0f415f70..d499638a840 100644 --- a/api_docs/v2/PartialApplicationKey.md +++ b/api_docs/v2/PartialApplicationKey.md @@ -3,6 +3,7 @@ # PartialApplicationKey Partial Datadog application key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/PartialApplicationKeyAttributes.md b/api_docs/v2/PartialApplicationKeyAttributes.md index 405af931c33..9e994caed17 100644 --- a/api_docs/v2/PartialApplicationKeyAttributes.md +++ b/api_docs/v2/PartialApplicationKeyAttributes.md @@ -3,6 +3,7 @@ # PartialApplicationKeyAttributes Attributes of a partial application key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/Permission.md b/api_docs/v2/Permission.md index d10c08be4e8..c94bfba237a 100644 --- a/api_docs/v2/Permission.md +++ b/api_docs/v2/Permission.md @@ -3,6 +3,7 @@ # Permission Permission object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/PermissionAttributes.md b/api_docs/v2/PermissionAttributes.md index 572dc023cc7..b21e8ede063 100644 --- a/api_docs/v2/PermissionAttributes.md +++ b/api_docs/v2/PermissionAttributes.md @@ -3,6 +3,7 @@ # PermissionAttributes Attributes of a permission. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/PermissionsResponse.md b/api_docs/v2/PermissionsResponse.md index d58bb3f34ba..5d1d9a33544 100644 --- a/api_docs/v2/PermissionsResponse.md +++ b/api_docs/v2/PermissionsResponse.md @@ -3,6 +3,7 @@ # PermissionsResponse Payload with API-returned permissions. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ProcessSummariesMeta.md b/api_docs/v2/ProcessSummariesMeta.md index a3131766f91..e23e684412f 100644 --- a/api_docs/v2/ProcessSummariesMeta.md +++ b/api_docs/v2/ProcessSummariesMeta.md @@ -3,6 +3,7 @@ # ProcessSummariesMeta Response metadata object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ProcessSummariesMetaPage.md b/api_docs/v2/ProcessSummariesMetaPage.md index 7a87a017c0b..38b838d27c1 100644 --- a/api_docs/v2/ProcessSummariesMetaPage.md +++ b/api_docs/v2/ProcessSummariesMetaPage.md @@ -3,6 +3,7 @@ # ProcessSummariesMetaPage Paging attributes. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ProcessSummariesResponse.md b/api_docs/v2/ProcessSummariesResponse.md index f8942638ecf..66ae986b943 100644 --- a/api_docs/v2/ProcessSummariesResponse.md +++ b/api_docs/v2/ProcessSummariesResponse.md @@ -3,6 +3,7 @@ # ProcessSummariesResponse List of process summaries. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ProcessSummary.md b/api_docs/v2/ProcessSummary.md index fff8669b2d2..fbd6f7a2388 100644 --- a/api_docs/v2/ProcessSummary.md +++ b/api_docs/v2/ProcessSummary.md @@ -3,6 +3,7 @@ # ProcessSummary Process summary object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ProcessSummaryAttributes.md b/api_docs/v2/ProcessSummaryAttributes.md index ec15facca51..db62924de35 100644 --- a/api_docs/v2/ProcessSummaryAttributes.md +++ b/api_docs/v2/ProcessSummaryAttributes.md @@ -3,6 +3,7 @@ # ProcessSummaryAttributes Attributes for a process summary. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToIncidentIntegrationMetadataData.md b/api_docs/v2/RelationshipToIncidentIntegrationMetadataData.md index dd029cf67f5..1df2d9c8502 100644 --- a/api_docs/v2/RelationshipToIncidentIntegrationMetadataData.md +++ b/api_docs/v2/RelationshipToIncidentIntegrationMetadataData.md @@ -3,6 +3,7 @@ # RelationshipToIncidentIntegrationMetadataData A relationship reference for an integration metadata object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToIncidentIntegrationMetadatas.md b/api_docs/v2/RelationshipToIncidentIntegrationMetadatas.md index fc4a541c8cf..1f22776ed04 100644 --- a/api_docs/v2/RelationshipToIncidentIntegrationMetadatas.md +++ b/api_docs/v2/RelationshipToIncidentIntegrationMetadatas.md @@ -3,6 +3,7 @@ # RelationshipToIncidentIntegrationMetadatas A relationship reference for multiple integration metadata objects. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToIncidentPostmortem.md b/api_docs/v2/RelationshipToIncidentPostmortem.md index 26d24815858..f1379b660c6 100644 --- a/api_docs/v2/RelationshipToIncidentPostmortem.md +++ b/api_docs/v2/RelationshipToIncidentPostmortem.md @@ -3,6 +3,7 @@ # RelationshipToIncidentPostmortem A relationship reference for postmortems. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToIncidentPostmortemData.md b/api_docs/v2/RelationshipToIncidentPostmortemData.md index 16ce9b81321..e8030cf2aeb 100644 --- a/api_docs/v2/RelationshipToIncidentPostmortemData.md +++ b/api_docs/v2/RelationshipToIncidentPostmortemData.md @@ -3,6 +3,7 @@ # RelationshipToIncidentPostmortemData The postmortem relationship data. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToOrganization.md b/api_docs/v2/RelationshipToOrganization.md index f9ed5a3f288..d90be206e8d 100644 --- a/api_docs/v2/RelationshipToOrganization.md +++ b/api_docs/v2/RelationshipToOrganization.md @@ -3,6 +3,7 @@ # RelationshipToOrganization Relationship to an organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToOrganizationData.md b/api_docs/v2/RelationshipToOrganizationData.md index 2730c92ac25..9ae1fd92b49 100644 --- a/api_docs/v2/RelationshipToOrganizationData.md +++ b/api_docs/v2/RelationshipToOrganizationData.md @@ -3,6 +3,7 @@ # RelationshipToOrganizationData Relationship to organization object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToOrganizations.md b/api_docs/v2/RelationshipToOrganizations.md index fb1a445a862..f6927f5b395 100644 --- a/api_docs/v2/RelationshipToOrganizations.md +++ b/api_docs/v2/RelationshipToOrganizations.md @@ -3,6 +3,7 @@ # RelationshipToOrganizations Relationship to organizations. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToPermission.md b/api_docs/v2/RelationshipToPermission.md index 5e55ecb51e5..71f73299929 100644 --- a/api_docs/v2/RelationshipToPermission.md +++ b/api_docs/v2/RelationshipToPermission.md @@ -3,6 +3,7 @@ # RelationshipToPermission Relationship to a permissions object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToPermissionData.md b/api_docs/v2/RelationshipToPermissionData.md index 0d7ed527c85..8d74a2941dc 100644 --- a/api_docs/v2/RelationshipToPermissionData.md +++ b/api_docs/v2/RelationshipToPermissionData.md @@ -3,6 +3,7 @@ # RelationshipToPermissionData Relationship to permission object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToPermissions.md b/api_docs/v2/RelationshipToPermissions.md index af3227c528c..aac924bdbb4 100644 --- a/api_docs/v2/RelationshipToPermissions.md +++ b/api_docs/v2/RelationshipToPermissions.md @@ -3,6 +3,7 @@ # RelationshipToPermissions Relationship to multiple permissions objects. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToRole.md b/api_docs/v2/RelationshipToRole.md index 79e8e300ab3..bf49e6e61ca 100644 --- a/api_docs/v2/RelationshipToRole.md +++ b/api_docs/v2/RelationshipToRole.md @@ -3,6 +3,7 @@ # RelationshipToRole Relationship to role. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToRoleData.md b/api_docs/v2/RelationshipToRoleData.md index 7c382a9ae5b..55ddc839008 100644 --- a/api_docs/v2/RelationshipToRoleData.md +++ b/api_docs/v2/RelationshipToRoleData.md @@ -3,6 +3,7 @@ # RelationshipToRoleData Relationship to role object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToRoles.md b/api_docs/v2/RelationshipToRoles.md index 9146ec4ba19..d9dec333a66 100644 --- a/api_docs/v2/RelationshipToRoles.md +++ b/api_docs/v2/RelationshipToRoles.md @@ -3,6 +3,7 @@ # RelationshipToRoles Relationship to roles. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToUser.md b/api_docs/v2/RelationshipToUser.md index ec114fb08b3..db2d5ade8db 100644 --- a/api_docs/v2/RelationshipToUser.md +++ b/api_docs/v2/RelationshipToUser.md @@ -3,6 +3,7 @@ # RelationshipToUser Relationship to user. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToUserData.md b/api_docs/v2/RelationshipToUserData.md index 6618a89e2e0..5c428058b45 100644 --- a/api_docs/v2/RelationshipToUserData.md +++ b/api_docs/v2/RelationshipToUserData.md @@ -3,6 +3,7 @@ # RelationshipToUserData Relationship to user object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToUsers.md b/api_docs/v2/RelationshipToUsers.md index fa2f88f77e3..67cf1d5fa3e 100644 --- a/api_docs/v2/RelationshipToUsers.md +++ b/api_docs/v2/RelationshipToUsers.md @@ -3,6 +3,7 @@ # RelationshipToUsers Relationship to users. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ResponseMetaAttributes.md b/api_docs/v2/ResponseMetaAttributes.md index 7ad4361c8ab..bac13c8e6e9 100644 --- a/api_docs/v2/ResponseMetaAttributes.md +++ b/api_docs/v2/ResponseMetaAttributes.md @@ -3,6 +3,7 @@ # ResponseMetaAttributes Object describing meta attributes of response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/Role.md b/api_docs/v2/Role.md index 0f24186a6ba..bc0ccc31f66 100644 --- a/api_docs/v2/Role.md +++ b/api_docs/v2/Role.md @@ -3,6 +3,7 @@ # Role Role object returned by the API. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleAttributes.md b/api_docs/v2/RoleAttributes.md index deddeaa719b..f9faaec1369 100644 --- a/api_docs/v2/RoleAttributes.md +++ b/api_docs/v2/RoleAttributes.md @@ -3,6 +3,7 @@ # RoleAttributes Attributes of the role. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleCreateAttributes.md b/api_docs/v2/RoleCreateAttributes.md index 5c37888c92d..80d42bdc71c 100644 --- a/api_docs/v2/RoleCreateAttributes.md +++ b/api_docs/v2/RoleCreateAttributes.md @@ -3,6 +3,7 @@ # RoleCreateAttributes Attributes of the created role. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleCreateData.md b/api_docs/v2/RoleCreateData.md index 4f25801a0b0..ee734849cb8 100644 --- a/api_docs/v2/RoleCreateData.md +++ b/api_docs/v2/RoleCreateData.md @@ -3,6 +3,7 @@ # RoleCreateData Data related to the creation of a role. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleCreateRequest.md b/api_docs/v2/RoleCreateRequest.md index e60214000f7..0d0769438d8 100644 --- a/api_docs/v2/RoleCreateRequest.md +++ b/api_docs/v2/RoleCreateRequest.md @@ -3,6 +3,7 @@ # RoleCreateRequest Create a role. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleCreateResponse.md b/api_docs/v2/RoleCreateResponse.md index f9344f53fea..2984e0f881a 100644 --- a/api_docs/v2/RoleCreateResponse.md +++ b/api_docs/v2/RoleCreateResponse.md @@ -3,6 +3,7 @@ # RoleCreateResponse Response containing information about a created role. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleCreateResponseData.md b/api_docs/v2/RoleCreateResponseData.md index 0279ea95c30..eca70aeb787 100644 --- a/api_docs/v2/RoleCreateResponseData.md +++ b/api_docs/v2/RoleCreateResponseData.md @@ -3,6 +3,7 @@ # RoleCreateResponseData Role object returned by the API. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleRelationships.md b/api_docs/v2/RoleRelationships.md index e17077e93eb..46ea3af6fd9 100644 --- a/api_docs/v2/RoleRelationships.md +++ b/api_docs/v2/RoleRelationships.md @@ -3,6 +3,7 @@ # RoleRelationships Relationships of the role object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleResponse.md b/api_docs/v2/RoleResponse.md index 7fdfe3c646d..1ea6def5206 100644 --- a/api_docs/v2/RoleResponse.md +++ b/api_docs/v2/RoleResponse.md @@ -3,6 +3,7 @@ # RoleResponse Response containing information about a single role. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleResponseRelationships.md b/api_docs/v2/RoleResponseRelationships.md index 6a8db9a0879..796713b30ac 100644 --- a/api_docs/v2/RoleResponseRelationships.md +++ b/api_docs/v2/RoleResponseRelationships.md @@ -3,6 +3,7 @@ # RoleResponseRelationships Relationships of the role object returned by the API. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleUpdateAttributes.md b/api_docs/v2/RoleUpdateAttributes.md index 651c2f4ce72..65617404c21 100644 --- a/api_docs/v2/RoleUpdateAttributes.md +++ b/api_docs/v2/RoleUpdateAttributes.md @@ -3,6 +3,7 @@ # RoleUpdateAttributes Attributes of the role. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleUpdateData.md b/api_docs/v2/RoleUpdateData.md index 342044ed6cc..caac4fd2820 100644 --- a/api_docs/v2/RoleUpdateData.md +++ b/api_docs/v2/RoleUpdateData.md @@ -3,6 +3,7 @@ # RoleUpdateData Data related to the update of a role. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleUpdateRequest.md b/api_docs/v2/RoleUpdateRequest.md index 70838a29819..9194626393e 100644 --- a/api_docs/v2/RoleUpdateRequest.md +++ b/api_docs/v2/RoleUpdateRequest.md @@ -3,6 +3,7 @@ # RoleUpdateRequest Update a role. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleUpdateResponse.md b/api_docs/v2/RoleUpdateResponse.md index b9597231806..938dd09b835 100644 --- a/api_docs/v2/RoleUpdateResponse.md +++ b/api_docs/v2/RoleUpdateResponse.md @@ -3,6 +3,7 @@ # RoleUpdateResponse Response containing information about an updated role. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleUpdateResponseData.md b/api_docs/v2/RoleUpdateResponseData.md index a1bb5c6a820..af4033ce1dd 100644 --- a/api_docs/v2/RoleUpdateResponseData.md +++ b/api_docs/v2/RoleUpdateResponseData.md @@ -3,6 +3,7 @@ # RoleUpdateResponseData Role object returned by the API. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RolesResponse.md b/api_docs/v2/RolesResponse.md index e5933025db3..6c95178c6c4 100644 --- a/api_docs/v2/RolesResponse.md +++ b/api_docs/v2/RolesResponse.md @@ -3,6 +3,7 @@ # RolesResponse Response containing information about multiple roles. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringFilter.md b/api_docs/v2/SecurityMonitoringFilter.md index fc156800f45..6aa9be8de28 100644 --- a/api_docs/v2/SecurityMonitoringFilter.md +++ b/api_docs/v2/SecurityMonitoringFilter.md @@ -3,6 +3,7 @@ # SecurityMonitoringFilter The rule's suppression filter. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringListRulesResponse.md b/api_docs/v2/SecurityMonitoringListRulesResponse.md index a95ef16516d..439a9a07104 100644 --- a/api_docs/v2/SecurityMonitoringListRulesResponse.md +++ b/api_docs/v2/SecurityMonitoringListRulesResponse.md @@ -3,6 +3,7 @@ # SecurityMonitoringListRulesResponse List of rules. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringRuleCase.md b/api_docs/v2/SecurityMonitoringRuleCase.md index 8ed8eb130af..1fa1d0838d3 100644 --- a/api_docs/v2/SecurityMonitoringRuleCase.md +++ b/api_docs/v2/SecurityMonitoringRuleCase.md @@ -3,6 +3,7 @@ # SecurityMonitoringRuleCase Case when signal is generated. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringRuleCaseCreate.md b/api_docs/v2/SecurityMonitoringRuleCaseCreate.md index 5caa2bc3dc2..8d84dd98dc2 100644 --- a/api_docs/v2/SecurityMonitoringRuleCaseCreate.md +++ b/api_docs/v2/SecurityMonitoringRuleCaseCreate.md @@ -3,6 +3,7 @@ # SecurityMonitoringRuleCaseCreate Case when signal is generated. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringRuleCreatePayload.md b/api_docs/v2/SecurityMonitoringRuleCreatePayload.md index e2ec1c54027..3c720f67ce1 100644 --- a/api_docs/v2/SecurityMonitoringRuleCreatePayload.md +++ b/api_docs/v2/SecurityMonitoringRuleCreatePayload.md @@ -3,6 +3,7 @@ # SecurityMonitoringRuleCreatePayload Create a new rule. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringRuleNewValueOptions.md b/api_docs/v2/SecurityMonitoringRuleNewValueOptions.md index 883bbc595ab..9e3215f36d8 100644 --- a/api_docs/v2/SecurityMonitoringRuleNewValueOptions.md +++ b/api_docs/v2/SecurityMonitoringRuleNewValueOptions.md @@ -3,6 +3,7 @@ # SecurityMonitoringRuleNewValueOptions Options on new value rules. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringRuleOptions.md b/api_docs/v2/SecurityMonitoringRuleOptions.md index b225bcc2491..9b262ed1d37 100644 --- a/api_docs/v2/SecurityMonitoringRuleOptions.md +++ b/api_docs/v2/SecurityMonitoringRuleOptions.md @@ -3,6 +3,7 @@ # SecurityMonitoringRuleOptions Options on rules. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringRuleQuery.md b/api_docs/v2/SecurityMonitoringRuleQuery.md index 8533f1559ca..949a173c96f 100644 --- a/api_docs/v2/SecurityMonitoringRuleQuery.md +++ b/api_docs/v2/SecurityMonitoringRuleQuery.md @@ -3,6 +3,7 @@ # SecurityMonitoringRuleQuery Query for matching rule. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringRuleQueryCreate.md b/api_docs/v2/SecurityMonitoringRuleQueryCreate.md index cf15beb41cc..9be512fd2a1 100644 --- a/api_docs/v2/SecurityMonitoringRuleQueryCreate.md +++ b/api_docs/v2/SecurityMonitoringRuleQueryCreate.md @@ -3,6 +3,7 @@ # SecurityMonitoringRuleQueryCreate Query for matching rule. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringRuleResponse.md b/api_docs/v2/SecurityMonitoringRuleResponse.md index 36e40cde886..e9a58923f8c 100644 --- a/api_docs/v2/SecurityMonitoringRuleResponse.md +++ b/api_docs/v2/SecurityMonitoringRuleResponse.md @@ -3,6 +3,7 @@ # SecurityMonitoringRuleResponse Detection rule. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringRuleUpdatePayload.md b/api_docs/v2/SecurityMonitoringRuleUpdatePayload.md index d2c79d9e844..b407261b3b3 100644 --- a/api_docs/v2/SecurityMonitoringRuleUpdatePayload.md +++ b/api_docs/v2/SecurityMonitoringRuleUpdatePayload.md @@ -3,6 +3,7 @@ # SecurityMonitoringRuleUpdatePayload Update an existing rule. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringSignal.md b/api_docs/v2/SecurityMonitoringSignal.md index d04f770938a..e47c68846b0 100644 --- a/api_docs/v2/SecurityMonitoringSignal.md +++ b/api_docs/v2/SecurityMonitoringSignal.md @@ -3,6 +3,7 @@ # SecurityMonitoringSignal Object description of a security signal. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringSignalAttributes.md b/api_docs/v2/SecurityMonitoringSignalAttributes.md index b64a711ebd4..497b3b1a8e7 100644 --- a/api_docs/v2/SecurityMonitoringSignalAttributes.md +++ b/api_docs/v2/SecurityMonitoringSignalAttributes.md @@ -3,6 +3,7 @@ # SecurityMonitoringSignalAttributes The object containing all signal attributes and their associated values. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringSignalListRequest.md b/api_docs/v2/SecurityMonitoringSignalListRequest.md index 786e75f7c23..3b0a9478502 100644 --- a/api_docs/v2/SecurityMonitoringSignalListRequest.md +++ b/api_docs/v2/SecurityMonitoringSignalListRequest.md @@ -3,6 +3,7 @@ # SecurityMonitoringSignalListRequest The request for a security signal list. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringSignalListRequestFilter.md b/api_docs/v2/SecurityMonitoringSignalListRequestFilter.md index ad234a685a9..f3b3ed9ce8f 100644 --- a/api_docs/v2/SecurityMonitoringSignalListRequestFilter.md +++ b/api_docs/v2/SecurityMonitoringSignalListRequestFilter.md @@ -3,6 +3,7 @@ # SecurityMonitoringSignalListRequestFilter Search filters for listing security signals. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringSignalListRequestPage.md b/api_docs/v2/SecurityMonitoringSignalListRequestPage.md index 54d22964e7f..817a4bb5e80 100644 --- a/api_docs/v2/SecurityMonitoringSignalListRequestPage.md +++ b/api_docs/v2/SecurityMonitoringSignalListRequestPage.md @@ -3,6 +3,7 @@ # SecurityMonitoringSignalListRequestPage The paging attributes for listing security signals. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringSignalsListResponse.md b/api_docs/v2/SecurityMonitoringSignalsListResponse.md index 76589633dff..995d6050df0 100644 --- a/api_docs/v2/SecurityMonitoringSignalsListResponse.md +++ b/api_docs/v2/SecurityMonitoringSignalsListResponse.md @@ -3,6 +3,7 @@ # SecurityMonitoringSignalsListResponse The response object with all security signals matching the request and pagination information. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringSignalsListResponseLinks.md b/api_docs/v2/SecurityMonitoringSignalsListResponseLinks.md index a40d7719f0c..4939bf387bd 100644 --- a/api_docs/v2/SecurityMonitoringSignalsListResponseLinks.md +++ b/api_docs/v2/SecurityMonitoringSignalsListResponseLinks.md @@ -3,6 +3,7 @@ # SecurityMonitoringSignalsListResponseLinks Links attributes. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringSignalsListResponseMeta.md b/api_docs/v2/SecurityMonitoringSignalsListResponseMeta.md index fecb387538d..61184350518 100644 --- a/api_docs/v2/SecurityMonitoringSignalsListResponseMeta.md +++ b/api_docs/v2/SecurityMonitoringSignalsListResponseMeta.md @@ -3,6 +3,7 @@ # SecurityMonitoringSignalsListResponseMeta Meta attributes. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringSignalsListResponseMetaPage.md b/api_docs/v2/SecurityMonitoringSignalsListResponseMetaPage.md index 0062c375bf0..c3b9964247e 100644 --- a/api_docs/v2/SecurityMonitoringSignalsListResponseMetaPage.md +++ b/api_docs/v2/SecurityMonitoringSignalsListResponseMetaPage.md @@ -3,6 +3,7 @@ # SecurityMonitoringSignalsListResponseMetaPage Paging attributes. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/User.md b/api_docs/v2/User.md index 37f6eab4a91..eb8af98df9f 100644 --- a/api_docs/v2/User.md +++ b/api_docs/v2/User.md @@ -3,6 +3,7 @@ # User User object returned by the API. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserAttributes.md b/api_docs/v2/UserAttributes.md index eb8d7702e8f..f8e78ef11c0 100644 --- a/api_docs/v2/UserAttributes.md +++ b/api_docs/v2/UserAttributes.md @@ -3,6 +3,7 @@ # UserAttributes Attributes of user object returned by the API. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserCreateAttributes.md b/api_docs/v2/UserCreateAttributes.md index 106c901c825..2781a6a121b 100644 --- a/api_docs/v2/UserCreateAttributes.md +++ b/api_docs/v2/UserCreateAttributes.md @@ -3,6 +3,7 @@ # UserCreateAttributes Attributes of the created user. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserCreateData.md b/api_docs/v2/UserCreateData.md index e4ff1334bfe..0d937a0e2fd 100644 --- a/api_docs/v2/UserCreateData.md +++ b/api_docs/v2/UserCreateData.md @@ -3,6 +3,7 @@ # UserCreateData Object to create a user. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserCreateRequest.md b/api_docs/v2/UserCreateRequest.md index 3dfd7bb5e32..dd199d2cd5d 100644 --- a/api_docs/v2/UserCreateRequest.md +++ b/api_docs/v2/UserCreateRequest.md @@ -3,6 +3,7 @@ # UserCreateRequest Create a user. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserInvitationData.md b/api_docs/v2/UserInvitationData.md index efaf97b003a..35067e1ad75 100644 --- a/api_docs/v2/UserInvitationData.md +++ b/api_docs/v2/UserInvitationData.md @@ -3,6 +3,7 @@ # UserInvitationData Object to create a user invitation. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserInvitationDataAttributes.md b/api_docs/v2/UserInvitationDataAttributes.md index 1bda5c0e392..3d944d358d9 100644 --- a/api_docs/v2/UserInvitationDataAttributes.md +++ b/api_docs/v2/UserInvitationDataAttributes.md @@ -3,6 +3,7 @@ # UserInvitationDataAttributes Attributes of a user invitation. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserInvitationRelationships.md b/api_docs/v2/UserInvitationRelationships.md index 8c06f800bc1..a6b43939ace 100644 --- a/api_docs/v2/UserInvitationRelationships.md +++ b/api_docs/v2/UserInvitationRelationships.md @@ -3,6 +3,7 @@ # UserInvitationRelationships Relationships data for user invitation. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserInvitationResponse.md b/api_docs/v2/UserInvitationResponse.md index 64c50d64e5b..8aac3ee501d 100644 --- a/api_docs/v2/UserInvitationResponse.md +++ b/api_docs/v2/UserInvitationResponse.md @@ -3,6 +3,7 @@ # UserInvitationResponse User invitation as returned by the API. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserInvitationResponseData.md b/api_docs/v2/UserInvitationResponseData.md index 4db7c9b648c..5157f137e0c 100644 --- a/api_docs/v2/UserInvitationResponseData.md +++ b/api_docs/v2/UserInvitationResponseData.md @@ -3,6 +3,7 @@ # UserInvitationResponseData Object of a user invitation returned by the API. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserInvitationsRequest.md b/api_docs/v2/UserInvitationsRequest.md index 4cd84944d18..d9e43430ed4 100644 --- a/api_docs/v2/UserInvitationsRequest.md +++ b/api_docs/v2/UserInvitationsRequest.md @@ -3,6 +3,7 @@ # UserInvitationsRequest Object to invite users to join the organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserInvitationsResponse.md b/api_docs/v2/UserInvitationsResponse.md index d4d029be2e2..8ea7db862df 100644 --- a/api_docs/v2/UserInvitationsResponse.md +++ b/api_docs/v2/UserInvitationsResponse.md @@ -3,6 +3,7 @@ # UserInvitationsResponse User invitations as returned by the API. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserRelationships.md b/api_docs/v2/UserRelationships.md index f79f722fe94..4a8f9e91e8e 100644 --- a/api_docs/v2/UserRelationships.md +++ b/api_docs/v2/UserRelationships.md @@ -3,6 +3,7 @@ # UserRelationships Relationships of the user object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserResponse.md b/api_docs/v2/UserResponse.md index 88a7a9f518c..08b5cc7f1f0 100644 --- a/api_docs/v2/UserResponse.md +++ b/api_docs/v2/UserResponse.md @@ -3,6 +3,7 @@ # UserResponse Response containing information about a single user. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserResponseRelationships.md b/api_docs/v2/UserResponseRelationships.md index 0d787de51bb..ffff90e91b5 100644 --- a/api_docs/v2/UserResponseRelationships.md +++ b/api_docs/v2/UserResponseRelationships.md @@ -3,6 +3,7 @@ # UserResponseRelationships Relationships of the user object returned by the API. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserUpdateAttributes.md b/api_docs/v2/UserUpdateAttributes.md index 2882483ad84..db4b6b01d8f 100644 --- a/api_docs/v2/UserUpdateAttributes.md +++ b/api_docs/v2/UserUpdateAttributes.md @@ -3,6 +3,7 @@ # UserUpdateAttributes Attributes of the edited user. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserUpdateData.md b/api_docs/v2/UserUpdateData.md index 00d50e79ca5..5de8590b933 100644 --- a/api_docs/v2/UserUpdateData.md +++ b/api_docs/v2/UserUpdateData.md @@ -3,6 +3,7 @@ # UserUpdateData Object to update a user. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserUpdateRequest.md b/api_docs/v2/UserUpdateRequest.md index f1922159e42..9e29692c600 100644 --- a/api_docs/v2/UserUpdateRequest.md +++ b/api_docs/v2/UserUpdateRequest.md @@ -3,6 +3,7 @@ # UserUpdateRequest Update a user. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UsersResponse.md b/api_docs/v2/UsersResponse.md index 8d0d2f5142e..89a10f33d64 100644 --- a/api_docs/v2/UsersResponse.md +++ b/api_docs/v2/UsersResponse.md @@ -3,6 +3,7 @@ # UsersResponse Response containing information about multiple users. + ## Properties Name | Type | Description | Notes