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,9 +372,24 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
String securityName = security.keySet().iterator().next(); String securityName = security.keySet().iterator().next();
SecuritySchemeDefinition securityDefinition = fromSecurity(securityName); SecuritySchemeDefinition securityDefinition = fromSecurity(securityName);
if (securityDefinition != null) { if (securityDefinition != null) {
if(securityDefinition instanceof OAuth2Definition) {
OAuth2Definition oauth2Definition = (OAuth2Definition) securityDefinition;
OAuth2Definition oauth2Operation = new OAuth2Definition();
oauth2Operation.setType(oauth2Definition.getType());
oauth2Operation.setAuthorizationUrl(oauth2Definition.getAuthorizationUrl());
oauth2Operation.setFlow(oauth2Definition.getFlow());
oauth2Operation.setTokenUrl(oauth2Definition.getTokenUrl());
for (String scope : security.values().iterator().next()) {
if (oauth2Definition.getScopes().containsKey(scope)) {
oauth2Operation.addScope(scope, oauth2Definition.getScopes().get(scope));
}
}
authMethods.put(securityName, oauth2Operation);
} else {
authMethods.put(securityName, securityDefinition); authMethods.put(securityName, securityDefinition);
} }
} }
}
if (!authMethods.isEmpty()) { if (!authMethods.isEmpty()) {
co.authMethods = config.fromSecurity(authMethods); co.authMethods = config.fromSecurity(authMethods);
} }
@ -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);
}
if (additionalProperties.containsKey("composerProjectName")) {
this.setComposerProjectName((String) additionalProperties.get("composerProjectName"));
} else {
additionalProperties.put("composerProjectName", composerProjectName);
}
if (additionalProperties.containsKey("composerVendorName")) {
this.setComposerVendorName((String) additionalProperties.get("composerVendorName"));
} else {
additionalProperties.put("composerVendorName", composerVendorName);
}
if (additionalProperties.containsKey("artifactVersion")) {
this.setArtifactVersion((String) additionalProperties.get("artifactVersion"));
} else {
additionalProperties.put("artifactVersion", artifactVersion);
} }
additionalProperties.put("srcBasePath", srcBasePath);
additionalProperties.put("modelPackage", modelPackage);
additionalProperties.put("apiPackage", apiPackage);
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"));
@ -236,6 +260,10 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
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;
} }
@ -244,6 +272,14 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
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) {
// parameter name starting with number won't compile // parameter name starting with number won't compile

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()) {
String value = queryParams.get(key);
if (value != null){
if(b.toString().length() == 0)
b.append("?"); b.append("?");
else if (queryParams != null){
for (Pair queryParam : queryParams){
if (!queryParam.getName().isEmpty()) {
b.append(escapeString(queryParam.getName()));
b.append("=");
b.append(escapeString(queryParam.getValue()));
b.append("&"); b.append("&");
b.append(escapeString(key)).append("=").append(escapeString(value));
} }
} }
String querystring = b.toString(); }
String querystring = b.substring(0, b.length() - 1);
Builder builder; Builder builder;
if (accept == null) if (accept == null)
@ -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,15 +59,15 @@ 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)

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}}));
@ -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()) {
String value = queryParams.get(key);
if (value != null){
if(b.toString().length() == 0)
b.append("?"); b.append("?");
else if (queryParams != null){
for (Pair queryParam : queryParams){
if (!queryParam.getName().isEmpty()) {
b.append(escapeString(queryParam.getName()));
b.append("=");
b.append(escapeString(queryParam.getValue()));
b.append("&"); b.append("&");
b.append(escapeString(key)).append("=").append(escapeString(value));
} }
} }
String 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,
@ -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

@ -32,6 +32,12 @@ namespace {{packageName}}.Client {
this.ErrorCode = errorCode; this.ErrorCode = errorCode;
} }
/// <summary>
/// Initializes a new instance of the <see cref="ApiException"/> class.
/// </summary>
/// <param name="errorCode">HTTP status code.</param>
/// <param name="message">Error message.</param>
/// <param name="errorContent">Error content.</param>
public ApiException(int errorCode, string message, dynamic errorContent = null) : base(message) { public ApiException(int errorCode, string message, dynamic errorContent = null) : base(message) {
this.ErrorCode = errorCode; this.ErrorCode = errorCode;
this.ErrorContent = errorContent; 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> /// <summary>
/// Represents a set of configuration settings /// Represents a set of configuration settings
/// </summary> /// </summary>
public class Configuration{ public class Configuration
{
/// <summary> /// <summary>
/// Version of the package /// Version of the package.
/// </summary> /// </summary>
/// <value>Version of the package.</value>
public const string Version = "{{packageVersion}}"; public const string Version = "{{packageVersion}}";
/// <summary> /// <summary>
/// Gets or sets the API client. This is the default API client for making HTTP calls. /// Gets or sets the default API client for making HTTP calls.
/// </summary> /// </summary>
/// <value>The API client.</value> /// <value>The API client.</value>
public static ApiClient apiClient = new ApiClient(); public static ApiClient DefaultApiClient = new ApiClient();
/// <summary> /// <summary>
/// Gets or sets the username (HTTP basic authentication) /// Gets or sets the username (HTTP basic authentication).
/// </summary> /// </summary>
/// <value>The username.</value> /// <value>The username.</value>
public static String username { get; set; } public static String Username { get; set; }
/// <summary> /// <summary>
/// Gets or sets the password (HTTP basic authentication) /// Gets or sets the password (HTTP basic authentication).
/// </summary> /// </summary>
/// <value>The password.</value> /// <value>The password.</value>
public static String password { get; set; } public static String Password { get; set; }
/// <summary> /// <summary>
/// Gets or sets the API key based on the authentication name /// Gets or sets the API key based on the authentication name.
/// </summary> /// </summary>
/// <value>The API key.</value> /// <value>The API key.</value>
public static Dictionary<String, String> apiKey = new Dictionary<String, String>(); public static Dictionary<String, String> ApiKey = new Dictionary<String, String>();
/// <summary> /// <summary>
/// Gets or sets the prefix (e.g. Token) of the API key based on the authentication name /// Gets or sets the prefix (e.g. Token) of the API key based on the authentication name.
/// </summary> /// </summary>
/// <value>The prefix of the API key.</value> /// <value>The prefix of the API key.</value>
public static Dictionary<String, String> apiKeyPrefix = new Dictionary<String, String>(); 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]];
} }
- (void)logRequest:(NSURLRequest*)request { NSLog(@"%@", message);
NSLog(@"request: %@", [self descriptionForRequest:request]);
} }
- (void)logResponse:(id)data forRequest:(NSURLRequest*)request error:(NSError*)error { #pragma mark - Cache Methods
NSLog(@"request: %@ response: %@ ", [self descriptionForRequest:request], data );
}
#pragma mark - + (void) setCacheEnabled:(BOOL)enabled {
cacheEnabled = enabled;
}
+(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) {
if([obj isKindOfClass:[SWGFile class]]) {
file = (SWGFile*) obj;
requestContentType = @"multipart/form-data";
}
else if([obj isKindOfClass:[NSDictionary class]]) {
for(NSString * key in obj) {
params[key] = obj[key];
}
}
}
NSString * urlString = [[NSURL URLWithString:path relativeToURL:self.baseURL] absoluteString];
// request with multipart form
if([requestContentType isEqualToString:@"multipart/form-data"]) {
request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" request = [self.requestSerializer multipartFormRequestWithMethod:@"POST"
URLString:urlString URLString:urlString
parameters:nil parameters:nil
constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formParams enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
for(NSString * key in params) { NSData *data = [obj dataUsingEncoding:NSUTF8StringEncoding];
NSData* data = [params[key] dataUsingEncoding:NSUTF8StringEncoding];
[formData appendPartWithFormData:data name:key]; [formData appendPartWithFormData:data name:key];
}];
[files enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
NSURL *filePath = (NSURL *)obj;
[formData appendPartWithFileURL:filePath name:key error:nil];
}];
} error:nil];
} }
if (file) {
[formData appendPartWithFileData: [file data]
name: [file paramName]
fileName: [file name]
mimeType: [file mimeType]];
}
}
error:nil];
}
// request with form parameters or json
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 request = [self.requestSerializer requestWithMethod:method
URLString:urlString URLString:urlString
parameters:params parameters:formParams
error:nil]; error:nil];
} }
if (body) {
}
else {
NSString * pathWithQueryParams = [self pathWithQueryParamsToString:path queryParams:queryParams];
NSString * urlString = [[NSURL URLWithString:pathWithQueryParams relativeToURL:self.baseURL] absoluteString];
request = [self.requestSerializer requestWithMethod:method request = [self.requestSerializer requestWithMethod:method
URLString:urlString URLString:urlString
parameters:body parameters:body
error:nil]; 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];
}
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[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]; else {
[self operationWithCompletionBlock:request requestId:requestId completionBlock:^(id data, NSError *error) {
completionBlock([self deserialize:data class:responseType], error);
}];
}
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}}
} }
@ -116,7 +117,7 @@ static NSString * basePath = @"{{basePath}}";
{{/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; id bodyParam = nil;
NSMutableDictionary *formParams = [[NSMutableDictionary alloc] init];
NSMutableDictionary *files = [[NSMutableDictionary alloc] init];
{{#bodyParam}} {{#bodyParam}}
id __body = {{paramName}}; bodyParam = {{paramName}};
if(__body != nil && [__body isKindOfClass:[NSArray class]]){ if(bodyParam != nil && [bodyParam isKindOfClass:[NSArray class]]){
NSMutableArray *objs = [[NSMutableArray alloc] init]; NSMutableArray *objs = [[NSMutableArray alloc] init];
for (id dict in (NSArray*)__body) { 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,10 +25,25 @@
* 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";
@ -25,16 +51,24 @@ class ApiClient {
public static $PUT = "PUT"; public static $PUT = "PUT";
public static $DELETE = "DELETE"; public static $DELETE = "DELETE";
/** @var Configuration */ /**
* Configuration
* @var Configuration
*/
protected $config; protected $config;
/** @var ObjectSerializer */ /**
* Object Serializer
* @var ObjectSerializer
*/
protected $serializer; protected $serializer;
/** /**
* Constructor of the class
* @param Configuration $config config for this ApiClient * @param Configuration $config config for this ApiClient
*/ */
function __construct(Configuration $config = null) { function __construct(Configuration $config = null)
{
if ($config == null) { if ($config == null) {
$config = Configuration::getDefaultConfiguration(); $config = Configuration::getDefaultConfiguration();
} }
@ -44,29 +78,32 @@ class ApiClient {
} }
/** /**
* get the config * Get the config
* @return Configuration * @return Configuration
*/ */
public function getConfig() { public function getConfig()
{
return $this->config; return $this->config;
} }
/** /**
* get the serializer * Get the serializer
* @return ObjectSerializer * @return ObjectSerializer
*/ */
public function getSerializer() { public function getSerializer()
{
return $this->serializer; return $this->serializer;
} }
/** /**
* Get API key (with prefix if set) * Get API key (with prefix if set)
* @param string $apiKey name of apikey * @param string $apiKeyIdentifier name of apikey
* @return string API key with the prefix * @return string API key with the prefix
*/ */
public function getApiKeyWithPrefix($apiKey) { public function getApiKeyWithPrefix($apiKeyIdentifier)
$prefix = $this->config->getApiKeyPrefix($apiKey); {
$apiKey = $this->config->getApiKey($apiKey); $prefix = $this->config->getApiKeyPrefix($apiKeyIdentifier);
$apiKey = $this->config->getApiKey($apiKeyIdentifier);
if (!isset($apiKey)) { if (!isset($apiKey)) {
return null; return null;
@ -82,20 +119,26 @@ class ApiClient {
} }
/** /**
* Make the HTTP call (Sync)
* @param string $resourcePath path to method endpoint * @param string $resourcePath path to method endpoint
* @param string $method method to call * @param string $method method to call
* @param array $queryParams parameters to be place in query URL * @param array $queryParams parameters to be place in query URL
* @param array $postData parameters to be placed in POST body * @param array $postData parameters to be placed in POST body
* @param array $headerParams parameters to be place in request header * @param array $headerParams parameters to be place in request header
* @param string $responseType expected response type of the endpoint
* @throws \{{invokerPackage}}\ApiException on a non 2xx response * @throws \{{invokerPackage}}\ApiException on a non 2xx response
* @return mixed * @return mixed
*/ */
public function callApi($resourcePath, $method, $queryParams, $postData, $headerParams) { public function callApi($resourcePath, $method, $queryParams, $postData, $headerParams, $responseType=null)
{
$headers = array(); $headers = array();
# construct the http header // construct the http header
$headerParams = array_merge((array)$this->config->getDefaultHeaders(), (array)$headerParams); $headerParams = array_merge(
(array)$this->config->getDefaultHeaders(),
(array)$headerParams
);
foreach ($headerParams as $key => $val) { foreach ($headerParams as $key => $val) {
$headers[] = "$key: $val"; $headers[] = "$key: $val";
@ -104,8 +147,7 @@ class ApiClient {
// form data // form data
if ($postData and in_array('Content-Type: application/x-www-form-urlencoded', $headers)) { if ($postData and in_array('Content-Type: application/x-www-form-urlencoded', $headers)) {
$postData = http_build_query($postData); $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
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)); $postData = json_encode($this->serializer->sanitizeForSerialization($postData));
} }
@ -174,26 +216,35 @@ class ApiClient {
if ($response_info['http_code'] == 0) { if ($response_info['http_code'] == 0) {
throw new ApiException("API call to $url timed out: ".serialize($response_info), 0, null, null); 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 ) { } 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); $data = json_decode($http_body);
if (json_last_error() > 0) { // if response is a string if (json_last_error() > 0) { // if response is a string
$data = $http_body; $data = $http_body;
} }
} else { } else {
throw new ApiException("[".$response_info['http_code']."] Error connecting to the API ($url)", throw new ApiException(
$response_info['http_code'], $http_header, $http_body); "[".$response_info['http_code']."] Error connecting to the API ($url)",
$response_info['http_code'], $http_header, $http_body
);
} }
return $data; return array($data, $http_header);
} }
/* /**
* return the header 'Accept' based on an array of Accept provided * Return the header 'Accept' based on an array of Accept provided
* *
* @param string[] $accept Array of header * @param string[] $accept Array of header
*
* @return string Accept (e.g. application/json) * @return string Accept (e.g. application/json)
*/ */
public static function selectHeaderAccept($accept) { public static function selectHeaderAccept($accept)
{
if (count($accept) === 0 or (count($accept) === 1 and $accept[0] === '')) { if (count($accept) === 0 or (count($accept) === 1 and $accept[0] === '')) {
return NULL; return null;
} elseif (preg_grep("/application\/json/i", $accept)) { } elseif (preg_grep("/application\/json/i", $accept)) {
return 'application/json'; return 'application/json';
} else { } else {
@ -201,13 +252,15 @@ class ApiClient {
} }
} }
/* /**
* return the content type based on an array of content-type provided * Return the content type based on an array of content-type provided
*
* @param string[] $content_type Array fo content-type
* *
* @param string[] content_type_array Array fo content-type
* @return string Content-Type (e.g. application/json) * @return string Content-Type (e.g. application/json)
*/ */
public static function selectHeaderContentType($content_type) { public static function selectHeaderContentType($content_type)
{
if (count($content_type) === 0 or (count($content_type) === 1 and $content_type[0] === '')) { if (count($content_type) === 0 or (count($content_type) === 1 and $content_type[0] === '')) {
return 'application/json'; return 'application/json';
} elseif (preg_grep("/application\/json/i", $content_type)) { } elseif (preg_grep("/application\/json/i", $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. */ /**
* The HTTP body of the server response.
* @var string
*/
protected $responseBody; protected $responseBody;
/** @var string[] The HTTP header of the server response. */ /**
* The HTTP header of the server response.
* @var string[]
*/
protected $responseHeaders; protected $responseHeaders;
/** /**
* The deserialized response object * The deserialized response object
* @var $responseObject;
*/ */
protected $responseObject; protected $responseObject;
public function __construct($message="", $code=0, $responseHeaders=null, $responseBody=null) { /**
* 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); parent::__construct($message, $code);
$this->responseHeaders = $responseHeaders; $this->responseHeaders = $responseHeaders;
$this->responseBody = $responseBody; $this->responseBody = $responseBody;
} }
/** /**
* Get the HTTP response header * Gets the HTTP response header
* *
* @return string HTTP response header * @return string HTTP response header
*/ */
public function getResponseHeaders() { public function getResponseHeaders()
{
return $this->responseHeaders; return $this->responseHeaders;
} }
/** /**
* Get the HTTP response body * Gets the HTTP response body
* *
* @return string HTTP response body * @return string HTTP response body
*/ */
public function getResponseBody() { public function getResponseBody()
{
return $this->responseBody; return $this->responseBody;
} }
/** /**
* sets the deseralized response object (during deserialization) * Sets the deseralized response object (during deserialization)
* @param mixed $obj * @param mixed $obj Deserialized response object
* @return void
*/ */
public function setResponseObject($obj) { public function setResponseObject($obj)
{
$this->responseObject = $obj; $this->responseObject = $obj;
} }
public function getResponseObject() { /**
* Gets the deseralized response object (during deserialization)
*
* @return mixed the deserialized response object
*/
public function getResponseObject()
{
return $this->responseObject; return $this->responseObject;
} }
} }

View File

@ -1,14 +1,59 @@
<?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) { if (is_scalar($data) || null === $data) {
$sanitized = $data; $sanitized = $data;
} else if ($data instanceof \DateTime) { } else if ($data instanceof \DateTime) {
@ -37,10 +82,13 @@ class ObjectSerializer {
/** /**
* 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,10 +97,13 @@ 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)) { if (is_array($object)) {
return implode(',', $object); return implode(',', $object);
} else { } else {
@ -64,10 +115,13 @@ class ObjectSerializer {
* 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);
} }
@ -75,21 +129,31 @@ class ObjectSerializer {
* 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)
{
if ($value instanceof SplFileObject) {
return $value->getRealPath();
} else {
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 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 if ($value instanceof \DateTime) { // datetime in ISO8601 format
return $value->format(\DateTime::ISO8601); return $value->format(\DateTime::ISO8601);
} else { } else {
@ -102,12 +166,15 @@ class ObjectSerializer {
* *
* @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) { if (null === $data) {
$deserialized = null; $deserialized = null;
} elseif (substr($class, 0, 4) == 'map[') { # for associative array e.g. map[string,int] } elseif (substr($class, 0, 4) === 'map[') { // for associative array e.g. map[string,int]
$inner = substr($class, 4, -1); $inner = substr($class, 4, -1);
$deserialized = array(); $deserialized = array();
if (strrpos($inner, ",") !== false) { if (strrpos($inner, ",") !== false) {
@ -124,11 +191,22 @@ class ObjectSerializer {
$values[] = $this->deserialize($value, $subClass); $values[] = $this->deserialize($value, $subClass);
} }
$deserialized = $values; $deserialized = $values;
} elseif ($class == 'DateTime') { } elseif ($class === 'DateTime') {
$deserialized = new \DateTime($data); $deserialized = new \DateTime($data);
} elseif (in_array($class, array('string', 'int', 'float', 'double', 'bool', 'object'))) { } elseif (in_array($class, array('string', 'int', 'float', 'double', 'bool', 'object'))) {
settype($data, $class); settype($data, $class);
$deserialized = $data; $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 { } else {
$instance = new $class(); $instance = new $class();
foreach ($instance::$swaggerTypes as $property => $type) { foreach ($instance::$swaggerTypes as $property => $type) {

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,16 +38,30 @@ use \{{invokerPackage}}\ApiClient;
use \{{invokerPackage}}\ApiException; use \{{invokerPackage}}\ApiException;
use \{{invokerPackage}}\ObjectSerializer; use \{{invokerPackage}}\ObjectSerializer;
{{#operations}} /**
class {{classname}} { * {{classname}} Class Doc Comment
*
/** @var \{{invokerPackage}}\ApiClient instance of the ApiClient */ * @category Class
private $apiClient; * @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}}
{
/** /**
* API Client
* @var \{{invokerPackage}}\ApiClient instance of the ApiClient
*/
protected $apiClient;
/**
* Constructor
* @param \{{invokerPackage}}\ApiClient|null $apiClient The api client to use * @param \{{invokerPackage}}\ApiClient|null $apiClient The api client to use
*/ */
function __construct($apiClient = null) { function __construct($apiClient = null)
{
if ($apiClient == null) { if ($apiClient == null) {
$apiClient = new ApiClient(); $apiClient = new ApiClient();
$apiClient->getConfig()->setHost('{{basePath}}'); $apiClient->getConfig()->setHost('{{basePath}}');
@ -46,17 +71,21 @@ class {{classname}} {
} }
/** /**
* Get API client
* @return \{{invokerPackage}}\ApiClient get the API client * @return \{{invokerPackage}}\ApiClient get the API client
*/ */
public function getApiClient() { public function getApiClient()
{
return $this->apiClient; return $this->apiClient;
} }
/** /**
* Set the API client
* @param \{{invokerPackage}}\ApiClient $apiClient set the API client * @param \{{invokerPackage}}\ApiClient $apiClient set the API client
* @return {{classname}} * @return {{classname}}
*/ */
public function setApiClient(ApiClient $apiClient) { public function setApiClient(ApiClient $apiClient)
{
$this->apiClient = $apiClient; $this->apiClient = $apiClient;
return $this; return $this;
} }
@ -67,17 +96,17 @@ class {{classname}} {
* *
* {{{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}}
* @throws \{{invokerPackage}}\ApiException on non-2xx response * @throws \{{invokerPackage}}\ApiException on non-2xx response
*/ */
public function {{nickname}}({{#allParams}}${{paramName}}{{#optional}}=null{{/optional}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) { public function {{nickname}}({{#allParams}}${{paramName}}{{^required}}=null{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}})
{
{{#allParams}}{{#required}} {{#allParams}}{{#required}}
// verify the required parameter '{{paramName}}' is set // verify the required parameter '{{paramName}}' is set
if (${{paramName}} === null) { if (${{paramName}} === null) {
throw new \InvalidArgumentException('Missing the required parameter ${{paramName}} when calling {{nickname}}'); throw new \InvalidArgumentException('Missing the required parameter ${{paramName}} when calling {{nickname}}');
} }{{/required}}{{/allParams}}
{{/required}}{{/allParams}}
// parse inputs // parse inputs
$resourcePath = "{{path}}"; $resourcePath = "{{path}}";
@ -103,9 +132,11 @@ class {{classname}} {
}{{/headerParams}} }{{/headerParams}}
{{#pathParams}}// path params {{#pathParams}}// path params
if (${{paramName}} !== null) { if (${{paramName}} !== null) {
$resourcePath = str_replace("{" . "{{baseName}}" . "}", $resourcePath = str_replace(
"{" . "{{baseName}}" . "}",
$this->apiClient->getSerializer()->toPathValue(${{paramName}}), $this->apiClient->getSerializer()->toPathValue(${{paramName}}),
$resourcePath); $resourcePath
);
}{{/pathParams}} }{{/pathParams}}
{{#formParams}}// form params {{#formParams}}// form params
if (${{paramName}} !== null) { if (${{paramName}} !== null) {
@ -121,8 +152,7 @@ class {{classname}} {
if (isset($_tempBody)) { if (isset($_tempBody)) {
$httpBody = $_tempBody; // $_tempBody is the method argument, if present $httpBody = $_tempBody; // $_tempBody is the method argument, if present
} else if (count($formParams) > 0) { } else if (count($formParams) > 0) {
// for HTTP post (form) $httpBody = $formParams; // for HTTP post (form)
$httpBody = $formParams;
} }
{{#authMethods}}{{#isApiKey}} {{#authMethods}}{{#isApiKey}}
$apiKey = $this->apiClient->getApiKeyWithPrefix('{{keyParamName}}'); $apiKey = $this->apiClient->getApiKeyWithPrefix('{{keyParamName}}');
@ -133,14 +163,17 @@ class {{classname}} {
{{#isOAuth}}//TODO support oauth{{/isOAuth}} {{#isOAuth}}//TODO support oauth{{/isOAuth}}
{{/authMethods}} {{/authMethods}}
// make the API Call // make the API Call
try { try
$response = $this->apiClient->callAPI($resourcePath, $method, {
list($response, $httpHeader) = $this->apiClient->callApi(
$resourcePath, $method,
$queryParams, $httpBody, $queryParams, $httpBody,
$headerParams); $headerParams{{#returnType}}, '{{returnType}}'{{/returnType}}
);
} catch (ApiException $e) { } catch (ApiException $e) {
switch ($e->getCode()) { {{#responses}}{{#dataType}} switch ($e->getCode()) { {{#responses}}{{#dataType}}
case {{code}}: case {{code}}:
$data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '{{dataType}}'); $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '{{dataType}}', $httpHeader);
$e->setResponseObject($data); $e->setResponseObject($data);
break;{{/dataType}}{{/responses}} break;{{/dataType}}{{/responses}}
} }
@ -152,8 +185,7 @@ class {{classname}} {
return null; return null;
} }
$responseObject = $this->apiClient->getSerializer()->deserialize($response,'{{returnType}}'); return $this->apiClient->getSerializer()->deserialize($response, '{{returnType}}');
return $responseObject;
{{/returnType}} {{/returnType}}
} }
{{/operation}} {{/operation}}

View File

@ -1,5 +1,5 @@
{ {
"name": "{{groupId}}/{{artifactId}}",{{#artifactVersion}} "name": "{{composerVendorName}}/{{composerProjectName}}",{{#artifactVersion}}
"version": "{{artifactVersion}}",{{/artifactVersion}} "version": "{{artifactVersion}}",{{/artifactVersion}}
"description": "{{description}}", "description": "{{description}}",
"keywords": [ "keywords": [

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,118 +26,222 @@
* 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;
/** @var string[] Associate array to store API key(s) */ /**
* Associate array to store API key(s)
*
* @var string[]
*/
protected $apiKeys = array(); protected $apiKeys = array();
/** string[] Associate array to store API prefix (e.g. Bearer) */ /**
* Associate array to store API prefix (e.g. Bearer)
*
* @var string[]
*/
protected $apiKeyPrefixes = array(); protected $apiKeyPrefixes = array();
/** @var string Username for HTTP basic authentication */ /**
* Username for HTTP basic authentication
*
* @var string
*/
protected $username = ''; protected $username = '';
/** @var string Password for HTTP basic authentication */ /**
* Password for HTTP basic authentication
*
* @var string
*/
protected $password = ''; protected $password = '';
/** @var \{{invokerPackage}}\ApiClient The default instance of ApiClient */ /**
* The default instance of ApiClient
*
* @var \{{invokerPackage}}\ApiClient
*/
protected $defaultHeaders = array(); protected $defaultHeaders = array();
/** @var string The host */ /**
* The host
*
* @var string
*/
protected $host = 'http://localhost'; protected $host = 'http://localhost';
/** @var string timeout (second) of the HTTP request, by default set to 0, no timeout */ /**
* Timeout (second) of the HTTP request, by default set to 0, no timeout
*
* @var string
*/
protected $curlTimeout = 0; protected $curlTimeout = 0;
/** @var string user agent of the HTTP request, set to "PHP-Swagger" by default */ /**
* User agent of the HTTP request, set to "PHP-Swagger" by default
*
* @var string
*/
protected $userAgent = "PHP-Swagger"; protected $userAgent = "PHP-Swagger";
/** @var bool Debug switch (default set to false) */ /**
* Debug switch (default set to false)
*
* @var bool
*/
protected $debug = false; protected $debug = false;
/** @var string Debug file location (log to STDOUT by default) */ /**
* Debug file location (log to STDOUT by default)
*
* @var string
*/
protected $debugFile = 'php://output'; protected $debugFile = 'php://output';
/** /**
* @param string $key * Debug file location (log to STDOUT by default)
* @param string $value *
* @var string
*/
protected $tempFolderPath;
/**
* Constructor
*/
public function __construct()
{
$this->tempFolderPath = sys_get_temp_dir();
}
/**
* Sets API key
*
* @param string $apiKeyIdentifier API key identifier (authentication scheme)
* @param string $key API key or token
*
* @return Configuration * @return Configuration
*/ */
public function setApiKey($key, $value) { public function setApiKey($apiKeyIdentifier, $key)
$this->apiKeys[$key] = $value; {
$this->apiKeys[$apiKeyIdentifier] = $key;
return $this; return $this;
} }
/** /**
* @param $key * Gets API key
* @return string *
* @param string $apiKeyIdentifier API key identifier (authentication scheme)
*
* @return string API key or token
*/ */
public function getApiKey($key) { public function getApiKey($apiKeyIdentifier)
return isset($this->apiKeys[$key]) ? $this->apiKeys[$key] : null; {
return isset($this->apiKeys[$apiKeyIdentifier]) ? $this->apiKeys[$apiKeyIdentifier] : null;
} }
/** /**
* @param string $key * Sets the prefix for API key (e.g. Bearer)
* @param string $value *
* @param string $apiKeyIdentifier API key identifier (authentication scheme)
* @param string $prefix API key prefix, e.g. Bearer
*
* @return Configuration * @return Configuration
*/ */
public function setApiKeyPrefix($key, $value) { public function setApiKeyPrefix($apiKeyIdentifier, $prefix)
$this->apiKeyPrefixes[$key] = $value; {
$this->apiKeyPrefixes[$apiKeyIdentifier] = $prefix;
return $this; return $this;
} }
/** /**
* @param $key * Gets API key prefix
*
* @param string $apiKeyIdentifier API key identifier (authentication scheme)
*
* @return string * @return string
*/ */
public function getApiKeyPrefix($key) { public function getApiKeyPrefix($apiKeyIdentifier)
return isset($this->apiKeyPrefixes[$key]) ? $this->apiKeyPrefixes[$key] : null; {
return isset($this->apiKeyPrefixes[$apiKeyIdentifier]) ? $this->apiKeyPrefixes[$apiKeyIdentifier] : null;
} }
/** /**
* @param string $username * Sets the username for HTTP basic authentication
*
* @param string $username Username for HTTP basic authentication
*
* @return Configuration * @return Configuration
*/ */
public function setUsername($username) { public function setUsername($username)
{
$this->username = $username; $this->username = $username;
return $this; return $this;
} }
/** /**
* @return string * Gets the username for HTTP basic authentication
*
* @return string Username for HTTP basic authentication
*/ */
public function getUsername() { public function getUsername()
{
return $this->username; return $this->username;
} }
/** /**
* @param string $password * Sets the password for HTTP basic authentication
*
* @param string $password Password for HTTP basic authentication
*
* @return Configuration * @return Configuration
*/ */
public function setPassword($password) { public function setPassword($password)
{
$this->password = $password; $this->password = $password;
return $this; return $this;
} }
/** /**
* @return string * Gets the password for HTTP basic authentication
*
* @return string Password for HTTP basic authentication
*/ */
public function getPassword() { public function getPassword()
{
return $this->password; return $this->password;
} }
/** /**
* add default header * Adds a default header
* *
* @param string $headerName header name (e.g. Token) * @param string $headerName header name (e.g. Token)
* @param string $headerValue header value (e.g. 1z8wp3) * @param string $headerValue header value (e.g. 1z8wp3)
*
* @return ApiClient * @return ApiClient
*/ */
public function addDefaultHeader($headerName, $headerValue) { public function addDefaultHeader($headerName, $headerValue)
{
if (!is_string($headerName)) { if (!is_string($headerName)) {
throw new \InvalidArgumentException('Header name must be a string.'); throw new \InvalidArgumentException('Header name must be a string.');
} }
@ -136,46 +251,59 @@ class Configuration {
} }
/** /**
* get the default header * Gets the default header
* *
* @return array default header * @return array An array of default header(s)
*/ */
public function getDefaultHeaders() { public function getDefaultHeaders()
{
return $this->defaultHeaders; return $this->defaultHeaders;
} }
/** /**
* delete a default header * Deletes a default header
*
* @param string $headerName the header to delete * @param string $headerName the header to delete
*
* @return Configuration * @return Configuration
*/ */
public function deleteDefaultHeader($headerName) { public function deleteDefaultHeader($headerName)
{
unset($this->defaultHeaders[$headerName]); unset($this->defaultHeaders[$headerName]);
} }
/** /**
* @param string $host * Sets the host
*
* @param string $host Host
*
* @return Configuration * @return Configuration
*/ */
public function setHost($host) { public function setHost($host)
{
$this->host = $host; $this->host = $host;
return $this; return $this;
} }
/** /**
* @return string * Gets the host
*
* @return string Host
*/ */
public function getHost() { public function getHost()
{
return $this->host; return $this->host;
} }
/** /**
* set the user agent of the api client * Sets the user agent of the api client
* *
* @param string $userAgent the user agent of the api client * @param string $userAgent the user agent of the api client
*
* @return ApiClient * @return ApiClient
*/ */
public function setUserAgent($userAgent) { public function setUserAgent($userAgent)
{
if (!is_string($userAgent)) { if (!is_string($userAgent)) {
throw new \InvalidArgumentException('User-agent must be a string.'); throw new \InvalidArgumentException('User-agent must be a string.');
} }
@ -185,21 +313,24 @@ class Configuration {
} }
/** /**
* get the user agent of the api client * Gets the user agent of the api client
* *
* @return string user agent * @return string user agent
*/ */
public function getUserAgent() { public function getUserAgent()
{
return $this->userAgent; return $this->userAgent;
} }
/** /**
* set the HTTP timeout value * Sets the HTTP timeout value
* *
* @param integer $seconds Number of seconds before timing out [set to 0 for no timeout] * @param integer $seconds Number of seconds before timing out [set to 0 for no timeout]
*
* @return ApiClient * @return ApiClient
*/ */
public function setCurlTimeout($seconds) { public function setCurlTimeout($seconds)
{
if (!is_numeric($seconds) || $seconds < 0) { if (!is_numeric($seconds) || $seconds < 0) {
throw new \InvalidArgumentException('Timeout value must be numeric and a non-negative number.'); throw new \InvalidArgumentException('Timeout value must be numeric and a non-negative number.');
} }
@ -209,58 +340,125 @@ class Configuration {
} }
/** /**
* get the HTTP timeout value * Gets the HTTP timeout value
* *
* @return string HTTP timeout value * @return string HTTP timeout value
*/ */
public function getCurlTimeout() { public function getCurlTimeout()
{
return $this->curlTimeout; return $this->curlTimeout;
} }
/** /**
* @param bool $debug * Sets debug flag
*
* @param bool $debug Debug flag
*
* @return Configuration * @return Configuration
*/ */
public function setDebug($debug) { public function setDebug($debug)
{
$this->debug = $debug; $this->debug = $debug;
return $this; return $this;
} }
/** /**
* Gets the debug flag
*
* @return bool * @return bool
*/ */
public function getDebug() { public function getDebug()
{
return $this->debug; return $this->debug;
} }
/** /**
* @param string $debugFile * Sets the debug file
*
* @param string $debugFile Debug file
*
* @return Configuration * @return Configuration
*/ */
public function setDebugFile($debugFile) { public function setDebugFile($debugFile)
{
$this->debugFile = $debugFile; $this->debugFile = $debugFile;
return $this; return $this;
} }
/** /**
* Gets the debug file
*
* @return string * @return string
*/ */
public function getDebugFile() { public function getDebugFile()
{
return $this->debugFile; return $this->debugFile;
} }
/** /**
* Sets the temp folder path
*
* @param string $tempFolderPath Temp folder path
*
* @return Configuration * @return Configuration
*/ */
public static function getDefaultConfiguration() { public function setTempFolderPath($tempFolderPath)
if (self::$defaultConfiguration == null) { {
return new Configuration(); $this->tempFolderPath = $tempFolderPath;
return $this;
} }
return self::$defaultConfiguration; /**
* Gets the temp folder path
*
* @return string Temp folder path
*/
public function getTempFolderPath()
{
return $this->tempFolderPath;
} }
public static function setDefaultConfiguration(Configuration $config) { /**
self::$defaultConfiguration = $config; * 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,50 +27,77 @@
* 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;
/**
class {{classname}} implements ArrayAccess { * {{classname}} Class Doc Comment
/** @var string[] Array of property to type mappings. Used for (de)serialization */ *
* @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( static $swaggerTypes = array(
{{#vars}}'{{name}}' => '{{{datatype}}}'{{#hasMore}}, {{#vars}}'{{name}}' => '{{{datatype}}}'{{#hasMore}},
{{/hasMore}}{{/vars}} {{/hasMore}}{{/vars}}
); );
/** @var string[] Array of attributes where the key is the local name, and the value is the original name */ /**
* Array of attributes where the key is the local name, and the value is the original name
* @var string[]
*/
static $attributeMap = array( static $attributeMap = array(
{{#vars}}'{{name}}' => '{{baseName}}'{{#hasMore}}, {{#vars}}'{{name}}' => '{{baseName}}'{{#hasMore}},
{{/hasMore}}{{/vars}} {{/hasMore}}{{/vars}}
); );
/** @var string[] Array of attributes to setter functions (for deserialization of responses) */ /**
* Array of attributes to setter functions (for deserialization of responses)
* @var string[]
*/
static $setters = array( static $setters = array(
{{#vars}}'{{name}}' => '{{setter}}'{{#hasMore}}, {{#vars}}'{{name}}' => '{{setter}}'{{#hasMore}},
{{/hasMore}}{{/vars}} {{/hasMore}}{{/vars}}
); );
/** @var string[] Array of attributes to getter functions (for serialization of requests) */ /**
* Array of attributes to getter functions (for serialization of requests)
* @var string[]
*/
static $getters = array( static $getters = array(
{{#vars}}'{{name}}' => '{{getter}}'{{#hasMore}}, {{#vars}}'{{name}}' => '{{getter}}'{{#hasMore}},
{{/hasMore}}{{/vars}} {{/hasMore}}{{/vars}}
); );
{{#vars}} {{#vars}}
/** @var {{datatype}} ${{name}} {{#description}}{{{description}}} {{/description}}*/ /**
* ${{name}} {{#description}}{{{description}}}{{/description}}
* @var {{datatype}}
*/
protected ${{name}}; protected ${{name}};
{{/vars}} {{/vars}}
public function __construct(array $data = null) {
/**
* Constructor
* @param mixed[] $data Associated array of property value initalizing the model
*/
public function __construct(array $data = null)
{
if ($data != null) { if ($data != null) {
{{#vars}}$this->{{name}} = $data["{{name}}"];{{#hasMore}} {{#vars}}$this->{{name}} = $data["{{name}}"];{{#hasMore}}
{{/hasMore}}{{/vars}} {{/hasMore}}{{/vars}}
@ -65,44 +105,80 @@ class {{classname}} implements ArrayAccess {
} }
{{#vars}} {{#vars}}
/** /**
* get {{name}} * Gets {{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}})
{
{{#isEnum}}$allowed_values = array({{#allowableValues}}{{#values}}"{{{this}}}"{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}});
if (!in_array(${{{name}}}, $allowed_values)) {
throw new \InvalidArgumentException("Invalid value for '{{name}}', must be one of {{#allowableValues}}{{#values}}'{{{this}}}'{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}");
}{{/isEnum}}
$this->{{name}} = ${{name}}; $this->{{name}} = ${{name}};
return $this; return $this;
} }
{{/vars}} {{/vars}}
public function offsetExists($offset) { /**
* Returns true if offset exists. False otherwise.
* @param integer $offset Offset
* @return boolean
*/
public function offsetExists($offset)
{
return isset($this->$offset); return isset($this->$offset);
} }
public function offsetGet($offset) { /**
* Gets offset.
* @param integer $offset Offset
* @return mixed
*/
public function offsetGet($offset)
{
return $this->$offset; return $this->$offset;
} }
public function offsetSet($offset, $value) { /**
* 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; $this->$offset = $value;
} }
public function offsetUnset($offset) { /**
* Unsets offset.
* @param integer $offset Offset
* @return void
*/
public function offsetUnset($offset)
{
unset($this->$offset); unset($this->$offset);
} }
public function __toString() { /**
* Gets the string presentation of the object
* @return string
*/
public function __toString()
{
if (defined('JSON_PRETTY_PRINT')) { if (defined('JSON_PRETTY_PRINT')) {
return json_encode($this, JSON_PRETTY_PRINT); return json_encode(get_object_vars($this), JSON_PRETTY_PRINT);
} else { } else {
return json_encode($this); return json_encode(get_object_vars($this));
} }
} }
} }

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: try:
value = attr_type(value) data = json.loads(response.data)
except UnicodeEncodeError: except ValueError:
value = unicode(value) data = response.data
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 return self.__deserialize(data, response_type)
def __parse_string_to_datetime(self, string): def __deserialize(self, data, klass):
""" """
Parse datetime in string to datetime. :param data: dict, list or str
:param klass: class literal, or string of class name
The string should be in iso8601 datetime format. :return: object
""" """
try: if data is None:
from dateutil.parser import parse return None
return parse(string)
except ImportError:
return string
def request(self, method, url, query_params=None, headers=None, post_params=None, body=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
if api_key.get(key) and api_key_prefix.get(key): def _singleton():
return api_key_prefix[key] + ' ' + api_key[key] if cls not in instances:
elif api_key.get(key): instances[cls] = cls(*args, **kw)
return api_key[key] return instances[cls]
return _singleton
def get_basic_auth_token():
global username
global password
return urllib3.util.make_headers(basic_auth=username + ':' + password).get('authorization') @singleton
class Configuration(object):
def auth_settings(): 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}} return { {{#authMethods}}{{#isApiKey}}
'{{name}}': { '{{name}}': {
'type': 'api_key', 'type': 'api_key',
'in': {{#isKeyInHeader}}'header'{{/isKeyInHeader}}{{#isKeyInQuery}}'query'{{/isKeyInQuery}}, 'in': {{#isKeyInHeader}}'header'{{/isKeyInHeader}}{{#isKeyInQuery}}'query'{{/isKeyInQuery}},
'key': '{{keyParamName}}', 'key': '{{keyParamName}}',
'value': get_api_key_with_prefix('{{keyParamName}}') 'value': self.get_api_key_with_prefix('{{keyParamName}}')
}, },
{{/isApiKey}}{{#isBasic}} {{/isApiKey}}{{#isBasic}}
'{{name}}': { '{{name}}': {
'type': 'basic', 'type': 'basic',
'in': 'header', 'in': 'header',
'key': 'Authorization', 'key': 'Authorization',
'value': get_basic_auth_token() 'value': self.get_basic_auth_token()
}, },
{{/isBasic}}{{/authMethods}} {{/isBasic}}{{/authMethods}}
} }
# Default Base url def to_debug_report(self):
host = "{{basePath}}" return "Python SDK Debug Report:\n"\
"OS: {env}\n"\
# Default api client "Python Version: {pyversion}\n"\
api_client = None "Version of the API: {{version}}\n"\
"SDK Package Version: {{packageVersion}}".format(env=sys.platform, pyversion=sys.version)
# 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):
if http_resp:
self.status = http_resp.status self.status = http_resp.status
self.reason = http_resp.reason self.reason = http_resp.reason
self.body = http_resp.data self.body = http_resp.data
self.headers = http_resp.getheaders() 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 end
# Construct a query string from the query-string-type params if Swagger.configuration.debug
def query_string Swagger.logger.debug "HTTP request body param ~BEGIN~\n#{data}\n~END~\n"
# 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 data
# if there aren't really any params
return "" if query_values.blank?
# Addressable requires query_values to be set after initialization..
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
Response.new(response)
end 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,7 +3,7 @@ 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

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