Merge branch 'masterswaggerio' into params_support_2.0_spec

Conflicts:
	.gitignore
This commit is contained in:
Andras Gaal 2015-11-19 15:09:08 +01:00
commit 2c52cc1d86
442 changed files with 18483 additions and 6499 deletions

7
.gitignore vendored
View File

@ -55,4 +55,9 @@ samples/client/petstore/python/.projectile
samples/client/petstore/python/.venv/
*/.settings
modules/*/.settings/
*.mustache~
*.java~
*.pm~
*.xml~
*.t~

141
README.md
View File

@ -6,7 +6,7 @@
## Overview
This is the swagger codegen project, which allows generation of client libraries automatically from a Swagger-compliant server.
Check out [Swagger-Spec](https://github.com/swagger-api/swagger-spec) for additional information about the Swagger project, including additional libraries with support for other languages and more.
Check out [Swagger-Spec](https://github.com/swagger-api/swagger-spec) for additional information about the Swagger project, including additional libraries with support for other languages and more.
# Table of contents
@ -14,50 +14,37 @@ Check out [Swagger-Spec](https://github.com/swagger-api/swagger-spec) for additi
- [Overview](#overview)
- [Table of Contents](#table-of-contents)
- Installation
- [Build and run using docker](#build-and-run-using-docker)
- [Build a nodejs server stub](#build-a-nodejs-server-stub)
- [Compatibility](#compatibility)
- [Prerequisites](#prerequisites)
- [OS X Users](#os-x-users)
- [Building](#building)
- [OS X Users](#os-x-users)
- [Building](#building)
- [Docker](#docker)
- [Build and run](#build-and-run-using-docker)
- [Build a Node.js server stub](#build-a-nodejs-server-stub)
- [Homebrew](#homebrew)
- Generators
- [To generate a sample client library](#to-generate-a-sample-client-library)
- [Generating libraries from your server](#generating-libraries-from-your-server)
- [Modifying the client library format](#modifying-the-client-library-format)
- [Making your own codegen modules](#making-your-own-codegen-modules)
- [Where is Javascript???](#where-is-javascript)
- [Generating a client from local files](#generating-a-client-from-local-files)
- [Generating a client from local files](#generating-a-client-from-local-files)
- [Customizing the generator](#customizing-the-generator)
- [Validating your swagger spec](#validating-your-swagger-spec)
- [Generating dynamic html api documentation](#generating-dynamic-html-api-documentation)
- [Generating static html api documentation](#generating-static-html-api-documentation)
- [To build a server stub](#to-build-a-server-stub)
- [node.js](#nodejs)
- [rails-grape](#rails-grape)
- [scala scalatra](#scala-scalatra)
- [java jax-rs](#java-jax-rs)
- [java spring-mvc](#java-spring-mvc)
- [Node.js](#nodejs)
- [PHP Silex](#php-silex)
- [Ruby Sinatra](#ruby-sinatra)
- [Scala Scalatra](#scala-scalatra)
- [Java JAX-RS](#java-jax-rs)
- [Java Spring MVC](#java-spring-mvc)
- [To build the codegen library](#to-build-the-codegen-library)
- [Online Generators](#online-generators)
- [Guidelines for Contribution](https://github.com/swagger-api/swagger-codegen/wiki/Guidelines-for-Contribution)
- [License](#license)
## 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:
@ -76,24 +63,52 @@ You need the following installed and available in your $PATH:
* [Java 7](http://java.oracle.com)
* [Apache maven 3.0.3 or greater](http://maven.apache.org/)
#### OS X Users
Don't forget to install Java 7. You probably have 1.6 or 1.8.
Export JAVA_HOME in order to user proper Java version:
Export JAVA_HOME in order to use the supported Java version:
```
export JAVA_HOME=`/usr/libexec/java_home -v 1.7`
export PATH=${JAVA_HOME}/bin:$PATH
```
#### Building
### Building
After cloning the project, you can build it from source with this command:
```
mvn package
```
### Docker
#### 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 Node.js server stub
```
./run-in-docker.sh generate \
-i http://petstore.swagger.io/v2/swagger.json \
-l nodejs \
-o samples/server/petstore/nodejs
```
### Homebrew
To install, run `brew install swagger-codegen`
Here is an example usage:
```
swagger-codegen generate -i http://petstore.swagger.io/v2/swagger.json -l ruby -o /tmp/test/
```
### To generate a sample client library
You can build a client against the swagger sample [petstore](http://petstore.swagger.io) API as follows:
@ -110,7 +125,7 @@ java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-o samples/client/petstore/java
```
With a number of options. You can get the options with the `help generate` command:
with a number of options. You can get the options with the `help generate` command:
```
NAME
@ -158,10 +173,10 @@ OPTIONS
-v, --verbose
verbose mode
-s , --skip-overwrite
specifies if the existing files should be overwritten during
the generation
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:
@ -190,7 +205,7 @@ You can look at `modules/swagger-codegen/src/main/resources/${your-language}` fo
If you're starting a project with a new language and don't see what you need, swagger-codegen can help you create a project to generate your own libraries:
```
java -jar modules/swagger-codegen-distribution/target/swagger-codegen-cli.jar meta \
java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar meta \
-o output/myLibrary -n myClientCodegen -p com.my.company.codegen
```
@ -202,7 +217,7 @@ static code generation.
There is a third-party component called [swagger-js-codegen](https://github.com/wcandillon/swagger-js-codegen) that can generate angularjs or nodejs source code from a swagger specification.
#### Generating a client from local files
### Generating a client from local files
If you don't want to call your server, you can save the swagger spec files into a directory and pass an argument
to the code generator like this:
@ -290,7 +305,8 @@ java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-o samples/client/petstore/java \
-c path/to/config.json
```
Supported config options can be different per language. Running `config-help -l {lang}` will show available options.
Supported config options can be different per language. Running `config-help -l {lang}` will show available options. **These options are applied
by passing them with `-D{optionName}={optionValue}**.
```
java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar config-help -l java
@ -336,6 +352,7 @@ CONFIG OPTIONS
jersey2 - HTTP client: Jersey client 2.6
okhttp-gson - HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1
retrofit - HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1 (Retrofit 1.9.0)
retrofit2 - HTTP client: OkHttp 2.5.0. JSON processing: Gson 2.4 (Retrofit 2.0.0-beta2)
```
Your config file for java can look like
@ -350,7 +367,7 @@ Your config file for java can look like
For all the unspecified options default values will be used.
Another way to override default options is to extend config class for specific language.
Another way to override default options is to extend the config class for the specific language.
To change, for example, the prefix for the Objective-C generated files, simply subclass the ObjcClientCodegen.java:
```
@ -406,7 +423,7 @@ open index.html
You can also use the codegen to generate a server for a couple different frameworks. Take a look here:
### node.js
### Node.js
```
java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
@ -415,11 +432,25 @@ java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-o samples/server/petstore/nodejs
```
### rails-grape
### PHP Silex
*Not yet migrated to this branch*
```
java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-i http://petstore.swagger.io/v2/swagger.json \
-l silex \
-o samples/server/petstore/silex
```
### scala scalatra
### Ruby Sinatra
```
java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-i http://petstore.swagger.io/v2/swagger.json \
-l sinatra \
-o samples/server/petstore/sinatra
```
### Scala Scalatra
```
java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-i http://petstore.swagger.io/v2/swagger.json \
@ -427,7 +458,7 @@ java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-o samples/server/petstore/scalatra
```
### java jax-rs
### Java JAX-RS
```
java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
@ -436,7 +467,7 @@ java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-o samples/server/petstore/jaxrs
```
### java spring-mvc
### Java Spring MVC
```
java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
@ -444,6 +475,7 @@ java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-l spring-mvc \
-o samples/server/petstore/spring-mvc
```
### To build the codegen library
This will create the swagger-codegen library from source.
@ -454,6 +486,21 @@ mvn package
Note! The templates are included in the library generated. If you want to modify the templates, you'll need to either repackage the library OR specify a path to your scripts
## Online generators
One can also generate API client or server using the online generators (https://generator.swagger.io)
For example, to generate Ruby API client, simply send the following HTTP request using curl:
```
curl -X POST -H "content-type:application/json" -d '{"swaggerUrl":"http://petstore.swagger.io/v2/swagger.json"}' https://generator.swagger.io/api/gen/clients/ruby
```
Then you will receieve a JSON response with the URL to download the zipped code.
Guidelines for Contribution
---------------------------
Please refer to this [page](https://github.com/swagger-api/swagger-codegen/wiki/Guidelines-for-Contribution)
License
-------

View File

@ -20,6 +20,7 @@ fi
cd $APP_DIR
./bin/akka-scala-petstore.sh
./bin/android-java-petstore.sh
./bin/clojure-petstore.sh
./bin/csharp-petstore.sh
./bin/dynamic-html.sh
./bin/html-petstore.sh
@ -27,6 +28,7 @@ cd $APP_DIR
./bin/java-petstore-jersey2.sh
./bin/java-petstore-okhttp-gson.sh
./bin/java-petstore-retrofit.sh
+./bin/java-petstore-retrofit2.sh
./bin/jaxrs-petstore-server.sh
./bin/nodejs-petstore-server.sh
./bin/objc-petstore.sh

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

31
bin/flaskConnexion.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 flaskConnexion -o samples/server/petstore/flaskConnexion "
java $JAVA_OPTS -Dservice -jar $executable $ags

View File

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

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

View File

@ -20,7 +20,7 @@ public class ConfigHelp implements Runnable {
System.out.println("CONFIG OPTIONS");
for (CliOption langCliOption : config.cliOptions()) {
System.out.println("\t" + langCliOption.getOpt());
System.out.println("\t " + langCliOption.getDescription().replaceAll("\n", "\n\t "));
System.out.println("\t " + langCliOption.getOptionHelp().replaceAll("\n", "\n\t "));
System.out.println();
}
}

View File

@ -103,6 +103,18 @@
<artifactId>maven-release-plugin</artifactId>
<version>2.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>

View File

@ -70,14 +70,29 @@ public abstract class AbstractGenerator {
String libTemplateFile = config.templateDir() + File.separator +
"libraries" + File.separator + library + File.separator +
templateFile;
if (templateExists(libTemplateFile)) {
if (new File(libTemplateFile).exists()) {
return libTemplateFile;
}
libTemplateFile = config.embeddedTemplateDir() + File.separator +
"libraries" + File.separator + library + File.separator +
templateFile;
if (embeddedTemplateExists(libTemplateFile)) {
// Fall back to the template file embedded/packaged in the JAR file...
return libTemplateFile;
}
}
return config.templateDir() + File.separator + templateFile;
String template = config.templateDir() + File.separator + templateFile;
if (new File(template).exists()) {
return template;
} else {
// Fall back to the template file embedded/packaged in the JAR file...
return config.embeddedTemplateDir() + File.separator + templateFile;
}
}
public boolean templateExists(String name) {
public boolean embeddedTemplateExists(String name) {
return this.getClass().getClassLoader().getResource(getCPResourcePath(name)) != null;
}

View File

@ -1,14 +1,31 @@
package io.swagger.codegen;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.models.properties.StringProperty;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.util.LinkedHashMap;
import java.util.Map;
public class CliOption {
private final String opt;
private String description;
private String type;
private String defaultValue;
private Map<String, String> enumValues;
public CliOption(String opt, String description) {
this.opt = opt;
this.description = description;
this(opt, description, StringProperty.TYPE);
}
public CliOption(String opt, String description, String type) {
this.opt = opt;
this.description = description;
this.type = type;
}
@ApiModelProperty(name = "optionName")
public String getOpt() {
return opt;
}
@ -20,4 +37,58 @@ public class CliOption {
public void setDescription(String description) {
this.description = description;
}
@ApiModelProperty(value = "Data type is based on the types supported by the JSON-Schema")
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDefault() {
return defaultValue;
}
public void setDefault(String defaultValue) {
this.defaultValue = defaultValue;
}
public CliOption defaultValue(String defaultValue) {
this.defaultValue = defaultValue;
return this;
}
public CliOption addEnum(String value, String description) {
if (this.enumValues == null) {
this.enumValues = new LinkedHashMap<String, String>();
}
if (!enumValues.containsKey(value)) {
enumValues.put(value, description);
}
return this;
}
public Map<String, String> getEnum() {
return enumValues;
}
public void setEnum(Map<String, String> enumValues) {
this.enumValues = enumValues;
}
@JsonIgnore
public String getOptionHelp() {
StringBuilder sb = new StringBuilder(description);
if(defaultValue != null) {
sb.append(" (Default: ").append(defaultValue).append(")");
}
if (enumValues != null) {
for (Map.Entry<String, String> entry : enumValues.entrySet()) {
sb.append("\n ").append(entry.getKey()).append(" - ").append(entry.getValue());
}
}
return sb.toString();
}
}

View File

@ -29,6 +29,8 @@ public interface CodegenConfig {
String templateDir();
String embeddedTemplateDir();
String modelFileFolder();
String modelPackage();

View File

@ -38,6 +38,12 @@ public class CodegenConstants {
public static final String LIBRARY_DESC = "library template (sub-template)";
public static final String SORT_PARAMS_BY_REQUIRED_FLAG = "sortParamsByRequiredFlag";
public static final String SORT_PARAMS_BY_REQUIRED_FLAG_DESC = "Sort method arguments to place required parameters before optional parameters. Default: true";
public static final String SORT_PARAMS_BY_REQUIRED_FLAG_DESC = "Sort method arguments to place required parameters before optional parameters.";
public static final String ENSURE_UNIQUE_PARAMS = "ensureUniqueParams";
public static final String ENSURE_UNIQUE_PARAMS_DESC = "Whether to ensure parameter names are unique in an operation (rename parameters that are not). Default: true";
public static final String PACKAGE_NAME = "packageName";
public static final String PACKAGE_VERSION = "packageVersion";
public static final String POD_VERSION = "podVersion";
}

View File

@ -10,9 +10,10 @@ import java.util.Set;
public class CodegenOperation {
public final List<CodegenProperty> responseHeaders = new ArrayList<CodegenProperty>();
public Boolean hasAuthMethods, hasConsumes, hasProduces, hasParams, returnTypeIsPrimitive,
returnSimpleType, subresourceOperation, isMapContainer, isListContainer,
hasMore = Boolean.TRUE, isMultipart, isResponseBinary = Boolean.FALSE;
public Boolean hasAuthMethods, hasConsumes, hasProduces, hasParams, hasOptionalParams,
returnTypeIsPrimitive, returnSimpleType, subresourceOperation, isMapContainer,
isListContainer, isMultipart, hasMore = Boolean.TRUE,
isResponseBinary = Boolean.FALSE, hasReference = Boolean.FALSE;
public String path, operationId, returnType, httpMethod, returnBaseType,
returnContainer, summary, notes, baseName, defaultResponse;
public List<Map<String, String>> consumes, produces;

View File

@ -78,6 +78,7 @@ public class DefaultCodegen {
protected Map<String, String> apiTemplateFiles = new HashMap<String, String>();
protected Map<String, String> modelTemplateFiles = new HashMap<String, String>();
protected String templateDir;
protected String embeddedTemplateDir;
protected Map<String, Object> additionalProperties = new HashMap<String, Object>();
protected List<SupportingFile> supportingFiles = new ArrayList<SupportingFile>();
protected List<CliOption> cliOptions = new ArrayList<CliOption>();
@ -86,6 +87,7 @@ public class DefaultCodegen {
protected Map<String, String> supportedLibraries = new LinkedHashMap<String, String>();
protected String library = null;
protected Boolean sortParamsByRequiredFlag = true;
protected Boolean ensureUniqueParams = true;
public List<CliOption> cliOptions() {
return cliOptions;
@ -105,7 +107,13 @@ public class DefaultCodegen {
}
if (additionalProperties.containsKey(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG)) {
this.setSortParamsByRequiredFlag(Boolean.valueOf((String)additionalProperties.get(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG).toString()));
this.setSortParamsByRequiredFlag(Boolean.valueOf(additionalProperties
.get(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG).toString()));
}
if (additionalProperties.containsKey(CodegenConstants.ENSURE_UNIQUE_PARAMS)) {
this.setEnsureUniqueParams(Boolean.valueOf(additionalProperties
.get(CodegenConstants.ENSURE_UNIQUE_PARAMS).toString()));
}
}
@ -183,6 +191,14 @@ public class DefaultCodegen {
return templateDir;
}
public String embeddedTemplateDir() {
if (embeddedTemplateDir != null) {
return embeddedTemplateDir;
} else {
return templateDir;
}
}
public Map<String, String> apiTemplateFiles() {
return apiTemplateFiles;
}
@ -192,11 +208,11 @@ public class DefaultCodegen {
}
public String apiFileFolder() {
return outputFolder + "/" + apiPackage().replace('.', File.separatorChar);
return outputFolder + "/" + apiPackage().replace('.', '/');
}
public String modelFileFolder() {
return outputFolder + "/" + modelPackage().replace('.', File.separatorChar);
return outputFolder + "/" + modelPackage().replace('.', '/');
}
public Map<String, Object> additionalProperties() {
@ -235,6 +251,10 @@ public class DefaultCodegen {
this.sortParamsByRequiredFlag = sortParamsByRequiredFlag;
}
public void setEnsureUniqueParams(Boolean ensureUniqueParams) {
this.ensureUniqueParams = ensureUniqueParams;
}
/**
* Return the file name of the Api
*
@ -423,9 +443,9 @@ public class DefaultCodegen {
importMapping.put("LocalDate", "org.joda.time.*");
importMapping.put("LocalTime", "org.joda.time.*");
cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC));
cliOptions.add(new CliOption(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG,
CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC).defaultValue("true"));
cliOptions.add(new CliOption(CodegenConstants.ENSURE_UNIQUE_PARAMS, CodegenConstants.ENSURE_UNIQUE_PARAMS_DESC));
}
/**
@ -804,6 +824,7 @@ public class DefaultCodegen {
LOGGER.error("unexpected missing property for name " + name);
return null;
}
CodegenProperty property = CodegenModelFactory.newInstance(CodegenModelType.PROPERTY);
property.name = toVarName(name);
@ -1200,6 +1221,7 @@ public class DefaultCodegen {
op.examples = new ExampleGenerator(definitions).generate(methodResponse.getExamples(), operation.getProduces(), responseProperty);
op.defaultResponse = toDefaultValue(responseProperty);
op.returnType = cm.datatype;
op.hasReference = definitions != null && definitions.containsKey(op.returnBaseType);
if (cm.isContainer != null) {
op.returnContainer = cm.containerType;
if ("map".equals(cm.containerType)) {
@ -1233,6 +1255,23 @@ public class DefaultCodegen {
if (parameters != null) {
for (Parameter param : parameters) {
CodegenParameter p = fromParameter(param, imports);
// rename parameters to make sure all of them have unique names
if (ensureUniqueParams) {
while (true) {
boolean exists = false;
for (CodegenParameter cp : allParams) {
if (p.paramName.equals(cp.paramName)) {
exists = true;
break;
}
}
if (exists) {
p.paramName = generateNextName(p.paramName);
} else {
break;
}
}
}
allParams.add(p);
if (param instanceof QueryParameter) {
p.isQueryParam = new Boolean(true);
@ -1260,6 +1299,9 @@ public class DefaultCodegen {
p.isFormParam = new Boolean(true);
formParams.add(p.copy());
}
if (p.required == null || !p.required) {
op.hasOptionalParams = true;
}
}
}
for (String i : imports) {
@ -1271,7 +1313,7 @@ public class DefaultCodegen {
op.httpMethod = httpMethod.toUpperCase();
// move "required" parameters in front of "optional" parameters
if(sortParamsByRequiredFlag) {
if (sortParamsByRequiredFlag) {
Collections.sort(allParams, new Comparator<CodegenParameter>() {
@Override
public int compare(CodegenParameter one, CodegenParameter another) {
@ -1406,6 +1448,9 @@ public class DefaultCodegen {
}
property = new ArrayProperty(inner);
collectionFormat = qp.getCollectionFormat();
if (collectionFormat == null) {
collectionFormat = "csv";
}
CodegenProperty pr = fromProperty("inner", inner);
p.baseType = pr.datatype;
p.isContainer = true;
@ -1713,6 +1758,28 @@ public class DefaultCodegen {
return word;
}
/**
* Generate the next name for the given name, i.e. append "2" to the base name if not ending with a number,
* otherwise increase the number by 1. For example:
* status => status2
* status2 => status3
* myName100 => myName101
*
* @param name The base name
* @return The next name for the base name
*/
private String generateNextName(String name) {
Pattern pattern = Pattern.compile("\\d+\\z");
Matcher matcher = pattern.matcher(name);
if (matcher.find()) {
String numStr = matcher.group();
int num = Integer.parseInt(numStr) + 1;
return name.substring(0, name.length() - numStr.length()) + num;
} else {
return name + "2";
}
}
private void addImport(CodegenModel m, String type) {
if (type != null && needToImport(type)) {
m.imports.add(type);
@ -1856,7 +1923,7 @@ public class DefaultCodegen {
public String apiFilename(String templateName, String tag) {
String suffix = apiTemplateFiles().get(templateName);
return apiFileFolder() + File.separator + toApiFilename(tag) + suffix;
return apiFileFolder() + '/' + toApiFilename(tag) + suffix;
}
public boolean shouldOverwrite(String filename) {
@ -1911,6 +1978,12 @@ public class DefaultCodegen {
// 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.
// better error handling when map/array type is invalid
if (name == null) {
LOGGER.error("String to be sanitized is null. Default to ERROR_UNKNOWN");
return "ERROR_UNKNOWN";
}
// input[] => input
name = name.replaceAll("\\[\\]", "");

View File

@ -1,19 +1,8 @@
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.models.ComposedModel;
import io.swagger.models.Contact;
import io.swagger.models.Info;
import io.swagger.models.License;
import io.swagger.models.Model;
import io.swagger.models.Operation;
import io.swagger.models.Path;
import io.swagger.models.SecurityRequirement;
import io.swagger.models.Swagger;
import io.swagger.models.*;
import io.swagger.models.auth.OAuth2Definition;
import io.swagger.models.auth.SecuritySchemeDefinition;
import io.swagger.models.parameters.Parameter;
@ -23,14 +12,12 @@ import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.*;
import java.util.*;
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);
@ -216,7 +203,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
.withLoader(new Mustache.TemplateLoader() {
@Override
public Reader getTemplate(String name) {
return getTemplateReader(config.templateDir() + File.separator + name + ".mustache");
return getTemplateReader(getFullTemplateFile(config, name + ".mustache"));
}
})
.defaultValue("")
@ -262,6 +249,13 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
operation.put("classVarName", config.toApiVarName(tag));
operation.put("importPath", config.toApiImport(tag));
// Pass sortParamsByRequiredFlag through to the Mustache template...
boolean sortParamsByRequiredFlag = true;
if (this.config.additionalProperties().containsKey(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG)) {
sortParamsByRequiredFlag = Boolean.valueOf((String)this.config.additionalProperties().get(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG).toString());
}
operation.put("sortParamsByRequiredFlag", sortParamsByRequiredFlag);
processMimeTypes(swagger.getConsumes(), operation, "consumes");
processMimeTypes(swagger.getProduces(), operation, "produces");
@ -285,7 +279,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
.withLoader(new Mustache.TemplateLoader() {
@Override
public Reader getTemplate(String name) {
return getTemplateReader(config.templateDir() + File.separator + name + ".mustache");
return getTemplateReader(getFullTemplateFile(config, name + ".mustache"));
}
})
.defaultValue("")
@ -314,6 +308,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
if (swagger.getHost() != null) {
bundle.put("host", swagger.getHost());
}
bundle.put("swagger", this.swagger);
bundle.put("basePath", basePath);
bundle.put("scheme", scheme);
bundle.put("contextPath", contextPath);
@ -376,7 +371,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
.withLoader(new Mustache.TemplateLoader() {
@Override
public Reader getTemplate(String name) {
return getTemplateReader(config.templateDir() + File.separator + name + ".mustache");
return getTemplateReader(getFullTemplateFile(config, name + ".mustache"));
}
})
.defaultValue("")

View File

@ -10,4 +10,14 @@ public class SupportingFile {
this.folder = folder;
this.destinationFilename = destinationFilename;
}
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("SupportingFile:").append("\n");
builder.append("\ttemplateFile: ").append(templateFile).append("\n");
builder.append("\tfolder: ").append(folder).append("\n");
builder.append("\tdestinationFilename: ").append(destinationFilename).append("\n");
return builder.toString();
}
}

View File

@ -339,6 +339,9 @@ public class CodegenConfigurator {
if (dynamicProperties.containsKey(opt)) {
codegenConfig.additionalProperties().put(opt, dynamicProperties.get(opt));
}
else if(systemProperties.containsKey(opt)) {
codegenConfig.additionalProperties().put(opt, systemProperties.get(opt).toString());
}
}
}

View File

@ -6,6 +6,8 @@ import io.swagger.models.properties.*;
import java.util.*;
import java.io.File;
import org.apache.commons.lang.StringUtils;
public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public CodegenType getTag() {
@ -15,14 +17,7 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
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"));
reservedWords = new HashSet<String>(Arrays.asList("abstract", "await", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "debugger", "default", "delete", "do", "double", "else", "enum", "export", "extends", "false", "final", "finally", "float", "for", "function", "goto", "if", "implements", "import", "in", "instanceof", "int", "interface", "let", "long", "native", "new", "null", "package", "private", "protected", "public", "return", "short", "static", "super", "switch", "synchronized", "this", "throw", "transient", "true", "try", "typeof", "var", "void", "volatile", "while", "with", "yield"));
languageSpecificPrimitives = new HashSet<String>(Arrays.asList(
"String",
@ -79,7 +74,7 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
return name;
// camelize the variable name
// pet_id => PetId
// pet_id => petId
name = camelize(name, true);
// for reserved word or word starting with number, append _
@ -141,4 +136,20 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
type = swaggerType;
return 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
// append _ at the beginning, e.g. _return
if (reservedWords.contains(operationId)) {
return escapeReservedWord(camelize(sanitizeName(operationId), true));
}
return camelize(sanitizeName(operationId), true);
}
}

View File

@ -3,6 +3,8 @@ package io.swagger.codegen.languages;
import com.google.common.base.CaseFormat;
import com.samskivert.mustache.Mustache;
import com.samskivert.mustache.Template;
import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenOperation;
@ -68,7 +70,7 @@ public class AkkaScalaClientCodegen extends DefaultCodegen implements CodegenCon
outputFolder = "generated-code/scala";
modelTemplateFiles.put("model.mustache", ".scala");
apiTemplateFiles.put("api.mustache", ".scala");
templateDir = "akka-scala";
embeddedTemplateDir = templateDir = "akka-scala";
apiPackage = mainPackage + ".api";
modelPackage = mainPackage + ".model";
@ -147,6 +149,9 @@ public class AkkaScalaClientCodegen extends DefaultCodegen implements CodegenCon
);
instantiationTypes.put("array", "ListBuffer");
instantiationTypes.put("map", "Map");
cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
}
public CodegenType getTag() {

View File

@ -17,6 +17,7 @@ import java.util.HashSet;
import org.apache.commons.lang.StringUtils;
public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfig {
public static final String USE_ANDROID_MAVEN_GRADLE_PLUGIN = "useAndroidMavenGradlePlugin";
protected String invokerPackage = "io.swagger.client";
protected String groupId = "io.swagger";
protected String artifactId = "swagger-android-client";
@ -30,7 +31,7 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
outputFolder = "generated-code/android";
modelTemplateFiles.put("model.mustache", ".java");
apiTemplateFiles.put("api.mustache", ".java");
templateDir = "android-java";
embeddedTemplateDir = templateDir = "android-java";
apiPackage = "io.swagger.client.api";
modelPackage = "io.swagger.client.model";
@ -59,12 +60,15 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
instantiationTypes.put("array", "ArrayList");
instantiationTypes.put("map", "HashMap");
cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
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."));
cliOptions.add(new CliOption(USE_ANDROID_MAVEN_GRADLE_PLUGIN, "A flag to toggle android-maven gradle plugin.")
.defaultValue("true"));
}
public CodegenType getTag() {
@ -220,14 +224,15 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
this.setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER));
}
if (additionalProperties.containsKey("useAndroidMavenGradlePlugin")) {
this.setUseAndroidMavenGradlePlugin((Boolean) additionalProperties.get("useAndroidMavenGradlePlugin"));
if (additionalProperties.containsKey(USE_ANDROID_MAVEN_GRADLE_PLUGIN)) {
this.setUseAndroidMavenGradlePlugin(Boolean.valueOf((String) additionalProperties
.get(USE_ANDROID_MAVEN_GRADLE_PLUGIN)));
} else {
additionalProperties.put("useAndroidMavenGradlePlugin", useAndroidMavenGradlePlugin);
additionalProperties.put(USE_ANDROID_MAVEN_GRADLE_PLUGIN, useAndroidMavenGradlePlugin);
}
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
additionalProperties.put("useAndroidMavenGradlePlugin", useAndroidMavenGradlePlugin);
additionalProperties.put(USE_ANDROID_MAVEN_GRADLE_PLUGIN, useAndroidMavenGradlePlugin);
supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
supportingFiles.add(new SupportingFile("build.mustache", "", "build.gradle"));

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.CodegenConstants;
import io.swagger.codegen.CodegenType;
@ -40,7 +41,7 @@ public class AsyncScalaClientCodegen extends DefaultCodegen implements CodegenCo
outputFolder = "generated-code/async-scala";
modelTemplateFiles.put("model.mustache", ".scala");
apiTemplateFiles.put("api.mustache", ".scala");
templateDir = "asyncscala";
embeddedTemplateDir = templateDir = "asyncscala";
apiPackage = "io.swagger.client.api";
modelPackage = "io.swagger.client.model";
@ -105,6 +106,9 @@ public class AsyncScalaClientCodegen extends DefaultCodegen implements CodegenCo
);
instantiationTypes.put("array", "ListBuffer");
instantiationTypes.put("map", "HashMap");
cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
}
public CodegenType getTag() {

View File

@ -1,9 +1,12 @@
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.codegen.CodegenProperty;
import io.swagger.codegen.CodegenModel;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
@ -13,10 +16,15 @@ import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(CSharpClientCodegen.class);
protected String packageName = "IO.Swagger";
protected String packageVersion = "1.0.0";
protected String clientPackage = "IO.Swagger.Client";
@ -27,7 +35,7 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
outputFolder = "generated-code" + File.separator + "csharp";
modelTemplateFiles.put("model.mustache", ".cs");
apiTemplateFiles.put("api.mustache", ".cs");
templateDir = "csharp";
embeddedTemplateDir = templateDir = "csharp";
apiPackage = "IO.Swagger.Api";
modelPackage = "IO.Swagger.Model";
@ -79,28 +87,29 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
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"));
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "C# package name (convention: Camel.Case).")
.defaultValue("IO.Swagger"));
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "C# package version.").defaultValue("1.0.0"));
cliOptions.add(new CliOption(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC));
}
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey("packageVersion")) {
packageVersion = (String) additionalProperties.get("packageVersion");
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) {
setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION));
} else {
additionalProperties.put("packageVersion", packageVersion);
additionalProperties.put(CodegenConstants.PACKAGE_VERSION, packageVersion);
}
if (additionalProperties.containsKey("packageName")) {
packageName = (String) additionalProperties.get("packageName");
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
apiPackage = packageName + ".Api";
modelPackage = packageName + ".Model";
clientPackage = packageName + ".Client";
} else {
additionalProperties.put("packageName", packageName);
additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
}
additionalProperties.put("clientPackage", clientPackage);
@ -252,4 +261,29 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
return camelize(sanitizeName(operationId));
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public void setPackageVersion(String packageVersion) {
this.packageVersion = packageVersion;
}
@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) {
// check to see if model name is same as the property name
// which will result in compilation error
// if found, prepend with _ to workaround the limitation
if (var.name.equals(cm.name)) {
var.name = "_" + var.name;
}
}
}
return objs;
}
}

