Merge remote-tracking branch 'upstream/master' https://github.com/swagger-api/swagger-codegen.git

This commit is contained in:
Justus Thorvaldsson 2015-12-22 10:43:42 +01:00
commit 7c9832c741
420 changed files with 19977 additions and 4673 deletions

6
.gitignore vendored
View File

@ -13,6 +13,7 @@ generated-sources/*
generated-code/* generated-code/*
*.swp *.swp
*.swo *.swo
*.csproj.user
/target /target
/generated-files /generated-files
@ -36,6 +37,9 @@ samples/client/petstore/objc/SwaggerClientTests/Pods
samples/client/petstore/objc/SwaggerClientTests/SwaggerClient.xcworkspace samples/client/petstore/objc/SwaggerClientTests/SwaggerClient.xcworkspace
samples/client/petstore/objc/SwaggerClientTests/Podfile.lock samples/client/petstore/objc/SwaggerClientTests/Podfile.lock
samples/server/petstore/nodejs/node_modules samples/server/petstore/nodejs/node_modules
samples/client/petstore/csharp/SwaggerClientTest/.vs
samples/client/petstore/csharp/SwaggerClientTest/obj
samples/client/petstore/csharp/SwaggerClientTest/bin
target target
.idea .idea
.lib .lib
@ -60,4 +64,4 @@ samples/client/petstore/python/.venv/
*.java~ *.java~
*.pm~ *.pm~
*.xml~ *.xml~
*.t~ *.t~

62
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,62 @@
# Guidelines For Contributing
## Before submitting an issue
- Before submitting an issue, search the [open issue](https://github.com/swagger-api/swagger-codegen/issues) and [closed issue](https://github.com/swagger-api/swagger-codegen/issues?q=is%3Aissue+is%3Aclosed) to ensure no one else has reported something similar before.
- The issue should contain details on how to repeat the issue, e.g.
- the Swagger spec for reproducing the issue (:bulb: use [Gist](https://gist.github.com) to share). If the Swagger spec cannot be shared publicly, it will be hard for the community to help
- version of Swagger Codegen
- language (`-l` in the command line, e.g. java, csharp, php)
- You can also make a suggestion or ask a question by opening an "issue"
## Before submitting a PR
- Search the [open issue](https://github.com/swagger-api/swagger-codegen/issues) to ensure no one else has reported something similar and no one is actively working on similar proposed change.
- If no one has suggested something similar, open an ["issue"](https://github.com/swagger-api/swagger-codegen/issues) with your suggestion to gather feedback from the community.
## How to contribute
### Code generators
All the code generators can be found in [modules/swagger-codegen/src/main/java/io/swagger/codegen/languages](https://github.com/swagger-api/swagger-codegen/tree/master/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages)
### Templates
All the templates ([mustache](https://mustache.github.io/)) can be found in [modules/swagger-codegen/src/main/resources](https://github.com/swagger-api/swagger-codegen/tree/master/modules/swagger-codegen/src/main/resources).
For a list of variables available in the template, please refer to this [page](https://github.com/swagger-api/swagger-codegen/wiki/Mustache-Template-Variables)
### Style guide
Code change should conform to the programming style guide of the respective langauages:
- C#: https://msdn.microsoft.com/en-us/library/vstudio/ff926074.aspx
- Java: https://google.github.io/styleguide/javaguide.html
- ObjC: https://github.com/NYTimes/objective-c-style-guide
- PHP: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md
- Python: https://www.python.org/dev/peps/pep-0008/
- Ruby: https://github.com/bbatsov/ruby-style-guide
- TypeScript: https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines
For other languages, feel free to suggest.
You may find the current code base not 100% conform to the coding style and we welcome contributions to fix those.
### Testing
To add test cases (optional) covering the change in the code generator, please refer to [modules/swagger-codegen/src/test/java/io/swagger/codegen](https://github.com/swagger-api/swagger-codegen/tree/master/modules/swagger-codegen/src/test/java/io/swagger/codegen)
To test the templates, please perform the following:
- Update the [Petstore](http://petstore.swagger.io/) sample by running the shell script under `bin` folder. For example, run `./bin/ruby-petstore.sh` to update the Ruby PetStore API client under [`samples/client/petstore/ruby`](https://github.com/swagger-api/swagger-codegen/tree/master/samples/client/petstore/ruby) (For Windows, the batch files can be found under `bin\windows` folder)
- Run the tests in the sample folder, e.g. in `samples/client/petstore/ruby`, run `mvn integration-test -rf :RubyPetstoreClientTests`. (some languages may not contain unit testing for Petstore and we're looking for contribution from the community to implement those tests)
- Finally, git commit the updated samples files: `git commit -a`
(`git add -A` if added files with new test cases)
To start the CI tests, you can run `mvn verify -Psamples` (assuming you've all the required tools installed to run tests for different languages) or you can leverage http://travis-ci.org to run the CI tests by adding your own Swagger-Codegen repository.
### Tips
- Smaller changes are easier to review
- [Optional] For bug fixes, provide a Swagger spec to repeat the issue so that the reviewer can use it to confirm the fix
- Add test case(s) to cover the change
- Document the fix in the code to make the code more readable
- Make sure test cases passed after the change (one way is to leverage https://travis-ci.org/ to run the CI tests)

View File

@ -3,6 +3,8 @@
[![Build Status](https://travis-ci.org/swagger-api/swagger-codegen.png)](https://travis-ci.org/swagger-api/swagger-codegen) [![Build Status](https://travis-ci.org/swagger-api/swagger-codegen.png)](https://travis-ci.org/swagger-api/swagger-codegen)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.swagger/swagger-codegen-project/badge.svg?style=plastic)](https://maven-badges.herokuapp.com/maven-central/io.swagger/swagger-codegen-project) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.swagger/swagger-codegen-project/badge.svg?style=plastic)](https://maven-badges.herokuapp.com/maven-central/io.swagger/swagger-codegen-project)
:star::star::star: If you would like to contribute, please refer to [guidelines](https://github.com/swagger-api/swagger-codegen/blob/master/CONTRIBUTING.md) and a list of [open tasks](https://github.com/swagger-api/swagger-codegen/issues?q=is%3Aopen+is%3Aissue+label%3A%22Need+community+contribution%22).:star::star::star:
## Overview ## Overview
This is the swagger codegen project, which allows generation of client libraries automatically from a Swagger-compliant server. This is the swagger codegen project, which allows generation of client libraries automatically from a Swagger-compliant server.
@ -117,6 +119,8 @@ You can build a client against the swagger sample [petstore](http://petstore.swa
./bin/java-petstore.sh ./bin/java-petstore.sh
``` ```
(On Windows, run `./bin/windows/java-petstore.bat` instead)
This will run the generator with this command: This will run the generator with this command:
``` ```
@ -212,11 +216,28 @@ java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar meta \
This will write, in the folder `output/myLibrary`, all the files you need to get started, including a README.md. Once modified and compiled, you can load your library with the codegen and generate clients with your own, custom-rolled logic. This will write, in the folder `output/myLibrary`, all the files you need to get started, including a README.md. Once modified and compiled, you can load your library with the codegen and generate clients with your own, custom-rolled logic.
You would then compile your library in the `output/myLibrary` folder with `mvn package` and execute the codegen like such:
```
java -cp output/myLibrary/target/myClientCodegen-swagger-codegen-1.0.0.jar:modules/swagger-codegen-cli/target/swagger-codegen-cli.jar io.swagger.codegen.Codegen
```
Note the `myClientCodegen` is an option now, and you can use the usual arguments for generating your library:
```
java -cp output/myLibrary/target/myClientCodegen-swagger-codegen-1.0.0.jar:modules/swagger-codegen-cli/target/swagger-codegen-cli.jar \
io.swagger.codegen.Codegen generate -l myClientCodegen\
-i http://petstore.swagger.io/v2/swagger.json \
-o myClient
```
### Where is Javascript??? ### Where is Javascript???
See our [javascript library](http://github.com/swagger-api/swagger-js)--it's completely dynamic and doesn't require See our [javascript library](http://github.com/swagger-api/swagger-js)--it's completely dynamic and doesn't require
static code generation. static code generation.
There is a third-party component called [swagger-js-codegen](https://github.com/wcandillon/swagger-js-codegen) that can generate angularjs or nodejs source code from a swagger specification. There is a third-party component called [swagger-js-codegen](https://github.com/wcandillon/swagger-js-codegen) that can generate angularjs or nodejs source code from a swagger specification.
:exclamation: On Dec 7th 2015, a Javascript API client generator has been added by @jfiala.
### Generating a client from local files ### Generating a client from local files
If you don't want to call your server, you can save the swagger spec files into a directory and pass an argument If you don't want to call your server, you can save the swagger spec files into a directory and pass an argument
@ -276,7 +297,9 @@ FlashClientCodegen.java
FlaskConnexionCodegen.java FlaskConnexionCodegen.java
JavaClientCodegen.java JavaClientCodegen.java
JavaInflectorServerCodegen.java JavaInflectorServerCodegen.java
JavascriptClientCodegen.java
JaxRSServerCodegen.java JaxRSServerCodegen.java
JMeterCodegen.java
NodeJSServerCodegen.java NodeJSServerCodegen.java
ObjcClientCodegen.java ObjcClientCodegen.java
PerlClientCodegen.java PerlClientCodegen.java
@ -288,6 +311,7 @@ ScalaClientCodegen.java
ScalatraServerCodegen.java ScalatraServerCodegen.java
SilexServerCodegen.java SilexServerCodegen.java
SinatraServerCodegen.java SinatraServerCodegen.java
SlimFrameworkServerCodegen.java
SpringMVCServerCodegen.java SpringMVCServerCodegen.java
StaticDocCodegen.java StaticDocCodegen.java
StaticHtmlGenerator.java StaticHtmlGenerator.java
@ -353,9 +377,10 @@ CONFIG OPTIONS
library template (sub-template) to use: library template (sub-template) to use:
<default> - HTTP client: Jersey client 1.18. JSON processing: Jackson 2.4.2 <default> - HTTP client: Jersey client 1.18. JSON processing: Jackson 2.4.2
jersey2 - HTTP client: Jersey client 2.6 jersey2 - HTTP client: Jersey client 2.6
feign - HTTP client: Netflix Feign 8.1.1. JSON processing: Jackson 2.6.3
okhttp-gson - HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1 okhttp-gson - HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1
retrofit - HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1 (Retrofit 1.9.0) retrofit - HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1 (Retrofit 1.9.0)
retrofit2 - HTTP client: OkHttp 2.5.0. JSON processing: Gson 2.4 (Retrofit 2.0.0-beta2) retrofit2 - HTTP client: OkHttp 2.5.0. JSON processing: Gson 2.4 (Retrofit 2.0.0-beta2)
``` ```
Your config file for java can look like Your config file for java can look like
@ -364,7 +389,8 @@ Your config file for java can look like
{ {
"groupId":"com.my.company", "groupId":"com.my.company",
"artifactId":"MyClent", "artifactId":"MyClent",
"artifactVersion":"1.2.0" "artifactVersion":"1.2.0",
"library":"feign"
} }
``` ```
@ -511,7 +537,7 @@ Then you will receieve a JSON response with the URL to download the zipped code.
Guidelines for Contribution Guidelines for Contribution
--------------------------- ---------------------------
Please refer to this [page](https://github.com/swagger-api/swagger-codegen/wiki/Guidelines-for-Contribution) Please refer to this [page](https://github.com/swagger-api/swagger-codegen/blob/master/CONTRIBUTING.md)
License License
------- -------

View File

@ -41,6 +41,7 @@ cd $APP_DIR
./bin/scala-petstore.sh ./bin/scala-petstore.sh
./bin/scalatra-petstore-server.sh ./bin/scalatra-petstore-server.sh
./bin/silex-petstore-server.sh ./bin/silex-petstore-server.sh
./bin/slim-petstore-server.sh
./bin/spring-mvc-petstore-server.sh ./bin/spring-mvc-petstore-server.sh
./bin/swift-petstore.sh ./bin/swift-petstore.sh
./bin/tizen-petstore.sh ./bin/tizen-petstore.sh

View File

@ -26,6 +26,6 @@ fi
# if you've executed sbt assembly previously it will use that instead. # 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" export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l flaskConnexion -o samples/server/petstore/flaskConnexion " ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l python-flask -o samples/server/petstore/flaskConnexion "
java $JAVA_OPTS -Dservice -jar $executable $ags java $JAVA_OPTS -Dservice -jar $executable $ags

View File

@ -0,0 +1,4 @@
{
"library": "feign",
"artifactId": "swagger-petstore-feign"
}

31
bin/java-petstore-feign.sh Executable file
View File

@ -0,0 +1,31 @@
#!/bin/sh
SCRIPT="$0"
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/swagger-codegen-cli/target/swagger-codegen-cli.jar"
if [ ! -f "$executable" ]
then
mvn clean package
fi
# 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 -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l java -c bin/java-petstore-feign.json -o samples/client/petstore/java/feign"
java $JAVA_OPTS -jar $executable $ags

31
bin/javascript-petstore.sh Executable file
View File

@ -0,0 +1,31 @@
#!/bin/sh
SCRIPT="$0"
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/swagger-codegen-cli/target/swagger-codegen-cli.jar"
if [ ! -f "$executable" ]
then
mvn clean package
fi
# 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/swagger-codegen/src/main/resources/javascript -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l javascript -o samples/client/petstore/javascript"
java -DappName=PetstoreClient $JAVA_OPTS -jar $executable $ags

View File

@ -0,0 +1,31 @@
#!/bin/sh
SCRIPT="$0"
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/swagger-codegen-cli/target/swagger-codegen-cli.jar"
if [ ! -f "$executable" ]
then
mvn clean package
fi
# 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/swagger-codegen/src/main/resources/slim -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l slim -o samples/server/petstore/slim"
java $JAVA_OPTS -jar $executable $ags

View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\akka-scala -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l akka-scala -o samples\client\petstore\akka-scala
java %JAVA_OPTS% -jar %executable% %ags%

View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\android-java -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l android -o samples\client\petstore\android-java
java %JAVA_OPTS% -jar %executable% %ags%

View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\asyncscala -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l async-scala -o samples\client\petstore\async-scala
java %JAVA_OPTS% -jar %executable% %ags%

View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\clojure -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l clojure -o samples\client\petstore\clojure
java %JAVA_OPTS% -jar %executable% %ags%

10
bin/windows/csharp-petstore.bat Executable file
View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\csharp -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l csharp -o samples\client\petstore\csharp\SwaggerClientTest\Lib\SwaggerClient
java %JAVA_OPTS% -jar %executable% %ags%

10
bin/windows/dart-petstore.bat Executable file
View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\dart -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l dart -o samples\client\petstore\dart
java %JAVA_OPTS% -jar %executable% %ags%

View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\dynamic-html -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l dynamic-html -o samples\client\petstore\dynamic-html
java %JAVA_OPTS% -jar %executable% %ags%

10
bin/windows/flash-petstore.bat Executable file
View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\flash -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l flash -o samples\client\petstore\flash
java %JAVA_OPTS% -jar %executable% %ags%

10
bin/windows/html-petstore.bat Executable file
View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\html -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l html -o samples\client\petstore\html
java %JAVA_OPTS% -jar %executable% %ags%

10
bin/windows/java-petstore.bat Executable file
View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\java -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l java -o samples\client\petstore\java
java %JAVA_OPTS% -jar %executable% %ags%

View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\javascript -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l javascript -o samples\client\petstore\javascript
java %JAVA_OPTS% -jar %executable% %ags%

10
bin/windows/objc-petstore.bat Executable file
View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\objc -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l objc -o samples\client\petstore\objc
java %JAVA_OPTS% -DappName=PetstoreClient -jar %executable% %ags%

10
bin/windows/perl-petstore.bat Executable file
View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\perl -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l perl -o samples\client\petstore\perl
java %JAVA_OPTS% -jar %executable% %ags%

10
bin/windows/php-petstore.bat Executable file
View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\php -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l php -o samples\client\petstore\php
java %JAVA_OPTS% -jar %executable% %ags%

10
bin/windows/python-petstore.bat Executable file
View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\python -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l python -o samples\client\petstore\python
java %JAVA_OPTS% -jar %executable% %ags%

10
bin/windows/qt5cpp-petstore.bat Executable file
View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\qt5cpp -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l qt5cpp -o samples\client\petstore\qt5cpp
java %JAVA_OPTS% -jar %executable% %ags%

10
bin/windows/ruby-petstore.bat Executable file
View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\ruby -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l ruby -o samples\client\petstore\ruby
java %JAVA_OPTS% -jar %executable% %ags%

10
bin/windows/scala-petstore.bat Executable file
View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\scala -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l scala -o samples\client\petstore\scala
java %JAVA_OPTS% -jar %executable% %ags%

10
bin/windows/swift-petstore.bat Executable file
View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\swift -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l swift -o samples\client\petstore\swift
java %JAVA_OPTS% -jar %executable% %ags%

10
bin/windows/tizen-petstore.bat Executable file
View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\tizen -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l tizen -o samples\client\petstore\tizen
java %JAVA_OPTS% -jar %executable% %ags%

View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\typescript-angular -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l typescript-angular -o samples\client\petstore\typescript-angular
java %JAVA_OPTS% -jar %executable% %ags%

10
bin/windows/typescript-node.bat Executable file
View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\typescript-node -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l typescript-node -o samples\client\petstore\typescript-node
java %JAVA_OPTS% -jar %executable% %ags%

1
config-feign.json Normal file
View File

@ -0,0 +1 @@
{"library":"feign"}

1
modules/swagger-codegen/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/.settings/

View File

@ -154,6 +154,7 @@
<reporting> <reporting>
<outputDirectory>target/site</outputDirectory> <outputDirectory>target/site</outputDirectory>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>

View File

@ -41,9 +41,11 @@ public class CodegenConstants {
public static final String SORT_PARAMS_BY_REQUIRED_FLAG_DESC = "Sort method arguments to place required parameters before optional parameters."; public static final String SORT_PARAMS_BY_REQUIRED_FLAG_DESC = "Sort method arguments to place required parameters before optional parameters.";
public static final String ENSURE_UNIQUE_PARAMS = "ensureUniqueParams"; public static final String ENSURE_UNIQUE_PARAMS = "ensureUniqueParams";
public static final String ENSURE_UNIQUE_PARAMS_DESC = "Whether to ensure parameter names are unique in an operation (rename parameters that are not). Default: true"; public static final String ENSURE_UNIQUE_PARAMS_DESC = "Whether to ensure parameter names are unique in an operation (rename parameters that are not).";
public static final String PACKAGE_NAME = "packageName"; public static final String PACKAGE_NAME = "packageName";
public static final String PACKAGE_VERSION = "packageVersion"; public static final String PACKAGE_VERSION = "packageVersion";
public static final String POD_VERSION = "podVersion"; public static final String POD_VERSION = "podVersion";
public static final String OPTIONAL_METHOD_ARGUMENT = "optionalMethodArgument";
} }

View File

@ -9,11 +9,16 @@ import java.util.Set;
public class CodegenModel { public class CodegenModel {
public String parent; public String parent;
public String name, classname, description, classVarName, modelJson; public String name, classname, description, classVarName, modelJson, dataType;
public String unescapedDescription; public String unescapedDescription;
public String defaultValue; public String defaultValue;
public List<CodegenProperty> vars = new ArrayList<CodegenProperty>(); public List<CodegenProperty> vars = new ArrayList<CodegenProperty>();
public List<String> allowableValues;
// list of all required parameters
public Set<String> mandatory = new HashSet<String>();
public Set<String> imports = new HashSet<String>(); public Set<String> imports = new HashSet<String>();
public Boolean hasVars, emptyVars, hasMoreModels, hasEnums; public Boolean hasVars, emptyVars, hasMoreModels, hasEnums, isEnum;
public ExternalDocs externalDocs; public ExternalDocs externalDocs;
} }

View File

@ -23,6 +23,51 @@ public class CodegenParameter {
*/ */
public Boolean required; public Boolean required;
/**
* See http://json-schema.org/latest/json-schema-validation.html#anchor17.
*/
public Number maximum;
/**
* See http://json-schema.org/latest/json-schema-validation.html#anchor17
*/
public Boolean exclusiveMaximum;
/**
* See http://json-schema.org/latest/json-schema-validation.html#anchor21
*/
public Number minimum;
/**
* See http://json-schema.org/latest/json-schema-validation.html#anchor21
*/
public Boolean exclusiveMinimum;
/**
* See http://json-schema.org/latest/json-schema-validation.html#anchor26
*/
public Integer maxLength;
/**
* See http://json-schema.org/latest/json-schema-validation.html#anchor29
*/
public Integer minLength;
/**
* See http://json-schema.org/latest/json-schema-validation.html#anchor33
*/
public String pattern;
/**
* See http://json-schema.org/latest/json-schema-validation.html#anchor42
*/
public Integer maxItems;
/**
* See http://json-schema.org/latest/json-schema-validation.html#anchor45
*/
public Integer minItems;
/**
* See http://json-schema.org/latest/json-schema-validation.html#anchor49
*/
public Boolean uniqueItems;
/**
* See http://json-schema.org/latest/json-schema-validation.html#anchor14
*/
public Number multipleOf;
public CodegenParameter copy() { public CodegenParameter copy() {
CodegenParameter output = new CodegenParameter(); CodegenParameter output = new CodegenParameter();
output.isFile = this.isFile; output.isFile = this.isFile;
@ -44,6 +89,17 @@ public class CodegenParameter {
output.isCookieParam = this.isCookieParam; output.isCookieParam = this.isCookieParam;
output.isBodyParam = this.isBodyParam; output.isBodyParam = this.isBodyParam;
output.required = this.required; output.required = this.required;
output.maximum = this.maximum;
output.exclusiveMaximum = this.exclusiveMaximum;
output.minimum = this.minimum;
output.exclusiveMinimum = this.exclusiveMinimum;
output.maxLength = this.maxLength;
output.minLength = this.minLength;
output.pattern = this.pattern;
output.maxItems = this.maxItems;
output.minItems = this.minItems;
output.uniqueItems = this.uniqueItems;
output.multipleOf = this.multipleOf;
output.jsonSchema = this.jsonSchema; output.jsonSchema = this.jsonSchema;
output.defaultValue = this.defaultValue; output.defaultValue = this.defaultValue;
output.isEnum = this.isEnum; output.isEnum = this.isEnum;
@ -58,3 +114,4 @@ public class CodegenParameter {
return output; return output;
} }
} }

View File

