From 23d714f2f1374629bad91f929348b3da030d3911 Mon Sep 17 00:00:00 2001 From: kubo_takaichi Date: Wed, 13 May 2015 22:51:14 +0900 Subject: [PATCH] Add swift code generator --- bin/swift-petstore.sh | 31 +++ .../codegen/languages/SwiftGenerator.java | 249 ++++++++++++++++++ .../com.wordnik.swagger.codegen.CodegenConfig | 1 + .../main/resources/swift/APIHelper.mustache | 21 ++ .../src/main/resources/swift/APIs.mustache | 51 ++++ .../swift/AlamofireImplementations.mustache | 73 +++++ .../main/resources/swift/Cartfile.mustache | 2 + .../main/resources/swift/Extensions.mustache | 111 ++++++++ .../src/main/resources/swift/Models.mustache | 47 ++++ .../src/main/resources/swift/api.mustache | 50 ++++ .../src/main/resources/swift/model.mustache | 46 ++++ .../petstore/swift/PetstoreClient/Cartfile | 2 + 12 files changed, 684 insertions(+) create mode 100755 bin/swift-petstore.sh create mode 100644 modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/SwiftGenerator.java create mode 100644 modules/swagger-codegen/src/main/resources/swift/APIHelper.mustache create mode 100644 modules/swagger-codegen/src/main/resources/swift/APIs.mustache create mode 100644 modules/swagger-codegen/src/main/resources/swift/AlamofireImplementations.mustache create mode 100644 modules/swagger-codegen/src/main/resources/swift/Cartfile.mustache create mode 100644 modules/swagger-codegen/src/main/resources/swift/Extensions.mustache create mode 100644 modules/swagger-codegen/src/main/resources/swift/Models.mustache create mode 100644 modules/swagger-codegen/src/main/resources/swift/api.mustache create mode 100644 modules/swagger-codegen/src/main/resources/swift/model.mustache create mode 100644 samples/client/petstore/swift/PetstoreClient/Cartfile diff --git a/bin/swift-petstore.sh b/bin/swift-petstore.sh new file mode 100755 index 000000000000..ce6a7e702f00 --- /dev/null +++ b/bin/swift-petstore.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +SCRIPT="$0" + +while [ -h "$SCRIPT" ] ; do + ls=`ls -ld "$SCRIPT"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + SCRIPT="$link" + else + SCRIPT=`dirname "$SCRIPT"`/"$link" + fi +done + +if [ ! -d "${APP_DIR}" ]; then + APP_DIR=`dirname "$SCRIPT"`/.. + APP_DIR=`cd "${APP_DIR}"; pwd` +fi + +executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar" + +if [ ! -f "$executable" ] +then + mvn clean package +fi + +# if you've executed sbt assembly previously it will use that instead. +export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" +ags="$@ generate -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" + +java -DappName=PetstoreClient $JAVA_OPTS -jar $executable $ags diff --git a/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/SwiftGenerator.java b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/SwiftGenerator.java new file mode 100644 index 000000000000..39a71449d5ed --- /dev/null +++ b/modules/swagger-codegen/src/main/java/com/wordnik/swagger/codegen/languages/SwiftGenerator.java @@ -0,0 +1,249 @@ +package com.wordnik.swagger.codegen.languages; + +import com.google.common.base.Predicate; +import com.google.common.collect.Iterators; +import com.google.common.collect.Lists; +import com.wordnik.swagger.codegen.*; +import com.wordnik.swagger.models.Model; +import com.wordnik.swagger.models.Operation; +import com.wordnik.swagger.models.parameters.HeaderParameter; +import com.wordnik.swagger.models.parameters.Parameter; +import com.wordnik.swagger.models.properties.*; +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 SwiftGenerator extends DefaultCodegen implements CodegenConfig { + private static final Pattern PATH_PARAM_PATTERN = Pattern.compile("\\{[a-zA-Z_]+\\}"); + protected String sourceFolder = "Classes/Swaggers"; + + public CodegenType getTag() { + return CodegenType.CLIENT; + } + + public String getName() { + return "swift"; + } + + public String getHelp() { + return "Generates a swift client library."; + } + + 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", appName, "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( + Arrays.asList( + "Int", + "Float", + "Double", + "Bool", + "Void", + "String", + "Character") + ); + defaultIncludes = new HashSet( + Arrays.asList( + "NSDate", + "Array", + "Dictionary", + "Set", + "Any", + "Empty", + "AnyObject") + ); + reservedWords = new HashSet( + 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(); + typeMapping.put("array", "Array"); + typeMapping.put("List", "Array"); + typeMapping.put("map", "Dictionary"); + 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(); + } + + @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> swiftEnums = new ArrayList>(); + List values = (List) codegenProperty.allowableValues.get("values"); + for (String value : values) { + Map map = new HashMap(); + 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 definitions) { + path = normalizePath(path); + List parameters = operation.getParameters(); + parameters = Lists.newArrayList(Iterators.filter(parameters.iterator(), new Predicate() { + @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(); + } +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/META-INF/services/com.wordnik.swagger.codegen.CodegenConfig b/modules/swagger-codegen/src/main/resources/META-INF/services/com.wordnik.swagger.codegen.CodegenConfig index 293079fbc972..facb299b5d14 100644 --- a/modules/swagger-codegen/src/main/resources/META-INF/services/com.wordnik.swagger.codegen.CodegenConfig +++ b/modules/swagger-codegen/src/main/resources/META-INF/services/com.wordnik.swagger.codegen.CodegenConfig @@ -18,4 +18,5 @@ com.wordnik.swagger.codegen.languages.StaticDocCodegen com.wordnik.swagger.codegen.languages.StaticHtmlGenerator com.wordnik.swagger.codegen.languages.SwaggerGenerator com.wordnik.swagger.codegen.languages.SwaggerYamlGenerator +com.wordnik.swagger.codegen.languages.SwiftGenerator com.wordnik.swagger.codegen.languages.TizenClientCodegen diff --git a/modules/swagger-codegen/src/main/resources/swift/APIHelper.mustache b/modules/swagger-codegen/src/main/resources/swift/APIHelper.mustache new file mode 100644 index 000000000000..418f1c8512b2 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/swift/APIHelper.mustache @@ -0,0 +1,21 @@ +// APIHelper.swift +// +// Generated by swagger-codegen +// https://github.com/swagger-api/swagger-codegen +// + +class APIHelper { + static func rejectNil(source: [String:AnyObject?]) -> [String:AnyObject]? { + var destination = [String:AnyObject]() + for (key, nillableValue) in source { + if let value: AnyObject = nillableValue { + destination[key] = value + } + } + + if destination.isEmpty { + return nil + } + return destination + } +} diff --git a/modules/swagger-codegen/src/main/resources/swift/APIs.mustache b/modules/swagger-codegen/src/main/resources/swift/APIs.mustache new file mode 100644 index 000000000000..073fbd93be74 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/swift/APIs.mustache @@ -0,0 +1,51 @@ +// APIs.swift +// +// Generated by swagger-codegen +// https://github.com/swagger-api/swagger-codegen +// + +import PromiseKit + +class {{projectName}}API { + static let basePath = "{{^basePathOverride}}{{basePath}}{{/basePathOverride}}{{basePathOverride}}" + static var credential: NSURLCredential? + static var requestBuilderFactory: RequestBuilderFactory = AlamofireRequestBuilderFactory() + + class APIBase { + } +} + +class RequestBuilder { + var credential: NSURLCredential? + var headers: [String:String] = [:] + let parameters: [String:AnyObject]? + let isBody: Bool + let method: String + let URLString: URLStringConvertible + + required init(method: String, URLString: URLStringConvertible, parameters: [String:AnyObject]?, isBody: Bool) { + self.method = method + self.URLString = URLString + self.parameters = parameters + self.isBody = isBody + } + + func execute() -> Promise> { fatalError("Not implemented") } + + func addHeader(#name: String, value: String) -> Self { + if !value.isEmpty { + headers[name] = value + } + return self + } + + func addCredential() -> Self { + self.credential = OneteamAPI.credential + return self + } +} + +protocol RequestBuilderFactory { + func getBuilder() -> RequestBuilder.Type +} + diff --git a/modules/swagger-codegen/src/main/resources/swift/AlamofireImplementations.mustache b/modules/swagger-codegen/src/main/resources/swift/AlamofireImplementations.mustache new file mode 100644 index 000000000000..8b34587717a8 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/swift/AlamofireImplementations.mustache @@ -0,0 +1,73 @@ +// AlamofireImplementations.swift +// +// Generated by swagger-codegen +// https://github.com/swagger-api/swagger-codegen +// + +import Alamofire +import PromiseKit + +class AlamofireRequestBuilderFactory: RequestBuilderFactory { + func getBuilder() -> RequestBuilder.Type { + return AlamofireRequestBuilder.self + } +} + +class AlamofireRequestBuilder: RequestBuilder { + required init(method: String, URLString: URLStringConvertible, parameters: [String : AnyObject]?, isBody: Bool) { + super.init(method: method, URLString: URLString, parameters: parameters, isBody: isBody) + } + + override func execute() -> Promise> { + let configuration: NSURLSessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration() + configuration.HTTPAdditionalHeaders = buildHeaders() + let manager = Alamofire.Manager(configuration: configuration) + let encoding = isBody ? Alamofire.ParameterEncoding.JSON : Alamofire.ParameterEncoding.URL + let request = manager.request(Alamofire.Method(rawValue: method)!, URLString, parameters: parameters, encoding: encoding) + if let credential = self.credential { + request.authenticate(usingCredential: credential) + } + + let defer = Promise>.defer() + request.responseJSON(options: .AllowFragments) { (req, res, json, error) in + if let error = error { + defer.reject(error) + return + } + if res!.statusCode >= 400 { + //TODO: Add error entity + let error = NSError(domain: res!.URL!.URLString, code: res!.statusCode, userInfo: [:]) + defer.reject(error) + return + } + + if Empty.instance is T { + let response = Response(response: res!, body: Empty.instance as! T) + defer.fulfill(response) + return + } + if let json: AnyObject = json { + if let body = T.decode(json) { + let response = Response(response: res!, body: body) + defer.fulfill(response) + } else { + defer.reject(NSError(domain: "localhost", code: 500, userInfo: ["reason": "cannot convertible: \(json)"])) + } + return + } + + defer.reject(NSError(domain: "localhost", code: 500, userInfo: ["reason": "unreacheable code"])) + } + return defer.promise + } + + private func buildHeaders() -> [String: AnyObject] { + var httpHeaders = Manager.defaultHTTPHeaders + for (key, value) in self.headers { + httpHeaders[key] = value + } + return httpHeaders + } +} + + diff --git a/modules/swagger-codegen/src/main/resources/swift/Cartfile.mustache b/modules/swagger-codegen/src/main/resources/swift/Cartfile.mustache new file mode 100644 index 000000000000..245a690a74b0 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/swift/Cartfile.mustache @@ -0,0 +1,2 @@ +github "Alamofire/Alamofire" >= 1.2 +github "mxcl/PromiseKit" \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/swift/Extensions.mustache b/modules/swagger-codegen/src/main/resources/swift/Extensions.mustache new file mode 100644 index 000000000000..d0aed716b7e9 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/swift/Extensions.mustache @@ -0,0 +1,111 @@ +// Extensions.swift +// +// Generated by swagger-codegen +// https://github.com/swagger-api/swagger-codegen +// + +import Alamofire +import PromiseKit +import SwiftyJSON + +extension Request { + func responsePromise() -> Promise> { + let defer = Promise>.defer() + responseJSON(options: .AllowFragments) { (req, res, json, error) in + if let error = error { + defer.reject(error) + return + } + if res!.statusCode >= 400 { + let error = NSError(domain: res!.URL!.URLString, code: res!.statusCode, userInfo: [:]) + defer.reject(error) + return + } + + if Empty.instance is T { + let response = Response(response: res!, body: Empty.instance as! T) + defer.fulfill(response) + return + } + if let json: AnyObject = json { + if let body = T.decode(json) { + let response = Response(response: res!, body: body) + defer.fulfill(response) + } else { + defer.reject(NSError(domain: "localhost", code: 500, userInfo: ["reason": "cannot convertible: \(json)"])) + } + return + } + + defer.reject(NSError(domain: "localhost", code: 500, userInfo: ["reason": "unreacheable code"])) + } + return defer.promise + } +} + +extension Array: JSONEncodable { + func encode() -> AnyObject { + if Element.self is JSONEncodable { + return self.map { ($0 as! JSONEncodable).encode() } + } else { + return self.map { ($0 as! AnyObject) } + } + } +} + +extension JSON { + func decode() -> Bool? { + return self.bool + } + func decode() -> Bool { + return self.boolValue + } + func decode() -> Int? { + return self.int + } + func decode() -> Int { + return self.intValue + } + func decode() -> Float? { + return self.float + } + func decode() -> Float { + return self.floatValue + } + func decode() -> Double? { + return self.double + } + func decode() -> Double { + return self.doubleValue + } + func decode() -> String? { + return self.string + } + func decode() -> String { + return self.stringValue + } + func decode() -> T? { + return T.decode(self.object) + } + func decode() -> [T]? { + return self.arrayObject?.map(T.decode).filter({ $0 != nil }).map({ $0! }) + } + func decode() -> [T]? { + return self.array?.map({ $0 as! T }) + } + static let DateFormat: NSDateFormatter = { + let formatter = NSDateFormatter() + formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'" + return formatter + }() + func decode() -> NSDate? { + return JSON.DateFormat.dateFromString(self.string ?? "") + } + func decode() -> NSData? { + return self.rawData(options: .allZeros, error: nil) + } + func decode() -> NSData { + return self.decode()! + } +} + diff --git a/modules/swagger-codegen/src/main/resources/swift/Models.mustache b/modules/swagger-codegen/src/main/resources/swift/Models.mustache new file mode 100644 index 000000000000..dd02aa12d700 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/swift/Models.mustache @@ -0,0 +1,47 @@ +// Models.swift +// +// Generated by swagger-codegen +// https://github.com/swagger-api/swagger-codegen +// + +import Foundation +import SwiftyJSON + +protocol JSONDecodable { + static func decode(source: AnyObject) -> Self? +} + +protocol JSONEncodable { + func encode() -> AnyObject +} + +class Response { + let statusCode: Int + let header: [String: String] + let body: T + + init(statusCode: Int, header: [String: String], body: T) { + self.statusCode = statusCode + self.header = header + self.body = body + } + + convenience init(response: NSHTTPURLResponse, body: T) { + let rawHeader = response.allHeaderFields + var header = [String:String]() + for (key, value) in rawHeader { + header[key as! String] = value as? String + } + self.init(statusCode: response.statusCode, header: header, body: body) + } +} + +final class Empty: JSONDecodable { + private init() { } + + static let instance = Empty() + + static func decode(source: AnyObject) -> Empty? { + return instance + } +} diff --git a/modules/swagger-codegen/src/main/resources/swift/api.mustache b/modules/swagger-codegen/src/main/resources/swift/api.mustache new file mode 100644 index 000000000000..0277ec8dfa34 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/swift/api.mustache @@ -0,0 +1,50 @@ +{{#operations}}// +// {{classname}}.swift +// +// Generated by swagger-codegen +// https://github.com/swagger-api/swagger-codegen +// + +import Alamofire +import PromiseKit + +extension {{projectName}}API { + {{#description}} + /** {{description}} */{{/description}} + class {{classname}}: APIBase { + {{#operation}} + /** + {{#summary}} + {{{summary}}} + {{/summary}} + - {{httpMethod}} {{path}}{{#notes}} + - {{{notes}}}{{/notes}}{{#subresourceOperation}} + - subresourceOperation: {{subresourceOperation}}{{/subresourceOperation}}{{#defaultResponse}} + - defaultResponse: {{defaultResponse}}{{/defaultResponse}}{{#authMethods}} + - authMethods: {{authMethods}}{{/authMethods}}{{#responseHeaders}} + - responseHeaders: {{responseHeaders}}{{/responseHeaders}}{{#examples}} + - examples: {{{examples}}}{{/examples}}{{#externalDocs}} + - externalDocs: {{externalDocs}}{{/externalDocs}}{{#hasParams}} + {{/hasParams}}{{#allParams}} + :param: {{paramName}} ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}}{{/allParams}} + + :returns: Promise> {{description}} + */ + func {{operationId}}({{#allParams}}{{^secondaryParam}}#{{/secondaryParam}}{{paramName}}: {{dataType}}{{^required}}?{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) -> RequestBuilder<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Empty{{/returnType}}> { + {{^pathParams}}let{{/pathParams}}{{#pathParams}}{{^secondaryParam}}var{{/secondaryParam}}{{/pathParams}} path = "{{path}}"{{#pathParams}} + path = path.stringByReplacingOccurrencesOfString("{{=<% %>=}}{<%paramName%>}<%={{ }}=%>", withString: "\({{paramName}})", options: .LiteralSearch, range: nil){{/pathParams}} + let url = {{projectName}}API.basePath + path + {{#bodyParam}} + let parameters = {{paramName}}.encode() as! [String:AnyObject]{{/bodyParam}}{{^bodyParam}} + let nillableParameters: [String:AnyObject?] = {{^queryParams}}[:]{{/queryParams}}{{#queryParams}}{{^secondaryParam}}[{{/secondaryParam}} + "{{paramName}}": {{paramName}}{{#hasMore}},{{/hasMore}}{{^hasMore}} + ]{{/hasMore}}{{/queryParams}} + let parameters = APIHelper.rejectNil(nillableParameters){{/bodyParam}} + + return {{projectName}}API.requestBuilderFactory.getBuilder() + (method: "{{httpMethod}}", URLString: url, parameters: parameters, isBody: {{^queryParams}}true{{/queryParams}}{{#queryParams}}{{^secondaryParam}}false{{/secondaryParam}}{{/queryParams}}) + } + {{/operation}} + } +} +{{/operations}} diff --git a/modules/swagger-codegen/src/main/resources/swift/model.mustache b/modules/swagger-codegen/src/main/resources/swift/model.mustache new file mode 100644 index 000000000000..e9c01fdecc2f --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/swift/model.mustache @@ -0,0 +1,46 @@ +{{#models}}{{#model}}// +// {{classname}}.swift +// +// Generated by swagger-codegen +// https://github.com/swagger-api/swagger-codegen +// + +import SwiftyJSON + +extension {{projectName}}API { + {{#description}} + + /** {{description}} */{{/description}} + final class {{classname}}: JSONEncodable, JSONDecodable { + {{#vars}}{{#isEnum}} + enum {{datatypeWithEnum}}: String { {{#allowableValues}}{{#values}} + case {{enum}} = "{{raw}}"{{/values}}{{/allowableValues}} + } + {{/isEnum}}{{/vars}} + {{#vars}}{{#isEnum}}{{#description}}/** {{description}} */ + {{/description}}var {{name}}: {{{datatypeWithEnum}}}{{^required}}?{{/required}}{{#required}}!{{/required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{/isEnum}}{{^isEnum}}{{#description}}/** {{description}} */ + {{/description}}var {{name}}: {{{datatype}}}{{^required}}?{{/required}}{{#required}}!{{/required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{/isEnum}} + {{/vars}} + + // MARK: JSONDecodable + static func decode(source: AnyObject) -> {{classname}}? { + let json = JSON(source) + var instance = {{classname}}(){{#vars}}{{#isEnum}} + instance.{{name}} = {{datatypeWithEnum}}(rawValue: json["{{name}}"].string ?? ""){{/isEnum}}{{^isEnum}} + instance.{{name}} = json["{{name}}"].decode(){{/isEnum}}{{/vars}} + return instance + } + + // MARK: JSONEncodable + func encode() -> AnyObject { + var nillableDictionary = [String:AnyObject?](){{#vars}}{{#isNotContainer}}{{#isPrimitiveType}}{{^isEnum}} + nillableDictionary["{{name}}"] = self.{{name}}{{/isEnum}}{{/isPrimitiveType}}{{#isEnum}} + nillableDictionary["{{name}}"] = self.{{name}}{{^required}}?{{/required}}.rawValue{{/isEnum}}{{^isPrimitiveType}} + nillableDictionary["{{name}}"] = self.{{name}}{{^required}}?{{/required}}.encode(){{/isPrimitiveType}}{{/isNotContainer}}{{#isContainer}} + nillableDictionary["{{name}}"] = self.{{name}}{{^required}}?{{/required}}.encode(){{/isContainer}}{{/vars}} + let dictionary: [String:AnyObject] = APIHelper.rejectNil(nillableDictionary) ?? [:] + return dictionary + } + }{{/model}} +} +{{/models}} diff --git a/samples/client/petstore/swift/PetstoreClient/Cartfile b/samples/client/petstore/swift/PetstoreClient/Cartfile new file mode 100644 index 000000000000..245a690a74b0 --- /dev/null +++ b/samples/client/petstore/swift/PetstoreClient/Cartfile @@ -0,0 +1,2 @@ +github "Alamofire/Alamofire" >= 1.2 +github "mxcl/PromiseKit" \ No newline at end of file