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/*
build/*
generated-files/*
generated-sources/*
generated-code/*
*.swp
*.swo
@ -30,8 +31,10 @@ 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/client/petstore/objc/SwaggerClientTests/Build
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
target
.idea
@ -41,3 +44,9 @@ atlassian-ide-plugin.xml
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/
samples/client/petstore/python/.projectile
samples/client/petstore/python/.venv/

View File

@ -1,5 +1,5 @@
sudo: false
language: java
script: mvn verify
script: mvn verify -Psamples
jdk:
- 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.
## 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
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
----------------------- | ------------ | -------------------------- | -----
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)
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>)]
[(-t <template directory> | --template-dir <template directory>)]
[(-v | --verbose)]
[(-s | --skip-overwrite)]
OPTIONS
-a <authorization>, --auth <authorization>
@ -105,6 +125,10 @@ OPTIONS
-v, --verbose
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:
@ -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/
AbstractTypeScriptClientCodegen.java
AkkaScalaClientCodegen.java
AndroidClientCodegen.java
AsyncScalaClientCodegen.java
CSharpClientCodegen.java
CodeGenStatus.java
CsharpDotNet2ClientCodegen.java
FlashClientCodegen.java
JavaClientCodegen.java
JavaInflectorServerCodegen.java
JaxRSServerCodegen.java
NodeJSServerCodegen.java
ObjcClientCodegen.java
@ -178,13 +207,17 @@ RetrofitClientCodegen.java
RubyClientCodegen.java
ScalaClientCodegen.java
ScalatraServerCodegen.java
SilexServerCodegen.java
SinatraServerCodegen.java
SpringMVCServerCodegen.java
StaticDocCodegen.java
StaticHtmlGenerator.java
SwaggerGenerator.java
SwaggerYamlGenerator.java
SwiftGenerator.java
SwiftCodegen.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.
@ -226,6 +259,12 @@ CONFIG OPTIONS
sourceFolder
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

View File

@ -18,19 +18,30 @@ if [ ! -d "${APP_DIR}" ]; then
fi
cd $APP_DIR
./bin/akka-scala-petstore.sh
./bin/android-java-petstore.sh
./bin/csharp-petstore.sh
./bin/dynamic-html.sh
./bin/html-petstore.sh
./bin/jaxrs-petstore-server.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/php-petstore.sh
./bin/python-petstore.sh
./bin/python3-petstore.sh
./bin/qt5-petstore.sh
./bin/retrofit-petstore.sh
./bin/ruby-petstore.sh
./bin/objc-petstore.sh
./bin/scala-async-petstore.sh
./bin/scala-petstore.sh
./bin/scalatra-petstore-server.sh
./bin/silex-petstore-server.sh
./bin/spring-mvc-petstore-server.sh
./bin/swift-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.
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

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.
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

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.
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

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

View File

@ -4,10 +4,7 @@ import io.airlift.airline.Command;
import io.airlift.airline.Option;
import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig;
import java.util.ServiceLoader;
import static java.util.ServiceLoader.load;
import io.swagger.codegen.CodegenConfigLoader;
@Command(name = "config-help", description = "Config help for chosen lang")
public class ConfigHelp implements Runnable {
@ -16,36 +13,14 @@ public class ConfigHelp implements Runnable {
description = "language to get config help for")
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
public void run() {
System.out.println();
CodegenConfig config = forName(lang);
CodegenConfig config = CodegenConfigLoader.forName(lang);
System.out.println("CONFIG OPTIONS");
for (CliOption langCliOption : config.cliOptions()) {
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();
}
}

View File

@ -8,16 +8,21 @@ 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.CodegenConstants;
import io.swagger.codegen.DefaultGenerator;
import io.swagger.codegen.cmd.utils.OptionUtils;
import io.swagger.models.Swagger;
import io.swagger.parser.SwaggerParser;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
/**
@ -31,8 +36,6 @@ public class Generate implements Runnable {
public static final Logger LOG = LoggerFactory.getLogger(Generate.class);
public static final String TEMPLATE_DIR_PARAM = "templateDir";
@Option(name = {"-v", "--verbose"}, description = "verbose mode")
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.")
private String configFile;
/**
* 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;
}
}
@Option(name = {"-s", "--skip-overwrite"}, title = "skip overwrite", description = "specifies if the existing files should be " +
"overwritten during the generation.")
private boolean skipOverwrite;
// 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);
}
}
@Option(name = {"--api-package"}, title = "api package", description = CodegenConstants.API_PACKAGE_DESC)
private String apiPackage;
@Option(name = {"--model-package"}, title = "model package", description = CodegenConstants.MODEL_PACKAGE_DESC)
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
public void run() {
@ -94,47 +116,92 @@ public class Generate implements Runnable {
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.setSkipOverwrite(skipOverwrite);
if (null != templateDir) {
config.additionalProperties().put(TEMPLATE_DIR_PARAM, new File(templateDir).getAbsolutePath());
putKeyValuePairsInMap(config.instantiationTypes(), instantiationTypes);
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) {
Config genConfig = ConfigParser.read(configFile);
if (null != genConfig) {
for (CliOption langCliOption : config.cliOptions()) {
if (genConfig.hasOption(langCliOption.getOpt())) {
config.additionalProperties().put(langCliOption.getOpt(), genConfig.getOption(langCliOption.getOpt()));
String opt = 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);
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() {
if (systemProperties != null && systemProperties.length() > 0) {
for (String property : systemProperties.split(",")) {
int ix = property.indexOf('=');
if (ix > 0 && ix < property.length() - 1) {
System.setProperty(property.substring(0, ix), property.substring(ix + 1));
final List<Pair<String, String>> systemPropertyPairs = OptionUtils.parseCommaSeparatedTuples(systemProperties);
for (Pair<String, String> pair : systemPropertyPairs) {
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
*

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

View File

@ -60,7 +60,28 @@ public abstract class AbstractGenerator {
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)) {
return name.replaceAll(Pattern.quote(File.separator), "/");
}

View File

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

View File

@ -65,6 +65,8 @@ public interface CodegenConfig {
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);
List<CodegenSecurity> fromSecurity(Map<String, SecuritySchemeDefinition> schemes);
@ -81,6 +83,8 @@ public interface CodegenConfig {
Map<String, String> modelTemplateFiles();
Set<String> languageSpecificPrimitives();
void processSwagger(Swagger swagger);
String toApiFilename(String name);
@ -102,4 +106,17 @@ public interface CodegenConfig {
String apiFilename(String templateName, String tag);
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 Boolean hasConsumes, hasProduces, hasParams, returnTypeIsPrimitive,
returnSimpleType, subresourceOperation, isMapContainer, isListContainer,
hasMore = Boolean.TRUE, isMultipart;
hasMore = Boolean.TRUE, isMultipart, isResponseBinary = Boolean.FALSE;
public String path, operationId, returnType, httpMethod, returnBaseType,
returnContainer, summary, notes, baseName, defaultResponse;
public List<Map<String, String>> consumes, produces;
@ -29,6 +29,24 @@ public class CodegenOperation {
public Set<String> imports = new HashSet<String>();
public List<Map<String, String>> examples;
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
public String nickname;

View File

@ -1,10 +1,19 @@
package io.swagger.codegen;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
public class CodegenParameter {
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 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",
@ -35,6 +44,14 @@ public class CodegenParameter {
output.required = this.required;
output.jsonSchema = this.jsonSchema;
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;
}

View File

@ -34,4 +34,107 @@ public class CodegenProperty {
public boolean isEnum;
public List<String> _enum;
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 isMapContainer;
public Boolean isListContainer;
public Boolean isBinary = Boolean.FALSE;
public Object schema;
public String jsonSchema;

View File

@ -1,5 +1,7 @@
package io.swagger.codegen;
import java.util.Set;
public class CodegenSecurity {
public String name;
public String type;
@ -7,4 +9,7 @@ public class CodegenSecurity {
// ApiKey specific
public String keyParamName;
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.BasicAuthDefinition;
import io.swagger.models.auth.In;
import io.swagger.models.auth.OAuth2Definition;
import io.swagger.models.auth.SecuritySchemeDefinition;
import io.swagger.models.parameters.BodyParameter;
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.ArrayProperty;
import io.swagger.models.properties.BooleanProperty;
import io.swagger.models.properties.ByteArrayProperty;
import io.swagger.models.properties.DateProperty;
import io.swagger.models.properties.DateTimeProperty;
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.Property;
import io.swagger.models.properties.PropertyBuilder;
import io.swagger.models.properties.PropertyBuilder.PropertyId;
import io.swagger.models.properties.RefProperty;
import io.swagger.models.properties.StringProperty;
import io.swagger.util.Json;
@ -49,9 +52,11 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -60,7 +65,7 @@ import java.util.regex.Pattern;
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 Set<String> defaultIncludes = new HashSet<String>();
@ -76,22 +81,27 @@ public class DefaultCodegen {
protected Map<String, Object> additionalProperties = new HashMap<String, Object>();
protected List<SupportingFile> supportingFiles = new ArrayList<SupportingFile>();
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() {
return cliOptions;
}
public void processOpts() {
if (additionalProperties.containsKey("templateDir")) {
this.setTemplateDir((String) additionalProperties.get("templateDir"));
if (additionalProperties.containsKey(CodegenConstants.TEMPLATE_DIR)) {
this.setTemplateDir((String) additionalProperties.get(CodegenConstants.TEMPLATE_DIR));
}
if (additionalProperties.containsKey("modelPackage")) {
this.setModelPackage((String) additionalProperties.get("modelPackage"));
if (additionalProperties.containsKey(CodegenConstants.MODEL_PACKAGE)) {
this.setModelPackage((String) additionalProperties.get(CodegenConstants.MODEL_PACKAGE));
}
if (additionalProperties.containsKey("apiPackage")) {
this.setApiPackage((String) additionalProperties.get("apiPackage"));
if (additionalProperties.containsKey(CodegenConstants.API_PACKAGE)) {
this.setApiPackage((String) additionalProperties.get(CodegenConstants.API_PACKAGE));
}
}
@ -117,6 +127,7 @@ public class DefaultCodegen {
// override with any special text escaping logic
public String escapeText(String input) {
if (input != null) {
input = input.trim();
String output = input.replaceAll("\n", "\\\\n");
output = output.replace("\"", "\\\"");
return output;
@ -225,6 +236,11 @@ public class DefaultCodegen {
}
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;
}
@ -298,6 +314,8 @@ public class DefaultCodegen {
typeMapping.put("double", "Double");
typeMapping.put("object", "Object");
typeMapping.put("integer", "Integer");
typeMapping.put("ByteArray", "byte[]");
instantiationTypes = new HashMap<String, String>();
@ -320,8 +338,8 @@ public class DefaultCodegen {
importMapping.put("LocalDate", "org.joda.time.*");
importMapping.put("LocalTime", "org.joda.time.*");
cliOptions.add(new CliOption("modelPackage", "package for generated models"));
cliOptions.add(new CliOption("apiPackage", "package for generated api classes"));
cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
}
@ -378,7 +396,13 @@ public class DefaultCodegen {
public String toInstantiationType(Property p) {
if (p instanceof MapProperty) {
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 + ">";
} else if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
@ -422,14 +446,6 @@ public class DefaultCodegen {
return dp.getDefault().toString();
}
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 {
return "null";
}
@ -442,6 +458,8 @@ public class DefaultCodegen {
String datatype = null;
if (p instanceof StringProperty) {
datatype = "string";
} else if (p instanceof ByteArrayProperty) {
datatype = "ByteArray";
} else if (p instanceof BooleanProperty) {
datatype = "boolean";
} else if (p instanceof DateProperty) {
@ -506,6 +524,10 @@ public class DefaultCodegen {
}
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);
if (reservedWords.contains(name)) {
m.name = escapeReservedWord(name);
@ -520,17 +542,65 @@ public class DefaultCodegen {
if (model instanceof ArrayModel) {
ArrayModel am = (ArrayModel) model;
ArrayProperty arrayProperty = new ArrayProperty(am.getItems());
m.hasEnums = false; // Otherwise there will be a NullPointerException in JavaClientCodegen.fromModel
addParentContainer(m, name, arrayProperty);
} else if (model instanceof RefModel) {
// TODO
} else if (model instanceof ComposedModel) {
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 String parentModel = toModelName(parent.getSimpleRef());
m.parent = parentModel;
addImport(m, parentModel);
final ModelImpl child = (ModelImpl) composed.getChild();
addVars(m, child.getProperties(), child.getRequired());
if (parent != null) {
final String parentRef = toModelName(parent.getSimpleRef());
m.parent = parentRef;
addImport(m, parentRef);
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 {
ModelImpl impl = (ModelImpl) model;
if (impl.getAdditionalProperties() != null) {
@ -553,7 +623,7 @@ public class DefaultCodegen {
public CodegenProperty fromProperty(String name, Property p) {
if (p == null) {
LOGGER.error("unexpected missing property for name " + null);
LOGGER.error("unexpected missing property for name " + name);
return null;
}
CodegenProperty property = CodegenModelFactory.newInstance(CodegenModelType.PROPERTY);
@ -583,8 +653,10 @@ public class DefaultCodegen {
if (np.getMaximum() != null) {
allowableValues.put("max", np.getMaximum());
}
if(allowableValues.size() > 0) {
property.allowableValues = allowableValues;
}
}
if (p instanceof StringProperty) {
StringProperty sp = (StringProperty) p;
@ -602,7 +674,102 @@ public class DefaultCodegen {
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);
// this can cause issues for clients which don't support enums
@ -618,7 +785,7 @@ public class DefaultCodegen {
property.isContainer = true;
property.containerType = "array";
ArrayProperty ap = (ArrayProperty) p;
CodegenProperty cp = fromProperty("inner", ap.getItems());
CodegenProperty cp = fromProperty(property.name, ap.getItems());
if (cp == null) {
LOGGER.warn("skipping invalid property " + Json.pretty(p));
} else {
@ -628,6 +795,12 @@ public class DefaultCodegen {
} else {
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) {
property.isContainer = true;
@ -675,6 +848,7 @@ public class DefaultCodegen {
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, Map<String, Model> definitions) {
CodegenOperation op = CodegenModelFactory.newInstance(CodegenModelType.OPERATION);
Set<String> imports = new HashSet<String>();
op.vendorExtensions = operation.getVendorExtensions();
String operationId = operation.getOperationId();
if (operationId == null) {
@ -699,7 +873,7 @@ public class DefaultCodegen {
}
}
operationId = builder.toString();
LOGGER.warn("generated operationId " + operationId);
LOGGER.info("generated operationId " + operationId + "\tfor Path: " + httpMethod + " " + path);
}
operationId = removeNonNameElementToCamelCase(operationId);
op.path = path;
@ -758,6 +932,9 @@ public class DefaultCodegen {
}
r.isDefault = response == methodResponse;
op.responses.add(r);
if (r.isBinary && r.isDefault){
op.isResponseBinary = Boolean.TRUE;
}
}
op.responses.get(op.responses.size() - 1).hasMore = false;
@ -850,6 +1027,20 @@ public class DefaultCodegen {
}
op.bodyParam = bodyParam;
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.bodyParams = addHasMore(bodyParams);
op.pathParams = addHasMore(pathParams);
@ -899,6 +1090,7 @@ public class DefaultCodegen {
}
}
r.dataType = cm.datatype;
r.isBinary = cm.datatype.equals("byte[]");
if (cm.isContainer != null) {
r.simpleType = false;
r.containerType = cm.containerType;
@ -927,6 +1119,10 @@ public class DefaultCodegen {
}
p.jsonSchema = Json.pretty(param);
if (System.getProperty("debugParser") != null) {
LOGGER.info("working on Parameter " + param);
}
// move the defaultValue for headers, forms and params
if (param instanceof QueryParameter) {
p.defaultValue = ((QueryParameter) param).getDefaultValue();
@ -936,11 +1132,17 @@ public class DefaultCodegen {
p.defaultValue = ((FormParameter) param).getDefaultValue();
}
p.vendorExtensions = param.getVendorExtensions();
if (param instanceof SerializableParameter) {
SerializableParameter qp = (SerializableParameter) param;
Property property = 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();
if (inner == null) {
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.isContainer = true;
imports.add(pr.baseType);
} else if ("object".equals(qp.getType())) {
} else if ("object".equals(type)) {
Property inner = qp.getItems();
if (inner == null) {
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;
imports.add(pr.baseType);
} 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) {
LOGGER.warn("warning! Property type \"" + qp.getType() + "\" 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");
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 " + type + " but not supported");
}
property.setRequired(param.getRequired());
CodegenProperty model = fromProperty(qp.getName(), property);
p.collectionFormat = collectionFormat;
p.dataType = model.datatype;
p.isEnum = model.isEnum;
p._enum = model._enum;
p.allowableValues = model.allowableValues;
p.collectionFormat = collectionFormat;
p.paramName = toParamName(qp.getName());
if (model.complexType != null) {
imports.add(model.complexType);
}
} else {
if (!(param instanceof BodyParameter)) {
LOGGER.error("Cannot use Parameter " + param + " as Body Parameter");
}
BodyParameter bp = (BodyParameter) param;
Model model = bp.getSchema();
@ -990,12 +1202,17 @@ public class DefaultCodegen {
p.dataType = getTypeDeclaration(cm.classname);
imports.add(p.dataType);
} else {
// TODO: missing format, so this will not always work
Property prop = PropertyBuilder.build(impl.getType(), null, null);
Property prop = PropertyBuilder.build(impl.getType(), impl.getFormat(), null);
prop.setRequired(bp.getRequired());
CodegenProperty cp = fromProperty("property", prop);
if (cp != null) {
p.dataType = cp.datatype;
if (p.dataType.equals("byte[]")) {
p.isBinary = true;
}
else {
p.isBinary = false;
}
}
}
} else if (model instanceof ArrayModel) {
@ -1056,10 +1273,17 @@ public class DefaultCodegen {
sec.keyParamName = apiKeyDefinition.getName();
sec.isKeyInHeader = apiKeyDefinition.getIn() == In.HEADER;
sec.isKeyInQuery = !sec.isKeyInHeader;
} else if(schemeDefinition instanceof BasicAuthDefinition) {
sec.isKeyInHeader = sec.isKeyInQuery = sec.isApiKey = sec.isOAuth = false;
sec.isBasic = true;
} else {
sec.isKeyInHeader = sec.isKeyInQuery = sec.isApiKey = false;
sec.isBasic = schemeDefinition instanceof BasicAuthDefinition;
sec.isOAuth = !sec.isBasic;
final OAuth2Definition oauth2Definition = (OAuth2Definition) schemeDefinition;
sec.isKeyInHeader = sec.isKeyInQuery = sec.isApiKey = sec.isBasic = false;
sec.isOAuth = true;
sec.flow = oauth2Definition.getFlow();
sec.authorizationUrl = oauth2Definition.getAuthorizationUrl();
sec.tokenUrl = oauth2Definition.getTokenUrl();
sec.scopes = oauth2Definition.getScopes().keySet();
}
sec.hasMore = it.hasNext();
@ -1146,7 +1370,9 @@ public class DefaultCodegen {
if (mappedType != null) {
addImport(m, mappedType);
}
} /**
}
/**
* Underscore the given word.
*
* @param word The word
@ -1208,10 +1434,9 @@ public class DefaultCodegen {
} else {
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
*
@ -1231,7 +1456,13 @@ public class DefaultCodegen {
name = name.substring(0, 1).toLowerCase() + name.substring(1);
}
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)
Pattern p = Pattern.compile("\\/(.?)");
Matcher m = p.matcher(word);
@ -1294,6 +1525,81 @@ public class DefaultCodegen {
}
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;
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.Template;
import io.swagger.codegen.languages.CodeGenStatus;
import io.swagger.models.ComposedModel;
import io.swagger.models.Contact;
import io.swagger.models.Info;
import io.swagger.models.License;
@ -9,9 +14,14 @@ import io.swagger.models.Model;
import io.swagger.models.Operation;
import io.swagger.models.Path;
import io.swagger.models.Swagger;
import io.swagger.models.auth.OAuth2Definition;
import io.swagger.models.auth.SecuritySchemeDefinition;
import io.swagger.models.parameters.Parameter;
import io.swagger.util.Json;
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.FileInputStream;
@ -20,6 +30,8 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
@ -28,14 +40,16 @@ import java.util.List;
import java.util.Map;
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 {
Logger LOGGER = LoggerFactory.getLogger(DefaultGenerator.class);
protected CodegenConfig config;
protected ClientOptInput opts = null;
protected Swagger swagger = null;
public CodeGenStatus status = CodeGenStatus.UNRUN;
@Override
public Generator opts(ClientOptInput opts) {
this.opts = opts;
@ -46,6 +60,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
return this;
}
@Override
public List<File> generate() {
if (swagger == null || config == null) {
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>();
try {
config.processOpts();
config.additionalProperties().put("generatedDate", DateTime.now().toString());
config.additionalProperties().put("generatorClass", config.getClass().toString());
if (swagger.getInfo() != null) {
Info info = swagger.getInfo();
if (info.getTitle() != null) {
@ -105,10 +124,8 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
}
if (swagger.getBasePath() != null) {
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();
@ -118,11 +135,13 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
// models
Map<String, Model> definitions = swagger.getDefinitions();
if (definitions != null) {
for (String name : definitions.keySet()) {
List<String> sortedModelKeys = sortModelsByInheritance(definitions);
for (String name : sortedModelKeys) {
Model model = definitions.get(name);
Map<String, Model> modelMap = new HashMap<String, Model>();
modelMap.put(name, model);
Map<String, Object> models = processModels(config, modelMap);
Map<String, Object> models = processModels(config, modelMap, definitions);
models.putAll(config.additionalProperties());
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()) {
String suffix = config.modelTemplateFiles().get(templateName);
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()
.withLoader(new Mustache.TemplateLoader() {
@Override
public Reader getTemplate(String name) {
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()) {
String filename = config.apiFilename(templateName, tag);
if (new File(filename).exists() && !config.shouldOverwrite(filename)) {
if (!config.shouldOverwrite(filename) && new File(filename).exists()) {
continue;
}
String template = readTemplate(config.templateDir() + File.separator + templateName);
String templateFile = getFullTemplateFile(config, templateName);
String template = readTemplate(templateFile);
Template tmpl = Mustache.compiler()
.withLoader(new Mustache.TemplateLoader() {
@Override
public Reader getTemplate(String name) {
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("apiFolder", config.apiPackage().replace('.', File.separatorChar));
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) {
bundle.put("externalDocs", swagger.getExternalDocs());
}
@ -245,11 +275,17 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
of.mkdirs();
}
String outputFilename = outputFolder + File.separator + support.destinationFilename;
if (!config.shouldOverwrite(outputFilename)) {
continue;
}
if (support.templateFile.endsWith("mustache")) {
String template = readTemplate(config.templateDir() + File.separator + support.templateFile);
String templateFile = getFullTemplateFile(config, support.templateFile);
if (templateFile.endsWith("mustache")) {
String template = readTemplate(templateFile);
Template tmpl = Mustache.compiler()
.withLoader(new Mustache.TemplateLoader() {
@Override
public Reader getTemplate(String name) {
return getTemplateReader(config.templateDir() + File.separator + name + ".mustache");
}
@ -263,20 +299,21 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
InputStream in = null;
try {
in = new FileInputStream(config.templateDir() + File.separator + support.templateFile);
in = new FileInputStream(templateFile);
} catch (Exception e) {
// continue
}
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);
OutputStream out = new FileOutputStream(outputFile, false);
if (in != null && out != null) {
System.out.println("writing file " + outputFile);
IOUtils.copy(in, out);
} else {
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) {
System.out.println("can't open " + outputFile + " for output");
@ -288,8 +325,10 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
}
config.processSwagger(swagger);
status = CodeGenStatus.SUCCESSFUL;
} catch (Exception e) {
e.printStackTrace();
status = CodeGenStatus.FAILED;
}
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) {
Map<String, List<CodegenOperation>> ops = new HashMap<String, List<CodegenOperation>>();
for (String resourcePath : paths.keySet()) {
Path path = paths.get(resourcePath);
processOperation(resourcePath, "get", path.getGet(), ops);
processOperation(resourcePath, "put", path.getPut(), ops);
processOperation(resourcePath, "post", path.getPost(), ops);
processOperation(resourcePath, "delete", path.getDelete(), ops);
processOperation(resourcePath, "patch", path.getPatch(), ops);
processOperation(resourcePath, "options", path.getOptions(), ops);
processOperation(resourcePath, "get", path.getGet(), ops, path);
processOperation(resourcePath, "put", path.getPut(), ops, path);
processOperation(resourcePath, "post", path.getPost(), ops, path);
processOperation(resourcePath, "delete", path.getDelete(), ops, path);
processOperation(resourcePath, "patch", path.getPatch(), ops, path);
processOperation(resourcePath, "options", path.getOptions(), ops, path);
}
return ops;
}
@ -338,17 +423,43 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
return map.get(name);
}
public void processOperation(String resourcePath, String httpMethod, Operation operation, Map<String, List<CodegenOperation>> operations) {
public void processOperation(String resourcePath, String httpMethod, Operation operation, Map<String, List<CodegenOperation>> operations, Path path) {
if (operation != null) {
if (System.getProperty("debugOperations") != null) {
LOGGER.debug("processOperation: resourcePath= " + resourcePath + "\t;" + httpMethod + " " + operation + "\n");
}
List<String> tags = operation.getTags();
if (tags == null) {
tags = new ArrayList<String>();
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) {
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.add(sanitizeTag(tag));
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();
SecuritySchemeDefinition securityDefinition = fromSecurity(securityName);
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);
}
}
}
if (!authMethods.isEmpty()) {
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) {
// 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> objs = new HashMap<String, Object>();
objs.put("classname", config.toApiName(tag));
objs.put("pathPrefix", config.toApiVarName(tag));
// check for operationId uniqueness
Set<String> opIds = new HashSet<String>();
@ -429,6 +568,12 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
}
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);
if (objs.size() > 0) {
List<CodegenOperation> os = (List<CodegenOperation>) objs.get("operation");
@ -441,14 +586,14 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
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>();
objs.put("package", config.modelPackage());
List<Object> models = new ArrayList<Object>();
Set<String> allImports = new LinkedHashSet<String>();
for (String key : definitions.keySet()) {
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>();
mo.put("model", cm);
mo.put("importPath", config.toModelImport(key));

View File

@ -128,7 +128,7 @@ public class XmlExampleGenerator {
ArrayProperty p = (ArrayProperty) property;
Property inner = p.getItems();
boolean wrapped = false;
if (property.getXml() != null && property.getXml().getWrapped()) {
if (property.getXml() != null && property.getXml().getWrapped() != null && property.getXml().getWrapped()) {
wrapped = true;
}
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.Template;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenProperty;
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")
);
additionalProperties.put("invokerPackage", invokerPackage);
additionalProperties.put("groupId", groupId);
additionalProperties.put("artifactId", artifactId);
additionalProperties.put("artifactVersion", artifactVersion);
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("configKey", configKey);
additionalProperties.put("configKeyPath", configKeyPath);
additionalProperties.put("defaultTimeout", defaultTimeoutInMs);
@ -251,6 +252,11 @@ public class AkkaScalaClientCodegen extends DefaultCodegen implements CodegenCon
@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");
}
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.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile;
@ -13,6 +14,8 @@ import java.io.File;
import java.util.Arrays;
import java.util.HashSet;
import org.apache.commons.lang.StringUtils;
public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String invokerPackage = "io.swagger.client";
protected String groupId = "io.swagger";
@ -56,11 +59,11 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
instantiationTypes.put("array", "ArrayList");
instantiationTypes.put("map", "HashMap");
cliOptions.add(new CliOption("invokerPackage", "root package to use for the generated code"));
cliOptions.add(new CliOption("groupId", "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("artifactVersion", "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.INVOKER_PACKAGE, CodegenConstants.INVOKER_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.GROUP_ID, "groupId 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(CodegenConstants.ARTIFACT_VERSION, "artifact version for use in the generated build.gradle and pom.xml"));
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."));
}
@ -168,6 +171,11 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
@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");
@ -180,36 +188,36 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey("invokerPackage")) {
this.setInvokerPackage((String) additionalProperties.get("invokerPackage"));
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("invokerPackage", invokerPackage);
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
}
if (additionalProperties.containsKey("groupId")) {
this.setGroupId((String) additionalProperties.get("groupId"));
if (additionalProperties.containsKey(CodegenConstants.GROUP_ID)) {
this.setGroupId((String) additionalProperties.get(CodegenConstants.GROUP_ID));
} else {
//not set, use to be passed to template
additionalProperties.put("groupId", groupId);
additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
}
if (additionalProperties.containsKey("artifactId")) {
this.setArtifactId((String) additionalProperties.get("artifactId"));
if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_ID)) {
this.setArtifactId((String) additionalProperties.get(CodegenConstants.ARTIFACT_ID));
} else {
//not set, use to be passed to template
additionalProperties.put("artifactId", artifactId);
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
}
if (additionalProperties.containsKey("artifactVersion")) {
this.setArtifactVersion((String) additionalProperties.get("artifactVersion"));
if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_VERSION)) {
this.setArtifactVersion((String) additionalProperties.get(CodegenConstants.ARTIFACT_VERSION));
} else {
//not set, use to be passed to template
additionalProperties.put("artifactVersion", artifactVersion);
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
}
if (additionalProperties.containsKey("sourceFolder")) {
this.setSourceFolder((String) additionalProperties.get("sourceFolder"));
if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) {
this.setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER));
}
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"));
supportingFiles.add(new SupportingFile("apiException.mustache",
(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() {

View File

@ -1,6 +1,7 @@
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;
@ -21,6 +22,8 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import org.apache.commons.lang.StringUtils;
public class AsyncScalaClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String invokerPackage = "io.swagger.client";
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")
);
additionalProperties.put("invokerPackage", invokerPackage);
additionalProperties.put("groupId", groupId);
additionalProperties.put("artifactId", artifactId);
additionalProperties.put("artifactVersion", artifactVersion);
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("asyncHttpClient", asyncHttpClient);
additionalProperties.put("authScheme", authScheme);
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.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;
import org.apache.commons.lang.StringUtils;
public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String invokerPackage = "IO.Swagger.Client";
protected String groupId = "io.swagger";
protected String artifactId = "swagger-csharp-client";
protected String artifactVersion = "1.0.0";
protected String sourceFolder = "src/main/csharp";
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 + "csharp";
public CSharpClientCodegen() {
super();
outputFolder = "generated-code/csharp";
outputFolder = "generated-code" + File.separator + "csharp";
modelTemplateFiles.put("model.mustache", ".cs");
apiTemplateFiles.put("api.mustache", ".cs");
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")
);
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>(
Arrays.asList(
"String",
"string",
"bool?",
"double?",
@ -64,6 +56,7 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
"Integer",
"Long",
"Float",
"Stream", // not really a primitive, we include it to avoid model import
"Object")
);
instantiationTypes.put("array", "List");
@ -79,12 +72,50 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
typeMapping.put("number", "double?");
typeMapping.put("datetime", "DateTime?");
typeMapping.put("date", "DateTime?");
typeMapping.put("file", "string"); // path to file
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);
}
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() {
@ -106,17 +137,18 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
@Override
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() {
return (outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', '/')).replace('.', File.separatorChar);
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("-", "_");
// sanitize name
name = sanitizeName(name);
// if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$")) {
@ -137,8 +169,24 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
@Override
public String toParamName(String name) {
// should be the same as variable name
return toVarName(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
@ -192,12 +240,17 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
@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(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;
import com.google.common.base.Strings;
import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.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.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(JavaClientCodegen.class);
protected String invokerPackage = "io.swagger.client";
protected String groupId = "io.swagger";
protected String artifactId = "swagger-java-client";
protected String artifactVersion = "1.0.0";
protected String sourceFolder = "src/main/java";
protected String localVariablePrefix = "";
protected Boolean serializableModel = false;
public JavaClientCodegen() {
super();
@ -49,26 +67,37 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
"Integer",
"Long",
"Float",
"Object")
"Object",
"byte[]")
);
instantiationTypes.put("array", "ArrayList");
instantiationTypes.put("map", "HashMap");
cliOptions.add(new CliOption("invokerPackage", "root package for generated code"));
cliOptions.add(new CliOption("groupId", "groupId in generated pom.xml"));
cliOptions.add(new CliOption("artifactId", "artifactId in generated pom.xml"));
cliOptions.add(new CliOption("artifactVersion", "artifact version in generated pom.xml"));
cliOptions.add(new CliOption("sourceFolder", "source folder for generated code"));
cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE, CodegenConstants.INVOKER_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.GROUP_ID, CodegenConstants.GROUP_ID_DESC));
cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_ID, CodegenConstants.ARTIFACT_ID_DESC));
cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_VERSION, CodegenConstants.ARTIFACT_VERSION_DESC));
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() {
return CodegenType.CLIENT;
}
@Override
public String getName() {
return "java";
}
@Override
public String getHelp() {
return "Generates a Java client library.";
}
@ -77,46 +106,74 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey("invokerPackage")) {
this.setInvokerPackage((String) additionalProperties.get("invokerPackage"));
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("invokerPackage", invokerPackage);
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
}
if (additionalProperties.containsKey("groupId")) {
this.setGroupId((String) additionalProperties.get("groupId"));
if (additionalProperties.containsKey(CodegenConstants.GROUP_ID)) {
this.setGroupId((String) additionalProperties.get(CodegenConstants.GROUP_ID));
} else {
//not set, use to be passed to template
additionalProperties.put("groupId", groupId);
additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
}
if (additionalProperties.containsKey("artifactId")) {
this.setArtifactId((String) additionalProperties.get("artifactId"));
if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_ID)) {
this.setArtifactId((String) additionalProperties.get(CodegenConstants.ARTIFACT_ID));
} else {
//not set, use to be passed to template
additionalProperties.put("artifactId", artifactId);
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
}
if (additionalProperties.containsKey("artifactVersion")) {
this.setArtifactVersion((String) additionalProperties.get("artifactVersion"));
if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_VERSION)) {
this.setArtifactVersion((String) additionalProperties.get(CodegenConstants.ARTIFACT_VERSION));
} else {
//not set, use to be passed to template
additionalProperties.put("artifactVersion", artifactVersion);
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
}
if (additionalProperties.containsKey("sourceFolder")) {
this.setSourceFolder((String) additionalProperties.get("sourceFolder"));
if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) {
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);
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("ApiClient.mustache", invokerFolder, "ApiClient.java"));
supportingFiles.add(new SupportingFile("apiException.mustache", invokerFolder, "ApiException.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"));
// 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);
supportingFiles.add(new SupportingFile("auth/Authentication.mustache", authFolder, "Authentication.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"));
}
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
public String escapeReservedWord(String name) {
@ -135,14 +211,19 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar);
}
@Override
public String modelFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar);
}
@Override
public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_");
// sanitize name
name = sanitizeName(name);
if("_".equals(name)) {
name = "_u";
}
// if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$")) {
@ -169,6 +250,8 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String toModelName(String name) {
name = sanitizeName(name);
// model name cannot use reserved keyword, e.g. return
if (reservedWords.contains(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
@ -200,6 +283,18 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
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
public String getSwaggerType(Property p) {
String swaggerType = super.getSwaggerType(p);
@ -207,22 +302,108 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
if (typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType);
if (languageSpecificPrimitives.contains(type)) {
return toModelName(type);
return type;
}
} else {
type = swaggerType;
}
if (null == type) {
LOGGER.error("No Type defined for Property " + p);
}
return toModelName(type);
}
@Override
public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method 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(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) {
@ -244,4 +425,27 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
public void setSourceFolder(String 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;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenResponse;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.SupportingFile;
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.util.ArrayList;
@ -38,10 +37,10 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
apiPackage = System.getProperty("swagger.codegen.jaxrs.apipackage", "io.swagger.api");
modelPackage = System.getProperty("swagger.codegen.jaxrs.modelpackage", "io.swagger.model");
additionalProperties.put("invokerPackage", invokerPackage);
additionalProperties.put("groupId", groupId);
additionalProperties.put("artifactId", artifactId);
additionalProperties.put("artifactVersion", artifactVersion);
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);
@ -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
public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations) {
String basePath = resourcePath;
@ -137,27 +121,35 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
if (operations != null) {
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
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) {
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.returnType = rt.substring("List<".length(), end).trim();
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.returnType = rt.substring("Map<".length(), end).split(",")[1].trim();
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.returnType = rt.substring("Set<".length(), end).trim();
operation.returnContainer = "Set";
}
}
@ -166,6 +158,15 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
return objs;
}
@Override
public String toApiName(String name) {
if (name.length() == 0) {
return "DefaultApi";
}
name = sanitizeName(name);
return camelize(name) + "Api";
}
@Override
public String apiFilename(String templateName, String tag) {
@ -200,7 +201,6 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
}
public boolean shouldOverwrite(String filename) {
return !filename.endsWith("ServiceImpl.java") && !filename.endsWith("ServiceFactory.java");
return super.shouldOverwrite(filename) && !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 java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
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 {
protected String apiVersion = "1.0.0";
@ -197,4 +205,50 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
}
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.Set;
import org.apache.commons.lang.StringUtils;
public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
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 projectName = "swaggerClient";
public ObjcClientCodegen() {
super();
outputFolder = "generated-code" + File.separator + "objc";
modelTemplateFiles.put("model-header.mustache", ".h");
modelTemplateFiles.put("model-body.mustache", ".m");
apiTemplateFiles.put("api-header.mustache", ".h");
apiTemplateFiles.put("api-body.mustache", ".m");
templateDir = "objc";
modelPackage = "";
defaultIncludes = new HashSet<String>(
Arrays.asList(
"bool",
"BOOL",
"int",
"NSString",
"NSObject",
"NSArray",
"NSNumber",
"NSDate",
"NSDictionary",
"NSMutableArray",
"NSMutableDictionary")
);
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"NSNumber",
"NSString",
"NSObject",
"NSDate",
"bool",
"BOOL")
);
defaultIncludes.clear();
defaultIncludes.add("bool");
defaultIncludes.add("BOOL");
defaultIncludes.add("int");
defaultIncludes.add("NSURL");
defaultIncludes.add("NSString");
defaultIncludes.add("NSObject");
defaultIncludes.add("NSArray");
defaultIncludes.add("NSNumber");
defaultIncludes.add("NSDate");
defaultIncludes.add("NSDictionary");
defaultIncludes.add("NSMutableArray");
defaultIncludes.add("NSMutableDictionary");
languageSpecificPrimitives.clear();
languageSpecificPrimitives.add("NSNumber");
languageSpecificPrimitives.add("NSString");
languageSpecificPrimitives.add("NSObject");
languageSpecificPrimitives.add("NSDate");
languageSpecificPrimitives.add("NSURL");
languageSpecificPrimitives.add("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
reservedWords = new HashSet<String>(
@ -70,26 +89,10 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
"double", "protocol", "interface", "implementation",
"NSObject", "NSInteger", "NSNumber", "CGFloat",
"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>();
foundationClasses = new HashSet<String>(
@ -98,15 +101,17 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
"NSObject",
"NSString",
"NSDate",
"NSURL",
"NSDictionary")
);
instantiationTypes.put("array", "NSMutableArray");
instantiationTypes.put("map", "NSMutableDictionary");
cliOptions.add(new CliOption("classPrefix", "prefix for generated classes"));
cliOptions.add(new CliOption("sourceFolder", "source folder for generated code"));
cliOptions.add(new CliOption("projectName", "name of the Xcode project in generated Podfile"));
cliOptions.clear();
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("podName", "cocoapods package name (convention: CameCase), default: `SwaggerClient`"));
cliOptions.add(new CliOption("podVersion", "cocoapods package version, default: `1.0.0`"));
}
public CodegenType getTag() {
@ -125,33 +130,43 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey("sourceFolder")) {
this.setSourceFolder((String) additionalProperties.get("sourceFolder"));
if (additionalProperties.containsKey("podName")) {
setPodName((String) additionalProperties.get("podName"));
}
if (additionalProperties.containsKey("podVersion")) {
setPodVersion((String) additionalProperties.get("podVersion"));
}
if (additionalProperties.containsKey("classPrefix")) {
this.setClassPrefix((String) additionalProperties.get("classPrefix"));
setClassPrefix((String) additionalProperties.get("classPrefix"));
}
if (additionalProperties.containsKey("projectName")) {
this.setProjectName((String) additionalProperties.get("projectName"));
} else {
additionalProperties.put("projectName", projectName);
}
additionalProperties.put("podName", podName);
additionalProperties.put("podVersion", podVersion);
additionalProperties.put("classPrefix", classPrefix);
supportingFiles.add(new SupportingFile("SWGObject.h", sourceFolder, "SWGObject.h"));
supportingFiles.add(new SupportingFile("SWGObject.m", sourceFolder, "SWGObject.m"));
supportingFiles.add(new SupportingFile("SWGQueryParamCollection.h", sourceFolder, "SWGQueryParamCollection.h"));
supportingFiles.add(new SupportingFile("SWGQueryParamCollection.m", sourceFolder, "SWGQueryParamCollection.m"));
supportingFiles.add(new SupportingFile("SWGApiClient.h", sourceFolder, "SWGApiClient.h"));
supportingFiles.add(new SupportingFile("SWGApiClient.m", sourceFolder, "SWGApiClient.m"));
supportingFiles.add(new SupportingFile("SWGFile.h", sourceFolder, "SWGFile.h"));
supportingFiles.add(new SupportingFile("SWGFile.m", sourceFolder, "SWGFile.m"));
supportingFiles.add(new SupportingFile("JSONValueTransformer+ISO8601.m", sourceFolder, "JSONValueTransformer+ISO8601.m"));
supportingFiles.add(new SupportingFile("JSONValueTransformer+ISO8601.h", sourceFolder, "JSONValueTransformer+ISO8601.h"));
supportingFiles.add(new SupportingFile("SWGConfiguration-body.mustache", sourceFolder, "SWGConfiguration.m"));
supportingFiles.add(new SupportingFile("SWGConfiguration-header.mustache", sourceFolder, "SWGConfiguration.h"));
supportingFiles.add(new SupportingFile("Podfile.mustache", "", "Podfile"));
String swaggerFolder = podName;
modelPackage = swaggerFolder;
apiPackage = swaggerFolder;
supportingFiles.add(new SupportingFile("Object-header.mustache", swaggerFolder, classPrefix + "Object.h"));
supportingFiles.add(new SupportingFile("Object-body.mustache", swaggerFolder, classPrefix + "Object.m"));
supportingFiles.add(new SupportingFile("QueryParamCollection-header.mustache", swaggerFolder, classPrefix + "QueryParamCollection.h"));
supportingFiles.add(new SupportingFile("QueryParamCollection-body.mustache", swaggerFolder, classPrefix + "QueryParamCollection.m"));
supportingFiles.add(new SupportingFile("ApiClient-header.mustache", swaggerFolder, classPrefix + "ApiClient.h"));
supportingFiles.add(new SupportingFile("ApiClient-body.mustache", swaggerFolder, classPrefix + "ApiClient.m"));
supportingFiles.add(new SupportingFile("JSONResponseSerializer-header.mustache", swaggerFolder, classPrefix + "JSONResponseSerializer.h"));
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
@ -200,21 +215,32 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
Property inner = ap.getItems();
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);
if (innerTypeDeclaration.endsWith("*")) {
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 + ">*";
}
} 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 {
String swaggerType = getSwaggerType(p);
@ -273,11 +299,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String toModelImport(String name) {
if ("".equals(modelPackage())) {
return name;
} else {
return modelPackage() + "." + name;
}
}
@Override
@ -287,12 +309,12 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String apiFileFolder() {
return outputFolder + File.separator + sourceFolder;
return outputFolder + File.separatorChar + apiPackage();
}
@Override
public String modelFileFolder() {
return outputFolder + File.separator + sourceFolder;
return outputFolder + File.separatorChar + modelPackage();
}
@Override
@ -306,9 +328,8 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String toVarName(String name) {
// replace non-word characters to `_`
// e.g. `created-at` to `created_at`
name = name.replaceAll("[^a-zA-Z0-9_]", "_");
// sanitize name
name = sanitizeName(name);
// if it's all upper case, do noting
if (name.matches("^[A-Z_]$")) {
@ -339,23 +360,28 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
@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(operationId, true);
}
public void setSourceFolder(String sourceFolder) {
this.sourceFolder = sourceFolder;
return camelize(sanitizeName(operationId), true);
}
public void setClassPrefix(String classPrefix) {
this.classPrefix = classPrefix;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
public void setPodName(String podName) {
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.MapProperty;
import io.swagger.models.properties.Property;
import io.swagger.codegen.CliOption;
import java.io.File;
import java.util.Arrays;
import java.util.HashSet;
import org.apache.commons.lang.StringUtils;
public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String invokerPackage = "SwaggerClient";
protected String groupId = "io.swagger";
protected String artifactId = "swagger-client";
protected String artifactVersion = "1.0.0";
protected String moduleName = "SwaggerClient";
protected String moduleVersion = "1.0.0";
public PerlClientCodegen() {
super();
@ -26,8 +27,6 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
apiTemplateFiles.put("api.mustache", ".pm");
templateDir = "perl";
typeMapping.clear();
languageSpecificPrimitives.clear();
reservedWords = new HashSet<String>(
Arrays.asList(
@ -44,11 +43,7 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
)
);
additionalProperties.put("invokerPackage", invokerPackage);
additionalProperties.put("groupId", groupId);
additionalProperties.put("artifactId", artifactId);
additionalProperties.put("artifactVersion", artifactVersion);
languageSpecificPrimitives.clear();
languageSpecificPrimitives.add("int");
languageSpecificPrimitives.add("double");
languageSpecificPrimitives.add("string");
@ -58,6 +53,7 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
languageSpecificPrimitives.add("HASH");
languageSpecificPrimitives.add("object");
typeMapping.clear();
typeMapping.put("integer", "int");
typeMapping.put("long", "int");
typeMapping.put("float", "double");
@ -71,9 +67,31 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("map", "HASH");
typeMapping.put("object", "object");
supportingFiles.add(new SupportingFile("ApiClient.mustache", ("lib/WWW/" + invokerPackage).replace('/', File.separatorChar), "ApiClient.pm"));
supportingFiles.add(new SupportingFile("Configuration.mustache", ("lib/WWW/" + invokerPackage).replace('/', File.separatorChar), "Configuration.pm"));
supportingFiles.add(new SupportingFile("BaseObject.mustache", ("lib/WWW/" + invokerPackage).replace('/', File.separatorChar), "Object/BaseObject.pm"));
cliOptions.clear();
cliOptions.add(new CliOption("moduleName", "perl module name (convention: CamelCase), default: SwaggerClient"));
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() {
@ -95,11 +113,11 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String apiFileFolder() {
return (outputFolder + "/lib/WWW/" + invokerPackage + apiPackage()).replace('/', File.separatorChar);
return (outputFolder + "/lib/WWW/" + moduleName + apiPackage()).replace('/', File.separatorChar);
}
public String modelFileFolder() {
return (outputFolder + "/lib/WWW/" + invokerPackage + modelPackage()).replace('/', File.separatorChar);
return (outputFolder + "/lib/WWW/" + moduleName + modelPackage()).replace('/', File.separatorChar);
}
@Override
@ -141,15 +159,17 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
@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("^[0-9]")) {
if (name.matches("^\\d.*")) {
name = "_" + name;
}
// return the name in underscore style
// PhoneNumber => phone_number
return underscore(name);
return name;
}
@Override
@ -196,6 +216,11 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
@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");

View File

@ -1,51 +1,51 @@
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.MapProperty;
import io.swagger.models.properties.Property;
import io.swagger.models.properties.RefProperty;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import org.apache.commons.lang3.StringUtils;
public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String invokerPackage = "io.swagger.client";
protected String groupId = "io.swagger";
protected String artifactId = "swagger-client";
protected String invokerPackage = "Swagger\\Client";
protected String composerVendorName = "swagger";
protected String composerProjectName = "swagger-client";
protected String packagePath = "SwaggerClient-php";
protected String artifactVersion = "1.0.0";
protected String srcBasePath = "lib";
protected String variableNamingConvention= "snake_case";
public PhpClientCodegen() {
super();
invokerPackage = camelize("SwaggerClient");
String packagePath = invokerPackage + "-php";
modelPackage = packagePath + "/lib/models";
apiPackage = packagePath + "/lib";
outputFolder = "generated-code/php";
outputFolder = "generated-code" + File.separator + "php";
modelTemplateFiles.put("model.mustache", ".php");
apiTemplateFiles.put("api.mustache", ".php");
templateDir = "php";
apiPackage = invokerPackage + "\\Api";
modelPackage = invokerPackage + "\\Model";
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("invokerPackage", invokerPackage);
additionalProperties.put("groupId", groupId);
additionalProperties.put("artifactId", artifactId);
additionalProperties.put("artifactVersion", artifactVersion);
// ref: http://php.net/manual/en/language.types.intro.php
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"bool",
"boolean",
"int",
"integer",
@ -55,12 +55,19 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
"object",
"DateTime",
"mixed",
"number")
"number",
"void",
"byte")
);
instantiationTypes.put("array", "array");
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
typeMapping = new HashMap<String, String>();
typeMapping.put("integer", "int");
@ -69,20 +76,56 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
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("boolean", "bool");
typeMapping.put("date", "\\DateTime");
typeMapping.put("datetime", "\\DateTime");
typeMapping.put("file", "\\SplFileObject");
typeMapping.put("map", "map");
typeMapping.put("array", "array");
typeMapping.put("list", "array");
typeMapping.put("object", "object");
typeMapping.put("DateTime", "\\DateTime");
supportingFiles.add(new SupportingFile("composer.mustache", packagePath.replace('/', File.separatorChar), "composer.json"));
supportingFiles.add(new SupportingFile("configuration.mustache", (packagePath + "/lib").replace('/', File.separatorChar), "Configuration.php"));
supportingFiles.add(new SupportingFile("ApiClient.mustache", (packagePath + "/lib").replace('/', File.separatorChar), "ApiClient.php"));
supportingFiles.add(new SupportingFile("ApiException.mustache", (packagePath + "/lib").replace('/', File.separatorChar), "ApiException.php"));
supportingFiles.add(new SupportingFile("require.mustache", packagePath.replace('/', File.separatorChar), invokerPackage + ".php"));
cliOptions.add(new CliOption("variableNamingConvention", "naming convention of variable name, e.g. camelCase. Default: snake_case"));
cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE, "The main namespace to use for all classes. e.g. Yay\\Pets"));
cliOptions.add(new CliOption("packagePath", "The main package name for classes. e.g. GeneratedPetstore"));
cliOptions.add(new CliOption("srcBasePath", "The directory under packagePath to serve as source root."));
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() {
@ -97,6 +140,68 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
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
public String escapeReservedWord(String name) {
return "_" + name;
@ -104,11 +209,11 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String apiFileFolder() {
return (outputFolder + "/" + apiPackage()).replace('/', File.separatorChar);
return (outputFolder + "/" + toPackagePath(apiPackage(), srcBasePath));
}
public String modelFileFolder() {
return (outputFolder + "/" + modelPackage()).replace('/', File.separatorChar);
return (outputFolder + "/" + toPackagePath(modelPackage(), srcBasePath));
}
@Override
@ -116,15 +221,27 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems();
return getSwaggerType(p) + "[" + getTypeDeclaration(inner) + "]";
return getTypeDeclaration(inner) + "[]";
} else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();
return getSwaggerType(p) + "[string," + getTypeDeclaration(inner) + "]";
} else if (p instanceof RefProperty) {
String type = super.getTypeDeclaration(p);
return (!languageSpecificPrimitives.contains(type))
? "\\" + modelPackage + "\\" + type : type;
}
return super.getTypeDeclaration(p);
}
@Override
public String getTypeDeclaration(String name) {
if (!languageSpecificPrimitives.contains(name)) {
return "\\" + modelPackage + "\\" + name;
}
return super.getTypeDeclaration(name);
}
@Override
public String getSwaggerType(Property p) {
String swaggerType = super.getSwaggerType(p);
@ -149,18 +266,60 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
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
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
// need to escape it by appending _ at the beginning
if (name.matches("^[0-9]")) {
if (name.matches("^\\d.*")) {
name = "_" + name;
}
// return the name in underscore style
// PhoneNumber => phone_number
return underscore(name);
return name;
}
@Override
@ -187,4 +346,19 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
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.HashSet;
import org.apache.commons.lang.StringUtils;
public class Python3ClientCodegen extends DefaultCodegen implements CodegenConfig {
String module = "client";
@ -33,6 +35,7 @@ public class Python3ClientCodegen extends DefaultCodegen implements CodegenConfi
languageSpecificPrimitives.add("bool");
languageSpecificPrimitives.add("str");
languageSpecificPrimitives.add("datetime");
languageSpecificPrimitives.add("date");
typeMapping.clear();
typeMapping.put("integer", "int");
@ -43,7 +46,8 @@ public class Python3ClientCodegen extends DefaultCodegen implements CodegenConfi
typeMapping.put("map", "map");
typeMapping.put("boolean", "bool");
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
reservedWords = new HashSet<String>(
@ -199,6 +203,11 @@ public class Python3ClientCodegen extends DefaultCodegen implements CodegenConfi
@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");

View File

@ -1,5 +1,6 @@
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;
@ -12,26 +13,22 @@ import java.io.File;
import java.util.Arrays;
import java.util.HashSet;
import org.apache.commons.lang.StringUtils;
public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String module = "SwaggerPetstore";
protected String invokerPackage;
protected String eggPackage;
protected String packageName = null;
protected String packageVersion = null;
public PythonClientCodegen() {
super();
eggPackage = module + "-python";
invokerPackage = eggPackage + File.separatorChar + module;
modelPackage = "models";
apiPackage = "api";
outputFolder = "generated-code" + File.separatorChar + "python";
modelTemplateFiles.put("model.mustache", ".py");
apiTemplateFiles.put("api.mustache", ".py");
templateDir = "python";
apiPackage = invokerPackage + File.separatorChar + "apis";
modelPackage = invokerPackage + File.separatorChar + "models";
languageSpecificPrimitives.clear();
languageSpecificPrimitives.add("int");
languageSpecificPrimitives.add("float");
@ -39,6 +36,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
languageSpecificPrimitives.add("bool");
languageSpecificPrimitives.add("str");
languageSpecificPrimitives.add("datetime");
languageSpecificPrimitives.add("date");
typeMapping.clear();
typeMapping.put("integer", "int");
@ -46,10 +44,13 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
typeMapping.put("long", "int");
typeMapping.put("double", "float");
typeMapping.put("array", "list");
typeMapping.put("map", "map");
typeMapping.put("map", "dict");
typeMapping.put("boolean", "bool");
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
reservedWords = new HashSet<String>(
@ -59,14 +60,43 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
"print", "class", "exec", "in", "raise", "continue", "finally", "is",
"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"));
supportingFiles.add(new SupportingFile("setup.mustache", eggPackage, "setup.py"));
supportingFiles.add(new SupportingFile("api_client.mustache", invokerPackage, "api_client.py"));
supportingFiles.add(new SupportingFile("rest.mustache", invokerPackage, "rest.py"));
supportingFiles.add(new SupportingFile("configuration.mustache", invokerPackage, "configuration.py"));
supportingFiles.add(new SupportingFile("__init__package.mustache", invokerPackage, "__init__.py"));
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey("packageName")) {
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__api.mustache", apiPackage, "__init__.py"));
}
@ -111,7 +141,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();
return getSwaggerType(p) + "(String, " + getTypeDeclaration(inner) + ")";
return getSwaggerType(p) + "(str, " + getTypeDeclaration(inner) + ")";
}
return super.getTypeDeclaration(p);
}
@ -132,14 +162,13 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
}
public String toDefaultValue(Property p) {
// TODO: Support Python def value
return "null";
return "None";
}
@Override
public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_");
// sanitize name
name = sanitizeName(name);
// if it's all uppper case, convert to lower case
if (name.matches("^[A-Z_]*$")) {
@ -148,7 +177,10 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
// underscore the variable name
// 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 _
if (reservedWords.contains(name) || name.matches("^\\d.*")) {
@ -216,12 +248,36 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
@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);
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;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
@ -15,6 +16,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
public class RetrofitClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String invokerPackage = "io.swagger.client";
protected String groupId = "io.swagger";
@ -42,10 +45,10 @@ public class RetrofitClientCodegen extends DefaultCodegen implements CodegenConf
"native", "super", "while")
);
additionalProperties.put("invokerPackage", invokerPackage);
additionalProperties.put("groupId", groupId);
additionalProperties.put("artifactId", artifactId);
additionalProperties.put("artifactVersion", artifactVersion);
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("service.mustache",
@ -171,6 +174,11 @@ public class RetrofitClientCodegen extends DefaultCodegen implements CodegenConf
@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");

View File

@ -1,5 +1,6 @@
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;
@ -12,17 +13,19 @@ import java.io.File;
import java.util.Arrays;
import java.util.HashSet;
import org.apache.commons.lang.StringUtils;
public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String gemName = "swagger_client";
protected String gemName = null;
protected String moduleName = null;
protected String gemVersion = "1.0.0";
protected String libFolder = "lib";
public RubyClientCodegen() {
super();
moduleName = generateModuleName();
modelPackage = gemName + "/models";
apiPackage = gemName + "/api";
outputFolder = "generated-code" + File.separatorChar + "ruby";
modelPackage = "models";
apiPackage = "api";
outputFolder = "generated-code" + File.separator + "ruby";
modelTemplateFiles.put("model.mustache", ".rb");
apiTemplateFiles.put("api.mustache", ".rb");
templateDir = "ruby";
@ -39,33 +42,82 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
"if", "not", "return", "undef", "yield")
);
additionalProperties.put("gemName", gemName);
additionalProperties.put("moduleName", moduleName);
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");
typeMapping.put("string", "String");
typeMapping.put("char", "String");
typeMapping.put("int", "Integer");
typeMapping.put("integer", "Integer");
typeMapping.put("long", "Integer");
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.mustache", "lib", gemName + ".rb"));
supportingFiles.add(new SupportingFile("monkey.mustache", baseFolder, "monkey.rb"));
supportingFiles.add(new SupportingFile("swagger_client.mustache", libFolder, gemName + ".rb"));
String baseFolder = libFolder + File.separator + gemName;
supportingFiles.add(new SupportingFile("swagger.mustache", baseFolder, "swagger.rb"));
supportingFiles.add(new SupportingFile("swagger" + File.separatorChar + "request.mustache", swaggerFolder, "request.rb"));
supportingFiles.add(new SupportingFile("swagger" + File.separatorChar + "response.mustache", swaggerFolder, "response.rb"));
supportingFiles.add(new SupportingFile("swagger" + File.separatorChar + "version.mustache", swaggerFolder, "version.rb"));
supportingFiles.add(new SupportingFile("swagger" + File.separatorChar + "configuration.mustache", swaggerFolder, "configuration.rb"));
String swaggerFolder = baseFolder + File.separator + "swagger";
supportingFiles.add(new SupportingFile("swagger" + File.separator + "request.mustache", swaggerFolder, "request.rb"));
supportingFiles.add(new SupportingFile("swagger" + File.separator + "response.mustache", swaggerFolder, "response.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"));
}
@ -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".
*/
public String generateModuleName() {
public String generateModuleName(String gemName) {
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
public String escapeReservedWord(String name) {
return "_" + name;
@ -95,11 +154,11 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
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() {
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
@ -107,11 +166,11 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems();
return getSwaggerType(p) + "[" + getTypeDeclaration(inner) + "]";
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 getSwaggerType(p) + "<String, " + getTypeDeclaration(inner) + ">";
}
return super.getTypeDeclaration(p);
}
@ -140,8 +199,8 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_");
// sanitize name
name = sanitizeName(name);
// if it's all uppper case, convert to lower case
if (name.matches("^[A-Z_]*$")) {
@ -210,22 +269,38 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
@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);
return underscore(sanitizeName(operationId));
}
@Override
public String toModelImport(String name) {
return modelPackage() + "/" + toModelFilename(name);
return gemName + "/" + modelPackage() + "/" + toModelFilename(name);
}
@Override
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;
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;
@ -20,6 +21,11 @@ import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig {
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")
);
additionalProperties.put("invokerPackage", invokerPackage);
additionalProperties.put("groupId", groupId);
additionalProperties.put("artifactId", artifactId);
additionalProperties.put("artifactVersion", artifactVersion);
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("asyncHttpClient", asyncHttpClient);
additionalProperties.put("authScheme", authScheme);
additionalProperties.put("authPreemptive", authPreemptive);
@ -206,6 +212,11 @@ public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig
@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");
@ -214,4 +225,17 @@ public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig
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;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
@ -73,10 +74,10 @@ public class ScalatraServerCodegen extends DefaultCodegen implements CodegenConf
additionalProperties.put("infoEmail", "apiteam@swagger.io");
additionalProperties.put("licenseInfo", "All rights reserved");
additionalProperties.put("licenseUrl", "http://apache.org/licenses/LICENSE-2.0.html");
additionalProperties.put("invokerPackage", invokerPackage);
additionalProperties.put("groupId", groupId);
additionalProperties.put("artifactId", artifactId);
additionalProperties.put("artifactVersion", artifactVersion);
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
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;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.SupportingFile;
import io.swagger.codegen.*;
import io.swagger.models.Operation;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty;
@ -27,7 +24,7 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen
protected String configPackage = "";
public SpringMVCServerCodegen() {
super.processOpts();
super();
outputFolder = "generated-code/javaSpringMVC";
modelTemplateFiles.put("model.mustache", ".java");
apiTemplateFiles.put("api.mustache", ".java");
@ -37,12 +34,12 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen
configPackage = "io.swagger.configuration";
additionalProperties.put("invokerPackage", invokerPackage);
additionalProperties.put("groupId", groupId);
additionalProperties.put("artifactId", artifactId);
additionalProperties.put("artifactVersion", artifactVersion);
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);
additionalProperties.put("apiPackage", apiPackage);
additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage);
additionalProperties.put("configPackage", configPackage);
languageSpecificPrimitives = new HashSet<String>(
@ -55,6 +52,9 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen
"Long",
"Float")
);
cliOptions.add(new CliOption("configPackage", "configuration package for generated code"));
}
public CodegenType getTag() {
@ -73,6 +73,10 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey("configPackage")) {
this.setConfigPackage((String) additionalProperties.get("configPackage"));
}
supportingFiles.clear();
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
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
public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations) {
String basePath = resourcePath;
@ -146,27 +135,38 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen
if (operations != null) {
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
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) {
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.returnType = rt.substring("List<".length(), end).trim();
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.returnType = rt.substring("Map<".length(), end).split(",")[1].trim();
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.returnType = rt.substring("Set<".length(), end).trim();
operation.returnContainer = "Set";
}
}
@ -174,5 +174,18 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen
}
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;
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;
@ -21,10 +22,10 @@ public class StaticDocCodegen extends DefaultCodegen implements CodegenConfig {
apiTemplateFiles.put("operation.mustache", ".html");
templateDir = "swagger-static";
additionalProperties.put("invokerPackage", invokerPackage);
additionalProperties.put("groupId", groupId);
additionalProperties.put("artifactId", artifactId);
additionalProperties.put("artifactVersion", artifactVersion);
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
supportingFiles.add(new SupportingFile("package.mustache", "", "package.json"));
supportingFiles.add(new SupportingFile("main.mustache", "", "main.js"));

View File

@ -1,6 +1,7 @@
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.DefaultCodegen;
@ -37,10 +38,10 @@ public class StaticHtmlGenerator extends DefaultCodegen implements CodegenConfig
additionalProperties.put("infoEmail", "hello@helloreverb.com");
additionalProperties.put("licenseInfo", "All rights reserved");
additionalProperties.put("licenseUrl", "http://apache.org/licenses/LICENSE-2.0.html");
additionalProperties.put("invokerPackage", invokerPackage);
additionalProperties.put("groupId", groupId);
additionalProperties.put("artifactId", artifactId);
additionalProperties.put("artifactVersion", artifactVersion);
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
supportingFiles.add(new SupportingFile("index.mustache", "", "index.html"));
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.Set;
import org.apache.commons.lang.StringUtils;
public class TizenClientCodegen extends DefaultCodegen implements CodegenConfig {
protected static String PREFIX = "Sami";
protected Set<String> foundationClasses = new HashSet<String>();
@ -265,6 +267,11 @@ public class TizenClientCodegen extends DefaultCodegen implements CodegenConfig
@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");

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}};
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.ClientResponse;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.client.filter.LoggingFilter;
import com.sun.jersey.api.client.WebResource.Builder;
import com.sun.jersey.multipart.FormDataMultiPart;
import com.sun.jersey.multipart.file.FileDataBodyPart;
import javax.ws.rs.core.Response.Status.Family;
import javax.ws.rs.core.MediaType;
@ -22,13 +19,16 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Date;
import java.util.TimeZone;
import java.net.URLEncoder;
import java.io.IOException;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.io.DataInputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
@ -39,14 +39,19 @@ import {{invokerPackage}}.auth.HttpBasicAuth;
import {{invokerPackage}}.auth.ApiKeyAuth;
import {{invokerPackage}}.auth.OAuth;
{{>generatedAnnotation}}
public class ApiClient {
private Map<String, Client> hostMap = new HashMap<String, Client>();
private Map<String, String> defaultHeaderMap = new HashMap<String, String>();
private boolean debugging = false;
private String basePath = "{{basePath}}";
private JSON json = new JSON();
private Map<String, Authentication> authentications;
private int statusCode;
private Map<String, List<String>> responseHeaders;
private DateFormat dateFormat;
public ApiClient() {
@ -78,6 +83,20 @@ public class ApiClient {
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).
*/
@ -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:
* if JSON exists in the given array, use it;
@ -280,84 +355,65 @@ public class ApiClient {
}
/**
* Deserialize the given JSON string to Java object.
*
* @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
* Serialize the given Java object into string according the given
* Content-Type (only JSON is supported for now).
*/
public Object deserialize(String json, String containerType, Class cls) throws ApiException {
if(null != containerType) {
containerType = containerType.toLowerCase();
}
try{
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);
public String serialize(Object obj, String contentType) throws ApiException {
if (contentType.startsWith("application/json")) {
return json.serialize(obj);
} else {
throw new ApiException(400, "can not serialize object into Content-Type: " + contentType);
}
}
/**
* 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 {
try {
if (obj != null)
return JsonUtil.getJsonMapper().writeValueAsString(obj);
public <T> T deserialize(ClientResponse response, TypeRef returnType) throws ApiException {
String contentType = null;
List<String> contentTypes = response.getHeaders().get("Content-Type");
if (contentTypes != null && !contentTypes.isEmpty())
contentType = contentTypes.get(0);
if (contentType == null)
throw new ApiException(500, "missing Content-Type in response");
String body;
if (response.hasEntity())
body = (String) response.getEntity(String.class);
else
return null;
}
catch (Exception e) {
throw new ApiException(500, e.getMessage());
body = "";
if (contentType.startsWith("application/json")) {
return json.deserialize(body, returnType);
} else {
throw new ApiException(500, "can not deserialize Content-Type: " + contentType);
}
}
/**
* 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
* @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 {
private ClientResponse getAPIResponse(String path, String method, List<Pair> queryParams, Object body, byte[] binaryBody, Map<String, String> headerParams, Map<String, Object> formParams, String accept, String contentType, String[] authNames) throws ApiException {
if (body != null && binaryBody != null){
throw new ApiException(500, "either body or binaryBody must be null");
}
updateParamsForAuth(authNames, queryParams, headerParams);
Client client = getClient();
StringBuilder b = new StringBuilder();
for(String key : queryParams.keySet()) {
String value = queryParams.get(key);
if (value != null){
if(b.toString().length() == 0)
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(escapeString(key)).append("=").append(escapeString(value));
}
}
String querystring = b.toString();
}
String querystring = b.substring(0, b.length() - 1);
Builder builder;
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;
if ("GET".equals(method)) {
response = (ClientResponse) builder.get(ClientResponse.class);
}
else if ("POST".equals(method)) {
if (contentType.startsWith("application/x-www-form-urlencoded")) {
String encodedFormParams = this
.getXWWWFormUrlencodedParams(formParams);
response = builder.type(contentType).post(ClientResponse.class,
encodedFormParams);
} else if ("POST".equals(method)) {
if (encodedFormParams != null) {
response = builder.type(contentType).post(ClientResponse.class, encodedFormParams);
} else if (body == null) {
if(binaryBody == null)
response = builder.post(ClientResponse.class, null);
else
response = builder.type(contentType).post(ClientResponse.class, binaryBody);
} else if (body instanceof FormDataMultiPart) {
response = builder.type(contentType).post(ClientResponse.class, body);
} else {
response = builder.type(contentType).post(ClientResponse.class, serialize(body, contentType));
}
} else if ("PUT".equals(method)) {
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
response = builder.type(contentType).post(ClientResponse.class, serialize(body));
}
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));
response = builder.type(contentType).put(ClientResponse.class, binaryBody);
} 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)) {
if ("application/x-www-form-urlencoded".equals(contentType)) {
String encodedFormParams = this
.getXWWWFormUrlencodedParams(formParams);
response = builder.type(contentType).delete(ClientResponse.class,
encodedFormParams);
} else if ("DELETE".equals(method)) {
if (encodedFormParams != null) {
response = builder.type(contentType).delete(ClientResponse.class, encodedFormParams);
} else if(body == null) {
if(binaryBody == null)
response = builder.delete(ClientResponse.class);
else
response = builder.type(contentType).delete(ClientResponse.class, binaryBody);
} else {
response = builder.type(contentType).delete(ClientResponse.class, serialize(body));
response = builder.type(contentType).delete(ClientResponse.class, serialize(body, contentType));
}
}
else {
} else {
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;
}
else if(response.getClientResponseStatus().getFamily() == Family.SUCCESSFUL) {
if(response.hasEntity()) {
return (String) response.getEntity(String.class);
}
else {
return "";
}
}
else {
} else if (response.getStatusInfo().getFamily() == Family.SUCCESSFUL) {
if (returnType == null)
return null;
else
return deserialize(response, returnType);
} else {
String message = "error";
String respBody = null;
if (response.hasEntity()) {
try {
respBody = String.valueOf(response.getEntity(String.class));
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) {
// e.printStackTrace();
}
}
throw new ApiException(
response.getClientResponseStatus().getStatusCode(),
message,
response.getHeaders(),
respBody);
response.getStatusInfo().getStatusCode(),
message);
}
}
@ -457,7 +597,7 @@ public class ApiClient {
*
* @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) {
Authentication auth = authentications.get(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.
*/
private String getXWWWFormUrlencodedParams(Map<String, String> formParams) {
private String getXWWWFormUrlencodedParams(Map<String, Object> formParams) {
StringBuilder formParamBuilder = new StringBuilder();
for (Entry<String, String> param : formParams.entrySet()) {
String keyStr = parameterToString(param.getKey());
for (Entry<String, Object> param : formParams.entrySet()) {
String keyStr = param.getKey();
String valueStr = parameterToString(param.getValue());
try {
formParamBuilder.append(URLEncoder.encode(keyStr, "utf8"))
formParamBuilder.append(URLEncoder.encode(param.getKey(), "utf8"))
.append("=")
.append(URLEncoder.encode(valueStr, "utf8"));
formParamBuilder.append("&");
@ -484,11 +623,12 @@ public class ApiClient {
// move on to next
}
}
String encodedFormParams = formParamBuilder.toString();
if (encodedFormParams.endsWith("&")) {
encodedFormParams = encodedFormParams.substring(0,
encodedFormParams.length() - 1);
encodedFormParams = encodedFormParams.substring(0, encodedFormParams.length() - 1);
}
return encodedFormParams;
}

View File

@ -1,5 +1,6 @@
package {{invokerPackage}};
{{>generatedAnnotation}}
public class Configuration {
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}};
{{>generatedAnnotation}}
public class StringUtil {
/**
* Check if the given array contains the given value (with case-insensitive comparison).
@ -38,4 +39,13 @@ public class StringUtil {
}
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}}.ApiClient;
import {{invokerPackage}}.Configuration;
import {{invokerPackage}}.Pair;
import {{invokerPackage}}.TypeRef;
import {{modelPackage}}.*;
@ -11,33 +13,29 @@ import java.util.*;
{{#imports}}import {{import}};
{{/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.util.Map;
import java.util.HashMap;
{{>generatedAnnotation}}
{{#operations}}
public class {{classname}} {
private ApiClient apiClient;
private ApiClient {{localVariablePrefix}}apiClient;
public {{classname}}() {
this(Configuration.getDefaultApiClient());
}
public {{classname}}(ApiClient apiClient) {
this.apiClient = apiClient;
this.{{localVariablePrefix}}apiClient = apiClient;
}
public ApiClient getApiClient() {
return apiClient;
return {{localVariablePrefix}}apiClient;
}
public void setApiClient(ApiClient apiClient) {
this.apiClient = apiClient;
this.{{localVariablePrefix}}apiClient = apiClient;
}
{{#operation}}
@ -48,77 +46,63 @@ public class {{classname}} {
{{/allParams}} * @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}
*/
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}}
// verify the required parameter '{{paramName}}' is set
if ({{paramName}} == null) {
throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{nickname}}");
}
{{/required}}{{/allParams}}
// create path and map variables
String path = "{{path}}".replaceAll("\\{format\\}","json"){{#pathParams}}
.replaceAll("\\{" + "{{paramName}}" + "\\}", apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}};
String {{localVariablePrefix}}path = "{{{path}}}".replaceAll("\\{format\\}","json"){{#pathParams}}
.replaceAll("\\{" + "{{baseName}}" + "\\}", {{localVariablePrefix}}apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}};
// query params
Map<String, String> queryParams = new HashMap<String, String>();
Map<String, String> headerParams = new HashMap<String, String>();
Map<String, String> formParams = new HashMap<String, String>();
List<Pair> {{localVariablePrefix}}queryParams = new ArrayList<Pair>();
Map<String, String> {{localVariablePrefix}}headerParams = new HashMap<String, String>();
Map<String, Object> {{localVariablePrefix}}formParams = new HashMap<String, Object>();
{{#queryParams}}if ({{paramName}} != null)
queryParams.put("{{baseName}}", apiClient.parameterToString({{paramName}}));
{{#queryParams}}
{{localVariablePrefix}}queryParams.addAll({{localVariablePrefix}}apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}}));
{{/queryParams}}
{{#headerParams}}if ({{paramName}} != null)
headerParams.put("{{baseName}}", apiClient.parameterToString({{paramName}}));
{{localVariablePrefix}}headerParams.put("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}}));
{{/headerParams}}
final String[] accepts = {
{{#formParams}}if ({{paramName}} != null)
{{localVariablePrefix}}formParams.put("{{baseName}}", {{paramName}});
{{/formParams}}
final String[] {{localVariablePrefix}}accepts = {
{{#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}}
};
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}}
}

View File

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

View File

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

View File

@ -1,8 +1,12 @@
package {{invokerPackage}}.auth;
import java.util.Map;
import {{invokerPackage}}.Pair;
import java.util.Map;
import java.util.List;
{{>generatedAnnotation}}
public interface Authentication {
/** 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;
import {{invokerPackage}}.Pair;
import java.util.Map;
import java.util.List;
import java.io.UnsupportedEncodingException;
import javax.xml.bind.DatatypeConverter;
{{>generatedAnnotation}}
public class HttpBasicAuth implements Authentication {
private String username;
private String password;
@ -26,7 +30,7 @@ public class HttpBasicAuth implements Authentication {
}
@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);
try {
headerParams.put("Authorization", "Basic " + DatatypeConverter.printBase64Binary(str.getBytes("UTF-8")));

View File

@ -1,10 +1,14 @@
package {{invokerPackage}}.auth;
import java.util.Map;
import {{invokerPackage}}.Pair;
import java.util.Map;
import java.util.List;
{{>generatedAnnotation}}
public class OAuth implements Authentication {
@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
}
}

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