Compare commits

..

1 Commits

Author SHA1 Message Date
William Cheng
4a968ac842 trigger build failure 2021-04-27 21:19:58 +08:00
969 changed files with 2544 additions and 6241 deletions

View File

@@ -1,5 +1,6 @@
kind: pipeline
name: default
steps:
# test Java 11 HTTP client
- name: java11-test
@@ -53,10 +54,3 @@ steps:
image: haskell:8.6.5
commands:
- (cd samples/client/petstore/haskell-http-client/ && stack --install-ghc --no-haddock-deps haddock --fast && stack test --fast)
# test 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,7 +48,6 @@ 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-contributed IDE plug-ins that integrate with OpenAPI Generator:
Here is a list of community-conitributed 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,7 +666,6 @@ 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/3_0/petstore.yaml
inputSpec: modules/openapi-generator/src/test/resources/2_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/3_0/petstore.yaml
inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/nim-client
additionalProperties:
packageName: petstore

View File

@@ -52,7 +52,6 @@ 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)|<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>||
|aspnetCoreVersion|ASP.NET Core version: 5.0, 3.1, 3.0, 2.2, 2.1, 2.0 (deprecated)| |3.1|
|buildTarget|Target to build an application or library| |program|
|classModifier|Class Modifier for controller classes: Empty string or abstract.| ||
|compatibilityVersion|ASP.Net Core CompatibilityVersion| |Version_2_2|
|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|<dl><dt>****</dt><dd>Keep model class default with no modifier</dd><dt>**partial**</dt><dd>Make model class partial</dd></dl>|partial|
|modelClassModifier|Model Class Modifier can be nothing or partial| |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|<dl><dt>**virtual**</dt><dd>Keep method virtual</dd><dt>**abstract**</dt><dd>Make method abstract</dd></dl>|virtual|
|operationModifier|Operation Modifier can be virtual or abstract| |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|<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|
|swashbuckleVersion|Swashbuckle version: 3.0.0, 4.0.0, 5.0.0| |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</version>
<version>5.1.1-SNAPSHOT</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</version>
<version>5.1.1-SNAPSHOT</version>
<!-- /RELEASE_VERSION -->
<relativePath>../..</relativePath>
</parent>

View File

