@@ -83,6 +83,72 @@ private func generateHeader() {
8383 """ )
8484}
8585
86+ /**
87+ Checking the key is present in the Optional Dictionary
88+ */
89+ private func isKeyPresentInOptionalDictionary( keyToSearch: String , tupleKey: String , optionalDictionary: [ String : [ String : String ] ] ) -> Bool {
90+ guard let optionalKeysAndTypes = optionalDictionary [ keyToSearch] else {
91+ return false
92+ }
93+
94+ let optionalArray = optionalKeysAndTypes. keys
95+ return optionalArray. contains ( tupleKey)
96+ }
97+
98+ /**
99+ Checking the key is present in all the plists
100+ */
101+ private func isKeyAvailableInAllPlists( keyToSearch: String , tupleKey: String , tuplesForPlists: [ String : KeyValueTuples ] ) -> Bool {
102+ let plistPaths = tuplesForPlists. keys
103+ for plistPath in plistPaths {
104+
105+ guard let tuples = tuplesForPlists [ plistPath] else {
106+ return false
107+ }
108+
109+ guard let dictionary = tuples [ tupleKey] as? Dictionary < String , Any > else {
110+ return false
111+ }
112+
113+ if ( dictionary. keys. contains ( keyToSearch) == false ) {
114+ return false
115+ }
116+ }
117+
118+ return true
119+ }
120+
121+ /**
122+ Generate Protocol for the Tuples and return the optional dictionary
123+ */
124+ private func generateProtocol( tuplesForPlists: [ String : KeyValueTuples ] , allKeyValueTuples: [ String : KeyValueTuples ] ) -> [ String : [ String : String ] ] {
125+ var optionalDictionary : [ String : [ String : String ] ] = [ : ]
126+ for (tupleKey, tuples) in allKeyValueTuples {
127+
128+ let name = tupleKey. uppercaseFirst ( )
129+ let protocolName = name. appending ( " Protocol " )
130+ print ( " protocol \( protocolName) { " )
131+ intend ( )
132+
133+ var optionalKeysAndTypes : [ String : String ] = [ : ]
134+ for tuple in tuples. tuples {
135+ let isOptional = !( isKeyAvailableInAllPlists ( keyToSearch: tuple. key, tupleKey: tupleKey, tuplesForPlists: tuplesForPlists) )
136+ var type = typeForValue ( tuple. value as Any )
137+ if ( isOptional == true ) {
138+ type = " \( type) ? "
139+ optionalKeysAndTypes [ tuple. key] = type
140+ }
141+
142+ print ( " \( tabs ( ) ) var \( tuple. key. lowercaseFirst ( ) ) : \( type) { get } " )
143+ }
144+
145+ optionalDictionary [ tupleKey] = optionalKeysAndTypes
146+ print ( " \( tabs ( intendBy: - 1 ) ) } \n " )
147+ }
148+
149+ return optionalDictionary
150+ }
151+
86152/**
87153Generates a protocol with public instance properties. Used to generate protocols that internal structs conform to.
88154
@@ -157,11 +223,11 @@ Generate structs out of Dictionaries and make them conform to a given protocol.
157223- protocolName: Name of the protocol; It has to end with a "Protocol" suffix; Default is 'nil' - the new generated protocol will be used
158224
159225*/
160- private func generateStructs( name structName : String ? = nil , tuples: KeyValueTuples , keysAndTypes: [ String : String ] ? = nil , oddKeys: [ String ] , protocolName: String ? = nil ) {
226+ private func generateStructs( name key : String ? = nil , tuples: KeyValueTuples , keysAndTypes: [ String : String ] ? = nil , oddKeys: [ String ] , protocolName: String ? = nil , optionalDictionary : [ String : [ String : String ] ] ) {
161227 var configName : String ? = tuples [ configurationKeyName] as? String
162228
163- if ( configName == nil && structName != nil ) {
164- configName = structName ? . uppercaseFirst ( )
229+ if ( configName == nil && key != nil ) {
230+ configName = key
165231 }
166232
167233 guard var structName = configName else {
@@ -207,45 +273,80 @@ private func generateStructs(name structName: String? = nil, tuples: KeyValueTup
207273 print ( " \n \( tabs ( ) ) internal struct \( structName) \( conformingToProtocol) { " )
208274 intend ( )
209275
276+ var availableKeys : [ String ] = [ ]
210277 for tuple in tuples. tuples {
211278
212- let key = tuple. key
213- let value = tuple. value
279+ let tupleKey = tuple. key
280+ let tupleValue = tuple. value
281+ availableKeys. append ( tupleKey)
214282
215- if ( oddKeys. contains ( key ) ) {
283+ if ( oddKeys. contains ( tupleKey ) ) {
216284 continue
217285 }
218286
219- guard let type = localKeysAndTypes ? [ key ] else {
287+ guard let type = localKeysAndTypes ? [ tupleKey ] else {
220288 return
221289 }
222290
291+ let isOptional : Bool = {
292+ guard let key = key else {
293+ return false
294+ }
295+
296+ return isKeyPresentInOptionalDictionary ( keyToSearch: key, tupleKey: tupleKey, optionalDictionary: optionalDictionary)
297+ } ( )
298+
223299 switch type {
224- case " String " :
225- print ( " \( tabs ( ) ) internal let \( key. lowercaseFirst ( ) ) : \( type) = \" \( value) \" " )
226- case " Int " :
227- print ( " \( tabs ( ) ) internal let \( key. lowercaseFirst ( ) ) : \( type) = \( value) " )
228- case " Bool " :
229- let boolString = ( ( ( value as? Bool ) == true ) ? " true " : " false " )
230- print ( " \( tabs ( ) ) internal let \( key. lowercaseFirst ( ) ) : \( type) = \( boolString) " )
231- case " Array<Any> " :
232- let arrayValue = value as! Array < String >
233- print ( " \( tabs ( ) ) internal let \( key. lowercaseFirst ( ) ) : \( type) = \( arrayValue) " )
300+ case " String " where ( isOptional == false ) :
301+ print ( " \( tabs ( ) ) internal let \( tupleKey. lowercaseFirst ( ) ) : \( type) = \" \( tupleValue) \" " )
302+ case " String " where ( isOptional == true ) :
303+ print ( " \( tabs ( ) ) internal var \( tupleKey. lowercaseFirst ( ) ) : \( type) ? = \" \( tupleValue) \" " )
304+ case " Int " where ( isOptional == false ) :
305+ print ( " \( tabs ( ) ) internal let \( tupleKey. lowercaseFirst ( ) ) : \( type) = \( tupleValue) " )
306+ case " Int " where ( isOptional == true ) :
307+ print ( " \( tabs ( ) ) internal var \( tupleKey. lowercaseFirst ( ) ) : \( type) ? = \( tupleValue) " )
308+ case " Bool " where ( isOptional == false ) :
309+ let boolString = ( ( ( tupleValue as? Bool ) == true ) ? " true " : " false " )
310+ print ( " \( tabs ( ) ) internal let \( tupleKey. lowercaseFirst ( ) ) : \( type) = \( boolString) " )
311+ case " Bool " where ( isOptional == true ) :
312+ let boolString = ( ( ( tupleValue as? Bool ) == true ) ? " true " : " false " )
313+ print ( " \( tabs ( ) ) internal var \( tupleKey. lowercaseFirst ( ) ) : \( type) ? = \( boolString) " )
314+ case " Array<Any> " where ( isOptional == false ) :
315+ let arrayValue = tupleValue as! Array < String >
316+ print ( " \( tabs ( ) ) internal let \( tupleKey. lowercaseFirst ( ) ) : \( type) = \( arrayValue) " )
317+ case " Array<Any> " where ( isOptional == true ) :
318+ let arrayValue = tupleValue as! Array < String >
319+ print ( " \( tabs ( ) ) internal var \( tupleKey. lowercaseFirst ( ) ) : \( type) ? = \( arrayValue) " )
234320 default :
235321 // default is a struct
236322 // Generate struct from the Dictionaries and Protocols
237323 if ( type. contains ( " Protocol " ) ) {
238- let dictionary = tuples [ key ] as? Dictionary < String , Any >
324+ let dictionary = tuples [ tupleKey ] as? Dictionary < String , Any >
239325 let sortedDictionary = dictionary? . sorted { ( pairOne, pairTwo) -> Bool in
240326 return pairOne. key < pairTwo. key
241327 }
242328
243- generateStructs ( name: key . uppercaseFirst ( ) , tuples: KeyValueTuples ( tuples: sortedDictionary ?? [ ] ) , oddKeys: oddKeys, protocolName: type)
329+ generateStructs ( name: tupleKey , tuples: KeyValueTuples ( tuples: sortedDictionary ?? [ ] ) , oddKeys: oddKeys, protocolName: type, optionalDictionary : optionalDictionary )
244330
245- print ( " \( tabs ( ) ) internal let \( key . lowercaseFirst ( ) ) : \( type) = \( key . uppercaseFirst ( ) ) () " )
331+ print ( " \( tabs ( ) ) internal let \( tupleKey . lowercaseFirst ( ) ) : \( type) = \( tupleKey . uppercaseFirst ( ) ) () " )
246332 }
333+
247334 }
248335 }
336+
337+ guard let key = key, let optionalKeysAndTypes = optionalDictionary [ key] else {
338+ print ( " \( tabs ( intendBy: - 1 ) ) } \n " )
339+ return
340+ }
341+
342+ let keysAndTypesToAdd = optionalKeysAndTypes. filter { ( key: String , type: String ) in
343+ return ( availableKeys. contains ( key) == false )
344+ }
345+
346+ for (key, type) in keysAndTypesToAdd {
347+ print ( " \( tabs ( ) ) internal var \( key. lowercaseFirst ( ) ) : \( type) = nil " )
348+ }
349+
249350 print ( " \( tabs ( intendBy: - 1 ) ) } \n " )
250351}
251352
@@ -260,7 +361,7 @@ Generates extensions to structs, conforming to protocol
260361- oddKeys: Keys to generate Optional properties from
261362
262363*/
263- private func generateExtensions( enumName: String , protocolName: String , allTuples: [ KeyValueTuples ] , keysAndTypes: Dictionary < String , String > , oddKeys: [ String ] ) {
364+ private func generateExtensions( enumName: String , protocolName: String , allTuples: [ KeyValueTuples ] , keysAndTypes: Dictionary < String , String > , oddKeys: [ String ] , optionalDictionary : [ String : [ String : String ] ] ) {
264365 for tuples in allTuples {
265366
266367 guard let caseName = tuples [ configurationKeyName] as? String else {
@@ -298,7 +399,7 @@ private func generateExtensions(enumName: String, protocolName: String, allTuple
298399 return pairOne. key < pairTwo. key
299400 }
300401
301- generateStructs ( name: oddKey. uppercaseFirst ( ) , tuples: KeyValueTuples ( tuples: sortedDictionary ?? [ ] ) , oddKeys: oddKeys, protocolName: type)
402+ generateStructs ( name: oddKey, tuples: KeyValueTuples ( tuples: sortedDictionary ?? [ ] ) , oddKeys: oddKeys, protocolName: type, optionalDictionary : optionalDictionary )
302403 print ( " \( tabs ( ) ) var \( oddKey. lowercaseFirst ( ) ) : \( type) ? { " )
303404 print ( " \( tabs ( intendBy: 1 ) ) return \( oddKey. uppercaseFirst ( ) ) () " )
304405 print ( " \( tabs ( intendBy: - 1 ) ) } " )
@@ -325,7 +426,7 @@ Generate an enum with structs and properties.
325426- oddKeys: Keys to generate Optional properties from
326427
327428*/
328- private func generateEnum( name enumName: String , protocolName: String , allTuples: [ KeyValueTuples ] , keysAndTypes: Dictionary < String , String > , oddKeys: [ String ] ) {
429+ private func generateEnum( name enumName: String , protocolName: String , allTuples: [ KeyValueTuples ] , keysAndTypes: Dictionary < String , String > , oddKeys: [ String ] , optionalDictionary : [ String : [ String : String ] ] ) {
329430
330431 let cases : [ String ] = allTuples. map { ( tuples: KeyValueTuples ) in
331432 return ( tuples [ configurationKeyName] as? String ?? " " )
@@ -339,7 +440,7 @@ private func generateEnum(name enumName: String, protocolName: String, allTuples
339440 }
340441
341442 for tuples in allTuples {
342- generateStructs ( tuples: tuples, keysAndTypes: keysAndTypes, oddKeys: oddKeys)
443+ generateStructs ( tuples: tuples, keysAndTypes: keysAndTypes, oddKeys: oddKeys, optionalDictionary : optionalDictionary )
343444 }
344445
345446 print ( """
@@ -357,7 +458,7 @@ private func generateEnum(name enumName: String, protocolName: String, allTuples
357458 print ( " \( tabs ( ) ) } " )
358459 print ( " \( tabs ( intendBy: - 1 ) ) } " )
359460 print ( " \( tabs ( intendBy: - 1 ) ) } \n " )
360- generateExtensions ( enumName: enumName, protocolName: protocolName, allTuples: allTuples, keysAndTypes: keysAndTypes, oddKeys: oddKeys)
461+ generateExtensions ( enumName: enumName, protocolName: protocolName, allTuples: allTuples, keysAndTypes: keysAndTypes, oddKeys: oddKeys, optionalDictionary : optionalDictionary )
361462}
362463
363464/**
@@ -497,7 +598,8 @@ var oddKeys = [String]()
497598var keysAndTypes : [ String : String ] = [ : ]
498599var allTuples : [ KeyValueTuples ] = [ ]
499600var protocolName : String = enumName. appending ( " Protocol " )
500-
601+ var tuplesForPlists : [ String : KeyValueTuples ] = [ : ]
602+ var allKeyValueTuples : [ String : KeyValueTuples ] = [ : ]
501603generateHeader ( )
502604
503605// gather keys and values... and types
@@ -508,6 +610,7 @@ for plistPath in plists {
508610 exit ( 1 )
509611 }
510612
613+ tuplesForPlists [ plistPath] = tuples
511614 allTuples. append ( tuples)
512615
513616 let allKeys = tuples. keys
@@ -537,8 +640,9 @@ for plistPath in plists {
537640 return pairOne. key < pairTwo. key
538641 }
539642
540- let protocolName = generateProtocol ( name: key. uppercaseFirst ( ) , tuples: KeyValueTuples ( tuples: sortedDictionary ?? [ ] ) )
541- // override type with new protocol
643+ allKeyValueTuples [ key] = KeyValueTuples ( tuples: sortedDictionary ?? [ ] )
644+ let name = key. uppercaseFirst ( )
645+ let protocolName = name. appending ( " Protocol " )
542646 keysAndTypes [ key] = protocolName
543647 }
544648 }
@@ -553,5 +657,6 @@ for plistPath in plists {
553657 }
554658}
555659
660+ let optionalDictionary = generateProtocol ( tuplesForPlists: tuplesForPlists, allKeyValueTuples: allKeyValueTuples)
556661generateProtocol ( name: protocolName, commonKeys: commonKeys, oddKeys: oddKeys, keysAndTypes: keysAndTypes)
557- generateEnum ( name: enumName, protocolName: protocolName, allTuples: allTuples, keysAndTypes: keysAndTypes, oddKeys: oddKeys)
662+ generateEnum ( name: enumName, protocolName: protocolName, allTuples: allTuples, keysAndTypes: keysAndTypes, oddKeys: oddKeys, optionalDictionary : optionalDictionary )
0 commit comments