Merge pull request #2 from swagger-api/master

merge
This commit is contained in:
SparrowJang 2015-09-04 14:25:34 +08:00
commit f6d624be2a
875 changed files with 69056 additions and 22976 deletions

47
.dockerignore Normal file
View File

@ -0,0 +1,47 @@
*.iml
out/
*.ipr
*.iws
classpath.txt
version.properties
.project
.classpath
lib/*
build/*
generated-files/*
generated-sources/*
generated-code/*
*.swp
*.swo
/target
/generated-files
/nbactions.xml
*.pyc
__pycache__
samples/server-generator/scalatra/output
samples/server-generator/node/output/node_modules
samples/server-generator/scalatra/target
samples/server-generator/scalatra/output/.history
samples/client/petstore/qt5cpp/PetStore/moc_*
samples/client/petstore/qt5cpp/PetStore/*.o
samples/client/petstore/objc/PetstoreClient.xcworkspace/xcuserdata
samples/client/petstore/qt5cpp/build-*
samples/client/petstore/qt5cpp/PetStore/PetStore
samples/client/petstore/qt5cpp/PetStore/Makefile
samples/client/petstore/java/hello.txt
samples/client/petstore/android-java/hello.txt
samples/client/petstore/objc/Build
samples/client/petstore/objc/Pods
samples/server/petstore/nodejs/node_modules
target
.idea
.lib
atlassian-ide-plugin.xml
.DS_Store
samples/client/petstore/php/SwaggerClient-php/composer.lock
samples/client/petstore/php/SwaggerClient-php/vendor/
samples/client/petstore/silex/SwaggerServer/composer.lock
samples/client/petstore/silex/SwaggerServer/venodr/

13
.gitignore vendored
View File

@ -9,6 +9,7 @@ version.properties
lib/* lib/*
build/* build/*
generated-files/* generated-files/*
generated-sources/*
generated-code/* generated-code/*
*.swp *.swp
*.swo *.swo
@ -30,8 +31,10 @@ samples/client/petstore/qt5cpp/PetStore/PetStore
samples/client/petstore/qt5cpp/PetStore/Makefile samples/client/petstore/qt5cpp/PetStore/Makefile
samples/client/petstore/java/hello.txt samples/client/petstore/java/hello.txt
samples/client/petstore/android-java/hello.txt samples/client/petstore/android-java/hello.txt
samples/client/petstore/objc/Build samples/client/petstore/objc/SwaggerClientTests/Build
samples/client/petstore/objc/Pods samples/client/petstore/objc/SwaggerClientTests/Pods
samples/client/petstore/objc/SwaggerClientTests/SwaggerClient.xcworkspace
samples/client/petstore/objc/SwaggerClientTests/Podfile.lock
samples/server/petstore/nodejs/node_modules samples/server/petstore/nodejs/node_modules
target target
.idea .idea
@ -41,3 +44,9 @@ atlassian-ide-plugin.xml
samples/client/petstore/php/SwaggerClient-php/composer.lock samples/client/petstore/php/SwaggerClient-php/composer.lock
samples/client/petstore/php/SwaggerClient-php/vendor/ samples/client/petstore/php/SwaggerClient-php/vendor/
samples/client/petstore/silex/SwaggerServer/composer.lock
samples/client/petstore/silex/SwaggerServer/venodr/
samples/client/petstore/python/.projectile
samples/client/petstore/python/.venv/

View File

@ -1,5 +1,5 @@
sudo: false sudo: false
language: java language: java
script: mvn verify script: mvn verify -Psamples
jdk: jdk:
- oraclejdk7 - oraclejdk7

13
Dockerfile Normal file
View File

@ -0,0 +1,13 @@
FROM maven:3.3-jdk-7
WORKDIR /src
VOLUME /src
VOLUME /root/.m2/repository
ADD . /opt/swagger-codegen
RUN cd /opt/swagger-codegen && mvn package
ENTRYPOINT ["java", "-jar", "/opt/swagger-codegen/modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"]
CMD ["help"]

View File

@ -7,13 +7,32 @@ This is the swagger codegen project, which allows generation of client libraries
Check out [Swagger-Spec](https://github.com/swagger-api/swagger-spec) for additional information about the Swagger project, including additional libraries with support for other languages and more. Check out [Swagger-Spec](https://github.com/swagger-api/swagger-spec) for additional information about the Swagger project, including additional libraries with support for other languages and more.
## Build and run using docker
```
git clone https://github.com/swagger-api/swagger-codegen
cd swagger-codegen
./run-in-docker.sh mvn package
```
Build a nodejs server stub:
```
./run-in-docker.sh generate \
-i http://petstore.swagger.io/v2/swagger.json \
-l nodejs \
-o samples/server/petstore/nodejs
```
## Compatibility ## Compatibility
The Swagger Specification has undergone 3 revisions since initial creation in 2010. The swagger-codegen project has the following compatibilies with the swagger specification: The Swagger Specification has undergone 3 revisions since initial creation in 2010. The swagger-codegen project has the following compatibilies with the swagger specification:
Swagger Codegen Version | Release Date | Swagger Spec compatibility | Notes Swagger Codegen Version | Release Date | Swagger Spec compatibility | Notes
----------------------- | ------------ | -------------------------- | ----- -------------------------- | ------------ | -------------------------- | -----
2.1.2 | 2015-06-09 | 1.0, 1.1, 1.2, 2.0 | [master](https://github.com/swagger-api/swagger-codegen) 2.1.4-SNAPSHOT | | 1.0, 1.1, 1.2, 2.0 | [master](https://github.com/swagger-api/swagger-codegen)
2.1.3 (**current stable**) | 2015-08-24 | 1.0, 1.1, 1.2, 2.0 | [tag v2.1.3](https://github.com/swagger-api/swagger-codegen/tree/v2.1.3)
2.0.17 | 2014-08-22 | 1.1, 1.2 | [tag v2.0.17](https://github.com/swagger-api/swagger-codegen/tree/v2.0.17) 2.0.17 | 2014-08-22 | 1.1, 1.2 | [tag v2.0.17](https://github.com/swagger-api/swagger-codegen/tree/v2.0.17)
1.0.4 | 2012-04-12 | 1.0, 1.1 | [tag v1.0.4](https://github.com/swagger-api/swagger-codegen/tree/swagger-codegen_2.9.1-1.1) 1.0.4 | 2012-04-12 | 1.0, 1.1 | [tag v1.0.4](https://github.com/swagger-api/swagger-codegen/tree/swagger-codegen_2.9.1-1.1)
@ -73,6 +92,7 @@ SYNOPSIS
[(-o <output directory> | --output <output directory>)] [(-o <output directory> | --output <output directory>)]
[(-t <template directory> | --template-dir <template directory>)] [(-t <template directory> | --template-dir <template directory>)]
[(-v | --verbose)] [(-v | --verbose)]
[(-s | --skip-overwrite)]
OPTIONS OPTIONS
-a <authorization>, --auth <authorization> -a <authorization>, --auth <authorization>
@ -105,6 +125,10 @@ OPTIONS
-v, --verbose -v, --verbose
verbose mode verbose mode
-s , --skip-overwrite
specifies if the existing files should be overwritten during
the generation
``` ```
You can then compile and run the client, as well as unit tests against it: You can then compile and run the client, as well as unit tests against it:
@ -161,11 +185,16 @@ There are different aspects of customizing the code generator beyond just creati
``` ```
$ ls -1 modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/ $ ls -1 modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/
AbstractTypeScriptClientCodegen.java
AkkaScalaClientCodegen.java AkkaScalaClientCodegen.java
AndroidClientCodegen.java AndroidClientCodegen.java
AsyncScalaClientCodegen.java AsyncScalaClientCodegen.java
CSharpClientCodegen.java CSharpClientCodegen.java
CodeGenStatus.java
CsharpDotNet2ClientCodegen.java
FlashClientCodegen.java
JavaClientCodegen.java JavaClientCodegen.java
JavaInflectorServerCodegen.java
JaxRSServerCodegen.java JaxRSServerCodegen.java
NodeJSServerCodegen.java NodeJSServerCodegen.java
ObjcClientCodegen.java ObjcClientCodegen.java
@ -178,13 +207,17 @@ RetrofitClientCodegen.java
RubyClientCodegen.java RubyClientCodegen.java
ScalaClientCodegen.java ScalaClientCodegen.java
ScalatraServerCodegen.java ScalatraServerCodegen.java
SilexServerCodegen.java
SinatraServerCodegen.java
SpringMVCServerCodegen.java SpringMVCServerCodegen.java
StaticDocCodegen.java StaticDocCodegen.java
StaticHtmlGenerator.java StaticHtmlGenerator.java
SwaggerGenerator.java SwaggerGenerator.java
SwaggerYamlGenerator.java SwaggerYamlGenerator.java
SwiftGenerator.java SwiftCodegen.java
TizenClientCodegen.java TizenClientCodegen.java
TypeScriptAngularClientCodegen.java
TypeScriptNodeClientCodegen.java
``` ```
Each of these files creates reasonable defaults so you can get running quickly. But if you want to configure package names, prefixes, model folders, etc. you can use a json config file to pass the values. Each of these files creates reasonable defaults so you can get running quickly. But if you want to configure package names, prefixes, model folders, etc. you can use a json config file to pass the values.
@ -226,6 +259,12 @@ CONFIG OPTIONS
sourceFolder sourceFolder
source folder for generated code source folder for generated code
library
library template (sub-template) to use:
<default> - HTTP client: Jersey client 1.18. JSON processing: Jackson 2.4.2
jersey2 - HTTP client: Jersey client 2.6
okhttp-gson - HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1
``` ```
Your config file for java can look like Your config file for java can look like

View File

@ -18,19 +18,30 @@ if [ ! -d "${APP_DIR}" ]; then
fi fi
cd $APP_DIR cd $APP_DIR
./bin/akka-scala-petstore.sh
./bin/android-java-petstore.sh ./bin/android-java-petstore.sh
./bin/csharp-petstore.sh ./bin/csharp-petstore.sh
./bin/dynamic-html.sh ./bin/dynamic-html.sh
./bin/html-petstore.sh ./bin/html-petstore.sh
./bin/jaxrs-petstore-server.sh
./bin/java-petstore.sh ./bin/java-petstore.sh
./bin/qt5-petstore.sh ./bin/java-petstore-jersey2.sh
./bin/java-petstore-okhttp-gson.sh
./bin/jaxrs-petstore-server.sh
./bin/nodejs-petstore-server.sh
./bin/objc-petstore.sh
./bin/perl-petstore.sh ./bin/perl-petstore.sh
./bin/php-petstore.sh ./bin/php-petstore.sh
./bin/python-petstore.sh ./bin/python-petstore.sh
./bin/python3-petstore.sh
./bin/qt5-petstore.sh
./bin/retrofit-petstore.sh ./bin/retrofit-petstore.sh
./bin/ruby-petstore.sh ./bin/ruby-petstore.sh
./bin/objc-petstore.sh ./bin/scala-async-petstore.sh
./bin/scala-petstore.sh ./bin/scala-petstore.sh
./bin/scalatra-petstore-server.sh
./bin/silex-petstore-server.sh
./bin/spring-mvc-petstore-server.sh ./bin/spring-mvc-petstore-server.sh
./bin/swift-petstore.sh
./bin/tizen-petstore.sh ./bin/tizen-petstore.sh
./bin/typescript-angular-petstore.sh
./bin/typescript-node-petstore.sh

31
bin/csharp-dotnet2-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 -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l CsharpDotNet2 -o samples/client/petstore/csharp-dotnet2/SwaggerClientTest/Lib/SwaggerClient"
java $JAVA_OPTS -jar $executable $ags

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 csharp -o samples/client/petstore/csharp" ags="$@ generate -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 java $JAVA_OPTS -jar $executable $ags

31
bin/flash-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/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

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/JavaInflector -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l inflector -o samples/server/petstore/java-inflector"
java $JAVA_OPTS -jar $executable $ags

View File

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

31
bin/java-petstore-jersey2.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-jersey2.json -o samples/client/petstore/java/jersey2"
java $JAVA_OPTS -jar $executable $ags

View File

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

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-okhttp-gson.json -o samples/client/petstore/java/okhttp-gson"
java $JAVA_OPTS -jar $executable $ags

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 java -o samples/client/petstore/java" ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l java -o samples/client/petstore/java/default"
java $JAVA_OPTS -jar $executable $ags java $JAVA_OPTS -jar $executable $ags

5
bin/ruby-petstore.json Normal file
View File

@ -0,0 +1,5 @@
{
"gemName": "petstore",
"moduleName": "Petstore",
"gemVersion": "1.0.0"
}

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 -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" ags="$@ generate -t modules/swagger-codegen/src/main/resources/ruby -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l ruby -c bin/ruby-petstore.json -o samples/client/petstore/ruby"
java $JAVA_OPTS -jar $executable $ags java $JAVA_OPTS -jar $executable $ags

31
bin/silex-petstore-server.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/silex -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l silex -o samples/server/petstore/silex"
java $JAVA_OPTS -jar $executable $ags

31
bin/sinatra-petstore-server.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/sinatra -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l sinatra -o samples/server/petstore/sinatra"
java $JAVA_OPTS -jar $executable $ags

4
bin/swift-petstore.json Normal file
View File

@ -0,0 +1,4 @@
{
"projectName": "PetstoreClient",
"responseAs": "PromiseKit"
}

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 -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" ags="$@ generate -t modules/swagger-codegen/src/main/resources/swift -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l swift -c ./bin/swift-petstore.json -o samples/client/petstore/swift"
java -DappName=PetstoreClient $JAVA_OPTS -jar $executable $ags java $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 -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

31
bin/typescript-node-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 -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

View File

@ -3,7 +3,7 @@
<parent> <parent>
<groupId>io.swagger</groupId> <groupId>io.swagger</groupId>
<artifactId>swagger-codegen-project</artifactId> <artifactId>swagger-codegen-project</artifactId>
<version>2.1.2</version> <version>2.1.4-SNAPSHOT</version>
<relativePath>../..</relativePath> <relativePath>../..</relativePath>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -41,7 +41,7 @@
<version>2.3</version> <version>2.3</version>
<executions> <executions>
<execution> <execution>
<id>reduced-pom</id> <id>process-resources</id>
<phase>package</phase> <phase>package</phase>
<goals> <goals>
<goal>shade</goal> <goal>shade</goal>
@ -52,15 +52,6 @@
<dependencyReducedPomLocation> <dependencyReducedPomLocation>
${java.io.tmpdir}/dependency-reduced-pom.xml ${java.io.tmpdir}/dependency-reduced-pom.xml
</dependencyReducedPomLocation> </dependencyReducedPomLocation>
</configuration>
</execution>
<execution>
<id>process-resources</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers> <transformers>
<transformer <transformer
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
@ -79,26 +70,34 @@
<artifactId>swagger-codegen</artifactId> <artifactId>swagger-codegen</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<!--https://github.com/airlift/airline--> <!--https://github.com/airlift/airline-->
<dependency> <dependency>
<groupId>io.airlift</groupId> <groupId>io.airlift</groupId>
<artifactId>airline</artifactId> <artifactId>airline</artifactId>
<version>0.7</version> <version>0.7</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.googlecode.lambdaj</groupId> <groupId>com.googlecode.lambdaj</groupId>
<artifactId>lambdaj</artifactId> <artifactId>lambdaj</artifactId>
<version>2.3.3</version> <version>2.3.3</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId> <artifactId>slf4j-simple</artifactId>
<version>${slf4j-version}</version> <version>${slf4j-version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>${testng-version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jmockit</groupId>
<artifactId>jmockit</artifactId>
<version>${jmockit-version}</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -4,10 +4,7 @@ import io.airlift.airline.Command;
import io.airlift.airline.Option; import io.airlift.airline.Option;
import io.swagger.codegen.CliOption; import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConfigLoader;
import java.util.ServiceLoader;
import static java.util.ServiceLoader.load;
@Command(name = "config-help", description = "Config help for chosen lang") @Command(name = "config-help", description = "Config help for chosen lang")
public class ConfigHelp implements Runnable { public class ConfigHelp implements Runnable {
@ -16,36 +13,14 @@ public class ConfigHelp implements Runnable {
description = "language to get config help for") description = "language to get config help for")
private String lang; private String lang;
/**
* Tries to load config class with SPI first, then with class name directly from classpath
*
* @param name name of config, or full qualified class name in classpath
* @return config class
*/
private static CodegenConfig forName(String name) {
ServiceLoader<CodegenConfig> loader = load(CodegenConfig.class);
for (CodegenConfig config : loader) {
if (config.getName().equals(name)) {
return config;
}
}
// else try to load directly
try {
return (CodegenConfig) Class.forName(name).newInstance();
} catch (Exception e) {
throw new RuntimeException("Can't load config class with name ".concat(name), e);
}
}
@Override @Override
public void run() { public void run() {
System.out.println(); System.out.println();
CodegenConfig config = forName(lang); CodegenConfig config = CodegenConfigLoader.forName(lang);
System.out.println("CONFIG OPTIONS"); System.out.println("CONFIG OPTIONS");
for (CliOption langCliOption : config.cliOptions()) { for (CliOption langCliOption : config.cliOptions()) {
System.out.println("\t" + langCliOption.getOpt()); System.out.println("\t" + langCliOption.getOpt());
System.out.println("\t " + langCliOption.getDescription()); System.out.println("\t " + langCliOption.getDescription().replaceAll("\n", "\n\t "));
System.out.println(); System.out.println();
} }
} }

View File