@ -5,7 +5,7 @@ import java.util.Map;
public class CodegenProperty { public class CodegenProperty {
public String baseName, complexType, getter, setter, description, datatype, datatypeWithEnum, public String baseName, complexType, getter, setter, description, datatype, datatypeWithEnum,
name, min, max, defaultValue, baseType, containerType; name, min, max, defaultValue, defaultValueWithParam, baseType, containerType;
public String unescapedDescription; public String unescapedDescription;

View File

@ -2,6 +2,7 @@ package io.swagger.codegen;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import io.swagger.codegen.examples.ExampleGenerator; import io.swagger.codegen.examples.ExampleGenerator;
import io.swagger.models.ArrayModel; import io.swagger.models.ArrayModel;
import io.swagger.models.ComposedModel; import io.swagger.models.ComposedModel;
@ -42,11 +43,13 @@ import io.swagger.models.properties.PropertyBuilder.PropertyId;
import io.swagger.models.properties.RefProperty; import io.swagger.models.properties.RefProperty;
import io.swagger.models.properties.StringProperty; import io.swagger.models.properties.StringProperty;
import io.swagger.util.Json; import io.swagger.util.Json;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -445,7 +448,8 @@ public class DefaultCodegen {
cliOptions.add(new CliOption(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, cliOptions.add(new CliOption(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG,
CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC).defaultValue("true")); CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC).defaultValue("true"));
cliOptions.add(new CliOption(CodegenConstants.ENSURE_UNIQUE_PARAMS, CodegenConstants.ENSURE_UNIQUE_PARAMS_DESC)); cliOptions.add(new CliOption(CodegenConstants.ENSURE_UNIQUE_PARAMS, CodegenConstants.ENSURE_UNIQUE_PARAMS_DESC)
.defaultValue("true"));
} }
/** /**
@ -574,6 +578,52 @@ public class DefaultCodegen {
return "null"; return "null";
} }
} }
/**
* Return the property initialized from a data object
* Useful for initialization with a plain object in Javascript
*
* @param name Name of the property object
* @param p Swagger property object
* @return string presentation of the default value of the property
*/
public String toDefaultValueWithParam(String name, Property p) {
if (p instanceof StringProperty) {
return " = data." + name + ";";
} else if (p instanceof BooleanProperty) {
return " = data." + name + ";";
} else if (p instanceof DateProperty) {
return " = data." + name + ";";
} else if (p instanceof DateTimeProperty) {
return " = data." + name + ";";
} else if (p instanceof DoubleProperty) {
DoubleProperty dp = (DoubleProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
return " = data." + name + ";";
} else if (p instanceof FloatProperty) {
FloatProperty dp = (FloatProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
return " = data." + name + ";";
} else if (p instanceof IntegerProperty) {
IntegerProperty dp = (IntegerProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
return " = data." + name + ";";
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
return " = data." + name + ";";
} else {
return " = data." + name + ";";
}
}
/** /**
* returns the swagger type for the property * returns the swagger type for the property
@ -788,6 +838,12 @@ public class DefaultCodegen {
addVars(m, properties, required); addVars(m, properties, required);
} else { } else {
ModelImpl impl = (ModelImpl) model; ModelImpl impl = (ModelImpl) model;
if(impl.getEnum() != null && impl.getEnum().size() > 0) {
m.isEnum = true;
m.allowableValues = impl.getEnum();
Property p = PropertyBuilder.build(impl.getType(), impl.getFormat(), null);
m.dataType = getSwaggerType(p);
}
if (impl.getAdditionalProperties() != null) { if (impl.getAdditionalProperties() != null) {
MapProperty mapProperty = new MapProperty(impl.getAdditionalProperties()); MapProperty mapProperty = new MapProperty(impl.getAdditionalProperties());
addParentContainer(m, name, mapProperty); addParentContainer(m, name, mapProperty);
@ -835,6 +891,8 @@ public class DefaultCodegen {
property.setter = "set" + getterAndSetterCapitalize(name); property.setter = "set" + getterAndSetterCapitalize(name);
property.example = p.getExample(); property.example = p.getExample();
property.defaultValue = toDefaultValue(p); property.defaultValue = toDefaultValue(p);
property.defaultValueWithParam = toDefaultValueWithParam(name, p);
property.jsonSchema = Json.pretty(p); property.jsonSchema = Json.pretty(p);
property.isReadOnly = p.getReadOnly(); property.isReadOnly = p.getReadOnly();
@ -1081,31 +1139,7 @@ public class DefaultCodegen {
Set<String> imports = new HashSet<String>(); Set<String> imports = new HashSet<String>();
op.vendorExtensions = operation.getVendorExtensions(); op.vendorExtensions = operation.getVendorExtensions();
String operationId = operation.getOperationId(); String operationId = getOrGenerateOperationId(operation, path, httpMethod);
if (operationId == null) {
String tmpPath = path;
tmpPath = tmpPath.replaceAll("\\{", "");
tmpPath = tmpPath.replaceAll("\\}", "");
String[] parts = (tmpPath + "/" + httpMethod).split("/");
StringBuilder builder = new StringBuilder();
if ("/".equals(tmpPath)) {
// must be root tmpPath
builder.append("root");
}
for (int i = 0; i < parts.length; i++) {
String part = parts[i];
if (part.length() > 0) {
if (builder.toString().length() == 0) {
part = Character.toLowerCase(part.charAt(0)) + part.substring(1);
} else {
part = initialCaps(part);
}
builder.append(part);
}
}
operationId = builder.toString();
LOGGER.info("generated operationId " + operationId + "\tfor Path: " + httpMethod + " " + path);
}
operationId = removeNonNameElementToCamelCase(operationId); operationId = removeNonNameElementToCamelCase(operationId);
op.path = path; op.path = path;
op.operationId = toOperationId(operationId); op.operationId = toOperationId(operationId);
@ -1491,6 +1525,21 @@ public class DefaultCodegen {
if (model.complexType != null) { if (model.complexType != null) {
imports.add(model.complexType); imports.add(model.complexType);
} }
p.maxLength = qp.getMaxLength();
p.minLength = qp.getMinLength();
p.pattern = qp.getPattern();
p.maximum = qp.getMaximum();
p.exclusiveMaximum = qp.isExclusiveMaximum();
p.minimum = qp.getMinimum();
p.exclusiveMinimum = qp.isExclusiveMinimum();
p.maxLength = qp.getMaxLength();
p.minLength = qp.getMinLength();
p.pattern = qp.getPattern();
p.maxItems = qp.getMaxItems();
p.minItems = qp.getMinItems();
p.uniqueItems = qp.isUniqueItems();
p.multipleOf = qp.getMultipleOf();
} else { } else {
if (!(param instanceof BodyParameter)) { if (!(param instanceof BodyParameter)) {
LOGGER.error("Cannot use Parameter " + param + " as Body Parameter"); LOGGER.error("Cannot use Parameter " + param + " as Body Parameter");
@ -1620,6 +1669,43 @@ public class DefaultCodegen {
return secs; return secs;
} }
/**
* Get operationId from the operation object, and if it's blank, generate a new one from the given parameters.
*
* @param operation the operation object
* @param path the path of the operation
* @param httpMethod the HTTP method of the operation
* @return the (generated) operationId
*/
protected String getOrGenerateOperationId(Operation operation, String path, String httpMethod) {
String operationId = operation.getOperationId();
if (StringUtils.isBlank(operationId)) {
String tmpPath = path;
tmpPath = tmpPath.replaceAll("\\{", "");
tmpPath = tmpPath.replaceAll("\\}", "");
String[] parts = (tmpPath + "/" + httpMethod).split("/");
StringBuilder builder = new StringBuilder();
if ("/".equals(tmpPath)) {
// must be root tmpPath
builder.append("root");
}
for (int i = 0; i < parts.length; i++) {
String part = parts[i];
if (part.length() > 0) {
if (builder.toString().length() == 0) {
part = Character.toLowerCase(part.charAt(0)) + part.substring(1);
} else {
part = initialCaps(part);
}
builder.append(part);
}
}
operationId = builder.toString();
LOGGER.info("generated operationId " + operationId + "\tfor Path: " + httpMethod + " " + path);
}
return operationId;
}
/** /**
* Check the type to see if it needs import the library/module/package * Check the type to see if it needs import the library/module/package
* *
@ -1628,8 +1714,7 @@ public class DefaultCodegen {
*/ */
protected boolean needToImport(String type) { protected boolean needToImport(String type) {
return !defaultIncludes.contains(type) return !defaultIncludes.contains(type)
&& !languageSpecificPrimitives.contains(type) && !languageSpecificPrimitives.contains(type);
&& type.indexOf(".") < 0;
} }
protected List<Map<String, Object>> toExamples(Map<String, Object> examples) { protected List<Map<String, Object>> toExamples(Map<String, Object> examples) {
@ -1743,6 +1828,16 @@ public class DefaultCodegen {
return word; return word;
} }
/**
* Dashize the given word.
*
* @param word The word
* @return The dashized version of the word, e.g. "my-name"
*/
protected String dashize(String word) {
return underscore(word).replaceAll("[_ ]", "-");
}
/** /**
* Generate the next name for the given name, i.e. append "2" to the base name if not ending with a number, * Generate the next name for the given name, i.e. append "2" to the base name if not ending with a number,
* otherwise increase the number by 1. For example: * otherwise increase the number by 1. For example:
@ -1802,6 +1897,9 @@ public class DefaultCodegen {
m.vars.add(cp); m.vars.add(cp);
} }
} }
m.mandatory = mandatory;
} else { } else {
m.emptyVars = true; m.emptyVars = true;
m.hasVars = false; m.hasVars = false;

View File

@ -45,13 +45,15 @@ public class InlineModelResolver {
if (bp.getSchema() != null) { if (bp.getSchema() != null) {
Model model = bp.getSchema(); Model model = bp.getSchema();
if(model instanceof ModelImpl) { if(model instanceof ModelImpl) {
String modelName = uniqueName(bp.getName());
ModelImpl obj = (ModelImpl) model; ModelImpl obj = (ModelImpl) model;
flattenProperties(obj.getProperties(), pathname); if (obj.getType() == null || "object".equals(obj.getType())) {
String modelName = uniqueName(bp.getName());
flattenProperties(obj.getProperties(), pathname);
bp.setSchema(new RefModel(modelName)); bp.setSchema(new RefModel(modelName));
addGenerated(modelName, model); addGenerated(modelName, model);
swagger.addDefinition(modelName, model); swagger.addDefinition(modelName, model);
}
} }
else if (model instanceof ArrayModel) { else if (model instanceof ArrayModel) {
ArrayModel am = (ArrayModel) model; ArrayModel am = (ArrayModel) model;

View File

@ -8,9 +8,7 @@ import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile; import io.swagger.codegen.SupportingFile;
import io.swagger.codegen.CodegenProperty; import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.CodegenModel; import io.swagger.codegen.CodegenModel;
import io.swagger.models.properties.ArrayProperty; import io.swagger.models.properties.*;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import io.swagger.codegen.CliOption; import io.swagger.codegen.CliOption;
import io.swagger.models.Model; import io.swagger.models.Model;
@ -30,6 +28,7 @@ import org.slf4j.LoggerFactory;
public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig { public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(CSharpClientCodegen.class); private static final Logger LOGGER = LoggerFactory.getLogger(CSharpClientCodegen.class);
protected boolean optionalMethodArgumentFlag = true;
protected String packageName = "IO.Swagger"; protected String packageName = "IO.Swagger";
protected String packageVersion = "1.0.0"; protected String packageVersion = "1.0.0";
protected String clientPackage = "IO.Swagger.Client"; protected String clientPackage = "IO.Swagger.Client";
@ -97,6 +96,7 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
.defaultValue("IO.Swagger")); .defaultValue("IO.Swagger"));
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "C# package version.").defaultValue("1.0.0")); cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "C# package version.").defaultValue("1.0.0"));
cliOptions.add(new CliOption(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC)); cliOptions.add(new CliOption(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC));
cliOptions.add(new CliOption(CodegenConstants.OPTIONAL_METHOD_ARGUMENT, "C# Optional method argument, e.g. void square(int x=10) (.net 4.0+ only). Default: false").defaultValue("false"));
} }
@Override @Override
@ -119,6 +119,12 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
} }
additionalProperties.put("clientPackage", clientPackage); additionalProperties.put("clientPackage", clientPackage);
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_METHOD_ARGUMENT)) {
setOptionalMethodArgumentFlag(Boolean.valueOf(additionalProperties
.get(CodegenConstants.OPTIONAL_METHOD_ARGUMENT).toString()));
}
additionalProperties.put("optionalMethodArgument", optionalMethodArgumentFlag);
supportingFiles.add(new SupportingFile("Configuration.mustache", supportingFiles.add(new SupportingFile("Configuration.mustache",
sourceFolder + File.separator + clientPackage.replace(".", java.io.File.separator), "Configuration.cs")); sourceFolder + File.separator + clientPackage.replace(".", java.io.File.separator), "Configuration.cs"));
@ -126,6 +132,8 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
sourceFolder + File.separator + clientPackage.replace(".", java.io.File.separator), "ApiClient.cs")); sourceFolder + File.separator + clientPackage.replace(".", java.io.File.separator), "ApiClient.cs"));
supportingFiles.add(new SupportingFile("ApiException.mustache", supportingFiles.add(new SupportingFile("ApiException.mustache",
sourceFolder + File.separator + clientPackage.replace(".", java.io.File.separator), "ApiException.cs")); sourceFolder + File.separator + clientPackage.replace(".", java.io.File.separator), "ApiException.cs"));
supportingFiles.add(new SupportingFile("ApiResponse.mustache",
sourceFolder + File.separator + clientPackage.replace(".", java.io.File.separator), "ApiResponse.cs"));
supportingFiles.add(new SupportingFile("Newtonsoft.Json.dll", "bin", "Newtonsoft.Json.dll")); supportingFiles.add(new SupportingFile("Newtonsoft.Json.dll", "bin", "Newtonsoft.Json.dll"));
supportingFiles.add(new SupportingFile("RestSharp.dll", "bin", "RestSharp.dll")); supportingFiles.add(new SupportingFile("RestSharp.dll", "bin", "RestSharp.dll"));
supportingFiles.add(new SupportingFile("compile.mustache", "", "compile.bat")); supportingFiles.add(new SupportingFile("compile.mustache", "", "compile.bat"));
@ -267,6 +275,10 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
return camelize(sanitizeName(operationId)); return camelize(sanitizeName(operationId));
} }
public void setOptionalMethodArgumentFlag(boolean flag) {
this.optionalMethodArgumentFlag = flag;
}
@Override @Override
public CodegenModel fromModel(String name, Model model, Map<String, Model> allDefinitions) { public CodegenModel fromModel(String name, Model model, Map<String, Model> allDefinitions) {
CodegenModel codegenModel = super.fromModel(name, model, allDefinitions); CodegenModel codegenModel = super.fromModel(name, model, allDefinitions);
@ -416,4 +428,50 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
public void setPackageVersion(String packageVersion) { public void setPackageVersion(String packageVersion) {
this.packageVersion = packageVersion; this.packageVersion = packageVersion;
} }
/**
* Return the default value of the property
*
* @param p Swagger property object
* @return string presentation of the default value of the property
*/
@Override
public String toDefaultValue(Property p) {
if (p instanceof StringProperty) {
StringProperty dp = (StringProperty) p;
if (dp.getDefault() != null) {
return "\"" + dp.getDefault().toString() + "\"";
}
} else if (p instanceof BooleanProperty) {
BooleanProperty dp = (BooleanProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof DateProperty) {
// TODO
} else if (p instanceof DateTimeProperty) {
// TODO
} else if (p instanceof DoubleProperty) {
DoubleProperty dp = (DoubleProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof FloatProperty) {
FloatProperty dp = (FloatProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof IntegerProperty) {
IntegerProperty dp = (IntegerProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
}
return null;
}
} }

View File

@ -177,6 +177,14 @@ public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfi
return name; return name;
} }
@Override
public String escapeText(String input) {
if (input == null) {
return null;
}
return input.trim().replace("\\", "\\\\").replace("\"", "\\\"");
}
@Override @Override
public Map<String, Object> postProcessOperations(Map<String, Object> operations) { public Map<String, Object> postProcessOperations(Map<String, Object> operations) {
Map<String, Object> objs = (Map<String, Object>) operations.get("operations"); Map<String, Object> objs = (Map<String, Object>) operations.get("operations");
@ -191,8 +199,4 @@ public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfi
protected String namespaceToFolder(String ns) { protected String namespaceToFolder(String ns) {
return ns.replace(".", File.separator).replace("-", "_"); return ns.replace(".", File.separator).replace("-", "_");
} }
protected String dashize(String s) {
return underscore(s).replaceAll("[_ ]", "-");
}
} }

View File

@ -5,6 +5,7 @@ import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import io.swagger.codegen.*; import io.swagger.codegen.*;
import io.swagger.models.HttpMethod;
import io.swagger.models.Operation; import io.swagger.models.Operation;
import io.swagger.models.Path; import io.swagger.models.Path;
import io.swagger.models.Swagger; import io.swagger.models.Swagger;
@ -205,13 +206,17 @@ public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConf
for(String pathname : swagger.getPaths().keySet()) { for(String pathname : swagger.getPaths().keySet()) {
Path path = swagger.getPath(pathname); Path path = swagger.getPath(pathname);
if(path.getOperations() != null) { if(path.getOperations() != null) {
for(Operation operation : path.getOperations()) { for(Map.Entry<HttpMethod, Operation> entry : path.getOperationMap().entrySet()) {
String operationId = operation.getOperationId(); // Normalize `operationId` and add package/class path in front, e.g.
if(operationId != null && operationId.indexOf(".") == -1) { // controllers.default_controller.add_pet
operation.setVendorExtension("x-operationId", underscore(sanitizeName(operationId))); String httpMethod = entry.getKey().name().toLowerCase();
operationId = controllerPackage + "." + defaultController + "." + underscore(sanitizeName(operationId)); Operation operation = entry.getValue();
operation.setOperationId(operationId); String operationId = getOrGenerateOperationId(operation, pathname, httpMethod);
if(!operationId.contains(".")) {
operationId = underscore(sanitizeName(operationId));
operationId = controllerPackage + "." + defaultController + "." + operationId;
} }
operation.setOperationId(operationId);
if(operation.getTags() != null) { if(operation.getTags() != null) {
List<Map<String, String>> tags = new ArrayList<Map<String, String>>(); List<Map<String, String>> tags = new ArrayList<Map<String, String>>();
for(String tag : operation.getTags()) { for(String tag : operation.getTags()) {
@ -292,4 +297,15 @@ public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConf
} }
return super.postProcessSupportingFileData(objs); return super.postProcessSupportingFileData(objs);
} }
@Override
public String toOperationId(String operationId) {
operationId = super.toOperationId(operationId);
// Use the part after the last dot, e.g.
// controllers.defaultController.addPet => addPet
operationId = operationId.replaceAll(".*\\.", "");
// Need to underscore it since it has been processed via removeNonNameElementToCamelCase, e.g.
// addPet => add_pet
return underscore(operationId);
}
} }

View File

@ -0,0 +1,183 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.*;
import io.swagger.models.Operation;
import io.swagger.models.Path;
import io.swagger.models.Swagger;
import io.swagger.models.properties.*;
import org.apache.commons.lang.StringUtils;
import java.util.*;
import java.io.File;
public class JMeterCodegen extends DefaultCodegen implements CodegenConfig {
// source folder where to write the files
protected String sourceFolder = "";
protected String apiVersion = "1.0.0";
/**
* Configures the type of generator.
*
* @return the CodegenType for this generator
* @see io.swagger.codegen.CodegenType
*/
public CodegenType getTag() {
return CodegenType.CLIENT;
}
/**
* Configures a friendly name for the generator. This will be used by the generator
* to select the library with the -l flag.
*
* @return the friendly name for the generator
*/
public String getName() {
return "jmeter";
}
/**
* Returns human-friendly help for the generator. Provide the consumer with help
* tips, parameters here
*
* @return A string value for the help message
*/
public String getHelp() {
return "Generates a JMeter .jmx file.";
}
public JMeterCodegen() {
super();
// set the output folder here
outputFolder = "generated-code/JMeterCodegen";
/**
* Api classes. You can write classes for each Api file with the apiTemplateFiles map.
* as with models, add multiple entries with different extensions for multiple files per
* class
*/
apiTemplateFiles.put(
"api.mustache", // the template to use
".jmx"); // the extension for each file to write
apiTemplateFiles.put("testdata-localhost.mustache", ".csv");
/**
* Template Location. This is the location which templates will be read from. The generator
* will use the resource stream to attempt to read the templates.
*/
templateDir = "JMeter";
/**
* Api Package. Optional, if needed, this can be used in templates
*/
apiPackage = "";
/**
* Model Package. Optional, if needed, this can be used in templates
*/
modelPackage = "";
/**
* Reserved words. Override this with reserved words specific to your language
*/
reservedWords = new HashSet<String> (
Arrays.asList(
"sample1", // replace with static values
"sample2")
);
/**
* Additional Properties. These values can be passed to the templates and
* are available in models, apis, and supporting files
*/
additionalProperties.put("apiVersion", apiVersion);
// supportingFiles.add(new SupportingFile("testdata-localhost.mustache", "input", "testdata-localhost.csv"));
}
public void preprocessSwagger(Swagger swagger) {
if (swagger != null && swagger.getPaths() != null) {
for (String pathname : swagger.getPaths().keySet()) {
Path path = swagger.getPath(pathname);
if (path.getOperations() != null) {
for (Operation operation : path.getOperations()) {
String pathWithDollars = pathname.replaceAll("\\{", "\\$\\{");
operation.setVendorExtension("x-path", pathWithDollars);
}
}
}
}
}
/**
* Escapes a reserved word as defined in the `reservedWords` array. Handle escaping
* those terms here. This logic is only called if a variable matches the reseved words
*
* @return the escaped term
*/
@Override
public String escapeReservedWord(String name) {
return "_" + name; // add an underscore to the name
}
/**
* Location to write model files. You can use the modelPackage() as defined when the class is
* instantiated
*/
public String modelFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar);
}
/**
* Location to write api files. You can use the apiPackage() as defined when the class is
* instantiated
*/
@Override
public String apiFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar);
}
/**
* Optional - type declaration. This is a String which is used by the templates to instantiate your
* types. There is typically special handling for different property types
*
* @return a string value used as the `dataType` field for model templates, `returnType` for api templates
*/
@Override
public String getTypeDeclaration(Property p) {
if(p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems();
return getSwaggerType(p) + "[" + getTypeDeclaration(inner) + "]";
}
else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();
return getSwaggerType(p) + "[String, " + getTypeDeclaration(inner) + "]";
}
return super.getTypeDeclaration(p);
}
/**
* Optional - swagger type conversion. This is used to map swagger types in a `Property` into
* either language specific types via `typeMapping` or into complex models if there is not a mapping.
*
* @return a string value of the type or complex model for this property
* @see io.swagger.models.properties.Property
*/
@Override
public String getSwaggerType(Property p) {
String swaggerType = super.getSwaggerType(p);
String type = null;
if(typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType);
if(languageSpecificPrimitives.contains(type))
return toModelName(type);
}
else
type = swaggerType;
return toModelName(type);
}
}

View File

@ -11,6 +11,12 @@ import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen; import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile; import io.swagger.codegen.SupportingFile;
import io.swagger.models.Model; import io.swagger.models.Model;
import io.swagger.models.Operation;
import io.swagger.models.Path;
import io.swagger.models.Swagger;
import io.swagger.models.parameters.BodyParameter;
import io.swagger.models.parameters.FormParameter;
import io.swagger.models.parameters.Parameter;
import io.swagger.models.properties.ArrayProperty; import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.BooleanProperty; import io.swagger.models.properties.BooleanProperty;
import io.swagger.models.properties.DoubleProperty; import io.swagger.models.properties.DoubleProperty;
@ -98,6 +104,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
.defaultValue("false")); .defaultValue("false"));
supportedLibraries.put(DEFAULT_LIBRARY, "HTTP client: Jersey client 1.18. JSON processing: Jackson 2.4.2"); supportedLibraries.put(DEFAULT_LIBRARY, "HTTP client: Jersey client 1.18. JSON processing: Jackson 2.4.2");
supportedLibraries.put("feign", "HTTP client: Netflix Feign 8.1.1");
supportedLibraries.put("jersey2", "HTTP client: Jersey client 2.6"); supportedLibraries.put("jersey2", "HTTP client: Jersey client 2.6");
supportedLibraries.put("okhttp-gson", "HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1"); supportedLibraries.put("okhttp-gson", "HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1");
supportedLibraries.put("retrofit", "HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1 (Retrofit 1.9.0)"); supportedLibraries.put("retrofit", "HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1 (Retrofit 1.9.0)");
@ -215,15 +222,18 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
supportingFiles.add(new SupportingFile("StringUtil.mustache", invokerFolder, "StringUtil.java")); supportingFiles.add(new SupportingFile("StringUtil.mustache", invokerFolder, "StringUtil.java"));
final String authFolder = (sourceFolder + '/' + invokerPackage + ".auth").replace(".", "/"); final String authFolder = (sourceFolder + '/' + invokerPackage + ".auth").replace(".", "/");
supportingFiles.add(new SupportingFile("auth/HttpBasicAuth.mustache", authFolder, "HttpBasicAuth.java")); if ("feign".equals(getLibrary())) {
supportingFiles.add(new SupportingFile("auth/ApiKeyAuth.mustache", authFolder, "ApiKeyAuth.java")); supportingFiles.add(new SupportingFile("FormAwareEncoder.mustache", invokerFolder, "FormAwareEncoder.java"));
supportingFiles.add(new SupportingFile("auth/OAuth.mustache", authFolder, "OAuth.java")); } else {
supportingFiles.add(new SupportingFile("auth/OAuthFlow.mustache", authFolder, "OAuthFlow.java")); supportingFiles.add(new SupportingFile("auth/HttpBasicAuth.mustache", authFolder, "HttpBasicAuth.java"));
supportingFiles.add(new SupportingFile("auth/ApiKeyAuth.mustache", authFolder, "ApiKeyAuth.java"));
supportingFiles.add(new SupportingFile("auth/OAuth.mustache", authFolder, "OAuth.java"));
supportingFiles.add(new SupportingFile("auth/OAuthFlow.mustache", authFolder, "OAuthFlow.java"));
}
if (!("retrofit".equals(getLibrary()) || "retrofit2".equals(getLibrary()))) { if (!("feign".equals(getLibrary()) || "retrofit".equals(getLibrary()) || "retrofit2".equals(getLibrary()))) {
supportingFiles.add(new SupportingFile("apiException.mustache", invokerFolder, "ApiException.java")); supportingFiles.add(new SupportingFile("apiException.mustache", invokerFolder, "ApiException.java"));
supportingFiles.add(new SupportingFile("Configuration.mustache", invokerFolder, "Configuration.java")); supportingFiles.add(new SupportingFile("Configuration.mustache", invokerFolder, "Configuration.java"));
supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java"));
supportingFiles.add(new SupportingFile("Pair.mustache", invokerFolder, "Pair.java")); supportingFiles.add(new SupportingFile("Pair.mustache", invokerFolder, "Pair.java"));
supportingFiles.add(new SupportingFile("auth/Authentication.mustache", authFolder, "Authentication.java")); supportingFiles.add(new SupportingFile("auth/Authentication.mustache", authFolder, "Authentication.java"));
} }
@ -232,13 +242,17 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
if ("okhttp-gson".equals(getLibrary())) { if ("okhttp-gson".equals(getLibrary())) {
// the "okhttp-gson" library template requires "ApiCallback.mustache" for async call // the "okhttp-gson" library template requires "ApiCallback.mustache" for async call
supportingFiles.add(new SupportingFile("ApiCallback.mustache", invokerFolder, "ApiCallback.java")); supportingFiles.add(new SupportingFile("ApiCallback.mustache", invokerFolder, "ApiCallback.java"));
supportingFiles.add(new SupportingFile("ApiResponse.mustache", invokerFolder, "ApiResponse.java"));
supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java"));
supportingFiles.add(new SupportingFile("ProgressRequestBody.mustache", invokerFolder, "ProgressRequestBody.java"));
supportingFiles.add(new SupportingFile("ProgressResponseBody.mustache", invokerFolder, "ProgressResponseBody.java"));
// "build.sbt" is for development with SBT // "build.sbt" is for development with SBT
supportingFiles.add(new SupportingFile("build.sbt.mustache", "", "build.sbt")); supportingFiles.add(new SupportingFile("build.sbt.mustache", "", "build.sbt"));
} else if ("retrofit".equals(getLibrary()) || "retrofit2".equals(getLibrary())) { } else if ("retrofit".equals(getLibrary()) || "retrofit2".equals(getLibrary())) {
supportingFiles.add(new SupportingFile("auth/OAuthOkHttpClient.mustache", authFolder, "OAuthOkHttpClient.java")); supportingFiles.add(new SupportingFile("auth/OAuthOkHttpClient.mustache", authFolder, "OAuthOkHttpClient.java"));
supportingFiles.add(new SupportingFile("CollectionFormats.mustache", invokerFolder, "CollectionFormats.java")); supportingFiles.add(new SupportingFile("CollectionFormats.mustache", invokerFolder, "CollectionFormats.java"));
} else { } else if("jersey2".equals(getLibrary())) {
supportingFiles.add(new SupportingFile("TypeRef.mustache", invokerFolder, "TypeRef.java")); supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java"));
} }
} }
@ -541,6 +555,57 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
return objs; return objs;
} }
public void preprocessSwagger(Swagger swagger) {
if (swagger != null && swagger.getPaths() != null) {
for (String pathname : swagger.getPaths().keySet()) {
Path path = swagger.getPath(pathname);
if (path.getOperations() != null) {
for (Operation operation : path.getOperations()) {
boolean hasFormParameters = false;
for (Parameter parameter : operation.getParameters()) {
if (parameter instanceof FormParameter) {
hasFormParameters = true;
}
}
String defaultContentType = hasFormParameters ? "application/x-www-form-urlencoded" : "application/json";
String contentType = operation.getConsumes() == null || operation.getConsumes().isEmpty()
? defaultContentType : operation.getConsumes().get(0);
String accepts = getAccept(operation);
operation.setVendorExtension("x-contentType", contentType);
operation.setVendorExtension("x-accepts", accepts);
}
}
}
}
}
private String getAccept(Operation operation) {
String accepts = null;
String defaultContentType = "application/json";
if (operation.getProduces() != null && !operation.getProduces().isEmpty()) {
StringBuilder sb = new StringBuilder();
for (String produces : operation.getProduces()) {
if (defaultContentType.equalsIgnoreCase(produces)) {
accepts = defaultContentType;
break;
} else {
if (sb.length() > 0) {
sb.append(",");
}
sb.append(produces);
}
}
if (accepts == null) {
accepts = sb.toString();
}
} else {
accepts = defaultContentType;
}
return accepts;
}
protected boolean needToImport(String type) { protected boolean needToImport(String type) {
return super.needToImport(type) && type.indexOf(".") < 0; return super.needToImport(type) && type.indexOf(".") < 0;
} }

