Merge branch 'feature/objc-sessionmanager' into feature/objc-sessionmanager-merge

* feature/objc-sessionmanager:
  updates templates with JSONModel workaround
  updates for ISO8601 0.5.1
  updates templates according to https://github.com/NYTimes/objective-c-style-guide
  first version of session manager
This commit is contained in:
Wolfgang Berger 2016-07-14 12:28:20 +02:00
commit 83e7cdb6a3
28 changed files with 2056 additions and 0 deletions

View File

@ -1,4 +1,35 @@
#import "{{classPrefix}}Object.h"
@implementation {{classPrefix}}Object
@implementation {{classPrefix}}Object
// workaround for JSONModel multithreading issues
// https://github.com/icanzilb/JSONModel/issues/441
- (instancetype)initWithDictionary:(NSDictionary *)dict error:(NSError **)err
{
static NSMutableSet *classNames;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
classNames = [NSMutableSet new];
});
BOOL initSync;
@synchronized([self class])
{
NSString *className = NSStringFromClass([self class]);
initSync = ![classNames containsObject:className];
if(initSync)
{
[classNames addObject:className];
self = [super initWithDictionary:dict error:err];
}
}
if(!initSync)
{
self = [super initWithDictionary:dict error:err];
}
return self;
}
@end

View File

@ -0,0 +1,74 @@
# Swagger Codegen for the ObjcSessionManager library
## Overview
This is a boiler-plate project to generate your own client library with Swagger. It's goal is
to get you started with the basic plumbing so you can put in your own logic. It won't work without
your changes applied.
## What's Swagger?
The goal of Swagger™ is to define a standard, language-agnostic interface to REST APIs which allows both humans and computers to discover and understand the capabilities of the service without access to source code, documentation, or through network traffic inspection. When properly defined via Swagger, a consumer can understand and interact with the remote service with a minimal amount of implementation logic. Similar to what interfaces have done for lower-level programming, Swagger removes the guesswork in calling the service.
Check out [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) for additional information about the Swagger project, including additional libraries with support for other languages and more.
## How do I use this?
At this point, you've likely generated a client setup. It will include something along these lines:
```
.
|- README.md // this file
|- pom.xml // build script
|-- src
|--- main
|---- java
|----- io.swagger.codegen.languages.ObjcsessionmanagerGenerator.java // generator file
|---- resources
|----- ObjcSessionManager // template files
|----- META-INF
|------ services
|------- io.swagger.codegen.CodegenConfig
```
You _will_ need to make changes in at least the following:
`ObjcsessionmanagerGenerator.java`
Templates in this folder:
`src/main/resources/ObjcSessionManager`
Once modified, you can run this:
```
mvn package
```
In your generator project. A single jar file will be produced in `target`. You can now use that with codegen:
```
java -cp /path/to/swagger-codegen-distribution:/path/to/your/jar io.swagger.codegen.Codegen -l ObjcSessionManager -o ./test
```
Now your templates are available to the client generator and you can write output values
## But how do I modify this?
The `ObjcsessionmanagerGenerator.java` has comments in it--lots of comments. There is no good substitute
for reading the code more, though. See how the `ObjcsessionmanagerGenerator` implements `CodegenConfig`.
That class has the signature of all values that can be overridden.
For the templates themselves, you have a number of values available to you for generation.
You can execute the `java` command from above while passing different debug flags to show
the object you have available during client generation:
```
# The following additional debug options are available for all codegen targets:
# -DdebugSwagger prints the OpenAPI Specification as interpreted by the codegen
# -DdebugModels prints models passed to the template engine
# -DdebugOperations prints operations passed to the template engine
# -DdebugSupportingFiles prints additional data passed to the template engine
java -DdebugOperations -cp /path/to/swagger-codegen-distribution:/path/to/your/jar io.swagger.codegen.Codegen -l ObjcSessionManager -o ./test
```
Will, for example, output the debug info for operations. You can use this info
in the `api.mustache` file.

View File