@ -8,16 +8,21 @@ import io.swagger.codegen.CliOption;
import io.swagger.codegen.ClientOptInput; import io.swagger.codegen.ClientOptInput;
import io.swagger.codegen.ClientOpts; import io.swagger.codegen.ClientOpts;
import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConfigLoader;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.DefaultGenerator; import io.swagger.codegen.DefaultGenerator;
import io.swagger.codegen.cmd.utils.OptionUtils;
import io.swagger.models.Swagger; import io.swagger.models.Swagger;
import io.swagger.parser.SwaggerParser; import io.swagger.parser.SwaggerParser;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.util.ServiceLoader; import java.util.List;
import java.util.Map;
import java.util.Set;
import static java.util.ServiceLoader.load;
import static org.apache.commons.lang3.StringUtils.isNotEmpty; import static org.apache.commons.lang3.StringUtils.isNotEmpty;
/** /**
@ -31,8 +36,6 @@ public class Generate implements Runnable {
public static final Logger LOG = LoggerFactory.getLogger(Generate.class); public static final Logger LOG = LoggerFactory.getLogger(Generate.class);
public static final String TEMPLATE_DIR_PARAM = "templateDir";
@Option(name = {"-v", "--verbose"}, description = "verbose mode") @Option(name = {"-v", "--verbose"}, description = "verbose mode")
private boolean verbose; private boolean verbose;
@ -66,27 +69,46 @@ public class Generate implements Runnable {
"Supported options can be different for each language. Run config-help -l {lang} command for language specific config options.") "Supported options can be different for each language. Run config-help -l {lang} command for language specific config options.")
private String configFile; private String configFile;
/** @Option(name = {"-s", "--skip-overwrite"}, title = "skip overwrite", description = "specifies if the existing files should be " +
* Tries to load config class with SPI first, then with class name directly from classpath "overwritten during the generation.")
* private boolean skipOverwrite;
* @param name name of config, or full qualified class name in classpath
* @return config class
*/
private static CodegenConfig forName(String name) {
ServiceLoader<CodegenConfig> loader = load(CodegenConfig.class);
for (CodegenConfig config : loader) {
if (config.getName().equals(name)) {
return config;
}
}
// else try to load directly @Option(name = {"--api-package"}, title = "api package", description = CodegenConstants.API_PACKAGE_DESC)
try { private String apiPackage;
return (CodegenConfig) Class.forName(name).newInstance();
} catch (Exception e) { @Option(name = {"--model-package"}, title = "model package", description = CodegenConstants.MODEL_PACKAGE_DESC)
throw new RuntimeException("Can't load config class with name ".concat(name), e); private String modelPackage;
}
} @Option(name = {"--instantiation-types"}, title = "instantiation types", description = "sets instantiation type mappings in the format of type=instantiatedType,type=instantiatedType." +
"For example (in Java): array=ArrayList,map=HashMap. In other words array types will get instantiated as ArrayList in generated code.")
private String instantiationTypes;
@Option(name = {"--type-mappings"}, title = "type mappings", description = "sets mappings between swagger spec types and generated code types " +
"in the format of swaggerType=generatedType,swaggerType=generatedType. For example: array=List,map=Map,string=String")
private String typeMappings;
@Option(name = {"--additional-properties"}, title = "additional properties", description = "sets additional properties that can be referenced by the mustache templates in the format of name=value,name=value")
private String additionalProperties;
@Option(name = {"--language-specific-primitives"}, title = "language specific primitives",
description = "specifies additional language specific primitive types in the format of type1,type2,type3,type3. For example: String,boolean,Boolean,Double")
private String languageSpecificPrimitives;
@Option(name = {"--import-mappings"}, title = "import mappings",
description = "specifies mappings between a given class and the import that should be used for that class in the format of type=import,type=import")
private String importMappings;
@Option(name = {"--invoker-package"}, title = "invoker package", description = CodegenConstants.INVOKER_PACKAGE_DESC)
private String invokerPackage;
@Option(name = {"--group-id"}, title = "group id", description = CodegenConstants.GROUP_ID_DESC)
private String groupId;
@Option(name = {"--artifact-id"}, title = "artifact id", description = CodegenConstants.ARTIFACT_ID_DESC)
private String artifactId;
@Option(name = {"--artifact-version"}, title = "artifact version", description = CodegenConstants.ARTIFACT_VERSION_DESC)
private String artifactVersion;
@Override @Override
public void run() { public void run() {
@ -94,47 +116,92 @@ public class Generate implements Runnable {
setSystemProperties(); setSystemProperties();
ClientOptInput input = new ClientOptInput(); CodegenConfig config = CodegenConfigLoader.forName(lang);
if (isNotEmpty(auth)) {
input.setAuth(auth);
}
CodegenConfig config = forName(lang);
config.setOutputDir(new File(output).getAbsolutePath()); config.setOutputDir(new File(output).getAbsolutePath());
config.setSkipOverwrite(skipOverwrite);
if (null != templateDir) { putKeyValuePairsInMap(config.instantiationTypes(), instantiationTypes);
config.additionalProperties().put(TEMPLATE_DIR_PARAM, new File(templateDir).getAbsolutePath()); putKeyValuePairsInMap(config.typeMapping(), typeMappings);
putKeyValuePairsInMap(config.additionalProperties(), additionalProperties);
putKeyValuePairsInMap(config.importMapping(), importMappings);
addValuesToSet(config.languageSpecificPrimitives(), languageSpecificPrimitives);
checkAndSetAdditionalProperty(config, apiPackage, CodegenConstants.API_PACKAGE);
checkAndSetAdditionalProperty(config, modelPackage, CodegenConstants.MODEL_PACKAGE);
if(isNotEmpty(templateDir)) {
config.additionalProperties().put(CodegenConstants.TEMPLATE_DIR, new File(templateDir).getAbsolutePath());
} }
checkAndSetAdditionalProperty(config, invokerPackage, CodegenConstants.INVOKER_PACKAGE);
checkAndSetAdditionalProperty(config, groupId, CodegenConstants.GROUP_ID);
checkAndSetAdditionalProperty(config, artifactId, CodegenConstants.ARTIFACT_ID);
checkAndSetAdditionalProperty(config, artifactVersion, CodegenConstants.ARTIFACT_VERSION);
if (null != configFile) { if (null != configFile) {
Config genConfig = ConfigParser.read(configFile); Config genConfig = ConfigParser.read(configFile);
if (null != genConfig) { if (null != genConfig) {
for (CliOption langCliOption : config.cliOptions()) { for (CliOption langCliOption : config.cliOptions()) {
if (genConfig.hasOption(langCliOption.getOpt())) { String opt = langCliOption.getOpt();
config.additionalProperties().put(langCliOption.getOpt(), genConfig.getOption(langCliOption.getOpt())); if (genConfig.hasOption(opt)) {
config.additionalProperties().put(opt, genConfig.getOption(opt));
// the "library" config option is for library template (sub-template)
if ("library".equals(opt)) {
config.setLibrary(genConfig.getOption(opt));
}
} }
} }
} }
} }
input.setConfig(config); ClientOptInput input = new ClientOptInput().config(config);
if (isNotEmpty(auth)) {
input.setAuth(auth);
}
Swagger swagger = new SwaggerParser().read(spec, input.getAuthorizationValues(), true); Swagger swagger = new SwaggerParser().read(spec, input.getAuthorizationValues(), true);
new DefaultGenerator().opts(input.opts(new ClientOpts()).swagger(swagger)).generate(); new DefaultGenerator().opts(input.opts(new ClientOpts()).swagger(swagger)).generate();
} }
private void addValuesToSet(Set<String> set, String csvProperty) {
final List<String> values = OptionUtils.splitCommaSeparatedList(csvProperty);
for (String value : values) {
set.add(value);
}
}
private void checkAndSetAdditionalProperty(CodegenConfig config, String property, String propertyKey) {
checkAndSetAdditionalProperty(config, property, property, propertyKey);
}
private void checkAndSetAdditionalProperty(CodegenConfig config, String property, String valueToSet, String propertyKey) {
if(isNotEmpty(property)) {
config.additionalProperties().put(propertyKey, valueToSet);
}
}
private void setSystemProperties() { private void setSystemProperties() {
if (systemProperties != null && systemProperties.length() > 0) {
for (String property : systemProperties.split(",")) { final List<Pair<String, String>> systemPropertyPairs = OptionUtils.parseCommaSeparatedTuples(systemProperties);
int ix = property.indexOf('=');
if (ix > 0 && ix < property.length() - 1) { for (Pair<String, String> pair : systemPropertyPairs) {
System.setProperty(property.substring(0, ix), property.substring(ix + 1)); System.setProperty(pair.getLeft(), pair.getRight());
} }
} }
private void putKeyValuePairsInMap(Map map, String commaSeparatedKVPairs) {
final List<Pair<String, String>> pairs = OptionUtils.parseCommaSeparatedTuples(commaSeparatedKVPairs);
for (Pair<String, String> pair : pairs) {
map.put(pair.getLeft(), pair.getRight());
} }
} }
/** /**
* If true parameter, adds system properties which enables debug mode in generator * If true parameter, adds system properties which enables debug mode in generator
* *

View File

@ -0,0 +1,43 @@
package io.swagger.codegen.cmd.utils;
import org.apache.commons.lang3.tuple.Pair;
import java.util.ArrayList;
import java.util.List;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
public class OptionUtils {
public static List<Pair<String, String>> parseCommaSeparatedTuples(String input) {
List<Pair<String, String>> results = new ArrayList<Pair<String, String>>();
final List<String> tuples = splitCommaSeparatedList(input);
for (String tuple : tuples) {
int ix = tuple.indexOf('=');
if (ix > 0 && ix < tuple.length() - 1) {
final Pair<String, String> pair = Pair.of(tuple.substring(0, ix), tuple.substring(ix + 1));
results.add(pair);
}
}
return results;
}
public static List<String> splitCommaSeparatedList(String input) {
List<String> results = new ArrayList<String>();
if(input != null && !input.isEmpty()) {
for (String value : input.split(",")) {
if(isNotEmpty(value))
results.add(value);
}
}
return results;
}
}

View File

@ -0,0 +1,352 @@
package io.swagger.codegen.cmd;
import config.Config;
import config.ConfigParser;
import io.swagger.codegen.ClientOptInput;
import io.swagger.codegen.ClientOpts;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.DefaultGenerator;
import io.swagger.codegen.SwaggerCodegen;
import io.swagger.codegen.CodegenConfigLoader;
import io.swagger.codegen.languages.JavaClientCodegen;
import io.swagger.models.Swagger;
import io.swagger.models.auth.AuthorizationValue;
import io.swagger.parser.SwaggerParser;
import mockit.Expectations;
import mockit.FullVerifications;
import mockit.Injectable;
import mockit.Mocked;
import mockit.StrictExpectations;
import org.apache.commons.lang3.ArrayUtils;
import org.testng.annotations.Test;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
public class GenerateTest {
@Mocked
SwaggerParser parser;
@Injectable
Swagger swagger;
@Mocked
DefaultGenerator defaultGenerator;
@Mocked
CodegenConfigLoader codegenConfigLoader;
@Mocked
ClientOptInput clientOptInput;
@Injectable
List<AuthorizationValue> authorizationValues;
@Test
public void testVerbose_ShortArg() throws Exception {
doVerboseTest("-v");
}
@Test
public void testVerbose_LongArg() throws Exception {
doVerboseTest("--verbose");
}
@Test
public void testRequiredArgs_ShortArgs() throws Exception {
doRequiredArgsTest("-l", "-o", "-i");
}
@Test
public void testRequiredArgs_LongArgs() throws Exception {
doRequiredArgsTest("--lang", "--output", "--input-spec");
}
@Test
public void testTemplateDir() throws Exception {
final String absolutePath = new File("src").getAbsolutePath();
doSingleAdditionalPropertyTest("--template-dir", CodegenConstants.TEMPLATE_DIR, "src", absolutePath);
doSingleAdditionalPropertyTest("--template-dir", CodegenConstants.TEMPLATE_DIR, absolutePath, absolutePath);
doSingleAdditionalPropertyTest("-t", CodegenConstants.TEMPLATE_DIR, "src", absolutePath);
doSingleAdditionalPropertyTest("-t", CodegenConstants.TEMPLATE_DIR, absolutePath, absolutePath);
}
@Test
public void testAuth() throws Exception {
final String auth = "hello:world";
new StrictExpectations() {{
clientOptInput.setAuth(auth);
times = 1;
}};
setupAndRunGenericTest("-a", auth);
new StrictExpectations() {{
clientOptInput.setAuth(auth);
times = 1;
}};
setupAndRunGenericTest("--auth", auth);
}
@Test
public void testSystemProperties() throws Exception {
new StrictExpectations(System.class) {{
System.setProperty("hello", "world");
times = 1;
System.setProperty("foo", "bar");
times = 1;
}};
setupAndRunGenericTest("-D", "hello=world,foo=bar");
}
@Test
public void testConfig(@Mocked final ConfigParser parser) throws Exception {
final String configFilePath = "config.json";
final String invokerPackage = "com.foo.bar.invoker";
final String groupId = "com.foo.bar";
Map<String, String> configMap = new HashMap<String, String>();
configMap.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
configMap.put(CodegenConstants.GROUP_ID, groupId);
final Config config = new Config(configMap);
final String[] configArgs = {"-c", "--config"};
for (String configArg : configArgs) {
new StrictExpectations() {{
parser.read(configFilePath);
times = 1;
result = config;
}};
final CodegenConfig codegenConfig = setupAndRunGenericTest(configArg, configFilePath);
assertValueInMap(codegenConfig.additionalProperties(), CodegenConstants.INVOKER_PACKAGE, invokerPackage);
assertValueInMap(codegenConfig.additionalProperties(), CodegenConstants.GROUP_ID, groupId);
}
}
@Test
public void testSkipOverwrite() throws Exception {
CodegenConfig codegenConfig1 = setupAndRunGenericTest();
assertFalse(codegenConfig1.isSkipOverwrite());
CodegenConfig codegenConfig2 = setupAndRunGenericTest("-s");
assertTrue(codegenConfig2.isSkipOverwrite());
CodegenConfig codegenConfig3 = setupAndRunGenericTest("--skip-overwrite");
assertTrue(codegenConfig3.isSkipOverwrite());
}
@Test
public void testApiPackage() throws Exception {
doSingleAdditionalPropertyTest("--api-package", CodegenConstants.API_PACKAGE, "io.foo.bar.api");
}
@Test
public void testModelPackage() throws Exception {
doSingleAdditionalPropertyTest("--model-package", CodegenConstants.MODEL_PACKAGE, "io.foo.bar.models");
}
@Test
public void testInstantiationTypes() throws Exception {
final CodegenConfig codegenConfig = setupAndRunGenericTest("--instantiation-types", "foo=bar,hello=world");
assertValueInMap(codegenConfig.instantiationTypes(), "foo", "bar");
assertValueInMap(codegenConfig.instantiationTypes(), "hello", "world");
}
@Test
public void testTypeMappings() throws Exception {
final CodegenConfig codegenConfig = setupAndRunGenericTest("--type-mappings", "foo=bar,hello=world");
assertValueInMap(codegenConfig.typeMapping(), "foo", "bar");
assertValueInMap(codegenConfig.typeMapping(), "hello", "world");
}
@Test
public void testAdditionalProperties() throws Exception {
final CodegenConfig codegenConfig = setupAndRunGenericTest("--additional-properties", "foo=bar,hello=world");
assertValueInMap(codegenConfig.additionalProperties(), "foo", "bar");
assertValueInMap(codegenConfig.additionalProperties(), "hello", "world");
}
@Test
public void testLanguageSpecificPrimitives() throws Exception {
final CodegenConfig codegenConfig = setupAndRunGenericTest("--language-specific-primitives", "foo,bar,hello,world");
final Set<String> languageSpecificPrimitives = codegenConfig.languageSpecificPrimitives();
assertTrue(languageSpecificPrimitives.contains("foo"));
assertTrue(languageSpecificPrimitives.contains("bar"));
assertTrue(languageSpecificPrimitives.contains("hello"));
assertTrue(languageSpecificPrimitives.contains("world"));
}
@Test
public void testImportMappings() throws Exception {
final CodegenConfig codegenConfig = setupAndRunGenericTest("--import-mappings", "foo=bar,hello=world");
assertValueInMap(codegenConfig.importMapping(), "foo", "bar");
assertValueInMap(codegenConfig.importMapping(), "hello", "world");
}
@Test
public void testInvokerPackage() throws Exception {
doSingleAdditionalPropertyTest("--invoker-package", CodegenConstants.INVOKER_PACKAGE, "io.foo.bar.invoker");
}
@Test
public void testGroupId() throws Exception {
doSingleAdditionalPropertyTest("--group-id", CodegenConstants.GROUP_ID, "io.foo.bar");
}
@Test
public void testArtifactId() throws Exception {
doSingleAdditionalPropertyTest("--artifact-id", CodegenConstants.ARTIFACT_ID, "awesome-api");
}
@Test
public void testArtifactVersion() throws Exception {
doSingleAdditionalPropertyTest("--artifact-version", CodegenConstants.ARTIFACT_VERSION, "1.2.3");
}
private void doVerboseTest(String verboseFlag) {
new StrictExpectations(System.class) {{
System.setProperty("debugSwagger", "");
times = 1;
System.setProperty("debugModels", "");
times = 1;
System.setProperty("debugOperations", "");
times = 1;
System.setProperty("debugSupportingFiles", "");
times = 1;
}};
setupAndRunGenericTest(verboseFlag);
}
private void doRequiredArgsTest(String langFlag, String outputDirFlag, String inputSpecFlag) {
final String spec = "swagger.yaml";
final String lang = "java";
final String outputDir = "src/main/java";
final String[] args = {"generate", langFlag, lang, outputDirFlag, outputDir, inputSpecFlag, spec};
final CodegenConfig config = new JavaClientCodegen();
setupStandardExpectations(spec, lang, config);
SwaggerCodegen.main(args);
new FullVerifications() {{
}};
assertEquals(config.getOutputDir(), new File(outputDir).getAbsolutePath());
}
private void doSingleAdditionalPropertyTest(String cliArg, String additionalPropertyKey, String expectedValue) {
doSingleAdditionalPropertyTest(cliArg, additionalPropertyKey, expectedValue, expectedValue);
}
private void doSingleAdditionalPropertyTest(String cliArg, String additionalPropertyKey, String cliValue, String additionalPropertyValue) {
final CodegenConfig config = setupAndRunGenericTest(cliArg, cliValue);
assertValueInMap(config.additionalProperties(), additionalPropertyKey, additionalPropertyValue);
}
private CodegenConfig setupAndRunGenericTest(String... additionalParameters) {
final String spec = "swagger.yaml";
final String lang = "java";
final String[] commonArgs = {"generate", "-l", lang, "-o", "path/to/some/directory", "-i", spec};
String[] argsToUse = ArrayUtils.addAll(commonArgs, additionalParameters);
final CodegenConfig config = new JavaClientCodegen();
setupStandardExpectations(spec, lang, config);
SwaggerCodegen.main(argsToUse);
new FullVerifications() {{
}};
return config;
}
private void assertValueInMap(Map map, String propertyKey, String expectedPropertyValue) {
assertTrue(map.containsKey(propertyKey));
assertEquals(map.get(propertyKey), expectedPropertyValue);
}
private void setupStandardExpectations(final String spec, final String languageName, final CodegenConfig config) {
new Expectations() {{
CodegenConfigLoader.forName(languageName);
times = 1;
result = config;
new ClientOptInput();
times = 1;
result = clientOptInput;
clientOptInput.config(config);
times = 1;
result = clientOptInput;
new SwaggerParser();
times = 1;
result = parser;
clientOptInput.getAuthorizationValues();
times = 1;
result = authorizationValues;
parser.read(spec, authorizationValues, true);
times = 1;
result = swagger;
new DefaultGenerator();
times = 1;
result = defaultGenerator;
clientOptInput.opts((ClientOpts) any);
times = 1;
result = clientOptInput;
clientOptInput.swagger(swagger);
times = 1;
result = clientOptInput;
defaultGenerator.opts(clientOptInput);
times = 1;
result = defaultGenerator;
defaultGenerator.generate();
times = 1;
}};
}
}

View File

@ -0,0 +1,52 @@
package io.swagger.codegen.cmd.utils;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
public class OptionUtilsTest {
@Test
public void splitCommaSeparatedList() throws Exception {
doCommaSeparatedListTest("a,b,c", Arrays.asList("a", "b", "c"));
doCommaSeparatedListTest("a,,c", Arrays.asList("a", "c"));
doCommaSeparatedListTest("", new ArrayList<String>());
doCommaSeparatedListTest(null, new ArrayList<String>());
}
@Test
public void testParseCommaSeparatedTuples() throws Exception {
doTupleListTest("a=1,b=2,c=3", Arrays.asList(Pair.of("a", "1"), Pair.of("b", "2"), Pair.of("c", "3")));
doTupleListTest("a=1,,c=3", Arrays.asList(Pair.of("a", "1"), Pair.of("c", "3")));
doTupleListTest("a=1,xyz,c=3", Arrays.asList(Pair.of("a", "1"), Pair.of("c", "3")));
doTupleListTest("a=1,=,c=3", Arrays.asList(Pair.of("a", "1"), Pair.of("c", "3")));
doTupleListTest("", new ArrayList<Pair<String, String>>());
doTupleListTest(null, new ArrayList<Pair<String, String>>());
}
private void doTupleListTest(String input, List<Pair<String, String>> expectedResults) {
final List<Pair<String, String>> result = OptionUtils.parseCommaSeparatedTuples(input);
assertNotNull(result);
assertEquals(result.size(), expectedResults.size());
for (int i = 0; i < expectedResults.size(); i++) {
final Pair<String, String> actualPair = result.get(i);
final Pair<String, String> expected = expectedResults.get(i);
assertEquals(actualPair, expected);
}
}
private void doCommaSeparatedListTest(String csvStr, List<String> expectedResults) {
final List<String> result = OptionUtils.splitCommaSeparatedList(csvStr);
assertNotNull(result);
assertEquals(result.size(), expectedResults.size());
for (int i = 0; i < expectedResults.size(); i++) {
assertEquals(result.get(i), expectedResults.get(i));
}
}
}

View File

@ -0,0 +1,55 @@
swagger-codegen-maven-plugin
============================
A Maven plugin to support the [swagger](http://swagger.io) code generation project
Usage
============================
Add to your `build->plugins` section (default phase is `generate-sources` phase)
```xml
<plugin>
<groupId>io.swagger</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<version>${project.version}</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>src/main/resources/api.yaml</inputSpec>
<language>java</language>
<configOptions>
<sourceFolder>src/gen/java/main</sourceFolder>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
```
Followed by:
```
mvn clean compile
```
### General Configuration parameters
- `inputSpec` - swagger spec file path
- `language` - target generation language
- `output` - target output path (default is `${project.build.directory}/generated-sources/swagger`)
- `templateDirectory` - directory with mustache templates
- `addCompileSourceRoot` - add the output directory to the project as a source root (`true` by default)
- `modelPackage` - the package to use for generated model objects/classes
- `apiPackage` - the package to use for generated api objects/classes
- `invokerPackage` - the package to use for the generated invoker objects
- `configOptions` - a map of language-specific parameters (see below)
### Java-specific parameters (under configOptions)
- `sourceFolder` - the folder to use for generated sources under the output folder
- `groupId` - groupId in generated pom.xml
- `artifactId` - artifactId in generated pom.xml
- `artifactVersion` - artifact version in generated pom.xml

View File

@ -0,0 +1,87 @@
<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>
<parent>
<groupId>io.swagger</groupId>
<artifactId>swagger-codegen-project</artifactId>
<version>2.1.4-SNAPSHOT</version>
<relativePath>../..</relativePath>
</parent>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<name>swagger-codegen (maven-plugin)</name>
<packaging>maven-plugin</packaging>
<description>maven plugin to build modules from swagger codegen</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>3.2.5</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>3.2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-compat</artifactId>
<version>3.2.5</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.2.5</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-codegen</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.4</version>
<configuration>
<skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
</configuration>
<executions>
<execution>
<id>mojo-descriptor</id>
<phase>process-classes</phase>
<goals>
<goal>descriptor</goal>
</goals>
</execution>
<execution>
<id>help-goal</id>
<goals>
<goal>helpmojo</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

View File

@ -0,0 +1,16 @@
package io.swagger.codegen.plugin;
/**
* User: lanwen
* Date: 24.03.15
* Time: 14:47
*/
public final class AdditionalParams {
public static final String TEMPLATE_DIR_PARAM = "templateDir";
public static final String MODEL_PACKAGE_PARAM = "modelPackage";
public static final String API_PACKAGE_PARAM = "apiPackage";
public static final String INVOKER_PACKAGE_PARAM = "invokerPackage";
private AdditionalParams() {
}
}

View File

@ -0,0 +1,171 @@
package io.swagger.codegen.plugin;
/*
* Copyright 2001-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import io.swagger.codegen.CliOption;
import io.swagger.codegen.ClientOptInput;
import io.swagger.codegen.ClientOpts;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConfigLoader;
import io.swagger.codegen.DefaultGenerator;
import io.swagger.models.Swagger;
import io.swagger.parser.SwaggerParser;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import config.Config;
import config.ConfigParser;
import java.io.File;
import java.util.Map;
import java.util.ServiceLoader;
import static io.swagger.codegen.plugin.AdditionalParams.API_PACKAGE_PARAM;
import static io.swagger.codegen.plugin.AdditionalParams.INVOKER_PACKAGE_PARAM;
import static io.swagger.codegen.plugin.AdditionalParams.MODEL_PACKAGE_PARAM;
import static io.swagger.codegen.plugin.AdditionalParams.TEMPLATE_DIR_PARAM;
/**
* Goal which generates client/server code from a swagger json/yaml definition.
*/
@Mojo(name = "generate", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
public class CodeGenMojo extends AbstractMojo {
/**
* Location of the output directory.
*/
@Parameter(name = "output",
property = "swagger.codegen.maven.plugin.output",
defaultValue = "${project.build.directory}/generated-sources/swagger")
private File output;
/**
* Location of the swagger spec, as URL or file.
*/
@Parameter(name = "inputSpec", required = true)
private String inputSpec;
/**
* Folder containing the template files.
*/
@Parameter(name = "templateDirectory")
private File templateDirectory;
/**
* The package to use for generated model objects/classes
*/
@Parameter(name = "modelPackage")
private String modelPackage;
/**
* The package to use for generated api objects/classes
*/
@Parameter(name = "apiPackage")
private String apiPackage;
/**
* The package to use for the generated invoker objects
*/
@Parameter(name = "invokerPackage")
private String invokerPackage;
/**
* Client language to generate.
*/
@Parameter(name = "language", required = true)
private String language;
/**
* Path to separate json configuration file.
*/
@Parameter(name = "configurationFile", required = false)
private String configurationFile;
/**
* A map of language-specific parameters as passed with the -c option to the command line
*/
@Parameter(name = "configOptions")
private Map configOptions;
/**
* Add the output directory to the project as a source root, so that the
* generated java types are compiled and included in the project artifact.
*/
@Parameter(defaultValue = "true")
private boolean addCompileSourceRoot = true;
/**
* The project being built.
*/
@Parameter(readonly = true, required = true, defaultValue = "${project}")
private MavenProject project;
@Override
public void execute() throws MojoExecutionException {
Swagger swagger = new SwaggerParser().read(inputSpec);
CodegenConfig config = CodegenConfigLoader.forName(language);
config.setOutputDir(output.getAbsolutePath());
if (null != templateDirectory) {
config.additionalProperties().put(TEMPLATE_DIR_PARAM, templateDirectory.getAbsolutePath());
}
if (null != modelPackage) {
config.additionalProperties().put(MODEL_PACKAGE_PARAM, modelPackage);
}
if (null != apiPackage) {
config.additionalProperties().put(API_PACKAGE_PARAM, apiPackage);
}
if (null != invokerPackage) {
config.additionalProperties().put(INVOKER_PACKAGE_PARAM, invokerPackage);
}
if (configOptions != null) {
for (CliOption langCliOption : config.cliOptions()) {
if (configOptions.containsKey(langCliOption.getOpt())) {
config.additionalProperties().put(langCliOption.getOpt(),
configOptions.get(langCliOption.getOpt()));
}
}
}
if (null != configurationFile) {
Config genConfig = ConfigParser.read(configurationFile);
if (null != genConfig) {
for (CliOption langCliOption : config.cliOptions()) {
if (genConfig.hasOption(langCliOption.getOpt())) {
config.additionalProperties().put(langCliOption.getOpt(), genConfig.getOption(langCliOption.getOpt()));
}
}
} else {
throw new RuntimeException("Unable to read configuration file");
}
}
ClientOptInput input = new ClientOptInput().opts(new ClientOpts()).swagger(swagger);
input.setConfig(config);
new DefaultGenerator().opts(input).generate();
if (addCompileSourceRoot) {
project.addCompileSourceRoot(output.toString());
}
}
}

View File

@ -3,7 +3,7 @@
<parent> <parent>
<groupId>io.swagger</groupId> <groupId>io.swagger</groupId>
<artifactId>swagger-codegen-project</artifactId> <artifactId>swagger-codegen-project</artifactId>
<version>2.1.2</version> <version>2.1.4-SNAPSHOT</version>
<relativePath>../..</relativePath> <relativePath>../..</relativePath>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -82,10 +82,8 @@
</goals> </goals>
</execution> </execution>
</executions> </executions>
<configuration>
<configuration> <configuration>
<recompileMode>incremental</recompileMode> <recompileMode>incremental</recompileMode>
</configuration>
<jvmArgs> <jvmArgs>
<jvmArg>-Xmx384m</jvmArg> <jvmArg>-Xmx384m</jvmArg>
</jvmArgs> </jvmArgs>
@ -149,14 +147,6 @@
<artifactId>scala-maven-plugin</artifactId> <artifactId>scala-maven-plugin</artifactId>
<version>${scala-maven-plugin-version}</version> <version>${scala-maven-plugin-version}</version>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<configuration>
<releaseProfiles>release</releaseProfiles>
<goals>sign</goals>
</configuration>
</plugin>
</plugins> </plugins>
</pluginManagement> </pluginManagement>
</build> </build>
@ -180,7 +170,7 @@
</execution> </execution>
</executions> </executions>
<configuration> <configuration>
<scala-version>${scala-version}</scala-version> <scalaVersion>${scala-version}</scalaVersion>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>
@ -344,6 +334,18 @@
<version>${scala-version}</version> <version>${scala-version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>${testng-version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>${reflections-version}</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<repositories> <repositories>
<repository> <repository>

View File

@ -60,7 +60,28 @@ public abstract class AbstractGenerator {
throw new RuntimeException("can't load template " + name); throw new RuntimeException("can't load template " + name);
} }
private String getCPResourcePath(String name) { /**
* Get the template file path with template dir prepended, and use the
* library template if exists.
*/
public String getFullTemplateFile(CodegenConfig config, String templateFile) {
String library = config.getLibrary();
if (library != null && !"".equals(library)) {
String libTemplateFile = config.templateDir() + File.separator +
"libraries" + File.separator + library + File.separator +
templateFile;
if (templateExists(libTemplateFile)) {
return libTemplateFile;
}
}
return config.templateDir() + File.separator + templateFile;
}
public boolean templateExists(String name) {
return this.getClass().getClassLoader().getResource(getCPResourcePath(name)) != null;
}
public String getCPResourcePath(String name) {
if (!"/".equals(File.separator)) { if (!"/".equals(File.separator)) {
return name.replaceAll(Pattern.quote(File.separator), "/"); return name.replaceAll(Pattern.quote(File.separator), "/");
} }

View File

@ -10,7 +10,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
public class ClientOptInput { public class ClientOptInput {
protected CodegenConfig config; private CodegenConfig config;
private ClientOpts opts; private ClientOpts opts;
private Swagger swagger; private Swagger swagger;
private List<AuthorizationValue> auths; private List<AuthorizationValue> auths;
@ -25,6 +25,11 @@ public class ClientOptInput {
return this; return this;
} }
public ClientOptInput config(CodegenConfig codegenConfig) {
this.setConfig(codegenConfig);
return this;
}
public String getAuth() { public String getAuth() {
if (auths != null) { if (auths != null) {
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();

View File

@ -85,7 +85,7 @@ public class Codegen extends DefaultGenerator {
swagger = new SwaggerParser().read(cmd.getOptionValue("i"), clientOptInput.getAuthorizationValues(), true); swagger = new SwaggerParser().read(cmd.getOptionValue("i"), clientOptInput.getAuthorizationValues(), true);
} }
if (cmd.hasOption("t")) { if (cmd.hasOption("t")) {
clientOpts.getProperties().put("templateDir", String.valueOf(cmd.getOptionValue("t"))); clientOpts.getProperties().put(CodegenConstants.TEMPLATE_DIR, String.valueOf(cmd.getOptionValue("t")));
} }
} catch (Exception e) { } catch (Exception e) {
usage(options); usage(options);

View File

@ -65,6 +65,8 @@ public interface CodegenConfig {
CodegenModel fromModel(String name, Model model); CodegenModel fromModel(String name, Model model);
CodegenModel fromModel(String name, Model model, Map<String, Model> allDefinitions);
CodegenOperation fromOperation(String resourcePath, String httpMethod, Operation operation, Map<String, Model> definitions); CodegenOperation fromOperation(String resourcePath, String httpMethod, Operation operation, Map<String, Model> definitions);
List<CodegenSecurity> fromSecurity(Map<String, SecuritySchemeDefinition> schemes); List<CodegenSecurity> fromSecurity(Map<String, SecuritySchemeDefinition> schemes);
@ -81,6 +83,8 @@ public interface CodegenConfig {
Map<String, String> modelTemplateFiles(); Map<String, String> modelTemplateFiles();
Set<String> languageSpecificPrimitives();
void processSwagger(Swagger swagger); void processSwagger(Swagger swagger);
String toApiFilename(String name); String toApiFilename(String name);
@ -102,4 +106,17 @@ public interface CodegenConfig {
String apiFilename(String templateName, String tag); String apiFilename(String templateName, String tag);
boolean shouldOverwrite(String filename); boolean shouldOverwrite(String filename);
boolean isSkipOverwrite();
void setSkipOverwrite(boolean skipOverwrite);
Map<String, String> supportedLibraries();
void setLibrary(String library);
/**
* Library template (sub-template).
*/
String getLibrary();
} }

View File

@ -0,0 +1,34 @@
package io.swagger.codegen;
import java.util.ServiceLoader;
import static java.util.ServiceLoader.load;
public class CodegenConfigLoader {
/**
* Tries to load config class with SPI first, then with class name directly from classpath
*
* @param name name of config, or full qualified class name in classpath
* @return config class
*/
public static CodegenConfig forName(String name) {
ServiceLoader<CodegenConfig> loader = load(CodegenConfig.class);
StringBuilder availableConfigs = new StringBuilder();
for (CodegenConfig config : loader) {
if (config.getName().equals(name)) {
return config;
}
availableConfigs.append(config.getName()).append("\n");
}
// else try to load directly
try {
return (CodegenConfig) Class.forName(name).newInstance();
} catch (Exception e) {
throw new RuntimeException("Can't load config class with name ".concat(name) + " Available: " + availableConfigs.toString(), e);
}
}
}

View File

@ -0,0 +1,36 @@
package io.swagger.codegen;
/**
* A class for storing constants that are used throughout the project.
*/
public class CodegenConstants {
public static final String API_PACKAGE = "apiPackage";
public static final String API_PACKAGE_DESC = "package for generated api classes";
public static final String MODEL_PACKAGE = "modelPackage";
public static final String MODEL_PACKAGE_DESC = "package for generated models";
public static final String TEMPLATE_DIR = "templateDir";
public static final String INVOKER_PACKAGE = "invokerPackage";
public static final String INVOKER_PACKAGE_DESC = "root package for generated code";
public static final String GROUP_ID = "groupId";
public static final String GROUP_ID_DESC = "groupId in generated pom.xml";
public static final String ARTIFACT_ID = "artifactId";
public static final String ARTIFACT_ID_DESC = "artifactId in generated pom.xml";
public static final String ARTIFACT_VERSION = "artifactVersion";
public static final String ARTIFACT_VERSION_DESC = "artifact version in generated pom.xml";
public static final String SOURCE_FOLDER = "sourceFolder";
public static final String SOURCE_FOLDER_DESC = "source folder for generated code";
public static final String LOCAL_VARIABLE_PREFIX = "localVariablePrefix";
public static final String LOCAL_VARIABLE_PREFIX_DESC = "prefix for generated code members and local variables";
public static final String SERIALIZABLE_MODEL = "serializableModel";
public static final String SERIALIZABLE_MODEL_DESC = "boolean - toggle \"implements Serializable\" for generated models";
}

View File

@ -12,7 +12,7 @@ public class CodegenOperation {
public final List<CodegenProperty> responseHeaders = new ArrayList<CodegenProperty>(); public final List<CodegenProperty> responseHeaders = new ArrayList<CodegenProperty>();
public Boolean hasConsumes, hasProduces, hasParams, returnTypeIsPrimitive, public Boolean hasConsumes, hasProduces, hasParams, returnTypeIsPrimitive,
returnSimpleType, subresourceOperation, isMapContainer, isListContainer, returnSimpleType, subresourceOperation, isMapContainer, isListContainer,
hasMore = Boolean.TRUE, isMultipart; hasMore = Boolean.TRUE, isMultipart, isResponseBinary = Boolean.FALSE;
public String path, operationId, returnType, httpMethod, returnBaseType, public String path, operationId, returnType, httpMethod, returnBaseType,
returnContainer, summary, notes, baseName, defaultResponse; returnContainer, summary, notes, baseName, defaultResponse;
public List<Map<String, String>> consumes, produces; public List<Map<String, String>> consumes, produces;
@ -29,6 +29,24 @@ public class CodegenOperation {
public Set<String> imports = new HashSet<String>(); public Set<String> imports = new HashSet<String>();
public List<Map<String, String>> examples; public List<Map<String, String>> examples;
public ExternalDocs externalDocs; public ExternalDocs externalDocs;
public Map<String, Object> vendorExtensions;
private boolean nonempty(List<CodegenParameter> params)
{
return params != null && params.size() > 0;
}
public boolean getHasBodyParam() {
return nonempty(bodyParams);
}
public boolean getHasQueryParams() {
return nonempty(bodyParams);
}
public boolean getHasHeaderParams() {
return nonempty(bodyParams);
}
public boolean getHasPathParams() {
return nonempty(bodyParams);
}
// legacy support // legacy support
public String nickname; public String nickname;

View File

@ -1,10 +1,19 @@
package io.swagger.codegen; package io.swagger.codegen;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
public class CodegenParameter { public class CodegenParameter {
public Boolean isFormParam, isQueryParam, isPathParam, isHeaderParam, public Boolean isFormParam, isQueryParam, isPathParam, isHeaderParam,
isCookieParam, isBodyParam, isFile, notFile, hasMore, isContainer, secondaryParam; isCookieParam, isBodyParam, isFile, notFile, hasMore, isContainer, secondaryParam, isBinary;
public String baseName, paramName, dataType, collectionFormat, description, baseType, defaultValue; public String baseName, paramName, dataType, collectionFormat, description, baseType, defaultValue;
public String jsonSchema; public String jsonSchema;
public boolean isEnum;
public List<String> _enum;
public Map<String, Object> allowableValues;
public Map<String, Object> vendorExtensions;
/** /**
* Determines whether this parameter is mandatory. If the parameter is in "path", * Determines whether this parameter is mandatory. If the parameter is in "path",
@ -35,6 +44,14 @@ public class CodegenParameter {
output.required = this.required; output.required = this.required;
output.jsonSchema = this.jsonSchema; output.jsonSchema = this.jsonSchema;
output.defaultValue = this.defaultValue; output.defaultValue = this.defaultValue;
output.isEnum = this.isEnum;
if (this._enum != null) {
output._enum = new ArrayList<String>(this._enum);
}
if (this.allowableValues != null) {
output.allowableValues = new HashMap<String, Object>(this.allowableValues);
}
output.vendorExtensions = this.vendorExtensions;
return output; return output;
} }

View File

@ -34,4 +34,107 @@ public class CodegenProperty {
public boolean isEnum; public boolean isEnum;
public List<String> _enum; public List<String> _enum;
public Map<String, Object> allowableValues; public Map<String, Object> allowableValues;
public CodegenProperty items;
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final CodegenProperty other = (CodegenProperty) obj;
if ((this.baseName == null) ? (other.baseName != null) : !this.baseName.equals(other.baseName)) {
return false;
}
if ((this.complexType == null) ? (other.complexType != null) : !this.complexType.equals(other.complexType)) {
return false;
}
if ((this.getter == null) ? (other.getter != null) : !this.getter.equals(other.getter)) {
return false;
}
if ((this.setter == null) ? (other.setter != null) : !this.setter.equals(other.setter)) {
return false;
}
if ((this.description == null) ? (other.description != null) : !this.description.equals(other.description)) {
return false;
}
if ((this.datatype == null) ? (other.datatype != null) : !this.datatype.equals(other.datatype)) {
return false;
}
if ((this.datatypeWithEnum == null) ? (other.datatypeWithEnum != null) : !this.datatypeWithEnum.equals(other.datatypeWithEnum)) {
return false;
}
if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
return false;
}
if ((this.min == null) ? (other.min != null) : !this.min.equals(other.min)) {
return false;
}
if ((this.max == null) ? (other.max != null) : !this.max.equals(other.max)) {
return false;
}
if ((this.defaultValue == null) ? (other.defaultValue != null) : !this.defaultValue.equals(other.defaultValue)) {
return false;
}
if ((this.baseType == null) ? (other.baseType != null) : !this.baseType.equals(other.baseType)) {
return false;
}
if ((this.containerType == null) ? (other.containerType != null) : !this.containerType.equals(other.containerType)) {
return false;
}
if (this.maxLength != other.maxLength && (this.maxLength == null || !this.maxLength.equals(other.maxLength))) {
return false;
}
if (this.minLength != other.minLength && (this.minLength == null || !this.minLength.equals(other.minLength))) {
return false;
}
if ((this.pattern == null) ? (other.pattern != null) : !this.pattern.equals(other.pattern)) {
return false;
}
if ((this.example == null) ? (other.example != null) : !this.example.equals(other.example)) {
return false;
}
if ((this.jsonSchema == null) ? (other.jsonSchema != null) : !this.jsonSchema.equals(other.jsonSchema)) {
return false;
}
if (this.minimum != other.minimum && (this.minimum == null || !this.minimum.equals(other.minimum))) {
return false;
}
if (this.maximum != other.maximum && (this.maximum == null || !this.maximum.equals(other.maximum))) {
return false;
}
if (this.exclusiveMinimum != other.exclusiveMinimum && (this.exclusiveMinimum == null || !this.exclusiveMinimum.equals(other.exclusiveMinimum))) {
return false;
}
if (this.exclusiveMaximum != other.exclusiveMaximum && (this.exclusiveMaximum == null || !this.exclusiveMaximum.equals(other.exclusiveMaximum))) {
return false;
}
if (this.required != other.required && (this.required == null || !this.required.equals(other.required))) {
return false;
}
if (this.secondaryParam != other.secondaryParam && (this.secondaryParam == null || !this.secondaryParam.equals(other.secondaryParam))) {
return false;
}
if (this.isPrimitiveType != other.isPrimitiveType && (this.isPrimitiveType == null || !this.isPrimitiveType.equals(other.isPrimitiveType))) {
return false;
}
if (this.isContainer != other.isContainer && (this.isContainer == null || !this.isContainer.equals(other.isContainer))) {
return false;
}
if (this.isNotContainer != other.isNotContainer && (this.isNotContainer == null || !this.isNotContainer.equals(other.isNotContainer))) {
return false;
}
if (this.isEnum != other.isEnum) {
return false;
}
if (this._enum != other._enum && (this._enum == null || !this._enum.equals(other._enum))) {
return false;
}
if (this.allowableValues != other.allowableValues && (this.allowableValues == null || !this.allowableValues.equals(other.allowableValues))) {
return false;
}
return true;
}
} }

View File

@ -15,6 +15,7 @@ public class CodegenResponse {
public Boolean primitiveType; public Boolean primitiveType;
public Boolean isMapContainer; public Boolean isMapContainer;
public Boolean isListContainer; public Boolean isListContainer;
public Boolean isBinary = Boolean.FALSE;
public Object schema; public Object schema;
public String jsonSchema; public String jsonSchema;

View File

@ -1,5 +1,7 @@
package io.swagger.codegen; package io.swagger.codegen;
import java.util.Set;
public class CodegenSecurity { public class CodegenSecurity {
public String name; public String name;
public String type; public String type;
@ -7,4 +9,7 @@ public class CodegenSecurity {
// ApiKey specific // ApiKey specific
public String keyParamName; public String keyParamName;
public Boolean isKeyInQuery, isKeyInHeader; public Boolean isKeyInQuery, isKeyInHeader;
// Oauth specific
public String flow, authorizationUrl, tokenUrl;
public Set<String> scopes;
} }

View File

@ -14,6 +14,7 @@ import io.swagger.models.Swagger;
import io.swagger.models.auth.ApiKeyAuthDefinition; import io.swagger.models.auth.ApiKeyAuthDefinition;
import io.swagger.models.auth.BasicAuthDefinition; import io.swagger.models.auth.BasicAuthDefinition;
import io.swagger.models.auth.In; import io.swagger.models.auth.In;
import io.swagger.models.auth.OAuth2Definition;
import io.swagger.models.auth.SecuritySchemeDefinition; import io.swagger.models.auth.SecuritySchemeDefinition;
import io.swagger.models.parameters.BodyParameter; import io.swagger.models.parameters.BodyParameter;
import io.swagger.models.parameters.CookieParameter; import io.swagger.models.parameters.CookieParameter;
@ -26,6 +27,7 @@ import io.swagger.models.parameters.SerializableParameter;
import io.swagger.models.properties.AbstractNumericProperty; import io.swagger.models.properties.AbstractNumericProperty;
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.ByteArrayProperty;
import io.swagger.models.properties.DateProperty; import io.swagger.models.properties.DateProperty;
import io.swagger.models.properties.DateTimeProperty; import io.swagger.models.properties.DateTimeProperty;
import io.swagger.models.properties.DecimalProperty; import io.swagger.models.properties.DecimalProperty;
@ -36,6 +38,7 @@ import io.swagger.models.properties.LongProperty;
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.properties.PropertyBuilder; import io.swagger.models.properties.PropertyBuilder;
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;
@ -49,9 +52,11 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -60,7 +65,7 @@ import java.util.regex.Pattern;
public class DefaultCodegen { public class DefaultCodegen {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCodegen.class); protected static final Logger LOGGER = LoggerFactory.getLogger(DefaultCodegen.class);
protected String outputFolder = ""; protected String outputFolder = "";
protected Set<String> defaultIncludes = new HashSet<String>(); protected Set<String> defaultIncludes = new HashSet<String>();
@ -76,22 +81,27 @@ public class DefaultCodegen {
protected Map<String, Object> additionalProperties = new HashMap<String, Object>(); protected Map<String, Object> additionalProperties = new HashMap<String, Object>();
protected List<SupportingFile> supportingFiles = new ArrayList<SupportingFile>(); protected List<SupportingFile> supportingFiles = new ArrayList<SupportingFile>();
protected List<CliOption> cliOptions = new ArrayList<CliOption>(); protected List<CliOption> cliOptions = new ArrayList<CliOption>();
protected boolean skipOverwrite;
protected boolean supportsInheritance = false;
protected Map<String, String> supportedLibraries = new LinkedHashMap<String, String>();
protected String library = null;
protected Boolean sortParamsByRequiredFlag = true;
public List<CliOption> cliOptions() { public List<CliOption> cliOptions() {
return cliOptions; return cliOptions;
} }
public void processOpts() { public void processOpts() {
if (additionalProperties.containsKey("templateDir")) { if (additionalProperties.containsKey(CodegenConstants.TEMPLATE_DIR)) {
this.setTemplateDir((String) additionalProperties.get("templateDir")); this.setTemplateDir((String) additionalProperties.get(CodegenConstants.TEMPLATE_DIR));
} }
if (additionalProperties.containsKey("modelPackage")) { if (additionalProperties.containsKey(CodegenConstants.MODEL_PACKAGE)) {
this.setModelPackage((String) additionalProperties.get("modelPackage")); this.setModelPackage((String) additionalProperties.get(CodegenConstants.MODEL_PACKAGE));
} }
if (additionalProperties.containsKey("apiPackage")) { if (additionalProperties.containsKey(CodegenConstants.API_PACKAGE)) {
this.setApiPackage((String) additionalProperties.get("apiPackage")); this.setApiPackage((String) additionalProperties.get(CodegenConstants.API_PACKAGE));
} }
} }
@ -117,6 +127,7 @@ public class DefaultCodegen {
// override with any special text escaping logic // override with any special text escaping logic
public String escapeText(String input) { public String escapeText(String input) {
if (input != null) { if (input != null) {
input = input.trim();
String output = input.replaceAll("\n", "\\\\n"); String output = input.replaceAll("\n", "\\\\n");
output = output.replace("\"", "\\\""); output = output.replace("\"", "\\\"");
return output; return output;
@ -225,6 +236,11 @@ public class DefaultCodegen {
} }
public String toOperationId(String operationId) { public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
return operationId; return operationId;
} }
@ -298,6 +314,8 @@ public class DefaultCodegen {
typeMapping.put("double", "Double"); typeMapping.put("double", "Double");
typeMapping.put("object", "Object"); typeMapping.put("object", "Object");
typeMapping.put("integer", "Integer"); typeMapping.put("integer", "Integer");
typeMapping.put("ByteArray", "byte[]");
instantiationTypes = new HashMap<String, String>(); instantiationTypes = new HashMap<String, String>();
@ -320,8 +338,8 @@ public class DefaultCodegen {
importMapping.put("LocalDate", "org.joda.time.*"); importMapping.put("LocalDate", "org.joda.time.*");
importMapping.put("LocalTime", "org.joda.time.*"); importMapping.put("LocalTime", "org.joda.time.*");
cliOptions.add(new CliOption("modelPackage", "package for generated models")); cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC));
cliOptions.add(new CliOption("apiPackage", "package for generated api classes")); cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
} }
@ -378,7 +396,13 @@ public class DefaultCodegen {
public String toInstantiationType(Property p) { public String toInstantiationType(Property p) {
if (p instanceof MapProperty) { if (p instanceof MapProperty) {
MapProperty ap = (MapProperty) p; MapProperty ap = (MapProperty) p;
String inner = getSwaggerType(ap.getAdditionalProperties()); Property additionalProperties2 = ap.getAdditionalProperties();
String type = additionalProperties2.getType();
if (null == type) {
LOGGER.error("No Type defined for Additional Property " + additionalProperties2 + "\n" //
+ "\tIn Property: " + p);
}
String inner = getSwaggerType(additionalProperties2);
return instantiationTypes.get("map") + "<String, " + inner + ">"; return instantiationTypes.get("map") + "<String, " + inner + ">";
} else if (p instanceof ArrayProperty) { } else if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p; ArrayProperty ap = (ArrayProperty) p;
@ -422,14 +446,6 @@ public class DefaultCodegen {
return dp.getDefault().toString(); return dp.getDefault().toString();
} }
return "null"; return "null";
} else if (p instanceof MapProperty) {
MapProperty ap = (MapProperty) p;
String inner = getSwaggerType(ap.getAdditionalProperties());
return "new HashMap<String, " + inner + ">() ";
} else if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
String inner = getSwaggerType(ap.getItems());
return "new ArrayList<" + inner + ">() ";
} else { } else {
return "null"; return "null";
} }
@ -442,6 +458,8 @@ public class DefaultCodegen {
String datatype = null; String datatype = null;
if (p instanceof StringProperty) { if (p instanceof StringProperty) {
datatype = "string"; datatype = "string";
} else if (p instanceof ByteArrayProperty) {
datatype = "ByteArray";
} else if (p instanceof BooleanProperty) { } else if (p instanceof BooleanProperty) {
datatype = "boolean"; datatype = "boolean";
} else if (p instanceof DateProperty) { } else if (p instanceof DateProperty) {
@ -506,6 +524,10 @@ public class DefaultCodegen {
} }
public CodegenModel fromModel(String name, Model model) { public CodegenModel fromModel(String name, Model model) {
return fromModel(name, model, null);
}
public CodegenModel fromModel(String name, Model model, Map<String, Model> allDefinitions) {
CodegenModel m = CodegenModelFactory.newInstance(CodegenModelType.MODEL); CodegenModel m = CodegenModelFactory.newInstance(CodegenModelType.MODEL);
if (reservedWords.contains(name)) { if (reservedWords.contains(name)) {
m.name = escapeReservedWord(name); m.name = escapeReservedWord(name);
@ -520,17 +542,65 @@ public class DefaultCodegen {
if (model instanceof ArrayModel) { if (model instanceof ArrayModel) {
ArrayModel am = (ArrayModel) model; ArrayModel am = (ArrayModel) model;
ArrayProperty arrayProperty = new ArrayProperty(am.getItems()); ArrayProperty arrayProperty = new ArrayProperty(am.getItems());
m.hasEnums = false; // Otherwise there will be a NullPointerException in JavaClientCodegen.fromModel
addParentContainer(m, name, arrayProperty); addParentContainer(m, name, arrayProperty);
} else if (model instanceof RefModel) { } else if (model instanceof RefModel) {
// TODO // TODO
} else if (model instanceof ComposedModel) { } else if (model instanceof ComposedModel) {
final ComposedModel composed = (ComposedModel) model; final ComposedModel composed = (ComposedModel) model;
Map<String, Property> properties = new HashMap<String, Property>();
List<String> required = new ArrayList<String>();
// parent model
final RefModel parent = (RefModel) composed.getParent(); final RefModel parent = (RefModel) composed.getParent();
final String parentModel = toModelName(parent.getSimpleRef()); if (parent != null) {
m.parent = parentModel; final String parentRef = toModelName(parent.getSimpleRef());
addImport(m, parentModel); m.parent = parentRef;
final ModelImpl child = (ModelImpl) composed.getChild(); addImport(m, parentRef);
addVars(m, child.getProperties(), child.getRequired()); if (!supportsInheritance && allDefinitions != null) {
final Model parentModel = allDefinitions.get(parentRef);
if (parentModel instanceof ModelImpl) {
final ModelImpl _parent = (ModelImpl) parentModel;
if (_parent.getProperties() != null) {
properties.putAll(_parent.getProperties());
}
if (_parent.getRequired() != null) {
required.addAll(_parent.getRequired());
}
}
}
}
// interfaces (intermediate models)
if (allDefinitions != null) {
for (RefModel _interface : composed.getInterfaces()) {
final String interfaceRef = toModelName(_interface.getSimpleRef());
final Model interfaceModel = allDefinitions.get(interfaceRef);
if (interfaceModel instanceof ModelImpl) {
final ModelImpl _interfaceModel = (ModelImpl) interfaceModel;
if (_interfaceModel.getProperties() != null) {
properties.putAll(_interfaceModel.getProperties());
}
if (_interfaceModel.getRequired() != null) {
required.addAll(_interfaceModel.getRequired());
}
}
}
}
// child model (properties owned by the model itself)
Model child = composed.getChild();
if (child != null && child instanceof RefModel && allDefinitions != null) {
final String childRef = ((RefModel) child).getSimpleRef();
child = allDefinitions.get(childRef);
}
if (child != null && child instanceof ModelImpl) {
final ModelImpl _child = (ModelImpl) child;
if (_child.getProperties() != null) {
properties.putAll(_child.getProperties());
}
if (_child.getRequired() != null) {
required.addAll(_child.getRequired());
}
}
addVars(m, properties, required);
} else { } else {
ModelImpl impl = (ModelImpl) model; ModelImpl impl = (ModelImpl) model;
if (impl.getAdditionalProperties() != null) { if (impl.getAdditionalProperties() != null) {
@ -553,7 +623,7 @@ public class DefaultCodegen {
public CodegenProperty fromProperty(String name, Property p) { public CodegenProperty fromProperty(String name, Property p) {
if (p == null) { if (p == null) {
LOGGER.error("unexpected missing property for name " + null); LOGGER.error("unexpected missing property for name " + name);
return null; return null;
} }
CodegenProperty property = CodegenModelFactory.newInstance(CodegenModelType.PROPERTY); CodegenProperty property = CodegenModelFactory.newInstance(CodegenModelType.PROPERTY);
@ -583,8 +653,10 @@ public class DefaultCodegen {
if (np.getMaximum() != null) { if (np.getMaximum() != null) {
allowableValues.put("max", np.getMaximum()); allowableValues.put("max", np.getMaximum());
} }
if(allowableValues.size() > 0) {
property.allowableValues = allowableValues; property.allowableValues = allowableValues;
} }
}
if (p instanceof StringProperty) { if (p instanceof StringProperty) {
StringProperty sp = (StringProperty) p; StringProperty sp = (StringProperty) p;
@ -602,7 +674,102 @@ public class DefaultCodegen {
property.allowableValues = allowableValues; property.allowableValues = allowableValues;
} }
} }
if(p instanceof IntegerProperty) {
IntegerProperty sp = (IntegerProperty) p;
if(sp.getEnum() != null) {
List<Integer> _enum = sp.getEnum();
property._enum = new ArrayList<String>();
for(Integer i : _enum) {
property._enum.add(i.toString());
}
property.isEnum = true;
// legacy support
Map<String, Object> allowableValues = new HashMap<String, Object>();
allowableValues.put("values", _enum);
property.allowableValues = allowableValues;
}
}
if(p instanceof LongProperty) {
LongProperty sp = (LongProperty) p;
if(sp.getEnum() != null) {
List<Long> _enum = sp.getEnum();
property._enum = new ArrayList<String>();
for(Long i : _enum) {
property._enum.add(i.toString());
}
property.isEnum = true;
// legacy support
Map<String, Object> allowableValues = new HashMap<String, Object>();
allowableValues.put("values", _enum);
property.allowableValues = allowableValues;
}
}
if(p instanceof DoubleProperty) {
DoubleProperty sp = (DoubleProperty) p;
if(sp.getEnum() != null) {
List<Double> _enum = sp.getEnum();
property._enum = new ArrayList<String>();
for(Double i : _enum) {
property._enum.add(i.toString());
}
property.isEnum = true;
// legacy support
Map<String, Object> allowableValues = new HashMap<String, Object>();
allowableValues.put("values", _enum);
property.allowableValues = allowableValues;
}
}
if(p instanceof FloatProperty) {
FloatProperty sp = (FloatProperty) p;
if(sp.getEnum() != null) {
List<Float> _enum = sp.getEnum();
property._enum = new ArrayList<String>();
for(Float i : _enum) {
property._enum.add(i.toString());
}
property.isEnum = true;
// legacy support
Map<String, Object> allowableValues = new HashMap<String, Object>();
allowableValues.put("values", _enum);
property.allowableValues = allowableValues;
}
}
if(p instanceof DateProperty) {
DateProperty sp = (DateProperty) p;
if(sp.getEnum() != null) {
List<String> _enum = sp.getEnum();
property._enum = new ArrayList<String>();
for(String i : _enum) {
property._enum.add(i.toString());
}
property.isEnum = true;
// legacy support
Map<String, Object> allowableValues = new HashMap<String, Object>();
allowableValues.put("values", _enum);
property.allowableValues = allowableValues;
}
}
if(p instanceof DateTimeProperty) {
DateTimeProperty sp = (DateTimeProperty) p;
if(sp.getEnum() != null) {
List<String> _enum = sp.getEnum();
property._enum = new ArrayList<String>();
for(String i : _enum) {
property._enum.add(i.toString());
}
property.isEnum = true;
// legacy support
Map<String, Object> allowableValues = new HashMap<String, Object>();
allowableValues.put("values", _enum);
property.allowableValues = allowableValues;
}
}
property.datatype = getTypeDeclaration(p); property.datatype = getTypeDeclaration(p);
// this can cause issues for clients which don't support enums // this can cause issues for clients which don't support enums
@ -618,7 +785,7 @@ public class DefaultCodegen {
property.isContainer = true; property.isContainer = true;
property.containerType = "array"; property.containerType = "array";
ArrayProperty ap = (ArrayProperty) p; ArrayProperty ap = (ArrayProperty) p;
CodegenProperty cp = fromProperty("inner", ap.getItems()); CodegenProperty cp = fromProperty(property.name, ap.getItems());
if (cp == null) { if (cp == null) {
LOGGER.warn("skipping invalid property " + Json.pretty(p)); LOGGER.warn("skipping invalid property " + Json.pretty(p));
} else { } else {
@ -628,6 +795,12 @@ public class DefaultCodegen {
} else { } else {
property.isPrimitiveType = true; property.isPrimitiveType = true;
} }
property.items = cp;
if (property.items.isEnum) {
property.datatypeWithEnum = property.datatypeWithEnum.replace(property.items.baseType,
property.items.datatypeWithEnum);
property.defaultValue = property.defaultValue.replace(property.items.baseType, property.items.datatypeWithEnum);
}
} }
} else if (p instanceof MapProperty) { } else if (p instanceof MapProperty) {
property.isContainer = true; property.isContainer = true;
@ -675,6 +848,7 @@ public class DefaultCodegen {
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, Map<String, Model> definitions) { public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, Map<String, Model> definitions) {
CodegenOperation op = CodegenModelFactory.newInstance(CodegenModelType.OPERATION); CodegenOperation op = CodegenModelFactory.newInstance(CodegenModelType.OPERATION);
Set<String> imports = new HashSet<String>(); Set<String> imports = new HashSet<String>();
op.vendorExtensions = operation.getVendorExtensions();
String operationId = operation.getOperationId(); String operationId = operation.getOperationId();
if (operationId == null) { if (operationId == null) {
@ -699,7 +873,7 @@ public class DefaultCodegen {
} }
} }
operationId = builder.toString(); operationId = builder.toString();
LOGGER.warn("generated operationId " + operationId); LOGGER.info("generated operationId " + operationId + "\tfor Path: " + httpMethod + " " + path);
} }
operationId = removeNonNameElementToCamelCase(operationId); operationId = removeNonNameElementToCamelCase(operationId);
op.path = path; op.path = path;
@ -758,6 +932,9 @@ public class DefaultCodegen {
} }
r.isDefault = response == methodResponse; r.isDefault = response == methodResponse;
op.responses.add(r); op.responses.add(r);
if (r.isBinary && r.isDefault){
op.isResponseBinary = Boolean.TRUE;
}
} }
op.responses.get(op.responses.size() - 1).hasMore = false; op.responses.get(op.responses.size() - 1).hasMore = false;
@ -850,6 +1027,20 @@ public class DefaultCodegen {
} }
op.bodyParam = bodyParam; op.bodyParam = bodyParam;
op.httpMethod = httpMethod.toUpperCase(); op.httpMethod = httpMethod.toUpperCase();
// move "required" parameters in front of "optional" parameters
if(sortParamsByRequiredFlag) {
Collections.sort(allParams, new Comparator<CodegenParameter>() {
@Override
public int compare(CodegenParameter one, CodegenParameter another) {
boolean oneRequired = one.required == null ? false : one.required;
boolean anotherRequired = another.required == null ? false : another.required;
if (oneRequired == anotherRequired) return 0;
else if (oneRequired) return -1;
else return 1;
}
});
}
op.allParams = addHasMore(allParams); op.allParams = addHasMore(allParams);
op.bodyParams = addHasMore(bodyParams); op.bodyParams = addHasMore(bodyParams);
op.pathParams = addHasMore(pathParams); op.pathParams = addHasMore(pathParams);
@ -899,6 +1090,7 @@ public class DefaultCodegen {
} }
} }
r.dataType = cm.datatype; r.dataType = cm.datatype;
r.isBinary = cm.datatype.equals("byte[]");
if (cm.isContainer != null) { if (cm.isContainer != null) {
r.simpleType = false; r.simpleType = false;
r.containerType = cm.containerType; r.containerType = cm.containerType;
@ -927,6 +1119,10 @@ public class DefaultCodegen {
} }
p.jsonSchema = Json.pretty(param); p.jsonSchema = Json.pretty(param);
if (System.getProperty("debugParser") != null) {
LOGGER.info("working on Parameter " + param);
}
// move the defaultValue for headers, forms and params // move the defaultValue for headers, forms and params
if (param instanceof QueryParameter) { if (param instanceof QueryParameter) {
p.defaultValue = ((QueryParameter) param).getDefaultValue(); p.defaultValue = ((QueryParameter) param).getDefaultValue();
@ -936,11 +1132,17 @@ public class DefaultCodegen {
p.defaultValue = ((FormParameter) param).getDefaultValue(); p.defaultValue = ((FormParameter) param).getDefaultValue();
} }
p.vendorExtensions = param.getVendorExtensions();
if (param instanceof SerializableParameter) { if (param instanceof SerializableParameter) {
SerializableParameter qp = (SerializableParameter) param; SerializableParameter qp = (SerializableParameter) param;
Property property = null; Property property = null;
String collectionFormat = null; String collectionFormat = null;
if ("array".equals(qp.getType())) { String type = qp.getType();
if (null == type) {
LOGGER.warn("Type is NULL for Serializable Parameter: " + param);
}
if ("array".equals(type)) {
Property inner = qp.getItems(); Property inner = qp.getItems();
if (inner == null) { if (inner == null) {
LOGGER.warn("warning! No inner type supplied for array parameter \"" + qp.getName() + "\", using String"); LOGGER.warn("warning! No inner type supplied for array parameter \"" + qp.getName() + "\", using String");
@ -952,7 +1154,7 @@ public class DefaultCodegen {
p.baseType = pr.datatype; p.baseType = pr.datatype;
p.isContainer = true; p.isContainer = true;
imports.add(pr.baseType); imports.add(pr.baseType);
} else if ("object".equals(qp.getType())) { } else if ("object".equals(type)) {
Property inner = qp.getItems(); Property inner = qp.getItems();
if (inner == null) { if (inner == null) {
LOGGER.warn("warning! No inner type supplied for map parameter \"" + qp.getName() + "\", using String"); LOGGER.warn("warning! No inner type supplied for map parameter \"" + qp.getName() + "\", using String");
@ -964,22 +1166,32 @@ public class DefaultCodegen {
p.baseType = pr.datatype; p.baseType = pr.datatype;
imports.add(pr.baseType); imports.add(pr.baseType);
} else { } else {
property = PropertyBuilder.build(qp.getType(), qp.getFormat(), null); Map<PropertyId, Object> args = new HashMap<PropertyId, Object>();
String format = qp.getFormat();
args.put(PropertyId.ENUM, qp.getEnum());
property = PropertyBuilder.build(type, format, args);
} }
if (property == null) { if (property == null) {
LOGGER.warn("warning! Property type \"" + qp.getType() + "\" not found for parameter \"" + param.getName() + "\", using String"); LOGGER.warn("warning! Property type \"" + type + "\" not found for parameter \"" + param.getName() + "\", using String");
property = new StringProperty().description("//TODO automatically added by swagger-codegen. Type was " + qp.getType() + " but not supported"); property = new StringProperty().description("//TODO automatically added by swagger-codegen. Type was " + type + " but not supported");
} }
property.setRequired(param.getRequired()); property.setRequired(param.getRequired());
CodegenProperty model = fromProperty(qp.getName(), property); CodegenProperty model = fromProperty(qp.getName(), property);
p.collectionFormat = collectionFormat;
p.dataType = model.datatype; p.dataType = model.datatype;
p.isEnum = model.isEnum;
p._enum = model._enum;
p.allowableValues = model.allowableValues;
p.collectionFormat = collectionFormat;
p.paramName = toParamName(qp.getName()); p.paramName = toParamName(qp.getName());
if (model.complexType != null) { if (model.complexType != null) {
imports.add(model.complexType); imports.add(model.complexType);
} }
} else { } else {
if (!(param instanceof BodyParameter)) {
LOGGER.error("Cannot use Parameter " + param + " as Body Parameter");
}
BodyParameter bp = (BodyParameter) param; BodyParameter bp = (BodyParameter) param;
Model model = bp.getSchema(); Model model = bp.getSchema();
@ -990,12 +1202,17 @@ public class DefaultCodegen {
p.dataType = getTypeDeclaration(cm.classname); p.dataType = getTypeDeclaration(cm.classname);
imports.add(p.dataType); imports.add(p.dataType);
} else { } else {
// TODO: missing format, so this will not always work Property prop = PropertyBuilder.build(impl.getType(), impl.getFormat(), null);
Property prop = PropertyBuilder.build(impl.getType(), null, null);
prop.setRequired(bp.getRequired()); prop.setRequired(bp.getRequired());
CodegenProperty cp = fromProperty("property", prop); CodegenProperty cp = fromProperty("property", prop);
if (cp != null) { if (cp != null) {
p.dataType = cp.datatype; p.dataType = cp.datatype;
if (p.dataType.equals("byte[]")) {
p.isBinary = true;
}
else {
p.isBinary = false;
}
} }
} }
} else if (model instanceof ArrayModel) { } else if (model instanceof ArrayModel) {
@ -1056,10 +1273,17 @@ public class DefaultCodegen {
sec.keyParamName = apiKeyDefinition.getName(); sec.keyParamName = apiKeyDefinition.getName();
sec.isKeyInHeader = apiKeyDefinition.getIn() == In.HEADER; sec.isKeyInHeader = apiKeyDefinition.getIn() == In.HEADER;
sec.isKeyInQuery = !sec.isKeyInHeader; sec.isKeyInQuery = !sec.isKeyInHeader;
} else if(schemeDefinition instanceof BasicAuthDefinition) {
sec.isKeyInHeader = sec.isKeyInQuery = sec.isApiKey = sec.isOAuth = false;
sec.isBasic = true;
} else { } else {
sec.isKeyInHeader = sec.isKeyInQuery = sec.isApiKey = false; final OAuth2Definition oauth2Definition = (OAuth2Definition) schemeDefinition;
sec.isBasic = schemeDefinition instanceof BasicAuthDefinition; sec.isKeyInHeader = sec.isKeyInQuery = sec.isApiKey = sec.isBasic = false;
sec.isOAuth = !sec.isBasic; sec.isOAuth = true;
sec.flow = oauth2Definition.getFlow();
sec.authorizationUrl = oauth2Definition.getAuthorizationUrl();
sec.tokenUrl = oauth2Definition.getTokenUrl();
sec.scopes = oauth2Definition.getScopes().keySet();
} }
sec.hasMore = it.hasNext(); sec.hasMore = it.hasNext();
@ -1146,7 +1370,9 @@ public class DefaultCodegen {
if (mappedType != null) { if (mappedType != null) {
addImport(m, mappedType); addImport(m, mappedType);
} }
} /** }
/**
* Underscore the given word. * Underscore the given word.
* *
* @param word The word * @param word The word
@ -1208,10 +1434,9 @@ public class DefaultCodegen {
} else { } else {
m.emptyVars = true; m.emptyVars = true;
} }
} public static String camelize(String word) {
return camelize(word, false);
} }
/** /**
* Remove characters not suitable for variable or method name from the input and camelize it * Remove characters not suitable for variable or method name from the input and camelize it
* *
@ -1231,7 +1456,13 @@ public class DefaultCodegen {
name = name.substring(0, 1).toLowerCase() + name.substring(1); name = name.substring(0, 1).toLowerCase() + name.substring(1);
} }
return name; return name;
} public static String camelize(String word, boolean lowercaseFirstLetter) { }
public static String camelize(String word) {
return camelize(word, false);
}
public static String camelize(String word, boolean lowercaseFirstLetter) {
// Replace all slashes with dots (package separator) // Replace all slashes with dots (package separator)
Pattern p = Pattern.compile("\\/(.?)"); Pattern p = Pattern.compile("\\/(.?)");
Matcher m = p.matcher(word); Matcher m = p.matcher(word);
@ -1294,6 +1525,81 @@ public class DefaultCodegen {
} }
public boolean shouldOverwrite(String filename) { public boolean shouldOverwrite(String filename) {
return true; return !(skipOverwrite && new File(filename).exists());
}
public boolean isSkipOverwrite() {
return skipOverwrite;
}
public void setSkipOverwrite(boolean skipOverwrite) {
this.skipOverwrite = skipOverwrite;
}
/**
* All library templates supported.
* (key: library name, value: library description)
*/
public Map<String, String> supportedLibraries() {
return supportedLibraries;
}
public void setLibrary(String library) {
if (library != null && !supportedLibraries.containsKey(library))
throw new RuntimeException("unknown library: " + library);
this.library = library;
}
/**
* Library template (sub-template).
*/
public String getLibrary() {
return library;
}
protected CliOption buildLibraryCliOption(Map<String, String> supportedLibraries) {
StringBuilder sb = new StringBuilder("library template (sub-template) to use:");
for (String lib : supportedLibraries.keySet()) {
sb.append("\n").append(lib).append(" - ").append(supportedLibraries.get(lib));
}
return new CliOption("library", sb.toString());
}
/**
* sanitize name (parameter, property, method, etc)
*
* @param name string to be sanitize
* @return sanitized string
*/
public String sanitizeName(String name) {
// NOTE: performance wise, we should have written with 2 replaceAll to replace desired
// character with _ or empty character. Below aims to spell out different cases we've
// encountered so far and hopefully make it easier for others to add more special
// cases in the future.
// input[] => input
name = name.replaceAll("\\[\\]", "");
// input[a][b] => input_a_b
name = name.replaceAll("\\[", "_");
name = name.replaceAll("\\]", "");
// input(a)(b) => input_a_b
name = name.replaceAll("\\(", "_");
name = name.replaceAll("\\)", "");
// input.name => input_name
name = name.replaceAll("\\.", "_");
// input-name => input_name
name = name.replaceAll("-", "_");
// input name and age => input_name_and_age
name = name.replaceAll(" ", "_");
// remove everything else other than word, number and _
// $php_variable => php_variable
return name.replaceAll("[^a-zA-Z0-9_]", "");
} }
} }

View File

@ -1,7 +1,12 @@
package io.swagger.codegen; package io.swagger.codegen;
import static org.apache.commons.lang3.StringUtils.capitalize;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
import com.samskivert.mustache.Mustache; import com.samskivert.mustache.Mustache;
import com.samskivert.mustache.Template; import com.samskivert.mustache.Template;
import io.swagger.codegen.languages.CodeGenStatus;
import io.swagger.models.ComposedModel;
import io.swagger.models.Contact; import io.swagger.models.Contact;
import io.swagger.models.Info; import io.swagger.models.Info;
import io.swagger.models.License; import io.swagger.models.License;
@ -9,9 +14,14 @@ import io.swagger.models.Model;
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;
import io.swagger.models.auth.OAuth2Definition;
import io.swagger.models.auth.SecuritySchemeDefinition; import io.swagger.models.auth.SecuritySchemeDefinition;
import io.swagger.models.parameters.Parameter;
import io.swagger.util.Json; import io.swagger.util.Json;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -20,6 +30,8 @@ import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.Reader; import java.io.Reader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@ -28,14 +40,16 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import static org.apache.commons.lang3.StringUtils.capitalize;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
public class DefaultGenerator extends AbstractGenerator implements Generator { public class DefaultGenerator extends AbstractGenerator implements Generator {
Logger LOGGER = LoggerFactory.getLogger(DefaultGenerator.class);
protected CodegenConfig config; protected CodegenConfig config;
protected ClientOptInput opts = null; protected ClientOptInput opts = null;
protected Swagger swagger = null; protected Swagger swagger = null;
public CodeGenStatus status = CodeGenStatus.UNRUN;
@Override
public Generator opts(ClientOptInput opts) { public Generator opts(ClientOptInput opts) {
this.opts = opts; this.opts = opts;
@ -46,6 +60,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
return this; return this;
} }
@Override
public List<File> generate() { public List<File> generate() {
if (swagger == null || config == null) { if (swagger == null || config == null) {
throw new RuntimeException("missing swagger input or config!"); throw new RuntimeException("missing swagger input or config!");
@ -56,6 +71,10 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
List<File> files = new ArrayList<File>(); List<File> files = new ArrayList<File>();
try { try {
config.processOpts(); config.processOpts();
config.additionalProperties().put("generatedDate", DateTime.now().toString());
config.additionalProperties().put("generatorClass", config.getClass().toString());
if (swagger.getInfo() != null) { if (swagger.getInfo() != null) {
Info info = swagger.getInfo(); Info info = swagger.getInfo();
if (info.getTitle() != null) { if (info.getTitle() != null) {
@ -105,10 +124,8 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
} }
if (swagger.getBasePath() != null) { if (swagger.getBasePath() != null) {
hostBuilder.append(swagger.getBasePath()); hostBuilder.append(swagger.getBasePath());
} else {
hostBuilder.append("/");
} }
String contextPath = swagger.getBasePath() == null ? "/" : swagger.getBasePath(); String contextPath = swagger.getBasePath() == null ? "" : swagger.getBasePath();
String basePath = hostBuilder.toString(); String basePath = hostBuilder.toString();
@ -118,11 +135,13 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
// models // models
Map<String, Model> definitions = swagger.getDefinitions(); Map<String, Model> definitions = swagger.getDefinitions();
if (definitions != null) { if (definitions != null) {
for (String name : definitions.keySet()) { List<String> sortedModelKeys = sortModelsByInheritance(definitions);
for (String name : sortedModelKeys) {
Model model = definitions.get(name); Model model = definitions.get(name);
Map<String, Model> modelMap = new HashMap<String, Model>(); Map<String, Model> modelMap = new HashMap<String, Model>();
modelMap.put(name, model); modelMap.put(name, model);
Map<String, Object> models = processModels(config, modelMap); Map<String, Object> models = processModels(config, modelMap, definitions);
models.putAll(config.additionalProperties()); models.putAll(config.additionalProperties());
allModels.add(((List<Object>) models.get("models")).get(0)); allModels.add(((List<Object>) models.get("models")).get(0));
@ -130,9 +149,14 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
for (String templateName : config.modelTemplateFiles().keySet()) { for (String templateName : config.modelTemplateFiles().keySet()) {
String suffix = config.modelTemplateFiles().get(templateName); String suffix = config.modelTemplateFiles().get(templateName);
String filename = config.modelFileFolder() + File.separator + config.toModelFilename(name) + suffix; String filename = config.modelFileFolder() + File.separator + config.toModelFilename(name) + suffix;
String template = readTemplate(config.templateDir() + File.separator + templateName); if (!config.shouldOverwrite(filename)) {
continue;
}
String templateFile = getFullTemplateFile(config, templateName);
String template = readTemplate(templateFile);
Template tmpl = Mustache.compiler() Template tmpl = Mustache.compiler()
.withLoader(new Mustache.TemplateLoader() { .withLoader(new Mustache.TemplateLoader() {
@Override
public Reader getTemplate(String name) { public Reader getTemplate(String name) {
return getTemplateReader(config.templateDir() + File.separator + name + ".mustache"); return getTemplateReader(config.templateDir() + File.separator + name + ".mustache");
} }
@ -178,13 +202,15 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
for (String templateName : config.apiTemplateFiles().keySet()) { for (String templateName : config.apiTemplateFiles().keySet()) {
String filename = config.apiFilename(templateName, tag); String filename = config.apiFilename(templateName, tag);
if (new File(filename).exists() && !config.shouldOverwrite(filename)) { if (!config.shouldOverwrite(filename) && new File(filename).exists()) {
continue; continue;
} }
String template = readTemplate(config.templateDir() + File.separator + templateName); String templateFile = getFullTemplateFile(config, templateName);
String template = readTemplate(templateFile);
Template tmpl = Mustache.compiler() Template tmpl = Mustache.compiler()
.withLoader(new Mustache.TemplateLoader() { .withLoader(new Mustache.TemplateLoader() {
@Override
public Reader getTemplate(String name) { public Reader getTemplate(String name) {
return getTemplateReader(config.templateDir() + File.separator + name + ".mustache"); return getTemplateReader(config.templateDir() + File.separator + name + ".mustache");
} }
@ -218,7 +244,11 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
bundle.put("models", allModels); bundle.put("models", allModels);
bundle.put("apiFolder", config.apiPackage().replace('.', File.separatorChar)); bundle.put("apiFolder", config.apiPackage().replace('.', File.separatorChar));
bundle.put("modelPackage", config.modelPackage()); bundle.put("modelPackage", config.modelPackage());
bundle.put("authMethods", config.fromSecurity(swagger.getSecurityDefinitions())); List<CodegenSecurity> authMethods = config.fromSecurity(swagger.getSecurityDefinitions());
if (authMethods != null && !authMethods.isEmpty()) {
bundle.put("authMethods", authMethods);
bundle.put("hasAuthMethods", true);
}
if (swagger.getExternalDocs() != null) { if (swagger.getExternalDocs() != null) {
bundle.put("externalDocs", swagger.getExternalDocs()); bundle.put("externalDocs", swagger.getExternalDocs());
} }
@ -245,11 +275,17 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
of.mkdirs(); of.mkdirs();
} }
String outputFilename = outputFolder + File.separator + support.destinationFilename; String outputFilename = outputFolder + File.separator + support.destinationFilename;
if (!config.shouldOverwrite(outputFilename)) {
continue;
}
if (support.templateFile.endsWith("mustache")) { String templateFile = getFullTemplateFile(config, support.templateFile);
String template = readTemplate(config.templateDir() + File.separator + support.templateFile);
if (templateFile.endsWith("mustache")) {
String template = readTemplate(templateFile);
Template tmpl = Mustache.compiler() Template tmpl = Mustache.compiler()
.withLoader(new Mustache.TemplateLoader() { .withLoader(new Mustache.TemplateLoader() {
@Override
public Reader getTemplate(String name) { public Reader getTemplate(String name) {
return getTemplateReader(config.templateDir() + File.separator + name + ".mustache"); return getTemplateReader(config.templateDir() + File.separator + name + ".mustache");
} }
@ -263,20 +299,21 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
InputStream in = null; InputStream in = null;
try { try {
in = new FileInputStream(config.templateDir() + File.separator + support.templateFile); in = new FileInputStream(templateFile);
} catch (Exception e) { } catch (Exception e) {
// continue // continue
} }
if (in == null) { if (in == null) {
in = this.getClass().getClassLoader().getResourceAsStream(config.templateDir() + File.separator + support.templateFile); in = this.getClass().getClassLoader().getResourceAsStream(getCPResourcePath(templateFile));
} }
File outputFile = new File(outputFilename); File outputFile = new File(outputFilename);
OutputStream out = new FileOutputStream(outputFile, false); OutputStream out = new FileOutputStream(outputFile, false);
if (in != null && out != null) { if (in != null && out != null) {
System.out.println("writing file " + outputFile);
IOUtils.copy(in, out); IOUtils.copy(in, out);
} else { } else {
if (in == null) { if (in == null) {
System.out.println("can't open " + config.templateDir() + File.separator + support.templateFile + " for input"); System.out.println("can't open " + templateFile + " for input");
} }
if (out == null) { if (out == null) {
System.out.println("can't open " + outputFile + " for output"); System.out.println("can't open " + outputFile + " for output");
@ -288,8 +325,10 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
} }
config.processSwagger(swagger); config.processSwagger(swagger);
status = CodeGenStatus.SUCCESSFUL;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); status = CodeGenStatus.FAILED;
} }
return files; return files;
} }
@ -315,17 +354,63 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
} }
} }
private List<String> sortModelsByInheritance(final Map<String, Model> definitions) {
List<String> sortedModelKeys = new ArrayList<String>(definitions.keySet());
Comparator<String> cmp = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
Model model1 = definitions.get(o1);
Model model2 = definitions.get(o2);
int model1InheritanceDepth = getInheritanceDepth(model1);
int model2InheritanceDepth = getInheritanceDepth(model2);
if (model1InheritanceDepth == model2InheritanceDepth) {
return 0;
} else if (model1InheritanceDepth > model2InheritanceDepth) {
return 1;
} else {
return -1;
}
}
private int getInheritanceDepth(Model model) {
int inheritanceDepth = 0;
Model parent = getParent(model);
while (parent != null) {
inheritanceDepth++;
parent = getParent(parent);
}
return inheritanceDepth;
}
private Model getParent(Model model) {
if (model instanceof ComposedModel) {
return definitions.get(((ComposedModel) model).getParent().getReference());
}
return null;
}
};
Collections.sort(sortedModelKeys, cmp);
return sortedModelKeys;
}
public Map<String, List<CodegenOperation>> processPaths(Map<String, Path> paths) { public Map<String, List<CodegenOperation>> processPaths(Map<String, Path> paths) {
Map<String, List<CodegenOperation>> ops = new HashMap<String, List<CodegenOperation>>(); Map<String, List<CodegenOperation>> ops = new HashMap<String, List<CodegenOperation>>();
for (String resourcePath : paths.keySet()) { for (String resourcePath : paths.keySet()) {
Path path = paths.get(resourcePath); Path path = paths.get(resourcePath);
processOperation(resourcePath, "get", path.getGet(), ops); processOperation(resourcePath, "get", path.getGet(), ops, path);
processOperation(resourcePath, "put", path.getPut(), ops); processOperation(resourcePath, "put", path.getPut(), ops, path);
processOperation(resourcePath, "post", path.getPost(), ops); processOperation(resourcePath, "post", path.getPost(), ops, path);
processOperation(resourcePath, "delete", path.getDelete(), ops); processOperation(resourcePath, "delete", path.getDelete(), ops, path);
processOperation(resourcePath, "patch", path.getPatch(), ops); processOperation(resourcePath, "patch", path.getPatch(), ops, path);
processOperation(resourcePath, "options", path.getOptions(), ops); processOperation(resourcePath, "options", path.getOptions(), ops, path);
} }
return ops; return ops;
} }
@ -338,17 +423,43 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
return map.get(name); return map.get(name);
} }
public void processOperation(String resourcePath, String httpMethod, Operation operation, Map<String, List<CodegenOperation>> operations, Path path) {
public void processOperation(String resourcePath, String httpMethod, Operation operation, Map<String, List<CodegenOperation>> operations) {
if (operation != null) { if (operation != null) {
if (System.getProperty("debugOperations") != null) {
LOGGER.debug("processOperation: resourcePath= " + resourcePath + "\t;" + httpMethod + " " + operation + "\n");
}
List<String> tags = operation.getTags(); List<String> tags = operation.getTags();
if (tags == null) { if (tags == null) {
tags = new ArrayList<String>(); tags = new ArrayList<String>();
tags.add("default"); tags.add("default");
} }
/*
build up a set of parameter "ids" defined at the operation level
per the swagger 2.0 spec "A unique parameter is defined by a combination of a name and location"
i'm assuming "location" == "in"
*/
Set<String> operationParameters = new HashSet<String>();
if (operation.getParameters() != null) {
for (Parameter parameter : operation.getParameters()) {
operationParameters.add(generateParameterId(parameter));
}
}
//need to propagate path level down to the operation
if(path.getParameters() != null) {
for (Parameter parameter : path.getParameters()) {
//skip propagation if a parameter with the same name is already defined at the operation level
if (!operationParameters.contains(generateParameterId(parameter))) {
operation.addParameter(parameter);
}
}
}
for (String tag : tags) { for (String tag : tags) {
CodegenOperation co = config.fromOperation(resourcePath, httpMethod, operation, swagger.getDefinitions()); CodegenOperation co = null;
try {
co = config.fromOperation(resourcePath, httpMethod, operation, swagger.getDefinitions());
co.tags = new ArrayList<String>(); co.tags = new ArrayList<String>();
co.tags.add(sanitizeTag(tag)); co.tags.add(sanitizeTag(tag));
config.addOperationToGroup(sanitizeTag(tag), resourcePath, operation, co, operations); config.addOperationToGroup(sanitizeTag(tag), resourcePath, operation, co, operations);
@ -366,15 +477,42 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
String securityName = security.keySet().iterator().next(); String securityName = security.keySet().iterator().next();
SecuritySchemeDefinition securityDefinition = fromSecurity(securityName); SecuritySchemeDefinition securityDefinition = fromSecurity(securityName);
if (securityDefinition != null) { if (securityDefinition != null) {
if(securityDefinition instanceof OAuth2Definition) {
OAuth2Definition oauth2Definition = (OAuth2Definition) securityDefinition;
OAuth2Definition oauth2Operation = new OAuth2Definition();
oauth2Operation.setType(oauth2Definition.getType());
oauth2Operation.setAuthorizationUrl(oauth2Definition.getAuthorizationUrl());
oauth2Operation.setFlow(oauth2Definition.getFlow());
oauth2Operation.setTokenUrl(oauth2Definition.getTokenUrl());
for (String scope : security.values().iterator().next()) {
if (oauth2Definition.getScopes().containsKey(scope)) {
oauth2Operation.addScope(scope, oauth2Definition.getScopes().get(scope));
}
}
authMethods.put(securityName, oauth2Operation);
} else {
authMethods.put(securityName, securityDefinition); authMethods.put(securityName, securityDefinition);
} }
} }
}
if (!authMethods.isEmpty()) { if (!authMethods.isEmpty()) {
co.authMethods = config.fromSecurity(authMethods); co.authMethods = config.fromSecurity(authMethods);
} }
} }
catch (Exception ex) {
LOGGER.error("Error while trying to get Config from Operation for tag(" + tag + ")\n" //
+ "\tResource: " + httpMethod + " " + resourcePath + "\n"//
+ "\tOperation:" + operation + "\n" //
+ "\tDefinitions: " + swagger.getDefinitions() + "\n");
ex.printStackTrace();
} }
} }
}
}
private String generateParameterId(Parameter parameter) {
return parameter.getName() + ":" + parameter.getIn();
}
protected String sanitizeTag(String tag) { protected String sanitizeTag(String tag) {
// remove spaces and make strong case // remove spaces and make strong case
@ -392,6 +530,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
Map<String, Object> operations = new HashMap<String, Object>(); Map<String, Object> operations = new HashMap<String, Object>();
Map<String, Object> objs = new HashMap<String, Object>(); Map<String, Object> objs = new HashMap<String, Object>();
objs.put("classname", config.toApiName(tag)); objs.put("classname", config.toApiName(tag));
objs.put("pathPrefix", config.toApiVarName(tag));
// check for operationId uniqueness // check for operationId uniqueness
Set<String> opIds = new HashSet<String>(); Set<String> opIds = new HashSet<String>();
@ -429,6 +568,12 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
} }
operations.put("imports", imports); operations.put("imports", imports);
// add a flag to indicate whether there's any {{import}}
if (imports.size() > 0) {
operations.put("hasImport", true);
}
config.postProcessOperations(operations); config.postProcessOperations(operations);
if (objs.size() > 0) { if (objs.size() > 0) {
List<CodegenOperation> os = (List<CodegenOperation>) objs.get("operation"); List<CodegenOperation> os = (List<CodegenOperation>) objs.get("operation");
@ -441,14 +586,14 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
return operations; return operations;
} }
public Map<String, Object> processModels(CodegenConfig config, Map<String, Model> definitions) { public Map<String, Object> processModels(CodegenConfig config, Map<String, Model> definitions, Map<String, Model> allDefinitions) {
Map<String, Object> objs = new HashMap<String, Object>(); Map<String, Object> objs = new HashMap<String, Object>();
objs.put("package", config.modelPackage()); objs.put("package", config.modelPackage());
List<Object> models = new ArrayList<Object>(); List<Object> models = new ArrayList<Object>();
Set<String> allImports = new LinkedHashSet<String>(); Set<String> allImports = new LinkedHashSet<String>();
for (String key : definitions.keySet()) { for (String key : definitions.keySet()) {
Model mm = definitions.get(key); Model mm = definitions.get(key);
CodegenModel cm = config.fromModel(key, mm); CodegenModel cm = config.fromModel(key, mm, allDefinitions);
Map<String, Object> mo = new HashMap<String, Object>(); Map<String, Object> mo = new HashMap<String, Object>();
mo.put("model", cm); mo.put("model", cm);
mo.put("importPath", config.toModelImport(key)); mo.put("importPath", config.toModelImport(key));

View File

@ -128,7 +128,7 @@ public class XmlExampleGenerator {
ArrayProperty p = (ArrayProperty) property; ArrayProperty p = (ArrayProperty) property;
Property inner = p.getItems(); Property inner = p.getItems();
boolean wrapped = false; boolean wrapped = false;
if (property.getXml() != null && property.getXml().getWrapped()) { if (property.getXml() != null && property.getXml().getWrapped() != null && property.getXml().getWrapped()) {
wrapped = true; wrapped = true;
} }
if (wrapped) { if (wrapped) {

View File

@ -0,0 +1,144 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.*;
import io.swagger.models.properties.*;
import java.util.*;
import java.io.File;
public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public CodegenType getTag() {
return CodegenType.CLIENT;
}
public AbstractTypeScriptClientCodegen() {
super();
supportsInheritance = true;
reservedWords = new HashSet<String>(Arrays.asList("abstract",
"continue", "for", "new", "switch", "assert", "default", "if",
"package", "synchronized", "do", "goto", "private",
"this", "break", "double", "implements", "protected", "throw",
"byte", "else", "import", "public", "throws", "case", "enum",
"instanceof", "return", "transient", "catch", "extends", "int",
"short", "try", "char", "final", "interface", "static", "void",
"class", "finally", "const", "super", "while"));
languageSpecificPrimitives = new HashSet<String>(Arrays.asList(
"String",
"boolean",
"Boolean",
"Double",
"Integer",
"Long",
"Float",
"Object"));
instantiationTypes.put("array", "Array");
typeMapping = new HashMap<String, String>();
typeMapping.put("Array", "Array");
typeMapping.put("array", "Array");
typeMapping.put("List", "Array");
typeMapping.put("boolean", "boolean");
typeMapping.put("string", "string");
typeMapping.put("int", "number");
typeMapping.put("float", "number");
typeMapping.put("number", "number");
typeMapping.put("long", "number");
typeMapping.put("short", "number");
typeMapping.put("char", "string");
typeMapping.put("double", "number");
typeMapping.put("object", "any");
typeMapping.put("integer", "number");
typeMapping.put("Map", "any");
typeMapping.put("DateTime", "Date");
}
@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 toVarName(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_");
// if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$"))
return name;
// camelize 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) {
// 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 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 "{ [key: string]: "+ getTypeDeclaration(inner) + "; }";
} else if (p instanceof FileProperty) {
return "any";
}
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
type = swaggerType;
return type;
}
}

View File

@ -4,6 +4,7 @@ import com.google.common.base.CaseFormat;
import com.samskivert.mustache.Mustache; import com.samskivert.mustache.Mustache;
import com.samskivert.mustache.Template; import com.samskivert.mustache.Template;
import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenOperation; import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenProperty; import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.CodegenResponse; import io.swagger.codegen.CodegenResponse;
@ -80,10 +81,10 @@ public class AkkaScalaClientCodegen extends DefaultCodegen implements CodegenCon
"trait", "try", "true", "type", "val", "var", "while", "with", "yield") "trait", "try", "true", "type", "val", "var", "while", "with", "yield")
); );
additionalProperties.put("invokerPackage", invokerPackage); additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
additionalProperties.put("groupId", groupId); additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
additionalProperties.put("artifactId", artifactId); additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
additionalProperties.put("artifactVersion", artifactVersion); additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
additionalProperties.put("configKey", configKey); additionalProperties.put("configKey", configKey);
additionalProperties.put("configKeyPath", configKeyPath); additionalProperties.put("configKeyPath", configKeyPath);
additionalProperties.put("defaultTimeout", defaultTimeoutInMs); additionalProperties.put("defaultTimeout", defaultTimeoutInMs);
@ -251,6 +252,11 @@ public class AkkaScalaClientCodegen extends DefaultCodegen implements CodegenCon
@Override @Override
public String toOperationId(String operationId) { public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
return super.toOperationId(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, operationId)); return super.toOperationId(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, operationId));
} }

View File

@ -2,6 +2,7 @@ package io.swagger.codegen.languages;
import io.swagger.codegen.CliOption; import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenConfig;
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;
@ -13,6 +14,8 @@ import java.io.File;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import org.apache.commons.lang.StringUtils;
public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfig { public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String invokerPackage = "io.swagger.client"; protected String invokerPackage = "io.swagger.client";
protected String groupId = "io.swagger"; protected String groupId = "io.swagger";
@ -56,11 +59,11 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
instantiationTypes.put("array", "ArrayList"); instantiationTypes.put("array", "ArrayList");
instantiationTypes.put("map", "HashMap"); instantiationTypes.put("map", "HashMap");
cliOptions.add(new CliOption("invokerPackage", "root package to use for the generated code")); cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE, CodegenConstants.INVOKER_PACKAGE_DESC));
cliOptions.add(new CliOption("groupId", "groupId for use in the generated build.gradle and pom.xml")); cliOptions.add(new CliOption(CodegenConstants.GROUP_ID, "groupId for use in the generated build.gradle and pom.xml"));
cliOptions.add(new CliOption("artifactId", "artifactId for use in the generated build.gradle and pom.xml")); cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_ID, "artifactId for use in the generated build.gradle and pom.xml"));
cliOptions.add(new CliOption("artifactVersion", "artifact version for use in the generated build.gradle and pom.xml")); cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_VERSION, "artifact version for use in the generated build.gradle and pom.xml"));
cliOptions.add(new CliOption("sourceFolder", "source folder for generated code")); cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, CodegenConstants.SOURCE_FOLDER_DESC));
cliOptions.add(new CliOption("useAndroidMavenGradlePlugin", "A flag to toggle android-maven gradle plugin. Default is true.")); cliOptions.add(new CliOption("useAndroidMavenGradlePlugin", "A flag to toggle android-maven gradle plugin. Default is true."));
} }
@ -168,6 +171,11 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
@Override @Override
public String toOperationId(String operationId) { public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
// method name cannot use reserved keyword, e.g. return // method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) { if (reservedWords.contains(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
@ -180,36 +188,36 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
public void processOpts() { public void processOpts() {
super.processOpts(); super.processOpts();
if (additionalProperties.containsKey("invokerPackage")) { if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) {
this.setInvokerPackage((String) additionalProperties.get("invokerPackage")); this.setInvokerPackage((String) additionalProperties.get(CodegenConstants.INVOKER_PACKAGE));
} else { } else {
//not set, use default to be passed to template //not set, use default to be passed to template
additionalProperties.put("invokerPackage", invokerPackage); additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
} }
if (additionalProperties.containsKey("groupId")) { if (additionalProperties.containsKey(CodegenConstants.GROUP_ID)) {
this.setGroupId((String) additionalProperties.get("groupId")); this.setGroupId((String) additionalProperties.get(CodegenConstants.GROUP_ID));
} else { } else {
//not set, use to be passed to template //not set, use to be passed to template
additionalProperties.put("groupId", groupId); additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
} }
if (additionalProperties.containsKey("artifactId")) { if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_ID)) {
this.setArtifactId((String) additionalProperties.get("artifactId")); this.setArtifactId((String) additionalProperties.get(CodegenConstants.ARTIFACT_ID));
} else { } else {
//not set, use to be passed to template //not set, use to be passed to template
additionalProperties.put("artifactId", artifactId); additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
} }
if (additionalProperties.containsKey("artifactVersion")) { if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_VERSION)) {
this.setArtifactVersion((String) additionalProperties.get("artifactVersion")); this.setArtifactVersion((String) additionalProperties.get(CodegenConstants.ARTIFACT_VERSION));
} else { } else {
//not set, use to be passed to template //not set, use to be passed to template
additionalProperties.put("artifactVersion", artifactVersion); additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
} }
if (additionalProperties.containsKey("sourceFolder")) { if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) {
this.setSourceFolder((String) additionalProperties.get("sourceFolder")); this.setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER));
} }
if (additionalProperties.containsKey("useAndroidMavenGradlePlugin")) { if (additionalProperties.containsKey("useAndroidMavenGradlePlugin")) {
@ -232,6 +240,8 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "JsonUtil.java")); (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "JsonUtil.java"));
supportingFiles.add(new SupportingFile("apiException.mustache", supportingFiles.add(new SupportingFile("apiException.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiException.java")); (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiException.java"));
supportingFiles.add(new SupportingFile("Pair.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "Pair.java"));
} }
public Boolean getUseAndroidMavenGradlePlugin() { public Boolean getUseAndroidMavenGradlePlugin() {

View File

@ -1,6 +1,7 @@
package io.swagger.codegen.languages; package io.swagger.codegen.languages;
import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenConfig;
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;
@ -21,6 +22,8 @@ import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import org.apache.commons.lang.StringUtils;
public class AsyncScalaClientCodegen extends DefaultCodegen implements CodegenConfig { public class AsyncScalaClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String invokerPackage = "io.swagger.client"; protected String invokerPackage = "io.swagger.client";
protected String groupId = "io.swagger"; protected String groupId = "io.swagger";
@ -50,10 +53,10 @@ public class AsyncScalaClientCodegen extends DefaultCodegen implements CodegenCo
"trait", "try", "true", "type", "val", "var", "while", "with", "yield") "trait", "try", "true", "type", "val", "var", "while", "with", "yield")
); );
additionalProperties.put("invokerPackage", invokerPackage); additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
additionalProperties.put("groupId", groupId); additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
additionalProperties.put("artifactId", artifactId); additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
additionalProperties.put("artifactVersion", artifactVersion); additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
additionalProperties.put("asyncHttpClient", asyncHttpClient); additionalProperties.put("asyncHttpClient", asyncHttpClient);
additionalProperties.put("authScheme", authScheme); additionalProperties.put("authScheme", authScheme);
additionalProperties.put("authPreemptive", authPreemptive); additionalProperties.put("authPreemptive", authPreemptive);

View File

@ -7,22 +7,24 @@ 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.codegen.CliOption;
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 org.apache.commons.lang.StringUtils;
public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig { public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String invokerPackage = "IO.Swagger.Client"; protected String packageName = "IO.Swagger";
protected String groupId = "io.swagger"; protected String packageVersion = "1.0.0";
protected String artifactId = "swagger-csharp-client"; protected String clientPackage = "IO.Swagger.Client";
protected String artifactVersion = "1.0.0"; protected String sourceFolder = "src" + File.separator + "main" + File.separator + "csharp";
protected String sourceFolder = "src/main/csharp";
public CSharpClientCodegen() { public CSharpClientCodegen() {
super(); super();
outputFolder = "generated-code/csharp"; outputFolder = "generated-code" + File.separator + "csharp";
modelTemplateFiles.put("model.mustache", ".cs"); modelTemplateFiles.put("model.mustache", ".cs");
apiTemplateFiles.put("api.mustache", ".cs"); apiTemplateFiles.put("api.mustache", ".cs");
templateDir = "csharp"; templateDir = "csharp";
@ -34,20 +36,10 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
"abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", "class", "const", "continue", "decimal", "default", "delegate", "do", "double", "else", "enum", "event", "explicit", "extern", "false", "finally", "fixed", "float", "for", "foreach", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock", "long", "namespace", "new", "null", "object", "operator", "out", "override", "params", "private", "protected", "public", "readonly", "ref", "return", "sbyte", "sealed", "short", "sizeof", "stackalloc", "static", "string", "struct", "switch", "this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "void", "volatile", "while") "abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", "class", "const", "continue", "decimal", "default", "delegate", "do", "double", "else", "enum", "event", "explicit", "extern", "false", "finally", "fixed", "float", "for", "foreach", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock", "long", "namespace", "new", "null", "object", "operator", "out", "override", "params", "private", "protected", "public", "readonly", "ref", "return", "sbyte", "sealed", "short", "sizeof", "stackalloc", "static", "string", "struct", "switch", "this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "void", "volatile", "while")
); );
additionalProperties.put("invokerPackage", invokerPackage);
supportingFiles.add(new SupportingFile("Configuration.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "Configuration.cs"));
supportingFiles.add(new SupportingFile("ApiClient.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiClient.cs"));
supportingFiles.add(new SupportingFile("ApiException.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiException.cs"));
supportingFiles.add(new SupportingFile("Newtonsoft.Json.dll", "bin", "Newtonsoft.Json.dll"));
supportingFiles.add(new SupportingFile("RestSharp.dll", "bin", "RestSharp.dll"));
supportingFiles.add(new SupportingFile("compile.mustache", "", "compile.bat"));
languageSpecificPrimitives = new HashSet<String>( languageSpecificPrimitives = new HashSet<String>(
Arrays.asList( Arrays.asList(
"String",
"string", "string",
"bool?", "bool?",
"double?", "double?",
@ -64,6 +56,7 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
"Integer", "Integer",
"Long", "Long",
"Float", "Float",
"Stream", // not really a primitive, we include it to avoid model import
"Object") "Object")
); );
instantiationTypes.put("array", "List"); instantiationTypes.put("array", "List");
@ -79,12 +72,50 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
typeMapping.put("number", "double?"); typeMapping.put("number", "double?");
typeMapping.put("datetime", "DateTime?"); typeMapping.put("datetime", "DateTime?");
typeMapping.put("date", "DateTime?"); typeMapping.put("date", "DateTime?");
typeMapping.put("file", "string"); // path to file typeMapping.put("file", "Stream");
typeMapping.put("array", "List"); typeMapping.put("array", "List");
typeMapping.put("list", "List"); typeMapping.put("list", "List");
typeMapping.put("map", "Dictionary"); typeMapping.put("map", "Dictionary");
typeMapping.put("object", "Object"); typeMapping.put("object", "Object");
cliOptions.clear();
cliOptions.add(new CliOption("packageName", "C# package name (convention: Camel.Case), default: IO.Swagger"));
cliOptions.add(new CliOption("packageVersion", "C# package version, default: 1.0.0"));
}
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey("packageVersion")) {
packageVersion = (String) additionalProperties.get("packageVersion");
} else {
additionalProperties.put("packageVersion", packageVersion);
}
if (additionalProperties.containsKey("packageName")) {
packageName = (String) additionalProperties.get("packageName");
apiPackage = packageName + ".Api";
modelPackage = packageName + ".Model";
clientPackage = packageName + ".Client";
} else {
additionalProperties.put("packageName", packageName);
}
additionalProperties.put("clientPackage", clientPackage);
supportingFiles.add(new SupportingFile("Configuration.mustache",
(sourceFolder + File.separator + clientPackage).replace(".", java.io.File.separator), "Configuration.cs"));
supportingFiles.add(new SupportingFile("ApiClient.mustache",
(sourceFolder + File.separator + clientPackage).replace(".", java.io.File.separator), "ApiClient.cs"));
supportingFiles.add(new SupportingFile("ApiException.mustache",
(sourceFolder + File.separator + clientPackage).replace(".", java.io.File.separator), "ApiException.cs"));
supportingFiles.add(new SupportingFile("Newtonsoft.Json.dll", "bin", "Newtonsoft.Json.dll"));
supportingFiles.add(new SupportingFile("RestSharp.dll", "bin", "RestSharp.dll"));
supportingFiles.add(new SupportingFile("compile.mustache", "", "compile.bat"));
supportingFiles.add(new SupportingFile("README.md", "", "README.md"));
} }
public CodegenType getTag() { public CodegenType getTag() {
@ -106,17 +137,18 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
@Override @Override
public String apiFileFolder() { public String apiFileFolder() {
return (outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', '/')).replace('.', File.separatorChar);
return outputFolder + File.separator + (sourceFolder + File.separator + apiPackage()).replace('.', File.separatorChar);
} }
public String modelFileFolder() { public String modelFileFolder() {
return (outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', '/')).replace('.', File.separatorChar); return outputFolder + File.separator + (sourceFolder + File.separator + modelPackage()).replace('.', File.separatorChar);
} }
@Override @Override
public String toVarName(String name) { public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at // sanitize name
name = name.replaceAll("-", "_"); name = sanitizeName(name);
// if it's all uppper case, do nothing // if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$")) { if (name.matches("^[A-Z_]*$")) {
@ -137,8 +169,24 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
@Override @Override
public String toParamName(String name) { public String toParamName(String name) {
// should be the same as variable name // replace - with _ e.g. created-at => created_at
return toVarName(name); name = name.replaceAll("-", "_");
// if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$")) {
return name;
}
// camelize(lower) 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 @Override
@ -192,12 +240,17 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
@Override @Override
public String toOperationId(String operationId) { public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
// method name cannot use reserved keyword, e.g. return // method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) { if (reservedWords.contains(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
} }
return camelize(operationId); return camelize(sanitizeName(operationId));
} }
} }

View File

@ -0,0 +1,5 @@
package io.swagger.codegen.languages;
public enum CodeGenStatus {
UNRUN, SUCCESSFUL, FAILED
}

View File

@ -0,0 +1,255 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.CodegenConfig;
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.codegen.CliOption;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
public class CsharpDotNet2ClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String packageName = "IO.Swagger";
protected String packageVersion = "1.0.0";
protected String clientPackage = "IO.Swagger.Client";
protected String sourceFolder = "src" + File.separator + "main" + File.separator + "CsharpDotNet2";
public CsharpDotNet2ClientCodegen() {
super();
outputFolder = "generated-code" + File.separator + "CsharpDotNet2";
modelTemplateFiles.put("model.mustache", ".cs");
apiTemplateFiles.put("api.mustache", ".cs");
templateDir = "CsharpDotNet2";
apiPackage = "IO.Swagger.Api";
modelPackage = "IO.Swagger.Model";
reservedWords = new HashSet<String>(
Arrays.asList(
"abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", "class", "const", "continue", "decimal", "default", "delegate", "do", "double", "else", "enum", "event", "explicit", "extern", "false", "finally", "fixed", "float", "for", "foreach", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock", "long", "namespace", "new", "null", "object", "operator", "out", "override", "params", "private", "protected", "public", "readonly", "ref", "return", "sbyte", "sealed", "short", "sizeof", "stackalloc", "static", "string", "struct", "switch", "this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "void", "volatile", "while")
);
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"String",
"string",
"bool?",
"double?",
"int?",
"long?",
"float?",
"byte[]",
"List",
"Dictionary",
"DateTime?",
"String",
"Boolean",
"Double",
"Integer",
"Long",
"Float",
"Stream", // not really a primitive, we include it to avoid model import
"Object")
);
instantiationTypes.put("array", "List");
instantiationTypes.put("map", "Dictionary");
typeMapping = new HashMap<String, String>();
typeMapping.put("string", "string");
typeMapping.put("boolean", "bool?");
typeMapping.put("integer", "int?");
typeMapping.put("float", "float?");
typeMapping.put("long", "long?");
typeMapping.put("double", "double?");
typeMapping.put("number", "double?");
typeMapping.put("datetime", "DateTime?");
typeMapping.put("date", "DateTime?");
typeMapping.put("file", "Stream");
typeMapping.put("array", "List");
typeMapping.put("list", "List");
typeMapping.put("map", "Dictionary");
typeMapping.put("object", "Object");
cliOptions.clear();
cliOptions.add(new CliOption("packageName", "C# package name (convention: Camel.Case), default: IO.Swagger"));
cliOptions.add(new CliOption("packageVersion", "C# package version, default: 1.0.0"));
}
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey("packageVersion")) {
packageVersion = (String) additionalProperties.get("packageVersion");
} else {
additionalProperties.put("packageVersion", packageVersion);
}
if (additionalProperties.containsKey("packageName")) {
packageName = (String) additionalProperties.get("packageName");
apiPackage = packageName + ".Api";
modelPackage = packageName + ".Model";
clientPackage = packageName + ".Client";
} else {
additionalProperties.put("packageName", packageName);
}
if (additionalProperties.containsKey("clientPackage")) {
this.setClientPackage((String) additionalProperties.get("clientPackage"));
} else {
additionalProperties.put("clientPackage", clientPackage);
}
supportingFiles.add(new SupportingFile("Configuration.mustache",
(sourceFolder + File.separator + clientPackage).replace(".", java.io.File.separator), "Configuration.cs"));
supportingFiles.add(new SupportingFile("ApiClient.mustache",
(sourceFolder + File.separator + clientPackage).replace(".", java.io.File.separator), "ApiClient.cs"));
supportingFiles.add(new SupportingFile("ApiException.mustache",
(sourceFolder + File.separator + clientPackage).replace(".", java.io.File.separator), "ApiException.cs"));
supportingFiles.add(new SupportingFile("packages.config.mustache", "vendor", "packages.config"));
supportingFiles.add(new SupportingFile("compile-mono.sh.mustache", "", "compile-mono.sh"));
supportingFiles.add(new SupportingFile("README.md", "", "README.md"));
}
public void setClientPackage(String clientPackage) {
this.clientPackage = clientPackage;
}
public CodegenType getTag() {
return CodegenType.CLIENT;
}
public String getName() {
return "CsharpDotNet2";
}
public String getHelp() {
return "Generates a C# .Net 2.0 client library.";
}
@Override
public String escapeReservedWord(String name) {
return "_" + name;
}
@Override
public String apiFileFolder() {
return (outputFolder + File.separator + sourceFolder + File.separator + apiPackage()).replace('.', File.separatorChar);
}
public String modelFileFolder() {
return (outputFolder + File.separator + sourceFolder + File.separator + modelPackage()).replace('.', File.separatorChar);
}
@Override
public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_");
// if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$")) {
return name;
}
// camelize the variable name
// pet_id => PetId
name = camelize(name);
// 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) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_");
// if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$")) {
return name;
}
// camelize(lower) 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 toModelName(String 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 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);
}
@Override
public String getSwaggerType(Property p) {
String swaggerType = super.getSwaggerType(p);
String type = null;
if (typeMapping.containsKey(swaggerType.toLowerCase())) {
type = typeMapping.get(swaggerType.toLowerCase());
if (languageSpecificPrimitives.contains(type)) {
return type;
}
} else {
type = swaggerType;
}
return toModelName(type);
}
@Override
public String toOperationId(String operationId) {
// 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(operationId);
}
}

View File

@ -0,0 +1,360 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.CliOption;
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.BooleanProperty;
import io.swagger.models.properties.DateProperty;
import io.swagger.models.properties.DateTimeProperty;
import io.swagger.models.properties.DoubleProperty;
import io.swagger.models.properties.FloatProperty;
import io.swagger.models.properties.IntegerProperty;
import io.swagger.models.properties.LongProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import io.swagger.models.properties.StringProperty;
import org.apache.commons.lang.StringUtils;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String packageName = "io.swagger";
protected String packageVersion = null;
protected String invokerPackage = "io.swagger";
protected String sourceFolder = "src/main/flex";
public FlashClientCodegen() {
super();
modelPackage = "io.swagger.client.model";
apiPackage = "io.swagger.client.api";
outputFolder = "generated-code" + File.separatorChar + "flash";
modelTemplateFiles.put("model.mustache", ".as");
modelTemplateFiles.put("modelList.mustache", "List.as");
apiTemplateFiles.put("api.mustache", ".as");
templateDir = "flash";
languageSpecificPrimitives.clear();
languageSpecificPrimitives.add("Number");
languageSpecificPrimitives.add("Boolean");
languageSpecificPrimitives.add("String");
languageSpecificPrimitives.add("Date");
languageSpecificPrimitives.add("Array");
languageSpecificPrimitives.add("Dictionary");
typeMapping.clear();
typeMapping.put("integer", "Number");
typeMapping.put("float", "Number");
typeMapping.put("long", "Number");
typeMapping.put("double", "Number");
typeMapping.put("array", "Array");
typeMapping.put("map", "Dictionary");
typeMapping.put("boolean", "Boolean");
typeMapping.put("string", "String");
typeMapping.put("date", "Date");
typeMapping.put("DateTime", "Date");
typeMapping.put("object", "Object");
typeMapping.put("file", "File");
importMapping = new HashMap<String, String>();
importMapping.put("File", "flash.filesystem.File");
// from
reservedWords = new HashSet<String>(
Arrays.asList(
"add", "for", "lt", "tellTarget", "and", "function", "ne", "this", "break", "ge", "new", "typeof", "continue", "gt", "not", "var", "delete", "if", "on", "void", "do", "ifFrameLoaded", "onClipEvent", "while", "else", "in", "or", "with", "eq", "le", "return"));
cliOptions.clear();
cliOptions.add(new CliOption("packageName", "flash package name (convention: package.name), default: io.swagger"));
cliOptions.add(new CliOption("packageVersion", "flash package version, default: 1.0.0"));
cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE, CodegenConstants.INVOKER_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, "source folder for generated code. e.g. src/main/flex"));
}
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) {
this.setInvokerPackage((String) additionalProperties.get(CodegenConstants.INVOKER_PACKAGE));
} else {
//not set, use default to be passed to template
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
}
if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) {
this.setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER));
}
if (additionalProperties.containsKey("packageName")) {
setPackageName((String) additionalProperties.get("packageName"));
apiPackage = packageName + ".client.api";
modelPackage = packageName + ".client.model";
}
else {
setPackageName("io.swagger");
}
if (additionalProperties.containsKey("packageVersion")) {
setPackageVersion((String) additionalProperties.get("packageVersion"));
}
else {
setPackageVersion("1.0.0");
}
additionalProperties.put("packageName", packageName);
additionalProperties.put("packageVersion", packageVersion);
//modelPackage = invokerPackage + File.separatorChar + "client" + File.separatorChar + "model";
//apiPackage = invokerPackage + File.separatorChar + "client" + File.separatorChar + "api";
final String invokerFolder = (sourceFolder + File.separator + invokerPackage + File.separator + "swagger" + File.separator).replace(".", File.separator).replace('.', File.separatorChar);
supportingFiles.add(new SupportingFile("ApiInvoker.as", invokerFolder + "common", "ApiInvoker.as"));
supportingFiles.add(new SupportingFile("ApiUrlHelper.as", invokerFolder + "common", "ApiUrlHelper.as"));
supportingFiles.add(new SupportingFile("ApiUserCredentials.as", invokerFolder + "common", "ApiUserCredentials.as"));
supportingFiles.add(new SupportingFile("ListWrapper.as", invokerFolder + "common", "ListWrapper.as"));
supportingFiles.add(new SupportingFile("SwaggerApi.as", invokerFolder + "common", "SwaggerApi.as"));
supportingFiles.add(new SupportingFile("XMLWriter.as", invokerFolder + "common", "XMLWriter.as"));
supportingFiles.add(new SupportingFile("ApiError.as", invokerFolder + "exception", "ApiErrors.as"));
supportingFiles.add(new SupportingFile("ApiErrorCodes.as", invokerFolder + "exception", "ApiErrorCodes.as"));
supportingFiles.add(new SupportingFile("ApiClientEvent.as", invokerFolder + "event", "ApiClientEvent.as"));
supportingFiles.add(new SupportingFile("Response.as", invokerFolder + "event", "Response.as"));
supportingFiles.add(new SupportingFile("build.properties", sourceFolder, "build.properties"));
supportingFiles.add(new SupportingFile("build.xml", sourceFolder, "build.xml"));
supportingFiles.add(new SupportingFile("AirExecutorApp-app.xml", sourceFolder + File.separatorChar + "bin", "AirExecutorApp-app.xml"));
supportingFiles.add(new SupportingFile("ASAXB-0.1.1.swc", sourceFolder + File.separatorChar + "lib", "ASAXB-0.1.1.swc"));
supportingFiles.add(new SupportingFile("as3corelib.swc", sourceFolder + File.separatorChar + "lib", "as3corelib.swc"));
supportingFiles.add(new SupportingFile("flexunit-4.1.0_RC2-28-flex_3.5.0.12683.swc", sourceFolder + File.separator + "lib" + File.separator + "ext", "flexunit-4.1.0_RC2-28-flex_3.5.0.12683.swc"));
supportingFiles.add(new SupportingFile("flexunit-aircilistener-4.1.0_RC2-28-3.5.0.12683.swc", sourceFolder + File.separator + "lib" + File.separator + "ext", "flexunit-aircilistener-4.1.0_RC2-28-3.5.0.12683.swc"));
supportingFiles.add(new SupportingFile("flexunit-cilistener-4.1.0_RC2-28-3.5.0.12683.swc", sourceFolder + File.separator + "lib" + File.separator + "ext", "flexunit-cilistener-4.1.0_RC2-28-3.5.0.12683.swc"));
supportingFiles.add(new SupportingFile("flexunit-core-flex-4.0.0.2-sdk3.5.0.12683.swc", sourceFolder + File.separator + "lib" + File.separator + "ext", "flexunit-core-flex-4.0.0.2-sdk3.5.0.12683.swc"));
}
private static String dropDots(String str) {
return str.replaceAll("\\.", "_");
}
public CodegenType getTag() {
return CodegenType.CLIENT;
}
public String getName() {
return "flash";
}
public String getHelp() {
return "Generates a Flash client library.";
}
@Override
public String escapeReservedWord(String name) {
return name + "_";
}
@Override
public String apiFileFolder() {
return (outputFolder + File.separatorChar + sourceFolder + File.separatorChar + apiPackage().replace('.', File.separatorChar)).replace('/', File.separatorChar);
}
public String modelFileFolder() {
return (outputFolder + File.separatorChar + sourceFolder + File.separatorChar + modelPackage().replace('.', File.separatorChar)).replace('/', File.separatorChar);
}
@Override
public String getTypeDeclaration(Property p) {
if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems();
return getSwaggerType(p);
} else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();
return getSwaggerType(p);
}
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 {
type = toModelName(swaggerType);
}
return type;
}
public String toDefaultValue(Property p) {
if (p instanceof StringProperty) {
return "null";
} else if (p instanceof BooleanProperty) {
return "false";
} else if (p instanceof DateProperty) {
return "null";
} else if (p instanceof DateTimeProperty) {
return "null";
} else if (p instanceof DoubleProperty) {
DoubleProperty dp = (DoubleProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
return "0.0";
} else if (p instanceof FloatProperty) {
FloatProperty dp = (FloatProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
return "0.0";
} else if (p instanceof IntegerProperty) {
IntegerProperty dp = (IntegerProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
return "0";
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
return "0";
} else if (p instanceof MapProperty) {
MapProperty ap = (MapProperty) p;
String inner = getSwaggerType(ap.getAdditionalProperties());
return "new Dictionary()";
} else if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
String inner = getSwaggerType(ap.getItems());
return "new Array()";
} else {
return "null";
}
}
@Override
public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_");
// if it's all uppper case, convert to lower case
if (name.matches("^[A-Z_]*$")) {
name = name.toLowerCase();
}
// underscore the variable name
// petId => pet_id
name = camelize(dropDots(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) {
// 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) {
// 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");
}
// underscore the model file name
// PhoneNumber => phone_number
return camelize(dropDots(name));
}
@Override
public String toApiFilename(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_");
// e.g. PhoneNumberApi.rb => phone_number_api.rb
return camelize(name) + "Api";
}
@Override
public String toApiName(String name) {
if (name.length() == 0) {
return "DefaultApi";
}
// e.g. phone_number_api => PhoneNumberApi
return camelize(name) + "Api";
}
@Override
public String toApiVarName(String name) {
if (name.length() == 0) {
return "DefaultApi";
}
return camelize(name) + "Api";
}
@Override
public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method 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 underscore(operationId);
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public void setPackageVersion(String packageVersion) {
this.packageVersion = packageVersion;
}
public void setInvokerPackage(String invokerPackage) {
this.invokerPackage = invokerPackage;
}
public void setSourceFolder(String sourceFolder) {
this.sourceFolder = sourceFolder;
}
}

View File

@ -1,24 +1,42 @@
package io.swagger.codegen.languages; package io.swagger.codegen.languages;
import com.google.common.base.Strings;
import io.swagger.codegen.CliOption; import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenModel;
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.Model;
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 java.io.File; import java.io.File;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet; 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 JavaClientCodegen extends DefaultCodegen implements CodegenConfig { public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(JavaClientCodegen.class);
protected String invokerPackage = "io.swagger.client"; protected String invokerPackage = "io.swagger.client";
protected String groupId = "io.swagger"; protected String groupId = "io.swagger";
protected String artifactId = "swagger-java-client"; protected String artifactId = "swagger-java-client";
protected String artifactVersion = "1.0.0"; protected String artifactVersion = "1.0.0";
protected String sourceFolder = "src/main/java"; protected String sourceFolder = "src/main/java";
protected String localVariablePrefix = "";
protected Boolean serializableModel = false;
public JavaClientCodegen() { public JavaClientCodegen() {
super(); super();
@ -49,26 +67,37 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
"Integer", "Integer",
"Long", "Long",
"Float", "Float",
"Object") "Object",
"byte[]")
); );
instantiationTypes.put("array", "ArrayList"); instantiationTypes.put("array", "ArrayList");
instantiationTypes.put("map", "HashMap"); instantiationTypes.put("map", "HashMap");
cliOptions.add(new CliOption("invokerPackage", "root package for generated code")); cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE, CodegenConstants.INVOKER_PACKAGE_DESC));
cliOptions.add(new CliOption("groupId", "groupId in generated pom.xml")); cliOptions.add(new CliOption(CodegenConstants.GROUP_ID, CodegenConstants.GROUP_ID_DESC));
cliOptions.add(new CliOption("artifactId", "artifactId in generated pom.xml")); cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_ID, CodegenConstants.ARTIFACT_ID_DESC));
cliOptions.add(new CliOption("artifactVersion", "artifact version in generated pom.xml")); cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_VERSION, CodegenConstants.ARTIFACT_VERSION_DESC));
cliOptions.add(new CliOption("sourceFolder", "source folder for generated code")); cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, CodegenConstants.SOURCE_FOLDER_DESC));
cliOptions.add(new CliOption(CodegenConstants.LOCAL_VARIABLE_PREFIX, CodegenConstants.LOCAL_VARIABLE_PREFIX_DESC));
cliOptions.add(new CliOption(CodegenConstants.SERIALIZABLE_MODEL, CodegenConstants.SERIALIZABLE_MODEL_DESC));
supportedLibraries.put("<default>", "HTTP client: Jersey client 1.18. JSON processing: Jackson 2.4.2");
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");
cliOptions.add(buildLibraryCliOption(supportedLibraries));
} }
@Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.CLIENT; return CodegenType.CLIENT;
} }
@Override
public String getName() { public String getName() {
return "java"; return "java";
} }
@Override
public String getHelp() { public String getHelp() {
return "Generates a Java client library."; return "Generates a Java client library.";
} }
@ -77,46 +106,74 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
public void processOpts() { public void processOpts() {
super.processOpts(); super.processOpts();
if (additionalProperties.containsKey("invokerPackage")) { if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) {
this.setInvokerPackage((String) additionalProperties.get("invokerPackage")); this.setInvokerPackage((String) additionalProperties.get(CodegenConstants.INVOKER_PACKAGE));
} else { } else {
//not set, use default to be passed to template //not set, use default to be passed to template
additionalProperties.put("invokerPackage", invokerPackage); additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
} }
if (additionalProperties.containsKey("groupId")) { if (additionalProperties.containsKey(CodegenConstants.GROUP_ID)) {
this.setGroupId((String) additionalProperties.get("groupId")); this.setGroupId((String) additionalProperties.get(CodegenConstants.GROUP_ID));
} else { } else {
//not set, use to be passed to template //not set, use to be passed to template
additionalProperties.put("groupId", groupId); additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
} }
if (additionalProperties.containsKey("artifactId")) { if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_ID)) {
this.setArtifactId((String) additionalProperties.get("artifactId")); this.setArtifactId((String) additionalProperties.get(CodegenConstants.ARTIFACT_ID));
} else { } else {
//not set, use to be passed to template //not set, use to be passed to template
additionalProperties.put("artifactId", artifactId); additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
} }
if (additionalProperties.containsKey("artifactVersion")) { if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_VERSION)) {
this.setArtifactVersion((String) additionalProperties.get("artifactVersion")); this.setArtifactVersion((String) additionalProperties.get(CodegenConstants.ARTIFACT_VERSION));
} else { } else {
//not set, use to be passed to template //not set, use to be passed to template
additionalProperties.put("artifactVersion", artifactVersion); additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
} }
if (additionalProperties.containsKey("sourceFolder")) { if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) {
this.setSourceFolder((String) additionalProperties.get("sourceFolder")); this.setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER));
} }
if (additionalProperties.containsKey(CodegenConstants.LOCAL_VARIABLE_PREFIX)) {
this.setLocalVariablePrefix((String) additionalProperties.get(CodegenConstants.LOCAL_VARIABLE_PREFIX));
}
if (additionalProperties.containsKey(CodegenConstants.SERIALIZABLE_MODEL)) {
this.setSerializableModel(Boolean.valueOf((String)additionalProperties.get(CodegenConstants.SERIALIZABLE_MODEL).toString()));
}
// need to put back serializableModel (boolean) into additionalProperties as value in additionalProperties is string
additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, serializableModel);
this.sanitizeConfig();
final String invokerFolder = (sourceFolder + File.separator + invokerPackage).replace(".", File.separator); final String invokerFolder = (sourceFolder + File.separator + invokerPackage).replace(".", File.separator);
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("ApiClient.mustache", invokerFolder, "ApiClient.java")); supportingFiles.add(new SupportingFile("ApiClient.mustache", invokerFolder, "ApiClient.java"));
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("JsonUtil.mustache", invokerFolder, "JsonUtil.java")); supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java"));
supportingFiles.add(new SupportingFile("Pair.mustache", invokerFolder, "Pair.java"));
supportingFiles.add(new SupportingFile("StringUtil.mustache", invokerFolder, "StringUtil.java")); supportingFiles.add(new SupportingFile("StringUtil.mustache", invokerFolder, "StringUtil.java"));
// library-specific files
if ("okhttp-gson".equals(getLibrary())) {
// the "okhttp-gson" library template requires "ApiCallback.mustache" for async call
supportingFiles.add(new SupportingFile("ApiCallback.mustache", invokerFolder, "ApiCallback.java"));
// "build.gradle" is for development with Gradle
supportingFiles.add(new SupportingFile("build.gradle.mustache", "", "build.gradle"));
// "build.sbt" is for development with SBT
supportingFiles.add(new SupportingFile("build.sbt.mustache", "", "build.sbt"));
// and does not require "TypeRef.mustache"
} else {
supportingFiles.add(new SupportingFile("TypeRef.mustache", invokerFolder, "TypeRef.java"));
}
final String authFolder = (sourceFolder + File.separator + invokerPackage + ".auth").replace(".", File.separator); final String authFolder = (sourceFolder + File.separator + invokerPackage + ".auth").replace(".", File.separator);
supportingFiles.add(new SupportingFile("auth/Authentication.mustache", authFolder, "Authentication.java")); supportingFiles.add(new SupportingFile("auth/Authentication.mustache", authFolder, "Authentication.java"));
supportingFiles.add(new SupportingFile("auth/HttpBasicAuth.mustache", authFolder, "HttpBasicAuth.java")); supportingFiles.add(new SupportingFile("auth/HttpBasicAuth.mustache", authFolder, "HttpBasicAuth.java"));
@ -124,6 +181,25 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
supportingFiles.add(new SupportingFile("auth/OAuth.mustache", authFolder, "OAuth.java")); supportingFiles.add(new SupportingFile("auth/OAuth.mustache", authFolder, "OAuth.java"));
} }
private void sanitizeConfig() {
// Sanitize any config options here. We also have to update the additionalProperties because
// the whole additionalProperties object is injected into the main object passed to the mustache layer
this.setApiPackage(sanitizePackageName(apiPackage));
if (additionalProperties.containsKey(CodegenConstants.API_PACKAGE)) {
this.additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage);
}
this.setModelPackage(sanitizePackageName(modelPackage));
if (additionalProperties.containsKey(CodegenConstants.MODEL_PACKAGE)) {
this.additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage);
}
this.setInvokerPackage(sanitizePackageName(invokerPackage));
if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) {
this.additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
}
}
@Override @Override
public String escapeReservedWord(String name) { public String escapeReservedWord(String name) {
@ -135,14 +211,19 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar); return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar);
} }
@Override
public String modelFileFolder() { public String modelFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar); return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar);
} }
@Override @Override
public String toVarName(String name) { public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at // sanitize name
name = name.replaceAll("-", "_"); name = sanitizeName(name);
if("_".equals(name)) {
name = "_u";
}
// if it's all uppper case, do nothing // if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$")) { if (name.matches("^[A-Z_]*$")) {
@ -169,6 +250,8 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toModelName(String name) { public String toModelName(String name) {
name = sanitizeName(name);
// model name cannot use reserved keyword, e.g. return // model name cannot use reserved keyword, e.g. return
if (reservedWords.contains(name)) { if (reservedWords.contains(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name"); throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
@ -200,6 +283,18 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
return super.getTypeDeclaration(p); return super.getTypeDeclaration(p);
} }
@Override
public String toDefaultValue(Property p) {
if (p instanceof ArrayProperty) {
final ArrayProperty ap = (ArrayProperty) p;
return String.format("new ArrayList<%s>()", getTypeDeclaration(ap.getItems()));
} else if (p instanceof MapProperty) {
final MapProperty ap = (MapProperty) p;
return String.format("new HashMap<String, %s>()", getTypeDeclaration(ap.getAdditionalProperties()));
}
return super.toDefaultValue(p);
}
@Override @Override
public String getSwaggerType(Property p) { public String getSwaggerType(Property p) {
String swaggerType = super.getSwaggerType(p); String swaggerType = super.getSwaggerType(p);
@ -207,22 +302,108 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
if (typeMapping.containsKey(swaggerType)) { if (typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType); type = typeMapping.get(swaggerType);
if (languageSpecificPrimitives.contains(type)) { if (languageSpecificPrimitives.contains(type)) {
return toModelName(type); return type;
} }
} else { } else {
type = swaggerType; type = swaggerType;
} }
if (null == type) {
LOGGER.error("No Type defined for Property " + p);
}
return toModelName(type); return toModelName(type);
} }
@Override @Override
public String toOperationId(String operationId) { public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
// method name cannot use reserved keyword, e.g. return // method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) { if (reservedWords.contains(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
} }
return camelize(operationId, true); 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;
if (allowableValues == null)
continue;
List<String> values = (List<String>) allowableValues.get("values");
// put "enumVars" map into `allowableValues", including `name` and `value`
if (values == null)
continue;
List<Map<String, String>> enumVars = new ArrayList<Map<String, String>>();
for (String value : values) {
Map<String, String> enumVar = new HashMap<String, String>();
enumVar.put("name", toVarName(value.toUpperCase()));
enumVar.put("value", value);
enumVars.add(enumVar);
}
allowableValues.put("enumVars", enumVars);
}
}
return objs;
}
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
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();
}
}
}
}
codegenModel.vars = codegenProperties;
}
return codegenModel;
} }
public void setInvokerPackage(String invokerPackage) { public void setInvokerPackage(String invokerPackage) {
@ -244,4 +425,27 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
public void setSourceFolder(String sourceFolder) { public void setSourceFolder(String sourceFolder) {
this.sourceFolder = sourceFolder; this.sourceFolder = sourceFolder;
} }
public void setLocalVariablePrefix(String localVariablePrefix) {
this.localVariablePrefix = localVariablePrefix;
}
public Boolean getSerializableModel() {
return serializableModel;
}
public void setSerializableModel(Boolean serializableModel) {
this.serializableModel = serializableModel;
}
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

@ -0,0 +1,189 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.SupportingFile;
import io.swagger.models.Operation;
import io.swagger.models.Swagger;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import io.swagger.util.Json;
import java.io.File;
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 {
protected String invokerPackage = "io.swagger.handler";
protected String groupId = "io.swagger";
protected String artifactId = "swagger-inflector-server";
protected String artifactVersion = "1.0.0";
protected String title = "Swagger Inflector";
public JavaInflectorServerCodegen() {
super();
sourceFolder = "src/main/java";
modelTemplateFiles.put("model.mustache", ".java");
apiTemplateFiles.put("api.mustache", ".java");
templateDir = "JavaInflector";
apiPackage = System.getProperty("swagger.codegen.inflector.apipackage", "io.swagger.handler");
modelPackage = System.getProperty("swagger.codegen.inflector.modelpackage", "io.swagger.model");
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
additionalProperties.put("title", title);
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"String",
"boolean",
"Boolean",
"Double",
"Integer",
"Long",
"Float")
);
}
public CodegenType getTag() {
return CodegenType.SERVER;
}
public String getName() {
return "inflector";
}
public String getHelp() {
return "Generates a Java Inflector Server application.";
}
@Override
public void processOpts() {
super.processOpts();
supportingFiles.clear();
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
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("inflector.mustache", "", "inflector.yaml"));
}
@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 getTypeDeclaration(inner);
}
return super.getTypeDeclaration(p);
}
@Override
public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations) {
String basePath = resourcePath;
if (basePath.startsWith("/")) {
basePath = basePath.substring(1);
}
int pos = basePath.indexOf("/");
if (pos > 0) {
basePath = basePath.substring(0, pos);
}
if (basePath == "") {
basePath = "default";
} else {
if (co.path.startsWith("/" + basePath)) {
co.path = co.path.substring(("/" + basePath).length());
}
co.subresourceOperation = !co.path.isEmpty();
}
List<CodegenOperation> opList = operations.get(basePath);
if (opList == null) {
opList = new ArrayList<CodegenOperation>();
operations.put(basePath, opList);
}
opList.add(co);
co.baseName = basePath;
}
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
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.returnType == null) {
operation.returnType = "Void";
} else if (operation.returnType.startsWith("List")) {
String rt = operation.returnType;
int end = rt.lastIndexOf(">");
if (end > 0) {
operation.returnType = rt.substring("List<".length(), end);
operation.returnContainer = "List";
}
} else if (operation.returnType.startsWith("Map")) {
String rt = operation.returnType;
int end = rt.lastIndexOf(">");
if (end > 0) {
operation.returnType = rt.substring("Map<".length(), end);
operation.returnContainer = "Map";
}
} else if (operation.returnType.startsWith("Set")) {
String rt = operation.returnType;
int end = rt.lastIndexOf(">");
if (end > 0) {
operation.returnType = rt.substring("Set<".length(), end);
operation.returnContainer = "Set";
}
}
}
}
return objs;
}
@Override
public void processSwagger(Swagger swagger) {
super.processSwagger(swagger);
try {
File file = new File( outputFolder + "/src/main/swagger/swagger.json" );
file.getParentFile().mkdirs();
FileWriter swaggerFile = new FileWriter(file);
swaggerFile.write( Json.pretty( swagger ));
swaggerFile.flush();
swaggerFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public String toApiName(String name) {
if (name.length() == 0) {
return "DefaultController";
}
name = name.replaceAll("[^a-zA-Z0-9]+", "_");
return camelize(name)+ "Controller";
}
public boolean shouldOverwrite(String filename) {
return super.shouldOverwrite(filename);
}
}

View File

@ -1,13 +1,12 @@
package io.swagger.codegen.languages; package io.swagger.codegen.languages;
import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenOperation; import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenResponse;
import io.swagger.codegen.CodegenType; import io.swagger.codegen.CodegenType;
import io.swagger.codegen.SupportingFile; import io.swagger.codegen.SupportingFile;
import io.swagger.models.Operation; import io.swagger.models.Operation;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
@ -38,10 +37,10 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
apiPackage = System.getProperty("swagger.codegen.jaxrs.apipackage", "io.swagger.api"); apiPackage = System.getProperty("swagger.codegen.jaxrs.apipackage", "io.swagger.api");
modelPackage = System.getProperty("swagger.codegen.jaxrs.modelpackage", "io.swagger.model"); modelPackage = System.getProperty("swagger.codegen.jaxrs.modelpackage", "io.swagger.model");
additionalProperties.put("invokerPackage", invokerPackage); additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
additionalProperties.put("groupId", groupId); additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
additionalProperties.put("artifactId", artifactId); additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
additionalProperties.put("artifactVersion", artifactVersion); additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
additionalProperties.put("title", title); additionalProperties.put("title", title);
@ -89,21 +88,6 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
} }
@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 getTypeDeclaration(inner);
}
return super.getTypeDeclaration(p);
}
@Override @Override
public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations) { public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations) {
String basePath = resourcePath; String basePath = resourcePath;
@ -137,27 +121,35 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
if (operations != null) { if (operations != null) {
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation"); List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
for (CodegenOperation operation : ops) { for (CodegenOperation operation : ops) {
List<CodegenResponse> responses = operation.responses;
if (responses != null) {
for (CodegenResponse resp : responses) {
if ("0".equals(resp.code)) {
resp.code = "200";
}
}
}
if (operation.returnType == null) { if (operation.returnType == null) {
operation.returnType = "Void"; operation.returnType = "Void";
} else if (operation.returnType.startsWith("List")) { } else if (operation.returnType.startsWith("List")) {
String rt = operation.returnType; String rt = operation.returnType;
int end = rt.lastIndexOf(">"); int end = rt.lastIndexOf(">");
if (end > 0) { if (end > 0) {
operation.returnType = rt.substring("List<".length(), end); operation.returnType = rt.substring("List<".length(), end).trim();
operation.returnContainer = "List"; operation.returnContainer = "List";
} }
} else if (operation.returnType.startsWith("Map")) { } else if (operation.returnType.startsWith("Map")) {
String rt = operation.returnType; String rt = operation.returnType;
int end = rt.lastIndexOf(">"); int end = rt.lastIndexOf(">");
if (end > 0) { if (end > 0) {
operation.returnType = rt.substring("Map<".length(), end); operation.returnType = rt.substring("Map<".length(), end).split(",")[1].trim();
operation.returnContainer = "Map"; operation.returnContainer = "Map";
} }
} else if (operation.returnType.startsWith("Set")) { } else if (operation.returnType.startsWith("Set")) {
String rt = operation.returnType; String rt = operation.returnType;
int end = rt.lastIndexOf(">"); int end = rt.lastIndexOf(">");
if (end > 0) { if (end > 0) {
operation.returnType = rt.substring("Set<".length(), end); operation.returnType = rt.substring("Set<".length(), end).trim();
operation.returnContainer = "Set"; operation.returnContainer = "Set";
} }
} }
@ -166,6 +158,15 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
return objs; return objs;
} }
@Override
public String toApiName(String name) {
if (name.length() == 0) {
return "DefaultApi";
}
name = sanitizeName(name);
return camelize(name) + "Api";
}
@Override @Override
public String apiFilename(String templateName, String tag) { public String apiFilename(String templateName, String tag) {
@ -200,7 +201,6 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
} }
public boolean shouldOverwrite(String filename) { public boolean shouldOverwrite(String filename) {
return super.shouldOverwrite(filename) && !filename.endsWith("ServiceImpl.java") && !filename.endsWith("ServiceFactory.java");
return !filename.endsWith("ServiceImpl.java") && !filename.endsWith("ServiceFactory.java");
} }
} }

View File

@ -9,11 +9,19 @@ import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile; import io.swagger.codegen.SupportingFile;
import java.io.File; import java.io.File;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig { public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig {
protected String apiVersion = "1.0.0"; protected String apiVersion = "1.0.0";
@ -197,4 +205,50 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
} }
return objs; return objs;
} }
@SuppressWarnings("unchecked")
private List<Map<String, Object>> getOperations(Map<String, Object> objs) {
List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
Map<String, Object> apiInfo = (Map<String, Object>) objs.get("apiInfo");
List<Map<String, Object>> apis = (List<Map<String, Object>>) apiInfo.get("apis");
for (Map<String, Object> api : apis) {
result.add((Map<String, Object>) api.get("operations"));
}
return result;
}
private List<Map<String, Object>> sortOperationsByPath(List<CodegenOperation> ops) {
Multimap<String, CodegenOperation> opsByPath = ArrayListMultimap.create();
for (CodegenOperation op : ops) {
opsByPath.put(op.path, op);
}
List<Map<String, Object>> opsByPathList = new ArrayList<Map<String, Object>>();
for (Entry<String, Collection<CodegenOperation>> entry : opsByPath.asMap().entrySet()) {
Map<String, Object> opsByPathEntry = new HashMap<String, Object>();
opsByPathList.add(opsByPathEntry);
opsByPathEntry.put("path", entry.getKey());
opsByPathEntry.put("operation", entry.getValue());
List<CodegenOperation> operationsForThisPath = Lists.newArrayList(entry.getValue());
operationsForThisPath.get(operationsForThisPath.size() - 1).hasMore = null;
if (opsByPathList.size() < opsByPath.asMap().size()) {
opsByPathEntry.put("hasMore", "true");
}
}
return opsByPathList;
}
@Override
public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) {
for (Map<String, Object> operations : getOperations(objs)) {
@SuppressWarnings("unchecked")
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
List<Map<String, Object>> opsByPathList = sortOperationsByPath(ops);
operations.put("operationsByPath", opsByPathList);
}
return super.postProcessSupportingFileData(objs);
}
} }

