Merge remote-tracking branch 'upstream/develop_2.0' into develop_2.0-RestSharp-path-params

Conflicts:
	modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache
	modules/swagger-codegen/src/main/resources/csharp/api.mustache
This commit is contained in:
Peter S. May 2015-07-17 21:45:54 -04:00
commit 1072c9d017
352 changed files with 15584 additions and 12673 deletions

9
.gitignore vendored
View File

@ -31,8 +31,10 @@ samples/client/petstore/qt5cpp/PetStore/PetStore
samples/client/petstore/qt5cpp/PetStore/Makefile samples/client/petstore/qt5cpp/PetStore/Makefile
samples/client/petstore/java/hello.txt samples/client/petstore/java/hello.txt
samples/client/petstore/android-java/hello.txt samples/client/petstore/android-java/hello.txt
samples/client/petstore/objc/Build samples/client/petstore/objc/SwaggerClientTests/Build
samples/client/petstore/objc/Pods samples/client/petstore/objc/SwaggerClientTests/Pods
samples/client/petstore/objc/SwaggerClientTests/SwaggerClient.xcworkspace
samples/client/petstore/objc/SwaggerClientTests/Podfile.lock
samples/server/petstore/nodejs/node_modules samples/server/petstore/nodejs/node_modules
target target
.idea .idea
@ -45,3 +47,6 @@ samples/client/petstore/php/SwaggerClient-php/vendor/
samples/client/petstore/silex/SwaggerServer/composer.lock samples/client/petstore/silex/SwaggerServer/composer.lock
samples/client/petstore/silex/SwaggerServer/venodr/ samples/client/petstore/silex/SwaggerServer/venodr/
samples/client/petstore/python/.projectile
samples/client/petstore/python/.venv/

View File

@ -183,7 +183,7 @@ StaticDocCodegen.java
StaticHtmlGenerator.java StaticHtmlGenerator.java
SwaggerGenerator.java SwaggerGenerator.java
SwaggerYamlGenerator.java SwaggerYamlGenerator.java
SwiftGenerator.java SwiftCodegen.java
TizenClientCodegen.java TizenClientCodegen.java
``` ```

View File

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

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

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

View File

@ -26,6 +26,6 @@ fi
# if you've executed sbt assembly previously it will use that instead. # if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -t modules/swagger-codegen/src/main/resources/ruby -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l ruby -o samples/client/petstore/ruby" ags="$@ generate -t modules/swagger-codegen/src/main/resources/ruby -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l ruby -c bin/ruby-petstore.json -o samples/client/petstore/ruby"
java $JAVA_OPTS -jar $executable $ags java $JAVA_OPTS -jar $executable $ags

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

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

View File

@ -26,6 +26,6 @@ fi
# if you've executed sbt assembly previously it will use that instead. # if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -t modules/swagger-codegen/src/main/resources/swift -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l swift -o samples/client/petstore/swift" ags="$@ generate -t modules/swagger-codegen/src/main/resources/swift -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l swift -c ./bin/swift-petstore.json -o samples/client/petstore/swift"
java -DappName=PetstoreClient $JAVA_OPTS -jar $executable $ags java $JAVA_OPTS -jar $executable $ags

View File

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

View File

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

View File

@ -14,6 +14,7 @@ import io.swagger.models.Swagger;
import io.swagger.models.auth.ApiKeyAuthDefinition; import io.swagger.models.auth.ApiKeyAuthDefinition;
import io.swagger.models.auth.BasicAuthDefinition; import io.swagger.models.auth.BasicAuthDefinition;
import io.swagger.models.auth.In; import io.swagger.models.auth.In;
import io.swagger.models.auth.OAuth2Definition;
import io.swagger.models.auth.SecuritySchemeDefinition; import io.swagger.models.auth.SecuritySchemeDefinition;
import io.swagger.models.parameters.BodyParameter; import io.swagger.models.parameters.BodyParameter;
import io.swagger.models.parameters.CookieParameter; import io.swagger.models.parameters.CookieParameter;
@ -36,6 +37,7 @@ import io.swagger.models.properties.LongProperty;
import io.swagger.models.properties.MapProperty; import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property; import io.swagger.models.properties.Property;
import io.swagger.models.properties.PropertyBuilder; import io.swagger.models.properties.PropertyBuilder;
import io.swagger.models.properties.PropertyBuilder.PropertyId;
import io.swagger.models.properties.RefProperty; import io.swagger.models.properties.RefProperty;
import io.swagger.models.properties.StringProperty; import io.swagger.models.properties.StringProperty;
import io.swagger.util.Json; import io.swagger.util.Json;
@ -49,6 +51,7 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
@ -850,6 +853,17 @@ public class DefaultCodegen {
} }
op.bodyParam = bodyParam; op.bodyParam = bodyParam;
op.httpMethod = httpMethod.toUpperCase(); op.httpMethod = httpMethod.toUpperCase();
// move "required" parameters in front of "optional" parameters
Collections.sort(allParams, new Comparator<CodegenParameter>() {
@Override
public int compare(CodegenParameter one, CodegenParameter another) {
boolean oneRequired = one.required == null ? false : one.required;
boolean anotherRequired = another.required == null ? false : another.required;
if (oneRequired == anotherRequired) return 0;
else if (oneRequired) return -1;
else return 1;
}
});
op.allParams = addHasMore(allParams); op.allParams = addHasMore(allParams);
op.bodyParams = addHasMore(bodyParams); op.bodyParams = addHasMore(bodyParams);
op.pathParams = addHasMore(pathParams); op.pathParams = addHasMore(pathParams);
@ -964,7 +978,9 @@ public class DefaultCodegen {
p.baseType = pr.datatype; p.baseType = pr.datatype;
imports.add(pr.baseType); imports.add(pr.baseType);
} else { } else {
property = PropertyBuilder.build(qp.getType(), qp.getFormat(), null); Map<PropertyId, Object> args = new HashMap<PropertyId, Object>();
args.put(PropertyId.ENUM, qp.getEnum());
property = PropertyBuilder.build(qp.getType(), qp.getFormat(), args);
} }
if (property == null) { if (property == null) {
LOGGER.warn("warning! Property type \"" + qp.getType() + "\" not found for parameter \"" + param.getName() + "\", using String"); LOGGER.warn("warning! Property type \"" + qp.getType() + "\" not found for parameter \"" + param.getName() + "\", using String");
@ -972,8 +988,11 @@ public class DefaultCodegen {
} }
property.setRequired(param.getRequired()); property.setRequired(param.getRequired());
CodegenProperty model = fromProperty(qp.getName(), property); CodegenProperty model = fromProperty(qp.getName(), property);
p.collectionFormat = collectionFormat;
p.dataType = model.datatype; p.dataType = model.datatype;
p.isEnum = model.isEnum;
p._enum = model._enum;
p.allowableValues = model.allowableValues;
p.collectionFormat = collectionFormat;
p.paramName = toParamName(qp.getName()); p.paramName = toParamName(qp.getName());
if (model.complexType != null) { if (model.complexType != null) {
@ -1056,10 +1075,17 @@ public class DefaultCodegen {
sec.keyParamName = apiKeyDefinition.getName(); sec.keyParamName = apiKeyDefinition.getName();
sec.isKeyInHeader = apiKeyDefinition.getIn() == In.HEADER; sec.isKeyInHeader = apiKeyDefinition.getIn() == In.HEADER;
sec.isKeyInQuery = !sec.isKeyInHeader; sec.isKeyInQuery = !sec.isKeyInHeader;
} else if(schemeDefinition instanceof BasicAuthDefinition) {
sec.isKeyInHeader = sec.isKeyInQuery = sec.isApiKey = sec.isOAuth = false;
sec.isBasic = true;
} else { } else {
sec.isKeyInHeader = sec.isKeyInQuery = sec.isApiKey = false; final OAuth2Definition oauth2Definition = (OAuth2Definition) schemeDefinition;
sec.isBasic = schemeDefinition instanceof BasicAuthDefinition; sec.isKeyInHeader = sec.isKeyInQuery = sec.isApiKey = sec.isBasic = false;
sec.isOAuth = !sec.isBasic; sec.isOAuth = true;
sec.flow = oauth2Definition.getFlow();
sec.authorizationUrl = oauth2Definition.getAuthorizationUrl();
sec.tokenUrl = oauth2Definition.getTokenUrl();
sec.scopes = oauth2Definition.getScopes().keySet();
} }
sec.hasMore = it.hasNext(); sec.hasMore = it.hasNext();

View File

@ -9,6 +9,7 @@ import io.swagger.models.Model;
import io.swagger.models.Operation; import io.swagger.models.Operation;
import io.swagger.models.Path; import io.swagger.models.Path;
import io.swagger.models.Swagger; import io.swagger.models.Swagger;
import io.swagger.models.auth.OAuth2Definition;
import io.swagger.models.auth.SecuritySchemeDefinition; import io.swagger.models.auth.SecuritySchemeDefinition;
import io.swagger.util.Json; import io.swagger.util.Json;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
@ -218,7 +219,11 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
bundle.put("models", allModels); bundle.put("models", allModels);
bundle.put("apiFolder", config.apiPackage().replace('.', File.separatorChar)); bundle.put("apiFolder", config.apiPackage().replace('.', File.separatorChar));
bundle.put("modelPackage", config.modelPackage()); bundle.put("modelPackage", config.modelPackage());
bundle.put("authMethods", config.fromSecurity(swagger.getSecurityDefinitions())); List<CodegenSecurity> authMethods = config.fromSecurity(swagger.getSecurityDefinitions());
if (authMethods != null && !authMethods.isEmpty()) {
bundle.put("authMethods", authMethods);
bundle.put("hasAuthMethods", true);
}
if (swagger.getExternalDocs() != null) { if (swagger.getExternalDocs() != null) {
bundle.put("externalDocs", swagger.getExternalDocs()); bundle.put("externalDocs", swagger.getExternalDocs());
} }
@ -367,7 +372,22 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
String securityName = security.keySet().iterator().next(); String securityName = security.keySet().iterator().next();
SecuritySchemeDefinition securityDefinition = fromSecurity(securityName); SecuritySchemeDefinition securityDefinition = fromSecurity(securityName);
if (securityDefinition != null) { if (securityDefinition != null) {
authMethods.put(securityName, securityDefinition); if(securityDefinition instanceof OAuth2Definition) {
OAuth2Definition oauth2Definition = (OAuth2Definition) securityDefinition;
OAuth2Definition oauth2Operation = new OAuth2Definition();
oauth2Operation.setType(oauth2Definition.getType());
oauth2Operation.setAuthorizationUrl(oauth2Definition.getAuthorizationUrl());
oauth2Operation.setFlow(oauth2Definition.getFlow());
oauth2Operation.setTokenUrl(oauth2Definition.getTokenUrl());
for (String scope : security.values().iterator().next()) {
if (oauth2Definition.getScopes().containsKey(scope)) {
oauth2Operation.addScope(scope, oauth2Definition.getScopes().get(scope));
}
}
authMethods.put(securityName, oauth2Operation);
} else {
authMethods.put(securityName, securityDefinition);
}
} }
} }
if (!authMethods.isEmpty()) { if (!authMethods.isEmpty()) {
@ -393,6 +413,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
Map<String, Object> operations = new HashMap<String, Object>(); Map<String, Object> operations = new HashMap<String, Object>();
Map<String, Object> objs = new HashMap<String, Object>(); Map<String, Object> objs = new HashMap<String, Object>();
objs.put("classname", config.toApiName(tag)); objs.put("classname", config.toApiName(tag));
objs.put("pathPrefix", config.toApiVarName(tag));
// check for operationId uniqueness // check for operationId uniqueness
Set<String> opIds = new HashSet<String>(); Set<String> opIds = new HashSet<String>();
@ -430,6 +451,12 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
} }
operations.put("imports", imports); operations.put("imports", imports);
// add a flag to indicate whether there's any {{import}}
if (imports.size() > 0) {
operations.put("hasImport", true);
}
config.postProcessOperations(operations); config.postProcessOperations(operations);
if (objs.size() > 0) { if (objs.size() > 0) {
List<CodegenOperation> os = (List<CodegenOperation>) objs.get("operation"); List<CodegenOperation> os = (List<CodegenOperation>) objs.get("operation");

View File

@ -232,6 +232,8 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "JsonUtil.java")); (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "JsonUtil.java"));
supportingFiles.add(new SupportingFile("apiException.mustache", supportingFiles.add(new SupportingFile("apiException.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiException.java")); (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiException.java"));
supportingFiles.add(new SupportingFile("Pair.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "Pair.java"));
} }
public Boolean getUseAndroidMavenGradlePlugin() { public Boolean getUseAndroidMavenGradlePlugin() {

View File

@ -37,6 +37,7 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
languageSpecificPrimitives = new HashSet<String>( languageSpecificPrimitives = new HashSet<String>(
Arrays.asList( Arrays.asList(
"String",
"string", "string",
"bool?", "bool?",
"double?", "double?",
@ -53,6 +54,7 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
"Integer", "Integer",
"Long", "Long",
"Float", "Float",
"Stream", // not really a primitive, we include it to avoid model import
"Object") "Object")
); );
instantiationTypes.put("array", "List"); instantiationTypes.put("array", "List");
@ -68,7 +70,7 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
typeMapping.put("number", "double?"); typeMapping.put("number", "double?");
typeMapping.put("datetime", "DateTime?"); typeMapping.put("datetime", "DateTime?");
typeMapping.put("date", "DateTime?"); typeMapping.put("date", "DateTime?");
typeMapping.put("file", "string"); // path to file typeMapping.put("file", "Stream");
typeMapping.put("array", "List"); typeMapping.put("array", "List");
typeMapping.put("list", "List"); typeMapping.put("list", "List");
typeMapping.put("map", "Dictionary"); typeMapping.put("map", "Dictionary");
@ -110,6 +112,7 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
supportingFiles.add(new SupportingFile("Newtonsoft.Json.dll", "bin", "Newtonsoft.Json.dll")); supportingFiles.add(new SupportingFile("Newtonsoft.Json.dll", "bin", "Newtonsoft.Json.dll"));
supportingFiles.add(new SupportingFile("RestSharp.dll", "bin", "RestSharp.dll")); supportingFiles.add(new SupportingFile("RestSharp.dll", "bin", "RestSharp.dll"));
supportingFiles.add(new SupportingFile("compile.mustache", "", "compile.bat")); supportingFiles.add(new SupportingFile("compile.mustache", "", "compile.bat"));
supportingFiles.add(new SupportingFile("README.md", "", "README.md"));
} }
@ -163,8 +166,24 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
@Override @Override
public String toParamName(String name) { public String toParamName(String name) {
// should be the same as variable name // replace - with _ e.g. created-at => created_at
return toVarName(name); name = name.replaceAll("-", "_");
// if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$")) {
return name;
}
// camelize(lower) the variable name
// pet_id => petId
name = camelize(name, true);
// for reserved word or word starting with number, append _
if (reservedWords.contains(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name);
}
return name;
} }
@Override @Override

View File

@ -116,6 +116,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
supportingFiles.add(new SupportingFile("Configuration.mustache", invokerFolder, "Configuration.java")); supportingFiles.add(new SupportingFile("Configuration.mustache", invokerFolder, "Configuration.java"));
supportingFiles.add(new SupportingFile("JsonUtil.mustache", invokerFolder, "JsonUtil.java")); supportingFiles.add(new SupportingFile("JsonUtil.mustache", invokerFolder, "JsonUtil.java"));
supportingFiles.add(new SupportingFile("StringUtil.mustache", invokerFolder, "StringUtil.java")); supportingFiles.add(new SupportingFile("StringUtil.mustache", invokerFolder, "StringUtil.java"));
supportingFiles.add(new SupportingFile("Pair.mustache", invokerFolder, "Pair.java"));
final String authFolder = (sourceFolder + File.separator + invokerPackage + ".auth").replace(".", File.separator); final String authFolder = (sourceFolder + File.separator + invokerPackage + ".auth").replace(".", File.separator);
supportingFiles.add(new SupportingFile("auth/Authentication.mustache", authFolder, "Authentication.java")); supportingFiles.add(new SupportingFile("auth/Authentication.mustache", authFolder, "Authentication.java"));

View File

@ -18,43 +18,60 @@ import java.util.Set;
public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig { public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
protected Set<String> foundationClasses = new HashSet<String>(); protected Set<String> foundationClasses = new HashSet<String>();
protected String sourceFolder = "client"; protected String podName = "SwaggerClient";
protected String podVersion = "1.0.0";
protected String classPrefix = "SWG"; protected String classPrefix = "SWG";
protected String projectName = "SwaggerClient";
public ObjcClientCodegen() { public ObjcClientCodegen() {
super(); super();
outputFolder = "generated-code" + File.separator + "objc"; outputFolder = "generated-code" + File.separator + "objc";
modelTemplateFiles.put("model-header.mustache", ".h"); modelTemplateFiles.put("model-header.mustache", ".h");
modelTemplateFiles.put("model-body.mustache", ".m"); modelTemplateFiles.put("model-body.mustache", ".m");
apiTemplateFiles.put("api-header.mustache", ".h"); apiTemplateFiles.put("api-header.mustache", ".h");
apiTemplateFiles.put("api-body.mustache", ".m"); apiTemplateFiles.put("api-body.mustache", ".m");
templateDir = "objc"; templateDir = "objc";
modelPackage = "";
defaultIncludes = new HashSet<String>( defaultIncludes.clear();
Arrays.asList( defaultIncludes.add("bool");
"bool", defaultIncludes.add("BOOL");
"BOOL", defaultIncludes.add("int");
"int", defaultIncludes.add("NSURL");
"NSString", defaultIncludes.add("NSString");
"NSObject", defaultIncludes.add("NSObject");
"NSArray", defaultIncludes.add("NSArray");
"NSNumber", defaultIncludes.add("NSNumber");
"NSDate", defaultIncludes.add("NSDate");
"NSDictionary", defaultIncludes.add("NSDictionary");
"NSMutableArray", defaultIncludes.add("NSMutableArray");
"NSMutableDictionary") defaultIncludes.add("NSMutableDictionary");
);
languageSpecificPrimitives = new HashSet<String>( languageSpecificPrimitives.clear();
Arrays.asList( languageSpecificPrimitives.add("NSNumber");
"NSNumber", languageSpecificPrimitives.add("NSString");
"NSString", languageSpecificPrimitives.add("NSObject");
"NSObject", languageSpecificPrimitives.add("NSDate");
"NSDate", languageSpecificPrimitives.add("NSURL");
"bool", languageSpecificPrimitives.add("bool");
"BOOL") languageSpecificPrimitives.add("BOOL");
);
typeMapping.clear();
typeMapping.put("enum", "NSString");
typeMapping.put("Date", "NSDate");
typeMapping.put("DateTime", "NSDate");
typeMapping.put("boolean", "NSNumber");
typeMapping.put("string", "NSString");
typeMapping.put("integer", "NSNumber");
typeMapping.put("int", "NSNumber");
typeMapping.put("float", "NSNumber");
typeMapping.put("long", "NSNumber");
typeMapping.put("double", "NSNumber");
typeMapping.put("array", "NSArray");
typeMapping.put("map", "NSDictionary");
typeMapping.put("number", "NSNumber");
typeMapping.put("List", "NSArray");
typeMapping.put("object", "NSObject");
typeMapping.put("file", "NSURL");
// ref: http://www.tutorialspoint.com/objective_c/objective_c_basic_syntax.htm // ref: http://www.tutorialspoint.com/objective_c/objective_c_basic_syntax.htm
reservedWords = new HashSet<String>( reservedWords = new HashSet<String>(
@ -70,26 +87,10 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
"double", "protocol", "interface", "implementation", "double", "protocol", "interface", "implementation",
"NSObject", "NSInteger", "NSNumber", "CGFloat", "NSObject", "NSInteger", "NSNumber", "CGFloat",
"property", "nonatomic", "retain", "strong", "property", "nonatomic", "retain", "strong",
"weak", "unsafe_unretained", "readwrite", "readonly" "weak", "unsafe_unretained", "readwrite", "readonly",
"description"
)); ));
typeMapping = new HashMap<String, String>();
typeMapping.put("enum", "NSString");
typeMapping.put("Date", "NSDate");
typeMapping.put("DateTime", "NSDate");
typeMapping.put("boolean", "BOOL");
typeMapping.put("string", "NSString");
typeMapping.put("integer", "NSNumber");
typeMapping.put("int", "NSNumber");
typeMapping.put("float", "NSNumber");
typeMapping.put("long", "NSNumber");
typeMapping.put("double", "NSNumber");
typeMapping.put("array", "NSArray");
typeMapping.put("map", "NSDictionary");
typeMapping.put("number", "NSNumber");
typeMapping.put("List", "NSArray");
typeMapping.put("object", "NSObject");
importMapping = new HashMap<String, String>(); importMapping = new HashMap<String, String>();
foundationClasses = new HashSet<String>( foundationClasses = new HashSet<String>(
@ -98,15 +99,17 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
"NSObject", "NSObject",
"NSString", "NSString",
"NSDate", "NSDate",
"NSURL",
"NSDictionary") "NSDictionary")
); );
instantiationTypes.put("array", "NSMutableArray"); instantiationTypes.put("array", "NSMutableArray");
instantiationTypes.put("map", "NSMutableDictionary"); instantiationTypes.put("map", "NSMutableDictionary");
cliOptions.add(new CliOption("classPrefix", "prefix for generated classes")); cliOptions.clear();
cliOptions.add(new CliOption("sourceFolder", "source folder for generated code")); cliOptions.add(new CliOption("classPrefix", "prefix for generated classes (convention: Abbreviation of pod name e.g. `HN` for `HackerNews`), default: `SWG`"));
cliOptions.add(new CliOption("projectName", "name of the Xcode project in generated Podfile")); cliOptions.add(new CliOption("podName", "cocoapods package name (convention: CameCase), default: `SwaggerClient`"));
cliOptions.add(new CliOption("podVersion", "cocoapods package version, default: `1.0.0`"));
} }
public CodegenType getTag() { public CodegenType getTag() {
@ -125,35 +128,43 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
public void processOpts() { public void processOpts() {
super.processOpts(); super.processOpts();
if (additionalProperties.containsKey("sourceFolder")) { if (additionalProperties.containsKey("podName")) {
this.setSourceFolder((String) additionalProperties.get("sourceFolder")); setPodName((String) additionalProperties.get("podName"));
}
if (additionalProperties.containsKey("podVersion")) {
setPodVersion((String) additionalProperties.get("podVersion"));
} }
if (additionalProperties.containsKey("classPrefix")) { if (additionalProperties.containsKey("classPrefix")) {
this.setClassPrefix((String) additionalProperties.get("classPrefix")); setClassPrefix((String) additionalProperties.get("classPrefix"));
} }
if (additionalProperties.containsKey("projectName")) { additionalProperties.put("podName", podName);
this.setProjectName((String) additionalProperties.get("projectName")); additionalProperties.put("podVersion", podVersion);
} else { additionalProperties.put("classPrefix", classPrefix);
additionalProperties.put("projectName", projectName);
}
supportingFiles.add(new SupportingFile("SWGObject.h", sourceFolder, "SWGObject.h")); String swaggerFolder = podName;
supportingFiles.add(new SupportingFile("SWGObject.m", sourceFolder, "SWGObject.m"));
supportingFiles.add(new SupportingFile("SWGQueryParamCollection.h", sourceFolder, "SWGQueryParamCollection.h")); modelPackage = swaggerFolder;
supportingFiles.add(new SupportingFile("SWGQueryParamCollection.m", sourceFolder, "SWGQueryParamCollection.m")); apiPackage = swaggerFolder;
supportingFiles.add(new SupportingFile("SWGApiClient-header.mustache", sourceFolder, "SWGApiClient.h"));
supportingFiles.add(new SupportingFile("SWGApiClient-body.mustache", sourceFolder, "SWGApiClient.m")); supportingFiles.add(new SupportingFile("Object-header.mustache", swaggerFolder, classPrefix + "Object.h"));
supportingFiles.add(new SupportingFile("SWGJSONResponseSerializer-header.mustache", sourceFolder, "SWGJSONResponseSerializer.h")); supportingFiles.add(new SupportingFile("Object-body.mustache", swaggerFolder, classPrefix + "Object.m"));
supportingFiles.add(new SupportingFile("SWGJSONResponseSerializer-body.mustache", sourceFolder, "SWGJSONResponseSerializer.m")); supportingFiles.add(new SupportingFile("QueryParamCollection-header.mustache", swaggerFolder, classPrefix + "QueryParamCollection.h"));
supportingFiles.add(new SupportingFile("SWGFile.h", sourceFolder, "SWGFile.h")); supportingFiles.add(new SupportingFile("QueryParamCollection-body.mustache", swaggerFolder, classPrefix + "QueryParamCollection.m"));
supportingFiles.add(new SupportingFile("SWGFile.m", sourceFolder, "SWGFile.m")); supportingFiles.add(new SupportingFile("ApiClient-header.mustache", swaggerFolder, classPrefix + "ApiClient.h"));
supportingFiles.add(new SupportingFile("JSONValueTransformer+ISO8601.m", sourceFolder, "JSONValueTransformer+ISO8601.m")); supportingFiles.add(new SupportingFile("ApiClient-body.mustache", swaggerFolder, classPrefix + "ApiClient.m"));
supportingFiles.add(new SupportingFile("JSONValueTransformer+ISO8601.h", sourceFolder, "JSONValueTransformer+ISO8601.h")); supportingFiles.add(new SupportingFile("JSONResponseSerializer-header.mustache", swaggerFolder, classPrefix + "JSONResponseSerializer.h"));
supportingFiles.add(new SupportingFile("SWGConfiguration-body.mustache", sourceFolder, "SWGConfiguration.m")); supportingFiles.add(new SupportingFile("JSONResponseSerializer-body.mustache", swaggerFolder, classPrefix + "JSONResponseSerializer.m"));
supportingFiles.add(new SupportingFile("SWGConfiguration-header.mustache", sourceFolder, "SWGConfiguration.h")); supportingFiles.add(new SupportingFile("JSONRequestSerializer-body.mustache", swaggerFolder, classPrefix + "JSONRequestSerializer.m"));
supportingFiles.add(new SupportingFile("Podfile.mustache", "", "Podfile")); supportingFiles.add(new SupportingFile("JSONRequestSerializer-header.mustache", swaggerFolder, classPrefix + "JSONRequestSerializer.h"));
supportingFiles.add(new SupportingFile("JSONValueTransformer+ISO8601.m", swaggerFolder, "JSONValueTransformer+ISO8601.m"));
supportingFiles.add(new SupportingFile("JSONValueTransformer+ISO8601.h", swaggerFolder, "JSONValueTransformer+ISO8601.h"));
supportingFiles.add(new SupportingFile("Configuration-body.mustache", swaggerFolder, classPrefix + "Configuration.m"));
supportingFiles.add(new SupportingFile("Configuration-header.mustache", swaggerFolder, classPrefix + "Configuration.h"));
supportingFiles.add(new SupportingFile("podspec.mustache", "", podName + ".podspec"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
} }
@Override @Override
@ -285,11 +296,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toModelImport(String name) { public String toModelImport(String name) {
if ("".equals(modelPackage())) { return name;
return name;
} else {
return modelPackage() + "." + name;
}
} }
@Override @Override
@ -299,12 +306,12 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String apiFileFolder() { public String apiFileFolder() {
return outputFolder + File.separator + sourceFolder; return outputFolder + File.separatorChar + apiPackage();
} }
@Override @Override
public String modelFileFolder() { public String modelFileFolder() {
return outputFolder + File.separator + sourceFolder; return outputFolder + File.separatorChar + modelPackage();
} }
@Override @Override
@ -359,15 +366,15 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
return camelize(operationId, true); return camelize(operationId, true);
} }
public void setSourceFolder(String sourceFolder) {
this.sourceFolder = sourceFolder;
}
public void setClassPrefix(String classPrefix) { public void setClassPrefix(String classPrefix) {
this.classPrefix = classPrefix; this.classPrefix = classPrefix;
} }
public void setProjectName(String projectName) { public void setPodName(String podName) {
this.projectName = projectName; this.podName = podName;
}
public void setPodVersion(String podVersion) {
this.podVersion = podVersion;
} }
} }

View File