@ -0,0 +1,102 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.swagger</groupId>
<artifactId>ObjcSessionManager-swagger-codegen</artifactId>
<packaging>jar</packaging>
<name>ObjcSessionManager-swagger-codegen</name>
<version>1.0.0</version>
<prerequisites>
<maven>2.2.0</maven>
</prerequisites>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12</version>
<configuration>
<systemProperties>
<property>
<name>loggerPath</name>
<value>conf/log4j.properties</value>
</property>
</systemProperties>
<argLine>-Xms512m -Xmx1500m</argLine>
<parallel>methods</parallel>
<forkMode>pertest</forkMode>
</configuration>
</plugin>
<!-- attach test jar -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<goals>
<goal>jar</goal>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
<configuration>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add_sources</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/main/java</source>
</sources>
</configuration>
</execution>
<execution>
<id>add_test_sources</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/test/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-codegen</artifactId>
<version>${swagger-codegen-version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<properties>
<swagger-codegen-version>2.1.5</swagger-codegen-version>
<maven-plugin-version>1.0.0</maven-plugin-version>
<junit-version>4.8.1</junit-version>
</properties>
</project>

View File

@ -0,0 +1,515 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile;
import io.swagger.models.properties.*;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
public class ObjcSessionManagerGenerator extends DefaultCodegen implements CodegenConfig {
public static final String CLASS_PREFIX = "classPrefix";
public static final String POD_NAME = "podName";
public static final String AUTHOR_NAME = "authorName";
public static final String AUTHOR_EMAIL = "authorEmail";
public static final String GIT_REPO_URL = "gitRepoURL";
public static final String LICENSE = "license";
protected Set<String> foundationClasses = new HashSet<String>();
protected String podName = "SwaggerClient";
protected String podVersion = "1.0.0";
protected String classPrefix = "SWG";
protected String authorName = "Swagger";
protected String authorEmail = "apiteam@swagger.io";
protected String license = "MIT";
protected String gitRepoURL = "https://github.com/swagger-api/swagger-codegen";
protected String[] specialWords = {"new", "copy"};
public ObjcSessionManagerGenerator() {
super();
outputFolder = "generated-code" + File.separator + "ObjcSessionManager";
modelTemplateFiles.put("model-header.mustache", ".h");
modelTemplateFiles.put("model-body.mustache", ".m");
apiTemplateFiles.put("api-header.mustache", ".h");
apiTemplateFiles.put("api-body.mustache", ".m");
embeddedTemplateDir = templateDir = "ObjcSessionManager";
defaultIncludes.clear();
defaultIncludes.add("bool");
defaultIncludes.add("BOOL");
defaultIncludes.add("int");
defaultIncludes.add("NSURL");
defaultIncludes.add("NSString");
defaultIncludes.add("NSObject");
defaultIncludes.add("NSArray");
defaultIncludes.add("NSNumber");
defaultIncludes.add("NSDate");
defaultIncludes.add("NSDictionary");
defaultIncludes.add("NSMutableArray");
defaultIncludes.add("NSMutableDictionary");
languageSpecificPrimitives.clear();
languageSpecificPrimitives.add("NSNumber");
languageSpecificPrimitives.add("NSString");
languageSpecificPrimitives.add("NSObject");
languageSpecificPrimitives.add("NSDate");
languageSpecificPrimitives.add("NSURL");
languageSpecificPrimitives.add("bool");
languageSpecificPrimitives.add("BOOL");
typeMapping.clear();
typeMapping.put("enum", "NSString");
typeMapping.put("date", "NSDate");
typeMapping.put("DateTime", "NSDate");
typeMapping.put("boolean", "NSNumber");
typeMapping.put("string", "NSString");
typeMapping.put("integer", "NSNumber");
typeMapping.put("int", "NSNumber");
typeMapping.put("float", "NSNumber");
typeMapping.put("long", "NSNumber");
typeMapping.put("double", "NSNumber");
typeMapping.put("array", "NSArray");
typeMapping.put("map", "NSDictionary");
typeMapping.put("number", "NSNumber");
typeMapping.put("List", "NSArray");
typeMapping.put("object", "NSObject");
typeMapping.put("file", "NSURL");
// ref: http://www.tutorialspoint.com/objective_c/objective_c_basic_syntax.htm
reservedWords = new HashSet<String>(
Arrays.asList(
// local variable names in API methods (endpoints)
"resourcePath", "pathParams", "queryParams", "headerParams",
"responseContentType", "requestContentType", "authSettings",
"formParams", "files", "bodyParam",
// objc reserved words
"auto", "else", "long", "switch",
"break", "enum", "register", "typedef",
"case", "extern", "return", "union",
"char", "float", "short", "unsigned",
"const", "for", "signed", "void",
"continue", "goto", "sizeof", "volatile",
"default", "if", "id", "static", "while",
"do", "int", "struct", "_Packed",
"double", "protocol", "interface", "implementation",
"NSObject", "NSInteger", "NSNumber", "CGFloat",
"property", "nonatomic", "retain", "strong",
"weak", "unsafe_unretained", "readwrite", "readonly",
"description"
));
importMapping = new HashMap<String, String>();
foundationClasses = new HashSet<String>(
Arrays.asList(
"NSNumber",
"NSObject",
"NSString",
"NSDate",
"NSURL",
"NSDictionary")
);
instantiationTypes.put("array", "NSMutableArray");
instantiationTypes.put("map", "NSMutableDictionary");
cliOptions.clear();
cliOptions.add(new CliOption(CLASS_PREFIX, "prefix for generated classes (convention: Abbreviation of pod name e.g. `HN` for `HackerNews`).`")
.defaultValue("SWG"));
cliOptions.add(new CliOption(POD_NAME, "cocoapods package name (convention: CameCase).")
.defaultValue("SwaggerClient"));
cliOptions.add(new CliOption(CodegenConstants.POD_VERSION, "cocoapods package version.")
.defaultValue("1.0.0"));
cliOptions.add(new CliOption(AUTHOR_NAME, "Name to use in the podspec file.").defaultValue("Swagger"));
cliOptions.add(new CliOption(AUTHOR_EMAIL, "Email to use in the podspec file.").defaultValue("apiteam@swagger.io"));
cliOptions.add(new CliOption(GIT_REPO_URL, "URL for the git repo where this podspec should point to.")
.defaultValue("https://github.com/swagger-api/swagger-codegen"));
cliOptions.add(new CliOption(LICENSE, "License to use in the podspec file.").defaultValue("MIT"));
}
@Override
public CodegenType getTag() {
return CodegenType.CLIENT;
}
@Override
public String getName() {
return "objc-SessionManager";
}
@Override
public String getHelp() {
return "Generates an Objective-C client library.";
}
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey(POD_NAME)) {
setPodName((String) additionalProperties.get(POD_NAME));
}
if (additionalProperties.containsKey(CodegenConstants.POD_VERSION)) {
setPodVersion((String) additionalProperties.get(CodegenConstants.POD_VERSION));
}
if (additionalProperties.containsKey(CLASS_PREFIX)) {
setClassPrefix((String) additionalProperties.get(CLASS_PREFIX));
}
if (additionalProperties.containsKey(AUTHOR_NAME)) {
setAuthorName((String) additionalProperties.get(AUTHOR_NAME));
}
if (additionalProperties.containsKey(AUTHOR_EMAIL)) {
setAuthorEmail((String) additionalProperties.get(AUTHOR_EMAIL));
}
if (additionalProperties.containsKey(GIT_REPO_URL)) {
setGitRepoURL((String) additionalProperties.get(GIT_REPO_URL));
}
if (additionalProperties.containsKey(LICENSE)) {
setLicense((String) additionalProperties.get(LICENSE));
}
additionalProperties.put(POD_NAME, podName);
additionalProperties.put(CodegenConstants.POD_VERSION, podVersion);
additionalProperties.put(CLASS_PREFIX, classPrefix);
additionalProperties.put(AUTHOR_NAME, authorName);
additionalProperties.put(AUTHOR_EMAIL, authorEmail);
additionalProperties.put(GIT_REPO_URL, gitRepoURL);
additionalProperties.put(LICENSE, license);
String swaggerFolder = podName;
modelPackage = swaggerFolder;
apiPackage = swaggerFolder;
supportingFiles.add(new SupportingFile("Object-header.mustache", swaggerFolder, classPrefix + "Object.h"));
supportingFiles.add(new SupportingFile("Object-body.mustache", swaggerFolder, classPrefix + "Object.m"));
supportingFiles.add(new SupportingFile("QueryParamCollection-header.mustache", swaggerFolder, classPrefix + "QueryParamCollection.h"));
supportingFiles.add(new SupportingFile("QueryParamCollection-body.mustache", swaggerFolder, classPrefix + "QueryParamCollection.m"));
supportingFiles.add(new SupportingFile("ApiSessionManager-header.mustache", swaggerFolder, classPrefix + "ApiSessionManager.h"));
supportingFiles.add(new SupportingFile("ApiSessionManager-body.mustache", swaggerFolder, classPrefix + "ApiSessionManager.m"));
supportingFiles.add(new SupportingFile("JSONResponseSerializer-header.mustache", swaggerFolder, classPrefix + "JSONResponseSerializer.h"));
supportingFiles.add(new SupportingFile("JSONResponseSerializer-body.mustache", swaggerFolder, classPrefix + "JSONResponseSerializer.m"));
supportingFiles.add(new SupportingFile("JSONRequestSerializer-body.mustache", swaggerFolder, classPrefix + "JSONRequestSerializer.m"));
supportingFiles.add(new SupportingFile("JSONRequestSerializer-header.mustache", swaggerFolder, classPrefix + "JSONRequestSerializer.h"));
supportingFiles.add(new SupportingFile("JSONValueTransformer+ISO8601.m", swaggerFolder, "JSONValueTransformer+ISO8601.m"));
supportingFiles.add(new SupportingFile("JSONValueTransformer+ISO8601.h", swaggerFolder, "JSONValueTransformer+ISO8601.h"));
supportingFiles.add(new SupportingFile("Configuration-protocol.mustache", swaggerFolder, classPrefix + "Configuration.h"));
supportingFiles.add(new SupportingFile("DefaultConfiguration-body.mustache", swaggerFolder, classPrefix + "DefaultConfiguration.m"));
supportingFiles.add(new SupportingFile("DefaultConfiguration-header.mustache", swaggerFolder, classPrefix + "DefaultConfiguration.h"));
supportingFiles.add(new SupportingFile("BasicAuthTokenProvider-header.mustache", swaggerFolder, classPrefix + "BasicAuthTokenProvider.h"));
supportingFiles.add(new SupportingFile("BasicAuthTokenProvider-body.mustache", swaggerFolder, classPrefix + "BasicAuthTokenProvider.m"));
supportingFiles.add(new SupportingFile("podspec.mustache", "", podName + ".podspec"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
}
@Override
public String toInstantiationType(Property p) {
if (p instanceof MapProperty) {
return instantiationTypes.get("map");
} else if (p instanceof ArrayProperty) {
return instantiationTypes.get("array");
} else {
return null;
}
}
@Override
public String getTypeDeclaration(String name) {
if (languageSpecificPrimitives.contains(name) && !foundationClasses.contains(name)) {
return name;
} else {
return name + "*";
}
}
@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) && !foundationClasses.contains(type)) {
return toModelName(type);
}
} else {
type = swaggerType;
}
return toModelName(type);
}
@Override
public String getTypeDeclaration(Property p) {
if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems();
String innerType = getSwaggerType(inner);
String innerTypeDeclaration = getTypeDeclaration(inner);
if (innerTypeDeclaration.endsWith("*")) {
innerTypeDeclaration = innerTypeDeclaration.substring(0, innerTypeDeclaration.length() - 1);
}
// In this codition, type of property p is array of primitive,
// return container type with pointer, e.g. `NSArray* /* NSString */'
if (languageSpecificPrimitives.contains(innerType)) {
return getSwaggerType(p) + "*" + " /* " + innerTypeDeclaration + " */";
}
// In this codition, type of property p is array of model,
// return container type combine inner type with pointer, e.g. `NSArray<SWGTag>*'
else {
return getSwaggerType(p) + "<" + innerTypeDeclaration + ">*";
}
} else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();
String innerTypeDeclaration = getTypeDeclaration(inner);
if (innerTypeDeclaration.endsWith("*")) {
innerTypeDeclaration = innerTypeDeclaration.substring(0, innerTypeDeclaration.length() - 1);
}
return getSwaggerType(p) + "* /* NSString, " + innerTypeDeclaration + " */";
} else {
String swaggerType = getSwaggerType(p);
// In this codition, type of p is objective-c primitive type, e.g. `NSSNumber',
// return type of p with pointer, e.g. `NSNumber*'
if (languageSpecificPrimitives.contains(swaggerType) &&
foundationClasses.contains(swaggerType)) {
return swaggerType + "*";
}
// In this codition, type of p is c primitive type, e.g. `bool',
// return type of p, e.g. `bool'
else if (languageSpecificPrimitives.contains(swaggerType)) {
return swaggerType;
}
// In this codition, type of p is objective-c object type, e.g. `SWGPet',
// return type of p with pointer, e.g. `SWGPet*'
else {
return swaggerType + "*";
}
}
}
@Override
public String toModelName(String type) {
type = type.replaceAll("[^0-9a-zA-Z_]", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// language build-in classes
if (typeMapping.keySet().contains(type) ||
foundationClasses.contains(type) ||
importMapping.values().contains(type) ||
defaultIncludes.contains(type) ||
languageSpecificPrimitives.contains(type)) {
return camelize(type);
}
// custom classes
else {
return classPrefix + camelize(type);
}
}
@Override
public String toModelFilename(String name) {
// should be the same as the model name
return toModelName(name);
}
@Override
protected void setNonArrayMapProperty(CodegenProperty property, String type) {
super.setNonArrayMapProperty(property, type);
if ("NSDictionary".equals(type)) {
property.setter = "initWithDictionary";
} else {
property.setter = "initWithValues";
}
}
@Override
public String toModelImport(String name) {
return name;
}
@Override
public String apiFileFolder() {
return outputFolder + File.separatorChar + apiPackage();
}
@Override
public String modelFileFolder() {
return outputFolder + File.separatorChar + modelPackage();
}
@Override
public String toApiName(String name) {
return classPrefix + camelize(name) + "Api";
}
@Override
public String toApiFilename(String name) {
return classPrefix + camelize(name) + "Api";
}
@Override
public String toVarName(String name) {
// sanitize name
name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// if it's all upper case, do noting
if (name.matches("^[A-Z_]$")) {
return name;
}
// if name starting with special word, escape with '_'
for(int i =0; i < specialWords.length; i++) {
if (name.matches("(?i:^" + specialWords[i] + ".*)"))
name = escapeSpecialWord(name);
}
// camelize (lower first character) the variable name
// e.g. `pet_id` to `petId`
name = camelize(name, true);
// for reserved word or word starting with number, prepend `_`
if (reservedWords.contains(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name);
}
return name;
}
@Override
public String toParamName(String name) {
// should be the same as variable name
return toVarName(name);
}
@Override
public String escapeReservedWord(String name) {
return "_" + name;
}
@SuppressWarnings("static-method")
public String escapeSpecialWord(String name) {
return "var_" + name;
}
@Override
public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
// method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
}
return camelize(sanitizeName(operationId), true);
}
public void setClassPrefix(String classPrefix) {
this.classPrefix = classPrefix;
}
public void setPodName(String podName) {
this.podName = podName;
}
public void setPodVersion(String podVersion) {
this.podVersion = podVersion;
}
public void setAuthorEmail(String authorEmail) {
this.authorEmail = authorEmail;
}
public void setAuthorName(String authorName) {
this.authorName = authorName;
}
public void setGitRepoURL(String gitRepoURL) {
this.gitRepoURL = gitRepoURL;
}
public void setLicense(String license) {
this.license = license;
}
/**
* Return the default value of the property
*
* @param p Swagger property object
* @return string presentation of the default value of the property
*/
@Override
public String toDefaultValue(Property p) {
if (p instanceof StringProperty) {
StringProperty dp = (StringProperty) p;
if (dp.getDefault() != null) {
return "@\"" + dp.getDefault().toString() + "\"";
}
} else if (p instanceof BooleanProperty) {
BooleanProperty dp = (BooleanProperty) p;
if (dp.getDefault() != null) {
if (dp.getDefault().toString().equalsIgnoreCase("false"))
return "@0";
else
return "@1";
}
} else if (p instanceof DateProperty) {
// TODO
} else if (p instanceof DateTimeProperty) {
// TODO
} else if (p instanceof DoubleProperty) {
DoubleProperty dp = (DoubleProperty) p;
if (dp.getDefault() != null) {
return "@" + dp.getDefault().toString();
}
} else if (p instanceof FloatProperty) {
FloatProperty dp = (FloatProperty) p;
if (dp.getDefault() != null) {
return "@" + dp.getDefault().toString();
}
} else if (p instanceof IntegerProperty) {
IntegerProperty dp = (IntegerProperty) p;
if (dp.getDefault() != null) {
return "@" + dp.getDefault().toString();
}
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
if (dp.getDefault() != null) {
return "@" + dp.getDefault().toString();
}
}
return null;
}
}