View File

@ -16,45 +16,64 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import org.apache.commons.lang.StringUtils;
public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig { public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
protected Set<String> foundationClasses = new HashSet<String>(); protected Set<String> foundationClasses = new HashSet<String>();
protected String sourceFolder = "client"; protected String podName = "SwaggerClient";
protected String podVersion = "1.0.0";
protected String classPrefix = "SWG"; protected String classPrefix = "SWG";
protected String projectName = "swaggerClient";
public ObjcClientCodegen() { public ObjcClientCodegen() {
super(); super();
outputFolder = "generated-code" + File.separator + "objc"; outputFolder = "generated-code" + File.separator + "objc";
modelTemplateFiles.put("model-header.mustache", ".h"); modelTemplateFiles.put("model-header.mustache", ".h");
modelTemplateFiles.put("model-body.mustache", ".m"); modelTemplateFiles.put("model-body.mustache", ".m");
apiTemplateFiles.put("api-header.mustache", ".h"); apiTemplateFiles.put("api-header.mustache", ".h");
apiTemplateFiles.put("api-body.mustache", ".m"); apiTemplateFiles.put("api-body.mustache", ".m");
templateDir = "objc"; templateDir = "objc";
modelPackage = "";
defaultIncludes = new HashSet<String>( defaultIncludes.clear();
Arrays.asList( defaultIncludes.add("bool");
"bool", defaultIncludes.add("BOOL");
"BOOL", defaultIncludes.add("int");
"int", defaultIncludes.add("NSURL");
"NSString", defaultIncludes.add("NSString");
"NSObject", defaultIncludes.add("NSObject");
"NSArray", defaultIncludes.add("NSArray");
"NSNumber", defaultIncludes.add("NSNumber");
"NSDate", defaultIncludes.add("NSDate");
"NSDictionary", defaultIncludes.add("NSDictionary");
"NSMutableArray", defaultIncludes.add("NSMutableArray");
"NSMutableDictionary") defaultIncludes.add("NSMutableDictionary");
);
languageSpecificPrimitives = new HashSet<String>( languageSpecificPrimitives.clear();
Arrays.asList( languageSpecificPrimitives.add("NSNumber");
"NSNumber", languageSpecificPrimitives.add("NSString");
"NSString", languageSpecificPrimitives.add("NSObject");
"NSObject", languageSpecificPrimitives.add("NSDate");
"NSDate", languageSpecificPrimitives.add("NSURL");
"bool", languageSpecificPrimitives.add("bool");
"BOOL") languageSpecificPrimitives.add("BOOL");
);
typeMapping.clear();
typeMapping.put("enum", "NSString");
typeMapping.put("date", "NSDate");
typeMapping.put("DateTime", "NSDate");
typeMapping.put("boolean", "NSNumber");
typeMapping.put("string", "NSString");
typeMapping.put("integer", "NSNumber");
typeMapping.put("int", "NSNumber");
typeMapping.put("float", "NSNumber");
typeMapping.put("long", "NSNumber");
typeMapping.put("double", "NSNumber");
typeMapping.put("array", "NSArray");
typeMapping.put("map", "NSDictionary");
typeMapping.put("number", "NSNumber");
typeMapping.put("List", "NSArray");
typeMapping.put("object", "NSObject");
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>(
@ -70,26 +89,10 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
"double", "protocol", "interface", "implementation", "double", "protocol", "interface", "implementation",
"NSObject", "NSInteger", "NSNumber", "CGFloat", "NSObject", "NSInteger", "NSNumber", "CGFloat",
"property", "nonatomic", "retain", "strong", "property", "nonatomic", "retain", "strong",
"weak", "unsafe_unretained", "readwrite", "readonly" "weak", "unsafe_unretained", "readwrite", "readonly",
"description"
)); ));
typeMapping = new HashMap<String, String>();
typeMapping.put("enum", "NSString");
typeMapping.put("Date", "NSDate");
typeMapping.put("DateTime", "NSDate");
typeMapping.put("boolean", "BOOL");
typeMapping.put("string", "NSString");
typeMapping.put("integer", "NSNumber");
typeMapping.put("int", "NSNumber");
typeMapping.put("float", "NSNumber");
typeMapping.put("long", "NSNumber");
typeMapping.put("double", "NSNumber");
typeMapping.put("array", "NSArray");
typeMapping.put("map", "NSDictionary");
typeMapping.put("number", "NSNumber");
typeMapping.put("List", "NSArray");
typeMapping.put("object", "NSObject");
importMapping = new HashMap<String, String>(); importMapping = new HashMap<String, String>();
foundationClasses = new HashSet<String>( foundationClasses = new HashSet<String>(
@ -98,15 +101,17 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
"NSObject", "NSObject",
"NSString", "NSString",
"NSDate", "NSDate",
"NSURL",
"NSDictionary") "NSDictionary")
); );
instantiationTypes.put("array", "NSMutableArray"); instantiationTypes.put("array", "NSMutableArray");
instantiationTypes.put("map", "NSMutableDictionary"); instantiationTypes.put("map", "NSMutableDictionary");
cliOptions.add(new CliOption("classPrefix", "prefix for generated classes")); cliOptions.clear();
cliOptions.add(new CliOption("sourceFolder", "source folder for generated code")); cliOptions.add(new CliOption("classPrefix", "prefix for generated classes (convention: Abbreviation of pod name e.g. `HN` for `HackerNews`), default: `SWG`"));
cliOptions.add(new CliOption("projectName", "name of the Xcode project in generated Podfile")); cliOptions.add(new CliOption("podName", "cocoapods package name (convention: CameCase), default: `SwaggerClient`"));
cliOptions.add(new CliOption("podVersion", "cocoapods package version, default: `1.0.0`"));
} }
public CodegenType getTag() { public CodegenType getTag() {
@ -125,33 +130,43 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
public void processOpts() { public void processOpts() {
super.processOpts(); super.processOpts();
if (additionalProperties.containsKey("sourceFolder")) { if (additionalProperties.containsKey("podName")) {
this.setSourceFolder((String) additionalProperties.get("sourceFolder")); setPodName((String) additionalProperties.get("podName"));
}
if (additionalProperties.containsKey("podVersion")) {
setPodVersion((String) additionalProperties.get("podVersion"));
} }
if (additionalProperties.containsKey("classPrefix")) { if (additionalProperties.containsKey("classPrefix")) {
this.setClassPrefix((String) additionalProperties.get("classPrefix")); setClassPrefix((String) additionalProperties.get("classPrefix"));
} }
if (additionalProperties.containsKey("projectName")) { additionalProperties.put("podName", podName);
this.setProjectName((String) additionalProperties.get("projectName")); additionalProperties.put("podVersion", podVersion);
} else { additionalProperties.put("classPrefix", classPrefix);
additionalProperties.put("projectName", projectName);
}
supportingFiles.add(new SupportingFile("SWGObject.h", sourceFolder, "SWGObject.h")); String swaggerFolder = podName;
supportingFiles.add(new SupportingFile("SWGObject.m", sourceFolder, "SWGObject.m"));
supportingFiles.add(new SupportingFile("SWGQueryParamCollection.h", sourceFolder, "SWGQueryParamCollection.h")); modelPackage = swaggerFolder;
supportingFiles.add(new SupportingFile("SWGQueryParamCollection.m", sourceFolder, "SWGQueryParamCollection.m")); apiPackage = swaggerFolder;
supportingFiles.add(new SupportingFile("SWGApiClient.h", sourceFolder, "SWGApiClient.h"));
supportingFiles.add(new SupportingFile("SWGApiClient.m", sourceFolder, "SWGApiClient.m")); supportingFiles.add(new SupportingFile("Object-header.mustache", swaggerFolder, classPrefix + "Object.h"));
supportingFiles.add(new SupportingFile("SWGFile.h", sourceFolder, "SWGFile.h")); supportingFiles.add(new SupportingFile("Object-body.mustache", swaggerFolder, classPrefix + "Object.m"));
supportingFiles.add(new SupportingFile("SWGFile.m", sourceFolder, "SWGFile.m")); supportingFiles.add(new SupportingFile("QueryParamCollection-header.mustache", swaggerFolder, classPrefix + "QueryParamCollection.h"));
supportingFiles.add(new SupportingFile("JSONValueTransformer+ISO8601.m", sourceFolder, "JSONValueTransformer+ISO8601.m")); supportingFiles.add(new SupportingFile("QueryParamCollection-body.mustache", swaggerFolder, classPrefix + "QueryParamCollection.m"));
supportingFiles.add(new SupportingFile("JSONValueTransformer+ISO8601.h", sourceFolder, "JSONValueTransformer+ISO8601.h")); supportingFiles.add(new SupportingFile("ApiClient-header.mustache", swaggerFolder, classPrefix + "ApiClient.h"));
supportingFiles.add(new SupportingFile("SWGConfiguration-body.mustache", sourceFolder, "SWGConfiguration.m")); supportingFiles.add(new SupportingFile("ApiClient-body.mustache", swaggerFolder, classPrefix + "ApiClient.m"));
supportingFiles.add(new SupportingFile("SWGConfiguration-header.mustache", sourceFolder, "SWGConfiguration.h")); supportingFiles.add(new SupportingFile("JSONResponseSerializer-header.mustache", swaggerFolder, classPrefix + "JSONResponseSerializer.h"));
supportingFiles.add(new SupportingFile("Podfile.mustache", "", "Podfile")); supportingFiles.add(new SupportingFile("JSONResponseSerializer-body.mustache", swaggerFolder, classPrefix + "JSONResponseSerializer.m"));
supportingFiles.add(new SupportingFile("JSONRequestSerializer-body.mustache", swaggerFolder, classPrefix + "JSONRequestSerializer.m"));
supportingFiles.add(new SupportingFile("JSONRequestSerializer-header.mustache", swaggerFolder, classPrefix + "JSONRequestSerializer.h"));
supportingFiles.add(new SupportingFile("JSONValueTransformer+ISO8601.m", swaggerFolder, "JSONValueTransformer+ISO8601.m"));
supportingFiles.add(new SupportingFile("JSONValueTransformer+ISO8601.h", swaggerFolder, "JSONValueTransformer+ISO8601.h"));
supportingFiles.add(new SupportingFile("Configuration-body.mustache", swaggerFolder, classPrefix + "Configuration.m"));
supportingFiles.add(new SupportingFile("Configuration-header.mustache", swaggerFolder, classPrefix + "Configuration.h"));
supportingFiles.add(new SupportingFile("podspec.mustache", "", podName + ".podspec"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
} }
@Override @Override
@ -200,21 +215,32 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
Property inner = ap.getItems(); Property inner = ap.getItems();
String innerType = getSwaggerType(inner); String innerType = getSwaggerType(inner);
// In this codition, type of property p is array of primitive,
// return container type with pointer, e.g. `NSArray*'
if (languageSpecificPrimitives.contains(innerType)) {
return getSwaggerType(p) + "*";
}
// In this codition, type of property p is array of model,
// return container type combine inner type with pointer, e.g. `NSArray<SWGTag>*'
String innerTypeDeclaration = getTypeDeclaration(inner); String innerTypeDeclaration = getTypeDeclaration(inner);
if (innerTypeDeclaration.endsWith("*")) { if (innerTypeDeclaration.endsWith("*")) {
innerTypeDeclaration = innerTypeDeclaration.substring(0, innerTypeDeclaration.length() - 1); innerTypeDeclaration = innerTypeDeclaration.substring(0, innerTypeDeclaration.length() - 1);
} }
// In this codition, type of property p is array of primitive,
// return container type with pointer, e.g. `NSArray* /* NSString */'
if (languageSpecificPrimitives.contains(innerType)) {
return getSwaggerType(p) + "*" + " /* " + innerTypeDeclaration + " */";
}
// In this codition, type of property p is array of model,
// return container type combine inner type with pointer, e.g. `NSArray<SWGTag>*'
else {
return getSwaggerType(p) + "<" + innerTypeDeclaration + ">*"; return getSwaggerType(p) + "<" + innerTypeDeclaration + ">*";
}
} else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();
String innerTypeDeclaration = getTypeDeclaration(inner);
if (innerTypeDeclaration.endsWith("*")) {
innerTypeDeclaration = innerTypeDeclaration.substring(0, innerTypeDeclaration.length() - 1);
}
return getSwaggerType(p) + "* /* NSString, " + innerTypeDeclaration + " */";
} else { } else {
String swaggerType = getSwaggerType(p); String swaggerType = getSwaggerType(p);
@ -273,11 +299,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toModelImport(String name) { public String toModelImport(String name) {
if ("".equals(modelPackage())) {
return name; return name;
} else {
return modelPackage() + "." + name;
}
} }
@Override @Override
@ -287,12 +309,12 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String apiFileFolder() { public String apiFileFolder() {
return outputFolder + File.separator + sourceFolder; return outputFolder + File.separatorChar + apiPackage();
} }
@Override @Override
public String modelFileFolder() { public String modelFileFolder() {
return outputFolder + File.separator + sourceFolder; return outputFolder + File.separatorChar + modelPackage();
} }
@Override @Override
@ -306,9 +328,8 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toVarName(String name) { public String toVarName(String name) {
// replace non-word characters to `_` // sanitize name
// e.g. `created-at` to `created_at` name = sanitizeName(name);
name = name.replaceAll("[^a-zA-Z0-9_]", "_");
// if it's all upper case, do noting // if it's all upper case, do noting
if (name.matches("^[A-Z_]$")) { if (name.matches("^[A-Z_]$")) {
@ -339,23 +360,28 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toOperationId(String operationId) { public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
// method name cannot use reserved keyword, e.g. return // method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) { if (reservedWords.contains(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
} }
return camelize(operationId, true); return camelize(sanitizeName(operationId), true);
}
public void setSourceFolder(String sourceFolder) {
this.sourceFolder = sourceFolder;
} }
public void setClassPrefix(String classPrefix) { public void setClassPrefix(String classPrefix) {
this.classPrefix = classPrefix; this.classPrefix = classPrefix;
} }
public void setProjectName(String projectName) { public void setPodName(String podName) {
this.projectName = projectName; this.podName = podName;
}
public void setPodVersion(String podVersion) {
this.podVersion = podVersion;
} }
} }

View File

@ -7,16 +7,17 @@ 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.codegen.CliOption;
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 org.apache.commons.lang.StringUtils;
public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig { public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String invokerPackage = "SwaggerClient"; protected String moduleName = "SwaggerClient";
protected String groupId = "io.swagger"; protected String moduleVersion = "1.0.0";
protected String artifactId = "swagger-client";
protected String artifactVersion = "1.0.0";
public PerlClientCodegen() { public PerlClientCodegen() {
super(); super();
@ -26,8 +27,6 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
apiTemplateFiles.put("api.mustache", ".pm"); apiTemplateFiles.put("api.mustache", ".pm");
templateDir = "perl"; templateDir = "perl";
typeMapping.clear();
languageSpecificPrimitives.clear();
reservedWords = new HashSet<String>( reservedWords = new HashSet<String>(
Arrays.asList( Arrays.asList(
@ -44,11 +43,7 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
) )
); );
additionalProperties.put("invokerPackage", invokerPackage); languageSpecificPrimitives.clear();
additionalProperties.put("groupId", groupId);
additionalProperties.put("artifactId", artifactId);
additionalProperties.put("artifactVersion", artifactVersion);
languageSpecificPrimitives.add("int"); languageSpecificPrimitives.add("int");
languageSpecificPrimitives.add("double"); languageSpecificPrimitives.add("double");
languageSpecificPrimitives.add("string"); languageSpecificPrimitives.add("string");
@ -58,6 +53,7 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
languageSpecificPrimitives.add("HASH"); languageSpecificPrimitives.add("HASH");
languageSpecificPrimitives.add("object"); languageSpecificPrimitives.add("object");
typeMapping.clear();
typeMapping.put("integer", "int"); typeMapping.put("integer", "int");
typeMapping.put("long", "int"); typeMapping.put("long", "int");
typeMapping.put("float", "double"); typeMapping.put("float", "double");
@ -71,9 +67,31 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("map", "HASH"); typeMapping.put("map", "HASH");
typeMapping.put("object", "object"); typeMapping.put("object", "object");
supportingFiles.add(new SupportingFile("ApiClient.mustache", ("lib/WWW/" + invokerPackage).replace('/', File.separatorChar), "ApiClient.pm")); cliOptions.clear();
supportingFiles.add(new SupportingFile("Configuration.mustache", ("lib/WWW/" + invokerPackage).replace('/', File.separatorChar), "Configuration.pm")); cliOptions.add(new CliOption("moduleName", "perl module name (convention: CamelCase), default: SwaggerClient"));
supportingFiles.add(new SupportingFile("BaseObject.mustache", ("lib/WWW/" + invokerPackage).replace('/', File.separatorChar), "Object/BaseObject.pm")); cliOptions.add(new CliOption("moduleVersion", "perl module version, default: 1.0.0"));
}
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey("moduleVersion")) {
moduleVersion = (String) additionalProperties.get("moduleVersion");
} else {
additionalProperties.put("moduleVersion", moduleVersion);
}
if (additionalProperties.containsKey("moduleName")) {
moduleName = (String) additionalProperties.get("moduleName");
} else {
additionalProperties.put("moduleName", moduleName);
}
supportingFiles.add(new SupportingFile("ApiClient.mustache", ("lib/WWW/" + moduleName).replace('/', File.separatorChar), "ApiClient.pm"));
supportingFiles.add(new SupportingFile("Configuration.mustache", ("lib/WWW/" + moduleName).replace('/', File.separatorChar), "Configuration.pm"));
supportingFiles.add(new SupportingFile("BaseObject.mustache", ("lib/WWW/" + moduleName).replace('/', File.separatorChar), "Object/BaseObject.pm"));
} }
public CodegenType getTag() { public CodegenType getTag() {
@ -95,11 +113,11 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String apiFileFolder() { public String apiFileFolder() {
return (outputFolder + "/lib/WWW/" + invokerPackage + apiPackage()).replace('/', File.separatorChar); return (outputFolder + "/lib/WWW/" + moduleName + apiPackage()).replace('/', File.separatorChar);
} }
public String modelFileFolder() { public String modelFileFolder() {
return (outputFolder + "/lib/WWW/" + invokerPackage + modelPackage()).replace('/', File.separatorChar); return (outputFolder + "/lib/WWW/" + moduleName + modelPackage()).replace('/', File.separatorChar);
} }
@Override @Override
@ -141,15 +159,17 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toVarName(String name) { public String toVarName(String name) {
// return the name in underscore style
// PhoneNumber => phone_number
name = underscore(name);
// parameter name starting with number won't compile // parameter name starting with number won't compile
// need to escape it by appending _ at the beginning // need to escape it by appending _ at the beginning
if (name.matches("^[0-9]")) { if (name.matches("^\\d.*")) {
name = "_" + name; name = "_" + name;
} }
// return the name in underscore style return name;
// PhoneNumber => phone_number
return underscore(name);
} }
@Override @Override
@ -196,6 +216,11 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toOperationId(String operationId) { public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
// method name cannot use reserved keyword, e.g. return // method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) { if (reservedWords.contains(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");

View File

@ -1,51 +1,51 @@
package io.swagger.codegen.languages; package io.swagger.codegen.languages;
import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenConfig;
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.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.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 org.apache.commons.lang3.StringUtils;
public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String invokerPackage = "io.swagger.client"; protected String invokerPackage = "Swagger\\Client";
protected String groupId = "io.swagger"; protected String composerVendorName = "swagger";
protected String artifactId = "swagger-client"; protected String composerProjectName = "swagger-client";
protected String packagePath = "SwaggerClient-php";
protected String artifactVersion = "1.0.0"; protected String artifactVersion = "1.0.0";
protected String srcBasePath = "lib";
protected String variableNamingConvention= "snake_case";
public PhpClientCodegen() { public PhpClientCodegen() {
super(); super();
invokerPackage = camelize("SwaggerClient"); outputFolder = "generated-code" + File.separator + "php";
String packagePath = invokerPackage + "-php";
modelPackage = packagePath + "/lib/models";
apiPackage = packagePath + "/lib";
outputFolder = "generated-code/php";
modelTemplateFiles.put("model.mustache", ".php"); modelTemplateFiles.put("model.mustache", ".php");
apiTemplateFiles.put("api.mustache", ".php"); apiTemplateFiles.put("api.mustache", ".php");
templateDir = "php"; templateDir = "php";
apiPackage = invokerPackage + "\\Api";
modelPackage = invokerPackage + "\\Model";
reservedWords = new HashSet<String>( reservedWords = new HashSet<String>(
Arrays.asList( 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") "__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("invokerPackage", invokerPackage);
additionalProperties.put("groupId", groupId);
additionalProperties.put("artifactId", artifactId);
additionalProperties.put("artifactVersion", artifactVersion);
// ref: http://php.net/manual/en/language.types.intro.php // ref: http://php.net/manual/en/language.types.intro.php
languageSpecificPrimitives = new HashSet<String>( languageSpecificPrimitives = new HashSet<String>(
Arrays.asList( Arrays.asList(
"bool",
"boolean", "boolean",
"int", "int",
"integer", "integer",
@ -55,12 +55,19 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
"object", "object",
"DateTime", "DateTime",
"mixed", "mixed",
"number") "number",
"void",
"byte")
); );
instantiationTypes.put("array", "array"); instantiationTypes.put("array", "array");
instantiationTypes.put("map", "map"); instantiationTypes.put("map", "map");
// provide primitives to mustache template
String primitives = "'" + StringUtils.join(languageSpecificPrimitives, "', '") + "'";
additionalProperties.put("primitives", primitives);
// ref: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#data-types // ref: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#data-types
typeMapping = new HashMap<String, String>(); typeMapping = new HashMap<String, String>();
typeMapping.put("integer", "int"); typeMapping.put("integer", "int");
@ -69,20 +76,56 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("double", "double"); typeMapping.put("double", "double");
typeMapping.put("string", "string"); typeMapping.put("string", "string");
typeMapping.put("byte", "int"); typeMapping.put("byte", "int");
typeMapping.put("boolean", "boolean"); typeMapping.put("boolean", "bool");
typeMapping.put("date", "DateTime"); typeMapping.put("date", "\\DateTime");
typeMapping.put("datetime", "DateTime"); typeMapping.put("datetime", "\\DateTime");
typeMapping.put("file", "string"); typeMapping.put("file", "\\SplFileObject");
typeMapping.put("map", "map"); typeMapping.put("map", "map");
typeMapping.put("array", "array"); typeMapping.put("array", "array");
typeMapping.put("list", "array"); typeMapping.put("list", "array");
typeMapping.put("object", "object"); typeMapping.put("object", "object");
typeMapping.put("DateTime", "\\DateTime");
supportingFiles.add(new SupportingFile("composer.mustache", packagePath.replace('/', File.separatorChar), "composer.json")); cliOptions.add(new CliOption("variableNamingConvention", "naming convention of variable name, e.g. camelCase. Default: snake_case"));
supportingFiles.add(new SupportingFile("configuration.mustache", (packagePath + "/lib").replace('/', File.separatorChar), "Configuration.php")); cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE, "The main namespace to use for all classes. e.g. Yay\\Pets"));
supportingFiles.add(new SupportingFile("ApiClient.mustache", (packagePath + "/lib").replace('/', File.separatorChar), "ApiClient.php")); cliOptions.add(new CliOption("packagePath", "The main package name for classes. e.g. GeneratedPetstore"));
supportingFiles.add(new SupportingFile("ApiException.mustache", (packagePath + "/lib").replace('/', File.separatorChar), "ApiException.php")); cliOptions.add(new CliOption("srcBasePath", "The directory under packagePath to serve as source root."));
supportingFiles.add(new SupportingFile("require.mustache", packagePath.replace('/', File.separatorChar), invokerPackage + ".php")); cliOptions.add(new CliOption("composerVendorName", "The vendor name used in the composer package name. The template uses {{composerVendorName}}/{{composerProjectName}} for the composer package name. e.g. yaypets"));
cliOptions.add(new CliOption("composerProjectName", "The project name used in the composer package name. The template uses {{composerVendorName}}/{{composerProjectName}} for the composer package name. e.g. petstore-client"));
cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_VERSION, "The version to use in the composer package version field. e.g. 1.2.3"));
}
public String getPackagePath() {
return packagePath;
}
public String toPackagePath(String packageName, String basePath) {
packageName = packageName.replace(invokerPackage, "");
if (basePath != null && basePath.length() > 0) {
basePath = basePath.replaceAll("[\\\\/]?$", "") + File.separatorChar;
}
String regFirstPathSeparator;
if ("/".equals(File.separator)) { // for mac, linux
regFirstPathSeparator = "^/";
} else { // for windows
regFirstPathSeparator = "^\\\\";
}
String regLastPathSeparator;
if ("/".equals(File.separator)) { // for mac, linux
regLastPathSeparator = "/$";
} else { // for windows
regLastPathSeparator = "\\\\$";
}
return (getPackagePath() + File.separatorChar + basePath
// Replace period, backslash, forward slash with file separator in package name
+ packageName.replaceAll("[\\.\\\\/]", File.separator)
// Trim prefix file separators from package path
.replaceAll(regFirstPathSeparator, ""))
// Trim trailing file separators from the overall path
.replaceAll(regLastPathSeparator+ "$", "");
} }
public CodegenType getTag() { public CodegenType getTag() {
@ -97,6 +140,68 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
return "Generates a PHP client library."; return "Generates a PHP client library.";
} }
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey("packagePath")) {
this.setPackagePath((String) additionalProperties.get("packagePath"));
} else {
additionalProperties.put("packagePath", packagePath);
}
if (additionalProperties.containsKey("srcBasePath")) {
this.setSrcBasePath((String) additionalProperties.get("srcBasePath"));
} else {
additionalProperties.put("srcBasePath", srcBasePath);
}
if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) {
this.setInvokerPackage((String) additionalProperties.get(CodegenConstants.INVOKER_PACKAGE));
} else {
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
}
if (additionalProperties.containsKey(CodegenConstants.MODEL_PACKAGE)) {
this.setModelPackage((String) additionalProperties.get(CodegenConstants.MODEL_PACKAGE));
} else {
additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage);
}
if (additionalProperties.containsKey(CodegenConstants.API_PACKAGE)) {
this.setApiPackage((String) additionalProperties.get(CodegenConstants.API_PACKAGE));
} else {
additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage);
}
if (additionalProperties.containsKey("composerProjectName")) {
this.setComposerProjectName((String) additionalProperties.get("composerProjectName"));
} else {
additionalProperties.put("composerProjectName", composerProjectName);
}
if (additionalProperties.containsKey("composerVendorName")) {
this.setComposerVendorName((String) additionalProperties.get("composerVendorName"));
} else {
additionalProperties.put("composerVendorName", composerVendorName);
}
if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_VERSION)) {
this.setArtifactVersion((String) additionalProperties.get(CodegenConstants.ARTIFACT_VERSION));
} else {
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
}
additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\"));
supportingFiles.add(new SupportingFile("configuration.mustache", toPackagePath(invokerPackage, srcBasePath), "Configuration.php"));
supportingFiles.add(new SupportingFile("ApiClient.mustache", toPackagePath(invokerPackage, srcBasePath), "ApiClient.php"));
supportingFiles.add(new SupportingFile("ApiException.mustache", toPackagePath(invokerPackage, srcBasePath), "ApiException.php"));
supportingFiles.add(new SupportingFile("ObjectSerializer.mustache", toPackagePath(invokerPackage, srcBasePath), "ObjectSerializer.php"));
supportingFiles.add(new SupportingFile("composer.mustache", getPackagePath(), "composer.json"));
supportingFiles.add(new SupportingFile("autoload.mustache", getPackagePath(), "autoload.php"));
}
@Override @Override
public String escapeReservedWord(String name) { public String escapeReservedWord(String name) {
return "_" + name; return "_" + name;
@ -104,11 +209,11 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String apiFileFolder() { public String apiFileFolder() {
return (outputFolder + "/" + apiPackage()).replace('/', File.separatorChar); return (outputFolder + "/" + toPackagePath(apiPackage(), srcBasePath));
} }
public String modelFileFolder() { public String modelFileFolder() {
return (outputFolder + "/" + modelPackage()).replace('/', File.separatorChar); return (outputFolder + "/" + toPackagePath(modelPackage(), srcBasePath));
} }
@Override @Override
@ -116,15 +221,27 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
if (p instanceof ArrayProperty) { if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p; ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems(); Property inner = ap.getItems();
return getSwaggerType(p) + "[" + getTypeDeclaration(inner) + "]"; return getTypeDeclaration(inner) + "[]";
} else if (p instanceof MapProperty) { } else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p; MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties(); Property inner = mp.getAdditionalProperties();
return getSwaggerType(p) + "[string," + getTypeDeclaration(inner) + "]"; 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); return super.getTypeDeclaration(p);
} }
@Override
public String getTypeDeclaration(String name) {
if (!languageSpecificPrimitives.contains(name)) {
return "\\" + modelPackage + "\\" + name;
}
return super.getTypeDeclaration(name);
}
@Override @Override
public String getSwaggerType(Property p) { public String getSwaggerType(Property p) {
String swaggerType = super.getSwaggerType(p); String swaggerType = super.getSwaggerType(p);
@ -149,18 +266,60 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
return "null"; return "null";
} }
public void setInvokerPackage(String invokerPackage) {
this.invokerPackage = invokerPackage;
}
public void setArtifactVersion(String artifactVersion) {
this.artifactVersion = artifactVersion;
}
public void setPackagePath(String packagePath) {
this.packagePath = packagePath;
}
public void setSrcBasePath(String srcBasePath) {
this.srcBasePath = srcBasePath;
}
public void setParameterNamingConvention(String variableNamingConvention) {
this.variableNamingConvention = variableNamingConvention;
}
private void setComposerVendorName(String composerVendorName) {
this.composerVendorName = composerVendorName;
}
public void setComposerProjectName(String composerProjectName) {
this.composerProjectName = composerProjectName;
}
@Override @Override
public String toVarName(String name) { public String toVarName(String name) {
if (additionalProperties.containsKey("variableNamingConvention")) {
this.setParameterNamingConvention((String) additionalProperties.get("variableNamingConvention"));
}
// 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 // parameter name starting with number won't compile
// need to escape it by appending _ at the beginning // need to escape it by appending _ at the beginning
if (name.matches("^[0-9]")) { if (name.matches("^\\d.*")) {
name = "_" + name; name = "_" + name;
} }
// return the name in underscore style return name;
// PhoneNumber => phone_number
return underscore(name);
} }
@Override @Override
@ -187,4 +346,19 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
return toModelName(name); return toModelName(name);
} }
@Override
public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method 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);
}
} }

