Merge branch 'develop_2.0' into Generic_API_Exception

Conflicts:
	modules/swagger-codegen/src/main/resources/csharp/apiException.mustache
This commit is contained in:
Fredrik Gustafsson
2015-06-05 12:47:48 +02:00
162 changed files with 6278 additions and 1812 deletions

View File

@@ -0,0 +1,23 @@
package com.wordnik.swagger.codegen;
public class CliOption {
private final String opt;
private String description;
public CliOption(String opt, String description) {
this.opt = opt;
this.description = description;
}
public String getOpt() {
return opt;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}

View File

@@ -140,4 +140,4 @@ public class Codegen extends DefaultGenerator {
}
}
}
}
}

View File

@@ -27,6 +27,7 @@ public interface CodegenConfig {
String getTypeDeclaration(Property p);
String getTypeDeclaration(String name);
void processOpts();
List<CliOption> cliOptions();
String generateExamplePath(String path, Operation operation);
Set<String> reservedWords();

View File

@@ -7,7 +7,7 @@ import java.util.*;
public class CodegenOperation {
public Boolean hasConsumes, hasProduces, hasParams, returnTypeIsPrimitive,
returnSimpleType, subresourceOperation, isMapContainer, isListContainer,
hasMore = Boolean.TRUE;
hasMore = Boolean.TRUE, isMultipart;
public String path, operationId, returnType, httpMethod, returnBaseType,
returnContainer, summary, notes, baseName, defaultResponse;

View File

@@ -77,11 +77,24 @@ public class DefaultCodegen {
protected String templateDir;
protected Map<String, Object> additionalProperties = new HashMap<String, Object>();
protected List<SupportingFile> supportingFiles = new ArrayList<SupportingFile>();
protected List<CliOption> cliOptions = new ArrayList<CliOption>();
public List<CliOption> cliOptions() {
return cliOptions;
}
public void processOpts(){
if(additionalProperties.containsKey("templateDir")) {
this.setTemplateDir((String)additionalProperties.get("templateDir"));
}
if(additionalProperties.containsKey("modelPackage")) {
this.setModelPackage((String)additionalProperties.get("modelPackage"));
}
if(additionalProperties.containsKey("apiPackage")) {
this.setApiPackage((String)additionalProperties.get("apiPackage"));
}
}
// override with any special post-processing
@@ -178,6 +191,14 @@ public class DefaultCodegen {
this.templateDir = templateDir;
}
public void setModelPackage(String modelPackage) {
this.modelPackage = modelPackage;
}
public void setApiPackage(String apiPackage) {
this.apiPackage = apiPackage;
}
public String toApiFilename(String name) {
return toApiName(name);
}
@@ -281,6 +302,9 @@ public class DefaultCodegen {
importMapping.put("LocalDateTime", "org.joda.time.*");
importMapping.put("LocalDate", "org.joda.time.*");
importMapping.put("LocalTime", "org.joda.time.*");
cliOptions.add(new CliOption("modelPackage", "package for generated models"));
cliOptions.add(new CliOption("apiPackage", "package for generated api classes"));
}

View File

@@ -47,26 +47,6 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
"native", "super", "while")
);
additionalProperties.put("invokerPackage", invokerPackage);
additionalProperties.put("groupId", groupId);
additionalProperties.put("artifactId", artifactId);
additionalProperties.put("artifactVersion", artifactVersion);
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
additionalProperties.put("useAndroidMavenGradlePlugin", useAndroidMavenGradlePlugin);
supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
supportingFiles.add(new SupportingFile("build.mustache", "", "build.gradle"));
supportingFiles.add(new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml"));
supportingFiles.add(new SupportingFile("apiInvoker.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiInvoker.java"));
supportingFiles.add(new SupportingFile("httpPatch.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "HttpPatch.java"));
supportingFiles.add(new SupportingFile("jsonUtil.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "JsonUtil.java"));
supportingFiles.add(new SupportingFile("apiException.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiException.java"));
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"String",
@@ -80,6 +60,13 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
);
instantiationTypes.put("array", "ArrayList");
instantiationTypes.put("map", "HashMap");
cliOptions.add(new CliOption("invokerPackage", "root package to use for the generated code"));
cliOptions.add(new CliOption("groupId", "groupId for use in the generated build.gradle and pom.xml"));
cliOptions.add(new CliOption("artifactId", "artifactId for use in the generated build.gradle and pom.xml"));
cliOptions.add(new CliOption("artifactVersion", "artifact version for use in the generated build.gradle and pom.xml"));
cliOptions.add(new CliOption("sourceFolder", "source folder for generated code"));
cliOptions.add(new CliOption("useAndroidMavenGradlePlugin", "A flag to toggle android-maven gradle plugin. Default is true."));
}
@Override
@@ -177,6 +164,96 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
return camelize(operationId, true);
}
@Override
public void processOpts() {
super.processOpts();
if(additionalProperties.containsKey("invokerPackage")) {
this.setInvokerPackage((String)additionalProperties.get("invokerPackage"));
}
else{
//not set, use default to be passed to template
additionalProperties.put("invokerPackage", invokerPackage);
}
if(additionalProperties.containsKey("groupId")) {
this.setGroupId((String)additionalProperties.get("groupId"));
}
else{
//not set, use to be passed to template
additionalProperties.put("groupId", groupId);
}
if(additionalProperties.containsKey("artifactId")) {
this.setArtifactId((String)additionalProperties.get("artifactId"));
}
else{
//not set, use to be passed to template
additionalProperties.put("artifactId", artifactId);
}
if(additionalProperties.containsKey("artifactVersion")) {
this.setArtifactVersion((String)additionalProperties.get("artifactVersion"));
}
else{
//not set, use to be passed to template
additionalProperties.put("artifactVersion", artifactVersion);
}
if(additionalProperties.containsKey("sourceFolder")) {
this.setSourceFolder((String)additionalProperties.get("sourceFolder"));
}
if(additionalProperties.containsKey("useAndroidMavenGradlePlugin")) {
this.setUseAndroidMavenGradlePlugin((Boolean)additionalProperties.get("useAndroidMavenGradlePlugin"));
}
else{
additionalProperties.put("useAndroidMavenGradlePlugin", useAndroidMavenGradlePlugin);
}
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
additionalProperties.put("useAndroidMavenGradlePlugin", useAndroidMavenGradlePlugin);
supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
supportingFiles.add(new SupportingFile("build.mustache", "", "build.gradle"));
supportingFiles.add(new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml"));
supportingFiles.add(new SupportingFile("apiInvoker.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiInvoker.java"));
supportingFiles.add(new SupportingFile("httpPatch.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "HttpPatch.java"));
supportingFiles.add(new SupportingFile("jsonUtil.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "JsonUtil.java"));
supportingFiles.add(new SupportingFile("apiException.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiException.java"));
}
public Boolean getUseAndroidMavenGradlePlugin() {
return useAndroidMavenGradlePlugin;
}
public void setUseAndroidMavenGradlePlugin(Boolean useAndroidMavenGradlePlugin) {
this.useAndroidMavenGradlePlugin = useAndroidMavenGradlePlugin;
}
public void setInvokerPackage(String invokerPackage) {
this.invokerPackage = invokerPackage;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
public void setArtifactId(String artifactId) {
this.artifactId = artifactId;
}
public void setArtifactVersion(String artifactVersion) {
this.artifactVersion = artifactVersion;
}
public void setSourceFolder(String sourceFolder) {
this.sourceFolder = sourceFolder;
}
}

View File

@@ -41,11 +41,14 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
additionalProperties.put("invokerPackage", invokerPackage);
supportingFiles.add(new SupportingFile("apiInvoker.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiInvoker.cs"));
supportingFiles.add(new SupportingFile("apiException.mustache",
supportingFiles.add(new SupportingFile("Configuration.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "Configuration.cs"));
supportingFiles.add(new SupportingFile("ApiClient.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiClient.cs"));
supportingFiles.add(new SupportingFile("ApiException.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiException.cs"));
supportingFiles.add(new SupportingFile("Newtonsoft.Json.dll", "bin", "Newtonsoft.Json.dll"));
supportingFiles.add(new SupportingFile("RestSharp.dll", "bin", "RestSharp.dll"));
supportingFiles.add(new SupportingFile("compile.mustache", "", "compile.bat"));
languageSpecificPrimitives = new HashSet<String>(
@@ -59,7 +62,7 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
"byte[]",
"List",
"Dictionary",
"DateTime",
"DateTime?",
"String",
"Boolean",
"Double",
@@ -79,9 +82,11 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
typeMapping.put("long", "long?");
typeMapping.put("double", "double?");
typeMapping.put("number", "double?");
typeMapping.put("Date", "DateTime");
typeMapping.put("datetime", "DateTime?");
typeMapping.put("date", "DateTime?");
typeMapping.put("file", "string"); // path to file
typeMapping.put("array", "List");
typeMapping.put("list", "List");
typeMapping.put("map", "Dictionary");
typeMapping.put("object", "Object");
@@ -94,11 +99,11 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
@Override
public String apiFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar);
return (outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', '/')).replace('.', File.separatorChar);
}
public String modelFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar);
return (outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', '/')).replace('.', File.separatorChar);
}
@Override
@@ -165,8 +170,8 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
public String getSwaggerType(Property p) {
String swaggerType = super.getSwaggerType(p);
String type = null;
if(typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType);
if(typeMapping.containsKey(swaggerType.toLowerCase())) {
type = typeMapping.get(swaggerType.toLowerCase());
if(languageSpecificPrimitives.contains(type))
return type;
}

View File

@@ -36,28 +36,15 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
reservedWords = new HashSet<String> (
Arrays.asList(
"abstract", "continue", "for", "new", "switch", "assert",
"default", "if", "package", "synchronized", "boolean", "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", "long", "strictfp", "volatile", "const", "float",
"abstract", "continue", "for", "new", "switch", "assert",
"default", "if", "package", "synchronized", "boolean", "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", "long", "strictfp", "volatile", "const", "float",
"native", "super", "while")
);
additionalProperties.put("invokerPackage", invokerPackage);
additionalProperties.put("groupId", groupId);
additionalProperties.put("artifactId", artifactId);
additionalProperties.put("artifactVersion", artifactVersion);
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("apiInvoker.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiInvoker.java"));
supportingFiles.add(new SupportingFile("JsonUtil.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "JsonUtil.java"));
supportingFiles.add(new SupportingFile("apiException.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiException.java"));
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"String",
@@ -71,8 +58,67 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
);
instantiationTypes.put("array", "ArrayList");
instantiationTypes.put("map", "HashMap");
cliOptions.add(new CliOption("invokerPackage", "root package for generated code"));
cliOptions.add(new CliOption("groupId", "groupId in generated pom.xml"));
cliOptions.add(new CliOption("artifactId", "artifactId in generated pom.xml"));
cliOptions.add(new CliOption("artifactVersion", "artifact version in generated pom.xml"));
cliOptions.add(new CliOption("sourceFolder", "source folder for generated code"));
}
@Override
public void processOpts() {
super.processOpts();
if(additionalProperties.containsKey("invokerPackage")) {
this.setInvokerPackage((String)additionalProperties.get("invokerPackage"));
}
else{
//not set, use default to be passed to template
additionalProperties.put("invokerPackage", invokerPackage);
}
if(additionalProperties.containsKey("groupId")) {
this.setGroupId((String)additionalProperties.get("groupId"));
}
else{
//not set, use to be passed to template
additionalProperties.put("groupId", groupId);
}
if(additionalProperties.containsKey("artifactId")) {
this.setArtifactId((String)additionalProperties.get("artifactId"));
}
else{
//not set, use to be passed to template
additionalProperties.put("artifactId", artifactId);
}
if(additionalProperties.containsKey("artifactVersion")) {
this.setArtifactVersion((String)additionalProperties.get("artifactVersion"));
}
else{
//not set, use to be passed to template
additionalProperties.put("artifactVersion", artifactVersion);
}
if(additionalProperties.containsKey("sourceFolder")) {
this.setSourceFolder((String)additionalProperties.get("sourceFolder"));
}
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("ApiClient.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiClient.java"));
supportingFiles.add(new SupportingFile("Configuration.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "Configuration.java"));
supportingFiles.add(new SupportingFile("JsonUtil.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "JsonUtil.java"));
supportingFiles.add(new SupportingFile("apiException.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiException.java"));
}
@Override
public String escapeReservedWord(String name) {
return "_" + name;
@@ -169,5 +215,23 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
return camelize(operationId, true);
}
public void setInvokerPackage(String invokerPackage) {
this.invokerPackage = invokerPackage;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
public void setArtifactId(String artifactId) {
this.artifactId = artifactId;
}
public void setArtifactVersion(String artifactVersion) {
this.artifactVersion = artifactVersion;
}
public void setSourceFolder(String sourceFolder) {
this.sourceFolder = sourceFolder;
}
}

View File

@@ -1,6 +1,5 @@
package com.wordnik.swagger.codegen.languages;
import com.wordnik.swagger.util.Json;
import com.wordnik.swagger.codegen.*;
import com.wordnik.swagger.models.properties.*;
@@ -10,7 +9,8 @@ import java.io.File;
public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
protected Set<String> foundationClasses = new HashSet<String>();
protected String sourceFolder = "client";
protected static String PREFIX = "SWG";
protected String classPrefix = "SWG";
protected String projectName = "swaggerClient";
public CodegenType getTag() {
return CodegenType.CLIENT;
@@ -26,7 +26,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
public ObjcClientCodegen() {
super();
outputFolder = "generated-code/objc";
outputFolder = "generated-code" + File.separator + "objc";
modelTemplateFiles.put("model-header.mustache", ".h");
modelTemplateFiles.put("model-body.mustache", ".m");
apiTemplateFiles.put("api-header.mustache", ".h");
@@ -34,12 +34,6 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
templateDir = "objc";
modelPackage = "";
String appName = System.getProperty("appName");
if(appName == null) {
appName = "swaggerClient";
}
additionalProperties.put("projectName", appName);
defaultIncludes = new HashSet<String>(
Arrays.asList(
"bool",
@@ -111,7 +105,31 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
instantiationTypes.put("array", "NSMutableArray");
instantiationTypes.put("map", "NSMutableDictionary");
cliOptions.add(new CliOption("classPrefix", "prefix for generated classes"));
cliOptions.add(new CliOption("sourceFolder", "source folder for generated code"));
cliOptions.add(new CliOption("projectName", "name of the Xcode project in generated Podfile"));
}
@Override
public void processOpts() {
super.processOpts();
if(additionalProperties.containsKey("sourceFolder")) {
this.setSourceFolder((String)additionalProperties.get("sourceFolder"));
}
if(additionalProperties.containsKey("classPrefix")) {
this.setClassPrefix((String)additionalProperties.get("classPrefix"));
}
if(additionalProperties.containsKey("projectName")) {
this.setProjectName((String)additionalProperties.get("projectName"));
}
else{
additionalProperties.put("projectName", projectName);
}
supportingFiles.add(new SupportingFile("SWGObject.h", sourceFolder, "SWGObject.h"));
supportingFiles.add(new SupportingFile("SWGObject.m", sourceFolder, "SWGObject.m"));
supportingFiles.add(new SupportingFile("SWGQueryParamCollection.h", sourceFolder, "SWGQueryParamCollection.h"));
@@ -122,6 +140,8 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
supportingFiles.add(new SupportingFile("SWGFile.m", sourceFolder, "SWGFile.m"));
supportingFiles.add(new SupportingFile("JSONValueTransformer+ISO8601.m", sourceFolder, "JSONValueTransformer+ISO8601.m"));
supportingFiles.add(new SupportingFile("JSONValueTransformer+ISO8601.h", sourceFolder, "JSONValueTransformer+ISO8601.h"));
supportingFiles.add(new SupportingFile("SWGConfiguration-body.mustache", sourceFolder, "SWGConfiguration.m"));
supportingFiles.add(new SupportingFile("SWGConfiguration-header.mustache", sourceFolder, "SWGConfiguration.h"));
supportingFiles.add(new SupportingFile("Podfile.mustache", "", "Podfile"));
}
@@ -220,7 +240,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
}
// custom classes
else {
return PREFIX + camelize(type);
return classPrefix + camelize(type);
}
}
@@ -266,11 +286,11 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String toApiName(String name) {
return PREFIX + camelize(name) + "Api";
return classPrefix + camelize(name) + "Api";
}
public String toApiFilename(String name) {
return PREFIX + camelize(name) + "Api";
return classPrefix + camelize(name) + "Api";
}
@Override
@@ -313,4 +333,15 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
return camelize(operationId, true);
}
public void setSourceFolder(String sourceFolder) {
this.sourceFolder = sourceFolder;
}
public void setClassPrefix(String classPrefix) {
this.classPrefix = classPrefix;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
}

View File

@@ -27,8 +27,8 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
public PerlClientCodegen() {
super();
modelPackage = "Object";
outputFolder = "generated-code/perl";
modelPackage = File.separatorChar + "Object";
outputFolder = "generated-code" + File.separatorChar + "perl";
modelTemplateFiles.put("object.mustache", ".pm");
apiTemplateFiles.put("api.mustache", ".pm");
templateDir = "perl";
@@ -63,6 +63,7 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
languageSpecificPrimitives.add("DateTime");
languageSpecificPrimitives.add("ARRAY");
languageSpecificPrimitives.add("HASH");
languageSpecificPrimitives.add("object");
typeMapping.put("integer", "int");
typeMapping.put("long", "int");
@@ -75,9 +76,11 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("password", "string");
typeMapping.put("array", "ARRAY");
typeMapping.put("map", "HASH");
typeMapping.put("object", "object");
supportingFiles.add(new SupportingFile("APIClient.mustache", "lib/WWW/" + invokerPackage, "APIClient.pm"));
supportingFiles.add(new SupportingFile("BaseObject.mustache", "lib/WWW/" + invokerPackage, "Object/BaseObject.pm"));
supportingFiles.add(new SupportingFile("ApiClient.mustache", ("lib/WWW/" + invokerPackage).replace('/', File.separatorChar), "ApiClient.pm"));
supportingFiles.add(new SupportingFile("Configuration.mustache", ("lib/WWW/" + invokerPackage).replace('/', File.separatorChar), "Configuration.pm"));
supportingFiles.add(new SupportingFile("BaseObject.mustache", ("lib/WWW/" + invokerPackage).replace('/', File.separatorChar), "Object/BaseObject.pm"));
}
@Override
@@ -87,11 +90,11 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String apiFileFolder() {
return outputFolder + "/lib/WWW/" + invokerPackage + apiPackage().replace('.', File.separatorChar);
return (outputFolder + "/lib/WWW/" + invokerPackage + apiPackage()).replace('/', File.separatorChar);
}
public String modelFileFolder() {
return outputFolder + "/lib/WWW/" + invokerPackage + "/" + modelPackage().replace('.', File.separatorChar);
return (outputFolder + "/lib/WWW/" + invokerPackage + modelPackage()).replace('/', File.separatorChar);
}
@Override

View File

@@ -82,12 +82,13 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("map", "map");
typeMapping.put("array", "array");
typeMapping.put("list", "array");
typeMapping.put("object", "object");
supportingFiles.add(new SupportingFile("composer.mustache", packagePath, "composer.json"));
supportingFiles.add(new SupportingFile("configuration.mustache", packagePath + "/lib", "Configuration.php"));
supportingFiles.add(new SupportingFile("APIClient.mustache", packagePath + "/lib", "APIClient.php"));
supportingFiles.add(new SupportingFile("APIClientException.mustache", packagePath + "/lib", "APIClientException.php"));
supportingFiles.add(new SupportingFile("require.mustache", packagePath, invokerPackage + ".php"));
supportingFiles.add(new SupportingFile("composer.mustache", packagePath.replace('/', File.separatorChar), "composer.json"));
supportingFiles.add(new SupportingFile("configuration.mustache", (packagePath + "/lib").replace('/', File.separatorChar), "Configuration.php"));
supportingFiles.add(new SupportingFile("ApiClient.mustache", (packagePath + "/lib").replace('/', File.separatorChar), "ApiClient.php"));
supportingFiles.add(new SupportingFile("ApiException.mustache", (packagePath + "/lib").replace('/', File.separatorChar), "ApiException.php"));
supportingFiles.add(new SupportingFile("require.mustache", packagePath.replace('/', File.separatorChar), invokerPackage + ".php"));
}
@Override
@@ -97,11 +98,11 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String apiFileFolder() {
return outputFolder + "/" + apiPackage().replace('.', File.separatorChar);
return (outputFolder + "/" + apiPackage()).replace('/', File.separatorChar);
}
public String modelFileFolder() {
return outputFolder + "/" + modelPackage().replace('.', File.separatorChar);
return (outputFolder + "/" + modelPackage()).replace('/', File.separatorChar);
}
@Override

View File

@@ -71,6 +71,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
supportingFiles.add(new SupportingFile("swagger.mustache", invokerPackage, "swagger.py"));
supportingFiles.add(new SupportingFile("rest.mustache", invokerPackage, "rest.py"));
supportingFiles.add(new SupportingFile("util.mustache", invokerPackage, "util.py"));
supportingFiles.add(new SupportingFile("config.mustache", invokerPackage, "config.py"));
supportingFiles.add(new SupportingFile("__init__package.mustache", invokerPackage, "__init__.py"));
supportingFiles.add(new SupportingFile("__init__model.mustache", modelPackage.replace('.', File.separatorChar), "__init__.py"));
supportingFiles.add(new SupportingFile("__init__api.mustache", apiPackage.replace('.', File.separatorChar), "__init__.py"));

View File

@@ -0,0 +1,190 @@
package com.wordnik.swagger.codegen.languages;
import com.wordnik.swagger.codegen.*;
import com.wordnik.swagger.models.Operation;
import com.wordnik.swagger.models.properties.*;
import java.util.*;
import java.io.File;
public class RetrofitClientCodegen extends DefaultCodegen implements CodegenConfig {
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";
public CodegenType getTag() {
return CodegenType.CLIENT;
}
public String getName() {
return "retrofit";
}
public String getHelp() {
return "Generates a Retrofit client library.";
}
public RetrofitClientCodegen() {
super();
outputFolder = "generated-code/java";
modelTemplateFiles.put("model.mustache", ".java");
apiTemplateFiles.put("api.mustache", ".java");
templateDir = "retrofit";
apiPackage = "io.swagger.client.api";
modelPackage = "io.swagger.client.model";
reservedWords = new HashSet<String> (
Arrays.asList(
"abstract", "continue", "for", "new", "switch", "assert",
"default", "if", "package", "synchronized", "boolean", "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", "long", "strictfp", "volatile", "const", "float",
"native", "super", "while")
);
additionalProperties.put("invokerPackage", invokerPackage);
additionalProperties.put("groupId", groupId);
additionalProperties.put("artifactId", artifactId);
additionalProperties.put("artifactVersion", artifactVersion);
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("service.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ServiceGenerator.java"));
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"String",
"boolean",
"Boolean",
"Double",
"Integer",
"Long",
"Float",
"Object")
);
instantiationTypes.put("array", "ArrayList");
instantiationTypes.put("map", "HashMap");
}
@Override
public String escapeReservedWord(String name) {
return "_" + name;
}
@Override
public String apiFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar);
}
public String modelFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar);
}
@Override
public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_");
// if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$"))
return name;
// camelize (lower first character) the variable name
// pet_id => petId
name = camelize(name, true);
// for reserved word or word starting with number, append _
if(reservedWords.contains(name) || name.matches("^\\d.*"))
name = escapeReservedWord(name);
return name;
}
@Override
public String toParamName(String name) {
// should be the same as variable name
return toVarName(name);
}
@Override
public String toModelName(String name) {
// model name cannot use reserved keyword, e.g. return
if(reservedWords.contains(name))
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
// camelize the model name
// phone_number => PhoneNumber
return camelize(name);
}
@Override
public String toModelFilename(String name) {
// should be the same as the model name
return toModelName(name);
}
@Override
public String getTypeDeclaration(Property p) {
if(p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems();
return getSwaggerType(p) + "<" + getTypeDeclaration(inner) + ">";
}
else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();
return getSwaggerType(p) + "<String, " + getTypeDeclaration(inner) + ">";
}
return super.getTypeDeclaration(p);
}
@Override
public String getSwaggerType(Property p) {
String swaggerType = super.getSwaggerType(p);
String type = null;
if(typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType);
if(languageSpecificPrimitives.contains(type))
return toModelName(type);
}
else
type = swaggerType;
return toModelName(type);
}
@Override
public String toOperationId(String operationId) {
// method name cannot use reserved keyword, e.g. return
if(reservedWords.contains(operationId))
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
return camelize(operationId, true);
}
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
Map<String, Object> operations = (Map<String, Object>)objs.get("operations");
if(operations != null) {
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
for(CodegenOperation operation : ops) {
if (operation.hasConsumes == Boolean.TRUE) {
Map<String, String> firstType = operation.consumes.get(0);
if (firstType != null) {
if ("multipart/form-data".equals(firstType.get("mediaType"))) {
operation.isMultipart = Boolean.TRUE;
}
}
}
if(operation.returnType == null) {
operation.returnType = "Void";
}
}
}
return objs;
}
}

View File

@@ -36,7 +36,7 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
moduleName = generateModuleName();
modelPackage = gemName + "/models";
apiPackage = gemName + "/api";
outputFolder = "generated-code/ruby";
outputFolder = "generated-code" + File.separatorChar + "ruby";
modelTemplateFiles.put("model.mustache", ".rb");
apiTemplateFiles.put("api.mustache", ".rb");
templateDir = "ruby";
@@ -69,17 +69,17 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("List", "array");
typeMapping.put("map", "map");
String baseFolder = "lib/" + gemName;
String swaggerFolder = baseFolder + "/swagger";
String modelFolder = baseFolder + "/models";
String baseFolder = "lib" + File.separatorChar + gemName;
String swaggerFolder = baseFolder + File.separatorChar + "swagger";
String modelFolder = baseFolder + File.separatorChar + "models";
supportingFiles.add(new SupportingFile("swagger_client.gemspec.mustache", "", gemName + ".gemspec"));
supportingFiles.add(new SupportingFile("swagger_client.mustache", "lib", gemName + ".rb"));
supportingFiles.add(new SupportingFile("monkey.mustache", baseFolder, "monkey.rb"));
supportingFiles.add(new SupportingFile("swagger.mustache", baseFolder, "swagger.rb"));
supportingFiles.add(new SupportingFile("swagger/request.mustache", swaggerFolder, "request.rb"));
supportingFiles.add(new SupportingFile("swagger/response.mustache", swaggerFolder, "response.rb"));
supportingFiles.add(new SupportingFile("swagger/version.mustache", swaggerFolder, "version.rb"));
supportingFiles.add(new SupportingFile("swagger/configuration.mustache", swaggerFolder, "configuration.rb"));
supportingFiles.add(new SupportingFile("swagger" + File.separatorChar + "request.mustache", swaggerFolder, "request.rb"));
supportingFiles.add(new SupportingFile("swagger" + File.separatorChar + "response.mustache", swaggerFolder, "response.rb"));
supportingFiles.add(new SupportingFile("swagger" + File.separatorChar + "version.mustache", swaggerFolder, "version.rb"));
supportingFiles.add(new SupportingFile("swagger" + File.separatorChar + "configuration.mustache", swaggerFolder, "configuration.rb"));
supportingFiles.add(new SupportingFile("base_object.mustache", modelFolder, "base_object.rb"));
}

View File

@@ -0,0 +1,33 @@
package config;
import com.google.common.collect.ImmutableMap;
import java.util.HashMap;
import java.util.Map;
public class Config {
private Map<String, String> options;
public Config() {
this.options = new HashMap<String, String>();
}
public Config(Map<String, String> properties) {
this.options = properties;
}
public Map<String, String> getOptions() {
return ImmutableMap.copyOf(options);
}
public boolean hasOption(String opt){
return options.containsKey(opt);
}
public String getOption(String opt){
return options.get(opt);
}
public void setOption(String opt, String value){
options.put(opt, value);
}
}

View File

@@ -0,0 +1,41 @@
package config;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.util.Iterator;
import java.util.Map;
public class ConfigParser {
public static Config read(String location) {
System.out.println("reading config from " + location);
ObjectMapper mapper = new ObjectMapper();
Config config = new Config();
try {
JsonNode rootNode = mapper.readTree(new File(location));
Iterator<Map.Entry<String, JsonNode>> optionNodes = rootNode.fields();
while (optionNodes.hasNext()) {
Map.Entry<String, JsonNode> optionNode = (Map.Entry<String, JsonNode>) optionNodes.next();
if(optionNode.getValue().isValueNode()){
config.setOption(optionNode.getKey(), optionNode.getValue().asText());
}
else{
System.out.println("omitting non-value node " + optionNode.getKey());
}
}
}
catch (Exception e) {
System.out.println(e.getMessage());
return null;
}
return config;
}
}

View File

@@ -29,69 +29,116 @@ import java.net.URLEncoder;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.text.ParseException;
public class ApiInvoker {
private static ApiInvoker INSTANCE = new ApiInvoker();
public class ApiClient {
private Map<String, Client> hostMap = new HashMap<String, Client>();
private Map<String, String> defaultHeaderMap = new HashMap<String, String>();
private boolean isDebug = false;
private boolean debugging = false;
private String basePath = "{{basePath}}";
/**
* ISO 8601 date time format.
* @see https://en.wikipedia.org/wiki/ISO_8601
*/
public static final SimpleDateFormat DATE_TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
private DateFormat dateFormat;
/**
* ISO 8601 date format.
* @see https://en.wikipedia.org/wiki/ISO_8601
*/
public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
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");
static {
// Use UTC as the default time zone.
DATE_TIME_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
// Set default User-Agent.
setUserAgent("Java-Swagger");
}
public static void setUserAgent(String userAgent) {
INSTANCE.addDefaultHeader("User-Agent", userAgent);
public String getBasePath() {
return basePath;
}
public static Date parseDateTime(String str) {
public ApiClient setBasePath(String basePath) {
this.basePath = basePath;
return this;
}
/**
* Set the User-Agent header's value (by adding to the default header map).
*/
public ApiClient setUserAgent(String userAgent) {
addDefaultHeader("User-Agent", userAgent);
return this;
}
/**
* Add a default header.
*
* @param key The header's key
* @param value The header's value
*/
public ApiClient addDefaultHeader(String key, String value) {
defaultHeaderMap.put(key, value);
return this;
}
/**
* Check that whether debugging is enabled for this API client.
*/
public boolean isDebugging() {
return debugging;
}
/**
* Enable/disable debugging for this API client.
*
* @param debugging To enable (true) or disable (false) debugging
*/
public ApiClient setDebugging(boolean debugging) {
this.debugging = debugging;
return this;
}
/**
* Get the date format used to parse/format date parameters.
*/
public DateFormat getDateFormat() {
return dateFormat;
}
/**
* Set the date format used to parse/format date parameters.
*/
public ApiClient getDateFormat(DateFormat dateFormat) {
this.dateFormat = dateFormat;
return this;
}
/**
* Parse the given string into Date object.
*/
public Date parseDate(String str) {
try {
return DATE_TIME_FORMAT.parse(str);
return dateFormat.parse(str);
} catch (java.text.ParseException e) {
throw new RuntimeException(e);
}
}
public static Date parseDate(String str) {
try {
return DATE_FORMAT.parse(str);
} catch (java.text.ParseException e) {
throw new RuntimeException(e);
}
/**
* Format the given Date object into string.
*/
public String formatDate(Date date) {
return dateFormat.format(date);
}
public static String formatDateTime(Date datetime) {
return DATE_TIME_FORMAT.format(datetime);
}
public static String formatDate(Date date) {
return DATE_FORMAT.format(date);
}
public static String parameterToString(Object param) {
/**
* Format the given parameter object into string.
*/
public String parameterToString(Object param) {
if (param == null) {
return "";
} else if (param instanceof Date) {
return formatDateTime((Date) param);
return formatDate((Date) param);
} else if (param instanceof Collection) {
StringBuilder b = new StringBuilder();
for(Object o : (Collection)param) {
@@ -105,28 +152,27 @@ public class ApiInvoker {
return String.valueOf(param);
}
}
public void enableDebug() {
isDebug = true;
}
public static ApiInvoker getInstance() {
return INSTANCE;
}
public void addDefaultHeader(String key, String value) {
defaultHeaderMap.put(key, value);
}
/**
* Escape the given string to be used as URL query value.
*/
public String escapeString(String str) {
try{
try {
return URLEncoder.encode(str, "utf8").replaceAll("\\+", "%20");
}
catch(UnsupportedEncodingException e) {
} catch (UnsupportedEncodingException e) {
return str;
}
}
public static Object deserialize(String json, String containerType, Class cls) throws ApiException {
/**
* Deserialize the given JSON string to Java object.
*
* @param json The JSON string
* @param containerType The container type, one of "list", "array" or ""
* @param cls The type of the Java object
* @return The deserialized Java object
*/
public Object deserialize(String json, String containerType, Class cls) throws ApiException {
if(null != containerType) {
containerType = containerType.toLowerCase();
}
@@ -147,11 +193,14 @@ public class ApiInvoker {
}
}
catch (IOException e) {
throw new ApiException(500, e.getMessage());
throw new ApiException(500, e.getMessage(), null, json);
}
}
public static String serialize(Object obj) throws ApiException {
/**
* Serialize the given Java object into JSON string.
*/
public String serialize(Object obj) throws ApiException {
try {
if (obj != null)
return JsonUtil.getJsonMapper().writeValueAsString(obj);
@@ -163,8 +212,20 @@ public class ApiInvoker {
}
}
public String invokeAPI(String host, String path, String method, Map<String, String> queryParams, Object body, Map<String, String> headerParams, Map<String, String> formParams, String contentType) throws ApiException {
Client client = getClient(host);
/**
* Invoke API by sending HTTP request with the given options.
*
* @param path The sub-path of the HTTP URL
* @param method The request method, one of "GET", "POST", "PUT", and "DELETE"
* @param queryParams The query parameters
* @param body The request body object
* @param headerParams The header parameters
* @param formParams The form parameters
* @param contentType The request Content-Type
* @return The response body in type of string
*/
public String invokeAPI(String path, String method, Map<String, String> queryParams, Object body, Map<String, String> headerParams, Map<String, String> formParams, String contentType) throws ApiException {
Client client = getClient();
StringBuilder b = new StringBuilder();
@@ -180,7 +241,7 @@ public class ApiInvoker {
}
String querystring = b.toString();
Builder builder = client.resource(host + path + querystring).accept("application/json");
Builder builder = client.resource(basePath + path + querystring).accept("application/json");
for(String key : headerParams.keySet()) {
builder = builder.header(key, headerParams.get(key));
}
@@ -236,6 +297,7 @@ public class ApiInvoker {
else {
throw new ApiException(500, "unknown method type " + method);
}
if(response.getClientResponseStatus() == ClientResponse.Status.NO_CONTENT) {
return null;
}
@@ -249,9 +311,11 @@ public class ApiInvoker {
}
else {
String message = "error";
String respBody = null;
if(response.hasEntity()) {
try{
message = String.valueOf(response.getEntity(String.class));
respBody = String.valueOf(response.getEntity(String.class));
message = respBody;
}
catch (RuntimeException e) {
// e.printStackTrace();
@@ -259,16 +323,21 @@ public class ApiInvoker {
}
throw new ApiException(
response.getClientResponseStatus().getStatusCode(),
message);
message,
response.getHeaders(),
respBody);
}
}
/**
* Encode the given form parameters as request body.
*/
private String getXWWWFormUrlencodedParams(Map<String, String> formParams) {
StringBuilder formParamBuilder = new StringBuilder();
for (Entry<String, String> param : formParams.entrySet()) {
String keyStr = ApiInvoker.parameterToString(param.getKey());
String valueStr = ApiInvoker.parameterToString(param.getValue());
String keyStr = parameterToString(param.getKey());
String valueStr = parameterToString(param.getValue());
try {
formParamBuilder.append(URLEncoder.encode(keyStr, "utf8"))
@@ -287,14 +356,16 @@ public class ApiInvoker {
return encodedFormParams;
}
private Client getClient(String host) {
if(!hostMap.containsKey(host)) {
/**
* Get an existing client or create a new client to handle HTTP request.
*/
private Client getClient() {
if(!hostMap.containsKey(basePath)) {
Client client = Client.create();
if(isDebug)
if (debugging)
client.addFilter(new LoggingFilter());
hostMap.put(host, client);
hostMap.put(basePath, client);
}
return hostMap.get(host);
return hostMap.get(basePath);
}
}
}

View File

@@ -0,0 +1,21 @@
package {{invokerPackage}};
public class Configuration {
private static ApiClient defaultApiClient = new ApiClient();
/**
* Get the default API client, which would be used when creating API
* instances without providing an API client.
*/
public static ApiClient getDefaultApiClient() {
return defaultApiClient;
}
/**
* Set the default API client, which would be used when creating API
* instances without providing an API client.
*/
public static void setDefaultApiClient(ApiClient apiClient) {
defaultApiClient = apiClient;
}
}

View File

@@ -1,7 +1,8 @@
package {{package}};
import {{invokerPackage}}.ApiException;
import {{invokerPackage}}.ApiInvoker;
import {{invokerPackage}}.ApiClient;
import {{invokerPackage}}.Configuration;
import {{modelPackage}}.*;
@@ -21,19 +22,22 @@ import java.util.HashMap;
{{#operations}}
public class {{classname}} {
String basePath = "{{basePath}}";
ApiInvoker apiInvoker = ApiInvoker.getInstance();
private ApiClient apiClient;
public ApiInvoker getInvoker() {
return apiInvoker;
public {{classname}}() {
this(Configuration.getDefaultApiClient());
}
public void setBasePath(String basePath) {
this.basePath = basePath;
public {{classname}}(ApiClient apiClient) {
this.apiClient = apiClient;
}
public String getBasePath() {
return basePath;
public ApiClient getApiClient() {
return apiClient;
}
public void setApiClient(ApiClient apiClient) {
this.apiClient = apiClient;
}
{{#operation}}
@@ -54,7 +58,7 @@ public class {{classname}} {
// create path and map variables
String path = "{{path}}".replaceAll("\\{format\\}","json"){{#pathParams}}
.replaceAll("\\{" + "{{paramName}}" + "\\}", apiInvoker.escapeString({{{paramName}}}.toString())){{/pathParams}};
.replaceAll("\\{" + "{{paramName}}" + "\\}", apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}};
// query params
Map<String, String> queryParams = new HashMap<String, String>();
@@ -62,9 +66,10 @@ public class {{classname}} {
Map<String, String> formParams = new HashMap<String, String>();
{{#queryParams}}if ({{paramName}} != null)
queryParams.put("{{baseName}}", ApiInvoker.parameterToString({{paramName}}));
queryParams.put("{{baseName}}", apiClient.parameterToString({{paramName}}));
{{/queryParams}}
{{#headerParams}}headerParams.put("{{baseName}}", ApiInvoker.parameterToString({{paramName}}));
{{#headerParams}}if ({{paramName}} != null)
headerParams.put("{{baseName}}", apiClient.parameterToString({{paramName}}));
{{/headerParams}}
String[] contentTypes = {
{{#consumes}}"{{mediaType}}"{{#hasMore}},{{/hasMore}}{{/consumes}}
@@ -76,25 +81,30 @@ public class {{classname}} {
boolean hasFields = false;
FormDataMultiPart mp = new FormDataMultiPart();
{{#formParams}}{{#notFile}}
hasFields = true;
mp.field("{{baseName}}", ApiInvoker.parameterToString({{paramName}}), MediaType.MULTIPART_FORM_DATA_TYPE);
if ({{paramName}} != null) {
hasFields = true;
mp.field("{{baseName}}", apiClient.parameterToString({{paramName}}), MediaType.MULTIPART_FORM_DATA_TYPE);
}
{{/notFile}}{{#isFile}}
hasFields = true;
mp.field("{{baseName}}", file.getName());
mp.bodyPart(new FileDataBodyPart("{{baseName}}", {{paramName}}, MediaType.MULTIPART_FORM_DATA_TYPE));
if ({{paramName}} != null) {
hasFields = true;
mp.field("{{baseName}}", {{paramName}}.getName());
mp.bodyPart(new FileDataBodyPart("{{baseName}}", {{paramName}}, MediaType.MULTIPART_FORM_DATA_TYPE));
}
{{/isFile}}{{/formParams}}
if(hasFields)
postBody = mp;
}
else {
{{#formParams}}{{#notFile}}formParams.put("{{baseName}}", ApiInvoker.parameterToString({{paramName}}));{{/notFile}}
{{#formParams}}{{#notFile}}if ({{paramName}} != null)
formParams.put("{{baseName}}", apiClient.parameterToString({{paramName}}));{{/notFile}}
{{/formParams}}
}
try {
String response = apiInvoker.invokeAPI(basePath, path, "{{httpMethod}}", queryParams, postBody, headerParams, formParams, contentType);
String response = apiClient.invokeAPI(path, "{{httpMethod}}", queryParams, postBody, headerParams, formParams, contentType);
if(response != null){
return {{#returnType}}({{{returnType}}}) ApiInvoker.deserialize(response, "{{returnContainer}}", {{returnBaseType}}.class){{/returnType}};
return {{#returnType}}({{{returnType}}}) apiClient.deserialize(response, "{{returnContainer}}", {{returnBaseType}}.class){{/returnType}};
}
else {
return {{#returnType}}null{{/returnType}};

View File

@@ -1,8 +1,13 @@
package {{invokerPackage}};
import java.util.Map;
import java.util.List;
public class ApiException extends Exception {
int code = 0;
String message = null;
private int code = 0;
private String message = null;
private Map<String, List<String>> responseHeaders = null;
private String responseBody = null;
public ApiException() {}
@@ -11,19 +16,32 @@ public class ApiException extends Exception {
this.message = message;
}
public ApiException(int code, String message, Map<String, List<String>> responseHeaders, String responseBody) {
this.code = code;
this.message = message;
this.responseHeaders = responseHeaders;
this.responseBody = responseBody;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
/**
* Get the HTTP response headers.
*/
public Map<String, List<String>> getResponseHeaders() {
return responseHeaders;
}
}
/**
* Get the HTTP response body.
*/
public String getResponseBody() {
return responseBody;
}
}

View File

@@ -10,6 +10,7 @@ com.wordnik.swagger.codegen.languages.PhpClientCodegen
com.wordnik.swagger.codegen.languages.PythonClientCodegen
com.wordnik.swagger.codegen.languages.Python3ClientCodegen
com.wordnik.swagger.codegen.languages.Qt5CPPGenerator
com.wordnik.swagger.codegen.languages.RetrofitClientCodegen
com.wordnik.swagger.codegen.languages.RubyClientCodegen
com.wordnik.swagger.codegen.languages.ScalaClientCodegen
com.wordnik.swagger.codegen.languages.ScalatraServerCodegen

View File

@@ -60,10 +60,10 @@ dependencies {
compile "com.google.code.gson:gson:$gson_version"
compile "org.apache.httpcomponents:httpcore:$httpclient_version"
compile "org.apache.httpcomponents:httpclient:$httpclient_version"
compile ("org.apache.httpcomponents:httpcore:$httpcore_version") {
compile ("org.apache.httpcomponents:httpcore:$httpclient_version") {
exclude(group: 'org.apache.httpcomponents', module: 'httpclient')
}
compile ("org.apache.httpcomponents:httpmime:$httpmime_version") {
compile ("org.apache.httpcomponents:httpmime:$httpclient_version") {
exclude(group: 'org.apache.httpcomponents', module: 'httpclient')
}
testCompile "junit:junit:$junit_version"

View File

@@ -5,7 +5,7 @@ import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.List;
import io.swagger.client.model.*;
import {{modelPackage}}.*;
public class JsonUtil {
public static GsonBuilder gsonBuilder;

View File

@@ -0,0 +1,217 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using RestSharp;
namespace {{invokerPackage}} {
/// <summary>
/// API client is mainly responible for making the HTTP call to the API backend
/// </summary>
public class ApiClient {
/// <summary>
/// Initializes a new instance of the <see cref="ApiClient"/> class.
/// </summary>
/// <param name="basePath">The base path.</param>
public ApiClient(String basePath="{{basePath}}") {
this.basePath = basePath;
this.restClient = new RestClient(this.basePath);
}
/// <summary>
/// Gets or sets the base path.
/// </summary>
/// <value>The base path.</value>
public string basePath { get; set; }
/// <summary>
/// Gets or sets the RestClient
/// </summary>
/// <value>The RestClient.</value>
public RestClient restClient { get; set; }
private Dictionary<String, String> defaultHeaderMap = new Dictionary<String, String>();
public Object CallApi(String Path, RestSharp.Method Method, Dictionary<String, String> QueryParams, String PostBody,
Dictionary<String, String> HeaderParams, Dictionary<String, String> FormParams, Dictionary<String, String> FileParams, String[] AuthSettings) {
var response = Task.Run(async () => {
var resp = await CallApiAsync(Path, Method, QueryParams, PostBody, HeaderParams, FormParams, FileParams, AuthSettings);
return resp;
});
return response.Result;
}
public async Task<Object> CallApiAsync(String Path, RestSharp.Method Method, Dictionary<String, String> QueryParams, String PostBody,
Dictionary<String, String> HeaderParams, Dictionary<String, String> FormParams, Dictionary<String, String> FileParams, String[] AuthSettings) {
var request = new RestRequest(Path, Method);
UpdateParamsForAuth(QueryParams, HeaderParams, AuthSettings);
// add default header, if any
foreach(KeyValuePair<string, string> defaultHeader in this.defaultHeaderMap)
request.AddHeader(defaultHeader.Key, defaultHeader.Value);
// add header parameter, if any
foreach(KeyValuePair<string, string> param in HeaderParams)
request.AddHeader(param.Key, param.Value);
// add query parameter, if any
foreach(KeyValuePair<string, string> param in QueryParams)
request.AddQueryParameter(param.Key, param.Value);
// add form parameter, if any
foreach(KeyValuePair<string, string> param in FormParams)
request.AddParameter(param.Key, param.Value);
// add file parameter, if any
foreach(KeyValuePair<string, string> param in FileParams)
request.AddFile(param.Key, param.Value);
if (PostBody != null) {
request.AddParameter("application/json", PostBody, ParameterType.RequestBody); // http body (model) parameter
}
return (Object) await restClient.ExecuteTaskAsync(request);
}
/// <summary>
/// Add default header
/// </summary>
/// <param name="key"> Header field name
/// <param name="value"> Header field value
/// <returns></returns>
public void AddDefaultHeader(string key, string value) {
defaultHeaderMap.Add(key, value);
}
/// <summary>
/// Get default header
/// </summary>
/// <returns>Dictionary of default header</returns>
public Dictionary<String, String> GetDefaultHeader() {
return defaultHeaderMap;
}
/// <summary>
/// escape string (url-encoded)
/// </summary>
/// <param name="str"> String to be escaped
/// <returns>Escaped string</returns>
public string EscapeString(string str) {
return str;
}
/// <summary>
/// if parameter is DateTime, output in ISO8601 format
/// if parameter is a list of string, join the list with ","
/// otherwise just return the string
/// </summary>
/// <param name="obj"> The parameter (header, path, query, form)
/// <returns>Formatted string</returns>
public string ParameterToString(object obj)
{
if (obj is DateTime) {
return ((DateTime)obj).ToString ("u");
} else if (obj is List<string>) {
return String.Join(",", obj as List<string>);
} else {
return Convert.ToString (obj);
}
}
/// <summary>
/// Deserialize the JSON string into a proper object
/// </summary>
/// <param name="json"> JSON string
/// <param name="type"> Object type
/// <returns>Object representation of the JSON string</returns>
public object Deserialize(string content, Type type) {
if (type.GetType() == typeof(Object))
return (Object)content;
try
{
return JsonConvert.DeserializeObject(content, type);
}
catch (IOException e) {
throw new ApiException(500, e.Message);
}
}
/// <summary>
/// Serialize an object into JSON string
/// </summary>
/// <param name="obj"> Object
/// <returns>JSON string</returns>
public string Serialize(object obj) {
try
{
return obj != null ? JsonConvert.SerializeObject(obj) : null;
}
catch (Exception e) {
throw new ApiException(500, e.Message);
}
}
/// <summary>
/// Get the API key with prefix
/// </summary>
/// <param name="obj"> Object
/// <returns>API key with prefix</returns>
public string GetApiKeyWithPrefix (string apiKey)
{
var apiKeyValue = "";
Configuration.apiKey.TryGetValue (apiKey, out apiKeyValue);
var apiKeyPrefix = "";
if (Configuration.apiKeyPrefix.TryGetValue (apiKey, out apiKeyPrefix)) {
return apiKeyPrefix + " " + apiKeyValue;
} else {
return apiKeyValue;
}
}
/// <summary>
/// Update parameters based on authentication
/// </summary>
/// <param name="QueryParams">Query parameters</param>
/// <param name="HeaderParams">Header parameters</param>
/// <param name="AuthSettings">Authentication settings</param>
public void UpdateParamsForAuth(Dictionary<String, String> QueryParams, Dictionary<String, String> HeaderParams, string[] AuthSettings) {
if (AuthSettings == null || AuthSettings.Length == 0)
return;
foreach (string auth in AuthSettings) {
// determine which one to use
switch(auth) {
{{#authMethods}}
case "{{name}}":
{{#isApiKey}}{{#isKeyInHeader}}HeaderParams["{{keyParamName}}"] = GetApiKeyWithPrefix("{{keyParamName}}");{{/isKeyInHeader}}{{#isKeyInQuery}}QueryParams["{{keyParamName}}"] = GetApiKeyWithPrefix("{{keyParamName}}");{{/isKeyInQuery}}{{/isApiKey}}{{#isBasic}}HeaderParams["Authorization"] = "Basic " + Base64Encode(Configuration.username + ":" + Configuration.password);{{/isBasic}}
{{#isOAuth}}//TODO support oauth{{/isOAuth}}
break;
{{/authMethods}}
default:
//TODO show warning about security definition not found
break;
}
}
}
/// <summary>
/// Encode string in base64 format
/// </summary>
/// <param name="text">String to be encoded</param>
public static string Base64Encode(string text) {
var textByte = System.Text.Encoding.UTF8.GetBytes(text);
return System.Convert.ToBase64String(textByte);
}
}
}

View File

@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using {{invokerPackage}};
namespace {{invokerPackage}} {
/// <summary>
/// Represents a set of configuration settings
/// </summary>
public class Configuration{
/// <summary>
/// Gets or sets the API client. This is the default API client for making HTTP calls.
/// </summary>
/// <value>The API client.</value>
public static ApiClient apiClient = new ApiClient();
/// <summary>
/// Gets or sets the username (HTTP basic authentication)
/// </summary>
/// <value>The username.</value>
public static String username { get; set; }
/// <summary>
/// Gets or sets the password (HTTP basic authentication)
/// </summary>
/// <value>The password.</value>
public static String password { get; set; }
/// <summary>
/// Gets or sets the API key based on the authentication name
/// </summary>
/// <value>The API key.</value>
public static Dictionary<String, String> apiKey = new Dictionary<String, String>();
/// <summary>
/// Gets or sets the prefix (e.g. Token) of the API key based on the authentication name
/// </summary>
/// <value>The prefix of the API key.</value>
public static Dictionary<String, String> apiKeyPrefix = new Dictionary<String, String>();
}
}

View File

@@ -12,118 +12,155 @@ namespace {{package}} {
public interface I{{classname}} {
{{#operation}}
/// <summary>
/// {{summary}} {{notes}}
/// </summary>
{{#allParams}}/// <param name="{{paramName}}">{{description}}</param>{{/allParams}}
/// <returns>{{#returnType}}{{{returnType}}}{{/returnType}}</returns>
{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{nickname}} ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
/// <summary>
/// {{summary}} {{notes}}
/// </summary>
{{#allParams}}/// <param name="{{paramName}}">{{description}}</param>{{/allParams}}
/// <returns>{{#returnType}}{{{returnType}}}{{/returnType}}</returns>
{{#returnType}}Task<{{{returnType}}}>{{/returnType}}{{^returnType}}Task{{/returnType}} {{nickname}}Async ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
{{/operation}}
}
/// <summary>
/// Represents a collection of functions to interact with the API endpoints
/// </summary>
public class {{classname}} : I{{classname}} {
string basePath;
protected RestClient restClient;
public {{classname}}(String basePath = "{{basePath}}")
{
this.basePath = basePath;
this.restClient = new RestClient(basePath);
}
/// <summary>
/// Sets the endpoint base url for the services being accessed
/// Initializes a new instance of the <see cref="{{classname}}"/> class.
/// </summary>
/// <param name="basePath"> Base URL
/// <param name="apiClient"> an instance of ApiClient (optional)
/// <returns></returns>
public void SetBasePath(string basePath) {
this.basePath = basePath;
public {{classname}}(ApiClient apiClient = null) {
if (apiClient == null) { // use the default one in Configuration
this.apiClient = Configuration.apiClient;
} else {
this.apiClient = apiClient;
}
}
/// <summary>
/// Gets the endpoint base url for the services being accessed
/// <returns>Base URL</returns>
/// Initializes a new instance of the <see cref="{{classname}}"/> class.
/// </summary>
public String GetBasePath() {
return this.basePath;
/// <returns></returns>
public {{classname}}(String basePath)
{
this.apiClient = new ApiClient(basePath);
}
/// <summary>
/// Sets the base path of the API client.
/// </summary>
/// <value>The base path</value>
public void SetBasePath(String basePath) {
this.apiClient.basePath = basePath;
}
/// <summary>
/// Gets the base path of the API client.
/// </summary>
/// <value>The base path</value>
public String GetBasePath(String basePath) {
return this.apiClient.basePath;
}
/// <summary>
/// Gets or sets the API client.
/// </summary>
/// <value>The API client</value>
public ApiClient apiClient {get; set;}
{{#operation}}
/// <summary>
/// {{summary}} {{notes}}
/// </summary>
{{#allParams}} /// <param name="{{paramName}}">{{description}}</param>
{{/allParams}}
{{#allParams}}/// <param name="{{paramName}}">{{description}}</param>{{/allParams}}
/// <returns>{{#returnType}}{{{returnType}}}{{/returnType}}</returns>
public {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{nickname}} ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) {
var _request = new RestRequest("{{path}}", Method.{{httpMethod}});
{{#allParams}}{{#required}}
// verify the required parameter '{{paramName}}' is set
if ({{paramName}} == null) throw new ApiException(400, "Missing required parameter '{{paramName}}' when calling {{nickname}}");
{{/required}}{{/allParams}}
// add default header, if any
foreach(KeyValuePair<string, string> defaultHeader in ApiInvoker.GetDefaultHeader())
{
_request.AddHeader(defaultHeader.Key, defaultHeader.Value);
}
_request.AddUrlSegment("format", "json"); // set format to json by default
{{#pathParams}}_request.AddUrlSegment("{{baseName}}", ApiInvoker.ParameterToString({{{paramName}}})); // path (url segment) parameter
var path = "{{path}}";
path = path.Replace("{format}", "json");
{{#pathParams}}path = path.Replace("{" + "{{baseName}}" + "}", apiClient.ParameterToString({{{paramName}}}));
{{/pathParams}}
{{#queryParams}} if ({{paramName}} != null) _request.AddParameter("{{baseName}}", ApiInvoker.ParameterToString({{paramName}})); // query parameter
var queryParams = new Dictionary<String, String>();
var headerParams = new Dictionary<String, String>();
var formParams = new Dictionary<String, String>();
var fileParams = new Dictionary<String, String>();
String postBody = null;
{{#queryParams}} if ({{paramName}} != null) queryParams.Add("{{baseName}}", apiClient.ParameterToString({{paramName}})); // query parameter
{{/queryParams}}
{{#headerParams}} if ({{paramName}} != null) _request.AddHeader("{{baseName}}", ApiInvoker.ParameterToString({{paramName}})); // header parameter
{{#headerParams}} if ({{paramName}} != null) headerParams.Add("{{baseName}}", apiClient.ParameterToString({{paramName}})); // header parameter
{{/headerParams}}
{{#formParams}}if ({{paramName}} != null) {{#isFile}}_request.AddFile("{{baseName}}", {{paramName}});{{/isFile}}{{^isFile}}_request.AddParameter("{{baseName}}", ApiInvoker.ParameterToString({{paramName}})); // form parameter{{/isFile}}
{{#formParams}}if ({{paramName}} != null) {{#isFile}}fileParams.Add("{{baseName}}", {{paramName}});{{/isFile}}{{^isFile}}formParams.Add("{{baseName}}", apiClient.ParameterToString({{paramName}})); // form parameter{{/isFile}}
{{/formParams}}
{{#bodyParam}}_request.AddParameter("application/json", ApiInvoker.Serialize({{paramName}}), ParameterType.RequestBody); // http body (model) parameter
{{#bodyParam}}postBody = apiClient.Serialize({{paramName}}); // http body (model) parameter
{{/bodyParam}}
// authentication setting, if any
String[] authSettings = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} };
// make the HTTP request
IRestResponse response = restClient.Execute(_request);
IRestResponse response = (IRestResponse) apiClient.CallApi(path, Method.{{httpMethod}}, queryParams, postBody, headerParams, formParams, fileParams, authSettings);
if (((int)response.StatusCode) >= 400) {
throw new ApiException ((int)response.StatusCode, "Error calling {{nickname}}: " + response.Content, response.Content);
}
{{#returnType}}return ({{{returnType}}}) ApiInvoker.Deserialize(response.Content, typeof({{{returnType}}}));{{/returnType}}{{^returnType}}
{{#returnType}}return ({{{returnType}}}) apiClient.Deserialize(response.Content, typeof({{{returnType}}}));{{/returnType}}{{^returnType}}
return;{{/returnType}}
}
/// <summary>
/// {{summary}} {{notes}}
/// </summary>
{{#allParams}} /// <param name="{{paramName}}">{{description}}</param>
{{/allParams}}
{{#allParams}}/// <param name="{{paramName}}">{{description}}</param>{{/allParams}}
/// <returns>{{#returnType}}{{{returnType}}}{{/returnType}}</returns>
public async {{#returnType}}Task<{{{returnType}}}>{{/returnType}}{{^returnType}}Task{{/returnType}} {{nickname}}Async ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) {
var _request = new RestRequest("{{path}}", Method.{{httpMethod}});
{{#allParams}}{{#required}}
// verify the required parameter '{{paramName}}' is set
if ({{paramName}} == null) throw new ApiException(400, "Missing required parameter '{{paramName}}' when calling {{nickname}}");
// verify the required parameter '{{paramName}}' is set
if ({{paramName}} == null) throw new ApiException(400, "Missing required parameter '{{paramName}}' when calling {{nickname}}");
{{/required}}{{/allParams}}
// add default header, if any
foreach(KeyValuePair<string, string> defaultHeader in ApiInvoker.GetDefaultHeader())
{
_request.AddHeader(defaultHeader.Key, defaultHeader.Value);
}
_request.AddUrlSegment("format", "json"); // set format to json by default
{{#pathParams}}_request.AddUrlSegment("{{baseName}}", ApiInvoker.ParameterToString({{{paramName}}})); // path (url segment) parameter
var path = "{{path}}";
path = path.Replace("{format}", "json");
{{#pathParams}}path = path.Replace("{" + "{{baseName}}" + "}", apiClient.ParameterToString({{{paramName}}}));
{{/pathParams}}
{{#queryParams}} if ({{paramName}} != null) _request.AddParameter("{{baseName}}", ApiInvoker.ParameterToString({{paramName}})); // query parameter
var queryParams = new Dictionary<String, String>();
var headerParams = new Dictionary<String, String>();
var formParams = new Dictionary<String, String>();
var fileParams = new Dictionary<String, String>();
String postBody = null;
{{#queryParams}} if ({{paramName}} != null) queryParams.Add("{{baseName}}", apiClient.ParameterToString({{paramName}})); // query parameter
{{/queryParams}}
{{#headerParams}} if ({{paramName}} != null) _request.AddHeader("{{baseName}}", ApiInvoker.ParameterToString({{paramName}})); // header parameter
{{#headerParams}} if ({{paramName}} != null) headerParams.Add("{{baseName}}", apiClient.ParameterToString({{paramName}})); // header parameter
{{/headerParams}}
{{#formParams}}if ({{paramName}} != null) {{#isFile}}_request.AddFile("{{baseName}}", {{paramName}});{{/isFile}}{{^isFile}}_request.AddParameter("{{baseName}}", ApiInvoker.ParameterToString({{paramName}})); // form parameter{{/isFile}}
{{#formParams}}if ({{paramName}} != null) {{#isFile}}fileParams.Add("{{baseName}}", {{paramName}});{{/isFile}}{{^isFile}}formParams.Add("{{baseName}}", apiClient.ParameterToString({{paramName}})); // form parameter{{/isFile}}
{{/formParams}}
{{#bodyParam}}_request.AddParameter("application/json", ApiInvoker.Serialize({{paramName}}), ParameterType.RequestBody); // http body (model) parameter
{{#bodyParam}}postBody = apiClient.Serialize({{paramName}}); // http body (model) parameter
{{/bodyParam}}
// authentication setting, if any
String[] authSettings = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} };
// make the HTTP request
IRestResponse response = await restClient.ExecuteTaskAsync(_request);
IRestResponse response = (IRestResponse) await apiClient.CallApiAsync(path, Method.{{httpMethod}}, queryParams, postBody, headerParams, formParams, fileParams, authSettings);
if (((int)response.StatusCode) >= 400) {
throw new ApiException ((int)response.StatusCode, "Error calling {{nickname}}: " + response.Content, response.Content);
}

View File

@@ -1,15 +1,29 @@
using System;
namespace {{invokerPackage}} {
/// <summary>
/// API Exception
/// </summary>
public class ApiException : Exception {
/// <summary>
/// Gets or sets the error code (HTTP status code)
/// </summary>
/// <value>The error code (HTTP status code).</value>
public int ErrorCode { get; set; }
public dynamic ErrorContent { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="ApiException"/> class.
/// </summary>
/// <param name="basePath">The base path.</param>
public ApiException() {}
/// <summary>
/// Initializes a new instance of the <see cref="ApiException"/> class.
/// </summary>
/// <param name="errorCode">HTTP status code.</param>
/// <param name="message">Error message.</param>
public ApiException(int errorCode, string message) : base(message) {
this.ErrorCode = errorCode;
}

View File

@@ -1,84 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using Newtonsoft.Json;
namespace {{invokerPackage}} {
public class ApiInvoker {
private static Dictionary<String, String> defaultHeaderMap = new Dictionary<String, String>();
/// <summary>
/// Add default header
/// </summary>
/// <param name="key"> Header field name
/// <param name="value"> Header field value
/// <returns></returns>
public static void AddDefaultHeader(string key, string value) {
defaultHeaderMap.Add(key, value);
}
/// <summary>
/// Get default header
/// </summary>
/// <returns>Dictionary of default header</returns>
public static Dictionary<String, String> GetDefaultHeader() {
return defaultHeaderMap;
}
/// <summary>
/// escape string (url-encoded)
/// </summary>
/// <param name="str"> String to be escaped
/// <returns>Escaped string</returns>
public static string EscapeString(string str) {
return str;
}
/// <summary>
/// if parameter is DateTime, output in ISO8601 format, otherwise just return the string
/// </summary>
/// <param name="obj"> The parameter (header, path, query, form)
/// <returns>Formatted string</returns>
public static string ParameterToString(object obj)
{
return (obj is DateTime) ? ((DateTime)obj).ToString ("u") : Convert.ToString (obj);
}
/// <summary>
/// Deserialize the JSON string into a proper object
/// </summary>
/// <param name="json"> JSON string
/// <param name="type"> Object type
/// <returns>Object representation of the JSON string</returns>
public static object Deserialize(string content, Type type) {
if (type.GetType() == typeof(Object))
return (Object)content;
try
{
return JsonConvert.DeserializeObject(content, type);
}
catch (IOException e) {
throw new ApiException(500, e.Message);
}
}
/// <summary>
/// Serialize an object into JSON string
/// </summary>
/// <param name="obj"> Object
/// <returns>JSON string</returns>
public static string Serialize(object obj) {
try
{
return obj != null ? JsonConvert.SerializeObject(obj) : null;
}
catch (Exception e) {
throw new ApiException(500, e.Message);
}
}
}
}

View File

@@ -1,2 +1,3 @@
SET CSCPATH=%SYSTEMROOT%\Microsoft.NET\Framework\v4.0.30319
%CSCPATH%\csc /reference:bin/Newtonsoft.Json.dll /target:library /out:bin/{{invokerPackage}}.dll /recurse:src\*.cs /doc:bin/{{invokerPackage}}.xml
%CSCPATH%\csc /reference:bin/Newtonsoft.Json.dll;bin/RestSharp.dll /target:library /out:bin/{{invokerPackage}}.dll /recurse:src\*.cs /doc:bin/{{invokerPackage}}.xml

View File

@@ -3,10 +3,15 @@ using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Newtonsoft.Json;
{{#models}}
{{#model}}
namespace {{package}} {
/// <summary>
/// {{description}}
/// </summary>
[DataContract]
public class {{classname}} {
{{#vars}}
@@ -15,6 +20,11 @@ namespace {{package}} {
public {{{datatype}}} {{name}} { get; set; }
{{/vars}}
/// <summary>
/// Get the string presentation of the object
/// </summary>
/// <returns>String presentation of the object</returns>
public override string ToString() {
var sb = new StringBuilder();
sb.Append("class {{classname}} {\n");
@@ -24,7 +34,16 @@ namespace {{package}} {
sb.Append("}\n");
return sb.ToString();
}
}
/// <summary>
/// Get the JSON string presentation of the object
/// </summary>
/// <returns>JSON string presentation of the object</returns>
public string ToJson() {
return JsonConvert.SerializeObject(this, Formatting.Indented);
}
}
{{/model}}
{{/models}}
}

View File

@@ -3,7 +3,7 @@
/**
* A key for `NSError` user info dictionaries.
*
*
* The corresponding value is the parsed response body for an HTTP error.
*/
extern NSString *const SWGResponseObjectErrorKey;
@@ -20,56 +20,197 @@ extern NSString *const SWGResponseObjectErrorKey;
@property(nonatomic, assign) BOOL logHTTP;
@property(nonatomic, readonly) NSOperationQueue* queue;
/**
* Get the Api Client instance from pool
*
* @param baseUrl The base url of api client.
*
* @return The SWGApiClient instance.
*/
+(SWGApiClient *)sharedClientFromPool:(NSString *)baseUrl;
/**
* Get the operations queue
*
* @return The `shardQueue` static variable.
*/
+(NSOperationQueue*) sharedQueue;
/**
* Turn on logging
*
* @param state logging state, must be `YES` or `NO`
*/
+(void)setLoggingEnabled:(bool) state;
/**
* Clear Cache
*/
+(void)clearCache;
/**
* Turn on cache
*
* @param enabled If the cached is enable, must be `YES` or `NO`
*/
+(void)setCacheEnabled:(BOOL) enabled;
/**
* Get the request queue size
*
* @return The size of `queuedRequests` static variable.
*/
+(unsigned long)requestQueueSize;
/**
* Set the client unreachable
*
* @param state off line state, must be `YES` or `NO`
*/
+(void) setOfflineState:(BOOL) state;
/**
* Get the client reachability
*
* @return The client reachability.
*/
+(AFNetworkReachabilityStatus) getReachabilityStatus;
/**
* Get the next request id
*
* @return The next executed request id.
*/
+(NSNumber*) nextRequestId;
/**
* Generate request id and add it to the queue
*
* @return The next executed request id.
*/
+(NSNumber*) queueRequest;
/**
* Remove request id from the queue
*
* @param requestId The request which will be removed.
*/
+(void) cancelRequest:(NSNumber*)requestId;
/**
* URL encode NSString
*
* @param unescaped The string which will be escaped.
*
* @return The escaped string.
*/
+(NSString*) escape:(id)unescaped;
/**
* Customize the behavior when the reachability changed
*
* @param changeBlock The block will be executed when the reachability changed.
*/
+(void) setReachabilityChangeBlock:(void(^)(int))changeBlock;
/**
* Set the client reachability strategy
*
* @param host The host of SWGApiClient.
*/
+(void) configureCacheReachibilityForHost:(NSString*)host;
/**
* Detect Accept header from accepts NSArray
*
* @param accepts NSArray of header
*
* @return The Accept header
*/
+(NSString *) selectHeaderAccept:(NSArray *)accepts;
/**
* Detect Content-Type header from contentTypes NSArray
*
* @param contentTypes NSArray of header
*
* @return The Content-Type header
*/
+(NSString *) selectHeaderContentType:(NSArray *)contentTypes;
/**
* Set header for request
*
* @param value The header value
* @param forKey The header key
*/
-(void)setHeaderValue:(NSString*) value
forKey:(NSString*) forKey;
forKey:(NSString*) forKey;
/**
* Update header parameters and query parameters for authentication
*
* @param headers The header parameter will be udpated, passed by pointer to pointer.
* @param querys The query parameters will be updated, passed by pointer to pointer.
* @param authSettings The authentication names NSArray.
*/
- (void) updateHeaderParams:(NSDictionary **)headers
queryParams:(NSDictionary **)querys
WithAuthSettings:(NSArray *)authSettings;
/**
* Perform request
*
* Request with non-empty response
*
* @param path Request url.
* @param method Request method.
* @param queryParams Request query parameters.
* @param body Request body.
* @param headerParams Request header parameters.
* @param authSettings Request authentication names.
* @param requestContentType Request content-type.
* @param responseContentType Response content-type.
* @param completionBlock The block will be executed when the request completed.
*
* @return The request id.
*/
-(NSNumber*) dictionary:(NSString*) path
method:(NSString*) method
queryParams:(NSDictionary*) queryParams
body:(id) body
headerParams:(NSDictionary*) headerParams
authSettings: (NSArray *) authSettings
requestContentType:(NSString*) requestContentType
responseContentType:(NSString*) responseContentType
completionBlock:(void (^)(NSDictionary*, NSError *))completionBlock;
/**
* Perform request
*
* Request with empty response
*
* @param path Request url.
* @param method Request method.
* @param queryParams Request query parameters.
* @param body Request body.
* @param headerParams Request header parameters.
* @param authSettings Request authentication names.
* @param requestContentType Request content-type.
* @param responseContentType Response content-type.
* @param completionBlock The block will be executed when the request completed.
*
* @return The request id.
*/
-(NSNumber*) stringWithCompletionBlock:(NSString*) path
method:(NSString*) method
queryParams:(NSDictionary*) queryParams
body:(id) body
headerParams:(NSDictionary*) headerParams
authSettings: (NSArray *) authSettings
requestContentType:(NSString*) requestContentType
responseContentType:(NSString*) responseContentType
completionBlock:(void (^)(NSString*, NSError *))completionBlock;
@end

View File

@@ -1,6 +1,7 @@
#import "SWGApiClient.h"
#import "SWGFile.h"
#import "SWGQueryParamCollection.h"
#import "SWGConfiguration.h"
@implementation SWGApiClient
@@ -15,10 +16,22 @@ static NSOperationQueue* sharedQueue;
static void (^reachabilityChangeBlock)(int);
static bool loggingEnabled = true;
#pragma mark - Log Methods
+(void)setLoggingEnabled:(bool) state {
loggingEnabled = state;
}
- (void)logRequest:(NSURLRequest*)request {
NSLog(@"request: %@", [self descriptionForRequest:request]);
}
- (void)logResponse:(id)data forRequest:(NSURLRequest*)request error:(NSError*)error {
NSLog(@"request: %@ response: %@ ", [self descriptionForRequest:request], data );
}
#pragma mark -
+(void)clearCache {
[[NSURLCache sharedURLCache] removeAllCachedResponses];
}
@@ -134,10 +147,12 @@ static bool loggingEnabled = true;
}
+(NSNumber*) nextRequestId {
long nextId = ++requestId;
if(loggingEnabled)
NSLog(@"got id %ld", nextId);
return [NSNumber numberWithLong:nextId];
@synchronized(self) {
long nextId = ++requestId;
if(loggingEnabled)
NSLog(@"got id %ld", nextId);
return [NSNumber numberWithLong:nextId];
}
}
+(NSNumber*) queueRequest {
@@ -303,19 +318,47 @@ static bool loggingEnabled = true;
return [[request URL] absoluteString];
}
- (void)logRequest:(NSURLRequest*)request {
NSLog(@"request: %@", [self descriptionForRequest:request]);
/**
* Update header and query params based on authentication settings
*/
- (void) updateHeaderParams:(NSDictionary *__autoreleasing *)headers
queryParams:(NSDictionary *__autoreleasing *)querys
WithAuthSettings:(NSArray *)authSettings {
if (!authSettings || [authSettings count] == 0) {
return;
}
NSMutableDictionary *headersWithAuth = [NSMutableDictionary dictionaryWithDictionary:*headers];
NSMutableDictionary *querysWithAuth = [NSMutableDictionary dictionaryWithDictionary:*querys];
SWGConfiguration *config = [SWGConfiguration sharedConfig];
for (NSString *auth in authSettings) {
NSDictionary *authSetting = [[config authSettings] objectForKey:auth];
if (authSetting) {
if ([authSetting[@"in"] isEqualToString:@"header"]) {
[headersWithAuth setObject:authSetting[@"value"] forKey:authSetting[@"key"]];
}
else if ([authSetting[@"in"] isEqualToString:@"query"]) {
[querysWithAuth setObject:authSetting[@"value"] forKey:authSetting[@"key"]];
}
}
}
*headers = [NSDictionary dictionaryWithDictionary:headersWithAuth];
*querys = [NSDictionary dictionaryWithDictionary:querysWithAuth];
}
- (void)logResponse:(id)data forRequest:(NSURLRequest*)request error:(NSError*)error {
NSLog(@"request: %@ response: %@ ", [self descriptionForRequest:request], data );
}
#pragma mark - Perform Request Methods
-(NSNumber*) dictionary: (NSString*) path
method: (NSString*) method
queryParams: (NSDictionary*) queryParams
body: (id) body
headerParams: (NSDictionary*) headerParams
authSettings: (NSArray *) authSettings
requestContentType: (NSString*) requestContentType
responseContentType: (NSString*) responseContentType
completionBlock: (void (^)(NSDictionary*, NSError *))completionBlock {
@@ -340,6 +383,9 @@ static bool loggingEnabled = true;
else {
self.responseSerializer = [AFHTTPResponseSerializer serializer];
}
// auth setting
[self updateHeaderParams:&headerParams queryParams:&queryParams WithAuthSettings:authSettings];
NSMutableURLRequest * request = nil;
if (body != nil && [body isKindOfClass:[NSArray class]]){
@@ -474,6 +520,7 @@ static bool loggingEnabled = true;
queryParams: (NSDictionary*) queryParams
body: (id) body
headerParams: (NSDictionary*) headerParams
authSettings: (NSArray *) authSettings
requestContentType: (NSString*) requestContentType
responseContentType: (NSString*) responseContentType
completionBlock: (void (^)(NSString*, NSError *))completionBlock {
@@ -498,6 +545,9 @@ static bool loggingEnabled = true;
else {
self.responseSerializer = [AFHTTPResponseSerializer serializer];
}
// auth setting
[self updateHeaderParams:&headerParams queryParams:&queryParams WithAuthSettings:authSettings];
NSMutableURLRequest * request = nil;
if (body != nil && [body isKindOfClass:[NSArray class]]){

View File

@@ -0,0 +1,99 @@
#import "SWGConfiguration.h"
@interface SWGConfiguration ()
@property (readwrite, nonatomic, strong) NSMutableDictionary *mutableApiKey;
@property (readwrite, nonatomic, strong) NSMutableDictionary *mutableApiKeyPrefix;
@end
@implementation SWGConfiguration
#pragma mark - Singletion Methods
+ (instancetype) sharedConfig {
static SWGConfiguration *shardConfig = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
shardConfig = [[self alloc] init];
});
return shardConfig;
}
#pragma mark - Initialize Methods
- (instancetype) init {
self = [super init];
if (self) {
self.username = @"";
self.password = @"";
self.mutableApiKey = [NSMutableDictionary dictionary];
self.mutableApiKeyPrefix = [NSMutableDictionary dictionary];
}
return self;
}
#pragma mark - Instance Methods
- (NSString *) getApiKeyWithPrefix:(NSString *)key {
if ([self.apiKeyPrefix objectForKey:key] && [self.apiKey objectForKey:key]) {
return [NSString stringWithFormat:@"%@ %@", [self.apiKeyPrefix objectForKey:key], [self.apiKey objectForKey:key]];
}
else if ([self.apiKey objectForKey:key]) {
return [NSString stringWithFormat:@"%@", [self.apiKey objectForKey:key]];
}
else {
return @"";
}
}
- (NSString *) getBasicAuthToken {
NSString *basicAuthCredentials = [NSString stringWithFormat:@"%@:%@", self.username, self.password];
NSData *data = [basicAuthCredentials dataUsingEncoding:NSUTF8StringEncoding];
basicAuthCredentials = [NSString stringWithFormat:@"Basic %@", [data base64EncodedStringWithOptions:0]];
return basicAuthCredentials;
}
#pragma mark - Setter Methods
- (void) setValue:(NSString *)value forApiKeyField:(NSString *)field {
[self.mutableApiKey setValue:value forKey:field];
}
- (void) setValue:(NSString *)value forApiKeyPrefixField:(NSString *)field {
[self.mutableApiKeyPrefix setValue:value forKey:field];
}
#pragma mark - Getter Methods
- (NSDictionary *) apiKey {
return [NSDictionary dictionaryWithDictionary:self.mutableApiKey];
}
- (NSDictionary *) apiKeyPrefix {
return [NSDictionary dictionaryWithDictionary:self.mutableApiKeyPrefix];
}
#pragma mark -
- (NSDictionary *) authSettings {
return @{ {{#authMethods}}{{#isApiKey}}
@"{{name}}": @{
@"type": @"api_key",
@"in": {{#isKeyInHeader}}@"header"{{/isKeyInHeader}}{{#isKeyInQuery}}@"query"{{/isKeyInQuery}},
@"key": @"{{keyParamName}}",
@"value": [self getApiKeyWithPrefix:@"{{keyParamName}}"]
},
{{/isApiKey}}{{#isBasic}}
@"{{name}}": @{
@"type": @"basic",
@"in": @"header",
@"key": @"Authorization",
@"value": [self getBasicAuthToken]
},
{{/isBasic}}{{/authMethods}}
};
}
@end

View File

@@ -0,0 +1,56 @@
#import <Foundation/Foundation.h>
@interface SWGConfiguration : NSObject
/**
* Api key values for Api Key type Authentication
*
* To add or remove api key, use `setValue:forApiKeyField:`.
*/
@property (readonly, nonatomic, strong) NSDictionary *apiKey;
/**
* Api key prefix values to be prepend to the respective api key
*
* To add or remove prefix, use `setValue:forApiKeyPrefixField:`.
*/
@property (readonly, nonatomic, strong) NSDictionary *apiKeyPrefix;
/**
* Usename and Password for Basic type Authentication
*/
@property (nonatomic) NSString *username;
@property (nonatomic) NSString *password;
/**
* Get configuration singleton instance
*/
+ (instancetype) sharedConfig;
/**
* Sets field in `apiKey`
*/
- (void) setValue:(NSString *)value forApiKeyField:(NSString*)field;
/**
* Sets field in `apiKeyPrefix`
*/
- (void) setValue:(NSString *)value forApiKeyPrefixField:(NSString *)field;
/**
* Get API key (with prefix if set)
*/
- (NSString *) getApiKeyWithPrefix:(NSString *) key;
/**
* Get Basic Auth token
*/
- (NSString *) getBasicAuthToken;
/**
* Get Authentication Setings
*/
- (NSDictionary *) authSettings;
@end

View File

@@ -13,4 +13,4 @@
return self;
}
@end
@end

View File

@@ -2,7 +2,6 @@
#import "{{classname}}.h"
#import "SWGFile.h"
#import "SWGQueryParamCollection.h"
#import "SWGApiClient.h"
{{#imports}}#import "{{import}}.h"
{{/imports}}
{{newline}}
@@ -12,8 +11,36 @@
@end
@implementation {{classname}}
static NSString * basePath = @"{{basePath}}";
#pragma mark - Initialize methods
- (id) init {
self = [super init];
if (self) {
self.apiClient = [SWGApiClient sharedClientFromPool:basePath];
self.defaultHeaders = [NSMutableDictionary dictionary];
}
return self;
}
- (id) initWithApiClient:(SWGApiClient *)apiClient {
self = [super init];
if (self) {
if (apiClient) {
self.apiClient = apiClient;
}
else {
self.apiClient = [SWGApiClient sharedClientFromPool:basePath];
}
self.defaultHeaders = [NSMutableDictionary dictionary];
}
return self;
}
#pragma mark -
+({{classname}}*) apiWithHeader:(NSString*)headerValue key:(NSString*)key {
static {{classname}}* singletonAPI = nil;
@@ -32,21 +59,10 @@ static NSString * basePath = @"{{basePath}}";
return basePath;
}
-(SWGApiClient*) apiClient {
return [SWGApiClient sharedClientFromPool:basePath];
}
-(void) addHeader:(NSString*)value forKey:(NSString*)key {
[self.defaultHeaders setValue:value forKey:key];
}
-(id) init {
self = [super init];
self.defaultHeaders = [NSMutableDictionary dictionary];
[self apiClient];
return self;
}
-(void) setHeaderValue:(NSString*) value
forKey:(NSString*)key {
[self.defaultHeaders setValue:value forKey:key];
@@ -115,6 +131,9 @@ static NSString * basePath = @"{{basePath}}";
// request content type
NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[{{#consumes}}@"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/consumes}}]];
// Authentication setting
NSArray *authSettings = @[{{#authMethods}}@"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}}];
id bodyDictionary = nil;
{{#bodyParam}}
id __body = {{paramName}};
@@ -177,8 +196,6 @@ static NSString * basePath = @"{{basePath}}";
{{/requiredParams}}
{{/requiredParamCount}}
SWGApiClient* client = [SWGApiClient sharedClientFromPool:basePath];
{{#returnContainer}}
// response is in a container
{{>apiBodyResponseWithContainer}}{{/returnContainer}}
@@ -206,3 +223,6 @@ static NSString * basePath = @"{{basePath}}";
{{newline}}
{{/operations}}
@end

View File

@@ -2,11 +2,15 @@
{{#imports}}#import "{{import}}.h"
{{/imports}}
#import "SWGObject.h"
#import "SWGApiClient.h"
{{newline}}
{{#operations}}
@interface {{classname}}: NSObject
@property(nonatomic, assign)SWGApiClient *apiClient;
-(instancetype) initWithApiClient:(SWGApiClient *)apiClient;
-(void) addHeader:(NSString*)value forKey:(NSString*)key;
-(unsigned long) requestQueueSize;
+({{classname}}*) apiWithHeader:(NSString*)headerValue key:(NSString*)key;
@@ -34,4 +38,4 @@
{{/operation}}
{{/operations}}
@end
@end

View File

@@ -1,9 +1,10 @@
// {{returnContainer}} container response type
return [client dictionary: requestUrl
return [self.apiClient dictionary: requestUrl
method: @"{{httpMethod}}"
queryParams: queryParams
body: bodyDictionary
headerParams: headerParams
authSettings: authSettings
requestContentType: requestContentType
responseContentType: responseContentType
completionBlock: ^(NSDictionary *data, NSError *error) {
@@ -34,4 +35,4 @@
{{/returnBaseType}}
{{/isListContainer}}
}];

View File

@@ -1,10 +1,11 @@
{{^returnTypeIsPrimitive}}
// comples response type
return [client dictionary: requestUrl
return [self.apiClient dictionary: requestUrl
method: @"{{httpMethod}}"
queryParams: queryParams
body: bodyDictionary
headerParams: headerParams
authSettings: authSettings
requestContentType: requestContentType
responseContentType: responseContentType
completionBlock: ^(NSDictionary *data, NSError *error) {

View File

@@ -1,9 +1,10 @@
// primitive response type
{{#returnBaseType}}return [client stringWithCompletionBlock: requestUrl
{{#returnBaseType}}return [self.apiClient stringWithCompletionBlock: requestUrl
method: @"{{httpMethod}}"
queryParams: queryParams
body: bodyDictionary
headerParams: headerParams
authSettings: authSettings
requestContentType: requestContentType
responseContentType: responseContentType
completionBlock: ^(NSString *data, NSError *error) {
@@ -17,7 +18,7 @@
{{/returnBaseType}}
{{^returnBaseType}}
// no return base type
return [client stringWithCompletionBlock: requestUrl
return [self.apiClient stringWithCompletionBlock: requestUrl
method: @"{{httpMethod}}"
queryParams: queryParams
body: bodyDictionary
@@ -32,4 +33,4 @@
completionBlock(nil);
}];
{{/returnBaseType}}

View File

@@ -1,8 +1,9 @@
return [client stringWithCompletionBlock: requestUrl
return [self.apiClient stringWithCompletionBlock: requestUrl
method: @"{{httpMethod}}"
queryParams: queryParams
body: bodyDictionary
headerParams: headerParams
authSettings: authSettings
requestContentType: requestContentType
responseContentType: responseContentType
completionBlock: ^(NSString *data, NSError *error) {

View File

@@ -0,0 +1,22 @@
package WWW::{{invokerPackage}}::Configuration;
use strict;
use warnings;
use utf8;
use Log::Any qw($log);
use Carp;
# class/static variables
our $api_client;
our $http_timeout = 180;
our $http_user_agent = 'Perl-Swagger';
# authenticaiton setting
our $api_key = {};
our $api_key_prefix = {};
our $username;
our $password;
1;

View File

@@ -27,14 +27,10 @@ use Exporter;
use Carp qw( croak );
use Log::Any qw($log);
#use WWW::Swagger::Model::Category;
#use WWW::Swagger::Model::Pet;
use WWW::{{invokerPackage}}::ApiClient;
use WWW::{{invokerPackage}}::Configuration;
{{#operations}}
use WWW::{{invokerPackage}}::APIClient;
our @EXPORT_OK = qw(
{{#operation}}{{{nickname}}}
{{/operation}}
@@ -42,7 +38,7 @@ our @EXPORT_OK = qw(
sub new {
my $class = shift;
my $default_api_client = WWW::{{invokerPackage}}::APIClient->new;
my $default_api_client = $WWW::{{invokerPackage}}::Configuration::api_client ? $WWW::{{invokerPackage}}::Configuration::api_client : WWW::{{invokerPackage}}::ApiClient->new;
my (%self) = (
'api_client' => $default_api_client,
@_
@@ -92,49 +88,49 @@ sub new {
}
$header_params->{'Content-Type'} = $self->{api_client}->select_header_content_type({{#consumes}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/consumes}});
{{#queryParams}} # query params
{{#queryParams}}# query params
if ( exists $args{'{{paramName}}'}) {
$query_params->{'{{baseName}}'} = WWW::{{invokerPacakge}}::APIClient::to_query_value($args{'{{paramName}}'});
$query_params->{'{{baseName}}'} = $self->{api_client}->to_query_value($args{'{{paramName}}'});
}{{/queryParams}}
{{#headerParams}} # header params
{{#headerParams}}# header params
if ( exists $args{'{{paramName}}'}) {
$header_params->{'{{baseName}}'} = WWW::{{invokerPackage}}::APIClient::to_header_value($args{'{{paramName}}'});
$header_params->{'{{baseName}}'} = $self->{api_client}->to_header_value($args{'{{paramName}}'});
}{{/headerParams}}
{{#pathParams}} # path params
{{#pathParams}}# path params
if ( exists $args{'{{paramName}}'}) {
my $_base_variable = "{" . "{{baseName}}" . "}";
my $_base_value = WWW::{{invokerPackage}}::APIClient::to_path_value($args{'{{paramName}}'});
my $_base_value = $self->{api_client}->to_path_value($args{'{{paramName}}'});
$_resource_path =~ s/$_base_variable/$_base_value/g;
}{{/pathParams}}
{{#formParams}} # form params
{{#formParams}}# form params
if ( exists $args{'{{paramName}}'} ) {
{{#isFile}}$form_params->{'{{baseName}}'} = [] unless defined $form_params->{'{{baseName}}'};
push $form_params->{'{{baseName}}'}, $args{'{{paramName}}'};
{{/isFile}}
{{^isFile}}$form_params->{'{{baseName}}'} = WWW::{{invokerPackage}}::APIClient::to_form_value($args{'{{paramName}}'});
{{^isFile}}$form_params->{'{{baseName}}'} = $self->{api_client}->to_form_value($args{'{{paramName}}'});
{{/isFile}}
}{{/formParams}}
my $_body_data;
{{#bodyParams}} # body params
{{#bodyParams}}# body params
if ( exists $args{'{{paramName}}'}) {
$_body_data = $args{'{{paramName}}'};
}{{/bodyParams}}
# for HTTP post (form)
#$_body_data = $_body ? undef : $form_params;
# authentication setting, if any
my $auth_settings = [{{#authMethods}}'{{name}}'{{#hasMore}}, {{/hasMore}}{{/authMethods}}];
# make the API Call
{{#returnType}}my $response = $self->{api_client}->call_api($_resource_path, $_method,
$query_params, $form_params,
$header_params, $_body_data);
$header_params, $_body_data, $auth_settings);
if (!$response) {
return;
}
my $_response_object = $self->{api_client}->deserialize('{{returnType}}', $response);
return $_response_object;{{/returnType}}
my $_response_object = $self->{api_client}->deserialize('{{returnType}}', $response);
return $_response_object;{{/returnType}}
{{^returnType}}$self->{api_client}->call_api($_resource_path, $_method,
$query_params, $form_params,
$header_params, $_body_data);
$header_params, $_body_data, $auth_settings);
return;
{{/returnType}}
}

View File

@@ -1,9 +1,10 @@
package WWW::{{invokerPackage}}::APIClient;
package WWW::{{invokerPackage}}::ApiClient;
use strict;
use warnings;
use utf8;
use MIME::Base64;
use LWP::UserAgent;
use HTTP::Headers;
use HTTP::Response;
@@ -15,20 +16,18 @@ use URI::Escape;
use Scalar::Util;
use Log::Any qw($log);
use Carp;
use Switch;
use Module::Runtime qw(use_module);
# class variables
my $ua = LWP::UserAgent->new;
my $http_user_agent = 'Perl-Swagger'; # HTTP user-agent
my $http_timeout; #timeout
my $base_url = "{{basePath}}";
use WWW::{{invokerPackage}}::Configuration;
sub new
{
my $class = shift;
my %args = @_;
my (%args) = (
'ua' => LWP::UserAgent->new,
'base_url' => '{{basePath}}',
@_
);
return bless \%args, $class;
}
@@ -38,8 +37,8 @@ sub new
# @param string $user_agent The user agent of the API client
#
sub set_user_agent {
my $user_agent = shift;
$http_user_agent= $user_agent;
my ($self, $user_agent) = @_;
$self->{http_user_agent}= $user_agent;
}
# Set timeout
@@ -47,11 +46,11 @@ sub set_user_agent {
# @param integer $seconds Number of seconds before timing out [set to 0 for no timeout]
#
sub set_timeout {
my $seconds = shift;
my ($self, $seconds) = @_;
if (!looks_like_number($seconds)) {
croak('Timeout variable must be numeric.');
}
$http_timeout = $seconds;
$self->{http_timeout} = $seconds;
}
# make the HTTP request
@@ -63,60 +62,63 @@ sub set_timeout {
# @return mixed
sub call_api {
my $self = shift;
my ($resource_path, $method, $query_params, $post_params, $header_params, $body_data) = @_;
my ($resource_path, $method, $query_params, $post_params, $header_params, $body_data, $auth_settings) = @_;
my $headers = HTTP::Headers->new(%$header_params);
# update parameters based on authentication settings
$self->update_params_for_auth($header_params, $query_params, $auth_settings);
my $_url = $base_url . $resource_path;
my $_url = $self->{base_url} . $resource_path;
# build query
if (%$query_params) {
$_url = ($_url . '?' . eval { URI::Query->new($query_params)->stringify });
}
# body data
$body_data = to_json($body_data->to_hash) if defined $body_data && $body_data->can('to_hash'); # model to json string
my $_body_data = %$post_params ? $post_params : $body_data;
# Make the HTTP request
my $_request;
switch ($method) {
case 'POST' {
if ($method eq 'POST') {
# multipart
my $_content_type = lc $header_params->{'Content-Type'} eq 'multipart/form' ?
$header_params->{'Content-Type'} = lc $header_params->{'Content-Type'} eq 'multipart/form' ?
'form-data' : $header_params->{'Content-Type'};
$_request = POST($_url, Accept => $header_params->{Accept},
Content_Type => $_content_type, Content => $_body_data);
}
case 'PUT' {
# multipart
my $_content_type = lc $header_params->{'Content-Type'} eq 'multipart/form' ?
'form-data' : $header_params->{'Content-Type'};
$_request = PUT($_url, Accept => $header_params->{Accept},
Content_Type => $_content_type, Content => $_body_data);
}
case 'GET' {
$_request = GET($_url, Accept => $header_params->{'Accept'},
Content_Type => $header_params->{'Content-Type'});
}
case 'HEAD' {
$_request = HEAD($_url, Accept => $header_params->{'Accept'},
Content_Type => $header_params->{'Content-Type'});
}
case 'DELETE' { #TODO support form data
$_request = DELETE($_url, Accept => $header_params->{'Accept'},
Content_Type => $header_params->{'Content-Type'}, Content => $_body_data);
}
case 'PATCH' { #TODO
}
$_request = POST($_url, %$header_params, Content => $_body_data);
}
elsif ($method eq 'PUT') {
# multipart
$header_params->{'Content-Type'} = lc $header_params->{'Content-Type'} eq 'multipart/form' ?
'form-data' : $header_params->{'Content-Type'};
$_request = PUT($_url, %$header_params, Content => $_body_data);
}
elsif ($method eq 'GET') {
my $headers = HTTP::Headers->new(%$header_params);
$_request = GET($_url, %$header_params);
}
elsif ($method eq 'HEAD') {
my $headers = HTTP::Headers->new(%$header_params);
$_request = HEAD($_url,%$header_params);
}
elsif ($method eq 'DELETE') { #TODO support form data
my $headers = HTTP::Headers->new(%$header_params);
$_request = DELETE($_url, %$headers);
}
elsif ($method eq 'PATCH') { #TODO
}
else {
}
$ua->timeout($http_timeout);
$ua->agent($http_user_agent);
$self->{ua}->timeout($self->{http_timeout} || $WWW::{{invokerPackage}}::Configuration::http_timeout);
$self->{ua}->agent($self->{http_user_agent} || $WWW::{{invokerPackage}}::Configuration::http_user_agent);
my $_response = $ua->request($_request);
my $_response = $self->{ua}->request($_request);
unless ($_response->is_success) {
croak("API Exception(".$_response->code."): ".$_response->message);
@@ -126,41 +128,13 @@ sub call_api {
}
# Build a JSON POST object
sub sanitize_for_serialization
{
# my $data = shift;
# if (is_scalar($data) || null === $data) {
# $sanitized = $data;
# } else if ($data instanceof \DateTime) {
# $sanitized = $data->format(\DateTime::ISO8601);
# } else if (is_array($data)) {
# foreach ($data as $property => $value) {
# $data[$property] = $this->sanitizeForSerialization($value);
# }
# $sanitized = $data;
# } else if (is_object($data)) {
# $values = array();
# foreach (array_keys($data::$swaggerTypes) as $property) {
# $values[$data::$attributeMap[$property]] = $this->sanitizeForSerialization($data->$property);
# }
# $sanitized = $values;
# } else {
# $sanitized = (string)$data;
# }
#
# return $sanitized;
}
# Take value and turn it into a string suitable for inclusion in
# the path, by url-encoding.
# @param string $value a string which will be part of the path
# @return string the serialized object
sub to_path_value {
my $value = shift;
return uri_escape(to_string($value));
my ($self, $value) = @_;
return uri_escape($self->to_string($value));
}
@@ -171,11 +145,11 @@ sub to_path_value {
# @param object $object an object to be serialized to a string
# @return string the serialized object
sub to_query_value {
my $object = shift;
my ($self, $object) = @_;
if (is_array($object)) {
return implode(',', $object);
} else {
return toString($object);
return $self->to_string($object);
}
}
@@ -186,8 +160,8 @@ sub to_query_value {
# @param string $value a string which will be part of the header
# @return string the header string
sub to_header_value {
my $value = shift;
return to_string($value);
my ($self, $value) = @_;
return $self->to_string($value);
}
# Take value and turn it into a string suitable for inclusion in
@@ -196,8 +170,8 @@ sub to_header_value {
# @param string $value the value of the form parameter
# @return string the form string
sub to_form_value {
my $value = shift;
return to_string($value);
my ($self, $value) = @_;
return $self->to_string($value);
}
# Take value and turn it into a string suitable for inclusion in
@@ -206,7 +180,7 @@ sub to_form_value {
# @param string $value the value of the parameter
# @return string the header string
sub to_string {
my $value = shift;
my ($self, $value) = @_;
if (ref($value) eq "DateTime") { # datetime in ISO8601 format
return $value->datetime();
}
@@ -242,7 +216,7 @@ sub deserialize
$_result = \@_values;
} elsif ($class eq 'DateTime') {
$_result = DateTime->from_epoch(epoch => str2time($data));
} elsif (grep /^$data$/, ('string', 'int', 'float', 'bool')) { #TODO revise the primitive type
} elsif (grep /^$class$/, ('string', 'int', 'float', 'bool', 'object')) { #TODO revise the primitive type
$_result= $data;
} else { # model
my $_instance = use_module("WWW::{{invokerPackage}}::Object::$class")->new;
@@ -287,5 +261,44 @@ sub select_header_content_type
}
# Get API key (with prefix if set)
# @param string key name
# @return string API key with the prefix
sub get_api_key_with_prefix
{
my ($self, $api_key) = @_;
if ($WWW::{{invokerPackage}}::Configuration::api_key_prefix->{$api_key}) {
return $WWW::{{invokerPackage}}::Configuration::api_key_prefix->{$api_key}." ".$WWW::{{invokerPackage}}::Configuration::api_key->{$api_key};
} else {
return $WWW::{{invokerPackage}}::Configuration::api_key->{$api_key};
}
}
# update hearder and query param based on authentication setting
#
# @param array $headerParams header parameters (by ref)
# @param array $queryParams query parameters (by ref)
# @param array $authSettings array of authentication scheme (e.g ['api_key'])
sub update_params_for_auth {
my ($self, $header_params, $query_params, $auth_settings) = @_;
return if (!defined($auth_settings) || scalar(@$auth_settings) == 0);
# one endpoint can have more than 1 auth settings
foreach my $auth (@$auth_settings) {
# determine which one to use
if (!defined($auth)) {
}
{{#authMethods}}elsif ($auth eq '{{name}}') {
{{#isApiKey}}{{#isKeyInHeader}}$header_params->{'{{keyParamName}}'} = $self->get_api_key_with_prefix('{{keyParamName}}');{{/isKeyInHeader}}{{#isKeyInQuery}}$query_params->{'{{keyParamName}}'} = $self->get_api_key_with_prefix('{{keyParamName}}');{{/isKeyInQuery}}{{/isApiKey}}{{#isBasic}}$header_params->{'Authorization'} = 'Basic '.encode_base64($WWW::{{invokerPackage}}::Configuration::username.":".$WWW::{{invokerPackage}}::Configuration::password);{{/isBasic}}
{{#isOAuth}}# TODO support oauth{{/isOAuth}}
}
{{/authMethods}}
else {
# TODO show warning about security definition not found
}
}
}
1;

View File

@@ -17,7 +17,7 @@
namespace {{invokerPackage}};
class APIClient {
class ApiClient {
public static $PATCH = "PATCH";
public static $POST = "POST";
@@ -173,7 +173,7 @@ class APIClient {
* @param array $headerParams parameters to be place in request header
* @return mixed
*/
public function callAPI($resourcePath, $method, $queryParams, $postData,
public function callApi($resourcePath, $method, $queryParams, $postData,
$headerParams, $authSettings) {
$headers = array();
@@ -182,13 +182,10 @@ class APIClient {
$this->updateParamsForAuth($headerParams, $queryParams, $authSettings);
# construct the http header
if ($headerParams != null) {
# add default header
$headerParams = array_merge((array)self::$default_header, $headerParams);
$headerParams = array_merge((array)self::$default_header, (array)$headerParams);
foreach ($headerParams as $key => $val) {
$headers[] = "$key: $val";
}
foreach ($headerParams as $key => $val) {
$headers[] = "$key: $val";
}
// form data
@@ -228,35 +225,49 @@ class APIClient {
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
} else if ($method != self::$GET) {
throw new APIClientException('Method ' . $method . ' is not recognized.');
throw new ApiException('Method ' . $method . ' is not recognized.');
}
curl_setopt($curl, CURLOPT_URL, $url);
// Set user agent
curl_setopt($curl, CURLOPT_USERAGENT, $this->user_agent);
// debugging for curl
if (Configuration::$debug) {
error_log("[DEBUG] HTTP Request body ~BEGIN~\n".print_r($postData, true)."\n~END~\n", 3, Configuration::$debug_file);
curl_setopt($curl, CURLOPT_VERBOSE, 1);
curl_setopt($curl, CURLOPT_STDERR, fopen(Configuration::$debug_file, 'a'));
} else {
curl_setopt($curl, CURLOPT_VERBOSE, 0);
}
// obtain the HTTP response headers
curl_setopt($curl, CURLOPT_HEADER, 1);
// Make the request
$response = curl_exec($curl);
$http_header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
$http_header = substr($response, 0, $http_header_size);
$http_body = substr($response, $http_header_size);
$response_info = curl_getinfo($curl);
// debug HTTP response body
if (Configuration::$debug) {
error_log("[DEBUG] HTTP Response body ~BEGIN~\n".print_r($http_body, true)."\n~END~\n", 3, Configuration::$debug_file);
}
// Handle the response
if ($response_info['http_code'] == 0) {
throw new APIClientException("TIMEOUT: api call to " . $url .
" took more than 5s to return", 0, $response_info, $response);
throw new ApiException("API call to $url timed out: ".serialize($response_info), 0, null, null);
} else if ($response_info['http_code'] >= 200 && $response_info['http_code'] <= 299 ) {
$data = json_decode($response);
$data = json_decode($http_body);
if (json_last_error() > 0) { // if response is a string
$data = $response;
$data = $http_body;
}
} else if ($response_info['http_code'] == 401) {
throw new APIClientException("Unauthorized API request to " . $url .
": " . serialize($response), 0, $response_info, $response);
} else if ($response_info['http_code'] == 404) {
$data = null;
} else {
throw new APIClientException("Can't connect to the api: " . $url .
" response code: " .
$response_info['http_code'], 0, $response_info, $response);
throw new ApiException("[".$response_info['http_code']."] Error connecting to the API ($url)",
$response_info['http_code'], $http_header, $http_body);
}
return $data;
}
@@ -278,7 +289,9 @@ class APIClient {
} else if (is_object($data)) {
$values = array();
foreach (array_keys($data::$swaggerTypes) as $property) {
$values[$data::$attributeMap[$property]] = $this->sanitizeForSerialization($data->$property);
if ($data->$property !== null) {
$values[$data::$attributeMap[$property]] = $this->sanitizeForSerialization($data->$property);
}
}
$sanitized = $values;
} else {
@@ -383,7 +396,7 @@ class APIClient {
$deserialized = $values;
} elseif ($class == 'DateTime') {
$deserialized = new \DateTime($data);
} elseif (in_array($class, array('string', 'int', 'float', 'double', 'bool'))) {
} elseif (in_array($class, array('string', 'int', 'float', 'double', 'bool', 'object'))) {
settype($data, $class);
$deserialized = $data;
} else {

View File

@@ -19,20 +19,40 @@ namespace {{invokerPackage}};
use \Exception;
class APIClientException extends Exception {
protected $response, $response_info;
class ApiException extends Exception {
public function __construct($message="", $code=0, $response_info=null, $response=null) {
/**
* The HTTP body of the server response.
*/
protected $response_body;
/**
* The HTTP header of the server response.
*/
protected $response_headers;
public function __construct($message="", $code=0, $responseHeaders=null, $responseBody=null) {
parent::__construct($message, $code);
$this->response_info = $response_info;
$this->response = $response;
$this->response_headers = $responseHeaders;
$this->response_body = $responseBody;
}
public function getResponse() {
return $this->response;
/**
* Get the HTTP response header
*
* @return string HTTP response header
*/
public function getResponseHeaders() {
return $this->response_headers;
}
public function getResponseInfo() {
return $this->response_info;
/**
* Get the HTTP response body
*
* @return string HTTP response body
*/
public function getResponseBody() {
return $this->response_body;
}
}

View File

@@ -28,7 +28,7 @@ class {{classname}} {
function __construct($apiClient = null) {
if (null === $apiClient) {
if (Configuration::$apiClient === null) {
Configuration::$apiClient = new APIClient(); // create a new API client if not present
Configuration::$apiClient = new ApiClient(); // create a new API client if not present
$this->apiClient = Configuration::$apiClient;
}
else
@@ -38,7 +38,7 @@ class {{classname}} {
}
}
private $apiClient; // instance of the APIClient
private $apiClient; // instance of the ApiClient
/**
* get the API client

View File

@@ -19,27 +19,47 @@ namespace {{invokerPackage}};
class Configuration {
public static $PATCH = "PATCH";
public static $POST = "POST";
public static $GET = "GET";
public static $PUT = "PUT";
public static $DELETE = "DELETE";
// authentication setting
/**
* Associate array to store API key(s)
*/
public static $apiKey = array();
/**
* Associate array to store API prefix (e.g. Bearer)
*/
public static $apiKeyPrefix = array();
/**
* Username for HTTP basic authentication
*/
public static $username = '';
/**
* Password for HTTP basic authentication
*/
public static $password = '';
// an instance of APIClient
/**
* The default instance of ApiClient
*/
public static $apiClient;
/*
* manually initalize API client
*/
/**
* Debug switch (default set to false)
*/
public static $debug = false;
/**
* Debug file location (log to STDOUT by default)
*/
public static $debug_file = 'php://output';
/*
* manually initalize ApiClient
*/
public static function init() {
if (self::$apiClient === null)
self::$apiClient = new APIClient();
self::$apiClient = new ApiClient();
}
}

View File

@@ -29,13 +29,16 @@ from six import iteritems
from ..util import remove_none
from ..swagger import ApiClient
from .. import config
{{#operations}}
class {{classname}}(object):
def __init__(self, api_client):
self.api_client = api_client
def __init__(self, api_client=None):
if api_client:
self.api_client = api_client
else:
self.api_client = config.api_client
{{#operation}}
def {{nickname}}(self, {{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}**kwargs):
"""
@@ -71,12 +74,12 @@ class {{classname}}(object):
body_params = {{#bodyParam}}params.get('{{paramName}}'){{/bodyParam}}{{^bodyParam}}None{{/bodyParam}}
# HTTP header `Accept`
header_params['Accept'] = ApiClient.select_header_accept([{{#produces}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/produces}}])
header_params['Accept'] = self.api_client.select_header_accept([{{#produces}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/produces}}])
if not header_params['Accept']:
del header_params['Accept']
# HTTP header `Content-Type`
header_params['Content-Type'] = ApiClient.select_header_content_type([{{#consumes}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/consumes}}])
header_params['Content-Type'] = self.api_client.select_header_content_type([{{#consumes}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/consumes}}])
response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params,
body=body_params, post_params=form_params, files=files,

View File

@@ -0,0 +1,8 @@
from __future__ import absolute_import
from .swagger import ApiClient
# Configuration variables
api_client = ApiClient("{{basePath}}")

View File

@@ -2,6 +2,8 @@
import sys
import io
import json
import ssl
import certifi
# python 2 and python 3 compatibility library
from six import iteritems
@@ -42,10 +44,30 @@ class RESTResponse(io.IOBase):
class RESTClientObject(object):
def __init__(self, pools_size=4):
# http pool manager
self.pool_manager = urllib3.PoolManager(
num_pools=pools_size
)
# https pool manager
# certificates validated using Mozillas root certificates
self.ssl_pool_manager = urllib3.PoolManager(
num_pools=pools_size,
cert_reqs=ssl.CERT_REQUIRED,
ca_certs=certifi.where()
)
def agent(self, url):
"""
Return proper pool manager for the http\https schemes.
"""
url = urllib3.util.url.parse_url(url)
scheme = url.scheme
if scheme == 'https':
return self.ssl_pool_manager
else:
return self.pool_manager
def request(self, method, url, query_params=None, headers=None,
body=None, post_params=None):
"""
@@ -56,7 +78,6 @@ class RESTClientObject(object):
:param body: request json body, for `application/json`
:param post_params: request post parameters, `application/x-www-form-urlencode`
and `multipart/form-data`
:param raw_response: if return the raw response
"""
method = method.upper()
assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT', 'PATCH']
@@ -75,27 +96,27 @@ class RESTClientObject(object):
if query_params:
url += '?' + urlencode(query_params)
if headers['Content-Type'] == 'application/json':
r = self.pool_manager.request(method, url,
body=json.dumps(body),
headers=headers)
r = self.agent(url).request(method, url,
body=json.dumps(body),
headers=headers)
if headers['Content-Type'] == 'application/x-www-form-urlencoded':
r = self.pool_manager.request(method, url,
fields=post_params,
encode_multipart=False,
headers=headers)
r = self.agent(url).request(method, url,
fields=post_params,
encode_multipart=False,
headers=headers)
if headers['Content-Type'] == 'multipart/form-data':
# must del headers['Content-Type'], or the correct Content-Type
# which generated by urllib3 will be overwritten.
del headers['Content-Type']
r = self.pool_manager.request(method, url,
fields=post_params,
encode_multipart=True,
headers=headers)
r = self.agent(url).request(method, url,
fields=post_params,
encode_multipart=True,
headers=headers)
# For `GET`, `HEAD`, `DELETE`
else:
r = self.pool_manager.request(method, url,
fields=query_params,
headers=headers)
r = self.agent(url).request(method, url,
fields=query_params,
headers=headers)
r = RESTResponse(r)
if r.status not in range(200, 206):

View File

@@ -12,7 +12,7 @@ from setuptools import setup, find_packages
# Try reading the setuptools documentation:
# http://pypi.python.org/pypi/setuptools
REQUIRES = ["urllib3 >= 1.10", "six >= 1.9"]
REQUIRES = ["urllib3 >= 1.10", "six >= 1.9", "certifi"]
setup(
name="{{module}}",

View File

@@ -66,28 +66,28 @@ class ApiClient(object):
if self.cookie:
headers['Cookie'] = self.cookie
if headers:
headers = ApiClient.sanitize_for_serialization(headers)
headers = self.sanitize_for_serialization(headers)
# path parameters
if path_params:
path_params = ApiClient.sanitize_for_serialization(path_params)
path_params = self.sanitize_for_serialization(path_params)
for k, v in iteritems(path_params):
replacement = quote(str(self.to_path_value(v)))
resource_path = resource_path.replace('{' + k + '}', replacement)
# query parameters
if query_params:
query_params = ApiClient.sanitize_for_serialization(query_params)
query_params = self.sanitize_for_serialization(query_params)
query_params = {k: self.to_path_value(v) for k, v in iteritems(query_params)}
# post parameters
if post_params:
post_params = self.prepare_post_parameters(post_params, files)
post_params = ApiClient.sanitize_for_serialization(post_params)
post_params = self.sanitize_for_serialization(post_params)
# body
if body:
body = ApiClient.sanitize_for_serialization(body)
body = self.sanitize_for_serialization(body)
# request url
url = self.host + resource_path
@@ -115,8 +115,7 @@ class ApiClient(object):
else:
return str(obj)
@staticmethod
def sanitize_for_serialization(obj):
def sanitize_for_serialization(self, obj):
"""
Sanitize an object for Request.
@@ -132,7 +131,7 @@ class ApiClient(object):
elif isinstance(obj, (str, int, float, bool, tuple)):
return obj
elif isinstance(obj, list):
return [ApiClient.sanitize_for_serialization(sub_obj) for sub_obj in obj]
return [self.sanitize_for_serialization(sub_obj) for sub_obj in obj]
elif isinstance(obj, (datetime.datetime, datetime.date)):
return obj.isoformat()
else:
@@ -145,7 +144,7 @@ class ApiClient(object):
obj_dict = {obj.attribute_map[key]: val
for key, val in iteritems(obj.__dict__)
if key != 'swagger_types' and key != 'attribute_map' and val is not None}
return {key: ApiClient.sanitize_for_serialization(val)
return {key: self.sanitize_for_serialization(val)
for key, val in iteritems(obj_dict)}
def deserialize(self, obj, obj_class):
@@ -253,8 +252,7 @@ class ApiClient(object):
return params
@staticmethod
def select_header_accept(accepts):
def select_header_accept(self, accepts):
"""
Return `Accept` based on an array of accepts provided
"""
@@ -268,8 +266,7 @@ class ApiClient(object):
else:
return ', '.join(accepts)
@staticmethod
def select_header_content_type(content_types):
def select_header_content_type(self, content_types):
"""
Return `Content-Type` baseed on an array of content_types provided
"""

View File

@@ -0,0 +1,29 @@
package {{package}};
import {{modelPackage}}.*;
import retrofit.http.*;
import retrofit.mime.*;
import java.util.*;
{{#imports}}import {{import}};
{{/imports}}
{{#operations}}
public interface {{classname}} {
{{#operation}}
/**
* {{summary}}
* {{notes}}
{{#allParams}} * @param {{paramName}} {{description}}
{{/allParams}} * @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}
*/
{{#formParams}}{{#-first}}
{{#isMultipart}}@Multipart{{/isMultipart}}{{^isMultipart}}@FormUrlEncoded{{/isMultipart}}{{/-first}}{{/formParams}}
@{{httpMethod}}("{{path}}")
{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Object{{/returnType}} {{nickname}}({{^allParams}});{{/allParams}}
{{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}},{{/hasMore}}{{^hasMore}}
);{{/hasMore}}{{/allParams}}
{{/operation}}
}
{{/operations}}

View File

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

View File

@@ -0,0 +1 @@
{{#isFormParam}}{{#notFile}}{{#isMultipart}}@Part{{/isMultipart}}{{^isMultipart}}@Field{{/isMultipart}}("{{paramName}}") {{{dataType}}} {{paramName}}{{/notFile}}{{#isFile}}{{#isMultipart}}@Part{{/isMultipart}}{{^isMultipart}}@Field{{/isMultipart}}("{{paramName}}") TypedFile {{paramName}}{{/isFile}}{{/isFormParam}}

View File

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

View File

@@ -0,0 +1,50 @@
package {{package}};
{{#imports}}import {{import}};
{{/imports}}
import com.wordnik.swagger.annotations.*;
import com.google.gson.annotations.SerializedName;
{{#models}}
{{#model}}{{#description}}
/**
* {{description}}
**/{{/description}}
@ApiModel(description = "{{{description}}}")
public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}} {
{{#vars}}{{#isEnum}}
public enum {{datatypeWithEnum}} {
{{#allowableValues}}{{#values}} {{.}}, {{/values}}{{/allowableValues}}
};{{/isEnum}}
/**{{#description}}
* {{{description}}}{{/description}}{{#minimum}}
* minimum: {{minimum}}{{/minimum}}{{#maximum}}
* maximum: {{maximum}}{{/maximum}}
**/
@ApiModelProperty({{#required}}required = {{required}}, {{/required}}value = "{{{description}}}")
@SerializedName("{{baseName}}"){{#isEnum}}
private {{{datatypeWithEnum}}} {{name}} = {{{defaultValue}}};{{/isEnum}}{{^isEnum}}
private {{{datatype}}} {{name}} = {{{defaultValue}}};{{/isEnum}}{{/vars}}
{{#vars}}
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(" " + super.toString()).append("\n");{{/parent}}
{{#vars}}sb.append(" {{name}}: ").append({{name}}).append("\n");
{{/vars}}sb.append("}\n");
return sb.toString();
}
}
{{/model}}
{{/models}}

View File

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

View File

@@ -0,0 +1,143 @@
<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:wordnik/swagger-mustache.git</connection>
<developerConnection>scm:git:git@github.com:wordnik/swagger-codegen.git</developerConnection>
<url>https://github.com/wordnik/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>com.wordnik</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger-annotations-version}</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${gson-version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.squareup.retrofit</groupId>
<artifactId>retrofit</artifactId>
<version>${retrofit-version}</version>
<scope>compile</scope>
</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.3-M1</swagger-annotations-version>
<gson-version>2.3.1</gson-version>
<retrofit-version>1.9.0</retrofit-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}}") {{{dataType}}} {{paramName}}{{/isQueryParam}}

View File

@@ -0,0 +1,23 @@
package {{invokerPackage}};
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import retrofit.RestAdapter;
import retrofit.converter.GsonConverter;
public class ServiceGenerator {
// No need to instantiate this class.
private ServiceGenerator() { }
public static <S> S createService(Class<S> serviceClass) {
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
.create();
RestAdapter adapter = new RestAdapter.Builder()
.setEndpoint("{{basePath}}")
.setConverter(new GsonConverter(gson))
.build();
return adapter.create(serviceClass);
}
}

View File

@@ -50,8 +50,9 @@ module {{moduleName}}
{{/bodyParam}}{{#bodyParam}}post_body = Swagger::Request.object_to_http_body({{#required}}{{{paramName}}}{{/required}}{{^required}}opts[:'{{{paramName}}}']{{/required}})
{{/bodyParam}}
{{#returnType}}response = Swagger::Request.new(:{{httpMethod}}, path, {:params => query_params, :headers => header_params, :form_params => form_params, :body => post_body}).make.body
{{#returnContainer}}response.map {|response| {{/returnContainer}}obj = {{returnBaseType}}.new() and obj.build_from_hash(response){{#returnContainer}} }{{/returnContainer}}{{/returnType}}{{^returnType}}Swagger::Request.new(:{{httpMethod}}, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body}).make
auth_names = [{{#authMethods}}'{{name}}'{{#hasMore}}, {{/hasMore}}{{/authMethods}}]
{{#returnType}}response = Swagger::Request.new(:{{httpMethod}}, path, {:params => query_params, :headers => header_params, :form_params => form_params, :body => post_body, :auth_names => auth_names}).make.body
{{#returnContainer}}response.map {|response| {{/returnContainer}}obj = {{returnBaseType}}.new() and obj.build_from_hash(response){{#returnContainer}} }{{/returnContainer}}{{/returnType}}{{^returnType}}Swagger::Request.new(:{{httpMethod}}, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body, :auth_names => auth_names}).make
nil{{/returnType}}
end
{{/operation}}

View File

@@ -16,9 +16,9 @@ module {{moduleName}}
#
# @example
# Swagger.configure do |config|
# config.api_key = '1234567890abcdef' # required
# config.username = 'wordlover' # optional, but needed for user-related functions
# config.password = 'i<3words' # optional, but needed for user-related functions
# config.api_key['api_key'] = '1234567890abcdef' # api key authentication
# config.username = 'wordlover' # http basic authentication
# config.password = 'i<3words' # http basic authentication
# config.format = 'json' # optional, defaults to 'json'
# end
#

View File

@@ -1,8 +1,8 @@
module {{moduleName}}
module Swagger
class Configuration
attr_accessor :format, :api_key, :username, :password, :auth_token, :scheme, :host, :base_path, :user_agent, :logger, :inject_format, :force_ending_format, :camelize_params, :user_agent
attr_accessor :format, :api_key, :api_key_prefix, :username, :password, :auth_token, :scheme, :host, :base_path, :user_agent, :logger, :inject_format, :force_ending_format, :camelize_params, :user_agent, :verify_ssl
# Defaults go in here..
def initialize
@format = 'json'
@@ -13,6 +13,16 @@ module {{moduleName}}
@inject_format = false
@force_ending_format = false
@camelize_params = true
# keys for API key authentication (param-name => api-key)
@api_key = {}
# api-key prefix for API key authentication, e.g. "Bearer" (param-name => api-key-prefix)
@api_key_prefix = {}
# whether to verify SSL certificate, default to true
# Note: do NOT set it to false in production code, otherwise you would
# face multiple types of cryptographic attacks
@verify_ssl = true
end
end
end

View File

@@ -5,7 +5,7 @@ module {{moduleName}}
require 'addressable/uri'
require 'typhoeus'
attr_accessor :host, :path, :format, :params, :body, :http_method, :headers, :form_params
attr_accessor :host, :path, :format, :params, :body, :http_method, :headers, :form_params, :auth_names
# All requests must have an HTTP method and a path
# Optionals parameters are :params, :headers, :body, :format, :host
@@ -16,21 +16,9 @@ module {{moduleName}}
# Set default headers
default_headers = {
'Content-Type' => "application/#{attributes[:format].downcase}",
:api_key => Swagger.configuration.api_key,
'User-Agent' => Swagger.configuration.user_agent
}
# api_key from headers hash trumps the default, even if its value is blank
if attributes[:headers].present? && attributes[:headers].has_key?(:api_key)
default_headers.delete(:api_key)
end
# api_key from params hash trumps all others (headers and default_headers)
if attributes[:params].present? && attributes[:params].has_key?(:api_key)
default_headers.delete(:api_key)
attributes[:headers].delete(:api_key) if attributes[:headers].present?
end
# Merge argument headers into defaults
attributes[:headers] = default_headers.merge(attributes[:headers] || {})
@@ -44,6 +32,33 @@ module {{moduleName}}
attributes.each do |name, value|
send("#{name.to_s.underscore.to_sym}=", value)
end
update_params_for_auth!
end
# Update hearder and query params based on authentication settings.
def update_params_for_auth!
(@auth_names || []).each do |auth_name|
case auth_name
{{#authMethods}}when '{{name}}'
{{#isApiKey}}{{#isKeyInHeader}}@headers ||= {}
@headers['{{keyParamName}}'] = get_api_key_with_prefix('{{keyParamName}}'){{/isKeyInHeader}}{{#isKeyInQuery}}@params ||= {}
@params['{{keyParamName}}'] = get_api_key_with_prefix('{{keyParamName}}'){{/isKeyInQuery}}{{/isApiKey}}{{#isBasic}}@headers ||= {}
http_auth_header = 'Basic ' + ["#{Swagger.configuration.username}:#{Swagger.configuration.password}"].pack('m').delete("\r\n")
@headers['Authorization'] = http_auth_header{{/isBasic}}{{#isOAuth}}# TODO: support oauth{{/isOAuth}}
{{/authMethods}}
end
end
end
# Get API key (with prefix if set).
# @param [String] param_name the parameter name of API key auth
def get_api_key_with_prefix(param_name)
if Swagger.configuration.api_key_prefix[param_name].present?
"#{Swagger.configuration.api_key_prefix[param_name]} #{Swagger.configuration.api_key[param_name]}"
else
Swagger.configuration.api_key[param_name]
end
end
# Construct a base URL
@@ -58,9 +73,6 @@ module {{moduleName}}
# Drop trailing question mark, if present
u.sub! /\?$/, ''
# Obfuscate API key?
u.sub! /api\_key=\w+/, 'api_key=YOUR_API_KEY' if options[:obfuscated]
u
end
@@ -108,14 +120,16 @@ module {{moduleName}}
# For form parameters, remove empty value
def outgoing_body
# http form
if @body.nil? && @form_params && !@form_params.empty?
if headers['Content-Type'] == 'application/x-www-form-urlencoded'
data = form_params.dup
data.each do |key, value|
data[key] = value.to_s if value && !value.is_a?(File) # remove emtpy form parameter
end
data
else # http body is JSON
elsif @body # http body is JSON
@body.is_a?(String) ? @body : @body.to_json
else
nil
end
end
@@ -129,7 +143,7 @@ module {{moduleName}}
next if self.path.include? "{#{key}}" # skip path params
next if value.blank? && value.class != FalseClass # skip empties
if Swagger.configuration.camelize_params
key = key.to_s.camelize(:lower).to_sym unless key.to_sym == :api_key # api_key is not a camelCased param
key = key.to_s.camelize(:lower).to_sym
end
query_values[key] = value.to_s
end
@@ -148,39 +162,40 @@ module {{moduleName}}
#TODO use configuration setting to determine if debugging
#logger = Logger.new STDOUT
#logger.debug self.url
request_options = {
:ssl_verifypeer => Swagger.configuration.verify_ssl,
:headers => self.headers.stringify_keys
}
response = case self.http_method.to_sym
when :get,:GET
Typhoeus::Request.get(
self.url,
:headers => self.headers.stringify_keys,
request_options
)
when :post,:POST
Typhoeus::Request.post(
self.url,
:body => self.outgoing_body,
:headers => self.headers.stringify_keys,
request_options.merge(:body => self.outgoing_body)
)
when :patch,:PATCH
Typhoeus::Request.patch(
self.url,
:body => self.outgoing_body,
:headers => self.headers.stringify_keys,
request_options.merge(:body => self.outgoing_body)
)
when :put,:PUT
Typhoeus::Request.put(
self.url,
:body => self.outgoing_body,
:headers => self.headers.stringify_keys,
request_options.merge(:body => self.outgoing_body)
)
when :delete,:DELETE
Typhoeus::Request.delete(
self.url,
:body => self.outgoing_body,
:headers => self.headers.stringify_keys,
request_options.merge(:body => self.outgoing_body)
)
end
Response.new(response)