View File

@ -0,0 +1 @@
io.swagger.codegen.languages.ObjcSessionManagerGenerator

View File

@ -0,0 +1,633 @@
#import <ISO8601/NSDate+ISO8601.h>
#import "{{classPrefix}}ApiSessionManager.h"
#import "{{classPrefix}}JSONRequestSerializer.h"
#import "{{classPrefix}}JSONResponseSerializer.h"
#import "{{classPrefix}}QueryParamCollection.h"
#import "{{classPrefix}}Object.h"
#import "{{classPrefix}}DefaultConfiguration.h"
#define {{classPrefix}}DebugLog(format, ...) [{{classPrefix}}ApiSessionManager debugLog:[NSString stringWithFormat:@"%s", __PRETTY_FUNCTION__] message: format, ##__VA_ARGS__];
NSString * const {{classPrefix}}ResponseObjectErrorKey = @"{{classPrefix}}ResponseObject";
@interface {{classPrefix}}ApiSessionManager ()
@property (nonatomic, strong, readwrite) id<{{classPrefix}}Configuration> configuration;
@end
@implementation {{classPrefix}}ApiSessionManager
- (instancetype)init {
return [self initWithConfiguration:[{{classPrefix}}DefaultConfiguration sharedConfiguration]];
}
- (instancetype)initWithBaseURL:(NSURL *)url {
return [self initWithBaseURL:url
configuration:[{{classPrefix}}DefaultConfiguration sharedConfiguration]];
}
- (instancetype)initWithConfiguration:(id<{{classPrefix}}Configuration>)configuration {
return [self initWithBaseURL:[NSURL URLWithString:configuration.host] configuration:configuration];
}
- (instancetype)initWithBaseURL:(NSURL *)url
configuration:(id<{{classPrefix}}Configuration>)configuration {
self = [super initWithBaseURL:url];
if (self) {
_configuration = configuration;
}
return self;
}
- (NSURLSessionTask *)requestWithCompletionBlock:(NSString *)path
method:(NSString *)method
pathParams:(NSDictionary *)pathParams
queryParams:(NSDictionary *)queryParams
formParams:(NSDictionary *)formParams
files:(NSDictionary *)files
body:(id)body
headerParams:(NSDictionary *)headerParams
authSettings:(NSArray *)authSettings
requestContentType:(NSString *)requestContentType
responseContentType:(NSString *)responseContentType
responseType:(NSString *)responseType
completionBlock:(void (^)(id, NSError *))completionBlock {
// setting request serializer
if ([requestContentType isEqualToString:@"application/json"]) {
self.requestSerializer = [{{classPrefix}}JSONRequestSerializer serializer];
}
else if ([requestContentType isEqualToString:@"application/x-www-form-urlencoded"]) {
self.requestSerializer = [AFHTTPRequestSerializer serializer];
}
else if ([requestContentType isEqualToString:@"multipart/form-data"]) {
self.requestSerializer = [AFHTTPRequestSerializer serializer];
}
else {
NSAssert(false, @"unsupport request type %@", requestContentType);
}
// setting response serializer
if ([responseContentType isEqualToString:@"application/json"]) {
self.responseSerializer = [{{classPrefix}}JSONResponseSerializer serializer];
}
else {
self.responseSerializer = [AFHTTPResponseSerializer serializer];
}
// sanitize parameters
pathParams = [self sanitizeForSerialization:pathParams];
queryParams = [self sanitizeForSerialization:queryParams];
headerParams = [self sanitizeForSerialization:headerParams];
formParams = [self sanitizeForSerialization:formParams];
body = [self sanitizeForSerialization:body];
// auth setting
[self updateHeaderParams:&headerParams queryParams:&queryParams WithAuthSettings:authSettings];
NSMutableString *resourcePath = [NSMutableString stringWithString:path];
[pathParams enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
[resourcePath replaceCharactersInRange:[resourcePath rangeOfString:[NSString stringWithFormat:@"%@%@%@", @"{", key, @"}"]]
withString:[{{classPrefix}}ApiSessionManager escape:obj]];
}];
NSMutableURLRequest * request = nil;
NSString* pathWithQueryParams = [self pathWithQueryParamsToString:resourcePath queryParams:queryParams];
if ([pathWithQueryParams hasPrefix:@"/"]) {
pathWithQueryParams = [pathWithQueryParams substringFromIndex:1];
}
NSString* urlString = [[NSURL URLWithString:pathWithQueryParams relativeToURL:self.baseURL] absoluteString];
if (files.count > 0) {
request = [self.requestSerializer multipartFormRequestWithMethod:@"POST"
URLString:urlString
parameters:nil
constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formParams enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
NSString *objString = [self parameterToString:obj];
NSData *data = [objString dataUsingEncoding:NSUTF8StringEncoding];
[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];
}
else {
if (formParams) {
request = [self.requestSerializer requestWithMethod:method
URLString:urlString
parameters:formParams
error:nil];
}
if (body) {
request = [self.requestSerializer requestWithMethod:method
URLString:urlString
parameters:body
error:nil];
}
}
// request cache
BOOL hasHeaderParams = false;
if (headerParams != nil && [headerParams count] > 0) {
hasHeaderParams = true;
}
if (self.configuration.offlineState) {
{{classPrefix}}DebugLog(@"%@ cache forced", resourcePath);
[request setCachePolicy:NSURLRequestReturnCacheDataDontLoad];
}
else if(!hasHeaderParams && [method isEqualToString:@"GET"] && self.configuration.cacheEnabled) {
{{classPrefix}}DebugLog(@"%@ cache enabled", resourcePath);
[request setCachePolicy:NSURLRequestUseProtocolCachePolicy];
}
else {
{{classPrefix}}DebugLog(@"%@ cache disabled", resourcePath);
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
}
if (hasHeaderParams) {
for(NSString * key in [headerParams keyEnumerator]) {
[request setValue:[headerParams valueForKey:key] forHTTPHeaderField:key];
}
}
[self.requestSerializer setValue:responseContentType forHTTPHeaderField:@"Accept"];
// Always disable cookies!
[request setHTTPShouldHandleCookies:NO];
NSURLSessionTask *task = nil;
if ([responseType isEqualToString:@"NSURL*"]) {
task = [self downloadTaskWithCompletionBlock:request completionBlock:^(id data, NSError *error) {
completionBlock(data, error);
}];
}
else {
task = [self taskWithCompletionBlock:request completionBlock:^(id data, NSError *error) {
completionBlock([self deserialize:data class:responseType], error);
}];
}
[task resume];
return task;
}
#pragma mark - Task Methods
- (NSURLSessionDataTask *) taskWithCompletionBlock: (NSURLRequest *)request
completionBlock: (void (^)(id, NSError *))completionBlock {
NSURLSessionDataTask *task = [self dataTaskWithRequest:request completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
if (error) {
NSMutableDictionary *userInfo = [error.userInfo mutableCopy];
if (responseObject) {
// Add in the (parsed) response body.
userInfo[{{classPrefix}}ResponseObjectErrorKey] = responseObject;
}
NSError *augmentedError = [error initWithDomain:error.domain code:error.code userInfo:userInfo];
completionBlock(nil, augmentedError);
} else {
completionBlock(responseObject, nil);
}
}];
return task;
}
- (NSURLSessionDownloadTask *) downloadTaskWithCompletionBlock: (NSURLRequest *)request
completionBlock: (void (^)(id, NSError *))completionBlock {
id<{{classPrefix}}Configuration> config = self.configuration;
NSURLSessionDownloadTask *task = [self downloadTaskWithRequest:request progress:nil destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
NSString *directory = nil;
if (config.tempFolderPath) {
directory = config.tempFolderPath;
}
else {
directory = NSTemporaryDirectory();
}
NSDictionary *headers = nil;
if ([response isKindOfClass:[NSHTTPURLResponse class]])
{
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
headers = httpResponse.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];
return file;
} completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
if (error) {
completionBlock(nil, error);
} else {
completionBlock(filePath, nil);
}
}];
return task;
}
#pragma mark - Serialization
- (void) updateHeaderParams:(NSDictionary *__autoreleasing *)headers
queryParams:(NSDictionary *__autoreleasing *)querys
WithAuthSettings:(NSArray *)authSettings {
if (!authSettings || [authSettings count] == 0) {
return;
}
NSMutableDictionary *headersWithAuth = [NSMutableDictionary dictionaryWithDictionary:*headers];
NSMutableDictionary *querysWithAuth = [NSMutableDictionary dictionaryWithDictionary:*querys];
id<{{classPrefix}}Configuration> config = self.configuration;
for (NSString *auth in authSettings) {
//NSDictionary *authSetting = [[config authSettings] objectForKey:auth];
NSDictionary *authSetting = config.authSettings[auth];
if (authSetting) {
if ([authSetting[@"in"] isEqualToString:@"header"]) {
[headersWithAuth setObject:authSetting[@"value"] forKey:authSetting[@"key"]];
}
else if ([authSetting[@"in"] isEqualToString:@"query"]) {
[querysWithAuth setObject:authSetting[@"value"] forKey:authSetting[@"key"]];
}
}
}
*headers = [NSDictionary dictionaryWithDictionary:headersWithAuth];
*querys = [NSDictionary dictionaryWithDictionary:querysWithAuth];
}
- (id)sanitizeForSerialization:(id)object {
if (object == nil) {
return nil;
}
else if ([object isKindOfClass:[NSString class]] || [object isKindOfClass:[NSNumber class]] || [object isKindOfClass:[{{classPrefix}}QueryParamCollection class]]) {
return object;
}
else if ([object isKindOfClass:[NSDate class]]) {
return [object ISO8601String];
}
else if ([object isKindOfClass:[NSArray class]]) {
NSArray *objectArray = object;
NSMutableArray *sanitizedObjs = [NSMutableArray arrayWithCapacity:[objectArray count]];
[object enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if (obj) {
[sanitizedObjs addObject:[self sanitizeForSerialization:obj]];
}
}];
return sanitizedObjs;
}
else if ([object isKindOfClass:[NSDictionary class]]) {
NSDictionary *objectDict = object;
NSMutableDictionary *sanitizedObjs = [NSMutableDictionary dictionaryWithCapacity:[objectDict count]];
[object enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
if (obj) {
[sanitizedObjs setValue:[self sanitizeForSerialization:obj] forKey:key];
}
}];
return sanitizedObjs;
}
else if ([object isKindOfClass:[{{classPrefix}}Object class]]) {
return [object toDictionary];
}
else {
NSException *e = [NSException
exceptionWithName:@"InvalidObjectArgumentException"
reason:[NSString stringWithFormat:@"*** The argument object: %@ is invalid", object]
userInfo:nil];
@throw e;
}
}
- (id)deserialize:(id)data class:(NSString *)class {
NSRegularExpression *regexp = nil;
NSTextCheckingResult *match = nil;
NSMutableArray *resultArray = nil;
NSMutableDictionary *resultDict = nil;
NSString *innerType = nil;
// return nil if data is nil or class is nil
if (!data || !class) {
return nil;
}
// remove "*" from class, if ends with "*"
if ([class hasSuffix:@"*"]) {
class = [class substringToIndex:[class length] - 1];
}
// pure object
if ([class isEqualToString:@"NSObject"]) {
return data;
}
// list of models
NSString *arrayOfModelsPat = @"NSArray<(.+)>";
regexp = [NSRegularExpression regularExpressionWithPattern:arrayOfModelsPat
options:NSRegularExpressionCaseInsensitive
error:nil];
match = [regexp firstMatchInString:class
options:0
range:NSMakeRange(0, [class length])];
if (match) {
NSArray *dataArray = data;
innerType = [class substringWithRange:[match rangeAtIndex:1]];
resultArray = [NSMutableArray arrayWithCapacity:[dataArray count]];
[data enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[resultArray addObject:[self deserialize:obj class:innerType]];
}
];
return resultArray;
}
// list of primitives
NSString *arrayOfPrimitivesPat = @"NSArray\\* /\\* (.+) \\*/";
regexp = [NSRegularExpression regularExpressionWithPattern:arrayOfPrimitivesPat
options:NSRegularExpressionCaseInsensitive
error:nil];
match = [regexp firstMatchInString:class
options:0
range:NSMakeRange(0, [class length])];
if (match) {
NSArray *dataArray = data;
innerType = [class substringWithRange:[match rangeAtIndex:1]];
resultArray = [NSMutableArray arrayWithCapacity:[dataArray count]];
[data enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[resultArray addObject:[self deserialize:obj class:innerType]];
}];
return resultArray;
}
// map
NSString *dictPat = @"NSDictionary\\* /\\* (.+?), (.+) \\*/";
regexp = [NSRegularExpression regularExpressionWithPattern:dictPat
options:NSRegularExpressionCaseInsensitive
error:nil];
match = [regexp firstMatchInString:class
options:0
range:NSMakeRange(0, [class length])];
if (match) {
NSDictionary *dataDict = data;
NSString *valueType = [class substringWithRange:[match rangeAtIndex:2]];
resultDict = [NSMutableDictionary dictionaryWithCapacity:[dataDict count]];
[data enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
[resultDict setValue:[self deserialize:obj class:valueType] forKey:key];
}];
return resultDict;
}
// primitives
NSArray *primitiveTypes = @[@"NSString", @"NSDate", @"NSNumber"];
if ([primitiveTypes containsObject:class]) {
if ([class isEqualToString:@"NSString"]) {
return [NSString stringWithString:data];
}
else if ([class isEqualToString:@"NSDate"]) {
return [NSDate dateWithISO8601String:data];
}
else if ([class isEqualToString:@"NSNumber"]) {
// NSNumber from NSNumber
if ([data isKindOfClass:[NSNumber class]]) {
return data;
}
else if ([data isKindOfClass:[NSString class]]) {
// NSNumber (NSCFBoolean) from NSString
if ([[data lowercaseString] isEqualToString:@"true"] || [[data lowercaseString] isEqualToString:@"false"]) {
return [NSNumber numberWithBool:[data boolValue]];
// NSNumber from NSString
} else {
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = NSNumberFormatterDecimalStyle;
return [formatter numberFromString:data];
}
}
}
}
// model
Class ModelClass = NSClassFromString(class);
if ([ModelClass instancesRespondToSelector:@selector(initWithDictionary:error:)]) {
return [[ModelClass alloc] initWithDictionary:data error:nil];
}
return nil;
}
- (NSString *)pathWithQueryParamsToString:(NSString *)path
queryParams:(NSDictionary *)queryParams {
NSString * separator = nil;
int counter = 0;
NSMutableString * requestUrl = [NSMutableString stringWithFormat:@"%@", path];
if (queryParams != nil){
for(NSString * key in [queryParams keyEnumerator]){
if (counter == 0) separator = @"?";
else separator = @"&";
id queryParam = [queryParams valueForKey:key];
if ([queryParam isKindOfClass:[NSString class]]){
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator,
[{{classPrefix}}ApiSessionManager escape:key], [{{classPrefix}}ApiSessionManager escape:[queryParams valueForKey:key]]]];
}
else if ([queryParam isKindOfClass:[{{classPrefix}}QueryParamCollection class]]){
{{classPrefix}}QueryParamCollection * coll = ({{classPrefix}}QueryParamCollection*) queryParam;
NSArray* values = [coll values];
NSString* format = [coll format];
if ([format isEqualToString:@"csv"]) {
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator,
[{{classPrefix}}ApiSessionManager escape:key], [NSString stringWithFormat:@"%@", [values componentsJoinedByString:@","]]]];
}
else if ([format isEqualToString:@"tsv"]) {
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator,
[{{classPrefix}}ApiSessionManager escape:key], [NSString stringWithFormat:@"%@", [values componentsJoinedByString:@"\t"]]]];
}
else if ([format isEqualToString:@"pipes"]) {
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator,
[{{classPrefix}}ApiSessionManager escape:key], [NSString stringWithFormat:@"%@", [values componentsJoinedByString:@"|"]]]];
}
else if ([format isEqualToString:@"multi"]) {
for(id obj in values) {
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator,
[{{classPrefix}}ApiSessionManager escape:key], [NSString stringWithFormat:@"%@", obj]]];
counter += 1;
}
}
}
else {
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator,
[{{classPrefix}}ApiSessionManager escape:key], [NSString stringWithFormat:@"%@", [queryParams valueForKey:key]]]];
}
counter += 1;
}
}
return requestUrl;
}
- (NSString *)parameterToString:(id)param {
if ([param isKindOfClass:[NSString class]]) {
return param;
}
else if ([param isKindOfClass:[NSNumber class]]) {
return [param stringValue];
}
else if ([param isKindOfClass:[NSDate class]]) {
return [param ISO8601String];
}
else if ([param isKindOfClass:[NSArray class]]) {
NSMutableArray *mutableParam;
[param enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[mutableParam addObject:[self parameterToString:obj]];
}];
return [mutableParam componentsJoinedByString:@","];
}
else {
NSException *e = [NSException
exceptionWithName:@"InvalidObjectArgumentException"
reason:[NSString stringWithFormat:@"*** The argument object: %@ is invalid", param]
userInfo:nil];
@throw e;
}
}
#pragma mark - Utility Methods
/*
* Detect `Accept` from accepts
*/
+ (NSString *)selectHeaderAccept:(NSArray *)accepts {
if (accepts == nil || [accepts count] == 0) {
return @"";
}
NSMutableArray *lowerAccepts = [[NSMutableArray alloc] initWithCapacity:[accepts count]];
for (NSString *string in accepts) {
NSString * lowerAccept = [string lowercaseString];
if ([lowerAccept containsString:@"application/json"]) {
return @"application/json";
}
[lowerAccepts addObject:lowerAccept];
}
if (lowerAccepts.count == 1) {
return [lowerAccepts firstObject];
}
return [lowerAccepts componentsJoinedByString:@", "];
}
/*
* Detect `Content-Type` from contentTypes
*/
+ (NSString *)selectHeaderContentType:(NSArray *)contentTypes {
if (contentTypes == nil || [contentTypes count] == 0) {
return @"application/json";
}
NSMutableArray *lowerContentTypes = [[NSMutableArray alloc] initWithCapacity:[contentTypes count]];
[contentTypes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[lowerContentTypes addObject:[obj lowercaseString]];
}];
if ([lowerContentTypes containsObject:@"application/json"]) {
return @"application/json";
}
else {
return lowerContentTypes[0];
}
}
+ (NSString*)escape:(id)unescaped {
if ([unescaped isKindOfClass:[NSString class]]){
return (NSString *)CFBridgingRelease
(CFURLCreateStringByAddingPercentEscapes(
NULL,
(__bridge CFStringRef) unescaped,
NULL,
(CFStringRef)@"!*'();:@&=+$,/?%#[]",
kCFStringEncodingUTF8));
}
else {
return [NSString stringWithFormat:@"%@", unescaped];
}
}
#pragma mark - Log Methods
+ (void)debugLog:(NSString *)method
message:(NSString *)format, ... {
NSMutableString *message = [NSMutableString stringWithCapacity:1];
if (method) {
[message appendString:[NSString stringWithFormat:@"%@: ", method]];
}
va_list args;
va_start(args, format);
[message appendString:[[NSString alloc] initWithFormat:format arguments:args]];
NSLog(@"%@", message);
va_end(args);
}
@end