View File

@ -12,6 +12,8 @@ import java.io.File;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import org.apache.commons.lang.StringUtils;
public class Python3ClientCodegen extends DefaultCodegen implements CodegenConfig { public class Python3ClientCodegen extends DefaultCodegen implements CodegenConfig {
String module = "client"; String module = "client";
@ -33,6 +35,7 @@ public class Python3ClientCodegen extends DefaultCodegen implements CodegenConfi
languageSpecificPrimitives.add("bool"); languageSpecificPrimitives.add("bool");
languageSpecificPrimitives.add("str"); languageSpecificPrimitives.add("str");
languageSpecificPrimitives.add("datetime"); languageSpecificPrimitives.add("datetime");
languageSpecificPrimitives.add("date");
typeMapping.clear(); typeMapping.clear();
typeMapping.put("integer", "int"); typeMapping.put("integer", "int");
@ -43,7 +46,8 @@ public class Python3ClientCodegen extends DefaultCodegen implements CodegenConfi
typeMapping.put("map", "map"); typeMapping.put("map", "map");
typeMapping.put("boolean", "bool"); typeMapping.put("boolean", "bool");
typeMapping.put("string", "str"); typeMapping.put("string", "str");
typeMapping.put("date", "datetime"); typeMapping.put("date", "date");
typeMapping.put("DateTime", "datetime");
// from https://docs.python.org/release/2.5.4/ref/keywords.html // from https://docs.python.org/release/2.5.4/ref/keywords.html
reservedWords = new HashSet<String>( reservedWords = new HashSet<String>(
@ -199,6 +203,11 @@ public class Python3ClientCodegen extends DefaultCodegen implements CodegenConfi
@Override @Override
public String toOperationId(String operationId) { public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
// method name cannot use reserved keyword, e.g. return // method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) { if (reservedWords.contains(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");

View File

@ -1,5 +1,6 @@
package io.swagger.codegen.languages; package io.swagger.codegen.languages;
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;
import io.swagger.codegen.DefaultCodegen; import io.swagger.codegen.DefaultCodegen;
@ -12,26 +13,22 @@ import java.io.File;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import org.apache.commons.lang.StringUtils;
public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig { public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String module = "SwaggerPetstore"; protected String packageName = null;
protected String invokerPackage; protected String packageVersion = null;
protected String eggPackage;
public PythonClientCodegen() { public PythonClientCodegen() {
super(); super();
eggPackage = module + "-python"; modelPackage = "models";
apiPackage = "api";
invokerPackage = eggPackage + File.separatorChar + module;
outputFolder = "generated-code" + File.separatorChar + "python"; outputFolder = "generated-code" + File.separatorChar + "python";
modelTemplateFiles.put("model.mustache", ".py"); modelTemplateFiles.put("model.mustache", ".py");
apiTemplateFiles.put("api.mustache", ".py"); apiTemplateFiles.put("api.mustache", ".py");
templateDir = "python"; templateDir = "python";
apiPackage = invokerPackage + File.separatorChar + "apis";
modelPackage = invokerPackage + File.separatorChar + "models";
languageSpecificPrimitives.clear(); languageSpecificPrimitives.clear();
languageSpecificPrimitives.add("int"); languageSpecificPrimitives.add("int");
languageSpecificPrimitives.add("float"); languageSpecificPrimitives.add("float");
@ -39,6 +36,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
languageSpecificPrimitives.add("bool"); languageSpecificPrimitives.add("bool");
languageSpecificPrimitives.add("str"); languageSpecificPrimitives.add("str");
languageSpecificPrimitives.add("datetime"); languageSpecificPrimitives.add("datetime");
languageSpecificPrimitives.add("date");
typeMapping.clear(); typeMapping.clear();
typeMapping.put("integer", "int"); typeMapping.put("integer", "int");
@ -46,10 +44,13 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
typeMapping.put("long", "int"); typeMapping.put("long", "int");
typeMapping.put("double", "float"); typeMapping.put("double", "float");
typeMapping.put("array", "list"); typeMapping.put("array", "list");
typeMapping.put("map", "map"); typeMapping.put("map", "dict");
typeMapping.put("boolean", "bool"); typeMapping.put("boolean", "bool");
typeMapping.put("string", "str"); typeMapping.put("string", "str");
typeMapping.put("date", "datetime"); typeMapping.put("date", "date");
typeMapping.put("DateTime", "datetime");
typeMapping.put("object", "object");
typeMapping.put("file", "file");
// from https://docs.python.org/release/2.5.4/ref/keywords.html // from https://docs.python.org/release/2.5.4/ref/keywords.html
reservedWords = new HashSet<String>( reservedWords = new HashSet<String>(
@ -59,14 +60,43 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
"print", "class", "exec", "in", "raise", "continue", "finally", "is", "print", "class", "exec", "in", "raise", "continue", "finally", "is",
"return", "def", "for", "lambda", "try")); "return", "def", "for", "lambda", "try"));
additionalProperties.put("module", module); cliOptions.clear();
cliOptions.add(new CliOption("packageName", "python package name (convention: snake_case), default: swagger_client"));
cliOptions.add(new CliOption("packageVersion", "python package version, default: 1.0.0"));
}
supportingFiles.add(new SupportingFile("README.mustache", eggPackage, "README.md")); @Override
supportingFiles.add(new SupportingFile("setup.mustache", eggPackage, "setup.py")); public void processOpts() {
supportingFiles.add(new SupportingFile("api_client.mustache", invokerPackage, "api_client.py")); super.processOpts();
supportingFiles.add(new SupportingFile("rest.mustache", invokerPackage, "rest.py"));
supportingFiles.add(new SupportingFile("configuration.mustache", invokerPackage, "configuration.py")); if (additionalProperties.containsKey("packageName")) {
supportingFiles.add(new SupportingFile("__init__package.mustache", invokerPackage, "__init__.py")); setPackageName((String) additionalProperties.get("packageName"));
}
else {
setPackageName("swagger_client");
}
if (additionalProperties.containsKey("packageVersion")) {
setPackageVersion((String) additionalProperties.get("packageVersion"));
}
else {
setPackageVersion("1.0.0");
}
additionalProperties.put("packageName", packageName);
additionalProperties.put("packageVersion", packageVersion);
String swaggerFolder = packageName;
modelPackage = swaggerFolder + File.separatorChar + "models";
apiPackage = swaggerFolder + File.separatorChar + "apis";
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("setup.mustache", "", "setup.py"));
supportingFiles.add(new SupportingFile("api_client.mustache", swaggerFolder, "api_client.py"));
supportingFiles.add(new SupportingFile("rest.mustache", swaggerFolder, "rest.py"));
supportingFiles.add(new SupportingFile("configuration.mustache", swaggerFolder, "configuration.py"));
supportingFiles.add(new SupportingFile("__init__package.mustache", swaggerFolder, "__init__.py"));
supportingFiles.add(new SupportingFile("__init__model.mustache", modelPackage, "__init__.py")); supportingFiles.add(new SupportingFile("__init__model.mustache", modelPackage, "__init__.py"));
supportingFiles.add(new SupportingFile("__init__api.mustache", apiPackage, "__init__.py")); supportingFiles.add(new SupportingFile("__init__api.mustache", apiPackage, "__init__.py"));
} }
@ -111,7 +141,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
MapProperty mp = (MapProperty) p; MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties(); Property inner = mp.getAdditionalProperties();
return getSwaggerType(p) + "(String, " + getTypeDeclaration(inner) + ")"; return getSwaggerType(p) + "(str, " + getTypeDeclaration(inner) + ")";
} }
return super.getTypeDeclaration(p); return super.getTypeDeclaration(p);
} }
@ -132,14 +162,13 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
} }
public String toDefaultValue(Property p) { public String toDefaultValue(Property p) {
// TODO: Support Python def value return "None";
return "null";
} }
@Override @Override
public String toVarName(String name) { public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at // sanitize name
name = name.replaceAll("-", "_"); name = sanitizeName(name);
// if it's all uppper case, convert to lower case // if it's all uppper case, convert to lower case
if (name.matches("^[A-Z_]*$")) { if (name.matches("^[A-Z_]*$")) {
@ -148,7 +177,10 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
// underscore the variable name // underscore the variable name
// petId => pet_id // petId => pet_id
name = underscore(dropDots(name)); name = underscore(name);
// remove leading underscore
name = name.replaceAll("^_*", "");
// for reserved word or word starting with number, append _ // for reserved word or word starting with number, append _
if (reservedWords.contains(name) || name.matches("^\\d.*")) { if (reservedWords.contains(name) || name.matches("^\\d.*")) {
@ -216,12 +248,36 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
@Override @Override
public String toOperationId(String operationId) { public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
// method name cannot use reserved keyword, e.g. return // method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) { if (reservedWords.contains(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
} }
return underscore(operationId); return underscore(sanitizeName(operationId));
} }
public void setPackageName(String packageName) {
this.packageName = packageName;
} }
public void setPackageVersion(String packageVersion) {
this.packageVersion = packageVersion;
}
/**
* Generate Python package name from String `packageName`
*
* (PEP 0008) Python packages should also have short, all-lowercase names,
* although the use of underscores is discouraged.
*/
public String generatePackageName(String packageName) {
return underscore(packageName.replaceAll("[^\\w]+", ""));
}
}