View File

@ -1,27 +1,15 @@
package io.swagger.codegen.languages; package io.swagger.codegen.languages;
import io.swagger.codegen.CodegenConfig; import com.fasterxml.jackson.core.JsonProcessingException;
import io.swagger.codegen.CodegenConstants; import io.swagger.codegen.*;
import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.SupportingFile;
import io.swagger.models.Operation; import io.swagger.models.Operation;
import io.swagger.models.Swagger; import io.swagger.models.Swagger;
import io.swagger.models.properties.ArrayProperty; import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty; import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property; import io.swagger.models.properties.Property;
import io.swagger.util.Json; import io.swagger.util.Yaml;
import java.io.File; import java.util.*;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
public class JavaInflectorServerCodegen extends JavaClientCodegen implements CodegenConfig { public class JavaInflectorServerCodegen extends JavaClientCodegen implements CodegenConfig {
protected String title = "Swagger Inflector"; protected String title = "Swagger Inflector";
@ -78,6 +66,10 @@ public class JavaInflectorServerCodegen extends JavaClientCodegen implements Cod
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("web.mustache", "src/main/webapp/WEB-INF", "web.xml")); supportingFiles.add(new SupportingFile("web.mustache", "src/main/webapp/WEB-INF", "web.xml"));
supportingFiles.add(new SupportingFile("inflector.mustache", "", "inflector.yaml")); supportingFiles.add(new SupportingFile("inflector.mustache", "", "inflector.yaml"));
supportingFiles.add(new SupportingFile("swagger.mustache",
"src/main/swagger",
"swagger.yaml")
);
} }
@Override @Override
@ -173,21 +165,18 @@ public class JavaInflectorServerCodegen extends JavaClientCodegen implements Cod
return objs; return objs;
} }
@Override @Override
public void processSwagger(Swagger swagger) { public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) {
super.processSwagger(swagger); Swagger swagger = (Swagger)objs.get("swagger");
if(swagger != null) {
try { try {
File file = new File( outputFolder + "/src/main/swagger/swagger.json" ); objs.put("swagger-yaml", Yaml.mapper().writeValueAsString(swagger));
file.getParentFile().mkdirs(); } catch (JsonProcessingException e) {
e.printStackTrace();
FileWriter swaggerFile = new FileWriter(file); }
swaggerFile.write( Json.pretty( swagger ));
swaggerFile.flush();
swaggerFile.close();
} catch (IOException e) {
e.printStackTrace();
} }
return super.postProcessSupportingFileData(objs);
} }
@Override @Override

View File

@ -0,0 +1,539 @@
package io.swagger.codegen.languages;
import com.google.common.base.Strings;
import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile;
import io.swagger.models.*;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.LongProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import io.swagger.models.properties.RefProperty;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class JavascriptClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(JavascriptClientCodegen.class);
private static final String PROJECT_NAME = "projectName";
private static final String MODULE_NAME = "moduleName";
private static final String PROJECT_DESCRIPTION = "projectDescription";
private static final String PROJECT_VERSION = "projectVersion";
private static final String PROJECT_LICENSE_NAME = "projectLicenseName";
protected String projectName = null;
protected String moduleName = null;
protected String projectDescription = null;
protected String projectVersion = null;
protected String sourceFolder = "src";
protected String localVariablePrefix = "";
public JavascriptClientCodegen() {
super();
outputFolder = "generated-code/js";
modelTemplateFiles.put("model.mustache", ".js");
apiTemplateFiles.put("api.mustache", ".js");
templateDir = "Javascript";
apiPackage = "api";
modelPackage = "model";
// reference: http://www.w3schools.com/js/js_reserved.asp
reservedWords = new HashSet<String>(
Arrays.asList(
"abstract", "arguments", "boolean", "break", "byte",
"case", "catch", "char", "class", "const",
"continue", "debugger", "default", "delete", "do",
"double", "else", "enum", "eval", "export",
"extends", "false", "final", "finally", "float",
"for", "function", "goto", "if", "implements",
"import", "in", "instanceof", "int", "interface",
"let", "long", "native", "new", "null",
"package", "private", "protected", "public", "return",
"short", "static", "super", "switch", "synchronized",
"this", "throw", "throws", "transient", "true",
"try", "typeof", "var", "void", "volatile",
"while", "with", "yield",
"Array", "Date", "eval", "function", "hasOwnProperty",
"Infinity", "isFinite", "isNaN", "isPrototypeOf",
"Math", "NaN", "Number", "Object",
"prototype", "String", "toString", "undefined", "valueOf")
);
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList("String", "Boolean", "Integer", "Number", "Array", "Object", "Date", "File")
);
defaultIncludes = new HashSet<String>(languageSpecificPrimitives);
cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, CodegenConstants.SOURCE_FOLDER_DESC).defaultValue("src"));
cliOptions.add(new CliOption(CodegenConstants.LOCAL_VARIABLE_PREFIX, CodegenConstants.LOCAL_VARIABLE_PREFIX_DESC));
cliOptions.add(new CliOption(PROJECT_NAME,
"name of the project (Default: generated from info.title or \"swagger-js-client\")"));
cliOptions.add(new CliOption(MODULE_NAME,
"module name for AMD, Node or globals (Default: generated from <projectName>)"));
cliOptions.add(new CliOption(PROJECT_DESCRIPTION,
"description of the project (Default: using info.description or \"Client library of <projectName>\")"));
cliOptions.add(new CliOption(PROJECT_VERSION,
"version of the project (Default: using info.version or \"1.0.0\")"));
cliOptions.add(new CliOption(PROJECT_LICENSE_NAME,
"name of the license the project uses (Default: using info.license.name)"));
}
@Override
public CodegenType getTag() {
return CodegenType.CLIENT;
}
@Override
public String getName() {
return "javascript";
}
@Override
public String getHelp() {
return "Generates a Javascript client library.";
}
@Override
public void processOpts() {
super.processOpts();
typeMapping = new HashMap<String, String>();
typeMapping.put("array", "Array");
typeMapping.put("List", "Array");
typeMapping.put("map", "Object");
typeMapping.put("object", "Object");
typeMapping.put("boolean", "Boolean");
typeMapping.put("char", "String");
typeMapping.put("string", "String");
typeMapping.put("short", "Integer");
typeMapping.put("int", "Integer");
typeMapping.put("integer", "Integer");
typeMapping.put("long", "Integer");
typeMapping.put("float", "Number");
typeMapping.put("double", "Number");
typeMapping.put("number", "Number");
typeMapping.put("DateTime", "Date");
importMapping.clear();
}
@Override
public void preprocessSwagger(Swagger swagger) {
super.preprocessSwagger(swagger);
if (additionalProperties.containsKey(PROJECT_NAME)) {
projectName = ((String) additionalProperties.get(PROJECT_NAME));
}
if (additionalProperties.containsKey(MODULE_NAME)) {
moduleName = ((String) additionalProperties.get(MODULE_NAME));
}
if (additionalProperties.containsKey(PROJECT_DESCRIPTION)) {
projectDescription = ((String) additionalProperties.get(PROJECT_DESCRIPTION));
}
if (additionalProperties.containsKey(PROJECT_VERSION)) {
projectVersion = ((String) additionalProperties.get(PROJECT_VERSION));
}
if (additionalProperties.containsKey(CodegenConstants.LOCAL_VARIABLE_PREFIX)) {
localVariablePrefix = (String) additionalProperties.get(CodegenConstants.LOCAL_VARIABLE_PREFIX);
}
if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) {
sourceFolder = (String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER);
}
if (swagger.getInfo() != null) {
Info info = swagger.getInfo();
if (projectName == null && info.getTitle() != null) {
// when projectName is not specified, generate it from info.title
projectName = dashize(info.getTitle());
}
if (projectVersion == null) {
// when projectVersion is not specified, use info.version
projectVersion = info.getVersion();
}
if (projectDescription == null) {
// when projectDescription is not specified, use info.description
projectDescription = info.getDescription();
}
if (info.getLicense() != null) {
License license = info.getLicense();
if (additionalProperties.get(PROJECT_LICENSE_NAME) == null) {
additionalProperties.put(PROJECT_LICENSE_NAME, license.getName());
}
}
}
// default values
if (projectName == null) {
projectName = "swagger-js-client";
}
if (moduleName == null) {
moduleName = camelize(underscore(projectName));
}
if (projectVersion == null) {
projectVersion = "1.0.0";
}
if (projectDescription == null) {
projectDescription = "Client library of " + projectName;
}
additionalProperties.put(PROJECT_NAME, projectName);
additionalProperties.put(MODULE_NAME, moduleName);
additionalProperties.put(PROJECT_DESCRIPTION, escapeText(projectDescription));
additionalProperties.put(PROJECT_VERSION, projectVersion);
additionalProperties.put(CodegenConstants.LOCAL_VARIABLE_PREFIX, localVariablePrefix);
additionalProperties.put(CodegenConstants.SOURCE_FOLDER, sourceFolder);
supportingFiles.add(new SupportingFile("package.mustache", "", "package.json"));
supportingFiles.add(new SupportingFile("index.mustache", sourceFolder, "index.js"));
}
@Override
public String escapeReservedWord(String name) {
return "_" + name;
}
@Override
public String apiFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar);
}
@Override
public String modelFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar);
}
@Override
public String toVarName(String name) {
// sanitize name
name = sanitizeName(name);
if("_".equals(name)) {
name = "_u";
}
// if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$")) {
return name;
}
// camelize (lower first character) the variable name
// pet_id => petId
name = camelize(name, true);
// for reserved word or word starting with number, append _
if (reservedWords.contains(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name);
}
return name;
}
@Override
public String toParamName(String name) {
// should be the same as variable name
return toVarName(name);
}
@Override
public String toModelName(String name) {
name = sanitizeName(name);
// model name cannot use reserved keyword, e.g. return
if (reservedWords.contains(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
}
// camelize the model name
// phone_number => PhoneNumber
return camelize(name);
}
@Override
public String toModelFilename(String name) {
// should be the same as the model name
return toModelName(name);
}
@Override
public String toModelImport(String name) {
return name;
}
@Override
public String toApiImport(String name) {
return toApiName(name);
}
@Override
public String getTypeDeclaration(Property p) {
if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems();
return getSwaggerType(p); // TODO: + "/* <" + getTypeDeclaration(inner) + "> */";
} else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();
return getSwaggerType(p) + "<String, " + getTypeDeclaration(inner) + ">";
}
return super.getTypeDeclaration(p);
}
@Override
public String toDefaultValue(Property p) {
if (p instanceof ArrayProperty) {
return "[]";
} else if (p instanceof MapProperty) {
return "{}";
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString()+"l";
}
return "null";
// added for Javascript
} else if (p instanceof RefProperty) {
RefProperty rp = (RefProperty)p;
return "new " +rp.getSimpleRef() + "()";
}
return super.toDefaultValue(p);
}
@Override
public String toDefaultValueWithParam(String name, Property p) {
if (p instanceof ArrayProperty) {
return " = new Array();";
} else if (p instanceof MapProperty) {
return " = {}";
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
return " = data." + name + ";";
// added for Javascript
} else if (p instanceof RefProperty) {
RefProperty rp = (RefProperty)p;
return ".constructFromObject(data." + name + ");";
}
return super.toDefaultValueWithParam(name, p);
}
@Override
public String getSwaggerType(Property p) {
String swaggerType = super.getSwaggerType(p);
String type = null;
if (typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType);
if (!needToImport(type)) {
return type;
}
} else {
type = swaggerType;
}
if (null == type) {
LOGGER.error("No Type defined for Property " + p);
}
return toModelName(type);
}
@Override
public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method/operation name (operationId) not allowed");
}
// method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
}
return camelize(sanitizeName(operationId), true);
}
@Override
public CodegenModel fromModel(String name, Model model, Map<String, Model> allDefinitions) {
CodegenModel codegenModel = super.fromModel(name, model, allDefinitions);
if (allDefinitions != null && codegenModel != null && codegenModel.parent != null && codegenModel.hasEnums) {
final Model parentModel = allDefinitions.get(toModelName(codegenModel.parent));
final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel);
codegenModel = this.reconcileInlineEnums(codegenModel, parentCodegenModel);
}
return codegenModel;
}
@Override
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
List<Object> models = (List<Object>) objs.get("models");
for (Object _mo : models) {
Map<String, Object> mo = (Map<String, Object>) _mo;
CodegenModel cm = (CodegenModel) mo.get("model");
for (CodegenProperty var : cm.vars) {
Map<String, Object> allowableValues = var.allowableValues;
// handle ArrayProperty
if (var.items != null) {
allowableValues = var.items.allowableValues;
}
if (allowableValues == null) {
continue;
}
List<String> values = (List<String>) allowableValues.get("values");
if (values == null) {
continue;
}
// put "enumVars" map into `allowableValues", including `name` and `value`
List<Map<String, String>> enumVars = new ArrayList<Map<String, String>>();
String commonPrefix = findCommonPrefixOfVars(values);
int truncateIdx = commonPrefix.length();
for (String value : values) {
Map<String, String> enumVar = new HashMap<String, String>();
String enumName;
if (truncateIdx == 0) {
enumName = value;
} else {
enumName = value.substring(truncateIdx);
if ("".equals(enumName)) {
enumName = value;
}
}
enumVar.put("name", toEnumVarName(enumName));
enumVar.put("value", value);
enumVars.add(enumVar);
}
allowableValues.put("enumVars", enumVars);
}
}
return objs;
}
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
if("retrofit".equals(getLibrary())) {
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
if (operations != null) {
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
for (CodegenOperation operation : ops) {
if (operation.hasConsumes == Boolean.TRUE) {
Map<String, String> firstType = operation.consumes.get(0);
if (firstType != null) {
if ("multipart/form-data".equals(firstType.get("mediaType"))) {
operation.isMultipart = Boolean.TRUE;
}
}
}
if (operation.returnType == null) {
operation.returnType = "Void";
}
}
}
}
return objs;
}
protected boolean needToImport(String type) {
return !defaultIncludes.contains(type)
&& !languageSpecificPrimitives.contains(type);
}
private String findCommonPrefixOfVars(List<String> vars) {
String prefix = StringUtils.getCommonPrefix(vars.toArray(new String[vars.size()]));
// exclude trailing characters that should be part of a valid variable
// e.g. ["status-on", "status-off"] => "status-" (not "status-o")
return prefix.replaceAll("[a-zA-Z0-9]+\\z", "");
}
private String toEnumVarName(String value) {
String var = value.replaceAll("\\W+", "_").toUpperCase();
if (var.matches("\\d.*")) {
return "_" + var;
} else {
return var;
}
}
private CodegenModel reconcileInlineEnums(CodegenModel codegenModel, CodegenModel parentCodegenModel) {
// This generator uses inline classes to define enums, which breaks when
// dealing with models that have subTypes. To clean this up, we will analyze
// the parent and child models, look for enums that match, and remove
// them from the child models and leave them in the parent.
// Because the child models extend the parents, the enums will be available via the parent.
// Only bother with reconciliation if the parent model has enums.
if (parentCodegenModel.hasEnums) {
// Get the properties for the parent and child models
final List<CodegenProperty> parentModelCodegenProperties = parentCodegenModel.vars;
List<CodegenProperty> codegenProperties = codegenModel.vars;
// Iterate over all of the parent model properties
boolean removedChildEnum = false;
for (CodegenProperty parentModelCodegenPropery : parentModelCodegenProperties) {
// Look for enums
if (parentModelCodegenPropery.isEnum) {
// Now that we have found an enum in the parent class,
// and search the child class for the same enum.
Iterator<CodegenProperty> iterator = codegenProperties.iterator();
while (iterator.hasNext()) {
CodegenProperty codegenProperty = iterator.next();
if (codegenProperty.isEnum && codegenProperty.equals(parentModelCodegenPropery)) {
// We found an enum in the child class that is
// a duplicate of the one in the parent, so remove it.
iterator.remove();
removedChildEnum = true;
}
}
}
}
if(removedChildEnum) {
// If we removed an entry from this model's vars, we need to ensure hasMore is updated
int count = 0, numVars = codegenProperties.size();
for(CodegenProperty codegenProperty : codegenProperties) {
count += 1;
codegenProperty.hasMore = (count < numVars) ? true : null;
}
codegenModel.vars = codegenProperties;
}
}
return codegenModel;
}
private String sanitizePackageName(String packageName) {
packageName = packageName.trim();
packageName = packageName.replaceAll("[^a-zA-Z0-9_\\.]", "_");
if(Strings.isNullOrEmpty(packageName)) {
return "invalidPackageName";
}
return packageName;
}
}