View File

@ -0,0 +1,72 @@
/**
* 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.
*/
#import <AFNetworking/AFNetworking.h>
#import "{{classPrefix}}Configuration.h"
/**
* A key for `NSError` user info dictionaries.
*
* The corresponding value is the parsed response body for an HTTP error.
*/
extern NSString *const {{classPrefix}}ResponseObjectErrorKey;
@interface {{classPrefix}}ApiSessionManager : AFHTTPSessionManager
@property (nonatomic, strong, readonly) id<{{classPrefix}}Configuration> configuration;
- (instancetype)initWithConfiguration:(id<{{classPrefix}}Configuration>)configuration;
/**
* Performs request
*
* @param path Request url.
* @param method Request method.
* @param pathParams Request path parameters.
* @param queryParams Request query parameters.
* @param body Request body.
* @param headerParams Request header parameters.
* @param authSettings Request authentication names.
* @param requestContentType Request content-type.
* @param responseContentType Response content-type.
* @param completionBlock The block will be executed when the request completed.
*
* @return The created session task.
*/
- (NSURLSessionTask *)requestWithCompletionBlock:(NSString*)path
method:(NSString*) method
pathParams:(NSDictionary *)pathParams
queryParams:(NSDictionary*)queryParams
formParams:(NSDictionary *)formParams
files:(NSDictionary *)files
body:(id)body
headerParams:(NSDictionary *)headerParams
authSettings: (NSArray *)authSettings
requestContentType:(NSString *)requestContentType
responseContentType:(NSString *)responseContentType
responseType:(NSString *)responseType
completionBlock:(void (^)(id, NSError *))completionBlock;
/**
* Detects Accept header from accepts NSArray
*
* @param accepts NSArray of header
*
* @return The Accept header
*/
+ (NSString *)selectHeaderAccept:(NSArray *)accepts;
/**
* Detects Content-Type header from contentTypes NSArray
*
* @param contentTypes NSArray of header
*
* @return The Content-Type header
*/
+ (NSString *)selectHeaderContentType:(NSArray *)contentTypes;
@end