View File

@ -1,6 +1,7 @@
package io.swagger.codegen.languages; package io.swagger.codegen.languages;
import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenOperation; import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenType; import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen; import io.swagger.codegen.DefaultCodegen;
@ -15,6 +16,8 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.commons.lang.StringUtils;
public class RetrofitClientCodegen extends DefaultCodegen implements CodegenConfig { public class RetrofitClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String invokerPackage = "io.swagger.client"; protected String invokerPackage = "io.swagger.client";
protected String groupId = "io.swagger"; protected String groupId = "io.swagger";
@ -42,10 +45,10 @@ public class RetrofitClientCodegen extends DefaultCodegen implements CodegenConf
"native", "super", "while") "native", "super", "while")
); );
additionalProperties.put("invokerPackage", invokerPackage); additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
additionalProperties.put("groupId", groupId); additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
additionalProperties.put("artifactId", artifactId); additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
additionalProperties.put("artifactVersion", artifactVersion); additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("service.mustache", supportingFiles.add(new SupportingFile("service.mustache",
@ -171,6 +174,11 @@ public class RetrofitClientCodegen extends DefaultCodegen implements CodegenConf
@Override @Override
public String toOperationId(String operationId) { public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
// method name cannot use reserved keyword, e.g. return // method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) { if (reservedWords.contains(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");

View File

@ -1,5 +1,6 @@
package io.swagger.codegen.languages; package io.swagger.codegen.languages;
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;
import io.swagger.codegen.DefaultCodegen; import io.swagger.codegen.DefaultCodegen;
@ -12,17 +13,19 @@ import java.io.File;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import org.apache.commons.lang.StringUtils;
public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig { public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String gemName = "swagger_client"; protected String gemName = null;
protected String moduleName = null; protected String moduleName = null;
protected String gemVersion = "1.0.0";
protected String libFolder = "lib"; protected String libFolder = "lib";
public RubyClientCodegen() { public RubyClientCodegen() {
super(); super();
moduleName = generateModuleName(); modelPackage = "models";
modelPackage = gemName + "/models"; apiPackage = "api";
apiPackage = gemName + "/api"; outputFolder = "generated-code" + File.separator + "ruby";
outputFolder = "generated-code" + File.separatorChar + "ruby";
modelTemplateFiles.put("model.mustache", ".rb"); modelTemplateFiles.put("model.mustache", ".rb");
apiTemplateFiles.put("api.mustache", ".rb"); apiTemplateFiles.put("api.mustache", ".rb");
templateDir = "ruby"; templateDir = "ruby";
@ -39,33 +42,82 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
"if", "not", "return", "undef", "yield") "if", "not", "return", "undef", "yield")
); );
additionalProperties.put("gemName", gemName);
additionalProperties.put("moduleName", moduleName);
languageSpecificPrimitives.add("int"); languageSpecificPrimitives.add("int");
languageSpecificPrimitives.add("array"); languageSpecificPrimitives.add("array");
languageSpecificPrimitives.add("map"); languageSpecificPrimitives.add("map");
languageSpecificPrimitives.add("string"); languageSpecificPrimitives.add("string");
languageSpecificPrimitives.add("DateTime"); languageSpecificPrimitives.add("DateTime");
typeMapping.put("long", "int"); typeMapping.put("string", "String");
typeMapping.put("integer", "int"); typeMapping.put("char", "String");
typeMapping.put("Array", "array"); typeMapping.put("int", "Integer");
typeMapping.put("String", "string"); typeMapping.put("integer", "Integer");
typeMapping.put("List", "array"); typeMapping.put("long", "Integer");
typeMapping.put("map", "map"); typeMapping.put("short", "Integer");
typeMapping.put("float", "Float");
typeMapping.put("double", "Float");
typeMapping.put("number", "Float");
typeMapping.put("date", "Date");
typeMapping.put("DateTime", "DateTime");
typeMapping.put("boolean", "BOOLEAN");
typeMapping.put("array", "Array");
typeMapping.put("List", "Array");
typeMapping.put("map", "Hash");
typeMapping.put("object", "Object");
typeMapping.put("file", "File");
// remove modelPackage and apiPackage added by default
cliOptions.clear();
cliOptions.add(new CliOption("gemName", "gem name (convention: underscore_case), default: swagger_client"));
cliOptions.add(new CliOption("moduleName", "top module name (convention: CamelCase, usually corresponding to gem name), default: SwaggerClient"));
cliOptions.add(new CliOption("gemVersion", "gem version, default: 1.0.0"));
}
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey("gemName")) {
setGemName((String) additionalProperties.get("gemName"));
}
if (additionalProperties.containsKey("moduleName")) {
setModuleName((String) additionalProperties.get("moduleName"));
}
if (gemName == null && moduleName == null) {
setGemName("swagger_client");
setModuleName(generateModuleName(gemName));
} else if (gemName == null) {
setGemName(generateGemName(moduleName));
} else if (moduleName == null) {
setModuleName(generateModuleName(gemName));
}
additionalProperties.put("gemName", gemName);
additionalProperties.put("moduleName", moduleName);
if (additionalProperties.containsKey("gemVersion")) {
setGemVersion((String) additionalProperties.get("gemVersion"));
} else {
// not set, pass the default value to template
additionalProperties.put("gemVersion", gemVersion);
}
// use constant model/api package (folder path)
setModelPackage("models");
setApiPackage("api");
String baseFolder = "lib" + File.separatorChar + gemName;
String swaggerFolder = baseFolder + File.separatorChar + "swagger";
String modelFolder = baseFolder + File.separatorChar + "models";
supportingFiles.add(new SupportingFile("swagger_client.gemspec.mustache", "", gemName + ".gemspec")); supportingFiles.add(new SupportingFile("swagger_client.gemspec.mustache", "", gemName + ".gemspec"));
supportingFiles.add(new SupportingFile("swagger_client.mustache", "lib", gemName + ".rb")); supportingFiles.add(new SupportingFile("swagger_client.mustache", libFolder, gemName + ".rb"));
supportingFiles.add(new SupportingFile("monkey.mustache", baseFolder, "monkey.rb")); String baseFolder = libFolder + File.separator + gemName;
supportingFiles.add(new SupportingFile("swagger.mustache", baseFolder, "swagger.rb")); supportingFiles.add(new SupportingFile("swagger.mustache", baseFolder, "swagger.rb"));
supportingFiles.add(new SupportingFile("swagger" + File.separatorChar + "request.mustache", swaggerFolder, "request.rb")); String swaggerFolder = baseFolder + File.separator + "swagger";
supportingFiles.add(new SupportingFile("swagger" + File.separatorChar + "response.mustache", swaggerFolder, "response.rb")); supportingFiles.add(new SupportingFile("swagger" + File.separator + "request.mustache", swaggerFolder, "request.rb"));
supportingFiles.add(new SupportingFile("swagger" + File.separatorChar + "version.mustache", swaggerFolder, "version.rb")); supportingFiles.add(new SupportingFile("swagger" + File.separator + "response.mustache", swaggerFolder, "response.rb"));
supportingFiles.add(new SupportingFile("swagger" + File.separatorChar + "configuration.mustache", swaggerFolder, "configuration.rb")); supportingFiles.add(new SupportingFile("swagger" + File.separator + "api_error.mustache", swaggerFolder, "api_error.rb"));
supportingFiles.add(new SupportingFile("swagger" + File.separator + "version.mustache", swaggerFolder, "version.rb"));
supportingFiles.add(new SupportingFile("swagger" + File.separator + "configuration.mustache", swaggerFolder, "configuration.rb"));
String modelFolder = baseFolder + File.separator + modelPackage.replace("/", File.separator);
supportingFiles.add(new SupportingFile("base_object.mustache", modelFolder, "base_object.rb")); supportingFiles.add(new SupportingFile("base_object.mustache", modelFolder, "base_object.rb"));
} }
@ -84,10 +136,17 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
/** /**
* Generate Ruby module name from the gem name, e.g. use "SwaggerClient" for "swagger_client". * Generate Ruby module name from the gem name, e.g. use "SwaggerClient" for "swagger_client".
*/ */
public String generateModuleName() { public String generateModuleName(String gemName) {
return camelize(gemName.replaceAll("[^\\w]+", "_")); return camelize(gemName.replaceAll("[^\\w]+", "_"));
} }
/**
* Generate Ruby gem name from the module name, e.g. use "swagger_client" for "SwaggerClient".
*/
public String generateGemName(String moduleName) {
return underscore(moduleName.replaceAll("[^\\w]+", ""));
}
@Override @Override
public String escapeReservedWord(String name) { public String escapeReservedWord(String name) {
return "_" + name; return "_" + name;
@ -95,11 +154,11 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String apiFileFolder() { public String apiFileFolder() {
return outputFolder + File.separatorChar + "lib" + File.separatorChar + gemName + File.separatorChar + "api"; return outputFolder + File.separator + libFolder + File.separator + gemName + File.separator + apiPackage.replace("/", File.separator);
} }
public String modelFileFolder() { public String modelFileFolder() {
return outputFolder + File.separatorChar + "lib" + File.separatorChar + gemName + File.separatorChar + "models"; return outputFolder + File.separator + libFolder + File.separator + gemName + File.separator + modelPackage.replace("/", File.separator);
} }
@Override @Override
@ -107,11 +166,11 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
if (p instanceof ArrayProperty) { if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p; ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems(); Property inner = ap.getItems();
return getSwaggerType(p) + "[" + getTypeDeclaration(inner) + "]"; return getSwaggerType(p) + "<" + getTypeDeclaration(inner) + ">";
} else if (p instanceof MapProperty) { } else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p; MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties(); Property inner = mp.getAdditionalProperties();
return getSwaggerType(p) + "[string," + getTypeDeclaration(inner) + "]"; return getSwaggerType(p) + "<String, " + getTypeDeclaration(inner) + ">";
} }
return super.getTypeDeclaration(p); return super.getTypeDeclaration(p);
} }
@ -140,8 +199,8 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toVarName(String name) { public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at // sanitize name
name = name.replaceAll("-", "_"); name = sanitizeName(name);
// if it's all uppper case, convert to lower case // if it's all uppper case, convert to lower case
if (name.matches("^[A-Z_]*$")) { if (name.matches("^[A-Z_]*$")) {
@ -210,22 +269,38 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toOperationId(String operationId) { public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
// method name cannot use reserved keyword, e.g. return // method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) { if (reservedWords.contains(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
} }
return underscore(operationId); return underscore(sanitizeName(operationId));
} }
@Override @Override
public String toModelImport(String name) { public String toModelImport(String name) {
return modelPackage() + "/" + toModelFilename(name); return gemName + "/" + modelPackage() + "/" + toModelFilename(name);
} }
@Override @Override
public String toApiImport(String name) { public String toApiImport(String name) {
return apiPackage() + "/" + toApiFilename(name); return gemName + "/" + apiPackage() + "/" + toApiFilename(name);
} }
public void setGemName(String gemName) {
this.gemName = gemName;
}
public void setModuleName(String moduleName) {
this.moduleName = moduleName;
}
public void setGemVersion(String gemVersion) {
this.gemVersion = gemVersion;
}
} }

