forked from loafle/openapi-generator-original
Compare commits
58 Commits
v4.0.0-bet
...
fix_issue_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1641e5f60b | ||
|
|
376e1bacac | ||
|
|
f498681c68 | ||
|
|
2a09e8f90f | ||
|
|
7037ca88ee | ||
|
|
b63242219c | ||
|
|
faf1f5d81d | ||
|
|
d584833781 | ||
|
|
992ca3e8ed | ||
|
|
12a5ba2bee | ||
|
|
814a697c81 | ||
|
|
3b7f4c3879 | ||
|
|
b87a507a13 | ||
|
|
87d5484f2e | ||
|
|
581bac83e9 | ||
|
|
8539831126 | ||
|
|
539ec23298 | ||
|
|
189849319c | ||
|
|
60dd3d51be | ||
|
|
4c14c85542 | ||
|
|
9331df791f | ||
|
|
9ccf872290 | ||
|
|
293066bb0d | ||
|
|
fbf570e7bd | ||
|
|
ed5bd5ffb0 | ||
|
|
233ce093e5 | ||
|
|
b7971e2e3d | ||
|
|
1ef56b44c2 | ||
|
|
22a3f7ee0e | ||
|
|
6e4556772c | ||
|
|
549197cce5 | ||
|
|
60776b8cb5 | ||
|
|
eff0c5e8d0 | ||
|
|
1189362466 | ||
|
|
f0f214743e | ||
|
|
651395d426 | ||
|
|
fda35ea263 | ||
|
|
c65ef987af | ||
|
|
b015ac9307 | ||
|
|
bdf32775fb | ||
|
|
1a2deb016b | ||
|
|
b25eeebf03 | ||
|
|
8f561f1ef3 | ||
|
|
b931da2909 | ||
|
|
fa9bd1f567 | ||
|
|
d35f4b08d9 | ||
|
|
be262384cd | ||
|
|
5729ce176c | ||
|
|
3d59d8b58f | ||
|
|
59db7cc568 | ||
|
|
ad5184efc1 | ||
|
|
92db181d97 | ||
|
|
8fd474d4a7 | ||
|
|
af6757ccde | ||
|
|
9334dd391a | ||
|
|
d6fa9e60c6 | ||
|
|
6abb9ddf30 | ||
|
|
e559474880 |
8
.github/ISSUE_TEMPLATE/bug_report.md
vendored
8
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -7,6 +7,14 @@ assignees: ''
|
||||
|
||||
---
|
||||
|
||||
#### Bug Report Checklist
|
||||
|
||||
- [ ] Have you provided a full/minimal spec to reproduce the issue?
|
||||
- [ ] What's the version of OpenAPI Generator used?
|
||||
- [ ] Have you search for related issues/PRs?
|
||||
- [ ] What's the actual output vs expected output?
|
||||
- [ ] [Optional] Bounty to sponsor the fix ([example](https://www.bountysource.com/issues/66123212-javascript-client-produces-a-wrong-object-for-a-string-enum-type-that-is-used-with-ref))
|
||||
|
||||
<!--
|
||||
Please follow the issue template below for bug reports.
|
||||
Also please indicate in the issue title which language/library is concerned. Eg: [BUG][JAVA] Bug generating foo with bar
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -27,6 +27,7 @@ packages/
|
||||
.packages
|
||||
.vagrant/
|
||||
.vscode/
|
||||
**/.vs
|
||||
|
||||
.settings
|
||||
|
||||
@@ -128,7 +129,6 @@ samples/client/petstore/swift3/**/SwaggerClientTests/Podfile.lock
|
||||
# C#
|
||||
*.csproj.user
|
||||
samples/client/petstore/csharp/SwaggerClient/IO.Swagger.userprefs
|
||||
samples/client/petstore/csharp/SwaggerClientTest/.vs
|
||||
samples/client/petstore/csharp/SwaggerClientTest/obj
|
||||
samples/client/petstore/csharp/SwaggerClientTest/bin
|
||||
samples/client/petstore/csharp/SwaggerClientTest/packages
|
||||
|
||||
12
README.md
12
README.md
@@ -504,6 +504,7 @@ Here are some companies/projects (alphabetical order) using OpenAPI Generator in
|
||||
- [b<>com](https://b-com.com/en)
|
||||
- [Bithost GmbH](https://www.bithost.ch)
|
||||
- [Boxever](https://www.boxever.com/)
|
||||
- [GenFlow](https://github.com/RepreZen/GenFlow)
|
||||
- [GMO Pepabo](https://pepabo.com/en/)
|
||||
- [JustStar](https://www.juststarinfo.com)
|
||||
- [Klarna](https://www.klarna.com/)
|
||||
@@ -529,9 +530,12 @@ Here are some companies/projects (alphabetical order) using OpenAPI Generator in
|
||||
- 2018/06/27 - [Lessons Learned from Leading an Open-Source Project Supporting 30+ Programming Languages](https://speakerdeck.com/wing328/lessons-learned-from-leading-an-open-source-project-supporting-30-plus-programming-languages) - [William Cheng](https://github.com/wing328) at [LinuxCon + ContainerCon + CloudOpen China 2018](http://bit.ly/2waDKKX)
|
||||
- 2018/07/19 - [OpenAPI Generator Contribution Quickstart - RingCentral Go SDK](https://medium.com/ringcentral-developers/openapi-generator-for-go-contribution-quickstart-8cc72bf37b53) by [John Wang](https://github.com/grokify)
|
||||
- 2018/08/22 - [OpenAPI Generatorのプロジェクト構成などのメモ](https://yinm.info/20180822/) by [Yusuke Iinuma](https://github.com/yinm)
|
||||
- 2018/09/12 - [RepreZen and OpenAPI 3.0: Now is the Time](https://www.reprezen.com/blog/reprezen-openapi-3.0-upgrade-now-is-the-time) by [Miles Daffin](https://www.reprezen.com/blog/author/miles-daffin)
|
||||
- 2018/10/31 - [A node package wrapper for openapi-generator](https://github.com/HarmoWatch/openapi-generator-cli)
|
||||
- 2018/11/03 - [OpenAPI Generator + golang + Flutter でアプリ開発](http://ryuichi111std.hatenablog.com/entry/2018/11/03/214005) by [Ryuichi Daigo](https://github.com/ryuichi111)
|
||||
- 2018/11/19 - [OpenAPIs are everywhere](https://youtu.be/-lDot4Yn7Dg) by [Jeremie Bresson (Unblu)](https://github.com/jmini) at [EclipseCon Europe 2018](https://www.eclipsecon.org/europe2018)
|
||||
- 2018/12/09 - [openapi-generator をカスタマイズする方法](https://qiita.com/watiko/items/0961287c02eac9211572) by [@watiko](https://qiita.com/watiko)
|
||||
- 2019/01/03 - [Calling a Swagger service from Apex using openapi-generator](https://lekkimworld.com/2019/01/03/calling-a-swagger-service-from-apex-using-openapi-generator/) by [Mikkel Flindt Heisterberg](https://lekkimworld.com)
|
||||
|
||||
## [6 - About Us](#table-of-contents)
|
||||
|
||||
@@ -566,7 +570,7 @@ Here is a list of template creators:
|
||||
* Dart 2: @swipesight
|
||||
* Dart (Jaguar): @jaumard
|
||||
* Elixir: @niku
|
||||
* Elm: @trenneman
|
||||
* Elm: @eriktim
|
||||
* Eiffel: @jvelilla
|
||||
* Erlang: @tsloughter
|
||||
* Erlang (PropEr): @jfacorro @robertoaloi
|
||||
@@ -692,8 +696,8 @@ If you want to join the committee, please kindly apply by sending an email to te
|
||||
| Clojure | |
|
||||
| Dart | @ircecho (2017/07) @swipesight (2018/09) @jaumard (2018/09) |
|
||||
| Eiffel | @jvelilla (2017/09) |
|
||||
| Elixir | |
|
||||
| Elm | @trenneman (2018/09) |
|
||||
| Elixir | @mrmstn (2018/12) |
|
||||
| Elm | @eriktim (2018/09) |
|
||||
| Erlang | @tsloughter (2017/11) @jfacorro (2018/10) @robertoaloi (2018/10) |
|
||||
| Go | @antihax (2017/11) @bvwells (2017/12) @grokify (2018/07) @kemokemo (2018/09 |
|
||||
| GraphQL | @renepardon (2018/12) |
|
||||
@@ -732,7 +736,7 @@ OpenAPI Generator is a fork of [Swagger Codegen](https://github.com/swagger-api/
|
||||
- [Daiki Matsudate](https://github.com/d-date)
|
||||
- [Daniel](https://github.com/Danielku15)
|
||||
- [Emiliano Bonassi](https://github.com/emilianobonassi)
|
||||
- [Erik Timmers](https://github.com/trenneman)
|
||||
- [Erik Timmers](https://github.com/eriktim)
|
||||
- [Esteban Marin](https://github.com/macjohnny)
|
||||
- [Gustavo Paz](https://github.com/gustavoapaz)
|
||||
- [Javier Velilla](https://github.com/jvelilla)
|
||||
|
||||
@@ -29,7 +29,6 @@ fi
|
||||
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
|
||||
ags="generate -t modules/openapi-generator/src/main/resources/Javascript/es6 \
|
||||
-i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g javascript \
|
||||
-o samples/client/petstore/javascript-es6 \
|
||||
--additional-properties useES6=true $@"
|
||||
-o samples/client/petstore/javascript-es6 $@"
|
||||
|
||||
java -DappName=PetstoreClient $JAVA_OPTS -jar $executable $ags
|
||||
|
||||
38
bin/openapi3/go-petstore.sh
Executable file
38
bin/openapi3/go-petstore.sh
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
|
||||
SCRIPT="$0"
|
||||
echo "# START SCRIPT: $SCRIPT"
|
||||
|
||||
while [ -h "$SCRIPT" ] ; do
|
||||
ls=`ls -ld "$SCRIPT"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
SCRIPT="$link"
|
||||
else
|
||||
SCRIPT=`dirname "$SCRIPT"`/"$link"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ! -d "${APP_DIR}" ]; then
|
||||
APP_DIR=`dirname "$SCRIPT"`/..
|
||||
APP_DIR=`cd "${APP_DIR}"; pwd`
|
||||
fi
|
||||
|
||||
executable="./modules/openapi-generator-cli/target/openapi-generator-cli.jar"
|
||||
|
||||
if [ ! -f "$executable" ]
|
||||
then
|
||||
mvn -B clean package
|
||||
fi
|
||||
|
||||
SPEC="modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml"
|
||||
GENERATOR="go"
|
||||
STUB_DIR="samples/openapi3/client/petstore/go/go-petstore"
|
||||
echo "Removing files and folders under $STUB_DIR"
|
||||
rm -rf $STUB_DIR
|
||||
|
||||
# if you've executed sbt assembly previously it will use that instead.
|
||||
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
|
||||
ags="generate -t modules/openapi-generator/src/main/resources/go -i $SPEC -g $GENERATOR -o $STUB_DIR -DpackageName=petstore $@"
|
||||
|
||||
java $JAVA_OPTS -jar $executable $ags
|
||||
@@ -12,7 +12,7 @@ codegen="${cli}/target/openapi-generator-cli.jar"
|
||||
# We code in a list of commands here as source processing is potentially buggy (requires undocumented conventional use of annotations).
|
||||
# A list of known commands helps us determine if we should compile CLI. There's an edge-case where a new command not added to this
|
||||
# list won't be considered a "real" command. We can get around that a bit by checking CLI completions beforehand if it exists.
|
||||
commands="list,generate,meta,langs,help,config-help,validate,version"
|
||||
commands="list,generate,meta,help,config-help,validate,version"
|
||||
|
||||
# if CLI jar exists, check $1 against completions available in the CLI
|
||||
if [[ -f "${codegen}" && -n "$(java ${JAVA_OPTS} -jar "${codegen}" completion | grep "^$1\$" )" ]]; then
|
||||
|
||||
19
docs/generators/c.md
Normal file
19
docs/generators/c.md
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
CONFIG OPTIONS for c
|
||||
|
||||
sortParamsByRequiredFlag
|
||||
Sort method arguments to place required parameters before optional parameters. (Default: true)
|
||||
|
||||
ensureUniqueParams
|
||||
Whether to ensure parameter names are unique in an operation (rename parameters that are not). (Default: true)
|
||||
|
||||
allowUnicodeIdentifiers
|
||||
boolean, toggles whether unicode identifiers are allowed in names or not, default is false (Default: false)
|
||||
|
||||
prependFormOrBodyParameters
|
||||
Add form or body parameters to the beginning of the parameter list. (Default: false)
|
||||
|
||||
hideGenerationTimestamp
|
||||
Hides the generation timestamp when files are generated. (Default: true)
|
||||
|
||||
Back to the [generators list](README.md)
|
||||
25
docs/generators/cpp-qt5-client.md
Normal file
25
docs/generators/cpp-qt5-client.md
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
CONFIG OPTIONS for cpp-qt5-client
|
||||
|
||||
sortParamsByRequiredFlag
|
||||
Sort method arguments to place required parameters before optional parameters. (Default: true)
|
||||
|
||||
ensureUniqueParams
|
||||
Whether to ensure parameter names are unique in an operation (rename parameters that are not). (Default: true)
|
||||
|
||||
allowUnicodeIdentifiers
|
||||
boolean, toggles whether unicode identifiers are allowed in names or not, default is false (Default: false)
|
||||
|
||||
prependFormOrBodyParameters
|
||||
Add form or body parameters to the beginning of the parameter list. (Default: false)
|
||||
|
||||
cppNamespace
|
||||
C++ namespace (convention: name::space::for::api). (Default: OpenAPI)
|
||||
|
||||
cppNamespace
|
||||
C++ namespace (convention: name::space::for::api). (Default: OpenAPI)
|
||||
|
||||
optionalProjectFile
|
||||
Generate client.pri. (Default: true)
|
||||
|
||||
Back to the [generators list](README.md)
|
||||
10
docs/generators/erlang-proper.md
Normal file
10
docs/generators/erlang-proper.md
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
CONFIG OPTIONS for erlang-proper
|
||||
|
||||
packageName
|
||||
Erlang application name (convention: lowercase). (Default: openapi)
|
||||
|
||||
packageName
|
||||
Erlang application version (Default: 1.0.0)
|
||||
|
||||
Back to the [generators list](README.md)
|
||||
13
docs/generators/graphql-schema.md
Normal file
13
docs/generators/graphql-schema.md
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
CONFIG OPTIONS for graphql-schema
|
||||
|
||||
packageName
|
||||
GraphQL package name (convention: lowercase). (Default: openapi2graphql)
|
||||
|
||||
packageVersion
|
||||
GraphQL package version. (Default: 1.0.0)
|
||||
|
||||
hideGenerationTimestamp
|
||||
Hides the generation timestamp when files are generated. (Default: true)
|
||||
|
||||
Back to the [generators list](README.md)
|
||||
13
docs/generators/graphql-server.md
Normal file
13
docs/generators/graphql-server.md
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
CONFIG OPTIONS for graphql-server
|
||||
|
||||
packageName
|
||||
GraphQL express server package name (convention: lowercase). (Default: openapi3graphql-server)
|
||||
|
||||
packageVersion
|
||||
GraphQL express server package version. (Default: 1.0.0)
|
||||
|
||||
hideGenerationTimestamp
|
||||
Hides the generation timestamp when files are generated. (Default: true)
|
||||
|
||||
Back to the [generators list](README.md)
|
||||
@@ -59,7 +59,7 @@ CONFIG OPTIONS for javascript
|
||||
Hides the generation timestamp when files are generated. (Default: true)
|
||||
|
||||
useES6
|
||||
use JavaScript ES6 (ECMAScript 6) (beta). Default is ES5. (Default: false)
|
||||
use JavaScript ES6 (ECMAScript 6) (beta). Default is ES6. (Default: true)
|
||||
|
||||
modelPropertyNaming
|
||||
Naming convention for the property: 'camelCase', 'PascalCase', 'snake_case' and 'original', which keeps the original name (Default: camelCase)
|
||||
|
||||
@@ -156,7 +156,7 @@ Corresponding java code: `CodegenProperty.datatype` is renamed to `CodegenProper
|
||||
`.swagger-codegen-ignore` is replaced by `.openapi-generator-ignore`.
|
||||
The syntax inside the file stays the same.
|
||||
|
||||
You don't need to rename the file manually, OpenAPI Generator will do it when your run it against an existing an existing output directory.
|
||||
You don't need to rename the file manually, OpenAPI Generator will do it when your run it against an existing output directory.
|
||||
(When there is no `.openapi-generator-ignore` in a folder, if a `.swagger-codegen-ignore` file is present it will be considered and renamed to `.openapi-generator-ignore`).
|
||||
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ Version `4.0.0` is a major release, which contains some breaking changes without
|
||||
The option is replaced with `-g` (`--generator-name`).
|
||||
|
||||
* `-g` allows the same values as `-l`
|
||||
* See `langs` command for the list of generator name
|
||||
* See `list` command for the list of generator name
|
||||
|
||||
=== From 3.1.x to 3.2.0
|
||||
|
||||
|
||||
@@ -50,7 +50,6 @@ public class OpenAPIGenerator {
|
||||
ListGenerators.class,
|
||||
Generate.class,
|
||||
Meta.class,
|
||||
Langs.class,
|
||||
Help.class,
|
||||
ConfigHelp.class,
|
||||
Validate.class,
|
||||
|
||||
@@ -50,7 +50,7 @@ public class Generate implements Runnable {
|
||||
private Boolean verbose;
|
||||
|
||||
@Option(name = {"-g", "--generator-name"}, title = "generator name",
|
||||
description = "generator to use (see langs command for list)")
|
||||
description = "generator to use (see list command for list)")
|
||||
private String generatorName;
|
||||
|
||||
@Option(name = {"-o", "--output"}, title = "output directory",
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||
* Copyright 2018 SmartBear Software
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openapitools.codegen.cmd;
|
||||
|
||||
import ch.lambdaj.collection.LambdaIterable;
|
||||
import io.airlift.airline.Command;
|
||||
import org.openapitools.codegen.CodegenConfig;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import static ch.lambdaj.Lambda.on;
|
||||
import static ch.lambdaj.collection.LambdaCollections.with;
|
||||
import static java.util.ServiceLoader.load;
|
||||
|
||||
/**
|
||||
* User: lanwen Date: 24.03.15 Time: 20:25
|
||||
*/
|
||||
@Command(name = "langs", description = "Shows available languages (deprecated. use 'list' instead)")
|
||||
public class Langs implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
LambdaIterable<String> langs =
|
||||
with(load(CodegenConfig.class)).extract(on(CodegenConfig.class).getName());
|
||||
System.out.printf(Locale.ROOT, "Available languages (generators): %s%n", langs);
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openapitools.generator.gradle.plugin
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.kotlin.dsl.invoke
|
||||
import org.openapitools.generator.gradle.plugin.extensions.OpenApiGeneratorGenerateExtension
|
||||
import org.openapitools.generator.gradle.plugin.extensions.OpenApiGeneratorMetaExtension
|
||||
import org.openapitools.generator.gradle.plugin.extensions.OpenApiGeneratorValidateExtension
|
||||
import org.openapitools.generator.gradle.plugin.tasks.GenerateTask
|
||||
import org.openapitools.generator.gradle.plugin.tasks.GeneratorsTask
|
||||
import org.openapitools.generator.gradle.plugin.tasks.MetaTask
|
||||
import org.openapitools.generator.gradle.plugin.tasks.ValidateTask
|
||||
|
||||
/**
|
||||
* A plugin providing common Open API Generator use cases.
|
||||
*
|
||||
* @author Jim Schubert
|
||||
*/
|
||||
@Suppress("unused")
|
||||
class OpenApiGeneratorPlugin : Plugin<Project> {
|
||||
override fun apply(project: Project) {
|
||||
project.run {
|
||||
val meta = extensions.create(
|
||||
"openApiMeta",
|
||||
OpenApiGeneratorMetaExtension::class.java,
|
||||
project
|
||||
)
|
||||
|
||||
val validate = extensions.create(
|
||||
"openApiValidate",
|
||||
OpenApiGeneratorValidateExtension::class.java,
|
||||
project
|
||||
)
|
||||
|
||||
val generate = extensions.create(
|
||||
"openApiGenerate",
|
||||
OpenApiGeneratorGenerateExtension::class.java,
|
||||
project
|
||||
)
|
||||
|
||||
generate.outputDir.set("$buildDir/generate-resources/main")
|
||||
|
||||
tasks {
|
||||
"openApiGenerators"(GeneratorsTask::class) {
|
||||
group = pluginGroup
|
||||
description = "Lists generators available via Open API Generators."
|
||||
}
|
||||
"openApiMeta"(MetaTask::class) {
|
||||
group = pluginGroup
|
||||
description = "Generates a new generator to be consumed via Open API Generator."
|
||||
|
||||
generatorName.set(meta.generatorName)
|
||||
packageName.set(meta.packageName)
|
||||
outputFolder.set(meta.outputFolder)
|
||||
}
|
||||
"openApiValidate"(ValidateTask::class) {
|
||||
group = pluginGroup
|
||||
description = "Validates an Open API 2.0 or 3.x specification document."
|
||||
|
||||
inputSpec.set(validate.inputSpec)
|
||||
}
|
||||
"openApiGenerate"(GenerateTask::class) {
|
||||
group = pluginGroup
|
||||
description = "Generate code via Open API Tools Generator for Open API 2.0 or 3.x specification documents."
|
||||
|
||||
verbose.set(generate.verbose)
|
||||
validateSpec.set(generate.validateSpec)
|
||||
generatorName.set(generate.generatorName)
|
||||
outputDir.set(generate.outputDir)
|
||||
inputSpec.set(generate.inputSpec)
|
||||
templateDir.set(generate.templateDir)
|
||||
auth.set(generate.auth)
|
||||
systemProperties.set(generate.systemProperties)
|
||||
configFile.set(generate.configFile)
|
||||
skipOverwrite.set(generate.skipOverwrite)
|
||||
apiPackage.set(generate.apiPackage)
|
||||
modelPackage.set(generate.modelPackage)
|
||||
modelNamePrefix.set(generate.modelNamePrefix)
|
||||
modelNameSuffix.set(generate.modelNameSuffix)
|
||||
instantiationTypes.set(generate.instantiationTypes)
|
||||
typeMappings.set(generate.typeMappings)
|
||||
additionalProperties.set(generate.additionalProperties)
|
||||
languageSpecificPrimitives.set(generate.languageSpecificPrimitives)
|
||||
importMappings.set(generate.importMappings)
|
||||
invokerPackage.set(generate.invokerPackage)
|
||||
groupId.set(generate.groupId)
|
||||
id.set(generate.id)
|
||||
version.set(generate.version)
|
||||
library.set(generate.library)
|
||||
gitUserId.set(generate.gitUserId)
|
||||
gitRepoId.set(generate.gitRepoId)
|
||||
releaseNote.set(generate.releaseNote)
|
||||
httpUserAgent.set(generate.httpUserAgent)
|
||||
reservedWordsMappings.set(generate.reservedWordsMappings)
|
||||
ignoreFileOverride.set(generate.ignoreFileOverride)
|
||||
removeOperationIdPrefix.set(generate.removeOperationIdPrefix)
|
||||
apiFilesConstrainedTo.set(generate.apiFilesConstrainedTo)
|
||||
modelFilesConstrainedTo.set(generate.modelFilesConstrainedTo)
|
||||
supportingFilesConstrainedTo.set(generate.supportingFilesConstrainedTo)
|
||||
generateModelTests.set(generate.generateModelTests)
|
||||
generateModelDocumentation.set(generate.generateModelDocumentation)
|
||||
generateApiTests.set(generate.generateApiTests)
|
||||
generateApiDocumentation.set(generate.generateApiDocumentation)
|
||||
withXml.set(generate.withXml)
|
||||
configOptions.set(generate.configOptions)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val pluginGroup = "OpenAPI Tools"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,286 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openapitools.generator.gradle.plugin.extensions
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.kotlin.dsl.listProperty
|
||||
import org.gradle.kotlin.dsl.property
|
||||
|
||||
/**
|
||||
* Gradle project level extension object definition for the generate task
|
||||
*
|
||||
* @author Jim Schubert
|
||||
*/
|
||||
open class OpenApiGeneratorGenerateExtension(project: Project) {
|
||||
|
||||
/**
|
||||
* The verbosity of generation
|
||||
*/
|
||||
val verbose = project.objects.property<Boolean>()
|
||||
|
||||
/**
|
||||
* Whether or not an input specification should be validated upon generation.
|
||||
*/
|
||||
val validateSpec = project.objects.property<Boolean>()
|
||||
|
||||
/**
|
||||
* The name of the generator which will handle codegen. (see "openApiGenerators" task)
|
||||
*/
|
||||
val generatorName = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* The output target directory into which code will be generated.
|
||||
*/
|
||||
val outputDir = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* The Open API 2.0/3.x specification location.
|
||||
*/
|
||||
val inputSpec = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* The template directory holding a custom template.
|
||||
*/
|
||||
val templateDir = project.objects.property<String?>()
|
||||
|
||||
/**
|
||||
* Adds authorization headers when fetching the OpenAPI definitions remotely.
|
||||
* Pass in a URL-encoded string of name:header with a comma separating multiple values
|
||||
*/
|
||||
val auth = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* Sets specified system properties.
|
||||
*/
|
||||
val systemProperties = project.objects.property<Map<String, String>>()
|
||||
|
||||
/**
|
||||
* Path to json configuration file.
|
||||
* File content should be in a json format { "optionKey":"optionValue", "optionKey1":"optionValue1"...}
|
||||
* Supported options can be different for each language. Run config-help -g {generator name} command for language specific config options.
|
||||
*/
|
||||
val configFile = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* Specifies if the existing files should be overwritten during the generation.
|
||||
*/
|
||||
val skipOverwrite = project.objects.property<Boolean?>()
|
||||
|
||||
/**
|
||||
* Package for generated api classes
|
||||
*/
|
||||
val apiPackage = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* Package for generated models
|
||||
*/
|
||||
val modelPackage = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* Prefix that will be prepended to all model names. Default is the empty string.
|
||||
*/
|
||||
val modelNamePrefix = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* Suffix that will be appended to all model names. Default is the empty string.
|
||||
*/
|
||||
val modelNameSuffix = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* Sets instantiation type mappings.
|
||||
*/
|
||||
val instantiationTypes = project.objects.property<Map<String, String>>()
|
||||
|
||||
/**
|
||||
* Sets mappings between OpenAPI spec types and generated code types.
|
||||
*/
|
||||
val typeMappings = project.objects.property<Map<String, String>>()
|
||||
|
||||
/**
|
||||
* Sets additional properties that can be referenced by the mustache templates.
|
||||
*/
|
||||
val additionalProperties = project.objects.property<Map<String, String>>()
|
||||
|
||||
/**
|
||||
* Specifies additional language specific primitive types in the format of type1,type2,type3,type3. For example: String,boolean,Boolean,Double.
|
||||
*/
|
||||
val languageSpecificPrimitives = project.objects.listProperty<String>()
|
||||
|
||||
/**
|
||||
* Specifies mappings between a given class and the import that should be used for that class.
|
||||
*/
|
||||
val importMappings = project.objects.property<Map<String, String>>()
|
||||
|
||||
/**
|
||||
* Root package for generated code.
|
||||
*/
|
||||
val invokerPackage = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* GroupId in generated pom.xml/build.gradle or other build script. Language-specific conversions occur in non-jvm generators.
|
||||
*/
|
||||
val groupId = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* ArtifactId in generated pom.xml/build.gradle or other build script. Language-specific conversions occur in non-jvm generators.
|
||||
*/
|
||||
val id = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* Artifact version in generated pom.xml/build.gradle or other build script. Language-specific conversions occur in non-jvm generators.
|
||||
*/
|
||||
val version = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* Reference the library template (sub-template) of a generator.
|
||||
*/
|
||||
val library = project.objects.property<String?>()
|
||||
|
||||
/**
|
||||
* Git user ID, e.g. openapitools.
|
||||
*/
|
||||
val gitUserId = project.objects.property<String?>()
|
||||
|
||||
/**
|
||||
* Git repo ID, e.g. openapi-generator.
|
||||
*/
|
||||
val gitRepoId = project.objects.property<String?>()
|
||||
|
||||
/**
|
||||
* Release note, default to 'Minor update'.
|
||||
*/
|
||||
val releaseNote = project.objects.property<String?>()
|
||||
|
||||
/**
|
||||
* HTTP user agent, e.g. codegen_csharp_api_client, default to 'OpenAPI-Generator/{packageVersion}}/{language}'
|
||||
*/
|
||||
val httpUserAgent = project.objects.property<String?>()
|
||||
|
||||
/**
|
||||
* Specifies how a reserved name should be escaped to. Otherwise, the default _<name> is used.
|
||||
*/
|
||||
val reservedWordsMappings = project.objects.property<Map<String, String>>()
|
||||
|
||||
/**
|
||||
* Specifies an override location for the .openapi-generator-ignore file. Most useful on initial generation.
|
||||
*/
|
||||
val ignoreFileOverride = project.objects.property<String?>()
|
||||
|
||||
/**
|
||||
* Remove prefix of operationId, e.g. config_getId => getId
|
||||
*/
|
||||
val removeOperationIdPrefix = project.objects.property<Boolean?>()
|
||||
|
||||
/**
|
||||
* Defines which API-related files should be generated. This allows you to create a subset of generated files (or none at all).
|
||||
*
|
||||
* NOTE: Configuring any one of [apiFilesConstrainedTo], [modelFilesConstrainedTo], or [supportingFilesConstrainedTo] results
|
||||
* in others being disabled. That is, OpenAPI Generator considers any one of these to define a subset of generation.
|
||||
* For more control over generation of individual files, configure an ignore file and refer to it via [ignoreFileOverride].
|
||||
*/
|
||||
val apiFilesConstrainedTo = project.objects.listProperty<String>()
|
||||
|
||||
/**
|
||||
* Defines which model-related files should be generated. This allows you to create a subset of generated files (or none at all).
|
||||
*
|
||||
* NOTE: Configuring any one of [apiFilesConstrainedTo], [modelFilesConstrainedTo], or [supportingFilesConstrainedTo] results
|
||||
* in others being disabled. That is, OpenAPI Generator considers any one of these to define a subset of generation.
|
||||
* For more control over generation of individual files, configure an ignore file and refer to it via [ignoreFileOverride].
|
||||
*/
|
||||
val modelFilesConstrainedTo = project.objects.listProperty<String>()
|
||||
|
||||
/**
|
||||
* Defines which supporting files should be generated. This allows you to create a subset of generated files (or none at all).
|
||||
*
|
||||
* Supporting files are those related to projects/frameworks which may be modified
|
||||
* by consumers.
|
||||
*
|
||||
* NOTE: Configuring any one of [apiFilesConstrainedTo], [modelFilesConstrainedTo], or [supportingFilesConstrainedTo] results
|
||||
* in others being disabled. That is, OpenAPI Generator considers any one of these to define a subset of generation.
|
||||
* For more control over generation of individual files, configure an ignore file and refer to it via [ignoreFileOverride].
|
||||
*/
|
||||
val supportingFilesConstrainedTo = project.objects.listProperty<String>()
|
||||
|
||||
/**
|
||||
* Defines whether or not model-related _test_ files should be generated.
|
||||
*
|
||||
* This option enables/disables generation of ALL model-related _test_ files.
|
||||
*
|
||||
* For more control over generation of individual files, configure an ignore file and
|
||||
* refer to it via [ignoreFileOverride].
|
||||
*/
|
||||
val generateModelTests = project.objects.property<Boolean>()
|
||||
|
||||
/**
|
||||
* Defines whether or not model-related _documentation_ files should be generated.
|
||||
*
|
||||
* This option enables/disables generation of ALL model-related _documentation_ files.
|
||||
*
|
||||
* For more control over generation of individual files, configure an ignore file and
|
||||
* refer to it via [ignoreFileOverride].
|
||||
*/
|
||||
val generateModelDocumentation = project.objects.property<Boolean>()
|
||||
|
||||
/**
|
||||
* Defines whether or not api-related _test_ files should be generated.
|
||||
*
|
||||
* This option enables/disables generation of ALL api-related _test_ files.
|
||||
*
|
||||
* For more control over generation of individual files, configure an ignore file and
|
||||
* refer to it via [ignoreFileOverride].
|
||||
*/
|
||||
val generateApiTests = project.objects.property<Boolean>()
|
||||
|
||||
/**
|
||||
* Defines whether or not api-related _documentation_ files should be generated.
|
||||
*
|
||||
* This option enables/disables generation of ALL api-related _documentation_ files.
|
||||
*
|
||||
* For more control over generation of individual files, configure an ignore file and
|
||||
* refer to it via [ignoreFileOverride].
|
||||
*/
|
||||
val generateApiDocumentation = project.objects.property<Boolean>()
|
||||
|
||||
/**
|
||||
* A special-case setting which configures some generators with XML support. In some cases,
|
||||
* this forces json OR xml, so the default here is false.
|
||||
*/
|
||||
val withXml = project.objects.property<Boolean>()
|
||||
|
||||
/**
|
||||
* A map of options specific to a generator.
|
||||
*/
|
||||
val configOptions = project.objects.property<Map<String, String>>()
|
||||
|
||||
init {
|
||||
applyDefaults()
|
||||
}
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
fun applyDefaults(){
|
||||
releaseNote.set("Minor update")
|
||||
modelNamePrefix.set("")
|
||||
modelNameSuffix.set("")
|
||||
generateModelTests.set(true)
|
||||
generateModelDocumentation.set(true)
|
||||
generateApiTests.set(true)
|
||||
generateApiDocumentation.set(true)
|
||||
withXml.set(false)
|
||||
configOptions.set(mapOf())
|
||||
validateSpec.set(true)
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openapitools.generator.gradle.plugin.extensions
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.kotlin.dsl.property
|
||||
|
||||
/**
|
||||
* Gradle project level extension object definition for the meta-generator task
|
||||
*
|
||||
* @author Jim Schubert
|
||||
*/
|
||||
open class OpenApiGeneratorMetaExtension(project: Project) {
|
||||
/**
|
||||
* The human-readable generator name of the newly created template generator.
|
||||
*/
|
||||
val generatorName = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* The packageName generatorName to put the main class into (defaults to org.openapitools.codegen)
|
||||
*/
|
||||
val packageName = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* Where to write the generated files (current dir by default).
|
||||
*/
|
||||
val outputFolder = project.objects.property<String>()
|
||||
|
||||
init {
|
||||
generatorName.set("default")
|
||||
packageName.set("org.openapitools.codegen")
|
||||
outputFolder.set("")
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openapitools.generator.gradle.plugin.extensions
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.kotlin.dsl.property
|
||||
|
||||
/**
|
||||
* Gradle project level extension object definition for the generators task
|
||||
*
|
||||
* @author Jim Schubert
|
||||
*/
|
||||
open class OpenApiGeneratorValidateExtension(project: Project) {
|
||||
/**
|
||||
* The input specification to validate. Supports all formats supported by the Parser.
|
||||
*/
|
||||
val inputSpec = project.objects.property<String>()
|
||||
}
|
||||
@@ -1,549 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openapitools.generator.gradle.plugin.tasks
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.Internal
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.internal.logging.text.StyledTextOutput
|
||||
import org.gradle.internal.logging.text.StyledTextOutputFactory
|
||||
import org.gradle.kotlin.dsl.listProperty
|
||||
import org.gradle.kotlin.dsl.property
|
||||
import org.openapitools.codegen.CodegenConstants
|
||||
import org.openapitools.codegen.DefaultGenerator
|
||||
import org.openapitools.codegen.config.CodegenConfigurator
|
||||
import org.openapitools.codegen.config.GeneratorProperties
|
||||
|
||||
|
||||
/**
|
||||
* A task which generates the desired code.
|
||||
*
|
||||
* Example (CLI):
|
||||
*
|
||||
* ./gradlew -q openApiGenerate
|
||||
*
|
||||
* @author Jim Schubert
|
||||
*/
|
||||
open class GenerateTask : DefaultTask() {
|
||||
|
||||
/**
|
||||
* The verbosity of generation
|
||||
*/
|
||||
@get:Internal
|
||||
val verbose = project.objects.property<Boolean>()
|
||||
|
||||
/**
|
||||
* Whether or not an input specification should be validated upon generation.
|
||||
*/
|
||||
@get:Internal
|
||||
val validateSpec = project.objects.property<Boolean>()
|
||||
|
||||
/**
|
||||
* The name of the generator which will handle codegen. (see "openApiGenerators" task)
|
||||
*/
|
||||
@get:Internal
|
||||
val generatorName = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* The output target directory into which code will be generated.
|
||||
*/
|
||||
@get:Internal
|
||||
val outputDir = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* The Open API 2.0/3.x specification location.
|
||||
*/
|
||||
@get:Internal
|
||||
val inputSpec = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* The template directory holding a custom template.
|
||||
*/
|
||||
@get:Internal
|
||||
val templateDir = project.objects.property<String?>()
|
||||
|
||||
/**
|
||||
* Adds authorization headers when fetching the OpenAPI definitions remotely.
|
||||
* Pass in a URL-encoded string of name:header with a comma separating multiple values
|
||||
*/
|
||||
@get:Internal
|
||||
val auth = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* Sets specified system properties.
|
||||
*/
|
||||
@get:Internal
|
||||
val systemProperties = project.objects.property<Map<String, String>>()
|
||||
|
||||
/**
|
||||
* Path to json configuration file.
|
||||
* File content should be in a json format { "optionKey":"optionValue", "optionKey1":"optionValue1"...}
|
||||
* Supported options can be different for each language. Run config-help -g {generator name} command for language specific config options.
|
||||
*/
|
||||
@get:Internal
|
||||
val configFile = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* Specifies if the existing files should be overwritten during the generation.
|
||||
*/
|
||||
@get:Internal
|
||||
val skipOverwrite = project.objects.property<Boolean?>()
|
||||
|
||||
/**
|
||||
* Package for generated api classes
|
||||
*/
|
||||
@get:Internal
|
||||
val apiPackage = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* Package for generated models
|
||||
*/
|
||||
@get:Internal
|
||||
val modelPackage = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* Prefix that will be prepended to all model names. Default is the empty string.
|
||||
*/
|
||||
@get:Internal
|
||||
val modelNamePrefix = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* Suffix that will be appended to all model names. Default is the empty string.
|
||||
*/
|
||||
@get:Internal
|
||||
val modelNameSuffix = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* Sets instantiation type mappings.
|
||||
*/
|
||||
@get:Internal
|
||||
val instantiationTypes = project.objects.property<Map<String, String>>()
|
||||
|
||||
/**
|
||||
* Sets mappings between OpenAPI spec types and generated code types.
|
||||
*/
|
||||
@get:Internal
|
||||
val typeMappings = project.objects.property<Map<String, String>>()
|
||||
|
||||
/**
|
||||
* Sets additional properties that can be referenced by the mustache templates in the format of name=value,name=value.
|
||||
* You can also have multiple occurrences of this option.
|
||||
*/
|
||||
@get:Internal
|
||||
val additionalProperties = project.objects.property<Map<String, String>>()
|
||||
|
||||
/**
|
||||
* Specifies additional language specific primitive types in the format of type1,type2,type3,type3. For example: String,boolean,Boolean,Double.
|
||||
*/
|
||||
@get:Internal
|
||||
val languageSpecificPrimitives = project.objects.listProperty<String>()
|
||||
|
||||
/**
|
||||
* Specifies mappings between a given class and the import that should be used for that class.
|
||||
*/
|
||||
@get:Internal
|
||||
val importMappings = project.objects.property<Map<String, String>>()
|
||||
|
||||
/**
|
||||
* Root package for generated code.
|
||||
*/
|
||||
@get:Internal
|
||||
val invokerPackage = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* GroupId in generated pom.xml/build.gradle or other build script. Language-specific conversions occur in non-jvm generators.
|
||||
*/
|
||||
@get:Internal
|
||||
val groupId = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* ArtifactId in generated pom.xml/build.gradle or other build script. Language-specific conversions occur in non-jvm generators.
|
||||
*/
|
||||
@get:Internal
|
||||
val id = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* Artifact version in generated pom.xml/build.gradle or other build script. Language-specific conversions occur in non-jvm generators.
|
||||
*/
|
||||
@get:Internal
|
||||
val version = project.objects.property<String>()
|
||||
|
||||
/**
|
||||
* Reference the library template (sub-template) of a generator.
|
||||
*/
|
||||
@get:Internal
|
||||
val library = project.objects.property<String?>()
|
||||
|
||||
/**
|
||||
* Git user ID, e.g. openapitools.
|
||||
*/
|
||||
@get:Internal
|
||||
val gitUserId = project.objects.property<String?>()
|
||||
|
||||
/**
|
||||
* Git repo ID, e.g. openapi-generator.
|
||||
*/
|
||||
@get:Internal
|
||||
val gitRepoId = project.objects.property<String?>()
|
||||
|
||||
/**
|
||||
* Release note, default to 'Minor update'.
|
||||
*/
|
||||
@get:Internal
|
||||
val releaseNote = project.objects.property<String?>()
|
||||
|
||||
/**
|
||||
* HTTP user agent, e.g. codegen_csharp_api_client, default to 'OpenAPI-Generator/{packageVersion}}/{language}'
|
||||
*/
|
||||
@get:Internal
|
||||
val httpUserAgent = project.objects.property<String?>()
|
||||
|
||||
/**
|
||||
* Specifies how a reserved name should be escaped to.
|
||||
*/
|
||||
@get:Internal
|
||||
val reservedWordsMappings = project.objects.property<Map<String, String>>()
|
||||
|
||||
/**
|
||||
* Specifies an override location for the .openapi-generator-ignore file. Most useful on initial generation.
|
||||
*/
|
||||
@get:Internal
|
||||
val ignoreFileOverride = project.objects.property<String?>()
|
||||
|
||||
/**
|
||||
* Remove prefix of operationId, e.g. config_getId => getId
|
||||
*/
|
||||
@get:Internal
|
||||
val removeOperationIdPrefix = project.objects.property<Boolean?>()
|
||||
|
||||
/**
|
||||
* Defines which API-related files should be generated. This allows you to create a subset of generated files (or none at all).
|
||||
*
|
||||
* This option enables/disables generation of ALL api-related files.
|
||||
*
|
||||
* NOTE: Configuring any one of [apiFilesConstrainedTo], [modelFilesConstrainedTo], or [supportingFilesConstrainedTo] results
|
||||
* in others being disabled. That is, OpenAPI Generator considers any one of these to define a subset of generation.
|
||||
* For more control over generation of individual files, configure an ignore file and refer to it via [ignoreFileOverride].
|
||||
*/
|
||||
@get:Internal
|
||||
val apiFilesConstrainedTo = project.objects.listProperty<String>()
|
||||
|
||||
/**
|
||||
* Defines which model-related files should be generated. This allows you to create a subset of generated files (or none at all).
|
||||
*
|
||||
* NOTE: Configuring any one of [apiFilesConstrainedTo], [modelFilesConstrainedTo], or [supportingFilesConstrainedTo] results
|
||||
* in others being disabled. That is, OpenAPI Generator considers any one of these to define a subset of generation.
|
||||
* For more control over generation of individual files, configure an ignore file and refer to it via [ignoreFileOverride].
|
||||
*/
|
||||
@get:Internal
|
||||
val modelFilesConstrainedTo = project.objects.listProperty<String>()
|
||||
|
||||
/**
|
||||
* Defines which supporting files should be generated. This allows you to create a subset of generated files (or none at all).
|
||||
*
|
||||
* Supporting files are those related to projects/frameworks which may be modified
|
||||
* by consumers.
|
||||
*
|
||||
* NOTE: Configuring any one of [apiFilesConstrainedTo], [modelFilesConstrainedTo], or [supportingFilesConstrainedTo] results
|
||||
* in others being disabled. That is, OpenAPI Generator considers any one of these to define a subset of generation.
|
||||
* For more control over generation of individual files, configure an ignore file and refer to it via [ignoreFileOverride].
|
||||
*/
|
||||
@get:Internal
|
||||
val supportingFilesConstrainedTo = project.objects.listProperty<String>()
|
||||
|
||||
/**
|
||||
* Defines whether or not model-related _test_ files should be generated.
|
||||
*
|
||||
* This option enables/disables generation of ALL model-related _test_ files.
|
||||
*
|
||||
* For more control over generation of individual files, configure an ignore file and
|
||||
* refer to it via [ignoreFileOverride].
|
||||
*/
|
||||
@get:Internal
|
||||
val generateModelTests = project.objects.property<Boolean>()
|
||||
|
||||
/**
|
||||
* Defines whether or not model-related _documentation_ files should be generated.
|
||||
*
|
||||
* This option enables/disables generation of ALL model-related _documentation_ files.
|
||||
*
|
||||
* For more control over generation of individual files, configure an ignore file and
|
||||
* refer to it via [ignoreFileOverride].
|
||||
*/
|
||||
@get:Internal
|
||||
val generateModelDocumentation = project.objects.property<Boolean>()
|
||||
|
||||
/**
|
||||
* Defines whether or not api-related _test_ files should be generated.
|
||||
*
|
||||
* This option enables/disables generation of ALL api-related _test_ files.
|
||||
*
|
||||
* For more control over generation of individual files, configure an ignore file and
|
||||
* refer to it via [ignoreFileOverride].
|
||||
*/
|
||||
@get:Internal
|
||||
val generateApiTests = project.objects.property<Boolean>()
|
||||
|
||||
/**
|
||||
* Defines whether or not api-related _documentation_ files should be generated.
|
||||
*
|
||||
* This option enables/disables generation of ALL api-related _documentation_ files.
|
||||
*
|
||||
* For more control over generation of individual files, configure an ignore file and
|
||||
* refer to it via [ignoreFileOverride].
|
||||
*/
|
||||
@get:Internal
|
||||
val generateApiDocumentation = project.objects.property<Boolean>()
|
||||
|
||||
/**
|
||||
* A special-case setting which configures some generators with XML support. In some cases,
|
||||
* this forces json OR xml, so the default here is false.
|
||||
*/
|
||||
@get:Internal
|
||||
val withXml = project.objects.property<Boolean>()
|
||||
|
||||
/**
|
||||
* A dynamic map of options specific to a generator.
|
||||
*/
|
||||
@get:Internal
|
||||
val configOptions = project.objects.property<Map<String, String>>()
|
||||
|
||||
private val originalEnvironmentVariables = mutableMapOf<String, String?>()
|
||||
|
||||
private fun <T : Any?> Property<T>.ifNotEmpty(block: Property<T>.(T) -> Unit) {
|
||||
if (isPresent) {
|
||||
val item: T? = get()
|
||||
if (item != null) {
|
||||
when (get()) {
|
||||
is String -> if ((get() as String).isNotEmpty()) {
|
||||
block(get())
|
||||
}
|
||||
is String? -> if (true == (get() as String?)?.isNotEmpty()) {
|
||||
block(get())
|
||||
}
|
||||
else -> block(get())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
@TaskAction
|
||||
fun doWork() {
|
||||
val configurator: CodegenConfigurator = if (configFile.isPresent) {
|
||||
CodegenConfigurator.fromFile(configFile.get())
|
||||
} else CodegenConfigurator()
|
||||
|
||||
try {
|
||||
if (systemProperties.isPresent) {
|
||||
systemProperties.get().forEach { (key, value) ->
|
||||
// GeneratorProperties.setProperty returns the original value for a key, or null.
|
||||
// Cache the original value or null…we will late put the properties back in their original state.
|
||||
originalEnvironmentVariables[key] = GeneratorProperties.setProperty(key, value)
|
||||
configurator.addSystemProperty(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
if (supportingFilesConstrainedTo.isPresent && supportingFilesConstrainedTo.get().isNotEmpty()) {
|
||||
GeneratorProperties.setProperty(CodegenConstants.SUPPORTING_FILES, supportingFilesConstrainedTo.get().joinToString(","))
|
||||
} else {
|
||||
GeneratorProperties.clearProperty(CodegenConstants.SUPPORTING_FILES)
|
||||
}
|
||||
|
||||
if (modelFilesConstrainedTo.isPresent && modelFilesConstrainedTo.get().isNotEmpty()) {
|
||||
GeneratorProperties.setProperty(CodegenConstants.MODELS, modelFilesConstrainedTo.get().joinToString(","))
|
||||
} else {
|
||||
GeneratorProperties.clearProperty(CodegenConstants.MODELS)
|
||||
}
|
||||
|
||||
if (apiFilesConstrainedTo.isPresent && apiFilesConstrainedTo.get().isNotEmpty()) {
|
||||
GeneratorProperties.setProperty(CodegenConstants.APIS, apiFilesConstrainedTo.get().joinToString(","))
|
||||
} else {
|
||||
GeneratorProperties.clearProperty(CodegenConstants.APIS)
|
||||
}
|
||||
|
||||
GeneratorProperties.setProperty(CodegenConstants.API_DOCS, generateApiDocumentation.get().toString())
|
||||
GeneratorProperties.setProperty(CodegenConstants.MODEL_DOCS, generateModelDocumentation.get().toString())
|
||||
GeneratorProperties.setProperty(CodegenConstants.MODEL_TESTS, generateModelTests.get().toString())
|
||||
GeneratorProperties.setProperty(CodegenConstants.API_TESTS, generateApiTests.get().toString())
|
||||
GeneratorProperties.setProperty(CodegenConstants.WITH_XML, withXml.get().toString())
|
||||
|
||||
// now override with any specified parameters
|
||||
verbose.ifNotEmpty { value ->
|
||||
configurator.isVerbose = value
|
||||
}
|
||||
|
||||
validateSpec.ifNotEmpty { value ->
|
||||
configurator.isValidateSpec = value
|
||||
}
|
||||
|
||||
skipOverwrite.ifNotEmpty { value ->
|
||||
configurator.isSkipOverwrite = value ?: false
|
||||
}
|
||||
|
||||
inputSpec.ifNotEmpty { value ->
|
||||
configurator.inputSpec = value
|
||||
}
|
||||
|
||||
generatorName.ifNotEmpty { value ->
|
||||
configurator.generatorName = value
|
||||
}
|
||||
|
||||
outputDir.ifNotEmpty { value ->
|
||||
configurator.outputDir = value
|
||||
}
|
||||
|
||||
auth.ifNotEmpty { value ->
|
||||
configurator.auth = value
|
||||
}
|
||||
|
||||
templateDir.ifNotEmpty { value ->
|
||||
configurator.templateDir = value
|
||||
}
|
||||
|
||||
apiPackage.ifNotEmpty { value ->
|
||||
configurator.apiPackage = value
|
||||
}
|
||||
|
||||
modelPackage.ifNotEmpty { value ->
|
||||
configurator.modelPackage = value
|
||||
}
|
||||
|
||||
modelNamePrefix.ifNotEmpty { value ->
|
||||
configurator.modelNamePrefix = value
|
||||
}
|
||||
|
||||
modelNameSuffix.ifNotEmpty { value ->
|
||||
configurator.modelNameSuffix = value
|
||||
}
|
||||
|
||||
invokerPackage.ifNotEmpty { value ->
|
||||
configurator.invokerPackage = value
|
||||
}
|
||||
|
||||
groupId.ifNotEmpty { value ->
|
||||
configurator.groupId = value
|
||||
}
|
||||
|
||||
id.ifNotEmpty { value ->
|
||||
configurator.artifactId = value
|
||||
}
|
||||
|
||||
version.ifNotEmpty { value ->
|
||||
configurator.artifactVersion = value
|
||||
}
|
||||
|
||||
library.ifNotEmpty { value ->
|
||||
configurator.library = value
|
||||
}
|
||||
|
||||
gitUserId.ifNotEmpty { value ->
|
||||
configurator.gitUserId = value
|
||||
}
|
||||
|
||||
gitRepoId.ifNotEmpty { value ->
|
||||
configurator.gitRepoId = value
|
||||
}
|
||||
|
||||
releaseNote.ifNotEmpty { value ->
|
||||
configurator.releaseNote = value
|
||||
}
|
||||
|
||||
httpUserAgent.ifNotEmpty { value ->
|
||||
configurator.httpUserAgent = value
|
||||
}
|
||||
|
||||
ignoreFileOverride.ifNotEmpty { value ->
|
||||
configurator.ignoreFileOverride = value
|
||||
}
|
||||
|
||||
removeOperationIdPrefix.ifNotEmpty { value ->
|
||||
configurator.removeOperationIdPrefix = value!!
|
||||
}
|
||||
|
||||
if (systemProperties.isPresent) {
|
||||
systemProperties.get().forEach { entry ->
|
||||
configurator.addSystemProperty(entry.key, entry.value)
|
||||
}
|
||||
}
|
||||
|
||||
if (instantiationTypes.isPresent) {
|
||||
instantiationTypes.get().forEach { entry ->
|
||||
configurator.addInstantiationType(entry.key, entry.value)
|
||||
}
|
||||
}
|
||||
|
||||
if (importMappings.isPresent) {
|
||||
importMappings.get().forEach { entry ->
|
||||
configurator.addImportMapping(entry.key, entry.value)
|
||||
}
|
||||
}
|
||||
|
||||
if (typeMappings.isPresent) {
|
||||
typeMappings.get().forEach { entry ->
|
||||
configurator.addTypeMapping(entry.key, entry.value)
|
||||
}
|
||||
}
|
||||
|
||||
if (additionalProperties.isPresent) {
|
||||
additionalProperties.get().forEach { entry ->
|
||||
configurator.addAdditionalProperty(entry.key, entry.value)
|
||||
}
|
||||
}
|
||||
|
||||
if (languageSpecificPrimitives.isPresent) {
|
||||
languageSpecificPrimitives.get().forEach {
|
||||
configurator.addLanguageSpecificPrimitive(it)
|
||||
}
|
||||
}
|
||||
|
||||
if (reservedWordsMappings.isPresent) {
|
||||
reservedWordsMappings.get().forEach { entry ->
|
||||
configurator.addAdditionalReservedWordMapping(entry.key, entry.value)
|
||||
}
|
||||
}
|
||||
|
||||
val clientOptInput = configurator.toClientOptInput()
|
||||
val codgenConfig = clientOptInput.config
|
||||
|
||||
if (configOptions.isPresent) {
|
||||
val userSpecifiedConfigOptions = configOptions.get()
|
||||
codgenConfig.cliOptions().forEach {
|
||||
if (userSpecifiedConfigOptions.containsKey(it.opt)) {
|
||||
clientOptInput.config.additionalProperties()[it.opt] = userSpecifiedConfigOptions[it.opt]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
val out = services.get(StyledTextOutputFactory::class.java).create("openapi")
|
||||
out.withStyle(StyledTextOutput.Style.Success)
|
||||
|
||||
DefaultGenerator().opts(clientOptInput).generate()
|
||||
|
||||
out.println("Successfully generated code to ${configurator.outputDir}")
|
||||
} catch (e: RuntimeException) {
|
||||
throw GradleException("Code generation failed.", e)
|
||||
}
|
||||
} finally {
|
||||
// Reset all modified system properties back to their original state
|
||||
GeneratorProperties.reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openapitools.generator.gradle.plugin.tasks
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.internal.logging.text.StyledTextOutput
|
||||
import org.gradle.internal.logging.text.StyledTextOutputFactory
|
||||
import org.openapitools.codegen.CodegenConfigLoader
|
||||
import org.openapitools.codegen.CodegenType
|
||||
|
||||
/**
|
||||
* A task which lists out the generators available in OpenAPI Generator
|
||||
*
|
||||
* Example (CLI):
|
||||
*
|
||||
* ./gradlew -q openApiGenerators
|
||||
*
|
||||
* @author Jim Schubert
|
||||
*/
|
||||
open class GeneratorsTask : DefaultTask() {
|
||||
@Suppress("unused")
|
||||
@TaskAction
|
||||
fun doWork() {
|
||||
val generators = CodegenConfigLoader.getAll()
|
||||
|
||||
val out = services.get(StyledTextOutputFactory::class.java).create("openapi")
|
||||
|
||||
StringBuilder().apply {
|
||||
val types = CodegenType.values()
|
||||
|
||||
append("The following generators are available:")
|
||||
|
||||
append(System.lineSeparator())
|
||||
append(System.lineSeparator())
|
||||
|
||||
for (type in types) {
|
||||
append(type.name).append(" generators:")
|
||||
append(System.lineSeparator())
|
||||
|
||||
generators.filter { it.tag == type }
|
||||
.sortedBy { it.name }
|
||||
.forEach({ generator ->
|
||||
append(" - ")
|
||||
append(generator.name)
|
||||
append(System.lineSeparator())
|
||||
})
|
||||
|
||||
append(System.lineSeparator())
|
||||
append(System.lineSeparator())
|
||||
}
|
||||
|
||||
out.withStyle(StyledTextOutput.Style.Success)
|
||||
out.formatln("%s%n", toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openapitools.generator.gradle.plugin.tasks
|
||||
|
||||
import com.samskivert.mustache.Mustache
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.tasks.Internal
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.internal.logging.text.StyledTextOutput
|
||||
import org.gradle.internal.logging.text.StyledTextOutputFactory
|
||||
import org.gradle.kotlin.dsl.property
|
||||
import org.openapitools.codegen.CodegenConfig
|
||||
import org.openapitools.codegen.CodegenConstants
|
||||
import org.openapitools.codegen.DefaultGenerator
|
||||
import org.openapitools.codegen.SupportingFile
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.nio.charset.Charset
|
||||
|
||||
/**
|
||||
* A task which generates a new generator (meta). Useful for redistributable generator packages.
|
||||
*
|
||||
* @author Jim Schubert
|
||||
*/
|
||||
open class MetaTask : DefaultTask() {
|
||||
|
||||
@get:Internal
|
||||
val generatorName = project.objects.property<String>()
|
||||
|
||||
@get:Internal
|
||||
val packageName = project.objects.property<String>()
|
||||
|
||||
@get:Internal
|
||||
val outputFolder = project.objects.property<String>()
|
||||
|
||||
@Suppress("unused")
|
||||
@TaskAction
|
||||
fun doWork() {
|
||||
|
||||
val packageToPath = packageName.get().replace(".", File.separator)
|
||||
val dir = File(outputFolder.get())
|
||||
val klass = "${generatorName.get().titleCasedTextOnly()}Generator"
|
||||
|
||||
val templateResourceDir = generatorName.get().hyphenatedTextOnly()
|
||||
|
||||
val out = services.get(StyledTextOutputFactory::class.java).create("openapi")
|
||||
|
||||
out.withStyle(StyledTextOutput.Style.Info)
|
||||
|
||||
logger.debug("package: {}", packageName.get())
|
||||
logger.debug("dir: {}", dir.absolutePath)
|
||||
logger.debug("generator class: {}", klass)
|
||||
|
||||
val supportingFiles = listOf(
|
||||
SupportingFile("pom.mustache", "", "pom.xml"),
|
||||
SupportingFile("generatorClass.mustache", dir("src", "main", "java", packageToPath), "$klass.java"),
|
||||
SupportingFile("README.mustache", "", "README.md"),
|
||||
SupportingFile("api.template", dir("src", "main", "resources", templateResourceDir), "api.mustache"),
|
||||
SupportingFile("model.template", dir("src", "main", "resources", templateResourceDir), "model.mustache"),
|
||||
SupportingFile("myFile.template", dir("src", "main", "resources", templateResourceDir), "myFile.mustache"),
|
||||
SupportingFile("services.mustache", dir("src", "main", "resources", "META-INF", "services"), CodegenConfig::class.java.canonicalName))
|
||||
|
||||
val currentVersion = CodegenConstants::class.java.`package`.implementationVersion
|
||||
|
||||
val data = mapOf("generatorPackage" to packageToPath,
|
||||
"generatorClass" to klass,
|
||||
"name" to templateResourceDir,
|
||||
"fullyQualifiedGeneratorClass" to "${packageName.get()}.$klass",
|
||||
"openapiGeneratorVersion" to currentVersion)
|
||||
|
||||
val generator = DefaultGenerator()
|
||||
supportingFiles.map {
|
||||
try {
|
||||
val destinationFolder = File(File(dir.absolutePath), it.folder)
|
||||
destinationFolder.mkdirs()
|
||||
val outputFile = File(destinationFolder, it.destinationFilename)
|
||||
|
||||
val template = generator.readTemplate(File("codegen", it.templateFile).path)
|
||||
var formatted = template
|
||||
|
||||
if (it.templateFile.endsWith(".mustache")) {
|
||||
formatted = Mustache.compiler()
|
||||
.withLoader(loader(generator))
|
||||
.defaultValue("")
|
||||
.compile(template).execute(data)
|
||||
}
|
||||
|
||||
outputFile.writeText(formatted, Charset.forName("UTF8"))
|
||||
|
||||
out.formatln("Wrote file to %s", outputFile.absolutePath)
|
||||
|
||||
// TODO: register outputs
|
||||
// return outputFile
|
||||
} catch (e: IOException) {
|
||||
logger.error(e.message)
|
||||
throw GradleException("Can't generate project", e)
|
||||
}
|
||||
}
|
||||
out.withStyle(StyledTextOutput.Style.Success)
|
||||
out.formatln("Created generator %s", klass)
|
||||
}
|
||||
|
||||
private fun loader(generator: DefaultGenerator): Mustache.TemplateLoader {
|
||||
return Mustache.TemplateLoader { name ->
|
||||
generator.getTemplateReader("codegen${File.separator}$name.mustache")
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.titleCasedTextOnly(): String =
|
||||
this.split(Regex("[^a-zA-Z0-9]")).joinToString(separator = "", transform = String::capitalize)
|
||||
|
||||
private fun String.hyphenatedTextOnly(): String =
|
||||
this.split(Regex("[^a-zA-Z0-9]")).joinToString(separator = "-", transform = String::toLowerCase)
|
||||
|
||||
private fun dir(vararg parts: String): String =
|
||||
parts.joinToString(separator = File.separator)
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openapitools.generator.gradle.plugin.tasks
|
||||
|
||||
import io.swagger.parser.OpenAPIParser
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.tasks.Internal
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.api.tasks.options.Option
|
||||
import org.gradle.internal.logging.text.StyledTextOutput
|
||||
import org.gradle.internal.logging.text.StyledTextOutputFactory
|
||||
import org.gradle.kotlin.dsl.property
|
||||
|
||||
/**
|
||||
* A generator which validates an Open API spec. This task outputs a list of validation issues and errors.
|
||||
*
|
||||
* Example:
|
||||
* cli:
|
||||
*
|
||||
* ./gradlew openApiValidate --input=/path/to/file
|
||||
*
|
||||
* build.gradle:
|
||||
*
|
||||
* openApiMeta {
|
||||
* inputSpec = "path/to/spec.yaml"
|
||||
* }
|
||||
*
|
||||
* @author Jim Schubert
|
||||
*/
|
||||
open class ValidateTask : DefaultTask() {
|
||||
@get:Internal
|
||||
var inputSpec = project.objects.property<String>()
|
||||
|
||||
@Suppress("unused")
|
||||
@get:Internal
|
||||
@set:Option(option = "input", description = "The input specification.")
|
||||
var input: String? = null
|
||||
set(value) {
|
||||
inputSpec.set(value)
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
@TaskAction
|
||||
fun doWork() {
|
||||
val spec = inputSpec.get()
|
||||
logger.quiet("Validating spec $spec")
|
||||
val result = OpenAPIParser().readLocation(spec, null, null)
|
||||
val messages = result.messages.toSet()
|
||||
val out = services.get(StyledTextOutputFactory::class.java).create("openapi")
|
||||
|
||||
if (messages.isNotEmpty()) {
|
||||
|
||||
out.withStyle(StyledTextOutput.Style.Error)
|
||||
out.println("\nSpec is invalid.\nIssues:\n")
|
||||
|
||||
messages.forEach {
|
||||
out.withStyle(StyledTextOutput.Style.Error)
|
||||
out.println("\t$it\n")
|
||||
}
|
||||
|
||||
throw GradleException("Validation failed.")
|
||||
} else {
|
||||
out.withStyle(StyledTextOutput.Style.Success)
|
||||
out.println("Spec is valid.")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package org.openapitools.generator.gradle.plugin
|
||||
|
||||
import org.gradle.testkit.runner.GradleRunner
|
||||
import org.gradle.testkit.runner.TaskOutcome
|
||||
import org.testng.annotations.Test
|
||||
import java.io.File
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class GenerateTaskDslTest : TestBase() {
|
||||
override var temp: File = createTempDir(javaClass.simpleName)
|
||||
|
||||
private val defaultBuildGradle = """
|
||||
plugins {
|
||||
id 'org.openapi.generator'
|
||||
}
|
||||
openApiGenerate {
|
||||
generatorName = "kotlin"
|
||||
inputSpec = file("spec.yaml").absolutePath
|
||||
outputDir = file("build/kotlin").absolutePath
|
||||
apiPackage = "org.openapitools.example.api"
|
||||
invokerPackage = "org.openapitools.example.invoker"
|
||||
modelPackage = "org.openapitools.example.model"
|
||||
configOptions = [
|
||||
dateLibrary: "java8"
|
||||
]
|
||||
}
|
||||
""".trimIndent()
|
||||
|
||||
@Test
|
||||
fun `openApiGenerate should create an expected file structure from DSL config`() {
|
||||
// Arrange
|
||||
val projectFiles = mapOf(
|
||||
"spec.yaml" to javaClass.classLoader.getResourceAsStream("specs/petstore-v3.0.yaml")
|
||||
)
|
||||
withProject(defaultBuildGradle, projectFiles)
|
||||
|
||||
// Act
|
||||
val result = GradleRunner.create()
|
||||
.withProjectDir(temp)
|
||||
.withArguments("openApiGenerate")
|
||||
.withPluginClasspath()
|
||||
.build()
|
||||
|
||||
// Assert
|
||||
assertTrue(result.output.contains("Successfully generated code to"), "User friendly generate notice is missing.")
|
||||
|
||||
listOf(
|
||||
"build/kotlin/.openapi-generator-ignore",
|
||||
"build/kotlin/docs/PetsApi.md",
|
||||
"build/kotlin/docs/Pets.md",
|
||||
"build/kotlin/docs/Error.md",
|
||||
"build/kotlin/docs/Pet.md",
|
||||
"build/kotlin/README.md",
|
||||
"build/kotlin/build.gradle",
|
||||
"build/kotlin/.openapi-generator/VERSION",
|
||||
"build/kotlin/settings.gradle",
|
||||
"build/kotlin/src/main/kotlin/org/openapitools/example/model/Pets.kt",
|
||||
"build/kotlin/src/main/kotlin/org/openapitools/example/model/Pet.kt",
|
||||
"build/kotlin/src/main/kotlin/org/openapitools/example/model/Error.kt",
|
||||
"build/kotlin/src/main/kotlin/org/openapitools/example/api/PetsApi.kt",
|
||||
"build/kotlin/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt"
|
||||
).map {
|
||||
val f = File(temp, it)
|
||||
assertTrue(f.exists() && f.isFile, "An expected file was not generated when invoking the generation.")
|
||||
}
|
||||
|
||||
assertEquals(TaskOutcome.SUCCESS, result.task(":openApiGenerate")?.outcome,
|
||||
"Expected a successful run, but found ${result.task(":openApiGenerate")?.outcome}")
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package org.openapitools.generator.gradle.plugin
|
||||
|
||||
import org.gradle.testkit.runner.GradleRunner
|
||||
import org.gradle.testkit.runner.TaskOutcome
|
||||
import org.testng.annotations.Test
|
||||
import java.io.File
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class GeneratorsTaskDslTest : TestBase() {
|
||||
override var temp: File = createTempDir(javaClass.simpleName)
|
||||
|
||||
@Test
|
||||
fun `openApiGenerators should list generators available to the user`() {
|
||||
// Arrange
|
||||
withProject("""
|
||||
| plugins {
|
||||
| id 'org.openapi.generator'
|
||||
| }
|
||||
""".trimMargin())
|
||||
|
||||
// Act
|
||||
val result = GradleRunner.create()
|
||||
.withProjectDir(temp)
|
||||
.withArguments("openApiGenerators")
|
||||
.withPluginClasspath()
|
||||
.build()
|
||||
|
||||
// Assert
|
||||
assertTrue(result.output.contains("The following generators are available:"), "User friendly generator notice is missing.")
|
||||
assertTrue(result.output.contains("CLIENT generators:"), "Expected client generator header is missing.")
|
||||
assertTrue(result.output.contains("android"), "Spot-checking listed client generators is missing a client generator.")
|
||||
assertTrue(result.output.contains("SERVER generators:"), "Expected server generator header is missing.")
|
||||
assertTrue(result.output.contains("kotlin-server"), "Spot-checking listed server generators is missing a server generator.")
|
||||
assertEquals(TaskOutcome.SUCCESS, result.task(":openApiGenerators")?.outcome,
|
||||
"Expected a successful run, but found ${result.task(":openApiGenerators")?.outcome}")
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
package org.openapitools.generator.gradle.plugin
|
||||
|
||||
import org.gradle.testkit.runner.GradleRunner
|
||||
import org.gradle.testkit.runner.TaskOutcome
|
||||
import org.testng.annotations.Test
|
||||
import java.io.File
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class MetaTaskDslTest : TestBase() {
|
||||
override var temp: File = createTempDir(javaClass.simpleName)
|
||||
|
||||
@Test
|
||||
fun `openApiMeta should generate desired project contents`() {
|
||||
// Arrange
|
||||
val buildDirReplacement = "\$buildDir/meta"
|
||||
withProject("""
|
||||
| plugins {
|
||||
| id 'org.openapi.generator'
|
||||
| }
|
||||
|
|
||||
| openApiMeta {
|
||||
| generatorName = "Sample"
|
||||
| packageName = "org.openapitools.example"
|
||||
| outputFolder = "$buildDirReplacement".toString()
|
||||
| }
|
||||
""".trimMargin())
|
||||
|
||||
// Act
|
||||
val result = GradleRunner.create()
|
||||
.withProjectDir(temp)
|
||||
.withArguments("openApiMeta")
|
||||
.withPluginClasspath()
|
||||
.build()
|
||||
|
||||
// Assert
|
||||
assertTrue(result.output.contains("Wrote file to"), "User friendly write notice is missing.")
|
||||
|
||||
// To avoid any OS-specific output causing issues with our stdout comparisons, only compare on expected filenames.
|
||||
listOf(
|
||||
"SampleGenerator.java",
|
||||
"README.md",
|
||||
"api.mustache",
|
||||
"model.mustache",
|
||||
"myFile.mustache",
|
||||
"org.openapitools.codegen.CodegenConfig",
|
||||
"pom.xml"
|
||||
).map {
|
||||
assertTrue(result.output.contains(it), "Expected $it to be listed in gradle stdout.")
|
||||
}
|
||||
|
||||
assertEquals(
|
||||
TaskOutcome.SUCCESS,
|
||||
result.task(":openApiMeta")?.outcome,
|
||||
"Expected a successful run, but found ${result.task(":openApiMeta")?.outcome}"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package org.openapitools.generator.gradle.plugin
|
||||
|
||||
import org.testng.annotations.AfterMethod
|
||||
import org.testng.annotations.BeforeMethod
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
|
||||
abstract class TestBase {
|
||||
protected open lateinit var temp: File
|
||||
|
||||
@BeforeMethod
|
||||
protected fun before() {
|
||||
temp = createTempDir(javaClass.simpleName)
|
||||
temp.deleteOnExit()
|
||||
}
|
||||
|
||||
@AfterMethod
|
||||
protected fun after(){
|
||||
temp.deleteRecursively()
|
||||
}
|
||||
|
||||
protected fun withProject(
|
||||
buildContents: String,
|
||||
projectFiles: Map<String, InputStream> = mapOf()
|
||||
) {
|
||||
val buildFile = File(temp,"build.gradle")
|
||||
buildFile.writeText(buildContents)
|
||||
|
||||
projectFiles.forEach { entry ->
|
||||
val target = File(temp, entry.key)
|
||||
entry.value.copyTo(target.outputStream())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
package org.openapitools.generator.gradle.plugin
|
||||
|
||||
import org.gradle.testkit.runner.GradleRunner
|
||||
import org.gradle.testkit.runner.TaskOutcome.FAILED
|
||||
import org.gradle.testkit.runner.TaskOutcome.SUCCESS
|
||||
import org.testng.annotations.Test
|
||||
import java.io.File
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class ValidateTaskDslTest : TestBase() {
|
||||
override var temp: File = createTempDir(javaClass.simpleName)
|
||||
|
||||
@Test
|
||||
fun `openApiValidate should fail on non-file spec`() {
|
||||
// Arrange
|
||||
withProject("""
|
||||
| plugins {
|
||||
| id 'org.openapi.generator'
|
||||
| }
|
||||
|
|
||||
| openApiValidate {
|
||||
| inputSpec = "some_location"
|
||||
| }
|
||||
""".trimMargin())
|
||||
|
||||
// Act
|
||||
val result = GradleRunner.create()
|
||||
.withProjectDir(temp)
|
||||
.withArguments("openApiValidate")
|
||||
.withPluginClasspath()
|
||||
.buildAndFail()
|
||||
|
||||
// Assert
|
||||
assertTrue(result.output.contains("unable to read location `some_location`"), "Unexpected/no message presented to the user for a spec pointing to an invalid URI.")
|
||||
assertEquals(FAILED, result.task(":openApiValidate")?.outcome,
|
||||
"Expected a failed run, but found ${result.task(":openApiValidate")?.outcome}")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `openApiValidate should succeed on valid spec`() {
|
||||
// Arrange
|
||||
val projectFiles = mapOf(
|
||||
"spec.yaml" to javaClass.classLoader.getResourceAsStream("specs/petstore-v3.0.yaml")
|
||||
)
|
||||
|
||||
withProject("""
|
||||
| plugins {
|
||||
| id 'org.openapi.generator'
|
||||
| }
|
||||
|
|
||||
| openApiValidate {
|
||||
| inputSpec = file("spec.yaml").absolutePath
|
||||
| }
|
||||
""".trimMargin(), projectFiles)
|
||||
|
||||
// Act
|
||||
val result = GradleRunner.create()
|
||||
.withProjectDir(temp)
|
||||
.withArguments("openApiValidate")
|
||||
.withPluginClasspath()
|
||||
.build()
|
||||
|
||||
// Assert
|
||||
assertTrue(result.output.contains("Spec is valid."), "Unexpected/no message presented to the user for a valid spec.")
|
||||
assertEquals(SUCCESS, result.task(":openApiValidate")?.outcome,
|
||||
"Expected a successful run, but found ${result.task(":openApiValidate")?.outcome}")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `openApiValidate should fail on invalid spec`() {
|
||||
// Arrange
|
||||
val projectFiles = mapOf(
|
||||
"spec.yaml" to javaClass.classLoader.getResourceAsStream("specs/petstore-v3.0-invalid.yaml")
|
||||
)
|
||||
withProject("""
|
||||
| plugins {
|
||||
| id 'org.openapi.generator'
|
||||
| }
|
||||
|
|
||||
| openApiValidate {
|
||||
| inputSpec = file('spec.yaml').absolutePath
|
||||
| }
|
||||
""".trimMargin(), projectFiles)
|
||||
|
||||
// Act
|
||||
val result = GradleRunner.create()
|
||||
.withProjectDir(temp)
|
||||
.withArguments("openApiValidate")
|
||||
.withPluginClasspath()
|
||||
.buildAndFail()
|
||||
|
||||
// Assert
|
||||
assertTrue(result.output.contains("Spec is invalid."), "Unexpected/no message presented to the user for an invalid spec.")
|
||||
assertEquals(FAILED, result.task(":openApiValidate")?.outcome,
|
||||
"Expected a failed run, but found ${result.task(":openApiValidate")?.outcome}")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
openapi: "3.0.0"
|
||||
servers:
|
||||
- url: http://petstore.swagger.io/v1
|
||||
paths:
|
||||
/pets:
|
||||
get:
|
||||
summary: List all pets
|
||||
operationId: listPets
|
||||
tags:
|
||||
- pets
|
||||
parameters:
|
||||
- name: limit
|
||||
in: query
|
||||
description: How many items to return at one time (max 100)
|
||||
required: false
|
||||
schema:
|
||||
type: integer
|
||||
format: int32
|
||||
responses:
|
||||
'200':
|
||||
description: A paged array of pets
|
||||
headers:
|
||||
x-next:
|
||||
description: A link to the next page of responses
|
||||
schema:
|
||||
type: string
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Pets"
|
||||
default:
|
||||
description: unexpected error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
post:
|
||||
summary: Create a pet
|
||||
tags:
|
||||
- pets
|
||||
responses:
|
||||
'201':
|
||||
description: Null response
|
||||
default:
|
||||
description: unexpected error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
/pets/{petId}:
|
||||
get:
|
||||
summary: Info for a specific pet
|
||||
operationId: showPetById
|
||||
tags:
|
||||
- pets
|
||||
parameters:
|
||||
- name: petId
|
||||
in: path
|
||||
required: true
|
||||
description: The id of the pet to retrieve
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: Expected response to a valid request
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Pets"
|
||||
default:
|
||||
description: unexpected error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
components:
|
||||
schemas:
|
||||
Pet:
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
name:
|
||||
type: string
|
||||
tag:
|
||||
type: string
|
||||
Pets:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/Pet"
|
||||
Error:
|
||||
required:
|
||||
- code
|
||||
- message
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
format: int32
|
||||
message:
|
||||
type: string
|
||||
@@ -1,109 +0,0 @@
|
||||
openapi: "3.0.0"
|
||||
info:
|
||||
version: 1.0.0
|
||||
title: Swagger Petstore
|
||||
license:
|
||||
name: MIT
|
||||
servers:
|
||||
- url: http://petstore.swagger.io/v1
|
||||
paths:
|
||||
/pets:
|
||||
get:
|
||||
summary: List all pets
|
||||
operationId: listPets
|
||||
tags:
|
||||
- pets
|
||||
parameters:
|
||||
- name: limit
|
||||
in: query
|
||||
description: How many items to return at one time (max 100)
|
||||
required: false
|
||||
schema:
|
||||
type: integer
|
||||
format: int32
|
||||
responses:
|
||||
'200':
|
||||
description: A paged array of pets
|
||||
headers:
|
||||
x-next:
|
||||
description: A link to the next page of responses
|
||||
schema:
|
||||
type: string
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Pets"
|
||||
default:
|
||||
description: unexpected error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
post:
|
||||
summary: Create a pet
|
||||
operationId: createPets
|
||||
tags:
|
||||
- pets
|
||||
responses:
|
||||
'201':
|
||||
description: Null response
|
||||
default:
|
||||
description: unexpected error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
/pets/{petId}:
|
||||
get:
|
||||
summary: Info for a specific pet
|
||||
operationId: showPetById
|
||||
tags:
|
||||
- pets
|
||||
parameters:
|
||||
- name: petId
|
||||
in: path
|
||||
required: true
|
||||
description: The id of the pet to retrieve
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: Expected response to a valid request
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Pets"
|
||||
default:
|
||||
description: unexpected error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
components:
|
||||
schemas:
|
||||
Pet:
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
name:
|
||||
type: string
|
||||
tag:
|
||||
type: string
|
||||
Pets:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/Pet"
|
||||
Error:
|
||||
required:
|
||||
- code
|
||||
- message
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
format: int32
|
||||
message:
|
||||
type: string
|
||||
@@ -181,3 +181,5 @@ compileTestKotlin {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
}
|
||||
|
||||
uploadArchives.dependsOn 'check'
|
||||
|
||||
@@ -48,14 +48,12 @@ class GenerateTaskDslTest : TestBase() {
|
||||
listOf(
|
||||
"build/kotlin/.openapi-generator-ignore",
|
||||
"build/kotlin/docs/PetsApi.md",
|
||||
"build/kotlin/docs/Pets.md",
|
||||
"build/kotlin/docs/Error.md",
|
||||
"build/kotlin/docs/Pet.md",
|
||||
"build/kotlin/README.md",
|
||||
"build/kotlin/build.gradle",
|
||||
"build/kotlin/.openapi-generator/VERSION",
|
||||
"build/kotlin/settings.gradle",
|
||||
"build/kotlin/src/main/kotlin/org/openapitools/example/model/Pets.kt",
|
||||
"build/kotlin/src/main/kotlin/org/openapitools/example/model/Pet.kt",
|
||||
"build/kotlin/src/main/kotlin/org/openapitools/example/model/Error.kt",
|
||||
"build/kotlin/src/main/kotlin/org/openapitools/example/api/PetsApi.kt",
|
||||
|
||||
@@ -145,12 +145,6 @@ public class CodeGenMojo extends AbstractMojo {
|
||||
@Parameter(name = "skipOverwrite", required = false)
|
||||
private Boolean skipOverwrite;
|
||||
|
||||
/**
|
||||
* Specifies if the existing files should be overwritten during the generation.
|
||||
*/
|
||||
@Parameter(name = "removeOperationIdPrefix", required = false)
|
||||
private Boolean removeOperationIdPrefix;
|
||||
|
||||
/**
|
||||
* The package to use for generated api objects/classes
|
||||
*/
|
||||
@@ -211,6 +205,36 @@ public class CodeGenMojo extends AbstractMojo {
|
||||
@Parameter(name = "ignoreFileOverride", required = false)
|
||||
private String ignoreFileOverride;
|
||||
|
||||
/**
|
||||
* To remove operationId prefix (e.g. user_getName => getName)
|
||||
*/
|
||||
@Parameter(name = "removeOperationIdPrefix", required = false)
|
||||
private Boolean removeOperationIdPrefix;
|
||||
|
||||
/**
|
||||
* To write all log messages (not just errors) to STDOUT
|
||||
*/
|
||||
@Parameter(name = "logToStderr", required = false)
|
||||
private Boolean logToStderr;
|
||||
|
||||
/**
|
||||
* To file post-processing hook
|
||||
*/
|
||||
@Parameter(name = "enablePostProcessFile", required = false)
|
||||
private Boolean enablePostProcessFile;
|
||||
|
||||
/**
|
||||
* To skip spec validation
|
||||
*/
|
||||
@Parameter(name = "skipValidateSpec", required = false)
|
||||
private Boolean skipValidateSpec;
|
||||
|
||||
/**
|
||||
* To generate alias (array, map) as model
|
||||
*/
|
||||
@Parameter(name = "generateAliasAsModel", required = false)
|
||||
private Boolean generateAliasAsModel;
|
||||
|
||||
/**
|
||||
* A map of language-specific parameters as passed with the -c option to the command line
|
||||
*/
|
||||
@@ -433,6 +457,22 @@ public class CodeGenMojo extends AbstractMojo {
|
||||
configurator.setIgnoreFileOverride(ignoreFileOverride);
|
||||
}
|
||||
|
||||
if (skipValidateSpec != null) {
|
||||
configurator.setSkipOverwrite(skipValidateSpec);
|
||||
}
|
||||
|
||||
if (logToStderr != null) {
|
||||
configurator.setLogToStderr(logToStderr);
|
||||
}
|
||||
|
||||
if (enablePostProcessFile != null) {
|
||||
configurator.setEnablePostProcessFile(enablePostProcessFile);
|
||||
}
|
||||
|
||||
if (generateAliasAsModel != null) {
|
||||
configurator.setGenerateAliasAsModel(generateAliasAsModel);
|
||||
}
|
||||
|
||||
// TODO: After 3.0.0 release (maybe for 3.1.0): Fully deprecate lang.
|
||||
if (isNotEmpty(generatorName)) {
|
||||
configurator.setGeneratorName(generatorName);
|
||||
|
||||
@@ -71,7 +71,6 @@ import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
@@ -83,8 +82,8 @@ import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.openapitools.codegen.utils.StringUtils.camelize;
|
||||
import static org.openapitools.codegen.utils.StringUtils.underscore;
|
||||
import static org.openapitools.codegen.utils.StringUtils.escape;
|
||||
import static org.openapitools.codegen.utils.StringUtils.underscore;
|
||||
|
||||
public class DefaultCodegen implements CodegenConfig {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCodegen.class);
|
||||
@@ -338,7 +337,7 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
enumVar.put("isString", isDataTypeString(cm.dataType));
|
||||
enumVars.add(enumVar);
|
||||
}
|
||||
// if "x-enum-varnames" defined, update varnames
|
||||
// if "x-enum-varnames" or "x-enum-descriptions" defined, update varnames
|
||||
updateEnumVarsWithExtensions(enumVars, cm.getVendorExtensions());
|
||||
cm.allowableValues.put("enumVars", enumVars);
|
||||
}
|
||||
@@ -1505,14 +1504,15 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* Capitalize the string
|
||||
* Capitalize the string. Please use org.openapitools.codegen.utils.StringUtils.camelize instead as this method will be deprecated.
|
||||
*
|
||||
* @param name string to be capitalized
|
||||
* @return capitalized string
|
||||
* @deprecated
|
||||
*/
|
||||
@SuppressWarnings("static-method")
|
||||
public String initialCaps(String name) {
|
||||
return StringUtils.capitalize(name);
|
||||
return camelize(name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1608,7 +1608,7 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
* @return capitalized model name
|
||||
*/
|
||||
public String toModelName(final String name) {
|
||||
return initialCaps(modelNamePrefix + name + modelNameSuffix);
|
||||
return initialCaps(modelNamePrefix + "_" + name + "_" + modelNameSuffix);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1840,7 +1840,7 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
.map(s -> ModelUtils.getSimpleRef(s.get$ref()))
|
||||
.collect(Collectors.toSet());
|
||||
if (parentSchemas.contains(schemaName)) {
|
||||
discriminator.getMappedModels().add(new MappedModel(childName, childName));
|
||||
discriminator.getMappedModels().add(new MappedModel(childName, toModelName(childName)));
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1863,18 +1863,21 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
protected void addProperties(Map<String, Schema> properties, List<String> required, Schema
|
||||
schema, Map<String, Schema> allSchemas) {
|
||||
if (schema instanceof ComposedSchema) {
|
||||
throw new RuntimeException("Please report the issue: Cannot process Composed Schema in addProperties: " + schema);
|
||||
/*
|
||||
ComposedSchema composedSchema = (ComposedSchema) schema;
|
||||
if (composedSchema.getAllOf() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Schema component : composedSchema.getAllOf()) {
|
||||
addProperties(properties, required, component, allSchemas);
|
||||
}
|
||||
|
||||
if (composedSchema.getOneOf() != null) {
|
||||
throw new RuntimeException("Please report the issue: Cannot process oneOf (Composed Scheme) in addProperties: " + schema);
|
||||
}
|
||||
|
||||
if (composedSchema.getAnyOf() != null) {
|
||||
throw new RuntimeException("Please report the issue: Cannot process anyOf (Composed Schema) in addProperties: " + schema);
|
||||
}
|
||||
|
||||
return;
|
||||
*/
|
||||
}
|
||||
|
||||
Schema unaliasSchema = ModelUtils.unaliasSchema(globalSchemas, schema);
|
||||
@@ -4031,6 +4034,9 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
if (Boolean.TRUE.equals(property.isFile)) {
|
||||
parameter.isFile = true;
|
||||
}
|
||||
if (Boolean.TRUE.equals(property.isModel)) {
|
||||
parameter.isModel = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4078,7 +4084,7 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
enumVar.put("isString", isDataTypeString(dataType));
|
||||
enumVars.add(enumVar);
|
||||
}
|
||||
// if "x-enum-varnames" defined, update varnames
|
||||
// if "x-enum-varnames" or "x-enum-descriptions" defined, update varnames
|
||||
Map<String, Object> extensions = var.mostInnerItems != null ? var.mostInnerItems.getVendorExtensions() : var.getVendorExtensions();
|
||||
updateEnumVarsWithExtensions(enumVars, extensions);
|
||||
allowableValues.put("enumVars", enumVars);
|
||||
@@ -4098,13 +4104,19 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateEnumVarsWithExtensions
|
||||
(List<Map<String, Object>> enumVars, Map<String, Object> vendorExtensions) {
|
||||
if (vendorExtensions != null && vendorExtensions.containsKey("x-enum-varnames")) {
|
||||
List<String> alias = (List<String>) vendorExtensions.get("x-enum-varnames");
|
||||
int size = Math.min(enumVars.size(), alias.size());
|
||||
private void updateEnumVarsWithExtensions(List<Map<String, Object>> enumVars, Map<String, Object> vendorExtensions) {
|
||||
if (vendorExtensions != null) {
|
||||
updateEnumVarsWithExtensions(enumVars, vendorExtensions, "x-enum-varnames", "name");
|
||||
updateEnumVarsWithExtensions(enumVars, vendorExtensions, "x-enum-descriptions", "enumDescription");
|
||||
}
|
||||
}
|
||||
|
||||
private void updateEnumVarsWithExtensions(List<Map<String, Object>> enumVars, Map<String, Object> vendorExtensions, String extensionKey, String key) {
|
||||
if (vendorExtensions.containsKey(extensionKey)) {
|
||||
List<String> values = (List<String>) vendorExtensions.get(extensionKey);
|
||||
int size = Math.min(enumVars.size(), values.size());
|
||||
for (int i = 0; i < size; i++) {
|
||||
enumVars.get(i).put("name", alias.get(i));
|
||||
enumVars.get(i).put(key, values.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4190,6 +4202,9 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
protected Parameter getParameterFromRef(String ref, OpenAPI openAPI) {
|
||||
String parameterName = ref.substring(ref.lastIndexOf('/') + 1);
|
||||
Map<String, Parameter> parameterMap = openAPI.getComponents().getParameters();
|
||||
if (parameterMap == null ) { // can't find the ref
|
||||
throw new RuntimeException(ref + " not defined in the spec.");
|
||||
}
|
||||
return parameterMap.get(parameterName);
|
||||
}
|
||||
|
||||
|
||||
@@ -839,6 +839,11 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
||||
if (authMethods != null && !authMethods.isEmpty()) {
|
||||
bundle.put("authMethods", authMethods);
|
||||
bundle.put("hasAuthMethods", true);
|
||||
|
||||
if (hasOAuthMethods(authMethods)) {
|
||||
bundle.put("hasOAuthMethods", true);
|
||||
bundle.put("oauthMethods", getOAuthMethods(authMethods));
|
||||
}
|
||||
}
|
||||
|
||||
List<CodegenServer> servers = config.fromServers(openAPI.getServers());
|
||||
@@ -1182,4 +1187,26 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
||||
}
|
||||
return authMethods;
|
||||
}
|
||||
|
||||
private boolean hasOAuthMethods(List<CodegenSecurity> authMethods) {
|
||||
for (CodegenSecurity cs : authMethods) {
|
||||
if (cs.isOAuth) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<CodegenSecurity> getOAuthMethods(List<CodegenSecurity> authMethods) {
|
||||
List<CodegenSecurity> oauthMethods = new ArrayList<>();
|
||||
|
||||
for (CodegenSecurity cs : authMethods) {
|
||||
if (cs.isOAuth) {
|
||||
oauthMethods.add(cs);
|
||||
}
|
||||
}
|
||||
|
||||
return oauthMethods;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,18 +17,16 @@
|
||||
|
||||
package org.openapitools.codegen;
|
||||
|
||||
import io.swagger.v3.oas.models.Components;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.*;
|
||||
import io.swagger.v3.oas.models.media.Schema;
|
||||
import io.swagger.v3.oas.models.media.ArraySchema;
|
||||
import io.swagger.v3.oas.models.media.ObjectSchema;
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
import io.swagger.v3.oas.models.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.models.Operation;
|
||||
import io.swagger.v3.oas.models.PathItem;
|
||||
import io.swagger.v3.oas.models.parameters.Parameter;
|
||||
import io.swagger.v3.oas.models.parameters.RequestBody;
|
||||
import io.swagger.v3.core.util.Json;
|
||||
import io.swagger.v3.oas.models.responses.ApiResponses;
|
||||
import org.openapitools.codegen.utils.ModelUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -56,260 +54,264 @@ public class InlineModelResolver {
|
||||
if (openapi.getComponents().getSchemas() == null) {
|
||||
openapi.getComponents().setSchemas(new HashMap<String, Schema>());
|
||||
}
|
||||
// operations
|
||||
Map<String, PathItem> paths = openapi.getPaths();
|
||||
Map<String, Schema> models = openapi.getComponents().getSchemas();
|
||||
if (paths != null) {
|
||||
for (String pathname : paths.keySet()) {
|
||||
PathItem path = paths.get(pathname);
|
||||
for (Operation operation : path.readOperations()) {
|
||||
RequestBody requestBody = operation.getRequestBody();
|
||||
if (requestBody != null) {
|
||||
Schema model = ModelUtils.getSchemaFromRequestBody(requestBody);
|
||||
if (model instanceof ObjectSchema) {
|
||||
Schema obj = (Schema) model;
|
||||
if (obj.getType() == null || "object".equals(obj.getType())) {
|
||||
if (obj.getProperties() != null && obj.getProperties().size() > 0) {
|
||||
flattenProperties(obj.getProperties(), pathname);
|
||||
// for model name, use "title" if defined, otherwise default to 'inline_object'
|
||||
String modelName = resolveModelName(obj.getTitle(), "inline_object");
|
||||
addGenerated(modelName, model);
|
||||
openapi.getComponents().addSchemas(modelName, model);
|
||||
|
||||
// create request body
|
||||
RequestBody rb = new RequestBody();
|
||||
Content content = new Content();
|
||||
MediaType mt = new MediaType();
|
||||
Schema schema = new Schema();
|
||||
schema.set$ref(modelName);
|
||||
mt.setSchema(schema);
|
||||
flattenPaths(openapi);
|
||||
flattenComponents(openapi);
|
||||
}
|
||||
|
||||
// get "consumes", e.g. application/xml, application/json
|
||||
Set<String> consumes;
|
||||
if (requestBody == null || requestBody.getContent() == null || requestBody.getContent().isEmpty()) {
|
||||
consumes = new HashSet<>();
|
||||
consumes.add("application/json"); // default to application/json
|
||||
LOGGER.info("Default to application/json for inline body schema");
|
||||
} else {
|
||||
consumes = requestBody.getContent().keySet();
|
||||
}
|
||||
/**
|
||||
* Flatten inline models in Paths
|
||||
*
|
||||
* @param openAPI target spec
|
||||
*/
|
||||
private void flattenPaths(OpenAPI openAPI) {
|
||||
Paths paths = openAPI.getPaths();
|
||||
if (paths == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (String consume : consumes) {
|
||||
content.addMediaType(consume, mt);
|
||||
}
|
||||
for (String pathname : paths.keySet()) {
|
||||
PathItem path = paths.get(pathname);
|
||||
for (Operation operation : path.readOperations()) {
|
||||
flattenRequestBody(openAPI, pathname, operation);
|
||||
flattenParameters(openAPI, pathname, operation);
|
||||
flattenResponses(openAPI, pathname, operation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rb.setContent(content);
|
||||
/**
|
||||
* Flatten inline models in RequestBody
|
||||
*
|
||||
* @param openAPI target spec
|
||||
* @param pathname target pathname
|
||||
* @param operation target operation
|
||||
*/
|
||||
private void flattenRequestBody(OpenAPI openAPI, String pathname, Operation operation) {
|
||||
RequestBody requestBody = operation.getRequestBody();
|
||||
if (requestBody == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// add to openapi "components"
|
||||
if (openapi.getComponents().getRequestBodies() == null) {
|
||||
Map<String, RequestBody> requestBodies = new HashMap<String, RequestBody>();
|
||||
requestBodies.put(modelName, rb);
|
||||
openapi.getComponents().setRequestBodies(requestBodies);
|
||||
} else {
|
||||
openapi.getComponents().getRequestBodies().put(modelName, rb);
|
||||
}
|
||||
Schema model = ModelUtils.getSchemaFromRequestBody(requestBody);
|
||||
if (model instanceof ObjectSchema) {
|
||||
Schema obj = (Schema) model;
|
||||
if (obj.getType() == null || "object".equals(obj.getType())) {
|
||||
if (obj.getProperties() != null && obj.getProperties().size() > 0) {
|
||||
flattenProperties(obj.getProperties(), pathname);
|
||||
// for model name, use "title" if defined, otherwise default to 'inline_object'
|
||||
String modelName = resolveModelName(obj.getTitle(), "inline_object");
|
||||
addGenerated(modelName, model);
|
||||
openAPI.getComponents().addSchemas(modelName, model);
|
||||
|
||||
// update requestBody to use $ref instead of inline def
|
||||
requestBody.set$ref(modelName);
|
||||
// create request body
|
||||
RequestBody rb = new RequestBody();
|
||||
Content content = new Content();
|
||||
MediaType mt = new MediaType();
|
||||
Schema schema = new Schema();
|
||||
schema.set$ref(modelName);
|
||||
mt.setSchema(schema);
|
||||
|
||||
}
|
||||
}
|
||||
} else if (model instanceof ArraySchema) {
|
||||
ArraySchema am = (ArraySchema) model;
|
||||
Schema inner = am.getItems();
|
||||
if (inner instanceof ObjectSchema) {
|
||||
ObjectSchema op = (ObjectSchema) inner;
|
||||
if (op.getProperties() != null && op.getProperties().size() > 0) {
|
||||
flattenProperties(op.getProperties(), pathname);
|
||||
String modelName = resolveModelName(op.getTitle(), null);
|
||||
Schema innerModel = modelFromProperty(op, modelName);
|
||||
String existing = matchGenerated(innerModel);
|
||||
if (existing != null) {
|
||||
Schema schema = new Schema().$ref(existing);
|
||||
schema.setRequired(op.getRequired());
|
||||
am.setItems(schema);
|
||||
} else {
|
||||
Schema schema = new Schema().$ref(modelName);
|
||||
schema.setRequired(op.getRequired());
|
||||
am.setItems(schema);
|
||||
addGenerated(modelName, innerModel);
|
||||
openapi.getComponents().addSchemas(modelName, innerModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// get "consumes", e.g. application/xml, application/json
|
||||
Set<String> consumes;
|
||||
if (requestBody == null || requestBody.getContent() == null || requestBody.getContent().isEmpty()) {
|
||||
consumes = new HashSet<>();
|
||||
consumes.add("application/json"); // default to application/json
|
||||
LOGGER.info("Default to application/json for inline body schema");
|
||||
} else {
|
||||
consumes = requestBody.getContent().keySet();
|
||||
}
|
||||
|
||||
List<Parameter> parameters = operation.getParameters();
|
||||
if (parameters != null) {
|
||||
for (Parameter parameter : parameters) {
|
||||
if (parameter.getSchema() != null) {
|
||||
Schema model = parameter.getSchema();
|
||||
if (model instanceof ObjectSchema) {
|
||||
Schema obj = (Schema) model;
|
||||
if (obj.getType() == null || "object".equals(obj.getType())) {
|
||||
if (obj.getProperties() != null && obj.getProperties().size() > 0) {
|
||||
flattenProperties(obj.getProperties(), pathname);
|
||||
String modelName = resolveModelName(obj.getTitle(), parameter.getName());
|
||||
|
||||
parameter.$ref(modelName);
|
||||
addGenerated(modelName, model);
|
||||
openapi.getComponents().addSchemas(modelName, model);
|
||||
}
|
||||
}
|
||||
} else if (model instanceof ArraySchema) {
|
||||
ArraySchema am = (ArraySchema) model;
|
||||
Schema inner = am.getItems();
|
||||
if (inner instanceof ObjectSchema) {
|
||||
ObjectSchema op = (ObjectSchema) inner;
|
||||
if (op.getProperties() != null && op.getProperties().size() > 0) {
|
||||
flattenProperties(op.getProperties(), pathname);
|
||||
String modelName = resolveModelName(op.getTitle(), parameter.getName());
|
||||
Schema innerModel = modelFromProperty(op, modelName);
|
||||
String existing = matchGenerated(innerModel);
|
||||
if (existing != null) {
|
||||
Schema schema = new Schema().$ref(existing);
|
||||
schema.setRequired(op.getRequired());
|
||||
am.setItems(schema);
|
||||
} else {
|
||||
Schema schema = new Schema().$ref(modelName);
|
||||
schema.setRequired(op.getRequired());
|
||||
am.setItems(schema);
|
||||
addGenerated(modelName, innerModel);
|
||||
openapi.getComponents().addSchemas(modelName, innerModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (String consume : consumes) {
|
||||
content.addMediaType(consume, mt);
|
||||
}
|
||||
Map<String, ApiResponse> responses = operation.getResponses();
|
||||
if (responses != null) {
|
||||
for (String key : responses.keySet()) {
|
||||
ApiResponse response = responses.get(key);
|
||||
if (ModelUtils.getSchemaFromResponse(response) != null) {
|
||||
Schema property = ModelUtils.getSchemaFromResponse(response);
|
||||
if (property instanceof ObjectSchema) {
|
||||
ObjectSchema op = (ObjectSchema) property;
|
||||
if (op.getProperties() != null && op.getProperties().size() > 0) {
|
||||
String modelName = resolveModelName(op.getTitle(), "inline_response_" + key);
|
||||
Schema model = modelFromProperty(op, modelName);
|
||||
String existing = matchGenerated(model);
|
||||
Content content = response.getContent();
|
||||
for (MediaType mediaType : content.values()) {
|
||||
if (existing != null) {
|
||||
Schema schema = this.makeSchema(existing, property);
|
||||
schema.setRequired(op.getRequired());
|
||||
mediaType.setSchema(schema);
|
||||
} else {
|
||||
Schema schema = this.makeSchema(modelName, property);
|
||||
schema.setRequired(op.getRequired());
|
||||
mediaType.setSchema(schema);
|
||||
addGenerated(modelName, model);
|
||||
openapi.getComponents().addSchemas(modelName, model);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (property instanceof ArraySchema) {
|
||||
ArraySchema ap = (ArraySchema) property;
|
||||
Schema inner = ap.getItems();
|
||||
if (inner instanceof ObjectSchema) {
|
||||
ObjectSchema op = (ObjectSchema) inner;
|
||||
if (op.getProperties() != null && op.getProperties().size() > 0) {
|
||||
flattenProperties(op.getProperties(), pathname);
|
||||
String modelName = resolveModelName(op.getTitle(),
|
||||
"inline_response_" + key);
|
||||
Schema innerModel = modelFromProperty(op, modelName);
|
||||
String existing = matchGenerated(innerModel);
|
||||
if (existing != null) {
|
||||
Schema schema = this.makeSchema(existing, op);
|
||||
schema.setRequired(op.getRequired());
|
||||
ap.setItems(schema);
|
||||
} else {
|
||||
Schema schema = this.makeSchema(modelName, op);
|
||||
schema.setRequired(op.getRequired());
|
||||
ap.setItems(schema);
|
||||
addGenerated(modelName, innerModel);
|
||||
openapi.getComponents().addSchemas(modelName, innerModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (property instanceof MapSchema) {
|
||||
MapSchema mp = (MapSchema) property;
|
||||
Schema innerProperty = ModelUtils.getAdditionalProperties(mp);
|
||||
if (innerProperty instanceof ObjectSchema) {
|
||||
ObjectSchema op = (ObjectSchema) innerProperty;
|
||||
if (op.getProperties() != null && op.getProperties().size() > 0) {
|
||||
flattenProperties(op.getProperties(), pathname);
|
||||
String modelName = resolveModelName(op.getTitle(),
|
||||
"inline_response_" + key);
|
||||
Schema innerModel = modelFromProperty(op, modelName);
|
||||
String existing = matchGenerated(innerModel);
|
||||
if (existing != null) {
|
||||
Schema schema = new Schema().$ref(existing);
|
||||
schema.setRequired(op.getRequired());
|
||||
mp.setAdditionalProperties(schema);
|
||||
} else {
|
||||
Schema schema = new Schema().$ref(modelName);
|
||||
schema.setRequired(op.getRequired());
|
||||
mp.setAdditionalProperties(schema);
|
||||
addGenerated(modelName, innerModel);
|
||||
openapi.getComponents().addSchemas(modelName, innerModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rb.setContent(content);
|
||||
|
||||
// add to openapi "components"
|
||||
if (openAPI.getComponents().getRequestBodies() == null) {
|
||||
Map<String, RequestBody> requestBodies = new HashMap<String, RequestBody>();
|
||||
requestBodies.put(modelName, rb);
|
||||
openAPI.getComponents().setRequestBodies(requestBodies);
|
||||
} else {
|
||||
openAPI.getComponents().getRequestBodies().put(modelName, rb);
|
||||
}
|
||||
|
||||
// update requestBody to use $ref instead of inline def
|
||||
requestBody.set$ref(modelName);
|
||||
|
||||
}
|
||||
}
|
||||
} else if (model instanceof ArraySchema) {
|
||||
ArraySchema am = (ArraySchema) model;
|
||||
Schema inner = am.getItems();
|
||||
if (inner instanceof ObjectSchema) {
|
||||
ObjectSchema op = (ObjectSchema) inner;
|
||||
if (op.getProperties() != null && op.getProperties().size() > 0) {
|
||||
flattenProperties(op.getProperties(), pathname);
|
||||
String modelName = resolveModelName(op.getTitle(), null);
|
||||
Schema innerModel = modelFromProperty(op, modelName);
|
||||
String existing = matchGenerated(innerModel);
|
||||
if (existing != null) {
|
||||
Schema schema = new Schema().$ref(existing);
|
||||
schema.setRequired(op.getRequired());
|
||||
am.setItems(schema);
|
||||
} else {
|
||||
Schema schema = new Schema().$ref(modelName);
|
||||
schema.setRequired(op.getRequired());
|
||||
am.setItems(schema);
|
||||
addGenerated(modelName, innerModel);
|
||||
openAPI.getComponents().addSchemas(modelName, innerModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten inline models in parameters
|
||||
*
|
||||
* @param openAPI target spec
|
||||
* @param pathname target pathname
|
||||
* @param operation target operation
|
||||
*/
|
||||
private void flattenParameters(OpenAPI openAPI, String pathname, Operation operation) {
|
||||
List<Parameter> parameters = operation.getParameters();
|
||||
if (parameters == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Parameter parameter : parameters) {
|
||||
if (parameter.getSchema() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Schema model = parameter.getSchema();
|
||||
if (model instanceof ObjectSchema) {
|
||||
Schema obj = (Schema) model;
|
||||
if (obj.getType() == null || "object".equals(obj.getType())) {
|
||||
if (obj.getProperties() != null && obj.getProperties().size() > 0) {
|
||||
flattenProperties(obj.getProperties(), pathname);
|
||||
String modelName = resolveModelName(obj.getTitle(), parameter.getName());
|
||||
|
||||
parameter.$ref(modelName);
|
||||
addGenerated(modelName, model);
|
||||
openAPI.getComponents().addSchemas(modelName, model);
|
||||
}
|
||||
}
|
||||
} else if (model instanceof ArraySchema) {
|
||||
ArraySchema am = (ArraySchema) model;
|
||||
Schema inner = am.getItems();
|
||||
if (inner instanceof ObjectSchema) {
|
||||
ObjectSchema op = (ObjectSchema) inner;
|
||||
if (op.getProperties() != null && op.getProperties().size() > 0) {
|
||||
flattenProperties(op.getProperties(), pathname);
|
||||
String modelName = resolveModelName(op.getTitle(), parameter.getName());
|
||||
Schema innerModel = modelFromProperty(op, modelName);
|
||||
String existing = matchGenerated(innerModel);
|
||||
if (existing != null) {
|
||||
Schema schema = new Schema().$ref(existing);
|
||||
schema.setRequired(op.getRequired());
|
||||
am.setItems(schema);
|
||||
} else {
|
||||
Schema schema = new Schema().$ref(modelName);
|
||||
schema.setRequired(op.getRequired());
|
||||
am.setItems(schema);
|
||||
addGenerated(modelName, innerModel);
|
||||
openAPI.getComponents().addSchemas(modelName, innerModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// definitions
|
||||
if (models != null) {
|
||||
List<String> modelNames = new ArrayList<String>(models.keySet());
|
||||
for (String modelName : modelNames) {
|
||||
Schema model = models.get(modelName);
|
||||
if (model instanceof Schema) {
|
||||
Schema m = (Schema) model;
|
||||
Map<String, Schema> properties = m.getProperties();
|
||||
flattenProperties(properties, modelName);
|
||||
fixStringModel(m);
|
||||
} else if (ModelUtils.isArraySchema(model)) {
|
||||
ArraySchema m = (ArraySchema) model;
|
||||
Schema inner = m.getItems();
|
||||
if (inner instanceof ObjectSchema) {
|
||||
ObjectSchema op = (ObjectSchema) inner;
|
||||
if (op.getProperties() != null && op.getProperties().size() > 0) {
|
||||
String innerModelName = resolveModelName(op.getTitle(), modelName + "_inner");
|
||||
Schema innerModel = modelFromProperty(op, innerModelName);
|
||||
String existing = matchGenerated(innerModel);
|
||||
if (existing == null) {
|
||||
openapi.getComponents().addSchemas(innerModelName, innerModel);
|
||||
addGenerated(innerModelName, innerModel);
|
||||
Schema schema = new Schema().$ref(innerModelName);
|
||||
schema.setRequired(op.getRequired());
|
||||
m.setItems(schema);
|
||||
} else {
|
||||
Schema schema = new Schema().$ref(existing);
|
||||
schema.setRequired(op.getRequired());
|
||||
m.setItems(schema);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten inline models in ApiResponses
|
||||
*
|
||||
* @param openAPI target spec
|
||||
* @param pathname target pathname
|
||||
* @param operation target operation
|
||||
*/
|
||||
private void flattenResponses(OpenAPI openAPI, String pathname, Operation operation) {
|
||||
ApiResponses responses = operation.getResponses();
|
||||
if (responses == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (String key : responses.keySet()) {
|
||||
ApiResponse response = responses.get(key);
|
||||
if (ModelUtils.getSchemaFromResponse(response) == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Schema property = ModelUtils.getSchemaFromResponse(response);
|
||||
if (property instanceof ObjectSchema) {
|
||||
ObjectSchema op = (ObjectSchema) property;
|
||||
if (op.getProperties() != null && op.getProperties().size() > 0) {
|
||||
String modelName = resolveModelName(op.getTitle(), "inline_response_" + key);
|
||||
Schema model = modelFromProperty(op, modelName);
|
||||
String existing = matchGenerated(model);
|
||||
Content content = response.getContent();
|
||||
for (MediaType mediaType : content.values()) {
|
||||
if (existing != null) {
|
||||
Schema schema = this.makeSchema(existing, property);
|
||||
schema.setRequired(op.getRequired());
|
||||
mediaType.setSchema(schema);
|
||||
} else {
|
||||
Schema schema = this.makeSchema(modelName, property);
|
||||
schema.setRequired(op.getRequired());
|
||||
mediaType.setSchema(schema);
|
||||
addGenerated(modelName, model);
|
||||
openAPI.getComponents().addSchemas(modelName, model);
|
||||
}
|
||||
}
|
||||
} else if (ModelUtils.isComposedSchema(model)) {
|
||||
ComposedSchema m = (ComposedSchema) model;
|
||||
if (m.getAllOf() != null && !m.getAllOf().isEmpty()) {
|
||||
Schema child = null;
|
||||
for (Schema component : m.getAllOf()) {
|
||||
if (component.get$ref() == null) {
|
||||
child = component;
|
||||
}
|
||||
}
|
||||
} else if (property instanceof ArraySchema) {
|
||||
ArraySchema ap = (ArraySchema) property;
|
||||
Schema inner = ap.getItems();
|
||||
if (inner instanceof ObjectSchema) {
|
||||
ObjectSchema op = (ObjectSchema) inner;
|
||||
if (op.getProperties() != null && op.getProperties().size() > 0) {
|
||||
flattenProperties(op.getProperties(), pathname);
|
||||
String modelName = resolveModelName(op.getTitle(),
|
||||
"inline_response_" + key);
|
||||
Schema innerModel = modelFromProperty(op, modelName);
|
||||
String existing = matchGenerated(innerModel);
|
||||
if (existing != null) {
|
||||
Schema schema = this.makeSchema(existing, op);
|
||||
schema.setRequired(op.getRequired());
|
||||
ap.setItems(schema);
|
||||
} else {
|
||||
Schema schema = this.makeSchema(modelName, op);
|
||||
schema.setRequired(op.getRequired());
|
||||
ap.setItems(schema);
|
||||
addGenerated(modelName, innerModel);
|
||||
openAPI.getComponents().addSchemas(modelName, innerModel);
|
||||
}
|
||||
if (child != null) {
|
||||
Map<String, Schema> properties = child.getProperties();
|
||||
flattenProperties(properties, modelName);
|
||||
}
|
||||
}
|
||||
} else if (property instanceof MapSchema) {
|
||||
MapSchema mp = (MapSchema) property;
|
||||
Schema innerProperty = ModelUtils.getAdditionalProperties(mp);
|
||||
if (innerProperty instanceof ObjectSchema) {
|
||||
ObjectSchema op = (ObjectSchema) innerProperty;
|
||||
if (op.getProperties() != null && op.getProperties().size() > 0) {
|
||||
flattenProperties(op.getProperties(), pathname);
|
||||
String modelName = resolveModelName(op.getTitle(),
|
||||
"inline_response_" + key);
|
||||
Schema innerModel = modelFromProperty(op, modelName);
|
||||
String existing = matchGenerated(innerModel);
|
||||
if (existing != null) {
|
||||
Schema schema = new Schema().$ref(existing);
|
||||
schema.setRequired(op.getRequired());
|
||||
mp.setAdditionalProperties(schema);
|
||||
} else {
|
||||
Schema schema = new Schema().$ref(modelName);
|
||||
schema.setRequired(op.getRequired());
|
||||
mp.setAdditionalProperties(schema);
|
||||
addGenerated(modelName, innerModel);
|
||||
openAPI.getComponents().addSchemas(modelName, innerModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -317,6 +319,65 @@ public class InlineModelResolver {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten inline models in components
|
||||
*
|
||||
* @param openAPI target spec
|
||||
*/
|
||||
private void flattenComponents(OpenAPI openAPI) {
|
||||
Map<String, Schema> models = openAPI.getComponents().getSchemas();
|
||||
if (models == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> modelNames = new ArrayList<String>(models.keySet());
|
||||
for (String modelName : modelNames) {
|
||||
Schema model = models.get(modelName);
|
||||
if (model instanceof Schema) {
|
||||
Schema m = (Schema) model;
|
||||
Map<String, Schema> properties = m.getProperties();
|
||||
flattenProperties(properties, modelName);
|
||||
fixStringModel(m);
|
||||
} else if (ModelUtils.isArraySchema(model)) {
|
||||
ArraySchema m = (ArraySchema) model;
|
||||
Schema inner = m.getItems();
|
||||
if (inner instanceof ObjectSchema) {
|
||||
ObjectSchema op = (ObjectSchema) inner;
|
||||
if (op.getProperties() != null && op.getProperties().size() > 0) {
|
||||
String innerModelName = resolveModelName(op.getTitle(), modelName + "_inner");
|
||||
Schema innerModel = modelFromProperty(op, innerModelName);
|
||||
String existing = matchGenerated(innerModel);
|
||||
if (existing == null) {
|
||||
openAPI.getComponents().addSchemas(innerModelName, innerModel);
|
||||
addGenerated(innerModelName, innerModel);
|
||||
Schema schema = new Schema().$ref(innerModelName);
|
||||
schema.setRequired(op.getRequired());
|
||||
m.setItems(schema);
|
||||
} else {
|
||||
Schema schema = new Schema().$ref(existing);
|
||||
schema.setRequired(op.getRequired());
|
||||
m.setItems(schema);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (ModelUtils.isComposedSchema(model)) {
|
||||
ComposedSchema m = (ComposedSchema) model;
|
||||
if (m.getAllOf() != null && !m.getAllOf().isEmpty()) {
|
||||
Schema child = null;
|
||||
for (Schema component : m.getAllOf()) {
|
||||
if (component.get$ref() == null) {
|
||||
child = component;
|
||||
}
|
||||
}
|
||||
if (child != null) {
|
||||
Map<String, Schema> properties = child.getProperties();
|
||||
flattenProperties(properties, modelName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function fix models that are string (mostly enum). Before this fix, the
|
||||
* example would look something like that in the doc: "\"example from def\""
|
||||
@@ -359,6 +420,7 @@ public class InlineModelResolver {
|
||||
}
|
||||
int count = 0;
|
||||
boolean done = false;
|
||||
key = key.replaceAll("/", "_"); // e.g. /me/videos => _me_videos
|
||||
key = key.replaceAll("[^a-z_\\.A-Z0-9 ]", ""); // FIXME: a parameter
|
||||
// should not be assigned. Also declare the methods parameters as 'final'.
|
||||
while (!done) {
|
||||
|
||||
@@ -95,6 +95,7 @@ public class CodegenConfigurator implements Serializable {
|
||||
private boolean verbose;
|
||||
private boolean skipOverwrite;
|
||||
private boolean removeOperationIdPrefix;
|
||||
private boolean logToStderr;
|
||||
private boolean validateSpec;
|
||||
private boolean enablePostProcessFile;
|
||||
private String templateDir;
|
||||
@@ -220,6 +221,15 @@ public class CodegenConfigurator implements Serializable {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean getLogToStderr() {
|
||||
return logToStderr;
|
||||
}
|
||||
|
||||
public CodegenConfigurator setLogToStderr(boolean logToStderrte) {
|
||||
this.logToStderr = logToStderr;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isGenerateAliasAsModel() {
|
||||
return ModelUtils.isGenerateAliasAsModel();
|
||||
}
|
||||
|
||||
@@ -117,6 +117,8 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
|
||||
|
||||
setReservedWordsLowerCase(
|
||||
Arrays.asList(
|
||||
// special words
|
||||
"object",
|
||||
// used as internal variables, can collide with parameter names
|
||||
"localVarPath", "localVarQueryParams", "localVarCollectionQueryParams",
|
||||
"localVarHeaderParams", "localVarFormParams", "localVarPostBody",
|
||||
@@ -1436,4 +1438,13 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
|
||||
public void setParentOverridden(final boolean parentOverridden) {
|
||||
this.parentOverridden = parentOverridden;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addAdditionPropertiesToCodeGenModel(CodegenModel codegenModel, Schema schema) {
|
||||
super.addAdditionPropertiesToCodeGenModel(codegenModel, schema);
|
||||
|
||||
// See https://github.com/OpenAPITools/openapi-generator/pull/1729#issuecomment-449937728
|
||||
codegenModel.additionalPropertiesType = getSchemaType(ModelUtils.getAdditionalProperties(schema));
|
||||
addImport(codegenModel, codegenModel.additionalPropertiesType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
|
||||
protected String modelDocPath = "docs/";
|
||||
protected String apiTestPath = "api/";
|
||||
protected String modelTestPath = "model/";
|
||||
protected boolean useES6 = false; // default is ES5
|
||||
protected boolean useES6 = true; // default is ES5
|
||||
private String modelPropertyNaming = "camelCase";
|
||||
|
||||
public JavascriptClientCodegen() {
|
||||
@@ -207,8 +207,8 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
|
||||
cliOptions.add(new CliOption(CodegenConstants.HIDE_GENERATION_TIMESTAMP, CodegenConstants.HIDE_GENERATION_TIMESTAMP_DESC)
|
||||
.defaultValue(Boolean.TRUE.toString()));
|
||||
cliOptions.add(new CliOption(USE_ES6,
|
||||
"use JavaScript ES6 (ECMAScript 6) (beta). Default is ES5.")
|
||||
.defaultValue(Boolean.FALSE.toString()));
|
||||
"use JavaScript ES6 (ECMAScript 6) (beta). Default is ES6.")
|
||||
.defaultValue(Boolean.TRUE.toString()));
|
||||
cliOptions.add(new CliOption(CodegenConstants.MODEL_PROPERTY_NAMING, CodegenConstants.MODEL_PROPERTY_NAMING_DESC).defaultValue("camelCase"));
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,10 @@ import org.openapitools.codegen.CodegenConstants;
|
||||
import org.openapitools.codegen.CodegenOperation;
|
||||
import org.openapitools.codegen.CodegenType;
|
||||
import org.openapitools.codegen.SupportingFile;
|
||||
import org.openapitools.codegen.CodegenSecurity;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import io.swagger.v3.oas.models.security.SecurityScheme;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
@@ -46,6 +48,8 @@ public class PhpSlimServerCodegen extends AbstractPhpCodegen {
|
||||
|
||||
protected String groupId = "org.openapitools";
|
||||
protected String artifactId = "openapi-server";
|
||||
protected String authDirName = "Auth";
|
||||
protected String authPackage = "";
|
||||
|
||||
public PhpSlimServerCodegen() {
|
||||
super();
|
||||
@@ -59,6 +63,7 @@ public class PhpSlimServerCodegen extends AbstractPhpCodegen {
|
||||
setInvokerPackage("OpenAPIServer");
|
||||
apiPackage = invokerPackage + "\\" + apiDirName;
|
||||
modelPackage = invokerPackage + "\\" + modelDirName;
|
||||
authPackage = invokerPackage + "\\" + authDirName;
|
||||
outputFolder = "generated-code" + File.separator + "slim";
|
||||
|
||||
modelTestTemplateFiles.put("model_test.mustache", ".php");
|
||||
@@ -118,6 +123,15 @@ public class PhpSlimServerCodegen extends AbstractPhpCodegen {
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) {
|
||||
// Update the invokerPackage for the default authPackage
|
||||
authPackage = invokerPackage + "\\" + authDirName;
|
||||
}
|
||||
|
||||
// make auth src path available in mustache template
|
||||
additionalProperties.put("authPackage", authPackage);
|
||||
additionalProperties.put("authSrcPath", "./" + toSrcPath(authPackage, srcBasePath));
|
||||
|
||||
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
|
||||
supportingFiles.add(new SupportingFile("composer.mustache", "", "composer.json"));
|
||||
supportingFiles.add(new SupportingFile("index.mustache", "", "index.php"));
|
||||
@@ -158,6 +172,15 @@ public class PhpSlimServerCodegen extends AbstractPhpCodegen {
|
||||
return objs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CodegenSecurity> fromSecurity(Map<String, SecurityScheme> securitySchemeMap) {
|
||||
List<CodegenSecurity> codegenSecurities = super.fromSecurity(securitySchemeMap);
|
||||
if (Boolean.FALSE.equals(codegenSecurities.isEmpty())) {
|
||||
supportingFiles.add(new SupportingFile("abstract_authenticator.mustache", toSrcPath(authPackage, srcBasePath), toAbstractName("Authenticator") + ".php"));
|
||||
}
|
||||
return codegenSecurities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiName(String name) {
|
||||
if (name.length() == 0) {
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.openapitools.codegen.CodegenType;
|
||||
import org.openapitools.codegen.DefaultCodegen;
|
||||
import org.openapitools.codegen.SupportingFile;
|
||||
import org.openapitools.codegen.utils.ModelUtils;
|
||||
import org.openapitools.codegen.utils.ProcessUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -425,6 +426,16 @@ public class PowerShellClientCodegen extends DefaultCodegen implements CodegenCo
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
return objs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
|
||||
List<Object> models = (List<Object>) objs.get("models");
|
||||
// add x-index to properties
|
||||
ProcessUtils.addIndexToProperties(models);
|
||||
return objs;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -619,7 +619,15 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
public String toDefaultValue(Schema p) {
|
||||
if (ModelUtils.isBooleanSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
if (p.getDefault().toString().equalsIgnoreCase("false"))
|
||||
if (Boolean.valueOf(p.getDefault().toString()) == false)
|
||||
return "False";
|
||||
else
|
||||
return "True";
|
||||
}
|
||||
// include fallback to example, default defined as server only
|
||||
// example is not defined as server only
|
||||
if (p.getExample() != null) {
|
||||
if (Boolean.valueOf(p.getExample().toString()) == false)
|
||||
return "False";
|
||||
else
|
||||
return "True";
|
||||
@@ -632,10 +640,24 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
if (p.getDefault() != null) {
|
||||
return p.getDefault().toString();
|
||||
}
|
||||
// default numbers are not yet returned by v2 spec openAPI results
|
||||
// https://github.com/swagger-api/swagger-parser/issues/971
|
||||
// include fallback to example, default defined as server only
|
||||
// example is not defined as server only
|
||||
if (p.getExample() != null) {
|
||||
return p.getExample().toString();
|
||||
}
|
||||
} else if (ModelUtils.isIntegerSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
return p.getDefault().toString();
|
||||
}
|
||||
// default integers are not yet returned by v2 spec openAPI results
|
||||
// https://github.com/swagger-api/swagger-parser/issues/971
|
||||
// include fallback to example, default defined as server only
|
||||
// example is not defined as server only
|
||||
if (p.getExample() != null) {
|
||||
return p.getExample().toString();
|
||||
}
|
||||
} else if (ModelUtils.isStringSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
if (Pattern.compile("\r\n|\r|\n").matcher((String) p.getDefault()).find())
|
||||
@@ -643,6 +665,23 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
else
|
||||
return "'" + p.getDefault() + "'";
|
||||
}
|
||||
// include fallback to example, default defined as server only
|
||||
// example is not defined as server only
|
||||
if (p.getExample() != null) {
|
||||
if (Pattern.compile("\r\n|\r|\n").matcher((String) p.getExample()).find())
|
||||
return "'''" + p.getExample() + "'''";
|
||||
else
|
||||
return "'" + p.getExample() + "'";
|
||||
}
|
||||
} else if (ModelUtils.isArraySchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
return p.getDefault().toString();
|
||||
}
|
||||
// include fallback to example, default defined as server only
|
||||
// example is not defined as server only
|
||||
if (p.getExample() != null) {
|
||||
return p.getExample().toString();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.openapitools.codegen.utils;
|
||||
|
||||
import org.openapitools.codegen.CodegenModel;
|
||||
import org.openapitools.codegen.CodegenProperty;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ProcessUtils {
|
||||
|
||||
/**
|
||||
* Add x-index extension to the model's properties
|
||||
*
|
||||
* @param models List of models
|
||||
*/
|
||||
public static void addIndexToProperties(List<Object> models) {
|
||||
for (Object _mo : models) {
|
||||
Map<String, Object> mo = (Map<String, Object>) _mo;
|
||||
CodegenModel cm = (CodegenModel) mo.get("model");
|
||||
|
||||
int i = 0;
|
||||
for (CodegenProperty var : cm.vars) {
|
||||
var.vendorExtensions.put("x-index", i);
|
||||
i++;
|
||||
}
|
||||
|
||||
int j = 0;
|
||||
for (CodegenProperty var : cm.allVars) {
|
||||
var.vendorExtensions.put("x-index", j);
|
||||
j++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -310,7 +310,9 @@
|
||||
{{/returnContainer}}
|
||||
//return type
|
||||
{{/returnTypeIsPrimitive}}
|
||||
apiClient_free(apiClient);
|
||||
if (apiClient->dataReceived) {
|
||||
free(apiClient->dataReceived);
|
||||
}
|
||||
{{#hasQueryParams}}list_free(localVarQueryParameters);{{/hasQueryParams}}
|
||||
{{#hasHeaderParams}}list_free(localVarHeaderParameters);{{/hasHeaderParams}}
|
||||
{{#hasFormParams}}list_free(localVarFormParameters);{{/hasFormParams}}
|
||||
@@ -380,7 +382,10 @@ end:
|
||||
{{/returnType}}
|
||||
{{^returnType}}
|
||||
//No return type
|
||||
end: apiClient_free(apiClient);
|
||||
end:
|
||||
if (apiClient->dataReceived) {
|
||||
free(apiClient->dataReceived);
|
||||
}
|
||||
{{#hasQueryParams}}list_free(localVarQueryParameters);{{/hasQueryParams}}
|
||||
{{#hasHeaderParams}}list_free(localVarHeaderParameters);{{/hasHeaderParams}}
|
||||
{{#hasFormParams}}list_free(localVarFormParameters);{{/hasFormParams}}
|
||||
|
||||
@@ -12,20 +12,48 @@ apiClient_t *apiClient_create() {
|
||||
apiClient->basePath = "{{{basePath}}}";
|
||||
apiClient->dataReceived = NULL;
|
||||
apiClient->response_code = 0;
|
||||
#ifdef BASIC_AUTH
|
||||
{{#hasAuthMethods}}
|
||||
{{#authMethods}}
|
||||
{{#isBasic}}
|
||||
apiClient->username = NULL;
|
||||
apiClient->password = NULL;
|
||||
#endif // BASIC_AUTH
|
||||
#ifdef OAUTH2
|
||||
{{/isBasic}}
|
||||
{{#isOAuth}}
|
||||
apiClient->accessToken = NULL;
|
||||
#endif // OAUTH2
|
||||
{{/isOAuth}}
|
||||
{{#isApiKey}}
|
||||
apiClient->apiKeys = NULL;
|
||||
{{/isApiKey}}
|
||||
{{/authMethods}}
|
||||
{{/hasAuthMethods}}
|
||||
|
||||
return apiClient;
|
||||
}
|
||||
|
||||
void apiClient_free(apiClient_t *apiClient) {
|
||||
if(apiClient->dataReceived) {
|
||||
free(apiClient->dataReceived);
|
||||
if(apiClient->basePath) {
|
||||
free(apiClient->basePath);
|
||||
}
|
||||
{{#hasAuthMethods}}
|
||||
{{#authMethods}}
|
||||
{{#isBasic}}
|
||||
if(apiClient->username) {
|
||||
free(apiClient->username);
|
||||
}
|
||||
if(apiClient->password) {
|
||||
free(apiClient->password);
|
||||
}
|
||||
{{/isBasic}}
|
||||
{{#isOAuth}}
|
||||
if(apiClient->accessToken) {
|
||||
free(apiClient->accessToken);
|
||||
}
|
||||
{{/isOAuth}}
|
||||
{{#isApiKey}}
|
||||
list_free(apiClient->apiKeys);
|
||||
{{/isApiKey}}
|
||||
{{/authMethods}}
|
||||
{{/hasAuthMethods}}
|
||||
free(apiClient);
|
||||
curl_global_cleanup();
|
||||
}
|
||||
@@ -254,11 +282,9 @@ void apiClient_invoke(apiClient_t *apiClient,
|
||||
if(strcmp(keyValuePair->key,
|
||||
"file") == 0)
|
||||
{
|
||||
printf("Size of fileVar - %p\n",fileVar);
|
||||
memcpy(&fileVar,
|
||||
keyValuePair->value,
|
||||
sizeof(fileVar));
|
||||
printf("Size of fileVar1 - %p\n",fileVar);
|
||||
curl_mime_data(part,
|
||||
fileVar->fileData,
|
||||
fileVar->fileSize);
|
||||
@@ -287,8 +313,12 @@ void apiClient_invoke(apiClient_t *apiClient,
|
||||
free(headerValueToWrite);
|
||||
}
|
||||
}
|
||||
{{#hasAuthMethods}}
|
||||
{{#authMethods}}
|
||||
{{#isApiKey}}
|
||||
// this would only be generated for apiKey authentication
|
||||
#ifdef API_KEY
|
||||
if (apiClient->apiKeys != NULL)
|
||||
{
|
||||
list_ForEach(listEntry, apiClient->apiKeys) {
|
||||
keyValuePair_t *apiKey = listEntry->data;
|
||||
if((apiKey->key != NULL) &&
|
||||
@@ -300,7 +330,10 @@ void apiClient_invoke(apiClient_t *apiClient,
|
||||
free(headerValueToWrite);
|
||||
}
|
||||
}
|
||||
#endif // API_KEY
|
||||
}
|
||||
{{/isApiKey}}
|
||||
{{/authMethods}}
|
||||
{{/hasAuthMethods}}
|
||||
|
||||
char *targetUrl =
|
||||
assembleTargetUrl(apiClient->basePath,
|
||||
@@ -316,19 +349,11 @@ void apiClient_invoke(apiClient_t *apiClient,
|
||||
&apiClient->dataReceived);
|
||||
curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
|
||||
curl_easy_setopt(handle, CURLOPT_VERBOSE, 0); // to get curl debug msg 0: to disable, 1L:to enable
|
||||
// this would only be generated for OAuth2 authentication
|
||||
#ifdef OAUTH2
|
||||
if(apiClient->accessToken != NULL) {
|
||||
// curl_easy_setopt(handle, CURLOPT_HTTPAUTH, CURLAUTH_BEARER);
|
||||
curl_easy_setopt(handle,
|
||||
CURLOPT_XOAUTH2_BEARER,
|
||||
apiClient->accessToken);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
{{#hasAuthMethods}}
|
||||
{{#authMethods}}
|
||||
{{#isBasic}}
|
||||
// this would only be generated for basic authentication:
|
||||
#ifdef BASIC_AUTH
|
||||
char *authenticationToken;
|
||||
|
||||
if((apiClient->username != NULL) &&
|
||||
@@ -351,8 +376,18 @@ void apiClient_invoke(apiClient_t *apiClient,
|
||||
CURLOPT_USERPWD,
|
||||
authenticationToken);
|
||||
}
|
||||
|
||||
#endif // BASIC_AUTH
|
||||
{{/isBasic}}
|
||||
{{#isOAuth}}
|
||||
// this would only be generated for OAuth2 authentication
|
||||
if(apiClient->accessToken != NULL) {
|
||||
// curl_easy_setopt(handle, CURLOPT_HTTPAUTH, CURLAUTH_BEARER);
|
||||
curl_easy_setopt(handle,
|
||||
CURLOPT_XOAUTH2_BEARER,
|
||||
apiClient->accessToken);
|
||||
}
|
||||
{{/isOAuth}}
|
||||
{{/authMethods}}
|
||||
{{/hasAuthMethods}}
|
||||
|
||||
if(bodyParameters != NULL) {
|
||||
postData(handle, bodyParameters);
|
||||
@@ -371,16 +406,27 @@ void apiClient_invoke(apiClient_t *apiClient,
|
||||
if(res == CURLE_OK) {
|
||||
curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &apiClient->response_code);
|
||||
} else {
|
||||
fprintf(stderr, "curl_easy_perform() failed: %s\n",
|
||||
char *url,*ip,*scheme;
|
||||
long port;
|
||||
curl_easy_getinfo(handle, CURLINFO_EFFECTIVE_URL, &url);
|
||||
curl_easy_getinfo(handle, CURLINFO_PRIMARY_IP, &ip);
|
||||
curl_easy_getinfo(handle, CURLINFO_PRIMARY_PORT, &port);
|
||||
curl_easy_getinfo(handle, CURLINFO_SCHEME, &scheme);
|
||||
fprintf(stderr, "curl_easy_perform() failed\n\nURL: %s\nIP: %s\nPORT: %li\nSCHEME: %s\nStrERROR: %s\n",url,ip,port,scheme,
|
||||
curl_easy_strerror(res));
|
||||
}
|
||||
#ifdef BASIC_AUTH
|
||||
{{#hasAuthMethods}}
|
||||
{{#authMethods}}
|
||||
{{#isBasic}}
|
||||
if((apiClient->username != NULL) &&
|
||||
(apiClient->password != NULL) )
|
||||
{
|
||||
free(authenticationToken);
|
||||
}
|
||||
#endif // BASIC_AUTH
|
||||
{{/isBasic}}
|
||||
{{/authMethods}}
|
||||
{{/hasAuthMethods}}
|
||||
|
||||
curl_easy_cleanup(handle);
|
||||
if(formParameters != NULL) {
|
||||
free(formString);
|
||||
|
||||
@@ -12,19 +12,20 @@ typedef struct apiClient_t {
|
||||
char *basePath;
|
||||
void *dataReceived;
|
||||
long response_code;
|
||||
// this would only be generated for basic authentication
|
||||
#ifdef BASIC_AUTH
|
||||
{{#hasAuthMethods}}
|
||||
{{#authMethods}}
|
||||
{{#isBasic}}
|
||||
char *username;
|
||||
char *password;
|
||||
#endif // BASIC_AUTH
|
||||
// this would only be generated for OAUTH2 authentication
|
||||
#ifdef OAUTH2
|
||||
{{/isBasic}}
|
||||
{{#isOAuth}}
|
||||
char *accessToken;
|
||||
#endif // OAUTH2
|
||||
#ifdef API_KEY
|
||||
//this would only be generated for apiKey authentication
|
||||
{{/isOAuth}}
|
||||
{{#isApiKey}}
|
||||
list_t *apiKeys;
|
||||
#endif // API_KEY
|
||||
{{/isApiKey}}
|
||||
{{/authMethods}}
|
||||
{{/hasAuthMethods}}
|
||||
} apiClient_t;
|
||||
|
||||
typedef struct FileStruct
|
||||
|
||||
@@ -121,7 +121,7 @@ if(hasProperty('target') && target == 'android') {
|
||||
ext {
|
||||
swagger_annotations_version = "1.5.21"
|
||||
jackson_version = "2.8.11"
|
||||
jackson_databind_version = "2.8.11.2"
|
||||
jackson_databind_version = "2.8.11.3"
|
||||
{{#threetenbp}}
|
||||
threepane_version = "2.6.4"
|
||||
{{/threetenbp}}
|
||||
|
||||
@@ -16,7 +16,7 @@ lazy val root = (project in file(".")).
|
||||
"io.github.openfeign.form" % "feign-form" % "2.1.0" % "compile",
|
||||
"com.fasterxml.jackson.core" % "jackson-core" % "2.8.11" % "compile",
|
||||
"com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.11" % "compile",
|
||||
"com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.2" % "compile",
|
||||
"com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.3" % "compile",
|
||||
"com.fasterxml.jackson.datatype" % "jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}" % "2.8.7" % "compile",
|
||||
"com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4" % "compile",
|
||||
"org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile",
|
||||
|
||||
@@ -303,7 +303,7 @@
|
||||
<feign-version>{{#useFeign10}}10.0.1{{/useFeign10}}{{^useFeign10}}9.4.0{{/useFeign10}}</feign-version>
|
||||
<feign-form-version>2.1.0</feign-form-version>
|
||||
<jackson-version>2.8.11</jackson-version>
|
||||
<jackson-databind-version>2.8.11.2</jackson-databind-version>
|
||||
<jackson-databind-version>2.8.11.3</jackson-databind-version>
|
||||
{{#threetenbp}}
|
||||
<jackson-threetenbp-version>2.6.4</jackson-threetenbp-version>
|
||||
{{/threetenbp}}
|
||||
|
||||
@@ -121,7 +121,7 @@ if(hasProperty('target') && target == 'android') {
|
||||
ext {
|
||||
swagger_annotations_version = "1.5.21"
|
||||
jackson_version = "2.8.11"
|
||||
jackson_databind_version = "2.8.11.2"
|
||||
jackson_databind_version = "2.8.11.3"
|
||||
google_api_client_version = "1.23.0"
|
||||
jersey_common_version = "2.25.1"
|
||||
jodatime_version = "2.9.9"
|
||||
|
||||
@@ -14,7 +14,7 @@ lazy val root = (project in file(".")).
|
||||
"org.glassfish.jersey.core" % "jersey-common" % "2.25.1",
|
||||
"com.fasterxml.jackson.core" % "jackson-core" % "2.8.11" % "compile",
|
||||
"com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.11" % "compile",
|
||||
"com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.2" % "compile",
|
||||
"com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.3" % "compile",
|
||||
{{#withXml}}
|
||||
"com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.8.9" % "compile",
|
||||
{{/withXml}}
|
||||
|
||||
@@ -296,7 +296,7 @@
|
||||
<google-api-client-version>1.23.0</google-api-client-version>
|
||||
<jersey-common-version>2.25.1</jersey-common-version>
|
||||
<jackson-version>2.8.11</jackson-version>
|
||||
<jackson-databind-version>2.8.11.2</jackson-databind-version>
|
||||
<jackson-databind-version>2.8.11.3</jackson-databind-version>
|
||||
{{#joda}}
|
||||
<jodatime-version>2.9.9</jodatime-version>
|
||||
{{/joda}}
|
||||
|
||||
@@ -120,7 +120,7 @@ if(hasProperty('target') && target == 'android') {
|
||||
ext {
|
||||
swagger_annotations_version = "1.5.21"
|
||||
jackson_version = "2.8.11"
|
||||
jackson_databind_version = "2.8.11.2"
|
||||
jackson_databind_version = "2.8.11.3"
|
||||
{{#supportJava6}}
|
||||
jersey_version = "2.6"
|
||||
commons_io_version=2.5
|
||||
|
||||
@@ -15,7 +15,7 @@ lazy val root = (project in file(".")).
|
||||
"org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}},
|
||||
"com.fasterxml.jackson.core" % "jackson-core" % "2.8.11" % "compile",
|
||||
"com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.11" % "compile",
|
||||
"com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.2" % "compile",
|
||||
"com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.3" % "compile",
|
||||
{{#joda}}
|
||||
"com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.8.9" % "compile",
|
||||
{{/joda}}
|
||||
|
||||
@@ -333,7 +333,7 @@
|
||||
<commons_lang3_version>3.6</commons_lang3_version>
|
||||
{{/supportJava6}}
|
||||
<jackson-version>2.8.11</jackson-version>
|
||||
<jackson-databind-version>2.8.11.2</jackson-databind-version>
|
||||
<jackson-databind-version>2.8.11.3</jackson-databind-version>
|
||||
{{#threetenbp}}
|
||||
<threetenbp-version>2.6.4</threetenbp-version>
|
||||
{{/threetenbp}}
|
||||
|
||||
@@ -18,9 +18,10 @@ import org.threeten.bp.LocalDate;
|
||||
import org.threeten.bp.OffsetDateTime;
|
||||
import org.threeten.bp.format.DateTimeFormatter;
|
||||
{{/threetenbp}}
|
||||
|
||||
{{#hasOAuthMethods}}
|
||||
import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder;
|
||||
import org.apache.oltu.oauth2.common.message.types.GrantType;
|
||||
{{/hasOAuthMethods}}
|
||||
|
||||
import javax.net.ssl.*;
|
||||
import java.io.File;
|
||||
@@ -92,7 +93,10 @@ public class ApiClient {
|
||||
// Prevent the authentications from being modified.
|
||||
authentications = Collections.unmodifiableMap(authentications);
|
||||
}
|
||||
{{#authMethods}}{{#isOAuth}}
|
||||
|
||||
{{#hasOAuthMethods}}
|
||||
{{#oauthMethods}}
|
||||
{{#-first}}
|
||||
/*
|
||||
* Constructor for ApiClient to support access token retry on 401/403 configured with client ID
|
||||
*/
|
||||
@@ -123,7 +127,10 @@ public class ApiClient {
|
||||
// Prevent the authentications from being modified.
|
||||
authentications = Collections.unmodifiableMap(authentications);
|
||||
}
|
||||
{{/isOAuth}}{{/authMethods}}
|
||||
|
||||
{{/-first}}
|
||||
{{/oauthMethods}}
|
||||
{{/hasOAuthMethods}}
|
||||
private void init() {
|
||||
httpClient = new OkHttpClient();
|
||||
|
||||
|
||||
@@ -119,12 +119,14 @@ if(hasProperty('target') && target == 'android') {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile 'io.swagger:swagger-annotations:1.5.17'
|
||||
compile 'io.swagger:swagger-annotations:1.5.21'
|
||||
compile 'com.squareup.okhttp:okhttp:2.7.5'
|
||||
compile 'com.squareup.okhttp:logging-interceptor:2.7.5'
|
||||
compile 'com.google.code.gson:gson:2.8.1'
|
||||
compile 'com.google.code.gson:gson:2.8.5'
|
||||
compile 'io.gsonfire:gson-fire:1.8.0'
|
||||
{{#hasOAuthMethods}}
|
||||
compile group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.1'
|
||||
{{/hasOAuthMethods}}
|
||||
compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.8.1'
|
||||
{{#joda}}
|
||||
compile 'joda-time:joda-time:2.9.9'
|
||||
|
||||
@@ -9,11 +9,14 @@ lazy val root = (project in file(".")).
|
||||
publishArtifact in (Compile, packageDoc) := false,
|
||||
resolvers += Resolver.mavenLocal,
|
||||
libraryDependencies ++= Seq(
|
||||
"io.swagger" % "swagger-annotations" % "1.5.17",
|
||||
"io.swagger" % "swagger-annotations" % "1.5.21",
|
||||
"com.squareup.okhttp" % "okhttp" % "2.7.5",
|
||||
"com.squareup.okhttp" % "logging-interceptor" % "2.7.5",
|
||||
"com.google.code.gson" % "gson" % "2.8.1",
|
||||
"com.google.code.gson" % "gson" % "2.8.5",
|
||||
"org.apache.commons" % "commons-lang3" % "3.8.1",
|
||||
{{#hasOAuthMethods}}
|
||||
"org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1",
|
||||
{{/hasOAuthMethods}}
|
||||
{{#joda}}
|
||||
"joda-time" % "joda-time" % "2.9.9" % "compile",
|
||||
{{/joda}}
|
||||
|
||||
@@ -220,11 +220,13 @@
|
||||
<artifactId>gson-fire</artifactId>
|
||||
<version>${gson-fire-version}</version>
|
||||
</dependency>
|
||||
{{#hasOAuthMethods}}
|
||||
<dependency>
|
||||
<groupId>org.apache.oltu.oauth2</groupId>
|
||||
<artifactId>org.apache.oltu.oauth2.client</artifactId>
|
||||
<version>1.0.1</version>
|
||||
</dependency>
|
||||
{{/hasOAuthMethods}}
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
@@ -288,9 +290,9 @@
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
<gson-fire-version>1.8.0</gson-fire-version>
|
||||
<swagger-core-version>1.5.18</swagger-core-version>
|
||||
<swagger-core-version>1.5.21</swagger-core-version>
|
||||
<okhttp-version>2.7.5</okhttp-version>
|
||||
<gson-version>2.8.1</gson-version>
|
||||
<gson-version>2.8.5</gson-version>
|
||||
<commons-lang3-version>3.8.1</commons-lang3-version>
|
||||
{{#joda}}
|
||||
<jodatime-version>2.9.9</jodatime-version>
|
||||
|
||||
@@ -120,7 +120,7 @@ if(hasProperty('target') && target == 'android') {
|
||||
ext {
|
||||
swagger_annotations_version = "1.5.21"
|
||||
jackson_version = "2.8.11"
|
||||
jackson_databind_version = "2.8.11.2"
|
||||
jackson_databind_version = "2.8.11.3"
|
||||
threetenbp_version = "2.6.4"
|
||||
resteasy_version = "3.1.3.Final"
|
||||
{{^java8}}
|
||||
|
||||
@@ -15,7 +15,7 @@ lazy val root = (project in file(".")).
|
||||
"org.jboss.resteasy" % "resteasy-jackson2-provider" % "3.1.3.Final" % "compile",
|
||||
"com.fasterxml.jackson.core" % "jackson-core" % "2.8.11" % "compile",
|
||||
"com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.11" % "compile",
|
||||
"com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.2" % "compile",
|
||||
"com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.3" % "compile",
|
||||
"com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4" % "compile",
|
||||
{{#java8}}
|
||||
"com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.8.6" % "compile",
|
||||
|
||||
@@ -267,7 +267,7 @@
|
||||
<swagger-annotations-version>1.5.21</swagger-annotations-version>
|
||||
<resteasy-version>3.1.3.Final</resteasy-version>
|
||||
<jackson-version>2.8.11</jackson-version>
|
||||
<jackson-databind-version>2.8.11</jackson-databind-version>
|
||||
<jackson-databind-version>2.8.11.3</jackson-databind-version>
|
||||
<threetenbp-version>2.6.4</threetenbp-version>
|
||||
{{^java8}}
|
||||
<jodatime-version>2.9.9</jodatime-version>
|
||||
|
||||
@@ -121,7 +121,7 @@ if(hasProperty('target') && target == 'android') {
|
||||
ext {
|
||||
swagger_annotations_version = "1.5.21"
|
||||
jackson_version = "2.8.11"
|
||||
jackson_databind_version = "2.8.11.2"
|
||||
jackson_databind_version = "2.8.11.3"
|
||||
spring_web_version = "4.3.9.RELEASE"
|
||||
jodatime_version = "2.9.9"
|
||||
junit_version = "4.12"
|
||||
|
||||
@@ -298,7 +298,7 @@
|
||||
<swagger-annotations-version>1.5.21</swagger-annotations-version>
|
||||
<spring-web-version>4.3.9.RELEASE</spring-web-version>
|
||||
<jackson-version>2.8.11</jackson-version>
|
||||
<jackson-databind-version>2.8.11.2</jackson-databind-version>
|
||||
<jackson-databind-version>2.8.11.3</jackson-databind-version>
|
||||
{{#joda}}
|
||||
<jodatime-version>2.9.9</jodatime-version>
|
||||
{{/joda}}
|
||||
|
||||
@@ -132,7 +132,7 @@ ext {
|
||||
{{/play25}}
|
||||
{{#play26}}
|
||||
jackson_version = "2.8.11"
|
||||
jackson_databind_version = "2.8.11"
|
||||
jackson_databind_version = "2.8.11.3"
|
||||
play_version = "2.6.7"
|
||||
{{/play26}}
|
||||
{{/usePlayWS}}
|
||||
@@ -187,6 +187,7 @@ dependencies {
|
||||
compile "com.squareup.retrofit2:converter-jackson:$retrofit_version"
|
||||
compile "com.fasterxml.jackson.core:jackson-core:$jackson_version"
|
||||
compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version"
|
||||
compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version"
|
||||
compile "com.fasterxml.jackson.datatype:jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}:$jackson_version"
|
||||
{{/usePlayWS}}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ lazy val root = (project in file(".")).
|
||||
"javax.validation" % "validation-api" % "1.1.0.Final" % "compile",
|
||||
"com.fasterxml.jackson.core" % "jackson-core" % "2.8.11" % "compile",
|
||||
"com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.11" % "compile",
|
||||
"com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.2" % "compile",
|
||||
"com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.3" % "compile",
|
||||
{{/play26}}
|
||||
"com.squareup.retrofit2" % "converter-jackson" % "2.3.0" % "compile",
|
||||
{{/usePlayWS}}
|
||||
|
||||
@@ -287,7 +287,7 @@
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson-version}</version>
|
||||
<version>${jackson-databind-version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
@@ -354,6 +354,7 @@
|
||||
<gson-fire-version>1.8.0</gson-fire-version>
|
||||
<swagger-annotations-version>1.5.21</swagger-annotations-version>
|
||||
{{#usePlayWS}}
|
||||
<jackson-databind-version>2.8.11.3</jackson-databind-version>
|
||||
{{#play24}}
|
||||
<jackson-version>2.6.6</jackson-version>
|
||||
<play-version>2.4.11</play-version>
|
||||
|
||||
@@ -2,6 +2,7 @@ package {{invokerPackage}};
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
@@ -88,16 +89,21 @@ public class ApiClient {
|
||||
|
||||
public ApiClient() {
|
||||
this.dateFormat = createDefaultDateFormat();
|
||||
this.webClient = buildWebClient(new ObjectMapper(), dateFormat);
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.setDateFormat(dateFormat);
|
||||
mapper.registerModule(new JavaTimeModule());
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
|
||||
this.webClient = buildWebClient(mapper);
|
||||
this.init();
|
||||
}
|
||||
|
||||
public ApiClient(ObjectMapper mapper, DateFormat format) {
|
||||
this(buildWebClient(mapper.copy(), format), format);
|
||||
this(buildWebClient(mapper.copy()), format);
|
||||
}
|
||||
|
||||
public ApiClient(WebClient webClient, ObjectMapper mapper, DateFormat format) {
|
||||
this(Optional.ofNullable(webClient).orElseGet(() ->buildWebClient(mapper.copy(), format)), format);
|
||||
this(Optional.ofNullable(webClient).orElseGet(() ->buildWebClient(mapper.copy())), format);
|
||||
}
|
||||
|
||||
private ApiClient(WebClient webClient, DateFormat format) {
|
||||
@@ -126,9 +132,7 @@ public class ApiClient {
|
||||
* Build the RestTemplate used to make HTTP requests.
|
||||
* @return RestTemplate
|
||||
*/
|
||||
public static WebClient buildWebClient(ObjectMapper mapper, DateFormat dateFormat) {
|
||||
mapper.setDateFormat(dateFormat);
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
public static WebClient buildWebClient(ObjectMapper mapper) {
|
||||
ExchangeStrategies strategies = ExchangeStrategies
|
||||
.builder()
|
||||
.codecs(clientDefaultCodecsConfigurer -> {
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
<swagger-annotations-version>1.5.20</swagger-annotations-version>
|
||||
<spring-web-version>5.0.7.RELEASE</spring-web-version>
|
||||
<jackson-version>2.8.11</jackson-version>
|
||||
<jackson-databind-version>2.8.11.2</jackson-databind-version>
|
||||
<jackson-databind-version>2.8.11.3</jackson-databind-version>
|
||||
<junit-version>4.12</junit-version>
|
||||
<reactor-version>3.1.8.RELEASE</reactor-version>
|
||||
<reactor-netty-version>0.7.8.RELEASE</reactor-netty-version>
|
||||
|
||||
@@ -18,6 +18,11 @@ import com.google.gson.stream.JsonWriter;
|
||||
{{/gson}}
|
||||
public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} {
|
||||
{{#allowableValues}}{{#enumVars}}
|
||||
{{#enumDescription}}
|
||||
/**
|
||||
* {{enumDescription}}
|
||||
*/
|
||||
{{/enumDescription}}
|
||||
{{{name}}}({{{value}}}){{^-last}},
|
||||
{{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}}
|
||||
|
||||
|
||||
@@ -7,6 +7,11 @@
|
||||
public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} {
|
||||
{{#allowableValues}}
|
||||
{{#enumVars}}
|
||||
{{#enumDescription}}
|
||||
/**
|
||||
* {{enumDescription}}
|
||||
*/
|
||||
{{/enumDescription}}
|
||||
{{{name}}}({{{value}}}){{^-last}},
|
||||
{{/-last}}{{#-last}};{{/-last}}
|
||||
{{/enumVars}}
|
||||
|
||||
@@ -95,6 +95,11 @@
|
||||
* Allow user to override superagent agent
|
||||
*/
|
||||
this.requestAgent = null;
|
||||
|
||||
/*
|
||||
* Allow user to add superagent plugins
|
||||
*/
|
||||
this.plugins = null;
|
||||
};
|
||||
|
||||
{{#emitJSDoc}} /**
|
||||
@@ -381,6 +386,14 @@
|
||||
var url = this.buildUrl(path, pathParams);
|
||||
var request = superagent(httpMethod, url);
|
||||
|
||||
if (this.plugins !== null) {
|
||||
for (var index in this.plugins) {
|
||||
if (this.plugins.hasOwnProperty(index)) {
|
||||
request.use(this.plugins[index])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// apply authentications
|
||||
this.applyAuthToRequest(request, authNames);
|
||||
|
||||
|
||||
@@ -84,6 +84,11 @@ class ApiClient {
|
||||
*/
|
||||
this.requestAgent = null;
|
||||
|
||||
/*
|
||||
* Allow user to add superagent plugins
|
||||
*/
|
||||
this.plugins = null;
|
||||
|
||||
}
|
||||
|
||||
{{#emitJSDoc}}/**
|
||||
@@ -352,6 +357,14 @@ class ApiClient {
|
||||
var url = this.buildUrl(path, pathParams);
|
||||
var request = superagent(httpMethod, url);
|
||||
|
||||
if (this.plugins !== null) {
|
||||
for (var index in this.plugins) {
|
||||
if (this.plugins.hasOwnProperty(index)) {
|
||||
request.use(this.plugins[index])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// apply authentications
|
||||
this.applyAuthToRequest(request, authNames);
|
||||
|
||||
@@ -425,7 +438,14 @@ class ApiClient {
|
||||
{{#usePromises}}return new Promise((resolve, reject) => {
|
||||
request.end((error, response) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
var err = {};
|
||||
err.status = response.status;
|
||||
err.statusText = response.statusText;
|
||||
err.body = response.body;
|
||||
err.response = response;
|
||||
err.error = error;
|
||||
|
||||
reject(err);
|
||||
} else {
|
||||
try {
|
||||
var data = this.deserialize(response, returnType);
|
||||
|
||||
@@ -36,7 +36,7 @@ nlohmann::json {{classname}}::toJson() const
|
||||
{{/required}}{{#required}}val["{{baseName}}"] = m_{{name}};
|
||||
{{/required}}{{/isListContainer}}{{/isPrimitiveType}}{{#isListContainer}}{
|
||||
nlohmann::json jsonArray;
|
||||
for( auto& item : m_{{name}} )
|
||||
for( const auto& item : m_{{name}} )
|
||||
{
|
||||
jsonArray.push_back({{prefix}}ModelBase::toJson(item));
|
||||
}
|
||||
@@ -49,7 +49,7 @@ nlohmann::json {{classname}}::toJson() const
|
||||
}
|
||||
{{/isListContainer}}{{#isMapContainer}}{
|
||||
nlohmann::json jsonObj;
|
||||
for( auto const& item : m_{{name}} )
|
||||
for( const auto& item : m_{{name}} )
|
||||
{ {{^items.isContainer}}
|
||||
jsonObj[item.first] = {{prefix}}ModelBase::toJson(item.second);{{/items.isContainer}} {{#items.isListContainer}}
|
||||
jsonObj[item.first] = {{prefix}}ArrayHelper::toJson<{{{items.items.datatype}}}>(item.second);
|
||||
@@ -84,7 +84,7 @@ void {{classname}}::fromJson(const nlohmann::json& val)
|
||||
{{^required}}if(val.find("{{baseName}}") != val.end())
|
||||
{
|
||||
{{/required}}
|
||||
for( auto& item : val["{{baseName}}"] )
|
||||
for( const auto& item : val["{{baseName}}"] )
|
||||
{
|
||||
{{#isPrimitiveType}}m_{{name}}.push_back(item);
|
||||
{{/isPrimitiveType}}{{^isPrimitiveType}}{{#items.isString}}m_{{name}}.push_back(item);
|
||||
@@ -114,7 +114,7 @@ void {{classname}}::fromJson(const nlohmann::json& val)
|
||||
if(val["{{baseName}}"].is_object()) { {{^items.isContainer}}
|
||||
m_{{name}} = {{prefix}}MapHelper::fromJson<{{{items.datatype}}}>(val["{{baseName}}"]);
|
||||
{{/items.isContainer}} {{#items.isContainer}}
|
||||
for( auto& item : val["{{baseName}}"].items() )
|
||||
for( const auto& item : val["{{baseName}}"].items() )
|
||||
{ {{#items.isMapContainer}}
|
||||
{{{items.datatype}}} newItem = {{prefix}}MapHelper::fromJson<{{{items.items.datatype}}}>(item.value());
|
||||
{{/items.isMapContainer}}{{#items.isListContainer}}
|
||||
|
||||
@@ -172,6 +172,7 @@ void
|
||||
|
||||
if (worker->error_type == QNetworkReply::NoError) {
|
||||
emit {{nickname}}Signal({{#returnType}}output{{/returnType}});
|
||||
emit {{nickname}}SignalFull(worker{{#returnType}}, output{{/returnType}});
|
||||
} else {
|
||||
emit {{nickname}}SignalE({{#returnType}}output, {{/returnType}}error_type, error_str);
|
||||
emit {{nickname}}SignalEFull(worker, error_type, error_str);
|
||||
|
||||
@@ -33,6 +33,8 @@ private:
|
||||
signals:
|
||||
{{#operations}}{{#operation}}void {{nickname}}Signal({{#returnType}}{{{returnType}}} summary{{/returnType}});
|
||||
{{/operation}}{{/operations}}
|
||||
{{#operations}}{{#operation}}void {{nickname}}SignalFull({{prefix}}HttpRequestWorker* worker{{#returnType}}, {{{returnType}}} summary{{/returnType}});
|
||||
{{/operation}}{{/operations}}
|
||||
{{#operations}}{{#operation}}void {{nickname}}SignalE({{#returnType}}{{{returnType}}} summary, {{/returnType}}QNetworkReply::NetworkError error_type, QString& error_str);
|
||||
{{/operation}}{{/operations}}
|
||||
{{#operations}}{{#operation}}void {{nickname}}SignalEFull({{prefix}}HttpRequestWorker* worker, QNetworkReply::NetworkError error_type, QString& error_str);
|
||||
|
||||
@@ -27,7 +27,6 @@ public:
|
||||
{{classname}}();
|
||||
{{classname}}(QString json);
|
||||
~{{classname}}() override;
|
||||
void init();
|
||||
|
||||
QString asJson () const override;
|
||||
QJsonObject asJsonObject() const override;
|
||||
@@ -43,6 +42,7 @@ public:
|
||||
virtual bool isValid() const override;
|
||||
|
||||
private:
|
||||
void init();
|
||||
{{#vars}}
|
||||
{{{dataType}}} {{name}};
|
||||
bool m_{{name}}_isSet;
|
||||
|
||||
@@ -11,6 +11,14 @@ namespace {{this}} {
|
||||
|
||||
class {{prefix}}Object {
|
||||
public:
|
||||
{{prefix}}Object() {
|
||||
|
||||
}
|
||||
|
||||
{{prefix}}Object(QString jsonString) {
|
||||
fromJson(jsonString);
|
||||
}
|
||||
|
||||
virtual ~{{prefix}}Object(){
|
||||
|
||||
}
|
||||
@@ -41,7 +49,7 @@ class {{prefix}}Object {
|
||||
return true;
|
||||
}
|
||||
private :
|
||||
QJsonObject jObj;
|
||||
QJsonObject jObj;
|
||||
};
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
|
||||
@@ -77,7 +77,7 @@ void {{classname}}Request::{{nickname}}Request({{#hasPathParams}}{{#pathParams}}
|
||||
{{^isMapContainer}}
|
||||
{{#isPrimitiveType}}
|
||||
{{{dataType}}} {{paramName}};
|
||||
::{{cppNamespace}}::fromStringValue((QString(socket->readAll()), {{paramName}});
|
||||
::{{cppNamespace}}::fromStringValue(QString(socket->readAll()), {{paramName}});
|
||||
{{/isPrimitiveType}}
|
||||
{{/isMapContainer}}
|
||||
{{#isMapContainer}}
|
||||
|
||||
@@ -27,7 +27,6 @@ public:
|
||||
{{classname}}();
|
||||
{{classname}}(QString json);
|
||||
~{{classname}}() override;
|
||||
void init();
|
||||
|
||||
QString asJson () const override;
|
||||
QJsonObject asJsonObject() const override;
|
||||
@@ -43,6 +42,7 @@ public:
|
||||
virtual bool isValid() const override;
|
||||
|
||||
private:
|
||||
void init();
|
||||
{{#vars}}
|
||||
{{{dataType}}} {{name}};
|
||||
bool m_{{name}}_isSet;
|
||||
|
||||
@@ -11,6 +11,14 @@ namespace {{this}} {
|
||||
|
||||
class {{prefix}}Object {
|
||||
public:
|
||||
{{prefix}}Object() {
|
||||
|
||||
}
|
||||
|
||||
{{prefix}}Object(QString jsonString) {
|
||||
fromJson(jsonString);
|
||||
}
|
||||
|
||||
virtual ~{{prefix}}Object(){
|
||||
|
||||
}
|
||||
@@ -41,7 +49,7 @@ class {{prefix}}Object {
|
||||
return true;
|
||||
}
|
||||
private :
|
||||
QJsonObject jObj;
|
||||
QJsonObject jObj;
|
||||
};
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace {{clientPackage}}
|
||||
private static string _dateTimeFormat = ISO8601_DATETIME_FORMAT;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the the date time format used when serializing in the ApiClient
|
||||
/// Gets or sets the date time format used when serializing in the ApiClient
|
||||
/// By default, it's set to ISO 8601 - "o", for others see:
|
||||
/// https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx
|
||||
/// and https://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx
|
||||
|
||||
@@ -242,7 +242,7 @@ namespace {{packageName}}.Client
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the the date time format used when serializing in the ApiClient
|
||||
/// Gets or sets the date time format used when serializing in the ApiClient
|
||||
/// By default, it's set to ISO 8601 - "o", for others see:
|
||||
/// https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx
|
||||
/// and https://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
{{#description}}
|
||||
/// <value>{{description}}</value>
|
||||
{{/description}}
|
||||
[DataMember(Name="{{baseName}}", EmitDefaultValue={{emitDefaultValue}})]
|
||||
[DataMember(Name="{{baseName}}", EmitDefaultValue={{#isNullable}}true{{/isNullable}}{{^isNullable}}{{emitDefaultValue}}{{/isNullable}})]
|
||||
public {{#complexType}}{{{complexType}}}{{/complexType}}{{^complexType}}{{{datatypeWithEnum}}}{{/complexType}}{{^isContainer}}{{^required}}?{{/required}}{{/isContainer}} {{name}} { get; set; }
|
||||
{{/isEnum}}
|
||||
{{/vars}}
|
||||
@@ -70,12 +70,16 @@
|
||||
{
|
||||
this.{{name}} = {{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}};
|
||||
}
|
||||
|
||||
{{/isEnum}}
|
||||
{{#isEnum}}
|
||||
this.{{name}} = {{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}};
|
||||
{{/isEnum}}
|
||||
{{/required}}
|
||||
{{/isNullable}}
|
||||
{{#isNullable}}
|
||||
this.{{name}} = {{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}};
|
||||
{{/isNullable}}
|
||||
{{/isReadOnly}}
|
||||
{{/isInherited}}
|
||||
{{/vars}}
|
||||
@@ -110,7 +114,7 @@
|
||||
/// {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}}
|
||||
/// </summary>{{#description}}
|
||||
/// <value>{{description}}</value>{{/description}}
|
||||
[DataMember(Name="{{baseName}}", EmitDefaultValue={{emitDefaultValue}})]{{#isDate}}
|
||||
[DataMember(Name="{{baseName}}", EmitDefaultValue={{#isNullable}}true{{/isNullable}}{{^isNullable}}{{emitDefaultValue}}{{/isNullable}})]{{#isDate}}
|
||||
[JsonConverter(typeof(OpenAPIDateConverter))]{{/isDate}}
|
||||
public {{{dataType}}} {{name}} { get; {{#isReadOnly}}private {{/isReadOnly}}set; }
|
||||
|
||||
|
||||
@@ -322,7 +322,7 @@ namespace {{packageName}}.Client
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the the date time format used when serializing in the ApiClient
|
||||
/// Gets or sets the date time format used when serializing in the ApiClient
|
||||
/// By default, it's set to ISO 8601 - "o", for others see:
|
||||
/// https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx
|
||||
/// and https://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx
|
||||
|
||||
@@ -89,22 +89,22 @@ class {{classname}} {
|
||||
authNames);
|
||||
|
||||
if(response.statusCode >= 400) {
|
||||
throw new ApiException(response.statusCode, response.body);
|
||||
throw new ApiException(response.statusCode, _decodeBodyBytes(response));
|
||||
} else if(response.body != null) {
|
||||
{{#isListContainer}}
|
||||
{{#returnType}}
|
||||
return (apiClient.deserialize(response.body, '{{{returnType}}}') as List).map((item) => item as {{returnBaseType}}).toList();
|
||||
return (apiClient.deserialize(_decodeBodyBytes(response), '{{{returnType}}}') as List).map((item) => item as {{returnBaseType}}).toList();
|
||||
{{/returnType}}
|
||||
{{/isListContainer}}
|
||||
{{^isListContainer}}
|
||||
{{#isMapContainer}}
|
||||
{{#returnType}}
|
||||
return new {{{returnType}}}.from(apiClient.deserialize(response.body, '{{{returnType}}}'));
|
||||
return new {{{returnType}}}.from(apiClient.deserialize(_decodeBodyBytes(response), '{{{returnType}}}'));
|
||||
{{/returnType}};
|
||||
{{/isMapContainer}}
|
||||
{{^isMapContainer}}
|
||||
{{#returnType}}
|
||||
return apiClient.deserialize(response.body, '{{{returnType}}}') as {{{returnType}}};
|
||||
return apiClient.deserialize(_decodeBodyBytes(response), '{{{returnType}}}') as {{{returnType}}};
|
||||
{{/returnType}}
|
||||
{{/isMapContainer}}
|
||||
{{/isListContainer}}
|
||||
|
||||
@@ -50,3 +50,15 @@ String parameterToString(dynamic value) {
|
||||
return value.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the decoded body by utf-8 if application/json with the given headers.
|
||||
/// Else, returns the decoded body by default algorithm of dart:http.
|
||||
/// Because avoid to text garbling when header only contains "application/json" without "; charset=utf-8".
|
||||
String _decodeBodyBytes(Response response) {
|
||||
var contentType = response.headers['content-type'];
|
||||
if (contentType != null && contentType.contains("application/json")) {
|
||||
return utf8.decode(response.bodyBytes);
|
||||
} else {
|
||||
return response.body;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,37 +16,41 @@ class {{classname}} {
|
||||
{{classname}}.fromJson(Map<String, dynamic> json) {
|
||||
if (json == null) return;
|
||||
{{#vars}}
|
||||
if (json['{{baseName}}'] == null) {
|
||||
{{name}} = null;
|
||||
} else {
|
||||
{{#isDateTime}}
|
||||
{{name}} = json['{{baseName}}'] == null ? null : DateTime.parse(json['{{baseName}}']);
|
||||
{{name}} = DateTime.parse(json['{{baseName}}']);
|
||||
{{/isDateTime}}
|
||||
{{#isDate}}
|
||||
{{name}} = json['{{baseName}}'] == null ? null : DateTime.parse(json['{{baseName}}']);
|
||||
{{name}} = DateTime.parse(json['{{baseName}}']);
|
||||
{{/isDate}}
|
||||
{{^isDateTime}}
|
||||
{{^isDate}}
|
||||
{{#complexType}}
|
||||
{{#isListContainer}}
|
||||
{{name}} = {{complexType}}.listFromJson(json['{{baseName}}']);
|
||||
{{name}} = {{complexType}}.listFromJson(json['{{baseName}}']);
|
||||
{{/isListContainer}}
|
||||
{{^isListContainer}}
|
||||
{{#isMapContainer}}
|
||||
{{name}} = {{complexType}}.mapFromJson(json['{{baseName}}']);
|
||||
{{name}} = {{complexType}}.mapFromJson(json['{{baseName}}']);
|
||||
{{/isMapContainer}}
|
||||
{{^isMapContainer}}
|
||||
{{name}} = new {{complexType}}.fromJson(json['{{baseName}}']);
|
||||
{{name}} = new {{complexType}}.fromJson(json['{{baseName}}']);
|
||||
{{/isMapContainer}}
|
||||
{{/isListContainer}}
|
||||
{{/complexType}}
|
||||
{{^complexType}}
|
||||
{{#isListContainer}}
|
||||
{{name}} = (json['{{baseName}}'] as List).map((item) => item as {{items.datatype}}).toList();
|
||||
{{name}} = (json['{{baseName}}'] as List).map((item) => item as {{items.datatype}}).toList();
|
||||
{{/isListContainer}}
|
||||
{{^isListContainer}}
|
||||
{{name}} = json['{{baseName}}'];
|
||||
{{name}} = json['{{baseName}}'];
|
||||
{{/isListContainer}}
|
||||
{{/complexType}}
|
||||
{{/isDate}}
|
||||
{{/isDateTime}}
|
||||
}
|
||||
{{/vars}}
|
||||
}
|
||||
|
||||
|
||||
@@ -89,22 +89,22 @@ class {{classname}} {
|
||||
authNames);
|
||||
|
||||
if(response.statusCode >= 400) {
|
||||
throw new ApiException(response.statusCode, response.body);
|
||||
throw new ApiException(response.statusCode, _decodeBodyBytes(response));
|
||||
} else if(response.body != null) {
|
||||
{{#isListContainer}}
|
||||
{{#returnType}}
|
||||
return (apiClient.deserialize(response.body, '{{{returnType}}}') as List).map((item) => item as {{returnBaseType}}).toList();
|
||||
return (apiClient.deserialize(_decodeBodyBytes(response), '{{{returnType}}}') as List).map((item) => item as {{returnBaseType}}).toList();
|
||||
{{/returnType}}
|
||||
{{/isListContainer}}
|
||||
{{^isListContainer}}
|
||||
{{#isMapContainer}}
|
||||
{{#returnType}}
|
||||
return new {{{returnType}}}.from(apiClient.deserialize(response.body, '{{{returnType}}}'));
|
||||
return new {{{returnType}}}.from(apiClient.deserialize(_decodeBodyBytes(response), '{{{returnType}}}'));
|
||||
{{/returnType}};
|
||||
{{/isMapContainer}}
|
||||
{{^isMapContainer}}
|
||||
{{#returnType}}
|
||||
return apiClient.deserialize(response.body, '{{{returnType}}}') as {{{returnType}}};
|
||||
return apiClient.deserialize(_decodeBodyBytes(response), '{{{returnType}}}') as {{{returnType}}};
|
||||
{{/returnType}}
|
||||
{{/isMapContainer}}
|
||||
{{/isListContainer}}
|
||||
|
||||
@@ -50,3 +50,15 @@ String parameterToString(dynamic value) {
|
||||
return value.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the decoded body by utf-8 if application/json with the given headers.
|
||||
/// Else, returns the decoded body by default algorithm of dart:http.
|
||||
/// Because avoid to text garbling when header only contains "application/json" without "; charset=utf-8".
|
||||
String _decodeBodyBytes(Response response) {
|
||||
var contentType = response.headers['content-type'];
|
||||
if (contentType != null && contentType.contains("application/json")) {
|
||||
return utf8.decode(response.bodyBytes);
|
||||
} else {
|
||||
return response.body;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,37 +16,41 @@ class {{classname}} {
|
||||
{{classname}}.fromJson(Map<String, dynamic> json) {
|
||||
if (json == null) return;
|
||||
{{#vars}}
|
||||
if (json['{{baseName}}'] == null) {
|
||||
{{name}} = null;
|
||||
} else {
|
||||
{{#isDateTime}}
|
||||
{{name}} = json['{{baseName}}'] == null ? null : DateTime.parse(json['{{baseName}}']);
|
||||
{{name}} = DateTime.parse(json['{{baseName}}']);
|
||||
{{/isDateTime}}
|
||||
{{#isDate}}
|
||||
{{name}} = json['{{baseName}}'] == null ? null : DateTime.parse(json['{{baseName}}']);
|
||||
{{name}} = DateTime.parse(json['{{baseName}}']);
|
||||
{{/isDate}}
|
||||
{{^isDateTime}}
|
||||
{{^isDate}}
|
||||
{{#complexType}}
|
||||
{{#isListContainer}}
|
||||
{{name}} = {{complexType}}.listFromJson(json['{{baseName}}']);
|
||||
{{name}} = {{complexType}}.listFromJson(json['{{baseName}}']);
|
||||
{{/isListContainer}}
|
||||
{{^isListContainer}}
|
||||
{{#isMapContainer}}
|
||||
{{name}} = {{complexType}}.mapFromJson(json['{{baseName}}']);
|
||||
{{name}} = {{complexType}}.mapFromJson(json['{{baseName}}']);
|
||||
{{/isMapContainer}}
|
||||
{{^isMapContainer}}
|
||||
{{name}} = new {{complexType}}.fromJson(json['{{baseName}}']);
|
||||
{{name}} = new {{complexType}}.fromJson(json['{{baseName}}']);
|
||||
{{/isMapContainer}}
|
||||
{{/isListContainer}}
|
||||
{{/complexType}}
|
||||
{{^complexType}}
|
||||
{{#isListContainer}}
|
||||
{{name}} = ((json['{{baseName}}'] ?? []) as List).map((item) => item as {{items.datatype}}).toList();
|
||||
{{name}} = (json['{{baseName}}'] as List).map((item) => item as {{items.datatype}}).toList();
|
||||
{{/isListContainer}}
|
||||
{{^isListContainer}}
|
||||
{{name}} = json['{{baseName}}'];
|
||||
{{name}} = json['{{baseName}}'];
|
||||
{{/isListContainer}}
|
||||
{{/complexType}}
|
||||
{{/isDate}}
|
||||
{{/isDateTime}}
|
||||
}
|
||||
{{/vars}}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,6 @@ const (
|
||||
type {{classname}} struct {
|
||||
{{#vars}}{{#description}}
|
||||
// {{{description}}}{{/description}}
|
||||
{{name}} {{^isEnum}}{{^isPrimitiveType}}{{^isContainer}}{{^isDateTime}}*{{/isDateTime}}{{/isContainer}}{{/isPrimitiveType}}{{/isEnum}}{{{dataType}}} `json:"{{baseName}}{{^required}},omitempty{{/required}}"{{#vendorExtensions.x-go-custom-tag}} {{{.}}}{{/vendorExtensions.x-go-custom-tag}}`
|
||||
{{name}} {{#isNullable}}*{{/isNullable}}{{{dataType}}} `json:"{{baseName}}{{^required}},omitempty{{/required}}"{{#vendorExtensions.x-go-custom-tag}} {{{.}}}{{/vendorExtensions.x-go-custom-tag}}`
|
||||
{{/vars}}
|
||||
}{{/isEnum}}{{/model}}{{/models}}
|
||||
|
||||
@@ -19,6 +19,6 @@ const (
|
||||
type {{classname}} struct {
|
||||
{{#vars}}{{#description}}
|
||||
// {{{description}}}{{/description}}
|
||||
{{name}} {{^isEnum}}{{^isPrimitiveType}}{{^isContainer}}{{^isDateTime}}*{{/isDateTime}}{{/isContainer}}{{/isPrimitiveType}}{{/isEnum}}{{{dataType}}} `json:"{{baseName}}{{^required}},omitempty{{/required}}"{{#vendorExtensions.x-go-custom-tag}} {{{.}}}{{/vendorExtensions.x-go-custom-tag}}`
|
||||
{{name}} {{#isNullable}}*{{/isNullable}}{{{dataType}}} `json:"{{baseName}}{{^required}},omitempty{{/required}}"{{#vendorExtensions.x-go-custom-tag}} {{{.}}}{{/vendorExtensions.x-go-custom-tag}}`
|
||||
{{/vars}}
|
||||
}{{/isEnum}}{{/model}}{{/models}}
|
||||
|
||||
@@ -35,7 +35,7 @@ type {{classname}} struct {
|
||||
{{#description}}
|
||||
// {{{description}}}
|
||||
{{/description}}
|
||||
{{name}} {{{dataType}}} `json:"{{baseName}}{{^required}},omitempty{{/required}}"{{#withXml}} xml:"{{baseName}}{{#isXmlAttribute}},attr{{/isXmlAttribute}}"{{/withXml}}{{#vendorExtensions.x-go-custom-tag}} {{{.}}}{{/vendorExtensions.x-go-custom-tag}}`
|
||||
{{name}} {{#isNullable}}*{{/isNullable}}{{{dataType}}} `json:"{{baseName}}{{^required}},omitempty{{/required}}"{{#withXml}} xml:"{{baseName}}{{#isXmlAttribute}},attr{{/isXmlAttribute}}"{{/withXml}}{{#vendorExtensions.x-go-custom-tag}} {{{.}}}{{/vendorExtensions.x-go-custom-tag}}`
|
||||
{{/vars}}
|
||||
}
|
||||
{{/isEnum}}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
{{#vars}}**{{name}}** | {{#isPrimitiveType}}**{{{dataType}}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{{dataType}}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#readOnly}}[readonly] {{/readOnly}}{{#defaultValue}}[default to {{{.}}}]{{/defaultValue}}
|
||||
{{#vars}}**{{name}}** | {{#isNullable}}Pointer to {{/isNullable}}{{#isPrimitiveType}}**{{{dataType}}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{{dataType}}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#readOnly}}[readonly] {{/readOnly}}{{#defaultValue}}[default to {{{.}}}]{{/defaultValue}}
|
||||
{{/vars}}
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
@@ -26,7 +26,6 @@ use Module::Runtime qw(use_module);
|
||||
|
||||
use {{moduleName}}::Configuration;
|
||||
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
|
||||
@@ -41,7 +40,7 @@ sub new {
|
||||
'ua' => LWP::UserAgent->new,
|
||||
'config' => $config,
|
||||
);
|
||||
|
||||
|
||||
return bless \%args, $class;
|
||||
}
|
||||
|
||||
@@ -76,23 +75,21 @@ sub set_timeout {
|
||||
sub call_api {
|
||||
my $self = shift;
|
||||
my ($resource_path, $method, $query_params, $post_params, $header_params, $body_data, $auth_settings) = @_;
|
||||
|
||||
|
||||
# update parameters based on authentication settings
|
||||
$self->update_params_for_auth($header_params, $query_params, $auth_settings);
|
||||
|
||||
|
||||
|
||||
my $_url = $self->{config}{base_url} . $resource_path;
|
||||
|
||||
|
||||
# build query
|
||||
if (%$query_params) {
|
||||
$_url = ($_url . '?' . eval { URI::Query->new($query_params)->stringify });
|
||||
}
|
||||
|
||||
|
||||
|
||||
# body data
|
||||
$body_data = to_json($body_data->to_hash) if defined $body_data && $body_data->can('to_hash'); # model to json string
|
||||
my $_body_data = %$post_params ? $post_params : $body_data;
|
||||
|
||||
|
||||
# Make the HTTP request
|
||||
my $_request;
|
||||
if ($method eq 'POST') {
|
||||
@@ -101,15 +98,15 @@ sub call_api {
|
||||
'form-data' : $header_params->{'Content-Type'};
|
||||
|
||||
$_request = POST($_url, %$header_params, Content => $_body_data);
|
||||
|
||||
|
||||
}
|
||||
elsif ($method eq 'PUT') {
|
||||
# multipart
|
||||
$header_params->{'Content-Type'} = lc $header_params->{'Content-Type'} eq 'multipart/form' ?
|
||||
'form-data' : $header_params->{'Content-Type'};
|
||||
|
||||
|
||||
$_request = PUT($_url, %$header_params, Content => $_body_data);
|
||||
|
||||
|
||||
}
|
||||
elsif ($method eq 'GET') {
|
||||
my $headers = HTTP::Headers->new(%$header_params);
|
||||
@@ -130,17 +127,17 @@ sub call_api {
|
||||
|
||||
$self->{ua}->timeout($self->{http_timeout} || $self->{config}{http_timeout});
|
||||
$self->{ua}->agent($self->{http_user_agent} || $self->{config}{http_user_agent});
|
||||
|
||||
|
||||
$log->debugf("REQUEST: %s", $_request->as_string);
|
||||
my $_response = $self->{ua}->request($_request);
|
||||
$log->debugf("RESPONSE: %s", $_response->as_string);
|
||||
|
||||
|
||||
unless ($_response->is_success) {
|
||||
croak(sprintf "API Exception(%s): %s\n%s", $_response->code, $_response->message, $_response->content);
|
||||
}
|
||||
|
||||
return $_response->content;
|
||||
|
||||
|
||||
}
|
||||
|
||||
# Take value and turn it into a string suitable for inclusion in
|
||||
@@ -160,12 +157,12 @@ sub to_path_value {
|
||||
# @param object $object an object to be serialized to a string
|
||||
# @return string the serialized object
|
||||
sub to_query_value {
|
||||
my ($self, $object) = @_;
|
||||
if (ref($object) eq 'ARRAY') {
|
||||
return join(',', @$object);
|
||||
} else {
|
||||
return $self->to_string($object);
|
||||
}
|
||||
my ($self, $object) = @_;
|
||||
if (ref($object) eq 'ARRAY') {
|
||||
return join(',', @$object);
|
||||
} else {
|
||||
return $self->to_string($object);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -213,7 +210,7 @@ sub deserialize
|
||||
{
|
||||
my ($self, $class, $data) = @_;
|
||||
$log->debugf("deserializing %s for %s", $data, $class);
|
||||
|
||||
|
||||
if (not defined $data) {
|
||||
return undef;
|
||||
} elsif ( (substr($class, 0, 5)) eq 'HASH[') { #hash
|
||||
@@ -232,10 +229,9 @@ sub deserialize
|
||||
} else {
|
||||
#TODO log error
|
||||
}
|
||||
|
||||
} elsif ( (substr($class, 0, 6)) eq 'ARRAY[' ) { # array of data
|
||||
return $data if $data eq '[]'; # return if empty array
|
||||
|
||||
|
||||
my $_sub_class = substr($class, 6, -1);
|
||||
my $_json_data = decode_json $data;
|
||||
my @_values = ();
|
||||
@@ -259,7 +255,6 @@ sub deserialize
|
||||
return $_instance->from_hash(decode_json $data);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# return 'Accept' based on an array of accept provided
|
||||
@@ -268,7 +263,7 @@ sub deserialize
|
||||
sub select_header_accept
|
||||
{
|
||||
my ($self, @header) = @_;
|
||||
|
||||
|
||||
if (@header == 0 || (@header == 1 && $header[0] eq '')) {
|
||||
return undef;
|
||||
} elsif (grep(/^application\/json$/i, @header)) {
|
||||
@@ -276,7 +271,7 @@ sub select_header_accept
|
||||
} else {
|
||||
return join(',', @header);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
# return the content type based on an array of content-type provided
|
||||
@@ -285,7 +280,7 @@ sub select_header_accept
|
||||
sub select_header_content_type
|
||||
{
|
||||
my ($self, @header) = @_;
|
||||
|
||||
|
||||
if (@header == 0 || (@header == 1 && $header[0] eq '')) {
|
||||
return 'application/json'; # default to application/json
|
||||
} elsif (grep(/^application\/json$/i, @header)) {
|
||||
@@ -293,7 +288,7 @@ sub select_header_content_type
|
||||
} else {
|
||||
return join(',', @header);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
# Get API key (with prefix if set)
|
||||
@@ -301,15 +296,15 @@ sub select_header_content_type
|
||||
# @return string API key with the prefix
|
||||
sub get_api_key_with_prefix
|
||||
{
|
||||
my ($self, $key_name) = @_;
|
||||
my ($self, $key_name) = @_;
|
||||
|
||||
my $api_key = $self->{config}{api_key}{$key_name};
|
||||
|
||||
return unless $api_key;
|
||||
|
||||
my $prefix = $self->{config}{api_key_prefix}{$key_name};
|
||||
return $prefix ? "$prefix $api_key" : $api_key;
|
||||
}
|
||||
my $api_key = $self->{config}{api_key}{$key_name};
|
||||
|
||||
return unless $api_key;
|
||||
|
||||
my $prefix = $self->{config}{api_key_prefix}{$key_name};
|
||||
return $prefix ? "$prefix $api_key" : $api_key;
|
||||
}
|
||||
|
||||
# update header and query param based on authentication setting
|
||||
#
|
||||
@@ -318,36 +313,46 @@ sub get_api_key_with_prefix
|
||||
# @param array $authSettings array of authentication scheme (e.g ['api_key'])
|
||||
sub update_params_for_auth {
|
||||
my ($self, $header_params, $query_params, $auth_settings) = @_;
|
||||
|
||||
|
||||
return $self->_global_auth_setup($header_params, $query_params)
|
||||
unless $auth_settings && @$auth_settings;
|
||||
|
||||
unless $auth_settings && @$auth_settings;
|
||||
|
||||
# one endpoint can have more than 1 auth settings
|
||||
foreach my $auth (@$auth_settings) {
|
||||
# determine which one to use
|
||||
if (!defined($auth)) {
|
||||
# TODO show warning about auth setting not defined
|
||||
}
|
||||
{{#authMethods}}elsif ($auth eq '{{name}}') {
|
||||
{{#isApiKey}}{{#isKeyInHeader}}
|
||||
{{#authMethods}}
|
||||
elsif ($auth eq '{{name}}') {
|
||||
{{#isApiKey}}
|
||||
{{#isKeyInHeader}}
|
||||
my $api_key = $self->get_api_key_with_prefix('{{keyParamName}}');
|
||||
if ($api_key) {
|
||||
$header_params->{'{{keyParamName}}'} = $api_key;
|
||||
}{{/isKeyInHeader}}{{#isKeyInQuery}}
|
||||
}
|
||||
{{/isKeyInHeader}}
|
||||
{{#isKeyInQuery}}
|
||||
my $api_key = $self->get_api_key_with_prefix('{{keyParamName}}');
|
||||
if ($api_key) {
|
||||
$query_params->{'{{keyParamName}}'} = $api_key;
|
||||
}{{/isKeyInQuery}}{{/isApiKey}}{{#isBasic}}
|
||||
}
|
||||
{{/isKeyInQuery}}
|
||||
{{/isApiKey}}
|
||||
{{#isBasic}}
|
||||
if ($self->{config}{username} || $self->{config}{password}) {
|
||||
$header_params->{'Authorization'} = 'Basic ' . encode_base64($self->{config}{username} . ":" . $self->{config}{password});
|
||||
}{{/isBasic}}{{#isOAuth}}
|
||||
}
|
||||
{{/isBasic}}
|
||||
{{#isOAuth}}
|
||||
if ($self->{config}{access_token}) {
|
||||
$header_params->{'Authorization'} = 'Bearer ' . $self->{config}{access_token};
|
||||
}{{/isOAuth}}
|
||||
}
|
||||
{{/isOAuth}}
|
||||
}
|
||||
{{/authMethods}}
|
||||
else {
|
||||
# TODO show warning about security definition not found
|
||||
# TODO show warning about security definition not found
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -357,37 +362,36 @@ sub update_params_for_auth {
|
||||
# OpenAPI Spec does not describe the intended authorization. So we check in the config for any
|
||||
# auth tokens and if we find any, we use them for all endpoints;
|
||||
sub _global_auth_setup {
|
||||
my ($self, $header_params, $query_params) = @_;
|
||||
|
||||
my $tokens = $self->{config}->get_tokens;
|
||||
return unless keys %$tokens;
|
||||
|
||||
# basic
|
||||
if (my $uname = delete $tokens->{username}) {
|
||||
my $pword = delete $tokens->{password};
|
||||
$header_params->{'Authorization'} = 'Basic '.encode_base64($uname.":".$pword);
|
||||
}
|
||||
|
||||
# oauth
|
||||
if (my $access_token = delete $tokens->{access_token}) {
|
||||
$header_params->{'Authorization'} = 'Bearer ' . $access_token;
|
||||
}
|
||||
|
||||
# other keys
|
||||
foreach my $token_name (keys %$tokens) {
|
||||
my $in = $tokens->{$token_name}->{in};
|
||||
my $token = $self->get_api_key_with_prefix($token_name);
|
||||
if ($in eq 'head') {
|
||||
$header_params->{$token_name} = $token;
|
||||
}
|
||||
elsif ($in eq 'query') {
|
||||
$query_params->{$token_name} = $token;
|
||||
}
|
||||
else {
|
||||
die "Don't know where to put token '$token_name' ('$in' is not 'head' or 'query')";
|
||||
}
|
||||
}
|
||||
my ($self, $header_params, $query_params) = @_;
|
||||
|
||||
my $tokens = $self->{config}->get_tokens;
|
||||
return unless keys %$tokens;
|
||||
|
||||
# basic
|
||||
if (my $uname = delete $tokens->{username}) {
|
||||
my $pword = delete $tokens->{password};
|
||||
$header_params->{'Authorization'} = 'Basic '.encode_base64($uname.":".$pword);
|
||||
}
|
||||
|
||||
# oauth
|
||||
if (my $access_token = delete $tokens->{access_token}) {
|
||||
$header_params->{'Authorization'} = 'Bearer ' . $access_token;
|
||||
}
|
||||
|
||||
# other keys
|
||||
foreach my $token_name (keys %$tokens) {
|
||||
my $in = $tokens->{$token_name}->{in};
|
||||
my $token = $self->get_api_key_with_prefix($token_name);
|
||||
if ($in eq 'head') {
|
||||
$header_params->{$token_name} = $token;
|
||||
}
|
||||
elsif ($in eq 'query') {
|
||||
$query_params->{$token_name} = $token;
|
||||
}
|
||||
else {
|
||||
die "Don't know where to put token '$token_name' ('$in' is not 'head' or 'query')";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
@@ -19,47 +19,47 @@ use {{moduleName}}::ApiClient;
|
||||
|
||||
=head1 Name
|
||||
|
||||
{{moduleName}}::ApiFactory - constructs APIs to retrieve {{moduleName}} objects
|
||||
{{moduleName}}::ApiFactory - constructs APIs to retrieve {{moduleName}} objects
|
||||
|
||||
=head1 Synopsis
|
||||
|
||||
package My::Petstore::App;
|
||||
|
||||
use {{moduleName}}::ApiFactory;
|
||||
|
||||
my $api_factory = {{moduleName}}::ApiFactory->new( ... ); # any args for ApiClient constructor
|
||||
|
||||
# later...
|
||||
my $pet_api = $api_factory->get_api('Pet');
|
||||
|
||||
# $pet_api isa {{moduleName}}::PetApi
|
||||
|
||||
my $pet = $pet_api->get_pet_by_id(pet_id => $pet_id);
|
||||
|
||||
# object attributes have proper accessors:
|
||||
printf "Pet's name is %s", $pet->name;
|
||||
|
||||
# change the value stored on the object:
|
||||
$pet->name('Dave');
|
||||
package My::Petstore::App;
|
||||
|
||||
use {{moduleName}}::ApiFactory;
|
||||
|
||||
my $api_factory = {{moduleName}}::ApiFactory->new( ... ); # any args for ApiClient constructor
|
||||
|
||||
# later...
|
||||
my $pet_api = $api_factory->get_api('Pet');
|
||||
|
||||
# $pet_api isa {{moduleName}}::PetApi
|
||||
|
||||
my $pet = $pet_api->get_pet_by_id(pet_id => $pet_id);
|
||||
|
||||
# object attributes have proper accessors:
|
||||
printf "Pet's name is %s", $pet->name;
|
||||
|
||||
# change the value stored on the object:
|
||||
$pet->name('Dave');
|
||||
|
||||
=cut
|
||||
|
||||
# Load all the API classes and construct a lookup table at startup time
|
||||
my %_apis = map { $_ =~ /^{{moduleName}}::(.*)$/; $1 => $_ }
|
||||
grep {$_ =~ /Api$/}
|
||||
usesub '{{moduleName}}';
|
||||
grep {$_ =~ /Api$/}
|
||||
usesub '{{moduleName}}';
|
||||
|
||||
=head1 new($api_client)
|
||||
|
||||
create a new {{moduleName}}::ApiFactory instance with the given {{moduleName}}::ApiClient instance.
|
||||
|
||||
create a new {{moduleName}}::ApiFactory instance with the given {{moduleName}}::ApiClient instance.
|
||||
|
||||
=head1 new(%parameters)
|
||||
|
||||
Any parameters are optional, and are passed to and stored on the api_client object.
|
||||
|
||||
See L<{{moduleName}}::ApiClient> and L<{{moduleName}}::Configuration> for valid parameters
|
||||
Any parameters are optional, and are passed to and stored on the api_client object.
|
||||
|
||||
See L<{{moduleName}}::ApiClient> and L<{{moduleName}}::Configuration> for valid parameters
|
||||
|
||||
=cut
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my ($class) = shift;
|
||||
@@ -75,25 +75,25 @@ sub new {
|
||||
|
||||
=head1 get_api($which)
|
||||
|
||||
Returns an API object of the requested type.
|
||||
|
||||
$which is a nickname for the class:
|
||||
|
||||
FooBarClient::BazApi has nickname 'Baz'
|
||||
|
||||
Returns an API object of the requested type.
|
||||
|
||||
$which is a nickname for the class:
|
||||
|
||||
FooBarClient::BazApi has nickname 'Baz'
|
||||
|
||||
=cut
|
||||
|
||||
sub get_api {
|
||||
my ($self, $which) = @_;
|
||||
croak "API not specified" unless $which;
|
||||
my $api_class = $_apis{"${which}Api"} || croak "No known API for '$which'";
|
||||
return $api_class->new($self->api_client);
|
||||
my ($self, $which) = @_;
|
||||
croak "API not specified" unless $which;
|
||||
my $api_class = $_apis{"${which}Api"} || croak "No known API for '$which'";
|
||||
return $api_class->new($self->api_client);
|
||||
}
|
||||
|
||||
=head1 api_client()
|
||||
|
||||
Returns the api_client object, should you ever need it.
|
||||
|
||||
Returns the api_client object, should you ever need it.
|
||||
|
||||
=cut
|
||||
|
||||
sub api_client { $_[0]->{api_client} }
|
||||
@@ -107,8 +107,8 @@ sub apis_available { return map { $_ =~ s/Api$//; $_ } sort keys %_apis }
|
||||
=cut
|
||||
|
||||
sub classname_for {
|
||||
my ($self, $api_name) = @_;
|
||||
return $_apis{"${api_name}Api"};
|
||||
my ($self, $api_name) = @_;
|
||||
return $_apis{"${api_name}Api"};
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -10,30 +10,30 @@ use List::MoreUtils qw(uniq);
|
||||
use Moose::Role;
|
||||
|
||||
sub autodoc {
|
||||
my ($self, $how) = @_;
|
||||
|
||||
die "Unknown format '$how'" unless $how =~ /^(pod|wide|narrow)$/;
|
||||
|
||||
$self->_printisa($how);
|
||||
$self->_printmethods($how);
|
||||
$self->_printattrs($how);
|
||||
print "\n";
|
||||
my ($self, $how) = @_;
|
||||
|
||||
die "Unknown format '$how'" unless $how =~ /^(pod|wide|narrow)$/;
|
||||
|
||||
$self->_printisa($how);
|
||||
$self->_printmethods($how);
|
||||
$self->_printattrs($how);
|
||||
print "\n";
|
||||
}
|
||||
|
||||
sub _printisa {
|
||||
my ($self, $how) = @_;
|
||||
my $meta = $self->meta;
|
||||
|
||||
my $myclass = ref $self;
|
||||
|
||||
my $super = join ', ', $meta->superclasses;
|
||||
my @roles = $meta->calculate_all_roles;
|
||||
#shift(@roles) if @roles > 1; # if > 1, the first is a composite, the rest are the roles
|
||||
my ($self, $how) = @_;
|
||||
my $meta = $self->meta;
|
||||
|
||||
my $myclass = ref $self;
|
||||
|
||||
my $super = join ', ', $meta->superclasses;
|
||||
my @roles = $meta->calculate_all_roles;
|
||||
#shift(@roles) if @roles > 1; # if > 1, the first is a composite, the rest are the roles
|
||||
|
||||
my $isa = join ', ', grep {$_ ne $myclass} $meta->linearized_isa;
|
||||
my $sub = join ', ', $meta->subclasses;
|
||||
my $dsub = join ', ', $meta->direct_subclasses;
|
||||
|
||||
my $isa = join ', ', grep {$_ ne $myclass} $meta->linearized_isa;
|
||||
my $sub = join ', ', $meta->subclasses;
|
||||
my $dsub = join ', ', $meta->direct_subclasses;
|
||||
|
||||
my $app_name = $self->version_info->{app_name};
|
||||
my $app_version = $self->version_info->{app_version};
|
||||
my $generated_date = $self->version_info->{generated_date};
|
||||
@@ -41,25 +41,25 @@ sub _printisa {
|
||||
|
||||
$~ = $how eq 'pod' ? 'INHERIT_POD' : 'INHERIT';
|
||||
write;
|
||||
|
||||
my ($rolepkg, $role_reqs);
|
||||
|
||||
foreach my $role (@roles) {
|
||||
$rolepkg = $role->{package} || next; # some are anonymous, or something
|
||||
next if $rolepkg eq '{{moduleName}}::Role::AutoDoc';
|
||||
$role_reqs = join ', ', keys %{$role->{required_methods}};
|
||||
$role_reqs ||= '';
|
||||
$~ = $how eq 'pod' ? 'ROLES_POD' : 'ROLES';
|
||||
write;
|
||||
}
|
||||
|
||||
if ($how eq 'pod') {
|
||||
$~ = 'ROLES_POD_CLOSE';
|
||||
write;
|
||||
}
|
||||
|
||||
|
||||
my ($rolepkg, $role_reqs);
|
||||
|
||||
foreach my $role (@roles) {
|
||||
$rolepkg = $role->{package} || next; # some are anonymous, or something
|
||||
next if $rolepkg eq '{{moduleName}}::Role::AutoDoc';
|
||||
$role_reqs = join ', ', keys %{$role->{required_methods}};
|
||||
$role_reqs ||= '';
|
||||
$~ = $how eq 'pod' ? 'ROLES_POD' : 'ROLES';
|
||||
write;
|
||||
}
|
||||
|
||||
if ($how eq 'pod') {
|
||||
$~ = 'ROLES_POD_CLOSE';
|
||||
write;
|
||||
}
|
||||
|
||||
# ----- format specs -----
|
||||
format INHERIT =
|
||||
format INHERIT =
|
||||
|
||||
@* -
|
||||
$myclass
|
||||
@@ -78,7 +78,7 @@ $myclass
|
||||
$generator_class
|
||||
|
||||
.
|
||||
format ROLES =
|
||||
format ROLES =
|
||||
Composes: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~
|
||||
$rolepkg
|
||||
requires: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~
|
||||
@@ -87,7 +87,7 @@ $myclass
|
||||
$role_reqs
|
||||
.
|
||||
|
||||
format INHERIT_POD =
|
||||
format INHERIT_POD =
|
||||
=head1 NAME
|
||||
|
||||
@*
|
||||
@@ -138,7 +138,7 @@ $myclass
|
||||
|
||||
|
||||
.
|
||||
format ROLES_POD =
|
||||
format ROLES_POD =
|
||||
=head2 C<@*>
|
||||
$rolepkg
|
||||
|
||||
@@ -148,7 +148,7 @@ Requires:
|
||||
$role_reqs
|
||||
|
||||
.
|
||||
format ROLES_POD_CLOSE =
|
||||
format ROLES_POD_CLOSE =
|
||||
|
||||
|
||||
.
|
||||
@@ -156,96 +156,96 @@ $role_reqs
|
||||
}
|
||||
|
||||
sub _printmethods {
|
||||
my ($self, $how) = @_;
|
||||
|
||||
if ($how eq 'narrow') {
|
||||
print <<HEAD;
|
||||
my ($self, $how) = @_;
|
||||
|
||||
if ($how eq 'narrow') {
|
||||
print <<HEAD;
|
||||
METHODS
|
||||
-------
|
||||
HEAD
|
||||
}
|
||||
elsif ($how eq 'wide') {
|
||||
$~ = 'METHODHEAD';
|
||||
write;
|
||||
}
|
||||
elsif ($how eq 'pod') {
|
||||
$~ = 'METHODHEAD_POD';
|
||||
write;
|
||||
}
|
||||
else {
|
||||
die "Don't know how to print '$how'";
|
||||
}
|
||||
|
||||
$self->_printmethod($_, $how) for uniq sort $self->meta->get_all_method_names; #$self->meta->get_method_list,
|
||||
|
||||
if ($how eq 'pod') {
|
||||
$~ = 'METHOD_POD_CLOSE';
|
||||
write;
|
||||
}
|
||||
}
|
||||
elsif ($how eq 'wide') {
|
||||
$~ = 'METHODHEAD';
|
||||
write;
|
||||
}
|
||||
elsif ($how eq 'pod') {
|
||||
$~ = 'METHODHEAD_POD';
|
||||
write;
|
||||
}
|
||||
else {
|
||||
die "Don't know how to print '$how'";
|
||||
}
|
||||
|
||||
$self->_printmethod($_, $how) for uniq sort $self->meta->get_all_method_names; #$self->meta->get_method_list,
|
||||
|
||||
if ($how eq 'pod') {
|
||||
$~ = 'METHOD_POD_CLOSE';
|
||||
write;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
sub _printmethod {
|
||||
my ($self, $methodname, $how) = @_;
|
||||
return if $methodname =~ /^_/;
|
||||
return if $self->meta->has_attribute($methodname);
|
||||
my %internal = map {$_ => 1} qw(BUILD BUILDARGS meta can new DEMOLISHALL DESTROY
|
||||
DOES isa BUILDALL does VERSION dump
|
||||
);
|
||||
return if $internal{$methodname};
|
||||
my $method = $self->meta->get_method($methodname) or return; # symbols imported into namespaces i.e. not known by Moose
|
||||
|
||||
return if $method->original_package_name eq __PACKAGE__;
|
||||
|
||||
my $delegate_to = '';
|
||||
my $via = '';
|
||||
my $on = '';
|
||||
my $doc = '';
|
||||
my $original_pkg = $method->original_package_name;
|
||||
if ($method->can('associated_attribute')) {
|
||||
$delegate_to = $method->delegate_to_method;
|
||||
my $aa = $method->associated_attribute;
|
||||
$on = $aa->{isa};
|
||||
$via = $aa->{name};
|
||||
$original_pkg = $on;
|
||||
$doc = $original_pkg->method_documentation->{$delegate_to}->{summary};
|
||||
}
|
||||
else {
|
||||
$doc = $method->documentation;
|
||||
}
|
||||
|
||||
if ($how eq 'narrow') {
|
||||
$~ = 'METHOD_NARROW';
|
||||
write;
|
||||
}
|
||||
elsif ($how eq 'pod' and $delegate_to) {
|
||||
$~ = 'METHOD_POD_DELEGATED';
|
||||
write;
|
||||
}
|
||||
elsif ($how eq 'pod') {
|
||||
$~ = 'METHOD_POD';
|
||||
write;
|
||||
}
|
||||
else {
|
||||
$~ = 'METHOD';
|
||||
write;
|
||||
}
|
||||
|
||||
my ($self, $methodname, $how) = @_;
|
||||
return if $methodname =~ /^_/;
|
||||
return if $self->meta->has_attribute($methodname);
|
||||
my %internal = map {$_ => 1} qw(BUILD BUILDARGS meta can new DEMOLISHALL DESTROY
|
||||
DOES isa BUILDALL does VERSION dump
|
||||
);
|
||||
return if $internal{$methodname};
|
||||
my $method = $self->meta->get_method($methodname) or return; # symbols imported into namespaces i.e. not known by Moose
|
||||
|
||||
return if $method->original_package_name eq __PACKAGE__;
|
||||
|
||||
my $delegate_to = '';
|
||||
my $via = '';
|
||||
my $on = '';
|
||||
my $doc = '';
|
||||
my $original_pkg = $method->original_package_name;
|
||||
if ($method->can('associated_attribute')) {
|
||||
$delegate_to = $method->delegate_to_method;
|
||||
my $aa = $method->associated_attribute;
|
||||
$on = $aa->{isa};
|
||||
$via = $aa->{name};
|
||||
$original_pkg = $on;
|
||||
$doc = $original_pkg->method_documentation->{$delegate_to}->{summary};
|
||||
}
|
||||
else {
|
||||
$doc = $method->documentation;
|
||||
}
|
||||
|
||||
if ($how eq 'narrow') {
|
||||
$~ = 'METHOD_NARROW';
|
||||
write;
|
||||
}
|
||||
elsif ($how eq 'pod' and $delegate_to) {
|
||||
$~ = 'METHOD_POD_DELEGATED';
|
||||
write;
|
||||
}
|
||||
elsif ($how eq 'pod') {
|
||||
$~ = 'METHOD_POD';
|
||||
write;
|
||||
}
|
||||
else {
|
||||
$~ = 'METHOD';
|
||||
write;
|
||||
}
|
||||
|
||||
# ----- format specs -----
|
||||
format METHODHEAD =
|
||||
format METHODHEAD =
|
||||
|
||||
METHODS
|
||||
-------
|
||||
Name delegates to on via
|
||||
===========================================================================================================================================================================
|
||||
.
|
||||
format METHOD =
|
||||
format METHOD =
|
||||
@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<... @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<... @<<<<<<<<<<<<<<<<...
|
||||
$methodname, $delegate_to, $on, $via
|
||||
.
|
||||
|
||||
format METHOD_NARROW =
|
||||
format METHOD_NARROW =
|
||||
@*
|
||||
$methodname
|
||||
original pkg: @*
|
||||
@@ -259,14 +259,14 @@ $methodname
|
||||
|
||||
.
|
||||
|
||||
format METHODHEAD_POD =
|
||||
format METHODHEAD_POD =
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
.
|
||||
|
||||
format METHOD_POD =
|
||||
|
||||
|
||||
format METHOD_POD =
|
||||
|
||||
=head2 C<@*()>
|
||||
$methodname
|
||||
|
||||
@@ -275,13 +275,13 @@ $methodname
|
||||
|
||||
|
||||
.
|
||||
format METHOD_POD_DELEGATED =
|
||||
format METHOD_POD_DELEGATED =
|
||||
|
||||
=head2 C<@*()>
|
||||
$methodname
|
||||
|
||||
Defined in: @*
|
||||
$original_pkg
|
||||
$original_pkg
|
||||
Delegates to: @*()
|
||||
$delegate_to
|
||||
On: @*
|
||||
@@ -294,90 +294,90 @@ $methodname
|
||||
$via, $delegate_to
|
||||
|
||||
.
|
||||
format METHOD_POD_CLOSE =
|
||||
|
||||
format METHOD_POD_CLOSE =
|
||||
|
||||
.
|
||||
# ----- / format specs -----
|
||||
}
|
||||
|
||||
sub _printattrs {
|
||||
my ($self, $how) = @_;
|
||||
|
||||
if ($how eq 'narrow') {
|
||||
print <<HEAD;
|
||||
my ($self, $how) = @_;
|
||||
|
||||
if ($how eq 'narrow') {
|
||||
print <<HEAD;
|
||||
ATTRIBUTES
|
||||
----------
|
||||
HEAD
|
||||
}
|
||||
elsif ($how eq 'wide') {
|
||||
$~ = 'ATTRHEAD';
|
||||
write;
|
||||
}
|
||||
elsif ($how eq 'pod') {
|
||||
$~ = 'ATTRHEAD_POD';
|
||||
write;
|
||||
}
|
||||
else {
|
||||
die "Don't know how to print attributes '$how'";
|
||||
}
|
||||
|
||||
$self->_printattr($_, $how) for sort $self->meta->get_attribute_list;
|
||||
|
||||
if ($how eq 'pod') {
|
||||
$~ = 'ATTR_POD_CLOSE';
|
||||
write;
|
||||
}
|
||||
}
|
||||
elsif ($how eq 'wide') {
|
||||
$~ = 'ATTRHEAD';
|
||||
write;
|
||||
}
|
||||
elsif ($how eq 'pod') {
|
||||
$~ = 'ATTRHEAD_POD';
|
||||
write;
|
||||
}
|
||||
else {
|
||||
die "Don't know how to print attributes '$how'";
|
||||
}
|
||||
|
||||
$self->_printattr($_, $how) for sort $self->meta->get_attribute_list;
|
||||
|
||||
if ($how eq 'pod') {
|
||||
$~ = 'ATTR_POD_CLOSE';
|
||||
write;
|
||||
}
|
||||
}
|
||||
|
||||
sub _printattr {
|
||||
my ($self, $attrname, $how) = @_;
|
||||
return if $attrname =~ /^_/;
|
||||
my $attr = $self->meta->get_attribute($attrname) or die "No attr for $attrname";
|
||||
|
||||
my $is;
|
||||
$is = 'rw' if $attr->get_read_method && $attr->get_write_method;
|
||||
$is = 'ro' if $attr->get_read_method && ! $attr->get_write_method;
|
||||
$is = 'wo' if $attr->get_write_method && ! $attr->get_read_method;
|
||||
$is = '--' if ! $attr->get_write_method && ! $attr->get_read_method;
|
||||
$is or die "No \$is for $attrname";
|
||||
|
||||
my $tc = $attr->type_constraint || '';
|
||||
my $from = $attr->associated_class->name || '';
|
||||
my $reqd = $attr->is_required ? 'yes' : 'no';
|
||||
my $lazy = $attr->is_lazy ? 'yes' : 'no';
|
||||
my $has_doc = $attr->has_documentation ? 'yes' : 'no'; # *_api attributes will never have doc, but other attributes might have
|
||||
my $doc = $attr->documentation || '';
|
||||
my $handles = join ', ', sort @{$attr->handles || []};
|
||||
$handles ||= '';
|
||||
|
||||
if ($how eq 'narrow') {
|
||||
$~ = 'ATTR_NARROW';
|
||||
}
|
||||
elsif ($how eq 'pod') {
|
||||
$~ = 'ATTR_POD';
|
||||
}
|
||||
else {
|
||||
$~ = 'ATTR';
|
||||
}
|
||||
my ($self, $attrname, $how) = @_;
|
||||
return if $attrname =~ /^_/;
|
||||
my $attr = $self->meta->get_attribute($attrname) or die "No attr for $attrname";
|
||||
|
||||
write;
|
||||
my $is;
|
||||
$is = 'rw' if $attr->get_read_method && $attr->get_write_method;
|
||||
$is = 'ro' if $attr->get_read_method && ! $attr->get_write_method;
|
||||
$is = 'wo' if $attr->get_write_method && ! $attr->get_read_method;
|
||||
$is = '--' if ! $attr->get_write_method && ! $attr->get_read_method;
|
||||
$is or die "No \$is for $attrname";
|
||||
|
||||
my $tc = $attr->type_constraint || '';
|
||||
my $from = $attr->associated_class->name || '';
|
||||
my $reqd = $attr->is_required ? 'yes' : 'no';
|
||||
my $lazy = $attr->is_lazy ? 'yes' : 'no';
|
||||
my $has_doc = $attr->has_documentation ? 'yes' : 'no'; # *_api attributes will never have doc, but other attributes might have
|
||||
my $doc = $attr->documentation || '';
|
||||
my $handles = join ', ', sort @{$attr->handles || []};
|
||||
$handles ||= '';
|
||||
|
||||
if ($how eq 'narrow') {
|
||||
$~ = 'ATTR_NARROW';
|
||||
}
|
||||
elsif ($how eq 'pod') {
|
||||
$~ = 'ATTR_POD';
|
||||
}
|
||||
else {
|
||||
$~ = 'ATTR';
|
||||
}
|
||||
|
||||
write;
|
||||
|
||||
# ----- format specs -----
|
||||
format ATTRHEAD =
|
||||
format ATTRHEAD =
|
||||
|
||||
ATTRIBUTES
|
||||
----------
|
||||
Name is isa reqd lazy doc handles
|
||||
==============================================================================================================
|
||||
.
|
||||
format ATTR =
|
||||
.
|
||||
format ATTR =
|
||||
@<<<<<<<<<<<<<<<<< @< @<<<<<<<<<<<<<<<<<<<<<<<< @<<< @<<< @<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
$attrname, $is, $tc, $reqd, $lazy, $has_doc, $handles
|
||||
^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~~
|
||||
$handles
|
||||
.
|
||||
|
||||
format ATTR_NARROW =
|
||||
format ATTR_NARROW =
|
||||
@*
|
||||
$attrname
|
||||
is: @*
|
||||
@@ -396,11 +396,11 @@ $attrname
|
||||
$handles
|
||||
|
||||
.
|
||||
format ATTRHEAD_POD =
|
||||
format ATTRHEAD_POD =
|
||||
=head1 ATTRIBUTES
|
||||
|
||||
.
|
||||
format ATTR_POD =
|
||||
format ATTR_POD =
|
||||
|
||||
=head2 C<@*>
|
||||
$attrname
|
||||
@@ -421,7 +421,7 @@ $attrname
|
||||
$handles
|
||||
|
||||
.
|
||||
format ATTR_POD_CLOSE =
|
||||
format ATTR_POD_CLOSE =
|
||||
|
||||
|
||||
.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user