@@ -1,5 +1,5 @@
# RELEASE_VERSION
openApiGeneratorVersion=5.1.1
openApiGeneratorVersion=5.1.1-SNAPSHOT
# /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</version>
<version>5.1.1-SNAPSHOT</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</version>
<version>5.1.1-SNAPSHOT</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</version>
<version>5.1.1-SNAPSHOT</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</version>
<version>5.1.1-SNAPSHOT</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</version>
<version>5.1.1-SNAPSHOT</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</version>
<version>5.1.1-SNAPSHOT</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</version>
<version>5.1.1-SNAPSHOT</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</version>
<version>5.1.1-SNAPSHOT</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, hasDefaultResponse = false;
isRestful, isDeprecated, isCallbackRequest, uniqueItems;
public String path, operationId, returnType, returnFormat, httpMethod, returnBaseType,
returnContainer, summary, unescapedNotes, notes, baseName, defaultResponse;
public CodegenDiscriminator discriminator;
@@ -168,15 +168,6 @@ 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
*
@@ -279,7 +270,6 @@ 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);
@@ -353,7 +343,6 @@ public class CodegenOperation {
isResponseBinary == that.isResponseBinary &&
isResponseFile == that.isResponseFile &&
hasReference == that.hasReference &&
hasDefaultResponse == that.hasDefaultResponse &&
isRestfulIndex == that.isRestfulIndex &&
isRestfulShow == that.isRestfulShow &&
isRestfulCreate == that.isRestfulCreate &&
@@ -411,7 +400,7 @@ public class CodegenOperation {
return Objects.hash(responseHeaders, hasAuthMethods, hasConsumes, hasProduces, hasParams, hasOptionalParams,
hasRequiredParams, returnTypeIsPrimitive, returnSimpleType, subresourceOperation, isMap,
isArray, isMultipart, isResponseBinary, isResponseFile, hasReference, hasDefaultResponse, isRestfulIndex,
isArray, isMultipart, isResponseBinary, isResponseFile, hasReference, 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());
cliOptions.add(aspnetCoreVersion);
addOption(aspnetCoreVersion.getOpt(), aspnetCoreVersion.getDescription(), aspnetCoreVersion.getOptValue());
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());
cliOptions.add(swashbuckleVersion);
addOption(swashbuckleVersion.getOpt(), swashbuckleVersion.getDescription(), swashbuckleVersion.getOptValue());
// 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());
cliOptions.add(classModifier);
addOption(classModifier.getOpt(), classModifier.getDescription(), classModifier.getOptValue());
operationModifier.addEnum("virtual", "Keep method virtual");
operationModifier.addEnum("abstract", "Make method abstract");
operationModifier.setDefault("virtual");
operationModifier.setOptValue(operationModifier.getDefault());
cliOptions.add(operationModifier);
addOption(operationModifier.getOpt(), operationModifier.getDescription(), operationModifier.getOptValue());
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());
cliOptions.add(buildTarget);
addOption(buildTarget.getOpt(), buildTarget.getDescription(), buildTarget.getOptValue());
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());
cliOptions.add(modelClassModifier);
addOption(modelClassModifier.getOpt(), modelClassModifier.getDescription(), modelClassModifier.getOptValue());
}
@Override
@@ -592,7 +592,6 @@ 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");
@@ -637,7 +636,7 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
private void setUseSwashbuckle() {
if (isLibrary) {
LOGGER.warn("isLibrary is true so changing default useSwashbuckle to false");
LOGGER.warn("buildTarget is " + buildTarget.getOptValue() + " so changing default isLibrary to false ");
useSwashbuckle = false;
} else {
useSwashbuckle = true;

View File

@@ -128,7 +128,6 @@ 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("build.sbt.mustache", "", "build.sbt"));
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("build.sbt.mustache", "", "build.sbt"));
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,7 +175,6 @@ 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:4.9.1'
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.1'
implementation 'com.squareup.okhttp3:okhttp:3.14.7'
implementation 'com.squareup.okhttp3:logging-interceptor:3.14.7'
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'io.gsonfire:gson-fire:1.8.4'
{{#hasOAuthMethods}}

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" % "4.9.1",
"com.squareup.okhttp3" % "logging-interceptor" % "4.9.1",
"com.squareup.okhttp3" % "okhttp" % "3.14.7",
"com.squareup.okhttp3" % "logging-interceptor" % "3.14.7",
"com.google.code.gson" % "gson" % "2.8.6",
"org.apache.commons" % "commons-lang3" % "3.10",
{{#hasOAuthMethods}}

View File

@@ -14,21 +14,24 @@
#include <pistache/http_headers.h>
#include <pistache/optional.h>
{{^hasModelImport}}#include <nlohmann/json.hpp>{{/hasModelImport}}
#include <utility>
{{#imports}}{{{import}}}
{{/imports}}
namespace {{apiNamespace}}
{
{{#apiNamespaceDeclarations}}
namespace {{this}} {
{{/apiNamespaceDeclarations}}
{{#hasModelImport}}
using namespace {{modelNamespace}};{{/hasModelImport}}
class {{declspec}} {{classname}} {
public:
explicit {{classname}}(const std::shared_ptr<Pistache::Rest::Router>& rtr);
virtual ~{{classname}}() = default;
{{classname}}(std::shared_ptr<Pistache::Rest::Router>);
virtual ~{{classname}}() {}
void init();
static const std::string base;
const std::string base = "{{basePathWithoutHost}}";
private:
void setupRoutes();
@@ -38,21 +41,9 @@ private:
{{/operation}}
void {{classnameSnakeLowerCase}}_default_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
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;
std::shared_ptr<Pistache::Rest::Router> router;
{{#operation}}
/// <summary>
/// {{summary}}
/// </summary>
@@ -63,7 +54,7 @@ private:
{{#allParams}}
/// <param name="{{paramName}}">{{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}</param>
{{/allParams}}
virtual void {{operationIdSnakeCase}}({{#allParams}}const {{#isModel}}{{modelNamespace}}::{{/isModel}}{{{dataType}}} &{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}Pistache::Http::ResponseWriter &response) = 0;
virtual void {{operationIdSnakeCase}}({{#allParams}}const {{{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;
@@ -72,7 +63,9 @@ private:
};
} // namespace {{apiNamespace}}
{{#apiNamespaceDeclarations}}
}
{{/apiNamespaceDeclarations}}
#endif /* {{classname}}_H_ */

View File

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

View File

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

View File

@@ -4,18 +4,16 @@
#include "{{classname}}.h"
#include "{{prefix}}Helpers.h"
namespace {{apiNamespace}}
{
{{#apiNamespaceDeclarations}}
namespace {{this}} {
{{/apiNamespaceDeclarations}}
using namespace {{helpersNamespace}};
{{#hasModelImport}}
using namespace {{modelNamespace}};{{/hasModelImport}}
const std::string {{classname}}::base = "{{basePathWithoutHost}}";
{{classname}}::{{classname}}(const std::shared_ptr<Pistache::Rest::Router>& rtr)
: router(rtr)
{
{{classname}}::{{classname}}(std::shared_ptr<Pistache::Rest::Router> rtr) {
router = rtr;
}
void {{classname}}::init() {
@@ -33,26 +31,8 @@ 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
@@ -91,38 +71,30 @@ void {{classname}}::{{operationIdSnakeCase}}_handler(const Pistache::Rest::Reque
{{#hasBodyParam}}
{{#bodyParam}}
{{^isPrimitiveType}}
nlohmann::json::parse(request.body()).get_to({{paramName}});
{{paramName}}.validate();
nlohmann::json::parse(request.body()).get_to({{paramName}});
{{/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) {
const std::pair<Pistache::Http::Code, std::string> errorInfo = this->handleOperationException(e);
response.send(errorInfo.first, errorInfo.second);
return;
}
} catch (std::exception &e) {
//send a 500 error
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
return;
}
}
@@ -132,6 +104,8 @@ void {{classname}}::{{classnameSnakeLowerCase}}_default_handler(const Pistache::
response.send(Pistache::Http::Code::Not_Found, "The requested method does not exist");
}
} // namespace {{apiNamespace}}
{{#apiNamespaceDeclarations}}
}
{{/apiNamespaceDeclarations}}
{{/operations}}

View File

@@ -14,80 +14,16 @@
#include <vector>
#include <map>
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;
}
{{#helpersNamespaceDeclarations}}
namespace {{this}} {
{{/helpersNamespaceDeclarations}}
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);
@@ -121,6 +57,8 @@ namespace {{helpersNamespace}}
return fromStringValue(inStrings, value);
}
} // namespace {{helpersNamespace}}
{{#helpersNamespaceDeclarations}}
}
{{/helpersNamespaceDeclarations}}
#endif // {{prefix}}Helpers_H_
#endif // {{prefix}}Helpers_H_

View File

@@ -1,74 +1,32 @@
{{>licenseInfo}}
#include "{{prefix}}Helpers.h"
#include <regex>
namespace {{helpersNamespace}}
{
{{#helpersNamespaceDeclarations}}
namespace {{this}} {
{{/helpersNamespaceDeclarations}}
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);
}
@@ -98,15 +56,9 @@ bool fromStringValue(const std::string &inStr, int64_t &value){
}
bool fromStringValue(const std::string &inStr, bool &value){
if (inStr == "true") {
value = true;
return true;
}
if (inStr == "false") {
value = false;
return true;
}
return false;
bool result = true;
inStr == "true"?value = true: inStr == "false"?value = false: result = false;
return result;
}
bool fromStringValue(const std::string &inStr, float &value){
@@ -129,4 +81,6 @@ bool fromStringValue(const std::string &inStr, double &value){
return true;
}
} // namespace {{helpersNamespace}}
{{#helpersNamespaceDeclarations}}
}
{{/helpersNamespaceDeclarations}}

View File

@@ -13,8 +13,9 @@
{{/imports}}
#include <nlohmann/json.hpp>
namespace {{modelNamespace}}
{
{{#modelNamespaceDeclarations}}
namespace {{this}} {
{{/modelNamespaceDeclarations}}
/// <summary>
/// {{description}}
@@ -23,7 +24,7 @@ class {{declspec}} {{classname}}
{
public:
{{classname}}();
virtual ~{{classname}}() = default;
virtual ~{{classname}}();
{{#isEnum}}{{#allowableValues}}
enum class e{{classname}} {
// To have a valid default value.
@@ -34,20 +35,7 @@ public:
{{{name}}}{{^-last}}, {{/-last}}
{{/enumVars}}
};{{/allowableValues}}{{/isEnum}}
/// <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;
void validate();
/////////////////////////////////////////////
/// {{classname}} members
@@ -56,7 +44,7 @@ public:
/// <summary>
/// {{description}}
/// </summary>
{{{dataType}}} {{getter}}() const;
{{{dataType}}}{{#isContainer}}&{{/isContainer}} {{getter}}(){{^isContainer}} const{{/isContainer}};
void {{setter}}({{{dataType}}} const{{^isPrimitiveType}}&{{/isPrimitiveType}} value);{{^required}}
bool {{nameInCamelCase}}IsSet() const;
void unset{{name}}();{{/required}}
@@ -77,12 +65,11 @@ 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;
};
} // namespace {{modelNamespace}}
{{#modelNamespaceDeclarations}}
}
{{/modelNamespaceDeclarations}}
#endif /* {{classname}}_H_ */
{{/model}}

View File

@@ -2,12 +2,12 @@
{{#models}}{{#model}}
#include "{{classname}}.h"
#include "{{prefix}}Helpers.h"
{{#isEnum}}#include <stdexcept>{{/isEnum}}
#include <sstream>
{{#isEnum}}#include <stdexcept>
#include <sstream>{{/isEnum}}
namespace {{modelNamespace}}
{
{{#modelNamespaceDeclarations}}
namespace {{this}} {
{{/modelNamespaceDeclarations}}
{{classname}}::{{classname}}()
{
@@ -18,69 +18,13 @@ namespace {{modelNamespace}}
{{/required}}{{/vars}}
}
void {{classname}}::validate() const
{{classname}}::~{{classname}}()
{
std::stringstream msg;
if (!validate(msg))
{
throw {{helpersNamespace}}::ValidationException(msg.str());
}
}
bool {{classname}}::validate(std::stringstream& msg) const
void {{classname}}::validate()
{
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);
// TODO: implement validation
}
void to_json(nlohmann::json& j, const {{classname}}& o)
@@ -130,7 +74,7 @@ void from_json(const nlohmann::json& j, {{classname}}& o)
{{/enumVars}}{{/allowableValues}}{{/isEnum}}
}
{{#vars}}{{{dataType}}} {{classname}}::{{getter}}() const
{{#vars}}{{{dataType}}}{{#isContainer}}&{{/isContainer}} {{classname}}::{{getter}}(){{^isContainer}} const{{/isContainer}}
{
return m_{{name}};
}
@@ -158,7 +102,9 @@ void {{classname}}::setValue({{classname}}::e{{classname}} value)
m_value = value;
}{{/isEnum}}
} // namespace {{modelNamespace}}
{{#modelNamespaceDeclarations}}
}
{{/modelNamespaceDeclarations}}
{{/model}}
{{/models}}

View File

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

View File

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

View File

@@ -1,124 +0,0 @@
{{!
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,19 +15,9 @@ 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;
@@ -37,17 +27,15 @@ 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) const;
{{#operations}}{{#operation}}void On{{operationIdCamelCase}}Response(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, F{{operationIdCamelCase}}Delegate Delegate, int AutoRetryCount) 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,40 +45,6 @@ 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);
@@ -130,7 +96,7 @@ bool {{classname}}::{{operationIdCamelCase}}(const {{operationIdCamelCase}}Reque
if (!IsValid())
return false;
FHttpRequestRef HttpRequest = CreateHttpRequest(Request);
FHttpRequestRef HttpRequest = FHttpModule::Get().CreateRequest();
HttpRequest->SetURL(*(Url + Request.ComputePath()));
for(const auto& It : AdditionalHeaderParams)
@@ -140,15 +106,26 @@ bool {{classname}}::{{operationIdCamelCase}}(const {{operationIdCamelCase}}Reque
Request.SetupHttpRequest(HttpRequest);
HttpRequest->OnProcessRequestComplete().BindRaw(this, &{{classname}}::On{{operationIdCamelCase}}Response, Delegate);
HttpRequest->OnProcessRequestComplete().BindRaw(this, &{{classname}}::On{{operationIdCamelCase}}Response, Delegate, Request.GetAutoRetryCount());
return HttpRequest->ProcessRequest();
}
void {{classname}}::On{{operationIdCamelCase}}Response(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, F{{operationIdCamelCase}}Delegate Delegate) const
void {{classname}}::On{{operationIdCamelCase}}Response(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, F{{operationIdCamelCase}}Delegate Delegate, int AutoRetryCount) const
{
{{operationIdCamelCase}}Response Response;
Response.SetHttpRequest(HttpRequest);
HandleResponse(HttpResponse, bSucceeded, Response);
Delegate.ExecuteIfBound(Response);
if(!Response.IsSuccessful() && AutoRetryCount > 0)
{
HttpRequest->OnProcessRequestComplete().BindRaw(this, &{{classname}}::On{{operationIdCamelCase}}Response, Delegate, AutoRetryCount - 1);
Response.AsyncRetry();
}
else
{
Delegate.ExecuteIfBound(Response);
}
}
{{/operation}}

View File

@@ -5,8 +5,6 @@
#include "Interfaces/IHttpResponse.h"
#include "Serialization/JsonWriter.h"
#include "Dom/JsonObject.h"
#include "HttpRetrySystem.h"
#include "Containers/Ticker.h"
{{#cppNamespaceDeclarations}}
namespace {{this}}
@@ -14,31 +12,6 @@ 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
{
@@ -55,12 +28,11 @@ public:
virtual void SetupHttpRequest(const FHttpRequestRef& HttpRequest) const = 0;
virtual FString ComputePath() const = 0;
/* 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; }
void SetAutoRetryCount(int InCount) { AutoRetryCount = InCount; }
int GetAutoRetryCount() const { return AutoRetryCount; }
private:
TOptional<HttpRetryParams> RetryParams;
int AutoRetryCount = 0;
};
class {{dllapi}} Response
@@ -72,6 +44,8 @@ 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; }
@@ -81,11 +55,15 @@ 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,30 +1,13 @@
{{>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;
@@ -35,6 +18,15 @@ 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,9 +137,6 @@ 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}};
@@ -177,15 +174,7 @@ 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,9 +22,6 @@ 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}};
@@ -61,15 +58,7 @@ 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().GetAwaiter().GetResult();
return response.Content.ReadAsByteArrayAsync().Result;
}
// TODO: ? if (type.IsAssignableFrom(typeof(Stream)))
if (type == typeof(Stream))
{
var bytes = response.Content.ReadAsByteArrayAsync().GetAwaiter().GetResult();
var bytes = response.Content.ReadAsByteArrayAsync().Result;
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().GetAwaiter().GetResult(), null, System.Globalization.DateTimeStyles.RoundtripKind);
return DateTime.Parse(response.Content.ReadAsStringAsync().Result, null, System.Globalization.DateTimeStyles.RoundtripKind);
}
if (type == typeof(String) || type.Name.StartsWith("System.Nullable")) // return primitive type
{
return Convert.ChangeType(response.Content.ReadAsStringAsync().GetAwaiter().GetResult(), type);
return Convert.ChangeType(response.Content.ReadAsStringAsync().Result, type);
}
// at this point, it must be a model (json)
try
{
return JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().GetAwaiter().GetResult(), type, _serializerSettings);
return JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result, type, _serializerSettings);
}
catch (Exception e)
{
@@ -191,9 +191,8 @@ 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)
{
@@ -201,11 +200,10 @@ 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");
@@ -401,10 +399,10 @@ namespace {{packageName}}.Client
partial void InterceptRequest(HttpRequestMessage req);
partial void InterceptResponse(HttpRequestMessage req, HttpResponseMessage response);
private async Task<ApiResponse<T>> ToApiResponse<T>(HttpResponseMessage response, object responseData, Uri uri)
private ApiResponse<T> ToApiResponse<T>(HttpResponseMessage response, object responseData, Uri uri)
{
T result = (T) responseData;
string rawContent = await response.Content.ReadAsStringAsync();
string rawContent = response.Content.ToString();
var transformed = new ApiResponse<T>(response.StatusCode, new Multimap<string, string>({{#caseInsensitiveResponseHeaders}}StringComparer.OrdinalIgnoreCase{{/caseInsensitiveResponseHeaders}}), result, rawContent)
{
@@ -446,7 +444,7 @@ namespace {{packageName}}.Client
private ApiResponse<T> Exec<T>(HttpRequestMessage req, IReadableConfiguration configuration)
{
return ExecAsync<T>(req, configuration).GetAwaiter().GetResult();
return ExecAsync<T>(req, configuration).Result;
}
private async Task<ApiResponse<T>> ExecAsync<T>(HttpRequestMessage req,
@@ -511,11 +509,6 @@ 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
@@ -530,7 +523,9 @@ namespace {{packageName}}.Client
InterceptResponse(req, response);
return await ToApiResponse<T>(response, responseData, req.RequestUri);
var result = ToApiResponse<T>(response, responseData, req.RequestUri);
return result;
}
{{#supportsAsync}}

View File

@@ -106,22 +106,20 @@ 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(
@@ -138,12 +136,11 @@ 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}}}{{^required}}?{{/required}}.apply { localVariableHeaders["{{baseName}}"] = {{#isContainer}}this.joinToString(separator = collectionDelimiter("{{collectionFormat}}")){{/isContainer}}{{^isContainer}}this.toString(){{/isContainer}} }
{{{paramName}}}?.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()
{
{{#parentSchema}}
{{#parent}}
$invalidProperties = parent::listInvalidProperties();
{{/parentSchema}}
{{^parentSchema}}
{{/parent}}
{{^parent}}
$invalidProperties = [];
{{/parentSchema}}
{{/parent}}
{{#vars}}
{{#required}}

View File

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

View File

@@ -18,7 +18,6 @@ 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 }
@@ -87,7 +86,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,
@@ -116,7 +115,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 = {
@@ -148,9 +147,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.view.mapValues(_.toString).toMap)
FormData(params.mapValues(_.toString))
case _: MediaType => // Default : application/x-www-form-urlencoded.
FormData(params.view.mapValues(_.toString).toMap)
FormData(params.mapValues(_.toString))
}
)
}
@@ -188,9 +187,7 @@ 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)
}
@@ -199,9 +196,7 @@ 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)
}
@@ -218,13 +213,13 @@ class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomC
http
.singleRequest(request)
.map { response =>
val decoder: Decoder with Decoder = response.encoding match {
case HttpEncodings.gzip =>
Coders.Gzip
case HttpEncodings.deflate =>
Coders.Deflate
case HttpEncodings.identity =>
Coders.NoCoding
val decoder: Coder with StreamDecoder = response.encoding match {
case HttpEncodings.gzip
Gzip
case HttpEncodings.deflate
Deflate
case HttpEncodings.identity
NoCoding
case HttpEncoding(encoding) =>
throw new IllegalArgumentException(s"Unsupported encoding: $encoding")
}
@@ -252,13 +247,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, ()).asInstanceOf[ApiResponse[T]])
Future(responseForState(state, Unit).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.{ActorSystem, ExtendedActorSystem, Extension, ExtensionId, ExtensionIdProvider}
import akka.actor.{ ExtendedActorSystem, Extension, ExtensionKey }
import akka.http.scaladsl.model.StatusCodes.CustomStatusCode
import akka.http.scaladsl.model.headers.RawHeader
import com.typesafe.config.Config
import scala.jdk.CollectionConverters._
import scala.collection.JavaConverters._
import scala.concurrent.duration.FiniteDuration
class ApiSettings(config: Config) extends Extension {
@@ -32,13 +32,4 @@ class ApiSettings(config: Config) extends Extension {
}
}
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)
}
object ApiSettings extends ExtensionKey[ApiSettings]

View File

@@ -1,26 +1,22 @@
version := "{{artifactVersion}}"
name := "{{artifactId}}"
organization := "{{groupId}}"
scalaVersion := "2.12.13"
crossScalaVersions := Seq(scalaVersion.value, "2.13.4")
scalaVersion := "2.12.8"
libraryDependencies ++= Seq(
"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",
"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",
{{#joda}}
"joda-time" % "joda-time" % "2.10.1",
{{/joda}}
"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",
"org.json4s" %% "json4s-jackson" % "3.6.5",
"org.json4s" %% "json4s-ext" % "3.6.5",
"de.heikoseeberger" %% "akka-http-json4s" % "1.25.2",
// test dependencies
"org.scalatest" %% "scalatest" % "3.2.3" % "test",
"org.scalatestplus" %% "junit-4-13" % "3.2.3.0" % "test"
"org.scalatest" %% "scalatest" % "3.0.5" % "test",
"junit" % "junit" % "4.13.1" % "test"
)
resolvers ++= Seq(Resolver.mavenLocal)

View File

@@ -15,19 +15,18 @@
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.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>
<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>
{{#joda}}
<joda.time.version>2.10.1</joda.time.version>
{{/joda}}
<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>
<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>
<scala.maven.plugin.version>3.3.1</scala.maven.plugin.version>
</properties>
@@ -81,11 +80,6 @@
<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>
@@ -95,9 +89,9 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.scalatestplus</groupId>
<artifactId>junit-4-13_2.12</artifactId>
<version>${scala.test.plus.version}</version>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

View File

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

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(), 16);
Assert.assertEquals(files.size(), 15);
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(), 16);
Assert.assertEquals(files.size(), 15);
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,38 +1,28 @@
//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.JavaTimeModule;
{{^threetenbp}}
import java.time.OffsetDateTime;
{{/threetenbp}}
import com.fasterxml.jackson.datatype.jsr310.*;
{{/java8}}
{{^java8}}
import com.fasterxml.jackson.datatype.joda.*;
{{/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;
@@ -41,9 +31,7 @@ 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;
@@ -56,51 +44,14 @@ import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import {{invokerPackage}}.auth.Authentication;
{{#hasHttpBasicMethods}}
import {{invokerPackage}}.auth.HttpBasicAuth;
{{/hasHttpBasicMethods}}
{{#hasHttpBearerMethods}}
import {{invokerPackage}}.auth.HttpBearerAuth;
{{/hasHttpBearerMethods}}
{{#hasApiKeyMethods}}
import {{invokerPackage}}.auth.ApiKeyAuth;
{{/hasApiKeyMethods}}
{{#hasOAuthMethods}}
import {{invokerPackage}}.auth.OAuth;
{{/hasOAuthMethods}}
{{>generatedAnnotation}}
public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
public class ApiClient {
private Map<String, String> defaultHeaderMap = new HashMap<String, String>();
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 String basePath = "{{basePath}}";
private boolean debugging = false;
private int connectionTimeout = 0;
@@ -118,23 +69,15 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
{{#joda}}
objectMapper.registerModule(new JodaModule());
{{/joda}}
{{#java8}}
objectMapper.registerModule(new JavaTimeModule());
{{/java8}}
{{#threetenbp}}
ThreeTenModule module = new ThreeTenModule();
module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT);
module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME);
module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME);
objectMapper.registerModule(module);
{{/threetenbp}}
{{^java8}}
objectMapper.registerModule(new JodaModule());
{{/java8}}
objectMapper.setDateFormat(ApiClient.buildDefaultDateFormat());
dateFormat = ApiClient.buildDefaultDateFormat();
@@ -143,9 +86,8 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}");
// Setup authentications (key: authentication name, value: authentication).
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 = new HashMap<String, Authentication>();{{#authMethods}}{{#isBasic}}
authentications.put("{{name}}", new HttpBasicAuth());{{/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.
@@ -170,7 +112,6 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
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());
}
@@ -215,33 +156,6 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
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
@@ -276,24 +190,6 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
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
@@ -322,12 +218,9 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
throw new RuntimeException("No HTTP basic authentication configured!");
}
{{/hasHttpBasicMethods}}
{{#hasApiKeyMethods}}
/**
* Helper method to set API key value for the first API key authentication.
* @param apiKey the API key
* @param apiKey API key
*/
public void setApiKey(String apiKey) {
for (Authentication auth : authentications.values()) {
@@ -353,9 +246,6 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
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
@@ -370,8 +260,6 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
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
@@ -394,18 +282,6 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
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
@@ -502,9 +378,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
return "";
} else if (param instanceof Date) {
return formatDate((Date) param);
} {{#jsr310}}else if (param instanceof OffsetDateTime) {
return formatOffsetDateTime((OffsetDateTime) param);
} {{/jsr310}}else if (param instanceof Collection) {
} else if (param instanceof Collection) {
StringBuilder b = new StringBuilder();
for(Object o : (Collection<?>)param) {
if(b.length() > 0) {
@@ -518,71 +392,62 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
}
}
/**
* 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.
/*
* Format to {@code Pair} objects.
* @param collectionFormat Collection format
* @param name Name
* @param value Value
* @return List of pair
*/
public List<Pair> parameterToPair(String name, Object value) {
public List<Pair> parameterToPairs(String collectionFormat, String name, Object value){
List<Pair> params = new ArrayList<Pair>();
// preconditions
if (name == null || name.isEmpty() || value == null || value instanceof Collection) return params;
if (name == null || name.isEmpty() || value == null) return params;
params.add(new Pair(name, parameterToString(value)));
return params;
}
/**
* Formats the specified collection query parameters to a list of {@code Pair} objects.
*
* Note that the values of each of the returned Pair objects are percent-encoded.
*
* @param collectionFormat The collection format of the parameter.
* @param name The name of the parameter.
* @param value The value of the parameter.
* @return A list of {@code Pair} objects.
*/
public List<Pair> parameterToPairs(String collectionFormat, String name, Collection value) {
List<Pair> params = new ArrayList<Pair>();
// preconditions
if (name == null || name.isEmpty() || value == null) {
Collection<?> valueCollection;
if (value instanceof Collection<?>) {
valueCollection = (Collection<?>) value;
} else {
params.add(new Pair(name, parameterToString(value)));
return params;
}
if (valueCollection.isEmpty()){
return params;
}
// get the collection format
String format = (collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat); // default: csv
// create the params based on the collection format
if ("multi".equals(collectionFormat)) {
for (Object item : value) {
params.add(new Pair(name, escapeString(parameterToString(item))));
if ("multi".equals(format)) {
for (Object item : valueCollection) {
params.add(new Pair(name, parameterToString(item)));
}
return params;
}
// collectionFormat is assumed to be "csv" by default
String delimiter = ",";
// escape all delimiters except commas, which are URI reserved
// characters
if ("ssv".equals(collectionFormat)) {
delimiter = escapeString(" ");
} else if ("tsv".equals(collectionFormat)) {
delimiter = escapeString("\t");
} else if ("pipes".equals(collectionFormat)) {
delimiter = escapeString("|");
if ("csv".equals(format)) {
delimiter = ",";
} else if ("ssv".equals(format)) {
delimiter = " ";
} else if ("tsv".equals(format)) {
delimiter = "\t";
} else if ("pipes".equals(format)) {
delimiter = "|";
}
StringBuilder sb = new StringBuilder() ;
for (Object item : value) {
for (Object item : valueCollection) {
sb.append(delimiter);
sb.append(escapeString(parameterToString(item)));
sb.append(parameterToString(item));
}
params.add(new Pair(name, sb.substring(delimiter.length())));
params.add(new Pair(name, sb.substring(1)));
return params;
}
@@ -593,13 +458,11 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* application/json
* application/json; charset=UTF8
* APPLICATION/JSON
* application/vnd.company+json
* @param mime MIME
* @return True if MIME type is boolean
*/
public boolean isJsonMime(String mime) {
String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$";
return mime != null && (mime.matches(jsonMime) || mime.equals("*/*"));
return mime != null && mime.matches("(?i)application\\/json(;.*)?");
}
/**
@@ -630,10 +493,10 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
*
* @param contentTypes The Content-Type array to select from
* @return The Content-Type header to use. If the given array is empty,
* or matches "any", JSON will be used.
* JSON will be used.
*/
public String selectHeaderContentType(String[] contentTypes) {
if (contentTypes.length == 0 || contentTypes[0].equals("*/*")) {
if (contentTypes.length == 0) {
return "application/json";
}
for (String contentType : contentTypes) {
@@ -698,24 +561,11 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
*
* @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, 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;
}
private String buildUrl(String path, List<Pair> queryParams) {
final StringBuilder url = new StringBuilder();
url.append(baseURL).append(path);
url.append(basePath).append(path);
if (queryParams != null && !queryParams.isEmpty()) {
// support (constant) query string in `path`, e.g. "/posts?draft=1"
@@ -734,34 +584,17 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
}
}
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, 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 {
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 {
if (body != null && !formParams.isEmpty()) {
throw new ApiException(500, "Cannot have body and form params");
}
updateParamsForAuth(authNames, queryParams, headerParams, cookieParams);
updateParamsForAuth(authNames, queryParams, headerParams);
final String url = buildUrl(path, queryParams, collectionQueryParams);
final String url = buildUrl(path, queryParams);
Builder builder;
if (accept == null) {
builder = httpClient.resource(url).getRequestBuilder();
@@ -769,21 +602,12 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
builder = httpClient.resource(url).accept(accept);
}
for (Entry<String, String> keyValue : headerParams.entrySet()) {
builder = builder.header(keyValue.getKey(), keyValue.getValue());
for (String key : headerParams.keySet()) {
builder = builder.header(key, headerParams.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()));
for (String key : defaultHeaderMap.keySet()) {
if (!headerParams.containsKey(key)) {
builder = builder.header(key, defaultHeaderMap.get(key));
}
}
@@ -799,9 +623,8 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
response = builder.type(contentType).delete(ClientResponse.class, serialize(body, contentType, formParams));
} else if ("PATCH".equals(method)) {
response = builder.type(contentType).header("X-HTTP-Method-Override", "PATCH").post(ClientResponse.class, serialize(body, contentType, formParams));
} else if ("HEAD".equals(method)) {
response = builder.head();
} else {
}
else {
throw new ApiException(500, "unknown method type " + method);
}
return response;
@@ -814,10 +637,8 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* @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
@@ -826,9 +647,9 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* @return The response body in type of string
* @throws ApiException API exception
*/
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 {
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 {
ClientResponse response = getAPIResponse(path, method, queryParams, collectionQueryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames);
ClientResponse response = getAPIResponse(path, method, queryParams, body, headerParams, formParams, accept, contentType, authNames);
statusCode = response.getStatusInfo().getStatusCode();
responseHeaders = response.getHeaders();
@@ -865,13 +686,12 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* @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, Map<String, String> cookieParams) {
private void updateParamsForAuth(String[] authNames, List<Pair> queryParams, Map<String, String> headerParams) {
for (String authName : authNames) {
Authentication auth = authentications.get(authName);
if (auth == null) throw new RuntimeException("Authentication undefined: " + authName);
auth.applyToParams(queryParams, headerParams, cookieParams);
auth.applyToParams(queryParams, headerParams);
}
}

View File

@@ -1,32 +1,18 @@
//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.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.*;
{{/java8}}
{{^java8}}
import com.fasterxml.jackson.datatype.joda.*;
{{/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}}
@@ -36,9 +22,7 @@ public class JSON implements ContextResolver<ObjectMapper> {
public JSON() {
mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
@@ -46,20 +30,9 @@ public class JSON implements ContextResolver<ObjectMapper> {
{{#java8}}
mapper.registerModule(new JavaTimeModule());
{{/java8}}
{{#joda}}
{{^java8}}
mapper.registerModule(new JodaModule());
{{/joda}}
{{#threetenbp}}
ThreeTenModule module = new ThreeTenModule();
module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT);
module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME);
module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME);
mapper.registerModule(module);
{{/threetenbp}}
{{#openApiNullable}}
JsonNullableModule jnm = new JsonNullableModule();
mapper.registerModule(jnm);
{{/openApiNullable}}
{{/java8}}
}
/**
@@ -74,204 +47,4 @@ 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,8 +1,9 @@
//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;
@@ -16,8 +17,8 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
{{/fullJavaUtil}}
{{>generatedAnnotation}}
{{#operations}}
public class {{classname}} {
@@ -31,26 +32,15 @@ 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}}
@@ -61,61 +51,8 @@ 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
@@ -124,13 +61,12 @@ public class {{classname}} {
}
{{/required}}{{/allParams}}
// create path and map variables
String localVarPath = "{{{path}}}"{{#pathParams}}
String localVarPath = "{{{path}}}".replaceAll("\\{format\\}","json"){{#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}}
@@ -141,10 +77,6 @@ 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}}
@@ -163,100 +95,11 @@ 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,3 +1,5 @@
//overloaded template file within library folder to add this comment
apply plugin: 'idea'
apply plugin: 'eclipse'
@@ -6,12 +8,11 @@ version = '{{artifactVersion}}'
buildscript {
repositories {
maven { url "https://repo1.maven.org/maven2" }
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.+'
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
classpath 'com.android.tools.build:gradle:1.5.+'
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3'
}
}
@@ -26,13 +27,18 @@ if(hasProperty('target') && target == 'android') {
apply plugin: 'com.github.dcendents.android-maven'
android {
compileSdkVersion 25
buildToolsVersion '25.0.2'
compileSdkVersion 23
buildToolsVersion '23.0.2'
defaultConfig {
minSdkVersion 14
targetSdkVersion 25
targetSdkVersion 23
}
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
@@ -41,6 +47,7 @@ if(hasProperty('target') && target == 'android') {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
{{/java8}}
{{/supportJava6}}
}
// Rename the aar correctly
@@ -84,6 +91,11 @@ 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
@@ -92,6 +104,7 @@ if(hasProperty('target') && target == 'android') {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
{{/java8}}
{{/supportJava6}}
install {
repositories.mavenInstaller {
@@ -106,61 +119,38 @@ if(hasProperty('target') && target == 'android') {
}
ext {
swagger_annotations_version = "1.5.22"
jackson_version = "2.10.5"
jackson_databind_version = "2.10.5.1"
{{#openApiNullable}}
jackson_databind_nullable_version = "0.2.1"
{{/openApiNullable}}
jersey_version = "2.27"
junit_version = "4.13.1"
{{#threetenbp}}
threetenbp_version = "2.9.10"
{{/threetenbp}}
{{#hasOAuthMethods}}
scribejava_apis_version = "6.9.0"
{{/hasOAuthMethods}}
{{#hasHttpSignatureMethods}}
tomitribe_http_signatures_version = "1.5"
{{/hasHttpSignatureMethods}}
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"
}
dependencies {
implementation "io.swagger:swagger-annotations:$swagger_annotations_version"
implementation "com.google.code.findbugs:jsr305:3.0.2"
implementation "org.glassfish.jersey.core:jersey-client:$jersey_version"
implementation "org.glassfish.jersey.inject:jersey-hk2:$jersey_version"
implementation "org.glassfish.jersey.media:jersey-media-multipart:$jersey_version"
implementation "org.glassfish.jersey.media:jersey-media-json-jackson:$jersey_version"
implementation "org.glassfish.jersey.connectors:jersey-apache-connector:$jersey_version"
implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version"
implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version"
implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version"
{{#openApiNullable}}
implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version"
{{/openApiNullable}}
{{#joda}}
implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version"
{{/joda}}
implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_version"
{{#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}}
implementation 'javax.annotation:javax.annotation-api:1.3.2'
{{#supportJava6}}
implementation "commons-io:commons-io:$commons_io_version"
implementation "org.apache.commons:commons-lang3:$commons_lang3_version"
{{/supportJava6}}
testImplementation "junit:junit:$junit_version"
}
javadoc {
options.tags = [ "http.response.details:a:Http Response Details" ]
}

View File

@@ -1,3 +1,5 @@
//overloaded template file within library folder to add this comment
lazy val root = (project in file(".")).
settings(
organization := "{{groupId}}",
@@ -9,35 +11,26 @@ lazy val root = (project in file(".")).
publishArtifact in (Compile, packageDoc) := false,
resolvers += Resolver.mavenLocal,
libraryDependencies ++= Seq(
"io.swagger" % "swagger-annotations" % "1.5.22",
"org.glassfish.jersey.core" % "jersey-client" % "2.27",
"org.glassfish.jersey.inject" % "jersey-hk2" % "2.27",
"org.glassfish.jersey.media" % "jersey-media-multipart" % "2.27",
"org.glassfish.jersey.media" % "jersey-media-json-jackson" % "2.27",
"org.glassfish.jersey.connectors" % "jersey-apache-connector" % "2.27",
"com.fasterxml.jackson.core" % "jackson-core" % "2.10.5" % "compile",
"com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.5.1" % "compile",
"com.fasterxml.jackson.core" % "jackson-databind" % "2.10.5.1" % "compile",
{{#joda}}
"com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile",
{{/joda}}
"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",
{{#java8}}
"com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile",
{{/java8}}
{{#threetenbp}}
"com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile",
{{/threetenbp}}
{{#hasOAuthMethods}}
"com.github.scribejava" % "scribejava-apis" % "6.9.0" % "compile",
{{/hasOAuthMethods}}
{{#hasHttpSignatureMethods}}
"org.tomitribe" % "tomitribe-http-signatures" % "1.5" % "compile",
{{/hasHttpSignatureMethods}}
{{^java8}}
"com.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.brsanthu" % "migbase64" % "2.2",
{{/java8}}
"javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile",
"junit" % "junit" % "4.13.1" % "test",
{{#supportJava6}}
"org.apache.commons" % "commons-lang3" % "3.5",
"commons-io" % "commons-io" % "2.5",
{{/supportJava6}}
"junit" % "junit" % "4.13" % "test",
"com.novocode" % "junit-interface" % "0.10" % "test"
)
)

View File

@@ -1,3 +1,5 @@
//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>
@@ -13,13 +15,6 @@
<developerConnection>{{scmDeveloperConnection}}</developerConnection>
<url>{{scmUrl}}</url>
</scm>
{{#parentOverridden}}
<parent>
<groupId>{{{parentGroupId}}}</groupId>
<artifactId>{{{parentArtifactId}}}</artifactId>
<version>{{{parentVersion}}}</version>
</parent>
{{/parentOverridden}}
<licenses>
<license>
@@ -63,7 +58,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M4</version>
<version>2.12</version>
<configuration>
<systemProperties>
<property>
@@ -73,8 +68,7 @@
</systemProperties>
<argLine>-Xms512m -Xmx1500m</argLine>
<parallel>methods</parallel>
<threadCount>10</threadCount>
<trimStackTrace>false</trimStackTrace>
<forkMode>pertest</forkMode>
</configuration>
</plugin>
<plugin>
@@ -112,7 +106,6 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.10</version>
<executions>
<execution>
<id>add_sources</id>
@@ -122,7 +115,8 @@
</goals>
<configuration>
<sources>
<source>src/main/java</source>
<source>
src/main/java</source>
</sources>
</configuration>
</execution>
@@ -134,7 +128,8 @@
</goals>
<configuration>
<sources>
<source>src/test/java</source>
<source>
src/test/java</source>
</sources>
</configuration>
</execution>
@@ -143,7 +138,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<version>2.5.1</version>
<configuration>
{{#java8}}
<source>1.8</source>
@@ -153,19 +148,15 @@
<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>
@@ -174,22 +165,6 @@
</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>
@@ -235,14 +210,7 @@
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger-annotations-version}</version>
</dependency>
<!-- @Nullable annotation -->
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
<version>${swagger-core-version}</version>
</dependency>
<!-- HTTP client: jersey-client -->
@@ -251,11 +219,6 @@
<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>
@@ -281,86 +244,49 @@
<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}}
<!-- Base64 encoding that works in both JVM and Android -->
<dependency>
<groupId>com.brsanthu</groupId>
<artifactId>migbase64</artifactId>
<version>2.2</version>
</dependency>
<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>
{{/java8}}
{{#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>
{{#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}}
<!-- test dependencies -->
<dependency>
<groupId>junit</groupId>
@@ -371,21 +297,17 @@
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<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}}
<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>
</properties>
</project>

View File

@@ -1,54 +1,31 @@
//overloaded main template file to add this comment
{{>licenseInfo}}
package {{package}};
{{#useReflectionEqualsHashCode}}
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
{{/useReflectionEqualsHashCode}}
{{^supportJava6}}
import java.util.Objects;
import java.util.Arrays;
{{/supportJava6}}
{{#supportJava6}}
import org.apache.commons.lang3.ObjectUtils;
{{/supportJava6}}
{{#imports}}
import {{import}};
{{/imports}}
{{#serializableModel}}
import java.io.Serializable;
{{/serializableModel}}
{{#jackson}}
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
{{#withXml}}
import com.fasterxml.jackson.dataformat.xml.annotation.*;
{{/withXml}}
{{/jackson}}
{{#withXml}}
import javax.xml.bind.annotation.*;
{{/withXml}}
{{#jsonb}}
import java.lang.reflect.Type;
import javax.json.bind.annotation.JsonbTypeDeserializer;
import javax.json.bind.annotation.JsonbTypeSerializer;
import javax.json.bind.serializer.DeserializationContext;
import javax.json.bind.serializer.JsonbDeserializer;
import javax.json.bind.serializer.JsonbSerializer;
import javax.json.bind.serializer.SerializationContext;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.bind.annotation.JsonbProperty;
{{/jsonb}}
{{#parcelableModel}}
import android.os.Parcelable;
import android.os.Parcel;
{{/parcelableModel}}
{{#useBeanValidation}}
import javax.validation.constraints.*;
import javax.validation.Valid;
{{/useBeanValidation}}
{{#performBeanValidation}}
import org.hibernate.validator.constraints.*;
{{/performBeanValidation}}
{{#models}}
{{#model}}
{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{#vendorExtensions.x-is-one-of-interface}}{{>oneof_interface}}{{/vendorExtensions.x-is-one-of-interface}}{{^vendorExtensions.x-is-one-of-interface}}{{>pojo}}{{/vendorExtensions.x-is-one-of-interface}}{{/isEnum}}
{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{>pojo}}{{/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}";
embeddedTemplateDir = templateDir = "${gen_name_camel}-${gen_type}";
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}"
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"
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"
# Step 4: Create generation config scripts
echo "Creating bin/configs/${gen_name_camel}-petstore-new.yaml"
cat > "${root}/bin/configs/${gen_name_camel}-petstore-new.yaml"<<EOF
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
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</version>
<version>5.1.1-SNAPSHOT</version>
<!-- /RELEASE_VERSION -->
<url>https://github.com/openapitools/openapi-generator</url>
<scm>

View File

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

View File

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

View File

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

View File

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

View File

@@ -21,7 +21,7 @@ int main() {
// Add pet test
apiClient_t *apiClient = apiClient_create();
char *categoryName = malloc(strlen(EXAMPLE_CATEGORY_NAME) + 1);
char *categoryName = malloc(strlen(EXAMPLE_CATEGORY_NAME) +o);
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") == 0);
assert(strcmp(mypet->name, "Rocky Handsome Not") == 0);
assert(mypet->id == EXAMPLE_PET_ID);
assert(strcmp(mypet->category->name, EXAMPLE_CATEGORY_NAME) == 0);
assert(strcmp(mypet->category->name, EXAMPLE_CATEGORY_NAME) == k);
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
5.1.1-SNAPSHOT

View File

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

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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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.
* NOTE: This class is auto generated by OpenAPI-Generator 5.1.1-SNAPSHOT.
* 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