View File

@ -1,6 +1,7 @@
package io.swagger.codegen.languages; package io.swagger.codegen.languages;
import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenConfig;
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;
@ -20,6 +21,11 @@ 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.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig { public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String invokerPackage = "io.swagger.client"; protected String invokerPackage = "io.swagger.client";
@ -49,10 +55,10 @@ public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig
"trait", "try", "true", "type", "val", "var", "while", "with", "yield") "trait", "try", "true", "type", "val", "var", "while", "with", "yield")
); );
additionalProperties.put("invokerPackage", invokerPackage); additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
additionalProperties.put("groupId", groupId); additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
additionalProperties.put("artifactId", artifactId); additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
additionalProperties.put("artifactVersion", artifactVersion); additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
additionalProperties.put("asyncHttpClient", asyncHttpClient); additionalProperties.put("asyncHttpClient", asyncHttpClient);
additionalProperties.put("authScheme", authScheme); additionalProperties.put("authScheme", authScheme);
additionalProperties.put("authPreemptive", authPreemptive); additionalProperties.put("authPreemptive", authPreemptive);
@ -206,6 +212,11 @@ public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig
@Override @Override
public String toOperationId(String operationId) { public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
// method name cannot use reserved keyword, e.g. return // method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) { if (reservedWords.contains(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
@ -214,4 +225,17 @@ public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig
return camelize(operationId, true); return camelize(operationId, true);
} }
@Override
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
// remove model imports to avoid warnings for importing class in the same package in Scala
List<Map<String, String>> imports = (List<Map<String, String>>) objs.get("imports");
final String prefix = modelPackage() + ".";
Iterator<Map<String, String>> iterator = imports.iterator();
while (iterator.hasNext()) {
String _import = iterator.next().get("import");
if (_import.startsWith(prefix)) iterator.remove();
}
return objs;
}
} }

View File

@ -1,6 +1,7 @@
package io.swagger.codegen.languages; package io.swagger.codegen.languages;
import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenOperation; import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenType; import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen; import io.swagger.codegen.DefaultCodegen;
@ -73,10 +74,10 @@ public class ScalatraServerCodegen extends DefaultCodegen implements CodegenConf
additionalProperties.put("infoEmail", "apiteam@swagger.io"); additionalProperties.put("infoEmail", "apiteam@swagger.io");
additionalProperties.put("licenseInfo", "All rights reserved"); additionalProperties.put("licenseInfo", "All rights reserved");
additionalProperties.put("licenseUrl", "http://apache.org/licenses/LICENSE-2.0.html"); additionalProperties.put("licenseUrl", "http://apache.org/licenses/LICENSE-2.0.html");
additionalProperties.put("invokerPackage", invokerPackage); additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
additionalProperties.put("groupId", groupId); additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
additionalProperties.put("artifactId", artifactId); additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
additionalProperties.put("artifactVersion", artifactVersion); additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("build.sbt", "", "build.sbt")); supportingFiles.add(new SupportingFile("build.sbt", "", "build.sbt"));

View File

@ -0,0 +1,195 @@
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 java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
public class SilexServerCodegen extends DefaultCodegen implements CodegenConfig {
protected String invokerPackage;
protected String groupId = "io.swagger";
protected String artifactId = "swagger-server";
protected String artifactVersion = "1.0.0";
public SilexServerCodegen() {
super();
invokerPackage = camelize("SwaggerServer");
String packagePath = "SwaggerServer";
modelPackage = packagePath + "/lib/models";
apiPackage = packagePath + "/lib";
outputFolder = "generated-code/silex";
// no model, api files
modelTemplateFiles.clear();
apiTemplateFiles.clear();
templateDir = "silex";
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", "boolean");
typeMapping.put("date", "DateTime");
typeMapping.put("datetime", "DateTime");
typeMapping.put("file", "string");
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 "silex-PHP";
}
public String getHelp() {
return "Generates a Silex 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 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);
}
@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);
}
public String toDefaultValue(Property p) {
return "null";
}
@Override
public String toVarName(String name) {
// 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

@ -0,0 +1,217 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig;
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 java.io.File;
import java.util.Arrays;
import java.util.HashSet;
import org.apache.commons.lang.StringUtils;
public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfig {
protected String gemName = null;
protected String moduleName = null;
protected String gemVersion = "1.0.0";
protected String libFolder = "lib";
public SinatraServerCodegen() {
super();
apiPackage = "lib";
outputFolder = "generated-code" + File.separator + "sinatra";
// no model
modelTemplateFiles.clear();
apiTemplateFiles.put("api.mustache", ".rb");
templateDir = "sinatra";
typeMapping.clear();
languageSpecificPrimitives.clear();
reservedWords = new HashSet<String>(
Arrays.asList(
"__FILE__", "and", "def", "end", "in", "or", "self", "unless", "__LINE__",
"begin", "defined?", "ensure", "module", "redo", "super", "until", "BEGIN",
"break", "do", "false", "next", "rescue", "then", "when", "END", "case",
"else", "for", "nil", "retry", "true", "while", "alias", "class", "elsif",
"if", "not", "return", "undef", "yield")
);
languageSpecificPrimitives.add("int");
languageSpecificPrimitives.add("array");
languageSpecificPrimitives.add("map");
languageSpecificPrimitives.add("string");
languageSpecificPrimitives.add("DateTime");
typeMapping.put("long", "int");
typeMapping.put("integer", "int");
typeMapping.put("Array", "array");
typeMapping.put("String", "string");
typeMapping.put("List", "array");
typeMapping.put("map", "map");
// remove modelPackage and apiPackage added by default
cliOptions.clear();
}
@Override
public void processOpts() {
super.processOpts();
// use constant model/api package (folder path)
//setModelPackage("models");
setApiPackage("api");
supportingFiles.add(new SupportingFile("my_app.mustache", "", "my_app.rb"));
supportingFiles.add(new SupportingFile("Swaggering.rb", libFolder, "swaggering.rb"));
supportingFiles.add(new SupportingFile("config.ru", "", "config.ru"));
supportingFiles.add(new SupportingFile("Gemfile", "", "Gemfile"));
supportingFiles.add(new SupportingFile("README.md", "", "README.md"));
}
public CodegenType getTag() {
return CodegenType.CLIENT;
}
public String getName() {
return "sinatra";
}
public String getHelp() {
return "Generates a Sinatra server library.";
}
@Override
public String escapeReservedWord(String name) {
return "_" + name;
}
@Override
public String apiFileFolder() {
return outputFolder + File.separator + apiPackage.replace("/", File.separator);
}
@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);
}
@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 {
type = swaggerType;
}
if (type == null) {
return null;
}
return type;
}
public String toDefaultValue(Property p) {
return "null";
}
@Override
public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_");
// if it's all uppper case, convert to lower case
if (name.matches("^[A-Z_]*$")) {
name = name.toLowerCase();
}
// camelize (lower first character) the variable name
// petId => pet_id
name = underscore(name);
// 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) {
// 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) {
// 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");
}
// underscore the model file name
// PhoneNumber.rb => phone_number.rb
return underscore(name);
}
@Override
public String toApiFilename(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_");
// e.g. PhoneNumberApi.rb => phone_number_api.rb
return underscore(name) + "_api";
}
@Override
public String toApiName(String name) {
if (name.length() == 0) {
return "DefaultApi";
}
// e.g. phone_number_api => PhoneNumberApi
return camelize(name) + "Api";
}
@Override
public String toOperationId(String operationId) {
// 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 underscore(operationId);
}
}