View File

@ -0,0 +1,178 @@
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;
import io.swagger.codegen.SupportingFile;
import io.swagger.models.Contact;
import io.swagger.models.Info;
import io.swagger.models.License;
import io.swagger.models.Swagger;
import org.apache.commons.lang.StringUtils;
import java.io.File;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.List;
public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final String PROJECT_NAME = "projectName";
private static final String PROJECT_DESCRIPTION = "projectDescription";
private static final String PROJECT_VERSION = "projectVersion";
private static final String PROJECT_URL = "projectUrl";
private static final String LICENSE_NAME = "licenseName";
private static final String LICENSE_URL = "licenseUrl";
private static final String BASE_NAMESPACE = "baseNamespace";
protected String projectName = null;
protected String projectDescription = null;
protected String projectVersion = null;
protected String sourceFolder = "src";
public ClojureClientCodegen() {
super();
outputFolder = "generated-code" + File.separator + "clojure";
apiTemplateFiles.put("api.mustache", ".clj");
embeddedTemplateDir = templateDir = "clojure";
}
@Override
public CodegenType getTag() {
return CodegenType.CLIENT;
}
@Override
public String getName() {
return "clojure";
}
@Override
public String getHelp() {
return "Generates a Clojure client library.";
}
@Override
public void preprocessSwagger(Swagger swagger) {
super.preprocessSwagger(swagger);
if (additionalProperties.containsKey(PROJECT_NAME)) {
projectName = ((String) additionalProperties.get(PROJECT_NAME));
}
if (additionalProperties.containsKey(PROJECT_DESCRIPTION)) {
projectDescription = ((String) additionalProperties.get(PROJECT_DESCRIPTION));
}
if (additionalProperties.containsKey(PROJECT_VERSION)) {
projectVersion = ((String) additionalProperties.get(PROJECT_VERSION));
}
if (swagger.getInfo() != null) {
Info info = swagger.getInfo();
if (projectName == null && info.getTitle() != null) {
// when projectName is not specified, generate it from info.title
projectName = dashize(info.getTitle());
}
if (projectVersion == null) {
// when projectVersion is not specified, use info.version
projectVersion = info.getVersion();
}
if (projectDescription == null) {
// when projectDescription is not specified, use info.description
projectDescription = info.getDescription();
}
if (info.getContact() != null) {
Contact contact = info.getContact();
if (additionalProperties.get(PROJECT_URL) == null) {
additionalProperties.put(PROJECT_URL, contact.getUrl());
}
}
if (info.getLicense() != null) {
License license = info.getLicense();
if (additionalProperties.get(LICENSE_NAME) == null) {
additionalProperties.put(LICENSE_NAME, license.getName());
}
if (additionalProperties.get(LICENSE_URL) == null) {
additionalProperties.put(LICENSE_URL, license.getUrl());
}
}
}
// default values
if (projectName == null) {
projectName = "swagger-clj-client";
}
if (projectVersion == null) {
projectVersion = "1.0.0";
}
if (projectDescription == null) {
projectDescription = "Client library of " + projectName;
}
final String baseNamespace = dashize(projectName);
apiPackage = baseNamespace + ".api";
additionalProperties.put(PROJECT_NAME, projectName);
additionalProperties.put(PROJECT_DESCRIPTION, escapeText(projectDescription));
additionalProperties.put(PROJECT_VERSION, projectVersion);
additionalProperties.put(BASE_NAMESPACE, baseNamespace);
additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage);
final String baseNamespaceFolder = sourceFolder + File.separator + namespaceToFolder(baseNamespace);
supportingFiles.add(new SupportingFile("project.mustache", "", "project.clj"));
supportingFiles.add(new SupportingFile("core.mustache", baseNamespaceFolder, "core.clj"));
}
@Override
public String apiFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + namespaceToFolder(apiPackage);
}
@Override
public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method/operation name (operationId) not allowed");
}
return dashize(sanitizeName(operationId));
}
@Override
public String toApiName(String name) {
return dashize(name);
}
@Override
public String toParamName(String name) {
return toVarName(name);
}
@Override
public String toVarName(String name) {
name = name.replaceAll("[^a-zA-Z0-9_-]+", "");
name = dashize(name);
return name;
}
@Override
public Map<String, Object> postProcessOperations(Map<String, Object> operations) {
Map<String, Object> objs = (Map<String, Object>) operations.get("operations");
List<CodegenOperation> ops = (List<CodegenOperation>) objs.get("operation");
for (CodegenOperation op : ops) {
// Convert httpMethod to lower case, e.g. "get", "post"
op.httpMethod = op.httpMethod.toLowerCase();
}
return operations;
}
protected String namespaceToFolder(String ns) {
return ns.replace(".", File.separator).replace("-", "_");
}
protected String dashize(String s) {
return underscore(s).replaceAll("[_ ]", "-");
}
}

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;
@ -15,6 +16,7 @@ import java.util.HashMap;
import java.util.HashSet;
public class CsharpDotNet2ClientCodegen extends DefaultCodegen implements CodegenConfig {
public static final String CLIENT_PACKAGE = "clientPackage";
protected String packageName = "IO.Swagger";
protected String packageVersion = "1.0.0";
protected String clientPackage = "IO.Swagger.Client";
@ -25,7 +27,7 @@ public class CsharpDotNet2ClientCodegen extends DefaultCodegen implements Codege
outputFolder = "generated-code" + File.separator + "CsharpDotNet2";
modelTemplateFiles.put("model.mustache", ".cs");
apiTemplateFiles.put("api.mustache", ".cs");
templateDir = "CsharpDotNet2";
embeddedTemplateDir = templateDir = "CsharpDotNet2";
apiPackage = "IO.Swagger.Api";
modelPackage = "IO.Swagger.Model";
@ -77,34 +79,36 @@ public class CsharpDotNet2ClientCodegen extends DefaultCodegen implements Codege
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"));
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "C# package name (convention: Camel.Case).")
.defaultValue("IO.Swagger"));
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "C# package version.").defaultValue("1.0.0"));
cliOptions.add(new CliOption(CLIENT_PACKAGE, "C# client package name (convention: Camel.Case).")
.defaultValue("IO.Swagger.Client"));
}
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey("packageVersion")) {
packageVersion = (String) additionalProperties.get("packageVersion");
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) {
setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION));
} else {
additionalProperties.put("packageVersion", packageVersion);
additionalProperties.put(CodegenConstants.PACKAGE_VERSION, packageVersion);
}
if (additionalProperties.containsKey("packageName")) {
packageName = (String) additionalProperties.get("packageName");
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
apiPackage = packageName + ".Api";
modelPackage = packageName + ".Model";
clientPackage = packageName + ".Client";
} else {
additionalProperties.put("packageName", packageName);
additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
}
if (additionalProperties.containsKey("clientPackage")) {
this.setClientPackage((String) additionalProperties.get("clientPackage"));
if (additionalProperties.containsKey(CLIENT_PACKAGE)) {
this.setClientPackage((String) additionalProperties.get(CLIENT_PACKAGE));
} else {
additionalProperties.put("clientPackage", clientPackage);
additionalProperties.put(CLIENT_PACKAGE, clientPackage);
}
supportingFiles.add(new SupportingFile("Configuration.mustache",
@ -123,6 +127,14 @@ public class CsharpDotNet2ClientCodegen extends DefaultCodegen implements Codege
this.clientPackage = clientPackage;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public void setPackageVersion(String packageVersion) {
this.packageVersion = packageVersion;
}
public CodegenType getTag() {
return CodegenType.CLIENT;
}

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;
@ -15,6 +16,10 @@ import java.util.HashSet;
import java.util.HashMap;
public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
public static final String BROWSER_CLIENT = "browserClient";
public static final String PUB_NAME = "pubName";
public static final String PUB_VERSION = "pubVersion";
public static final String PUB_DESCRIPTION = "pubDescription";
protected boolean browserClient = true;
protected String pubName = "swagger";
protected String pubVersion = "1.0.0";
@ -26,7 +31,7 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
outputFolder = "generated-code/dart";
modelTemplateFiles.put("model.mustache", ".dart");
apiTemplateFiles.put("api.mustache", ".dart");
templateDir = "dart";
embeddedTemplateDir = templateDir = "dart";
apiPackage = "lib.api";
modelPackage = "lib.model";
@ -72,10 +77,11 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("date", "DateTime");
typeMapping.put("File", "MultipartFile");
cliOptions.add(new CliOption("browserClient", "Is the client browser based"));
cliOptions.add(new CliOption("pubName", "Name in generated pubspec"));
cliOptions.add(new CliOption("pubVersion", "Version in generated pubspec"));
cliOptions.add(new CliOption("sourceFolder", "source folder for generated code"));
cliOptions.add(new CliOption(BROWSER_CLIENT, "Is the client browser based"));
cliOptions.add(new CliOption(PUB_NAME, "Name in generated pubspec"));
cliOptions.add(new CliOption(PUB_VERSION, "Version in generated pubspec"));
cliOptions.add(new CliOption(PUB_DESCRIPTION, "Description in generated pubspec"));
cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, "source folder for generated code"));
}
public CodegenType getTag() {
@ -94,37 +100,37 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey("browserClient")) {
this.setBrowserClient(Boolean.parseBoolean((String) additionalProperties.get("browserClient")));
additionalProperties.put("browserClient", browserClient);
if (additionalProperties.containsKey(BROWSER_CLIENT)) {
this.setBrowserClient(Boolean.parseBoolean((String) additionalProperties.get(BROWSER_CLIENT)));
additionalProperties.put(BROWSER_CLIENT, browserClient);
} else {
//not set, use to be passed to template
additionalProperties.put("browserClient", browserClient);
additionalProperties.put(BROWSER_CLIENT, browserClient);
}
if (additionalProperties.containsKey("pubName")) {
this.setPubName((String) additionalProperties.get("pubName"));
if (additionalProperties.containsKey(PUB_NAME)) {
this.setPubName((String) additionalProperties.get(PUB_NAME));
} else {
//not set, use to be passed to template
additionalProperties.put("pubName", pubName);
additionalProperties.put(PUB_NAME, pubName);
}
if (additionalProperties.containsKey("pubVersion")) {
this.setPubVersion((String) additionalProperties.get("pubVersion"));
if (additionalProperties.containsKey(PUB_VERSION)) {
this.setPubVersion((String) additionalProperties.get(PUB_VERSION));
} else {
//not set, use to be passed to template
additionalProperties.put("pubVersion", pubVersion);
additionalProperties.put(PUB_VERSION, pubVersion);
}
if (additionalProperties.containsKey("pubDescription")) {
this.setPubDescription((String) additionalProperties.get("pubDescription"));
if (additionalProperties.containsKey(PUB_DESCRIPTION)) {
this.setPubDescription((String) additionalProperties.get(PUB_DESCRIPTION));
} else {
//not set, use to be passed to template
additionalProperties.put("pubDescription", pubDescription);
additionalProperties.put(PUB_DESCRIPTION, pubDescription);
}
if (additionalProperties.containsKey("sourceFolder")) {
this.setSourceFolder((String) additionalProperties.get("sourceFolder"));
if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) {
this.setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER));
}
final String libFolder = sourceFolder + File.separator + "lib";

View File

@ -40,7 +40,7 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
modelTemplateFiles.put("model.mustache", ".as");
modelTemplateFiles.put("modelList.mustache", "List.as");
apiTemplateFiles.put("api.mustache", ".as");
templateDir = "flash";
embeddedTemplateDir = templateDir = "flash";
languageSpecificPrimitives.clear();
languageSpecificPrimitives.add("Number");
@ -68,15 +68,19 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
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"));
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.PACKAGE_NAME, "flash package name (convention:" +
" package.name)").defaultValue("io.swagger"));
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "flash package version")
.defaultValue("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"));
cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, "source folder for generated " +
"code. e.g. src/main/flex"));
}
@ -95,8 +99,8 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
this.setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER));
}
if (additionalProperties.containsKey("packageName")) {
setPackageName((String) additionalProperties.get("packageName"));
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
apiPackage = packageName + ".client.api";
modelPackage = packageName + ".client.model";
}
@ -104,20 +108,21 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
setPackageName("io.swagger");
}
if (additionalProperties.containsKey("packageVersion")) {
setPackageVersion((String) additionalProperties.get("packageVersion"));
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) {
setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION));
}
else {
setPackageVersion("1.0.0");
}
additionalProperties.put("packageName", packageName);
additionalProperties.put("packageVersion", packageVersion);
additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
additionalProperties.put(CodegenConstants.PACKAGE_VERSION, 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);
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"));
@ -131,13 +136,20 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
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"));
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) {
@ -163,11 +175,13 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
@Override
public String apiFileFolder() {
return (outputFolder + File.separatorChar + sourceFolder + File.separatorChar + apiPackage().replace('.', File.separatorChar)).replace('/', File.separatorChar);
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);
return (outputFolder + File.separatorChar + sourceFolder + File.separatorChar
+ modelPackage().replace('.', File.separatorChar)).replace('/', File.separatorChar);
}
@Override