@ -17,10 +17,10 @@ import java.util.HashSet;
public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String invokerPackage = "Swagger\\Client"; protected String invokerPackage = "Swagger\\Client";
protected String groupId = "swagger"; protected String composerVendorName = "swagger";
protected String artifactId = "swagger-client"; protected String composerProjectName = "swagger-client";
protected String packagePath = "SwaggerClient-php"; protected String packagePath = "SwaggerClient-php";
protected String artifactVersion = null; protected String artifactVersion = "1.0.0";
protected String srcBasePath = "lib"; protected String srcBasePath = "lib";
public PhpClientCodegen() { public PhpClientCodegen() {
@ -38,15 +38,6 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
"__halt_compiler", "abstract", "and", "array", "as", "break", "callable", "case", "catch", "class", "clone", "const", "continue", "declare", "default", "die", "do", "echo", "else", "elseif", "empty", "enddeclare", "endfor", "endforeach", "endif", "endswitch", "endwhile", "eval", "exit", "extends", "final", "for", "foreach", "function", "global", "goto", "if", "implements", "include", "include_once", "instanceof", "insteadof", "interface", "isset", "list", "namespace", "new", "or", "print", "private", "protected", "public", "require", "require_once", "return", "static", "switch", "throw", "trait", "try", "unset", "use", "var", "while", "xor") "__halt_compiler", "abstract", "and", "array", "as", "break", "callable", "case", "catch", "class", "clone", "const", "continue", "declare", "default", "die", "do", "echo", "else", "elseif", "empty", "enddeclare", "endfor", "endforeach", "endif", "endswitch", "endwhile", "eval", "exit", "extends", "final", "for", "foreach", "function", "global", "goto", "if", "implements", "include", "include_once", "instanceof", "insteadof", "interface", "isset", "list", "namespace", "new", "or", "print", "private", "protected", "public", "require", "require_once", "return", "static", "switch", "throw", "trait", "try", "unset", "use", "var", "while", "xor")
); );
additionalProperties.put("invokerPackage", invokerPackage);
additionalProperties.put("modelPackage", modelPackage);
additionalProperties.put("apiPackage", apiPackage);
additionalProperties.put("srcBasePath", srcBasePath);
additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\"));
additionalProperties.put("groupId", groupId);
additionalProperties.put("artifactId", artifactId);
additionalProperties.put("artifactVersion", artifactVersion);
// ref: http://php.net/manual/en/language.types.intro.php // ref: http://php.net/manual/en/language.types.intro.php
languageSpecificPrimitives = new HashSet<String>( languageSpecificPrimitives = new HashSet<String>(
Arrays.asList( Arrays.asList(
@ -79,15 +70,19 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("boolean", "bool"); typeMapping.put("boolean", "bool");
typeMapping.put("date", "\\DateTime"); typeMapping.put("date", "\\DateTime");
typeMapping.put("datetime", "\\DateTime"); typeMapping.put("datetime", "\\DateTime");
typeMapping.put("file", "string"); typeMapping.put("file", "\\SplFileObject");
typeMapping.put("map", "map"); typeMapping.put("map", "map");
typeMapping.put("array", "array"); typeMapping.put("array", "array");
typeMapping.put("list", "array"); typeMapping.put("list", "array");
typeMapping.put("object", "object"); typeMapping.put("object", "object");
typeMapping.put("DateTime", "\\DateTime"); typeMapping.put("DateTime", "\\DateTime");
cliOptions.add(new CliOption("packagePath", "main package name for classes")); cliOptions.add(new CliOption("invokerPackage", "The main namespace to use for all classes."));
cliOptions.add(new CliOption("srcBasePath", "directory directory under packagePath to serve as source root")); cliOptions.add(new CliOption("packagePath", "The main package name for classes."));
cliOptions.add(new CliOption("srcBasePath", "The directory under packagePath to serve as source root."));
cliOptions.add(new CliOption("composerVendorName", "The vendor name used in the composer package name. The template uses {{composerVendorName}}/{{composerProjectName}} for the composer package name."));
cliOptions.add(new CliOption("composerProjectName", "The project name used in the composer package name. The template uses {{composerVendorName}}/{{composerProjectName}} for the composer package name."));
cliOptions.add(new CliOption("artifactVersion", "The version to use in the composer package version field."));
} }
public String getPackagePath() { public String getPackagePath() {
@ -141,23 +136,52 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
if (additionalProperties.containsKey("packagePath")) { if (additionalProperties.containsKey("packagePath")) {
this.setPackagePath((String) additionalProperties.get("packagePath")); this.setPackagePath((String) additionalProperties.get("packagePath"));
} else {
additionalProperties.put("packagePath", packagePath);
} }
if (additionalProperties.containsKey("srcBasePath")) { if (additionalProperties.containsKey("srcBasePath")) {
this.setSrcBasePath((String) additionalProperties.get("srcBasePath")); this.setSrcBasePath((String) additionalProperties.get("srcBasePath"));
} else {
additionalProperties.put("srcBasePath", srcBasePath);
} }
if (additionalProperties.containsKey("invokerPackage")) {
this.setInvokerPackage((String) additionalProperties.get("invokerPackage"));
} else {
additionalProperties.put("invokerPackage", invokerPackage);
}
if (additionalProperties.containsKey("modelPackage")) { if (additionalProperties.containsKey("modelPackage")) {
this.setModelPackage((String) additionalProperties.get("modelPackage")); this.setModelPackage((String) additionalProperties.get("modelPackage"));
} else {
additionalProperties.put("modelPackage", modelPackage);
} }
if (additionalProperties.containsKey("apiPackage")) { if (additionalProperties.containsKey("apiPackage")) {
this.setApiPackage((String) additionalProperties.get("apiPackage")); this.setApiPackage((String) additionalProperties.get("apiPackage"));
} else {
additionalProperties.put("apiPackage", apiPackage);
} }
additionalProperties.put("srcBasePath", srcBasePath); if (additionalProperties.containsKey("composerProjectName")) {
additionalProperties.put("modelPackage", modelPackage); this.setComposerProjectName((String) additionalProperties.get("composerProjectName"));
additionalProperties.put("apiPackage", apiPackage); } else {
additionalProperties.put("composerProjectName", composerProjectName);
}
if (additionalProperties.containsKey("composerVendorName")) {
this.setComposerVendorName((String) additionalProperties.get("composerVendorName"));
} else {
additionalProperties.put("composerVendorName", composerVendorName);
}
if (additionalProperties.containsKey("artifactVersion")) {
this.setArtifactVersion((String) additionalProperties.get("artifactVersion"));
} else {
additionalProperties.put("artifactVersion", artifactVersion);
}
additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\")); additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\"));
supportingFiles.add(new SupportingFile("configuration.mustache", toPackagePath(invokerPackage, srcBasePath), "Configuration.php")); supportingFiles.add(new SupportingFile("configuration.mustache", toPackagePath(invokerPackage, srcBasePath), "Configuration.php"));
@ -235,6 +259,10 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
public void setInvokerPackage(String invokerPackage) { public void setInvokerPackage(String invokerPackage) {
this.invokerPackage = invokerPackage; this.invokerPackage = invokerPackage;
} }
public void setArtifactVersion(String artifactVersion) {
this.artifactVersion = artifactVersion;
}
public void setPackagePath(String packagePath) { public void setPackagePath(String packagePath) {
this.packagePath = packagePath; this.packagePath = packagePath;
@ -243,6 +271,14 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
public void setSrcBasePath(String srcBasePath) { public void setSrcBasePath(String srcBasePath) {
this.srcBasePath = srcBasePath; this.srcBasePath = srcBasePath;
} }
private void setComposerVendorName(String composerVendorName) {
this.composerVendorName = composerVendorName;
}
public void setComposerProjectName(String composerProjectName) {
this.composerProjectName = composerProjectName;
}
@Override @Override
public String toVarName(String name) { public String toVarName(String name) {

View File

@ -33,6 +33,7 @@ public class Python3ClientCodegen extends DefaultCodegen implements CodegenConfi
languageSpecificPrimitives.add("bool"); languageSpecificPrimitives.add("bool");
languageSpecificPrimitives.add("str"); languageSpecificPrimitives.add("str");
languageSpecificPrimitives.add("datetime"); languageSpecificPrimitives.add("datetime");
languageSpecificPrimitives.add("date");
typeMapping.clear(); typeMapping.clear();
typeMapping.put("integer", "int"); typeMapping.put("integer", "int");
@ -43,7 +44,8 @@ public class Python3ClientCodegen extends DefaultCodegen implements CodegenConfi
typeMapping.put("map", "map"); typeMapping.put("map", "map");
typeMapping.put("boolean", "bool"); typeMapping.put("boolean", "bool");
typeMapping.put("string", "str"); typeMapping.put("string", "str");
typeMapping.put("date", "datetime"); typeMapping.put("date", "date");
typeMapping.put("DateTime", "datetime");
// from https://docs.python.org/release/2.5.4/ref/keywords.html // from https://docs.python.org/release/2.5.4/ref/keywords.html
reservedWords = new HashSet<String>( reservedWords = new HashSet<String>(

View File

@ -34,6 +34,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
languageSpecificPrimitives.add("bool"); languageSpecificPrimitives.add("bool");
languageSpecificPrimitives.add("str"); languageSpecificPrimitives.add("str");
languageSpecificPrimitives.add("datetime"); languageSpecificPrimitives.add("datetime");
languageSpecificPrimitives.add("date");
typeMapping.clear(); typeMapping.clear();
typeMapping.put("integer", "int"); typeMapping.put("integer", "int");
@ -44,8 +45,10 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
typeMapping.put("map", "dict"); typeMapping.put("map", "dict");
typeMapping.put("boolean", "bool"); typeMapping.put("boolean", "bool");
typeMapping.put("string", "str"); typeMapping.put("string", "str");
typeMapping.put("date", "datetime"); typeMapping.put("date", "date");
typeMapping.put("DateTime", "datetime");
typeMapping.put("object", "object"); typeMapping.put("object", "object");
typeMapping.put("file", "file");
// from https://docs.python.org/release/2.5.4/ref/keywords.html // from https://docs.python.org/release/2.5.4/ref/keywords.html
reservedWords = new HashSet<String>( reservedWords = new HashSet<String>(

View File

@ -55,12 +55,14 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("float", "Float"); typeMapping.put("float", "Float");
typeMapping.put("double", "Float"); typeMapping.put("double", "Float");
typeMapping.put("number", "Float"); typeMapping.put("number", "Float");
typeMapping.put("date", "Date");
typeMapping.put("DateTime", "DateTime"); typeMapping.put("DateTime", "DateTime");
typeMapping.put("boolean", "BOOLEAN"); typeMapping.put("boolean", "BOOLEAN");
typeMapping.put("array", "Array"); typeMapping.put("array", "Array");
typeMapping.put("List", "Array"); typeMapping.put("List", "Array");
typeMapping.put("map", "Hash"); typeMapping.put("map", "Hash");
typeMapping.put("object", "Object"); typeMapping.put("object", "Object");
typeMapping.put("file", "File");
// remove modelPackage and apiPackage added by default // remove modelPackage and apiPackage added by default
cliOptions.clear(); cliOptions.clear();
@ -106,7 +108,6 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
supportingFiles.add(new SupportingFile("swagger_client.gemspec.mustache", "", gemName + ".gemspec")); supportingFiles.add(new SupportingFile("swagger_client.gemspec.mustache", "", gemName + ".gemspec"));
supportingFiles.add(new SupportingFile("swagger_client.mustache", libFolder, gemName + ".rb")); supportingFiles.add(new SupportingFile("swagger_client.mustache", libFolder, gemName + ".rb"));
String baseFolder = libFolder + File.separator + gemName; String baseFolder = libFolder + File.separator + gemName;
supportingFiles.add(new SupportingFile("monkey.mustache", baseFolder, "monkey.rb"));
supportingFiles.add(new SupportingFile("swagger.mustache", baseFolder, "swagger.rb")); supportingFiles.add(new SupportingFile("swagger.mustache", baseFolder, "swagger.rb"));
String swaggerFolder = baseFolder + File.separator + "swagger"; String swaggerFolder = baseFolder + File.separator + "swagger";
supportingFiles.add(new SupportingFile("swagger" + File.separator + "request.mustache", swaggerFolder, "request.rb")); supportingFiles.add(new SupportingFile("swagger" + File.separator + "request.mustache", swaggerFolder, "request.rb"));

View File

@ -2,6 +2,7 @@ package io.swagger.codegen.languages;
import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenOperation; import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenResponse;
import io.swagger.codegen.CodegenType; import io.swagger.codegen.CodegenType;
import io.swagger.codegen.SupportingFile; import io.swagger.codegen.SupportingFile;
import io.swagger.models.Operation; import io.swagger.models.Operation;
@ -146,6 +147,14 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen
if (operations != null) { if (operations != null) {
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation"); List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
for (CodegenOperation operation : ops) { for (CodegenOperation operation : ops) {
List<CodegenResponse> responses = operation.responses;
if (responses != null) {
for (CodegenResponse resp : responses) {
if ("0".equals(resp.code)) {
resp.code = "200";
}
}
}
if (operation.returnType == null) { if (operation.returnType == null) {
operation.returnType = "Void"; operation.returnType = "Void";
} else if (operation.returnType.startsWith("List")) { } else if (operation.returnType.startsWith("List")) {

View File

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

View File

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

View File

@ -18,7 +18,7 @@ public class TypeScriptAngularClientCodegen extends TypeScriptNodeClientCodegen
apiTemplateFiles.put("api.mustache", ".ts"); apiTemplateFiles.put("api.mustache", ".ts");
templateDir = "TypeScript-Angular"; templateDir = "TypeScript-Angular";
apiPackage = "api"; apiPackage = "api";
modelPackage = "api"; modelPackage = "model";
supportingFiles.add(new SupportingFile("api.d.mustache", apiPackage + File.separator, "api.d.ts")); supportingFiles.add(new SupportingFile("api.d.mustache", apiPackage + File.separator, "api.d.ts"));
} }

View File

@ -77,6 +77,8 @@ public class TypeScriptNodeClientCodegen extends DefaultCodegen implements Codeg
typeMapping.put("double", "number"); typeMapping.put("double", "number");
typeMapping.put("object", "any"); typeMapping.put("object", "any");
typeMapping.put("integer", "number"); typeMapping.put("integer", "number");
typeMapping.put("Map", "any");
typeMapping.put("DateTime", "Date");
} }

View File

@ -22,6 +22,7 @@ import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.TimeZone; import java.util.TimeZone;
@ -238,6 +239,62 @@ public class ApiClient {
} }
} }
/*
Format to {@code Pair} objects.
*/
public List<Pair> parameterToPairs(String collectionFormat, String name, Object value){
List<Pair> params = new ArrayList<Pair>();
// preconditions
if (name == null || name.isEmpty() || value == null) return params;
Collection valueCollection = null;
if (value instanceof Collection) {
valueCollection = (Collection) value;
} else {
params.add(new Pair(name, parameterToString(value)));
return params;
}
if (valueCollection.isEmpty()){
return params;
}
// get the collection format
collectionFormat = (collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat); // default: csv
// create the params based on the collection format
if (collectionFormat.equals("multi")) {
for (Object item : valueCollection) {
params.add(new Pair(name, parameterToString(item)));
}
return params;
}
String delimiter = ",";
if (collectionFormat.equals("csv")) {
delimiter = ",";
} else if (collectionFormat.equals("ssv")) {
delimiter = " ";
} else if (collectionFormat.equals("tsv")) {
delimiter = "\t";
} else if (collectionFormat.equals("pipes")) {
delimiter = "|";
}
StringBuilder sb = new StringBuilder() ;
for (Object item : valueCollection) {
sb.append(delimiter);
sb.append(parameterToString(item));
}
params.add(new Pair(name, sb.substring(1)));
return params;
}
/** /**
* Select the Accept header's value from the given accepts array: * Select the Accept header's value from the given accepts array:
* if JSON exists in the given array, use it; * if JSON exists in the given array, use it;
@ -341,23 +398,25 @@ public class ApiClient {
* @param authNames The authentications to apply * @param authNames The authentications to apply
* @return The response body in type of string * @return The response body in type of string
*/ */
public String invokeAPI(String path, String method, Map<String, String> queryParams, Object body, Map<String, String> headerParams, Map<String, String> formParams, String accept, String contentType, String[] authNames) throws ApiException { public String invokeAPI(String path, String method, List<Pair> queryParams, Object body, Map<String, String> headerParams, Map<String, String> formParams, String accept, String contentType, String[] authNames) throws ApiException {
updateParamsForAuth(authNames, queryParams, headerParams); updateParamsForAuth(authNames, queryParams, headerParams);
Client client = getClient(); Client client = getClient();
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();
for(String key : queryParams.keySet()) { b.append("?");
String value = queryParams.get(key); if (queryParams != null){
if (value != null){ for (Pair queryParam : queryParams){
if(b.toString().length() == 0) if (!queryParam.getName().isEmpty()) {
b.append("?"); b.append(escapeString(queryParam.getName()));
else b.append("=");
b.append(escapeString(queryParam.getValue()));
b.append("&"); b.append("&");
b.append(escapeString(key)).append("=").append(escapeString(value)); }
} }
} }
String querystring = b.toString();
String querystring = b.substring(0, b.length() - 1);
Builder builder; Builder builder;
if (accept == null) if (accept == null)
@ -457,7 +516,7 @@ public class ApiClient {
* *
* @param authNames The authentications to apply * @param authNames The authentications to apply
*/ */
private void updateParamsForAuth(String[] authNames, Map<String, String> queryParams, Map<String, String> headerParams) { private void updateParamsForAuth(String[] authNames, List<Pair> queryParams, Map<String, String> headerParams) {
for (String authName : authNames) { for (String authName : authNames) {
Authentication auth = authentications.get(authName); Authentication auth = authentications.get(authName);
if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); if (auth == null) throw new RuntimeException("Authentication undefined: " + authName);

View File

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

View File

@ -3,6 +3,7 @@ package {{package}};
import {{invokerPackage}}.ApiException; import {{invokerPackage}}.ApiException;
import {{invokerPackage}}.ApiClient; import {{invokerPackage}}.ApiClient;
import {{invokerPackage}}.Configuration; import {{invokerPackage}}.Configuration;
import {{invokerPackage}}.Pair;
import {{modelPackage}}.*; import {{modelPackage}}.*;
@ -58,19 +59,19 @@ public class {{classname}} {
// create path and map variables // create path and map variables
String path = "{{path}}".replaceAll("\\{format\\}","json"){{#pathParams}} String path = "{{path}}".replaceAll("\\{format\\}","json"){{#pathParams}}
.replaceAll("\\{" + "{{paramName}}" + "\\}", apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; .replaceAll("\\{" + "{{baseName}}" + "\\}", apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}};
// query params // query params
Map<String, String> queryParams = new HashMap<String, String>(); List<Pair> queryParams = new ArrayList<Pair>();
Map<String, String> headerParams = new HashMap<String, String>(); Map<String, String> headerParams = new HashMap<String, String>();
Map<String, String> formParams = new HashMap<String, String>(); Map<String, String> formParams = new HashMap<String, String>();
{{#queryParams}}if ({{paramName}} != null) {{#queryParams}}
queryParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); queryParams.addAll(apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}}));
{{/queryParams}} {{/queryParams}}
{{#headerParams}}if ({{paramName}} != null) {{#headerParams}}if ({{paramName}} != null)
headerParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); headerParams.put("{{baseName}}", apiClient.parameterToString({{paramName}}));
{{/headerParams}} {{/headerParams}}
final String[] accepts = { final String[] accepts = {

View File

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

View File

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

View File

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

View File

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

View File

@ -8,4 +8,5 @@ This server was generated by the [swagger-codegen](https://github.com/swagger-ap
The underlying library integrating swagger to Spring-MVC is [springfox](https://github.com/springfox/springfox) The underlying library integrating swagger to Spring-MVC is [springfox](https://github.com/springfox/springfox)
You can view the server in swagger-ui by pointing to http://localhost:8002{{^contextPath}}/{{/contextPath}}{{#contextPath}}{{contextPath}}{{/contextPath}}/sdoc.jsp You can view the server in swagger-ui by pointing to
http://localhost:8002{{^contextPath}}/{{/contextPath}}{{#contextPath}}{{contextPath}}{{/contextPath}}/swagger-ui.html

View File

@ -33,8 +33,7 @@
<webAppConfig> <webAppConfig>
<contextPath>{{^contextPath}}/{{/contextPath}}{{#contextPath}}{{contextPath}}{{/contextPath}}</contextPath> <contextPath>{{^contextPath}}/{{/contextPath}}{{#contextPath}}{{contextPath}}{{/contextPath}}</contextPath>
</webAppConfig> </webAppConfig>
<webAppSourceDirectory>target/${project.artifactId}-${project-version}</webAppSourceDirectory> <webAppSourceDirectory>target/${project.artifactId}-${project.version}</webAppSourceDirectory>
<webDefaultXml>${project.basedir}/conf/jetty/webdefault.xml</webDefaultXml>
<stopPort>8079</stopPort> <stopPort>8079</stopPort>
<stopKey>stopit</stopKey> <stopKey>stopit</stopKey>
<httpConnector> <httpConnector>
@ -63,49 +62,6 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>com.googlecode.maven-download-plugin</groupId>
<artifactId>download-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>swagger-ui</id>
<goals>
<goal>wget</goal>
</goals>
<configuration>
<url>https://github.com/swagger-api/swagger-ui/archive/v${swagger-ui-version}.tar.gz</url>
<unpack>true</unpack>
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>target/${project.artifactId}-${project.version}</outputDirectory>
<resources>
<resource>
<directory>${project.build.directory}/swagger-ui-${swagger-ui-version}/dist</directory>
<filtering>true</filtering>
<excludes>
<exclude>index.html</exclude>
</excludes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins> </plugins>
</build> </build>
<dependencies> <dependencies>
@ -163,21 +119,6 @@
</dependency> </dependency>
<!--SpringFox dependencies--> <!--SpringFox dependencies-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-core</artifactId>
<version>${springfox-version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-spi</artifactId>
<version>${springfox-version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-spring-web</artifactId>
<version>${springfox-version}</version>
</dependency>
<dependency> <dependency>
<groupId>io.springfox</groupId> <groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId> <artifactId>springfox-swagger2</artifactId>
@ -189,12 +130,6 @@
<version>${springfox-version}</version> <version>${springfox-version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.scalatest</groupId>
<artifactId>scalatest_2.9.1</artifactId>
<version>${scala-test-version}</version>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
@ -217,13 +152,12 @@
<properties> <properties>
<swagger-core-version>1.5.0</swagger-core-version> <swagger-core-version>1.5.0</swagger-core-version>
<jetty-version>9.2.9.v20150224</jetty-version> <jetty-version>9.2.9.v20150224</jetty-version>
<swagger-ui-version>2.1.0-M2</swagger-ui-version>
<jersey-version>1.13</jersey-version> <jersey-version>1.13</jersey-version>
<slf4j-version>1.6.3</slf4j-version> <slf4j-version>1.6.3</slf4j-version>
<scala-test-version>1.6.1</scala-test-version> <scala-test-version>1.6.1</scala-test-version>
<junit-version>4.8.1</junit-version> <junit-version>4.8.1</junit-version>
<servlet-api-version>2.5</servlet-api-version> <servlet-api-version>2.5</servlet-api-version>
<springfox-version>2.0.0-SNAPSHOT</springfox-version> <springfox-version>2.0.4-SNAPSHOT</springfox-version>
<spring-version>4.0.9.RELEASE</spring-version> <spring-version>4.0.9.RELEASE</spring-version>
</properties> </properties>
</project> </project>

View File

@ -21,7 +21,7 @@ io.swagger.codegen.languages.StaticDocCodegen
io.swagger.codegen.languages.StaticHtmlGenerator io.swagger.codegen.languages.StaticHtmlGenerator
io.swagger.codegen.languages.SwaggerGenerator io.swagger.codegen.languages.SwaggerGenerator
io.swagger.codegen.languages.SwaggerYamlGenerator io.swagger.codegen.languages.SwaggerYamlGenerator
io.swagger.codegen.languages.SwiftGenerator io.swagger.codegen.languages.SwiftCodegen
io.swagger.codegen.languages.TizenClientCodegen io.swagger.codegen.languages.TizenClientCodegen
io.swagger.codegen.languages.TypeScriptAngularClientCodegen io.swagger.codegen.languages.TypeScriptAngularClientCodegen
io.swagger.codegen.languages.TypeScriptNodeClientCodegen io.swagger.codegen.languages.TypeScriptNodeClientCodegen

View File

@ -12,7 +12,7 @@ module {{package}} {
*/ */
{{/description}} {{/description}}
export class {{classname}} { export class {{classname}} {
private basePath = '{{basePath}}'; private basePath = '{{contextPath}}';
static $inject: string[] = ['$http']; static $inject: string[] = ['$http'];
@ -22,7 +22,7 @@ module {{package}} {
} }
} }
{{#operation}} {{#operation}}
public {{nickname}} ({{#allParams}}{{paramName}}: {{{dataType}}}, {{/allParams}} extraHttpRequestParams?: any ) : ng.IHttpPromise<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}{}{{/returnType}}> { public {{nickname}} ({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}extraHttpRequestParams?: any ) : ng.IHttpPromise<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}{}{{/returnType}}> {
var path = this.basePath + '{{path}}'; var path = this.basePath + '{{path}}';
{{#pathParams}} {{#pathParams}}
path = path.replace('{' + '{{paramName}}' + '}', String({{paramName}})); path = path.replace('{' + '{{paramName}}' + '}', String({{paramName}}));
@ -50,7 +50,7 @@ module {{package}} {
}; };
if (extraHttpRequestParams) { if (extraHttpRequestParams) {
for (var k in extraHttpRequestParams){ for (var k in extraHttpRequestParams) {
if (extraHttpRequestParams.hasOwnProperty(k)) { if (extraHttpRequestParams.hasOwnProperty(k)) {
httpRequestParams[k] = extraHttpRequestParams[k]; httpRequestParams[k] = extraHttpRequestParams[k];
} }
@ -61,8 +61,5 @@ module {{package}} {
} }
{{/operation}} {{/operation}}
} }
angular.module('{{package}}_{{classname}}', ['$http'])
.service('{{classname}}', {{classname}});
} }
{{/operations}} {{/operations}}

View File

@ -7,7 +7,7 @@
*/ */
{{/description}} {{/description}}
export class {{classname}} { export class {{classname}} {
private basePath = '{{basePath}}'; private basePath = '{{contextPath}}';
constructor(private url: string, private username: string, private password: string, basePath?: string) { constructor(private url: string, private username: string, private password: string, basePath?: string) {
if (basePath) { if (basePath) {
@ -16,7 +16,7 @@ export class {{classname}} {
} }
{{#operation}} {{#operation}}
public {{nickname}} ({{#allParams}}{{paramName}}: {{{dataType}}}{{#hasMore}}, {{/hasMore}}{{/allParams}} ) : Promise<{ response: http.ClientResponse; {{#returnType}}body: {{{returnType}}}; {{/returnType}} }> { public {{nickname}} ({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) : Promise<{ response: http.ClientResponse; {{#returnType}}body: {{{returnType}}}; {{/returnType}} }> {
var path = this.url + this.basePath + '{{path}}'; var path = this.url + this.basePath + '{{path}}';
{{#pathParams}} {{#pathParams}}

View File

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

View File

@ -2,6 +2,7 @@ package {{package}};
import {{invokerPackage}}.ApiException; import {{invokerPackage}}.ApiException;
import {{invokerPackage}}.ApiInvoker; import {{invokerPackage}}.ApiInvoker;
import {{invokerPackage}}.Pair;
import {{modelPackage}}.*; import {{modelPackage}}.*;
@ -55,20 +56,21 @@ public class {{classname}} {
{{/required}}{{/allParams}} {{/required}}{{/allParams}}
// create path and map variables // create path and map variables
String path = "{{path}}".replaceAll("\\{format\\}","json"){{#pathParams}}.replaceAll("\\{" + "{{paramName}}" + "\\}", apiInvoker.escapeString({{{paramName}}}.toString())){{/pathParams}}; String path = "{{path}}".replaceAll("\\{format\\}","json"){{#pathParams}}.replaceAll("\\{" + "{{baseName}}" + "\\}", apiInvoker.escapeString({{{paramName}}}.toString())){{/pathParams}};
// query params // query params
Map<String, String> queryParams = new HashMap<String, String>(); List<Pair> queryParams = new ArrayList<Pair>();
// header params // header params
Map<String, String> headerParams = new HashMap<String, String>(); Map<String, String> headerParams = new HashMap<String, String>();
// form params // form params
Map<String, String> formParams = new HashMap<String, String>(); Map<String, String> formParams = new HashMap<String, String>();
{{#queryParams}}if ({{paramName}} != null) {{#queryParams}}
queryParams.put("{{baseName}}", ApiInvoker.parameterToString({{paramName}})); queryParams.addAll(ApiInvoker.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}}));
{{/queryParams}} {{/queryParams}}
{{#headerParams}}headerParams.put("{{baseName}}", ApiInvoker.parameterToString({{paramName}})); {{#headerParams}}
headerParams.put("{{baseName}}", ApiInvoker.parameterToString({{paramName}}));
{{/headerParams}} {{/headerParams}}
String[] contentTypes = { String[] contentTypes = {

View File

@ -23,6 +23,7 @@ import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.ArrayList;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
@ -132,6 +133,62 @@ public class ApiInvoker {
} }
} }
/*
Format to {@code Pair} objects.
*/
public static List<Pair> parameterToPairs(String collectionFormat, String name, Object value){
List<Pair> params = new ArrayList<Pair>();
// preconditions
if (name == null || name.isEmpty() || value == null) return params;
Collection valueCollection = null;
if (value instanceof Collection) {
valueCollection = (Collection) value;
} else {
params.add(new Pair(name, parameterToString(value)));
return params;
}
if (valueCollection.isEmpty()){
return params;
}
// get the collection format
collectionFormat = (collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat); // default: csv
// create the params based on the collection format
if (collectionFormat.equals("multi")) {
for (Object item : valueCollection) {
params.add(new Pair(name, parameterToString(item)));
}
return params;
}
String delimiter = ",";
if (collectionFormat.equals("csv")) {
delimiter = ",";
} else if (collectionFormat.equals("ssv")) {
delimiter = " ";
} else if (collectionFormat.equals("tsv")) {
delimiter = "\t";
} else if (collectionFormat.equals("pipes")) {
delimiter = "|";
}
StringBuilder sb = new StringBuilder() ;
for (Object item : valueCollection) {
sb.append(delimiter);
sb.append(parameterToString(item));
}
params.add(new Pair(name, sb.substring(1)));
return params;
}
public ApiInvoker() { public ApiInvoker() {
initConnectionManager(); initConnectionManager();
} }
@ -184,21 +241,24 @@ 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 { public String invokeAPI(String host, String path, String method, List<Pair> queryParams, Object body, Map<String, String> headerParams, Map<String, String> formParams, String contentType) throws ApiException {
HttpClient client = getClient(host); HttpClient client = getClient(host);
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();
for(String key : queryParams.keySet()) { b.append("?");
String value = queryParams.get(key); if (queryParams != null){
if (value != null){ for (Pair queryParam : queryParams){
if(b.toString().length() == 0) if (!queryParam.getName().isEmpty()) {
b.append("?"); b.append(escapeString(queryParam.getName()));
else b.append("=");
b.append(escapeString(queryParam.getValue()));
b.append("&"); b.append("&");
b.append(escapeString(key)).append("=").append(escapeString(value)); }
} }
} }
String url = host + path + b.toString();
String querystring = b.substring(0, b.length() - 1);
String url = host + path + querystring;
HashMap<String, String> headers = new HashMap<String, String>(); HashMap<String, String> headers = new HashMap<String, String>();

View File

@ -11,10 +11,9 @@ import collection.mutable
class {{classname}}(client: TransportClient, config: SwaggerConfig) extends ApiClient(client, config) { class {{classname}}(client: TransportClient, config: SwaggerConfig) extends ApiClient(client, config) {
{{#operation}} {{#operation}}
def {{nickname}}({{#allParams}}{{#optional}}{{paramName}}: Option[{{dataType}}] = {{#defaultValue}}Some({{defaultValue}}){{/defaultValue}}{{^defaultValue}}None{{/defaultValue}}{{#hasMore}}, def {{nickname}}({{#allParams}}{{^required}}{{paramName}}: Option[{{dataType}}] = {{#defaultValue}}Some({{defaultValue}}){{/defaultValue}}{{^defaultValue}}None{{/defaultValue}}{{#hasMore}},{{/hasMore}}
{{/hasMore}} {{/required}}{{#required}}{{paramName}}: {{dataType}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{#hasMore}},
{{/optional}}{{^optional}}{{paramName}}: {{dataType}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{#hasMore}}, {{/hasMore}}{{/required}}{{/allParams}})(implicit reader: ClientResponseReader[{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Unit{{/returnType}}]{{#bodyParams}}, writer: RequestWriter[{{dataType}}]{{/bodyParams}}){{#returnType}}: Future[{{returnType}}]{{/returnType}}{{^returnType}}: Future[Unit]{{/returnType}} = {
{{/hasMore}}{{/optional}}{{/allParams}})(implicit reader: ClientResponseReader[{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Unit{{/returnType}}]{{#bodyParams}}, writer: RequestWriter[{{dataType}}]{{/bodyParams}}){{#returnType}}: Future[{{returnType}}]{{/returnType}}{{^returnType}}: Future[Unit]{{/returnType}} = {
// create path and map variables // create path and map variables
val path = (addFmt("{{path}}"){{#pathParams}} val path = (addFmt("{{path}}"){{#pathParams}}
replaceAll ("\\{" + "{{baseName}}" + "\\}",{{paramName}}.toString){{/pathParams}}) replaceAll ("\\{" + "{{baseName}}" + "\\}",{{paramName}}.toString){{/pathParams}})
@ -27,8 +26,8 @@ class {{classname}}(client: TransportClient, config: SwaggerConfig) extends ApiC
val paramCount = (Set[Any]({{/requiredParamCount}}{{#requiredParams}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}{{#requiredParamCount}}) - null).size val paramCount = (Set[Any]({{/requiredParamCount}}{{#requiredParams}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}{{#requiredParamCount}}) - null).size
if (paramCount != {{requiredParamCount}}) sys.error("missing required params"){{/requiredParamCount}} if (paramCount != {{requiredParamCount}}) sys.error("missing required params"){{/requiredParamCount}}
{{#queryParams}}{{#optional}}if({{paramName}} != null) {{paramName}}.foreach { v => queryParams += "{{baseName}}" -> v.toString }{{/optional}}{{^optional}} {{#queryParams}}{{^required}}if({{paramName}} != null) {{paramName}}.foreach { v => queryParams += "{{baseName}}" -> v.toString }{{/required}}{{#required}}
if({{paramName}} != null) queryParams += "{{baseName}}" -> {{paramName}}.toString{{/optional}}{{/queryParams}} if({{paramName}} != null) queryParams += "{{baseName}}" -> {{paramName}}.toString{{/required}}{{/queryParams}}
{{#headerParams}}headerParams += "{{baseName}}" -> {{paramName}}.toString{{/headerParams}} {{#headerParams}}headerParams += "{{baseName}}" -> {{paramName}}.toString{{/headerParams}}

View File

@ -50,7 +50,6 @@ namespace {{packageName}}.Client
get { return _defaultHeaderMap; } get { return _defaultHeaderMap; }
} }
<<<<<<< HEAD
// Creates and sets up a RestRequest prior to a call. // Creates and sets up a RestRequest prior to a call.
private RestRequest PrepareRequest( private RestRequest PrepareRequest(
String path, RestSharp.Method method, Dictionary<String, String> queryParams, String postBody, String path, RestSharp.Method method, Dictionary<String, String> queryParams, String postBody,
@ -58,9 +57,9 @@ namespace {{packageName}}.Client
Dictionary<String, FileParameter> fileParams, Dictionary<String, String> pathParams, String[] authSettings) Dictionary<String, FileParameter> fileParams, Dictionary<String, String> pathParams, String[] authSettings)
{ {
var request = new RestRequest(path, method); var request = new RestRequest(path, method);
UpdateParamsForAuth(queryParams, headerParams, authSettings); UpdateParamsForAuth(queryParams, headerParams, authSettings);
// add default header, if any // add default header, if any
foreach(var defaultHeader in _defaultHeaderMap) foreach(var defaultHeader in _defaultHeaderMap)
request.AddHeader(defaultHeader.Key, defaultHeader.Value); request.AddHeader(defaultHeader.Key, defaultHeader.Value);
@ -72,15 +71,15 @@ namespace {{packageName}}.Client
// add header parameter, if any // add header parameter, if any
foreach(var param in headerParams) foreach(var param in headerParams)
request.AddHeader(param.Key, param.Value); request.AddHeader(param.Key, param.Value);
// add query parameter, if any // add query parameter, if any
foreach(var param in queryParams) foreach(var param in queryParams)
request.AddQueryParameter(param.Key, param.Value); request.AddQueryParameter(param.Key, param.Value);
// add form parameter, if any // add form parameter, if any
foreach(var param in formParams) foreach(var param in formParams)
request.AddParameter(param.Key, param.Value); request.AddParameter(param.Key, param.Value);
// add file parameter, if any // add file parameter, if any
foreach(var param in fileParams) foreach(var param in fileParams)
request.AddFile(param.Value.Name, param.Value.Writer, param.Value.FileName, param.Value.ContentType); request.AddFile(param.Value.Name, param.Value.Writer, param.Value.FileName, param.Value.ContentType);
@ -208,173 +207,6 @@ namespace {{packageName}}.Client
? Path.GetTempPath() ? Path.GetTempPath()
: Configuration.TempFolderPath; : Configuration.TempFolderPath;
=======
/// <summary>
/// Makes the HTTP request (Sync).
/// </summary>
/// <param name="path">URL path.</param>
/// <param name="method">HTTP method.</param>
/// <param name="queryParams">Query parameters.</param>
/// <param name="postBody">HTTP body (POST request).</param>
/// <param name="headerParams">Header parameters.</param>
/// <param name="formParams">Form parameters.</param>
/// <param name="fileParams">File parameters.</param>
/// <param name="authSettings">Authentication settings.</param>
/// <returns>Object</returns>
public Object CallApi(String path, RestSharp.Method method, Dictionary<String, String> queryParams, String postBody,
Dictionary<String, String> headerParams, Dictionary<String, String> formParams,
Dictionary<String, FileParameter> fileParams, String[] authSettings)
{
var request = new RestRequest(path, method);
UpdateParamsForAuth(queryParams, headerParams, authSettings);
// add default header, if any
foreach(var defaultHeader in _defaultHeaderMap)
request.AddHeader(defaultHeader.Key, defaultHeader.Value);
// add header parameter, if any
foreach(var param in headerParams)
request.AddHeader(param.Key, param.Value);
// add query parameter, if any
foreach(var param in queryParams)
request.AddQueryParameter(param.Key, param.Value);
// add form parameter, if any
foreach(var param in formParams)
request.AddParameter(param.Key, param.Value);
// add file parameter, if any
foreach(var param in fileParams)
request.AddFile(param.Value.Name, param.Value.Writer, param.Value.FileName, param.Value.ContentType);
if (postBody != null) // http body (model) parameter
request.AddParameter("application/json", postBody, ParameterType.RequestBody);
return (Object)RestClient.Execute(request);
}
/// <summary>
/// Makes the asynchronous HTTP request.
/// </summary>
/// <param name="path">URL path.</param>
/// <param name="method">HTTP method.</param>
/// <param name="queryParams">Query parameters.</param>
/// <param name="postBody">HTTP body (POST request).</param>
/// <param name="headerParams">Header parameters.</param>
/// <param name="formParams">Form parameters.</param>
/// <param name="fileParams">File parameters.</param>
/// <param name="authSettings">Authentication settings.</param>
/// <returns>The Task instance.</returns>
public async System.Threading.Tasks.Task<Object> CallApiAsync(String path, RestSharp.Method method, Dictionary<String, String> queryParams, String postBody,
Dictionary<String, String> headerParams, Dictionary<String, String> formParams, Dictionary<String, FileParameter> fileParams, String[] authSettings)
{
var request = new RestRequest(path, method);
UpdateParamsForAuth(queryParams, headerParams, authSettings);
// add default header, if any
foreach(var defaultHeader in _defaultHeaderMap)
request.AddHeader(defaultHeader.Key, defaultHeader.Value);
// add header parameter, if any
foreach(var param in headerParams)
request.AddHeader(param.Key, param.Value);
// add query parameter, if any
foreach(var param in queryParams)
request.AddQueryParameter(param.Key, param.Value);
// add form parameter, if any
foreach(var param in formParams)
request.AddParameter(param.Key, param.Value);
// add file parameter, if any
foreach(var param in fileParams)
request.AddFile(param.Value.Name, param.Value.Writer, param.Value.FileName, param.Value.ContentType);
if (postBody != null) // http body (model) parameter
request.AddParameter("application/json", postBody, ParameterType.RequestBody);
return (Object) await RestClient.ExecuteTaskAsync(request);
}
/// <summary>
/// Add default header.
/// </summary>
/// <param name="key">Header field name.</param>
/// <param name="value">Header field value.</param>
/// <returns></returns>
public void AddDefaultHeader(string key, string value)
{
_defaultHeaderMap.Add(key, value);
}
/// <summary>
/// Escape string (url-encoded).
/// </summary>
/// <param name="str">String to be escaped.</param>
/// <returns>Escaped string.</returns>
public string EscapeString(string str)
{
return HttpUtility.UrlEncode(str);
}
/// <summary>
/// Create FileParameter based on Stream.
/// </summary>
/// <param name="name">Parameter name.</param>
/// <param name="stream">Input stream.</param>
/// <returns>FileParameter.</returns>
public FileParameter ParameterToFile(string name, Stream stream)
{
if (stream is FileStream)
return FileParameter.Create(name, stream.ReadAsBytes(), Path.GetFileName(((FileStream)stream).Name));
else
return FileParameter.Create(name, stream.ReadAsBytes(), "no_file_name_provided");
}
/// <summary>
/// If parameter is DateTime, output in ISO8601 format.
/// If parameter is a list of string, join the list with ",".
/// Otherwise just return the string.
/// </summary>
/// <param name="obj">The parameter (header, path, query, form).</param>
/// <returns>Formatted string.</returns>
public string ParameterToString(object obj)
{
if (obj is DateTime)
return ((DateTime)obj).ToString ("u");
else if (obj is List<string>)
return String.Join(",", obj as List<string>);
else
return Convert.ToString (obj);
}
/// <summary>
/// Deserialize the JSON string into a proper object.
/// </summary>
/// <param name="content">HTTP body (e.g. string, JSON).</param>
/// <param name="type">Object type.</param>
/// <returns>Object representation of the JSON string.</returns>
public object Deserialize(string content, Type type, IList<Parameter> headers=null)
{
if (type == typeof(Object)) // return an object
{
return content;
}
if (type == typeof(Stream))
{
var filePath = String.IsNullOrEmpty(Configuration.TempFolderPath)
? Path.GetTempPath()
: Configuration.TempFolderPath;
>>>>>>> e879268043b53fe30ea0238807b9519687c1e5f2
var fileName = filePath + Guid.NewGuid(); var fileName = filePath + Guid.NewGuid();
if (headers != null) if (headers != null)
{ {

View File

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

View File

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

View File

@ -0,0 +1,15 @@
## Frameworks supported
- .NET 3.5 or later
- Windows Phone 7.1 (Mango)
## Dependencies
- [RestSharp] (https://www.nuget.org/packages/RestSharp)
- [Json.NET] (https://www.nuget.org/packages/Newtonsoft.Json/)
NOTE: The DLLs included in the package may not be the latest version. We recommned using [NuGet] (https://docs.nuget.org/consume/installing-nuget) to obtain the latest version of the packages:
```
Install-Package RestSharp
Install-Package Newtonsoft.Json
```

View File

@ -95,27 +95,17 @@ namespace {{packageName}}.Api
{{/required}}{{/allParams}} {{/required}}{{/allParams}}
var path = "{{path}}"; var path = "{{path}}";
<<<<<<< HEAD
var pathParams = new Dictionary<String, String>(); var pathParams = new Dictionary<String, String>();
=======
path = path.Replace("{format}", "json");
{{#pathParams}}path = path.Replace("{" + "{{baseName}}" + "}", ApiClient.ParameterToString({{{paramName}}}));
{{/pathParams}}
>>>>>>> e879268043b53fe30ea0238807b9519687c1e5f2
var queryParams = new Dictionary<String, String>(); var queryParams = new Dictionary<String, String>();
var headerParams = new Dictionary<String, String>(); var headerParams = new Dictionary<String, String>();
var formParams = new Dictionary<String, String>(); var formParams = new Dictionary<String, String>();
var fileParams = new Dictionary<String, FileParameter>(); var fileParams = new Dictionary<String, FileParameter>();
String postBody = null; String postBody = null;
<<<<<<< HEAD
pathParams.Add("format", "json"); pathParams.Add("format", "json");
{{#pathParams}} if ({{paramName}} != null) pathParams.Add("{{baseName}}", apiClient.ParameterToString({{paramName}})); // path parameter {{#pathParams}} if ({{paramName}} != null) pathParams.Add("{{baseName}}", apiClient.ParameterToString({{paramName}})); // path parameter
{{/pathParams}} {{/pathParams}}
=======
>>>>>>> e879268043b53fe30ea0238807b9519687c1e5f2
{{#queryParams}} if ({{paramName}} != null) queryParams.Add("{{baseName}}", ApiClient.ParameterToString({{paramName}})); // query parameter {{#queryParams}} if ({{paramName}} != null) queryParams.Add("{{baseName}}", ApiClient.ParameterToString({{paramName}})); // query parameter
{{/queryParams}} {{/queryParams}}
@ -130,11 +120,7 @@ namespace {{packageName}}.Api
String[] authSettings = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; String[] authSettings = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} };
// make the HTTP request // make the HTTP request
<<<<<<< HEAD
IRestResponse response = (IRestResponse) ApiClient.CallApi(path, Method.{{httpMethod}}, queryParams, postBody, headerParams, formParams, fileParams, pathParams, authSettings); IRestResponse response = (IRestResponse) ApiClient.CallApi(path, Method.{{httpMethod}}, queryParams, postBody, headerParams, formParams, fileParams, pathParams, authSettings);
=======
IRestResponse response = (IRestResponse) ApiClient.CallApi(path, Method.{{httpMethod}}, queryParams, postBody, headerParams, formParams, fileParams, authSettings);
>>>>>>> e879268043b53fe30ea0238807b9519687c1e5f2
if (((int)response.StatusCode) >= 400) if (((int)response.StatusCode) >= 400)
throw new ApiException ((int)response.StatusCode, "Error calling {{nickname}}: " + response.Content, response.Content); throw new ApiException ((int)response.StatusCode, "Error calling {{nickname}}: " + response.Content, response.Content);
@ -156,30 +142,18 @@ namespace {{packageName}}.Api
{{/required}}{{/allParams}} {{/required}}{{/allParams}}
var path = "{{path}}"; var path = "{{path}}";
<<<<<<< HEAD
var pathParams = new Dictionary<String, String>(); var pathParams = new Dictionary<String, String>();
=======
path = path.Replace("{format}", "json");
{{#pathParams}}path = path.Replace("{" + "{{baseName}}" + "}", ApiClient.ParameterToString({{{paramName}}}));
{{/pathParams}}
>>>>>>> e879268043b53fe30ea0238807b9519687c1e5f2
var queryParams = new Dictionary<String, String>(); var queryParams = new Dictionary<String, String>();
var headerParams = new Dictionary<String, String>(); var headerParams = new Dictionary<String, String>();
var formParams = new Dictionary<String, String>(); var formParams = new Dictionary<String, String>();
var fileParams = new Dictionary<String, FileParameter>(); var fileParams = new Dictionary<String, FileParameter>();
String postBody = null; String postBody = null;
<<<<<<< HEAD
pathParams.Add("format", "json"); pathParams.Add("format", "json");
{{#pathParams}} if ({{paramName}} != null) pathParams.Add("{{baseName}}", apiClient.ParameterToString({{paramName}})); // path parameter {{#pathParams}} if ({{paramName}} != null) pathParams.Add("{{baseName}}", apiClient.ParameterToString({{paramName}})); // path parameter
{{/pathParams}} {{/pathParams}}
=======
>>>>>>> e879268043b53fe30ea0238807b9519687c1e5f2
{{#queryParams}} if ({{paramName}} != null) queryParams.Add("{{baseName}}", ApiClient.ParameterToString({{paramName}})); // query parameter {{#queryParams}} if ({{paramName}} != null) queryParams.Add("{{baseName}}", ApiClient.ParameterToString({{paramName}})); // query parameter
{{/queryParams}} {{/queryParams}}
{{#headerParams}} if ({{paramName}} != null) headerParams.Add("{{baseName}}", ApiClient.ParameterToString({{paramName}})); // header parameter {{#headerParams}} if ({{paramName}} != null) headerParams.Add("{{baseName}}", ApiClient.ParameterToString({{paramName}})); // header parameter
@ -193,11 +167,7 @@ namespace {{packageName}}.Api
String[] authSettings = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; String[] authSettings = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} };
// make the HTTP request // make the HTTP request
<<<<<<< HEAD
IRestResponse response = (IRestResponse) await ApiClient.CallApiAsync(path, Method.{{httpMethod}}, queryParams, postBody, headerParams, formParams, fileParams, pathParams, authSettings); IRestResponse response = (IRestResponse) await ApiClient.CallApiAsync(path, Method.{{httpMethod}}, queryParams, postBody, headerParams, formParams, fileParams, pathParams, authSettings);
=======
IRestResponse response = (IRestResponse) await ApiClient.CallApiAsync(path, Method.{{httpMethod}}, queryParams, postBody, headerParams, formParams, fileParams, authSettings);
>>>>>>> e879268043b53fe30ea0238807b9519687c1e5f2
if (((int)response.StatusCode) >= 400) if (((int)response.StatusCode) >= 400)
throw new ApiException ((int)response.StatusCode, "Error calling {{nickname}}: " + response.Content, response.Content); throw new ApiException ((int)response.StatusCode, "Error calling {{nickname}}: " + response.Content, response.Content);

View File

@ -15,7 +15,10 @@ namespace {{packageName}}.Model {
[DataContract] [DataContract]
public class {{classname}}{{#parent}} : {{{parent}}}{{/parent}} { public class {{classname}}{{#parent}} : {{{parent}}}{{/parent}} {
{{#vars}} {{#vars}}
{{#description}}/* {{{description}}} */{{/description}} /// <summary>
/// {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{{description}}}{{/description}}
/// </summary>{{#description}}
/// <value>{{{description}}}</value>{{/description}}
[DataMember(Name="{{baseName}}", EmitDefaultValue=false)] [DataMember(Name="{{baseName}}", EmitDefaultValue=false)]
public {{{datatype}}} {{name}} { get; set; } public {{{datatype}}} {{name}} { get; set; }

View File

@ -1,11 +1,8 @@
#import "SWGApiClient.h" #import "{{classPrefix}}ApiClient.h"
#import "SWGFile.h"
#import "SWGQueryParamCollection.h"
#import "SWGConfiguration.h"
@implementation SWGApiClient @implementation {{classPrefix}}ApiClient
NSString *const SWGResponseObjectErrorKey = @"SWGResponseObject"; NSString *const {{classPrefix}}ResponseObjectErrorKey = @"{{classPrefix}}ResponseObject";
static long requestId = 0; static long requestId = 0;
static bool offlineState = false; static bool offlineState = false;
@ -14,31 +11,38 @@ static bool cacheEnabled = false;
static AFNetworkReachabilityStatus reachabilityStatus = AFNetworkReachabilityStatusNotReachable; static AFNetworkReachabilityStatus reachabilityStatus = AFNetworkReachabilityStatusNotReachable;
static NSOperationQueue* sharedQueue; static NSOperationQueue* sharedQueue;
static void (^reachabilityChangeBlock)(int); static void (^reachabilityChangeBlock)(int);
static bool loggingEnabled = true;
#pragma mark - Log Methods #pragma mark - Log Methods
+(void)setLoggingEnabled:(bool) state { - (void)logResponse:(AFHTTPRequestOperation *)operation
loggingEnabled = state; forRequest:(NSURLRequest *)request
error:(NSError*)error {
{{classPrefix}}Configuration *config = [{{classPrefix}}Configuration sharedConfig];
NSString *message = [NSString stringWithFormat:@"\n[DEBUG] Request body \n~BEGIN~\n %@\n~END~\n"\
"[DEBUG] HTTP Response body \n~BEGIN~\n %@\n~END~\n",
[[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding],
operation.responseString];
if (config.loggingFileHanlder) {
[config.loggingFileHanlder seekToEndOfFile];
[config.loggingFileHanlder writeData:[message dataUsingEncoding:NSUTF8StringEncoding]];
}
NSLog(@"%@", message);
} }
- (void)logRequest:(NSURLRequest*)request { #pragma mark - Cache Methods
NSLog(@"request: %@", [self descriptionForRequest:request]);
}
- (void)logResponse:(id)data forRequest:(NSURLRequest*)request error:(NSError*)error { + (void) setCacheEnabled:(BOOL)enabled {
NSLog(@"request: %@ response: %@ ", [self descriptionForRequest:request], data ); cacheEnabled = enabled;
} }
#pragma mark -
+(void)clearCache { +(void)clearCache {
[[NSURLCache sharedURLCache] removeAllCachedResponses]; [[NSURLCache sharedURLCache] removeAllCachedResponses];
} }
+(void)setCacheEnabled:(BOOL)enabled { #pragma mark -
cacheEnabled = enabled;
}
+(void)configureCacheWithMemoryAndDiskCapacity: (unsigned long) memorySize +(void)configureCacheWithMemoryAndDiskCapacity: (unsigned long) memorySize
diskSize: (unsigned long) diskSize { diskSize: (unsigned long) diskSize {
@ -58,7 +62,7 @@ static bool loggingEnabled = true;
return sharedQueue; return sharedQueue;
} }
+(SWGApiClient *)sharedClientFromPool:(NSString *)baseUrl { +({{classPrefix}}ApiClient *)sharedClientFromPool:(NSString *)baseUrl {
static NSMutableDictionary *_pool = nil; static NSMutableDictionary *_pool = nil;
if (queuedRequests == nil) { if (queuedRequests == nil) {
queuedRequests = [[NSMutableSet alloc]init]; queuedRequests = [[NSMutableSet alloc]init];
@ -72,21 +76,21 @@ static bool loggingEnabled = true;
_pool = [[NSMutableDictionary alloc] init]; _pool = [[NSMutableDictionary alloc] init];
// initialize URL cache // initialize URL cache
[SWGApiClient configureCacheWithMemoryAndDiskCapacity:4*1024*1024 diskSize:32*1024*1024]; [{{classPrefix}}ApiClient configureCacheWithMemoryAndDiskCapacity:4*1024*1024 diskSize:32*1024*1024];
// configure reachability // configure reachability
[SWGApiClient configureCacheReachibilityForHost:baseUrl]; [{{classPrefix}}ApiClient configureCacheReachibilityForHost:baseUrl];
} }
@synchronized(self) { @synchronized(self) {
SWGApiClient * client = [_pool objectForKey:baseUrl]; {{classPrefix}}ApiClient * client = [_pool objectForKey:baseUrl];
if (client == nil) { if (client == nil) {
client = [[SWGApiClient alloc] initWithBaseURL:[NSURL URLWithString:baseUrl]]; client = [[{{classPrefix}}ApiClient alloc] initWithBaseURL:[NSURL URLWithString:baseUrl]];
[_pool setValue:client forKey:baseUrl ]; [_pool setValue:client forKey:baseUrl ];
if(loggingEnabled) if([[{{classPrefix}}Configuration sharedConfig] debug])
NSLog(@"new client for path %@", baseUrl); NSLog(@"new client for path %@", baseUrl);
} }
if(loggingEnabled) if([[{{classPrefix}}Configuration sharedConfig] debug])
NSLog(@"returning client for path %@", baseUrl); NSLog(@"returning client for path %@", baseUrl);
return client; return client;
} }
@ -149,15 +153,15 @@ static bool loggingEnabled = true;
+(NSNumber*) nextRequestId { +(NSNumber*) nextRequestId {
@synchronized(self) { @synchronized(self) {
long nextId = ++requestId; long nextId = ++requestId;
if(loggingEnabled) if([[{{classPrefix}}Configuration sharedConfig] debug])
NSLog(@"got id %ld", nextId); NSLog(@"got id %ld", nextId);
return [NSNumber numberWithLong:nextId]; return [NSNumber numberWithLong:nextId];
} }
} }
+(NSNumber*) queueRequest { +(NSNumber*) queueRequest {
NSNumber* requestId = [SWGApiClient nextRequestId]; NSNumber* requestId = [{{classPrefix}}ApiClient nextRequestId];
if(loggingEnabled) if([[{{classPrefix}}Configuration sharedConfig] debug])
NSLog(@"added %@ to request queue", requestId); NSLog(@"added %@ to request queue", requestId);
[queuedRequests addObject:requestId]; [queuedRequests addObject:requestId];
return requestId; return requestId;
@ -190,7 +194,7 @@ static bool loggingEnabled = true;
}]; }];
if(matchingItems.count == 1) { if(matchingItems.count == 1) {
if(loggingEnabled) if([[{{classPrefix}}Configuration sharedConfig] debug])
NSLog(@"removing request id %@", requestId); NSLog(@"removing request id %@", requestId);
[queuedRequests removeObject:requestId]; [queuedRequests removeObject:requestId];
return true; return true;
@ -221,31 +225,31 @@ static bool loggingEnabled = true;
} }
+(void) configureCacheReachibilityForHost:(NSString*)host { +(void) configureCacheReachibilityForHost:(NSString*)host {
[[SWGApiClient sharedClientFromPool:host].reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { [[{{classPrefix}}ApiClient sharedClientFromPool:host].reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
reachabilityStatus = status; reachabilityStatus = status;
switch (status) { switch (status) {
case AFNetworkReachabilityStatusUnknown: case AFNetworkReachabilityStatusUnknown:
if(loggingEnabled) if([[{{classPrefix}}Configuration sharedConfig] debug])
NSLog(@"reachability changed to AFNetworkReachabilityStatusUnknown"); NSLog(@"reachability changed to AFNetworkReachabilityStatusUnknown");
[SWGApiClient setOfflineState:true]; [{{classPrefix}}ApiClient setOfflineState:true];
break; break;
case AFNetworkReachabilityStatusNotReachable: case AFNetworkReachabilityStatusNotReachable:
if(loggingEnabled) if([[{{classPrefix}}Configuration sharedConfig] debug])
NSLog(@"reachability changed to AFNetworkReachabilityStatusNotReachable"); NSLog(@"reachability changed to AFNetworkReachabilityStatusNotReachable");
[SWGApiClient setOfflineState:true]; [{{classPrefix}}ApiClient setOfflineState:true];
break; break;
case AFNetworkReachabilityStatusReachableViaWWAN: case AFNetworkReachabilityStatusReachableViaWWAN:
if(loggingEnabled) if([[{{classPrefix}}Configuration sharedConfig] debug])
NSLog(@"reachability changed to AFNetworkReachabilityStatusReachableViaWWAN"); NSLog(@"reachability changed to AFNetworkReachabilityStatusReachableViaWWAN");
[SWGApiClient setOfflineState:false]; [{{classPrefix}}ApiClient setOfflineState:false];
break; break;
case AFNetworkReachabilityStatusReachableViaWiFi: case AFNetworkReachabilityStatusReachableViaWiFi:
if(loggingEnabled) if([[{{classPrefix}}Configuration sharedConfig] debug])
NSLog(@"reachability changed to AFNetworkReachabilityStatusReachableViaWiFi"); NSLog(@"reachability changed to AFNetworkReachabilityStatusReachableViaWiFi");
[SWGApiClient setOfflineState:false]; [{{classPrefix}}ApiClient setOfflineState:false];
break; break;
default: default:
break; break;
@ -255,7 +259,7 @@ static bool loggingEnabled = true;
reachabilityChangeBlock(status); reachabilityChangeBlock(status);
} }
}]; }];
[[SWGApiClient sharedClientFromPool:host].reachabilityManager startMonitoring]; [[{{classPrefix}}ApiClient sharedClientFromPool:host].reachabilityManager startMonitoring];
} }
-(NSString*) pathWithQueryParamsToString:(NSString*) path -(NSString*) pathWithQueryParamsToString:(NSString*) path
@ -268,36 +272,35 @@ static bool loggingEnabled = true;
for(NSString * key in [queryParams keyEnumerator]){ for(NSString * key in [queryParams keyEnumerator]){
if(counter == 0) separator = @"?"; if(counter == 0) separator = @"?";
else separator = @"&"; else separator = @"&";
NSString * value;
id queryParam = [queryParams valueForKey:key]; id queryParam = [queryParams valueForKey:key];
if([queryParam isKindOfClass:[NSString class]]){ if([queryParam isKindOfClass:[NSString class]]){
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator, [requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator,
[SWGApiClient escape:key], [SWGApiClient escape:[queryParams valueForKey:key]]]]; [{{classPrefix}}ApiClient escape:key], [{{classPrefix}}ApiClient escape:[queryParams valueForKey:key]]]];
} }
else if([queryParam isKindOfClass:[SWGQueryParamCollection class]]){ else if([queryParam isKindOfClass:[{{classPrefix}}QueryParamCollection class]]){
SWGQueryParamCollection * coll = (SWGQueryParamCollection*) queryParam; {{classPrefix}}QueryParamCollection * coll = ({{classPrefix}}QueryParamCollection*) queryParam;
NSArray* values = [coll values]; NSArray* values = [coll values];
NSString* format = [coll format]; NSString* format = [coll format];
if([format isEqualToString:@"csv"]) { if([format isEqualToString:@"csv"]) {
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator, [requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator,
[SWGApiClient escape:key], [NSString stringWithFormat:@"%@", [values componentsJoinedByString:@","]]]]; [{{classPrefix}}ApiClient escape:key], [NSString stringWithFormat:@"%@", [values componentsJoinedByString:@","]]]];
} }
else if([format isEqualToString:@"tsv"]) { else if([format isEqualToString:@"tsv"]) {
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator, [requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator,
[SWGApiClient escape:key], [NSString stringWithFormat:@"%@", [values componentsJoinedByString:@"\t"]]]]; [{{classPrefix}}ApiClient escape:key], [NSString stringWithFormat:@"%@", [values componentsJoinedByString:@"\t"]]]];
} }
else if([format isEqualToString:@"pipes"]) { else if([format isEqualToString:@"pipes"]) {
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator, [requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator,
[SWGApiClient escape:key], [NSString stringWithFormat:@"%@", [values componentsJoinedByString:@"|"]]]]; [{{classPrefix}}ApiClient escape:key], [NSString stringWithFormat:@"%@", [values componentsJoinedByString:@"|"]]]];
} }
else if([format isEqualToString:@"multi"]) { else if([format isEqualToString:@"multi"]) {
for(id obj in values) { for(id obj in values) {
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator, [requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator,
[SWGApiClient escape:key], [NSString stringWithFormat:@"%@", obj]]]; [{{classPrefix}}ApiClient escape:key], [NSString stringWithFormat:@"%@", obj]]];
counter += 1; counter += 1;
} }
@ -305,7 +308,7 @@ static bool loggingEnabled = true;
} }
else { else {
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator, [requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator,
[SWGApiClient escape:key], [NSString stringWithFormat:@"%@", [queryParams valueForKey:key]]]]; [{{classPrefix}}ApiClient escape:key], [NSString stringWithFormat:@"%@", [queryParams valueForKey:key]]]];
} }
counter += 1; counter += 1;
@ -314,11 +317,6 @@ static bool loggingEnabled = true;
return requestUrl; return requestUrl;
} }
- (NSString*)descriptionForRequest:(NSURLRequest*)request {
return [[request URL] absoluteString];
}
/** /**
* Update header and query params based on authentication settings * Update header and query params based on authentication settings
*/ */
@ -333,7 +331,7 @@ static bool loggingEnabled = true;
NSMutableDictionary *headersWithAuth = [NSMutableDictionary dictionaryWithDictionary:*headers]; NSMutableDictionary *headersWithAuth = [NSMutableDictionary dictionaryWithDictionary:*headers];
NSMutableDictionary *querysWithAuth = [NSMutableDictionary dictionaryWithDictionary:*querys]; NSMutableDictionary *querysWithAuth = [NSMutableDictionary dictionaryWithDictionary:*querys];
SWGConfiguration *config = [SWGConfiguration sharedConfig]; {{classPrefix}}Configuration *config = [{{classPrefix}}Configuration sharedConfig];
for (NSString *auth in authSettings) { for (NSString *auth in authSettings) {
NSDictionary *authSetting = [[config authSettings] objectForKey:auth]; NSDictionary *authSetting = [[config authSettings] objectForKey:auth];
@ -359,8 +357,8 @@ static bool loggingEnabled = true;
NSMutableArray *resultArray = nil; NSMutableArray *resultArray = nil;
NSMutableDictionary *resultDict = nil; NSMutableDictionary *resultDict = nil;
// return nil if data is nil // return nil if data is nil or class is nil
if (!data) { if (!data || !class) {
return nil; return nil;
} }
@ -473,20 +471,112 @@ static bool loggingEnabled = true;
return nil; return nil;
} }
#pragma mark - Operation Methods
- (void) operationWithCompletionBlock: (NSURLRequest *)request
requestId: (NSNumber *) requestId
completionBlock: (void (^)(id, NSError *))completionBlock {
AFHTTPRequestOperation *op = [self HTTPRequestOperationWithRequest:request
success:^(AFHTTPRequestOperation *operation, id response) {
if([self executeRequestWithId:requestId]) {
if([[{{classPrefix}}Configuration sharedConfig] debug]) {
[self logResponse:operation forRequest:request error:nil];
}
completionBlock(response, nil);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if([self executeRequestWithId:requestId]) {
NSMutableDictionary *userInfo = [error.userInfo mutableCopy];
if(operation.responseObject) {
// Add in the (parsed) response body.
userInfo[{{classPrefix}}ResponseObjectErrorKey] = operation.responseObject;
}
NSError *augmentedError = [error initWithDomain:error.domain code:error.code userInfo:userInfo];
if([[{{classPrefix}}Configuration sharedConfig] debug])
[self logResponse:nil forRequest:request error:augmentedError];
completionBlock(nil, augmentedError);
}
}];
[self.operationQueue addOperation:op];
}
- (void) downloadOperationWithCompletionBlock: (NSURLRequest *)request
requestId: (NSNumber *) requestId
completionBlock: (void (^)(id, NSError *))completionBlock {
AFHTTPRequestOperation *op = [self HTTPRequestOperationWithRequest:request
success:^(AFHTTPRequestOperation *operation, id responseObject) {
{{classPrefix}}Configuration *config = [{{classPrefix}}Configuration sharedConfig];
NSString *directory = nil;
if (config.tempFolderPath) {
directory = config.tempFolderPath;
}
else {
directory = NSTemporaryDirectory();
}
NSDictionary *headers = operation.response.allHeaderFields;
NSString *filename = nil;
if ([headers objectForKey:@"Content-Disposition"]) {
NSString *pattern = @"filename=['\"]?([^'\"\\s]+)['\"]?";
NSRegularExpression *regexp = [NSRegularExpression regularExpressionWithPattern:pattern
options:NSRegularExpressionCaseInsensitive
error:nil];
NSString *contentDispositionHeader = [headers objectForKey:@"Content-Disposition"];
NSTextCheckingResult *match = [regexp firstMatchInString:contentDispositionHeader
options:0
range:NSMakeRange(0, [contentDispositionHeader length])];
filename = [contentDispositionHeader substringWithRange:[match rangeAtIndex:1]];
}
else {
filename = [NSString stringWithFormat:@"%@", [[NSProcessInfo processInfo] globallyUniqueString]];
}
NSString *filepath = [directory stringByAppendingPathComponent:filename];
NSURL *file = [NSURL fileURLWithPath:filepath];
[operation.responseData writeToURL:file atomically:YES];
completionBlock(file, nil);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if ([self executeRequestWithId:requestId]) {
NSMutableDictionary *userInfo = [error.userInfo mutableCopy];
if (operation.responseObject) {
userInfo[{{classPrefix}}ResponseObjectErrorKey] = operation.responseObject;
}
NSError *augmentedError = [error initWithDomain:error.domain code:error.code userInfo:userInfo];
if ([[{{classPrefix}}Configuration sharedConfig] debug]) {
[self logResponse:nil forRequest:request error:augmentedError];
}
completionBlock(nil, augmentedError);
}
}];
[self.operationQueue addOperation:op];
}
#pragma mark - Perform Request Methods #pragma mark - Perform Request Methods
-(NSNumber*) requestWithCompletionBlock: (NSString*) path -(NSNumber*) requestWithCompletionBlock: (NSString*) path
method: (NSString*) method method: (NSString*) method
queryParams: (NSDictionary*) queryParams queryParams: (NSDictionary*) queryParams
formParams: (NSDictionary *) formParams
files: (NSDictionary *) files
body: (id) body body: (id) body
headerParams: (NSDictionary*) headerParams headerParams: (NSDictionary*) headerParams
authSettings: (NSArray *) authSettings authSettings: (NSArray *) authSettings
requestContentType: (NSString*) requestContentType requestContentType: (NSString*) requestContentType
responseContentType: (NSString*) responseContentType responseContentType: (NSString*) responseContentType
responseType: (NSString *) responseType
completionBlock: (void (^)(id, NSError *))completionBlock { completionBlock: (void (^)(id, NSError *))completionBlock {
// setting request serializer // setting request serializer
if ([requestContentType isEqualToString:@"application/json"]) { if ([requestContentType isEqualToString:@"application/json"]) {
self.requestSerializer = [AFJSONRequestSerializer serializer]; self.requestSerializer = [{{classPrefix}}JSONRequestSerializer serializer];
} }
else if ([requestContentType isEqualToString:@"application/x-www-form-urlencoded"]) { else if ([requestContentType isEqualToString:@"application/x-www-form-urlencoded"]) {
self.requestSerializer = [AFHTTPRequestSerializer serializer]; self.requestSerializer = [AFHTTPRequestSerializer serializer];
@ -500,7 +590,7 @@ static bool loggingEnabled = true;
// setting response serializer // setting response serializer
if ([responseContentType isEqualToString:@"application/json"]) { if ([responseContentType isEqualToString:@"application/json"]) {
self.responseSerializer = [SWGJSONResponseSerializer serializer]; self.responseSerializer = [{{classPrefix}}JSONResponseSerializer serializer];
} }
else { else {
self.responseSerializer = [AFHTTPResponseSerializer serializer]; self.responseSerializer = [AFHTTPResponseSerializer serializer];
@ -510,68 +600,42 @@ static bool loggingEnabled = true;
[self updateHeaderParams:&headerParams queryParams:&queryParams WithAuthSettings:authSettings]; [self updateHeaderParams:&headerParams queryParams:&queryParams WithAuthSettings:authSettings];
NSMutableURLRequest * request = nil; NSMutableURLRequest * request = nil;
if (body != nil && [body isKindOfClass:[NSArray class]]){ NSString* pathWithQueryParams = [self pathWithQueryParamsToString:path queryParams:queryParams];
SWGFile * file; NSString* urlString = [[NSURL URLWithString:pathWithQueryParams relativeToURL:self.baseURL] absoluteString];
NSMutableDictionary * params = [[NSMutableDictionary alloc] init]; if (files.count > 0) {
for(id obj in body) { request = [self.requestSerializer multipartFormRequestWithMethod:@"POST"
if([obj isKindOfClass:[SWGFile class]]) { URLString:urlString
file = (SWGFile*) obj; parameters:nil
requestContentType = @"multipart/form-data"; constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
} [formParams enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
else if([obj isKindOfClass:[NSDictionary class]]) { NSData *data = [obj dataUsingEncoding:NSUTF8StringEncoding];
for(NSString * key in obj) { [formData appendPartWithFormData:data name:key];
params[key] = obj[key]; }];
} [files enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
} NSURL *filePath = (NSURL *)obj;
} [formData appendPartWithFileURL:filePath name:key error:nil];
NSString * urlString = [[NSURL URLWithString:path relativeToURL:self.baseURL] absoluteString]; }];
} error:nil];
// request with multipart form
if([requestContentType isEqualToString:@"multipart/form-data"]) {
request = [self.requestSerializer multipartFormRequestWithMethod: @"POST"
URLString: urlString
parameters: nil
constructingBodyWithBlock: ^(id<AFMultipartFormData> formData) {
for(NSString * key in params) {
NSData* data = [params[key] dataUsingEncoding:NSUTF8StringEncoding];
[formData appendPartWithFormData: data name: key];
}
if (file) {
[formData appendPartWithFileData: [file data]
name: [file paramName]
fileName: [file name]
mimeType: [file mimeType]];
}
}
error:nil];
}
// request with form parameters or json
else {
NSString* pathWithQueryParams = [self pathWithQueryParamsToString:path queryParams:queryParams];
NSString* urlString = [[NSURL URLWithString:pathWithQueryParams relativeToURL:self.baseURL] absoluteString];
request = [self.requestSerializer requestWithMethod:method
URLString:urlString
parameters:params
error:nil];
}
} }
else { else {
NSString * pathWithQueryParams = [self pathWithQueryParamsToString:path queryParams:queryParams]; if (formParams) {
NSString * urlString = [[NSURL URLWithString:pathWithQueryParams relativeToURL:self.baseURL] absoluteString]; request = [self.requestSerializer requestWithMethod:method
URLString:urlString
request = [self.requestSerializer requestWithMethod: method parameters:formParams
URLString: urlString error:nil];
parameters: body }
error: nil]; if (body) {
request = [self.requestSerializer requestWithMethod:method
URLString:urlString
parameters:body
error:nil];
}
} }
BOOL hasHeaderParams = false; BOOL hasHeaderParams = false;
if(headerParams != nil && [headerParams count] > 0) if(headerParams != nil && [headerParams count] > 0) {
hasHeaderParams = true; hasHeaderParams = true;
}
if(offlineState) { if(offlineState) {
NSLog(@"%@ cache forced", path); NSLog(@"%@ cache forced", path);
[request setCachePolicy:NSURLRequestReturnCacheDataDontLoad]; [request setCachePolicy:NSURLRequestReturnCacheDataDontLoad];
@ -585,17 +649,7 @@ static bool loggingEnabled = true;
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData]; [request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
} }
if(hasHeaderParams){
if(body != nil) {
if([body isKindOfClass:[NSDictionary class]] || [body isKindOfClass:[NSArray class]]){
[self.requestSerializer setValue:requestContentType forHTTPHeaderField:@"Content-Type"];
}
else if ([body isKindOfClass:[SWGFile class]]){}
else {
NSAssert(false, @"unsupported post type!");
}
}
if(headerParams != nil){
for(NSString * key in [headerParams keyEnumerator]){ for(NSString * key in [headerParams keyEnumerator]){
[request setValue:[headerParams valueForKey:key] forHTTPHeaderField:key]; [request setValue:[headerParams valueForKey:key] forHTTPHeaderField:key];
} }
@ -606,31 +660,17 @@ static bool loggingEnabled = true;
// Always disable cookies! // Always disable cookies!
[request setHTTPShouldHandleCookies:NO]; [request setHTTPShouldHandleCookies:NO];
NSNumber* requestId = [SWGApiClient queueRequest]; NSNumber* requestId = [{{classPrefix}}ApiClient queueRequest];
AFHTTPRequestOperation *op = [self HTTPRequestOperationWithRequest:request if ([responseType isEqualToString:@"NSURL*"]) {
success:^(AFHTTPRequestOperation *operation, id response) { [self downloadOperationWithCompletionBlock:request requestId:requestId completionBlock:^(id data, NSError *error) {
if([self executeRequestWithId:requestId]) { completionBlock(data, error);
if(self.logServerResponses) { }];
[self logResponse:response forRequest:request error:nil]; }
} else {
completionBlock(response, nil); [self operationWithCompletionBlock:request requestId:requestId completionBlock:^(id data, NSError *error) {
} completionBlock([self deserialize:data class:responseType], error);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) { }];
if([self executeRequestWithId:requestId]) { }
NSMutableDictionary *userInfo = [error.userInfo mutableCopy];
if(operation.responseObject) {
// Add in the (parsed) response body.
userInfo[SWGResponseObjectErrorKey] = operation.responseObject;
}
NSError *augmentedError = [error initWithDomain:error.domain code:error.code userInfo:userInfo];
if(self.logServerResponses)
[self logResponse:nil forRequest:request error:augmentedError];
completionBlock(nil, augmentedError);
}
}];
[self.operationQueue addOperation:op];
return requestId; return requestId;
} }
@ -639,8 +679,3 @@ static bool loggingEnabled = true;

View File

@ -1,7 +1,11 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import <ISO8601/ISO8601.h> #import <ISO8601/ISO8601.h>
#import "AFHTTPRequestOperationManager.h" #import <AFNetworking/AFHTTPRequestOperationManager.h>
#import "SWGJSONResponseSerializer.h" #import "{{classPrefix}}JSONResponseSerializer.h"
#import "{{classPrefix}}JSONRequestSerializer.h"
#import "{{classPrefix}}QueryParamCollection.h"
#import "{{classPrefix}}Configuration.h"
{{#models}}{{#model}}#import "{{classname}}.h" {{#models}}{{#model}}#import "{{classname}}.h"
{{/model}}{{/models}} {{/model}}{{/models}}
@ -11,18 +15,13 @@
* *
* The corresponding value is the parsed response body for an HTTP error. * The corresponding value is the parsed response body for an HTTP error.
*/ */
extern NSString *const SWGResponseObjectErrorKey; extern NSString *const {{classPrefix}}ResponseObjectErrorKey;
@interface SWGApiClient : AFHTTPRequestOperationManager @interface {{classPrefix}}ApiClient : AFHTTPRequestOperationManager
@property(nonatomic, assign) NSURLRequestCachePolicy cachePolicy; @property(nonatomic, assign) NSURLRequestCachePolicy cachePolicy;
@property(nonatomic, assign) NSTimeInterval timeoutInterval; @property(nonatomic, assign) NSTimeInterval timeoutInterval;
@property(nonatomic, assign) BOOL logRequests;
@property(nonatomic, assign) BOOL logCacheHits;
@property(nonatomic, assign) BOOL logServerResponses;
@property(nonatomic, assign) BOOL logJSON;
@property(nonatomic, assign) BOOL logHTTP;
@property(nonatomic, readonly) NSOperationQueue* queue; @property(nonatomic, readonly) NSOperationQueue* queue;
/** /**
@ -30,9 +29,9 @@ extern NSString *const SWGResponseObjectErrorKey;
* *
* @param baseUrl The base url of api client. * @param baseUrl The base url of api client.
* *
* @return The SWGApiClient instance. * @return The {{classPrefix}}ApiClient instance.
*/ */
+(SWGApiClient *)sharedClientFromPool:(NSString *)baseUrl; +({{classPrefix}}ApiClient *)sharedClientFromPool:(NSString *)baseUrl;
/** /**
* Get the operations queue * Get the operations queue
@ -41,13 +40,6 @@ extern NSString *const SWGResponseObjectErrorKey;
*/ */
+(NSOperationQueue*) sharedQueue; +(NSOperationQueue*) sharedQueue;
/**
* Turn on logging
*
* @param state logging state, must be `YES` or `NO`
*/
+(void)setLoggingEnabled:(bool) state;
/** /**
* Clear Cache * Clear Cache
*/ */
@ -121,7 +113,7 @@ extern NSString *const SWGResponseObjectErrorKey;
/** /**
* Set the client reachability strategy * Set the client reachability strategy
* *
* @param host The host of SWGApiClient. * @param host The host of {{classPrefix}}ApiClient.
*/ */
+(void) configureCacheReachibilityForHost:(NSString*)host; +(void) configureCacheReachibilityForHost:(NSString*)host;
@ -171,6 +163,17 @@ extern NSString *const SWGResponseObjectErrorKey;
*/ */
- (id) deserialize:(id) data class:(NSString *) class; - (id) deserialize:(id) data class:(NSString *) class;
/**
* Logging request and response
*
* @param operation AFHTTPRequestOperation for the HTTP request.
* @param request The HTTP request.
* @param error The error of the HTTP request.
*/
- (void)logResponse:(AFHTTPRequestOperation *)operation
forRequest:(NSURLRequest *)request
error:(NSError *)error;
/** /**
* Perform request * Perform request
* *
@ -189,15 +192,14 @@ extern NSString *const SWGResponseObjectErrorKey;
-(NSNumber*) requestWithCompletionBlock:(NSString*) path -(NSNumber*) requestWithCompletionBlock:(NSString*) path
method:(NSString*) method method:(NSString*) method
queryParams:(NSDictionary*) queryParams queryParams:(NSDictionary*) queryParams
formParams:(NSDictionary *) formParams
files:(NSDictionary *) files
body:(id) body body:(id) body
headerParams:(NSDictionary*) headerParams headerParams:(NSDictionary*) headerParams
authSettings: (NSArray *) authSettings authSettings: (NSArray *) authSettings
requestContentType:(NSString*) requestContentType requestContentType:(NSString*) requestContentType
responseContentType:(NSString*) responseContentType responseContentType:(NSString*) responseContentType
responseType:(NSString *) responseType
completionBlock:(void (^)(id, NSError *))completionBlock; completionBlock:(void (^)(id, NSError *))completionBlock;
@end @end

View File

@ -1,18 +1,18 @@
#import "SWGConfiguration.h" #import "{{classPrefix}}Configuration.h"
@interface SWGConfiguration () @interface {{classPrefix}}Configuration ()
@property (readwrite, nonatomic, strong) NSMutableDictionary *mutableApiKey; @property (readwrite, nonatomic, strong) NSMutableDictionary *mutableApiKey;
@property (readwrite, nonatomic, strong) NSMutableDictionary *mutableApiKeyPrefix; @property (readwrite, nonatomic, strong) NSMutableDictionary *mutableApiKeyPrefix;
@end @end
@implementation SWGConfiguration @implementation {{classPrefix}}Configuration
#pragma mark - Singletion Methods #pragma mark - Singletion Methods
+ (instancetype) sharedConfig { + (instancetype) sharedConfig {
static SWGConfiguration *shardConfig = nil; static {{classPrefix}}Configuration *shardConfig = nil;
static dispatch_once_t onceToken; static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{ dispatch_once(&onceToken, ^{
shardConfig = [[self alloc] init]; shardConfig = [[self alloc] init];
@ -27,6 +27,9 @@
if (self) { if (self) {
self.username = @""; self.username = @"";
self.password = @""; self.password = @"";
self.tempFolderPath = nil;
self.debug = NO;
self.loggingFile = nil;
self.mutableApiKey = [NSMutableDictionary dictionary]; self.mutableApiKey = [NSMutableDictionary dictionary];
self.mutableApiKeyPrefix = [NSMutableDictionary dictionary]; self.mutableApiKeyPrefix = [NSMutableDictionary dictionary];
} }
@ -65,6 +68,20 @@
[self.mutableApiKeyPrefix setValue:value forKey:field]; [self.mutableApiKeyPrefix setValue:value forKey:field];
} }
- (void) setLoggingFile:(NSString *)loggingFile {
// close old file handler
if ([self.loggingFileHanlder isKindOfClass:[NSFileHandle class]]) {
[self.loggingFileHanlder closeFile];
}
_loggingFile = loggingFile;
self.loggingFileHanlder = [NSFileHandle fileHandleForWritingAtPath:_loggingFile];
if (self.loggingFileHanlder == nil) {
[[NSFileManager defaultManager] createFileAtPath:_loggingFile contents:nil attributes:nil];
self.loggingFileHanlder = [NSFileHandle fileHandleForWritingAtPath:_loggingFile];
}
}
#pragma mark - Getter Methods #pragma mark - Getter Methods
- (NSDictionary *) apiKey { - (NSDictionary *) apiKey {
@ -78,21 +95,14 @@
#pragma mark - #pragma mark -
- (NSDictionary *) authSettings { - (NSDictionary *) authSettings {
return @{ {{#authMethods}}{{#isApiKey}} return @{
@"{{name}}": @{ @"api_key": @{
@"type": @"api_key", @"type": @"api_key",
@"in": {{#isKeyInHeader}}@"header"{{/isKeyInHeader}}{{#isKeyInQuery}}@"query"{{/isKeyInQuery}},
@"key": @"{{keyParamName}}",
@"value": [self getApiKeyWithPrefix:@"{{keyParamName}}"]
},
{{/isApiKey}}{{#isBasic}}
@"{{name}}": @{
@"type": @"basic",
@"in": @"header", @"in": @"header",
@"key": @"Authorization", @"key": @"api_key",
@"value": [self getBasicAuthToken] @"value": [self getApiKeyWithPrefix:@"api_key"]
}, },
{{/isBasic}}{{/authMethods}}
}; };
} }

View File

@ -1,6 +1,6 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
@interface SWGConfiguration : NSObject @interface {{classPrefix}}Configuration : NSObject
/** /**
@ -23,6 +23,18 @@
@property (nonatomic) NSString *username; @property (nonatomic) NSString *username;
@property (nonatomic) NSString *password; @property (nonatomic) NSString *password;
/**
* Temp folder for file download
*/
@property (nonatomic) NSString *tempFolderPath;
/**
* Logging Settings
*/
@property (nonatomic) BOOL debug;
@property (nonatomic) NSString *loggingFile;
@property (nonatomic) NSFileHandle *loggingFileHanlder;
/** /**
* Get configuration singleton instance * Get configuration singleton instance
*/ */

View File

@ -0,0 +1,35 @@
#import "{{classPrefix}}JSONRequestSerializer.h"
@implementation {{classPrefix}}JSONRequestSerializer
///
/// When customize a request serializer,
/// the serializer must conform the protocol `AFURLRequestSerialization`
/// and implements the protocol method `requestBySerializingRequest:withParameters:error:`
///
/// @param request The original request.
/// @param parameters The parameters to be encoded.
/// @param error The error that occurred while attempting to encode the request parameters.
///
/// @return A serialized request.
///
- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
withParameters:(id)parameters
error:(NSError *__autoreleasing *)error
{
// If the body data which will be serialized isn't NSArray or NSDictionary
// then put the data in the http request body directly.
if ([parameters isKindOfClass:[NSArray class]] || [parameters isKindOfClass:[NSDictionary class]]) {
return [super requestBySerializingRequest:request withParameters:parameters error:error];
} else {
NSMutableURLRequest *mutableRequest = [request mutableCopy];
if (parameters) {
[mutableRequest setHTTPBody:[parameters dataUsingEncoding:self.stringEncoding]];
}
return mutableRequest;
}
}
@end

View File

@ -0,0 +1,5 @@
#import <Foundation/Foundation.h>
#import <AFNetworking/AFURLRequestSerialization.h>
@interface {{classPrefix}}JSONRequestSerializer : AFJSONRequestSerializer
@end

View File

@ -1,4 +1,4 @@
#import "SWGJSONResponseSerializer.h" #import "{{classPrefix}}JSONResponseSerializer.h"
static BOOL JSONParseError(NSError *error) { static BOOL JSONParseError(NSError *error) {
if ([error.domain isEqualToString:NSCocoaErrorDomain] && error.code == 3840) { if ([error.domain isEqualToString:NSCocoaErrorDomain] && error.code == 3840) {
@ -8,7 +8,7 @@ static BOOL JSONParseError(NSError *error) {
return NO; return NO;
} }
@implementation SWGJSONResponseSerializer @implementation {{classPrefix}}JSONResponseSerializer
/// ///
/// When customize a response serializer, /// When customize a response serializer,

View File

@ -1,6 +1,6 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import <AFNetworking/AFURLResponseSerialization.h> #import <AFNetworking/AFURLResponseSerialization.h>
@interface SWGJSONResponseSerializer : AFJSONResponseSerializer @interface {{classPrefix}}JSONResponseSerializer : AFJSONResponseSerializer
@end @end

View File

@ -0,0 +1,4 @@
#import "{{classPrefix}}Object.h"
@implementation {{classPrefix}}Object
@end

View File

@ -0,0 +1,5 @@
#import <Foundation/Foundation.h>
#import <JSONModel/JSONModel.h>
@interface {{classPrefix}}Object : JSONModel
@end

View File

@ -1,5 +0,0 @@
platform :ios, '6.0'
xcodeproj '{{projectName}}/{{projectName}}.xcodeproj'
pod 'AFNetworking', '~> 2.1'
pod 'JSONModel', '~> 1.0'
pod 'ISO8601'

View File

@ -1,6 +1,6 @@
#import "SWGQueryParamCollection.h" #import "{{classPrefix}}QueryParamCollection.h"
@implementation SWGQueryParamCollection @implementation {{classPrefix}}QueryParamCollection
@synthesize values = _values; @synthesize values = _values;
@synthesize format = _format; @synthesize format = _format;

View File

@ -1,6 +1,6 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
@interface SWGQueryParamCollection : NSObject @interface {{classPrefix}}QueryParamCollection : NSObject
@property(nonatomic, readonly) NSArray* values; @property(nonatomic, readonly) NSArray* values;
@property(nonatomic, readonly) NSString* format; @property(nonatomic, readonly) NSString* format;

View File

@ -0,0 +1,19 @@
# {{podName}}
## Requirements
The API client library requires ARC (Automatic Reference Counting) to be enabled in your Xcode project.
## Installation
To install it, put the API client library in your project and then simply add the following line to your Podfile:
```ruby
pod "{{podName}}", :path => "/path/to/lib"
```
## Author
{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}}
{{/hasMore}}{{/apis}}{{/apiInfo}}

View File

@ -1,14 +0,0 @@
#import <Foundation/Foundation.h>
@interface SWGFile : NSObject
@property(nonatomic, readonly) NSString* name;
@property(nonatomic, readonly) NSString* mimeType;
@property(nonatomic, readonly) NSData* data;
@property(nonatomic) NSString* paramName;
- (id) initWithNameData: (NSString*) filename
mimeType: (NSString*) mimeType
data: (NSData*) data;
@end

View File

@ -1,26 +0,0 @@
#import "SWGFile.h"
@implementation SWGFile
@synthesize name = _name;
@synthesize mimeType = _mimeType;
@synthesize data = _data;
- (id) init {
self = [super init];
return self;
}
- (id) initWithNameData: (NSString*) filename
mimeType: (NSString*) fileMimeType
data: (NSData*) data {
self = [super init];
if(self) {
_name = filename;
_mimeType = fileMimeType;
_data = data;
}
return self;
}
@end

View File

@ -1,7 +1,6 @@
{{#operations}} {{#operations}}
#import "{{classname}}.h" #import "{{classname}}.h"
#import "SWGFile.h" #import "{{classPrefix}}QueryParamCollection.h"
#import "SWGQueryParamCollection.h"
{{#imports}}#import "{{import}}.h" {{#imports}}#import "{{import}}.h"
{{/imports}} {{/imports}}
{{newline}} {{newline}}
@ -19,20 +18,20 @@ static NSString * basePath = @"{{basePath}}";
- (id) init { - (id) init {
self = [super init]; self = [super init];
if (self) { if (self) {
self.apiClient = [SWGApiClient sharedClientFromPool:basePath]; self.apiClient = [{{classPrefix}}ApiClient sharedClientFromPool:basePath];
self.defaultHeaders = [NSMutableDictionary dictionary]; self.defaultHeaders = [NSMutableDictionary dictionary];
} }
return self; return self;
} }
- (id) initWithApiClient:(SWGApiClient *)apiClient { - (id) initWithApiClient:({{classPrefix}}ApiClient *)apiClient {
self = [super init]; self = [super init];
if (self) { if (self) {
if (apiClient) { if (apiClient) {
self.apiClient = apiClient; self.apiClient = apiClient;
} }
else { else {
self.apiClient = [SWGApiClient sharedClientFromPool:basePath]; self.apiClient = [{{classPrefix}}ApiClient sharedClientFromPool:basePath];
} }
self.defaultHeaders = [NSMutableDictionary dictionary]; self.defaultHeaders = [NSMutableDictionary dictionary];
} }
@ -69,7 +68,7 @@ static NSString * basePath = @"{{basePath}}";
} }
-(unsigned long) requestQueueSize { -(unsigned long) requestQueueSize {
return [SWGApiClient requestQueueSize]; return [{{classPrefix}}ApiClient requestQueueSize];
} }
#pragma mark - Api Methods #pragma mark - Api Methods
@ -84,12 +83,14 @@ static NSString * basePath = @"{{basePath}}";
/// ///
-(NSNumber*) {{nickname}}WithCompletionBlock{{^allParams}}: {{/allParams}}{{#allParams}}{{#secondaryParam}} {{paramName}}{{/secondaryParam}}: ({{{dataType}}}) {{paramName}} -(NSNumber*) {{nickname}}WithCompletionBlock{{^allParams}}: {{/allParams}}{{#allParams}}{{#secondaryParam}} {{paramName}}{{/secondaryParam}}: ({{{dataType}}}) {{paramName}}
{{/allParams}} {{/allParams}}
{{#returnBaseType}}{{#hasParams}}completionHandler: {{/hasParams}}(void (^)({{{returnType}}} output, NSError* error))completionBlock{{/returnBaseType}} {{#returnBaseType}}{{#hasParams}}completionHandler: {{/hasParams}}(void (^)({{{returnType}}} output, NSError* error))completionBlock { {{/returnBaseType}}
{{^returnBaseType}}{{#hasParams}}completionHandler: {{/hasParams}}(void (^)(NSError* error))completionBlock{{/returnBaseType}} { {{^returnBaseType}}{{#hasParams}}completionHandler: {{/hasParams}}(void (^)(NSError* error))completionBlock { {{/returnBaseType}}
{{#allParams}}{{#required}} {{#allParams}}{{#required}}
// verify the required parameter '{{paramName}}' is set // verify the required parameter '{{paramName}}' is set
NSAssert({{paramName}} != nil, @"Missing the required parameter `{{paramName}}` when calling {{nickname}}"); if ({{paramName}} == nil) {
[NSException raise:@"Invalid parameter" format:@"Missing the required parameter `{{paramName}}` when calling `{{nickname}}`"];
}
{{/required}}{{/allParams}} {{/required}}{{/allParams}}
NSMutableString* requestUrl = [NSMutableString stringWithFormat:@"%@{{path}}", basePath]; NSMutableString* requestUrl = [NSMutableString stringWithFormat:@"%@{{path}}", basePath];
@ -98,13 +99,13 @@ static NSString * basePath = @"{{basePath}}";
if ([requestUrl rangeOfString:@".{format}"].location != NSNotFound) if ([requestUrl rangeOfString:@".{format}"].location != NSNotFound)
[requestUrl replaceCharactersInRange: [requestUrl rangeOfString:@".{format}"] withString:@".json"]; [requestUrl replaceCharactersInRange: [requestUrl rangeOfString:@".{format}"] withString:@".json"];
{{#pathParams}}[requestUrl replaceCharactersInRange: [requestUrl rangeOfString:[NSString stringWithFormat:@"%@%@%@", @"{", @"{{baseName}}", @"}"]] withString: [SWGApiClient escape:{{paramName}}]]; {{#pathParams}}[requestUrl replaceCharactersInRange: [requestUrl rangeOfString:[NSString stringWithFormat:@"%@%@%@", @"{", @"{{baseName}}", @"}"]] withString: [{{classPrefix}}ApiClient escape:{{paramName}}]];
{{/pathParams}} {{/pathParams}}
NSMutableDictionary* queryParams = [[NSMutableDictionary alloc] init]; NSMutableDictionary* queryParams = [[NSMutableDictionary alloc] init];
{{#queryParams}}if({{paramName}} != nil) { {{#queryParams}}if({{paramName}} != nil) {
{{#collectionFormat}} {{#collectionFormat}}
queryParams[@"{{baseName}}"] = [[SWGQueryParamCollection alloc] initWithValuesAndFormat: {{baseName}} format: @"{{collectionFormat}}"]; queryParams[@"{{baseName}}"] = [[{{classPrefix}}QueryParamCollection alloc] initWithValuesAndFormat: {{baseName}} format: @"{{collectionFormat}}"];
{{/collectionFormat}} {{/collectionFormat}}
{{^collectionFormat}}queryParams[@"{{baseName}}"] = {{paramName}};{{/collectionFormat}} {{^collectionFormat}}queryParams[@"{{baseName}}"] = {{paramName}};{{/collectionFormat}}
} }
@ -114,9 +115,9 @@ static NSString * basePath = @"{{basePath}}";
{{#headerParams}}if({{paramName}} != nil) {{#headerParams}}if({{paramName}} != nil)
headerParams[@"{{baseName}}"] = {{paramName}}; headerParams[@"{{baseName}}"] = {{paramName}};
{{/headerParams}} {{/headerParams}}
// HTTP header `Accept` // HTTP header `Accept`
headerParams[@"Accept"] = [SWGApiClient selectHeaderAccept:@[{{#produces}}@"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/produces}}]]; headerParams[@"Accept"] = [{{classPrefix}}ApiClient selectHeaderAccept:@[{{#produces}}@"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/produces}}]];
if ([headerParams[@"Accept"] length] == 0) { if ([headerParams[@"Accept"] length] == 0) {
[headerParams removeObjectForKey:@"Accept"]; [headerParams removeObjectForKey:@"Accept"];
} }
@ -131,62 +132,39 @@ static NSString * basePath = @"{{basePath}}";
} }
// request content type // request content type
NSString *requestContentType = [SWGApiClient selectHeaderContentType:@[{{#consumes}}@"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/consumes}}]]; NSString *requestContentType = [{{classPrefix}}ApiClient selectHeaderContentType:@[{{#consumes}}@"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/consumes}}]];
// Authentication setting // Authentication setting
NSArray *authSettings = @[{{#authMethods}}@"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}}]; NSArray *authSettings = @[{{#authMethods}}@"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}}];
id bodyDictionary = nil;
{{#bodyParam}}
id __body = {{paramName}};
if(__body != nil && [__body isKindOfClass:[NSArray class]]){ id bodyParam = nil;
NSMutableArray * objs = [[NSMutableArray alloc] init]; NSMutableDictionary *formParams = [[NSMutableDictionary alloc] init];
for (id dict in (NSArray*)__body) { NSMutableDictionary *files = [[NSMutableDictionary alloc] init];
{{#bodyParam}}
bodyParam = {{paramName}};
if(bodyParam != nil && [bodyParam isKindOfClass:[NSArray class]]){
NSMutableArray *objs = [[NSMutableArray alloc] init];
for (id dict in (NSArray*)bodyParam) {
if([dict respondsToSelector:@selector(toDictionary)]) { if([dict respondsToSelector:@selector(toDictionary)]) {
[objs addObject:[(SWGObject*)dict toDictionary]]; [objs addObject:[({{classPrefix}}Object*)dict toDictionary]];
} }
else{ else{
[objs addObject:dict]; [objs addObject:dict];
} }
} }
bodyDictionary = objs; bodyParam = objs;
} }
else if([__body respondsToSelector:@selector(toDictionary)]) { else if([bodyParam respondsToSelector:@selector(toDictionary)]) {
bodyDictionary = [(SWGObject*)__body toDictionary]; bodyParam = [({{classPrefix}}Object*)bodyParam toDictionary];
} }
else if([__body isKindOfClass:[NSString class]]) { {{/bodyParam}}{{^bodyParam}}
// convert it to a dictionary
NSError * error;
NSString * str = (NSString*)__body;
NSDictionary *JSON =
[NSJSONSerialization JSONObjectWithData: [str dataUsingEncoding: NSUTF8StringEncoding]
options: NSJSONReadingMutableContainers
error: &error];
bodyDictionary = JSON;
}
{{/bodyParam}}
{{^bodyParam}}
NSMutableDictionary * formParams = [[NSMutableDictionary alloc]init];
{{#formParams}} {{#formParams}}
{{#notFile}} {{#notFile}}
formParams[@"{{paramName}}"] = {{paramName}}; formParams[@"{{paramName}}"] = {{paramName}};
{{/notFile}}{{#isFile}} {{/notFile}}{{#isFile}}
requestContentType = @"multipart/form-data"; files[@"{{paramName}}"] = {{paramName}};
if(bodyDictionary == nil) {
bodyDictionary = [[NSMutableArray alloc] init];
}
if({{paramName}} != nil) {
[bodyDictionary addObject:{{paramName}}];
{{paramName}}.paramName = @"{{baseName}}";
}
{{/isFile}} {{/isFile}}
if(bodyDictionary == nil) {
bodyDictionary = [[NSMutableArray alloc] init];
}
[bodyDictionary addObject:formParams];
{{/formParams}} {{/formParams}}
{{/bodyParam}} {{/bodyParam}}
@ -200,14 +178,17 @@ static NSString * basePath = @"{{basePath}}";
return [self.apiClient requestWithCompletionBlock: requestUrl return [self.apiClient requestWithCompletionBlock: requestUrl
method: @"{{httpMethod}}" method: @"{{httpMethod}}"
queryParams: queryParams queryParams: queryParams
body: bodyDictionary formParams: formParams
files: files
body: bodyParam
headerParams: headerParams headerParams: headerParams
authSettings: authSettings authSettings: authSettings
requestContentType: requestContentType requestContentType: requestContentType
responseContentType: responseContentType responseContentType: responseContentType
responseType: {{^returnType}}nil{{/returnType}}{{#returnType}}@"{{{ returnType }}}"{{/returnType}}
completionBlock: ^(id data, NSError *error) { completionBlock: ^(id data, NSError *error) {
{{^returnType}}completionBlock(error);{{/returnType}} {{^returnType}}completionBlock(error);{{/returnType}}
{{#returnType}}completionBlock([self.apiClient deserialize: data class:@"{{{returnType}}}"], error);{{/returnType}} {{#returnType}}completionBlock(({{{ returnType }}})data, error);{{/returnType}}
} }
]; ];
} }
@ -217,6 +198,3 @@ static NSString * basePath = @"{{basePath}}";
{{newline}} {{newline}}
{{/operations}} {{/operations}}
@end @end

View File

@ -1,16 +1,16 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
{{#imports}}#import "{{import}}.h" {{#imports}}#import "{{import}}.h"
{{/imports}} {{/imports}}
#import "SWGObject.h" #import "{{classPrefix}}Object.h"
#import "SWGApiClient.h" #import "{{classPrefix}}ApiClient.h"
{{newline}} {{newline}}
{{#operations}} {{#operations}}
@interface {{classname}}: NSObject @interface {{classname}}: NSObject
@property(nonatomic, assign)SWGApiClient *apiClient; @property(nonatomic, assign){{classPrefix}}ApiClient *apiClient;
-(instancetype) initWithApiClient:(SWGApiClient *)apiClient; -(instancetype) initWithApiClient:({{classPrefix}}ApiClient *)apiClient;
-(void) addHeader:(NSString*)value forKey:(NSString*)key; -(void) addHeader:(NSString*)value forKey:(NSString*)key;
-(unsigned long) requestQueueSize; -(unsigned long) requestQueueSize;
+({{classname}}*) apiWithHeader:(NSString*)headerValue key:(NSString*)key; +({{classname}}*) apiWithHeader:(NSString*)headerValue key:(NSString*)key;

View File

@ -1,5 +1,5 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import "SWGObject.h" #import "{{classPrefix}}Object.h"
{{#imports}}#import "{{import}}.h" {{#imports}}#import "{{import}}.h"
{{/imports}} {{/imports}}
{{newline}} {{newline}}
@ -9,7 +9,7 @@
@protocol {{classname}} @protocol {{classname}}
@end @end
@interface {{classname}} : SWGObject @interface {{classname}} : {{classPrefix}}Object
{{#vars}} {{#vars}}
{{#description}}/* {{{description}}} {{^required}}[optional]{{/required}} {{#description}}/* {{{description}}} {{^required}}[optional]{{/required}}

View File

@ -0,0 +1,31 @@
#
# Be sure to run `pod lib lint {{podName}}.podspec' to ensure this is a
# valid spec and remove all comments before submitting the spec.
#
# Any lines starting with a # are optional, but encouraged
#
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
#
Pod::Spec.new do |s|
s.name = "{{podName}}"
s.version = "{{podVersion}}"
{{#apiInfo}}{{#apis}}{{^hasMore}}
s.summary = "{{appName}}"
s.description = <<-DESC
{{appDescription}}
DESC
{{/hasMore}}{{/apis}}{{/apiInfo}}
s.platform = :ios, '7.0'
s.requires_arc = true
s.framework = 'SystemConfiguration'
s.source_files = '{{podName}}/**/*'
s.public_header_files = '{{podName}}/**/*.h'
s.dependency 'AFNetworking', '~> 2.3'
s.dependency 'JSONModel', '~> 1.1'
s.dependency 'ISO8601', '~> 0.3'
end

View File

@ -54,7 +54,7 @@ sub new {
# #
# {{{summary}}} # {{{summary}}}
# #
{{#allParams}}# @param {{dataType}} ${{paramName}} {{description}} {{^optional}}(required){{/optional}}{{#optional}}(optional){{/optional}} {{#allParams}}# @param {{dataType}} ${{paramName}} {{description}} {{#required}}(required){{/required}}{{^required}}(optional){{/required}}
{{/allParams}}# @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{/allParams}}# @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}
# #
sub {{nickname}} { sub {{nickname}} {

View File

@ -1,4 +1,15 @@
<?php <?php
/**
* ApiClient
*
* PHP version 5
*
* @category Class
* @package {{invokerPackage}}
* @author http://github.com/swagger-api/swagger-codegen
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache Licene v2
* @link https://github.com/swagger-api/swagger-codegen
*/
/** /**
* Copyright 2015 SmartBear Software * Copyright 2015 SmartBear Software
* *
@ -14,206 +25,248 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
/**
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen
* Do not edit the class manually.
*/
namespace {{invokerPackage}}; namespace {{invokerPackage}};
class ApiClient { /**
* ApiClient Class Doc Comment
*
* @category Class
* @package {{invokerPackage}}
* @author http://github.com/swagger-api/swagger-codegen
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache Licene v2
* @link https://github.com/swagger-api/swagger-codegen
*/
class ApiClient
{
public static $PATCH = "PATCH"; public static $PATCH = "PATCH";
public static $POST = "POST"; public static $POST = "POST";
public static $GET = "GET"; public static $GET = "GET";
public static $PUT = "PUT"; public static $PUT = "PUT";
public static $DELETE = "DELETE"; public static $DELETE = "DELETE";
/** @var Configuration */ /**
protected $config; * Configuration
* @var Configuration
/** @var ObjectSerializer */ */
protected $serializer; protected $config;
/** /**
* @param Configuration $config config for this ApiClient * Object Serializer
*/ * @var ObjectSerializer
function __construct(Configuration $config = null) { */
if ($config == null) { protected $serializer;
$config = Configuration::getDefaultConfiguration();
/**
* Constructor of the class
* @param Configuration $config config for this ApiClient
*/
function __construct(Configuration $config = null)
{
if ($config == null) {
$config = Configuration::getDefaultConfiguration();
}
$this->config = $config;
$this->serializer = new ObjectSerializer();
}
/**
* Get the config
* @return Configuration
*/
public function getConfig()
{
return $this->config;
}
/**
* Get the serializer
* @return ObjectSerializer
*/
public function getSerializer()
{
return $this->serializer;
}
/**
* Get API key (with prefix if set)
* @param string $apiKeyIdentifier name of apikey
* @return string API key with the prefix
*/
public function getApiKeyWithPrefix($apiKeyIdentifier)
{
$prefix = $this->config->getApiKeyPrefix($apiKeyIdentifier);
$apiKey = $this->config->getApiKey($apiKeyIdentifier);
if (!isset($apiKey)) {
return null;
}
if (isset($prefix)) {
$keyWithPrefix = $prefix." ".$apiKey;
} else {
$keyWithPrefix = $apiKey;
}
return $keyWithPrefix;
} }
$this->config = $config; /**
$this->serializer = new ObjectSerializer(); * Make the HTTP call (Sync)
} * @param string $resourcePath path to method endpoint
* @param string $method method to call
/** * @param array $queryParams parameters to be place in query URL
* get the config * @param array $postData parameters to be placed in POST body
* @return Configuration * @param array $headerParams parameters to be place in request header
*/ * @param string $responseType expected response type of the endpoint
public function getConfig() { * @throws \{{invokerPackage}}\ApiException on a non 2xx response
return $this->config; * @return mixed
} */
public function callApi($resourcePath, $method, $queryParams, $postData, $headerParams, $responseType=null)
/** {
* get the serializer
* @return ObjectSerializer
*/
public function getSerializer() {
return $this->serializer;
}
/**
* Get API key (with prefix if set)
* @param string $apiKey name of apikey
* @return string API key with the prefix
*/
public function getApiKeyWithPrefix($apiKey) {
$prefix = $this->config->getApiKeyPrefix($apiKey);
$apiKey = $this->config->getApiKey($apiKey);
if (!isset($apiKey)) {
return null;
}
if (isset($prefix)) {
$keyWithPrefix = $prefix." ".$apiKey;
} else {
$keyWithPrefix = $apiKey;
}
return $keyWithPrefix;
}
/** $headers = array();
* @param string $resourcePath path to method endpoint
* @param string $method method to call // construct the http header
* @param array $queryParams parameters to be place in query URL $headerParams = array_merge(
* @param array $postData parameters to be placed in POST body (array)$this->config->getDefaultHeaders(),
* @param array $headerParams parameters to be place in request header (array)$headerParams
* @throws \{{invokerPackage}}\ApiException on a non 2xx response );
* @return mixed
*/ foreach ($headerParams as $key => $val) {
public function callApi($resourcePath, $method, $queryParams, $postData, $headerParams) { $headers[] = "$key: $val";
}
$headers = array();
// form data
# construct the http header if ($postData and in_array('Content-Type: application/x-www-form-urlencoded', $headers)) {
$headerParams = array_merge((array)$this->config->getDefaultHeaders(), (array)$headerParams); $postData = http_build_query($postData);
} else if ((is_object($postData) or is_array($postData)) and !in_array('Content-Type: multipart/form-data', $headers)) { // json model
foreach ($headerParams as $key => $val) { $postData = json_encode($this->serializer->sanitizeForSerialization($postData));
$headers[] = "$key: $val"; }
$url = $this->config->getHost() . $resourcePath;
$curl = curl_init();
// set timeout, if needed
if ($this->config->getCurlTimeout() != 0) {
curl_setopt($curl, CURLOPT_TIMEOUT, $this->config->getCurlTimeout());
}
// return the result on success, rather than just TRUE
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
if (! empty($queryParams)) {
$url = ($url . '?' . http_build_query($queryParams));
}
if ($method == self::$POST) {
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
} else if ($method == self::$PATCH) {
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PATCH");
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
} else if ($method == self::$PUT) {
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
} else if ($method == self::$DELETE) {
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
} else if ($method != self::$GET) {
throw new ApiException('Method ' . $method . ' is not recognized.');
}
curl_setopt($curl, CURLOPT_URL, $url);
// Set user agent
curl_setopt($curl, CURLOPT_USERAGENT, $this->config->getUserAgent());
// debugging for curl
if ($this->config->getDebug()) {
error_log("[DEBUG] HTTP Request body ~BEGIN~\n".print_r($postData, true)."\n~END~\n", 3, $this->config->getDebugFile());
curl_setopt($curl, CURLOPT_VERBOSE, 1);
curl_setopt($curl, CURLOPT_STDERR, fopen($this->config->getDebugFile(), '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 ($this->config->getDebug()) {
error_log("[DEBUG] HTTP Response body ~BEGIN~\n".print_r($http_body, true)."\n~END~\n", 3, $this->config->getDebugFile());
}
// Handle the response
if ($response_info['http_code'] == 0) {
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 ) {
// return raw body if response is a file
if ($responseType == '\SplFileObject') {
return array($http_body, $http_header);
}
$data = json_decode($http_body);
if (json_last_error() > 0) { // if response is a string
$data = $http_body;
}
} else {
throw new ApiException(
"[".$response_info['http_code']."] Error connecting to the API ($url)",
$response_info['http_code'], $http_header, $http_body
);
}
return array($data, $http_header);
} }
// form data /**
if ($postData and in_array('Content-Type: application/x-www-form-urlencoded', $headers)) { * Return the header 'Accept' based on an array of Accept provided
$postData = http_build_query($postData); *
* @param string[] $accept Array of header
*
* @return string Accept (e.g. application/json)
*/
public static function selectHeaderAccept($accept)
{
if (count($accept) === 0 or (count($accept) === 1 and $accept[0] === '')) {
return null;
} elseif (preg_grep("/application\/json/i", $accept)) {
return 'application/json';
} else {
return implode(',', $accept);
}
} }
else if ((is_object($postData) or is_array($postData)) and !in_array('Content-Type: multipart/form-data', $headers)) { // json model
$postData = json_encode($this->serializer->sanitizeForSerialization($postData)); /**
* Return the content type based on an array of content-type provided
*
* @param string[] $content_type Array fo content-type
*
* @return string Content-Type (e.g. application/json)
*/
public static function selectHeaderContentType($content_type)
{
if (count($content_type) === 0 or (count($content_type) === 1 and $content_type[0] === '')) {
return 'application/json';
} elseif (preg_grep("/application\/json/i", $content_type)) {
return 'application/json';
} else {
return implode(',', $content_type);
}
} }
$url = $this->config->getHost() . $resourcePath;
$curl = curl_init();
// set timeout, if needed
if ($this->config->getCurlTimeout() != 0) {
curl_setopt($curl, CURLOPT_TIMEOUT, $this->config->getCurlTimeout());
}
// return the result on success, rather than just TRUE
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
if (! empty($queryParams)) {
$url = ($url . '?' . http_build_query($queryParams));
}
if ($method == self::$POST) {
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
} else if ($method == self::$PATCH) {
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PATCH");
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
} else if ($method == self::$PUT) {
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
} else if ($method == self::$DELETE) {
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
} else if ($method != self::$GET) {
throw new ApiException('Method ' . $method . ' is not recognized.');
}
curl_setopt($curl, CURLOPT_URL, $url);
// Set user agent
curl_setopt($curl, CURLOPT_USERAGENT, $this->config->getUserAgent());
// debugging for curl
if ($this->config->getDebug()) {
error_log("[DEBUG] HTTP Request body ~BEGIN~\n".print_r($postData, true)."\n~END~\n", 3, $this->config->getDebugFile());
curl_setopt($curl, CURLOPT_VERBOSE, 1);
curl_setopt($curl, CURLOPT_STDERR, fopen($this->config->getDebugFile(), '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 ($this->config->getDebug()) {
error_log("[DEBUG] HTTP Response body ~BEGIN~\n".print_r($http_body, true)."\n~END~\n", 3, $this->config->getDebugFile());
}
// Handle the response
if ($response_info['http_code'] == 0) {
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($http_body);
if (json_last_error() > 0) { // if response is a string
$data = $http_body;
}
} else {
throw new ApiException("[".$response_info['http_code']."] Error connecting to the API ($url)",
$response_info['http_code'], $http_header, $http_body);
}
return $data;
}
/*
* return the header 'Accept' based on an array of Accept provided
*
* @param string[] $accept Array of header
* @return string Accept (e.g. application/json)
*/
public static function selectHeaderAccept($accept) {
if (count($accept) === 0 or (count($accept) === 1 and $accept[0] === '')) {
return NULL;
} elseif (preg_grep("/application\/json/i", $accept)) {
return 'application/json';
} else {
return implode(',', $accept);
}
}
/*
* return the content type based on an array of content-type provided
*
* @param string[] content_type_array Array fo content-type
* @return string Content-Type (e.g. application/json)
*/
public static function selectHeaderContentType($content_type) {
if (count($content_type) === 0 or (count($content_type) === 1 and $content_type[0] === '')) {
return 'application/json';
} elseif (preg_grep("/application\/json/i", $content_type)) {
return 'application/json';
} else {
return implode(',', $content_type);
}
}
} }

View File

@ -1,4 +1,14 @@
<?php <?php
/**
* ApiException
* PHP version 5
*
* @category Class
* @package {{invokerPackage}}
* @author http://github.com/swagger-api/swagger-codegen
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache Licene v2
* @link https://github.com/swagger-api/swagger-codegen
*/
/** /**
* Copyright 2015 SmartBear Software * Copyright 2015 SmartBear Software
* *
@ -14,57 +24,97 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
/**
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen
* Do not edit the class manually.
*/
namespace {{invokerPackage}}; namespace {{invokerPackage}};
use \Exception; use \Exception;
class ApiException extends Exception { /**
* ApiException Class Doc Comment
*
* @category Class
* @package {{invokerPackage}}
* @author http://github.com/swagger-api/swagger-codegen
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache Licene v2
* @link https://github.com/swagger-api/swagger-codegen
*/
class ApiException extends Exception
{
/** @var string The HTTP body of the server response. */ /**
protected $responseBody; * The HTTP body of the server response.
* @var string
*/
protected $responseBody;
/**
* The HTTP header of the server response.
* @var string[]
*/
protected $responseHeaders;
/**
* The deserialized response object
* @var $responseObject;
*/
protected $responseObject;
/**
* Constructor
* @param string $message Error message
* @param string $code HTTP status code
* @param string $responseHeaders HTTP response header
* @param string $responseBody Deseralized response object
*/
public function __construct($message="", $code=0, $responseHeaders=null, $responseBody=null)
{
parent::__construct($message, $code);
$this->responseHeaders = $responseHeaders;
$this->responseBody = $responseBody;
}
/**
* Gets the HTTP response header
*
* @return string HTTP response header
*/
public function getResponseHeaders()
{
return $this->responseHeaders;
}
/**
* Gets the HTTP response body
*
* @return string HTTP response body
*/
public function getResponseBody()
{
return $this->responseBody;
}
/**
* Sets the deseralized response object (during deserialization)
* @param mixed $obj Deserialized response object
* @return void
*/
public function setResponseObject($obj)
{
$this->responseObject = $obj;
}
/** @var string[] The HTTP header of the server response. */ /**
protected $responseHeaders; * Gets the deseralized response object (during deserialization)
*
/** * @return mixed the deserialized response object
* The deserialized response object */
*/ public function getResponseObject()
protected $responseObject; {
return $this->responseObject;
public function __construct($message="", $code=0, $responseHeaders=null, $responseBody=null) { }
parent::__construct($message, $code);
$this->responseHeaders = $responseHeaders;
$this->responseBody = $responseBody;
}
/**
* Get the HTTP response header
*
* @return string HTTP response header
*/
public function getResponseHeaders() {
return $this->responseHeaders;
}
/**
* Get the HTTP response body
*
* @return string HTTP response body
*/
public function getResponseBody() {
return $this->responseBody;
}
/**
* sets the deseralized response object (during deserialization)
* @param mixed $obj
*/
public function setResponseObject($obj) {
$this->responseObject = $obj;
}
public function getResponseObject() {
return $this->responseObject;
}
} }

View File

@ -1,47 +1,95 @@
<?php <?php
/**
* ObjectSerializer
*
* PHP version 5
*
* @category Class
* @package {{invokerPackage}}
* @author http://github.com/swagger-api/swagger-codegen
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache Licene v2
* @link https://github.com/swagger-api/swagger-codegen
*/
/**
* Copyright 2015 SmartBear Software
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen
* Do not edit the class manually.
*/
namespace {{invokerPackage}}; namespace {{invokerPackage}};
class ObjectSerializer { /**
* ObjectSerializer Class Doc Comment
*
* @category Class
* @package {{invokerPackage}}
* @author http://github.com/swagger-api/swagger-codegen
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache Licene v2
* @link https://github.com/swagger-api/swagger-codegen
*/
class ObjectSerializer
{
/** /**
* Build a JSON POST object * Build a JSON POST object
*
* @param mixed $data the data to serialize * @param mixed $data the data to serialize
*
* @return string serialized form of $data * @return string serialized form of $data
*/ */
public function sanitizeForSerialization($data) { public function sanitizeForSerialization($data)
if (is_scalar($data) || null === $data) { {
$sanitized = $data; if (is_scalar($data) || null === $data) {
} else if ($data instanceof \DateTime) { $sanitized = $data;
$sanitized = $data->format(\DateTime::ISO8601); } else if ($data instanceof \DateTime) {
} else if (is_array($data)) { $sanitized = $data->format(\DateTime::ISO8601);
foreach ($data as $property => $value) { } else if (is_array($data)) {
$data[$property] = $this->sanitizeForSerialization($value); 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) {
$getter = $data::$getters[$property];
if ($data->$getter() !== null) {
$values[$data::$attributeMap[$property]] = $this->sanitizeForSerialization($data->$getter());
}
}
$sanitized = $values;
} else {
$sanitized = (string)$data;
} }
$sanitized = $data;
} else if (is_object($data)) {
$values = array();
foreach (array_keys($data::$swaggerTypes) as $property) {
$getter = $data::$getters[$property];
if ($data->$getter() !== null) {
$values[$data::$attributeMap[$property]] = $this->sanitizeForSerialization($data->$getter());
}
}
$sanitized = $values;
} else {
$sanitized = (string)$data;
}
return $sanitized; return $sanitized;
} }
/** /**
* Take value and turn it into a string suitable for inclusion in * Take value and turn it into a string suitable for inclusion in
* the path, by url-encoding. * the path, by url-encoding.
*
* @param string $value a string which will be part of the path * @param string $value a string which will be part of the path
*
* @return string the serialized object * @return string the serialized object
*/ */
public function toPathValue($value) { public function toPathValue($value)
return rawurlencode($this->toString($value)); {
return rawurlencode($this->toString($value));
} }
/** /**
@ -49,103 +97,133 @@ class ObjectSerializer {
* the query, by imploding comma-separated if it's an object. * the query, by imploding comma-separated if it's an object.
* If it's a string, pass through unchanged. It will be url-encoded * If it's a string, pass through unchanged. It will be url-encoded
* later. * later.
*
* @param object $object an object to be serialized to a string * @param object $object an object to be serialized to a string
*
* @return string the serialized object * @return string the serialized object
*/ */
public function toQueryValue($object) { public function toQueryValue($object)
if (is_array($object)) { {
return implode(',', $object); if (is_array($object)) {
} else { return implode(',', $object);
return $this->toString($object); } else {
} return $this->toString($object);
}
} }
/** /**
* Take value and turn it into a string suitable for inclusion in * Take value and turn it into a string suitable for inclusion in
* the header. If it's a string, pass through unchanged * the header. If it's a string, pass through unchanged
* If it's a datetime object, format it in ISO8601 * If it's a datetime object, format it in ISO8601
*
* @param string $value a string which will be part of the header * @param string $value a string which will be part of the header
*
* @return string the header string * @return string the header string
*/ */
public function toHeaderValue($value) { public function toHeaderValue($value)
return $this->toString($value); {
return $this->toString($value);
} }
/** /**
* Take value and turn it into a string suitable for inclusion in * Take value and turn it into a string suitable for inclusion in
* the http body (form parameter). If it's a string, pass through unchanged * the http body (form parameter). If it's a string, pass through unchanged
* If it's a datetime object, format it in ISO8601 * If it's a datetime object, format it in ISO8601
*
* @param string $value the value of the form parameter * @param string $value the value of the form parameter
*
* @return string the form string * @return string the form string
*/ */
public function toFormValue($value) { public function toFormValue($value)
return $this->toString($value); {
if ($value instanceof SplFileObject) {
return $value->getRealPath();
} else {
return $this->toString($value);
}
} }
/** /**
* Take value and turn it into a string suitable for inclusion in * Take value and turn it into a string suitable for inclusion in
* the parameter. If it's a string, pass through unchanged * the parameter. If it's a string, pass through unchanged
* If it's a datetime object, format it in ISO8601 * If it's a datetime object, format it in ISO8601
*
* @param string $value the value of the parameter * @param string $value the value of the parameter
*
* @return string the header string * @return string the header string
*/ */
public function toString($value) { public function toString($value)
if ($value instanceof \DateTime) { // datetime in ISO8601 format {
return $value->format(\DateTime::ISO8601); if ($value instanceof \DateTime) { // datetime in ISO8601 format
} else { return $value->format(\DateTime::ISO8601);
return $value; } else {
} return $value;
}
} }
/** /**
* Deserialize a JSON string into an object * Deserialize a JSON string into an object
* *
* @param mixed $data object or primitive to be deserialized * @param mixed $data object or primitive to be deserialized
* @param string $class class name is passed as a string * @param string $class class name is passed as a string
* @param string $httpHeader HTTP headers
*
* @return object an instance of $class * @return object an instance of $class
*/ */
public function deserialize($data, $class) { public function deserialize($data, $class, $httpHeader=null)
if (null === $data) { {
$deserialized = null; if (null === $data) {
} elseif (substr($class, 0, 4) == 'map[') { # for associative array e.g. map[string,int] $deserialized = null;
$inner = substr($class, 4, -1); } elseif (substr($class, 0, 4) === 'map[') { // for associative array e.g. map[string,int]
$deserialized = array(); $inner = substr($class, 4, -1);
if(strrpos($inner, ",") !== false) { $deserialized = array();
$subClass_array = explode(',', $inner, 2); if (strrpos($inner, ",") !== false) {
$subClass = $subClass_array[1]; $subClass_array = explode(',', $inner, 2);
foreach ($data as $key => $value) { $subClass = $subClass_array[1];
$deserialized[$key] = $this->deserialize($value, $subClass); foreach ($data as $key => $value) {
} $deserialized[$key] = $this->deserialize($value, $subClass);
}
}
} elseif (strcasecmp(substr($class, -2), '[]') == 0) {
$subClass = substr($class, 0, -2);
$values = array();
foreach ($data as $key => $value) {
$values[] = $this->deserialize($value, $subClass);
}
$deserialized = $values;
} elseif ($class === 'DateTime') {
$deserialized = new \DateTime($data);
} elseif (in_array($class, array('string', 'int', 'float', 'double', 'bool', 'object'))) {
settype($data, $class);
$deserialized = $data;
} elseif ($class === '\SplFileObject') {
// determine file name
if (preg_match('/Content-Disposition: inline; filename=[\'"]?([^\'"\s]+)[\'"]?$/i', $httpHeader, $match)) {
$filename = Configuration::getDefaultConfiguration()->getTempFolderPath().$match[1];
} else {
$filename = tempnam(Configuration::getDefaultConfiguration()->getTempFolderPath(), '');
}
$deserialized = new \SplFileObject($filename, "w");
$byte_written = $deserialized->fwrite($data);
error_log("[INFO] Written $byte_written byte to $filename. Please move the file to a proper folder or delete the temp file after processing.\n", 3, Configuration::getDefaultConfiguration()->getDebugFile());
} else {
$instance = new $class();
foreach ($instance::$swaggerTypes as $property => $type) {
$propertySetter = $instance::$setters[$property];
if (!isset($propertySetter) || !isset($data->{$instance::$attributeMap[$property]})) {
continue;
}
$propertyValue = $data->{$instance::$attributeMap[$property]};
if (isset($propertyValue)) {
$instance->$propertySetter($this->deserialize($propertyValue, $type));
}
}
$deserialized = $instance;
} }
} elseif (strcasecmp(substr($class, -2),'[]') == 0) {
$subClass = substr($class, 0, -2); return $deserialized;
$values = array();
foreach ($data as $key => $value) {
$values[] = $this->deserialize($value, $subClass);
}
$deserialized = $values;
} elseif ($class == 'DateTime') {
$deserialized = new \DateTime($data);
} elseif (in_array($class, array('string', 'int', 'float', 'double', 'bool', 'object'))) {
settype($data, $class);
$deserialized = $data;
} else {
$instance = new $class();
foreach ($instance::$swaggerTypes as $property => $type) {
$propertySetter = $instance::$setters[$property];
if (!isset($propertySetter) || !isset($data->{$instance::$attributeMap[$property]})) {
continue;
}
$propertyValue = $data->{$instance::$attributeMap[$property]};
if (isset($propertyValue)) {
$instance->$propertySetter($this->deserialize($propertyValue, $type));
}
}
$deserialized = $instance;
}
return $deserialized;
} }
} }

View File

@ -1,4 +1,14 @@
<?php <?php
/**
* {{classname}}
* PHP version 5
*
* @category Class
* @package {{invokerPackage}}
* @author http://github.com/swagger-api/swagger-codegen
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache Licene v2
* @link https://github.com/swagger-api/swagger-codegen
*/
/** /**
* Copyright 2015 SmartBear Software * Copyright 2015 SmartBear Software
* *
@ -16,8 +26,9 @@
*/ */
/** /**
* * NOTE: This class is auto generated by the swagger code generator program.
* NOTE: This class is auto generated by the swagger code generator program. Do not edit the class manually. * https://github.com/swagger-api/swagger-codegen
* Do not edit the class manually.
*/ */
namespace {{apiPackage}}; namespace {{apiPackage}};
@ -27,135 +38,156 @@ use \{{invokerPackage}}\ApiClient;
use \{{invokerPackage}}\ApiException; use \{{invokerPackage}}\ApiException;
use \{{invokerPackage}}\ObjectSerializer; use \{{invokerPackage}}\ObjectSerializer;
{{#operations}} /**
class {{classname}} { * {{classname}} Class Doc Comment
*
* @category Class
* @package {{invokerPackage}}
* @author http://github.com/swagger-api/swagger-codegen
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache Licene v2
* @link https://github.com/swagger-api/swagger-codegen
*/
{{#operations}}class {{classname}}
{
/** @var \{{invokerPackage}}\ApiClient instance of the ApiClient */ /**
private $apiClient; * API Client
* @var \{{invokerPackage}}\ApiClient instance of the ApiClient
/** */
* @param \{{invokerPackage}}\ApiClient|null $apiClient The api client to use protected $apiClient;
*/
function __construct($apiClient = null) { /**
if ($apiClient == null) { * Constructor
$apiClient = new ApiClient(); * @param \{{invokerPackage}}\ApiClient|null $apiClient The api client to use
$apiClient->getConfig()->setHost('{{basePath}}'); */
} function __construct($apiClient = null)
{
$this->apiClient = $apiClient; if ($apiClient == null) {
} $apiClient = new ApiClient();
$apiClient->getConfig()->setHost('{{basePath}}');
/**
* @return \{{invokerPackage}}\ApiClient get the API client
*/
public function getApiClient() {
return $this->apiClient;
}
/**
* @param \{{invokerPackage}}\ApiClient $apiClient set the API client
* @return {{classname}}
*/
public function setApiClient(ApiClient $apiClient) {
$this->apiClient = $apiClient;
return $this;
}
{{#operation}}
/**
* {{{nickname}}}
*
* {{{summary}}}
*
{{#allParams}} * @param {{dataType}} ${{paramName}} {{description}} {{^optional}}(required){{/optional}}{{#optional}}(optional){{/optional}}
{{/allParams}} * @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}
* @throws \{{invokerPackage}}\ApiException on non-2xx response
*/
public function {{nickname}}({{#allParams}}${{paramName}}{{#optional}}=null{{/optional}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) {
{{#allParams}}{{#required}}
// verify the required parameter '{{paramName}}' is set
if (${{paramName}} === null) {
throw new \InvalidArgumentException('Missing the required parameter ${{paramName}} when calling {{nickname}}');
}
{{/required}}{{/allParams}}
// parse inputs
$resourcePath = "{{path}}";
$resourcePath = str_replace("{format}", "json", $resourcePath);
$method = "{{httpMethod}}";
$httpBody = '';
$queryParams = array();
$headerParams = array();
$formParams = array();
$_header_accept = ApiClient::selectHeaderAccept(array({{#produces}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/produces}}));
if (!is_null($_header_accept)) {
$headerParams['Accept'] = $_header_accept;
}
$headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array({{#consumes}}'{{mediaType}}'{{#hasMore}},{{/hasMore}}{{/consumes}}));
{{#queryParams}}// query params
if(${{paramName}} !== null) {
$queryParams['{{baseName}}'] = $this->apiClient->getSerializer()->toQueryValue(${{paramName}});
}{{/queryParams}}
{{#headerParams}}// header params
if(${{paramName}} !== null) {
$headerParams['{{baseName}}'] = $this->apiClient->getSerializer()->toHeaderValue(${{paramName}});
}{{/headerParams}}
{{#pathParams}}// path params
if(${{paramName}} !== null) {
$resourcePath = str_replace("{" . "{{baseName}}" . "}",
$this->apiClient->getSerializer()->toPathValue(${{paramName}}),
$resourcePath);
}{{/pathParams}}
{{#formParams}}// form params
if (${{paramName}} !== null) {
$formParams['{{baseName}}'] = {{#isFile}}'@' . {{/isFile}}$this->apiClient->getSerializer()->toFormValue(${{paramName}});
}{{/formParams}}
{{#bodyParams}}// body params
$_tempBody = null;
if (isset(${{paramName}})) {
$_tempBody = ${{paramName}};
}{{/bodyParams}}
// for model (json/xml)
if (isset($_tempBody)) {
$httpBody = $_tempBody; // $_tempBody is the method argument, if present
} else if (count($formParams) > 0) {
// for HTTP post (form)
$httpBody = $formParams;
}
{{#authMethods}}{{#isApiKey}}
$apiKey = $this->apiClient->getApiKeyWithPrefix('{{keyParamName}}');
if (isset($apiKey)) {
{{#isKeyInHeader}}$headerParams['{{keyParamName}}'] = $apiKey;{{/isKeyInHeader}}{{#isKeyInQuery}}$queryParams['{{keyParamName}}'] = $apiKey;{{/isKeyInQuery}}
}{{/isApiKey}}
{{#isBasic}}$headerParams['Authorization'] = 'Basic '.base64_encode($this->apiClient->getConfig()->getUsername().":".$this->apiClient->getConfig()->getPassword());{{/isBasic}}
{{#isOAuth}}//TODO support oauth{{/isOAuth}}
{{/authMethods}}
// make the API Call
try {
$response = $this->apiClient->callAPI($resourcePath, $method,
$queryParams, $httpBody,
$headerParams);
} catch (ApiException $e) {
switch ($e->getCode()) { {{#responses}}{{#dataType}}
case {{code}}:
$data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '{{dataType}}');
$e->setResponseObject($data);
break;{{/dataType}}{{/responses}}
} }
throw $e; $this->apiClient = $apiClient;
} }
{{#returnType}}
if (!$response) { /**
return null; * Get API client
} * @return \{{invokerPackage}}\ApiClient get the API client
*/
$responseObject = $this->apiClient->getSerializer()->deserialize($response,'{{returnType}}'); public function getApiClient()
return $responseObject; {
{{/returnType}} return $this->apiClient;
} }
{{/operation}}
/**
* Set the API client
* @param \{{invokerPackage}}\ApiClient $apiClient set the API client
* @return {{classname}}
*/
public function setApiClient(ApiClient $apiClient)
{
$this->apiClient = $apiClient;
return $this;
}
{{#operation}}
/**
* {{{nickname}}}
*
* {{{summary}}}
*
{{#allParams}} * @param {{dataType}} ${{paramName}} {{description}} {{#required}}(required){{/required}}{{^required}}(optional){{/required}}
{{/allParams}} * @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}
* @throws \{{invokerPackage}}\ApiException on non-2xx response
*/
public function {{nickname}}({{#allParams}}${{paramName}}{{^required}}=null{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}})
{
{{#allParams}}{{#required}}
// verify the required parameter '{{paramName}}' is set
if (${{paramName}} === null) {
throw new \InvalidArgumentException('Missing the required parameter ${{paramName}} when calling {{nickname}}');
}{{/required}}{{/allParams}}
// parse inputs
$resourcePath = "{{path}}";
$resourcePath = str_replace("{format}", "json", $resourcePath);
$method = "{{httpMethod}}";
$httpBody = '';
$queryParams = array();
$headerParams = array();
$formParams = array();
$_header_accept = ApiClient::selectHeaderAccept(array({{#produces}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/produces}}));
if (!is_null($_header_accept)) {
$headerParams['Accept'] = $_header_accept;
}
$headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array({{#consumes}}'{{mediaType}}'{{#hasMore}},{{/hasMore}}{{/consumes}}));
{{#queryParams}}// query params
if (${{paramName}} !== null) {
$queryParams['{{baseName}}'] = $this->apiClient->getSerializer()->toQueryValue(${{paramName}});
}{{/queryParams}}
{{#headerParams}}// header params
if (${{paramName}} !== null) {
$headerParams['{{baseName}}'] = $this->apiClient->getSerializer()->toHeaderValue(${{paramName}});
}{{/headerParams}}
{{#pathParams}}// path params
if (${{paramName}} !== null) {
$resourcePath = str_replace(
"{" . "{{baseName}}" . "}",
$this->apiClient->getSerializer()->toPathValue(${{paramName}}),
$resourcePath
);
}{{/pathParams}}
{{#formParams}}// form params
if (${{paramName}} !== null) {
$formParams['{{baseName}}'] = {{#isFile}}'@' . {{/isFile}}$this->apiClient->getSerializer()->toFormValue(${{paramName}});
}{{/formParams}}
{{#bodyParams}}// body params
$_tempBody = null;
if (isset(${{paramName}})) {
$_tempBody = ${{paramName}};
}{{/bodyParams}}
// for model (json/xml)
if (isset($_tempBody)) {
$httpBody = $_tempBody; // $_tempBody is the method argument, if present
} else if (count($formParams) > 0) {
$httpBody = $formParams; // for HTTP post (form)
}
{{#authMethods}}{{#isApiKey}}
$apiKey = $this->apiClient->getApiKeyWithPrefix('{{keyParamName}}');
if (isset($apiKey)) {
{{#isKeyInHeader}}$headerParams['{{keyParamName}}'] = $apiKey;{{/isKeyInHeader}}{{#isKeyInQuery}}$queryParams['{{keyParamName}}'] = $apiKey;{{/isKeyInQuery}}
}{{/isApiKey}}
{{#isBasic}}$headerParams['Authorization'] = 'Basic '.base64_encode($this->apiClient->getConfig()->getUsername().":".$this->apiClient->getConfig()->getPassword());{{/isBasic}}
{{#isOAuth}}//TODO support oauth{{/isOAuth}}
{{/authMethods}}
// make the API Call
try
{
list($response, $httpHeader) = $this->apiClient->callApi(
$resourcePath, $method,
$queryParams, $httpBody,
$headerParams{{#returnType}}, '{{returnType}}'{{/returnType}}
);
} catch (ApiException $e) {
switch ($e->getCode()) { {{#responses}}{{#dataType}}
case {{code}}:
$data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '{{dataType}}', $httpHeader);
$e->setResponseObject($data);
break;{{/dataType}}{{/responses}}
}
throw $e;
}
{{#returnType}}
if (!$response) {
return null;
}
return $this->apiClient->getSerializer()->deserialize($response, '{{returnType}}');
{{/returnType}}
}
{{/operation}}
} }
{{/operations}} {{/operations}}

View File

@ -1,33 +1,33 @@
{ {
"name": "{{groupId}}/{{artifactId}}",{{#artifactVersion}} "name": "{{composerVendorName}}/{{composerProjectName}}",{{#artifactVersion}}
"version": "{{artifactVersion}}",{{/artifactVersion}} "version": "{{artifactVersion}}",{{/artifactVersion}}
"description": "{{description}}", "description": "{{description}}",
"keywords": [ "keywords": [
"swagger", "swagger",
"php", "php",
"sdk", "sdk",
"api" "api"
], ],
"homepage": "http://swagger.io", "homepage": "http://swagger.io",
"license": "Apache v2", "license": "Apache v2",
"authors": [ "authors": [
{ {
"name": "Swagger and contributors", "name": "Swagger and contributors",
"homepage": "https://github.com/swagger-api/swagger-codegen" "homepage": "https://github.com/swagger-api/swagger-codegen"
}
],
"require": {
"php": ">=5.3.3",
"ext-curl": "*",
"ext-json": "*",
"ext-mbstring": "*"
},
"require-dev": {
"phpunit/phpunit": "~4.0",
"satooshi/php-coveralls": "~0.6.1",
"squizlabs/php_codesniffer": "~2.0"
},
"autoload": {
"psr-4": { "{{escapedInvokerPackage}}\\" : "{{srcBasePath}}/" }
} }
],
"require": {
"php": ">=5.3.3",
"ext-curl": "*",
"ext-json": "*",
"ext-mbstring": "*"
},
"require-dev": {
"phpunit/phpunit": "~4.0",
"satooshi/php-coveralls": "~0.6.1",
"squizlabs/php_codesniffer": "~2.0"
},
"autoload": {
"psr-4": { "{{escapedInvokerPackage}}\\" : "{{srcBasePath}}/" }
}
} }

View File

@ -1,4 +1,15 @@
<?php <?php
/**
* Configuration
* PHP version 5
*
* @category Class
* @package {{invokerPackage}}
* @author http://github.com/swagger-api/swagger-codegen
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache Licene v2
* @link https://github.com/swagger-api/swagger-codegen
*/
/** /**
* Copyright 2015 SmartBear Software * Copyright 2015 SmartBear Software
* *
@ -15,252 +26,439 @@
* limitations under the License. * limitations under the License.
*/ */
/**
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen
* Do not edit the class manually.
*/
namespace {{invokerPackage}}; namespace {{invokerPackage}};
class Configuration { /**
* Configuration Class Doc Comment
* PHP version 5
*
* @category Class
* @package {{invokerPackage}}
* @author http://github.com/swagger-api/swagger-codegen
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache Licene v2
* @link https://github.com/swagger-api/swagger-codegen
*/
class Configuration
{
private static $defaultConfiguration = null; private static $_defaultConfiguration = null;
/**
* Associate array to store API key(s)
*
* @var string[]
*/
protected $apiKeys = array();
/**
* Associate array to store API prefix (e.g. Bearer)
*
* @var string[]
*/
protected $apiKeyPrefixes = array();
/**
* Username for HTTP basic authentication
*
* @var string
*/
protected $username = '';
/**
* Password for HTTP basic authentication
*
* @var string
*/
protected $password = '';
/**
* The default instance of ApiClient
*
* @var \{{invokerPackage}}\ApiClient
*/
protected $defaultHeaders = array();
/**
* The host
*
* @var string
*/
protected $host = 'http://localhost';
/**
* Timeout (second) of the HTTP request, by default set to 0, no timeout
*
* @var string
*/
protected $curlTimeout = 0;
/**
* User agent of the HTTP request, set to "PHP-Swagger" by default
*
* @var string
*/
protected $userAgent = "PHP-Swagger";
/**
* Debug switch (default set to false)
*
* @var bool
*/
protected $debug = false;
/**
* Debug file location (log to STDOUT by default)
*
* @var string
*/
protected $debugFile = 'php://output';
/** @var string[] Associate array to store API key(s) */ /**
protected $apiKeys = array(); * Debug file location (log to STDOUT by default)
*
* @var string
*/
protected $tempFolderPath;
/** string[] Associate array to store API prefix (e.g. Bearer) */ /**
protected $apiKeyPrefixes = array(); * Constructor
*/
/** @var string Username for HTTP basic authentication */ public function __construct()
protected $username = ''; {
$this->tempFolderPath = sys_get_temp_dir();
/** @var string Password for HTTP basic authentication */
protected $password = '';
/** @var \{{invokerPackage}}\ApiClient The default instance of ApiClient */
protected $defaultHeaders = array();
/** @var string The host */
protected $host = 'http://localhost';
/** @var string timeout (second) of the HTTP request, by default set to 0, no timeout */
protected $curlTimeout = 0;
/** @var string user agent of the HTTP request, set to "PHP-Swagger" by default */
protected $userAgent = "PHP-Swagger";
/** @var bool Debug switch (default set to false) */
protected $debug = false;
/** @var string Debug file location (log to STDOUT by default) */
protected $debugFile = 'php://output';
/**
* @param string $key
* @param string $value
* @return Configuration
*/
public function setApiKey($key, $value) {
$this->apiKeys[$key] = $value;
return $this;
}
/**
* @param $key
* @return string
*/
public function getApiKey($key) {
return isset($this->apiKeys[$key]) ? $this->apiKeys[$key] : null;
}
/**
* @param string $key
* @param string $value
* @return Configuration
*/
public function setApiKeyPrefix($key, $value) {
$this->apiKeyPrefixes[$key] = $value;
return $this;
}
/**
* @param $key
* @return string
*/
public function getApiKeyPrefix($key) {
return isset($this->apiKeyPrefixes[$key]) ? $this->apiKeyPrefixes[$key] : null;
}
/**
* @param string $username
* @return Configuration
*/
public function setUsername($username) {
$this->username = $username;
return $this;
}
/**
* @return string
*/
public function getUsername() {
return $this->username;
}
/**
* @param string $password
* @return Configuration
*/
public function setPassword($password) {
$this->password = $password;
return $this;
}
/**
* @return string
*/
public function getPassword() {
return $this->password;
}
/**
* add default header
*
* @param string $headerName header name (e.g. Token)
* @param string $headerValue header value (e.g. 1z8wp3)
* @return ApiClient
*/
public function addDefaultHeader($headerName, $headerValue) {
if (!is_string($headerName)) {
throw new \InvalidArgumentException('Header name must be a string.');
} }
$this->defaultHeaders[$headerName] = $headerValue; /**
return $this; * Sets API key
} *
* @param string $apiKeyIdentifier API key identifier (authentication scheme)
/** * @param string $key API key or token
* get the default header *
* * @return Configuration
* @return array default header */
*/ public function setApiKey($apiKeyIdentifier, $key)
public function getDefaultHeaders() { {
return $this->defaultHeaders; $this->apiKeys[$apiKeyIdentifier] = $key;
} return $this;
/**
* delete a default header
* @param string $headerName the header to delete
* @return Configuration
*/
public function deleteDefaultHeader($headerName) {
unset($this->defaultHeaders[$headerName]);
}
/**
* @param string $host
* @return Configuration
*/
public function setHost($host) {
$this->host = $host;
return $this;
}
/**
* @return string
*/
public function getHost() {
return $this->host;
}
/**
* set the user agent of the api client
*
* @param string $userAgent the user agent of the api client
* @return ApiClient
*/
public function setUserAgent($userAgent) {
if (!is_string($userAgent)) {
throw new \InvalidArgumentException('User-agent must be a string.');
} }
$this->userAgent = $userAgent; /**
return $this; * Gets API key
} *
* @param string $apiKeyIdentifier API key identifier (authentication scheme)
/** *
* get the user agent of the api client * @return string API key or token
* */
* @return string user agent public function getApiKey($apiKeyIdentifier)
*/ {
public function getUserAgent() { return isset($this->apiKeys[$apiKeyIdentifier]) ? $this->apiKeys[$apiKeyIdentifier] : null;
return $this->userAgent;
}
/**
* set the HTTP timeout value
*
* @param integer $seconds Number of seconds before timing out [set to 0 for no timeout]
* @return ApiClient
*/
public function setCurlTimeout($seconds) {
if (!is_numeric($seconds) || $seconds < 0) {
throw new \InvalidArgumentException('Timeout value must be numeric and a non-negative number.');
} }
$this->curlTimeout = $seconds; /**
return $this; * Sets the prefix for API key (e.g. Bearer)
} *
* @param string $apiKeyIdentifier API key identifier (authentication scheme)
/** * @param string $prefix API key prefix, e.g. Bearer
* get the HTTP timeout value *
* * @return Configuration
* @return string HTTP timeout value */
*/ public function setApiKeyPrefix($apiKeyIdentifier, $prefix)
public function getCurlTimeout() { {
return $this->curlTimeout; $this->apiKeyPrefixes[$apiKeyIdentifier] = $prefix;
} return $this;
/**
* @param bool $debug
* @return Configuration
*/
public function setDebug($debug) {
$this->debug = $debug;
return $this;
}
/**
* @return bool
*/
public function getDebug() {
return $this->debug;
}
/**
* @param string $debugFile
* @return Configuration
*/
public function setDebugFile($debugFile) {
$this->debugFile = $debugFile;
return $this;
}
/**
* @return string
*/
public function getDebugFile() {
return $this->debugFile;
}
/**
* @return Configuration
*/
public static function getDefaultConfiguration() {
if (self::$defaultConfiguration == null) {
return new Configuration();
} }
return self::$defaultConfiguration; /**
} * Gets API key prefix
*
public static function setDefaultConfiguration(Configuration $config) { * @param string $apiKeyIdentifier API key identifier (authentication scheme)
self::$defaultConfiguration = $config; *
} * @return string
*/
public function getApiKeyPrefix($apiKeyIdentifier)
{
return isset($this->apiKeyPrefixes[$apiKeyIdentifier]) ? $this->apiKeyPrefixes[$apiKeyIdentifier] : null;
}
/**
* Sets the username for HTTP basic authentication
*
* @param string $username Username for HTTP basic authentication
*
* @return Configuration
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Gets the username for HTTP basic authentication
*
* @return string Username for HTTP basic authentication
*/
public function getUsername()
{
return $this->username;
}
/**
* Sets the password for HTTP basic authentication
*
* @param string $password Password for HTTP basic authentication
*
* @return Configuration
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Gets the password for HTTP basic authentication
*
* @return string Password for HTTP basic authentication
*/
public function getPassword()
{
return $this->password;
}
/**
* Adds a default header
*
* @param string $headerName header name (e.g. Token)
* @param string $headerValue header value (e.g. 1z8wp3)
*
* @return ApiClient
*/
public function addDefaultHeader($headerName, $headerValue)
{
if (!is_string($headerName)) {
throw new \InvalidArgumentException('Header name must be a string.');
}
$this->defaultHeaders[$headerName] = $headerValue;
return $this;
}
/**
* Gets the default header
*
* @return array An array of default header(s)
*/
public function getDefaultHeaders()
{
return $this->defaultHeaders;
}
/**
* Deletes a default header
*
* @param string $headerName the header to delete
*
* @return Configuration
*/
public function deleteDefaultHeader($headerName)
{
unset($this->defaultHeaders[$headerName]);
}
/**
* Sets the host
*
* @param string $host Host
*
* @return Configuration
*/
public function setHost($host)
{
$this->host = $host;
return $this;
}
/**
* Gets the host
*
* @return string Host
*/
public function getHost()
{
return $this->host;
}
/**
* Sets the user agent of the api client
*
* @param string $userAgent the user agent of the api client
*
* @return ApiClient
*/
public function setUserAgent($userAgent)
{
if (!is_string($userAgent)) {
throw new \InvalidArgumentException('User-agent must be a string.');
}
$this->userAgent = $userAgent;
return $this;
}
/**
* Gets the user agent of the api client
*
* @return string user agent
*/
public function getUserAgent()
{
return $this->userAgent;
}
/**
* Sets the HTTP timeout value
*
* @param integer $seconds Number of seconds before timing out [set to 0 for no timeout]
*
* @return ApiClient
*/
public function setCurlTimeout($seconds)
{
if (!is_numeric($seconds) || $seconds < 0) {
throw new \InvalidArgumentException('Timeout value must be numeric and a non-negative number.');
}
$this->curlTimeout = $seconds;
return $this;
}
/**
* Gets the HTTP timeout value
*
* @return string HTTP timeout value
*/
public function getCurlTimeout()
{
return $this->curlTimeout;
}
/**
* Sets debug flag
*
* @param bool $debug Debug flag
*
* @return Configuration
*/
public function setDebug($debug)
{
$this->debug = $debug;
return $this;
}
/**
* Gets the debug flag
*
* @return bool
*/
public function getDebug()
{
return $this->debug;
}
/**
* Sets the debug file
*
* @param string $debugFile Debug file
*
* @return Configuration
*/
public function setDebugFile($debugFile)
{
$this->debugFile = $debugFile;
return $this;
}
/**
* Gets the debug file
*
* @return string
*/
public function getDebugFile()
{
return $this->debugFile;
}
/**
* Sets the temp folder path
*
* @param string $tempFolderPath Temp folder path
*
* @return Configuration
*/
public function setTempFolderPath($tempFolderPath)
{
$this->tempFolderPath = $tempFolderPath;
return $this;
}
/**
* Gets the temp folder path
*
* @return string Temp folder path
*/
public function getTempFolderPath()
{
return $this->tempFolderPath;
}
/**
* Gets the default configuration instance
*
* @return Configuration
*/
public static function getDefaultConfiguration()
{
if (self::$_defaultConfiguration == null) {
self::$_defaultConfiguration = new Configuration();
}
return self::$_defaultConfiguration;
}
/**
* Sets the detault configuration instance
*
* @param Configuration $config An instance of the Configuration Object
*
* @return void
*/
public static function setDefaultConfiguration(Configuration $config)
{
self::$_defaultConfiguration = $config;
}
/**
* Gets the essential information for debugging
*
* @return string The report for debugging
*/
public static function toDebugReport()
{
$report = "PHP SDK ({{invokerPackage}}) Debug Report:\n";
$report .= " OS: ".php_uname()."\n";
$report .= " PHP Version: ".phpversion()."\n";
$report .= " Swagger Spec Version: {{version}}\n";
$report .= " SDK Package Version: {{artifactVersion}}\n";
$report .= " Temp Folder Path: ".self::getDefaultConfiguration()->getTempFolderPath()."\n";
return $report;
}
} }

View File

@ -1,4 +1,17 @@
<?php <?php
{{#models}}
{{#model}}
/**
* {{classname}}
*
* PHP version 5
*
* @category Class
* @package {{invokerPackage}}
* @author http://github.com/swagger-api/swagger-codegen
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache Licene v2
* @link https://github.com/swagger-api/swagger-codegen
*/
/** /**
* Copyright 2015 SmartBear Software * Copyright 2015 SmartBear Software
* *
@ -14,97 +27,160 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
{{#models}}
{{#model}}
/** /**
* {{description}} * NOTE: This class is auto generated by the swagger code generator program.
* * https://github.com/swagger-api/swagger-codegen
* NOTE: This class is auto generated by the swagger code generator program. Do not edit the class manually. * Do not edit the class manually.
*
*/ */
namespace {{modelPackage}}; namespace {{modelPackage}};
use \ArrayAccess; use \ArrayAccess;
/**
* {{classname}} Class Doc Comment
*
* @category Class
* @description {{description}}
* @package {{invokerPackage}}
* @author http://github.com/swagger-api/swagger-codegen
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache Licene v2
* @link https://github.com/swagger-api/swagger-codegen
*/
class {{classname}} implements ArrayAccess
{
/**
* Array of property to type mappings. Used for (de)serialization
* @var string[]
*/
static $swaggerTypes = array(
{{#vars}}'{{name}}' => '{{{datatype}}}'{{#hasMore}},
{{/hasMore}}{{/vars}}
);
/**
* Array of attributes where the key is the local name, and the value is the original name
* @var string[]
*/
static $attributeMap = array(
{{#vars}}'{{name}}' => '{{baseName}}'{{#hasMore}},
{{/hasMore}}{{/vars}}
);
/**
* Array of attributes to setter functions (for deserialization of responses)
* @var string[]
*/
static $setters = array(
{{#vars}}'{{name}}' => '{{setter}}'{{#hasMore}},
{{/hasMore}}{{/vars}}
);
/**
* Array of attributes to getter functions (for serialization of requests)
* @var string[]
*/
static $getters = array(
{{#vars}}'{{name}}' => '{{getter}}'{{#hasMore}},
{{/hasMore}}{{/vars}}
);
{{#vars}}
/**
* ${{name}} {{#description}}{{{description}}}{{/description}}
* @var {{datatype}}
*/
protected ${{name}};
{{/vars}}
class {{classname}} implements ArrayAccess { /**
/** @var string[] Array of property to type mappings. Used for (de)serialization */ * Constructor
static $swaggerTypes = array( * @param mixed[] $data Associated array of property value initalizing the model
{{#vars}}'{{name}}' => '{{{datatype}}}'{{#hasMore}}, */
{{/hasMore}}{{/vars}} public function __construct(array $data = null)
); {
if ($data != null) {
/** @var string[] Array of attributes where the key is the local name, and the value is the original name */ {{#vars}}$this->{{name}} = $data["{{name}}"];{{#hasMore}}
static $attributeMap = array( {{/hasMore}}{{/vars}}
{{#vars}}'{{name}}' => '{{baseName}}'{{#hasMore}}, }
{{/hasMore}}{{/vars}}
);
/** @var string[] Array of attributes to setter functions (for deserialization of responses) */
static $setters = array(
{{#vars}}'{{name}}' => '{{setter}}'{{#hasMore}},
{{/hasMore}}{{/vars}}
);
/** @var string[] Array of attributes to getter functions (for serialization of requests) */
static $getters = array(
{{#vars}}'{{name}}' => '{{getter}}'{{#hasMore}},
{{/hasMore}}{{/vars}}
);
{{#vars}}
/** @var {{datatype}} ${{name}} {{#description}}{{{description}}} {{/description}}*/
protected ${{name}};
{{/vars}}
public function __construct(array $data = null) {
if ($data != null) {
{{#vars}}$this->{{name}} = $data["{{name}}"];{{#hasMore}}
{{/hasMore}}{{/vars}}
} }
} {{#vars}}
{{#vars}} /**
/** * Gets {{name}}
* get {{name}} * @return {{datatype}}
* @return {{datatype}} */
*/ public function {{getter}}()
public function {{getter}}() { {
return $this->{{name}}; return $this->{{name}};
} }
/** /**
* set {{name}} * Sets {{name}}
* @param {{datatype}} ${{name}} * @param {{datatype}} ${{name}} {{#description}}{{{description}}}{{/description}}
* @return $this * @return $this
*/ */
public function {{setter}}(${{name}}) { public function {{setter}}(${{name}})
$this->{{name}} = ${{name}}; {
return $this; {{#isEnum}}$allowed_values = array({{#allowableValues}}{{#values}}"{{{this}}}"{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}});
} if (!in_array(${{{name}}}, $allowed_values)) {
{{/vars}} throw new \InvalidArgumentException("Invalid value for '{{name}}', must be one of {{#allowableValues}}{{#values}}'{{{this}}}'{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}");
public function offsetExists($offset) { }{{/isEnum}}
return isset($this->$offset); $this->{{name}} = ${{name}};
} return $this;
}
public function offsetGet($offset) { {{/vars}}
return $this->$offset; /**
} * Returns true if offset exists. False otherwise.
* @param integer $offset Offset
public function offsetSet($offset, $value) { * @return boolean
$this->$offset = $value; */
} public function offsetExists($offset)
{
public function offsetUnset($offset) { return isset($this->$offset);
unset($this->$offset); }
}
/**
public function __toString() { * Gets offset.
if (defined('JSON_PRETTY_PRINT')) { * @param integer $offset Offset
return json_encode($this, JSON_PRETTY_PRINT); * @return mixed
} else { */
return json_encode($this); public function offsetGet($offset)
{
return $this->$offset;
}
/**
* Sets value based on offset.
* @param integer $offset Offset
* @param mixed $value Value to be set
* @return void
*/
public function offsetSet($offset, $value)
{
$this->$offset = $value;
}
/**
* Unsets offset.
* @param integer $offset Offset
* @return void
*/
public function offsetUnset($offset)
{
unset($this->$offset);
}
/**
* Gets the string presentation of the object
* @return string
*/
public function __toString()
{
if (defined('JSON_PRETTY_PRINT')) {
return json_encode(get_object_vars($this), JSON_PRETTY_PRINT);
} else {
return json_encode(get_object_vars($this));
}
} }
}
} }
{{/model}} {{/model}}
{{/models}} {{/models}}

View File

@ -11,13 +11,13 @@ python setup.py install
Or you can install from Github via pip: Or you can install from Github via pip:
```sh ```sh
pip install git+https://github.com/geekerzp/SwaggerPetstore-python.git pip install git+https://github.com/geekerzp/swagger_client.git
``` ```
To use the bindings, import the pacakge: To use the bindings, import the pacakge:
```python ```python
import SwaggerPetstore import swagger_client
``` ```
## Manual Installation ## Manual Installation
@ -25,7 +25,7 @@ If you do not wish to use setuptools, you can download the latest release.
Then, to use the bindings, import the package: Then, to use the bindings, import the package:
```python ```python
import path.to.SwaggerPetstore-python.SwaggerPetstore import path.to.swagger_client
``` ```
## Getting Started ## Getting Started
@ -38,9 +38,9 @@ TODO
## Tests ## Tests
(Make sure you are running it inside of a [virtualenv](http://docs.python-guide.org/en/latest/dev/virtualenvs/)) (Please make sure you have [virtualenv](http://docs.python-guide.org/en/latest/dev/virtualenvs/) installed)
You can run the tests in the current python platform: Execute the following command to run the tests in the current Python (v2 or v3) environment:
```sh ```sh
$ make test $ make test
@ -71,4 +71,3 @@ $ make test-all
py34: commands succeeded py34: commands succeeded
congratulations :) congratulations :)
``` ```

View File

@ -8,3 +8,7 @@ from __future__ import absolute_import
{{/apis}}{{/apiInfo}} {{/apis}}{{/apiInfo}}
# import ApiClient # import ApiClient
from .api_client import ApiClient from .api_client import ApiClient
from .configuration import Configuration
configuration = Configuration()

View File

@ -27,19 +27,20 @@ import os
# python 2 and python 3 compatibility library # python 2 and python 3 compatibility library
from six import iteritems from six import iteritems
from .. import configuration from ..configuration import Configuration
from ..api_client import ApiClient from ..api_client import ApiClient
{{#operations}} {{#operations}}
class {{classname}}(object): class {{classname}}(object):
def __init__(self, api_client=None): def __init__(self, api_client=None):
config = Configuration()
if api_client: if api_client:
self.api_client = api_client self.api_client = api_client
else: else:
if not configuration.api_client: if not config.api_client:
configuration.api_client = ApiClient('{{basePath}}') config.api_client = ApiClient('{{basePath}}')
self.api_client = configuration.api_client self.api_client = config.api_client
{{#operation}} {{#operation}}
def {{nickname}}(self, {{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}**kwargs): def {{nickname}}(self, {{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}**kwargs):
@ -47,9 +48,18 @@ class {{classname}}(object):
{{{summary}}} {{{summary}}}
{{{notes}}} {{{notes}}}
SDK also supports asynchronous requests in which you can define a `callback` function
to be passed along and invoked when receiving response:
>>> def callback_function(response):
>>> pprint(response)
>>>
>>> thread = api.{{nickname}}({{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}callback=callback_function)
:param callback function: The callback function for asynchronous request. (optional)
{{#allParams}}:param {{dataType}} {{paramName}}: {{{description}}} {{#required}}(required){{/required}}{{#optional}}(optional){{/optional}} {{#allParams}}:param {{dataType}} {{paramName}}: {{{description}}} {{#required}}(required){{/required}}{{#optional}}(optional){{/optional}}
{{/allParams}} {{/allParams}}
:return: {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}None{{/returnType}} :return: {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}None{{/returnType}}
If the method is called asynchronously, returns the request thread.
""" """
{{#allParams}}{{#required}} {{#allParams}}{{#required}}
# verify the required parameter '{{paramName}}' is set # verify the required parameter '{{paramName}}' is set
@ -57,6 +67,7 @@ class {{classname}}(object):
raise ValueError("Missing the required parameter `{{paramName}}` when calling `{{nickname}}`") raise ValueError("Missing the required parameter `{{paramName}}` when calling `{{nickname}}`")
{{/required}}{{/allParams}} {{/required}}{{/allParams}}
all_params = [{{#allParams}}'{{paramName}}'{{#hasMore}}, {{/hasMore}}{{/allParams}}] all_params = [{{#allParams}}'{{paramName}}'{{#hasMore}}, {{/hasMore}}{{/allParams}}]
all_params.append('callback')
params = locals() params = locals()
for key, val in iteritems(params['kwargs']): for key, val in iteritems(params['kwargs']):
@ -107,17 +118,7 @@ class {{classname}}(object):
response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params, response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params,
body=body_params, post_params=form_params, files=files, body=body_params, post_params=form_params, files=files,
response={{#returnType}}'{{returnType}}'{{/returnType}}{{^returnType}}None{{/returnType}}, auth_settings=auth_settings) response_type={{#returnType}}'{{returnType}}'{{/returnType}}{{^returnType}}None{{/returnType}}, auth_settings=auth_settings, callback=params.get('callback'))
{{#returnType}}
return response return response
{{/returnType}}{{/operation}} {{/operation}}
{{/operations}} {{/operations}}

View File

@ -9,14 +9,19 @@ templates."""
from __future__ import absolute_import from __future__ import absolute_import
from . import models from . import models
from .rest import RESTClient from .rest import RESTClient
from .rest import ApiException
import os import os
import re import re
import urllib import urllib
import json import json
import datetime
import mimetypes import mimetypes
import random import random
import tempfile
import threading
from datetime import datetime
from datetime import date
# python 2 and python 3 compatibility library # python 2 and python 3 compatibility library
from six import iteritems from six import iteritems
@ -28,7 +33,7 @@ except ImportError:
# for python2 # for python2
from urllib import quote from urllib import quote
from . import configuration from .configuration import Configuration
class ApiClient(object): class ApiClient(object):
""" """
@ -38,7 +43,7 @@ class ApiClient(object):
:param header_name: a header to pass when making calls to the API :param header_name: a header to pass when making calls to the API
:param header_value: a header value to pass when making calls to the API :param header_value: a header value to pass when making calls to the API
""" """
def __init__(self, host=configuration.host, header_name=None, header_value=None): def __init__(self, host=Configuration().host, header_name=None, header_value=None):
self.default_headers = {} self.default_headers = {}
if header_name is not None: if header_name is not None:
self.default_headers[header_name] = header_value self.default_headers[header_name] = header_value
@ -58,8 +63,8 @@ class ApiClient(object):
def set_default_header(self, header_name, header_value): def set_default_header(self, header_name, header_value):
self.default_headers[header_name] = header_value self.default_headers[header_name] = header_value
def call_api(self, resource_path, method, path_params=None, query_params=None, header_params=None, def __call_api(self, resource_path, method, path_params=None, query_params=None, header_params=None,
body=None, post_params=None, files=None, response=None, auth_settings=None): body=None, post_params=None, files=None, response_type=None, auth_settings=None, callback=None):
# headers parameters # headers parameters
header_params = header_params or {} header_params = header_params or {}
@ -100,11 +105,18 @@ class ApiClient(object):
response_data = self.request(method, url, query_params=query_params, headers=header_params, response_data = self.request(method, url, query_params=query_params, headers=header_params,
post_params=post_params, body=body) post_params=post_params, body=body)
self.last_response = response_data
# deserialize response data # deserialize response data
if response: if response_type:
return self.deserialize(response_data, response) deserialized_data = self.deserialize(response_data, response_type)
else: else:
return None deserialized_data = None
if callback:
callback(deserialized_data)
else:
return deserialized_data
def to_path_value(self, obj): def to_path_value(self, obj):
""" """
@ -136,7 +148,7 @@ class ApiClient(object):
return obj return obj
elif isinstance(obj, list): elif isinstance(obj, list):
return [self.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)): elif isinstance(obj, (datetime, date)):
return obj.isoformat() return obj.isoformat()
else: else:
if isinstance(obj, dict): if isinstance(obj, dict):
@ -151,84 +163,106 @@ class ApiClient(object):
return {key: self.sanitize_for_serialization(val) return {key: self.sanitize_for_serialization(val)
for key, val in iteritems(obj_dict)} for key, val in iteritems(obj_dict)}
def deserialize(self, obj, obj_class): def deserialize(self, response, response_type):
""" """
Derialize a JSON string into an object. Derialize response into an object.
:param obj: string or object to be deserialized :param response: RESTResponse object to be deserialized
:param obj_class: class literal for deserialzied object, or string of class name :param response_type: class literal for deserialzied object, or string of class name
:return object: deserialized object :return: deserialized object
""" """
# Have to accept obj_class as string or actual type. Type could be a # handle file downloading - save response body into a tmp file and return the instance
# native Python type, or one of the model classes. if "file" == response_type:
if type(obj_class) == str: return self.__deserialize_file(response)
if 'list[' in obj_class:
match = re.match('list\[(.*)\]', obj_class)
sub_class = match.group(1)
return [self.deserialize(sub_obj, sub_class) for sub_obj in obj]
if 'dict(' in obj_class: # fetch data from response object
match = re.match('dict\((.*), (.*)\)', obj_class)
sub_class = match.group(2)
return {k: self.deserialize(v, sub_class) for k, v in iteritems(obj)}
if obj_class in ['int', 'float', 'dict', 'list', 'str', 'bool', 'datetime', "object"]:
obj_class = eval(obj_class)
else: # not a native type, must be model class
obj_class = eval('models.' + obj_class)
if obj_class in [int, float, dict, list, str, bool]:
return obj_class(obj)
elif obj_class == object:
return object()
elif obj_class == datetime:
return self.__parse_string_to_datetime(obj)
instance = obj_class()
for attr, attr_type in iteritems(instance.swagger_types):
if obj is not None and instance.attribute_map[attr] in obj and type(obj) in [list, dict]:
value = obj[instance.attribute_map[attr]]
if attr_type in ['str', 'int', 'float', 'bool']:
attr_type = eval(attr_type)
try:
value = attr_type(value)
except UnicodeEncodeError:
value = unicode(value)
except TypeError:
value = value
setattr(instance, attr, value)
elif attr_type == 'datetime':
setattr(instance, attr, self.__parse_string_to_datetime(value))
elif 'list[' in attr_type:
match = re.match('list\[(.*)\]', attr_type)
sub_class = match.group(1)
sub_values = []
if not value:
setattr(instance, attr, None)
else:
for sub_value in value:
sub_values.append(self.deserialize(sub_value, sub_class))
setattr(instance, attr, sub_values)
else:
setattr(instance, attr, self.deserialize(value, attr_type))
return instance
def __parse_string_to_datetime(self, string):
"""
Parse datetime in string to datetime.
The string should be in iso8601 datetime format.
"""
try: try:
from dateutil.parser import parse data = json.loads(response.data)
return parse(string) except ValueError:
except ImportError: data = response.data
return string
def request(self, method, url, query_params=None, headers=None, post_params=None, body=None): return self.__deserialize(data, response_type)
def __deserialize(self, data, klass):
"""
:param data: dict, list or str
:param klass: class literal, or string of class name
:return: object
"""
if data is None:
return None
if type(klass) == str:
if 'list[' in klass:
sub_kls = re.match('list\[(.*)\]', klass).group(1)
return [self.__deserialize(sub_data, sub_kls) for sub_data in data]
if 'dict(' in klass:
sub_kls = re.match('dict\((.*), (.*)\)', klass).group(2)
return {k: self.__deserialize(v, sub_kls) for k, v in iteritems(data)}
# convert str to class
# for native types
if klass in ['int', 'float', 'str', 'bool', "date", 'datetime', "object"]:
klass = eval(klass)
# for model types
else:
klass = eval('models.' + klass)
if klass in [int, float, str, bool]:
return self.__deserialize_primitive(data, klass)
elif klass == object:
return self.__deserialize_object()
elif klass == date:
return self.__deserialize_date(data)
elif klass == datetime:
return self.__deserialize_datatime(data)
else:
return self.__deserialize_model(data, klass)
def call_api(self, resource_path, method,
path_params=None, query_params=None, header_params=None,
body=None, post_params=None, files=None,
response_type=None, auth_settings=None, callback=None):
"""
Perform http request and return deserialized data
:param resource_path: Path to method endpoint.
:param method: Method to call.
:param path_params: Path parameters in the url.
:param query_params: Query parameters in the url.
:param header_params: Header parameters to be placed in the request header.
:param body: Request body.
:param post_params dict: Request post form parameters, for `application/x-www-form-urlencoded`, `multipart/form-data`.
:param auth_settings list: Auth Settings names for the request.
:param response: Response data type.
:param files dict: key -> filename, value -> filepath, for `multipart/form-data`.
:param callback function: Callback function for asynchronous request.
If provide this parameter, the request will be called asynchronously.
:return:
If provide parameter callback, the request will be called asynchronously.
The method will return the request thread.
If parameter callback is None, then the method will return the response directly.
"""
if callback is None:
return self.__call_api(resource_path, method,
path_params, query_params, header_params,
body, post_params, files,
response_type, auth_settings, callback)
else:
thread = threading.Thread(target=self.__call_api,
args=(resource_path, method,
path_params, query_params, header_params,
body, post_params, files,
response_type, auth_settings, callback))
thread.start()
return thread
def request(self, method, url, query_params=None, headers=None,
post_params=None, body=None):
""" """
Perform http request using RESTClient. Perform http request using RESTClient.
""" """
@ -296,11 +330,13 @@ class ApiClient(object):
""" """
Update header and query params based on authentication setting Update header and query params based on authentication setting
""" """
config = Configuration()
if not auth_settings: if not auth_settings:
return return
for auth in auth_settings: for auth in auth_settings:
auth_setting = configuration.auth_settings().get(auth) auth_setting = config.auth_settings().get(auth)
if auth_setting: if auth_setting:
if auth_setting['in'] == 'header': if auth_setting['in'] == 'header':
headers[auth_setting['key']] = auth_setting['value'] headers[auth_setting['key']] = auth_setting['value']
@ -308,3 +344,98 @@ class ApiClient(object):
querys[auth_setting['key']] = auth_setting['value'] querys[auth_setting['key']] = auth_setting['value']
else: else:
raise ValueError('Authentication token must be in `query` or `header`') raise ValueError('Authentication token must be in `query` or `header`')
def __deserialize_file(self, response):
"""
Save response body into a file in (the defined) temporary folder, using the filename
from the `Content-Disposition` header if provided, otherwise a random filename.
:param response: RESTResponse
:return: file path
"""
fd, path = tempfile.mkstemp(dir=configuration.temp_folder_path)
os.close(fd)
os.remove(path)
content_disposition = response.getheader("Content-Disposition")
if content_disposition:
filename = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?', content_disposition).group(1)
path = os.path.join(os.path.dirname(path), filename)
with open(path, "w") as f:
f.write(response.data)
return path
def __deserialize_primitive(self, data, klass):
"""
Deserialize string to primitive type
:param data: str
:param klass: class literal
:return: int, float, str, bool
"""
try:
value = klass(data)
except UnicodeEncodeError:
value = unicode(data)
except TypeError:
value = data
return value
def __deserialize_object(self):
"""
Deserialize empty object
"""
return object()
def __deserialize_date(self, string):
"""
Deserialize string to date
:param string: str
:return: date
"""
try:
from dateutil.parser import parse
return parse(string).date()
except ImportError:
return string
except ValueError:
raise ApiException(status=0, reason="Failed to parse `{0}` into a date object".format(string))
def __deserialize_datatime(self, string):
"""
Deserialize string to datetime.
The string should be in iso8601 datetime format.
:param string: str
:return: datetime
"""
try:
from dateutil.parser import parse
return parse(string)
except ImportError:
return string
except ValueError:
raise ApiException(status=0, reason="Failed to parse `{0}` into a datetime object".format(string))
def __deserialize_model(self, data, klass):
"""
Deserialize list or dict to model
:param data: dict, list
:param klass: class literal
"""
instance = klass()
for attr, attr_type in iteritems(instance.swagger_types):
if data is not None \
and instance.attribute_map[attr] in data\
and isinstance(data, (list, dict)):
value = data[instance.attribute_map[attr]]
setattr(instance, attr, self.__deserialize(value, attr_type))
return instance

View File

@ -1,51 +1,121 @@
from __future__ import absolute_import from __future__ import absolute_import
import base64 import base64
import urllib3 import urllib3
import httplib
import sys
import logging
def get_api_key_with_prefix(key): def singleton(cls, *args, **kw):
global api_key instances = {}
global api_key_prefix
def _singleton():
if cls not in instances:
instances[cls] = cls(*args, **kw)
return instances[cls]
return _singleton
@singleton
class Configuration(object):
def __init__(self):
# Default Base url
self.host = "{{basePath}}"
# Default api client
self.api_client = None
# Authentication Settings
self.api_key = {}
self.api_key_prefix = {}
self.username = ""
self.password = ""
# Logging Settings
self.logging_format = '%(asctime)s %(levelname)s %(message)s'
self.__logging_file = None
self.__debug = False
self.init_logger()
def init_logger(self):
self.logger = logging.getLogger()
formatter = logging.Formatter(self.logging_format)
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(formatter)
self.logger.addHandler(stream_handler)
if self.__debug:
self.logger.setLevel(logging.DEBUG)
else:
self.logger.setLevel(logging.WARNING)
if self.__logging_file:
file_handler = logging.FileHandler(self.__logging_file)
file_handler.setFormatter(formatter)
self.logger.addFilter(file_handler)
@property
def logging_file(self):
return self.__logging_file
@logging_file.setter
def logging_file(self, value):
self.__logging_file = value
if self.__logging_file:
formater = logging.Formatter(self.logging_format)
file_handler = logging.FileHandler(self.__logging_file)
file_handler.setFormatter(formater)
self.logger.addHandler(file_handler)
@property
def debug(self):
return self.__debug
@debug.setter
def debug(self, value):
self.__debug = value
if self.__debug:
# if debug status is True, turn on debug logging
self.logger.setLevel(logging.DEBUG)
# turn on httplib debug
httplib.HTTPConnection.debuglevel = 1
else:
# if debug status is False, turn off debug logging,
# setting log level to default `logging.WARNING`
self.logger.setLevel(logging.WARNING)
def get_api_key_with_prefix(self, key):
""" Return api key prepend prefix for key """
if self.api_key.get(key) and self.api_key_prefix.get(key):
return self.api_key_prefix[key] + ' ' + self.api_key[key]
elif self.api_key.get(key):
return self.api_key[key]
def get_basic_auth_token(self):
""" Return basic auth header string """
return urllib3.util.make_headers(basic_auth=self.username + ':' + self.password)\
.get('authorization')
def auth_settings(self):
""" Return Auth Settings for api client """
return { {{#authMethods}}{{#isApiKey}}
'{{name}}': {
'type': 'api_key',
'in': {{#isKeyInHeader}}'header'{{/isKeyInHeader}}{{#isKeyInQuery}}'query'{{/isKeyInQuery}},
'key': '{{keyParamName}}',
'value': self.get_api_key_with_prefix('{{keyParamName}}')
},
{{/isApiKey}}{{#isBasic}}
'{{name}}': {
'type': 'basic',
'in': 'header',
'key': 'Authorization',
'value': self.get_basic_auth_token()
},
{{/isBasic}}{{/authMethods}}
}
def to_debug_report(self):
return "Python SDK Debug Report:\n"\
"OS: {env}\n"\
"Python Version: {pyversion}\n"\
"Version of the API: {{version}}\n"\
"SDK Package Version: {{packageVersion}}".format(env=sys.platform, pyversion=sys.version)
if api_key.get(key) and api_key_prefix.get(key):
return api_key_prefix[key] + ' ' + api_key[key]
elif api_key.get(key):
return api_key[key]
def get_basic_auth_token():
global username
global password
return urllib3.util.make_headers(basic_auth=username + ':' + password).get('authorization')
def auth_settings():
return { {{#authMethods}}{{#isApiKey}}
'{{name}}': {
'type': 'api_key',
'in': {{#isKeyInHeader}}'header'{{/isKeyInHeader}}{{#isKeyInQuery}}'query'{{/isKeyInQuery}},
'key': '{{keyParamName}}',
'value': get_api_key_with_prefix('{{keyParamName}}')
},
{{/isApiKey}}{{#isBasic}}
'{{name}}': {
'type': 'basic',
'in': 'header',
'key': 'Authorization',
'value': get_basic_auth_token()
},
{{/isBasic}}{{/authMethods}}
}
# Default Base url
host = "{{basePath}}"
# Default api client
api_client = None
# Authentication settings
api_key = {}
api_key_prefix = {}
username = ''
password = ''

View File

@ -10,6 +10,7 @@ import io
import json import json
import ssl import ssl
import certifi import certifi
import logging
# python 2 and python 3 compatibility library # python 2 and python 3 compatibility library
from six import iteritems from six import iteritems
@ -27,6 +28,9 @@ except ImportError:
from urllib import urlencode from urllib import urlencode
logger = logging.getLogger(__name__)
class RESTResponse(io.IOBase): class RESTResponse(io.IOBase):
def __init__(self, resp): def __init__(self, resp):
@ -65,9 +69,10 @@ class RESTClientObject(object):
def agent(self, url): def agent(self, url):
""" """
Return proper pool manager for the http\https schemes. Use `urllib3.util.parse_url` for backward compatibility.
Return proper pool manager for the http/https schemes.
""" """
url = urllib3.util.url.parse_url(url) url = urllib3.util.parse_url(url)
scheme = url.scheme scheme = url.scheme
if scheme == 'https': if scheme == 'https':
return self.ssl_pool_manager return self.ssl_pool_manager
@ -125,24 +130,18 @@ class RESTClientObject(object):
headers=headers) headers=headers)
r = RESTResponse(r) r = RESTResponse(r)
if r.status not in range(200, 206):
raise ApiException(r)
return self.process_response(r)
def process_response(self, response):
# In the python 3, the response.data is bytes. # In the python 3, the response.data is bytes.
# we need to decode it to string. # we need to decode it to string.
if sys.version_info > (3,): if sys.version_info > (3,):
data = response.data.decode('utf8') r.data = r.data.decode('utf8')
else:
data = response.data
try:
resp = json.loads(data)
except ValueError:
resp = data
return resp # log response body
logger.debug("response body: %s" % r.data)
if r.status not in range(200, 206):
raise ApiException(http_resp=r)
return r
def GET(self, url, headers=None, query_params=None): def GET(self, url, headers=None, query_params=None):
return self.request("GET", url, headers=headers, query_params=query_params) return self.request("GET", url, headers=headers, query_params=query_params)
@ -164,37 +163,32 @@ class RESTClientObject(object):
class ApiException(Exception): class ApiException(Exception):
"""
Non-2xx HTTP response
"""
def __init__(self, http_resp): def __init__(self, status=None, reason=None, http_resp=None):
self.status = http_resp.status if http_resp:
self.reason = http_resp.reason self.status = http_resp.status
self.body = http_resp.data self.reason = http_resp.reason
self.headers = http_resp.getheaders() self.body = http_resp.data
self.headers = http_resp.getheaders()
# In the python 3, the self.body is bytes.
# we need to decode it to string.
if sys.version_info > (3,):
data = self.body.decode('utf8')
else: else:
data = self.body self.status = status
self.reason = reason
try: self.body = None
self.body = json.loads(data) self.headers = None
except ValueError:
self.body = data
def __str__(self): def __str__(self):
""" """
Custom error response messages Custom error messages for exception
""" """
return "({0})\n"\ error_message = "({0})\n"\
"Reason: {1}\n"\ "Reason: {1}\n".format(self.status, self.reason)
"HTTP response headers: {2}\n"\ if self.headers:
"HTTP response body: {3}\n".\ error_message += "HTTP response headers: {0}".format(self.headers)
format(self.status, self.reason, self.headers, self.body)
if self.body:
error_message += "HTTP response body: {0}".format(self.body)
return error_message
class RESTClient(object): class RESTClient(object):
""" """

View File

@ -15,7 +15,7 @@ VERSION = "{{packageVersion}}"
# Try reading the setuptools documentation: # Try reading the setuptools documentation:
# http://pypi.python.org/pypi/setuptools # http://pypi.python.org/pypi/setuptools
REQUIRES = ["urllib3 >= 1.10", "six >= 1.9", "certifi"] REQUIRES = ["urllib3 >= 1.10", "six >= 1.9", "certifi", "python-dateutil"]
setup( setup(
name=NAME, name=NAME,

View File

@ -36,7 +36,7 @@ class {{classname}}(object):
{{{notes}}} {{{notes}}}
Args: Args:
{{#allParams}}{{paramName}}, {{dataType}}: {{{description}}} {{^optional}}(required){{/optional}}{{#optional}}(optional){{/optional}} {{#allParams}}{{paramName}}, {{dataType}}: {{{description}}} {{#required}}(required){{/required}}{{^required}}(optional){{/required}}
{{/allParams}} {{/allParams}}
Returns: {{returnType}} Returns: {{returnType}}

View File

@ -3,8 +3,6 @@ require "uri"
module {{moduleName}} module {{moduleName}}
{{#operations}} {{#operations}}
class {{classname}} class {{classname}}
basePath = "{{basePath}}"
# apiInvoker = APIInvoker
{{#operation}} {{#operation}}
{{newline}} {{newline}}
# {{summary}} # {{summary}}
@ -14,11 +12,20 @@ module {{moduleName}}
{{#allParams}}{{^required}} # @option opts [{{{dataType}}}] :{{paramName}} {{description}} {{#allParams}}{{^required}} # @option opts [{{{dataType}}}] :{{paramName}} {{description}}
{{/required}}{{/allParams}} # @return [{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}nil{{/returnType}}] {{/required}}{{/allParams}} # @return [{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}nil{{/returnType}}]
def self.{{nickname}}({{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}opts = {}) def self.{{nickname}}({{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}opts = {})
if Swagger.configuration.debug
Swagger.logger.debug "Calling API: {{classname}}#{{nickname}} ..."
end
{{#allParams}}{{#required}} {{#allParams}}{{#required}}
# verify the required parameter '{{paramName}}' is set # verify the required parameter '{{paramName}}' is set
raise "Missing the required parameter '{{paramName}}' when calling {{nickname}}" if {{{paramName}}}.nil? fail "Missing the required parameter '{{paramName}}' when calling {{nickname}}" if {{{paramName}}}.nil?{{#isEnum}}
{{/required}}{{/allParams}} unless [{{#allowableValues}}{{#values}}'{{{this}}}'{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}].include?({{{paramName}}})
fail "invalid value for '{{{paramName}}}', must be one of {{#allowableValues}}{{#values}}{{{this}}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}"
end{{/isEnum}}
{{/required}}{{^required}}{{#isEnum}}
if opts[:'{{{paramName}}}'] && ![{{#allowableValues}}{{#values}}'{{{this}}}'{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}].include?(opts[:'{{{paramName}}}'])
fail 'invalid value for "{{{paramName}}}", must be one of {{#allowableValues}}{{#values}}{{{this}}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}'
end
{{/isEnum}}{{/required}}{{/allParams}}
# resource path # resource path
path = "{{path}}".sub('{format}','json'){{#pathParams}}.sub('{' + '{{baseName}}' + '}', {{paramName}}.to_s){{/pathParams}} path = "{{path}}".sub('{format}','json'){{#pathParams}}.sub('{' + '{{baseName}}' + '}', {{paramName}}.to_s){{/pathParams}}
@ -52,7 +59,14 @@ module {{moduleName}}
auth_names = [{{#authMethods}}'{{name}}'{{#hasMore}}, {{/hasMore}}{{/authMethods}}] 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 {{#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
response.deserialize('{{{returnType}}}'){{/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 result = response.deserialize('{{{returnType}}}')
if Swagger.configuration.debug
Swagger.logger.debug "API called: {{classname}}#{{nickname}}. Result: #{result.inspect}"
end
result{{/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
if Swagger.configuration.debug
Swagger.logger.debug "API called: {{classname}}#{{nickname}}"
end
nil{{/returnType}} nil{{/returnType}}
end end
{{/operation}} {{/operation}}

View File

@ -1,3 +1,5 @@
require 'date'
module {{moduleName}} module {{moduleName}}
# base class containing fundamental method such as to_hash, build_from_hash and more # base class containing fundamental method such as to_hash, build_from_hash and more
class BaseObject class BaseObject
@ -26,6 +28,8 @@ module {{moduleName}}
case type.to_sym case type.to_sym
when :DateTime when :DateTime
DateTime.parse(value) DateTime.parse(value)
when :Date
Date.parse(value)
when :String when :String
value.to_s value.to_s
when :Integer when :Integer

View File

@ -29,11 +29,20 @@ module {{moduleName}}
{{#vars}} {{#vars}}
if attributes[:'{{{baseName}}}'] if attributes[:'{{{baseName}}}']
{{#isContainer}}if (value = attributes[:'{{{baseName}}}']).is_a?(Array) {{#isContainer}}if (value = attributes[:'{{{baseName}}}']).is_a?(Array)
@{{{name}}} = value self.{{{name}}} = value
end{{/isContainer}}{{^isContainer}}@{{{name}}} = attributes[:'{{{baseName}}}']{{/isContainer}} end{{/isContainer}}{{^isContainer}}self.{{{name}}} = attributes[:'{{{baseName}}}']{{/isContainer}}
end end
{{/vars}} {{/vars}}
end end
{{#vars}}{{#isEnum}}
def {{{name}}}=({{{name}}})
allowed_values = [{{#allowableValues}}{{#values}}"{{{this}}}"{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}]
if {{{name}}} && !allowed_values.include?({{{name}}})
fail "invalid value for '{{{name}}}', must be one of #{allowed_values}"
end
@{{{name}}} = {{{name}}}
end
{{/isEnum}}{{/vars}}
end end
{{/model}} {{/model}}
{{/models}} {{/models}}

View File

@ -1,82 +0,0 @@
class Object
unless Object.method_defined? :blank?
def blank?
respond_to?(:empty?) ? empty? : !self
end
end
unless Object.method_defined? :present?
def present?
!blank?
end
end
end
class String
unless String.method_defined? :underscore
def underscore
self.gsub(/::/, '/').
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
gsub(/([a-z\d])([A-Z])/,'\1_\2').
tr("-", "_").
downcase
end
end
unless String.method_defined? :camelize
def camelize(first_letter_in_uppercase = true)
if first_letter_in_uppercase != :lower
self.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
else
self.to_s[0].chr.downcase + camelize(self)[1..-1]
end
end
end
end
class Hash
unless Hash.method_defined? :stringify_keys
def stringify_keys
inject({}) do |options, (key, value)|
options[key.to_s] = value
options
end
end
end
unless Hash.method_defined? :stringify_keys!
def stringify_keys!
self.replace(self.stringify_keys)
end
end
unless Hash.method_defined? :symbolize_keys
def symbolize_keys
inject({}) do |options, (key, value)|
options[(key.to_sym rescue key) || key] = value
options
end
end
end
unless Hash.method_defined? :symbolize_keys!
def symbolize_keys!
self.replace(self.symbolize_keys)
end
end
unless Hash.method_defined? :symbolize_and_underscore_keys
def symbolize_and_underscore_keys
inject({}) do |options, (key, value)|
options[(key.to_s.underscore.to_sym rescue key) || key] = value
options
end
end
end
unless Hash.method_defined? :symbolize_and_underscore_keys!
def symbolize_and_underscore_keys!
self.replace(self.symbolize_and_underscore_keys)
end
end
end

View File

@ -1,6 +1,3 @@
require 'logger'
require 'json'
module {{moduleName}} module {{moduleName}}
module Swagger module Swagger
class << self class << self
@ -25,8 +22,7 @@ module {{moduleName}}
def configure def configure
yield(configuration) if block_given? yield(configuration) if block_given?
# Configure logger. Default to use Rails self.logger = configuration.logger
self.logger ||= configuration.logger || (defined?(Rails) ? Rails.logger : Logger.new(STDOUT))
# remove :// from scheme # remove :// from scheme
configuration.scheme.sub!(/:\/\//, '') configuration.scheme.sub!(/:\/\//, '')
@ -41,7 +37,7 @@ module {{moduleName}}
end end
def authenticated? def authenticated?
Swagger.configuration.auth_token.present? !Swagger.configuration.auth_token.nil?
end end
def de_authenticate def de_authenticate
@ -51,7 +47,7 @@ module {{moduleName}}
def authenticate def authenticate
return if Swagger.authenticated? return if Swagger.authenticated?
if Swagger.configuration.username.blank? || Swagger.configuration.password.blank? if Swagger.configuration.username.nil? || Swagger.configuration.password.nil?
raise ApiError, "Username and password are required to authenticate." raise ApiError, "Username and password are required to authenticate."
end end
@ -67,6 +63,14 @@ module {{moduleName}}
response_body = request.response.body response_body = request.response.body
Swagger.configuration.auth_token = response_body['token'] Swagger.configuration.auth_token = response_body['token']
end end
def last_response
Thread.current[:swagger_last_response]
end
def last_response=(response)
Thread.current[:swagger_last_response] = response
end
end end
end end
end end

View File

@ -1,7 +1,76 @@
require 'logger'
module {{moduleName}} module {{moduleName}}
module Swagger module Swagger
class Configuration class Configuration
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 attr_accessor :scheme, :host, :base_path, :user_agent, :format, :auth_token, :inject_format, :force_ending_format
# Defines the username used with HTTP basic authentication.
#
# @return [String]
attr_accessor :username
# Defines the password used with HTTP basic authentication.
#
# @return [String]
attr_accessor :password
# Defines API keys used with API Key authentications.
#
# @return [Hash] key: parameter name, value: parameter value (API key)
#
# @example parameter name is "api_key", API key is "xxx" (e.g. "api_key=xxx" in query string)
# config.api_key['api_key'] = 'xxx'
attr_accessor :api_key
# Defines API key prefixes used with API Key authentications.
#
# @return [Hash] key: parameter name, value: API key prefix
#
# @example parameter name is "Authorization", API key prefix is "Token" (e.g. "Authorization: Token xxx" in headers)
# config.api_key_prefix['api_key'] = 'Token'
attr_accessor :api_key_prefix
# Set this to false to skip verifying SSL certificate when calling API from https server.
# Default to true.
#
# @note Do NOT set it to false in production code, otherwise you would face multiple types of cryptographic attacks.
#
# @return [true, false]
attr_accessor :verify_ssl
# Set this to customize the certificate file to verify the peer.
#
# @return [String] the path to the certificate file
#
# @see The `cainfo` option of Typhoeus, `--cert` option of libcurl. Related source code:
# https://github.com/typhoeus/typhoeus/blob/master/lib/typhoeus/easy_factory.rb#L145
attr_accessor :ssl_ca_cert
# Set this to enable/disable debugging. When enabled (set to true), HTTP request/response
# details will be logged with `logger.debug` (see the `logger` attribute).
# Default to false.
#
# @return [true, false]
attr_accessor :debug
# Defines the logger used for debugging.
# Default to `Rails.logger` (when in Rails) or logging to STDOUT.
#
# @return [#debug]
attr_accessor :logger
# Defines the temporary folder to store downloaded files
# (for API endpoints that have file response).
# Default to use `Tempfile`.
#
# @return [String]
attr_accessor :temp_folder_path
# Defines the headers to be used in HTTP requests of all API calls by default.
#
# @return [Hash]
attr_accessor :default_headers
# Defaults go in here.. # Defaults go in here..
def initialize def initialize
@ -12,17 +81,20 @@ module {{moduleName}}
@user_agent = "ruby-swagger-#{Swagger::VERSION}" @user_agent = "ruby-swagger-#{Swagger::VERSION}"
@inject_format = false @inject_format = false
@force_ending_format = false @force_ending_format = false
@camelize_params = true
@default_headers = {
'Content-Type' => "application/#{@format.downcase}",
'User-Agent' => @user_agent
}
# keys for API key authentication (param-name => api-key) # keys for API key authentication (param-name => api-key)
@api_key = {} @api_key = {}
# api-key prefix for API key authentication, e.g. "Bearer" (param-name => api-key-prefix)
@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 @verify_ssl = true
@debug = false
@logger = defined?(Rails) ? Rails.logger : Logger.new(STDOUT)
end end
end end
end end

View File

@ -1,41 +1,35 @@
require 'uri'
require 'typhoeus'
module {{moduleName}} module {{moduleName}}
module Swagger module Swagger
class Request class Request
require 'uri' attr_accessor :host, :path, :format, :params, :body, :http_method, :headers, :form_params, :auth_names, :response
require 'addressable/uri'
require 'typhoeus'
attr_accessor :host, :path, :format, :params, :body, :http_method, :headers, :form_params, :auth_names
# All requests must have an HTTP method and a path # All requests must have an HTTP method and a path
# Optionals parameters are :params, :headers, :body, :format, :host # Optionals parameters are :params, :headers, :body, :format, :host
def initialize(http_method, path, attributes={}) def initialize(http_method, path, attributes = {})
attributes[:format] ||= Swagger.configuration.format @http_method = http_method.to_sym.downcase
attributes[:params] ||= {} @path = path
# Set default headers attributes.each { |name, value| send "#{name}=", value }
default_headers = {
'Content-Type' => "application/#{attributes[:format].downcase}",
'User-Agent' => Swagger.configuration.user_agent
}
# Merge argument headers into defaults @format ||= Swagger.configuration.format
attributes[:headers] = default_headers.merge(attributes[:headers] || {}) @params ||= {}
# Apply default headers
@headers = Swagger.configuration.default_headers.merge(@headers || {})
# Stick in the auth token if there is one # Stick in the auth token if there is one
if Swagger.authenticated? if Swagger.authenticated?
attributes[:headers].merge!({:auth_token => Swagger.configuration.auth_token}) @headers.merge!({:auth_token => Swagger.configuration.auth_token})
end end
{{#hasAuthMethods}}
self.http_method = http_method.to_sym
self.path = path
attributes.each do |name, value|
send("#{name.to_s.underscore.to_sym}=", value)
end
update_params_for_auth! update_params_for_auth!
{{/hasAuthMethods}}
end end
{{#hasAuthMethods}}
# Update hearder and query params based on authentication settings. # Update hearder and query params based on authentication settings.
def update_params_for_auth! def update_params_for_auth!
(@auth_names || []).each do |auth_name| (@auth_names || []).each do |auth_name|
@ -50,30 +44,23 @@ module {{moduleName}}
end end
end end
end end
{{/hasAuthMethods}}
# Get API key (with prefix if set). # Get API key (with prefix if set).
# @param [String] param_name the parameter name of API key auth # @param [String] param_name the parameter name of API key auth
def get_api_key_with_prefix(param_name) def get_api_key_with_prefix(param_name)
if Swagger.configuration.api_key_prefix[param_name].present? if Swagger.configuration.api_key_prefix[param_name]
"#{Swagger.configuration.api_key_prefix[param_name]} #{Swagger.configuration.api_key[param_name]}" "#{Swagger.configuration.api_key_prefix[param_name]} #{Swagger.configuration.api_key[param_name]}"
else else
Swagger.configuration.api_key[param_name] Swagger.configuration.api_key[param_name]
end end
end end
# Construct a base URL # Construct the request URL.
def url(options = {}) def url(options = {})
u = Addressable::URI.new( _path = self.interpreted_path
:scheme => Swagger.configuration.scheme, _path = "/#{_path}" unless _path.start_with?('/')
:host => Swagger.configuration.host, "#{Swagger.configuration.scheme}://#{Swagger.configuration.host}#{_path}"
:path => self.interpreted_path,
:query => self.query_string.sub(/\?/, '')
).to_s
# Drop trailing question mark, if present
u.sub! /\?$/, ''
u
end end
# Iterate over the params hash, injecting any path values into the path string # Iterate over the params hash, injecting any path values into the path string
@ -104,18 +91,6 @@ module {{moduleName}}
URI.encode [Swagger.configuration.base_path, p].join("/").gsub(/\/+/, '/') URI.encode [Swagger.configuration.base_path, p].join("/").gsub(/\/+/, '/')
end end
# Massage the request body into a state of readiness
# If body is a hash, camelize all keys then convert to a json string
def body=(value)
if value.is_a?(Hash)
value = value.inject({}) do |memo, (k,v)|
memo[k.to_s.camelize(:lower).to_sym] = v
memo
end
end
@body = value
end
# If body is an object, JSONify it before making the actual request. # If body is an object, JSONify it before making the actual request.
# For form parameters, remove empty value # For form parameters, remove empty value
def outgoing_body def outgoing_body
@ -125,93 +100,60 @@ module {{moduleName}}
data.each do |key, value| data.each do |key, value|
data[key] = value.to_s if value && !value.is_a?(File) # remove emtpy form parameter data[key] = value.to_s if value && !value.is_a?(File) # remove emtpy form parameter
end end
data
elsif @body # http body is JSON elsif @body # http body is JSON
@body.is_a?(String) ? @body : @body.to_json data = @body.is_a?(String) ? @body : @body.to_json
else else
nil data = nil
end
end
# Construct a query string from the query-string-type params
def query_string
# Iterate over all params,
# .. removing the ones that are part of the path itself.
# .. stringifying values so Addressable doesn't blow up.
query_values = {}
self.params.each_pair do |key, value|
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
end
query_values[key] = value.to_s
end end
# We don't want to end up with '?' as our query string if Swagger.configuration.debug
# if there aren't really any params Swagger.logger.debug "HTTP request body param ~BEGIN~\n#{data}\n~END~\n"
return "" if query_values.blank? end
# Addressable requires query_values to be set after initialization.. data
qs = Addressable::URI.new
qs.query_values = query_values
qs.to_s
end end
def make def make
#TODO use configuration setting to determine if debugging
#logger = Logger.new STDOUT
#logger.debug self.url
request_options = { request_options = {
:method => self.http_method,
:headers => self.headers,
:params => self.params,
:ssl_verifypeer => Swagger.configuration.verify_ssl, :ssl_verifypeer => Swagger.configuration.verify_ssl,
:headers => self.headers.stringify_keys :cainfo => Swagger.configuration.ssl_ca_cert,
:verbose => Swagger.configuration.debug
} }
response = case self.http_method.to_sym
when :get,:GET
Typhoeus::Request.get(
self.url,
request_options
)
when :post,:POST if [:post, :patch, :put, :delete].include?(self.http_method)
Typhoeus::Request.post( request_options.update :body => self.outgoing_body
self.url,
request_options.merge(:body => self.outgoing_body)
)
when :patch,:PATCH
Typhoeus::Request.patch(
self.url,
request_options.merge(:body => self.outgoing_body)
)
when :put,:PUT
Typhoeus::Request.put(
self.url,
request_options.merge(:body => self.outgoing_body)
)
when :delete,:DELETE
Typhoeus::Request.delete(
self.url,
request_options.merge(:body => self.outgoing_body)
)
end end
Response.new(response)
end
def response raw = Typhoeus::Request.new(self.url, request_options).run
self.make @response = Response.new(raw)
if Swagger.configuration.debug
Swagger.logger.debug "HTTP response body ~BEGIN~\n#{@response.body}\n~END~\n"
end
# record as last response
Swagger.last_response = @response
unless @response.success?
fail ApiError.new(:code => @response.code,
:response_headers => @response.headers,
:response_body => @response.body),
@response.status_message
end
@response
end end
def response_code_pretty def response_code_pretty
return unless @response.present? return unless @response
@response.code.to_s @response.code.to_s
end end
def response_headers_pretty def response_headers_pretty
return unless @response.present? return unless @response
# JSON.pretty_generate(@response.headers).gsub(/\n/, '<br/>') # <- This was for RestClient # JSON.pretty_generate(@response.headers).gsub(/\n/, '<br/>') # <- This was for RestClient
@response.headers.gsub(/\n/, '<br/>') # <- This is for Typhoeus @response.headers.gsub(/\n/, '<br/>') # <- This is for Typhoeus
end end

View File

@ -3,76 +3,89 @@ module {{moduleName}}
class Response class Response
require 'json' require 'json'
require 'date' require 'date'
require 'tempfile'
attr_accessor :raw attr_accessor :raw
def initialize(raw) def initialize(raw)
self.raw = raw self.raw = raw
unless raw.success?
fail ApiError.new(:code => code,
:response_headers => headers,
:response_body => body),
raw.status_message
end
end end
def code def code
raw.code raw.code
end end
def status_message
raw.status_message
end
def body def body
raw.body raw.body
end end
def success?
raw.success?
end
# Deserialize the raw response body to the given return type. # Deserialize the raw response body to the given return type.
# #
# @param [String] return_type some examples: "User", "Array[User]", "Hash[String,Integer]" # @param [String] return_type some examples: "User", "Array[User]", "Hash[String,Integer]"
def deserialize(return_type) def deserialize(return_type)
return nil if body.blank? return nil if body.nil? || body.empty?
# handle file downloading - save response body into a tmp file and return the File instance
return download_file if return_type == 'File'
# ensuring a default content type # ensuring a default content type
content_type = raw.headers_hash['Content-Type'] || 'application/json' content_type = raw.headers['Content-Type'] || 'application/json'
unless content_type.start_with?('application/json') unless content_type.start_with?('application/json')
fail "Content-Type is not supported: #{content_type}" fail "Content-Type is not supported: #{content_type}"
end end
begin begin
data = JSON.parse(body, :symbolize_names => true) data = JSON.parse("[#{body}]", :symbolize_names => true)[0]
rescue JSON::ParserError => e rescue JSON::ParserError => e
if return_type == 'String' if %w(String Date DateTime).include?(return_type)
return body data = body
else else
raise e raise e
end end
end end
build_models data, return_type convert_to_type data, return_type
end end
# Walk through the given data and, when necessary, build model(s) from # Convert data to the given return type.
# Hash data for array/hash values of the response. def convert_to_type(data, return_type)
def build_models(data, return_type) return nil if data.nil?
case return_type case return_type
when 'String', 'Integer', 'Float', 'BOOLEAN' when 'String'
# primitives, return directly data.to_s
data when 'Integer'
data.to_i
when 'Float'
data.to_f
when 'BOOLEAN'
data == true
when 'DateTime' when 'DateTime'
# parse date time (expecting ISO 8601 format) # parse date time (expecting ISO 8601 format)
DateTime.parse data DateTime.parse data
when 'Date'
# parse date time (expecting ISO 8601 format)
Date.parse data
when 'Object' when 'Object'
# generic object, return directly # generic object, return directly
data data
when /\AArray<(.+)>\z/ when /\AArray<(.+)>\z/
# e.g. Array<Pet> # e.g. Array<Pet>
sub_type = $1 sub_type = $1
data.map {|item| build_models(item, sub_type) } data.map {|item| convert_to_type(item, sub_type) }
when /\AHash\<String, (.+)\>\z/ when /\AHash\<String, (.+)\>\z/
# e.g. Hash<String, Integer> # e.g. Hash<String, Integer>
sub_type = $1 sub_type = $1
{}.tap do |hash| {}.tap do |hash|
data.each {|k, v| hash[k] = build_models(v, sub_type) } data.each {|k, v| hash[k] = convert_to_type(v, sub_type) }
end end
else else
# models, e.g. Pet # models, e.g. Pet
@ -82,6 +95,28 @@ module {{moduleName}}
end end
end end
# Save response body into a file in (the defined) temporary folder, using the filename
# from the "Content-Disposition" header if provided, otherwise a random filename.
#
# @see Configuration#temp_folder_path
# @return [File] the file downloaded
def download_file
tmp_file = Tempfile.new '', Swagger.configuration.temp_folder_path
content_disposition = raw.headers['Content-Disposition']
if content_disposition
filename = content_disposition[/filename=['"]?([^'"\s]+)['"]?/, 1]
path = File.join File.dirname(tmp_file), filename
else
path = tmp_file.path
end
# close and delete temp file
tmp_file.close!
File.open(path, 'w') { |file| file.write(raw.body) }
Swagger.logger.info "File written to #{path}. Please move the file to a proper folder for further processing and delete the temp afterwards"
return File.new(path)
end
# `headers_hash` is a Typhoeus-specific extension of Hash, # `headers_hash` is a Typhoeus-specific extension of Hash,
# so simplify it back into a regular old Hash. # so simplify it back into a regular old Hash.
def headers def headers
@ -105,9 +140,11 @@ module {{moduleName}}
end end
def pretty_body def pretty_body
return unless body.present? return unless body
case format if format == 'json'
when 'json' then JSON.pretty_generate(JSON.parse(body)).gsub(/\n/, '<br/>') JSON.pretty_generate(JSON.parse(body)).gsub(/\n/, '<br/>')
else
body
end end
end end

View File

@ -14,7 +14,6 @@ Gem::Specification.new do |s|
s.license = "Apache-2.0" s.license = "Apache-2.0"
s.add_runtime_dependency 'typhoeus', '~> 0.2', '>= 0.2.1' s.add_runtime_dependency 'typhoeus', '~> 0.2', '>= 0.2.1'
s.add_runtime_dependency 'addressable', '~> 2.2', '>= 2.2.4'
s.add_runtime_dependency 'json', '~> 1.4', '>= 1.4.6' s.add_runtime_dependency 'json', '~> 1.4', '>= 1.4.6'
s.add_development_dependency 'rspec', '~> 3.2', '>= 3.2.0' s.add_development_dependency 'rspec', '~> 3.2', '>= 3.2.0'

View File

@ -1,5 +1,4 @@
# Swagger common files # Swagger common files
require '{{gemName}}/monkey'
require '{{gemName}}/swagger' require '{{gemName}}/swagger'
require '{{gemName}}/swagger/configuration' require '{{gemName}}/swagger/configuration'
require '{{gemName}}/swagger/api_error' require '{{gemName}}/swagger/api_error'
@ -22,5 +21,6 @@ require '{{importPath}}'
module {{moduleName}} module {{moduleName}}
# Initialize the default configuration # Initialize the default configuration
Swagger.configuration ||= Swagger::Configuration.new Swagger.configuration = Swagger::Configuration.new
Swagger.configure { |config| }
end end

View File

@ -15,18 +15,18 @@ MyApp.add_route('{{httpMethod}}', '{{path}}', {
{ {
"name" => "{{paramName}}", "name" => "{{paramName}}",
"description" => "{{description}}", "description" => "{{description}}",
"dataType" => "{{swaggerDataType}}", "dataType" => "{{dataType}}",
"paramType" => "query", "paramType" => "query",
"allowMultiple" => {{allowMultiple}}, {{#collectionFormat}}"collectionFormat" => "{{collectionFormat}}",{{/collectionFormat}}
"allowableValues" => "{{allowableValues}}", "allowableValues" => "{{allowableValues}}",
{{#defaultValue}}"defaultValue" => {{{defaultValue}}}{{/defaultValue}} {{#defaultValue}}"defaultValue" => "{{{defaultValue}}}"{{/defaultValue}}
}, },
{{/queryParams}} {{/queryParams}}
{{#pathParams}} {{#pathParams}}
{ {
"name" => "{{paramName}}", "name" => "{{paramName}}",
"description" => "{{description}}", "description" => "{{description}}",
"dataType" => "{{swaggerDataType}}", "dataType" => "{{dataType}}",
"paramType" => "path", "paramType" => "path",
}, },
{{/pathParams}} {{/pathParams}}
@ -34,7 +34,7 @@ MyApp.add_route('{{httpMethod}}', '{{path}}', {
{ {
"name" => "{{paramName}}", "name" => "{{paramName}}",
"description" => "{{description}}", "description" => "{{description}}",
"dataType" => "{{swaggerDataType}}", "dataType" => "{{dataType}}",
"paramType" => "header", "paramType" => "header",
}, },
{{/headerParams}} {{/headerParams}}
@ -42,7 +42,7 @@ MyApp.add_route('{{httpMethod}}', '{{path}}', {
{ {
"name" => "body", "name" => "body",
"description" => "{{description}}", "description" => "{{description}}",
"dataType" => "{{swaggerDataType}}", "dataType" => "{{dataType}}",
"paramType" => "body", "paramType" => "body",
} }
{{/bodyParams}} {{/bodyParams}}

View File

@ -3,10 +3,10 @@ require './lib/swaggering'
# only need to extend if you want special configuration! # only need to extend if you want special configuration!
class MyApp < Swaggering class MyApp < Swaggering
self.configure do |config| self.configure do |config|
config.api_version = '0.2' config.api_version = '{{version}}'
end end
end end
{{#apis}} {{#apis}}
require './lib/{{className}}.rb' require './lib/{{className}}.rb'
{{/apis}} {{/apis}}

View File

@ -5,17 +5,16 @@
// //
import Foundation import Foundation
import PromiseKit
class {{projectName}}API { class {{projectName}}API {
static let basePath = "{{^basePathOverride}}{{basePath}}{{/basePathOverride}}{{basePathOverride}}" static let basePath = "{{basePath}}"
static var credential: NSURLCredential? static var credential: NSURLCredential?
static var requestBuilderFactory: RequestBuilderFactory = AlamofireRequestBuilderFactory() static var requestBuilderFactory: RequestBuilderFactory = AlamofireRequestBuilderFactory()
} }
class APIBase { class APIBase {
func toParameters(encodable: JSONEncodable?) -> [String: AnyObject]? { func toParameters(encodable: JSONEncodable?) -> [String: AnyObject]? {
let encoded: AnyObject? = encodable?.encode() let encoded: AnyObject? = encodable?.encodeToJSON()
if encoded! is [AnyObject] { if encoded! is [AnyObject] {
var dictionary = [String:AnyObject]() var dictionary = [String:AnyObject]()
@ -44,7 +43,7 @@ class RequestBuilder<T> {
self.isBody = isBody self.isBody = isBody
} }
func execute() -> Promise<Response<T>> { fatalError("Not implemented") } func execute(completion: (response: Response<T>?, erorr: NSError?) -> Void) { }
func addHeader(#name: String, value: String) -> Self { func addHeader(#name: String, value: String) -> Self {
if !value.isEmpty { if !value.isEmpty {
@ -54,7 +53,7 @@ class RequestBuilder<T> {
} }
func addCredential() -> Self { func addCredential() -> Self {
self.credential = {{projectName}}API.credential self.credential = OneteamAPI.credential
return self return self
} }
} }
@ -63,4 +62,3 @@ protocol RequestBuilderFactory {
func getBuilder<T>() -> RequestBuilder<T>.Type func getBuilder<T>() -> RequestBuilder<T>.Type
} }

View File

@ -5,7 +5,6 @@
// //
import Alamofire import Alamofire
import PromiseKit
class AlamofireRequestBuilderFactory: RequestBuilderFactory { class AlamofireRequestBuilderFactory: RequestBuilderFactory {
func getBuilder<T>() -> RequestBuilder<T>.Type { func getBuilder<T>() -> RequestBuilder<T>.Type {
@ -21,7 +20,7 @@ class AlamofireRequestBuilder<T>: RequestBuilder<T> {
super.init(method: method, URLString: URLString, parameters: parameters, isBody: isBody) super.init(method: method, URLString: URLString, parameters: parameters, isBody: isBody)
} }
override func execute() -> Promise<Response<T>> { override func execute(completion: (response: Response<T>?, erorr: NSError?) -> Void) {
let managerId = NSUUID().UUIDString let managerId = NSUUID().UUIDString
// Create a new manager for each request to customize its request header // Create a new manager for each request to customize its request header
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration() let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
@ -35,36 +34,41 @@ class AlamofireRequestBuilder<T>: RequestBuilder<T> {
request.authenticate(usingCredential: credential) request.authenticate(usingCredential: credential)
} }
let defer = Promise<Response<T>>.defer()
request.responseJSON(options: .AllowFragments) { (req, res, json, error) in request.responseJSON(options: .AllowFragments) { (req, res, json, error) in
managerStore.removeValueForKey(managerId) managerStore.removeValueForKey(managerId)
if let error = error { if let error = error {
defer.reject(error) completion(response: nil, erorr: error)
return return
} }
if res!.statusCode >= 400 { if res!.statusCode >= 400 {
//TODO: Add error entity //TODO: Add error entity
let error = NSError(domain: res!.URL!.URLString, code: res!.statusCode, userInfo: [:]) let userInfo: [NSObject : AnyObject] = (json != nil) ? ["data": json!] : [:]
defer.reject(error) let error = NSError(domain: res!.URL!.URLString, code: res!.statusCode, userInfo: userInfo)
completion(response: nil, erorr: error)
return return
} }
if () is T { if () is T {
let response = Response(response: res!, body: () as! T) let response = Response(response: res!, body: () as! T)
defer.fulfill(response) completion(response: response, erorr: nil)
return return
} }
if let json: AnyObject = json { if let json: AnyObject = json {
let body = Decoders.decode(clazz: T.self, source: json) let body = Decoders.decode(clazz: T.self, source: json)
let response = Response(response: res!, body: body) let response = Response(response: res!, body: body)
defer.fulfill(response) completion(response: response, erorr: nil)
return
} else if "" is T {
// swagger-parser currently doesn't support void, which will be fixed in future swagger-parser release
// https://github.com/swagger-api/swagger-parser/pull/34
let response = Response(response: res!, body: "" as! T)
completion(response: response, erorr: nil)
return return
} }
defer.reject(NSError(domain: "localhost", code: 500, userInfo: ["reason": "unreacheable code"])) completion(response: nil, erorr: NSError(domain: "localhost", code: 500, userInfo: ["reason": "unreacheable code"]))
} }
return defer.promise
} }
private func buildHeaders() -> [String: AnyObject] { private func buildHeaders() -> [String: AnyObject] {
@ -76,4 +80,3 @@ class AlamofireRequestBuilder<T>: RequestBuilder<T> {
} }
} }

View File

@ -4,45 +4,45 @@
// https://github.com/swagger-api/swagger-codegen // https://github.com/swagger-api/swagger-codegen
// //
import Alamofire import Alamofire{{#usePromiseKit}}
import PromiseKit import PromiseKit{{/usePromiseKit}}
extension Bool: JSONEncodable { extension Bool: JSONEncodable {
func encode() -> AnyObject { return self } func encodeToJSON() -> AnyObject { return self }
} }
extension Float: JSONEncodable { extension Float: JSONEncodable {
func encode() -> AnyObject { return self } func encodeToJSON() -> AnyObject { return self }
} }
extension Int: JSONEncodable { extension Int: JSONEncodable {
func encode() -> AnyObject { return self } func encodeToJSON() -> AnyObject { return self }
} }
extension Double: JSONEncodable { extension Double: JSONEncodable {
func encode() -> AnyObject { return self } func encodeToJSON() -> AnyObject { return self }
} }
extension String: JSONEncodable { extension String: JSONEncodable {
func encode() -> AnyObject { return self } func encodeToJSON() -> AnyObject { return self }
} }
private func encodeIfPossible<T>(object: T) -> AnyObject { private func encodeIfPossible<T>(object: T) -> AnyObject {
if object is JSONEncodable { if object is JSONEncodable {
return (object as! JSONEncodable).encode() return (object as! JSONEncodable).encodeToJSON()
} else { } else {
return object as! AnyObject return object as! AnyObject
} }
} }
extension Array: JSONEncodable { extension Array: JSONEncodable {
func encode() -> AnyObject { func encodeToJSON() -> AnyObject {
return self.map(encodeIfPossible) return self.map(encodeIfPossible)
} }
} }
extension Dictionary: JSONEncodable { extension Dictionary: JSONEncodable {
func encode() -> AnyObject { func encodeToJSON() -> AnyObject {
var dictionary = [NSObject:AnyObject]() var dictionary = [NSObject:AnyObject]()
for (key, value) in self { for (key, value) in self {
dictionary[key as! NSObject] = encodeIfPossible(value) dictionary[key as! NSObject] = encodeIfPossible(value)
@ -50,3 +50,30 @@ extension Dictionary: JSONEncodable {
return dictionary return dictionary
} }
} }
private let dateFormatter: NSDateFormatter = {
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
return dateFormatter
}()
extension NSDate: JSONEncodable {
func encodeToJSON() -> AnyObject {
return dateFormatter.stringFromDate(self)
}
}
{{#usePromiseKit}}extension RequestBuilder {
func execute() -> Promise<Response<T>> {
let deferred = Promise<Response<T>>.defer()
self.execute { (response: Response<T>?, error: NSError?) in
if let response = response {
deferred.fulfill(response)
} else {
deferred.reject(error!)
}
}
return deferred.promise
}
}{{/usePromiseKit}}

View File

@ -7,7 +7,7 @@
import Foundation import Foundation
protocol JSONEncodable { protocol JSONEncodable {
func encode() -> AnyObject func encodeToJSON() -> AnyObject
} }
class Response<T> { class Response<T> {
@ -97,25 +97,32 @@ class Decoders {
static private func initialize() { static private func initialize() {
dispatch_once(&once) { dispatch_once(&once) {
let dateTimeFormatter = NSDateFormatter() let formatters = [
dateTimeFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'" "yyyy-MM-dd",
let dateFormatter = NSDateFormatter() "yyyy-MM-dd'T'HH:mm:ssZZZZZ",
dateFormatter.dateFormat = "yyyy-MM-dd" "yyyy-MM-dd'T'HH:mm:ss'Z'"
].map { (format: String) -> NSDateFormatter in
let formatter = NSDateFormatter()
formatter.dateFormat = format
return formatter
}
// Decoder for NSDate // Decoder for NSDate
Decoders.addDecoder(clazz: NSDate.self) { (source: AnyObject) -> NSDate in Decoders.addDecoder(clazz: NSDate.self) { (source: AnyObject) -> NSDate in
let sourceString = source as! String let sourceString = source as! String
if count(sourceString) == 10 { for formatter in formatters {
return dateFormatter.dateFromString(sourceString)! if let date = formatter.dateFromString(sourceString) {
return date
}
} }
return dateTimeFormatter.dateFromString(sourceString)! fatalError("formatter failed to parse \(sourceString)")
} {{#models}}{{#model}} } {{#models}}{{#model}}
// Decoder for {{{classname}}} // Decoder for {{{classname}}}
Decoders.addDecoder(clazz: {{{classname}}}.self) { (source: AnyObject) -> {{{classname}}} in Decoders.addDecoder(clazz: {{{classname}}}.self) { (source: AnyObject) -> {{{classname}}} in
let sourceDictionary = source as! [NSObject:AnyObject] let sourceDictionary = source as! [NSObject:AnyObject]
var instance = {{classname}}(){{#vars}}{{#isEnum}} var instance = {{classname}}(){{#vars}}{{#isEnum}}
instance.{{name}} = (sourceDictionary["{{name}}"] as? String).map { {{classname}}.{{datatypeWithEnum}}(rawValue: $0)! }{{#required}}!{{/required}} {{/isEnum}}{{^isEnum}} instance.{{name}} = (sourceDictionary["{{name}}"] as? String).map { {{classname}}.{{datatypeWithEnum}}(rawValue: $0)! }{{#unwrapRequired}}{{#required}}!{{/required}}{{/unwrapRequired}} {{/isEnum}}{{^isEnum}}
instance.{{name}} = Decoders.decode{{^required}}Optional{{/required}}(clazz: {{{baseType}}}.self, source: sourceDictionary["{{name}}"]{{#required}}!{{/required}}){{/isEnum}}{{/vars}} instance.{{name}} = Decoders.decode{{^unwrapRequired}}Optional{{/unwrapRequired}}{{#unwrapRequired}}{{^required}}Optional{{/required}}{{/unwrapRequired}}(clazz: {{{baseType}}}.self, source: sourceDictionary["{{name}}"]{{#unwrapRequired}}{{#required}}!{{/required}}{{/unwrapRequired}}){{/isEnum}}{{/vars}}
return instance return instance
}{{/model}} }{{/model}}
{{/models}} {{/models}}

View File

@ -21,7 +21,9 @@ extension {{projectName}}API {
- {{{notes}}}{{/notes}}{{#subresourceOperation}} - {{{notes}}}{{/notes}}{{#subresourceOperation}}
- subresourceOperation: {{subresourceOperation}}{{/subresourceOperation}}{{#defaultResponse}} - subresourceOperation: {{subresourceOperation}}{{/subresourceOperation}}{{#defaultResponse}}
- defaultResponse: {{defaultResponse}}{{/defaultResponse}}{{#authMethods}} - defaultResponse: {{defaultResponse}}{{/defaultResponse}}{{#authMethods}}
- authMethods: {{authMethods}}{{/authMethods}}{{#responseHeaders}} - {{#isBasic}}BASIC{{/isBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}:
- type: {{type}}{{#keyParamName}} {{keyParamName}} {{#isKeyInQuery}}(QUERY){{/isKeyInQuery}}{{#isKeyInHeaer}}(HEADER){{/isKeyInHeaer}}{{/keyParamName}}
- name: {{name}}{{/authMethods}}{{#responseHeaders}}
- responseHeaders: {{responseHeaders}}{{/responseHeaders}}{{#examples}} - responseHeaders: {{responseHeaders}}{{/responseHeaders}}{{#examples}}
- examples: {{{examples}}}{{/examples}}{{#externalDocs}} - examples: {{{examples}}}{{/examples}}{{#externalDocs}}
- externalDocs: {{externalDocs}}{{/externalDocs}}{{#hasParams}} - externalDocs: {{externalDocs}}{{/externalDocs}}{{#hasParams}}
@ -35,7 +37,7 @@ extension {{projectName}}API {
path = path.stringByReplacingOccurrencesOfString("{{=<% %>=}}{<%paramName%>}<%={{ }}=%>", withString: "\({{paramName}})", options: .LiteralSearch, range: nil){{/pathParams}} path = path.stringByReplacingOccurrencesOfString("{{=<% %>=}}{<%paramName%>}<%={{ }}=%>", withString: "\({{paramName}})", options: .LiteralSearch, range: nil){{/pathParams}}
let url = {{projectName}}API.basePath + path let url = {{projectName}}API.basePath + path
{{#bodyParam}} {{#bodyParam}}
let parameters = {{paramName}}{{^required}}?{{/required}}.encode() as? [String:AnyObject]{{/bodyParam}}{{^bodyParam}} let parameters = {{paramName}}{{^required}}?{{/required}}.encodeToJSON() as? [String:AnyObject]{{/bodyParam}}{{^bodyParam}}
let nillableParameters: [String:AnyObject?] = {{^queryParams}}[:]{{/queryParams}}{{#queryParams}}{{^secondaryParam}}[{{/secondaryParam}} let nillableParameters: [String:AnyObject?] = {{^queryParams}}[:]{{/queryParams}}{{#queryParams}}{{^secondaryParam}}[{{/secondaryParam}}
"{{paramName}}": {{paramName}}{{#hasMore}},{{/hasMore}}{{^hasMore}} "{{paramName}}": {{paramName}}{{#hasMore}},{{/hasMore}}{{^hasMore}}
]{{/hasMore}}{{/queryParams}} ]{{/hasMore}}{{/queryParams}}

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