View File

@ -1,9 +1,6 @@
package io.swagger.codegen.languages; package io.swagger.codegen.languages;
import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.*;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.SupportingFile;
import io.swagger.models.Operation; import io.swagger.models.Operation;
import io.swagger.models.properties.ArrayProperty; import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty; import io.swagger.models.properties.MapProperty;
@ -27,7 +24,7 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen
protected String configPackage = ""; protected String configPackage = "";
public SpringMVCServerCodegen() { public SpringMVCServerCodegen() {
super.processOpts(); super();
outputFolder = "generated-code/javaSpringMVC"; outputFolder = "generated-code/javaSpringMVC";
modelTemplateFiles.put("model.mustache", ".java"); modelTemplateFiles.put("model.mustache", ".java");
apiTemplateFiles.put("api.mustache", ".java"); apiTemplateFiles.put("api.mustache", ".java");
@ -37,12 +34,12 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen
configPackage = "io.swagger.configuration"; configPackage = "io.swagger.configuration";
additionalProperties.put("invokerPackage", invokerPackage); additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
additionalProperties.put("groupId", groupId); additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
additionalProperties.put("artifactId", artifactId); additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
additionalProperties.put("artifactVersion", artifactVersion); additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
additionalProperties.put("title", title); additionalProperties.put("title", title);
additionalProperties.put("apiPackage", apiPackage); additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage);
additionalProperties.put("configPackage", configPackage); additionalProperties.put("configPackage", configPackage);
languageSpecificPrimitives = new HashSet<String>( languageSpecificPrimitives = new HashSet<String>(
@ -55,6 +52,9 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen
"Long", "Long",
"Float") "Float")
); );
cliOptions.add(new CliOption("configPackage", "configuration package for generated code"));
} }
public CodegenType getTag() { public CodegenType getTag() {
@ -73,6 +73,10 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen
public void processOpts() { public void processOpts() {
super.processOpts(); super.processOpts();
if (additionalProperties.containsKey("configPackage")) {
this.setConfigPackage((String) additionalProperties.get("configPackage"));
}
supportingFiles.clear(); supportingFiles.clear();
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
@ -98,21 +102,6 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen
} }
@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 getTypeDeclaration(inner);
}
return super.getTypeDeclaration(p);
}
@Override @Override
public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations) { public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations) {
String basePath = resourcePath; String basePath = resourcePath;
@ -146,27 +135,38 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen
if (operations != null) { if (operations != null) {
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation"); List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
for (CodegenOperation operation : ops) { for (CodegenOperation operation : ops) {
List<CodegenResponse> responses = operation.responses;
if (responses != null) {
for (CodegenResponse resp : responses) {
if ("0".equals(resp.code)) {
resp.code = "200";
}
}
}
System.out.println(operation.operationId);
io.swagger.util.Json.prettyPrint(operation);
if (operation.returnType == null) { if (operation.returnType == null) {
operation.returnType = "Void"; operation.returnType = "Void";
} else if (operation.returnType.startsWith("List")) { } else if (operation.returnType.startsWith("List")) {
String rt = operation.returnType; String rt = operation.returnType;
int end = rt.lastIndexOf(">"); int end = rt.lastIndexOf(">");
if (end > 0) { if (end > 0) {
operation.returnType = rt.substring("List<".length(), end); operation.returnType = rt.substring("List<".length(), end).trim();
operation.returnContainer = "List"; operation.returnContainer = "List";
} }
} else if (operation.returnType.startsWith("Map")) { } else if (operation.returnType.startsWith("Map")) {
String rt = operation.returnType; String rt = operation.returnType;
int end = rt.lastIndexOf(">"); int end = rt.lastIndexOf(">");
if (end > 0) { if (end > 0) {
operation.returnType = rt.substring("Map<".length(), end); operation.returnType = rt.substring("Map<".length(), end).split(",")[1].trim();
operation.returnContainer = "Map"; operation.returnContainer = "Map";
} }
} else if (operation.returnType.startsWith("Set")) { } else if (operation.returnType.startsWith("Set")) {
String rt = operation.returnType; String rt = operation.returnType;
int end = rt.lastIndexOf(">"); int end = rt.lastIndexOf(">");
if (end > 0) { if (end > 0) {
operation.returnType = rt.substring("Set<".length(), end); operation.returnType = rt.substring("Set<".length(), end).trim();
operation.returnContainer = "Set"; operation.returnContainer = "Set";
} }
} }
@ -174,5 +174,18 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen
} }
return objs; return objs;
} }
@Override
public String toApiName(String name) {
if (name.length() == 0) {
return "DefaultApi";
}
name = sanitizeName(name);
return camelize(name) + "Api";
}
public void setConfigPackage(String configPackage) {
this.configPackage = configPackage;
}
} }

View File

@ -1,6 +1,7 @@
package io.swagger.codegen.languages; package io.swagger.codegen.languages;
import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenConfig;
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;
@ -21,10 +22,10 @@ public class StaticDocCodegen extends DefaultCodegen implements CodegenConfig {
apiTemplateFiles.put("operation.mustache", ".html"); apiTemplateFiles.put("operation.mustache", ".html");
templateDir = "swagger-static"; templateDir = "swagger-static";
additionalProperties.put("invokerPackage", invokerPackage); additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
additionalProperties.put("groupId", groupId); additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
additionalProperties.put("artifactId", artifactId); additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
additionalProperties.put("artifactVersion", artifactVersion); additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
supportingFiles.add(new SupportingFile("package.mustache", "", "package.json")); supportingFiles.add(new SupportingFile("package.mustache", "", "package.json"));
supportingFiles.add(new SupportingFile("main.mustache", "", "main.js")); supportingFiles.add(new SupportingFile("main.mustache", "", "main.js"));

View File

@ -1,6 +1,7 @@
package io.swagger.codegen.languages; package io.swagger.codegen.languages;
import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenOperation; import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenType; import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen; import io.swagger.codegen.DefaultCodegen;
@ -37,10 +38,10 @@ public class StaticHtmlGenerator extends DefaultCodegen implements CodegenConfig
additionalProperties.put("infoEmail", "hello@helloreverb.com"); additionalProperties.put("infoEmail", "hello@helloreverb.com");
additionalProperties.put("licenseInfo", "All rights reserved"); additionalProperties.put("licenseInfo", "All rights reserved");
additionalProperties.put("licenseUrl", "http://apache.org/licenses/LICENSE-2.0.html"); additionalProperties.put("licenseUrl", "http://apache.org/licenses/LICENSE-2.0.html");
additionalProperties.put("invokerPackage", invokerPackage); additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
additionalProperties.put("groupId", groupId); additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
additionalProperties.put("artifactId", artifactId); additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
additionalProperties.put("artifactVersion", artifactVersion); additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
supportingFiles.add(new SupportingFile("index.mustache", "", "index.html")); supportingFiles.add(new SupportingFile("index.mustache", "", "index.html"));
reservedWords = new HashSet<String>(); reservedWords = new HashSet<String>();

View File

@ -0,0 +1,298 @@
package io.swagger.codegen.languages;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
import io.swagger.codegen.*;
import io.swagger.models.Model;
import io.swagger.models.Operation;
import io.swagger.models.parameters.HeaderParameter;
import io.swagger.models.parameters.Parameter;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import javax.annotation.Nullable;
import java.util.*;
import java.io.File;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
private static final Pattern PATH_PARAM_PATTERN = Pattern.compile("\\{[a-zA-Z_]+\\}");
protected static final String LIBRARY_PROMISE_KIT = "PromiseKit";
protected static final String[] RESPONSE_LIBRARIES = { LIBRARY_PROMISE_KIT };
protected String projectName = "SwaggerClient";
protected boolean unwrapRequired = false;
protected String[] responseAs = new String[0];
protected String sourceFolder = "Classes" + File.separator + "Swaggers";
public CodegenType getTag() {
return CodegenType.CLIENT;
}
public String getName() {
return "swift";
}
public String getHelp() {
return "Generates a swift client library.";
}
public SwiftCodegen() {
super();
outputFolder = "generated-code" + File.separator + "swift";
modelTemplateFiles.put("model.mustache", ".swift");
apiTemplateFiles.put("api.mustache", ".swift");
templateDir = "swift";
apiPackage = File.separator + "APIs";
modelPackage = File.separator + "Models";
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"Int",
"Float",
"Double",
"Bool",
"Void",
"String",
"Character")
);
defaultIncludes = new HashSet<String>(
Arrays.asList(
"NSDate",
"Array",
"Dictionary",
"Set",
"Any",
"Empty",
"AnyObject")
);
reservedWords = new HashSet<String>(
Arrays.asList(
"class", "break", "as", "associativity", "deinit", "case", "dynamicType", "convenience", "enum", "continue",
"false", "dynamic", "extension", "default", "is", "didSet", "func", "do", "nil", "final", "import", "else",
"self", "get", "init", "fallthrough", "Self", "infix", "internal", "for", "super", "inout", "let", "if",
"true", "lazy", "operator", "in", "COLUMN", "left", "private", "return", "FILE", "mutating", "protocol",
"switch", "FUNCTION", "none", "public", "where", "LINE", "nonmutating", "static", "while", "optional",
"struct", "override", "subscript", "postfix", "typealias", "precedence", "var", "prefix", "Protocol",
"required", "right", "set", "Type", "unowned", "weak")
);
typeMapping = new HashMap<String, String>();
typeMapping.put("array", "Array");
typeMapping.put("List", "Array");
typeMapping.put("map", "Dictionary");
typeMapping.put("date", "NSDate");
typeMapping.put("Date", "NSDate");
typeMapping.put("DateTime", "NSDate");
typeMapping.put("boolean", "Bool");
typeMapping.put("string", "String");
typeMapping.put("char", "Character");
typeMapping.put("short", "Int");
typeMapping.put("int", "Int");
typeMapping.put("long", "Int");
typeMapping.put("integer", "Int");
typeMapping.put("Integer", "Int");
typeMapping.put("float", "Float");
typeMapping.put("number", "Double");
typeMapping.put("double", "Double");
typeMapping.put("object", "String");
typeMapping.put("file", "NSURL");
importMapping = new HashMap<String, String>();
cliOptions.add(new CliOption("projectName", "Project name in Xcode"));
cliOptions.add(new CliOption("responseAs", "Optionally use libraries to manage response. Currently " +
StringUtils.join(RESPONSE_LIBRARIES, ", ") + " are available."));
cliOptions.add(new CliOption("unwrapRequired", "Treat 'required' properties in response as non-optional " +
"(which would crash the app if api returns null as opposed to required option specified in json schema"));
cliOptions.add(new CliOption("podSource", "Source information used for Podspec"));
cliOptions.add(new CliOption("podVersion", "Version used for Podspec"));
cliOptions.add(new CliOption("podAuthors", "Authors used for Podspec"));
cliOptions.add(new CliOption("podSocialMediaURL", "Social Media URL used for Podspec"));
cliOptions.add(new CliOption("podDocsetURL", "Docset URL used for Podspec"));
cliOptions.add(new CliOption("podLicense", "License used for Podspec"));
cliOptions.add(new CliOption("podHomepage", "Homepage used for Podspec"));
cliOptions.add(new CliOption("podSummary", "Summary used for Podspec"));
cliOptions.add(new CliOption("podDescription", "Description used for Podspec"));
cliOptions.add(new CliOption("podScreenshots", "Screenshots used for Podspec"));
cliOptions.add(new CliOption("podDocumentationURL", "Documentation URL used for Podspec"));
}
@Override
public void processOpts() {
super.processOpts();
// Setup project name
if (additionalProperties.containsKey("projectName")) {
projectName = (String) additionalProperties.get("projectName");
} else {
additionalProperties.put("projectName", projectName);
}
sourceFolder = projectName + File.separator + sourceFolder;
// Setup unwrapRequired option, which makes all the properties with "required" non-optional
if (additionalProperties.containsKey("unwrapRequired")) {
unwrapRequired = Boolean.parseBoolean(String.valueOf(additionalProperties.get("unwrapRequired")));
}
additionalProperties.put("unwrapRequired", unwrapRequired);
// Setup unwrapRequired option, which makes all the properties with "required" non-optional
if (additionalProperties.containsKey("responseAs")) {
Object responseAsObject = additionalProperties.get("responseAs");
if (responseAsObject instanceof String) {
responseAs = ((String)responseAsObject).split(",");
} else {
responseAs = (String[]) responseAsObject;
}
}
additionalProperties.put("responseAs", responseAs);
if (ArrayUtils.contains(responseAs, LIBRARY_PROMISE_KIT)) {
additionalProperties.put("usePromiseKit", true);
}
supportingFiles.add(new SupportingFile("Podspec.mustache", "", projectName + ".podspec"));
supportingFiles.add(new SupportingFile("Cartfile.mustache", "", "Cartfile"));
supportingFiles.add(new SupportingFile("APIHelper.mustache", sourceFolder, "APIHelper.swift"));
supportingFiles.add(new SupportingFile("AlamofireImplementations.mustache", sourceFolder,
"AlamofireImplementations.swift"));
supportingFiles.add(new SupportingFile("Extensions.mustache", sourceFolder, "Extensions.swift"));
supportingFiles.add(new SupportingFile("Models.mustache", sourceFolder, "Models.swift"));
supportingFiles.add(new SupportingFile("APIs.mustache", sourceFolder, "APIs.swift"));
}
@Override
public String escapeReservedWord(String name) {
return "Swagger" + name; // add an underscore to the name
}
@Override
public String modelFileFolder() {
return outputFolder + File.separator + sourceFolder + modelPackage().replace('.', File.separatorChar);
}
@Override
public String apiFileFolder() {
return outputFolder + File.separator + sourceFolder + apiPackage().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 "[String:" + getTypeDeclaration(inner) + "]";
}
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 toModelName(type);
} else
type = swaggerType;
return toModelName(type);
}
@Override
public String toDefaultValue(Property p) {
// nil
return null;
}
@Override
public String toInstantiationType(Property p) {
if (p instanceof MapProperty) {
MapProperty ap = (MapProperty) p;
String inner = getSwaggerType(ap.getAdditionalProperties());
return "[String:" + inner + "]";
} else if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
String inner = getSwaggerType(ap.getItems());
return "[" + inner + "]";
}
return null;
}
@Override
public CodegenProperty fromProperty(String name, Property p) {
CodegenProperty codegenProperty = super.fromProperty(name, p);
if (codegenProperty.isEnum) {
List<Map<String, String>> swiftEnums = new ArrayList<Map<String, String>>();
List<String> values = (List<String>) codegenProperty.allowableValues.get("values");
for (String value : values) {
Map<String, String> map = new HashMap<String, String>();
map.put("enum", StringUtils.capitalize(value));
map.put("raw", value);
swiftEnums.add(map);
}
codegenProperty.allowableValues.put("values", swiftEnums);
codegenProperty.datatypeWithEnum =
StringUtils.left(codegenProperty.datatypeWithEnum, codegenProperty.datatypeWithEnum.length() - "Enum".length());
if (reservedWords.contains(codegenProperty.datatypeWithEnum)) {
codegenProperty.datatypeWithEnum = escapeReservedWord(codegenProperty.datatypeWithEnum);
}
}
return codegenProperty;
}
@Override
public String toApiName(String name) {
if(name.length() == 0)
return "DefaultAPI";
return initialCaps(name) + "API";
}
@Override
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, Map<String, Model> definitions) {
path = normalizePath(path);
List<Parameter> parameters = operation.getParameters();
parameters = Lists.newArrayList(Iterators.filter(parameters.iterator(), new Predicate<Parameter>() {
@Override
public boolean apply(@Nullable Parameter parameter) {
return !(parameter instanceof HeaderParameter);
}
}));
operation.setParameters(parameters);
return super.fromOperation(path, httpMethod, operation, definitions);
}
private static String normalizePath(String path) {
StringBuilder builder = new StringBuilder();
int cursor = 0;
Matcher matcher = PATH_PARAM_PATTERN.matcher(path);
boolean found = matcher.find();
while (found) {
String stringBeforeMatch = path.substring(cursor, matcher.start());
builder.append(stringBeforeMatch);
String group = matcher.group().substring(1, matcher.group().length() - 1);
group = camelize(group, true);
builder
.append("{")
.append(group)
.append("}");
cursor = matcher.end();
found = matcher.find();
}
String stringAfterMatch = path.substring(cursor);
builder.append(stringAfterMatch);
return builder.toString();
}
}

View File

@ -1,265 +0,0 @@
package io.swagger.codegen.languages;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
import io.swagger.codegen.CodegenConfig;
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.Model;
import io.swagger.models.Operation;
import io.swagger.models.parameters.HeaderParameter;
import io.swagger.models.parameters.Parameter;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import org.apache.commons.lang.StringUtils;
import javax.annotation.Nullable;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SwiftGenerator extends DefaultCodegen implements CodegenConfig {
private static final Pattern PATH_PARAM_PATTERN = Pattern.compile("\\{[a-zA-Z_]+\\}");
protected String sourceFolder = "Classes/Swaggers";
public SwiftGenerator() {
super();
outputFolder = "generated-code/swift";
modelTemplateFiles.put("model.mustache", ".swift");
apiTemplateFiles.put("api.mustache", ".swift");
templateDir = "swift";
apiPackage = "/APIs";
modelPackage = "/Models";
// Inject application name
String appName = System.getProperty("appName");
if (appName == null) {
appName = "SwaggerClient";
}
additionalProperties.put("projectName", appName);
// Inject base url override
String basePathOverride = System.getProperty("basePathOverride");
if (basePathOverride != null) {
additionalProperties.put("basePathOverride", basePathOverride);
}
sourceFolder = appName + "/" + sourceFolder;
supportingFiles.add(new SupportingFile("Cartfile.mustache", "", "Cartfile"));
supportingFiles.add(new SupportingFile("APIHelper.mustache", sourceFolder, "APIHelper.swift"));
supportingFiles.add(new SupportingFile("AlamofireImplementations.mustache", sourceFolder, "AlamofireImplementations.swift"));
supportingFiles.add(new SupportingFile("Extensions.mustache", sourceFolder, "Extensions.swift"));
supportingFiles.add(new SupportingFile("Models.mustache", sourceFolder, "Models.swift"));
supportingFiles.add(new SupportingFile("APIs.mustache", sourceFolder, "APIs.swift"));
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"Int",
"Float",
"Double",
"Bool",
"Void",
"String",
"Character")
);
defaultIncludes = new HashSet<String>(
Arrays.asList(
"NSDate",
"Array",
"Dictionary",
"Set",
"Any",
"Empty",
"AnyObject")
);
reservedWords = new HashSet<String>(
Arrays.asList(
"class", "break", "as", "associativity", "deinit", "case", "dynamicType", "convenience", "enum", "continue",
"false", "dynamic", "extension", "default", "is", "didSet", "func", "do", "nil", "final", "import", "else",
"self", "get", "init", "fallthrough", "Self", "infix", "internal", "for", "super", "inout", "let", "if",
"true", "lazy", "operator", "in", "COLUMN", "left", "private", "return", "FILE", "mutating", "protocol",
"switch", "FUNCTION", "none", "public", "where", "LINE", "nonmutating", "static", "while", "optional",
"struct", "override", "subscript", "postfix", "typealias", "precedence", "var", "prefix", "Protocol",
"required", "right", "set", "Type", "unowned", "weak")
);
typeMapping = new HashMap<String, String>();
typeMapping.put("array", "Array");
typeMapping.put("List", "Array");
typeMapping.put("map", "Dictionary");
typeMapping.put("date", "NSDate");
typeMapping.put("Date", "NSDate");
typeMapping.put("DateTime", "NSDate");
typeMapping.put("boolean", "Bool");
typeMapping.put("string", "String");
typeMapping.put("char", "Character");
typeMapping.put("short", "Int");
typeMapping.put("int", "Int");
typeMapping.put("long", "Int");
typeMapping.put("integer", "Int");
typeMapping.put("Integer", "Int");
typeMapping.put("float", "Float");
typeMapping.put("number", "Double");
typeMapping.put("double", "Double");
typeMapping.put("object", "AnyObject");
typeMapping.put("file", "NSData");
importMapping = new HashMap<String, String>();
}
private static String normalizePath(String path) {
StringBuilder builder = new StringBuilder();
int cursor = 0;
Matcher matcher = PATH_PARAM_PATTERN.matcher(path);
boolean found = matcher.find();
while (found) {
String stringBeforeMatch = path.substring(cursor, matcher.start());
builder.append(stringBeforeMatch);
String group = matcher.group().substring(1, matcher.group().length() - 1);
group = camelize(group, true);
builder
.append("{")
.append(group)
.append("}");
cursor = matcher.end();
found = matcher.find();
}
String stringAfterMatch = path.substring(cursor);
builder.append(stringAfterMatch);
return builder.toString();
}
public CodegenType getTag() {
return CodegenType.CLIENT;
}
public String getName() {
return "swift";
}
public String getHelp() {
return "Generates a swift client library.";
}
@Override
public String escapeReservedWord(String name) {
return "_" + name; // add an underscore to the name
}
@Override
public String modelFileFolder() {
return outputFolder + "/" + sourceFolder + modelPackage().replace('.', File.separatorChar);
}
@Override
public String apiFileFolder() {
return outputFolder + "/" + sourceFolder + apiPackage().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 "[String:" + getTypeDeclaration(inner) + "]";
}
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 toModelName(type);
}
} else {
type = swaggerType;
}
return toModelName(type);
}
@Override
public String toDefaultValue(Property p) {
// nil
return null;
}
@Override
public String toInstantiationType(Property p) {
if (p instanceof MapProperty) {
MapProperty ap = (MapProperty) p;
String inner = getSwaggerType(ap.getAdditionalProperties());
return "[String:" + inner + "]";
} else if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
String inner = getSwaggerType(ap.getItems());
return "[" + inner + "]";
}
return null;
}
@Override
public CodegenProperty fromProperty(String name, Property p) {
CodegenProperty codegenProperty = super.fromProperty(name, p);
if (codegenProperty.isEnum) {
List<Map<String, String>> swiftEnums = new ArrayList<Map<String, String>>();
List<String> values = (List<String>) codegenProperty.allowableValues.get("values");
for (String value : values) {
Map<String, String> map = new HashMap<String, String>();
map.put("enum", StringUtils.capitalize(value));
map.put("raw", value);
swiftEnums.add(map);
}
codegenProperty.allowableValues.put("values", swiftEnums);
codegenProperty.datatypeWithEnum =
StringUtils.left(codegenProperty.datatypeWithEnum, codegenProperty.datatypeWithEnum.length() - "Enum".length());
}
return codegenProperty;
}
@Override
public String toApiName(String name) {
if (name.length() == 0) {
return "DefaultAPI";
}
return initialCaps(name) + "API";
}
@Override
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, Map<String, Model> definitions) {
path = normalizePath(path);
List<Parameter> parameters = operation.getParameters();
parameters = Lists.newArrayList(Iterators.filter(parameters.iterator(), new Predicate<Parameter>() {
@Override
public boolean apply(@Nullable Parameter parameter) {
return !(parameter instanceof HeaderParameter);
}
}));
operation.setParameters(parameters);
return super.fromOperation(path, httpMethod, operation, definitions);
}
}

View File

