diff --git a/README.md b/README.md index bf9118a..e48a396 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,12 @@ [![Build Status](https://travis-ci.org/insanoid/SwiftyJSONAccelerator.svg?branch=master)](https://travis-ci.org/insanoid/SwiftyJSONAccelerator) [![codecov](https://codecov.io/gh/insanoid/SwiftyJSONAccelerator/branch/master/graph/badge.svg)](https://codecov.io/gh/insanoid/SwiftyJSONAccelerator) +**Version v1.2.0 Released!** + +- Now supports [Marshal](https://github.com/utahiosmac/Marshal)! One of the fastest JSONSerialisation class out there! [(Read more)](https://github.com/bwhiteley/JSONShootout) +- Set `class` as `final`. +- `init` marked as `required` by default for `class`. + **Version v1.1.0 Released!** - Now generates the correct option `struct` and `class` based on what was selected. @@ -18,8 +24,8 @@ Status](https://travis-ci.org/insanoid/SwiftyJSONAccelerator.svg?branch=master)] ## Download/Installing -- Download the repo, install pods and run the project! -- [Download the .app(v1.1.0)](https://github.com/insanoid/SwiftyJSONAccelerator/releases/download/v1.1.0/SwiftyJSONAccelerator.zip).0/SwiftyJSONAccelerator.zip) +- **Option 1:** Download the repo, install pods and run the project! +- **Option 2:** [Download the .app(v1.2.0)](https://github.com/insanoid/SwiftyJSONAccelerator/releases/download/v1.2.0/SwiftyJSONAccelerator.zip) A swift model generator like the Objective-C [JSONAccelerator](http://nerdery.com/json-accelerator). Formats and generates models for the given JSON and also breaks them into files making it easy to manage and share between several models. @@ -27,6 +33,7 @@ The models that are generated depend on JSON object mapping libraries, currently - [SwiftyJSON](https://github.com/SwiftyJSON/SwiftyJSON) - [Hearst-DD/ObjectMapper](https://github.com/Hearst-DD/ObjectMapper) +- [Marshal](https://github.com/utahiosmac/Marshal) Currently, the pattern is very similar to its Objective-C counterpart. It generates classes with following properties. diff --git a/SwiftyJSONAccelerator.xcodeproj/project.pbxproj b/SwiftyJSONAccelerator.xcodeproj/project.pbxproj index 56a686c..9ea1327 100644 --- a/SwiftyJSONAccelerator.xcodeproj/project.pbxproj +++ b/SwiftyJSONAccelerator.xcodeproj/project.pbxproj @@ -15,6 +15,9 @@ 930462B51D31131800FE61A6 /* PropertyComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 930462B11D310FF200FE61A6 /* PropertyComponent.swift */; }; 930462B61D31133B00FE61A6 /* FileGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 930462AC1D3106A400FE61A6 /* FileGenerator.swift */; }; 930462B71D31134900FE61A6 /* ModelComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 930462AF1D310F6900FE61A6 /* ModelComponent.swift */; }; + 9327F2881DF4BCA70002BE40 /* MarshalModelFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9327F2871DF4BCA70002BE40 /* MarshalModelFile.swift */; }; + 9327F28A1DF4BD540002BE40 /* MarshalTemplate.txt in Resources */ = {isa = PBXBuildFile; fileRef = 9327F2891DF4BD540002BE40 /* MarshalTemplate.txt */; }; + 9327F2971DF4CF650002BE40 /* MarshalModelFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9327F2871DF4BCA70002BE40 /* MarshalModelFile.swift */; }; 9341A14A1BD6E5FE0048CE2C /* ModelGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9341A1491BD6E5FE0048CE2C /* ModelGenerator.swift */; }; 9341A14F1BD6E7290048CE2C /* BaseTemplate.txt in Resources */ = {isa = PBXBuildFile; fileRef = 9341A14E1BD6E7290048CE2C /* BaseTemplate.txt */; }; 9361FD141BD18558001ED533 /* LineNumberRulerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9361FD131BD18558001ED533 /* LineNumberRulerView.swift */; }; @@ -79,6 +82,8 @@ 930462AC1D3106A400FE61A6 /* FileGenerator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileGenerator.swift; sourceTree = ""; }; 930462AF1D310F6900FE61A6 /* ModelComponent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ModelComponent.swift; sourceTree = ""; }; 930462B11D310FF200FE61A6 /* PropertyComponent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PropertyComponent.swift; sourceTree = ""; }; + 9327F2871DF4BCA70002BE40 /* MarshalModelFile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarshalModelFile.swift; sourceTree = ""; }; + 9327F2891DF4BD540002BE40 /* MarshalTemplate.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MarshalTemplate.txt; sourceTree = ""; }; 9341A1491BD6E5FE0048CE2C /* ModelGenerator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ModelGenerator.swift; sourceTree = ""; }; 9341A14E1BD6E7290048CE2C /* BaseTemplate.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = BaseTemplate.txt; sourceTree = ""; }; 9361FD131BD18558001ED533 /* LineNumberRulerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LineNumberRulerView.swift; sourceTree = ""; }; @@ -211,6 +216,7 @@ children = ( 93F1593F1CFF96E700175636 /* ObjectMapperModelFile.swift */, 93F1593D1CFF969900175636 /* SwiftyJSONModelFile.swift */, + 9327F2871DF4BCA70002BE40 /* MarshalModelFile.swift */, ); path = "Library-Extensions"; sourceTree = ""; @@ -291,6 +297,7 @@ children = ( C667011C1BDCAF23009BA254 /* ObjectMapperTemplate.txt */, C667011A1BDCABCE009BA254 /* SwiftyJSONTemplate.txt */, + 9327F2891DF4BD540002BE40 /* MarshalTemplate.txt */, ); path = "Library-Extension-Templates"; sourceTree = ""; @@ -369,7 +376,7 @@ 93F174371BD0707D007E7DFC /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0800; + LastUpgradeCheck = 0810; ORGANIZATIONNAME = "Karthikeya Udupa K M"; TargetAttributes = { 93F1743E1BD0707D007E7DFC = { @@ -414,6 +421,7 @@ C667011D1BDCAF23009BA254 /* ObjectMapperTemplate.txt in Resources */, 9341A14F1BD6E7290048CE2C /* BaseTemplate.txt in Resources */, 93F1744A1BD0707D007E7DFC /* Main.storyboard in Resources */, + 9327F28A1DF4BD540002BE40 /* MarshalTemplate.txt in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -549,6 +557,7 @@ 9341A14A1BD6E5FE0048CE2C /* ModelGenerator.swift in Sources */, 930462B21D310FF200FE61A6 /* PropertyComponent.swift in Sources */, 93F1593A1CFF853C00175636 /* NameGenerator.swift in Sources */, + 9327F2881DF4BCA70002BE40 /* MarshalModelFile.swift in Sources */, 930462AD1D3106A400FE61A6 /* FileGenerator.swift in Sources */, 93F174451BD0707D007E7DFC /* SJEditorViewController.swift in Sources */, 93F1593E1CFF969900175636 /* SwiftyJSONModelFile.swift in Sources */, @@ -578,6 +587,7 @@ 93D850EF1D00D3070023D573 /* ObjectMapperModelFile.swift in Sources */, 93D850DC1D00D2ED0023D573 /* SJEditorViewController.swift in Sources */, 93D850D81D00D2030023D573 /* ModelGenerator.swift in Sources */, + 9327F2971DF4CF650002BE40 /* MarshalModelFile.swift in Sources */, 93D850E91D00D3020023D573 /* String+Helpers.swift in Sources */, 9362F8661BD07DBA0001372E /* JSONHelperTests.swift in Sources */, 93D850DE1D00D2F00023D573 /* SJTextView.swift in Sources */, diff --git a/SwiftyJSONAccelerator.xcodeproj/xcshareddata/xcschemes/SwiftyJSONAccelerator.xcscheme b/SwiftyJSONAccelerator.xcodeproj/xcshareddata/xcschemes/SwiftyJSONAccelerator.xcscheme index f45399d..acdb05b 100644 --- a/SwiftyJSONAccelerator.xcodeproj/xcshareddata/xcschemes/SwiftyJSONAccelerator.xcscheme +++ b/SwiftyJSONAccelerator.xcodeproj/xcshareddata/xcschemes/SwiftyJSONAccelerator.xcscheme @@ -1,6 +1,6 @@ String { + static func loadFileWith(_ filename: String) -> String { - let bundle = Bundle.main - let path = bundle.path(forResource: filename, ofType: "txt") + let bundle = Bundle.main + let path = bundle.path(forResource: filename, ofType: "txt") - do { - let content = try String.init(contentsOfFile: path!) - return content - } catch { } + do { + let content = try String.init(contentsOfFile: path!) + return content + } catch { } - return "" - } - - static func generateFileContentWith(_ modelFile: ModelFile, configuration: ModelGenerationConfiguration) -> String { - - var content = loadFileWith("BaseTemplate") - content = content.replacingOccurrences(of: "{OBJECT_NAME}", with: modelFile.fileName) - content = content.replacingOccurrences(of: "{DATE}", with: todayDateString()) - content = content.replacingOccurrences(of: "{OBJECT_KIND}", with: modelFile.type.rawValue) - content = content.replacingOccurrences(of: "{JSON_PARSER_LIBRARY_BODY}", with: loadFileWith(modelFile.mainBodyFileName())) - if let authorName = configuration.authorName { - content = content.replacingOccurrences(of: "__NAME__", with: authorName) - } - if let companyName = configuration.companyName { - content = content.replacingOccurrences(of: "__MyCompanyName__", with: companyName) - } - content = content.replacingOccurrences(of: "{INCLUDE_HEADER}", with: "\nimport \(modelFile.moduleName())") - - var classesExtendFrom: [String] = [] - if let extendFrom = modelFile.baseElementName() { - classesExtendFrom = [extendFrom] - } - if configuration.supportNSCoding && configuration.constructType == .ClassType { - classesExtendFrom = classesExtendFrom + ["NSCoding"] - } - - if classesExtendFrom.count > 0 { - content = content.replacingOccurrences(of: "{EXTEND_FROM}", with: classesExtendFrom.joined(separator: ", ")) - content = content.replacingOccurrences(of: "{EXTENDED_OBJECT_COLON}", with: ": ") - } else { - content = content.replacingOccurrences(of: "{EXTEND_FROM}", with: "") - content = content.replacingOccurrences(of: "{EXTENDED_OBJECT_COLON}", with: "") + return "" } - let stringConstants = modelFile.component.stringConstants.map({ " " + $0 }).joined(separator: "\n") - let declarations = modelFile.component.declarations.map({ " " + $0 }).joined(separator: "\n") - let initialisers = modelFile.component.initialisers.map({ " " + $0 }).joined(separator: "\n") - let description = modelFile.component.description.map({ " " + $0 }).joined(separator: "\n") - - content = content.replacingOccurrences(of: "{STRING_CONSTANT}", with: stringConstants) - content = content.replacingOccurrences(of: "{DECLARATION}", with: declarations) - content = content.replacingOccurrences(of: "{INITALIZER}", with: initialisers) - content = content.replacingOccurrences(of: "{DESCRIPTION}", with: description) - - if configuration.constructType == .StructType { - content = content.replacingOccurrences(of: " convenience", with: "") + static func generateFileContentWith(_ modelFile: ModelFile, configuration: ModelGenerationConfiguration) -> String { + + var content = loadFileWith("BaseTemplate") + content = content.replacingOccurrences(of: "{OBJECT_NAME}", with: modelFile.fileName) + content = content.replacingOccurrences(of: "{DATE}", with: todayDateString()) + content = content.replacingOccurrences(of: "{OBJECT_KIND}", with: modelFile.type.rawValue) + content = content.replacingOccurrences(of: "{JSON_PARSER_LIBRARY_BODY}", with: loadFileWith(modelFile.mainBodyFileName())) + + if modelFile.type == .ClassType { + content = content.replacingOccurrences(of: "{REQUIRED}", with: " required ") + } else { + content = content.replacingOccurrences(of: "{REQUIRED}", with: " ") + } + if let authorName = configuration.authorName { + content = content.replacingOccurrences(of: "__NAME__", with: authorName) + } + if let companyName = configuration.companyName { + content = content.replacingOccurrences(of: "__MyCompanyName__", with: companyName) + } + content = content.replacingOccurrences(of: "{INCLUDE_HEADER}", with: "\nimport \(modelFile.moduleName())") + + var classesExtendFrom: [String] = [] + if let extendFrom = modelFile.baseElementName() { + classesExtendFrom = [extendFrom] + } + if configuration.supportNSCoding && configuration.constructType == .ClassType { + classesExtendFrom = classesExtendFrom + ["NSCoding"] + } + + if configuration.isFinalRequired && configuration.constructType == .ClassType { + content = content.replacingOccurrences(of: "{IS_FINAL}", with: " final ") + } else { + content = content.replacingOccurrences(of: "{IS_FINAL}", with: " ") + } + + if classesExtendFrom.count > 0 { + content = content.replacingOccurrences(of: "{EXTEND_FROM}", with: classesExtendFrom.joined(separator: ", ")) + content = content.replacingOccurrences(of: "{EXTENDED_OBJECT_COLON}", with: ": ") + } else { + content = content.replacingOccurrences(of: "{EXTEND_FROM}", with: "") + content = content.replacingOccurrences(of: "{EXTENDED_OBJECT_COLON}", with: "") + } + + let stringConstants = modelFile.component.stringConstants.map({ " " + $0 }).joined(separator: "\n") + let declarations = modelFile.component.declarations.map({ " " + $0 }).joined(separator: "\n") + let initialisers = modelFile.component.initialisers.map({ " " + $0 }).joined(separator: "\n") + let description = modelFile.component.description.map({ " " + $0 }).joined(separator: "\n") + + content = content.replacingOccurrences(of: "{STRING_CONSTANT}", with: stringConstants) + content = content.replacingOccurrences(of: "{DECLARATION}", with: declarations) + content = content.replacingOccurrences(of: "{INITIALIZER}", with: initialisers) + content = content.replacingOccurrences(of: "{DESCRIPTION}", with: description) + + if configuration.constructType == .StructType { + content = content.replacingOccurrences(of: " convenience", with: "") + } + + if configuration.supportNSCoding && configuration.constructType == .ClassType { + content = content.replacingOccurrences(of: "{NSCODING_SUPPORT}", with: loadFileWith("NSCodingTemplate")) + let encoders = modelFile.component.encoders.map({ " " + $0 }).joined(separator: "\n") + let decoders = modelFile.component.decoders.map({ " " + $0 }).joined(separator: "\n") + content = content.replacingOccurrences(of: "{DECODERS}", with: decoders) + content = content.replacingOccurrences(of: "{ENCODERS}", with: encoders) + } else { + content = content.replacingOccurrences(of: "{NSCODING_SUPPORT}", with: "") + } + + return content } - if configuration.supportNSCoding && configuration.constructType == .ClassType { - content = content.replacingOccurrences(of: "{NSCODING_SUPPORT}", with: loadFileWith("NSCodingTemplate")) - let encoders = modelFile.component.encoders.map({ " " + $0 }).joined(separator: "\n") - let decoders = modelFile.component.decoders.map({ " " + $0 }).joined(separator: "\n") - content = content.replacingOccurrences(of: "{DECODERS}", with: decoders) - content = content.replacingOccurrences(of: "{ENCODERS}", with: encoders) - } else { - content = content.replacingOccurrences(of: "{NSCODING_SUPPORT}", with: "") - } - - return content - } - - /** + /** Write the given content to a file at the mentioned path. - parameter name: The name of the file. @@ -97,24 +109,24 @@ struct FileGenerator { - returns: Boolean indicating if the process was successful. */ - static internal func writeToFileWith(_ name: String, content: String, path: String) -> Bool { - let filename = path.appendingFormat("%@", (name + ".swift")) - do { - try FileManager.default.createDirectory(at: URL.init(fileURLWithPath: path), - withIntermediateDirectories: true, - attributes: nil) - try content.write(toFile: filename, atomically: true, encoding: String.Encoding.utf8) - return true - } catch let error as NSError { - print(error) - return false + static internal func writeToFileWith(_ name: String, content: String, path: String) -> Bool { + let filename = path.appendingFormat("%@", (name + ".swift")) + do { + try FileManager.default.createDirectory(at: URL.init(fileURLWithPath: path), + withIntermediateDirectories: true, + attributes: nil) + try content.write(toFile: filename, atomically: true, encoding: String.Encoding.utf8) + return true + } catch let error as NSError { + print(error) + return false + } } - } - static fileprivate func todayDateString() -> String { - let formatter = DateFormatter.init() - formatter.dateStyle = .short - return formatter.string(from: Date.init()) - } + static fileprivate func todayDateString() -> String { + let formatter = DateFormatter.init() + formatter.dateStyle = .short + return formatter.string(from: Date.init()) + } } diff --git a/SwiftyJSONAccelerator/Generators/ModelGenerator.swift b/SwiftyJSONAccelerator/Generators/ModelGenerator.swift index 57d17a7..7adc830 100644 --- a/SwiftyJSONAccelerator/Generators/ModelGenerator.swift +++ b/SwiftyJSONAccelerator/Generators/ModelGenerator.swift @@ -145,6 +145,8 @@ public struct ModelGenerator { return ObjectMapperModelFile() case .SwiftyJSON: return SwiftyJSONModelFile() + case .Marshal: + return MarshalModelFile() } } diff --git a/SwiftyJSONAccelerator/Library-Extensions/MarshalModelFile.swift b/SwiftyJSONAccelerator/Library-Extensions/MarshalModelFile.swift new file mode 100644 index 0000000..be61c1b --- /dev/null +++ b/SwiftyJSONAccelerator/Library-Extensions/MarshalModelFile.swift @@ -0,0 +1,92 @@ +// +// MarshalModelFile.swift +// SwiftyJSONAccelerator +// +// Created by Karthik on 04/12/2016. +// Copyright © 2016 Karthikeya Udupa K M. All rights reserved. +// + +import Foundation + +struct MarshalModelFile: ModelFile, DefaultModelFileComponent { + + /// Filename for the model. + var fileName: String + var type: ConstructType + var component: ModelComponent + + init() { + self.fileName = "" + type = ConstructType.StructType + component = ModelComponent.init() + } + + mutating func setInfo(_ fileName: String, _ configuration: ModelGenerationConfiguration) { + self.fileName = fileName + type = configuration.constructType + } + + func moduleName() -> String { + return "Marshal" + } + + func baseElementName() -> String? { + return "Unmarshaling" + } + + func mainBodyFileName() -> String { + return "MarshalTemplate" + } + + mutating func generateAndAddComponentsFor(_ property: PropertyComponent) { + switch property.propertyType { + + case .ValueType: + component.declarations.append(genVariableDeclaration(property.name, property.type, false)) + component.description.append(genDescriptionForPrimitive(property.name, property.type, property.constantName)) + component.decoders.append(genDecoder(property.name, property.type, property.constantName, false)) + component.encoders.append(genEncoder(property.name, property.type, property.constantName)) + generateCommonComponentsFor(property) + case .ValueTypeArray: + component.description.append(genDescriptionForPrimitiveArray(property.name, property.constantName)) + component.declarations.append(genVariableDeclaration(property.name, property.type, true)) + component.decoders.append(genDecoder(property.name, property.type, property.constantName, true)) + component.encoders.append(genEncoder(property.name, property.type, property.constantName)) + generateCommonComponentsFor(property) + case .ObjectType: + component.description.append(genDescriptionForObject(property.name, property.constantName)) + component.declarations.append(genVariableDeclaration(property.name, property.type, false)) + component.decoders.append(genDecoder(property.name, property.type, property.constantName, false)) + component.encoders.append(genEncoder(property.name, property.type, property.constantName)) + generateCommonComponentsFor(property) + case .ObjectTypeArray: + component.declarations.append(genVariableDeclaration(property.name, property.type, true)) + component.description.append(genDescriptionForObjectArray(property.name, property.constantName)) + component.decoders.append(genDecoder(property.name, property.type, property.constantName, true)) + component.encoders.append(genEncoder(property.name, property.type, property.constantName)) + generateCommonComponentsFor(property) + + case .EmptyArray: + component.declarations.append(genVariableDeclaration(property.name, "Any", true)) + component.description.append(genDescriptionForPrimitiveArray(property.name, property.constantName)) + component.decoders.append(genDecoder(property.name, "Any", property.constantName, true)) + component.encoders.append(genEncoder(property.name, "Any", property.constantName)) + generateCommonComponentsFor(property) + case .NullType: break + // Currently we do not deal with null values. + + } + } + + fileprivate mutating func generateCommonComponentsFor(_ property: PropertyComponent) { + component.stringConstants.append(genStringConstant(property.constantName, property.key)) + component.initialisers.append(genInitializerForVariable(property.name, property.constantName)) + } + + // MARK: - Customised methods for ObjectMapper + // MARK: - Initialisers + func genInitializerForVariable(_ name: String, _ constantName: String) -> String { + return "\(name) = try? object.value(for: \(constantName))" + } + +} diff --git a/SwiftyJSONAccelerator/Models-Components/ModelGenerationConfiguration.swift b/SwiftyJSONAccelerator/Models-Components/ModelGenerationConfiguration.swift index a7db4e6..670e891 100644 --- a/SwiftyJSONAccelerator/Models-Components/ModelGenerationConfiguration.swift +++ b/SwiftyJSONAccelerator/Models-Components/ModelGenerationConfiguration.swift @@ -12,20 +12,22 @@ import Foundation * Structure to store the configuration for the model generation. */ struct ModelGenerationConfiguration { - /// Path where the generated files have to be stored. - var filePath: String - /// Name of the root level class for the provided JSON. - var baseClassName: String - /// The author name that has to be put in the file's header comments. - var authorName: String? - /// Company name that has to be put into the file's header. - var companyName: String? - /// A namespace prefix for the file (not recommended for Swift but people might want it) - var prefix: String? - /// Type of the object that have to be generated. - var constructType: ConstructType - /// Model mapping library to be used. - var modelMappingLibrary: JSONMappingLibrary - /// Include NSCodingSupport/Currently only works for Classes. - var supportNSCoding: Bool + /// Path where the generated files have to be stored. + var filePath: String + /// Name of the root level class for the provided JSON. + var baseClassName: String + /// The author name that has to be put in the file's header comments. + var authorName: String? + /// Company name that has to be put into the file's header. + var companyName: String? + /// A namespace prefix for the file (not recommended for Swift but people might want it) + var prefix: String? + /// Type of the object that have to be generated. + var constructType: ConstructType + /// Model mapping library to be used. + var modelMappingLibrary: JSONMappingLibrary + /// Include NSCodingSupport/Currently only works for Classes. + var supportNSCoding: Bool + /// Indicates if the final keyword is required for the object. + var isFinalRequired: Bool } diff --git a/SwiftyJSONAccelerator/Storyboard/Base.lproj/Main.storyboard b/SwiftyJSONAccelerator/Storyboard/Base.lproj/Main.storyboard index 4016232..02e6005 100644 --- a/SwiftyJSONAccelerator/Storyboard/Base.lproj/Main.storyboard +++ b/SwiftyJSONAccelerator/Storyboard/Base.lproj/Main.storyboard @@ -1,8 +1,10 @@ - - + + - + + + @@ -751,13 +753,15 @@ - + - + - @@ -786,12 +790,19 @@ + @@ -801,7 +812,7 @@ - + @@ -814,6 +825,8 @@ + + @@ -824,8 +837,10 @@ + + @@ -848,6 +863,7 @@ + diff --git a/SwiftyJSONAccelerator/Templates/BaseTemplate.txt b/SwiftyJSONAccelerator/Templates/BaseTemplate.txt index 620e617..2ea2620 100644 --- a/SwiftyJSONAccelerator/Templates/BaseTemplate.txt +++ b/SwiftyJSONAccelerator/Templates/BaseTemplate.txt @@ -7,7 +7,7 @@ import Foundation{INCLUDE_HEADER} -public {OBJECT_KIND} {OBJECT_NAME}{EXTENDED_OBJECT_COLON}{EXTEND_FROM} { +public{IS_FINAL}{OBJECT_KIND} {OBJECT_NAME}{EXTENDED_OBJECT_COLON}{EXTEND_FROM} { // MARK: Declaration for string constants to be used to decode and also serialize. {STRING_CONSTANT} diff --git a/SwiftyJSONAccelerator/Templates/Library-Extension-Templates/MarshalTemplate.txt b/SwiftyJSONAccelerator/Templates/Library-Extension-Templates/MarshalTemplate.txt new file mode 100644 index 0000000..de8ad68 --- /dev/null +++ b/SwiftyJSONAccelerator/Templates/Library-Extension-Templates/MarshalTemplate.txt @@ -0,0 +1,9 @@ + // MARK: Marshal Initializers + + /** + Map a JSON object to this class using ObjectMapper + - parameter map: A mapping from ObjectMapper + */ + public{REQUIRED}init(object: MarshaledObject) { +{INITIALIZER} + } diff --git a/SwiftyJSONAccelerator/Templates/Library-Extension-Templates/ObjectMapperTemplate.txt b/SwiftyJSONAccelerator/Templates/Library-Extension-Templates/ObjectMapperTemplate.txt index e94f72e..d6c6341 100644 --- a/SwiftyJSONAccelerator/Templates/Library-Extension-Templates/ObjectMapperTemplate.txt +++ b/SwiftyJSONAccelerator/Templates/Library-Extension-Templates/ObjectMapperTemplate.txt @@ -1,9 +1,9 @@ - // MARK: ObjectMapper Initalizers + // MARK: ObjectMapper Initializers /** Map a JSON object to this class using ObjectMapper - parameter map: A mapping from ObjectMapper */ - required public init?(_ map: Map){ + public{REQUIRED}init?(_ map: Map){ } @@ -12,5 +12,5 @@ - parameter map: A mapping from ObjectMapper */ public func mapping(map: Map) { -{INITALIZER} +{INITIALIZER} } diff --git a/SwiftyJSONAccelerator/Templates/Library-Extension-Templates/SwiftyJSONTemplate.txt b/SwiftyJSONAccelerator/Templates/Library-Extension-Templates/SwiftyJSONTemplate.txt index 8caeedc..054d7fa 100644 --- a/SwiftyJSONAccelerator/Templates/Library-Extension-Templates/SwiftyJSONTemplate.txt +++ b/SwiftyJSONAccelerator/Templates/Library-Extension-Templates/SwiftyJSONTemplate.txt @@ -1,18 +1,18 @@ - // MARK: SwiftyJSON Initalizers + // MARK: SwiftyJSON Initializers /** - Initates the instance based on the object + Initiates the instance based on the object - parameter object: The object of either Dictionary or Array kind that was passed. - - returns: An initalized instance of the class. + - returns: An initialized instance of the class. */ - convenience public init(object: Any) { + public convenience init(object: Any) { self.init(json: JSON(object)) } /** - Initates the instance based on the JSON that was passed. + Initiates the instance based on the JSON that was passed. - parameter json: JSON object from SwiftyJSON. - - returns: An initalized instance of the class. + - returns: An initialized instance of the class. */ - public init(json: JSON) { -{INITALIZER} + public{REQUIRED}init(json: JSON) { +{INITIALIZER} } diff --git a/SwiftyJSONAccelerator/UI/SJEditorViewController.swift b/SwiftyJSONAccelerator/UI/SJEditorViewController.swift index 82af2ed..8e85cfb 100644 --- a/SwiftyJSONAccelerator/UI/SJEditorViewController.swift +++ b/SwiftyJSONAccelerator/UI/SJEditorViewController.swift @@ -43,6 +43,7 @@ class SJEditorViewController: NSViewController, NSTextViewDelegate { @IBOutlet var authorNameTextField: NSTextField! @IBOutlet var includeHeaderImportCheckbox: NSButton! @IBOutlet var enableNSCodingSupportCheckbox: NSButton! + @IBOutlet var setAsFinalCheckbox: NSButton! @IBOutlet var librarySelector: NSPopUpButton! @IBOutlet var modelTypeSelectorSegment: NSSegmentedControl! @@ -123,8 +124,9 @@ class SJEditorViewController: NSViewController, NSTextViewDelegate { if object != nil { let nsCodingState = self.enableNSCodingSupportCheckbox.state == 1 && (modelTypeSelectorSegment.selectedSegment == 1) + let isFinalClass = self.setAsFinalCheckbox.state == 1 && (modelTypeSelectorSegment.selectedSegment == 1) let constructType = self.modelTypeSelectorSegment.selectedSegment == 0 ? ConstructType.StructType : ConstructType.ClassType - let libraryType = self.librarySelector.indexOfSelectedItem == 0 ? JSONMappingLibrary.SwiftyJSON : JSONMappingLibrary.ObjectMapper + let libraryType = libraryForIndex(self.librarySelector.indexOfSelectedItem) let configuration = ModelGenerationConfiguration.init( filePath: filePath!.appending("/"), baseClassName: baseClassTextField.stringValue, @@ -133,7 +135,8 @@ class SJEditorViewController: NSViewController, NSTextViewDelegate { prefix: prefixClassTextField.stringValue, constructType: constructType, modelMappingLibrary: libraryType, - supportNSCoding: nsCodingState) + supportNSCoding: nsCodingState, + isFinalRequired: isFinalClass) let modelGenerator = ModelGenerator.init(JSON(object!), configuration) let filesGenerated = modelGenerator.generate() var successState = true @@ -151,8 +154,18 @@ class SJEditorViewController: NSViewController, NSTextViewDelegate { } } + func libraryForIndex(_ index: Int) -> JSONMappingLibrary { + if index == 2 { + return JSONMappingLibrary.ObjectMapper + } else if index == 3 { + return JSONMappingLibrary.Marshal + } + return JSONMappingLibrary.SwiftyJSON + } + @IBAction func recalcEnabledBoxes(_ sender: AnyObject) { self.enableNSCodingSupportCheckbox.isEnabled = (modelTypeSelectorSegment.selectedSegment == 1) + self.setAsFinalCheckbox.isEnabled = (modelTypeSelectorSegment.selectedSegment == 1) } diff --git a/SwiftyJSONAcceleratorTests/ModelGeneratorTests.swift b/SwiftyJSONAcceleratorTests/ModelGeneratorTests.swift index 27ca391..bb3285b 100644 --- a/SwiftyJSONAcceleratorTests/ModelGeneratorTests.swift +++ b/SwiftyJSONAcceleratorTests/ModelGeneratorTests.swift @@ -14,290 +14,355 @@ import SwiftyJSON /// Test cases for the model Generator. class ModelGeneratorTests: XCTestCase { - override func setUp() { - super.setUp() - NSUserNotificationCenter.default.removeAllDeliveredNotifications() - } + override func setUp() { + super.setUp() + NSUserNotificationCenter.default.removeAllDeliveredNotifications() + } - override func tearDown() { - NSUserNotificationCenter.default.removeAllDeliveredNotifications() - super.tearDown() - } + override func tearDown() { + NSUserNotificationCenter.default.removeAllDeliveredNotifications() + super.tearDown() + } - /** + /** Generate a sample JSON class with all possible scenarioes. - returns: A valid JSON. */ - func testJSON() -> JSON { - return JSON.init( - ["value_one": "string value", - "value_two": 3, - "value_three": true, - "value_four": 3.4, - "value_dont_show": nil, - "value_five": ["string", "random_stuff"], - "value_six": ["sub_value": "value", "sub_value_second": false], - "value_seven": [ - [ - "sub_value_third": 4.5, - "double_value": Double.init(5.3), - "sub_value_four": "value", - "internal": "renamed_value", - "sub_value_five": ["two_level_down": "value"] - ] - ], - "value_eight": [] - ]) - } - - /** + func testJSON() -> JSON { + return JSON.init( + ["value_one": "string value", + "value_two": 3, + "value_three": true, + "value_four": 3.4, + "value_dont_show": nil, + "value_five": ["string", "random_stuff"], + "value_six": ["sub_value": "value", "sub_value_second": false], + "value_seven": [ + [ + "sub_value_third": 4.5, + "double_value": Double.init(5.3), + "sub_value_four": "value", + "internal": "renamed_value", + "sub_value_five": ["two_level_down": "value"] + ] + ], + "value_eight": [] + ]) + } + + /** Default configuration for the tests. - parameter library: Type of library to use. - returns: Default configuration file. */ - func defaultConfiguration(_ library: JSONMappingLibrary) -> ModelGenerationConfiguration { - return ModelGenerationConfiguration.init( - filePath: "/tmp/", - baseClassName: "BaseClass", - authorName: "Jane Smith", - companyName: "Acme Co.", - prefix: "AC", - constructType: .StructType, - modelMappingLibrary: library, - supportNSCoding: true) - } - - /** + func defaultConfiguration(_ library: JSONMappingLibrary) -> ModelGenerationConfiguration { + return ModelGenerationConfiguration.init( + filePath: "/tmp/", + baseClassName: "BaseClass", + authorName: "Jane Smith", + companyName: "Acme Co.", + prefix: "AC", + constructType: .StructType, + modelMappingLibrary: library, + supportNSCoding: true, + isFinalRequired: true) + } + + /** Test model file initialisation test. */ - func testinitaliseModelFileFor() { - let config = defaultConfiguration(.SwiftyJSON) - let m = ModelGenerator.init(JSON.init([testJSON()]), config) - expect(m.initaliseModelFileFor(.SwiftyJSON) is SwiftyJSONModelFile).to(equal(true)) - expect(m.initaliseModelFileFor(.SwiftyJSON) is ObjectMapperModelFile).to(equal(false)) - expect(m.initaliseModelFileFor(.ObjectMapper) is SwiftyJSONModelFile).to(equal(false)) - expect(m.initaliseModelFileFor(.ObjectMapper) is ObjectMapperModelFile).to(equal(true)) - } - - /** + func testinitaliseModelFileFor() { + let config = defaultConfiguration(.SwiftyJSON) + let m = ModelGenerator.init(JSON.init([testJSON()]), config) + expect(m.initaliseModelFileFor(.SwiftyJSON) is SwiftyJSONModelFile).to(equal(true)) + expect(m.initaliseModelFileFor(.SwiftyJSON) is ObjectMapperModelFile).to(equal(false)) + expect(m.initaliseModelFileFor(.ObjectMapper) is SwiftyJSONModelFile).to(equal(false)) + expect(m.initaliseModelFileFor(.ObjectMapper) is ObjectMapperModelFile).to(equal(true)) + } + + /** Test notifications to be generated for the given files. */ - func testNotifications() { - let config = defaultConfiguration(.SwiftyJSON) - let m = ModelGenerator.init(JSON.init([testJSON()]), config) - let files = m.generate() - let errorNotification = m.generateNotificationFor([]) - expect(errorNotification.title).to(equal("SwiftyJSONAccelerator")) - expect(errorNotification.subtitle).to(equal("No files were generated, cannot model arrays inside arrays.")) - let correctNotification = m.generateNotificationFor(files) - expect(correctNotification.title).to(equal("SwiftyJSONAccelerator")) - expect(correctNotification.subtitle).to(equal("Completed - ACBaseClass.swift")) - - } - - /** + func testNotifications() { + let config = defaultConfiguration(.SwiftyJSON) + let m = ModelGenerator.init(JSON.init([testJSON()]), config) + let files = m.generate() + let errorNotification = m.generateNotificationFor([]) + expect(errorNotification.title).to(equal("SwiftyJSONAccelerator")) + expect(errorNotification.subtitle).to(equal("No files were generated, cannot model arrays inside arrays.")) + let correctNotification = m.generateNotificationFor(files) + expect(correctNotification.title).to(equal("SwiftyJSONAccelerator")) + expect(correctNotification.subtitle).to(equal("Completed - ACBaseClass.swift")) + + } + + /** Test for invalid JSON. */ - func testSwiftyJSONForInvalidJSON() { - let config = defaultConfiguration(.SwiftyJSON) - let m = ModelGenerator.init(JSON.init(["hello!"]), config) - let files = m.generate() - expect(files.count).to(equal(0)) - } - - /** + func testSwiftyJSONForInvalidJSON() { + let config = defaultConfiguration(.SwiftyJSON) + let m = ModelGenerator.init(JSON.init(["hello!"]), config) + let files = m.generate() + expect(files.count).to(equal(0)) + } + + /** Generate files for JSON which is an array. */ - func testSwiftyJSONModelWithRootAsArray() { - let config = defaultConfiguration(.SwiftyJSON) - let m = ModelGenerator.init(JSON.init([testJSON()]), config) - let files = m.generate() - expect(files.count).to(equal(4)) - - var objectKey = "ValueSix" - objectKey.appendPrefix(config.prefix) - expect(files[1].fileName).to(equal(objectKey)) - - var subValueKey = "ValueSeven" - subValueKey.appendPrefix(config.prefix) - expect(files[2].fileName).to(equal(subValueKey)) - - var objectArrayKey = "SubValueFive" - objectArrayKey.appendPrefix(config.prefix) - expect(files[3].fileName).to(equal(objectArrayKey)) - - let baseModelFile = files.first - var baseClass = config.baseClassName - baseClass.appendPrefix(config.prefix) - expect(baseModelFile!.fileName).to(equal(baseClass)) - } + func testSwiftyJSONModelWithRootAsArray() { + let config = defaultConfiguration(.SwiftyJSON) + let m = ModelGenerator.init(JSON.init([testJSON()]), config) + let files = m.generate() + expect(files.count).to(equal(4)) + + var objectKey = "ValueSix" + objectKey.appendPrefix(config.prefix) + expect(files[1].fileName).to(equal(objectKey)) + + var subValueKey = "ValueSeven" + subValueKey.appendPrefix(config.prefix) + expect(files[2].fileName).to(equal(subValueKey)) + + var objectArrayKey = "SubValueFive" + objectArrayKey.appendPrefix(config.prefix) + expect(files[3].fileName).to(equal(objectArrayKey)) + + let baseModelFile = files.first + var baseClass = config.baseClassName + baseClass.appendPrefix(config.prefix) + expect(baseModelFile!.fileName).to(equal(baseClass)) + } - /** + /** Generate and test the files generated for SwiftyJSON value. */ - func testSwiftyJSONModel() { - let config = defaultConfiguration(.SwiftyJSON) - let m = ModelGenerator.init(testJSON(), config) - let files = m.generate() - runCheckForBaseModel(files, config, runSwiftyJSONInitialiserCheckForBaseModel(_:)) - - for m in files { - let content = FileGenerator.generateFileContentWith(m, configuration: config) - let name = m.fileName - let path = "/Users/karthikeyaudupa/Desktop/tmp/sj/" - expect(FileGenerator.writeToFileWith(name, content: content, path: path)).to(equal(true)) - } + func testSwiftyJSONModel() { + let config = defaultConfiguration(.SwiftyJSON) + let m = ModelGenerator.init(testJSON(), config) + let files = m.generate() + runCheckForBaseModel(files, config, runSwiftyJSONInitialiserCheckForBaseModel(_:)) + + for m in files { + let content = FileGenerator.generateFileContentWith(m, configuration: config) + let name = m.fileName + let path = "/Users/karthikeyaudupa/Desktop/tmp/sj/" + expect(FileGenerator.writeToFileWith(name, content: content, path: path)).to(equal(true)) + } - } + } - /** + /** Generate and test the files generated for ObjectMapper value. */ - func testObjectMapperModel() { - let config = defaultConfiguration(.ObjectMapper) - let m = ModelGenerator.init(testJSON(), config) - let files = m.generate() - runCheckForBaseModel(files, config, runObjectMapperInitialiserCheckForBaseModel(_:)) - - for m in files { - let content = FileGenerator.generateFileContentWith(m, configuration: config) - let name = m.fileName - let path = "/Users/karthikeyaudupa/Desktop/tmp/om/" - expect(FileGenerator.writeToFileWith(name, content: content, path: path)).to(equal(true)) + func testObjectMapperModel() { + let config = defaultConfiguration(.ObjectMapper) + let m = ModelGenerator.init(testJSON(), config) + let files = m.generate() + runCheckForBaseModel(files, config, runObjectMapperInitialiserCheckForBaseModel(_:)) + + for m in files { + let content = FileGenerator.generateFileContentWith(m, configuration: config) + let name = m.fileName + let path = "/Users/karthikeyaudupa/Desktop/tmp/om/" + expect(FileGenerator.writeToFileWith(name, content: content, path: path)).to(equal(true)) + } } - } - - func runCheckForBaseModel(_ files: [ModelFile], _ config: ModelGenerationConfiguration, _ initialiserCheeck: ((ModelFile) -> Void)) { - - expect(files.count).to(equal(4)) - - var objectKey = "ValueSix" - objectKey.appendPrefix(config.prefix) - expect(files[1].fileName).to(equal(objectKey)) - - var subValueKey = "ValueSeven" - subValueKey.appendPrefix(config.prefix) - expect(files[2].fileName).to(equal(subValueKey)) - - var objectArrayKey = "SubValueFive" - objectArrayKey.appendPrefix(config.prefix) - expect(files[3].fileName).to(equal(objectArrayKey)) - - let baseModelFile = files.first - var baseClass = config.baseClassName - baseClass.appendPrefix(config.prefix) - expect(baseModelFile!.fileName).to(equal(baseClass)) - - expect(baseModelFile!.component.stringConstants.count).to(equal(8)) - let stringConstants = [ - "private let kACBaseClassValueSevenKey: String = \"value_seven\"", - "private let kACBaseClassValueTwoKey: String = \"value_two\"", - "private let kACBaseClassValueFourKey: String = \"value_four\"", - "private let kACBaseClassValueFiveKey: String = \"value_five\"", - "private let kACBaseClassValueSixKey: String = \"value_six\"", - "private let kACBaseClassValueOneKey: String = \"value_one\"", - "private let kACBaseClassValueThreeKey: String = \"value_three\"", - "private let kACBaseClassValueEightKey: String = \"value_eight\"" - ] - for stringConstant in stringConstants { - expect(baseModelFile!.component.stringConstants.contains(stringConstant)).to(equal(true)) + /** + Generate and test the files generated for Marshal value. + */ + func testMarshalModel() { + let config = defaultConfiguration(.Marshal) + let m = ModelGenerator.init(testJSON(), config) + let files = m.generate() + runCheckForBaseModel(files, config, runMarshalInitialiserCheckForBaseModel(_:)) + + for m in files { + let content = FileGenerator.generateFileContentWith(m, configuration: config) + expect(content.contains("public required init(object: MarshaledObject)")).to(equal(false)) + expect(content.contains("public init(object: MarshaledObject)")).to(equal(true)) + expect(content.contains("public struct")).to(equal(true)) + let name = m.fileName + let path = "/Users/karthikeyaudupa/Desktop/tmp/om/" + expect(FileGenerator.writeToFileWith(name, content: content, path: path)).to(equal(true)) + } } - - expect(baseModelFile!.component.declarations.count).to(equal(8)) - let declarations = [ - "public var valueSeven: [ACValueSeven]?", - "public var valueTwo: Int?", - "public var valueFour: Float?", - "public var valueFive: [String]?", - "public var valueSix: ACValueSix?", - "public var valueOne: String?", - "public var valueThree: Bool = false", - "public var valueEight: [Any]?" - ] - for declaration in declarations { - expect(baseModelFile!.component.declarations.contains(declaration)).to(equal(true)) + + func testMarshalModelAsClass() { + let config = ModelGenerationConfiguration.init( + filePath: "/tmp/", + baseClassName: "BaseClass", + authorName: "Jane Smith", + companyName: "Acme Co.", + prefix: "AC", + constructType: .ClassType, + modelMappingLibrary: .Marshal, + supportNSCoding: true, + isFinalRequired: true) + let m = ModelGenerator.init(testJSON(), config) + let files = m.generate() + runCheckForBaseModel(files, config, runMarshalInitialiserCheckForBaseModel(_:)) + + for m in files { + let content = FileGenerator.generateFileContentWith(m, configuration: config) + expect(content.contains("public required init(object: MarshaledObject)")).to(equal(true)) + expect(content.contains("public init(object: MarshaledObject)")).to(equal(false)) + expect(content.contains("public final class")).to(equal(true)) + let name = m.fileName + let path = "/Users/karthikeyaudupa/Desktop/tmp/om/" + expect(FileGenerator.writeToFileWith(name, content: content, path: path)).to(equal(true)) + } } + - expect(baseModelFile!.component.description.count).to(equal(8)) - let descriptions = [ - "if let value = valueSix { dictionary[kACBaseClassValueSixKey] = value.dictionaryRepresentation() }", - "if let value = valueFive { dictionary[kACBaseClassValueFiveKey] = value }", - "if let value = valueTwo { dictionary[kACBaseClassValueTwoKey] = value }", - "dictionary[kACBaseClassValueThreeKey] = valueThree", - "if let value = valueSeven { dictionary[kACBaseClassValueSevenKey] = value.map { $0.dictionaryRepresentation() } }", - "if let value = valueOne { dictionary[kACBaseClassValueOneKey] = value }", - "if let value = valueFour { dictionary[kACBaseClassValueFourKey] = value }", - "if let value = valueEight { dictionary[kACBaseClassValueEightKey] = value }" - ] - for description in descriptions { - expect(baseModelFile!.component.description.contains(description)).to(equal(true)) + func runCheckForBaseModel(_ files: [ModelFile], _ config: ModelGenerationConfiguration, _ initialiserCheeck: ((ModelFile) -> Void)) { + + expect(files.count).to(equal(4)) + + var objectKey = "ValueSix" + objectKey.appendPrefix(config.prefix) + expect(files[1].fileName).to(equal(objectKey)) + + var subValueKey = "ValueSeven" + subValueKey.appendPrefix(config.prefix) + expect(files[2].fileName).to(equal(subValueKey)) + + var objectArrayKey = "SubValueFive" + objectArrayKey.appendPrefix(config.prefix) + expect(files[3].fileName).to(equal(objectArrayKey)) + + let baseModelFile = files.first + var baseClass = config.baseClassName + baseClass.appendPrefix(config.prefix) + expect(baseModelFile!.fileName).to(equal(baseClass)) + + expect(baseModelFile!.component.stringConstants.count).to(equal(8)) + let stringConstants = [ + "private let kACBaseClassValueSevenKey: String = \"value_seven\"", + "private let kACBaseClassValueTwoKey: String = \"value_two\"", + "private let kACBaseClassValueFourKey: String = \"value_four\"", + "private let kACBaseClassValueFiveKey: String = \"value_five\"", + "private let kACBaseClassValueSixKey: String = \"value_six\"", + "private let kACBaseClassValueOneKey: String = \"value_one\"", + "private let kACBaseClassValueThreeKey: String = \"value_three\"", + "private let kACBaseClassValueEightKey: String = \"value_eight\"" + ] + for stringConstant in stringConstants { + expect(baseModelFile!.component.stringConstants.contains(stringConstant)).to(equal(true)) + } + + expect(baseModelFile!.component.declarations.count).to(equal(8)) + let declarations = [ + "public var valueSeven: [ACValueSeven]?", + "public var valueTwo: Int?", + "public var valueFour: Float?", + "public var valueFive: [String]?", + "public var valueSix: ACValueSix?", + "public var valueOne: String?", + "public var valueThree: Bool = false", + "public var valueEight: [Any]?" + ] + for declaration in declarations { + expect(baseModelFile!.component.declarations.contains(declaration)).to(equal(true)) + } + + expect(baseModelFile!.component.description.count).to(equal(8)) + let descriptions = [ + "if let value = valueSix { dictionary[kACBaseClassValueSixKey] = value.dictionaryRepresentation() }", + "if let value = valueFive { dictionary[kACBaseClassValueFiveKey] = value }", + "if let value = valueTwo { dictionary[kACBaseClassValueTwoKey] = value }", + "dictionary[kACBaseClassValueThreeKey] = valueThree", + "if let value = valueSeven { dictionary[kACBaseClassValueSevenKey] = value.map { $0.dictionaryRepresentation() } }", + "if let value = valueOne { dictionary[kACBaseClassValueOneKey] = value }", + "if let value = valueFour { dictionary[kACBaseClassValueFourKey] = value }", + "if let value = valueEight { dictionary[kACBaseClassValueEightKey] = value }" + ] + for description in descriptions { + expect(baseModelFile!.component.description.contains(description)).to(equal(true)) + } + + expect(baseModelFile!.component.encoders.count).to(equal(8)) + let encoders = [ + "aCoder.encode(valueSeven, forKey: kACBaseClassValueSevenKey)", + "aCoder.encode(valueTwo, forKey: kACBaseClassValueTwoKey)", + "aCoder.encode(valueFour, forKey: kACBaseClassValueFourKey)", + "aCoder.encode(valueFive, forKey: kACBaseClassValueFiveKey)", + "aCoder.encode(valueSix, forKey: kACBaseClassValueSixKey)", + "aCoder.encode(valueOne, forKey: kACBaseClassValueOneKey)", + "aCoder.encode(valueThree, forKey: kACBaseClassValueThreeKey)", + "aCoder.encode(valueEight, forKey: kACBaseClassValueEightKey)"] + for encoder in encoders { + expect(baseModelFile!.component.encoders.contains(encoder)).to(equal(true)) + } + + expect(baseModelFile!.component.decoders.count).to(equal(8)) + let decoders = [ + "self.valueSeven = aDecoder.decodeObject(forKey: kACBaseClassValueSevenKey) as? [ACValueSeven]", + "self.valueTwo = aDecoder.decodeObject(forKey: kACBaseClassValueTwoKey) as? Int", + "self.valueFour = aDecoder.decodeObject(forKey: kACBaseClassValueFourKey) as? Float", + "self.valueFive = aDecoder.decodeObject(forKey: kACBaseClassValueFiveKey) as? [String]", + "self.valueSix = aDecoder.decodeObject(forKey: kACBaseClassValueSixKey) as? ACValueSix", + "self.valueOne = aDecoder.decodeObject(forKey: kACBaseClassValueOneKey) as? String", + "self.valueThree = aDecoder.decodeBool(forKey: kACBaseClassValueThreeKey)", + "self.valueEight = aDecoder.decodeObject(forKey: kACBaseClassValueEightKey) as? [Any]" + ] + for decoder in decoders { + expect(baseModelFile!.component.decoders.contains(decoder)).to(equal(true)) + } } - expect(baseModelFile!.component.encoders.count).to(equal(8)) - let encoders = [ - "aCoder.encode(valueSeven, forKey: kACBaseClassValueSevenKey)", - "aCoder.encode(valueTwo, forKey: kACBaseClassValueTwoKey)", - "aCoder.encode(valueFour, forKey: kACBaseClassValueFourKey)", - "aCoder.encode(valueFive, forKey: kACBaseClassValueFiveKey)", - "aCoder.encode(valueSix, forKey: kACBaseClassValueSixKey)", - "aCoder.encode(valueOne, forKey: kACBaseClassValueOneKey)", - "aCoder.encode(valueThree, forKey: kACBaseClassValueThreeKey)", - "aCoder.encode(valueEight, forKey: kACBaseClassValueEightKey)"] - for encoder in encoders { - expect(baseModelFile!.component.encoders.contains(encoder)).to(equal(true)) + func runSwiftyJSONInitialiserCheckForBaseModel(_ baseModelFile: ModelFile) { + expect(baseModelFile.component.initialisers.count).to(equal(8)) + let initialisers = [ + "if let items = json[kACBaseClassValueSevenKey].array { valueSeven = items.map { ACValueSeven(json: $0) } }", + "valueTwo = json[kACBaseClassValueTwoKey].int", + "valueFour = json[kACBaseClassValueFourKey].float", + "if let items = json[kACBaseClassValueFiveKey].array { valueFive = items.map { $0.stringValue } }", + "valueSix = ACValueSix(json: json[kACBaseClassValueSixKey])", + "valueOne = json[kACBaseClassValueOneKey].string", + "valueThree = json[kACBaseClassValueThreeKey].boolValue", + "if let items = json[kACBaseClassValueEightKey].array { valueEight = items.map { $0.object} }" + ] + for initialiser in initialisers { + expect(baseModelFile.component.initialisers.contains(initialiser)).to(equal(true)) + } } - expect(baseModelFile!.component.decoders.count).to(equal(8)) - let decoders = [ - "self.valueSeven = aDecoder.decodeObject(forKey: kACBaseClassValueSevenKey) as? [ACValueSeven]", - "self.valueTwo = aDecoder.decodeObject(forKey: kACBaseClassValueTwoKey) as? Int", - "self.valueFour = aDecoder.decodeObject(forKey: kACBaseClassValueFourKey) as? Float", - "self.valueFive = aDecoder.decodeObject(forKey: kACBaseClassValueFiveKey) as? [String]", - "self.valueSix = aDecoder.decodeObject(forKey: kACBaseClassValueSixKey) as? ACValueSix", - "self.valueOne = aDecoder.decodeObject(forKey: kACBaseClassValueOneKey) as? String", - "self.valueThree = aDecoder.decodeBool(forKey: kACBaseClassValueThreeKey)", - "self.valueEight = aDecoder.decodeObject(forKey: kACBaseClassValueEightKey) as? [Any]" - ] - for decoder in decoders { - expect(baseModelFile!.component.decoders.contains(decoder)).to(equal(true)) + func runObjectMapperInitialiserCheckForBaseModel(_ baseModelFile: ModelFile) { + expect(baseModelFile.component.initialisers.count).to(equal(8)) + let initialisers = [ + "valueSeven <- map[kACBaseClassValueSevenKey]", + "valueTwo <- map[kACBaseClassValueTwoKey]", + "valueFour <- map[kACBaseClassValueFourKey]", + "valueFive <- map[kACBaseClassValueFiveKey]", + "valueSix <- map[kACBaseClassValueSixKey]", + "valueEight <- map[kACBaseClassValueEightKey]", + "valueOne <- map[kACBaseClassValueOneKey]", + "valueThree <- map[kACBaseClassValueThreeKey]" + ] + for initialiser in initialisers { + expect(baseModelFile.component.initialisers.contains(initialiser)).to(equal(true)) + } } - } - - func runSwiftyJSONInitialiserCheckForBaseModel(_ baseModelFile: ModelFile) { - expect(baseModelFile.component.initialisers.count).to(equal(8)) - let initialisers = [ - "if let items = json[kACBaseClassValueSevenKey].array { valueSeven = items.map { ACValueSeven(json: $0) } }", - "valueTwo = json[kACBaseClassValueTwoKey].int", - "valueFour = json[kACBaseClassValueFourKey].float", - "if let items = json[kACBaseClassValueFiveKey].array { valueFive = items.map { $0.stringValue } }", - "valueSix = ACValueSix(json: json[kACBaseClassValueSixKey])", - "valueOne = json[kACBaseClassValueOneKey].string", - "valueThree = json[kACBaseClassValueThreeKey].boolValue", - "if let items = json[kACBaseClassValueEightKey].array { valueEight = items.map { $0.object} }" - ] - for initialiser in initialisers { - expect(baseModelFile.component.initialisers.contains(initialiser)).to(equal(true)) - } - } - - func runObjectMapperInitialiserCheckForBaseModel(_ baseModelFile: ModelFile) { - expect(baseModelFile.component.initialisers.count).to(equal(8)) - let initialisers = [ - "valueSeven <- map[kACBaseClassValueSevenKey]", - "valueTwo <- map[kACBaseClassValueTwoKey]", - "valueFour <- map[kACBaseClassValueFourKey]", - "valueFive <- map[kACBaseClassValueFiveKey]", - "valueSix <- map[kACBaseClassValueSixKey]", - "valueEight <- map[kACBaseClassValueEightKey]", - "valueOne <- map[kACBaseClassValueOneKey]", - "valueThree <- map[kACBaseClassValueThreeKey]" - ] - for initialiser in initialisers { - expect(baseModelFile.component.initialisers.contains(initialiser)).to(equal(true)) + + func runMarshalInitialiserCheckForBaseModel(_ baseModelFile: ModelFile) { + expect(baseModelFile.component.initialisers.count).to(equal(8)) + let initialisers = [ + "valueSeven = try? object.value(for: kACBaseClassValueSevenKey)", + "valueTwo = try? object.value(for: kACBaseClassValueTwoKey)", + "valueFour = try? object.value(for: kACBaseClassValueFourKey)", + "valueFive = try? object.value(for: kACBaseClassValueFiveKey)", + "valueSix = try? object.value(for: kACBaseClassValueSixKey)", + "valueOne = try? object.value(for: kACBaseClassValueOneKey)", + "valueThree = try? object.value(for: kACBaseClassValueThreeKey)", + "valueEight = try? object.value(for: kACBaseClassValueEightKey)" + ] + for initialiser in initialisers { + expect(baseModelFile.component.initialisers.contains(initialiser)).to(equal(true)) + } } - } + } diff --git a/preview.png b/preview.png index 4992950..79c03e0 100644 Binary files a/preview.png and b/preview.png differ