View File

@ -0,0 +1,14 @@
#import "{{classPrefix}}BasicAuthTokenProvider.h"
@implementation {{classPrefix}}BasicAuthTokenProvider
+ (NSString *)createBasicAuthTokenWithUsername:(NSString *)username password:(NSString *)password {
NSString *basicAuthCredentials = [NSString stringWithFormat:@"%@:%@", username, password];
NSData *data = [basicAuthCredentials dataUsingEncoding:NSUTF8StringEncoding];
basicAuthCredentials = [NSString stringWithFormat:@"Basic %@", [data base64EncodedStringWithOptions:0]];
return basicAuthCredentials;
}
@end

View File

@ -0,0 +1,14 @@
/** The `{{classPrefix}}BasicAuthTokenProvider` class creates a basic auth token from username and password.
*
* 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.
*/
#import <Foundation/Foundation.h>
@interface {{classPrefix}}BasicAuthTokenProvider : NSObject
+ (NSString *)createBasicAuthTokenWithUsername:(NSString *)username password:(NSString *)password;
@end

View File

@ -0,0 +1,23 @@
/** The `{{classPrefix}}Configuration` protocol defines the interface of a configuration object for the sdk.
*
* 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.
*/
#import <Foundation/Foundation.h>
@protocol {{classPrefix}}Configuration <NSObject>
@property (nonatomic, readonly) BOOL debug;
@property (nonatomic, readonly) BOOL cacheEnabled;
@property (nonatomic, readonly) BOOL offlineState;
@property (nonatomic, readonly) NSString *tempFolderPath;
@property (nonatomic, readonly) NSDictionary *authSettings;
@property (nonatomic, readonly) NSString *host;
@property (nonatomic, readonly) NSString *username;
@property (nonatomic, readonly) NSString *password;
@end