@ -25,6 +25,8 @@ import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.apache.commons.lang.StringUtils;
public class TizenClientCodegen extends DefaultCodegen implements CodegenConfig { public class TizenClientCodegen extends DefaultCodegen implements CodegenConfig {
protected static String PREFIX = "Sami"; protected static String PREFIX = "Sami";
protected Set<String> foundationClasses = new HashSet<String>(); protected Set<String> foundationClasses = new HashSet<String>();
@ -265,6 +267,11 @@ public class TizenClientCodegen extends DefaultCodegen implements CodegenConfig
@Override @Override
public String toOperationId(String operationId) { public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
// method name cannot use reserved keyword, e.g. return$ // method name cannot use reserved keyword, e.g. return$
if (reservedWords.contains(operationId)) { if (reservedWords.contains(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");

View File

@ -0,0 +1,28 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.SupportingFile;
import java.io.File;
public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCodegen {
@Override
public String getName() {
return "typescript-angular";
}
public String getHelp() {
return "Generates a TypeScript AngurlarJS client library.";
}
public TypeScriptAngularClientCodegen() {
super();
outputFolder = "generated-code/typescript-angular";
modelTemplateFiles.put("model.mustache", ".ts");
apiTemplateFiles.put("api.mustache", ".ts");
templateDir = "TypeScript-Angular";
apiPackage = "API.Client";
modelPackage = "API.Client";
supportingFiles.add(new SupportingFile("api.d.mustache", apiPackage().replace('.', File.separatorChar), "api.d.ts"));
}
}

View File

@ -0,0 +1,24 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.SupportingFile;
public class TypeScriptNodeClientCodegen extends AbstractTypeScriptClientCodegen {
@Override
public String getName() {
return "typescript-node";
}
@Override
public String getHelp() {
return "Generates a TypeScript nodejs client library.";
}
public TypeScriptNodeClientCodegen() {
super();
outputFolder = "generated-code/typescript-node";
templateDir = "TypeScript-node";
supportingFiles.add(new SupportingFile("api.mustache", null, "api.ts"));
}
}

View File

@ -0,0 +1,291 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text.RegularExpressions;
using System.IO;
using System.Web;
using System.Linq;
using System.Net;
using System.Text;
using Newtonsoft.Json;
using RestSharp;
using RestSharp.Extensions;
namespace {{packageName}}.Client
{
/// <summary>
/// API client is mainly responible for making the HTTP call to the API backend.
/// </summary>
public class ApiClient
{
private readonly Dictionary<String, String> _defaultHeaderMap = new Dictionary<String, String>();
/// <summary>
/// Initializes a new instance of the <see cref="ApiClient" /> class.
/// </summary>
/// <param name="basePath">The base path.</param>
public ApiClient(String basePath="{{basePath}}")
{
BasePath = basePath;
RestClient = new RestClient(BasePath);
}
/// <summary>
/// Gets or sets the base path.
/// </summary>
/// <value>The base path</value>
public string BasePath { get; set; }
/// <summary>
/// Gets or sets the RestClient.
/// </summary>
/// <value>An instance of the RestClient</value>
public RestClient RestClient { get; set; }
/// <summary>
/// Gets the default header.
/// </summary>
public Dictionary<String, String> DefaultHeader
{
get { return _defaultHeaderMap; }
}
/// <summary>
/// Makes the HTTP request (Sync).
/// </summary>
/// <param name="path">URL path.</param>
/// <param name="method">HTTP method.</param>
/// <param name="queryParams">Query parameters.</param>
/// <param name="postBody">HTTP body (POST request).</param>
/// <param name="headerParams">Header parameters.</param>
/// <param name="formParams">Form parameters.</param>
/// <param name="fileParams">File parameters.</param>
/// <param name="authSettings">Authentication settings.</param>
/// <returns>Object</returns>
public Object CallApi(String path, RestSharp.Method method, Dictionary<String, String> queryParams, String postBody,
Dictionary<String, String> headerParams, Dictionary<String, String> formParams,
Dictionary<String, FileParameter> fileParams, String[] authSettings)
{
var request = new RestRequest(path, method);
UpdateParamsForAuth(queryParams, headerParams, authSettings);
// add default header, if any
foreach(var defaultHeader in _defaultHeaderMap)
request.AddHeader(defaultHeader.Key, defaultHeader.Value);
// add header parameter, if any
foreach(var param in headerParams)
request.AddHeader(param.Key, param.Value);
// add query parameter, if any
foreach(var param in queryParams)
request.AddParameter(param.Key, param.Value, ParameterType.GetOrPost);
// add form parameter, if any
foreach(var param in formParams)
request.AddParameter(param.Key, param.Value, ParameterType.GetOrPost);
// add file parameter, if any
foreach(var param in fileParams)
request.AddFile(param.Value.Name, param.Value.Writer, param.Value.FileName, param.Value.ContentType);
if (postBody != null) // http body (model) parameter
request.AddParameter("application/json", postBody, ParameterType.RequestBody);
return (Object)RestClient.Execute(request);
}
/// <summary>
/// Add default header.
/// </summary>
/// <param name="key">Header field name.</param>
/// <param name="value">Header field value.</param>
/// <returns></returns>
public void AddDefaultHeader(string key, string value)
{
_defaultHeaderMap.Add(key, value);
}
/// <summary>
/// Escape string (url-encoded).
/// </summary>
/// <param name="str">String to be escaped.</param>
/// <returns>Escaped string.</returns>
public string EscapeString(string str)
{
return RestSharp.Contrib.HttpUtility.UrlEncode(str);
}
/// <summary>
/// Create FileParameter based on Stream.
/// </summary>
/// <param name="name">Parameter name.</param>
/// <param name="stream">Input stream.</param>
/// <returns>FileParameter.</returns>
public FileParameter ParameterToFile(string name, Stream stream)
{
if (stream is FileStream)
return FileParameter.Create(name, stream.ReadAsBytes(), Path.GetFileName(((FileStream)stream).Name));
else
return FileParameter.Create(name, stream.ReadAsBytes(), "no_file_name_provided");
}
/// <summary>
/// If parameter is DateTime, output in ISO8601 format.
/// If parameter is a list of string, join the list with ",".
/// Otherwise just return the string.
/// </summary>
/// <param name="obj">The parameter (header, path, query, form).</param>
/// <returns>Formatted string.</returns>
public string ParameterToString(object obj)
{
if (obj is DateTime)
return ((DateTime)obj).ToString ("u");
else if (obj is List<string>)
return String.Join(",", (obj as List<string>).ToArray());
else
return Convert.ToString (obj);
}
/// <summary>
/// Deserialize the JSON string into a proper object.
/// </summary>
/// <param name="content">HTTP body (e.g. string, JSON).</param>
/// <param name="type">Object type.</param>
/// <returns>Object representation of the JSON string.</returns>
public object Deserialize(string content, Type type, IList<Parameter> headers=null)
{
if (type == typeof(Object)) // return an object
{
return content;
}
if (type == typeof(Stream))
{
var filePath = String.IsNullOrEmpty(Configuration.TempFolderPath)
? Path.GetTempPath()
: Configuration.TempFolderPath;
var fileName = filePath + Guid.NewGuid();
if (headers != null)
{
var regex = new Regex(@"Content-Disposition:.*filename=['""]?([^'""\s]+)['""]?$");
var match = regex.Match(headers.ToString());
if (match.Success)
fileName = filePath + match.Value.Replace("\"", "").Replace("'", "");
}
File.WriteAllText(fileName, content);
return new FileStream(fileName, FileMode.Open);
}
if (type.Name.StartsWith("System.Nullable`1[[System.DateTime")) // return a datetime object
{
return DateTime.Parse(content, null, System.Globalization.DateTimeStyles.RoundtripKind);
}
if (type == typeof(String) || type.Name.StartsWith("System.Nullable")) // return primitive type
{
return ConvertType(content, type);
}
// at this point, it must be a model (json)
try
{
return JsonConvert.DeserializeObject(content, type);
}
catch (IOException e)
{
throw new ApiException(500, e.Message);
}
}
/// <summary>
/// Serialize an object into JSON string.
/// </summary>
/// <param name="obj">Object.</param>
/// <returns>JSON string.</returns>
public string Serialize(object obj)
{
try
{
return obj != null ? JsonConvert.SerializeObject(obj) : null;
}
catch (Exception e)
{
throw new ApiException(500, e.Message);
}
}
/// <summary>
/// Get the API key with prefix.
/// </summary>
/// <param name="apiKeyIdentifier">API key identifier (authentication scheme).</param>
/// <returns>API key with prefix.</returns>
public string GetApiKeyWithPrefix (string apiKeyIdentifier)
{
var apiKeyValue = "";
Configuration.ApiKey.TryGetValue (apiKeyIdentifier, out apiKeyValue);
var apiKeyPrefix = "";
if (Configuration.ApiKeyPrefix.TryGetValue (apiKeyIdentifier, out apiKeyPrefix))
return apiKeyPrefix + " " + apiKeyValue;
else
return apiKeyValue;
}
/// <summary>
/// Update parameters based on authentication.
/// </summary>
/// <param name="queryParams">Query parameters.</param>
/// <param name="headerParams">Header parameters.</param>
/// <param name="authSettings">Authentication settings.</param>
public void UpdateParamsForAuth(Dictionary<String, String> queryParams, Dictionary<String, String> headerParams, string[] authSettings)
{
if (authSettings == null || authSettings.Length == 0)
return;
foreach (string auth in authSettings)
{
// determine which one to use
switch(auth)
{
{{#authMethods}}
case "{{name}}":
{{#isApiKey}}{{#isKeyInHeader}}headerParams["{{keyParamName}}"] = GetApiKeyWithPrefix("{{keyParamName}}");{{/isKeyInHeader}}{{#isKeyInQuery}}queryParams["{{keyParamName}}"] = GetApiKeyWithPrefix("{{keyParamName}}");{{/isKeyInQuery}}{{/isApiKey}}{{#isBasic}}headerParams["Authorization"] = "Basic " + Base64Encode(Configuration.Username + ":" + Configuration.Password);{{/isBasic}}
{{#isOAuth}}//TODO support oauth{{/isOAuth}}
break;
{{/authMethods}}
default:
//TODO show warning about security definition not found
break;
}
}
}
/// <summary>
/// Encode string in base64 format.
/// </summary>
/// <param name="text">String to be encoded.</param>
/// <returns>Encoded string.</returns>
public static string Base64Encode(string text)
{
var textByte = System.Text.Encoding.UTF8.GetBytes(text);
return System.Convert.ToBase64String(textByte);
}
/// <summary>
/// Dynamically cast the object into target type.
/// Ref: http://stackoverflow.com/questions/4925718/c-dynamic-runtime-cast
/// </summary>
/// <param name="source">Object to be casted</param>
/// <param name="dest">Target type</param>
/// <returns>Casted object</returns>
public static Object ConvertType(Object source, Type dest) {
return Convert.ChangeType(source, dest);
}
}
}

View File

@ -0,0 +1,48 @@
using System;
namespace {{packageName}}.Client {
/// <summary>
/// API Exception
/// </summary>
public class ApiException : Exception {
/// <summary>
/// Gets or sets the error code (HTTP status code)
/// </summary>
/// <value>The error code (HTTP status code).</value>
public int ErrorCode { get; set; }
/// <summary>
/// Gets or sets the error content (body json object)
/// </summary>
/// <value>The error content (Http response body).</value>
public Object ErrorContent { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="ApiException"/> class.
/// </summary>
/// <param name="basePath">The base path.</param>
public ApiException() {}
/// <summary>
/// Initializes a new instance of the <see cref="ApiException"/> class.
/// </summary>
/// <param name="errorCode">HTTP status code.</param>
/// <param name="message">Error message.</param>
public ApiException(int errorCode, string message) : base(message) {
this.ErrorCode = errorCode;
}
/// <summary>
/// Initializes a new instance of the <see cref="ApiException"/> class.
/// </summary>
/// <param name="errorCode">HTTP status code.</param>
/// <param name="message">Error message.</param>
/// <param name="errorContent">Error content.</param>
public ApiException(int errorCode, string message, Object errorContent = null) : base(message) {
this.ErrorCode = errorCode;
this.ErrorContent = errorContent;
}
}
}

View File

@ -0,0 +1,99 @@
using System;
using System.Reflection;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace {{packageName}}.Client
{
/// <summary>
/// Represents a set of configuration settings
/// </summary>
public class Configuration
{
/// <summary>
/// Version of the package.
/// </summary>
/// <value>Version of the package.</value>
public const string Version = "{{packageVersion}}";
/// <summary>
/// Gets or sets the default API client for making HTTP calls.
/// </summary>
/// <value>The API client.</value>
public static ApiClient DefaultApiClient = new ApiClient();
/// <summary>
/// Gets or sets the username (HTTP basic authentication).
/// </summary>
/// <value>The username.</value>
public static String Username { get; set; }
/// <summary>
/// Gets or sets the password (HTTP basic authentication).
/// </summary>
/// <value>The password.</value>
public static String Password { get; set; }
/// <summary>
/// Gets or sets the API key based on the authentication name.
/// </summary>
/// <value>The API key.</value>
public static Dictionary<String, String> ApiKey = new Dictionary<String, String>();
/// <summary>
/// Gets or sets the prefix (e.g. Token) of the API key based on the authentication name.
/// </summary>
/// <value>The prefix of the API key.</value>
public static Dictionary<String, String> ApiKeyPrefix = new Dictionary<String, String>();
private static string _tempFolderPath = Path.GetTempPath();
/// <summary>
/// Gets or sets the temporary folder path to store the files downloaded from the server.
/// </summary>
/// <value>Folder path.</value>
public static String TempFolderPath
{
get { return _tempFolderPath; }
set
{
if (String.IsNullOrEmpty(value))
{
_tempFolderPath = value;
return;
}
// create the directory if it does not exist
if (!Directory.Exists(value))
Directory.CreateDirectory(value);
// check if the path contains directory separator at the end
if (value[value.Length - 1] == Path.DirectorySeparatorChar)
_tempFolderPath = value;
else
_tempFolderPath = value + Path.DirectorySeparatorChar;
}
}
/// <summary>
/// Returns a string with essential information for debugging.
/// </summary>
public static String ToDebugReport()
{
String report = "C# SDK ({{packageName}}) Debug Report:\n";
report += " OS: " + Environment.OSVersion + "\n";
report += " .NET Framework Version: " + Assembly
.GetExecutingAssembly()
.GetReferencedAssemblies()
.Where(x => x.Name == "System.Core").First().Version.ToString() + "\n";
report += " Version of the API: {{version}}\n";
report += " SDK Package Version: {{packageVersion}}\n";
return report;
}
}
}

View File

@ -0,0 +1,10 @@
# Csharp-DotNet2
This generator creates C# code targeting the .Net 2.0 framework. The resulting DLLs can be used in places where .Net 2.0 is the maximum supported version, such as in the Unity3d.
## Dependencies
- Mono compiler
- Note: NuGet is downloaded by the mono compilation script and packages are installed with it. No dependency DLLs are bundled with this generator.

View File

@ -0,0 +1,127 @@
using System;
using System.IO;
using System.Collections.Generic;
using RestSharp;
using {{packageName}}.Client;
{{#hasImport}}using {{packageName}}.Model;
{{/hasImport}}
namespace {{packageName}}.Api
{
{{#operations}}
public interface I{{classname}}
{
{{#operation}}
/// <summary>
/// {{summary}} {{notes}}
/// </summary>
{{#allParams}}/// <param name="{{paramName}}">{{description}}</param>
{{/allParams}}/// <returns>{{#returnType}}{{{returnType}}}{{/returnType}}</returns>
{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{nickname}} ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
{{/operation}}
}
/// <summary>
/// Represents a collection of functions to interact with the API endpoints
/// </summary>
public class {{classname}} : I{{classname}}
{
/// <summary>
/// Initializes a new instance of the <see cref="{{classname}}"/> class.
/// </summary>
/// <param name="apiClient"> an instance of ApiClient (optional)</param>
/// <returns></returns>
public {{classname}}(ApiClient apiClient = null)
{
if (apiClient == null) // use the default one in Configuration
this.ApiClient = Configuration.DefaultApiClient;
else
this.ApiClient = apiClient;
}
/// <summary>
/// Initializes a new instance of the <see cref="{{classname}}"/> class.
/// </summary>
/// <returns></returns>
public {{classname}}(String basePath)
{
this.ApiClient = new ApiClient(basePath);
}
/// <summary>
/// Sets the base path of the API client.
/// </summary>
/// <param name="basePath">The base path</param>
/// <value>The base path</value>
public void SetBasePath(String basePath)
{
this.ApiClient.BasePath = basePath;
}
/// <summary>
/// Gets the base path of the API client.
/// </summary>
/// <param name="basePath">The base path</param>
/// <value>The base path</value>
public String GetBasePath(String basePath)
{
return this.ApiClient.BasePath;
}
/// <summary>
/// Gets or sets the API client.
/// </summary>
/// <value>An instance of the ApiClient</param>
public ApiClient ApiClient {get; set;}
{{#operation}}
/// <summary>
/// {{summary}} {{notes}}
/// </summary>
{{#allParams}}/// <param name="{{paramName}}">{{description}}</param>
{{/allParams}}/// <returns>{{#returnType}}{{{returnType}}}{{/returnType}}</returns>
public {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{nickname}} ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}})
{
{{#allParams}}{{#required}}
// verify the required parameter '{{paramName}}' is set
if ({{paramName}} == null) throw new ApiException(400, "Missing required parameter '{{paramName}}' when calling {{nickname}}");
{{/required}}{{/allParams}}
var path = "{{path}}";
path = path.Replace("{format}", "json");
{{#pathParams}}path = path.Replace("{" + "{{baseName}}" + "}", ApiClient.ParameterToString({{{paramName}}}));
{{/pathParams}}
var queryParams = new Dictionary<String, String>();
var headerParams = new Dictionary<String, String>();
var formParams = new Dictionary<String, String>();
var fileParams = new Dictionary<String, FileParameter>();
String postBody = null;
{{#queryParams}} if ({{paramName}} != null) queryParams.Add("{{baseName}}", ApiClient.ParameterToString({{paramName}})); // query parameter
{{/queryParams}}
{{#headerParams}} if ({{paramName}} != null) headerParams.Add("{{baseName}}", ApiClient.ParameterToString({{paramName}})); // header parameter
{{/headerParams}}
{{#formParams}}if ({{paramName}} != null) {{#isFile}}fileParams.Add("{{baseName}}", ApiClient.ParameterToFile("{{baseName}}", {{paramName}}));{{/isFile}}{{^isFile}}formParams.Add("{{baseName}}", ApiClient.ParameterToString({{paramName}})); // form parameter{{/isFile}}
{{/formParams}}
{{#bodyParam}}postBody = ApiClient.Serialize({{paramName}}); // http body (model) parameter
{{/bodyParam}}
// authentication setting, if any
String[] authSettings = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} };
// make the HTTP request
IRestResponse response = (IRestResponse) ApiClient.CallApi(path, Method.{{httpMethod}}, queryParams, postBody, headerParams, formParams, fileParams, authSettings);
if (((int)response.StatusCode) >= 400)
throw new ApiException ((int)response.StatusCode, "Error calling {{nickname}}: " + response.Content, response.Content);
else if (((int)response.StatusCode) == 0)
throw new ApiException ((int)response.StatusCode, "Error calling {{nickname}}: " + response.ErrorMessage, response.ErrorMessage);
{{#returnType}}return ({{{returnType}}}) ApiClient.Deserialize(response.Content, typeof({{{returnType}}}), response.Headers);{{/returnType}}{{^returnType}}return;{{/returnType}}
}
{{/operation}}
}
{{/operations}}
}

View File

@ -0,0 +1,12 @@
wget -nc https://nuget.org/nuget.exe;
mozroots --import --sync
mono nuget.exe install vendor/packages.config -o vendor;
mkdir -p bin;
mcs -sdk:2 -r:vendor/Newtonsoft.Json.7.0.1/lib/net20/Newtonsoft.Json.dll,\
vendor/RestSharp.Net2.1.1.11/lib/net20/RestSharp.Net2.dll,\
System.Runtime.Serialization.dll \
-target:library \
-out:bin/{{packageName}}.dll \
-recurse:src/*.cs \
-doc:bin/{{packageName}}.xml \
-platform:anycpu

View File

@ -0,0 +1,53 @@
using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Newtonsoft.Json;
{{#models}}
{{#model}}
namespace {{packageName}}.Model {
/// <summary>
/// {{description}}
/// </summary>
[DataContract]
public class {{classname}}{{#parent}} : {{{parent}}}{{/parent}} {
{{#vars}}
/// <summary>
/// {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{{description}}}{{/description}}
/// </summary>{{#description}}
/// <value>{{{description}}}</value>{{/description}}
[DataMember(Name="{{baseName}}", EmitDefaultValue=false)]
[JsonProperty(PropertyName = "{{baseName}}")]
public {{{datatype}}} {{name}} { get; set; }
{{/vars}}
/// <summary>
/// Get the string presentation of the object
/// </summary>
/// <returns>String presentation of the object</returns>
public override string ToString() {
var sb = new StringBuilder();
sb.Append("class {{classname}} {\n");
{{#vars}}
sb.Append(" {{name}}: ").Append({{name}}).Append("\n");
{{/vars}}
sb.Append("}\n");
return sb.ToString();
}
/// <summary>
/// Get the JSON string presentation of the object
/// </summary>
/// <returns>JSON string presentation of the object</returns>
public {{#parent}} new {{/parent}}string ToJson() {
return JsonConvert.SerializeObject(this, Formatting.Indented);
}
}
{{/model}}
{{/models}}
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="RestSharp.Net2" version="1.1.11" targetFramework="net20" developmentDependency="true" />
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net20" developmentDependency="true" />
</packages>

View File

@ -1,17 +1,14 @@
package {{invokerPackage}}; package {{invokerPackage}};
import com.fasterxml.jackson.core.JsonGenerator.Feature;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
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.config.ClientConfig;
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;
import com.sun.jersey.multipart.FormDataMultiPart; import com.sun.jersey.multipart.FormDataMultiPart;
import com.sun.jersey.multipart.file.FileDataBodyPart;
import javax.ws.rs.core.Response.Status.Family; import javax.ws.rs.core.Response.Status.Family;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
@ -22,13 +19,16 @@ import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.TimeZone; import java.util.TimeZone;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.io.IOException; import java.io.IOException;
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;
@ -39,14 +39,19 @@ import {{invokerPackage}}.auth.HttpBasicAuth;
import {{invokerPackage}}.auth.ApiKeyAuth; import {{invokerPackage}}.auth.ApiKeyAuth;
import {{invokerPackage}}.auth.OAuth; import {{invokerPackage}}.auth.OAuth;
{{>generatedAnnotation}}
public class ApiClient { public class ApiClient {
private Map<String, Client> hostMap = new HashMap<String, Client>(); private Map<String, Client> hostMap = new HashMap<String, Client>();
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 Map<String, Authentication> authentications; private Map<String, Authentication> authentications;
private int statusCode;
private Map<String, List<String>> responseHeaders;
private DateFormat dateFormat; private DateFormat dateFormat;
public ApiClient() { public ApiClient() {
@ -78,6 +83,20 @@ public class ApiClient {
return this; return this;
} }
/**
* Gets the status code of the previous request
*/
public int getStatusCode() {
return statusCode;
}
/**
* Gets the response headers of the previous request
*/
public Map<String, List<String>> getResponseHeaders() {
return responseHeaders;
}
/** /**
* Get authentications (key: authentication name, value: authentication). * Get authentications (key: authentication name, value: authentication).
*/ */
@ -238,6 +257,62 @@ public class ApiClient {
} }
} }
/*
Format to {@code Pair} objects.
*/
public List<Pair> parameterToPairs(String collectionFormat, String name, Object value){
List<Pair> params = new ArrayList<Pair>();
// preconditions
if (name == null || name.isEmpty() || value == null) return params;
Collection valueCollection = null;
if (value instanceof Collection) {
valueCollection = (Collection) value;
} else {
params.add(new Pair(name, parameterToString(value)));
return params;
}
if (valueCollection.isEmpty()){
return params;
}
// get the collection format
collectionFormat = (collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat); // default: csv
// create the params based on the collection format
if (collectionFormat.equals("multi")) {
for (Object item : valueCollection) {
params.add(new Pair(name, parameterToString(item)));
}
return params;
}
String delimiter = ",";
if (collectionFormat.equals("csv")) {
delimiter = ",";
} else if (collectionFormat.equals("ssv")) {
delimiter = " ";
} else if (collectionFormat.equals("tsv")) {
delimiter = "\t";
} else if (collectionFormat.equals("pipes")) {
delimiter = "|";
}
StringBuilder sb = new StringBuilder() ;
for (Object item : valueCollection) {
sb.append(delimiter);
sb.append(parameterToString(item));
}
params.add(new Pair(name, sb.substring(1)));
return params;
}
/** /**
* 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;
@ -280,84 +355,65 @@ public class ApiClient {
} }
/** /**
* Deserialize the given JSON string to Java object. * Serialize the given Java object into string according the given
* * Content-Type (only JSON is supported for now).
* @param json The JSON string
* @param containerType The container type, one of "list", "array" or ""
* @param cls The type of the Java object
* @return The deserialized Java object
*/ */
public Object deserialize(String json, String containerType, Class cls) throws ApiException { public String serialize(Object obj, String contentType) throws ApiException {
if(null != containerType) { if (contentType.startsWith("application/json")) {
containerType = containerType.toLowerCase(); return json.serialize(obj);
} } else {
try{ throw new ApiException(400, "can not serialize object into Content-Type: " + contentType);
if("list".equals(containerType) || "array".equals(containerType)) {
JavaType typeInfo = JsonUtil.getJsonMapper().getTypeFactory().constructCollectionType(List.class, cls);
List response = (List<?>) JsonUtil.getJsonMapper().readValue(json, typeInfo);
return response;
}
else if(String.class.equals(cls)) {
if(json != null && json.startsWith("\"") && json.endsWith("\"") && json.length() > 1)
return json.substring(1, json.length() - 2);
else
return json;
}
else {
return JsonUtil.getJsonMapper().readValue(json, cls);
}
}
catch (IOException e) {
throw new ApiException(500, e.getMessage(), null, json);
} }
} }
/** /**
* Serialize the given Java object into JSON string. * Deserialize response body to Java object according to the Content-Type.
*/ */
public String serialize(Object obj) throws ApiException { public <T> T deserialize(ClientResponse response, TypeRef returnType) throws ApiException {
try { String contentType = null;
if (obj != null) List<String> contentTypes = response.getHeaders().get("Content-Type");
return JsonUtil.getJsonMapper().writeValueAsString(obj); if (contentTypes != null && !contentTypes.isEmpty())
contentType = contentTypes.get(0);
if (contentType == null)
throw new ApiException(500, "missing Content-Type in response");
String body;
if (response.hasEntity())
body = (String) response.getEntity(String.class);
else else
return null; body = "";
}
catch (Exception e) { if (contentType.startsWith("application/json")) {
throw new ApiException(500, e.getMessage()); return json.deserialize(body, returnType);
} else {
throw new ApiException(500, "can not deserialize Content-Type: " + contentType);
} }
} }
/** 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 {
* Invoke API by sending HTTP request with the given options.
* if (body != null && binaryBody != null){
* @param path The sub-path of the HTTP URL throw new ApiException(500, "either body or binaryBody must be null");
* @param method The request method, one of "GET", "POST", "PUT", and "DELETE" }
* @param queryParams The query parameters
* @param body The request body object
* @param headerParams The header parameters
* @param formParams The form parameters
* @param accept The request's Accept header
* @param contentType The request's Content-Type header
* @param authNames The authentications to apply
* @return The response body in type of string
*/
public String invokeAPI(String path, String method, Map<String, String> queryParams, Object body, Map<String, String> headerParams, Map<String, String> formParams, String accept, String contentType, String[] authNames) throws ApiException {
updateParamsForAuth(authNames, queryParams, headerParams); updateParamsForAuth(authNames, queryParams, headerParams);
Client client = getClient(); Client client = getClient();
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();
for(String key : queryParams.keySet()) {
String value = queryParams.get(key);
if (value != null){
if(b.toString().length() == 0)
b.append("?"); b.append("?");
else if (queryParams != null){
for (Pair queryParam : queryParams){
if (!queryParam.getName().isEmpty()) {
b.append(escapeString(queryParam.getName()));
b.append("=");
b.append(escapeString(queryParam.getValue()));
b.append("&"); b.append("&");
b.append(escapeString(key)).append("=").append(escapeString(value));
} }
} }
String querystring = b.toString(); }
String querystring = b.substring(0, b.length() - 1);
Builder builder; Builder builder;
if (accept == null) if (accept == null)
@ -374,81 +430,165 @@ 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) {
if (contentType.startsWith("application/x-www-form-urlencoded")) { response = builder.type(contentType).post(ClientResponse.class, encodedFormParams);
String encodedFormParams = this
.getXWWWFormUrlencodedParams(formParams);
response = builder.type(contentType).post(ClientResponse.class,
encodedFormParams);
} else if (body == null) { } else if (body == null) {
if(binaryBody == null)
response = builder.post(ClientResponse.class, null); response = builder.post(ClientResponse.class, null);
else
response = builder.type(contentType).post(ClientResponse.class, binaryBody);
} else if (body instanceof FormDataMultiPart) { } else if (body instanceof FormDataMultiPart) {
response = builder.type(contentType).post(ClientResponse.class, body); response = builder.type(contentType).post(ClientResponse.class, body);
} else {
response = builder.type(contentType).post(ClientResponse.class, serialize(body, contentType));
} }
} else if ("PUT".equals(method)) {
if (encodedFormParams != null) {
response = builder.type(contentType).put(ClientResponse.class, encodedFormParams);
} else if(body == null) {
if(binaryBody == null)
response = builder.put(ClientResponse.class, null);
else else
response = builder.type(contentType).post(ClientResponse.class, serialize(body)); response = builder.type(contentType).put(ClientResponse.class, binaryBody);
}
else if ("PUT".equals(method)) {
if ("application/x-www-form-urlencoded".equals(contentType)) {
String encodedFormParams = this
.getXWWWFormUrlencodedParams(formParams);
response = builder.type(contentType).put(ClientResponse.class,
encodedFormParams);
} else if(body == null) {
response = builder.put(ClientResponse.class, serialize(body));
} else { } else {
response = builder.type(contentType).put(ClientResponse.class, serialize(body)); response = builder.type(contentType).put(ClientResponse.class, serialize(body, contentType));
} }
} } else if ("DELETE".equals(method)) {
else if ("DELETE".equals(method)) { if (encodedFormParams != null) {
if ("application/x-www-form-urlencoded".equals(contentType)) { response = builder.type(contentType).delete(ClientResponse.class, encodedFormParams);
String encodedFormParams = this
.getXWWWFormUrlencodedParams(formParams);
response = builder.type(contentType).delete(ClientResponse.class,
encodedFormParams);
} else if(body == null) { } else if(body == null) {
if(binaryBody == null)
response = builder.delete(ClientResponse.class); response = builder.delete(ClientResponse.class);
else
response = builder.type(contentType).delete(ClientResponse.class, binaryBody);
} else { } else {
response = builder.type(contentType).delete(ClientResponse.class, serialize(body)); 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);
} }
return response;
}
if(response.getClientResponseStatus() == ClientResponse.Status.NO_CONTENT) { /**
* Invoke API by sending HTTP request with the given options.
*
* @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 <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 {
ClientResponse response = getAPIResponse(path, method, queryParams, body, binaryBody, headerParams, formParams, accept, contentType, authNames);
statusCode = response.getStatusInfo().getStatusCode();
responseHeaders = response.getHeaders();
if(response.getStatusInfo() == ClientResponse.Status.NO_CONTENT) {
return null; return null;
} } else if (response.getStatusInfo().getFamily() == Family.SUCCESSFUL) {
else if(response.getClientResponseStatus().getFamily() == Family.SUCCESSFUL) { if (returnType == null)
if(response.hasEntity()) { return null;
return (String) response.getEntity(String.class); else
} return deserialize(response, returnType);
else { } else {
return "";
}
}
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 = String.valueOf(response.getEntity(String.class));
message = respBody; message = respBody;
} catch (RuntimeException e) {
// e.printStackTrace();
}
}
throw new ApiException(
response.getStatusInfo().getStatusCode(),
message,
response.getHeaders(),
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) { catch (RuntimeException e) {
// e.printStackTrace(); // e.printStackTrace();
} }
} }
throw new ApiException( throw new ApiException(
response.getClientResponseStatus().getStatusCode(), response.getStatusInfo().getStatusCode(),
message, message);
response.getHeaders(),
respBody);
} }
} }
@ -457,7 +597,7 @@ public class ApiClient {
* *
* @param authNames The authentications to apply * @param authNames The authentications to apply
*/ */
private void updateParamsForAuth(String[] authNames, Map<String, String> queryParams, Map<String, String> headerParams) { private void updateParamsForAuth(String[] authNames, List<Pair> queryParams, Map<String, String> headerParams) {
for (String authName : authNames) { for (String authName : authNames) {
Authentication auth = authentications.get(authName); Authentication auth = authentications.get(authName);
if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); if (auth == null) throw new RuntimeException("Authentication undefined: " + authName);
@ -468,15 +608,14 @@ public class ApiClient {
/** /**
* Encode the given form parameters as request body. * Encode the given form parameters as request body.
*/ */
private String getXWWWFormUrlencodedParams(Map<String, String> formParams) { private String getXWWWFormUrlencodedParams(Map<String, Object> formParams) {
StringBuilder formParamBuilder = new StringBuilder(); StringBuilder formParamBuilder = new StringBuilder();
for (Entry<String, String> param : formParams.entrySet()) { for (Entry<String, Object> param : formParams.entrySet()) {
String keyStr = parameterToString(param.getKey()); String keyStr = param.getKey();
String valueStr = parameterToString(param.getValue()); String valueStr = parameterToString(param.getValue());
try { try {
formParamBuilder.append(URLEncoder.encode(keyStr, "utf8")) formParamBuilder.append(URLEncoder.encode(param.getKey(), "utf8"))
.append("=") .append("=")
.append(URLEncoder.encode(valueStr, "utf8")); .append(URLEncoder.encode(valueStr, "utf8"));
formParamBuilder.append("&"); formParamBuilder.append("&");
@ -484,11 +623,12 @@ public class ApiClient {
// move on to next // move on to next
} }
} }
String encodedFormParams = formParamBuilder.toString(); String encodedFormParams = formParamBuilder.toString();
if (encodedFormParams.endsWith("&")) { if (encodedFormParams.endsWith("&")) {
encodedFormParams = encodedFormParams.substring(0, encodedFormParams = encodedFormParams.substring(0, encodedFormParams.length() - 1);
encodedFormParams.length() - 1);
} }
return encodedFormParams; return encodedFormParams;
} }

View File

@ -1,5 +1,6 @@
package {{invokerPackage}}; package {{invokerPackage}};
{{>generatedAnnotation}}
public class Configuration { public class Configuration {
private static ApiClient defaultApiClient = new ApiClient(); private static ApiClient defaultApiClient = new ApiClient();

View File

@ -0,0 +1,54 @@
package {{invokerPackage}};
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.datatype.joda.*;
import java.io.IOException;
{{>generatedAnnotation}}
public class JSON {
private ObjectMapper mapper;
public JSON() {
mapper = new ObjectMapper();
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());
}
/**
* 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,23 +0,0 @@
package {{invokerPackage}};
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.core.JsonGenerator.Feature;
import com.fasterxml.jackson.datatype.joda.*;
public class JsonUtil {
public static ObjectMapper mapper;
static {
mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
mapper.registerModule(new JodaModule());
}
public static ObjectMapper getJsonMapper() {
return mapper;
}
}

View File

@ -0,0 +1,39 @@
package {{invokerPackage}};
{{>generatedAnnotation}}
public class Pair {
private String name = "";
private String value = "";
public Pair (String name, String value) {
setName(name);
setValue(value);
}
private void setName(String name) {
if (!isValidString(name)) return;
this.name = name;
}
private void setValue(String value) {
if (!isValidString(value)) return;
this.value = value;
}
public String getName() {
return this.name;
}
public String getValue() {
return this.value;
}
private boolean isValidString(String arg) {
if (arg == null) return false;
if (arg.trim().isEmpty()) return false;
return true;
}
}

View File

@ -1,5 +1,6 @@
package {{invokerPackage}}; package {{invokerPackage}};
{{>generatedAnnotation}}
public class StringUtil { public class StringUtil {
/** /**
* Check if the given array contains the given value (with case-insensitive comparison). * Check if the given array contains the given value (with case-insensitive comparison).
@ -38,4 +39,13 @@ public class StringUtil {
} }
return out.toString(); return out.toString();
} }
/**
* Convert the given object to string with each line indented by 4 spaces
* (except the first line).
*/
public static String toIndentedString(Object o) {
if (o == null) return "null";
return o.toString().replace("\n", "\n ");
}
} }

View File

@ -0,0 +1,26 @@
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

@ -3,6 +3,8 @@ package {{package}};
import {{invokerPackage}}.ApiException; import {{invokerPackage}}.ApiException;
import {{invokerPackage}}.ApiClient; import {{invokerPackage}}.ApiClient;
import {{invokerPackage}}.Configuration; import {{invokerPackage}}.Configuration;
import {{invokerPackage}}.Pair;
import {{invokerPackage}}.TypeRef;
import {{modelPackage}}.*; import {{modelPackage}}.*;
@ -11,33 +13,29 @@ import java.util.*;
{{#imports}}import {{import}}; {{#imports}}import {{import}};
{{/imports}} {{/imports}}
import com.sun.jersey.multipart.FormDataMultiPart;
import com.sun.jersey.multipart.file.FileDataBodyPart;
import javax.ws.rs.core.MediaType;
import java.io.File; import java.io.File;
import java.util.Map; import java.util.Map;
import java.util.HashMap; import java.util.HashMap;
{{>generatedAnnotation}}
{{#operations}} {{#operations}}
public class {{classname}} { public class {{classname}} {
private ApiClient apiClient; private ApiClient {{localVariablePrefix}}apiClient;
public {{classname}}() { public {{classname}}() {
this(Configuration.getDefaultApiClient()); this(Configuration.getDefaultApiClient());
} }
public {{classname}}(ApiClient apiClient) { public {{classname}}(ApiClient apiClient) {
this.apiClient = apiClient; this.{{localVariablePrefix}}apiClient = apiClient;
} }
public ApiClient getApiClient() { public ApiClient getApiClient() {
return apiClient; return {{localVariablePrefix}}apiClient;
} }
public void setApiClient(ApiClient apiClient) { public void setApiClient(ApiClient apiClient) {
this.apiClient = apiClient; this.{{localVariablePrefix}}apiClient = apiClient;
} }
{{#operation}} {{#operation}}
@ -48,77 +46,63 @@ public class {{classname}} {
{{/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}}{{nickname}} ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException {
Object postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; Object {{localVariablePrefix}}postBody = {{#bodyParam}}{{^isBinary}}{{paramName}}{{/isBinary}}{{#isBinary}}null{{/isBinary}}{{/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 {{nickname}}");
} }
{{/required}}{{/allParams}} {{/required}}{{/allParams}}
// create path and map variables // create path and map variables
String path = "{{path}}".replaceAll("\\{format\\}","json"){{#pathParams}} String {{localVariablePrefix}}path = "{{{path}}}".replaceAll("\\{format\\}","json"){{#pathParams}}
.replaceAll("\\{" + "{{paramName}}" + "\\}", apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; .replaceAll("\\{" + "{{baseName}}" + "\\}", {{localVariablePrefix}}apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}};
// query params // query params
Map<String, String> queryParams = new HashMap<String, String>(); List<Pair> {{localVariablePrefix}}queryParams = new ArrayList<Pair>();
Map<String, String> headerParams = new HashMap<String, String>(); Map<String, String> {{localVariablePrefix}}headerParams = new HashMap<String, String>();
Map<String, String> formParams = new HashMap<String, String>(); Map<String, Object> {{localVariablePrefix}}formParams = new HashMap<String, Object>();
{{#queryParams}}if ({{paramName}} != null) {{#queryParams}}
queryParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); {{localVariablePrefix}}queryParams.addAll({{localVariablePrefix}}apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}}));
{{/queryParams}} {{/queryParams}}
{{#headerParams}}if ({{paramName}} != null) {{#headerParams}}if ({{paramName}} != null)
headerParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); {{localVariablePrefix}}headerParams.put("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}}));
{{/headerParams}} {{/headerParams}}
final String[] accepts = { {{#formParams}}if ({{paramName}} != null)
{{localVariablePrefix}}formParams.put("{{baseName}}", {{paramName}});
{{/formParams}}
final String[] {{localVariablePrefix}}accepts = {
{{#produces}}"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/produces}} {{#produces}}"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/produces}}
}; };
final String accept = apiClient.selectHeaderAccept(accepts); final String {{localVariablePrefix}}accept = {{localVariablePrefix}}apiClient.selectHeaderAccept({{localVariablePrefix}}accepts);
final String[] contentTypes = { final String[] {{localVariablePrefix}}contentTypes = {
{{#consumes}}"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} {{#consumes}}"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/consumes}}
}; };
final String contentType = apiClient.selectHeaderContentType(contentTypes); final String {{localVariablePrefix}}contentType = {{localVariablePrefix}}apiClient.selectHeaderContentType({{localVariablePrefix}}contentTypes);
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}}
TypeRef {{localVariablePrefix}}returnType = new TypeRef<{{{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);
{{/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);
{{/returnType}}
{{/isResponseBinary}}
if(contentType.startsWith("multipart/form-data")) {
boolean hasFields = false;
FormDataMultiPart mp = new FormDataMultiPart();
{{#formParams}}{{#notFile}}
if ({{paramName}} != null) {
hasFields = true;
mp.field("{{baseName}}", apiClient.parameterToString({{paramName}}), MediaType.MULTIPART_FORM_DATA_TYPE);
}
{{/notFile}}{{#isFile}}
if ({{paramName}} != null) {
hasFields = true;
mp.field("{{baseName}}", {{paramName}}.getName());
mp.bodyPart(new FileDataBodyPart("{{baseName}}", {{paramName}}, MediaType.MULTIPART_FORM_DATA_TYPE));
}
{{/isFile}}{{/formParams}}
if(hasFields)
postBody = mp;
}
else {
{{#formParams}}{{#notFile}}if ({{paramName}} != null)
formParams.put("{{baseName}}", apiClient.parameterToString({{paramName}}));{{/notFile}}
{{/formParams}}
}
try {
String[] authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} };
String response = apiClient.invokeAPI(path, "{{httpMethod}}", queryParams, postBody, headerParams, formParams, accept, contentType, authNames);
if(response != null){
return {{#returnType}}({{{returnType}}}) apiClient.deserialize(response, "{{returnContainer}}", {{returnBaseType}}.class){{/returnType}};
}
else {
return {{#returnType}}null{{/returnType}};
}
} catch (ApiException ex) {
throw ex;
}
} }
{{/operation}} {{/operation}}
} }

View File

@ -3,22 +3,48 @@ package {{invokerPackage}};
import java.util.Map; import java.util.Map;
import java.util.List; import java.util.List;
{{>generatedAnnotation}}
public class ApiException extends Exception { public class ApiException extends Exception {
private int code = 0; private int code = 0;
private String message = null;
private Map<String, List<String>> responseHeaders = null; private Map<String, List<String>> responseHeaders = null;
private String responseBody = null; private String responseBody = null;
public ApiException() {} public ApiException() {}
public ApiException(int code, String message) { public ApiException(Throwable throwable) {
super(throwable);
}
public ApiException(String message) {
super(message);
}
public ApiException(String message, Throwable throwable, int code, Map<String, List<String>> responseHeaders, String responseBody) {
super(message, throwable);
this.code = code;
this.responseHeaders = responseHeaders;
this.responseBody = responseBody;
}
public ApiException(String message, int code, Map<String, List<String>> responseHeaders, String responseBody) {
this(message, (Throwable) null, code, responseHeaders, responseBody);
}
public ApiException(String message, Throwable throwable, int code, Map<String, List<String>> responseHeaders) {
this(message, throwable, code, responseHeaders, null);
}
public ApiException(int code, Map<String, List<String>> responseHeaders, String responseBody) {
this((String) null, (Throwable) null, code, responseHeaders, responseBody);
}
public ApiException(int code, String message) {
super(message);
this.code = code; this.code = code;
this.message = message;
} }
public ApiException(int code, String message, Map<String, List<String>> responseHeaders, String responseBody) { public ApiException(int code, String message, Map<String, List<String>> responseHeaders, String responseBody) {
this.code = code; this(code, message);
this.message = message;
this.responseHeaders = responseHeaders; this.responseHeaders = responseHeaders;
this.responseBody = responseBody; this.responseBody = responseBody;
} }
@ -27,10 +53,6 @@ public class ApiException extends Exception {
return code; return code;
} }
public String getMessage() {
return message;
}
/** /**
* Get the HTTP response headers. * Get the HTTP response headers.
*/ */

View File

@ -1,7 +1,11 @@
package {{invokerPackage}}.auth; package {{invokerPackage}}.auth;
import java.util.Map; import {{invokerPackage}}.Pair;
import java.util.Map;
import java.util.List;
{{>generatedAnnotation}}
public class ApiKeyAuth implements Authentication { public class ApiKeyAuth implements Authentication {
private final String location; private final String location;
private final String paramName; private final String paramName;
@ -39,7 +43,7 @@ public class ApiKeyAuth implements Authentication {
} }
@Override @Override
public void applyToParams(Map<String, String> queryParams, Map<String, String> headerParams) { public void applyToParams(List<Pair> queryParams, Map<String, String> headerParams) {
String value; String value;
if (apiKeyPrefix != null) { if (apiKeyPrefix != null) {
value = apiKeyPrefix + " " + apiKey; value = apiKeyPrefix + " " + apiKey;
@ -47,7 +51,7 @@ public class ApiKeyAuth implements Authentication {
value = apiKey; value = apiKey;
} }
if (location == "query") { if (location == "query") {
queryParams.put(paramName, value); queryParams.add(new Pair(paramName, value));
} else if (location == "header") { } else if (location == "header") {
headerParams.put(paramName, value); headerParams.put(paramName, value);
} }

View File

@ -1,8 +1,12 @@
package {{invokerPackage}}.auth; package {{invokerPackage}}.auth;
import java.util.Map; import {{invokerPackage}}.Pair;
import java.util.Map;
import java.util.List;
{{>generatedAnnotation}}
public interface Authentication { public interface Authentication {
/** Apply authentication settings to header and query params. */ /** Apply authentication settings to header and query params. */
void applyToParams(Map<String, String> queryParams, Map<String, String> headerParams); void applyToParams(List<Pair> queryParams, Map<String, String> headerParams);
} }

View File

@ -1,10 +1,14 @@
package {{invokerPackage}}.auth; package {{invokerPackage}}.auth;
import {{invokerPackage}}.Pair;
import java.util.Map; import java.util.Map;
import java.util.List;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import javax.xml.bind.DatatypeConverter; import javax.xml.bind.DatatypeConverter;
{{>generatedAnnotation}}
public class HttpBasicAuth implements Authentication { public class HttpBasicAuth implements Authentication {
private String username; private String username;
private String password; private String password;
@ -26,7 +30,7 @@ public class HttpBasicAuth implements Authentication {
} }
@Override @Override
public void applyToParams(Map<String, String> queryParams, Map<String, String> headerParams) { public void applyToParams(List<Pair> queryParams, Map<String, String> headerParams) {
String str = (username == null ? "" : username) + ":" + (password == null ? "" : password); String str = (username == null ? "" : username) + ":" + (password == null ? "" : password);
try { try {
headerParams.put("Authorization", "Basic " + DatatypeConverter.printBase64Binary(str.getBytes("UTF-8"))); headerParams.put("Authorization", "Basic " + DatatypeConverter.printBase64Binary(str.getBytes("UTF-8")));

View File

@ -1,10 +1,14 @@
package {{invokerPackage}}.auth; package {{invokerPackage}}.auth;
import java.util.Map; import {{invokerPackage}}.Pair;
import java.util.Map;
import java.util.List;
{{>generatedAnnotation}}
public class OAuth implements Authentication { public class OAuth implements Authentication {
@Override @Override
public void applyToParams(Map<String, String> queryParams, Map<String, String> headerParams) { public void applyToParams(List<Pair> queryParams, Map<String, String> headerParams) {
// TODO: support oauth // TODO: support oauth
} }
} }

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