View File

@ -0,0 +1,295 @@
package io.swagger.codegen.languages;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import io.swagger.codegen.*;
import io.swagger.models.Operation;
import io.swagger.models.Path;
import io.swagger.models.Swagger;
import io.swagger.util.Yaml;
import java.io.File;
import java.util.*;
public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConfig {
public static final String CONTROLLER_PACKAGE = "controllerPackage";
public static final String DEFAULT_CONTROLLER = "defaultController";
protected String apiVersion = "1.0.0";
protected int serverPort = 8080;
protected String projectName = "swagger-server";
protected String controllerPackage;
protected String defaultController;
public FlaskConnexionCodegen() {
super();
languageSpecificPrimitives.clear();
languageSpecificPrimitives.add("int");
languageSpecificPrimitives.add("float");
languageSpecificPrimitives.add("list");
languageSpecificPrimitives.add("bool");
languageSpecificPrimitives.add("str");
languageSpecificPrimitives.add("datetime");
languageSpecificPrimitives.add("date");
typeMapping.clear();
typeMapping.put("integer", "int");
typeMapping.put("float", "float");
typeMapping.put("number", "float");
typeMapping.put("long", "int");
typeMapping.put("double", "float");
typeMapping.put("array", "list");
typeMapping.put("map", "dict");
typeMapping.put("boolean", "bool");
typeMapping.put("string", "str");
typeMapping.put("date", "date");
typeMapping.put("DateTime", "datetime");
typeMapping.put("object", "object");
typeMapping.put("file", "file");
// set the output folder here
outputFolder = "generated-code/connexion";
modelTemplateFiles.clear();
apiTemplateFiles.clear();
/**
* Template Location. This is the location which templates will be read from. The generator
* will use the resource stream to attempt to read the templates.
*/
embeddedTemplateDir = templateDir = "flaskConnexion";
// from https://docs.python.org/release/2.5.4/ref/keywords.html
reservedWords = new HashSet<String>(
Arrays.asList(
"and", "del", "from", "not", "while", "as", "elif", "global", "or", "with",
"assert", "else", "if", "pass", "yield", "break", "except", "import",
"print", "class", "exec", "in", "raise", "continue", "finally", "is",
"return", "def", "for", "lambda", "try"));
/**
* Additional Properties. These values can be passed to the templates and
* are available in models, apis, and supporting files
*/
additionalProperties.put("apiVersion", apiVersion);
additionalProperties.put("serverPort", serverPort);
/**
* Supporting Files. You can write single files for the generator with the
* entire object tree available. If the input file has a suffix of `.mustache
* it will be processed by the template engine. Otherwise, it will be copied
*/
supportingFiles.add(new SupportingFile("swagger.mustache",
"swagger",
"swagger.yaml")
);
supportingFiles.add(new SupportingFile("app.mustache",
"",
"app.py")
);
supportingFiles.add(new SupportingFile("README.mustache",
"",
"README.md")
);
cliOptions.add(new CliOption(CONTROLLER_PACKAGE, "controller package").
defaultValue("controllers"));
cliOptions.add(new CliOption(DEFAULT_CONTROLLER, "default controller").
defaultValue("default_controller"));
}
@Override
public void processOpts() {
super.processOpts();
apiTemplateFiles.clear();
if (additionalProperties.containsKey(CONTROLLER_PACKAGE)) {
this.controllerPackage = additionalProperties.get(CONTROLLER_PACKAGE).toString();
}
else {
this.controllerPackage = "controllers";
additionalProperties.put(CONTROLLER_PACKAGE, this.controllerPackage);
}
if (additionalProperties.containsKey(DEFAULT_CONTROLLER)) {
this.defaultController = additionalProperties.get(DEFAULT_CONTROLLER).toString();
}
else {
this.defaultController = "default_controller";
additionalProperties.put(DEFAULT_CONTROLLER, this.defaultController);
}
if(!new java.io.File(controllerPackage + File.separator + defaultController + ".py").exists()) {
supportingFiles.add(new SupportingFile("controller.mustache",
controllerPackage,
defaultController + ".py")
);
}
}
public String apiPackage() {
return controllerPackage;
}
/**
* Configures the type of generator.
*
* @return the CodegenType for this generator
* @see io.swagger.codegen.CodegenType
*/
public CodegenType getTag() {
return CodegenType.SERVER;
}
/**
* Configures a friendly name for the generator. This will be used by the generator
* to select the library with the -l flag.
*
* @return the friendly name for the generator
*/
public String getName() {
return "python-flask";
}
/**
* Returns human-friendly help for the generator. Provide the consumer with help
* tips, parameters here
*
* @return A string value for the help message
*/
public String getHelp() {
return "Generates a python server library using the connexion project. By default, " +
"it will also generate service classes--which you can disable with the `-Dnoservice` environment variable.";
}
@Override
public String toApiName(String name) {
if (name.length() == 0) {
return "DefaultController";
}
return initialCaps(name);
}
@Override
public String toApiFilename(String name) {
return toApiName(name);
}
/**
* Escapes a reserved word as defined in the `reservedWords` array. Handle escaping
* those terms here. This logic is only called if a variable matches the reseved words
*
* @return the escaped term
*/
@Override
public String escapeReservedWord(String name) {
return "_" + name; // add an underscore to the name
}
/**
* Location to write api files. You can use the apiPackage() as defined when the class is
* instantiated
*/
@Override
public String apiFileFolder() {
return outputFolder + File.separator + apiPackage().replace('.', File.separatorChar);
}
@Override
public void preprocessSwagger(Swagger swagger) {
if(swagger != null && swagger.getPaths() != null) {
for(String pathname : swagger.getPaths().keySet()) {
Path path = swagger.getPath(pathname);
if(path.getOperations() != null) {
for(Operation operation : path.getOperations()) {
String operationId = operation.getOperationId();
if(operationId != null && operationId.indexOf(".") == -1) {
operation.setVendorExtension("x-operationId", underscore(sanitizeName(operationId)));
operationId = controllerPackage + "." + defaultController + "." + underscore(sanitizeName(operationId));
operation.setOperationId(operationId);
}
if(operation.getTags() != null) {
List<Map<String, String>> tags = new ArrayList<Map<String, String>>();
for(String tag : operation.getTags()) {
Map<String, String> value = new HashMap<String, String>();
value.put("tag", tag);
value.put("hasMore", "true");
tags.add(value);
}
if(tags.size() > 0) {
tags.get(tags.size() - 1).remove("hasMore");
}
if(operation.getTags().size() > 0) {
String tag = operation.getTags().get(0);
operation.setTags(Arrays.asList(tag));
}
operation.setVendorExtension("x-tags", tags);
}
else {
String tag = "default_controller";
operation.setTags(Arrays.asList(tag));
}
}
}
}
}
}
@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 (Map.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) {
Swagger swagger = (Swagger)objs.get("swagger");
if(swagger != null) {
try {
objs.put("swagger-yaml", Yaml.mapper().writeValueAsString(swagger));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
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

@ -12,9 +12,14 @@ 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.BooleanProperty;
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 java.io.File;
import java.util.ArrayList;
@ -31,12 +36,15 @@ import org.slf4j.LoggerFactory;
public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(JavaClientCodegen.class);
public static final String FULL_JAVA_UTIL = "fullJavaUtil";
public static final String DEFAULT_LIBRARY = "<default>";
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 projectFolder = "src" + File.separator + "main";
protected String sourceFolder = projectFolder + File.separator + "java";
protected String localVariablePrefix = "";
protected boolean fullJavaUtil = false;
protected String javaUtilPrefix = "";
@ -44,10 +52,10 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
public JavaClientCodegen() {
super();
outputFolder = "generated-code/java";
outputFolder = "generated-code" + File.separator + "java";
modelTemplateFiles.put("model.mustache", ".java");
apiTemplateFiles.put("api.mustache", ".java");
templateDir = "Java";
embeddedTemplateDir = templateDir = "Java";
apiPackage = "io.swagger.client.api";
modelPackage = "io.swagger.client.model";
@ -77,6 +85,8 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
instantiationTypes.put("array", "ArrayList");
instantiationTypes.put("map", "HashMap");
cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
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));
@ -84,13 +94,19 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
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));
cliOptions.add(new CliOption("fullJavaUtil", "whether to use fully qualified name for classes under java.util (default to false)"));
cliOptions.add(new CliOption(FULL_JAVA_UTIL, "whether to use fully qualified name for classes under java.util")
.defaultValue("false"));
supportedLibraries.put("<default>", "HTTP client: Jersey client 1.18. JSON processing: Jackson 2.4.2");
supportedLibraries.put(DEFAULT_LIBRARY, "HTTP client: Jersey client 1.18. JSON processing: Jackson 2.4.2");
supportedLibraries.put("jersey2", "HTTP client: Jersey client 2.6");
supportedLibraries.put("okhttp-gson", "HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1");
supportedLibraries.put("retrofit", "HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1 (Retrofit 1.9.0)");
cliOptions.add(buildLibraryCliOption(supportedLibraries));
supportedLibraries.put("retrofit2", "HTTP client: OkHttp 2.5.0. JSON processing: Gson 2.4 (Retrofit 2.0.0-beta2)");
CliOption library = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use");
library.setDefault(DEFAULT_LIBRARY);
library.setEnum(supportedLibraries);
library.setDefault(DEFAULT_LIBRARY);
cliOptions.add(library);
}
@Override
@ -150,7 +166,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
}
if (additionalProperties.containsKey(CodegenConstants.SERIALIZABLE_MODEL)) {
this.setSerializableModel(Boolean.valueOf((String)additionalProperties.get(CodegenConstants.SERIALIZABLE_MODEL).toString()));
this.setSerializableModel(Boolean.valueOf(additionalProperties.get(CodegenConstants.SERIALIZABLE_MODEL).toString()));
}
if (additionalProperties.containsKey(CodegenConstants.LIBRARY)) {
@ -160,13 +176,13 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
// need to put back serializableModel (boolean) into additionalProperties as value in additionalProperties is string
additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, serializableModel);
if (additionalProperties.containsKey("fullJavaUtil")) {
fullJavaUtil = Boolean.valueOf(additionalProperties.get("fullJavaUtil").toString());
if (additionalProperties.containsKey(FULL_JAVA_UTIL)) {
this.setFullJavaUtil(Boolean.valueOf(additionalProperties.get(FULL_JAVA_UTIL).toString()));
}
if (fullJavaUtil) {
javaUtilPrefix = "java.util.";
}
additionalProperties.put("fullJavaUtil", fullJavaUtil);
additionalProperties.put(FULL_JAVA_UTIL, fullJavaUtil);
additionalProperties.put("javaUtilPrefix", javaUtilPrefix);
if (fullJavaUtil) {
@ -188,21 +204,23 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
this.sanitizeConfig();
final String invokerFolder = (sourceFolder + File.separator + invokerPackage).replace(".", File.separator);
final String invokerFolder = (sourceFolder + '/' + invokerPackage).replace(".", "/");
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("build.gradle.mustache", "", "build.gradle"));
supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
supportingFiles.add(new SupportingFile("gradle.properties.mustache", "", "gradle.properties"));
supportingFiles.add(new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml"));
supportingFiles.add(new SupportingFile("ApiClient.mustache", invokerFolder, "ApiClient.java"));
supportingFiles.add(new SupportingFile("StringUtil.mustache", invokerFolder, "StringUtil.java"));
final String authFolder = (sourceFolder + File.separator + invokerPackage + ".auth").replace(".", File.separator);
final String authFolder = (sourceFolder + '/' + invokerPackage + ".auth").replace(".", "/");
supportingFiles.add(new SupportingFile("auth/HttpBasicAuth.mustache", authFolder, "HttpBasicAuth.java"));
supportingFiles.add(new SupportingFile("auth/ApiKeyAuth.mustache", authFolder, "ApiKeyAuth.java"));
supportingFiles.add(new SupportingFile("auth/OAuth.mustache", authFolder, "OAuth.java"));
supportingFiles.add(new SupportingFile("auth/OAuthFlow.mustache", authFolder, "OAuthFlow.java"));
if (!"retrofit".equals(getLibrary())) {
if (!("retrofit".equals(getLibrary()) || "retrofit2".equals(getLibrary()))) {
supportingFiles.add(new SupportingFile("apiException.mustache", invokerFolder, "ApiException.java"));
supportingFiles.add(new SupportingFile("Configuration.mustache", invokerFolder, "Configuration.java"));
supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java"));
@ -216,7 +234,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
supportingFiles.add(new SupportingFile("ApiCallback.mustache", invokerFolder, "ApiCallback.java"));
// "build.sbt" is for development with SBT
supportingFiles.add(new SupportingFile("build.sbt.mustache", "", "build.sbt"));
} else if ("retrofit".equals(getLibrary())) {
} else if ("retrofit".equals(getLibrary()) || "retrofit2".equals(getLibrary())) {
supportingFiles.add(new SupportingFile("auth/OAuthOkHttpClient.mustache", authFolder, "OAuthOkHttpClient.java"));
supportingFiles.add(new SupportingFile("CollectionFormats.mustache", invokerFolder, "CollectionFormats.java"));
} else {
@ -251,12 +269,12 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String apiFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar);
return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', '/');
}
@Override
public String modelFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar);
return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', '/');
}
@Override
@ -346,12 +364,48 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
pattern = "new HashMap<String, %s>()";
}
return String.format(pattern, getTypeDeclaration(ap.getAdditionalProperties()));
} else if (p instanceof IntegerProperty) {
IntegerProperty dp = (IntegerProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
return "null";
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString()+"l";
}
return "null";
} else if (p instanceof DoubleProperty) {
DoubleProperty dp = (DoubleProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString() + "d";
}
return "null";
} else if (p instanceof FloatProperty) {
FloatProperty dp = (FloatProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString() + "f";
}
return "null";
} else if (p instanceof BooleanProperty) {
BooleanProperty bp = (BooleanProperty) p;
if (bp.getDefault() != null) {
return bp.getDefault().toString();
}
return "null";
} else if (p instanceof StringProperty) {
StringProperty sp = (StringProperty) p;
if (sp.getDefault() != null) {
String _default = sp.getDefault();
if (sp.getEnum() == null) {
return "\"" + escapeText(_default) + "\"";
} else {
// convert to enum var name later in postProcessModels
return _default;
}
}
return "null";
}
return super.toDefaultValue(p);
}
@ -444,13 +498,26 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
enumVars.add(enumVar);
}
allowableValues.put("enumVars", enumVars);
// handle default value for enum, e.g. available => StatusEnum.AVAILABLE
if (var.defaultValue != null) {
String enumName = null;
for (Map<String, String> enumVar : enumVars) {
if (var.defaultValue.equals(enumVar.get("value"))) {
enumName = enumVar.get("name");
break;
}
}
if (enumName != null) {
var.defaultValue = var.datatypeWithEnum + "." + enumName;
}
}
}
}
return objs;
}
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
if("retrofit".equals(getLibrary())) {
if("retrofit".equals(getLibrary()) || "retrofit2".equals(getLibrary())) {
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
if (operations != null) {
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
@ -466,6 +533,8 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
if (operation.returnType == null) {
operation.returnType = "Void";
}
if ("retrofit2".equals(getLibrary()) && StringUtils.isNotEmpty(operation.path) && operation.path.startsWith("/"))
operation.path = operation.path.substring(1);
}
}
}
@ -582,4 +651,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
return packageName;
}
public void setFullJavaUtil(boolean fullJavaUtil) {
this.fullJavaUtil = fullJavaUtil;
}
}

View File