View File

@ -33,18 +33,6 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId); additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion); additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
additionalProperties.put("title", title); additionalProperties.put("title", title);
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"String",
"boolean",
"Boolean",
"Double",
"Integer",
"Long",
"Float")
);
} }
public CodegenType getTag() { public CodegenType getTag() {
@ -109,6 +97,9 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
@Override @Override
public void preprocessSwagger(Swagger swagger) { public void preprocessSwagger(Swagger swagger) {
if("/".equals(swagger.getBasePath())) {
swagger.setBasePath("");
}
if(swagger != null && swagger.getPaths() != null) { if(swagger != null && swagger.getPaths() != null) {
for(String pathname : swagger.getPaths().keySet()) { for(String pathname : swagger.getPaths().keySet()) {
Path path = swagger.getPath(pathname); Path path = swagger.getPath(pathname);

View File

@ -7,9 +7,7 @@ import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.CodegenType; import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen; import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile; import io.swagger.codegen.SupportingFile;
import io.swagger.models.properties.ArrayProperty; import io.swagger.models.properties.*;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import java.io.File; import java.io.File;
import java.util.Arrays; import java.util.Arrays;
@ -34,6 +32,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String authorEmail = "apiteam@swagger.io"; protected String authorEmail = "apiteam@swagger.io";
protected String license = "MIT"; protected String license = "MIT";
protected String gitRepoURL = "https://github.com/swagger-api/swagger-codegen"; protected String gitRepoURL = "https://github.com/swagger-api/swagger-codegen";
protected String[] specialWords = {"new", "copy"};
public ObjcClientCodegen() { public ObjcClientCodegen() {
super(); super();
@ -86,6 +85,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("object", "NSObject"); typeMapping.put("object", "NSObject");
typeMapping.put("file", "NSURL"); typeMapping.put("file", "NSURL");
// ref: http://www.tutorialspoint.com/objective_c/objective_c_basic_syntax.htm // ref: http://www.tutorialspoint.com/objective_c/objective_c_basic_syntax.htm
reservedWords = new HashSet<String>( reservedWords = new HashSet<String>(
Arrays.asList( Arrays.asList(
@ -341,11 +341,6 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
return name; return name;
} }
@Override
public String toDefaultValue(Property p) {
return null;
}
@Override @Override
public String apiFileFolder() { public String apiFileFolder() {
return outputFolder + File.separatorChar + apiPackage(); return outputFolder + File.separatorChar + apiPackage();
@ -375,6 +370,12 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
return name; return name;
} }
// if name starting with special word, escape with '_'
for(int i =0; i < specialWords.length; i++) {
if (name.matches("(?i:^" + specialWords[i] + ".*)"))
name = escapeSpecialWord(name);
}
// camelize (lower first character) the variable name // camelize (lower first character) the variable name
// e.g. `pet_id` to `petId` // e.g. `pet_id` to `petId`
name = camelize(name, true); name = camelize(name, true);
@ -384,6 +385,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
name = escapeReservedWord(name); name = escapeReservedWord(name);
} }
return name; return name;
} }
@ -397,6 +399,10 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
return "_" + name; return "_" + name;
} }
public String escapeSpecialWord(String name) {
return "var_" + name;
}
@Override @Override
public String toOperationId(String operationId) { public String toOperationId(String operationId) {
// throw exception if method name is empty // throw exception if method name is empty
@ -439,4 +445,55 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
public void setLicense(String license) { public void setLicense(String license) {
this.license = license; this.license = license;
} }
/**
* Return the default value of the property
*
* @param p Swagger property object
* @return string presentation of the default value of the property
*/
@Override
public String toDefaultValue(Property p) {
if (p instanceof StringProperty) {
StringProperty dp = (StringProperty) p;
if (dp.getDefault() != null) {
return "@\"" + dp.getDefault().toString() + "\"";
}
} else if (p instanceof BooleanProperty) {
BooleanProperty dp = (BooleanProperty) p;
if (dp.getDefault() != null) {
if (dp.getDefault().toString().equalsIgnoreCase("false"))
return "@0";
else
return "@1";
}
} else if (p instanceof DateProperty) {
// TODO
} else if (p instanceof DateTimeProperty) {
// TODO
} else if (p instanceof DoubleProperty) {
DoubleProperty dp = (DoubleProperty) p;
if (dp.getDefault() != null) {
return "@" + dp.getDefault().toString();
}
} else if (p instanceof FloatProperty) {
FloatProperty dp = (FloatProperty) p;
if (dp.getDefault() != null) {
return "@" + dp.getDefault().toString();
}
} else if (p instanceof IntegerProperty) {
IntegerProperty dp = (IntegerProperty) p;
if (dp.getDefault() != null) {
return "@" + dp.getDefault().toString();
}
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
if (dp.getDefault() != null) {
return "@" + dp.getDefault().toString();
}
}
return null;
}
} }

View File

@ -6,19 +6,22 @@ import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenType; import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen; import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile; import io.swagger.codegen.SupportingFile;
import io.swagger.models.properties.ArrayProperty; import io.swagger.models.properties.*;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import io.swagger.models.properties.RefProperty;
import java.io.File; import java.io.File;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.regex.Matcher;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
static Logger LOGGER = LoggerFactory.getLogger(PhpClientCodegen.class);
public static final String VARIABLE_NAMING_CONVENTION = "variableNamingConvention"; public static final String VARIABLE_NAMING_CONVENTION = "variableNamingConvention";
public static final String PACKAGE_PATH = "packagePath"; public static final String PACKAGE_PATH = "packagePath";
public static final String SRC_BASE_PATH = "srcBasePath"; public static final String SRC_BASE_PATH = "srcBasePath";
@ -129,7 +132,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
return (getPackagePath() + File.separatorChar + basePath return (getPackagePath() + File.separatorChar + basePath
// Replace period, backslash, forward slash with file separator in package name // Replace period, backslash, forward slash with file separator in package name
+ packageName.replaceAll("[\\.\\\\/]", File.separator) + packageName.replaceAll("[\\.\\\\/]", Matcher.quoteReplacement(File.separator))
// Trim prefix file separators from package path // Trim prefix file separators from package path
.replaceAll(regFirstPathSeparator, "")) .replaceAll(regFirstPathSeparator, ""))
// Trim trailing file separators from the overall path // Trim trailing file separators from the overall path
@ -217,11 +220,11 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String apiFileFolder() { public String apiFileFolder() {
return (outputFolder + "/" + toPackagePath(apiPackage(), srcBasePath)); return (outputFolder + "/" + toPackagePath(apiPackage, srcBasePath));
} }
public String modelFileFolder() { public String modelFileFolder() {
return (outputFolder + "/" + toPackagePath(modelPackage(), srcBasePath)); return (outputFolder + "/" + toPackagePath(modelPackage, srcBasePath));
} }
@Override @Override
@ -270,10 +273,6 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
return toModelName(type); return toModelName(type);
} }
public String toDefaultValue(Property p) {
return "null";
}
public void setInvokerPackage(String invokerPackage) { public void setInvokerPackage(String invokerPackage) {
this.invokerPackage = invokerPackage; this.invokerPackage = invokerPackage;
} }
@ -371,4 +370,51 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
return camelize(sanitizeName(operationId), true); return camelize(sanitizeName(operationId), true);
} }
/**
* Return the default value of the property
*
* @param p Swagger property object
* @return string presentation of the default value of the property
*/
@Override
public String toDefaultValue(Property p) {
if (p instanceof StringProperty) {
StringProperty dp = (StringProperty) p;
if (dp.getDefault() != null) {
return "'" + dp.getDefault().toString() + "'";
}
} else if (p instanceof BooleanProperty) {
BooleanProperty dp = (BooleanProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof DateProperty) {
// TODO
} else if (p instanceof DateTimeProperty) {
// TODO
} else if (p instanceof DoubleProperty) {
DoubleProperty dp = (DoubleProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof FloatProperty) {
FloatProperty dp = (FloatProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof IntegerProperty) {
IntegerProperty dp = (IntegerProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
}
return null;
}
} }

View File

@ -6,9 +6,7 @@ import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenType; import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen; import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile; import io.swagger.codegen.SupportingFile;
import io.swagger.models.properties.ArrayProperty; import io.swagger.models.properties.*;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import java.io.File; import java.io.File;
import java.util.Arrays; import java.util.Arrays;
@ -166,10 +164,6 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
return type; return type;
} }
public String toDefaultValue(Property p) {
return "None";
}
@Override @Override
public String toVarName(String name) { public String toVarName(String name) {
// sanitize name // sanitize name
@ -291,4 +285,55 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
public String generatePackageName(String packageName) { public String generatePackageName(String packageName) {
return underscore(packageName.replaceAll("[^\\w]+", "")); return underscore(packageName.replaceAll("[^\\w]+", ""));
} }
/**
* Return the default value of the property
*
* @param p Swagger property object
* @return string presentation of the default value of the property
*/
@Override
public String toDefaultValue(Property p) {
if (p instanceof StringProperty) {
StringProperty dp = (StringProperty) p;
if (dp.getDefault() != null) {
return "'" + dp.getDefault().toString() + "'";
}
} else if (p instanceof BooleanProperty) {
BooleanProperty dp = (BooleanProperty) p;
if (dp.getDefault() != null) {
if (dp.getDefault().toString().equalsIgnoreCase("false"))
return "False";
else
return "True";
}
} else if (p instanceof DateProperty) {
// TODO
} else if (p instanceof DateTimeProperty) {
// TODO
} else if (p instanceof DoubleProperty) {
DoubleProperty dp = (DoubleProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof FloatProperty) {
FloatProperty dp = (FloatProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof IntegerProperty) {
IntegerProperty dp = (IntegerProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
}
return null;
}
} }

View File

@ -6,9 +6,7 @@ import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenType; import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen; import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile; import io.swagger.codegen.SupportingFile;
import io.swagger.models.properties.ArrayProperty; import io.swagger.models.properties.*;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import java.io.File; import java.io.File;
import java.util.Arrays; import java.util.Arrays;
@ -186,6 +184,43 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
return super.getTypeDeclaration(p); return super.getTypeDeclaration(p);
} }
@Override
public String toDefaultValue(Property p) {
if (p instanceof IntegerProperty) {
IntegerProperty dp = (IntegerProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof DoubleProperty) {
DoubleProperty dp = (DoubleProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof FloatProperty) {
FloatProperty dp = (FloatProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof BooleanProperty) {
BooleanProperty bp = (BooleanProperty) p;
if (bp.getDefault() != null) {
return bp.getDefault().toString();
}
} else if (p instanceof StringProperty) {
StringProperty sp = (StringProperty) p;
if (sp.getDefault() != null) {
return "\"" + escapeText(sp.getDefault()) + "\"";
}
}
return null;
}
@Override @Override
public String getSwaggerType(Property p) { public String getSwaggerType(Property p) {
String swaggerType = super.getSwaggerType(p); String swaggerType = super.getSwaggerType(p);
@ -204,10 +239,6 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
return type; return type;
} }
public String toDefaultValue(Property p) {
return "null";
}
@Override @Override
public String toVarName(String name) { public String toVarName(String name) {
// sanitize name // sanitize name

View File

@ -1,5 +1,7 @@
package io.swagger.codegen.languages; package io.swagger.codegen.languages;
import com.fasterxml.jackson.core.JsonProcessingException;
import io.swagger.codegen.CliOption; import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenType; import io.swagger.codegen.CodegenType;
@ -8,10 +10,13 @@ import io.swagger.codegen.SupportingFile;
import io.swagger.models.properties.ArrayProperty; import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty; import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property; import io.swagger.models.properties.Property;
import io.swagger.models.Swagger;
import io.swagger.util.Yaml;
import java.io.File; import java.io.File;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
@ -73,6 +78,7 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
supportingFiles.add(new SupportingFile("config.ru", "", "config.ru")); supportingFiles.add(new SupportingFile("config.ru", "", "config.ru"));
supportingFiles.add(new SupportingFile("Gemfile", "", "Gemfile")); supportingFiles.add(new SupportingFile("Gemfile", "", "Gemfile"));
supportingFiles.add(new SupportingFile("README.md", "", "README.md")); supportingFiles.add(new SupportingFile("README.md", "", "README.md"));
supportingFiles.add(new SupportingFile("swagger.mustache","","swagger.yaml"));
} }
public CodegenType getTag() { public CodegenType getTag() {
@ -213,5 +219,17 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
return underscore(operationId); return underscore(operationId);
} }
@Override
public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) {
Swagger swagger = (Swagger)objs.get("swagger");
if(swagger != null) {
try {
objs.put("swagger-yaml", Yaml.mapper().writeValueAsString(swagger));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
return super.postProcessSupportingFileData(objs);
}
} }

View File

@ -0,0 +1,221 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import io.swagger.models.properties.RefProperty;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
public class SlimFrameworkServerCodegen extends DefaultCodegen implements CodegenConfig {
protected String invokerPackage;
protected String groupId = "io.swagger";
protected String artifactId = "swagger-server";
protected String artifactVersion = "1.0.0";
private String variableNamingConvention = "camelCase";
public SlimFrameworkServerCodegen() {
super();
invokerPackage = camelize("SwaggerServer");
String packagePath = "SwaggerServer";
modelPackage = packagePath + "\\lib\\Models";
apiPackage = packagePath + "\\lib";
outputFolder = "generated-code" + File.separator + "slim";
modelTemplateFiles.put("model.mustache", ".php");
// no api files
apiTemplateFiles.clear();
embeddedTemplateDir = templateDir = "slim";
reservedWords = new HashSet<String>(
Arrays.asList(
"__halt_compiler", "abstract", "and", "array", "as", "break", "callable", "case", "catch", "class", "clone", "const", "continue", "declare", "default", "die", "do", "echo", "else", "elseif", "empty", "enddeclare", "endfor", "endforeach", "endif", "endswitch", "endwhile", "eval", "exit", "extends", "final", "for", "foreach", "function", "global", "goto", "if", "implements", "include", "include_once", "instanceof", "insteadof", "interface", "isset", "list", "namespace", "new", "or", "print", "private", "protected", "public", "require", "require_once", "return", "static", "switch", "throw", "trait", "try", "unset", "use", "var", "while", "xor")
);
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
// ref: http://php.net/manual/en/language.types.intro.php
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"boolean",
"int",
"integer",
"double",
"float",
"string",
"object",
"DateTime",
"mixed",
"number")
);
instantiationTypes.put("array", "array");
instantiationTypes.put("map", "map");
// ref: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#data-types
typeMapping = new HashMap<String, String>();
typeMapping.put("integer", "int");
typeMapping.put("long", "int");
typeMapping.put("float", "float");
typeMapping.put("double", "double");
typeMapping.put("string", "string");
typeMapping.put("byte", "int");
typeMapping.put("boolean", "bool");
typeMapping.put("date", "\\DateTime");
typeMapping.put("datetime", "\\DateTime");
typeMapping.put("file", "\\SplFileObject");
typeMapping.put("map", "map");
typeMapping.put("array", "array");
typeMapping.put("list", "array");
typeMapping.put("object", "object");
supportingFiles.add(new SupportingFile("README.mustache", packagePath.replace('/', File.separatorChar), "README.md"));
supportingFiles.add(new SupportingFile("composer.json", packagePath.replace('/', File.separatorChar), "composer.json"));
supportingFiles.add(new SupportingFile("index.mustache", packagePath.replace('/', File.separatorChar), "index.php"));
supportingFiles.add(new SupportingFile(".htaccess", packagePath.replace('/', File.separatorChar), ".htaccess"));
}
public CodegenType getTag() {
return CodegenType.SERVER;
}
public String getName() {
return "slim";
}
public String getHelp() {
return "Generates a Slim Framework server library.";
}
@Override
public String escapeReservedWord(String name) {
return "_" + name;
}
@Override
public String apiFileFolder() {
return (outputFolder + "/" + apiPackage()).replace('/', File.separatorChar);
}
public String modelFileFolder() {
return (outputFolder + "/" + modelPackage()).replace('/', File.separatorChar);
}
@Override
public String getTypeDeclaration(Property p) {
if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems();
return getTypeDeclaration(inner) + "[]";
} else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();
return getSwaggerType(p) + "[string," + getTypeDeclaration(inner) + "]";
} else if (p instanceof RefProperty) {
String type = super.getTypeDeclaration(p);
return (!languageSpecificPrimitives.contains(type))
? "\\" + modelPackage + "\\" + type : type;
}
return super.getTypeDeclaration(p);
}
@Override
public String getSwaggerType(Property p) {
String swaggerType = super.getSwaggerType(p);
String type = null;
if (typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType);
if (languageSpecificPrimitives.contains(type)) {
return type;
} else if (instantiationTypes.containsKey(type)) {
return type;
}
} else {
type = swaggerType;
}
if (type == null) {
return null;
}
return toModelName(type);
}
@Override
public String getTypeDeclaration(String name) {
if (!languageSpecificPrimitives.contains(name)) {
return "\\" + modelPackage + "\\" + name;
}
return super.getTypeDeclaration(name);
}
public String toDefaultValue(Property p) {
return "null";
}
public void setParameterNamingConvention(String variableNamingConvention) {
this.variableNamingConvention = variableNamingConvention;
}
@Override
public String toVarName(String name) {
// sanitize name
name = sanitizeName(name);
if ("camelCase".equals(variableNamingConvention)) {
// return the name in camelCase style
// phone_number => phoneNumber
name = camelize(name, true);
} else { // default to snake case
// return the name in underscore style
// PhoneNumber => phone_number
name = underscore(name);
}
// parameter name starting with number won't compile
// need to escape it by appending _ at the beginning
if (name.matches("^\\d.*")) {
name = "_" + name;
}
return name;
}
@Override
public String toParamName(String name) {
// should be the same as variable name
return toVarName(name);
}
@Override
public String toModelName(String name) {
// model name cannot use reserved keyword
if (reservedWords.contains(name)) {
escapeReservedWord(name); // e.g. return => _return
}
// camelize the model name
// phone_number => PhoneNumber
return camelize(name);
}
@Override
public String toModelFilename(String name) {
// should be the same as the model name
return toModelName(name);
}
}

View File

@ -134,7 +134,7 @@ namespace {{packageName}}.Client
} }
/// <summary> /// <summary>
/// If parameter is DateTime, output in ISO8601 format. /// If parameter is DateTime, output in a formatted string (default ISO 8601), customizable with Configuration.DateTime.
/// If parameter is a list of string, join the list with ",". /// If parameter is a list of string, join the list with ",".
/// Otherwise just return the string. /// Otherwise just return the string.
/// </summary> /// </summary>
@ -143,7 +143,11 @@ namespace {{packageName}}.Client
public string ParameterToString(object obj) public string ParameterToString(object obj)
{ {
if (obj is DateTime) if (obj is DateTime)
return ((DateTime)obj).ToString ("u"); // Return a formatted date string - Can be customized with Configuration.DateTimeFormat
// Defaults to an ISO 8601, using the known as a Round-trip date/time pattern ("o")
// https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx#Anchor_8
// For example: 2009-06-15T13:45:30.0000000
return ((DateTime)obj).ToString (Configuration.DateTimeFormat);
else if (obj is List<string>) else if (obj is List<string>)
return String.Join(",", (obj as List<string>).ToArray()); return String.Join(",", (obj as List<string>).ToArray());
else else

View File

@ -78,7 +78,40 @@ namespace {{packageName}}.Client
_tempFolderPath = value + Path.DirectorySeparatorChar; _tempFolderPath = value + Path.DirectorySeparatorChar;
} }
} }
private const string ISO8601_DATETIME_FORMAT = "o";
private static string _dateTimeFormat = ISO8601_DATETIME_FORMAT;
/// <summary>
/// Gets or sets the 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
/// No validation is done to ensure that the string you're providing is valid
/// </summary>
/// <value>The DateTimeFormat string</value>
public static String DateTimeFormat
{
get
{
return _dateTimeFormat;
}
set
{
if (string.IsNullOrEmpty(value))
{
// Never allow a blank or null string, go back to the default
_dateTimeFormat = ISO8601_DATETIME_FORMAT;
return;
}
// Caution, no validation when you choose date time format other than ISO 8601
// Take a look at the above links
_dateTimeFormat = value;
}
}
/// <summary> /// <summary>
/// Returns a string with essential information for debugging. /// Returns a string with essential information for debugging.
/// </summary> /// </summary>

View File

