Compare commits

..

22 Commits

Author SHA1 Message Date
William Cheng
560bf7e080 v5.1.1 release (#9421) 2021-05-07 09:57:19 +08:00
Luca Mazzanti
2f2e250ab2 [csharp-netcore][httpclient] Issues managing error statuses (#9389)
* [csharp-netcore] correct rawContent read

* [csharp-netcore] avoid deserialize result when in error

* [csharp-netcore] avoid aggregate exceptions

* Updated samples

* Updated samples

* Refactored PetApiTest

* Updated samples

* Fixed test issues

* reverted previous commit
2021-05-07 07:23:53 +08:00
Bruno Coelho
f4f4d5de0e [kotlin][client] fix warning for non optional header parameter (#9415) 2021-05-07 00:26:22 +08:00
William Cheng
7703c923f9 update doc 2021-05-06 12:14:45 +08:00
Samuel Kahn
343d7eb712 [cpp-ue4] Improved retry system to use Unreal's FHttpRetrySystem (#9382)
* Revert "[cpp-ue4] Added the possibility to retry requests easily with AsyncRetry method on the response and SetAutoRetryCount on the request"

* [cpp-ue4] Improved retry system to use Unreal's FHttpRetrySystem

* [cpp-ue4] Updated style guide link

* update samples

Co-authored-by: William Cheng <wing328hk@gmail.com>
2021-05-06 11:26:07 +08:00
matt beary
32b2ea3291 Fixes #9398: fix aspnet enum documentation (#9404) 2021-05-06 11:23:32 +08:00
matt beary
45d55f6b73 [aspnetcore] Fix incorrect logging messages (#9405)
* fix incorrect aspnetcore logging messages

* address comments from review

cleans up log messages
2021-05-06 10:46:06 +08:00
William Cheng
ec085713ce [Erlang] migrate CI to drone.io (#9406)
* test erlang client, server in drone.io

* rearrange tests, add server folder

* comment out erlang server tests
2021-05-06 10:42:46 +08:00
Julian G
8f5639554e [C++] [Pistache] Model validation, general overhaul (#9251)
* overhaul pistache templates

* fix function signature in model-source
return type now aligns with definition in model-header

* use default keyword for destructors

* generate pistache samples

* move bin/configs/other/cpp-pistache-server-cpp-pistache.yaml to bin/configs/cpp-pistache-server-cpp-pistache.yaml

* Only generate validation body if necessary

* generate pistache samples
2021-05-05 16:52:47 +08:00
shylacs
4d2b022619 Add VMware to users list (#9388)
* Add VMware to users list

LMK if I can provide the png for company logo. I tried uploading to img folder and could not.

* add logo, update readme

Co-authored-by: William Cheng <wing328hk@gmail.com>
2021-05-05 00:08:15 +08:00
Luca Mazzanti
e9fa936886 [csharp][netcore-httpclient] Refactor of constructors: removed obsolete attribute (#9373)
* Removed obsolete attribute on constructors without HttpClient prameter

* add clickable link in the tooltip

* update doc, add tests

Co-authored-by: William Cheng <wing328hk@gmail.com>
2021-05-04 23:58:20 +08:00
Stefan Wendt
d21743e9e5 [TypeScript-fetch] Fix issue 9360 (#9362)
* [TypeScript] Fix misplaced parentheses

* [TypeScript] Run PR relevant scripts

* [TypeScript] ensure up to date

* Revert "[TypeScript] ensure up to date"

This reverts commit 320ec45f

* Revert "[TypeScript] Run PR relevant scripts"

This reverts commit 23cda753

Co-authored-by: Stefan Wendt <stefan.wendt@isax.com>
2021-05-03 18:15:52 +02:00
Matthew
3da1999135 Fix typo in readme (#9387) 2021-05-03 22:45:55 +08:00
johnthagen
a88313c40c [Python] Avoid DeprecationWarning in inspect.getargspec on Python 3 (#9271)
* Avoid DeprecationWarning in inspect.getargspec on Python 3

* Regenerate samples
2021-04-30 11:59:33 -07:00
ex0ns
ebc1d7bd95 [scala][akka] Update dependencies for scala 2.13 in scala-akka (#8624)
* [scala][akka] Update dependencies for scala 2.13

* Update pom.mustache to support multiple scala's version

* Update pom.xml

* Scala cross build 2.12 and 2.13

* Update version. Migrate to sbt

* Remove space

* Add pom.xml back
2021-04-29 18:51:30 +08:00
Anders Aaen Springborg
dbb42f9027 [BUG] new.sh fix generator type , issue #9320 (#9321)
* generation type on  template dir path

* remove gen_type from template and resources
2021-04-29 18:23:13 +08:00
William Cheng
18cdb36d3e [Test] Migrate samples from 2.0 Spec to 3.0 spec (#9347)
* nim petstore to use 3.0 spec

* ktorm to use 3.0 spec

* update c petstore to use 3.0 spec

* Revert "update c petstore to use 3.0 spec"

This reverts commit a8ff0517ba.
2021-04-29 10:23:55 +08:00
William Cheng
5d946289ef Bump OkHTTP dependency to latest in build.sbt (#9361) 2021-04-28 22:36:29 +08:00
Ayman Bagabas
057c1080f8 [Codegen] Add hasDefaultResponse property (#9203)
Check if there's a default response in the specs.
2021-04-28 17:03:22 +08:00
Toby Murray
83adc064a4 Fixes #9151: Bump OkHTTP dependency to latest (#9353)
In 5.0.1 the generated line in `ApiClient` was:
```
return RequestBody.create(MediaType.parse(contentType), (byte[]) obj);
```
in 5.1.0 it is:
```
return RequestBody.create((byte[]) obj, MediaType.parse(contentType));
```

Looks like this change was introduced in #8969, and requires a more recent version of OkHttp to compile in some (all?) circumstances.
2021-04-28 16:55:12 +08:00
Andre Praca
ad9e2395ac [PHP] Fix parentSchema conditional causing parent call when parent isn't present (#8705)
* Fix parentSchema conditional

we cannot call `parent::` if parent isn't present. Everywhere else in the schema we're checking for `{{parentSchema}}` but here we're checking for `{{parent}}` which is causing errors when parent is not present

* Update samples
2021-04-28 15:08:50 +08:00
William Cheng
4aaaae765b [Scala][Akka] Use Files.createTempFile to address security concerns (#9348)
* fix scala akka server temp file issue

* update test templates
2021-04-28 14:53:51 +08:00
969 changed files with 6241 additions and 2544 deletions

View File

@@ -1,6 +1,5 @@
kind: pipeline
name: default
steps:
# test Java 11 HTTP client
- name: java11-test
@@ -54,3 +53,10 @@ steps:
image: haskell:8.6.5
commands:
- (cd samples/client/petstore/haskell-http-client/ && stack --install-ghc --no-haddock-deps haddock --fast && stack test --fast)
# test erlang client and server
- name: erlang
image: erlang:alpine
commands:
- (cd samples/client/petstore/erlang-client && rebar3 compile)
- (cd samples/client/petstore/erlang-proper && rebar3 compile)
#- (cd samples/server/petstore/erlang-server && rebar3 compile)

View File

@@ -48,6 +48,7 @@ Code change should conform to the programming style guide of the respective lang
- C#: https://msdn.microsoft.com/en-us/library/vstudio/ff926074.aspx
- C++: https://google.github.io/styleguide/cppguide.html
- C++ (Tizen): https://wiki.tizen.org/Native_Platform_Coding_Idiom_and_Style_Guide#C.2B.2B_Coding_Style
- C++ (Unreal Engine 4): https://docs.unrealengine.com/en-US/ProductionPipelines/DevelopmentSetup/CodingStandard/index.html
- Clojure: https://github.com/bbatsov/clojure-style-guide
- Crystal: https://crystal-lang.org/reference/conventions/coding_style.html
- Dart: https://www.dartlang.org/guides/language/effective-dart/style

View File

@@ -562,7 +562,7 @@ When code is generated from this project, it shall be considered **AS IS** and o
### [3.5 - IDE Integration](#table-of-contents)
Here is a list of community-conitributed IDE plug-ins that integrate with OpenAPI Generator:
Here is a list of community-contributed IDE plug-ins that integrate with OpenAPI Generator:
- Eclipse: [Codewind OpenAPI Tools for Eclipse](https://www.eclipse.org/codewind/open-api-tools-for-eclipse.html) by [IBM](https://www.ibm.com)
- IntelliJ IDEA: [OpenAPI Generator](https://plugins.jetbrains.com/plugin/8433-openapi-generator) by [Jim Schubert](https://jimschubert.us/#/)
@@ -666,6 +666,7 @@ Here are some companies/projects (alphabetical order) using OpenAPI Generator in
- [Twitter](https://twitter.com)
- [unblu inc.](https://www.unblu.com/)
- [Veamly](https://www.veamly.com/)
- [VMWare](https://www.vmware.com/)
- [wbt-solutions](https://www.wbt-solutions.de/)
- [Woleet](https://www.woleet.io/)
- [WSO2](https://wso2.com/)

View File

@@ -1,7 +1,7 @@
generatorName: ktorm-schema
outputDir: samples/schema/petstore/ktorm
inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore.yaml
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/ktorm-schema
additionalProperties:
hideGenerationTimestamp: true
importModelPackageName: org.openapitools.client.models
importModelPackageName: org.openapitools.client.models

View File

@@ -1,6 +1,6 @@
generatorName: nim
outputDir: samples/client/petstore/nim
inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore.yaml
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/nim-client
additionalProperties:
packageName: petstore

View File

@@ -52,6 +52,7 @@ Code change should conform to the programming style guide of the respective lang
- C#: https://msdn.microsoft.com/en-us/library/vstudio/ff926074.aspx
- C++: https://google.github.io/styleguide/cppguide.html
- C++ (Tizen): https://wiki.tizen.org/Native_Platform_Coding_Idiom_and_Style_Guide#C.2B.2B_Coding_Style
- C++ (Unreal Engine 4): https://docs.unrealengine.com/en-US/ProductionPipelines/DevelopmentSetup/CodingStandard/index.html
- Clojure: https://github.com/bbatsov/clojure-style-guide
- Crystal: https://crystal-lang.org/reference/conventions/coding_style.html
- Dart: https://www.dartlang.org/guides/language/effective-dart/style

View File

@@ -7,9 +7,9 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| Option | Description | Values | Default |
| ------ | ----------- | ------ | ------- |
|aspnetCoreVersion|ASP.NET Core version: 5.0, 3.1, 3.0, 2.2, 2.1, 2.0 (deprecated)| |3.1|
|buildTarget|Target to build an application or library| |program|
|classModifier|Class Modifier for controller classes: Empty string or abstract.| ||
|aspnetCoreVersion|ASP.NET Core version: 5.0, 3.1, 3.0, 2.2, 2.1, 2.0 (deprecated)|<dl><dt>**2.0**</dt><dd>ASP.NET Core 2.0</dd><dt>**2.1**</dt><dd>ASP.NET Core 2.1</dd><dt>**2.2**</dt><dd>ASP.NET Core 2.2</dd><dt>**3.0**</dt><dd>ASP.NET Core 3.0</dd><dt>**3.1**</dt><dd>ASP.NET Core 3.1</dd><dt>**5.0**</dt><dd>ASP.NET Core 5.0</dd></dl>|3.1|
|buildTarget|Target to build an application or library|<dl><dt>**program**</dt><dd>Generate code for a standalone server</dd><dt>**library**</dt><dd>Generate code for a server abstract class library</dd></dl>|program|
|classModifier|Class Modifier for controller classes: Empty string or abstract.|<dl><dt>****</dt><dd>Keep class default with no modifier</dd><dt>**abstract**</dt><dd>Make class abstract</dd></dl>||
|compatibilityVersion|ASP.Net Core CompatibilityVersion| |Version_2_2|
|enumNameSuffix|Suffix that will be appended to all enum names.| |Enum|
|enumValueSuffix|Suffix that will be appended to all enum values.| |Enum|
@@ -17,10 +17,10 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|isLibrary|Is the build a library| |false|
|licenseName|The name of the license| |NoLicense|
|licenseUrl|The URL of the license| |http://localhost|
|modelClassModifier|Model Class Modifier can be nothing or partial| |partial|
|modelClassModifier|Model Class Modifier can be nothing or partial|<dl><dt>****</dt><dd>Keep model class default with no modifier</dd><dt>**partial**</dt><dd>Make model class partial</dd></dl>|partial|
|newtonsoftVersion|Version for Microsoft.AspNetCore.Mvc.NewtonsoftJson for ASP.NET Core 3.0+| |3.0.0|
|operationIsAsync|Set methods to async or sync (default).| |false|
|operationModifier|Operation Modifier can be virtual or abstract| |virtual|
|operationModifier|Operation Modifier can be virtual or abstract|<dl><dt>**virtual**</dt><dd>Keep method virtual</dd><dt>**abstract**</dt><dd>Make method abstract</dd></dl>|virtual|
|operationResultTask|Set methods result to Task&lt;&gt;.| |false|
|packageAuthors|Specifies Authors property in the .NET Core project file.| |OpenAPI|
|packageCopyright|Specifies an AssemblyCopyright for the .NET Framework global assembly attributes stored in the AssemblyInfo file.| |No Copyright|
@@ -32,7 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|returnICollection|Return ICollection&lt;T&gt; instead of the concrete type.| |false|
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|sourceFolder|source folder for generated code| |src|
|swashbuckleVersion|Swashbuckle version: 3.0.0, 4.0.0, 5.0.0| |3.0.0|
|swashbuckleVersion|Swashbuckle version: 3.0.0, 4.0.0, 5.0.0|<dl><dt>**3.0.0**</dt><dd>Swashbuckle 3.0.0</dd><dt>**4.0.0**</dt><dd>Swashbuckle 4.0.0</dd><dt>**5.0.0**</dt><dd>Swashbuckle 5.0.0</dd></dl>|3.0.0|
|useCollection|Deserialize array types to Collection&lt;T&gt; instead of List&lt;T&gt;.| |false|
|useDateTimeOffset|Use DateTimeOffset to model date-time properties| |false|
|useDefaultRouting|Use default routing for the ASP.NET Core version.| |true|

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -29,7 +29,7 @@ public class CodegenOperation {
isArray, isMultipart,
isResponseBinary = false, isResponseFile = false, hasReference = false,
isRestfulIndex, isRestfulShow, isRestfulCreate, isRestfulUpdate, isRestfulDestroy,
isRestful, isDeprecated, isCallbackRequest, uniqueItems;
isRestful, isDeprecated, isCallbackRequest, uniqueItems, hasDefaultResponse = false;
public String path, operationId, returnType, returnFormat, httpMethod, returnBaseType,
returnContainer, summary, unescapedNotes, notes, baseName, defaultResponse;
public CodegenDiscriminator discriminator;
@@ -168,6 +168,15 @@ public class CodegenOperation {
return nonempty(examples);
}
/**
* Check if there's a default response
*
* @return true if responses contain a default response, false otherwise
*/
public boolean getHasDefaultResponse() {
return responses.stream().filter(response -> response.isDefault).findFirst().isPresent();
}
/**
* Check if act as Restful index method
*
@@ -270,6 +279,7 @@ public class CodegenOperation {
sb.append(", isResponseBinary=").append(isResponseBinary);
sb.append(", isResponseFile=").append(isResponseFile);
sb.append(", hasReference=").append(hasReference);
sb.append(", hasDefaultResponse=").append(hasDefaultResponse);
sb.append(", isRestfulIndex=").append(isRestfulIndex);
sb.append(", isRestfulShow=").append(isRestfulShow);
sb.append(", isRestfulCreate=").append(isRestfulCreate);
@@ -343,6 +353,7 @@ public class CodegenOperation {
isResponseBinary == that.isResponseBinary &&
isResponseFile == that.isResponseFile &&
hasReference == that.hasReference &&
hasDefaultResponse == that.hasDefaultResponse &&
isRestfulIndex == that.isRestfulIndex &&
isRestfulShow == that.isRestfulShow &&
isRestfulCreate == that.isRestfulCreate &&
@@ -400,7 +411,7 @@ public class CodegenOperation {
return Objects.hash(responseHeaders, hasAuthMethods, hasConsumes, hasProduces, hasParams, hasOptionalParams,
hasRequiredParams, returnTypeIsPrimitive, returnSimpleType, subresourceOperation, isMap,
isArray, isMultipart, isResponseBinary, isResponseFile, hasReference, isRestfulIndex,
isArray, isMultipart, isResponseBinary, isResponseFile, hasReference, hasDefaultResponse, isRestfulIndex,
isRestfulShow, isRestfulCreate, isRestfulUpdate, isRestfulDestroy, isRestful, isDeprecated,
isCallbackRequest, uniqueItems, path, operationId, returnType, httpMethod, returnBaseType,
returnContainer, summary, unescapedNotes, notes, baseName, defaultResponse, discriminator, consumes,

View File

@@ -199,14 +199,14 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
aspnetCoreVersion.addEnum("5.0", "ASP.NET Core 5.0");
aspnetCoreVersion.setDefault("3.1");
aspnetCoreVersion.setOptValue(aspnetCoreVersion.getDefault());
addOption(aspnetCoreVersion.getOpt(), aspnetCoreVersion.getDescription(), aspnetCoreVersion.getOptValue());
cliOptions.add(aspnetCoreVersion);
swashbuckleVersion.addEnum("3.0.0", "Swashbuckle 3.0.0");
swashbuckleVersion.addEnum("4.0.0", "Swashbuckle 4.0.0");
swashbuckleVersion.addEnum("5.0.0", "Swashbuckle 5.0.0");
swashbuckleVersion.setDefault("3.0.0");
swashbuckleVersion.setOptValue(swashbuckleVersion.getDefault());
addOption(swashbuckleVersion.getOpt(), swashbuckleVersion.getDescription(), swashbuckleVersion.getOptValue());
cliOptions.add(swashbuckleVersion);
// CLI Switches
addSwitch(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG,
@@ -261,19 +261,19 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
classModifier.addEnum("abstract", "Make class abstract");
classModifier.setDefault("");
classModifier.setOptValue(classModifier.getDefault());
addOption(classModifier.getOpt(), classModifier.getDescription(), classModifier.getOptValue());
cliOptions.add(classModifier);
operationModifier.addEnum("virtual", "Keep method virtual");
operationModifier.addEnum("abstract", "Make method abstract");
operationModifier.setDefault("virtual");
operationModifier.setOptValue(operationModifier.getDefault());
addOption(operationModifier.getOpt(), operationModifier.getDescription(), operationModifier.getOptValue());
cliOptions.add(operationModifier);
buildTarget.addEnum("program", "Generate code for a standalone server");
buildTarget.addEnum("library", "Generate code for a server abstract class library");
buildTarget.setDefault("program");
buildTarget.setOptValue(buildTarget.getDefault());
addOption(buildTarget.getOpt(), buildTarget.getDescription(), buildTarget.getOptValue());
cliOptions.add(buildTarget);
addSwitch(GENERATE_BODY,
"Generates method body.",
@@ -292,7 +292,7 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
modelClassModifier.addEnum("partial", "Make model class partial");
modelClassModifier.setDefault("partial");
modelClassModifier.setOptValue(modelClassModifier.getDefault());
addOption(modelClassModifier.getOpt(), modelClassModifier.getDescription(), modelClassModifier.getOptValue());
cliOptions.add(modelClassModifier);
}
@Override
@@ -592,6 +592,7 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
private void setBuildTarget() {
setCliOption(buildTarget);
if ("library".equals(buildTarget.getOptValue())) {
LOGGER.warn("buildTarget is {} so changing default isLibrary to true", buildTarget.getOptValue());
isLibrary = true;
projectSdk = SDK_LIB;
additionalProperties.put(CLASS_MODIFIER, "abstract");
@@ -636,7 +637,7 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
private void setUseSwashbuckle() {
if (isLibrary) {
LOGGER.warn("buildTarget is " + buildTarget.getOptValue() + " so changing default isLibrary to false ");
LOGGER.warn("isLibrary is true so changing default useSwashbuckle to false");
useSwashbuckle = false;
} else {
useSwashbuckle = true;

View File

@@ -128,6 +128,7 @@ public class CppPistacheServerCodegen extends AbstractCppCodegen {
typeMapping.put("boolean", "bool");
typeMapping.put("array", "std::vector");
typeMapping.put("map", "std::map");
typeMapping.put("set", "std::vector");
typeMapping.put("file", "std::string");
typeMapping.put("object", "Object");
typeMapping.put("binary", "std::string");

View File

@@ -166,8 +166,8 @@ public class ScalaAkkaClientCodegen extends AbstractScalaCodegen implements Code
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("build.sbt.mustache", "", "build.sbt"));
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("reference.mustache", resourcesFolder, "reference.conf"));
final String invokerFolder = (sourceFolder + File.separator + invokerPackage).replace(".", File.separator);
supportingFiles.add(new SupportingFile("apiRequest.mustache", invokerFolder, "ApiRequest.scala"));
@@ -175,6 +175,7 @@ public class ScalaAkkaClientCodegen extends AbstractScalaCodegen implements Code
supportingFiles.add(new SupportingFile("requests.mustache", invokerFolder, "requests.scala"));
supportingFiles.add(new SupportingFile("apiSettings.mustache", invokerFolder, "ApiSettings.scala"));
final String apiFolder = (sourceFolder + File.separator + apiPackage).replace(".", File.separator);
supportingFiles.add(new SupportingFile("project/build.properties.mustache", "project", "build.properties"));
supportingFiles.add(new SupportingFile("enumsSerializers.mustache", apiFolder, "EnumsSerializers.scala"));
supportingFiles.add(new SupportingFile("serializers.mustache", invokerFolder, "Serializers.scala"));
}

View File

@@ -104,8 +104,8 @@ if(hasProperty('target') && target == 'android') {
dependencies {
implementation 'io.swagger:swagger-annotations:1.5.24'
implementation "com.google.code.findbugs:jsr305:3.0.2"
implementation 'com.squareup.okhttp3:okhttp:3.14.7'
implementation 'com.squareup.okhttp3:logging-interceptor:3.14.7'
implementation 'com.squareup.okhttp3:okhttp:4.9.1'
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.1'
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'io.gsonfire:gson-fire:1.8.4'
{{#hasOAuthMethods}}

View File

@@ -10,8 +10,8 @@ lazy val root = (project in file(".")).
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.squareup.okhttp3" % "okhttp" % "4.9.1",
"com.squareup.okhttp3" % "logging-interceptor" % "4.9.1",
"com.google.code.gson" % "gson" % "2.8.6",
"org.apache.commons" % "commons-lang3" % "3.10",
{{#hasOAuthMethods}}

View File

@@ -14,24 +14,21 @@
#include <pistache/http_headers.h>
#include <pistache/optional.h>
{{^hasModelImport}}#include <nlohmann/json.hpp>{{/hasModelImport}}
#include <utility>
{{#imports}}{{{import}}}
{{/imports}}
{{#apiNamespaceDeclarations}}
namespace {{this}} {
{{/apiNamespaceDeclarations}}
{{#hasModelImport}}
using namespace {{modelNamespace}};{{/hasModelImport}}
namespace {{apiNamespace}}
{
class {{declspec}} {{classname}} {
public:
{{classname}}(std::shared_ptr<Pistache::Rest::Router>);
virtual ~{{classname}}() {}
explicit {{classname}}(const std::shared_ptr<Pistache::Rest::Router>& rtr);
virtual ~{{classname}}() = default;
void init();
const std::string base = "{{basePathWithoutHost}}";
static const std::string base;
private:
void setupRoutes();
@@ -41,9 +38,21 @@ private:
{{/operation}}
void {{classnameSnakeLowerCase}}_default_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
std::shared_ptr<Pistache::Rest::Router> router;
{{#operation}}
const std::shared_ptr<Pistache::Rest::Router> router;
/// <summary>
/// Helper function to handle unexpected Exceptions during Parameter parsing and validation.
/// May be overriden to return custom error formats.
/// </summary>
virtual std::pair<Pistache::Http::Code, std::string> handleParsingException(const std::exception& ex) const noexcept;
/// <summary>
/// Helper function to handle unexpected Exceptions during processing of the request in handler functions.
/// May be overriden to return custom error formats.
/// </summary>
virtual std::pair<Pistache::Http::Code, std::string> handleOperationException(const std::exception& ex) const noexcept;
{{#operation}}
/// <summary>
/// {{summary}}
/// </summary>
@@ -54,7 +63,7 @@ private:
{{#allParams}}
/// <param name="{{paramName}}">{{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}</param>
{{/allParams}}
virtual void {{operationIdSnakeCase}}({{#allParams}}const {{{dataType}}} &{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}Pistache::Http::ResponseWriter &response) = 0;
virtual void {{operationIdSnakeCase}}({{#allParams}}const {{#isModel}}{{modelNamespace}}::{{/isModel}}{{{dataType}}} &{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}Pistache::Http::ResponseWriter &response) = 0;
{{/vendorExtensions.x-codegen-pistache-is-parsing-supported}}
{{^vendorExtensions.x-codegen-pistache-is-parsing-supported}}
virtual void {{operationIdSnakeCase}}(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter &response) = 0;
@@ -63,9 +72,7 @@ private:
};
{{#apiNamespaceDeclarations}}
}
{{/apiNamespaceDeclarations}}
} // namespace {{apiNamespace}}
#endif /* {{classname}}_H_ */

View File

@@ -22,17 +22,16 @@
{{#imports}}{{{import}}}
{{/imports}}
{{#apiNamespaceDeclarations}}
namespace {{this}} {
{{/apiNamespaceDeclarations}}
namespace {{apiNamespace}}
{
{{#hasModelImport}}
using namespace {{modelNamespace}};{{/hasModelImport}}
class {{classname}}Impl : public {{apiNamespace}}::{{classname}} {
public:
{{classname}}Impl(std::shared_ptr<Pistache::Rest::Router>);
~{{classname}}Impl() {}
explicit {{classname}}Impl(const std::shared_ptr<Pistache::Rest::Router>& rtr);
~{{classname}}Impl() override = default;
{{#operation}}
{{#vendorExtensions.x-codegen-pistache-is-parsing-supported}}
@@ -45,11 +44,9 @@ public:
};
{{#apiNamespaceDeclarations}}
}
{{/apiNamespaceDeclarations}}
} // namespace {{apiNamespace}}
{{/operations}}
#endif
#endif

View File

@@ -10,9 +10,10 @@ namespace {{this}} {
{{#hasModelImport}}
using namespace {{modelNamespace}};{{/hasModelImport}}
{{classname}}Impl::{{classname}}Impl(std::shared_ptr<Pistache::Rest::Router> rtr)
{{classname}}Impl::{{classname}}Impl(const std::shared_ptr<Pistache::Rest::Router>& rtr)
: {{classname}}(rtr)
{ }
{
}
{{#operation}}
{{#vendorExtensions.x-codegen-pistache-is-parsing-supported}}
@@ -31,4 +32,4 @@ void {{classname}}Impl::{{operationIdSnakeCase}}(const Pistache::Rest::Request &
}
{{/apiNamespaceDeclarations}}
{{/operations}}
{{/operations}}

View File

@@ -4,16 +4,18 @@
#include "{{classname}}.h"
#include "{{prefix}}Helpers.h"
{{#apiNamespaceDeclarations}}
namespace {{this}} {
{{/apiNamespaceDeclarations}}
namespace {{apiNamespace}}
{
using namespace {{helpersNamespace}};
{{#hasModelImport}}
using namespace {{modelNamespace}};{{/hasModelImport}}
{{classname}}::{{classname}}(std::shared_ptr<Pistache::Rest::Router> rtr) {
router = rtr;
const std::string {{classname}}::base = "{{basePathWithoutHost}}";
{{classname}}::{{classname}}(const std::shared_ptr<Pistache::Rest::Router>& rtr)
: router(rtr)
{
}
void {{classname}}::init() {
@@ -31,8 +33,26 @@ void {{classname}}::setupRoutes() {
router->addCustomHandler(Routes::bind(&{{classname}}::{{classnameSnakeLowerCase}}_default_handler, this));
}
std::pair<Pistache::Http::Code, std::string> {{classname}}::handleParsingException(const std::exception& ex) const noexcept
{
try {
throw ex;
} catch (nlohmann::detail::exception &e) {
return std::make_pair(Pistache::Http::Code::Bad_Request, e.what());
} catch ({{helpersNamespace}}::ValidationException &e) {
return std::make_pair(Pistache::Http::Code::Bad_Request, e.what());
}
}
std::pair<Pistache::Http::Code, std::string> {{classname}}::handleOperationException(const std::exception& ex) const noexcept
{
return std::make_pair(Pistache::Http::Code::Internal_Server_Error, ex.what());
}
{{#operation}}
void {{classname}}::{{operationIdSnakeCase}}_handler(const Pistache::Rest::Request &{{#hasParams}}request{{/hasParams}}, Pistache::Http::ResponseWriter response) {
try {
{{#vendorExtensions.x-codegen-pistache-is-parsing-supported}}
{{#hasPathParams}}
// Getting the path params
@@ -71,32 +91,40 @@ void {{classname}}::{{operationIdSnakeCase}}_handler(const Pistache::Rest::Reque
{{#hasBodyParam}}
{{#bodyParam}}
{{^isPrimitiveType}}
nlohmann::json::parse(request.body()).get_to({{paramName}});
nlohmann::json::parse(request.body()).get_to({{paramName}});
{{paramName}}.validate();
{{/isPrimitiveType}}
{{#isPrimitiveType}}
{{paramName}} = request.body();
{{paramName}} = request.body();
{{/isPrimitiveType}}
} catch (std::exception &e) {
const std::pair<Pistache::Http::Code, std::string> errorInfo = this->handleParsingException(e);
response.send(errorInfo.first, errorInfo.second);
return;
}
try {
{{/bodyParam}}
{{/hasBodyParam}}
this->{{operationIdSnakeCase}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}response);
this->{{operationIdSnakeCase}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}response);
{{/vendorExtensions.x-codegen-pistache-is-parsing-supported}}
{{^vendorExtensions.x-codegen-pistache-is-parsing-supported}}
try {
this->{{operationIdSnakeCase}}(request, response);
{{/vendorExtensions.x-codegen-pistache-is-parsing-supported}}
} catch (nlohmann::detail::exception &e) {
//send a 400 error
response.send(Pistache::Http::Code::Bad_Request, e.what());
return;
} catch (Pistache::Http::HttpError &e) {
response.send(static_cast<Pistache::Http::Code>(e.code()), e.what());
return;
} catch (std::exception &e) {
//send a 500 error
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
const std::pair<Pistache::Http::Code, std::string> errorInfo = this->handleOperationException(e);
response.send(errorInfo.first, errorInfo.second);
return;
}
} catch (std::exception &e) {
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
}
}
{{/operation}}
@@ -104,8 +132,6 @@ void {{classname}}::{{classnameSnakeLowerCase}}_default_handler(const Pistache::
response.send(Pistache::Http::Code::Not_Found, "The requested method does not exist");
}
{{#apiNamespaceDeclarations}}
}
{{/apiNamespaceDeclarations}}
} // namespace {{apiNamespace}}
{{/operations}}

View File

@@ -14,16 +14,80 @@
#include <vector>
#include <map>
{{#helpersNamespaceDeclarations}}
namespace {{this}} {
{{/helpersNamespaceDeclarations}}
namespace {{helpersNamespace}}
{
class ValidationException : public std::runtime_error
{
public:
explicit ValidationException(const std::string& what)
: std::runtime_error(what)
{ }
~ValidationException() override = default;
};
/// <summary>
/// Validate a string against the full-date definition of RFC 3339, section 5.6.
/// </summary>
bool validateRfc3339_date(const std::string& str);
/// <summary>
/// Validate a string against the date-time definition of RFC 3339, section 5.6.
/// </summary>
bool validateRfc3339_date_time(const std::string& str);
namespace sfinae_helpers
{
struct NoType {};
template <typename T1, typename T2> NoType operator==(const T1&, const T2&);
template <typename T1, typename T2> class EqualsOperatorAvailable
{
public:
enum
{
value = !std::is_same< decltype(std::declval<T1>() == std::declval<T2>()), NoType >::value
};
};
} // namespace sfinae_helpers
/// <summary>
/// Determine if the given vector<T> only has unique elements. T must provide the == operator.
/// </summary>
template <typename T>
bool hasOnlyUniqueItems(const std::vector<T>& vec)
{
static_assert(sfinae_helpers::EqualsOperatorAvailable<T, T>::value,
"hasOnlyUniqueItems<T> cannot be called, passed template type does not provide == operator.");
if (vec.size() <= 1)
{
return true;
}
// Compare every element of vec to every other element of vec.
// This isn't an elegant way to do this, since it's O(n^2),
// but it's the best solution working only with the == operator.
// This could be greatly improved if our models provided a valid hash
// and/or the < operator
for (size_t i = 0; i < vec.size() - 1; i++)
{
for (size_t j = i + 1; j < vec.size(); j++)
{
if (vec[i] == vec[j])
{
return false;
}
}
}
return true;
}
std::string toStringValue(const std::string &value);
std::string toStringValue(const int32_t &value);
std::string toStringValue(const int64_t &value);
std::string toStringValue(const bool &value);
std::string toStringValue(const float &value);
std::string toStringValue(const double &value);
std::string toStringValue(const int32_t value);
std::string toStringValue(const int64_t value);
std::string toStringValue(const bool value);
std::string toStringValue(const float value);
std::string toStringValue(const double value);
bool fromStringValue(const std::string &inStr, std::string &value);
bool fromStringValue(const std::string &inStr, int32_t &value);
@@ -57,8 +121,6 @@ namespace {{this}} {
return fromStringValue(inStrings, value);
}
{{#helpersNamespaceDeclarations}}
}
{{/helpersNamespaceDeclarations}}
} // namespace {{helpersNamespace}}
#endif // {{prefix}}Helpers_H_
#endif // {{prefix}}Helpers_H_

View File

@@ -1,32 +1,74 @@
{{>licenseInfo}}
#include "{{prefix}}Helpers.h"
#include <regex>
{{#helpersNamespaceDeclarations}}
namespace {{this}} {
{{/helpersNamespaceDeclarations}}
namespace {{helpersNamespace}}
{
const std::regex regexRfc3339_date(R"(^(\d{4})\-(\d{2})\-(\d{2})$)");
const std::regex regexRfc3339_date_time(
R"(^(\d{4})\-(\d{2})\-(\d{2})[Tt](\d{2}):(\d{2}):(\d{2})(\.\d+)?([Zz]|([\+\-])(\d{2}):(\d{2}))$)"
);
namespace
{
// Determine if given year is a leap year
// See RFC 3339, Appendix C https://tools.ietf.org/html/rfc3339#appendix-C
bool isLeapYear(const uint16_t year) {
return (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0));
}
bool validateDateValues(const uint16_t year, const uint16_t month, const uint16_t day) {
return !(
(month == 0 || month > 12)
|| (day == 0)
|| (month == 2 && day > (28 + (isLeapYear(year) ? 1 : 0)))
|| (month <= 7 && day > (30 + month % 2))
|| (month >= 8 && day > (31 - month % 2))
);
}
bool validateTimeValues(const uint16_t hours, const uint16_t minutes, const uint16_t seconds) {
return (hours <= 23) && (minutes <= 59) && (seconds <= 60);
}
}
bool validateRfc3339_date(const std::string& str) {
std::smatch match;
const bool found = std::regex_search(str, match, regexRfc3339_date);
return found && validateDateValues(std::stoi(match[1]), std::stoi(match[2]), std::stoi(match[3]));
}
bool validateRfc3339_date_time(const std::string& str) {
std::smatch match;
const bool found = std::regex_search(str, match, regexRfc3339_date_time);
return found
&& validateDateValues(std::stoi(match[1]), std::stoi(match[2]), std::stoi(match[3]))
&& validateTimeValues(std::stoi(match[4]), std::stoi(match[5]), std::stoi(match[6]));
}
std::string toStringValue(const std::string &value){
return std::string(value);
}
std::string toStringValue(const int32_t &value){
std::string toStringValue(const int32_t value){
return std::to_string(value);
}
std::string toStringValue(const int64_t &value){
std::string toStringValue(const int64_t value){
return std::to_string(value);
}
std::string toStringValue(const bool &value){
return value?std::string("true"):std::string("false");
std::string toStringValue(const bool value){
return value ? std::string("true") : std::string("false");
}
std::string toStringValue(const float &value){
std::string toStringValue(const float value){
return std::to_string(value);
}
std::string toStringValue(const double &value){
std::string toStringValue(const double value){
return std::to_string(value);
}
@@ -56,9 +98,15 @@ bool fromStringValue(const std::string &inStr, int64_t &value){
}
bool fromStringValue(const std::string &inStr, bool &value){
bool result = true;
inStr == "true"?value = true: inStr == "false"?value = false: result = false;
return result;
if (inStr == "true") {
value = true;
return true;
}
if (inStr == "false") {
value = false;
return true;
}
return false;
}
bool fromStringValue(const std::string &inStr, float &value){
@@ -81,6 +129,4 @@ bool fromStringValue(const std::string &inStr, double &value){
return true;
}
{{#helpersNamespaceDeclarations}}
}
{{/helpersNamespaceDeclarations}}
} // namespace {{helpersNamespace}}

View File

@@ -13,9 +13,8 @@
{{/imports}}
#include <nlohmann/json.hpp>
{{#modelNamespaceDeclarations}}
namespace {{this}} {
{{/modelNamespaceDeclarations}}
namespace {{modelNamespace}}
{
/// <summary>
/// {{description}}
@@ -24,7 +23,7 @@ class {{declspec}} {{classname}}
{
public:
{{classname}}();
virtual ~{{classname}}();
virtual ~{{classname}}() = default;
{{#isEnum}}{{#allowableValues}}
enum class e{{classname}} {
// To have a valid default value.
@@ -35,7 +34,20 @@ public:
{{{name}}}{{^-last}}, {{/-last}}
{{/enumVars}}
};{{/allowableValues}}{{/isEnum}}
void validate();
/// <summary>
/// Validate the current data in the model. Throws a ValidationException on failure.
/// </summary>
void validate() const;
/// <summary>
/// Validate the current data in the model. Returns false on error and writes an error
/// message into the given stringstream.
/// </summary>
bool validate(std::stringstream& msg) const;
bool operator==(const {{classname}}& rhs) const;
bool operator!=(const {{classname}}& rhs) const;
/////////////////////////////////////////////
/// {{classname}} members
@@ -44,7 +56,7 @@ public:
/// <summary>
/// {{description}}
/// </summary>
{{{dataType}}}{{#isContainer}}&{{/isContainer}} {{getter}}(){{^isContainer}} const{{/isContainer}};
{{{dataType}}} {{getter}}() const;
void {{setter}}({{{dataType}}} const{{^isPrimitiveType}}&{{/isPrimitiveType}} value);{{^required}}
bool {{nameInCamelCase}}IsSet() const;
void unset{{name}}();{{/required}}
@@ -65,11 +77,12 @@ protected:
{{#isEnum}}
{{classname}}::e{{classname}} m_value = {{classname}}::e{{classname}}::INVALID_VALUE_OPENAPI_GENERATED;
{{/isEnum}}
// Helper overload for validate. Used when one model stores another model and calls it's validate.
bool validate(std::stringstream& msg, const std::string& pathPrefix) const;
};
{{#modelNamespaceDeclarations}}
}
{{/modelNamespaceDeclarations}}
} // namespace {{modelNamespace}}
#endif /* {{classname}}_H_ */
{{/model}}

View File

@@ -2,12 +2,12 @@
{{#models}}{{#model}}
#include "{{classname}}.h"
{{#isEnum}}#include <stdexcept>
#include <sstream>{{/isEnum}}
#include "{{prefix}}Helpers.h"
{{#isEnum}}#include <stdexcept>{{/isEnum}}
#include <sstream>
{{#modelNamespaceDeclarations}}
namespace {{this}} {
{{/modelNamespaceDeclarations}}
namespace {{modelNamespace}}
{
{{classname}}::{{classname}}()
{
@@ -18,13 +18,69 @@ namespace {{this}} {
{{/required}}{{/vars}}
}
{{classname}}::~{{classname}}()
void {{classname}}::validate() const
{
std::stringstream msg;
if (!validate(msg))
{
throw {{helpersNamespace}}::ValidationException(msg.str());
}
}
void {{classname}}::validate()
bool {{classname}}::validate(std::stringstream& msg) const
{
// TODO: implement validation
return validate(msg, "");
}
bool {{classname}}::validate(std::stringstream& msg, const std::string& pathPrefix) const
{
bool success = true;
const std::string _pathPrefix = pathPrefix.empty() ? "{{classname}}" : pathPrefix;
{{#isEnum}}{{! Special case for enum types }}
if (m_value == {{classname}}::e{{classname}}::INVALID_VALUE_OPENAPI_GENERATED)
{
success = false;
msg << _pathPrefix << ": has no value;";
}
{{/isEnum}}
{{^isEnum}}
{{#vars}}
{{#isArray}} {{! Always generate validation body for array types }}
{{^required}}if ({{nameInCamelCase}}IsSet()){{/required}}
{{#required}}/* {{name}} */ {{/required}}{
const {{{dataType}}}& value = m_{{name}};
const std::string currentValuePath = _pathPrefix + ".{{nameInCamelCase}}";
{{> model-validation-body }}
}
{{/isArray}}{{^isArray}}{{#hasValidation}} {{! Only generate validation if necessary }}
{{^required}}if ({{nameInCamelCase}}IsSet()){{/required}}
{{#required}}/* {{name}} */ {{/required}}{
const {{{dataType}}}& value = m_{{name}};
const std::string currentValuePath = _pathPrefix + ".{{nameInCamelCase}}";
{{> model-validation-body }}
}
{{/hasValidation}}{{/isArray}}
{{/vars}}
{{/isEnum}}
return success;
}
bool {{classname}}::operator==(const {{classname}}& rhs) const
{
return
{{#isEnum}}getValue() == rhs.getValue(){{/isEnum}}
{{^isEnum}}{{#vars}}
{{#required}}({{getter}}() == rhs.{{getter}}()){{/required}}
{{^required}}((!{{nameInCamelCase}}IsSet() && !rhs.{{nameInCamelCase}}IsSet()) || ({{nameInCamelCase}}IsSet() && rhs.{{nameInCamelCase}}IsSet() && {{getter}}() == rhs.{{getter}}())){{/required}}{{^-last}} &&{{/-last}}
{{/vars}}{{/isEnum}}
;
}
bool {{classname}}::operator!=(const {{classname}}& rhs) const
{
return !(*this == rhs);
}
void to_json(nlohmann::json& j, const {{classname}}& o)
@@ -74,7 +130,7 @@ void from_json(const nlohmann::json& j, {{classname}}& o)
{{/enumVars}}{{/allowableValues}}{{/isEnum}}
}
{{#vars}}{{{dataType}}}{{#isContainer}}&{{/isContainer}} {{classname}}::{{getter}}(){{^isContainer}} const{{/isContainer}}
{{#vars}}{{{dataType}}} {{classname}}::{{getter}}() const
{
return m_{{name}};
}
@@ -102,9 +158,7 @@ void {{classname}}::setValue({{classname}}::e{{classname}} value)
m_value = value;
}{{/isEnum}}
{{#modelNamespaceDeclarations}}
}
{{/modelNamespaceDeclarations}}
} // namespace {{modelNamespace}}
{{/model}}
{{/models}}

View File

@@ -14,9 +14,8 @@
#include <nlohmann/json.hpp>
{{#hasOptional}}#include <pistache/optional.h>{{/hasOptional}}
{{#modelNamespaceDeclarations}}
namespace {{this}} {
{{/modelNamespaceDeclarations}}
namespace {{modelNamespace}}
{
struct {{classname}}
{
@@ -34,9 +33,9 @@ struct {{classname}}
void to_json(nlohmann::json& j, const {{classname}}& o);
void from_json(const nlohmann::json& j, {{classname}}& o);
{{#modelNamespaceDeclarations}}
} // {{this}}
{{/modelNamespaceDeclarations}}
} // namespace {{modelNamespace}}
#endif /* {{classname}}_H_ */
{{/model}}

View File

@@ -3,9 +3,8 @@
#include "{{classname}}.h"
{{#modelNamespaceDeclarations}}
namespace {{this}} {
{{/modelNamespaceDeclarations}}
namespace {{modelNamespace}}
{
nlohmann::json {{classname}}::to_json() const
{
@@ -51,9 +50,7 @@ void from_json(const nlohmann::json& j, {{classname}}& o)
{{/vars}}
}
{{#modelNamespaceDeclarations}}
} // {{this}}
{{/modelNamespaceDeclarations}}
} // namespace {{modelNamespace}}
{{/model}}
{{/models}}

View File

@@ -0,0 +1,124 @@
{{!
This template generates the validation logic for a model.
This template file calls itself recursively for arrays.
}}
{{! Check for eunm properties that are their own schema }}
{{! These are in their own class with a validate function, the way to check for this is quite a hack
since isEnum, isString and isModel are all false. }}
{{^isString}}{{#allowableValues.enumVars.0.value}}
success = value.validate(msg, currentValuePath) && success;
{{/allowableValues.enumVars.0.value}}{{/isString}}
{{#isModel}}success = value.validate(msg, currentValuePath + ".{{nameInCamelCase}}") && success;{{/isModel}}
{{! Date validation }}
{{#isDate}}
if (!{{helpersNamespace}}::validateRfc3339_date(value))
{
success = false;
msg << currentValuePath << ": must be a valid RFC 3339 date-full string;";
}
{{/isDate}}
{{! Date-Time validation }}
{{#isDateTime}}
if (!{{helpersNamespace}}::validateRfc3339_date_time(value))
{
success = false;
msg << currentValuePath << ": must be a valid RFC 3339 date-time string;";
}
{{/isDateTime}}
{{! string validation }}
{{#isString}}
{{#minLength}}
if (value.length() < {{minLength}})
{
success = false;
msg << currentValuePath << ": must be at least {{minLength}} characters long;";
}
{{/minLength}}
{{#maxLength}}
if (value.length() > {{maxLength}})
{
success = false;
msg << currentValuePath << ": must be at most {{maxLength}} characters long;";
}
{{/maxLength}}
{{!
TODO validate regex of string using pattern variable. This has two challenges
- Is compatibility with the given regex pattern guaranteed?
- Creating the std::regex on every validation would be rather slow. Ideally one would
initialize them for the class once as a static const and use them.
}}
{{! string encoded enum validation }}
{{#isEnum}}
{{#allowableValues}}
if ({{#enumVars}}
value != "{{value}}"{{^-last}} &&{{/-last}}{{/enumVars}}
) {
success = false;
msg << currentValuePath << ": has invalid value \"" << value << "\";";
}
{{/allowableValues}}
{{/isEnum}}
{{/isString}}
{{! numeric validation }}
{{#isNumeric}}
{{#minimum}}
if (value <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{#isFloat}}static_cast<float>({{/isFloat}}{{minimum}}{{#isFloat}}){{/isFloat}}{{#isLong}}ll{{/isLong}})
{
success = false;
msg << currentValuePath << ": must be greater than{{^exclusiveMinimum}} or equal to{{/exclusiveMinimum}} {{minimum}};";
}
{{/minimum}}
{{#maximum}}
if (value >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{#isFloat}}static_cast<float>({{/isFloat}}{{maximum}}{{#isFloat}}){{/isFloat}}{{#isLong}}ll{{/isLong}})
{
success = false;
msg << currentValuePath << ": must be less than{{^exclusiveMaximum}} or equal to{{/exclusiveMaximum}} {{maximum}};";
}
{{/maximum}}
{{#multipleOf}}
{{#isInteger}}if (value % {{multipleOf}}{{#isLong}}ll{{/isLong}} != 0){{/isInteger}}
{{#isFloat}}if (std::fmod(value, static_cast<float>({{multipleOf}})) != 0){{/isFloat}}
{{#isDouble}}if (std::fmod(value, {{multipleOf}}) != 0){{/isDouble}}
{
success = false;
msg << currentValuePath << ": must be a multiple of {{multipleOf}};";
}
{{/multipleOf}}
{{/isNumeric}}
{{! Array validation }}
{{#isArray}}
{{#minItems}}
if (value.size() < {{minItems}})
{
success = false;
msg << currentValuePath << ": must have at least {{minItems}} elements;";
}
{{/minItems}}
{{#maxItems}}
if (value.size() > {{maxItems}})
{
success = false;
msg << currentValuePath << ": must have at most {{maxItems}} elements;";
}
{{/maxItems}}
{{#uniqueItems}}
if (!{{helpersNamespace}}::hasOnlyUniqueItems(value))
{
success = false;
msg << currentValuePath << ": may not contain the same item more than once;";
}
{{/uniqueItems}}
{ // Recursive validation of array elements
const std::string oldValuePath = currentValuePath;
int i = 0;
{{! the element var has the same name as the vector, so that the recursive template works - what a wonderful hack }}
for (const {{{items.dataType}}}& value : value)
{ {{! and I do a similar hack with currentValuePath... }}
const std::string currentValuePath = oldValuePath + "[" + std::to_string(i) + "]";
{{#items}}
{{> model-validation-body }} {{! Recursively apply template to array - this is where things will probbaly go wrong }}
{{/items}}
i++;
}
}
{{/isArray}}

View File

@@ -15,9 +15,19 @@ public:
{{classname}}();
~{{classname}}();
/* Sets the URL Endpoint.
* Note: several fallback endpoints can be configured in request retry policies, see Request::SetShouldRetry */
void SetURL(const FString& Url);
/* Adds global header params to all requests */
void AddHeaderParam(const FString& Key, const FString& Value);
void ClearHeaderParams();
/* Sets the retry manager to the user-defined retry manager. User must manage the lifetime of the retry manager.
* If no retry manager is specified and a request needs retries, a default retry manager will be used.
* See also: Request::SetShouldRetry */
void SetHttpRetryManager(FHttpRetrySystem::FManager& RetryManager);
FHttpRetrySystem::FManager& GetHttpRetryManager();
{{#operations}}{{#operation}}class {{operationIdCamelCase}}Request;
class {{operationIdCamelCase}}Response;
@@ -27,15 +37,17 @@ public:
{{#operations}}{{#operation}}{{#description}}/* {{{description}}} */
{{/description}}bool {{operationIdCamelCase}}(const {{operationIdCamelCase}}Request& Request, const F{{operationIdCamelCase}}Delegate& Delegate = F{{operationIdCamelCase}}Delegate()) const;
{{/operation}}{{/operations}}
private:
{{#operations}}{{#operation}}void On{{operationIdCamelCase}}Response(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, F{{operationIdCamelCase}}Delegate Delegate, int AutoRetryCount) const;
{{#operations}}{{#operation}}void On{{operationIdCamelCase}}Response(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, F{{operationIdCamelCase}}Delegate Delegate) const;
{{/operation}}{{/operations}}
FHttpRequestRef CreateHttpRequest(const Request& Request) const;
bool IsValid() const;
void HandleResponse(FHttpResponsePtr HttpResponse, bool bSucceeded, Response& InOutResponse) const;
FString Url;
TMap<FString,FString> AdditionalHeaderParams;
mutable FHttpRetrySystem::FManager* RetryManager = nullptr;
mutable TUniquePtr<HttpRetryManager> DefaultRetryManager;
};
{{#cppNamespaceDeclarations}}

View File

@@ -45,6 +45,40 @@ bool {{classname}}::IsValid() const
return true;
}
void {{classname}}::SetHttpRetryManager(FHttpRetrySystem::FManager& InRetryManager)
{
if(RetryManager != &GetHttpRetryManager())
{
DefaultRetryManager.Reset();
RetryManager = &InRetryManager;
}
}
FHttpRetrySystem::FManager& {{classname}}::GetHttpRetryManager()
{
return *RetryManager;
}
FHttpRequestRef {{classname}}::CreateHttpRequest(const Request& Request) const
{
if (!Request.GetRetryParams().IsSet())
{
return FHttpModule::Get().CreateRequest();
}
else
{
if (!RetryManager)
{
// Create default retry manager if none was specified
DefaultRetryManager = MakeUnique<HttpRetryManager>(6, 60);
RetryManager = DefaultRetryManager.Get();
}
const HttpRetryParams& Params = Request.GetRetryParams().GetValue();
return RetryManager->CreateRequest(Params.RetryLimitCountOverride, Params.RetryTimeoutRelativeSecondsOverride, Params.RetryResponseCodes, Params.RetryVerbs, Params.RetryDomains);
}
}
void {{classname}}::HandleResponse(FHttpResponsePtr HttpResponse, bool bSucceeded, Response& InOutResponse) const
{
InOutResponse.SetHttpResponse(HttpResponse);
@@ -96,7 +130,7 @@ bool {{classname}}::{{operationIdCamelCase}}(const {{operationIdCamelCase}}Reque
if (!IsValid())
return false;
FHttpRequestRef HttpRequest = FHttpModule::Get().CreateRequest();
FHttpRequestRef HttpRequest = CreateHttpRequest(Request);
HttpRequest->SetURL(*(Url + Request.ComputePath()));
for(const auto& It : AdditionalHeaderParams)
@@ -106,26 +140,15 @@ bool {{classname}}::{{operationIdCamelCase}}(const {{operationIdCamelCase}}Reque
Request.SetupHttpRequest(HttpRequest);
HttpRequest->OnProcessRequestComplete().BindRaw(this, &{{classname}}::On{{operationIdCamelCase}}Response, Delegate, Request.GetAutoRetryCount());
HttpRequest->OnProcessRequestComplete().BindRaw(this, &{{classname}}::On{{operationIdCamelCase}}Response, Delegate);
return HttpRequest->ProcessRequest();
}
void {{classname}}::On{{operationIdCamelCase}}Response(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, F{{operationIdCamelCase}}Delegate Delegate, int AutoRetryCount) const
void {{classname}}::On{{operationIdCamelCase}}Response(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, F{{operationIdCamelCase}}Delegate Delegate) const
{
{{operationIdCamelCase}}Response Response;
Response.SetHttpRequest(HttpRequest);
HandleResponse(HttpResponse, bSucceeded, Response);
if(!Response.IsSuccessful() && AutoRetryCount > 0)
{
HttpRequest->OnProcessRequestComplete().BindRaw(this, &{{classname}}::On{{operationIdCamelCase}}Response, Delegate, AutoRetryCount - 1);
Response.AsyncRetry();
}
else
{
Delegate.ExecuteIfBound(Response);
}
Delegate.ExecuteIfBound(Response);
}
{{/operation}}

View File

@@ -5,6 +5,8 @@
#include "Interfaces/IHttpResponse.h"
#include "Serialization/JsonWriter.h"
#include "Dom/JsonObject.h"
#include "HttpRetrySystem.h"
#include "Containers/Ticker.h"
{{#cppNamespaceDeclarations}}
namespace {{this}}
@@ -12,6 +14,31 @@ namespace {{this}}
{{/cppNamespaceDeclarations}}
typedef TSharedRef<TJsonWriter<>> JsonWriter;
using namespace FHttpRetrySystem;
struct {{dllapi}} HttpRetryManager : public FManager, public FTickerObjectBase
{
using FManager::FManager;
bool Tick(float DeltaTime) final;
};
struct {{dllapi}} HttpRetryParams
{
HttpRetryParams(
const FRetryLimitCountSetting& InRetryLimitCountOverride = FRetryLimitCountSetting(),
const FRetryTimeoutRelativeSecondsSetting& InRetryTimeoutRelativeSecondsOverride = FRetryTimeoutRelativeSecondsSetting(),
const FRetryResponseCodes& InRetryResponseCodes = FRetryResponseCodes(),
const FRetryVerbs& InRetryVerbs = FRetryVerbs(),
const FRetryDomainsPtr& InRetryDomains = FRetryDomainsPtr()
);
FRetryLimitCountSetting RetryLimitCountOverride;
FRetryTimeoutRelativeSecondsSetting RetryTimeoutRelativeSecondsOverride;
FRetryResponseCodes RetryResponseCodes;
FRetryVerbs RetryVerbs;
FRetryDomainsPtr RetryDomains;
};
class {{dllapi}} Model
{
@@ -28,11 +55,12 @@ public:
virtual void SetupHttpRequest(const FHttpRequestRef& HttpRequest) const = 0;
virtual FString ComputePath() const = 0;
void SetAutoRetryCount(int InCount) { AutoRetryCount = InCount; }
int GetAutoRetryCount() const { return AutoRetryCount; }
/* Enables retry and optionally sets a retry policy for this request */
void SetShouldRetry(const HttpRetryParams& Params = HttpRetryParams()) { RetryParams = Params; }
const TOptional<HttpRetryParams>& GetRetryParams() const { return RetryParams; }
private:
int AutoRetryCount = 0;
TOptional<HttpRetryParams> RetryParams;
};
class {{dllapi}} Response
@@ -44,8 +72,6 @@ public:
void SetSuccessful(bool InSuccessful) { Successful = InSuccessful; }
bool IsSuccessful() const { return Successful; }
void AsyncRetry() const;
virtual void SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode);
EHttpResponseCodes::Type GetHttpResponseCode() const { return ResponseCode; }
@@ -55,15 +81,11 @@ public:
void SetHttpResponse(const FHttpResponsePtr& InHttpResponse) { HttpResponse = InHttpResponse; }
const FHttpResponsePtr& GetHttpResponse() const { return HttpResponse; }
void SetHttpRequest(const FHttpRequestPtr& InHttpRequest) { HttpRequest = InHttpRequest; }
const FHttpRequestPtr& GetHttpRequest() const { return HttpRequest; }
private:
bool Successful;
EHttpResponseCodes::Type ResponseCode;
FString ResponseString;
FHttpResponsePtr HttpResponse;
FHttpRequestPtr HttpRequest;
};
{{#cppNamespaceDeclarations}}

View File

@@ -1,13 +1,30 @@
{{>licenseInfo}}
#include "{{modelNamePrefix}}BaseModel.h"
#include "Async/Async.h"
{{#cppNamespaceDeclarations}}
namespace {{this}}
{
{{/cppNamespaceDeclarations}}
bool HttpRetryManager::Tick(float DeltaTime)
{
FManager::Update();
return true;
}
HttpRetryParams::HttpRetryParams(const FRetryLimitCountSetting& InRetryLimitCountOverride /*= FRetryLimitCountSetting()*/,
const FRetryTimeoutRelativeSecondsSetting& InRetryTimeoutRelativeSecondsOverride /*= FRetryTimeoutRelativeSecondsSetting()*/,
const FRetryResponseCodes& InRetryResponseCodes /*= FRetryResponseCodes()*/,
const FRetryVerbs& InRetryVerbs /*= FRetryVerbs()*/,
const FRetryDomainsPtr& InRetryDomains /*= FRetryDomainsPtr() */)
: RetryLimitCountOverride(InRetryLimitCountOverride)
, RetryTimeoutRelativeSecondsOverride(InRetryTimeoutRelativeSecondsOverride)
, RetryResponseCodes(InRetryResponseCodes)
, RetryVerbs(InRetryVerbs)
, RetryDomains(InRetryDomains)
{
}
void Response::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
{
ResponseCode = InHttpResponseCode;
@@ -18,15 +35,6 @@ void Response::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
}
}
void Response::AsyncRetry() const
{
// Unfortunately, it is currently usafe to call ProcessRequest() directly here.
// This is because the HttpManager will remove all references to this HttpRequest in FHttpManager::Tick including the new request we just added, instead of removing just one.
// This will lead to the request's destruction and eventually a crash.
// The only solution is therefore to ensure we are taking an extra reference to the request, and that the request is added after the queue is flushed.
Async(EAsyncExecution::TaskGraph, [AddRef = FHttpRequestPtr(GetHttpRequest())](){ AddRef->ProcessRequest(); });
}
{{#cppNamespaceDeclarations}}
}
{{/cppNamespaceDeclarations}}

View File

@@ -137,6 +137,9 @@ services.AddHttpClient<YourApiClass>(httpClient =>
```csharp
using System.Collections.Generic;
using System.Diagnostics;
{{#useHttpClient}}
using System.Net.Http;
{{/useHttpClient}}
using {{packageName}}.{{apiPackage}};
using {{packageName}}.Client;
using {{packageName}}.{{modelPackage}};
@@ -174,7 +177,15 @@ namespace Example
{{/authMethods}}
{{/hasAuthMethods}}
{{#useHttpClient}}
// create instances of HttpClient, HttpClientHandler to be reused later with different Api classes
HttpClient httpClient = new HttpClient();
HttpClientHandler httpClientHandler = new HttpClientHandler();
var apiInstance = new {{classname}}(httpClient, config, httpClientHandler);
{{/useHttpClient}}
{{^useHttpClient}}
var apiInstance = new {{classname}}(config);
{{/useHttpClient}}
{{#allParams}}
{{#isPrimitiveType}}
var {{paramName}} = {{{example}}}; // {{{dataType}}} | {{{description}}}{{^required}} (optional) {{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}}

View File

@@ -22,6 +22,9 @@ Method | HTTP request | Description
```csharp
using System.Collections.Generic;
using System.Diagnostics;
{{#useHttpClient}}
using System.Net.Http;
{{/useHttpClient}}
using {{packageName}}.{{apiPackage}};
using {{packageName}}.Client;
using {{packageName}}.{{modelPackage}};
@@ -58,7 +61,15 @@ namespace Example
{{/authMethods}}
{{/hasAuthMethods}}
{{#useHttpClient}}
// create instances of HttpClient, HttpClientHandler to be reused later with different Api classes
HttpClient httpClient = new HttpClient();
HttpClientHandler httpClientHandler = new HttpClientHandler();
var apiInstance = new {{classname}}(httpClient, config, httpClientHandler);
{{/useHttpClient}}
{{^useHttpClient}}
var apiInstance = new {{classname}}(config);
{{/useHttpClient}}
{{#allParams}}
{{#isPrimitiveType}}
var {{paramName}} = {{{example}}}; // {{{dataType}}} | {{{description}}}{{^required}} (optional) {{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}}

View File

@@ -98,13 +98,13 @@ namespace {{packageName}}.Client
if (type == typeof(byte[])) // return byte array
{
return response.Content.ReadAsByteArrayAsync().Result;
return response.Content.ReadAsByteArrayAsync().GetAwaiter().GetResult();
}
// TODO: ? if (type.IsAssignableFrom(typeof(Stream)))
if (type == typeof(Stream))
{
var bytes = response.Content.ReadAsByteArrayAsync().Result;
var bytes = response.Content.ReadAsByteArrayAsync().GetAwaiter().GetResult();
if (headers != null)
{
var filePath = String.IsNullOrEmpty(_configuration.TempFolderPath)
@@ -128,18 +128,18 @@ namespace {{packageName}}.Client
if (type.Name.StartsWith("System.Nullable`1[[System.DateTime")) // return a datetime object
{
return DateTime.Parse(response.Content.ReadAsStringAsync().Result, null, System.Globalization.DateTimeStyles.RoundtripKind);
return DateTime.Parse(response.Content.ReadAsStringAsync().GetAwaiter().GetResult(), null, System.Globalization.DateTimeStyles.RoundtripKind);
}
if (type == typeof(String) || type.Name.StartsWith("System.Nullable")) // return primitive type
{
return Convert.ChangeType(response.Content.ReadAsStringAsync().Result, type);
return Convert.ChangeType(response.Content.ReadAsStringAsync().GetAwaiter().GetResult(), type);
}
// at this point, it must be a model (json)
try
{
return JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result, type, _serializerSettings);
return JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().GetAwaiter().GetResult(), type, _serializerSettings);
}
catch (Exception e)
{
@@ -191,8 +191,9 @@ namespace {{packageName}}.Client
/// <summary>
/// Initializes a new instance of the <see cref="ApiClient" />, defaulting to the global configurations' base url.
/// **IMPORTANT** This will also create an istance of HttpClient, which is less than ideal.
/// It's better to reuse the <see href="https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests#issues-with-the-original-httpclient-class-available-in-net">HttpClient and HttpClientHander</see>.
/// </summary>
[Obsolete("Constructors without HttpClient have non-trivial drawbacks and are thus considered deprecated. Check README.md for details.")]
public ApiClient() :
this({{packageName}}.Client.GlobalConfiguration.Instance.BasePath)
{
@@ -200,10 +201,11 @@ namespace {{packageName}}.Client
/// <summary>
/// Initializes a new instance of the <see cref="ApiClient" />.
/// **IMPORTANT** This will also create an istance of HttpClient, which is less than ideal.
/// It's better to reuse the <see href="https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests#issues-with-the-original-httpclient-class-available-in-net">HttpClient and HttpClientHander</see>.
/// </summary>
/// <param name="basePath">The target service's base path in URL format.</param>
/// <exception cref="ArgumentException"></exception>
[Obsolete("Constructors without HttpClient have non-trivial drawbacks and are thus considered deprecated. Check README.md for details.")]
public ApiClient(String basePath)
{
if (string.IsNullOrEmpty(basePath)) throw new ArgumentException("basePath cannot be empty");
@@ -399,10 +401,10 @@ namespace {{packageName}}.Client
partial void InterceptRequest(HttpRequestMessage req);
partial void InterceptResponse(HttpRequestMessage req, HttpResponseMessage response);
private ApiResponse<T> ToApiResponse<T>(HttpResponseMessage response, object responseData, Uri uri)
private async Task<ApiResponse<T>> ToApiResponse<T>(HttpResponseMessage response, object responseData, Uri uri)
{
T result = (T) responseData;
string rawContent = response.Content.ToString();
string rawContent = await response.Content.ReadAsStringAsync();
var transformed = new ApiResponse<T>(response.StatusCode, new Multimap<string, string>({{#caseInsensitiveResponseHeaders}}StringComparer.OrdinalIgnoreCase{{/caseInsensitiveResponseHeaders}}), result, rawContent)
{
@@ -444,7 +446,7 @@ namespace {{packageName}}.Client
private ApiResponse<T> Exec<T>(HttpRequestMessage req, IReadableConfiguration configuration)
{
return ExecAsync<T>(req, configuration).Result;
return ExecAsync<T>(req, configuration).GetAwaiter().GetResult();
}
private async Task<ApiResponse<T>> ExecAsync<T>(HttpRequestMessage req,
@@ -509,6 +511,11 @@ namespace {{packageName}}.Client
}
{{/supportsRetry}}
if (!response.IsSuccessStatusCode)
{
return await ToApiResponse<T>(response, default(T), req.RequestUri);
}
object responseData = deserializer.Deserialize<T>(response);
// if the response type is oneOf/anyOf, call FromJSON to deserialize the data
@@ -523,9 +530,7 @@ namespace {{packageName}}.Client
InterceptResponse(req, response);
var result = ToApiResponse<T>(response, responseData, req.RequestUri);
return result;
return await ToApiResponse<T>(response, responseData, req.RequestUri);
}
{{#supportsAsync}}

View File

@@ -106,20 +106,22 @@ namespace {{packageName}}.{{apiPackage}}
/// <summary>
/// Initializes a new instance of the <see cref="{{classname}}"/> class.
/// **IMPORTANT** This will also create an istance of HttpClient, which is less than ideal.
/// It's better to reuse the <see href="https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests#issues-with-the-original-httpclient-class-available-in-net">HttpClient and HttpClientHander</see>.
/// </summary>
/// <returns></returns>
[Obsolete("Constructors without HttpClient have non-trivial drawbacks and are thus considered deprecated. Check README.md for details.")]
public {{classname}}() : this((string)null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="{{classname}}"/> class.
/// **IMPORTANT** This will also create an istance of HttpClient, which is less than ideal.
/// It's better to reuse the <see href="https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests#issues-with-the-original-httpclient-class-available-in-net">HttpClient and HttpClientHander</see>.
/// </summary>
/// <param name="basePath">The target service's base path in URL format.</param>
/// <exception cref="ArgumentException"></exception>
/// <returns></returns>
[Obsolete("Constructors without HttpClient have non-trivial drawbacks and are thus considered deprecated. Check README.md for details.")]
public {{classname}}(String basePath)
{
this.Configuration = {{packageName}}.Client.Configuration.MergeConfigurations(
@@ -136,11 +138,12 @@ namespace {{packageName}}.{{apiPackage}}
/// <summary>
/// Initializes a new instance of the <see cref="{{classname}}"/> class using Configuration object.
/// **IMPORTANT** This will also create an istance of HttpClient, which is less than ideal.
/// It's better to reuse the <see href="https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests#issues-with-the-original-httpclient-class-available-in-net">HttpClient and HttpClientHander</see>.
/// </summary>
/// <param name="configuration">An instance of Configuration.</param>
/// <exception cref="ArgumentNullException"></exception>
/// <returns></returns>
[Obsolete("Constructors without HttpClient have non-trivial drawbacks and are thus considered deprecated. Check README.md for details.")]
public {{classname}}({{packageName}}.Client.Configuration configuration)
{
if (configuration == null) throw new ArgumentNullException("configuration");

View File

@@ -97,7 +97,7 @@ import {{packageName}}.infrastructure.toMultiValue
{{/hasQueryParams}}
val localVariableHeaders: MutableMap<String, String> = mutableMapOf({{#hasFormParams}}"Content-Type" to {{^consumes}}"multipart/form-data"{{/consumes}}{{#consumes.0}}"{{{mediaType}}}"{{/consumes.0}}{{/hasFormParams}})
{{#headerParams}}
{{{paramName}}}?.apply { localVariableHeaders["{{baseName}}"] = {{#isContainer}}this.joinToString(separator = collectionDelimiter("{{collectionFormat}}")){{/isContainer}}{{^isContainer}}this.toString(){{/isContainer}} }
{{{paramName}}}{{^required}}?{{/required}}.apply { localVariableHeaders["{{baseName}}"] = {{#isContainer}}this.joinToString(separator = collectionDelimiter("{{collectionFormat}}")){{/isContainer}}{{^isContainer}}this.toString(){{/isContainer}} }
{{/headerParams}}
val localVariableConfig = RequestConfig(

View File

@@ -188,12 +188,12 @@ class {{classname}} {{#parentSchema}}extends {{{parent}}}{{/parentSchema}}{{^par
*/
public function listInvalidProperties()
{
{{#parent}}
{{#parentSchema}}
$invalidProperties = parent::listInvalidProperties();
{{/parent}}
{{^parent}}
{{/parentSchema}}
{{^parentSchema}}
$invalidProperties = [];
{{/parent}}
{{/parentSchema}}
{{#vars}}
{{#required}}

View File

@@ -2,7 +2,10 @@
{{>partial_header}}
import inspect
try:
from inspect import getfullargspec
except ImportError:
from inspect import getargspec as getfullargspec
import pprint
import re # noqa: F401
import six
@@ -203,7 +206,7 @@ class {{classname}}(object):
def convert(x):
if hasattr(x, "to_dict"):
args = inspect.getargspec(x.to_dict).args
args = getfullargspec(x.to_dict).args
if len(args) == 1:
return x.to_dict()
else:

View File

@@ -18,6 +18,7 @@ import de.heikoseeberger.akkahttpjson4s.Json4sSupport
import org.json4s._
import org.json4s.jackson.JsonMethods._
import org.json4s.jackson.Serialization
import scala.collection.compat._
import scala.collection.immutable
import scala.concurrent.{ ExecutionContext, ExecutionContextExecutor, Future }
@@ -86,7 +87,7 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
private val http = Http()
val CompressionFilter: HttpMessage Boolean = (msg: HttpMessage) =>
val CompressionFilter: HttpMessage => Boolean = (msg: HttpMessage) =>
Seq(
{ _: HttpMessage => settings.compressionEnabled },
Encoder.DefaultFilter,
@@ -115,7 +116,7 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
private def headers(headers: Map[String, Any]): immutable.Seq[HttpHeader] =
headers.asFormattedParams
.map { case (name, value) => RawHeader(name, value.toString) }
.to[immutable.Seq]
.to(immutable.Seq)
private def bodyPart(name: String, value: Any): BodyPart = {
@@ -147,9 +148,9 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
case MediaTypes.`multipart/form-data` =>
Multipart.FormData(Source(params.toList.map { case (name, value) => bodyPart(name, value) }))
case MediaTypes.`application/x-www-form-urlencoded` =>
FormData(params.mapValues(_.toString))
FormData(params.view.mapValues(_.toString).toMap)
case _: MediaType => // Default : application/x-www-form-urlencoded.
FormData(params.mapValues(_.toString))
FormData(params.view.mapValues(_.toString).toMap)
}
)
}
@@ -187,7 +188,9 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
params + (keyName -> key.value)
case (params, _) => params
}.asFormattedParams
.view
.mapValues(_.toString)
.toMap
.foldRight[Query](Uri.Query.Empty) {
case ((name, value), acc) => acc.+:(name, value)
}
@@ -196,7 +199,9 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
def makeUri(r: ApiRequest[_]): Uri = {
val opPath = r.operationPath.replaceAll("\\{format\\}", "json")
val opPathWithParams = r.pathParams.asFormattedParams
.view
.mapValues(_.toString)
.toMap
.foldLeft(opPath) {
case (path, (name, value)) => path.replaceAll(s"\\{$name\\}", value)
}
@@ -213,13 +218,13 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
http
.singleRequest(request)
.map { response =>
val decoder: Coder with StreamDecoder = response.encoding match {
case HttpEncodings.gzip
Gzip
case HttpEncodings.deflate
Deflate
case HttpEncodings.identity
NoCoding
val decoder: Decoder with Decoder = response.encoding match {
case HttpEncodings.gzip =>
Coders.Gzip
case HttpEncodings.deflate =>
Coders.Deflate
case HttpEncodings.identity =>
Coders.NoCoding
case HttpEncoding(encoding) =>
throw new IllegalArgumentException(s"Unsupported encoding: $encoding")
}
@@ -247,13 +252,13 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
request
.responseForCode(response.status.intValue) match {
case Some((Manifest.Unit, state: ResponseState)) =>
Future(responseForState(state, Unit).asInstanceOf[ApiResponse[T]])
Future(responseForState(state, ()).asInstanceOf[ApiResponse[T]])
case Some((manifest, state: ResponseState)) if manifest == mf =>
implicit val m: Unmarshaller[HttpEntity, T] = unmarshaller[T](mf, serialization, formats)
Unmarshal(response.entity)
.to[T]
.recoverWith {
case e throw ApiError(response.status.intValue, s"Unable to unmarshall content to [$manifest]", Some(response.entity.toString), e)
case e => throw ApiError(response.status.intValue, s"Unable to unmarshall content to [$manifest]", Some(response.entity.toString), e)
}
.map(value => responseForState(state, value))
case None | Some(_) =>

View File

@@ -3,12 +3,12 @@ package {{invokerPackage}}
import java.util.concurrent.TimeUnit
import akka.actor.{ ExtendedActorSystem, Extension, ExtensionKey }
import akka.actor.{ActorSystem, ExtendedActorSystem, Extension, ExtensionId, ExtensionIdProvider}
import akka.http.scaladsl.model.StatusCodes.CustomStatusCode
import akka.http.scaladsl.model.headers.RawHeader
import com.typesafe.config.Config
import scala.collection.JavaConverters._
import scala.jdk.CollectionConverters._
import scala.concurrent.duration.FiniteDuration
class ApiSettings(config: Config) extends Extension {
@@ -32,4 +32,13 @@ class ApiSettings(config: Config) extends Extension {
}
}
object ApiSettings extends ExtensionKey[ApiSettings]
object ApiSettings extends ExtensionId[ApiSettings] with ExtensionIdProvider {
override def lookup = ApiSettings
override def createExtension(system: ExtendedActorSystem): ApiSettings =
new ApiSettings(system)
// needed to get the type right when used from Java
override def get(system: ActorSystem): ApiSettings = super.get(system)
}

View File

@@ -1,22 +1,26 @@
version := "{{artifactVersion}}"
name := "{{artifactId}}"
organization := "{{groupId}}"
scalaVersion := "2.12.8"
scalaVersion := "2.12.13"
crossScalaVersions := Seq(scalaVersion.value, "2.13.4")
libraryDependencies ++= Seq(
"com.typesafe" % "config" % "1.3.3",
"com.typesafe.akka" %% "akka-actor" % "2.5.21",
"com.typesafe.akka" %% "akka-stream" % "2.5.21",
"com.typesafe.akka" %% "akka-http" % "10.1.7",
"com.typesafe" % "config" % "1.4.1",
"com.typesafe.akka" %% "akka-actor" % "2.6.12",
"com.typesafe.akka" %% "akka-stream" % "2.6.12",
"com.typesafe.akka" %% "akka-http" % "10.2.3",
{{#joda}}
"joda-time" % "joda-time" % "2.10.1",
{{/joda}}
"org.json4s" %% "json4s-jackson" % "3.6.5",
"org.json4s" %% "json4s-ext" % "3.6.5",
"de.heikoseeberger" %% "akka-http-json4s" % "1.25.2",
"org.json4s" %% "json4s-jackson" % "3.6.7",
"org.json4s" %% "json4s-ext" % "3.6.7",
"de.heikoseeberger" %% "akka-http-json4s" % "1.27.0",
"org.scala-lang.modules" %% "scala-collection-compat" % "2.4.1",
// test dependencies
"org.scalatest" %% "scalatest" % "3.0.5" % "test",
"junit" % "junit" % "4.13.1" % "test"
"org.scalatest" %% "scalatest" % "3.2.3" % "test",
"org.scalatestplus" %% "junit-4-13" % "3.2.3.0" % "test"
)
resolvers ++= Seq(Resolver.mavenLocal)

View File

@@ -15,18 +15,19 @@
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<scala.version>2.12.8</scala.version>
<json4s.jackson.version>3.5.3</json4s.jackson.version>
<json4s.ext.version>3.2.11</json4s.ext.version>
<akka.version>2.5.21</akka.version>
<akka.http.version>10.1.7</akka.http.version>
<scala.version>2.12.13</scala.version>
<json4s.jackson.version>3.6.7</json4s.jackson.version>
<json4s.ext.version>3.6.7</json4s.ext.version>
<akka.version>2.6.12</akka.version>
<akka.http.version>10.2.3</akka.http.version>
{{#joda}}
<joda.time.version>2.10.1</joda.time.version>
{{/joda}}
<typesafeconfig.version>1.3.3</typesafeconfig.version>
<akka.http.json4s.version>1.25.2</akka.http.json4s.version>
<junit.version>4.13.1</junit.version>
<scala.test.version>3.0.5</scala.test.version>
<typesafeconfig.version>1.4.1</typesafeconfig.version>
<akka.http.json4s.version>1.27.0</akka.http.json4s.version>
<scala.compat.version>2.4.1</scala.compat.version>
<scala.test.version>3.2.3</scala.test.version>
<scala.test.plus.version>3.2.3.0</scala.test.plus.version>
<scala.maven.plugin.version>3.3.1</scala.maven.plugin.version>
</properties>
@@ -80,6 +81,11 @@
<artifactId>akka-http-json4s_2.12</artifactId>
<version>${akka.http.json4s.version}</version>
</dependency>
<dependency>
<groupId>org.scala-lang.modules</groupId>
<artifactId>scala-collection-compat_2.12</artifactId>
<version>${scala.compat.version}</version>
</dependency>
<!--test dependencies-->
<dependency>
@@ -89,9 +95,9 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<groupId>org.scalatestplus</groupId>
<artifactId>junit-4-13_2.12</artifactId>
<version>${scala.test.plus.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

View File

@@ -0,0 +1 @@
sbt.version=1.3.10

View File

@@ -1,6 +1,7 @@
package {{invokerPackage}}
import java.io.File
import java.nio.file.Files
import akka.annotation.ApiMayChange
import akka.http.scaladsl.model.Multipart.FormData
@@ -69,7 +70,7 @@ trait MultipartDirectives {
object MultipartDirectives extends MultipartDirectives with FileUploadDirectives {
val tempFileFromFileInfo: FileInfo => File = {
file: FileInfo => File.createTempFile(file.fileName, ".tmp")
file: FileInfo => Files.createTempFile(file.fileName, ".tmp").toFile()
}
}

View File

@@ -109,7 +109,7 @@ export function {{classname}}ToJSON(value?: {{classname}} | null): any {
{{^isPrimitiveType}}
{{#isArray}}
{{#uniqueItems}}
'{{baseName}}': {{^required}}value.{{name}} === undefined ? undefined : {{/required}}({{#isNullable}}value.{{name}} === null ? null : {{/isNullable}}Array.from((value.{{name}} as Set<any>).map({{#items}}{{datatype}}{{/items}}ToJSON))),
'{{baseName}}': {{^required}}value.{{name}} === undefined ? undefined : {{/required}}({{#isNullable}}value.{{name}} === null ? null : {{/isNullable}}Array.from(value.{{name}} as Set<any>).map({{#items}}{{datatype}}{{/items}}ToJSON)),
{{/uniqueItems}}
{{^uniqueItems}}
'{{baseName}}': {{^required}}value.{{name}} === undefined ? undefined : {{/required}}({{#isNullable}}value.{{name}} === null ? null : {{/isNullable}}(value.{{name}} as Array<any>).map({{#items}}{{datatype}}{{/items}}ToJSON)),

View File

@@ -472,7 +472,7 @@ public class ScalaAkkaClientCodegenTest {
Generator gen = generator.opts(clientOptInput);
List<File> files = gen.generate();
Assert.assertEquals(files.size(), 15);
Assert.assertEquals(files.size(), 16);
TestUtils.ensureContainsFile(files, output, "src/main/scala/hello/world/model/SomeObj.scala");
TestUtils.ensureContainsFile(files, output, "src/main/scala/hello/world/core/ApiSettings.scala");
@@ -509,7 +509,7 @@ public class ScalaAkkaClientCodegenTest {
Generator gen = generator.opts(clientOptInput);
List<File> files = gen.generate();
Assert.assertEquals(files.size(), 15);
Assert.assertEquals(files.size(), 16);
TestUtils.ensureContainsFile(files, output, "src/main/scala/hello/world/model/package/SomeObj.scala");
TestUtils.ensureContainsFile(files, output, "src/main/scala/hello/world/package/invoker/ApiSettings.scala");

View File

@@ -1,28 +1,38 @@
//overloaded main template file to add this comment
{{>licenseInfo}}
package {{invokerPackage}};
{{#threetenbp}}
import org.threeten.bp.*;
{{/threetenbp}}
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.*;
{{#joda}}
import com.fasterxml.jackson.datatype.joda.JodaModule;
{{/joda}}
{{#java8}}
import com.fasterxml.jackson.datatype.jsr310.*;
{{/java8}}
{{^java8}}
import com.fasterxml.jackson.datatype.joda.*;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
{{^threetenbp}}
import java.time.OffsetDateTime;
{{/threetenbp}}
{{/java8}}
{{#threetenbp}}
import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule;
{{/threetenbp}}
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.GenericType;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.client.filter.GZIPContentEncodingFilter;
import com.sun.jersey.api.client.filter.LoggingFilter;
import com.sun.jersey.api.client.WebResource.Builder;
import com.sun.jersey.multipart.FormDataMultiPart;
import com.sun.jersey.multipart.file.FileDataBodyPart;
import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.Response.Status.Family;
import javax.ws.rs.core.MediaType;
@@ -31,7 +41,9 @@ import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Date;
import java.util.TimeZone;
@@ -44,14 +56,51 @@ import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import {{invokerPackage}}.auth.Authentication;
{{#hasHttpBasicMethods}}
import {{invokerPackage}}.auth.HttpBasicAuth;
{{/hasHttpBasicMethods}}
{{#hasHttpBearerMethods}}
import {{invokerPackage}}.auth.HttpBearerAuth;
{{/hasHttpBearerMethods}}
{{#hasApiKeyMethods}}
import {{invokerPackage}}.auth.ApiKeyAuth;
{{/hasApiKeyMethods}}
{{#hasOAuthMethods}}
import {{invokerPackage}}.auth.OAuth;
{{/hasOAuthMethods}}
{{>generatedAnnotation}}
public class ApiClient {
public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
private Map<String, String> defaultHeaderMap = new HashMap<String, String>();
private String basePath = "{{basePath}}";
private Map<String, String> defaultCookieMap = new HashMap<String, String>();
private String basePath = "{{{basePath}}}";
protected List<ServerConfiguration> servers = new ArrayList<ServerConfiguration>({{#servers}}{{#-first}}Arrays.asList(
{{/-first}} new ServerConfiguration(
"{{{url}}}",
"{{{description}}}{{^description}}No description provided{{/description}}",
new HashMap<String, ServerVariable>(){{#variables}}{{#-first}} {{
{{/-first}} put("{{{name}}}", new ServerVariable(
"{{{description}}}{{^description}}No description provided{{/description}}",
"{{{defaultValue}}}",
new HashSet<String>(
{{#enumValues}}
{{#-first}}
Arrays.asList(
{{/-first}}
"{{{.}}}"{{^-last}},{{/-last}}
{{#-last}}
)
{{/-last}}
{{/enumValues}}
)
));
{{#-last}}
}}{{/-last}}{{/variables}}
){{^-last}},{{/-last}}
{{#-last}}
){{/-last}}{{/servers}});
protected Integer serverIndex = 0;
protected Map<String, String> serverVariables = null;
private boolean debugging = false;
private int connectionTimeout = 0;
@@ -69,15 +118,23 @@ public class ApiClient {
objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
{{#joda}}
objectMapper.registerModule(new JodaModule());
{{/joda}}
{{#java8}}
objectMapper.registerModule(new JavaTimeModule());
{{/java8}}
{{^java8}}
objectMapper.registerModule(new JodaModule());
{{/java8}}
{{#threetenbp}}
ThreeTenModule module = new ThreeTenModule();
module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT);
module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME);
module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME);
objectMapper.registerModule(module);
{{/threetenbp}}
objectMapper.setDateFormat(ApiClient.buildDefaultDateFormat());
dateFormat = ApiClient.buildDefaultDateFormat();
@@ -86,8 +143,9 @@ public class ApiClient {
setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}");
// Setup authentications (key: authentication name, value: authentication).
authentications = new HashMap<String, Authentication>();{{#authMethods}}{{#isBasic}}
authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}}
authentications = new HashMap<String, 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}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}}
authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}}
// Prevent the authentications from being modified.
@@ -112,6 +170,7 @@ public class ApiClient {
DefaultClientConfig conf = new DefaultClientConfig();
conf.getSingletons().add(jsonProvider);
Client client = Client.create(conf);
client.addFilter(new GZIPContentEncodingFilter({{#useGzipFeature}}true{{/useGzipFeature}}{{^useGzipFeature}}false{{/useGzipFeature}}));
if (debugging) {
client.addFilter(new LoggingFilter());
}
@@ -156,6 +215,33 @@ public class ApiClient {
return this;
}
public List<ServerConfiguration> getServers() {
return servers;
}
public ApiClient setServers(List<ServerConfiguration> servers) {
this.servers = servers;
return this;
}
public Integer getServerIndex() {
return serverIndex;
}
public ApiClient setServerIndex(Integer serverIndex) {
this.serverIndex = serverIndex;
return this;
}
public Map<String, String> getServerVariables() {
return serverVariables;
}
public ApiClient setServerVariables(Map<String, String> serverVariables) {
this.serverVariables = serverVariables;
return this;
}
/**
* Gets the status code of the previous request
* @return Status code
@@ -190,6 +276,24 @@ public class ApiClient {
return authentications.get(authName);
}
{{#hasHttpBearerMethods}}
/**
* Helper method to set access token for the first Bearer authentication.
* @param bearerToken Bearer token
*/
public void setBearerToken(String bearerToken) {
for (Authentication auth : authentications.values()) {
if (auth instanceof HttpBearerAuth) {
((HttpBearerAuth) auth).setBearerToken(bearerToken);
return;
}
}
throw new RuntimeException("No Bearer authentication configured!");
}
{{/hasHttpBearerMethods}}
{{#hasHttpBasicMethods}}
/**
* Helper method to set username for the first HTTP basic authentication.
* @param username Username
@@ -218,9 +322,12 @@ public class ApiClient {
throw new RuntimeException("No HTTP basic authentication configured!");
}
{{/hasHttpBasicMethods}}
{{#hasApiKeyMethods}}
/**
* Helper method to set API key value for the first API key authentication.
* @param apiKey API key
* @param apiKey the API key
*/
public void setApiKey(String apiKey) {
for (Authentication auth : authentications.values()) {
@@ -246,6 +353,9 @@ public class ApiClient {
throw new RuntimeException("No API key authentication configured!");
}
{{/hasApiKeyMethods}}
{{#hasOAuthMethods}}
/**
* Helper method to set access token for the first OAuth2 authentication.
* @param accessToken Access token
@@ -260,6 +370,8 @@ public class ApiClient {
throw new RuntimeException("No OAuth2 authentication configured!");
}
{{/hasOAuthMethods}}
/**
* Set the User-Agent header's value (by adding to the default header map).
* @param userAgent User agent
@@ -282,6 +394,18 @@ public class ApiClient {
return this;
}
/**
* Add a default cookie.
*
* @param key The cookie's key
* @param value The cookie's value
* @return API client
*/
public ApiClient addDefaultCookie(String key, String value) {
defaultCookieMap.put(key, value);
return this;
}
/**
* Check that whether debugging is enabled for this API client.
* @return True if debugging is on
@@ -378,7 +502,9 @@ public class ApiClient {
return "";
} else if (param instanceof Date) {
return formatDate((Date) param);
} else if (param instanceof Collection) {
} {{#jsr310}}else if (param instanceof OffsetDateTime) {
return formatOffsetDateTime((OffsetDateTime) param);
} {{/jsr310}}else if (param instanceof Collection) {
StringBuilder b = new StringBuilder();
for(Object o : (Collection<?>)param) {
if(b.length() > 0) {
@@ -392,62 +518,71 @@ public class ApiClient {
}
}
/*
* Format to {@code Pair} objects.
* @param collectionFormat Collection format
* @param name Name
* @param value Value
* @return List of pair
/**
* Formats the specified query parameter to a list containing a single {@code Pair} object.
*
* Note that {@code value} must not be a collection.
*
* @param name The name of the parameter.
* @param value The value of the parameter.
* @return A list containing a single {@code Pair} object.
*/
public List<Pair> parameterToPairs(String collectionFormat, String name, Object value){
public List<Pair> parameterToPair(String name, Object value) {
List<Pair> params = new ArrayList<Pair>();
// preconditions
if (name == null || name.isEmpty() || value == null) return params;
if (name == null || name.isEmpty() || value == null || value instanceof Collection) return params;
Collection<?> valueCollection;
if (value instanceof Collection<?>) {
valueCollection = (Collection<?>) value;
} else {
params.add(new Pair(name, parameterToString(value)));
params.add(new Pair(name, parameterToString(value)));
return params;
}
/**
* Formats the specified collection query parameters to a list of {@code Pair} objects.
*
* Note that the values of each of the returned Pair objects are percent-encoded.
*
* @param collectionFormat The collection format of the parameter.
* @param name The name of the parameter.
* @param value The value of the parameter.
* @return A list of {@code Pair} objects.
*/
public List<Pair> parameterToPairs(String collectionFormat, String name, Collection value) {
List<Pair> params = new ArrayList<Pair>();
// preconditions
if (name == null || name.isEmpty() || value == null) {
return params;
}
if (valueCollection.isEmpty()){
return params;
}
// get the collection format
String format = (collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat); // default: csv
// create the params based on the collection format
if ("multi".equals(format)) {
for (Object item : valueCollection) {
params.add(new Pair(name, parameterToString(item)));
if ("multi".equals(collectionFormat)) {
for (Object item : value) {
params.add(new Pair(name, escapeString(parameterToString(item))));
}
return params;
}
// collectionFormat is assumed to be "csv" by default
String delimiter = ",";
if ("csv".equals(format)) {
delimiter = ",";
} else if ("ssv".equals(format)) {
delimiter = " ";
} else if ("tsv".equals(format)) {
delimiter = "\t";
} else if ("pipes".equals(format)) {
delimiter = "|";
// escape all delimiters except commas, which are URI reserved
// characters
if ("ssv".equals(collectionFormat)) {
delimiter = escapeString(" ");
} else if ("tsv".equals(collectionFormat)) {
delimiter = escapeString("\t");
} else if ("pipes".equals(collectionFormat)) {
delimiter = escapeString("|");
}
StringBuilder sb = new StringBuilder() ;
for (Object item : valueCollection) {
for (Object item : value) {
sb.append(delimiter);
sb.append(parameterToString(item));
sb.append(escapeString(parameterToString(item)));
}
params.add(new Pair(name, sb.substring(1)));
params.add(new Pair(name, sb.substring(delimiter.length())));
return params;
}
@@ -458,11 +593,13 @@ public class ApiClient {
* application/json
* application/json; charset=UTF8
* APPLICATION/JSON
* application/vnd.company+json
* @param mime MIME
* @return True if MIME type is boolean
*/
public boolean isJsonMime(String mime) {
return mime != null && mime.matches("(?i)application\\/json(;.*)?");
String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$";
return mime != null && (mime.matches(jsonMime) || mime.equals("*/*"));
}
/**
@@ -493,10 +630,10 @@ public class ApiClient {
*
* @param contentTypes The Content-Type array to select from
* @return The Content-Type header to use. If the given array is empty,
* JSON will be used.
* or matches "any", JSON will be used.
*/
public String selectHeaderContentType(String[] contentTypes) {
if (contentTypes.length == 0) {
if (contentTypes.length == 0 || contentTypes[0].equals("*/*")) {
return "application/json";
}
for (String contentType : contentTypes) {
@@ -561,11 +698,24 @@ public class ApiClient {
*
* @param path The sub path
* @param queryParams The query parameters
* @param collectionQueryParams The collection query parameters
* @return The full URL
*/
private String buildUrl(String path, List<Pair> queryParams) {
private String buildUrl(String path, List<Pair> queryParams, List<Pair> collectionQueryParams) {
String baseURL;
if (serverIndex != null) {
if (serverIndex < 0 || serverIndex >= servers.size()) {
throw new ArrayIndexOutOfBoundsException(String.format(
"Invalid index %d when selecting the host settings. Must be less than %d", serverIndex, servers.size()
));
}
baseURL = servers.get(serverIndex).URL(serverVariables);
} else {
baseURL = basePath;
}
final StringBuilder url = new StringBuilder();
url.append(basePath).append(path);
url.append(baseURL).append(path);
if (queryParams != null && !queryParams.isEmpty()) {
// support (constant) query string in `path`, e.g. "/posts?draft=1"
@@ -584,17 +734,34 @@ public class ApiClient {
}
}
if (collectionQueryParams != null && !collectionQueryParams.isEmpty()) {
String prefix = url.toString().contains("?") ? "&" : "?";
for (Pair param : collectionQueryParams) {
if (param.getValue() != null) {
if (prefix != null) {
url.append(prefix);
prefix = null;
} else {
url.append("&");
}
String value = parameterToString(param.getValue());
// collection query parameter value already escaped as part of parameterToPairs
url.append(escapeString(param.getName())).append("=").append(value);
}
}
}
return url.toString();
}
private ClientResponse getAPIResponse(String path, String method, List<Pair> queryParams, Object body, Map<String, String> headerParams, Map<String, Object> formParams, String accept, String contentType, String[] authNames) throws ApiException {
private ClientResponse getAPIResponse(String path, String method, List<Pair> queryParams, List<Pair> collectionQueryParams, Object body, Map<String, String> headerParams, Map<String, String> cookieParams, Map<String, Object> formParams, String accept, String contentType, String[] authNames) throws ApiException {
if (body != null && !formParams.isEmpty()) {
throw new ApiException(500, "Cannot have body and form params");
}
updateParamsForAuth(authNames, queryParams, headerParams);
updateParamsForAuth(authNames, queryParams, headerParams, cookieParams);
final String url = buildUrl(path, queryParams);
final String url = buildUrl(path, queryParams, collectionQueryParams);
Builder builder;
if (accept == null) {
builder = httpClient.resource(url).getRequestBuilder();
@@ -602,12 +769,21 @@ public class ApiClient {
builder = httpClient.resource(url).accept(accept);
}
for (String key : headerParams.keySet()) {
builder = builder.header(key, headerParams.get(key));
for (Entry<String, String> keyValue : headerParams.entrySet()) {
builder = builder.header(keyValue.getKey(), keyValue.getValue());
}
for (String key : defaultHeaderMap.keySet()) {
if (!headerParams.containsKey(key)) {
builder = builder.header(key, defaultHeaderMap.get(key));
for (Map.Entry<String,String> keyValue : defaultHeaderMap.entrySet()) {
if (!headerParams.containsKey(keyValue.getKey())) {
builder = builder.header(keyValue.getKey(), keyValue.getValue());
}
}
for (Entry<String, String> keyValue : cookieParams.entrySet()) {
builder = builder.cookie(new Cookie(keyValue.getKey(), keyValue.getValue()));
}
for (Map.Entry<String,String> keyValue : defaultCookieMap.entrySet()) {
if (!cookieParams.containsKey(keyValue.getKey())) {
builder = builder.cookie(new Cookie(keyValue.getKey(), keyValue.getValue()));
}
}
@@ -623,8 +799,9 @@ public class ApiClient {
response = builder.type(contentType).delete(ClientResponse.class, serialize(body, contentType, formParams));
} else if ("PATCH".equals(method)) {
response = builder.type(contentType).header("X-HTTP-Method-Override", "PATCH").post(ClientResponse.class, serialize(body, contentType, formParams));
}
else {
} else if ("HEAD".equals(method)) {
response = builder.head();
} else {
throw new ApiException(500, "unknown method type " + method);
}
return response;
@@ -637,8 +814,10 @@ public class ApiClient {
* @param path The sub-path of the HTTP URL
* @param method The request method, one of "GET", "POST", "PUT", and "DELETE"
* @param queryParams The query parameters
* @param collectionQueryParams The collection query parameters
* @param body The request body object - if it is not binary, otherwise null
* @param headerParams The header parameters
* @param cookieParams The cookie parameters
* @param formParams The form parameters
* @param accept The request's Accept header
* @param contentType The request's Content-Type header
@@ -647,9 +826,9 @@ public class ApiClient {
* @return The response body in type of string
* @throws ApiException API exception
*/
public <T> T invokeAPI(String path, String method, List<Pair> queryParams, Object body, Map<String, String> headerParams, Map<String, Object> formParams, String accept, String contentType, String[] authNames, GenericType<T> returnType) throws ApiException {
public <T> T invokeAPI(String path, String method, List<Pair> queryParams, List<Pair> collectionQueryParams, Object body, Map<String, String> headerParams, Map<String, String> cookieParams, Map<String, Object> formParams, String accept, String contentType, String[] authNames, GenericType<T> returnType) throws ApiException {
ClientResponse response = getAPIResponse(path, method, queryParams, body, headerParams, formParams, accept, contentType, authNames);
ClientResponse response = getAPIResponse(path, method, queryParams, collectionQueryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames);
statusCode = response.getStatusInfo().getStatusCode();
responseHeaders = response.getHeaders();
@@ -686,12 +865,13 @@ public class ApiClient {
* @param authNames The authentications to apply
* @param queryParams Query parameters
* @param headerParams Header parameters
* @param cookieParams Cookie parameters
*/
private void updateParamsForAuth(String[] authNames, List<Pair> queryParams, Map<String, String> headerParams) {
private void updateParamsForAuth(String[] authNames, List<Pair> queryParams, Map<String, String> headerParams, Map<String, String> cookieParams) {
for (String authName : authNames) {
Authentication auth = authentications.get(authName);
if (auth == null) throw new RuntimeException("Authentication undefined: " + authName);
auth.applyToParams(queryParams, headerParams);
auth.applyToParams(queryParams, headerParams, cookieParams);
}
}

View File

@@ -1,18 +1,32 @@
//overloaded template file within library folder to add this comment
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.*;
{{/java8}}
{{^java8}}
import com.fasterxml.jackson.datatype.joda.*;
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}}
@@ -22,7 +36,9 @@ public class JSON implements ContextResolver<ObjectMapper> {
public JSON() {
mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
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);
@@ -30,9 +46,20 @@ public class JSON implements ContextResolver<ObjectMapper> {
{{#java8}}
mapper.registerModule(new JavaTimeModule());
{{/java8}}
{{^java8}}
{{#joda}}
mapper.registerModule(new JodaModule());
{{/java8}}
{{/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}}
}
/**
@@ -47,4 +74,204 @@ public class JSON implements ContextResolver<ObjectMapper> {
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<Class<?>>());
}
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<String, Class<?>> discriminatorMappings;
// Constructs a new class discriminator.
ClassDiscriminatorMapping(Class<?> cls, String propertyName, Map<String, Class<?>> mappings) {
modelClass = cls;
discriminatorName = propertyName;
discriminatorMappings = new HashMap<String, Class<?>>();
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<Class<?>> 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<Class<?>> 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<String, GenericType> 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<Class<?>, ClassDiscriminatorMapping> modelDiscriminators = new HashMap<Class<?>, ClassDiscriminatorMapping>();
/**
* A map of oneOf/anyOf descendants for each model class.
*/
private static Map<Class<?>, Map<String, GenericType>> modelDescendants = new HashMap<Class<?>, Map<String, GenericType>>();
/**
* 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<String, Class<?>> 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<String, GenericType> 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;
}
}

View File

@@ -1,9 +1,8 @@
//overloaded template file within library folder to add this comment
package {{package}};
import {{invokerPackage}}.ApiException;
import {{invokerPackage}}.ApiClient;
import {{invokerPackage}}.ApiResponse;
import {{invokerPackage}}.Configuration;
import {{invokerPackage}}.Pair;
@@ -17,8 +16,8 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
{{/fullJavaUtil}}
{{/fullJavaUtil}}
{{>generatedAnnotation}}
{{#operations}}
public class {{classname}} {
@@ -32,15 +31,26 @@ public class {{classname}} {
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}}
@@ -51,8 +61,61 @@ public class {{classname}} {
* @return {{returnType}}
{{/returnType}}
* @throws ApiException if fails to make API call
{{#responses.0}}
* @http.response.details
<table summary="Response Details" border="1">
<tr><td> Status Code </td><td> Description </td><td> Response Headers </td></tr>
{{#responses}}
<tr><td> {{code}} </td><td> {{message}} </td><td> {{#headers}} * {{baseName}} - {{description}} <br> {{/headers}}{{^headers.0}} - {{/headers.0}} </td></tr>
{{/responses}}
</table>
{{/responses.0}}
{{#isDeprecated}}
* @deprecated
{{/isDeprecated}}
{{#externalDocs}}
* {{description}}
* @see <a href="{{url}}">{{summary}} Documentation</a>
{{/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&lt;{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}&gt;
* @throws ApiException if fails to make API call
{{#responses.0}}
* @http.response.details
<table summary="Response Details" border="1">
<tr><td> Status Code </td><td> Description </td><td> Response Headers </td></tr>
{{#responses}}
<tr><td> {{code}} </td><td> {{message}} </td><td> {{#headers}} * {{baseName}} - {{description}} <br> {{/headers}}{{^headers.0}} - {{/headers.0}} </td></tr>
{{/responses}}
</table>
{{/responses.0}}
{{#isDeprecated}}
* @deprecated
{{/isDeprecated}}
{{#externalDocs}}
* {{description}}
* @see <a href="{{url}}">{{summary}} Documentation</a>
{{/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
@@ -61,12 +124,13 @@ public class {{classname}} {
}
{{/required}}{{/allParams}}
// create path and map variables
String localVarPath = "{{{path}}}".replaceAll("\\{format\\}","json"){{#pathParams}}
String localVarPath = "{{{path}}}"{{#pathParams}}
.replaceAll("\\{" + "{{baseName}}" + "\\}", apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}};
// query params
{{javaUtilPrefix}}List<Pair> localVarQueryParams = new {{javaUtilPrefix}}ArrayList<Pair>();
{{javaUtilPrefix}}Map<String, String> localVarHeaderParams = new {{javaUtilPrefix}}HashMap<String, String>();
{{javaUtilPrefix}}Map<String, String> localVarCookieParams = new {{javaUtilPrefix}}HashMap<String, String>();
{{javaUtilPrefix}}Map<String, Object> localVarFormParams = new {{javaUtilPrefix}}HashMap<String, Object>();
{{#queryParams}}
@@ -77,6 +141,10 @@ public class {{classname}} {
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}}
@@ -95,11 +163,100 @@ public class {{classname}} {
{{#returnType}}
GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {};
return apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType);
{{/returnType}}{{^returnType}}
apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, null);
{{/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
<table summary="Response Details" border="1">
<tr><td> Status Code </td><td> Description </td><td> Response Headers </td></tr>
{{#responses}}
<tr><td> {{code}} </td><td> {{message}} </td><td> {{#headers}} * {{baseName}} - {{description}} <br> {{/headers}}{{^headers.0}} - {{/headers.0}} </td></tr>
{{/responses}}
</table>
{{/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&lt;{{#returnType}}{{.}}{{/returnType}}{{^returnType}}Void{{/returnType}}&gt;
* @throws ApiException if fails to make API call
{{#responses.0}}
* @http.response.details
<table summary="Response Details" border="1">
<tr><td> Status Code </td><td> Description </td><td> Response Headers </td></tr>
{{#responses}}
<tr><td> {{code}} </td><td> {{message}} </td><td> {{#headers}} * {{baseName}} - {{description}} <br> {{/headers}}{{^headers.0}} - {{/headers.0}} </td></tr>
{{/responses}}
</table>
{{/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 <a href="{{url}}">{{summary}} Documentation</a>{{/externalDocs}}
*/
{{#isDeprecated}}
@Deprecated
{{/isDeprecated}}
public API{{operationId}}Request {{operationId}}({{#pathParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}) throws ApiException {
return new API{{operationId}}Request({{#pathParams}}{{paramName}}{{^-last}}, {{/-last}}{{/pathParams}});
}
{{/vendorExtensions.x-group-parameters}}
{{/operation}}
}
{{/operations}}

View File

@@ -1,5 +1,3 @@
//overloaded template file within library folder to add this comment
apply plugin: 'idea'
apply plugin: 'eclipse'
@@ -8,11 +6,12 @@ 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'
classpath 'com.android.tools.build:gradle:2.3.+'
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
}
}
@@ -27,18 +26,13 @@ if(hasProperty('target') && target == 'android') {
apply plugin: 'com.github.dcendents.android-maven'
android {
compileSdkVersion 23
buildToolsVersion '23.0.2'
compileSdkVersion 25
buildToolsVersion '25.0.2'
defaultConfig {
minSdkVersion 14
targetSdkVersion 23
targetSdkVersion 25
}
compileOptions {
{{#supportJava6}}
sourceCompatibility JavaVersion.VERSION_1_6
targetCompatibility JavaVersion.VERSION_1_6
{{/supportJava6}}
{{^supportJava6}}
{{#java8}}
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
@@ -47,7 +41,6 @@ if(hasProperty('target') && target == 'android') {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
{{/java8}}
{{/supportJava6}}
}
// Rename the aar correctly
@@ -91,11 +84,6 @@ if(hasProperty('target') && target == 'android') {
apply plugin: 'java'
apply plugin: 'maven'
{{#supportJava6}}
sourceCompatibility = JavaVersion.VERSION_1_6
targetCompatibility = JavaVersion.VERSION_1_6
{{/supportJava6}}
{{^supportJava6}}
{{#java8}}
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
@@ -104,7 +92,6 @@ if(hasProperty('target') && target == 'android') {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
{{/java8}}
{{/supportJava6}}
install {
repositories.mavenInstaller {
@@ -119,38 +106,61 @@ if(hasProperty('target') && target == 'android') {
}
ext {
swagger_annotations_version = "1.5.8"
jackson_version = "2.7.5"
jersey_version = "2.22.2"
{{^java8}}
jodatime_version = "2.9.4"
{{/java8}}
{{#supportJava6}}
commons_io_version=2.5
commons_lang3_version=3.5
{{/supportJava6}}
junit_version = "4.13"
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_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.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version"
implementation "joda-time:joda-time:$jodatime_version"
implementation "com.brsanthu:migbase64:2.2"
{{/java8}}
{{#supportJava6}}
implementation "commons-io:commons-io:$commons_io_version"
implementation "org.apache.commons:commons-lang3:$commons_lang3_version"
{{/supportJava6}}
implementation 'javax.annotation:javax.annotation-api:1.3.2'
testImplementation "junit:junit:$junit_version"
}
javadoc {
options.tags = [ "http.response.details:a:Http Response Details" ]
}

View File

@@ -1,5 +1,3 @@
//overloaded template file within library folder to add this comment
lazy val root = (project in file(".")).
settings(
organization := "{{groupId}}",
@@ -11,26 +9,35 @@ lazy val root = (project in file(".")).
publishArtifact in (Compile, packageDoc) := false,
resolvers += Resolver.mavenLocal,
libraryDependencies ++= Seq(
"io.swagger" % "swagger-annotations" % "1.5.8",
"org.glassfish.jersey.core" % "jersey-client" % "2.22.2",
"org.glassfish.jersey.media" % "jersey-media-multipart" % "2.22.2",
"org.glassfish.jersey.media" % "jersey-media-json-jackson" % "2.22.2",
"com.fasterxml.jackson.core" % "jackson-core" % "2.7.5",
"com.fasterxml.jackson.core" % "jackson-annotations" % "2.7.5",
"com.fasterxml.jackson.core" % "jackson-databind" % "2.7.5",
"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.7.5",
{{/java8}}
{{^java8}}
"com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.7.5",
"joda-time" % "joda-time" % "2.9.4",
"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}}
{{#supportJava6}}
"org.apache.commons" % "commons-lang3" % "3.5",
"commons-io" % "commons-io" % "2.5",
{{/supportJava6}}
"junit" % "junit" % "4.13" % "test",
"javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile",
"junit" % "junit" % "4.13.1" % "test",
"com.novocode" % "junit-interface" % "0.10" % "test"
)
)

View File

@@ -1,5 +1,3 @@
//overloaded template file within library folder to add this comment
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
@@ -15,6 +13,13 @@
<developerConnection>{{scmDeveloperConnection}}</developerConnection>
<url>{{scmUrl}}</url>
</scm>
{{#parentOverridden}}
<parent>
<groupId>{{{parentGroupId}}}</groupId>
<artifactId>{{{parentArtifactId}}}</artifactId>
<version>{{{parentVersion}}}</version>
</parent>
{{/parentOverridden}}
<licenses>
<license>
@@ -58,7 +63,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12</version>
<version>3.0.0-M4</version>
<configuration>
<systemProperties>
<property>
@@ -68,7 +73,8 @@
</systemProperties>
<argLine>-Xms512m -Xmx1500m</argLine>
<parallel>methods</parallel>
<forkMode>pertest</forkMode>
<threadCount>10</threadCount>
<trimStackTrace>false</trimStackTrace>
</configuration>
</plugin>
<plugin>
@@ -106,6 +112,7 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.10</version>
<executions>
<execution>
<id>add_sources</id>
@@ -115,8 +122,7 @@
</goals>
<configuration>
<sources>
<source>
src/main/java</source>
<source>src/main/java</source>
</sources>
</configuration>
</execution>
@@ -128,8 +134,7 @@
</goals>
<configuration>
<sources>
<source>
src/test/java</source>
<source>src/test/java</source>
</sources>
</configuration>
</execution>
@@ -138,7 +143,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<version>3.8.1</version>
<configuration>
{{#java8}}
<source>1.8</source>
@@ -148,15 +153,19 @@
<source>1.7</source>
<target>1.7</target>
{{/java8}}
<fork>true</fork>
<meminitial>128m</meminitial>
<maxmem>512m</maxmem>
<compilerArgs>
<arg>-Xlint:all</arg>
<arg>-J-Xss4m</arg><!-- Compiling the generated JSON.java file may require larger stack size. -->
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<doclint>none</doclint>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
@@ -165,6 +174,22 @@
</goals>
</execution>
</executions>
<configuration>
<doclint>none</doclint>
{{#java8}}
<source>1.8</source>
{{/java8}}
{{^java8}}
<source>1.7</source>
{{/java8}}
<tags>
<tag>
<name>http.response.details</name>
<placement>a</placement>
<head>Http Response Details:</head>
</tag>
</tags>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -210,7 +235,14 @@
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger-core-version}</version>
<version>${swagger-annotations-version}</version>
</dependency>
<!-- @Nullable annotation -->
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
</dependency>
<!-- HTTP client: jersey-client -->
@@ -219,6 +251,11 @@
<artifactId>jersey-client</artifactId>
<version>${jersey-version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>${jersey-version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
@@ -244,49 +281,86 @@
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-databind-version}</version>
</dependency>
{{#openApiNullable}}
<dependency>
<groupId>org.openapitools</groupId>
<artifactId>jackson-databind-nullable</artifactId>
<version>${jackson-databind-nullable-version}</version>
</dependency>
{{/openApiNullable}}
{{#withXml}}
<!-- XML processing: JAXB -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-jaxb</artifactId>
<version>${jersey-version}</version>
</dependency>
{{/withXml}}
{{#joda}}
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
<version>${jackson-version}</version>
</dependency>
{{/joda}}
{{#java8}}
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson-version}</version>
</dependency>
{{/java8}}
{{#threetenbp}}
<dependency>
<groupId>com.github.joschi.jackson</groupId>
<artifactId>jackson-datatype-threetenbp</artifactId>
<version>${threetenbp-version}</version>
</dependency>
{{/threetenbp}}
{{^java8}}
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>${jodatime-version}</version>
</dependency>
<!-- Base64 encoding that works in both JVM and Android -->
<dependency>
<groupId>com.brsanthu</groupId>
<artifactId>migbase64</artifactId>
<version>2.2</version>
</dependency>
<!-- Base64 encoding that works in both JVM and Android -->
<dependency>
<groupId>com.brsanthu</groupId>
<artifactId>migbase64</artifactId>
<version>2.2</version>
</dependency>
{{/java8}}
{{#supportJava6}}
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons_lang3_version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons_io_version}</version>
</dependency>
{{/supportJava6}}
{{#hasHttpSignatureMethods}}
<dependency>
<groupId>org.tomitribe</groupId>
<artifactId>tomitribe-http-signatures</artifactId>
<version>${http-signature-version}</version>
</dependency>
{{/hasHttpSignatureMethods}}
{{#hasOAuthMethods}}
<dependency>
<groupId>com.github.scribejava</groupId>
<artifactId>scribejava-apis</artifactId>
<version>${scribejava-apis-version}</version>
</dependency>
{{/hasOAuthMethods}}
{{#useBeanValidation}}
<!-- Bean Validation API support -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
<scope>provided</scope>
</dependency>
{{/useBeanValidation}}
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>${javax-annotation-version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.connectors</groupId>
<artifactId>jersey-apache-connector</artifactId>
<version>${jersey-version}</version>
</dependency>
<!-- test dependencies -->
<dependency>
<groupId>junit</groupId>
@@ -297,17 +371,21 @@
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<swagger-core-version>1.5.18</swagger-core-version>
<jersey-version>2.22.2</jersey-version>
<jackson-version>2.8.9</jackson-version>
{{^java8}}
<jodatime-version>2.9.4</jodatime-version>
{{/java8}}
{{#supportJava6}}
<commons_io_version>2.5</commons_io_version>
<commons_lang3_version>3.5</commons_lang3_version>
{{/supportJava6}}
<maven-plugin-version>1.0.0</maven-plugin-version>
<junit-version>4.13</junit-version>
<swagger-annotations-version>1.6.1</swagger-annotations-version>
<jersey-version>2.30.1</jersey-version>
<jackson-version>2.10.5</jackson-version>
<jackson-databind-version>2.10.5.1</jackson-databind-version>
<jackson-databind-nullable-version>0.2.1</jackson-databind-nullable-version>
{{#threetenbp}}
<threetenbp-version>2.9.10</threetenbp-version>
{{/threetenbp}}
<javax-annotation-version>1.3.2</javax-annotation-version>
<junit-version>4.13.1</junit-version>
{{#hasHttpSignatureMethods}}
<http-signature-version>1.5</http-signature-version>
{{/hasHttpSignatureMethods}}
{{#hasOAuthMethods}}
<scribejava-apis-version>6.9.0</scribejava-apis-version>
{{/hasOAuthMethods}}
</properties>
</project>

View File

@@ -1,31 +1,54 @@
//overloaded main template file to add this comment
{{>licenseInfo}}
package {{package}};
{{^supportJava6}}
{{#useReflectionEqualsHashCode}}
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
{{/useReflectionEqualsHashCode}}
import java.util.Objects;
{{/supportJava6}}
{{#supportJava6}}
import org.apache.commons.lang3.ObjectUtils;
{{/supportJava6}}
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}}{{>pojo}}{{/isEnum}}
{{#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}}

20
new.sh
View File

@@ -178,7 +178,7 @@ public class ${lang_classname} extends DefaultCodegen implements CodegenConfig {
outputFolder = "generated-code" + File.separator + "${gen_name_camel}";
modelTemplateFiles.put("model.mustache", ".zz");
apiTemplateFiles.put("api.mustache", ".zz");
embeddedTemplateDir = templateDir = "${gen_name_camel}-${gen_type}";
embeddedTemplateDir = templateDir = "${gen_name_camel}";
apiPackage = "Apis";
modelPackage = "Models";
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
@@ -191,17 +191,17 @@ EOF
echo -e "\norg.openapitools.codegen.languages.${lang_classname}" >> "${root}/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig"
# Step 3: Create resource files
mkdir -p "${root}/modules/openapi-generator/src/main/resources/${gen_name_camel}-${gen_type}"
echo "Creating modules/openapi-generator/src/main/resources/${gen_name_camel}-${gen_type}/README.mustache" && \
touch "${root}/modules/openapi-generator/src/main/resources/${gen_name_camel}-${gen_type}/README.mustache"
echo "Creating modules/openapi-generator/src/main/resources/${gen_name_camel}-${gen_type}/model.mustache" && \
touch "${root}/modules/openapi-generator/src/main/resources/${gen_name_camel}-${gen_type}/model.mustache"
echo "Creating modules/openapi-generator/src/main/resources/${gen_name_camel}-${gen_type}/api.mustache" && \
touch "${root}/modules/openapi-generator/src/main/resources/${gen_name_camel}-${gen_type}/api.mustache"
mkdir -p "${root}/modules/openapi-generator/src/main/resources/${gen_name_camel}"
echo "Creating modules/openapi-generator/src/main/resources/${gen_name_camel}/README.mustache" && \
touch "${root}/modules/openapi-generator/src/main/resources/${gen_name_camel}/README.mustache"
echo "Creating modules/openapi-generator/src/main/resources/${gen_name_camel}/model.mustache" && \
touch "${root}/modules/openapi-generator/src/main/resources/${gen_name_camel}/model.mustache"
echo "Creating modules/openapi-generator/src/main/resources/${gen_name_camel}/api.mustache" && \
touch "${root}/modules/openapi-generator/src/main/resources/${gen_name_camel}/api.mustache"
# Step 4: Create generation config scripts
echo "Creating bin/configs/${gen_name_camel}-${gen_type}-petstore-new.yaml"
cat > "${root}/bin/configs/${gen_name_camel}-${gen_type}-petstore-new.yaml"<<EOF
echo "Creating bin/configs/${gen_name_camel}-petstore-new.yaml"
cat > "${root}/bin/configs/${gen_name_camel}-petstore-new.yaml"<<EOF
generatorName: ${gen_name_camel}
outputDir: samples/${gen_type}/petstore/${gen_name_camel_path}
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml

View File

@@ -10,7 +10,7 @@
<packaging>pom</packaging>
<name>openapi-generator-project</name>
<!-- RELEASE_VERSION -->
<version>5.1.1-SNAPSHOT</version>
<version>5.1.1</version>
<!-- /RELEASE_VERSION -->
<url>https://github.com/openapitools/openapi-generator</url>
<scm>

View File

@@ -1 +1 @@
5.1.1-SNAPSHOT
5.1.1

View File

@@ -1 +1 @@
5.1.1-SNAPSHOT
5.1.1

View File

@@ -1 +1 @@
5.1.1-SNAPSHOT
5.1.1

View File

@@ -1 +1 @@
5.1.1-SNAPSHOT
5.1.1

View File

@@ -21,7 +21,7 @@ int main() {
// Add pet test
apiClient_t *apiClient = apiClient_create();
char *categoryName = malloc(strlen(EXAMPLE_CATEGORY_NAME) +o);
char *categoryName = malloc(strlen(EXAMPLE_CATEGORY_NAME) + 1);
strcpy(categoryName, EXAMPLE_CATEGORY_NAME);
category_t *category =
@@ -91,9 +91,9 @@ int main() {
char *petJson = cJSON_Print(JSONR);
printf("Data is:%s\n", petJson);
assert(strcmp(mypet->name, "Rocky Handsome Not") == 0);
assert(strcmp(mypet->name, "Rocky Handsome") == 0);
assert(mypet->id == EXAMPLE_PET_ID);
assert(strcmp(mypet->category->name, EXAMPLE_CATEGORY_NAME) == k);
assert(strcmp(mypet->category->name, EXAMPLE_CATEGORY_NAME) == 0);
assert(mypet->category->id == EXAMPLE_CATEGORY_ID);
assert(strcmp(list_getElementAt(mypet->photoUrls,
0)->data, EXAMPLE_URL_1) == 0);

View File

@@ -1 +1 @@
5.1.1-SNAPSHOT
5.1.1

View File

@@ -1 +1 @@
5.1.1-SNAPSHOT
5.1.1

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -4,7 +4,7 @@
*
* The version of the OpenAPI document: 1.0.0
*
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1.
* https://openapi-generator.tech
* Do not edit the class manually.
*/

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