View File

@ -0,0 +1,39 @@
#import "{{classPrefix}}DefaultConfiguration.h"
@implementation {{classPrefix}}DefaultConfiguration
#pragma mark - Singletion Methods
+ (instancetype)sharedConfiguration {
static {{classPrefix}}DefaultConfiguration *shardConfig = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
shardConfig = [[self alloc] init];
});
return shardConfig;
}
#pragma mark - Initialize Methods
- (instancetype)init {
self = [super init];
if (self) {
_host = @"{{basePath}}";
_username = @"";
_password = @"";
_tempFolderPath = nil;
_debug = NO;
_cacheEnabled = YES;
_offlineState = NO;
}
return self;
}
#pragma mark -
- (NSDictionary *) authSettings {
return @{};
}
@end

View File

@ -0,0 +1,26 @@
/** The `{{classPrefix}}Configuration` class provides a default implementation of the configuration protocol for the sdk.
*
* 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.
*/
#import <Foundation/Foundation.h>
#import "{{classPrefix}}Configuration.h"
@interface {{classPrefix}}DefaultConfiguration : NSObject <{{classPrefix}}Configuration>
+ ({{classPrefix}}DefaultConfiguration *)sharedConfiguration;
@property (nonatomic, assign) BOOL debug;
@property (nonatomic, assign) BOOL cacheEnabled;
@property (nonatomic, assign) BOOL offlineState;
@property (nonatomic, strong) NSString *host;
@property (nonatomic, strong) NSString *username;
@property (nonatomic, strong) NSString *password;
@property (nonatomic, strong) NSString *tempFolderPath;
@end

