Skip to content

Commit f7cd351

Browse files
committed
Added option to mark class as Final
1 parent 046796b commit f7cd351

File tree

6 files changed

+166
-112
lines changed

6 files changed

+166
-112
lines changed

SwiftyJSONAccelerator/Generators/FileGenerator.swift

Lines changed: 95 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -10,91 +10,97 @@ import Foundation
1010

1111
struct FileGenerator {
1212

13-
/**
13+
/**
1414
Fetch the template for creating model.swift files.
1515

1616
- parameter filename: Name of the file to be loaded
1717

1818
- returns: String containing the template.
1919
*/
20-
static func loadFileWith(_ filename: String) -> String {
20+
static func loadFileWith(_ filename: String) -> String {
2121

22-
let bundle = Bundle.main
23-
let path = bundle.path(forResource: filename, ofType: "txt")
22+
let bundle = Bundle.main
23+
let path = bundle.path(forResource: filename, ofType: "txt")
2424

25-
do {
26-
let content = try String.init(contentsOfFile: path!)
27-
return content
28-
} catch { }
25+
do {
26+
let content = try String.init(contentsOfFile: path!)
27+
return content
28+
} catch { }
2929

30-
return ""
31-
}
32-
33-
static func generateFileContentWith(_ modelFile: ModelFile, configuration: ModelGenerationConfiguration) -> String {
34-
35-
var content = loadFileWith("BaseTemplate")
36-
content = content.replacingOccurrences(of: "{OBJECT_NAME}", with: modelFile.fileName)
37-
content = content.replacingOccurrences(of: "{DATE}", with: todayDateString())
38-
content = content.replacingOccurrences(of: "{OBJECT_KIND}", with: modelFile.type.rawValue)
39-
content = content.replacingOccurrences(of: "{JSON_PARSER_LIBRARY_BODY}", with: loadFileWith(modelFile.mainBodyFileName()))
40-
41-
if modelFile.type == .ClassType {
42-
content = content.replacingOccurrences(of: "{REQUIRED}", with: " required ")
43-
} else {
44-
content = content.replacingOccurrences(of: "{REQUIRED}", with: " ")
45-
}
46-
if let authorName = configuration.authorName {
47-
content = content.replacingOccurrences(of: "__NAME__", with: authorName)
48-
}
49-
if let companyName = configuration.companyName {
50-
content = content.replacingOccurrences(of: "__MyCompanyName__", with: companyName)
51-
}
52-
content = content.replacingOccurrences(of: "{INCLUDE_HEADER}", with: "\nimport \(modelFile.moduleName())")
53-
54-
var classesExtendFrom: [String] = []
55-
if let extendFrom = modelFile.baseElementName() {
56-
classesExtendFrom = [extendFrom]
57-
}
58-
if configuration.supportNSCoding && configuration.constructType == .ClassType {
59-
classesExtendFrom = classesExtendFrom + ["NSCoding"]
30+
return ""
6031
}
6132

62-
if classesExtendFrom.count > 0 {
63-
content = content.replacingOccurrences(of: "{EXTEND_FROM}", with: classesExtendFrom.joined(separator: ", "))
64-
content = content.replacingOccurrences(of: "{EXTENDED_OBJECT_COLON}", with: ": ")
65-
} else {
66-
content = content.replacingOccurrences(of: "{EXTEND_FROM}", with: "")
67-
content = content.replacingOccurrences(of: "{EXTENDED_OBJECT_COLON}", with: "")
33+
static func generateFileContentWith(_ modelFile: ModelFile, configuration: ModelGenerationConfiguration) -> String {
34+
35+
var content = loadFileWith("BaseTemplate")
36+
content = content.replacingOccurrences(of: "{OBJECT_NAME}", with: modelFile.fileName)
37+
content = content.replacingOccurrences(of: "{DATE}", with: todayDateString())
38+
content = content.replacingOccurrences(of: "{OBJECT_KIND}", with: modelFile.type.rawValue)
39+
content = content.replacingOccurrences(of: "{JSON_PARSER_LIBRARY_BODY}", with: loadFileWith(modelFile.mainBodyFileName()))
40+
41+
if modelFile.type == .ClassType {
42+
content = content.replacingOccurrences(of: "{REQUIRED}", with: " required ")
43+
} else {
44+
content = content.replacingOccurrences(of: "{REQUIRED}", with: " ")
45+
}
46+
if let authorName = configuration.authorName {
47+
content = content.replacingOccurrences(of: "__NAME__", with: authorName)
48+
}
49+
if let companyName = configuration.companyName {
50+
content = content.replacingOccurrences(of: "__MyCompanyName__", with: companyName)
51+
}
52+
content = content.replacingOccurrences(of: "{INCLUDE_HEADER}", with: "\nimport \(modelFile.moduleName())")
53+
54+
var classesExtendFrom: [String] = []
55+
if let extendFrom = modelFile.baseElementName() {
56+
classesExtendFrom = [extendFrom]
57+
}
58+
if configuration.supportNSCoding && configuration.constructType == .ClassType {
59+
classesExtendFrom = classesExtendFrom + ["NSCoding"]
60+
}
61+
62+
if configuration.isFinalRequired && configuration.constructType == .ClassType {
63+
content = content.replacingOccurrences(of: "{IS_FINAL}", with: " final ")
64+
} else {
65+
content = content.replacingOccurrences(of: "{IS_FINAL}", with: " ")
66+
}
67+
68+
if classesExtendFrom.count > 0 {
69+
content = content.replacingOccurrences(of: "{EXTEND_FROM}", with: classesExtendFrom.joined(separator: ", "))
70+
content = content.replacingOccurrences(of: "{EXTENDED_OBJECT_COLON}", with: ": ")
71+
} else {
72+
content = content.replacingOccurrences(of: "{EXTEND_FROM}", with: "")
73+
content = content.replacingOccurrences(of: "{EXTENDED_OBJECT_COLON}", with: "")
74+
}
75+
76+
let stringConstants = modelFile.component.stringConstants.map({ " " + $0 }).joined(separator: "\n")
77+
let declarations = modelFile.component.declarations.map({ " " + $0 }).joined(separator: "\n")
78+
let initialisers = modelFile.component.initialisers.map({ " " + $0 }).joined(separator: "\n")
79+
let description = modelFile.component.description.map({ " " + $0 }).joined(separator: "\n")
80+
81+
content = content.replacingOccurrences(of: "{STRING_CONSTANT}", with: stringConstants)
82+
content = content.replacingOccurrences(of: "{DECLARATION}", with: declarations)
83+
content = content.replacingOccurrences(of: "{INITIALIZER}", with: initialisers)
84+
content = content.replacingOccurrences(of: "{DESCRIPTION}", with: description)
85+
86+
if configuration.constructType == .StructType {
87+
content = content.replacingOccurrences(of: " convenience", with: "")
88+
}
89+
90+
if configuration.supportNSCoding && configuration.constructType == .ClassType {
91+
content = content.replacingOccurrences(of: "{NSCODING_SUPPORT}", with: loadFileWith("NSCodingTemplate"))
92+
let encoders = modelFile.component.encoders.map({ " " + $0 }).joined(separator: "\n")
93+
let decoders = modelFile.component.decoders.map({ " " + $0 }).joined(separator: "\n")
94+
content = content.replacingOccurrences(of: "{DECODERS}", with: decoders)
95+
content = content.replacingOccurrences(of: "{ENCODERS}", with: encoders)
96+
} else {
97+
content = content.replacingOccurrences(of: "{NSCODING_SUPPORT}", with: "")
98+
}
99+
100+
return content
68101
}
69102

70-
let stringConstants = modelFile.component.stringConstants.map({ " " + $0 }).joined(separator: "\n")
71-
let declarations = modelFile.component.declarations.map({ " " + $0 }).joined(separator: "\n")
72-
let initialisers = modelFile.component.initialisers.map({ " " + $0 }).joined(separator: "\n")
73-
let description = modelFile.component.description.map({ " " + $0 }).joined(separator: "\n")
74-
75-
content = content.replacingOccurrences(of: "{STRING_CONSTANT}", with: stringConstants)
76-
content = content.replacingOccurrences(of: "{DECLARATION}", with: declarations)
77-
content = content.replacingOccurrences(of: "{INITIALIZER}", with: initialisers)
78-
content = content.replacingOccurrences(of: "{DESCRIPTION}", with: description)
79-
80-
if configuration.constructType == .StructType {
81-
content = content.replacingOccurrences(of: " convenience", with: "")
82-
}
83-
84-
if configuration.supportNSCoding && configuration.constructType == .ClassType {
85-
content = content.replacingOccurrences(of: "{NSCODING_SUPPORT}", with: loadFileWith("NSCodingTemplate"))
86-
let encoders = modelFile.component.encoders.map({ " " + $0 }).joined(separator: "\n")
87-
let decoders = modelFile.component.decoders.map({ " " + $0 }).joined(separator: "\n")
88-
content = content.replacingOccurrences(of: "{DECODERS}", with: decoders)
89-
content = content.replacingOccurrences(of: "{ENCODERS}", with: encoders)
90-
} else {
91-
content = content.replacingOccurrences(of: "{NSCODING_SUPPORT}", with: "")
92-
}
93-
94-
return content
95-
}
96-
97-
/**
103+
/**
98104
Write the given content to a file at the mentioned path.
99105

100106
- parameter name: The name of the file.
@@ -103,24 +109,24 @@ struct FileGenerator {
103109

104110
- returns: Boolean indicating if the process was successful.
105111
*/
106-
static internal func writeToFileWith(_ name: String, content: String, path: String) -> Bool {
107-
let filename = path.appendingFormat("%@", (name + ".swift"))
108-
do {
109-
try FileManager.default.createDirectory(at: URL.init(fileURLWithPath: path),
110-
withIntermediateDirectories: true,
111-
attributes: nil)
112-
try content.write(toFile: filename, atomically: true, encoding: String.Encoding.utf8)
113-
return true
114-
} catch let error as NSError {
115-
print(error)
116-
return false
112+
static internal func writeToFileWith(_ name: String, content: String, path: String) -> Bool {
113+
let filename = path.appendingFormat("%@", (name + ".swift"))
114+
do {
115+
try FileManager.default.createDirectory(at: URL.init(fileURLWithPath: path),
116+
withIntermediateDirectories: true,
117+
attributes: nil)
118+
try content.write(toFile: filename, atomically: true, encoding: String.Encoding.utf8)
119+
return true
120+
} catch let error as NSError {
121+
print(error)
122+
return false
123+
}
117124
}
118-
}
119125

120-
static fileprivate func todayDateString() -> String {
121-
let formatter = DateFormatter.init()
122-
formatter.dateStyle = .short
123-
return formatter.string(from: Date.init())
124-
}
126+
static fileprivate func todayDateString() -> String {
127+
let formatter = DateFormatter.init()
128+
formatter.dateStyle = .short
129+
return formatter.string(from: Date.init())
130+
}
125131

126132
}

SwiftyJSONAccelerator/Models-Components/ModelGenerationConfiguration.swift

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,22 @@ import Foundation
1212
* Structure to store the configuration for the model generation.
1313
*/
1414
struct ModelGenerationConfiguration {
15-
/// Path where the generated files have to be stored.
16-
var filePath: String
17-
/// Name of the root level class for the provided JSON.
18-
var baseClassName: String
19-
/// The author name that has to be put in the file's header comments.
20-
var authorName: String?
21-
/// Company name that has to be put into the file's header.
22-
var companyName: String?
23-
/// A namespace prefix for the file (not recommended for Swift but people might want it)
24-
var prefix: String?
25-
/// Type of the object that have to be generated.
26-
var constructType: ConstructType
27-
/// Model mapping library to be used.
28-
var modelMappingLibrary: JSONMappingLibrary
29-
/// Include NSCodingSupport/Currently only works for Classes.
30-
var supportNSCoding: Bool
15+
/// Path where the generated files have to be stored.
16+
var filePath: String
17+
/// Name of the root level class for the provided JSON.
18+
var baseClassName: String
19+
/// The author name that has to be put in the file's header comments.
20+
var authorName: String?
21+
/// Company name that has to be put into the file's header.
22+
var companyName: String?
23+
/// A namespace prefix for the file (not recommended for Swift but people might want it)
24+
var prefix: String?
25+
/// Type of the object that have to be generated.
26+
var constructType: ConstructType
27+
/// Model mapping library to be used.
28+
var modelMappingLibrary: JSONMappingLibrary
29+
/// Include NSCodingSupport/Currently only works for Classes.
30+
var supportNSCoding: Bool
31+
/// Indicates if the final keyword is required for the object.
32+
var isFinalRequired: Bool
3133
}

SwiftyJSONAccelerator/Storyboard/Base.lproj/Main.storyboard

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<dependencies>
44
<deployment identifier="macosx"/>
55
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11542"/>
6+
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
67
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
78
</dependencies>
89
<scenes>
@@ -757,7 +758,7 @@
757758
<font key="font" metaFont="menu"/>
758759
<menu key="menu" autoenablesItems="NO" id="QJi-PT-im1">
759760
<items>
760-
<menuItem title="SwiftyJSON" state="on" hidden="YES" id="0QP-u9-O6V"/>
761+
<menuItem title="SwiftyJSON" state="on" id="0QP-u9-O6V"/>
761762
<menuItem title="ObjectMapper" id="FPc-o9-hXy"/>
762763
<menuItem title="Marshal" id="7Q8-u2-Yfm"/>
763764
</items>
@@ -788,12 +789,19 @@
788789
</buttonCell>
789790
</button>
790791
<button translatesAutoresizingMaskIntoConstraints="NO" id="ZXf-O8-Z1c">
791-
<rect key="frame" x="363" y="14" width="346" height="18"/>
792+
<rect key="frame" x="363" y="14" width="175" height="18"/>
792793
<buttonCell key="cell" type="check" title="Support NSCoding" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="X76-Zb-p14">
793794
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
794795
<font key="font" metaFont="system"/>
795796
</buttonCell>
796797
</button>
798+
<button translatesAutoresizingMaskIntoConstraints="NO" id="DR0-oc-DGs">
799+
<rect key="frame" x="542" y="14" width="175" height="18"/>
800+
<buttonCell key="cell" type="check" title="Set As Final" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="2nM-63-TSR">
801+
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
802+
<font key="font" metaFont="system"/>
803+
</buttonCell>
804+
</button>
797805
</subviews>
798806
<constraints>
799807
<constraint firstAttribute="trailing" secondItem="AwX-MF-DMD" secondAttribute="trailing" constant="10" id="1wF-Ly-8ue"/>
@@ -803,7 +811,7 @@
803811
<constraint firstItem="aJ1-yn-Pl7" firstAttribute="width" secondItem="mJg-3P-2Aw" secondAttribute="width" id="9m4-gy-MnL"/>
804812
<constraint firstAttribute="trailing" secondItem="Gmg-Tp-PPn" secondAttribute="trailing" id="APF-Xg-5Am"/>
805813
<constraint firstItem="U3A-Rw-grw" firstAttribute="leading" secondItem="mJg-3P-2Aw" secondAttribute="leading" id="Avf-R5-mSy"/>
806-
<constraint firstItem="ZXf-O8-Z1c" firstAttribute="width" secondItem="ZUC-Iy-7fC" secondAttribute="width" id="Dai-9x-FG5"/>
814+
<constraint firstItem="ZXf-O8-Z1c" firstAttribute="width" secondItem="ZUC-Iy-7fC" secondAttribute="width" multiplier="0.5" id="Dai-9x-FG5"/>
807815
<constraint firstItem="sNu-7Z-F06" firstAttribute="leading" secondItem="mJg-3P-2Aw" secondAttribute="leading" id="EKU-pL-FZ6"/>
808816
<constraint firstItem="LPu-t9-bJY" firstAttribute="width" secondItem="r5l-Lv-rfg" secondAttribute="width" id="Edd-qg-wGx"/>
809817
<constraint firstItem="ZUC-Iy-7fC" firstAttribute="trailing" secondItem="U3A-Rw-grw" secondAttribute="trailing" id="FHj-IO-zG7"/>
@@ -816,6 +824,8 @@
816824
<constraint firstItem="Gmg-Tp-PPn" firstAttribute="top" secondItem="m2S-Jp-Qdl" secondAttribute="top" id="KPd-r3-s21"/>
817825
<constraint firstAttribute="bottom" secondItem="ZXf-O8-Z1c" secondAttribute="bottom" constant="16" id="Klm-8m-iFi"/>
818826
<constraint firstItem="r5l-Lv-rfg" firstAttribute="leading" secondItem="U3A-Rw-grw" secondAttribute="leading" id="LxH-kq-I6f"/>
827+
<constraint firstItem="DR0-oc-DGs" firstAttribute="top" secondItem="ZXf-O8-Z1c" secondAttribute="top" id="N4k-Sd-h1W"/>
828+
<constraint firstItem="DR0-oc-DGs" firstAttribute="height" secondItem="ZXf-O8-Z1c" secondAttribute="height" id="NKg-rh-bTk"/>
819829
<constraint firstItem="LPu-t9-bJY" firstAttribute="bottom" secondItem="ZXf-O8-Z1c" secondAttribute="bottom" id="O4W-2e-5be"/>
820830
<constraint firstItem="U3A-Rw-grw" firstAttribute="top" secondItem="mJg-3P-2Aw" secondAttribute="bottom" constant="7" id="ORY-sD-wV5"/>
821831
<constraint firstItem="U3A-Rw-grw" firstAttribute="width" secondItem="mJg-3P-2Aw" secondAttribute="width" id="Oat-h7-73K"/>
@@ -826,8 +836,10 @@
826836
<constraint firstItem="ZUC-Iy-7fC" firstAttribute="top" secondItem="r5l-Lv-rfg" secondAttribute="top" id="XWe-CU-xq2"/>
827837
<constraint firstItem="ZUC-Iy-7fC" firstAttribute="width" secondItem="r5l-Lv-rfg" secondAttribute="width" id="ZA8-0k-S6v"/>
828838
<constraint firstItem="PJA-AP-s5I" firstAttribute="leading" secondItem="m2S-Jp-Qdl" secondAttribute="leading" constant="15" id="ZKf-XD-X3C"/>
839+
<constraint firstItem="DR0-oc-DGs" firstAttribute="width" secondItem="ZXf-O8-Z1c" secondAttribute="width" id="aLF-NZ-8Ng"/>
829840
<constraint firstItem="AwX-MF-DMD" firstAttribute="top" secondItem="Gmg-Tp-PPn" secondAttribute="bottom" constant="7" id="cHK-Sj-6ps"/>
830841
<constraint firstItem="AwX-MF-DMD" firstAttribute="top" secondItem="PJA-AP-s5I" secondAttribute="top" id="ds3-Tk-TKg"/>
842+
<constraint firstItem="DR0-oc-DGs" firstAttribute="leading" secondItem="ZXf-O8-Z1c" secondAttribute="trailing" constant="8" id="f09-ft-TiP"/>
831843
<constraint firstItem="aJ1-yn-Pl7" firstAttribute="top" secondItem="PJA-AP-s5I" secondAttribute="bottom" constant="10" id="gHI-A7-SyE"/>
832844
<constraint firstItem="mJg-3P-2Aw" firstAttribute="top" secondItem="sNu-7Z-F06" secondAttribute="bottom" constant="2" id="h24-Ox-KU7"/>
833845
<constraint firstItem="Gmg-Tp-PPn" firstAttribute="leading" secondItem="m2S-Jp-Qdl" secondAttribute="leading" id="hMN-xb-eV1"/>
@@ -850,6 +862,7 @@
850862
<outlet property="messageLabel" destination="GbJ-FJ-Uuc" id="19Z-0L-YwW"/>
851863
<outlet property="modelTypeSelectorSegment" destination="ZUC-Iy-7fC" id="p0d-4X-4cG"/>
852864
<outlet property="prefixClassTextField" destination="b3c-Wz-v36" id="3wr-bV-AAf"/>
865+
<outlet property="setAsFinalCheckbox" destination="DR0-oc-DGs" id="hmS-RW-efa"/>
853866
<outlet property="textView" destination="fWl-7Q-Cq6" id="1lh-CW-y1Y"/>
854867
</connections>
855868
</viewController>

SwiftyJSONAccelerator/Templates/BaseTemplate.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import Foundation{INCLUDE_HEADER}
99

10-
public {OBJECT_KIND} {OBJECT_NAME}{EXTENDED_OBJECT_COLON}{EXTEND_FROM} {
10+
public{IS_FINAL}{OBJECT_KIND} {OBJECT_NAME}{EXTENDED_OBJECT_COLON}{EXTEND_FROM} {
1111

1212
// MARK: Declaration for string constants to be used to decode and also serialize.
1313
{STRING_CONSTANT}

0 commit comments

Comments
 (0)