@ -2,7 +2,9 @@ package io.swagger.codegen.languages;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.SupportingFile;
import io.swagger.models.Operation;
@ -30,7 +32,7 @@ public class JavaInflectorServerCodegen extends JavaClientCodegen implements Cod
sourceFolder = "src/main/java";
modelTemplateFiles.put("model.mustache", ".java");
apiTemplateFiles.put("api.mustache", ".java");
templateDir = "JavaInflector";
embeddedTemplateDir = templateDir = "JavaInflector";
invokerPackage = "io.swagger.handler";
artifactId = "swagger-inflector-server";
@ -121,6 +123,22 @@ public class JavaInflectorServerCodegen extends JavaClientCodegen implements Cod
co.baseName = basePath;
}
@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) {
// handle default value for enum, e.g. available => StatusEnum.available
if (var.isEnum && var.defaultValue != null && !"null".equals(var.defaultValue)) {
var.defaultValue = var.datatypeWithEnum + "." + var.defaultValue;
}
}
}
return objs;
}
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
if (operations != null) {

View File

@ -1,19 +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.codegen.*;
import io.swagger.models.Operation;
import io.swagger.models.Path;
import io.swagger.models.Swagger;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.*;
public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConfig {
protected String title = "Swagger Server";
@ -31,7 +24,7 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
apiTemplateFiles.put("apiService.mustache", ".java");
apiTemplateFiles.put("apiServiceImpl.mustache", ".java");
apiTemplateFiles.put("apiServiceFactory.mustache", ".java");
templateDir = "JavaJaxRS";
embeddedTemplateDir = templateDir = "JavaJaxRS";
apiPackage = System.getProperty("swagger.codegen.jaxrs.apipackage", "io.swagger.api");
modelPackage = System.getProperty("swagger.codegen.jaxrs.modelpackage", "io.swagger.model");
@ -74,13 +67,13 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("ApiException.mustache",
(sourceFolder + File.separator + apiPackage).replace(".", java.io.File.separator), "ApiException.java"));
(sourceFolder + '/' + apiPackage).replace(".", "/"), "ApiException.java"));
supportingFiles.add(new SupportingFile("ApiOriginFilter.mustache",
(sourceFolder + File.separator + apiPackage).replace(".", java.io.File.separator), "ApiOriginFilter.java"));
(sourceFolder + '/' + apiPackage).replace(".", "/"), "ApiOriginFilter.java"));
supportingFiles.add(new SupportingFile("ApiResponseMessage.mustache",
(sourceFolder + File.separator + apiPackage).replace(".", java.io.File.separator), "ApiResponseMessage.java"));
(sourceFolder + '/' + apiPackage).replace(".", "/"), "ApiResponseMessage.java"));
supportingFiles.add(new SupportingFile("NotFoundException.mustache",
(sourceFolder + File.separator + apiPackage).replace(".", java.io.File.separator), "NotFoundException.java"));
(sourceFolder + '/' + apiPackage).replace(".", "/"), "NotFoundException.java"));
supportingFiles.add(new SupportingFile("web.mustache",
("src/main/webapp/WEB-INF"), "web.xml"));
@ -114,6 +107,52 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
co.baseName = basePath;
}
@Override
public void preprocessSwagger(Swagger swagger) {
if(swagger != null && swagger.getPaths() != null) {
for(String pathname : swagger.getPaths().keySet()) {
Path path = swagger.getPath(pathname);
if(path.getOperations() != null) {
for(Operation operation : path.getOperations()) {
if(operation.getTags() != null) {
List<Map<String, String>> tags = new ArrayList<Map<String, String>>();
for(String tag : operation.getTags()) {
Map<String, String> value = new HashMap<String, String>();
value.put("tag", tag);
value.put("hasMore", "true");
tags.add(value);
}
if(tags.size() > 0) {
tags.get(tags.size() - 1).remove("hasMore");
}
if(operation.getTags().size() > 0) {
String tag = operation.getTags().get(0);
operation.setTags(Arrays.asList(tag));
}
operation.setVendorExtension("x-tags", tags);
}
}
}
}
}
}
@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) {
// handle default value for enum, e.g. available => StatusEnum.available
if (var.isEnum && var.defaultValue != null && !"null".equals(var.defaultValue)) {
var.defaultValue = var.datatypeWithEnum + "." + var.defaultValue;
}
}
}
return objs;
}
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
if (operations != null) {
@ -175,9 +214,10 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
result = result.substring(0, ix) + "/impl" + result.substring(ix, result.length() - 5) + "ServiceImpl.java";
String output = System.getProperty("swagger.codegen.jaxrs.impl.source");
if (output != null) {
result = result.replace(apiFileFolder(), implFileFolder(output));
if(output == null) {
output = "src" + File.separator + "main" + File.separator + "java";
}
result = result.replace(apiFileFolder(), implFileFolder(output));
} else if (templateName.endsWith("Factory.mustache")) {
int ix = result.lastIndexOf('/');
result = result.substring(0, ix) + "/factories" + result.substring(ix, result.length() - 5) + "ServiceFactory.java";
@ -195,7 +235,7 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
}
private String implFileFolder(String output) {
return outputFolder + "/" + output + "/" + apiPackage().replace('.', File.separatorChar);
return outputFolder + "/" + output + "/" + apiPackage().replace('.', '/');
}
public boolean shouldOverwrite(String filename) {

View File

@ -1,27 +1,16 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenParameter;
import io.swagger.codegen.CodegenResponse;
import io.swagger.codegen.CodegenType;
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.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import io.swagger.codegen.*;
import io.swagger.models.Swagger;
import io.swagger.util.Yaml;
import java.io.File;
import java.util.*;
import java.util.Map.Entry;
public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig {
protected String apiVersion = "1.0.0";
@ -55,7 +44,7 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
* Template Location. This is the location which templates will be read from. The generator
* will use the resource stream to attempt to read the templates.
*/
templateDir = "nodejs";
embeddedTemplateDir = templateDir = "nodejs";
/**
* Reserved words. Override this with reserved words specific to your language
@ -87,7 +76,7 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
// );
supportingFiles.add(new SupportingFile("swagger.mustache",
"api",
"swagger.json")
"swagger.yaml")
);
supportingFiles.add(new SupportingFile("index.mustache",
"",
@ -97,6 +86,10 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
"",
"package.json")
);
supportingFiles.add(new SupportingFile("README.mustache",
"",
"README.md")
);
if (System.getProperty("noservice") == null) {
apiTemplateFiles.put(
"service.mustache", // the template to use
@ -242,6 +235,14 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
@Override
public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) {
Swagger swagger = (Swagger)objs.get("swagger");
if(swagger != null) {
try {
objs.put("swagger-yaml", Yaml.mapper().writeValueAsString(swagger));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
for (Map<String, Object> operations : getOperations(objs)) {
@SuppressWarnings("unchecked")
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");

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.CodegenProperty;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
@ -19,6 +20,12 @@ import java.util.Set;
import org.apache.commons.lang.StringUtils;
public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
public static final String CLASS_PREFIX = "classPrefix";
public static final String POD_NAME = "podName";
public static final String AUTHOR_NAME = "authorName";
public static final String AUTHOR_EMAIL = "authorEmail";
public static final String GIT_REPO_URL = "gitRepoURL";
public static final String LICENSE = "license";
protected Set<String> foundationClasses = new HashSet<String>();
protected String podName = "SwaggerClient";
protected String podVersion = "1.0.0";
@ -36,7 +43,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
modelTemplateFiles.put("model-body.mustache", ".m");
apiTemplateFiles.put("api-header.mustache", ".h");
apiTemplateFiles.put("api-body.mustache", ".m");
templateDir = "objc";
embeddedTemplateDir = templateDir = "objc";
defaultIncludes.clear();
defaultIncludes.add("bool");
@ -113,13 +120,17 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
instantiationTypes.put("map", "NSMutableDictionary");
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`"));
cliOptions.add(new CliOption("authorName", "Name to use in the podspec file, default: `Swagger`"));
cliOptions.add(new CliOption("authorEmail", "Email to use in the podspec file, default: `apiteam@swagger.io`"));
cliOptions.add(new CliOption("gitRepoURL", "URL for the git repo where this podspec should point to, default: `https://github.com/swagger-api/swagger-codegen`"));
cliOptions.add(new CliOption("license", "License to use in the podspec file, default: `MIT`"));
cliOptions.add(new CliOption(CLASS_PREFIX, "prefix for generated classes (convention: Abbreviation of pod name e.g. `HN` for `HackerNews`).`")
.defaultValue("SWG"));
cliOptions.add(new CliOption(POD_NAME, "cocoapods package name (convention: CameCase).")
.defaultValue("SwaggerClient"));
cliOptions.add(new CliOption(CodegenConstants.POD_VERSION, "cocoapods package version.")
.defaultValue("1.0.0"));
cliOptions.add(new CliOption(AUTHOR_NAME, "Name to use in the podspec file.").defaultValue("Swagger"));
cliOptions.add(new CliOption(AUTHOR_EMAIL, "Email to use in the podspec file.").defaultValue("apiteam@swagger.io"));
cliOptions.add(new CliOption(GIT_REPO_URL, "URL for the git repo where this podspec should point to.")
.defaultValue("https://github.com/swagger-api/swagger-codegen"));
cliOptions.add(new CliOption(LICENSE, "License to use in the podspec file.").defaultValue("MIT"));
}
public CodegenType getTag() {
@ -138,41 +149,41 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey("podName")) {
setPodName((String) additionalProperties.get("podName"));
if (additionalProperties.containsKey(POD_NAME)) {
setPodName((String) additionalProperties.get(POD_NAME));
}
if (additionalProperties.containsKey("podVersion")) {
setPodVersion((String) additionalProperties.get("podVersion"));
if (additionalProperties.containsKey(CodegenConstants.POD_VERSION)) {
setPodVersion((String) additionalProperties.get(CodegenConstants.POD_VERSION));
}
if (additionalProperties.containsKey("classPrefix")) {
setClassPrefix((String) additionalProperties.get("classPrefix"));
if (additionalProperties.containsKey(CLASS_PREFIX)) {
setClassPrefix((String) additionalProperties.get(CLASS_PREFIX));
}
if (additionalProperties.containsKey("authorName")) {
setAuthorName((String) additionalProperties.get("authorName"));
if (additionalProperties.containsKey(AUTHOR_NAME)) {
setAuthorName((String) additionalProperties.get(AUTHOR_NAME));
}
if (additionalProperties.containsKey("authorEmail")) {
setAuthorEmail((String) additionalProperties.get("authorEmail"));
if (additionalProperties.containsKey(AUTHOR_EMAIL)) {
setAuthorEmail((String) additionalProperties.get(AUTHOR_EMAIL));
}
if (additionalProperties.containsKey("gitRepoURL")) {
setGitRepoURL((String) additionalProperties.get("gitRepoURL"));
if (additionalProperties.containsKey(GIT_REPO_URL)) {
setGitRepoURL((String) additionalProperties.get(GIT_REPO_URL));
}
if (additionalProperties.containsKey("license")) {
setLicense((String) additionalProperties.get("license"));
if (additionalProperties.containsKey(LICENSE)) {
setLicense((String) additionalProperties.get(LICENSE));
}
additionalProperties.put("podName", podName);
additionalProperties.put("podVersion", podVersion);
additionalProperties.put("classPrefix", classPrefix);
additionalProperties.put("authorName", authorName);
additionalProperties.put("authorEmail", authorEmail);
additionalProperties.put("gitRepoURL", gitRepoURL);
additionalProperties.put("license", license);
additionalProperties.put(POD_NAME, podName);
additionalProperties.put(CodegenConstants.POD_VERSION, podVersion);
additionalProperties.put(CLASS_PREFIX, classPrefix);
additionalProperties.put(AUTHOR_NAME, authorName);
additionalProperties.put(AUTHOR_EMAIL, authorEmail);
additionalProperties.put(GIT_REPO_URL, gitRepoURL);
additionalProperties.put(LICENSE, license);
String swaggerFolder = podName;

View File

@ -4,10 +4,11 @@ import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CliOption;
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;
@ -16,6 +17,8 @@ import java.util.HashSet;
import org.apache.commons.lang.StringUtils;
public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
public static final String MODULE_NAME = "moduleName";
public static final String MODULE_VERSION = "moduleVersion";
protected String moduleName = "SwaggerClient";
protected String moduleVersion = "1.0.0";
@ -25,7 +28,7 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
outputFolder = "generated-code" + File.separatorChar + "perl";
modelTemplateFiles.put("object.mustache", ".pm");
apiTemplateFiles.put("api.mustache", ".pm");
templateDir = "perl";
embeddedTemplateDir = templateDir = "perl";
reservedWords = new HashSet<String>(
@ -68,8 +71,11 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("object", "object");
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"));
cliOptions.add(new CliOption(MODULE_NAME, "Perl module name (convention: CamelCase).").defaultValue("SwaggerClient"));
cliOptions.add(new CliOption(MODULE_VERSION, "Perl module version.").defaultValue("1.0.0"));
cliOptions.add(new CliOption(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC));
cliOptions.add(new CliOption(CodegenConstants.ENSURE_UNIQUE_PARAMS, CodegenConstants.ENSURE_UNIQUE_PARAMS_DESC));
}
@ -77,21 +83,25 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey("moduleVersion")) {
moduleVersion = (String) additionalProperties.get("moduleVersion");
if (additionalProperties.containsKey(MODULE_VERSION)) {
setModuleVersion((String) additionalProperties.get(MODULE_VERSION));
} else {
additionalProperties.put("moduleVersion", moduleVersion);
additionalProperties.put(MODULE_VERSION, moduleVersion);
}
if (additionalProperties.containsKey("moduleName")) {
moduleName = (String) additionalProperties.get("moduleName");
if (additionalProperties.containsKey(MODULE_NAME)) {
setModuleName((String) additionalProperties.get(MODULE_NAME));
} else {
additionalProperties.put("moduleName", moduleName);
additionalProperties.put(MODULE_NAME, 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"));
supportingFiles.add(new SupportingFile("ApiFactory.mustache", ("lib/WWW/" + moduleName).replace('/', File.separatorChar), "ApiFactory.pm"));
supportingFiles.add(new SupportingFile("Role.mustache", ("lib/WWW/" + moduleName).replace('/', File.separatorChar), "Role.pm"));
supportingFiles.add(new SupportingFile("AutoDoc.mustache", ("lib/WWW/" + moduleName + "/Role").replace('/', File.separatorChar), "AutoDoc.pm"));
supportingFiles.add(new SupportingFile("autodoc.script.mustache", ("bin/").replace('/', File.separatorChar), "autodoc"));
}
public CodegenType getTag() {
@ -229,5 +239,11 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
return underscore(operationId);
}
public void setModuleName(String moduleName) {
this.moduleName = moduleName;
}
public void setModuleVersion(String moduleVersion) {
this.moduleVersion = moduleVersion;
}
}

View File

@ -19,6 +19,11 @@ import java.util.HashSet;
import org.apache.commons.lang3.StringUtils;
public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
public static final String VARIABLE_NAMING_CONVENTION = "variableNamingConvention";
public static final String PACKAGE_PATH = "packagePath";
public static final String SRC_BASE_PATH = "srcBasePath";
public static final String COMPOSER_VENDOR_NAME = "composerVendorName";
public static final String COMPOSER_PROJECT_NAME = "composerProjectName";
protected String invokerPackage = "Swagger\\Client";
protected String composerVendorName = "swagger";
protected String composerProjectName = "swagger-client";
@ -33,7 +38,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
outputFolder = "generated-code" + File.separator + "php";
modelTemplateFiles.put("model.mustache", ".php");
apiTemplateFiles.put("api.mustache", ".php");
templateDir = "php";
embeddedTemplateDir = templateDir = "php";
apiPackage = invokerPackage + "\\Api";
modelPackage = invokerPackage + "\\Model";
@ -86,12 +91,15 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("object", "object");
typeMapping.put("DateTime", "\\DateTime");
cliOptions.add(new CliOption("variableNamingConvention", "naming convention of variable name, e.g. camelCase. Default: snake_case"));
cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
cliOptions.add(new CliOption(VARIABLE_NAMING_CONVENTION, "naming convention of variable name, e.g. camelCase.")
.defaultValue("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(PACKAGE_PATH, "The main package name for classes. e.g. GeneratedPetstore"));
cliOptions.add(new CliOption(SRC_BASE_PATH, "The directory under packagePath to serve as source root."));
cliOptions.add(new CliOption(COMPOSER_VENDOR_NAME, "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(COMPOSER_PROJECT_NAME, "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"));
}
@ -144,16 +152,16 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey("packagePath")) {
this.setPackagePath((String) additionalProperties.get("packagePath"));
if (additionalProperties.containsKey(PACKAGE_PATH)) {
this.setPackagePath((String) additionalProperties.get(PACKAGE_PATH));
} else {
additionalProperties.put("packagePath", packagePath);
additionalProperties.put(PACKAGE_PATH, packagePath);
}
if (additionalProperties.containsKey("srcBasePath")) {
this.setSrcBasePath((String) additionalProperties.get("srcBasePath"));
if (additionalProperties.containsKey(SRC_BASE_PATH)) {
this.setSrcBasePath((String) additionalProperties.get(SRC_BASE_PATH));
} else {
additionalProperties.put("srcBasePath", srcBasePath);
additionalProperties.put(SRC_BASE_PATH, srcBasePath);
}
if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) {
@ -162,28 +170,24 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
}
if (additionalProperties.containsKey(CodegenConstants.MODEL_PACKAGE)) {
this.setModelPackage((String) additionalProperties.get(CodegenConstants.MODEL_PACKAGE));
} else {
if (!additionalProperties.containsKey(CodegenConstants.MODEL_PACKAGE)) {
additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage);
}
if (additionalProperties.containsKey(CodegenConstants.API_PACKAGE)) {
this.setApiPackage((String) additionalProperties.get(CodegenConstants.API_PACKAGE));
} else {
if (!additionalProperties.containsKey(CodegenConstants.API_PACKAGE)) {
additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage);
}
if (additionalProperties.containsKey("composerProjectName")) {
this.setComposerProjectName((String) additionalProperties.get("composerProjectName"));
if (additionalProperties.containsKey(COMPOSER_PROJECT_NAME)) {
this.setComposerProjectName((String) additionalProperties.get(COMPOSER_PROJECT_NAME));
} else {
additionalProperties.put("composerProjectName", composerProjectName);
additionalProperties.put(COMPOSER_PROJECT_NAME, composerProjectName);
}
if (additionalProperties.containsKey("composerVendorName")) {
this.setComposerVendorName((String) additionalProperties.get("composerVendorName"));
if (additionalProperties.containsKey(COMPOSER_VENDOR_NAME)) {
this.setComposerVendorName((String) additionalProperties.get(COMPOSER_VENDOR_NAME));
} else {
additionalProperties.put("composerVendorName", composerVendorName);
additionalProperties.put(COMPOSER_VENDOR_NAME, composerVendorName);
}
if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_VERSION)) {
@ -191,6 +195,10 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
} else {
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
}
if (additionalProperties.containsKey(VARIABLE_NAMING_CONVENTION)) {
this.setParameterNamingConvention((String) additionalProperties.get(VARIABLE_NAMING_CONVENTION));
}
additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\"));
@ -286,7 +294,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
this.variableNamingConvention = variableNamingConvention;
}
private void setComposerVendorName(String composerVendorName) {
public void setComposerVendorName(String composerVendorName) {
this.composerVendorName = composerVendorName;
}
@ -296,10 +304,6 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String toVarName(String name) {
if (additionalProperties.containsKey("variableNamingConvention")) {
this.setParameterNamingConvention((String) additionalProperties.get("variableNamingConvention"));
}
// sanitize name
name = sanitizeName(name);
@ -333,6 +337,9 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
// Note: backslash ("\\") is allowed for e.g. "\\DateTime"
name = name.replaceAll("[^\\w\\\\]+", "_");
// remove dollar sign
name = name.replaceAll("$", "");
// model name cannot use reserved keyword
if (reservedWords.contains(name)) {
escapeReservedWord(name); // e.g. return => _return

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;
@ -27,7 +28,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
outputFolder = "generated-code" + File.separatorChar + "python";
modelTemplateFiles.put("model.mustache", ".py");
apiTemplateFiles.put("api.mustache", ".py");
templateDir = "python";
embeddedTemplateDir = templateDir = "python";
languageSpecificPrimitives.clear();
languageSpecificPrimitives.add("int");
@ -62,30 +63,33 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
"return", "def", "for", "lambda", "try"));
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"));
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "python package name (convention: snake_case).")
.defaultValue("swagger_client"));
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "python package version.")
.defaultValue("1.0.0"));
cliOptions.add(new CliOption(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC));
}
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey("packageName")) {
setPackageName((String) additionalProperties.get("packageName"));
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
}
else {
setPackageName("swagger_client");
}
if (additionalProperties.containsKey("packageVersion")) {
setPackageVersion((String) additionalProperties.get("packageVersion"));
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) {
setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION));
}
else {
setPackageVersion("1.0.0");
}
additionalProperties.put("packageName", packageName);
additionalProperties.put("packageVersion", packageVersion);
additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
additionalProperties.put(CodegenConstants.PACKAGE_VERSION, packageVersion);
String swaggerFolder = packageName;
@ -171,6 +175,9 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
// sanitize name
name = sanitizeName(name);
// remove dollar sign
name = name.replaceAll("$", "");
// if it's all uppper case, convert to lower case
if (name.matches("^[A-Z_]*$")) {
name = name.toLowerCase();
@ -201,6 +208,9 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
public String toModelName(String name) {
name = sanitizeName(name);
// remove dollar sign
name = name.replaceAll("$", "");
// 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");

View File

@ -71,7 +71,7 @@ public class Qt5CPPGenerator extends DefaultCodegen implements CodegenConfig {
* Template Location. This is the location which templates will be read from. The generator
* will use the resource stream to attempt to read the templates.
*/
templateDir = "qt5cpp";
embeddedTemplateDir = templateDir = "qt5cpp";
/**
* Reserved words. Override this with reserved words specific to your language
@ -97,7 +97,9 @@ public class Qt5CPPGenerator extends DefaultCodegen implements CodegenConfig {
Arrays.asList(
"bool",
"qint32",
"qint64")
"qint64",
"float",
"double")
);
supportingFiles.add(new SupportingFile("helpers-header.mustache", sourceFolder, PREFIX + "Helpers.h"));
@ -321,4 +323,4 @@ public class Qt5CPPGenerator extends DefaultCodegen implements CodegenConfig {
public String toApiName(String type) {
return PREFIX + Character.toUpperCase(type.charAt(0)) + type.substring(1) + "Api";
}
}
}

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;
@ -12,10 +13,14 @@ import io.swagger.models.properties.Property;
import java.io.File;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import org.apache.commons.lang.StringUtils;
public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
public static final String GEM_NAME = "gemName";
public static final String MODULE_NAME = "moduleName";
public static final String GEM_VERSION = "gemVersion";
protected String gemName = null;
protected String moduleName = null;
protected String gemVersion = "1.0.0";
@ -28,7 +33,7 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
outputFolder = "generated-code" + File.separator + "ruby";
modelTemplateFiles.put("model.mustache", ".rb");
apiTemplateFiles.put("api.mustache", ".rb");
templateDir = "ruby";
embeddedTemplateDir = templateDir = "ruby";
typeMapping.clear();
languageSpecificPrimitives.clear();
@ -67,21 +72,30 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
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"));
Iterator<CliOption> itr = cliOptions.iterator();
while (itr.hasNext()) {
CliOption opt = itr.next();
if (CodegenConstants.MODEL_PACKAGE.equals(opt.getOpt()) ||
CodegenConstants.API_PACKAGE.equals(opt.getOpt())) {
itr.remove();
}
}
cliOptions.add(new CliOption(GEM_NAME, "gem name (convention: underscore_case).").
defaultValue("swagger_client"));
cliOptions.add(new CliOption(MODULE_NAME, "top module name (convention: CamelCase, usually corresponding" +
" to gem name).").defaultValue("SwaggerClient"));
cliOptions.add(new CliOption(GEM_VERSION, "gem version.").defaultValue("1.0.0"));
}
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey("gemName")) {
setGemName((String) additionalProperties.get("gemName"));
if (additionalProperties.containsKey(GEM_NAME)) {
setGemName((String) additionalProperties.get(GEM_NAME));
}
if (additionalProperties.containsKey("moduleName")) {
setModuleName((String) additionalProperties.get("moduleName"));
if (additionalProperties.containsKey(MODULE_NAME)) {
setModuleName((String) additionalProperties.get(MODULE_NAME));
}
if (gemName == null && moduleName == null) {
@ -93,14 +107,14 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
setModuleName(generateModuleName(gemName));
}
additionalProperties.put("gemName", gemName);
additionalProperties.put("moduleName", moduleName);
additionalProperties.put(GEM_NAME, gemName);
additionalProperties.put(MODULE_NAME, moduleName);
if (additionalProperties.containsKey("gemVersion")) {
setGemVersion((String) additionalProperties.get("gemVersion"));
if (additionalProperties.containsKey(GEM_VERSION)) {
setGemVersion((String) additionalProperties.get(GEM_VERSION));
} else {
// not set, pass the default value to template
additionalProperties.put("gemVersion", gemVersion);
additionalProperties.put(GEM_VERSION, gemVersion);
}
// use constant model/api package (folder path)

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.CodegenConstants;
import io.swagger.codegen.CodegenType;
@ -42,7 +43,7 @@ public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig
outputFolder = "generated-code/scala";
modelTemplateFiles.put("model.mustache", ".scala");
apiTemplateFiles.put("api.mustache", ".scala");
templateDir = "scala";
embeddedTemplateDir = templateDir = "scala";
apiPackage = "io.swagger.client.api";
modelPackage = "io.swagger.client.model";
@ -106,6 +107,9 @@ public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig
);
instantiationTypes.put("array", "ListBuffer");
instantiationTypes.put("map", "HashMap");
cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
}
public CodegenType getTag() {

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.CodegenConstants;
import io.swagger.codegen.CodegenOperation;
@ -29,7 +30,7 @@ public class ScalatraServerCodegen extends DefaultCodegen implements CodegenConf
outputFolder = "generated-code/scalatra";
modelTemplateFiles.put("model.mustache", ".scala");
apiTemplateFiles.put("api.mustache", ".scala");
templateDir = "scalatra";
embeddedTemplateDir = templateDir = "scalatra";
apiPackage = "com.wordnik.client.api";
modelPackage = "com.wordnik.client.model";
@ -117,6 +118,9 @@ public class ScalatraServerCodegen extends DefaultCodegen implements CodegenConf
importMapping.put("LocalDateTime", "org.joda.time.LocalDateTime");
importMapping.put("LocalDate", "org.joda.time.LocalDate");
importMapping.put("LocalTime", "org.joda.time.LocalTime");
cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
}
public CodegenType getTag() {

View File

@ -35,7 +35,7 @@ public class SilexServerCodegen extends DefaultCodegen implements CodegenConfig
modelTemplateFiles.clear();
apiTemplateFiles.clear();
templateDir = "silex";
embeddedTemplateDir = templateDir = "silex";
reservedWords = new HashSet<String>(
Arrays.asList(

View File

@ -29,7 +29,7 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
// no model
modelTemplateFiles.clear();
apiTemplateFiles.put("api.mustache", ".rb");
templateDir = "sinatra";
embeddedTemplateDir = templateDir = "sinatra";
typeMapping.clear();
languageSpecificPrimitives.clear();

View File

@ -15,6 +15,7 @@ import java.util.Map;
import java.util.Iterator;
public class SpringMVCServerCodegen extends JavaClientCodegen implements CodegenConfig {
public static final String CONFIG_PACKAGE = "configPackage";
protected String title = "Petstore Server";
protected String configPackage = "";
@ -23,7 +24,7 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen
outputFolder = "generated-code/javaSpringMVC";
modelTemplateFiles.put("model.mustache", ".java");
apiTemplateFiles.put("api.mustache", ".java");
templateDir = "JavaSpringMVC";
embeddedTemplateDir = templateDir = "JavaSpringMVC";
apiPackage = "io.swagger.api";
modelPackage = "io.swagger.model";
configPackage = "io.swagger.configuration";
@ -36,7 +37,7 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
additionalProperties.put("title", title);
additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage);
additionalProperties.put("configPackage", configPackage);
additionalProperties.put(CONFIG_PACKAGE, configPackage);
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
@ -49,8 +50,7 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen
"Float")
);
cliOptions.add(new CliOption("configPackage", "configuration package for generated code"));
cliOptions.add(new CliOption(CONFIG_PACKAGE, "configuration package for generated code"));
}
public CodegenType getTag() {
@ -69,8 +69,8 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey("configPackage")) {
this.setConfigPackage((String) additionalProperties.get("configPackage"));
if (additionalProperties.containsKey(CONFIG_PACKAGE)) {
this.setConfigPackage((String) additionalProperties.get(CONFIG_PACKAGE));
}
supportingFiles.clear();
@ -193,6 +193,17 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen
String _import = iterator.next().get("import");
if (_import.endsWith(".Object")) iterator.remove();
}
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) {
// handle default value for enum, e.g. available => StatusEnum.available
if (var.isEnum && var.defaultValue != null && !"null".equals(var.defaultValue)) {
var.defaultValue = var.datatypeWithEnum + "." + var.defaultValue;
}
}
}
return objs;
}
}

View File

@ -20,7 +20,7 @@ public class StaticDocCodegen extends DefaultCodegen implements CodegenConfig {
outputFolder = "docs";
modelTemplateFiles.put("model.mustache", ".html");
apiTemplateFiles.put("operation.mustache", ".html");
templateDir = "swagger-static";
embeddedTemplateDir = templateDir = "swagger-static";
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
additionalProperties.put(CodegenConstants.GROUP_ID, groupId);

View File

@ -28,7 +28,7 @@ public class StaticHtmlGenerator extends DefaultCodegen implements CodegenConfig
public StaticHtmlGenerator() {
super();
outputFolder = "docs";
templateDir = "htmlDocs";
embeddedTemplateDir = templateDir = "htmlDocs";
defaultIncludes = new HashSet<String>();

View File

@ -13,7 +13,7 @@ import java.io.File;
public class SwaggerGenerator extends DefaultCodegen implements CodegenConfig {
public SwaggerGenerator() {
super();
templateDir = "swagger";
embeddedTemplateDir = templateDir = "swagger";
outputFolder = "generated-code/swagger";
supportingFiles.add(new SupportingFile("README.md", "", "README.md"));

View File

@ -13,7 +13,7 @@ import java.io.File;
public class SwaggerYamlGenerator extends DefaultCodegen implements CodegenConfig {
public SwaggerYamlGenerator() {
super();
templateDir = "swagger";
embeddedTemplateDir = templateDir = "swagger";
outputFolder = "generated-code/swagger";
supportingFiles.add(new SupportingFile("README.md", "", "README.md"));

View File

@ -24,13 +24,26 @@ 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_]+\\}");
public static final String PROJECT_NAME = "projectName";
public static final String RESPONSE_AS = "responseAs";
public static final String UNWRAP_REQUIRED = "unwrapRequired";
public static final String POD_SOURCE = "podSource";
public static final String POD_AUTHORS = "podAuthors";
public static final String POD_SOCIAL_MEDIA_URL = "podSocialMediaURL";
public static final String POD_DOCSET_URL = "podDocsetURL";
public static final String POD_LICENSE = "podLicense";
public static final String POD_HOMEPAGE = "podHomepage";
public static final String POD_SUMMARY = "podSummary";
public static final String POD_DESCRIPTION = "podDescription";
public static final String POD_SCREENSHOTS = "podScreenshots";
public static final String POD_DOCUMENTATION_URL = "podDocumentationURL";
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";
private static final Pattern PATH_PARAM_PATTERN = Pattern.compile("\\{[a-zA-Z_]+\\}");
public CodegenType getTag() {
return CodegenType.CLIENT;
@ -49,7 +62,7 @@ public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
outputFolder = "generated-code" + File.separator + "swift";
modelTemplateFiles.put("model.mustache", ".swift");
apiTemplateFiles.put("api.mustache", ".swift");
templateDir = "swift";
embeddedTemplateDir = templateDir = "swift";
apiPackage = File.separator + "APIs";
modelPackage = File.separator + "Models";
@ -107,22 +120,22 @@ public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
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 " +
cliOptions.add(new CliOption(PROJECT_NAME, "Project name in Xcode"));
cliOptions.add(new CliOption(RESPONSE_AS, "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 " +
cliOptions.add(new CliOption(UNWRAP_REQUIRED, "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"));
cliOptions.add(new CliOption(POD_SOURCE, "Source information used for Podspec"));
cliOptions.add(new CliOption(CodegenConstants.POD_VERSION, "Version used for Podspec"));
cliOptions.add(new CliOption(POD_AUTHORS, "Authors used for Podspec"));
cliOptions.add(new CliOption(POD_SOCIAL_MEDIA_URL, "Social Media URL used for Podspec"));
cliOptions.add(new CliOption(POD_DOCSET_URL, "Docset URL used for Podspec"));
cliOptions.add(new CliOption(POD_LICENSE, "License used for Podspec"));
cliOptions.add(new CliOption(POD_HOMEPAGE, "Homepage used for Podspec"));
cliOptions.add(new CliOption(POD_SUMMARY, "Summary used for Podspec"));
cliOptions.add(new CliOption(POD_DESCRIPTION, "Description used for Podspec"));
cliOptions.add(new CliOption(POD_SCREENSHOTS, "Screenshots used for Podspec"));
cliOptions.add(new CliOption(POD_DOCUMENTATION_URL, "Documentation URL used for Podspec"));
}
@Override
@ -130,29 +143,29 @@ public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
super.processOpts();
// Setup project name
if (additionalProperties.containsKey("projectName")) {
projectName = (String) additionalProperties.get("projectName");
if (additionalProperties.containsKey(PROJECT_NAME)) {
setProjectName((String) additionalProperties.get(PROJECT_NAME));
} else {
additionalProperties.put("projectName", projectName);
additionalProperties.put(PROJECT_NAME, 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")));
if (additionalProperties.containsKey(UNWRAP_REQUIRED)) {
setUnwrapRequired(Boolean.parseBoolean(String.valueOf(additionalProperties.get(UNWRAP_REQUIRED))));
}
additionalProperties.put("unwrapRequired", unwrapRequired);
additionalProperties.put(UNWRAP_REQUIRED, unwrapRequired);
// Setup unwrapRequired option, which makes all the properties with "required" non-optional
if (additionalProperties.containsKey("responseAs")) {
Object responseAsObject = additionalProperties.get("responseAs");
if (additionalProperties.containsKey(RESPONSE_AS)) {
Object responseAsObject = additionalProperties.get(RESPONSE_AS);
if (responseAsObject instanceof String) {
responseAs = ((String)responseAsObject).split(",");
setResponseAs(((String)responseAsObject).split(","));
} else {
responseAs = (String[]) responseAsObject;
setResponseAs((String[]) responseAsObject);
}
}
additionalProperties.put("responseAs", responseAs);
additionalProperties.put(RESPONSE_AS, responseAs);
if (ArrayUtils.contains(responseAs, LIBRARY_PROMISE_KIT)) {
additionalProperties.put("usePromiseKit", true);
}
@ -308,4 +321,16 @@ public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
return builder.toString();
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
public void setUnwrapRequired(boolean unwrapRequired) {
this.unwrapRequired = unwrapRequired;
}
public void setResponseAs(String[] responseAs) {
this.responseAs = responseAs;
}
}

View File

@ -40,7 +40,7 @@ public class TizenClientCodegen extends DefaultCodegen implements CodegenConfig
modelTemplateFiles.put("model-body.mustache", ".cpp");
apiTemplateFiles.put("api-header.mustache", ".h");
apiTemplateFiles.put("api-body.mustache", ".cpp");
templateDir = "tizen";
embeddedTemplateDir = templateDir = "tizen";
modelPackage = "";
defaultIncludes = new HashSet<String>(

View File

@ -4,7 +4,7 @@ import io.swagger.codegen.SupportingFile;
import java.io.File;
public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCodegen {
@Override
public String getName() {
return "typescript-angular";
@ -19,7 +19,7 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode
outputFolder = "generated-code/typescript-angular";
modelTemplateFiles.put("model.mustache", ".ts");
apiTemplateFiles.put("api.mustache", ".ts");
templateDir = "TypeScript-Angular";
embeddedTemplateDir = 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

@ -17,7 +17,7 @@ public class TypeScriptNodeClientCodegen extends AbstractTypeScriptClientCodegen
public TypeScriptNodeClientCodegen() {
super();
outputFolder = "generated-code/typescript-node";
templateDir = "TypeScript-node";
embeddedTemplateDir = templateDir = "TypeScript-node";
supportingFiles.add(new SupportingFile("api.mustache", null, "api.ts"));
}

View File

@ -55,13 +55,15 @@ public class ApiClient {
private DateFormat dateFormat;
public ApiClient() {
// Use ISO 8601 format for date and datetime.
// See https://en.wikipedia.org/wiki/ISO_8601
this.dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
// Use RFC3339 format for date and datetime.
// See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14
this.dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
// Use UTC as the default time zone.
this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
this.json.setDateFormat((DateFormat) dateFormat.clone());
// Set default User-Agent.
setUserAgent("Java-Swagger");
@ -74,6 +76,13 @@ public class ApiClient {
authentications = Collections.unmodifiableMap(authentications);
}
/**
* Gets the JSON instance to do JSON serialization and deserialization.
*/
public JSON getJSON() {
return json;
}
public String getBasePath() {
return basePath;
}
@ -166,6 +175,19 @@ public class ApiClient {
throw new RuntimeException("No API key authentication configured!");
}
/**
* Helper method to set access token for the first OAuth2 authentication.
*/
public void setAccessToken(String accessToken) {
for (Authentication auth : authentications.values()) {
if (auth instanceof OAuth) {
((OAuth) auth).setAccessToken(accessToken);
return;
}
}
throw new RuntimeException("No OAuth2 authentication configured!");
}
/**
* Set the User-Agent header's value (by adding to the default header map).
*/
@ -214,6 +236,8 @@ public class ApiClient {
*/
public ApiClient setDateFormat(DateFormat dateFormat) {
this.dateFormat = dateFormat;
// also set the date format for model (de)serialization with Date properties
this.json.setDateFormat((DateFormat) dateFormat.clone());
return this;
}

View File

@ -4,6 +4,8 @@ import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.datatype.joda.*;
import java.text.DateFormat;
import java.io.IOException;
{{>generatedAnnotation}}
@ -20,6 +22,13 @@ public class JSON {
mapper.registerModule(new JodaModule());
}
/**
* Set the date format for JSON (de)serialization with Date properties.
*/
public void setDateFormat(DateFormat dateFormat) {
mapper.setDateFormat(dateFormat);
}
/**
* Serialize the given Java object into JSON string.
*/

View File

@ -0,0 +1,43 @@
# {{artifactId}}
## Requirements
Building the API client library requires [Maven](https://maven.apache.org/) to be installed.
## Installation & Usage
To install the API client library to your local Maven repository, simply execute:
```shell
mvn install
```
To deploy it to a remote Maven repository instead, configure the settings of the repository and execute:
```shell
mvn deploy
```
Refer to the [official documentation](https://maven.apache.org/plugins/maven-deploy-plugin/usage.html) for more information.
After the client libarary is installed/deployed, you can use it in your Maven project by adding the following to your *pom.xml*:
```xml
<dependency>
<groupId>{{groupId}}</groupId>
<artifactId>{{artifactId}}</artifactId>
<version>{{artifactVersion}}</version>
<scope>compile</scope>
</dependency>
```
## Recommendation
It's recommended to create an instance of `ApiClient` per thread in a multithreaded environment to avoid any potential issue.
## Author
{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}}
{{/hasMore}}{{/apis}}{{/apiInfo}}

View File

@ -64,7 +64,7 @@ public class {{classname}} {
{{/queryParams}}
{{#headerParams}}if ({{paramName}} != null)
{{localVariablePrefix}}headerParams.put("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}}));
{{localVariablePrefix}}headerParams.put("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}}));
{{/headerParams}}
{{#formParams}}if ({{paramName}} != null)

View File

@ -7,8 +7,20 @@ import java.util.List;
{{>generatedAnnotation}}
public class OAuth implements Authentication {
private String accessToken;
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
@Override
public void applyToParams(List<Pair> queryParams, Map<String, String> headerParams) {
// TODO: support oauth
if (accessToken != null) {
headerParams.put("Authorization", "Bearer " + accessToken);
}
}
}

View File

@ -18,72 +18,76 @@ repositories {
if(hasProperty('target') && target == 'android') {
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
android {
compileSdkVersion 22
buildToolsVersion '22.0.0'
defaultConfig {
minSdkVersion 14
targetSdkVersion 22
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
// Rename the aar correctly
libraryVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.aar')) {
def fileName = "${project.name}-${variant.baseName}-${version}.aar"
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
}
afterEvaluate {
android.libraryVariants.all { variant ->
def task = project.tasks.create "jar${variant.name.capitalize()}", Jar
task.description = "Create jar artifact for ${variant.name}"
task.dependsOn variant.javaCompile
task.from variant.javaCompile.destinationDir
task.destinationDir = project.file("${project.buildDir}/outputs/jar")
task.archiveName = "${project.name}-${variant.baseName}-${version}.jar"
artifacts.add('archives', task);
}
}
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
artifacts {
archives sourcesJar
}
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
android {
compileSdkVersion 22
buildToolsVersion '22.0.0'
defaultConfig {
minSdkVersion 14
targetSdkVersion 22
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
// Rename the aar correctly
libraryVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.aar')) {
def fileName = "${project.name}-${variant.baseName}-${version}.aar"
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
dependencies {
provided 'javax.annotation:jsr250-api:1.0'
}
}
afterEvaluate {
android.libraryVariants.all { variant ->
def task = project.tasks.create "jar${variant.name.capitalize()}", Jar
task.description = "Create jar artifact for ${variant.name}"
task.dependsOn variant.javaCompile
task.from variant.javaCompile.destinationDir
task.destinationDir = project.file("${project.buildDir}/outputs/jar")
task.archiveName = "${project.name}-${variant.baseName}-${version}.jar"
artifacts.add('archives', task);
}
}
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
artifacts {
archives sourcesJar
}
} else {
apply plugin: 'java'
apply plugin: 'maven'
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
install {
repositories.mavenInstaller {
pom.artifactId = '{{artifactId}}'
}
}
task execute(type:JavaExec) {
main = System.getProperty('mainClass')
classpath = sourceSets.main.runtimeClasspath
}
apply plugin: 'java'
apply plugin: 'maven'
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
install {
repositories.mavenInstaller {
pom.artifactId = '{{artifactId}}'
}
}
task execute(type:JavaExec) {
main = System.getProperty('mainClass')
classpath = sourceSets.main.runtimeClasspath
}
}
ext {

View File

@ -45,6 +45,7 @@ import {{invokerPackage}}.auth.OAuth;
{{>generatedAnnotation}}
public class ApiClient {
private Client client;
private Map<String, Client> hostMap = new HashMap<String, Client>();
private Map<String, String> defaultHeaderMap = new HashMap<String, String>();
private boolean debugging = false;
@ -59,16 +60,20 @@ public class ApiClient {
private DateFormat dateFormat;
public ApiClient() {
// Use ISO 8601 format for date and datetime.
// See https://en.wikipedia.org/wiki/ISO_8601
this.dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
// Use RFC3339 format for date and datetime.
// See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14
this.dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
// Use UTC as the default time zone.
this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
this.json.setDateFormat((DateFormat) dateFormat.clone());
// Set default User-Agent.
setUserAgent("Java-Swagger");
buildClient();
// Setup authentications (key: authentication name, value: authentication).
authentications = new HashMap<String, Authentication>();{{#authMethods}}{{#isBasic}}
authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}}
@ -78,6 +83,13 @@ public class ApiClient {
authentications = Collections.unmodifiableMap(authentications);
}
/**
* Gets the JSON instance to do JSON serialization and deserialization.
*/
public JSON getJSON() {
return json;
}
public String getBasePath() {
return basePath;
}
@ -170,6 +182,19 @@ public class ApiClient {
throw new RuntimeException("No API key authentication configured!");
}
/**
* Helper method to set access token for the first OAuth2 authentication.
*/
public void setAccessToken(String accessToken) {
for (Authentication auth : authentications.values()) {
if (auth instanceof OAuth) {
((OAuth) auth).setAccessToken(accessToken);
return;
}
}
throw new RuntimeException("No OAuth2 authentication configured!");
}
/**
* Set the User-Agent header's value (by adding to the default header map).
*/
@ -203,6 +228,7 @@ public class ApiClient {
*/
public ApiClient setDebugging(boolean debugging) {
this.debugging = debugging;
buildClient();
return this;
}
@ -218,6 +244,8 @@ public class ApiClient {
*/
public ApiClient setDateFormat(DateFormat dateFormat) {
this.dateFormat = dateFormat;
// also set the date format for model (de)serialization with Date properties
this.json.setDateFormat((DateFormat) dateFormat.clone());
return this;
}
@ -419,13 +447,6 @@ public class ApiClient {
public <T> T invokeAPI(String path, String method, List<Pair> queryParams, Object body, Map<String, String> headerParams, Map<String, Object> formParams, String accept, String contentType, String[] authNames, TypeRef returnType) throws ApiException {
updateParamsForAuth(authNames, queryParams, headerParams);
final ClientConfig clientConfig = new ClientConfig();
clientConfig.register(MultiPartFeature.class);
if (debugging) {
clientConfig.register(LoggingFilter.class);
}
Client client = ClientBuilder.newClient(clientConfig);
WebTarget target = client.target(this.basePath).path(path);
if (queryParams != null) {
@ -537,6 +558,15 @@ public class ApiClient {
}
}
private void buildClient() {
final ClientConfig clientConfig = new ClientConfig();
clientConfig.register(MultiPartFeature.class);
if (debugging) {
clientConfig.register(LoggingFilter.class);
}
this.client = ClientBuilder.newClient(clientConfig);
}
private Map<String, List<String>> buildResponseHeaders(Response response) {
Map<String, List<String>> responseHeaders = new HashMap<String, List<String>>();
for (Entry<String, List<Object>> entry: response.getHeaders().entrySet()) {

View File

@ -18,72 +18,76 @@ repositories {
if(hasProperty('target') && target == 'android') {
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
android {
compileSdkVersion 22
buildToolsVersion '22.0.0'
defaultConfig {
minSdkVersion 14
targetSdkVersion 22
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
// Rename the aar correctly
libraryVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.aar')) {
def fileName = "${project.name}-${variant.baseName}-${version}.aar"
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
}
afterEvaluate {
android.libraryVariants.all { variant ->
def task = project.tasks.create "jar${variant.name.capitalize()}", Jar
task.description = "Create jar artifact for ${variant.name}"
task.dependsOn variant.javaCompile
task.from variant.javaCompile.destinationDir
task.destinationDir = project.file("${project.buildDir}/outputs/jar")
task.archiveName = "${project.name}-${variant.baseName}-${version}.jar"
artifacts.add('archives', task);
}
}
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
artifacts {
archives sourcesJar
}
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
android {
compileSdkVersion 22
buildToolsVersion '22.0.0'
defaultConfig {
minSdkVersion 14
targetSdkVersion 22
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
// Rename the aar correctly
libraryVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.aar')) {
def fileName = "${project.name}-${variant.baseName}-${version}.aar"
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
dependencies {
provided 'javax.annotation:jsr250-api:1.0'
}
}
afterEvaluate {
android.libraryVariants.all { variant ->
def task = project.tasks.create "jar${variant.name.capitalize()}", Jar
task.description = "Create jar artifact for ${variant.name}"
task.dependsOn variant.javaCompile
task.from variant.javaCompile.destinationDir
task.destinationDir = project.file("${project.buildDir}/outputs/jar")
task.archiveName = "${project.name}-${variant.baseName}-${version}.jar"
artifacts.add('archives', task);
}
}
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
artifacts {
archives sourcesJar
}
} else {
apply plugin: 'java'
apply plugin: 'maven'
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
install {
repositories.mavenInstaller {
pom.artifactId = '{{artifactId}}'
}
}
task execute(type:JavaExec) {
main = System.getProperty('mainClass')
classpath = sourceSets.main.runtimeClasspath
}
apply plugin: 'java'
apply plugin: 'maven'
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
install {
repositories.mavenInstaller {
pom.artifactId = '{{artifactId}}'
}
}
task execute(type:JavaExec) {
main = System.getProperty('mainClass')
classpath = sourceSets.main.runtimeClasspath
}
}
ext {

View File

@ -162,7 +162,7 @@
</dependencies>
<properties>
<swagger-annotations-version>1.5.0</swagger-annotations-version>
<jersey-version>2.6</jersey-version>
<jersey-version>2.12</jersey-version>
<jackson-version>2.4.2</jackson-version>
<jodatime-version>2.3</jodatime-version>
<maven-plugin-version>1.0.0</maven-plugin-version>

View File

@ -75,13 +75,11 @@ public class ApiClient {
private int statusCode;
private Map<String, List<String>> responseHeaders;
private String dateFormat;
private DateFormat dateFormatter;
private DateFormat dateFormat;
private DateFormat datetimeFormat;
private boolean lenientDatetimeFormat;
private int dateLength;
private String datetimeFormat;
private DateFormat datetimeFormatter;
private InputStream sslCaCert;
private boolean verifyingSsl;
@ -95,10 +93,19 @@ public class ApiClient {
json = new JSON(this);
// Use ISO 8601 format for date and datetime.
// See https://en.wikipedia.org/wiki/ISO_8601
setDateFormat("yyyy-MM-dd");
setDatetimeFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
/*
* Use RFC3339 format for date and datetime.
* See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14
*/
this.dateFormat = new SimpleDateFormat("yyyy-MM-dd");
// Always use UTC as the default time zone when dealing with date (without time).
this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
// Use the system's default time zone when dealing with datetime (mainly formatting).
this.datetimeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
// Be lenient on datetime formats when parsing datetime from string.
// See <code>parseDatetime</code>.
this.lenientDatetimeFormat = true;
// Set default User-Agent.
setUserAgent("Java-Swagger");
@ -186,32 +193,35 @@ public class ApiClient {
return this;
}
public String getDateFormat() {
public DateFormat getDateFormat() {
return dateFormat;
}
public ApiClient setDateFormat(String dateFormat) {
public ApiClient setDateFormat(DateFormat dateFormat) {
this.dateFormat = dateFormat;
this.dateFormatter = new SimpleDateFormat(dateFormat);
// Use UTC as the default time zone.
this.dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
this.dateLength = this.dateFormatter.format(new Date()).length();
this.dateLength = this.dateFormat.format(new Date()).length();
return this;
}
public String getDatetimeFormat() {
public DateFormat getDatetimeFormat() {
return datetimeFormat;
}
public ApiClient setDatetimeFormat(String datetimeFormat) {
public ApiClient setDatetimeFormat(DateFormat datetimeFormat) {
this.datetimeFormat = datetimeFormat;
return this;
}
this.datetimeFormatter = new SimpleDateFormat(datetimeFormat);
// Note: The datetime formatter uses the system's default time zone.
/**
* Whether to allow various ISO 8601 datetime formats when parsing a datetime string.
* @see #parseDatetime(String)
*/
public boolean isLenientDatetimeFormat() {
return lenientDatetimeFormat;
}
public ApiClient setLenientDatetimeFormat(boolean lenientDatetimeFormat) {
this.lenientDatetimeFormat = lenientDatetimeFormat;
return this;
}
@ -225,15 +235,15 @@ public class ApiClient {
if (str == null)
return null;
try {
return dateFormatter.parse(str);
return dateFormat.parse(str);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
/**
* Parse the given date-time string into Date object.
* The default <code>datetimeFormat</code> supports these ISO 8601 datetime formats:
* Parse the given datetime string into Date object.
* When <code>lenientDatetimeFormat</code> is enabled, the following ISO 8601 datetime formats are supported:
* 2015-08-16T08:20:05Z
* 2015-8-16T8:20:05Z
* 2015-08-16T08:20:05+00:00
@ -253,25 +263,25 @@ public class ApiClient {
if (str == null)
return null;
if ("yyyy-MM-dd'T'HH:mm:ss.SSSZ".equals(datetimeFormat)) {
if (lenientDatetimeFormat) {
/*
* When the default datetime format is used, process the given string
* When lenientDatetimeFormat is enabled, process the given string
* to support various formats defined by ISO 8601.
*/
// normalize time zone
// trailing "Z": 2015-08-16T08:20:05Z => 2015-08-16T08:20:05+0000
str = str.replaceAll("[zZ]\\z", "+0000");
// remove colon: 2015-08-16T08:20:05+00:00 => 2015-08-16T08:20:05+0000
str = str.replaceAll("([+-]\\d{2}):(\\d{2})\\z", "$1$2");
// expand time zone: 2015-08-16T08:20:05+00 => 2015-08-16T08:20:05+0000
str = str.replaceAll("([+-]\\d{2})\\z", "$100");
// trailing "Z": 2015-08-16T08:20:05Z => 2015-08-16T08:20:05+00:00
str = str.replaceAll("[zZ]\\z", "+00:00");
// add colon: 2015-08-16T08:20:05+0000 => 2015-08-16T08:20:05+00:00
str = str.replaceAll("([+-]\\d{2})(\\d{2})\\z", "$1:$2");
// expand time zone: 2015-08-16T08:20:05+00 => 2015-08-16T08:20:05+00:00
str = str.replaceAll("([+-]\\d{2})\\z", "$1:00");
// add milliseconds when missing
// 2015-08-16T08:20:05+0000 => 2015-08-16T08:20:05.000+0000
str = str.replaceAll("(:\\d{1,2})([+-]\\d{4})\\z", "$1.000$2");
// 2015-08-16T08:20:05+00:00 => 2015-08-16T08:20:05.000+00:00
str = str.replaceAll("(:\\d{1,2})([+-]\\d{2}:\\d{2})\\z", "$1.000$2");
}
try {
return datetimeFormatter.parse(str);
return datetimeFormat.parse(str);
} catch (ParseException e) {
throw new RuntimeException(e);
}
@ -290,14 +300,14 @@ public class ApiClient {
* Format the given Date object into string.
*/
public String formatDate(Date date) {
return dateFormatter.format(date);
return dateFormat.format(date);
}
/**
* Format the given Date object into string.
*/
public String formatDatetime(Date date) {
return datetimeFormatter.format(date);
return datetimeFormat.format(date);
}
/**
@ -369,6 +379,19 @@ public class ApiClient {
throw new RuntimeException("No API key authentication configured!");
}
/**
* Helper method to set access token for the first OAuth2 authentication.
*/
public void setAccessToken(String accessToken) {
for (Authentication auth : authentications.values()) {
if (auth instanceof OAuth) {
((OAuth) auth).setAccessToken(accessToken);
return;
}
}
throw new RuntimeException("No OAuth2 authentication configured!");
}
/**
* Set the User-Agent header's value (by adding to the default header map).
*/

View File

@ -18,72 +18,76 @@ repositories {
if(hasProperty('target') && target == 'android') {
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
android {
compileSdkVersion 22
buildToolsVersion '22.0.0'
defaultConfig {
minSdkVersion 14
targetSdkVersion 22
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
// Rename the aar correctly
libraryVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.aar')) {
def fileName = "${project.name}-${variant.baseName}-${version}.aar"
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
}
afterEvaluate {
android.libraryVariants.all { variant ->
def task = project.tasks.create "jar${variant.name.capitalize()}", Jar
task.description = "Create jar artifact for ${variant.name}"
task.dependsOn variant.javaCompile
task.from variant.javaCompile.destinationDir
task.destinationDir = project.file("${project.buildDir}/outputs/jar")
task.archiveName = "${project.name}-${variant.baseName}-${version}.jar"
artifacts.add('archives', task);
}
}
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
artifacts {
archives sourcesJar
}
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
android {
compileSdkVersion 22
buildToolsVersion '22.0.0'
defaultConfig {
minSdkVersion 14
targetSdkVersion 22
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
// Rename the aar correctly
libraryVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.aar')) {
def fileName = "${project.name}-${variant.baseName}-${version}.aar"
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
dependencies {
provided 'javax.annotation:jsr250-api:1.0'
}
}
afterEvaluate {
android.libraryVariants.all { variant ->
def task = project.tasks.create "jar${variant.name.capitalize()}", Jar
task.description = "Create jar artifact for ${variant.name}"
task.dependsOn variant.javaCompile
task.from variant.javaCompile.destinationDir
task.destinationDir = project.file("${project.buildDir}/outputs/jar")
task.archiveName = "${project.name}-${variant.baseName}-${version}.jar"
artifacts.add('archives', task);
}
}
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
artifacts {
archives sourcesJar
}
} else {
apply plugin: 'java'
apply plugin: 'maven'
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
install {
repositories.mavenInstaller {
pom.artifactId = '{{artifactId}}'
}
}
task execute(type:JavaExec) {
main = System.getProperty('mainClass')
classpath = sourceSets.main.runtimeClasspath
}
apply plugin: 'java'
apply plugin: 'maven'
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
install {
repositories.mavenInstaller {
pom.artifactId = '{{artifactId}}'
}
}
task execute(type:JavaExec) {
main = System.getProperty('mainClass')
classpath = sourceSets.main.runtimeClasspath
}
}
dependencies {

View File

@ -28,6 +28,7 @@ import com.squareup.okhttp.OkHttpClient;
import {{invokerPackage}}.auth.HttpBasicAuth;
import {{invokerPackage}}.auth.ApiKeyAuth;
import {{invokerPackage}}.auth.OAuth;
import {{invokerPackage}}.auth.OAuth.AccessTokenListener;
import {{invokerPackage}}.auth.OAuthFlow;
@ -44,12 +45,7 @@ public class ApiClient {
public ApiClient(String[] authNames) {
this();
okClient = new OkHttpClient();
adapterBuilder.setClient(new OkClient(okClient));
for(String authName : authNames) {
if (apiAuthorizations.containsKey(authName)) {
throw new RuntimeException("auth name \"" + authName + "\" already in api authorizations");
}{{#hasAuthMethods}}
for(String authName : authNames) { {{#hasAuthMethods}}
Interceptor auth;
{{#authMethods}}if (authName == "{{name}}") { {{#isBasic}}
auth = new HttpBasicAuth();{{/isBasic}}{{#isApiKey}}
@ -58,10 +54,9 @@ public class ApiClient {
} else {{/authMethods}}{
throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names");
}
apiAuthorizations.put(authName, auth);{{/hasAuthMethods}}{{^hasAuthMethods}}
addAuthorization(authName, auth);{{/hasAuthMethods}}{{^hasAuthMethods}}
throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names");{{/hasAuthMethods}}
}
addAuthsToOkClient(okClient);
}
/**
@ -115,9 +110,12 @@ public class ApiClient {
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
.create();
okClient = new OkHttpClient();
adapterBuilder = new RestAdapter
.Builder()
.setEndpoint("{{basePath}}")
.setClient(new OkClient(okClient))
.setConverter(new GsonConverterWrapper(gson));
}
@ -224,6 +222,33 @@ public class ApiClient {
}
}
/**
* Configures a listener which is notified when a new access token is received.
* @param accessTokenListener
*/
public void registerAccessTokenListener(AccessTokenListener accessTokenListener) {
for(Interceptor apiAuthorization : apiAuthorizations.values()) {
if (apiAuthorization instanceof OAuth) {
OAuth oauth = (OAuth) apiAuthorization;
oauth.registerAccessTokenListener(accessTokenListener);
return;
}
}
}
/**
* Adds an authorization to be used by the client
* @param authName
* @param authorization
*/
public void addAuthorization(String authName, Interceptor authorization) {
if (apiAuthorizations.containsKey(authName)) {
throw new RuntimeException("auth name \"" + authName + "\" already in api authorizations");
}
apiAuthorizations.put(authName, authorization);
okClient.interceptors().add(authorization);
}
public Map<String, Interceptor> getApiAuthorizations() {
return apiAuthorizations;
}

View File

@ -1,6 +1,7 @@
package {{invokerPackage}}.auth;
import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;
import static java.net.HttpURLConnection.HTTP_FORBIDDEN;
import java.io.IOException;
import java.util.Map;
@ -14,6 +15,7 @@ import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.types.GrantType;
import org.apache.oltu.oauth2.common.token.BasicOAuthToken;
import com.squareup.okhttp.Interceptor;
import com.squareup.okhttp.OkHttpClient;
@ -23,12 +25,18 @@ import com.squareup.okhttp.Response;
public class OAuth implements Interceptor {
public interface AccessTokenListener {
public void notify(BasicOAuthToken token);
}
private volatile String accessToken;
private OAuthClient oauthClient;
private TokenRequestBuilder tokenRequestBuilder;
private AuthenticationRequestBuilder authenticationRequestBuilder;
private AccessTokenListener accessTokenListener;
public OAuth( OkHttpClient client, TokenRequestBuilder requestBuilder ) {
this.oauthClient = new OAuthClient(new OAuthOkHttpClient(client));
this.tokenRequestBuilder = requestBuilder;
@ -78,47 +86,67 @@ public class OAuth implements Interceptor {
updateAccessToken(null);
}
// Build the request
Builder rb = request.newBuilder();
String requestAccessToken = new String(getAccessToken());
try {
oAuthRequest = new OAuthBearerClientRequest(request.urlString())
.setAccessToken(requestAccessToken)
.buildHeaderMessage();
} catch (OAuthSystemException e) {
throw new IOException(e);
if (getAccessToken() != null) {
// Build the request
Builder rb = request.newBuilder();
String requestAccessToken = new String(getAccessToken());
try {
oAuthRequest = new OAuthBearerClientRequest(request.urlString())
.setAccessToken(requestAccessToken)
.buildHeaderMessage();
} catch (OAuthSystemException e) {
throw new IOException(e);
}
for ( Map.Entry<String, String> header : oAuthRequest.getHeaders().entrySet() ) {
rb.addHeader(header.getKey(), header.getValue());
}
rb.url( oAuthRequest.getLocationUri());
//Execute the request
Response response = chain.proceed(rb.build());
// 401 most likely indicates that access token has expired.
// Time to refresh and resend the request
if ( response != null && (response.code() == HTTP_UNAUTHORIZED | response.code() == HTTP_FORBIDDEN) ) {
if (updateAccessToken(requestAccessToken)) {
return intercept( chain );
}
}
return response;
} else {
return chain.proceed(chain.request());
}
for ( Map.Entry<String, String> header : oAuthRequest.getHeaders().entrySet() ) {
rb.addHeader(header.getKey(), header.getValue());
}
rb.url( oAuthRequest.getLocationUri());
//Execute the request
Response response = chain.proceed(rb.build());
// 401 most likely indicates that access token has expired.
// Time to refresh and resend the request
if ( response.code() == HTTP_UNAUTHORIZED ) {
updateAccessToken(requestAccessToken);
return intercept( chain );
}
return response;
}
public synchronized void updateAccessToken(String requestAccessToken) throws IOException {
/*
* Returns true if the access token has been updated
*/
public synchronized boolean updateAccessToken(String requestAccessToken) throws IOException {
if (getAccessToken() == null || getAccessToken().equals(requestAccessToken)) {
try {
OAuthJSONAccessTokenResponse accessTokenResponse;
accessTokenResponse = oauthClient.accessToken(this.tokenRequestBuilder.buildBodyMessage());
setAccessToken(accessTokenResponse.getAccessToken());
OAuthJSONAccessTokenResponse accessTokenResponse = oauthClient.accessToken(this.tokenRequestBuilder.buildBodyMessage());
if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) {
setAccessToken(accessTokenResponse.getAccessToken());
if (accessTokenListener != null) {
accessTokenListener.notify((BasicOAuthToken) accessTokenResponse.getOAuthToken());
}
return getAccessToken().equals(requestAccessToken);
} else {
return false;
}
} catch (OAuthSystemException e) {
throw new IOException(e);
} catch (OAuthProblemException e) {
throw new IOException(e);
}
}
return true;
}
public void registerAccessTokenListener(AccessTokenListener accessTokenListener) {
this.accessTokenListener = accessTokenListener;
}
public synchronized String getAccessToken() {

View File

@ -18,72 +18,76 @@ repositories {
if(hasProperty('target') && target == 'android') {
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
android {
compileSdkVersion 22
buildToolsVersion '22.0.0'
defaultConfig {
minSdkVersion 14
targetSdkVersion 22
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
// Rename the aar correctly
libraryVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.aar')) {
def fileName = "${project.name}-${variant.baseName}-${version}.aar"
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
}
afterEvaluate {
android.libraryVariants.all { variant ->
def task = project.tasks.create "jar${variant.name.capitalize()}", Jar
task.description = "Create jar artifact for ${variant.name}"
task.dependsOn variant.javaCompile
task.from variant.javaCompile.destinationDir
task.destinationDir = project.file("${project.buildDir}/outputs/jar")
task.archiveName = "${project.name}-${variant.baseName}-${version}.jar"
artifacts.add('archives', task);
}
}
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
artifacts {
archives sourcesJar
}
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
android {
compileSdkVersion 22
buildToolsVersion '22.0.0'
defaultConfig {
minSdkVersion 14
targetSdkVersion 22
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
// Rename the aar correctly
libraryVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.aar')) {
def fileName = "${project.name}-${variant.baseName}-${version}.aar"
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
dependencies {
provided 'javax.annotation:jsr250-api:1.0'
}
}
afterEvaluate {
android.libraryVariants.all { variant ->
def task = project.tasks.create "jar${variant.name.capitalize()}", Jar
task.description = "Create jar artifact for ${variant.name}"
task.dependsOn variant.javaCompile
task.from variant.javaCompile.destinationDir
task.destinationDir = project.file("${project.buildDir}/outputs/jar")
task.archiveName = "${project.name}-${variant.baseName}-${version}.jar"
artifacts.add('archives', task);
}
}
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
artifacts {
archives sourcesJar
}
} else {
apply plugin: 'java'
apply plugin: 'maven'
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
install {
repositories.mavenInstaller {
pom.artifactId = '{{artifactId}}'
}
}
task execute(type:JavaExec) {
main = System.getProperty('mainClass')
classpath = sourceSets.main.runtimeClasspath
}
apply plugin: 'java'
apply plugin: 'maven'
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
install {
repositories.mavenInstaller {
pom.artifactId = '{{artifactId}}'
}
}
task execute(type:JavaExec) {
main = System.getProperty('mainClass')
classpath = sourceSets.main.runtimeClasspath
}
}
ext {

View File

@ -0,0 +1,343 @@
package {{invokerPackage}};
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder;
import retrofit.Converter;
import retrofit.Retrofit;
import retrofit.GsonConverterFactory;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonParseException;
import com.squareup.okhttp.Interceptor;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.ResponseBody;
import {{invokerPackage}}.auth.HttpBasicAuth;
import {{invokerPackage}}.auth.ApiKeyAuth;
import {{invokerPackage}}.auth.OAuth;
import {{invokerPackage}}.auth.OAuth.AccessTokenListener;
import {{invokerPackage}}.auth.OAuthFlow;
public class ApiClient {
private Map<String, Interceptor> apiAuthorizations;
private OkHttpClient okClient;
private Retrofit.Builder adapterBuilder;
public ApiClient() {
apiAuthorizations = new LinkedHashMap<String, Interceptor>();
createDefaultAdapter();
}
public ApiClient(String[] authNames) {
this();
for(String authName : authNames) { {{#hasAuthMethods}}
Interceptor auth;
{{#authMethods}}if (authName == "{{name}}") { {{#isBasic}}
auth = new HttpBasicAuth();{{/isBasic}}{{#isApiKey}}
auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}");{{/isApiKey}}{{#isOAuth}}
auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{#hasMore}}, {{/hasMore}}{{/scopes}}");{{/isOAuth}}
} else {{/authMethods}}{
throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names");
}
addAuthorization(authName, auth);{{/hasAuthMethods}}{{^hasAuthMethods}}
throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names");{{/hasAuthMethods}}
}
}
/**
* Basic constructor for single auth name
* @param authName
*/
public ApiClient(String authName) {
this(new String[]{authName});
}
/**
* Helper constructor for single api key
* @param authName
* @param apiKey
*/
public ApiClient(String authName, String apiKey) {
this(authName);
this.setApiKey(apiKey);
}
/**
* Helper constructor for single basic auth or password oauth2
* @param authName
* @param username
* @param password
*/
public ApiClient(String authName, String username, String password) {
this(authName);
this.setCredentials(username, password);
}
/**
* Helper constructor for single password oauth2
* @param authName
* @param clientId
* @param secret
* @param username
* @param password
*/
public ApiClient(String authName, String clientId, String secret, String username, String password) {
this(authName);
this.getTokenEndPoint()
.setClientId(clientId)
.setClientSecret(secret)
.setUsername(username)
.setPassword(password);
}
public void createDefaultAdapter() {
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
.create();
okClient = new OkHttpClient();
String baseUrl = "{{basePath}}";
if(!baseUrl.endsWith("/"))
baseUrl = baseUrl + "/";
adapterBuilder = new Retrofit
.Builder()
.baseUrl(baseUrl)
.client(okClient)
.addConverterFactory(GsonCustomConverterFactory.create(gson));
}
public <S> S createService(Class<S> serviceClass) {
return adapterBuilder.build().create(serviceClass);
}
/**
* Helper method to configure the first api key found
* @param apiKey
*/
private void setApiKey(String apiKey) {
for(Interceptor apiAuthorization : apiAuthorizations.values()) {
if (apiAuthorization instanceof ApiKeyAuth) {
ApiKeyAuth keyAuth = (ApiKeyAuth) apiAuthorization;
keyAuth.setApiKey(apiKey);
return;
}
}
}
/**
* Helper method to configure the username/password for basic auth or password oauth
* @param username
* @param password
*/
private void setCredentials(String username, String password) {
for(Interceptor apiAuthorization : apiAuthorizations.values()) {
if (apiAuthorization instanceof HttpBasicAuth) {
HttpBasicAuth basicAuth = (HttpBasicAuth) apiAuthorization;
basicAuth.setCredentials(username, password);
return;
}
if (apiAuthorization instanceof OAuth) {
OAuth oauth = (OAuth) apiAuthorization;
oauth.getTokenRequestBuilder().setUsername(username).setPassword(password);
return;
}
}
}
/**
* Helper method to configure the token endpoint of the first oauth found in the apiAuthorizations (there should be only one)
* @return
*/
public TokenRequestBuilder getTokenEndPoint() {
for(Interceptor apiAuthorization : apiAuthorizations.values()) {
if (apiAuthorization instanceof OAuth) {
OAuth oauth = (OAuth) apiAuthorization;
return oauth.getTokenRequestBuilder();
}
}
return null;
}
/**
* Helper method to configure authorization endpoint of the first oauth found in the apiAuthorizations (there should be only one)
* @return
*/
public AuthenticationRequestBuilder getAuthorizationEndPoint() {
for(Interceptor apiAuthorization : apiAuthorizations.values()) {
if (apiAuthorization instanceof OAuth) {
OAuth oauth = (OAuth) apiAuthorization;
return oauth.getAuthenticationRequestBuilder();
}
}
return null;
}
/**
* Helper method to pre-set the oauth access token of the first oauth found in the apiAuthorizations (there should be only one)
* @param accessToken
*/
public void setAccessToken(String accessToken) {
for(Interceptor apiAuthorization : apiAuthorizations.values()) {
if (apiAuthorization instanceof OAuth) {
OAuth oauth = (OAuth) apiAuthorization;
oauth.setAccessToken(accessToken);
return;
}
}
}
/**
* Helper method to configure the oauth accessCode/implicit flow parameters
* @param clientId
* @param clientSecret
* @param redirectURI
*/
public void configureAuthorizationFlow(String clientId, String clientSecret, String redirectURI) {
for(Interceptor apiAuthorization : apiAuthorizations.values()) {
if (apiAuthorization instanceof OAuth) {
OAuth oauth = (OAuth) apiAuthorization;
oauth.getTokenRequestBuilder()
.setClientId(clientId)
.setClientSecret(clientSecret)
.setRedirectURI(redirectURI);
oauth.getAuthenticationRequestBuilder()
.setClientId(clientId)
.setRedirectURI(redirectURI);
return;
}
}
}
/**
* Configures a listener which is notified when a new access token is received.
* @param accessTokenListener
*/
public void registerAccessTokenListener(AccessTokenListener accessTokenListener) {
for(Interceptor apiAuthorization : apiAuthorizations.values()) {
if (apiAuthorization instanceof OAuth) {
OAuth oauth = (OAuth) apiAuthorization;
oauth.registerAccessTokenListener(accessTokenListener);
return;
}
}
}
/**
* Adds an authorization to be used by the client
* @param authName
* @param authorization
*/
public void addAuthorization(String authName, Interceptor authorization) {
if (apiAuthorizations.containsKey(authName)) {
throw new RuntimeException("auth name \"" + authName + "\" already in api authorizations");
}
apiAuthorizations.put(authName, authorization);
okClient.interceptors().add(authorization);
}
public Map<String, Interceptor> getApiAuthorizations() {
return apiAuthorizations;
}
public void setApiAuthorizations(Map<String, Interceptor> apiAuthorizations) {
this.apiAuthorizations = apiAuthorizations;
}
public Retrofit.Builder getAdapterBuilder() {
return adapterBuilder;
}
public void setAdapterBuilder(Retrofit.Builder adapterBuilder) {
this.adapterBuilder = adapterBuilder;
}
public OkHttpClient getOkClient() {
return okClient;
}
public void addAuthsToOkClient(OkHttpClient okClient) {
for(Interceptor apiAuthorization : apiAuthorizations.values()) {
okClient.interceptors().add(apiAuthorization);
}
}
/**
* Clones the okClient given in parameter, adds the auth interceptors and uses it to configure the Retrofit
* @param okClient
*/
public void configureFromOkclient(OkHttpClient okClient) {
OkHttpClient clone = okClient.clone();
addAuthsToOkClient(clone);
adapterBuilder.client(clone);
}
}
/**
* This wrapper is to take care of this case:
* when the deserialization fails due to JsonParseException and the
* expected type is String, then just return the body string.
*/
class GsonResponseBodyConverterToString<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final Type type;
GsonResponseBodyConverterToString(Gson gson, Type type) {
this.gson = gson;
this.type = type;
}
@Override public T convert(ResponseBody value) throws IOException {
String returned = value.string();
try {
return gson.fromJson(returned, type);
}
catch (JsonParseException e) {
return (T) returned;
}
}
}
class GsonCustomConverterFactory extends Converter.Factory
{
public static GsonCustomConverterFactory create(Gson gson) {
return new GsonCustomConverterFactory(gson);
}
private final Gson gson;
private final GsonConverterFactory gsonConverterFactory;
private GsonCustomConverterFactory(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
this.gson = gson;
this.gsonConverterFactory = GsonConverterFactory.create(gson);
}
@Override
public Converter<ResponseBody, ?> fromResponseBody(Type type, Annotation[] annotations) {
if(type.equals(String.class))
return new GsonResponseBodyConverterToString<Object>(gson, type);
else
return gsonConverterFactory.fromResponseBody(type, annotations);
}
@Override
public Converter<?, RequestBody> toRequestBody(Type type, Annotation[] annotations) {
return gsonConverterFactory.toRequestBody(type, annotations);
}
}

View File

@ -0,0 +1,95 @@
package {{invokerPackage}};
import java.util.Arrays;
import java.util.List;
public class CollectionFormats {
public static class CSVParams {
protected List<String> params;
public CSVParams() {
}
public CSVParams(List<String> params) {
this.params = params;
}
public CSVParams(String... params) {
this.params = Arrays.asList(params);
}
public List<String> getParams() {
return params;
}
public void setParams(List<String> params) {
this.params = params;
}
@Override
public String toString() {
return StringUtil.join(params.toArray(new String[0]), ",");
}
}
public static class SSVParams extends CSVParams {
public SSVParams() {
}
public SSVParams(List<String> params) {
super(params);
}
public SSVParams(String... params) {
super(params);
}
@Override
public String toString() {
return StringUtil.join(params.toArray(new String[0]), " ");
}
}
public static class TSVParams extends CSVParams {
public TSVParams() {
}
public TSVParams(List<String> params) {
super(params);
}
public TSVParams(String... params) {
super(params);
}
@Override
public String toString() {
return StringUtil.join( params.toArray(new String[0]), "\t");
}
}
public static class PIPESParams extends CSVParams {
public PIPESParams() {
}
public PIPESParams(List<String> params) {
super(params);
}
public PIPESParams(String... params) {
super(params);
}
@Override
public String toString() {
return StringUtil.join(params.toArray(new String[0]), "|");
}
}
}

View File

@ -0,0 +1,34 @@
package {{package}};
import {{invokerPackage}}.CollectionFormats.*;
import retrofit.Call;
import retrofit.http.*;
import com.squareup.okhttp.RequestBody;
{{#imports}}import {{import}};
{{/imports}}
{{^fullJavaUtil}}
import java.util.*;
{{/fullJavaUtil}}
{{#operations}}
public interface {{classname}} {
{{#operation}}
/**
* {{summary}}
* {{notes}}
{{#allParams}} * @param {{paramName}} {{description}}
{{/allParams}} * @return Call<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Object{{/returnType}}>
*/
{{#formParams}}{{#-first}}
{{#isMultipart}}@Multipart{{/isMultipart}}{{^isMultipart}}@FormUrlEncoded{{/isMultipart}}{{/-first}}{{/formParams}}
@{{httpMethod}}("{{path}}")
Call<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Object{{/returnType}}> {{nickname}}({{^allParams}});{{/allParams}}
{{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}}
);{{/hasMore}}{{/allParams}}
{{/operation}}
}
{{/operations}}

View File

@ -0,0 +1,68 @@
package {{invokerPackage}}.auth;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import com.squareup.okhttp.Interceptor;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
public class ApiKeyAuth implements Interceptor {
private final String location;
private final String paramName;
private String apiKey;
public ApiKeyAuth(String location, String paramName) {
this.location = location;
this.paramName = paramName;
}
public String getLocation() {
return location;
}
public String getParamName() {
return paramName;
}
public String getApiKey() {
return apiKey;
}
public void setApiKey(String apiKey) {
this.apiKey = apiKey;
}
@Override
public Response intercept(Chain chain) throws IOException {
String paramValue;
Request request = chain.request();
if (location == "query") {
String newQuery = request.uri().getQuery();
paramValue = paramName + "=" + apiKey;
if (newQuery == null) {
newQuery = paramValue;
} else {
newQuery += "&" + paramValue;
}
URI newUri;
try {
newUri = new URI(request.uri().getScheme(), request.uri().getAuthority(),
request.uri().getPath(), newQuery, request.uri().getFragment());
} catch (URISyntaxException e) {
throw new IOException(e);
}
request = request.newBuilder().url(newUri.toURL()).build();
} else if (location == "header") {
request = request.newBuilder()
.addHeader(paramName, apiKey)
.build();
}
return chain.proceed(request);
}
}

View File

@ -0,0 +1,49 @@
package {{invokerPackage}}.auth;
import java.io.IOException;
import com.squareup.okhttp.Credentials;
import com.squareup.okhttp.Interceptor;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
public class HttpBasicAuth implements Interceptor {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public void setCredentials(String username, String password) {
this.username = username;
this.password = password;
}
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
// If the request already have an authorization (eg. Basic auth), do nothing
if (request.header("Authorization") == null) {
String credentials = Credentials.basic(username, password);
request = request.newBuilder()
.addHeader("Authorization", credentials)
.build();
}
return chain.proceed(request);
}
}

View File

@ -0,0 +1,161 @@
package {{invokerPackage}}.auth;
import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;
import java.io.IOException;
import java.util.Map;
import org.apache.oltu.oauth2.client.OAuthClient;
import org.apache.oltu.oauth2.client.request.OAuthBearerClientRequest;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder;
import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.types.GrantType;
import org.apache.oltu.oauth2.common.token.BasicOAuthToken;
import com.squareup.okhttp.Interceptor;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Request.Builder;
import com.squareup.okhttp.Response;
public class OAuth implements Interceptor {
public interface AccessTokenListener {
public void notify(BasicOAuthToken token);
}
private volatile String accessToken;
private OAuthClient oauthClient;
private TokenRequestBuilder tokenRequestBuilder;
private AuthenticationRequestBuilder authenticationRequestBuilder;
private AccessTokenListener accessTokenListener;
public OAuth( OkHttpClient client, TokenRequestBuilder requestBuilder ) {
this.oauthClient = new OAuthClient(new OAuthOkHttpClient(client));
this.tokenRequestBuilder = requestBuilder;
}
public OAuth(TokenRequestBuilder requestBuilder ) {
this(new OkHttpClient(), requestBuilder);
}
public OAuth(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) {
this(OAuthClientRequest.tokenLocation(tokenUrl).setScope(scopes));
setFlow(flow);
authenticationRequestBuilder = OAuthClientRequest.authorizationLocation(authorizationUrl);
}
public void setFlow(OAuthFlow flow) {
switch(flow) {
case accessCode:
case implicit:
tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE);
break;
case password:
tokenRequestBuilder.setGrantType(GrantType.PASSWORD);
break;
case application:
tokenRequestBuilder.setGrantType(GrantType.CLIENT_CREDENTIALS);
break;
default:
break;
}
}
@Override
public Response intercept(Chain chain)
throws IOException {
Request request = chain.request();
// If the request already have an authorization (eg. Basic auth), do nothing
if (request.header("Authorization") != null) {
return chain.proceed(request);
}
// If first time, get the token
OAuthClientRequest oAuthRequest;
if (getAccessToken() == null) {
updateAccessToken(null);
}
// Build the request
Builder rb = request.newBuilder();
String requestAccessToken = new String(getAccessToken());
try {
oAuthRequest = new OAuthBearerClientRequest(request.urlString())
.setAccessToken(requestAccessToken)
.buildHeaderMessage();
} catch (OAuthSystemException e) {
throw new IOException(e);
}
for ( Map.Entry<String, String> header : oAuthRequest.getHeaders().entrySet() ) {
rb.addHeader(header.getKey(), header.getValue());
}
rb.url( oAuthRequest.getLocationUri());
//Execute the request
Response response = chain.proceed(rb.build());
// 401 most likely indicates that access token has expired.
// Time to refresh and resend the request
if ( response.code() == HTTP_UNAUTHORIZED ) {
updateAccessToken(requestAccessToken);
return intercept( chain );
}
return response;
}
public synchronized void updateAccessToken(String requestAccessToken) throws IOException {
if (getAccessToken() == null || getAccessToken().equals(requestAccessToken)) {
try {
OAuthJSONAccessTokenResponse accessTokenResponse = oauthClient.accessToken(this.tokenRequestBuilder.buildBodyMessage());
setAccessToken(accessTokenResponse.getAccessToken());
if (accessTokenListener != null) {
accessTokenListener.notify((BasicOAuthToken) accessTokenResponse.getOAuthToken());
}
} catch (OAuthSystemException e) {
throw new IOException(e);
} catch (OAuthProblemException e) {
throw new IOException(e);
}
}
}
public void registerAccessTokenListener(AccessTokenListener accessTokenListener) {
this.accessTokenListener = accessTokenListener;
}
public synchronized String getAccessToken() {
return accessToken;
}
public synchronized void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public TokenRequestBuilder getTokenRequestBuilder() {
return tokenRequestBuilder;
}
public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) {
this.tokenRequestBuilder = tokenRequestBuilder;
}
public AuthenticationRequestBuilder getAuthenticationRequestBuilder() {
return authenticationRequestBuilder;
}
public void setAuthenticationRequestBuilder(AuthenticationRequestBuilder authenticationRequestBuilder) {
this.authenticationRequestBuilder = authenticationRequestBuilder;
}
}

View File

@ -0,0 +1,69 @@
package {{invokerPackage}}.auth;
import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.oltu.oauth2.client.HttpClient;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
import org.apache.oltu.oauth2.client.response.OAuthClientResponse;
import org.apache.oltu.oauth2.client.response.OAuthClientResponseFactory;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;
public class OAuthOkHttpClient implements HttpClient {
private OkHttpClient client;
public OAuthOkHttpClient() {
this.client = new OkHttpClient();
}
public OAuthOkHttpClient(OkHttpClient client) {
this.client = client;
}
public <T extends OAuthClientResponse> T execute(OAuthClientRequest request, Map<String, String> headers,
String requestMethod, Class<T> responseClass)
throws OAuthSystemException, OAuthProblemException {
MediaType mediaType = MediaType.parse("application/json");
Request.Builder requestBuilder = new Request.Builder().url(request.getLocationUri());
if(headers != null) {
for (Entry<String, String> entry : headers.entrySet()) {
if (entry.getKey().equalsIgnoreCase("Content-Type")) {
mediaType = MediaType.parse(entry.getValue());
} else {
requestBuilder.addHeader(entry.getKey(), entry.getValue());
}
}
}
RequestBody body = request.getBody() != null ? RequestBody.create(mediaType, request.getBody()) : null;
requestBuilder.method(requestMethod, body);
try {
Response response = client.newCall(requestBuilder.build()).execute();
return OAuthClientResponseFactory.createCustomResponse(
response.body().string(),
response.body().contentType().toString(),
response.code(),
responseClass);
} catch (IOException e) {
throw new OAuthSystemException(e);
}
}
public void shutdown() {
// Nothing to do here
}
}

View File

@ -0,0 +1 @@
{{#isBodyParam}}@Body {{{dataType}}} {{paramName}}{{/isBodyParam}}

View File

@ -0,0 +1,106 @@
group = '{{groupId}}'
version = '{{artifactVersion}}'
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.2'
classpath 'com.github.dcendents:android-maven-plugin:1.2'
}
}
repositories {
jcenter()
}
if(hasProperty('target') && target == 'android') {
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
android {
compileSdkVersion 22
buildToolsVersion '22.0.0'
defaultConfig {
minSdkVersion 14
targetSdkVersion 22
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
// Rename the aar correctly
libraryVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.aar')) {
def fileName = "${project.name}-${variant.baseName}-${version}.aar"
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
}
afterEvaluate {
android.libraryVariants.all { variant ->
def task = project.tasks.create "jar${variant.name.capitalize()}", Jar
task.description = "Create jar artifact for ${variant.name}"
task.dependsOn variant.javaCompile
task.from variant.javaCompile.destinationDir
task.destinationDir = project.file("${project.buildDir}/outputs/jar")
task.archiveName = "${project.name}-${variant.baseName}-${version}.jar"
artifacts.add('archives', task);
}
}
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
artifacts {
archives sourcesJar
}
} else {
apply plugin: 'java'
apply plugin: 'maven'
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
install {
repositories.mavenInstaller {
pom.artifactId = '{{artifactId}}'
}
}
task execute(type:JavaExec) {
main = System.getProperty('mainClass')
classpath = sourceSets.main.runtimeClasspath
}
}
ext {
okhttp_version = "2.5.0"
oltu_version = "1.0.0"
retrofit_version = "2.0.0-beta2"
gson_version = "2.4"
swagger_annotations_version = "1.5.0"
junit_version = "4.12"
}
dependencies {
compile "com.squareup.okhttp:okhttp:$okhttp_version"
compile "com.squareup.retrofit:retrofit:$retrofit_version"
compile 'com.google.code.gson:gson:$gson_version'
compile 'com.squareup.retrofit:converter-gson:$retrofit_version'
compile "io.swagger:swagger-annotations:$swagger_annotations_version"
compile "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version"
testCompile "junit:junit:$junit_version"
}

View File

@ -0,0 +1 @@
{{#isFormParam}}{{#notFile}}{{#isMultipart}}@Part{{/isMultipart}}{{^isMultipart}}@Field{{/isMultipart}}("{{baseName}}") {{{dataType}}} {{paramName}}{{/notFile}}{{#isFile}}{{#isMultipart}}@Part{{/isMultipart}}{{^isMultipart}}@Field{{/isMultipart}}("{{baseName}}\"; filename=\"{{baseName}}\"") RequestBody {{paramName}}{{/isFile}}{{/isFormParam}}

View File

@ -0,0 +1 @@
{{#isHeaderParam}}@Header("{{baseName}}") {{{dataType}}} {{paramName}}{{/isHeaderParam}}

View File

@ -0,0 +1,58 @@
package {{package}};
import {{invokerPackage}}.StringUtil;
{{#imports}}import {{import}};
{{/imports}}
import com.google.gson.annotations.SerializedName;
{{#serializableModel}}
import java.io.Serializable;{{/serializableModel}}
import io.swagger.annotations.*;
{{#models}}
{{#model}}{{#description}}
/**
* {{description}}
**/{{/description}}
@ApiModel(description = "{{{description}}}")
public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}} {{#serializableModel}}implements Serializable{{/serializableModel}} {
{{#vars}}{{#isEnum}}
{{>libraries/okhttp-gson/enumClass}}{{/isEnum}}{{#items.isEnum}}{{#items}}
{{>libraries/okhttp-gson/enumClass}}{{/items}}{{/items.isEnum}}
@SerializedName("{{baseName}}")
private {{{datatypeWithEnum}}} {{name}} = {{{defaultValue}}};
{{/vars}}
{{#vars}}
/**{{#description}}
* {{{description}}}{{/description}}{{#minimum}}
* minimum: {{minimum}}{{/minimum}}{{#maximum}}
* maximum: {{maximum}}{{/maximum}}
**/
@ApiModelProperty({{#required}}required = {{required}}, {{/required}}value = "{{{description}}}")
public {{{datatypeWithEnum}}} {{getter}}() {
return {{name}};
}
public void {{setter}}({{{datatypeWithEnum}}} {{name}}) {
this.{{name}} = {{name}};
}
{{/vars}}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class {{classname}} {\n");
{{#parent}}sb.append(" ").append(StringUtil.toIndentedString(super.toString())).append("\n");{{/parent}}
{{#vars}}sb.append(" {{name}}: ").append(StringUtil.toIndentedString({{name}})).append("\n");
{{/vars}}sb.append("}");
return sb.toString();
}
}
{{/model}}
{{/models}}

View File

@ -0,0 +1 @@
{{#isPathParam}}@Path("{{baseName}}") {{{dataType}}} {{paramName}}{{/isPathParam}}

View File

@ -0,0 +1,158 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>{{groupId}}</groupId>
<artifactId>{{artifactId}}</artifactId>
<packaging>jar</packaging>
<name>{{artifactId}}</name>
<version>{{artifactVersion}}</version>
<scm>
<connection>scm:git:git@github.com:swagger-api/swagger-mustache.git</connection>
<developerConnection>scm:git:git@github.com:swagger-api/swagger-codegen.git</developerConnection>
<url>https://github.com/swagger-api/swagger-codegen</url>
</scm>
<prerequisites>
<maven>2.2.0</maven>
</prerequisites>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12</version>
<configuration>
<systemProperties>
<property>
<name>loggerPath</name>
<value>conf/log4j.properties</value>
</property>
</systemProperties>
<argLine>-Xms512m -Xmx1500m</argLine>
<parallel>methods</parallel>
<forkMode>pertest</forkMode>
</configuration>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!-- attach test jar -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<goals>
<goal>jar</goal>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
<configuration>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add_sources</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/main/java</source>
</sources>
</configuration>
</execution>
<execution>
<id>add_test_sources</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/test/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger-annotations-version}</version>
</dependency>
<dependency>
<groupId>com.squareup.retrofit</groupId>
<artifactId>retrofit</artifactId>
<version>${retrofit-version}</version>
</dependency>
<dependency>
<groupId>com.squareup.retrofit</groupId>
<artifactId>converter-gson</artifactId>
<version>${retrofit-version}</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${gson-version}</version>
</dependency>
<dependency>
<groupId>org.apache.oltu.oauth2</groupId>
<artifactId>org.apache.oltu.oauth2.client</artifactId>
<version>${oltu-version}</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp</groupId>
<artifactId>okhttp</artifactId>
<version>${okhttp-version}</version>
</dependency>
<!-- test dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit-version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<swagger-annotations-version>1.5.0</swagger-annotations-version>
<retrofit-version>2.0.0-beta2</retrofit-version>
<okhttp-version>2.5.0</okhttp-version>
<gson-version>2.4</gson-version>
<oltu-version>1.0.0</oltu-version>
<maven-plugin-version>1.0.0</maven-plugin-version>
<junit-version>4.12</junit-version>
</properties>
</project>

View File

@ -0,0 +1 @@
{{#isQueryParam}}@Query("{{baseName}}") {{#collectionFormat}}{{#isCollectionFormatMulti}}{{{dataType}}}{{/isCollectionFormatMulti}}{{^isCollectionFormatMulti}}{{{collectionFormat.toUpperCase}}}Params{{/isCollectionFormatMulti}}{{/collectionFormat}}{{^collectionFormat}}{{{dataType}}}{{/collectionFormat}} {{paramName}}{{/isQueryParam}}

View File

@ -0,0 +1,3 @@
<manifest package="{{invokerPackage}}" xmlns:android="http://schemas.android.com/apk/res/android">
<application />
</manifest>

View File

@ -22,14 +22,13 @@ import com.sun.jersey.multipart.FormDataParam;
import javax.ws.rs.core.Response;
import javax.ws.rs.*;
@Path("{{basePathWithoutHost}}/{{baseName}}")
@Path("/{{baseName}}")
{{#hasConsumes}}@Consumes({ {{#consumes}}"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} }){{/hasConsumes}}
{{#hasProduces}}@Produces({ {{#produces}}"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }){{/hasProduces}}
@io.swagger.annotations.Api(value = "/{{baseName}}", description = "the {{baseName}} API")
@io.swagger.annotations.Api(description = "the {{baseName}} API")
{{>generatedAnnotation}}
{{#operations}}
public class {{classname}} {
private final {{classname}}Service delegate = {{classname}}ServiceFactory.get{{classname}}();
{{#operation}}
@ -43,7 +42,7 @@ public class {{classname}} {
{{/hasMore}}{{/scopes}}
}{{/isOAuth}}){{#hasMore}},
{{/hasMore}}{{/authMethods}}
}{{/hasAuthMethods}})
}{{/hasAuthMethods}}, tags={ {{#vendorExtensions.x-tags}}"{{tag}}"{{#hasMore}}, {{/hasMore}}{{/vendorExtensions.x-tags}} })
@io.swagger.annotations.ApiResponses(value = { {{#responses}}
@io.swagger.annotations.ApiResponse(code = {{{code}}}, message = "{{{message}}}", response = {{{returnType}}}.class{{#returnContainer}}, responseContainer = "{{{returnContainer}}}"{{/returnContainer}}){{#hasMore}},
{{/hasMore}}{{/responses}} })

View File

@ -34,14 +34,14 @@
</init-param>
<init-param>
<param-name>swagger.api.basepath</param-name>
<param-value>http://localhost:8080</param-value>
<param-value>{{basePath}}</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey</servlet-name>
<url-pattern>/*</url-pattern>
<url-pattern>{{contextPath}}/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>ApiOriginFilter</filter-name>

View File

@ -1 +1 @@
{{#isBodyParam}}@ApiParam(value = "{{{description}}}" {{#required}},required=true{{/required}} {{#allowableValues}}, allowableValues="{{{allowableValues}}}"{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) {{{dataType}}} {{paramName}}{{/isBodyParam}}
{{#isBodyParam}}@ApiParam(value = "{{{description}}}" {{#required}},required=true{{/required}} {{#allowableValues}}, allowableValues="{{{allowableValues}}}"{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) @RequestBody {{{dataType}}} {{paramName}}{{/isBodyParam}}

View File

@ -3,6 +3,7 @@ io.swagger.codegen.languages.AsyncScalaClientCodegen
io.swagger.codegen.languages.CSharpClientCodegen
io.swagger.codegen.languages.DartClientCodegen
io.swagger.codegen.languages.FlashClientCodegen
io.swagger.codegen.languages.FlaskConnexionCodegen
io.swagger.codegen.languages.JavaClientCodegen
io.swagger.codegen.languages.JaxRSServerCodegen
io.swagger.codegen.languages.JavaInflectorServerCodegen
@ -28,3 +29,4 @@ io.swagger.codegen.languages.TypeScriptAngularClientCodegen
io.swagger.codegen.languages.TypeScriptNodeClientCodegen
io.swagger.codegen.languages.AkkaScalaClientCodegen
io.swagger.codegen.languages.CsharpDotNet2ClientCodegen
io.swagger.codegen.languages.ClojureClientCodegen

View File

@ -12,26 +12,38 @@ namespace {{package}} {
*/
{{/description}}
export class {{classname}} {
private basePath = '{{basePath}}';
protected basePath = '{{basePath}}';
public defaultHeaders : any = {};
static $inject: string[] = ['$http', '$httpParamSerializer'];
constructor(private $http: ng.IHttpService, basePath?: string, private $httpParamSerializer?: (d: any) => any) {
constructor(protected $http: ng.IHttpService, protected $httpParamSerializer?: (d: any) => any, basePath?: string) {
if (basePath) {
this.basePath = basePath;
}
}
private extendObj<T1,T2>(objA: T1, objB: T2) {
for(let key in objB){
if(objB.hasOwnProperty(key)){
objA[key] = objB[key];
}
}
return <T1&T2>objA;
}
{{#operation}}
/**
* {{summary}}
* {{notes}}
{{#allParams}}* @param {{paramName}} {{description}}
{{/allParams}}*/
public {{nickname}} ({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}extraHttpRequestParams?: any ) : ng.IHttpPromise<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}{}{{/returnType}}> {
let path = this.basePath + '{{path}}';
const path = this.basePath + '{{path}}'{{#pathParams}}
.replace('{' + '{{baseName}}' + '}', String({{paramName}})){{/pathParams}};
{{#pathParams}}
path = path.replace('{' + '{{baseName}}' + '}', String({{paramName}}));
{{/pathParams}}
let queryParameters: any = {};
let headerParams: any = {};
let headerParams: any = this.extendObj({}, this.defaultHeaders);
{{#hasFormParams}}
let formParams: any = {};
@ -42,7 +54,6 @@ namespace {{package}} {
if (!{{paramName}}) {
throw new Error('Missing required parameter {{paramName}} when calling {{nickname}}');
}
{{/required}}
{{/allParams}}
{{#queryParams}}
@ -61,7 +72,7 @@ namespace {{package}} {
{{/hasFormParams}}
{{#formParams}}
formParams['{{baseName}}'] = {{paramName}};
{{/formParams}}
let httpRequestParams: any = {
method: '{{httpMethod}}',
@ -76,11 +87,7 @@ namespace {{package}} {
};
if (extraHttpRequestParams) {
for (let k in extraHttpRequestParams) {
if (extraHttpRequestParams.hasOwnProperty(k)) {
httpRequestParams[k] = extraHttpRequestParams[k];
}
}
httpRequestParams = this.extendObj(httpRequestParams, extraHttpRequestParams);
}
return this.$http(httpRequestParams);

View File

@ -18,7 +18,7 @@ namespace {{package}} {
* {{{description}}}
*/
{{/description}}
{{name}}: {{#isEnum}}{{classname}}.{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{datatype}}}{{/isEnum}};
{{name}}{{^required}}?{{/required}}: {{#isEnum}}{{classname}}.{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{datatype}}}{{/isEnum}};
{{/vars}}
}
@ -27,7 +27,7 @@ namespace {{package}} {
{{#vars}}
{{#isEnum}}
export enum {{datatypeWithEnum}} { {{#allowableValues}}{{#values}}
export enum {{datatypeWithEnum}} { {{#allowableValues}}{{#values}}
{{.}} = <any> '{{.}}',{{/values}}{{/allowableValues}}
}
{{/isEnum}}
@ -36,4 +36,4 @@ namespace {{package}} {
{{/hasEnums}}
{{/model}}
{{/models}}
}
}

View File

@ -95,7 +95,11 @@ class VoidAuth implements Authentication {
*/
{{/description}}
export class {{classname}} {
private basePath = '{{basePath}}';
protected basePath = '{{basePath}}';
protected defaultHeaders : any = {};
public authentications = {
'default': <Authentication>new VoidAuth(),
{{#authMethods}}
@ -154,17 +158,25 @@ export class {{classname}} {
{{#isOAuth}}
{{/isOAuth}}
{{/authMethods}}
private extendObj<T1,T2>(objA: T1, objB: T2) {
for(let key in objB){
if(objB.hasOwnProperty(key)){
objA[key] = objB[key];
}
}
return <T1&T2>objA;
}
{{#operation}}
public {{nickname}} ({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) : Promise<{ response: http.ClientResponse; {{#returnType}}body: {{{returnType}}}; {{/returnType}} }> {
let path = this.url + this.basePath + '{{path}}';
{{#pathParams}}
path = path.replace('{' + '{{baseName}}' + '}', String({{paramName}}));
{{/pathParams}}
/**
* {{summary}}
* {{notes}}
{{#allParams}}* @param {{paramName}} {{description}}
{{/allParams}}*/
public {{nickname}} ({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) : Promise<{ response: http.ClientResponse; {{#returnType}}body: {{{returnType}}}; {{/returnType}}{{^returnType}}body?: any; {{/returnType}} }> {
const path = this.url + this.basePath + '{{path}}'{{#pathParams}}
.replace('{' + '{{baseName}}' + '}', String({{paramName}})){{/pathParams}};
let queryParameters: any = {};
let headerParams: any = {};
let headerParams: any = this.extendObj({}, this.defaultHeaders);
let formParams: any = {};
{{#allParams}}{{#required}}
@ -194,7 +206,7 @@ export class {{classname}} {
{{/isFile}}
{{/formParams}}
let deferred = promise.defer<{ response: http.ClientResponse; {{#returnType}}body: {{{returnType}}}; {{/returnType}} }>();
let deferred = promise.defer<{ response: http.ClientResponse; {{#returnType}}body: {{{returnType}}}; {{/returnType}}{{^returnType}}body?: any; {{/returnType}} }>();
let requestOptions: request.Options = {
method: '{{httpMethod}}',

View File

@ -0,0 +1,19 @@
{{=< >=}}(ns <package>.<classname>
(:require [<projectName>.core :refer [call-api check-required-params]])
(:import (java.io File)))
<#operations><#operation>
(defn <nickname>
"<&summary><#notes>
<&notes></notes>"<#hasOptionalParams>
([<#allParams><#required><#isFile>^File </isFile><paramName> </required></allParams>] (<nickname><#allParams><#required> <paramName></required></allParams> nil))</hasOptionalParams>
<#hasOptionalParams>(</hasOptionalParams>[<#allParams><#required><#isFile>^File </isFile><paramName> </required></allParams><#hasOptionalParams>{:keys [<#allParams><^required><#isFile>^File </isFile><paramName> </required></allParams>]}</hasOptionalParams>]<#hasRequiredParams>
<#hasOptionalParams> </hasOptionalParams>(check-required-params<#allParams><#required> <paramName></required></allParams>)</hasRequiredParams>
<#hasOptionalParams> </hasOptionalParams>(call-api "<path>" :<httpMethod>
<#hasOptionalParams> </hasOptionalParams> {:path-params {<#pathParams>"<baseName>" <paramName> </pathParams>}
<#hasOptionalParams> </hasOptionalParams> :header-params {<#headerParams>"<baseName>" <paramName> </headerParams>}
<#hasOptionalParams> </hasOptionalParams> :query-params {<#queryParams>"<baseName>" <paramName> </queryParams>}
<#hasOptionalParams> </hasOptionalParams> :form-params {<#formParams>"<baseName>" <paramName> </formParams>}<#bodyParam>
<#hasOptionalParams> </hasOptionalParams> :body-param <paramName></bodyParam>
<#hasOptionalParams> </hasOptionalParams> :content-types [<#consumes>"<mediaType>"<#hasMore> </hasMore></consumes>]
<#hasOptionalParams> </hasOptionalParams> :accepts [<#produces>"<mediaType>"<#hasMore> </hasMore></produces>]}))<#hasOptionalParams>)</hasOptionalParams>
</operation></operations>

View File

@ -0,0 +1,178 @@
(ns {{{baseNamespace}}}.core
(:require [cheshire.core :refer [generate-string parse-string]]
[clojure.string :as str]
[clj-http.client :as client])
(:import (com.fasterxml.jackson.core JsonParseException)
(java.io File)
(java.util Date TimeZone)
(java.text SimpleDateFormat)))
(def default-api-context
"Default API context."
{:base-url "http://petstore.swagger.io/v2"
:date-format "yyyy-MM-dd"
:datetime-format "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"
:debug false})
(def ^:dynamic *api-context*
"Dynamic API context to be applied in API calls."
default-api-context)
(defmacro with-api-context
"A helper macro to wrap *api-context* with default values."
[context & body]
`(binding [*api-context* (merge *api-context* ~context)]
~@body))
(defmacro check-required-params
"Throw exception if the given parameter value is nil."
[& params]
(->> params
(map (fn [p]
`(if (nil? ~p)
(throw (IllegalArgumentException. ~(str "The parameter \"" p "\" is required"))))))
(list* 'do)))
(defn- make-date-format
([format-str] (make-date-format format-str nil))
([format-str time-zone]
(let [date-format (SimpleDateFormat. format-str)]
(when time-zone
(.setTimeZone date-format (TimeZone/getTimeZone time-zone)))
date-format)))
(defn format-date
"Format the given Date object with the :date-format defined in *api-options*.
NOTE: The UTC time zone is used."
[^Date date]
(let [{:keys [date-format]} *api-context*]
(-> (make-date-format date-format "UTC")
(.format date))))
(defn parse-date
"Parse the given string to a Date object with the :date-format defined in *api-options*.
NOTE: The UTC time zone is used."
[^String s]
(let [{:keys [date-format]} *api-context*]
(-> (make-date-format date-format "UTC")
(.parse s))))
(defn format-datetime
"Format the given Date object with the :datetime-format defined in *api-options*.
NOTE: The system's default time zone is used when not provided."
([^Date date] (format-datetime date nil))
([^Date date ^String time-zone]
(let [{:keys [datetime-format]} *api-context*]
(-> (make-date-format datetime-format time-zone)
(.format date)))))
(defn parse-datetime
"Parse the given string to a Date object with the :datetime-format defined in *api-options*.
NOTE: The system's default time zone is used when not provided."
([^String s] (parse-datetime s nil))
([^String s ^String time-zone]
(let [{:keys [datetime-format]} *api-context*]
(-> (make-date-format datetime-format time-zone)
(.parse s)))))
(defn param-to-str [param]
"Format the given parameter value to string."
(cond
(instance? Date param) (format-datetime param)
(sequential? param) (str/join "," param)
:else (str param)))
(defn make-url
"Make full URL by adding base URL and filling path parameters."
[path path-params]
(let [path (reduce (fn [p [k v]]
(str/replace p (re-pattern (str "\\{" k "\\}")) (param-to-str v)))
path
path-params)]
(str (:base-url *api-context*) path)))
(defn normalize-param
"Normalize parameter value, handling three cases:
for sequential value, normalize each elements of it;
for File value, do nothing with it;
otherwise, call `param-to-string`."
[param]
(cond
(sequential? param) (map normalize-param param)
(instance? File param) param
:else (param-to-str param)))
(defn normalize-params
"Normalize parameters values: remove nils, format to string with `param-to-str`."
[params]
(->> params
(remove (comp nil? second))
(map (fn [[k v]] [k (normalize-param v)]))
(into {})))
(defn json-mime? [mime]
"Check if the given MIME is a standard JSON MIME or :json."
(if mime
(or (= :json mime)
(re-matches #"application/json(;.*)?" (name mime)))))
(defn json-preferred-mime [mimes]
"Choose a MIME from the given MIMEs with JSON preferred,
i.e. return JSON if included, otherwise return the first one."
(-> (filter json-mime? mimes)
first
(or (first mimes))))
(defn serialize
"Serialize the given data according to content-type.
Only JSON is supported for now."
[data content-type]
(if (json-mime? content-type)
(generate-string data {:date-format (:datetime-format *api-context*)})
(throw (IllegalArgumentException. (str "Content type \"" content-type "\" is not support for serialization")))))
(defn deserialize
"Deserialize the given HTTP response according to the Content-Type header."
[{:keys [body] {:keys [content-type]} :headers}]
(cond
(json-mime? content-type)
(try
(parse-string body true)
(catch JsonParseException e
;; return the body string directly on JSON parsing error
body))
;; for non-JSON response, return the body string directly
:else body))
(defn form-params-to-multipart
"Convert the given form parameters map into a vector as clj-http's :multipart option."
[form-params]
(->> form-params
(map (fn [[k v]] (array-map :name k :content v)))
vec))
(defn call-api
"Call an API by making HTTP request and return its response."
[path method {:keys [path-params query-params header-params form-params body-param content-types accepts]}]
(let [{:keys [debug]} *api-context*
url (make-url path path-params)
content-type (or (json-preferred-mime content-types)
(and body-param :json))
accept (or (json-preferred-mime accepts) :json)
multipart? (= "multipart/form-data" content-type)
opts (cond-> {:url url :method method}
accept (assoc :accept accept)
(seq query-params) (assoc :query-params (normalize-params query-params))
(seq header-params) (assoc :header-params (normalize-params header-params))
(and content-type (not multipart?)) (assoc :content-type content-type)
multipart? (assoc :multipart (-> form-params
normalize-params
form-params-to-multipart))
(and (not multipart?) (seq form-params)) (assoc :form-params (normalize-params form-params))
body-param (assoc :body (serialize body-param content-type))
debug (assoc :debug true :debug-body true))
resp (client/request opts)]
(when debug
(println "Response:")
(println resp))
(deserialize resp)))

View File

@ -0,0 +1,8 @@
{{=< >=}}(defproject <&projectName> "<&projectVersion>"
:description "<&projectDescription>"<#projectUrl>
:url "<&projectUrl>"</projectUrl><#licenseName>
:license {:name "<&licenseName>"<#licenseUrl>
:url "<&licenseUrl>"</licenseUrl>}</licenseName>
:dependencies [[org.clojure/clojure "1.7.0"]
[clj-http "2.0.0"]
[cheshire "5.5.0"]])

View File

@ -10,7 +10,6 @@ using System.Net;
using System.Text;
using Newtonsoft.Json;
using RestSharp;
using RestSharp.Extensions;
namespace {{packageName}}.Client
{
@ -171,7 +170,7 @@ namespace {{packageName}}.Client
/// <returns>Escaped string.</returns>
public string EscapeString(string str)
{
return RestSharp.Extensions.StringExtensions.UrlEncode(str);
return UrlEncode(str);
}
/// <summary>
@ -183,9 +182,9 @@ namespace {{packageName}}.Client
public FileParameter ParameterToFile(string name, Stream stream)
{
if (stream is FileStream)
return FileParameter.Create(name, stream.ReadAsBytes(), Path.GetFileName(((FileStream)stream).Name));
return FileParameter.Create(name, ReadAsBytes(stream), Path.GetFileName(((FileStream)stream).Name));
else
return FileParameter.Create(name, stream.ReadAsBytes(), "no_file_name_provided");
return FileParameter.Create(name, ReadAsBytes(stream), "no_file_name_provided");
}
/// <summary>
@ -319,8 +318,7 @@ namespace {{packageName}}.Client
{
{{#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}}
{{#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}}headerParams["Authorization"] = "Bearer " + Configuration.AccessToken;{{/isOAuth}}
break;
{{/authMethods}}
default:
@ -366,6 +364,62 @@ namespace {{packageName}}.Client
public static dynamic ConvertType(dynamic source, Type dest) {
return Convert.ChangeType(source, dest);
}
/// <summary>
/// Convert stream to byte array
/// Credit/Ref: http://stackoverflow.com/a/221941/677735
/// </summary>
/// <param name="input">Input stream to be converted</param>
/// <returns>Byte array</returns>
public static byte[] ReadAsBytes(Stream input)
{
byte[] buffer = new byte[16*1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
/// <summary>
/// URL encode a string
/// Credit/Ref: https://github.com/restsharp/RestSharp/blob/master/RestSharp/Extensions/StringExtensions.cs#L50
/// </summary>
/// <param name="input">String to be URL encoded</param>
/// <returns>Byte array</returns>
public static string UrlEncode(string input)
{
const int maxLength = 32766;
if (input == null)
{
throw new ArgumentNullException("input");
}
if (input.Length <= maxLength)
{
return Uri.EscapeDataString(input);
}
StringBuilder sb = new StringBuilder(input.Length * 2);
int index = 0;
while (index < input.Length)
{
int length = Math.Min(input.Length - index, maxLength);
string subString = input.Substring(index, length);
sb.Append(Uri.EscapeDataString(subString));
index += subString.Length;
}
return sb.ToString();
}
}
}

View File

@ -37,6 +37,12 @@ namespace {{packageName}}.Client
/// <value>The password.</value>
public static String Password { get; set; }
/// <summary>
/// Gets or sets the access token for OAuth2 authentication.
/// </summary>
/// <value>The access token.</value>
public static String AccessToken { get; set; }
/// <summary>
/// Gets or sets the API key based on the authentication name.
/// </summary>

View File

@ -102,7 +102,7 @@ namespace {{packageName}}.Api
if ({{paramName}} == null) throw new ApiException(400, "Missing required parameter '{{paramName}}' when calling {{nickname}}");
{{/required}}{{/allParams}}
var path = "{{path}}";
var path_ = "{{path}}";
var pathParams = new Dictionary<String, String>();
var queryParams = new Dictionary<String, String>();
@ -137,7 +137,7 @@ namespace {{packageName}}.Api
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, pathParams, authSettings);
IRestResponse response = (IRestResponse) ApiClient.CallApi(path_, Method.{{httpMethod}}, queryParams, postBody, headerParams, formParams, fileParams, pathParams, authSettings);
if (((int)response.StatusCode) >= 400)
throw new ApiException ((int)response.StatusCode, "Error calling {{nickname}}: " + response.Content, response.Content);
@ -158,7 +158,7 @@ namespace {{packageName}}.Api
if ({{paramName}} == null) throw new ApiException(400, "Missing required parameter '{{paramName}}' when calling {{nickname}}");
{{/required}}{{/allParams}}
var path = "{{path}}";
var path_ = "{{path}}";
var pathParams = new Dictionary<String, String>();
var queryParams = new Dictionary<String, String>();
@ -193,7 +193,7 @@ namespace {{packageName}}.Api
String[] authSettings = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} };
// make the HTTP request
IRestResponse response = (IRestResponse) await ApiClient.CallApiAsync(path, Method.{{httpMethod}}, queryParams, postBody, headerParams, formParams, fileParams, pathParams, authSettings);
IRestResponse response = (IRestResponse) await ApiClient.CallApiAsync(path_, Method.{{httpMethod}}, queryParams, postBody, headerParams, formParams, fileParams, pathParams, authSettings);
if (((int)response.StatusCode) >= 400)
throw new ApiException ((int)response.StatusCode, "Error calling {{nickname}}: " + response.Content, response.Content);

View File

@ -1,4 +1,5 @@
using System;
using System.IO;
using System.Text;
using System.Collections;
using System.Collections.Generic;

View File

@ -0,0 +1,27 @@
# Swagger generated server
## Overview
This server was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. By using the
[swagger-spec](https://github.com/swagger-api/swagger-core/wiki) from a remote server, you can easily generate a server stub. This
is an example of building a swagger-enabled flask server.
This example uses the [connexion](https://github.com/zalando/connexion) library on top of Flask.
To run the server, please execute the following:
```
python3 app.py
```
and open your browser to here:
```
http://localhost:{{serverPort}}/ui
```
Your swagger definition lives here:
```
http://localhost:{{serverPort}}{{basePathWithoutHost}}/swagger.json
```

View File

@ -0,0 +1,9 @@
#!/usr/bin/env python3
import connexion
if __name__ == '__main__':
app = connexion.App(__name__, {{serverPort}},
specification_dir='./swagger/')
app.add_api('swagger.yaml', arguments={'title': '{{appDescription}}'})
app.run()

View File

@ -0,0 +1,11 @@
{{#apiInfo}}
{{#apis}}
{{#operations}}
{{#operation}}
def {{vendorExtensions.x-operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) -> str:
return 'do some magic!'
{{/operation}}
{{/operations}}
{{/apis}}
{{/apiInfo}}

View File

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

View File

@ -94,17 +94,15 @@
</div> <!-- field-items -->
{{/hasFormParams}}
<!-- Remove Return type... unclear where this comes from;
for our swagger.json files, it is always empty and there is no boolean guard or hasReturnType
do we end up with a heading but not content
{{#returnType}}
<h3 class="field-label">Return type</h3>
<div class="return-type"><a href="#{{returnContainer}}">{{{returnType}}}</a></div>
<div class="return-type">
{{#hasReference}}{{^returnSimpleType}}{{returnContainer}}[{{/returnSimpleType}}<a href="#{{returnBaseType}}">{{returnBaseType}}</a>{{^returnSimpleType}}]{{/returnSimpleType}}{{/hasReference}}
{{^hasReference}}{{returnType}}{{/hasReference}}
</div>
{{/returnType}}
Todo: process Response Object and its headers, schema, examples
-->
<!--Todo: process Response Object and its headers, schema, examples -->
{{#hasExamples}}
{{#examples}}

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