View File

@ -0,0 +1,36 @@
#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

@ -0,0 +1,39 @@
#import "{{classPrefix}}JSONResponseSerializer.h"
static BOOL JSONParseError(NSError *error) {
if ([error.domain isEqualToString:NSCocoaErrorDomain] && error.code == 3840) {
return YES;
}
return NO;
}
@implementation {{classPrefix}}JSONResponseSerializer
///
/// When customize a response serializer,
/// the serializer must conform the protocol `AFURLResponseSerialization`
/// and implements the protocol method `responseObjectForResponse:error:`
///
/// @param response The response to be processed.
/// @param data The response data to be decoded.
/// @param error The error that occurred while attempting to decode the respnse data.
///
/// @return The object decoded from the specified response data.
///
- (id)responseObjectForResponse:(NSURLResponse *)response
data:(NSData *)data
error:(NSError *__autoreleasing *)error {
NSDictionary *responseJson = [super responseObjectForResponse:response data:data error:error];
// if response data is not a valid json, return string of data.
if (JSONParseError(*error)) {
*error = nil;
NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return responseString;
}
return responseJson;
}
@end

View File

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

View File

@ -0,0 +1,5 @@
#import <Foundation/Foundation.h>
#import <JSONModel/JSONValueTransformer.h>
@interface JSONValueTransformer (ISO8601)
@end

View File

@ -0,0 +1,10 @@
#import <ISO8601/NSDate+ISO8601.h>
#import "JSONValueTransformer+ISO8601.h"
@implementation JSONValueTransformer (ISO8601)
- (NSDate *)NSDateFromNSString:(NSString *)string {
return [NSDate dateWithISO8601String:string];
}
@end

View File

@ -0,0 +1,33 @@
#import "{{classPrefix}}Object.h"
@implementation {{classPrefix}}Object
// workaround for JSONModel multithreading issues
// https://github.com/icanzilb/JSONModel/issues/441
- (instancetype)initWithDictionary:(NSDictionary *)dict error:(NSError **)err
{
static NSMutableSet *classNames;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
classNames = [NSMutableSet new];
});
BOOL initSync;
@synchronized([self class])
{
NSString *className = NSStringFromClass([self class]);
initSync = ![classNames containsObject:className];
if(initSync)
{
[classNames addObject:className];
self = [super initWithDictionary:dict error:err];
}
}
if(!initSync)
{
self = [super initWithDictionary:dict error:err];
}
return self;
}
@end

View File

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

View File

@ -0,0 +1,24 @@
#import "{{classPrefix}}QueryParamCollection.h"
@interface {{classPrefix}}QueryParamCollection ()
@property (nonatomic, strong) NSArray * values;
@property (nonatomic, strong) NSString * format;
@end
@implementation {{classPrefix}}QueryParamCollection
- (id)initWithValuesAndFormat:(NSArray *)values
format:(NSString *)format {
self = [super init];
if (self) {
_values = values;
_format = format;
}
return self;
}
@end

View File

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

View File