@ -0,0 +1,178 @@
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="2.8" jmeter="2.13 r1665067">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="{{classname}} Test Plan" enabled="true">
<stringProp name="TestPlan.comments"></stringProp>
<boolProp name="TestPlan.functional_mode">false</boolProp>
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments">
<elementProp name="host" elementType="Argument">
<stringProp name="Argument.name">host</stringProp>
<stringProp name="Argument.value">localhost</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="port" elementType="Argument">
<stringProp name="Argument.name">port</stringProp>
<stringProp name="Argument.value">8080</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
</collectionProp>
</elementProp>
<stringProp name="TestPlan.user_define_classpath"></stringProp>
</TestPlan>
<hashTree>
<Arguments guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments">
<elementProp name="testCases" elementType="Argument">
<stringProp name="Argument.name">testCases</stringProp>
<stringProp name="Argument.value">${__P(host,10)}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="host" elementType="Argument">
<stringProp name="Argument.name">host</stringProp>
<stringProp name="Argument.value">${__P(host,localhost)}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="port" elementType="Argument">
<stringProp name="Argument.name">port</stringProp>
<stringProp name="Argument.value">${__P(port,8080)}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>{{#operations}}{{#operation}}
<elementProp name="testData.{{operationId}}File" elementType="Argument">
<stringProp name="Argument.name">testData.{{operationId}}File</stringProp>
<stringProp name="Argument.value">${__P(testData.{{operationId}}File,{{classname}}.csv)}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>{{/operation}}{{/operations}}
</collectionProp>
</Arguments>
<hashTree/>
<ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP Request Defaults" enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.domain">${host}</stringProp>
<stringProp name="HTTPSampler.port">${port}</stringProp>
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
<stringProp name="HTTPSampler.response_timeout"></stringProp>
<stringProp name="HTTPSampler.protocol"></stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path"></stringProp>
<stringProp name="HTTPSampler.concurrentPool">4</stringProp>
</ConfigTestElement>
<hashTree/>
{{#operations}}{{#operation}}<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group - {{operationId}}" enabled="true">
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<boolProp name="LoopController.continue_forever">false</boolProp>
<stringProp name="LoopController.loops">${testCases}</stringProp>
</elementProp>
<stringProp name="ThreadGroup.num_threads">1</stringProp>
<stringProp name="ThreadGroup.ramp_time">1</stringProp>
<longProp name="ThreadGroup.start_time">1448391617000</longProp>
<longProp name="ThreadGroup.end_time">1448391617000</longProp>
<boolProp name="ThreadGroup.scheduler">false</boolProp>
<stringProp name="ThreadGroup.duration"></stringProp>
<stringProp name="ThreadGroup.delay"></stringProp>
</ThreadGroup>
<hashTree>
<HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true">
<collectionProp name="HeaderManager.headers">{{#headerParams}}
<elementProp name="" elementType="Header">
<stringProp name="Header.name">{{paramName}}</stringProp>
<stringProp name="Header.value">${__RandomString(10,qwertyuiopasdfghjklzxcvbnm)}</stringProp>
</elementProp>{{/headerParams}}
</collectionProp>
</HeaderManager>
<hashTree/>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="{{operationId}} - ${testCase}" enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments">{{#queryParams}}
<elementProp name="{{paramName}}" elementType="HTTPArgument">
<boolProp name="HTTPArgument.always_encode">false</boolProp>
<stringProp name="Argument.value">0</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
<boolProp name="HTTPArgument.use_equals">true</boolProp>
<stringProp name="Argument.name">{{paramName}}</stringProp>
</elementProp>{{/queryParams}}
</collectionProp>
</elementProp>
<stringProp name="HTTPSampler.domain"></stringProp>
<stringProp name="HTTPSampler.port"></stringProp>
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
<stringProp name="HTTPSampler.response_timeout"></stringProp>
<stringProp name="HTTPSampler.protocol"></stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path">{{vendorExtensions.x-path}}</stringProp>
<stringProp name="HTTPSampler.method">{{httpMethod}}</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
<stringProp name="HTTPSampler.implementation">HttpClient3.1</stringProp>
<boolProp name="HTTPSampler.monitor">false</boolProp>
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
<stringProp name="TestPlan.comments">{{summary}} {{notes}}</stringProp>
</HTTPSamplerProxy>
<hashTree>
<CSVDataSet guiclass="TestBeanGUI" testclass="CSVDataSet" testname="Load CSV Test Data - {{operationId}}" enabled="true">
<stringProp name="delimiter">,</stringProp>
<stringProp name="fileEncoding"></stringProp>
<stringProp name="filename">${testData.{{operationId}}File}</stringProp>
<boolProp name="quotedData">true</boolProp>
<boolProp name="recycle">true</boolProp>
<stringProp name="shareMode">shareMode.all</stringProp>
<boolProp name="stopThread">false</boolProp>
<stringProp name="variableNames"></stringProp>
</CSVDataSet>
<hashTree/>
</hashTree>
<ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="HTTP Status Assertion" enabled="true">
<collectionProp name="Asserion.test_strings">
<stringProp name="812696575">${httpStatusCode}</stringProp>
</collectionProp>
<stringProp name="Assertion.test_field">Assertion.response_code</stringProp>
<boolProp name="Assertion.assume_success">false</boolProp>
<intProp name="Assertion.test_type">8</intProp>
</ResponseAssertion>
<hashTree/>
</hashTree>
{{/operation}}
{{/operations}}
<!-- end of operations -->
<ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>false</xml>
<fieldNames>false</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
<threadCounts>true</threadCounts>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
</hashTree>
</hashTree>
</jmeterTestPlan>

View File

@ -0,0 +1,2 @@
testCase,httpStatusCode{{#operations}}{{#operation}}{{#hasParams}},{{/hasParams}}{{#allParams}}{{paramName}}{{#hasMore}},{{/hasMore}}{{/allParams}}{{/operation}}{{/operations}}
Success,200{{#operations}}{{#operation}}{{#hasParams}},{{/hasParams}}{{#allParams}}0{{#hasMore}},{{/hasMore}}{{/allParams}}{{/operation}}{{/operations}}

View File

@ -1,8 +1,13 @@
package {{invokerPackage}}; package {{invokerPackage}};
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.datatype.joda.*;
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.config.ClientConfig; import com.sun.jersey.api.client.GenericType;
import com.sun.jersey.api.client.config.DefaultClientConfig; import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.client.filter.LoggingFilter; import com.sun.jersey.api.client.filter.LoggingFilter;
import com.sun.jersey.api.client.WebResource.Builder; import com.sun.jersey.api.client.WebResource.Builder;
@ -25,14 +30,11 @@ import java.util.TimeZone;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.io.IOException;
import java.io.File; import java.io.File;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.io.DataInputStream;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.text.ParseException;
import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.Authentication;
import {{invokerPackage}}.auth.HttpBasicAuth; import {{invokerPackage}}.auth.HttpBasicAuth;
@ -45,7 +47,7 @@ public class ApiClient {
private Map<String, String> defaultHeaderMap = new HashMap<String, String>(); private Map<String, String> defaultHeaderMap = new HashMap<String, String>();
private boolean debugging = false; private boolean debugging = false;
private String basePath = "{{basePath}}"; private String basePath = "{{basePath}}";
private JSON json = new JSON(); private ObjectMapper mapper;
private Map<String, Authentication> authentications; private Map<String, Authentication> authentications;
@ -55,6 +57,14 @@ public class ApiClient {
private DateFormat dateFormat; private DateFormat dateFormat;
public ApiClient() { public ApiClient() {
mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
mapper.registerModule(new JodaModule());
// Use RFC3339 format for date and datetime. // Use RFC3339 format for date and datetime.
// See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14 // See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14
this.dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); this.dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
@ -62,7 +72,7 @@ public class ApiClient {
// Use UTC as the default time zone. // Use UTC as the default time zone.
this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
this.json.setDateFormat((DateFormat) dateFormat.clone()); this.mapper.setDateFormat((DateFormat) dateFormat.clone());
// Set default User-Agent. // Set default User-Agent.
setUserAgent("Java-Swagger"); setUserAgent("Java-Swagger");
@ -76,13 +86,6 @@ public class ApiClient {
authentications = Collections.unmodifiableMap(authentications); authentications = Collections.unmodifiableMap(authentications);
} }
/**
* Gets the JSON instance to do JSON serialization and deserialization.
*/
public JSON getJSON() {
return json;
}
public String getBasePath() { public String getBasePath() {
return basePath; return basePath;
} }
@ -237,7 +240,7 @@ public class ApiClient {
public ApiClient setDateFormat(DateFormat dateFormat) { public ApiClient setDateFormat(DateFormat dateFormat) {
this.dateFormat = dateFormat; this.dateFormat = dateFormat;
// also set the date format for model (de)serialization with Date properties // also set the date format for model (de)serialization with Date properties
this.json.setDateFormat((DateFormat) dateFormat.clone()); this.mapper.setDateFormat((DateFormat) dateFormat.clone());
return this; return this;
} }
@ -269,7 +272,7 @@ public class ApiClient {
return formatDate((Date) param); return formatDate((Date) param);
} else if (param instanceof Collection) { } else if (param instanceof Collection) {
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();
for(Object o : (Collection)param) { for(Object o : (Collection<?>)param) {
if(b.length() > 0) { if(b.length() > 0) {
b.append(","); b.append(",");
} }
@ -290,9 +293,9 @@ public class ApiClient {
// preconditions // preconditions
if (name == null || name.isEmpty() || value == null) return params; if (name == null || name.isEmpty() || value == null) return params;
Collection valueCollection = null; Collection<?> valueCollection = null;
if (value instanceof Collection) { if (value instanceof Collection<?>) {
valueCollection = (Collection) value; valueCollection = (Collection<?>) value;
} else { } else {
params.add(new Pair(name, parameterToString(value))); params.add(new Pair(name, parameterToString(value)));
return params; return params;
@ -337,6 +340,17 @@ public class ApiClient {
return params; return params;
} }
/**
* Check if the given MIME is a JSON MIME.
* JSON MIME examples:
* application/json
* application/json; charset=UTF8
* APPLICATION/JSON
*/
public boolean isJsonMime(String mime) {
return mime != null && mime.matches("(?i)application\\/json(;.*)?");
}
/** /**
* Select the Accept header's value from the given accepts array: * Select the Accept header's value from the given accepts array:
* if JSON exists in the given array, use it; * if JSON exists in the given array, use it;
@ -347,8 +361,14 @@ public class ApiClient {
* null will be returned (not to set the Accept header explicitly). * null will be returned (not to set the Accept header explicitly).
*/ */
public String selectHeaderAccept(String[] accepts) { public String selectHeaderAccept(String[] accepts) {
if (accepts.length == 0) return null; if (accepts.length == 0) {
if (StringUtil.containsIgnoreCase(accepts, "application/json")) return "application/json"; return null;
}
for (String accept : accepts) {
if (isJsonMime(accept)) {
return accept;
}
}
return StringUtil.join(accepts, ","); return StringUtil.join(accepts, ",");
} }
@ -362,8 +382,14 @@ public class ApiClient {
* JSON will be used. * JSON will be used.
*/ */
public String selectHeaderContentType(String[] contentTypes) { public String selectHeaderContentType(String[] contentTypes) {
if (contentTypes.length == 0) return "application/json"; if (contentTypes.length == 0) {
if (StringUtil.containsIgnoreCase(contentTypes, "application/json")) return "application/json"; return "application/json";
}
for (String contentType : contentTypes) {
if (isJsonMime(contentType)) {
return contentType;
}
}
return contentTypes[0]; return contentTypes[0];
} }
@ -382,49 +408,30 @@ public class ApiClient {
* Serialize the given Java object into string according the given * Serialize the given Java object into string according the given
* Content-Type (only JSON is supported for now). * Content-Type (only JSON is supported for now).
*/ */
public String serialize(Object obj, String contentType) throws ApiException { public Object serialize(Object obj, String contentType, Map<String, Object> formParams) throws ApiException {
if (contentType.startsWith("application/json")) { if (contentType.startsWith("multipart/form-data")) {
return json.serialize(obj); FormDataMultiPart mp = new FormDataMultiPart();
for (Entry<String, Object> param: formParams.entrySet()) {
if (param.getValue() instanceof File) {
File file = (File) param.getValue();
mp.bodyPart(new FileDataBodyPart(param.getKey(), file, MediaType.MULTIPART_FORM_DATA_TYPE));
} else {
mp.field(param.getKey(), parameterToString(param.getValue()), MediaType.MULTIPART_FORM_DATA_TYPE);
}
}
return mp;
} else if (contentType.startsWith("application/x-www-form-urlencoded")) {
return this.getXWWWFormUrlencodedParams(formParams);
} else { } else {
throw new ApiException(400, "can not serialize object into Content-Type: " + contentType); // We let Jersey attempt to serialize the body
return obj;
} }
} }
/** private ClientResponse getAPIResponse(String path, String method, List<Pair> queryParams, Object body, Map<String, String> headerParams, Map<String, Object> formParams, String accept, String contentType, String[] authNames) throws ApiException {
* Deserialize response body to Java object according to the Content-Type.
*/
public <T> T deserialize(ClientResponse response, TypeRef returnType) throws ApiException {
String contentType = null;
List<String> contentTypes = response.getHeaders().get("Content-Type");
if (contentTypes != null && !contentTypes.isEmpty())
contentType = contentTypes.get(0);
if (contentType == null)
throw new ApiException(500, "missing Content-Type in response");
String body; if (body != null && !formParams.isEmpty()){
if (response.hasEntity()) throw new ApiException(500, "Cannot have body and form params");
body = (String) response.getEntity(String.class);
else
body = "";
if (contentType.startsWith("application/json")) {
return json.deserialize(body, returnType);
} else if (returnType.getType().equals(String.class)) {
// Expecting string, return the raw response body.
return (T) body;
} else {
throw new ApiException(
500,
"Content type \"" + contentType + "\" is not supported for type: "
+ returnType.getType()
);
}
}
private ClientResponse getAPIResponse(String path, String method, List<Pair> queryParams, Object body, byte[] binaryBody, Map<String, String> headerParams, Map<String, Object> formParams, String accept, String contentType, String[] authNames) throws ApiException {
if (body != null && binaryBody != null){
throw new ApiException(500, "either body or binaryBody must be null");
} }
updateParamsForAuth(authNames, queryParams, headerParams); updateParamsForAuth(authNames, queryParams, headerParams);
@ -461,62 +468,16 @@ public class ApiClient {
} }
} }
String encodedFormParams = null;
if (contentType.startsWith("multipart/form-data")) {
FormDataMultiPart mp = new FormDataMultiPart();
for (Entry<String, Object> param: formParams.entrySet()) {
if (param.getValue() instanceof File) {
File file = (File) param.getValue();
mp.field(param.getKey(), file.getName());
mp.bodyPart(new FileDataBodyPart(param.getKey(), file, MediaType.MULTIPART_FORM_DATA_TYPE));
} else {
mp.field(param.getKey(), parameterToString(param.getValue()), MediaType.MULTIPART_FORM_DATA_TYPE);
}
}
body = mp;
} else if (contentType.startsWith("application/x-www-form-urlencoded")) {
encodedFormParams = this.getXWWWFormUrlencodedParams(formParams);
}
ClientResponse response = null; ClientResponse response = null;
if ("GET".equals(method)) { if ("GET".equals(method)) {
response = (ClientResponse) builder.get(ClientResponse.class); response = (ClientResponse) builder.get(ClientResponse.class);
} else if ("POST".equals(method)) { } else if ("POST".equals(method)) {
if (encodedFormParams != null) { response = builder.type(contentType).post(ClientResponse.class, serialize(body, contentType, formParams));
response = builder.type(contentType).post(ClientResponse.class, encodedFormParams);
} else if (body == null) {
if(binaryBody == null)
response = builder.post(ClientResponse.class, null);
else
response = builder.type(contentType).post(ClientResponse.class, binaryBody);
} else if (body instanceof FormDataMultiPart) {
response = builder.type(contentType).post(ClientResponse.class, body);
} else {
response = builder.type(contentType).post(ClientResponse.class, serialize(body, contentType));
}
} else if ("PUT".equals(method)) { } else if ("PUT".equals(method)) {
if (encodedFormParams != null) { response = builder.type(contentType).put(ClientResponse.class, serialize(body, contentType, formParams));
response = builder.type(contentType).put(ClientResponse.class, encodedFormParams);
} else if(body == null) {
if(binaryBody == null)
response = builder.put(ClientResponse.class, null);
else
response = builder.type(contentType).put(ClientResponse.class, binaryBody);
} else {
response = builder.type(contentType).put(ClientResponse.class, serialize(body, contentType));
}
} else if ("DELETE".equals(method)) { } else if ("DELETE".equals(method)) {
if (encodedFormParams != null) { response = builder.type(contentType).delete(ClientResponse.class, serialize(body, contentType, formParams));
response = builder.type(contentType).delete(ClientResponse.class, encodedFormParams);
} else if(body == null) {
if(binaryBody == null)
response = builder.delete(ClientResponse.class);
else
response = builder.type(contentType).delete(ClientResponse.class, binaryBody);
} else {
response = builder.type(contentType).delete(ClientResponse.class, serialize(body, contentType));
}
} else { } else {
throw new ApiException(500, "unknown method type " + method); throw new ApiException(500, "unknown method type " + method);
} }
@ -530,7 +491,6 @@ public class ApiClient {
* @param method The request method, one of "GET", "POST", "PUT", and "DELETE" * @param method The request method, one of "GET", "POST", "PUT", and "DELETE"
* @param queryParams The query parameters * @param queryParams The query parameters
* @param body The request body object - if it is not binary, otherwise null * @param body The request body object - if it is not binary, otherwise null
* @param binaryBody The request body object - if it is binary, otherwise null
* @param headerParams The header parameters * @param headerParams The header parameters
* @param formParams The form parameters * @param formParams The form parameters
* @param accept The request's Accept header * @param accept The request's Accept header
@ -538,9 +498,9 @@ public class ApiClient {
* @param authNames The authentications to apply * @param authNames The authentications to apply
* @return The response body in type of string * @return The response body in type of string
*/ */
public <T> T invokeAPI(String path, String method, List<Pair> queryParams, Object body, byte[] binaryBody, Map<String, String> headerParams, Map<String, Object> formParams, String accept, String contentType, String[] authNames, TypeRef returnType) throws ApiException { public <T> T invokeAPI(String path, String method, List<Pair> queryParams, Object body, Map<String, String> headerParams, Map<String, Object> formParams, String accept, String contentType, String[] authNames, GenericType<T> returnType) throws ApiException {
ClientResponse response = getAPIResponse(path, method, queryParams, body, binaryBody, headerParams, formParams, accept, contentType, authNames); ClientResponse response = getAPIResponse(path, method, queryParams, body, headerParams, formParams, accept, contentType, authNames);
statusCode = response.getStatusInfo().getStatusCode(); statusCode = response.getStatusInfo().getStatusCode();
responseHeaders = response.getHeaders(); responseHeaders = response.getHeaders();
@ -551,13 +511,13 @@ public class ApiClient {
if (returnType == null) if (returnType == null)
return null; return null;
else else
return deserialize(response, returnType); return response.getEntity(returnType);
} else { } else {
String message = "error"; String message = "error";
String respBody = null; String respBody = null;
if (response.hasEntity()) { if (response.hasEntity()) {
try { try {
respBody = String.valueOf(response.getEntity(String.class)); respBody = response.getEntity(String.class);
message = respBody; message = respBody;
} catch (RuntimeException e) { } catch (RuntimeException e) {
// e.printStackTrace(); // e.printStackTrace();
@ -570,58 +530,6 @@ public class ApiClient {
respBody); respBody);
} }
} }
/**
* Invoke API by sending HTTP request with the given options - return binary result
*
* @param path The sub-path of the HTTP URL
* @param method The request method, one of "GET", "POST", "PUT", and "DELETE"
* @param queryParams The query parameters
* @param body The request body object - if it is not binary, otherwise null
* @param binaryBody The request body object - if it is binary, otherwise null
* @param headerParams The header parameters
* @param formParams The form parameters
* @param accept The request's Accept header
* @param contentType The request's Content-Type header
* @param authNames The authentications to apply
* @return The response body in type of string
*/
public byte[] invokeBinaryAPI(String path, String method, List<Pair> queryParams, Object body, byte[] binaryBody, Map<String, String> headerParams, Map<String, Object> formParams, String accept, String contentType, String[]authNames) throws ApiException {
ClientResponse response = getAPIResponse(path, method, queryParams, body, binaryBody, headerParams, formParams, accept, contentType, authNames);
if(response.getStatusInfo() == ClientResponse.Status.NO_CONTENT) {
return null;
}
else if(response.getStatusInfo().getFamily() == Family.SUCCESSFUL) {
if(response.hasEntity()) {
DataInputStream stream = new DataInputStream(response.getEntityInputStream());
byte[] data = new byte[response.getLength()];
try {
stream.readFully(data);
} catch (IOException ex) {
throw new ApiException(500, "Error obtaining binary response data");
}
return data;
}
else {
return new byte[0];
}
}
else {
String message = "error";
if(response.hasEntity()) {
try{
message = String.valueOf(response.getEntity(String.class));
}
catch (RuntimeException e) {
// e.printStackTrace();
}
}
throw new ApiException(
response.getStatusInfo().getStatusCode(),
message);
}
}
/** /**
* Update query and header parameters based on authentication settings. * Update query and header parameters based on authentication settings.
@ -643,7 +551,6 @@ public class ApiClient {
StringBuilder formParamBuilder = new StringBuilder(); StringBuilder formParamBuilder = new StringBuilder();
for (Entry<String, Object> param : formParams.entrySet()) { for (Entry<String, Object> param : formParams.entrySet()) {
String keyStr = param.getKey();
String valueStr = parameterToString(param.getValue()); String valueStr = parameterToString(param.getValue());
try { try {
formParamBuilder.append(URLEncoder.encode(param.getKey(), "utf8")) formParamBuilder.append(URLEncoder.encode(param.getKey(), "utf8"))
@ -668,7 +575,11 @@ public class ApiClient {
*/ */
private Client getClient() { private Client getClient() {
if(!hostMap.containsKey(basePath)) { if(!hostMap.containsKey(basePath)) {
Client client = Client.create(); // Add the JSON serialization support to Jersey
JacksonJsonProvider jsonProvider = new JacksonJsonProvider(mapper);
DefaultClientConfig conf = new DefaultClientConfig();
conf.getSingletons().add(jsonProvider);
Client client = Client.create(conf);
if (debugging) if (debugging)
client.addFilter(new LoggingFilter()); client.addFilter(new LoggingFilter());
hostMap.put(basePath, client); hostMap.put(basePath, client);

View File

@ -1,64 +0,0 @@
package {{invokerPackage}};
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.datatype.joda.*;
import java.text.DateFormat;
import java.io.IOException;
{{>generatedAnnotation}}
public class JSON {
private ObjectMapper mapper;
public JSON() {
mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
mapper.registerModule(new JodaModule());
}
/**
* Set the date format for JSON (de)serialization with Date properties.
*/
public void setDateFormat(DateFormat dateFormat) {
mapper.setDateFormat(dateFormat);
}
/**
* Serialize the given Java object into JSON string.
*/
public String serialize(Object obj) throws ApiException {
try {
if (obj != null)
return mapper.writeValueAsString(obj);
else
return null;
} catch (Exception e) {
throw new ApiException(400, e.getMessage());
}
}
/**
* Deserialize the given JSON string to Java object.
*
* @param body The JSON string
* @param returnType The type to deserialize inot
* @return The deserialized Java object
*/
public <T> T deserialize(String body, TypeRef returnType) throws ApiException {
JavaType javaType = mapper.constructType(returnType.getType());
try {
return mapper.readValue(body, javaType);
} catch (IOException e) {
if (returnType.getType().equals(String.class))
return (T) body;
else
throw new ApiException(500, e.getMessage(), null, body);
}
}
}

View File

@ -1,26 +0,0 @@
package {{invokerPackage}};
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
{{>generatedAnnotation}}
public class TypeRef<T> {
private final Type type;
public TypeRef() {
this.type = getGenericType(getClass());
}
private static Type getGenericType(Class<?> klass) {
Type superclass = klass.getGenericSuperclass();
if (superclass instanceof Class) {
throw new RuntimeException("No type parameter provided");
}
ParameterizedType parameterized = (ParameterizedType) superclass;
return parameterized.getActualTypeArguments()[0];
}
public Type getType() {
return type;
}
}

View File

@ -1,10 +1,11 @@
package {{package}}; package {{package}};
import com.sun.jersey.api.client.GenericType;
import {{invokerPackage}}.ApiException; import {{invokerPackage}}.ApiException;
import {{invokerPackage}}.ApiClient; import {{invokerPackage}}.ApiClient;
import {{invokerPackage}}.Configuration; import {{invokerPackage}}.Configuration;
import {{invokerPackage}}.Pair; import {{invokerPackage}}.Pair;
import {{invokerPackage}}.TypeRef;
{{#imports}}import {{import}}; {{#imports}}import {{import}};
{{/imports}} {{/imports}}
@ -41,13 +42,12 @@ public class {{classname}} {
{{#allParams}} * @param {{paramName}} {{description}} {{#allParams}} * @param {{paramName}} {{description}}
{{/allParams}} * @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{/allParams}} * @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}
*/ */
public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}} ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException {
Object {{localVariablePrefix}}postBody = {{#bodyParam}}{{^isBinary}}{{paramName}}{{/isBinary}}{{#isBinary}}null{{/isBinary}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; Object {{localVariablePrefix}}postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}};
byte[] {{localVariablePrefix}}postBinaryBody = {{#bodyParam}}{{#isBinary}}{{paramName}}{{/isBinary}}{{^isBinary}}null{{/isBinary}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}};
{{#allParams}}{{#required}} {{#allParams}}{{#required}}
// verify the required parameter '{{paramName}}' is set // verify the required parameter '{{paramName}}' is set
if ({{paramName}} == null) { if ({{paramName}} == null) {
throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{nickname}}"); throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}");
} }
{{/required}}{{/allParams}} {{/required}}{{/allParams}}
// create path and map variables // create path and map variables
@ -83,22 +83,12 @@ public class {{classname}} {
String[] {{localVariablePrefix}}authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; String[] {{localVariablePrefix}}authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} };
{{#isResponseBinary}}
byte[] {{localVariablePrefix}}response = null;
{{localVariablePrefix}}response = {{localVariablePrefix}}apiClient.invokeBinaryAPI({{localVariablePrefix}}path, "{{httpMethod}}", {{localVariablePrefix}}queryParams,{{localVariablePrefix}} postBody, {{localVariablePrefix}}postBinaryBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames);
return {{localVariablePrefix}}response;
{{/isResponseBinary}}
{{^isResponseBinary}}
{{#returnType}} {{#returnType}}
TypeRef {{localVariablePrefix}}returnType = new TypeRef<{{{returnType}}}>() {}; GenericType<{{{returnType}}}> {{localVariablePrefix}}returnType = new GenericType<{{{returnType}}}>() {};
return {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}path, "{{httpMethod}}", {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}postBinaryBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames, {{localVariablePrefix}}returnType); return {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}path, "{{httpMethod}}", {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames, {{localVariablePrefix}}returnType);
{{/returnType}}{{^returnType}} {{/returnType}}{{^returnType}}
{{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}path, "{{httpMethod}}", {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}postBinaryBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames, null); {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}path, "{{httpMethod}}", {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames, null);
{{/returnType}} {{/returnType}}
{{/isResponseBinary}}
} }
{{/operation}} {{/operation}}
} }

View File

@ -1,14 +1,16 @@
public enum {{datatypeWithEnum}} {
{{#allowableValues}}{{#enumVars}}{{name}}("{{value}}"){{^-last}}, public enum {{{datatypeWithEnum}}} {
{{#allowableValues}}{{#enumVars}}{{{name}}}("{{{value}}}"){{^-last}},
{{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}} {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}}
private String value; private String value;
{{datatypeWithEnum}}(String value) { {{{datatypeWithEnum}}}(String value) {
this.value = value; this.value = value;
} }
@Override @Override
@JsonValue
public String toString() { public String toString() {
return value; return value;
} }

View File

@ -0,0 +1,3 @@
public enum {{classname}} {
{{#allowableValues}}{{.}}{{^-last}}, {{/-last}}{{/allowableValues}}
}

View File

@ -0,0 +1,86 @@
package {{invokerPackage}};
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import feign.Feign;
import feign.jackson.JacksonDecoder;
import feign.jackson.JacksonEncoder;
import feign.slf4j.Slf4jLogger;
{{>generatedAnnotation}}
public class ApiClient {
public interface Api {}
private ObjectMapper objectMapper;
private String basePath = "{{basePath}}";
public ApiClient() {
objectMapper = createObjectMapper();
}
public String getBasePath() {
return basePath;
}
public ApiClient setBasePath(String basePath) {
this.basePath = basePath;
return this;
}
private ObjectMapper createObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
return objectMapper;
}
/**
* Creates a feign client for given API interface.
*
* Usage:
* ApiClient apiClient = new ApiClient();
* apiClient.setBasePath("http://localhost:8080");
* XYZApi api = apiClient.buildClient(XYZApi.class);
* XYZResponse response = api.someMethod(...);
*/
public <T extends Api> T buildClient(Class<T> clientClass) {
return Feign.builder()
.encoder(new FormAwareEncoder(new JacksonEncoder(objectMapper)))
.decoder(new JacksonDecoder(objectMapper))
// enable for basic auth:
// .requestInterceptor(new feign.auth.BasicAuthRequestInterceptor(username, password))
.logger(new Slf4jLogger())
.target(clientClass, basePath);
}
/**
* Select the Accept header's value from the given accepts array:
* if JSON exists in the given array, use it;
* otherwise use all of them (joining into a string)
*
* @param accepts The accepts array to select from
* @return The Accept header to use. If the given array is empty,
* null will be returned (not to set the Accept header explicitly).
*/
public String selectHeaderAccept(String[] accepts) {
if (accepts.length == 0) return null;
if (StringUtil.containsIgnoreCase(accepts, "application/json")) return "application/json";
return StringUtil.join(accepts, ",");
}
/**
* Select the Content-Type header's value from the given array:
* if JSON exists in the given array, use it;
* otherwise use the first one of the array.
*
* @param contentTypes The Content-Type array to select from
* @return The Content-Type header to use. If the given array is empty,
* JSON will be used.
*/
public String selectHeaderContentType(String[] contentTypes) {
if (contentTypes.length == 0) return "application/json";
if (StringUtil.containsIgnoreCase(contentTypes, "application/json")) return "application/json";
return contentTypes[0];
}
}

View File

@ -0,0 +1,197 @@
package {{invokerPackage}};
import java.io.*;
import java.lang.reflect.Type;
import java.net.URLEncoder;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.util.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import feign.codec.EncodeException;
import feign.codec.Encoder;
import feign.RequestTemplate;
{{>generatedAnnotation}}
public class FormAwareEncoder implements Encoder {
public static final String UTF_8 = "utf-8";
private static final String LINE_FEED = "\r\n";
private static final String TWO_DASH = "--";
private static final String BOUNDARY = "----------------314159265358979323846";
private byte[] lineFeedBytes;
private byte[] boundaryBytes;
private byte[] twoDashBytes;
private byte[] atBytes;
private byte[] eqBytes;
private final Encoder delegate;
private final DateFormat dateFormat;
public FormAwareEncoder(Encoder delegate) {
this.delegate = delegate;
// Use RFC3339 format for date and datetime.
// See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14
this.dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
// Use UTC as the default time zone.
this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
try {
this.lineFeedBytes = LINE_FEED.getBytes(UTF_8);
this.boundaryBytes = BOUNDARY.getBytes(UTF_8);
this.twoDashBytes = TWO_DASH.getBytes(UTF_8);
this.atBytes = "&".getBytes(UTF_8);
this.eqBytes = "=".getBytes(UTF_8);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException {
if (object instanceof Map) {
try {
encodeFormParams(template, (Map<String, Object>) object);
} catch (IOException e) {
throw new EncodeException("Failed to create request", e);
}
} else {
delegate.encode(object, bodyType, template);
}
}
private void encodeFormParams(RequestTemplate template, Map<String, Object> formParams) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
boolean isMultiPart = isMultiPart(formParams);
boolean isFirstField = true;
for (Map.Entry<String, Object> param : formParams.entrySet()) {
String keyStr = param.getKey();
if (param.getValue() instanceof File) {
addFilePart(baos, keyStr, (File) param.getValue());
} else {
String valueStr = parameterToString(param.getValue());
if (isMultiPart) {
addMultiPartFormField(baos, keyStr, valueStr);
} else {
addEncodedFormField(baos, keyStr, valueStr, isFirstField);
isFirstField = false;
}
}
}
if (isMultiPart) {
baos.write(lineFeedBytes);
baos.write(twoDashBytes);
baos.write(boundaryBytes);
baos.write(twoDashBytes);
baos.write(lineFeedBytes);
}
String contentType = isMultiPart ? "multipart/form-data; boundary=" + BOUNDARY : "application/x-www-form-urlencoded";
template.header("Content-type");
template.header("Content-type", contentType);
template.header("MIME-Version", "1.0");
template.body(baos.toByteArray(), Charset.forName(UTF_8));
}
/*
* Currently only supports text files
*/
private void addFilePart(ByteArrayOutputStream baos, String fieldName, File uploadFile) throws IOException {
String fileName = uploadFile.getName();
baos.write(twoDashBytes);
baos.write(boundaryBytes);
baos.write(lineFeedBytes);
String contentDisposition = "Content-Disposition: form-data; name=\"" + fieldName
+ "\"; filename=\"" + fileName + "\"";
baos.write(contentDisposition.getBytes(UTF_8));
baos.write(lineFeedBytes);
String contentType = "Content-Type: " + URLConnection.guessContentTypeFromName(fileName);
baos.write(contentType.getBytes(UTF_8));
baos.write(lineFeedBytes);
baos.write(lineFeedBytes);
BufferedReader reader = new BufferedReader(new FileReader(uploadFile));
InputStream input = new FileInputStream(uploadFile);
byte[] bytes = new byte[4096];
int len = bytes.length;
while ((len = input.read(bytes)) != -1) {
baos.write(bytes, 0, len);
baos.write(lineFeedBytes);
}
baos.write(lineFeedBytes);
}
private void addEncodedFormField(ByteArrayOutputStream baos, String name, String value, boolean isFirstField) throws IOException {
if (!isFirstField) {
baos.write(atBytes);
}
String encodedName = URLEncoder.encode(name, UTF_8);
String encodedValue = URLEncoder.encode(value, UTF_8);
baos.write(encodedName.getBytes(UTF_8));
baos.write("=".getBytes(UTF_8));
baos.write(encodedValue.getBytes(UTF_8));
}
private void addMultiPartFormField(ByteArrayOutputStream baos, String name, String value) throws IOException {
baos.write(twoDashBytes);
baos.write(boundaryBytes);
baos.write(lineFeedBytes);
String contentDisposition = "Content-Disposition: form-data; name=\"" + name + "\"";
String contentType = "Content-Type: text/plain; charset=utf-8";
baos.write(contentDisposition.getBytes(UTF_8));
baos.write(lineFeedBytes);
baos.write(contentType.getBytes(UTF_8));
baos.write(lineFeedBytes);
baos.write(lineFeedBytes);
baos.write(value.getBytes(UTF_8));
baos.write(lineFeedBytes);
}
private boolean isMultiPart(Map<String, Object> formParams) {
boolean isMultiPart = false;
for (Map.Entry<String, Object> entry : formParams.entrySet()) {
if (entry.getValue() instanceof File) {
isMultiPart = true;
break;
}
}
return isMultiPart;
}
/**
* Format the given parameter object into string.
*/
public String parameterToString(Object param) {
if (param == null) {
return "";
} else if (param instanceof Date) {
return formatDate((Date) param);
} else if (param instanceof Collection) {
StringBuilder b = new StringBuilder();
for(Object o : (Collection)param) {
if(b.length() > 0) {
b.append(",");
}
b.append(String.valueOf(o));
}
return b.toString();
} else {
return String.valueOf(param);
}
}
/**
* Format the given Date object into string.
*/
public String formatDate(Date date) {
return dateFormat.format(date);
}
}

View File

@ -0,0 +1,32 @@
package {{package}};
import {{invokerPackage}}.ApiClient;
{{#imports}}import {{import}};
{{/imports}}
{{^fullJavaUtil}}import java.util.*;
{{/fullJavaUtil}}
import feign.*;
{{>generatedAnnotation}}
public interface {{classname}} extends ApiClient.Api {
{{#operations}}{{#operation}}
/**
* {{summary}}
* {{notes}}
{{#allParams}} * @param {{paramName}} {{description}}
{{/allParams}} * @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}
*/
@RequestLine("{{httpMethod}} {{{path}}}{{#hasQueryParams}}?{{/hasQueryParams}}{{#queryParams}}{{paramName}}={{=<% %>=}}{<%paramName%>}<%={{ }}=%>{{#hasMore}}&{{/hasMore}}{{/queryParams}}")
@Headers({
"Content-type: {{vendorExtensions.x-contentType}}",
"Accepts: {{vendorExtensions.x-accepts}}",{{#headerParams}}
"{{paramName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{#hasMore}},
{{/hasMore}}{{/headerParams}}
})
{{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}@Param("{{paramName}}") {{/isBodyParam}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
{{/operation}}
{{/operations}}
}

View File

@ -0,0 +1,113 @@
group = '{{groupId}}'
version = '{{artifactVersion}}'
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.2'
classpath 'com.github.dcendents:android-maven-plugin:1.2'
}
}
repositories {
jcenter()
}
if(hasProperty('target') && target == 'android') {
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
android {
compileSdkVersion 22
buildToolsVersion '22.0.0'
defaultConfig {
minSdkVersion 14
targetSdkVersion 22
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
// Rename the aar correctly
libraryVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.aar')) {
def fileName = "${project.name}-${variant.baseName}-${version}.aar"
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
dependencies {
provided 'javax.annotation:jsr250-api:1.0'
}
}
afterEvaluate {
android.libraryVariants.all { variant ->
def task = project.tasks.create "jar${variant.name.capitalize()}", Jar
task.description = "Create jar artifact for ${variant.name}"
task.dependsOn variant.javaCompile
task.from variant.javaCompile.destinationDir
task.destinationDir = project.file("${project.buildDir}/outputs/jar")
task.archiveName = "${project.name}-${variant.baseName}-${version}.jar"
artifacts.add('archives', task);
}
}
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
artifacts {
archives sourcesJar
}
} else {
apply plugin: 'java'
apply plugin: 'maven'
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
install {
repositories.mavenInstaller {
pom.artifactId = '{{artifactId}}'
}
}
task execute(type:JavaExec) {
main = System.getProperty('mainClass')
classpath = sourceSets.main.runtimeClasspath
}
}
ext {
swagger_annotations_version = "1.5.0"
jackson_version = "2.6.3"
feign_version = "8.1.1"
jodatime_version = "2.5"
junit_version = "4.12"
}
dependencies {
compile "io.swagger:swagger-annotations:$swagger_annotations_version"
compile "com.netflix.feign:feign-core:$feign_version"
compile "com.netflix.feign:feign-jackson:$feign_version"
compile "com.netflix.feign:feign-slf4j:$feign_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_version"
compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:2.1.5"
compile "joda-time:joda-time:$jodatime_version"
compile "com.brsanthu:migbase64:2.2"
testCompile "junit:junit:$junit_version"
}

View File

@ -0,0 +1,183 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>{{groupId}}</groupId>
<artifactId>{{artifactId}}</artifactId>
<packaging>jar</packaging>
<name>{{artifactId}}</name>
<version>{{artifactVersion}}</version>
<scm>
<connection>scm:git:git@github.com:swagger-api/swagger-mustache.git</connection>
<developerConnection>scm:git:git@github.com:swagger-api/swagger-codegen.git</developerConnection>
<url>https://github.com/swagger-api/swagger-codegen</url>
</scm>
<prerequisites>
<maven>2.2.0</maven>
</prerequisites>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12</version>
<configuration>
<systemProperties>
<property>
<name>loggerPath</name>
<value>conf/log4j.properties</value>
</property>
</systemProperties>
<argLine>-Xms512m -Xmx1500m</argLine>
<parallel>methods</parallel>
<forkMode>pertest</forkMode>
</configuration>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!-- attach test jar -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<goals>
<goal>jar</goal>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
<configuration>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add_sources</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/main/java</source>
</sources>
</configuration>
</execution>
<execution>
<id>add_test_sources</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/test/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger-annotations-version}</version>
</dependency>
<!-- HTTP client: Netflix Feign -->
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-core</artifactId>
<version>${feign-version}</version>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-jackson</artifactId>
<version>${feign-version}</version>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-slf4j</artifactId>
<version>${feign-version}</version>
</dependency>
<!-- JSON processing: jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
<version>2.1.5</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>${jodatime-version}</version>
</dependency>
<!-- Base64 encoding that works in both JVM and Android -->
<dependency>
<groupId>com.brsanthu</groupId>
<artifactId>migbase64</artifactId>
<version>2.2</version>
</dependency>
<!-- test dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit-version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<swagger-annotations-version>1.5.0</swagger-annotations-version>
<feign-version>8.1.1</feign-version>
<jackson-version>2.6.3</jackson-version>
<jodatime-version>2.5</jodatime-version>
<junit-version>4.12</junit-version>
<maven-plugin-version>1.0.0</maven-plugin-version>
</properties>
</project>

View File

@ -6,6 +6,7 @@ import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation; import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget; import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Form; import javax.ws.rs.core.Form;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.Response.Status;
@ -13,10 +14,9 @@ import javax.ws.rs.core.Response.Status;
import org.glassfish.jersey.client.ClientConfig; import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.filter.LoggingFilter; import org.glassfish.jersey.filter.LoggingFilter;
import org.glassfish.jersey.media.multipart.FormDataBodyPart; import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.glassfish.jersey.media.multipart.FormDataMultiPart; import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.MultiPart; import org.glassfish.jersey.media.multipart.MultiPart;
import org.glassfish.jersey.media.multipart.MultiPartFeature; import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.media.multipart.file.FileDataBodyPart;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -30,13 +30,11 @@ import java.util.TimeZone;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.io.IOException;
import java.io.File; import java.io.File;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.text.ParseException;
import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.Authentication;
import {{invokerPackage}}.auth.HttpBasicAuth; import {{invokerPackage}}.auth.HttpBasicAuth;
@ -345,6 +343,17 @@ public class ApiClient {
return params; return params;
} }
/**
* Check if the given MIME is a JSON MIME.
* JSON MIME examples:
* application/json
* application/json; charset=UTF8
* APPLICATION/JSON
*/
public boolean isJsonMime(String mime) {
return mime != null && mime.matches("(?i)application\\/json(;.*)?");
}
/** /**
* Select the Accept header's value from the given accepts array: * Select the Accept header's value from the given accepts array:
* if JSON exists in the given array, use it; * if JSON exists in the given array, use it;
@ -355,8 +364,14 @@ public class ApiClient {
* null will be returned (not to set the Accept header explicitly). * null will be returned (not to set the Accept header explicitly).
*/ */
public String selectHeaderAccept(String[] accepts) { public String selectHeaderAccept(String[] accepts) {
if (accepts.length == 0) return null; if (accepts.length == 0) {
if (StringUtil.containsIgnoreCase(accepts, "application/json")) return "application/json"; return null;
}
for (String accept : accepts) {
if (isJsonMime(accept)) {
return accept;
}
}
return StringUtil.join(accepts, ","); return StringUtil.join(accepts, ",");
} }
@ -370,8 +385,14 @@ public class ApiClient {
* JSON will be used. * JSON will be used.
*/ */
public String selectHeaderContentType(String[] contentTypes) { public String selectHeaderContentType(String[] contentTypes) {
if (contentTypes.length == 0) return "application/json"; if (contentTypes.length == 0) {
if (StringUtil.containsIgnoreCase(contentTypes, "application/json")) return "application/json"; return "application/json";
}
for (String contentType : contentTypes) {
if (isJsonMime(contentType)) {
return contentType;
}
}
return contentTypes[0]; return contentTypes[0];
} }
@ -390,18 +411,39 @@ public class ApiClient {
* Serialize the given Java object into string entity according the given * Serialize the given Java object into string entity according the given
* Content-Type (only JSON is supported for now). * Content-Type (only JSON is supported for now).
*/ */
public Entity<String> serialize(Object obj, String contentType) throws ApiException { public Entity<?> serialize(Object obj, Map<String, Object> formParams, String contentType) throws ApiException {
if (contentType.startsWith("application/json")) { Entity<?> entity = null;
return Entity.json(json.serialize(obj)); if (contentType.startsWith("multipart/form-data")) {
MultiPart multiPart = new MultiPart();
for (Entry<String, Object> param: formParams.entrySet()) {
if (param.getValue() instanceof File) {
File file = (File) param.getValue();
FormDataContentDisposition contentDisp = FormDataContentDisposition.name(param.getKey())
.fileName(file.getName()).size(file.length()).build();
multiPart.bodyPart(new FormDataBodyPart(contentDisp, file, MediaType.APPLICATION_OCTET_STREAM_TYPE));
} else {
FormDataContentDisposition contentDisp = FormDataContentDisposition.name(param.getKey()).build();
multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(param.getValue())));
}
}
entity = Entity.entity(multiPart, MediaType.MULTIPART_FORM_DATA_TYPE);
} else if (contentType.startsWith("application/x-www-form-urlencoded")) {
Form form = new Form();
for (Entry<String, Object> param: formParams.entrySet()) {
form.param(param.getKey(), parameterToString(param.getValue()));
}
entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE);
} else { } else {
throw new ApiException(400, "can not serialize object into Content-Type: " + contentType); // We let jersey handle the serialization
entity = Entity.entity(obj, contentType);
} }
return entity;
} }
/** /**
* Deserialize response body to Java object according to the Content-Type. * Deserialize response body to Java object according to the Content-Type.
*/ */
public <T> T deserialize(Response response, TypeRef returnType) throws ApiException { public <T> T deserialize(Response response, GenericType<T> returnType) throws ApiException {
String contentType = null; String contentType = null;
List<Object> contentTypes = response.getHeaders().get("Content-Type"); List<Object> contentTypes = response.getHeaders().get("Content-Type");
if (contentTypes != null && !contentTypes.isEmpty()) if (contentTypes != null && !contentTypes.isEmpty())
@ -409,24 +451,7 @@ public class ApiClient {
if (contentType == null) if (contentType == null)
throw new ApiException(500, "missing Content-Type in response"); throw new ApiException(500, "missing Content-Type in response");
String body; return response.readEntity(returnType);
if (response.hasEntity())
body = (String) response.readEntity(String.class);
else
body = "";
if (contentType.startsWith("application/json")) {
return json.deserialize(body, returnType);
} else if (returnType.getType().equals(String.class)) {
// Expecting string, return the raw response body.
return (T) body;
} else {
throw new ApiException(
500,
"Content type \"" + contentType + "\" is not supported for type: "
+ returnType.getType()
);
}
} }
/** /**
@ -444,7 +469,7 @@ public class ApiClient {
* @param returnType The return type into which to deserialize the response * @param returnType The return type into which to deserialize the response
* @return The response body in type of string * @return The response body in type of string
*/ */
public <T> T invokeAPI(String path, String method, List<Pair> queryParams, Object body, Map<String, String> headerParams, Map<String, Object> formParams, String accept, String contentType, String[] authNames, TypeRef returnType) throws ApiException { public <T> T invokeAPI(String path, String method, List<Pair> queryParams, Object body, Map<String, String> headerParams, Map<String, Object> formParams, String accept, String contentType, String[] authNames, GenericType<T> returnType) throws ApiException {
updateParamsForAuth(authNames, queryParams, headerParams); updateParamsForAuth(authNames, queryParams, headerParams);
WebTarget target = client.target(this.basePath).path(path); WebTarget target = client.target(this.basePath).path(path);
@ -475,54 +500,16 @@ public class ApiClient {
} }
} }
Entity<?> formEntity = null; Entity<?> entity = serialize(body, formParams, contentType);
if (contentType.startsWith("multipart/form-data")) {
MultiPart multipart = new MultiPart();
for (Entry<String, Object> param: formParams.entrySet()) {
if (param.getValue() instanceof File) {
File file = (File) param.getValue();
FormDataMultiPart mp = new FormDataMultiPart();
mp.bodyPart(new FormDataBodyPart(param.getKey(), file.getName()));
multipart.bodyPart(mp, MediaType.MULTIPART_FORM_DATA_TYPE);
multipart.bodyPart(new FileDataBodyPart(param.getKey(), file, MediaType.APPLICATION_OCTET_STREAM_TYPE));
} else {
FormDataMultiPart mp = new FormDataMultiPart();
mp.bodyPart(new FormDataBodyPart(param.getKey(), parameterToString(param.getValue())));
multipart.bodyPart(mp, MediaType.MULTIPART_FORM_DATA_TYPE);
}
}
formEntity = Entity.entity(multipart, MediaType.MULTIPART_FORM_DATA_TYPE);
} else if (contentType.startsWith("application/x-www-form-urlencoded")) {
Form form = new Form();
for (Entry<String, Object> param: formParams.entrySet()) {
form.param(param.getKey(), parameterToString(param.getValue()));
}
formEntity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE);
}
Response response = null; Response response = null;
if ("GET".equals(method)) { if ("GET".equals(method)) {
response = invocationBuilder.get(); response = invocationBuilder.get();
} else if ("POST".equals(method)) { } else if ("POST".equals(method)) {
if (formEntity != null) { response = invocationBuilder.post(entity);
response = invocationBuilder.post(formEntity);
} else if (body == null) {
response = invocationBuilder.post(null);
} else {
response = invocationBuilder.post(serialize(body, contentType));
}
} else if ("PUT".equals(method)) { } else if ("PUT".equals(method)) {
if (formEntity != null) { response = invocationBuilder.put(entity);
response = invocationBuilder.put(formEntity);
} else if (body == null) {
response = invocationBuilder.put(null);
} else {
response = invocationBuilder.put(serialize(body, contentType));
}
} else if ("DELETE".equals(method)) { } else if ("DELETE".equals(method)) {
response = invocationBuilder.delete(); response = invocationBuilder.delete();
} else { } else {
@ -561,6 +548,8 @@ public class ApiClient {
private void buildClient() { private void buildClient() {
final ClientConfig clientConfig = new ClientConfig(); final ClientConfig clientConfig = new ClientConfig();
clientConfig.register(MultiPartFeature.class); clientConfig.register(MultiPartFeature.class);
clientConfig.register(json);
clientConfig.register(org.glassfish.jersey.jackson.JacksonFeature.class);
if (debugging) { if (debugging) {
clientConfig.register(LoggingFilter.class); clientConfig.register(LoggingFilter.class);
} }

View File

@ -0,0 +1,36 @@
package {{invokerPackage}};
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.datatype.joda.*;
import java.text.DateFormat;
import javax.ws.rs.ext.ContextResolver;
{{>generatedAnnotation}}
public class JSON implements ContextResolver<ObjectMapper> {
private ObjectMapper mapper;
public JSON() {
mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
mapper.registerModule(new JodaModule());
}
/**
* Set the date format for JSON (de)serialization with Date properties.
*/
public void setDateFormat(DateFormat dateFormat) {
mapper.setDateFormat(dateFormat);
}
@Override
public ObjectMapper getContext(Class<?> type) {
return mapper;
}
}

View File

@ -4,7 +4,8 @@ import {{invokerPackage}}.ApiException;
import {{invokerPackage}}.ApiClient; import {{invokerPackage}}.ApiClient;
import {{invokerPackage}}.Configuration; import {{invokerPackage}}.Configuration;
import {{invokerPackage}}.Pair; import {{invokerPackage}}.Pair;
import {{invokerPackage}}.TypeRef;
import javax.ws.rs.core.GenericType;
{{#imports}}import {{import}}; {{#imports}}import {{import}};
{{/imports}} {{/imports}}
@ -41,12 +42,12 @@ public class {{classname}} {
{{#allParams}} * @param {{paramName}} {{description}} {{#allParams}} * @param {{paramName}} {{description}}
{{/allParams}} * @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{/allParams}} * @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}
*/ */
public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}} ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException {
Object {{localVariablePrefix}}postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; Object {{localVariablePrefix}}postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}};
{{#allParams}}{{#required}} {{#allParams}}{{#required}}
// verify the required parameter '{{paramName}}' is set // verify the required parameter '{{paramName}}' is set
if ({{paramName}} == null) { if ({{paramName}} == null) {
throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{nickname}}"); throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}");
} }
{{/required}}{{/allParams}} {{/required}}{{/allParams}}
// create path and map variables // create path and map variables
@ -83,7 +84,7 @@ public class {{classname}} {
String[] {{localVariablePrefix}}authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; String[] {{localVariablePrefix}}authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} };
{{#returnType}} {{#returnType}}
TypeRef {{localVariablePrefix}}returnType = new TypeRef<{{{returnType}}}>() {}; GenericType<{{{returnType}}}> {{localVariablePrefix}}returnType = new GenericType<{{{returnType}}}>() {};
return {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}path, "{{httpMethod}}", {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames, {{localVariablePrefix}}returnType); return {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}path, "{{httpMethod}}", {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames, {{localVariablePrefix}}returnType);
{{/returnType}}{{^returnType}} {{/returnType}}{{^returnType}}
{{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}path, "{{httpMethod}}", {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames, null); {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}path, "{{httpMethod}}", {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames, null);

View File

@ -124,7 +124,12 @@
<artifactId>jersey-media-multipart</artifactId> <artifactId>jersey-media-multipart</artifactId>
<version>${jersey-version}</version> <version>${jersey-version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.22.1</version>
</dependency>
<!-- JSON processing: jackson --> <!-- JSON processing: jackson -->
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>

View File

@ -28,4 +28,22 @@ public interface ApiCallback<T> {
* @param responseHeaders Headers of the response * @param responseHeaders Headers of the response
*/ */
void onSuccess(T result, int statusCode, Map<String, List<String>> responseHeaders); void onSuccess(T result, int statusCode, Map<String, List<String>> responseHeaders);
/**
* This is called when the API upload processing.
*
* @param bytesWritten bytes Written
* @param contentLength content length of request body
* @param done write end
*/
void onUploadProgress(long bytesWritten, long contentLength, boolean done);
/**
* This is called when the API downlond processing.
*
* @param bytesRead bytes Read
* @param contentLength content lenngth of the response
* @param done Read end
*/
void onDownloadProgress(long bytesRead, long contentLength, boolean done);
} }

View File

@ -104,9 +104,6 @@ public class ApiClient {
private Map<String, Authentication> authentications; private Map<String, Authentication> authentications;
private int statusCode;
private Map<String, List<String>> responseHeaders;
private DateFormat dateFormat; private DateFormat dateFormat;
private DateFormat datetimeFormat; private DateFormat datetimeFormat;
private boolean lenientDatetimeFormat; private boolean lenientDatetimeFormat;
@ -177,24 +174,6 @@ public class ApiClient {
return this; return this;
} }
/**
* Gets the status code of the previous request.
* NOTE: Status code of last async response is not recorded here, it is
* passed to the callback methods instead.
*/
public int getStatusCode() {
return statusCode;
}
/**
* Gets the response headers of the previous request.
* NOTE: Headers of last async response is not recorded here, it is passed
* to callback methods instead.
*/
public Map<String, List<String>> getResponseHeaders() {
return responseHeaders;
}
public boolean isVerifyingSsl() { public boolean isVerifyingSsl() {
return verifyingSsl; return verifyingSsl;
} }
@ -570,6 +549,17 @@ public class ApiClient {
return params; return params;
} }
/**
* Check if the given MIME is a JSON MIME.
* JSON MIME examples:
* application/json
* application/json; charset=UTF8
* APPLICATION/JSON
*/
public boolean isJsonMime(String mime) {
return mime != null && mime.matches("(?i)application\\/json(;.*)?");
}
/** /**
* Select the Accept header's value from the given accepts array: * Select the Accept header's value from the given accepts array:
* if JSON exists in the given array, use it; * if JSON exists in the given array, use it;
@ -580,8 +570,14 @@ public class ApiClient {
* null will be returned (not to set the Accept header explicitly). * null will be returned (not to set the Accept header explicitly).
*/ */
public String selectHeaderAccept(String[] accepts) { public String selectHeaderAccept(String[] accepts) {
if (accepts.length == 0) return null; if (accepts.length == 0) {
if (StringUtil.containsIgnoreCase(accepts, "application/json")) return "application/json"; return null;
}
for (String accept : accepts) {
if (isJsonMime(accept)) {
return accept;
}
}
return StringUtil.join(accepts, ","); return StringUtil.join(accepts, ",");
} }
@ -595,8 +591,14 @@ public class ApiClient {
* JSON will be used. * JSON will be used.
*/ */
public String selectHeaderContentType(String[] contentTypes) { public String selectHeaderContentType(String[] contentTypes) {
if (contentTypes.length == 0) return "application/json"; if (contentTypes.length == 0) {
if (StringUtil.containsIgnoreCase(contentTypes, "application/json")) return "application/json"; return "application/json";
}
for (String contentType : contentTypes) {
if (isJsonMime(contentType)) {
return contentType;
}
}
return contentTypes[0]; return contentTypes[0];
} }
@ -618,6 +620,8 @@ public class ApiClient {
* @param response HTTP response * @param response HTTP response
* @param returnType The type of the Java object * @param returnType The type of the Java object
* @return The deserialized Java object * @return The deserialized Java object
* @throws ApiException If fail to deserialize response body, i.e. cannot read response body
* or the Content-Type of the response is not supported.
*/ */
public <T> T deserialize(Response response, Type returnType) throws ApiException { public <T> T deserialize(Response response, Type returnType) throws ApiException {
if (response == null || returnType == null) if (response == null || returnType == null)
@ -645,7 +649,7 @@ public class ApiClient {
// ensuring a default content type // ensuring a default content type
contentType = "application/json"; contentType = "application/json";
} }
if (contentType.startsWith("application/json")) { if (isJsonMime(contentType)) {
return json.deserialize(respBody, returnType); return json.deserialize(respBody, returnType);
} else if (returnType.equals(String.class)) { } else if (returnType.equals(String.class)) {
// Expecting string, return the raw response body. // Expecting string, return the raw response body.
@ -666,9 +670,10 @@ public class ApiClient {
* @param obj The Java object * @param obj The Java object
* @param contentType The request Content-Type * @param contentType The request Content-Type
* @return The serialized string * @return The serialized string
* @throws ApiException If fail to serialize the given object
*/ */
public String serialize(Object obj, String contentType) throws ApiException { public String serialize(Object obj, String contentType) throws ApiException {
if (contentType.startsWith("application/json")) { if (isJsonMime(contentType)) {
if (obj != null) if (obj != null)
return json.serialize(obj); return json.serialize(obj);
else else
@ -680,6 +685,7 @@ public class ApiClient {
/** /**
* Download file from the given response. * Download file from the given response.
* @throws ApiException If fail to read file content from response and write to disk
*/ */
public File downloadFileFromResponse(Response response) throws ApiException { public File downloadFileFromResponse(Response response) throws ApiException {
try { try {
@ -731,7 +737,7 @@ public class ApiClient {
/** /**
* @see #execute(Call, Type) * @see #execute(Call, Type)
*/ */
public <T> T execute(Call call) throws ApiException { public <T> ApiResponse<T> execute(Call call) throws ApiException {
return execute(call, null); return execute(call, null);
} }
@ -740,14 +746,16 @@ public class ApiClient {
* *
* @param returnType The return type used to deserialize HTTP response body * @param returnType The return type used to deserialize HTTP response body
* @param <T> The return type corresponding to (same with) returnType * @param <T> The return type corresponding to (same with) returnType
* @return The Java object deserialized from response body. Returns null if returnType is null. * @return <code>ApiResponse</code> object containing response status, headers and
* data, which is a Java object deserialized from response body and would be null
* when returnType is null.
* @throws ApiException If fail to execute the call
*/ */
public <T> T execute(Call call, Type returnType) throws ApiException { public <T> ApiResponse<T> execute(Call call, Type returnType) throws ApiException {
try { try {
Response response = call.execute(); Response response = call.execute();
this.statusCode = response.code(); T data = handleResponse(response, returnType);
this.responseHeaders = response.headers().toMultimap(); return new ApiResponse<T>(response.code(), response.headers().toMultimap(), data);
return handleResponse(response, returnType);
} catch (IOException e) { } catch (IOException e) {
throw new ApiException(e); throw new ApiException(e);
} }
@ -756,7 +764,7 @@ public class ApiClient {
/** /**
* #see executeAsync(Call, Type, ApiCallback) * #see executeAsync(Call, Type, ApiCallback)
*/ */
public <T> void executeAsync(Call call, ApiCallback<T> callback) throws ApiException { public <T> void executeAsync(Call call, ApiCallback<T> callback) {
executeAsync(call, null, callback); executeAsync(call, null, callback);
} }
@ -787,6 +795,12 @@ public class ApiClient {
}); });
} }
/**
* Handle the given response, return the deserialized object when the response is successful.
*
* @throws ApiException If the response has a unsuccessful status code or
* fail to deserialize the response body
*/
public <T> T handleResponse(Response response, Type returnType) throws ApiException { public <T> T handleResponse(Response response, Type returnType) throws ApiException {
if (response.isSuccessful()) { if (response.isSuccessful()) {
if (returnType == null || response.code() == 204) { if (returnType == null || response.code() == 204) {
@ -820,8 +834,9 @@ public class ApiClient {
* @param formParams The form parameters * @param formParams The form parameters
* @param authNames The authentications to apply * @param authNames The authentications to apply
* @return The HTTP call * @return The HTTP call
* @throws ApiException If fail to serialize the request body object
*/ */
public Call buildCall(String path, String method, List<Pair> queryParams, Object body, Map<String, String> headerParams, Map<String, Object> formParams, String[] authNames) throws ApiException { public Call buildCall(String path, String method, List<Pair> queryParams, Object body, Map<String, String> headerParams, Map<String, Object> formParams, String[] authNames, ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException {
updateParamsForAuth(authNames, queryParams, headerParams); updateParamsForAuth(authNames, queryParams, headerParams);
final String url = buildUrl(path, queryParams); final String url = buildUrl(path, queryParams);
@ -830,7 +845,9 @@ public class ApiClient {
String contentType = (String) headerParams.get("Content-Type"); String contentType = (String) headerParams.get("Content-Type");
// ensuring a default content type // ensuring a default content type
if (contentType == null) contentType = "application/json"; if (contentType == null) {
contentType = "application/json";
}
RequestBody reqBody; RequestBody reqBody;
if (!HttpMethod.permitsRequestBody(method)) { if (!HttpMethod.permitsRequestBody(method)) {
@ -851,7 +868,15 @@ public class ApiClient {
reqBody = RequestBody.create(MediaType.parse(contentType), serialize(body, contentType)); reqBody = RequestBody.create(MediaType.parse(contentType), serialize(body, contentType));
} }
Request request = reqBuilder.method(method, reqBody).build(); Request request = null;
if(progressRequestListener != null && reqBody != null) {
ProgressRequestBody progressRequestBody = new ProgressRequestBody(reqBody, progressRequestListener);
request = reqBuilder.method(method, progressRequestBody).build();
} else {
request = reqBuilder.method(method, reqBody).build();
}
return httpClient.newCall(request); return httpClient.newCall(request);
} }

View File

@ -0,0 +1,46 @@
package {{invokerPackage}};
import java.util.List;
import java.util.Map;
/**
* API response returned by API call.
*
* @param T The type of data that is deserialized from response body
*/
public class ApiResponse<T> {
final private int statusCode;
final private Map<String, List<String>> headers;
final private T data;
/**
* @param statusCode The status code of HTTP response
* @param headers The headers of HTTP response
*/
public ApiResponse(int statusCode, Map<String, List<String>> headers) {
this(statusCode, headers, null);
}
/**
* @param statusCode The status code of HTTP response
* @param headers The headers of HTTP response
* @param data The object deserialized from response bod
*/
public ApiResponse(int statusCode, Map<String, List<String>> headers, T data) {
this.statusCode = statusCode;
this.headers = headers;
this.data = data;
}
public int getStatusCode() {
return statusCode;
}
public Map<String, List<String>> getHeaders() {
return headers;
}
public T getData() {
return data;
}
}

View File

@ -0,0 +1,70 @@
package {{invokerPackage}};
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.RequestBody;
import java.io.IOException;
import okio.Buffer;
import okio.BufferedSink;
import okio.ForwardingSink;
import okio.Okio;
import okio.Sink;
public class ProgressRequestBody extends RequestBody {
public interface ProgressRequestListener {
void onRequestProgress(long bytesWritten, long contentLength, boolean done);
}
private final RequestBody requestBody;
private final ProgressRequestListener progressListener;
private BufferedSink bufferedSink;
public ProgressRequestBody(RequestBody requestBody, ProgressRequestListener progressListener) {
this.requestBody = requestBody;
this.progressListener = progressListener;
}
@Override
public MediaType contentType() {
return requestBody.contentType();
}
@Override
public long contentLength() throws IOException {
return requestBody.contentLength();
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
if (bufferedSink == null) {
bufferedSink = Okio.buffer(sink(sink));
}
requestBody.writeTo(bufferedSink);
bufferedSink.flush();
}
private Sink sink(Sink sink) {
return new ForwardingSink(sink) {
long bytesWritten = 0L;
long contentLength = 0L;
@Override
public void write(Buffer source, long byteCount) throws IOException {
super.write(source, byteCount);
if (contentLength == 0) {
contentLength = contentLength();
}
bytesWritten += byteCount;
progressListener.onRequestProgress(bytesWritten, contentLength, bytesWritten == contentLength);
}
};
}
}

View File

@ -0,0 +1,63 @@
package {{invokerPackage}};
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.ResponseBody;
import java.io.IOException;
import okio.Buffer;
import okio.BufferedSource;
import okio.ForwardingSource;
import okio.Okio;
import okio.Source;
public class ProgressResponseBody extends ResponseBody {
public interface ProgressListener {
void update(long bytesRead, long contentLength, boolean done);
}
private final ResponseBody responseBody;
private final ProgressListener progressListener;
private BufferedSource bufferedSource;
public ProgressResponseBody(ResponseBody responseBody, ProgressListener progressListener) {
this.responseBody = responseBody;
this.progressListener = progressListener;
}
@Override
public MediaType contentType() {
return responseBody.contentType();
}
@Override
public long contentLength() throws IOException {
return responseBody.contentLength();
}
@Override
public BufferedSource source() throws IOException {
if (bufferedSource == null) {
bufferedSource = Okio.buffer(source(responseBody.source()));
}
return bufferedSource;
}
private Source source(Source source) {
return new ForwardingSource(source) {
long totalBytesRead = 0L;
@Override
public long read(Buffer sink, long byteCount) throws IOException {
long bytesRead = super.read(sink, byteCount);
// read() returns the number of bytes read, or -1 if this source is exhausted.
totalBytesRead += bytesRead != -1 ? bytesRead : 0;
progressListener.update(totalBytesRead, responseBody.contentLength(), bytesRead == -1);
return bytesRead;
}
};
}
}

View File

@ -3,12 +3,19 @@ package {{package}};
import {{invokerPackage}}.ApiCallback; import {{invokerPackage}}.ApiCallback;
import {{invokerPackage}}.ApiClient; import {{invokerPackage}}.ApiClient;
import {{invokerPackage}}.ApiException; import {{invokerPackage}}.ApiException;
import {{invokerPackage}}.ApiResponse;
import {{invokerPackage}}.Configuration; import {{invokerPackage}}.Configuration;
import {{invokerPackage}}.Pair; import {{invokerPackage}}.Pair;
import {{invokerPackage}}.ProgressRequestBody;
import {{invokerPackage}}.ProgressResponseBody;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import com.squareup.okhttp.Call; import com.squareup.okhttp.Call;
import com.squareup.okhttp.Interceptor;
import com.squareup.okhttp.Response;
import java.io.IOException;
{{#imports}}import {{import}}; {{#imports}}import {{import}};
{{/imports}} {{/imports}}
@ -39,13 +46,13 @@ public class {{classname}} {
} }
{{#operation}} {{#operation}}
/* Build call for {{nickname}} */ /* Build call for {{operationId}} */
private Call {{nickname}}Call({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { private Call {{operationId}}Call({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ProgressResponseBody.ProgressListener progressListener, final ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException {
Object {{localVariablePrefix}}postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; Object {{localVariablePrefix}}postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}};
{{#allParams}}{{#required}} {{#allParams}}{{#required}}
// verify the required parameter '{{paramName}}' is set // verify the required parameter '{{paramName}}' is set
if ({{paramName}} == null) { if ({{paramName}} == null) {
throw new ApiException("Missing the required parameter '{{paramName}}' when calling {{nickname}}(Async)"); throw new ApiException("Missing the required parameter '{{paramName}}' when calling {{operationId}}(Async)");
} }
{{/required}}{{/allParams}} {{/required}}{{/allParams}}
@ -77,8 +84,20 @@ public class {{classname}} {
final String {{localVariablePrefix}}contentType = {{localVariablePrefix}}apiClient.selectHeaderContentType({{localVariablePrefix}}contentTypes); final String {{localVariablePrefix}}contentType = {{localVariablePrefix}}apiClient.selectHeaderContentType({{localVariablePrefix}}contentTypes);
{{localVariablePrefix}}headerParams.put("Content-Type", {{localVariablePrefix}}contentType); {{localVariablePrefix}}headerParams.put("Content-Type", {{localVariablePrefix}}contentType);
if(progressListener != null) {
apiClient.getHttpClient().networkInterceptors().add(new Interceptor() {
@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder()
.body(new ProgressResponseBody(originalResponse.body(), progressListener))
.build();
}
});
}
String[] {{localVariablePrefix}}authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; String[] {{localVariablePrefix}}authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} };
return {{localVariablePrefix}}apiClient.buildCall({{localVariablePrefix}}path, "{{httpMethod}}", {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}authNames); return {{localVariablePrefix}}apiClient.buildCall({{localVariablePrefix}}path, "{{httpMethod}}", {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}authNames, progressRequestListener);
} }
/** /**
@ -86,11 +105,24 @@ public class {{classname}} {
* {{notes}}{{#allParams}} * {{notes}}{{#allParams}}
* @param {{paramName}} {{description}}{{/allParams}}{{#returnType}} * @param {{paramName}} {{description}}{{/allParams}}{{#returnType}}
* @return {{{returnType}}}{{/returnType}} * @return {{{returnType}}}{{/returnType}}
* @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body
*/ */
public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException {
Call {{localVariablePrefix}}call = {{nickname}}Call({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); {{#returnType}}ApiResponse<{{{returnType}}}> {{localVariablePrefix}}resp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}}
return {{localVariablePrefix}}resp.getData();{{/returnType}}
}
/**
* {{summary}}
* {{notes}}{{#allParams}}
* @param {{paramName}} {{description}}{{/allParams}}
* @return ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>
* @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body
*/
public ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException {
Call {{localVariablePrefix}}call = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}null, null);
{{#returnType}}Type {{localVariablePrefix}}returnType = new TypeToken<{{{returnType}}}>(){}.getType(); {{#returnType}}Type {{localVariablePrefix}}returnType = new TypeToken<{{{returnType}}}>(){}.getType();
return {{localVariablePrefix}}apiClient.execute({{localVariablePrefix}}call, {{localVariablePrefix}}returnType);{{/returnType}}{{^returnType}}{{localVariablePrefix}}apiClient.execute({{localVariablePrefix}}call);{{/returnType}} return {{localVariablePrefix}}apiClient.execute({{localVariablePrefix}}call, {{localVariablePrefix}}returnType);{{/returnType}}{{^returnType}}return {{localVariablePrefix}}apiClient.execute({{localVariablePrefix}}call);{{/returnType}}
} }
/** /**
@ -99,9 +131,30 @@ public class {{classname}} {
* @param {{paramName}} {{description}}{{/allParams}} * @param {{paramName}} {{description}}{{/allParams}}
* @param callback The callback to be executed when the API call finishes * @param callback The callback to be executed when the API call finishes
* @return The request call * @return The request call
* @throws ApiException If fail to process the API call, e.g. serializing the request body object
*/ */
public Call {{nickname}}Async({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}ApiCallback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{localVariablePrefix}}callback) throws ApiException { public Call {{operationId}}Async({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ApiCallback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{localVariablePrefix}}callback) throws ApiException {
Call {{localVariablePrefix}}call = {{nickname}}Call({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
ProgressResponseBody.ProgressListener progressListener = null;
ProgressRequestBody.ProgressRequestListener progressRequestListener = null;
if (callback != null) {
progressListener = new ProgressResponseBody.ProgressListener() {
@Override
public void update(long bytesRead, long contentLength, boolean done) {
callback.onDownloadProgress(bytesRead, contentLength, done);
}
};
progressRequestListener = new ProgressRequestBody.ProgressRequestListener() {
@Override
public void onRequestProgress(long bytesWritten, long contentLength, boolean done) {
callback.onUploadProgress(bytesWritten, contentLength, done);
}
};
}
Call {{localVariablePrefix}}call = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}progressListener, progressRequestListener);
{{#returnType}}Type {{localVariablePrefix}}returnType = new TypeToken<{{{returnType}}}>(){}.getType(); {{#returnType}}Type {{localVariablePrefix}}returnType = new TypeToken<{{{returnType}}}>(){}.getType();
{{localVariablePrefix}}apiClient.executeAsync({{localVariablePrefix}}call, {{localVariablePrefix}}returnType, {{localVariablePrefix}}callback);{{/returnType}}{{^returnType}}{{localVariablePrefix}}apiClient.executeAsync({{localVariablePrefix}}call, {{localVariablePrefix}}callback);{{/returnType}} {{localVariablePrefix}}apiClient.executeAsync({{localVariablePrefix}}call, {{localVariablePrefix}}returnType, {{localVariablePrefix}}callback);{{/returnType}}{{^returnType}}{{localVariablePrefix}}apiClient.executeAsync({{localVariablePrefix}}call, {{localVariablePrefix}}callback);{{/returnType}}
return {{localVariablePrefix}}call; return {{localVariablePrefix}}call;

View File

@ -1,12 +1,12 @@
public enum {{datatypeWithEnum}} { public enum {{{datatypeWithEnum}}} {
{{#allowableValues}}{{#enumVars}}@SerializedName("{{value}}") {{#allowableValues}}{{#enumVars}}@SerializedName("{{{value}}}")
{{name}}("{{value}}"){{^-last}}, {{{name}}}("{{{value}}}"){{^-last}},
{{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}} {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}}
private String value; private String value;
{{datatypeWithEnum}}(String value) { {{{datatypeWithEnum}}}(String value) {
this.value = value; this.value = value;
} }

View File

@ -8,6 +8,7 @@ import com.google.gson.annotations.SerializedName;
{{#serializableModel}} {{#serializableModel}}
import java.io.Serializable;{{/serializableModel}} import java.io.Serializable;{{/serializableModel}}
import java.util.Objects;
import io.swagger.annotations.*; import io.swagger.annotations.*;
@ -44,6 +45,25 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}} {{#seriali
{{/vars}} {{/vars}}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
{{classname}} {{classVarName}} = ({{classname}}) o;{{#hasVars}}
return {{#vars}}Objects.equals({{name}}, {{classVarName}}.{{name}}){{#hasMore}} &&
{{/hasMore}}{{^hasMore}};{{/hasMore}}{{/vars}}{{/hasVars}}{{^hasVars}}
return true;{{/hasVars}}
}
@Override
public int hashCode() {
return Objects.hash({{#vars}}{{name}}{{#hasMore}}, {{/hasMore}}{{/vars}});
}
@Override @Override
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();

View File

@ -26,7 +26,7 @@ public interface {{classname}} {
{{#formParams}}{{#-first}} {{#formParams}}{{#-first}}
{{#isMultipart}}@Multipart{{/isMultipart}}{{^isMultipart}}@FormUrlEncoded{{/isMultipart}}{{/-first}}{{/formParams}} {{#isMultipart}}@Multipart{{/isMultipart}}{{^isMultipart}}@FormUrlEncoded{{/isMultipart}}{{/-first}}{{/formParams}}
@{{httpMethod}}("{{path}}") @{{httpMethod}}("{{path}}")
{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Object{{/returnType}} {{nickname}}({{^allParams}});{{/allParams}} {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Object{{/returnType}} {{operationId}}({{^allParams}});{{/allParams}}
{{#allParams}}{{>libraries/retrofit/queryParams}}{{>libraries/retrofit/pathParams}}{{>libraries/retrofit/headerParams}}{{>libraries/retrofit/bodyParams}}{{>libraries/retrofit/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}} {{#allParams}}{{>libraries/retrofit/queryParams}}{{>libraries/retrofit/pathParams}}{{>libraries/retrofit/headerParams}}{{>libraries/retrofit/bodyParams}}{{>libraries/retrofit/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}}
);{{/hasMore}}{{/allParams}} );{{/hasMore}}{{/allParams}}
@ -40,7 +40,7 @@ public interface {{classname}} {
{{#formParams}}{{#-first}} {{#formParams}}{{#-first}}
{{#isMultipart}}@Multipart{{/isMultipart}}{{^isMultipart}}@FormUrlEncoded{{/isMultipart}}{{/-first}}{{/formParams}} {{#isMultipart}}@Multipart{{/isMultipart}}{{^isMultipart}}@FormUrlEncoded{{/isMultipart}}{{/-first}}{{/formParams}}
@{{httpMethod}}("{{path}}") @{{httpMethod}}("{{path}}")
void {{nickname}}( void {{operationId}}(
{{#allParams}}{{>libraries/retrofit/queryParams}}{{>libraries/retrofit/pathParams}}{{>libraries/retrofit/headerParams}}{{>libraries/retrofit/bodyParams}}{{>libraries/retrofit/formParams}}, {{/allParams}}Callback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Object{{/returnType}}> cb {{#allParams}}{{>libraries/retrofit/queryParams}}{{>libraries/retrofit/pathParams}}{{>libraries/retrofit/headerParams}}{{>libraries/retrofit/bodyParams}}{{>libraries/retrofit/formParams}}, {{/allParams}}Callback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Object{{/returnType}}> cb
); );
{{/operation}} {{/operation}}

View File

@ -8,6 +8,7 @@ import com.google.gson.annotations.SerializedName;
{{#serializableModel}} {{#serializableModel}}
import java.io.Serializable;{{/serializableModel}} import java.io.Serializable;{{/serializableModel}}
import java.util.Objects;
import io.swagger.annotations.*; import io.swagger.annotations.*;
@ -44,6 +45,25 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}} {{#seriali
{{/vars}} {{/vars}}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
{{classname}} {{classVarName}} = ({{classname}}) o;{{#hasVars}}
return {{#vars}}Objects.equals({{name}}, {{classVarName}}.{{name}}){{#hasMore}} &&
{{/hasMore}}{{^hasMore}};{{/hasMore}}{{/vars}}{{/hasVars}}{{^hasVars}}
return true;{{/hasVars}}
}
@Override
public int hashCode() {
return Objects.hash({{#vars}}{{name}}{{#hasMore}}, {{/hasMore}}{{/vars}});
}
@Override @Override
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();

View File

@ -25,7 +25,7 @@ public interface {{classname}} {
{{#formParams}}{{#-first}} {{#formParams}}{{#-first}}
{{#isMultipart}}@Multipart{{/isMultipart}}{{^isMultipart}}@FormUrlEncoded{{/isMultipart}}{{/-first}}{{/formParams}} {{#isMultipart}}@Multipart{{/isMultipart}}{{^isMultipart}}@FormUrlEncoded{{/isMultipart}}{{/-first}}{{/formParams}}
@{{httpMethod}}("{{path}}") @{{httpMethod}}("{{path}}")
Call<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Object{{/returnType}}> {{nickname}}({{^allParams}});{{/allParams}} Call<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Object{{/returnType}}> {{operationId}}({{^allParams}});{{/allParams}}
{{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}} {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}}
);{{/hasMore}}{{/allParams}} );{{/hasMore}}{{/allParams}}

View File

@ -98,8 +98,8 @@ ext {
dependencies { dependencies {
compile "com.squareup.okhttp:okhttp:$okhttp_version" compile "com.squareup.okhttp:okhttp:$okhttp_version"
compile "com.squareup.retrofit:retrofit:$retrofit_version" compile "com.squareup.retrofit:retrofit:$retrofit_version"
compile 'com.google.code.gson:gson:$gson_version' compile "com.google.code.gson:gson:$gson_version"
compile 'com.squareup.retrofit:converter-gson:$retrofit_version' compile "com.squareup.retrofit:converter-gson:$retrofit_version"
compile "io.swagger:swagger-annotations:$swagger_annotations_version" compile "io.swagger:swagger-annotations:$swagger_annotations_version"
compile "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version" compile "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version"
testCompile "junit:junit:$junit_version" testCompile "junit:junit:$junit_version"

View File

@ -8,6 +8,7 @@ import com.google.gson.annotations.SerializedName;
{{#serializableModel}} {{#serializableModel}}
import java.io.Serializable;{{/serializableModel}} import java.io.Serializable;{{/serializableModel}}
import java.util.Objects;
import io.swagger.annotations.*; import io.swagger.annotations.*;
@ -44,6 +45,25 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}} {{#seriali
{{/vars}} {{/vars}}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
{{classname}} {{classVarName}} = ({{classname}}) o;{{#hasVars}}
return {{#vars}}Objects.equals({{name}}, {{classVarName}}.{{name}}){{#hasMore}} &&
{{/hasMore}}{{^hasMore}};{{/hasMore}}{{/vars}}{{/hasVars}}{{^hasVars}}
return true;{{/hasVars}}
}
@Override
public int hashCode() {
return Objects.hash({{#vars}}{{name}}{{#hasMore}}, {{/hasMore}}{{/vars}});
}
@Override @Override
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();

View File

@ -6,51 +6,17 @@ import {{invokerPackage}}.StringUtil;
{{#serializableModel}} {{#serializableModel}}
import java.io.Serializable;{{/serializableModel}} import java.io.Serializable;{{/serializableModel}}
import java.util.Objects;
import io.swagger.annotations.*; import io.swagger.annotations.*;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.*;
{{#models}} {{#models}}
{{#model}}{{#description}} {{#model}}{{#description}}
/** /**
* {{description}} * {{description}}
**/{{/description}} **/{{/description}}
@ApiModel(description = "{{{description}}}") {{#isEnum}}{{>enumOuterClass}}{{/isEnum}}
{{>generatedAnnotation}} {{^isEnum}}{{>pojo}}{{/isEnum}}
public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}} {{#serializableModel}}implements Serializable{{/serializableModel}} {
{{#vars}}{{#isEnum}}
{{>enumClass}}{{/isEnum}}{{#items.isEnum}}{{#items}}
{{>enumClass}}{{/items}}{{/items.isEnum}}
private {{{datatypeWithEnum}}} {{name}} = {{{defaultValue}}};{{/vars}}
{{#vars}}
/**{{#description}}
* {{{description}}}{{/description}}{{#minimum}}
* minimum: {{minimum}}{{/minimum}}{{#maximum}}
* maximum: {{maximum}}{{/maximum}}
**/
@ApiModelProperty({{#required}}required = {{required}}, {{/required}}value = "{{{description}}}")
@JsonProperty("{{baseName}}")
public {{{datatypeWithEnum}}} {{getter}}() {
return {{name}};
}
public void {{setter}}({{{datatypeWithEnum}}} {{name}}) {
this.{{name}} = {{name}};
}
{{/vars}}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class {{classname}} {\n");
{{#parent}}sb.append(" ").append(StringUtil.toIndentedString(super.toString())).append("\n");{{/parent}}
{{#vars}}sb.append(" {{name}}: ").append(StringUtil.toIndentedString({{name}})).append("\n");
{{/vars}}sb.append("}");
return sb.toString();
}
}
{{/model}} {{/model}}
{{/models}} {{/models}}

View File

@ -0,0 +1,56 @@
@ApiModel(description = "{{{description}}}")
{{>generatedAnnotation}}
public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}} {{#serializableModel}}implements Serializable{{/serializableModel}} {
{{#vars}}{{#isEnum}}
{{>enumClass}}{{/isEnum}}{{#items.isEnum}}{{#items}}
{{>enumClass}}{{/items}}{{/items.isEnum}}
private {{{datatypeWithEnum}}} {{name}} = {{{defaultValue}}};{{/vars}}
{{#vars}}
/**{{#description}}
* {{{description}}}{{/description}}{{#minimum}}
* minimum: {{minimum}}{{/minimum}}{{#maximum}}
* maximum: {{maximum}}{{/maximum}}
**/
@ApiModelProperty({{#required}}required = {{required}}, {{/required}}value = "{{{description}}}")
@JsonProperty("{{baseName}}")
public {{{datatypeWithEnum}}} {{getter}}() {
return {{name}};
}
public void {{setter}}({{{datatypeWithEnum}}} {{name}}) {
this.{{name}} = {{name}};
}
{{/vars}}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
{{classname}} {{classVarName}} = ({{classname}}) o;{{#hasVars}}
return {{#vars}}Objects.equals({{name}}, {{classVarName}}.{{name}}){{#hasMore}} &&
{{/hasMore}}{{^hasMore}};{{/hasMore}}{{/vars}}{{/hasVars}}{{^hasVars}}
return true;{{/hasVars}}
}
@Override
public int hashCode() {
return Objects.hash({{#vars}}{{name}}{{#hasMore}}, {{/hasMore}}{{/vars}});
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class {{classname}} {\n");
{{#parent}}sb.append(" ").append(StringUtil.toIndentedString(super.toString())).append("\n");{{/parent}}
{{#vars}}sb.append(" {{name}}: ").append(StringUtil.toIndentedString({{name}})).append("\n");
{{/vars}}sb.append("}");
return sb.toString();
}
}

View File

@ -137,6 +137,11 @@
<artifactId>jackson-databind</artifactId> <artifactId>jackson-databind</artifactId>
<version>${jackson-version}</version> <version>${jackson-version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.datatype</groupId> <groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId> <artifactId>jackson-datatype-joda</artifactId>

View File

@ -24,7 +24,7 @@ public class {{classname}} {
{{#operation}} {{#operation}}
/* /*
public ResponseContext {{nickname}}(RequestContext request {{#allParams}}, {{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{/allParams}}) { public ResponseContext {{operationId}}(RequestContext request {{#allParams}}, {{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{/allParams}}) {
return new ResponseContext().status(Status.INTERNAL_SERVER_ERROR).entity( "Not implemented" ); return new ResponseContext().status(Status.INTERNAL_SERVER_ERROR).entity( "Not implemented" );
} }
*/ */

View File

@ -1,6 +1,6 @@
controllerPackage: {{invokerPackage}} controllerPackage: {{invokerPackage}}
modelPackage: {{modelPackage}} modelPackage: {{modelPackage}}
swaggerUrl: ./src/main/swagger/swagger.json swaggerUrl: ./src/main/swagger/swagger.yaml
modelMappings: modelMappings:
{{#models}}{{#model}}{{classname}} : {{modelPackage}}.{{classname}}{{/model}} {{#models}}{{#model}}{{classname}} : {{modelPackage}}.{{classname}}{{/model}}
{{/models}} {{/models}}

View File

@ -74,11 +74,11 @@
</plugins> </plugins>
</build> </build>
<dependencies> <dependencies>
<!-- inflector client --> <!-- inflector library -->
<dependency> <dependency>
<groupId>io.swagger</groupId> <groupId>io.swagger</groupId>
<artifactId>swagger-inflector</artifactId> <artifactId>swagger-inflector</artifactId>
<version>1.0.0-SNAPSHOT</version> <version>1.0.0</version>
</dependency> </dependency>
</dependencies> </dependencies>
<properties> <properties>

View File

@ -0,0 +1 @@
{{{swagger-yaml}}}

View File

@ -12,3 +12,12 @@ To run the server, please execute the following:
``` ```
mvn clean package jetty:run mvn clean package jetty:run
``` ```
You can then view the swagger listing here:
```
http://localhost:8080{{contextPath}}/swagger.json
```
Note that if you have configured the `host` to be something other than localhost, the calls through
swagger-ui will be directed to that host and not localhost!

View File

@ -19,7 +19,9 @@ import java.io.InputStream;
import com.sun.jersey.core.header.FormDataContentDisposition; import com.sun.jersey.core.header.FormDataContentDisposition;
import com.sun.jersey.multipart.FormDataParam; import com.sun.jersey.multipart.FormDataParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.*; import javax.ws.rs.*;
@Path("/{{baseName}}") @Path("/{{baseName}}")
@ -47,12 +49,10 @@ public class {{classname}} {
@io.swagger.annotations.ApiResponse(code = {{{code}}}, message = "{{{message}}}", response = {{{returnType}}}.class{{#returnContainer}}, responseContainer = "{{{returnContainer}}}"{{/returnContainer}}){{#hasMore}}, @io.swagger.annotations.ApiResponse(code = {{{code}}}, message = "{{{message}}}", response = {{{returnType}}}.class{{#returnContainer}}, responseContainer = "{{{returnContainer}}}"{{/returnContainer}}){{#hasMore}},
{{/hasMore}}{{/responses}} }) {{/hasMore}}{{/responses}} })
public Response {{nickname}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}}, public Response {{nickname}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}},{{/allParams}}@Context SecurityContext securityContext)
{{/hasMore}}{{/allParams}})
throws NotFoundException { throws NotFoundException {
return delegate.{{nickname}}({{#allParams}}{{#isFile}}fileDetail{{/isFile}}{{^isFile}}{{paramName}}{{/isFile}}{{#hasMore}},{{/hasMore}}{{/allParams}}); return delegate.{{nickname}}({{#allParams}}{{#isFile}}fileDetail{{/isFile}}{{^isFile}}{{paramName}}{{/isFile}},{{/allParams}}securityContext);
} }
{{/operation}} {{/operation}}
} }
{{/operations}} {{/operations}}

View File

@ -17,12 +17,13 @@ import com.sun.jersey.core.header.FormDataContentDisposition;
import com.sun.jersey.multipart.FormDataParam; import com.sun.jersey.multipart.FormDataParam;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
{{>generatedAnnotation}} {{>generatedAnnotation}}
{{#operations}} {{#operations}}
public abstract class {{classname}}Service { public abstract class {{classname}}Service {
{{#operation}} {{#operation}}
public abstract Response {{nickname}}({{#allParams}}{{>serviceQueryParams}}{{>servicePathParams}}{{>serviceHeaderParams}}{{>serviceBodyParams}}{{>serviceFormParams}}{{#hasMore}},{{/hasMore}}{{/allParams}}) public abstract Response {{nickname}}({{#allParams}}{{>serviceQueryParams}}{{>servicePathParams}}{{>serviceHeaderParams}}{{>serviceBodyParams}}{{>serviceFormParams}},{{/allParams}}SecurityContext securityContext)
throws NotFoundException; throws NotFoundException;
{{/operation}} {{/operation}}
} }

View File

@ -17,13 +17,14 @@ import com.sun.jersey.core.header.FormDataContentDisposition;
import com.sun.jersey.multipart.FormDataParam; import com.sun.jersey.multipart.FormDataParam;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
{{>generatedAnnotation}} {{>generatedAnnotation}}
{{#operations}} {{#operations}}
public class {{classname}}ServiceImpl extends {{classname}}Service { public class {{classname}}ServiceImpl extends {{classname}}Service {
{{#operation}} {{#operation}}
@Override @Override
public Response {{nickname}}({{#allParams}}{{>serviceQueryParams}}{{>servicePathParams}}{{>serviceHeaderParams}}{{>serviceBodyParams}}{{>serviceFormParams}}{{#hasMore}},{{/hasMore}}{{/allParams}}) public Response {{nickname}}({{#allParams}}{{>serviceQueryParams}}{{>servicePathParams}}{{>serviceHeaderParams}}{{>serviceBodyParams}}{{>serviceFormParams}},{{/allParams}}SecurityContext securityContext)
throws NotFoundException { throws NotFoundException {
// do some magic! // do some magic!
return Response.ok().entity(new ApiResponseMessage(ApiResponseMessage.OK, "magic!")).build(); return Response.ok().entity(new ApiResponseMessage(ApiResponseMessage.OK, "magic!")).build();

View File

@ -5,6 +5,8 @@ package {{package}};
import io.swagger.annotations.*; import io.swagger.annotations.*;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Objects;
{{#models}} {{#models}}
{{#model}}{{#unescapedDescription}} {{#model}}{{#unescapedDescription}}
@ -38,6 +40,25 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}} {
{{/vars}} {{/vars}}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
{{classname}} {{classVarName}} = ({{classname}}) o;{{#hasVars}}
return {{#vars}}Objects.equals({{name}}, {{classVarName}}.{{name}}){{#hasMore}} &&
{{/hasMore}}{{^hasMore}};{{/hasMore}}{{/vars}}{{/hasVars}}{{^hasVars}}
return true;{{/hasVars}}
}
@Override
public int hashCode() {
return Objects.hash({{#vars}}{{name}}{{#hasMore}}, {{/hasMore}}{{/vars}});
}
@Override @Override
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();

View File

@ -50,7 +50,7 @@ public class {{classname}} {
{{#hasProduces}}produces = { {{#produces}}"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }, {{/hasProduces}} {{#hasProduces}}produces = { {{#produces}}"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }, {{/hasProduces}}
{{#hasConsumes}}consumes = { {{#consumes}}"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} },{{/hasConsumes}} {{#hasConsumes}}consumes = { {{#consumes}}"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} },{{/hasConsumes}}
method = RequestMethod.{{httpMethod}}) method = RequestMethod.{{httpMethod}})
public ResponseEntity<{{>returnTypes}}> {{nickname}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}}, public ResponseEntity<{{>returnTypes}}> {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}},
{{/hasMore}}{{/allParams}}) {{/hasMore}}{{/allParams}})
throws NotFoundException { throws NotFoundException {
// do some magic! // do some magic!

View File

@ -5,6 +5,8 @@ package {{package}};
import io.swagger.annotations.*; import io.swagger.annotations.*;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Objects;
{{#models}} {{#models}}
{{#model}}{{#description}} {{#model}}{{#description}}
@ -38,6 +40,25 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}} {
{{/vars}} {{/vars}}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
{{classname}} {{classVarName}} = ({{classname}}) o;{{#hasVars}}
return {{#vars}}Objects.equals({{name}}, {{classVarName}}.{{name}}){{#hasMore}} &&
{{/hasMore}}{{^hasMore}};{{/hasMore}}{{/vars}}{{/hasVars}}{{^hasVars}}
return true;{{/hasVars}}
}
@Override
public int hashCode() {
return Objects.hash({{#vars}}{{name}}{{#hasMore}}, {{/hasMore}}{{/vars}});
}
@Override @Override
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();

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