@ -0,0 +1,23 @@
# {{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"
```
## Recommendation
It's recommended to create an instance of ApiClient per thread in a multithreaded environment to avoid any potential issue.
## Author
{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}}
{{/hasMore}}{{/apis}}{{/apiInfo}}

View File

@ -0,0 +1,153 @@
{{#operations}}
#import "{{classname}}.h"
#import "{{classPrefix}}QueryParamCollection.h"
{{#imports}}#import "{{import}}.h"
{{/imports}}
{{newline}}
@interface {{classname}} ()
@property (nonatomic, strong, readwrite) {{classPrefix}}ApiSessionManager *sessionManager;
@property (nonatomic, strong, readwrite) NSMutableDictionary *defaultHeaders;
@end
@implementation {{classname}}
#pragma mark - Initialize methods
- (id)initWithSessionManager:({{classPrefix}}ApiSessionManager *)sessionManager {
self = [super init];
if (self) {
_sessionManager = sessionManager;
_defaultHeaders = [NSMutableDictionary dictionary];
}
return self;
}
#pragma mark -
- (void)addHeader:(NSString *)value forKey:(NSString *)key {
[self.defaultHeaders setValue:value forKey:key];
}
#pragma mark - Api Methods
{{#operation}}
///
/// {{{summary}}}
/// {{{notes}}}
/// {{#allParams}} @param {{paramName}} {{{description}}}
///
/// {{/allParams}} @returns {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}
///
- (NSURLSessionTask *){{nickname}}WithCompletionBlock{{^allParams}}: {{/allParams}}{{#allParams}}{{#secondaryParam}} {{paramName}}{{/secondaryParam}}: ({{{dataType}}}) {{paramName}}
{{/allParams}}
{{#returnBaseType}}{{#hasParams}}completionHandler: {{/hasParams}}(void (^)({{{returnType}}} output, NSError* error))completionBlock { {{/returnBaseType}}
{{^returnBaseType}}{{#hasParams}}completionHandler: {{/hasParams}}(void (^)(NSError* error))completionBlock { {{/returnBaseType}}
{{#allParams}}{{#required}}
// verify the required parameter '{{paramName}}' is set
if ({{paramName}} == nil) {
[NSException raise:@"Invalid parameter" format:@"Missing the required parameter `{{paramName}}` when calling `{{nickname}}`"];
}
{{/required}}{{/allParams}}
NSMutableString* resourcePath = [NSMutableString stringWithFormat:@"{{path}}"];
// remove format in URL if needed
if ([resourcePath rangeOfString:@".{format}"].location != NSNotFound) {
[resourcePath replaceCharactersInRange: [resourcePath rangeOfString:@".{format}"] withString:@".json"];
}
NSMutableDictionary *pathParams = [[NSMutableDictionary alloc] init];
{{#pathParams}}if ({{paramName}} != nil) {
pathParams[@"{{baseName}}"] = {{paramName}};
}
{{/pathParams}}
NSMutableDictionary* queryParams = [[NSMutableDictionary alloc] init];
{{#queryParams}}if ({{paramName}} != nil) {
{{#collectionFormat}}
queryParams[@"{{baseName}}"] = [[{{classPrefix}}QueryParamCollection alloc] initWithValuesAndFormat: {{baseName}} format: @"{{collectionFormat}}"];
{{/collectionFormat}}
{{^collectionFormat}}queryParams[@"{{baseName}}"] = {{paramName}};{{/collectionFormat}}
}
{{/queryParams}}
NSMutableDictionary* headerParams = [NSMutableDictionary dictionaryWithDictionary:self.defaultHeaders];
{{#headerParams}}if ({{paramName}} != nil) {
headerParams[@"{{baseName}}"] = {{paramName}};
}
{{/headerParams}}
// HTTP header `Accept`
headerParams[@"Accept"] = [{{classPrefix}}ApiSessionManager selectHeaderAccept:@[{{#produces}}@"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/produces}}]];
if ([headerParams[@"Accept"] length] == 0) {
[headerParams removeObjectForKey:@"Accept"];
}
// response content type
NSString *responseContentType;
if ([headerParams objectForKey:@"Accept"]) {
responseContentType = [headerParams[@"Accept"] componentsSeparatedByString:@", "][0];
}
else {
responseContentType = @"";
}
// request content type
NSString *requestContentType = [{{classPrefix}}ApiSessionManager selectHeaderContentType:@[{{#consumes}}@"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/consumes}}]];
// Authentication setting
NSArray *authSettings = @[{{#authMethods}}@"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}}];
id bodyParam = nil;
NSMutableDictionary *formParams = [[NSMutableDictionary alloc] init];
NSMutableDictionary *files = [[NSMutableDictionary alloc] init];
{{#bodyParam}}
bodyParam = {{paramName}};
{{/bodyParam}}{{^bodyParam}}
{{#formParams}}
{{#notFile}}
if ({{paramName}}) {
formParams[@"{{baseName}}"] = {{paramName}};
}
{{/notFile}}{{#isFile}}
files[@"{{paramName}}"] = {{paramName}};
{{/isFile}}
{{/formParams}}
{{/bodyParam}}
{{#requiredParamCount}}
{{#requiredParams}}
if ({{paramName}} == nil) {
// error
}
{{/requiredParams}}
{{/requiredParamCount}}
return [self.sessionManager requestWithCompletionBlock: resourcePath
method: @"{{httpMethod}}"
pathParams: pathParams
queryParams: queryParams
formParams: formParams
files: files
body: bodyParam
headerParams: headerParams
authSettings: authSettings
requestContentType: requestContentType
responseContentType: responseContentType
responseType: {{^returnType}}nil{{/returnType}}{{#returnType}}@"{{{ returnType }}}"{{/returnType}}
completionBlock: ^(id data, NSError *error) {
{{^returnType}}completionBlock(error);{{/returnType}}
{{#returnType}}completionBlock(({{{ returnType }}})data, error);{{/returnType}}
}
];
}
{{/operation}}
{{newline}}
{{/operations}}
@end

View File

@ -0,0 +1,42 @@
#import <Foundation/Foundation.h>
{{#imports}}#import "{{import}}.h"
{{/imports}}
#import "{{classPrefix}}ApiSessionManager.h"
{{newline}}
/**
* 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.
*/
{{#operations}}
@interface {{classname}}: NSObject
@property (nonatomic, strong, readonly) {{classPrefix}}ApiSessionManager *sessionManager;
- (instancetype)initWithSessionManager:({{classPrefix}}ApiSessionManager *)sessionManager;
- (void)addHeader:(NSString *)value forKey:(NSString *)key;
{{#operation}}
///
///
/// {{{summary}}}
/// {{#notes}}{{{notes}}}{{/notes}}
///
/// {{#allParams}}@param {{paramName}} {{description}}
/// {{/allParams}}
///
/// @return {{{returnType}}}
- (NSURLSessionTask *){{nickname}}WithCompletionBlock {{^allParams}}:{{/allParams}}{{#allParams}}{{#secondaryParam}} {{paramName}}{{/secondaryParam}}:({{{dataType}}}){{paramName}} {{#hasMore}}
{{/hasMore}}{{/allParams}}
{{#returnBaseType}}{{#hasParams}}
completionHandler:{{/hasParams}}(void (^)({{{returnType}}} output, NSError *error))completionBlock;{{/returnBaseType}}
{{^returnBaseType}}{{#hasParams}}
completionHandler: {{/hasParams}}(void (^)(NSError * error))completionBlock;{{/returnBaseType}}
{{newline}}
{{/operation}}
{{/operations}}
@end

View File

@ -0,0 +1,55 @@
{{#models}}
{{#model}}
#import "{{classname}}.h"
@implementation {{classname}}
- (instancetype)init {
self = [super init];
if (self) {
// initalise property's default value, if any
{{#vars}}{{#defaultValue}}self.{{name}} = {{{defaultValue}}};
{{/defaultValue}}{{/vars}}
}
return self;
}
/**
* Maps json key to property name.
* This method is used by `JSONModel`.
*/
+ (JSONKeyMapper *)keyMapper
{
return [[JSONKeyMapper alloc] initWithDictionary:@{ {{#vars}}@"{{baseName}}": @"{{name}}"{{#hasMore}}, {{/hasMore}}{{/vars}} }];
}
/**
* Indicates whether the property with the given name is optional.
* If `propertyName` is optional, then return `YES`, otherwise return `NO`.
* This method is used by `JSONModel`.
*/
+ (BOOL)propertyIsOptional:(NSString *)propertyName
{
NSArray *optionalProperties = @[{{#vars}}{{^required}}@"{{name}}"{{#hasMore}}, {{/hasMore}}{{/required}}{{/vars}}];
if ([optionalProperties containsObject:propertyName]) {
return YES;
}
else {
return NO;
}
}
/**
* Gets the string presentation of the object.
* This method will be called when logging model object using `NSLog`.
*/
- (NSString *)description {
return [[self toDictionary] description];
}
{{/model}}
@end
{{/models}}

View File

@ -0,0 +1,29 @@
#import <Foundation/Foundation.h>
#import "{{classPrefix}}Object.h"
/**
* 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.
*/
{{#imports}}#import "{{import}}.h"
{{/imports}}
{{newline}}
{{#models}}
{{#model}}
@protocol {{classname}}
@end
@interface {{classname}} : {{#parent}}{{{parent}}}{{/parent}}{{^parent}}{{classPrefix}}Object{{/parent}}
{{#vars}}
{{#description}}/* {{{description}}} {{^required}}[optional]{{/required}}
*/{{/description}}
@property(nonatomic) {{{ datatype }}} {{name}};
{{/vars}}
@end
{{/model}}
{{/models}}

View File

@ -0,0 +1,36 @@
#
# 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.homepage = "{{gitRepoURL}}"
s.license = "{{license}}"
s.source = { :git => "{{gitRepoURL}}.git", :tag => "#{s.version}" }
s.author = { "{{authorName}}" => "{{authorEmail}}" }
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