gyro 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,67 @@
1
+ =begin
2
+ Copyright 2016 - Niji
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ =end
16
+
17
+ module Gyro
18
+ module Realm
19
+ module Java
20
+ module Templates
21
+
22
+ # ANNOTATIONS
23
+ PRIMARY_KEY_ANNOTATION = '@PrimaryKey'
24
+ INDEXED_ANNOTATION = '@Index'
25
+ IGNORED_ANNOTATION = '@Ignore'
26
+ GSON_ANNOTATION = "@SerializedName(\"%s\")"
27
+ SUPPORT_ANNOTATION = "@android.support.annotation.%s"
28
+
29
+ # COMMONS
30
+ PACKAGE_TEMPLATE = 'package %s;'
31
+ JAVA_FILE_TEMPLATE = '%s.java'
32
+ GENERATED_MESSAGE = '/* DO NOT EDIT | Generated by gyro */'
33
+
34
+ # IMPORTS
35
+ IMPORT_DATE = 'import java.util.Date;'
36
+ IMPORT_LIST = 'import java.util.List;'
37
+ IMPORT_GSON = 'import com.google.gson.annotations.SerializedName;'
38
+ IMPORT_REALM_LIST = 'import io.realm.RealmList;'
39
+ IMPORT_REALM_OBJECT = 'import io.realm.RealmObject;'
40
+ IMPORT_REALM_IGNORE = 'import io.realm.annotations.Ignore;'
41
+ IMPORT_REALM_INDEX = 'import io.realm.annotations.Index;'
42
+ IMPORT_REALM_PRIMARY_KEY = 'import io.realm.annotations.PrimaryKey;'
43
+
44
+ # ENUM
45
+ ENUM_TEMPLATE = 'public enum %s {'
46
+ ENUM_JSON_VALUE = "(\"%s\")"
47
+
48
+ # CLASS
49
+ CLASS_TEMPLATE = 'public class %s extends RealmObject {'
50
+ ATTRIBUTE_TEMPLATE = 'private %s %s;'
51
+ FINAL_ATTRIBUTE_TEMPLATE = 'private final %s %s;'
52
+ REALM_LIST_TEMPLATE = 'RealmList<%s>'
53
+ LIST_TEMPLATE = 'List<%s>'
54
+
55
+ # CONSTANTS
56
+ ATTRIBUTE_CONSTANTS = 'public interface Attributes {'
57
+ RELATIONSHIP_CONSTANTS = 'public interface Relationships {'
58
+ CONSTANT_TEMPLATE = 'String %s = "%s";'
59
+
60
+ # COMMENTS
61
+ CLASS_COMMENT_TEMPLATE = "/**\n * %s\n */"
62
+ ATTRIBUTE_COMMENT_TEMPLATE = '/** %s */'
63
+
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,63 @@
1
+ =begin
2
+ Copyright 2016 - Niji
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ =end
16
+
17
+ module Gyro
18
+ module Realm
19
+ module ObjC
20
+ module Converter
21
+
22
+ TYPES = {
23
+ :integer_16 => 'int',
24
+ :integer_32 => 'long',
25
+ :integer_64 => 'long long',
26
+ :decimal => 'double',
27
+ :double => 'double',
28
+ :float => 'float',
29
+ :string => 'NSString *',
30
+ :boolean => 'BOOL',
31
+ :date => 'NSDate *',
32
+ :binary => 'NSData *'
33
+ }
34
+
35
+ DEFAULTS = {
36
+ :integer_16 => '@(0)',
37
+ :integer_32 => '@(0)',
38
+ :integer_64 => '@(0)',
39
+ :decimal => '@(0.0)',
40
+ :double => '@(0.0)',
41
+ :float => '@(0.0)',
42
+ :string => '@""',
43
+ :boolean => '@(NO)',
44
+ :date => '[NSDate date]',
45
+ :binary => '[NSData new]'
46
+ }
47
+
48
+ def is_number_type?(type)
49
+ [:integer_16, :integer_32, :integer_64, :decimal, :double, :float].include?(type)
50
+ end
51
+
52
+ def convert_type(type, use_nsnumber = false)
53
+ use_nsnumber && is_number_type?(type) ? 'NSNumber *' : TYPES[type]
54
+ end
55
+
56
+ def convert_default(type)
57
+ DEFAULTS[type]
58
+ end
59
+
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,86 @@
1
+ =begin
2
+ Copyright 2016 - Niji
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ =end
16
+
17
+ require File.expand_path('templates', File.dirname(__FILE__))
18
+ require File.expand_path('converter', File.dirname(__FILE__))
19
+ require File.expand_path('../../utils/string_xcdatamodel', File.dirname(__FILE__))
20
+ require File.expand_path('../../utils/file_utils', File.dirname(__FILE__))
21
+
22
+ module Gyro
23
+ module Realm
24
+ module ObjC
25
+ module EnumGenerator
26
+
27
+ # INCLUDES #############################################################
28
+
29
+ include Templates
30
+ include Converter
31
+
32
+ # PUBLIC METHODS #######################################################
33
+
34
+ def generate_enum_file(path, xcdatamodel)
35
+ enums = []
36
+ enum_file = String.new
37
+ enum_file << GENERATED_MESSAGE + "\n"
38
+ enum_file << "\n" + SEPARATOR + "\n\n"
39
+ enum_file << PRAGMA_MARK_TYPES + "\n\n"
40
+ xcdatamodel.entities.each do |_, entity|
41
+ entity.attributes.each do |_, attribute|
42
+ if attribute.enum? and !enums.include?(attribute.enum_type)
43
+ int_type = convert_type(attribute.type)
44
+ enum_type = attribute.enum_type
45
+ enum_file << "\n" if enums.length > 0
46
+ enums.push(enum_type)
47
+ enum = generate_enum(int_type, enum_type, attribute)
48
+ enum_file << enum
49
+ end
50
+ end
51
+ end
52
+ if enums.size != 0
53
+ Gyro.write_file_with_name(path, HEADER_TEMPLATE%[ENUM_FILE_NAME], enum_file)
54
+ end
55
+ end
56
+
57
+ private ################################################################
58
+
59
+ def generate_enum(int_type, enum_name, attribute)
60
+ enum_string = String.new
61
+ enum_string << ENUM_TYPEDEF_TEMPLATE%[int_type, enum_name] + "\n"
62
+ enum_values = Array.new
63
+ enum_values += %W(#{enum_name}None) if attribute.optional?
64
+ enum_values += attribute.enum_values
65
+ if enum_values.length != 0
66
+ # First one
67
+ value = enum_values[0]
68
+ enum_string << ' ' + value + ' = 0,' + "\n"
69
+ # Others
70
+ (1..enum_values.length - 2).each { |i|
71
+ value = enum_values[i]
72
+ enum_string << ' ' + value + ',' + "\n"
73
+ }
74
+ # Last one if at least 2 values
75
+ if enum_values.length > 1
76
+ value = enum_values.last
77
+ enum_string << ' ' + value + "\n"
78
+ end
79
+ end
80
+ enum_string << '};' + "\n"
81
+ end
82
+
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,373 @@
1
+ =begin
2
+ Copyright 2016 - Niji
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ =end
16
+
17
+ require File.expand_path('../../utils/log', File.dirname(__FILE__))
18
+ require File.expand_path('../../utils/string_xcdatamodel', File.dirname(__FILE__))
19
+ require File.expand_path('../../utils/file_utils', File.dirname(__FILE__))
20
+ require File.expand_path('../../xcdatamodel/parser/relationship', File.dirname(__FILE__))
21
+ require File.expand_path('converter', File.dirname(__FILE__))
22
+ require File.expand_path('templates', File.dirname(__FILE__))
23
+ require File.expand_path('protocol_generator', File.dirname(__FILE__))
24
+ require File.expand_path('enum_generator', File.dirname(__FILE__))
25
+ require File.expand_path('json_category_generator', File.dirname(__FILE__))
26
+
27
+ module Gyro
28
+ module Realm
29
+ module ObjC
30
+
31
+ class Generator
32
+
33
+ # INCLUDES #############################################################
34
+
35
+ include Gyro::XCDataModel::Parser
36
+ include Converter
37
+ include Templates
38
+ include ProtocolGenerator
39
+ include EnumGenerator
40
+ include JSONCategoryGenerator
41
+
42
+ # PUBLIC METHODS #######################################################
43
+
44
+ def initialize(path, xcdatamodel, json = false, framework = false, use_nsnumber = false)
45
+ generate_class_files(path, xcdatamodel, use_nsnumber)
46
+ generate_protocol_file(path, xcdatamodel)
47
+ generate_enum_file(path, xcdatamodel)
48
+ generate_objc_categories(path, xcdatamodel, framework) if json
49
+ end
50
+
51
+ private ################################################################
52
+
53
+ def generate_class_files(path, xcdatamodel, use_nsnumber)
54
+ puts "\n"
55
+ Gyro::Log::title('Objc Realm')
56
+ xcdatamodel.entities.each do |_, entity|
57
+ unless entity.abstract?
58
+ Gyro::Log::success("Generating entity #{entity.name}...")
59
+ generate_class(path, entity, use_nsnumber)
60
+ end
61
+ end
62
+ end
63
+
64
+ def generate_class(path, entity, use_nsnumber)
65
+ header_file = generate_header_file(entity, use_nsnumber)
66
+ source_file = generate_source_file(entity, use_nsnumber)
67
+ Gyro.write_file_with_name(path, HEADER_TEMPLATE%[entity.name], header_file)
68
+ Gyro.write_file_with_name(path, SOURCE_TEMPLATE%[entity.name], source_file)
69
+ end
70
+
71
+ def generate_header_file(entity, use_nsnumber)
72
+ header_file = String.new
73
+ header_file << GENERATED_MESSAGE + "\n"
74
+ header_file << "\n" + SEPARATOR + "\n\n"
75
+ header_file << PRAGMA_MARK_IMPORTS + "\n\n"
76
+ header_file << IMPORT_REALM + "\n"
77
+ header_file << IMPORT_HEADER%[ENUM_FILE_NAME] + "\n" if require_enum_import(entity)
78
+ header_file << generate_import_protocols(entity)
79
+ header_file << generate_class_types(entity)
80
+ header_file << generate_header_constants(entity)
81
+ header_file << "\n" + SEPARATOR + "\n\n"
82
+ header_file << PRAGMA_MARK_INTERFACE + "\n\n"
83
+ header_file << CLASS_COMMENT_TEMPLATE%[entity.comment] + "\n" unless entity.comment.empty?
84
+ header_file << INTERFACE_TEMPLATE%[entity.name] + "\n"
85
+ header_file << generate_properties(entity, use_nsnumber)
86
+ header_file << "\n" << END_CODE + "\n"
87
+ end
88
+
89
+ def generate_properties(entity, use_nsnumber)
90
+ header_file = String.new
91
+ header_file << "\n" + PRAGMA_MARK_PROPERTIES + "\n\n"
92
+ entity.attributes.each do |_, attribute|
93
+ header_file << PROPERTY_COMMENT_TEMPLATE%[attribute.comment] + "\n" unless attribute.comment.empty?
94
+ name = attribute.name
95
+ use_nsnumber_wrapper = use_nsnumber && require_nsnumber_wrapper(attribute)
96
+ type = attribute.enum? ? attribute.enum_type : convert_type(attribute.type, use_nsnumber_wrapper)
97
+ if type.nil?
98
+ Gyro::Log::error("The property #{name} of entity #{entity.name} has an Undefined type.")
99
+ type = 'id'
100
+ end
101
+ type = '(readonly) ' + type unless attribute.realm_read_only.empty?
102
+ header_file << SIMPLE_PROPERTY_TEMPLATE%[type, type.end_with?('*') ? name : ' ' + name] + "\n"
103
+ if use_nsnumber_wrapper
104
+ num_type = convert_type(attribute.type)
105
+ header_file << NUMBER_ACCESSOR_DECL_TEMPLATES%[num_type, name, name.capitalize_first_letter, num_type]
106
+ end
107
+ end
108
+ entity.relationships.each do |_, relationship|
109
+ is_list = relationship.type == :to_many
110
+ if relationship.inverse?
111
+ type = '(readonly) ' + (is_list ? 'NSArray' : relationship.inverse_type)
112
+ name = relationship.name.delete_inverse_suffix
113
+ else
114
+ if relationship.destination.empty?
115
+ type = is_list ? REALM_LIST_TEMPLATE%[relationship.inverse_type] : relationship.inverse_type
116
+ else
117
+ type = LIST_TEMPLATE%[convert_type(relationship.destination.downcase.to_sym)]
118
+ end
119
+ name = relationship.name
120
+ end
121
+ header_file << OBJECT_PROPERTY_TEMPLATE%[type, name] + "\n"
122
+ end
123
+ header_file
124
+ end
125
+
126
+ def require_nsnumber_wrapper(attribute)
127
+ !attribute.enum? && attribute.realm_read_only.empty? && is_number_type?(attribute.type)
128
+ end
129
+
130
+ def require_enum_import(entity)
131
+ entity.attributes.each do |_, attribute|
132
+ if attribute.enum?
133
+ return true
134
+ end
135
+ end
136
+ false
137
+ end
138
+
139
+ def generate_import_protocols(entity)
140
+ entity.has_list_attributes?(true) ? IMPORT_HEADER%[PROTOCOL_FILE_NAME] + "\n" : ''
141
+ end
142
+
143
+ def generate_class_types(entity)
144
+ class_types = String.new
145
+ entity.relationships.each do |_, relationship|
146
+ class_types << CLASS_TEMPLATE%[relationship.inverse_type] + "\n" if relationship.inverse_type != entity.name && relationship.destination.empty?
147
+ end
148
+ class_types.empty? ? class_types : "\n" + PRAGMA_MARK_TYPES + "\n\n" + class_types
149
+ end
150
+
151
+ def generate_header_constants(entity)
152
+ constants = String.new
153
+ unless entity.attributes.empty?
154
+ name = CONSTANT_ATTRIBUTES_NAME%[entity.name]
155
+ constants << CONSTANT_HEADER_ATTRIBUTES%[name, name] + "\n"
156
+ entity.attributes.each do |_, attribute|
157
+ constants << ' ' + CONSTANT_HEADER_ITEM%[attribute.name] + "\n"
158
+ end
159
+ constants << "} #{name};\n"
160
+ end
161
+ if entity.has_no_inverse_relationship?
162
+ constants << "\n" unless constants.empty?
163
+ name = CONSTANT_RELATIONSHIPS_NAME%[entity.name]
164
+ constants << CONSTANT_HEADER_RELATIONSHIPS%[name] + "\n"
165
+ entity.relationships.each do |_, relationship|
166
+ constants << ' ' + CONSTANT_HEADER_ITEM%[relationship.name] + "\n" unless relationship.inverse?
167
+ end
168
+ constants << "} #{name};\n"
169
+ end
170
+ constants.empty? ? constants : "\n" + PRAGMA_MARK_CONSTANTS + "\n\n"+ constants
171
+ end
172
+
173
+ def generate_source_file(entity, use_nsnumber)
174
+ source_file = String.new
175
+ source_file << GENERATED_MESSAGE + "\n"
176
+ source_file << "\n" + SEPARATOR + "\n\n"
177
+ source_file << PRAGMA_MARK_IMPORTS + "\n\n"
178
+ source_file << IMPORT_HEADER%[entity.name] + "\n"
179
+ source_file << generate_source_constants(entity)
180
+ source_file << "\n" + SEPARATOR + "\n\n"
181
+ source_file << PRAGMA_MARK_IMPLEMENTATION + "\n\n"
182
+ source_file << IMPLEMENTATION_TEMPLATE%[entity.name] + "\n"
183
+ source_file << generate_numbers_accessors(entity) if use_nsnumber
184
+ if require_overriding(entity)
185
+ source_file << "\n" + PRAGMA_MARK_SUPER + "\n"
186
+ source_file << generate_primary_key(entity)
187
+ source_file << generate_required_properties(entity)
188
+ source_file << generate_default_values(entity)
189
+ source_file << generate_ignored_properties(entity)
190
+ source_file << generate_read_only_properties(entity, use_nsnumber)
191
+ source_file << generate_inverse_properties(entity)
192
+ end
193
+ source_file << "\n" << END_CODE + "\n"
194
+ end
195
+
196
+ def generate_source_constants(entity)
197
+ constants = String.new
198
+ unless entity.attributes.empty?
199
+ name = CONSTANT_ATTRIBUTES_NAME%[entity.name]
200
+ constants << CONSTANT_SOURCE_ATTRIBUTES%[name, name] + "\n"
201
+ entity.attributes.each_with_index do |(_, attribute), idx|
202
+ constants << ',' + "\n" unless idx == 0
203
+ constants << ' ' + CONSTANT_SOURCE_ITEM%[attribute.name, attribute.name]
204
+ constants << "\n" if idx == entity.attributes.length - 1
205
+ end
206
+ constants << '};' + "\n"
207
+ end
208
+ if entity.has_no_inverse_relationship?
209
+ constants << "\n" unless constants.empty?
210
+ name = CONSTANT_RELATIONSHIPS_NAME%[entity.name]
211
+ constants << CONSTANT_SOURCE_RELATIONSHIPS%[name, name] + "\n"
212
+ has_first = false
213
+ entity.relationships.each_with_index do |(_, relationship), idx|
214
+ unless relationship.inverse?
215
+ constants << ',' + "\n" if has_first
216
+ constants << ' ' + CONSTANT_SOURCE_ITEM%[relationship.name, relationship.name]
217
+ has_first = true
218
+ end
219
+ constants << "\n" if idx == entity.relationships.length - 1
220
+ end
221
+ constants << '};' + "\n"
222
+ end
223
+ constants.empty? ? constants : "\n" + PRAGMA_MARK_CONSTANTS + "\n\n" + constants
224
+ end
225
+
226
+ def generate_numbers_accessors(entity)
227
+ number_accessors = String.new
228
+ entity.attributes.each do |_, attribute|
229
+ if require_nsnumber_wrapper(attribute)
230
+ type = convert_type(attribute.type)
231
+ name = attribute.name
232
+ selector = type.gsub(/ /, '') + 'Value'
233
+ number_accessors << NUMBER_ACCESSOR_SOURCE_TEMPLATES%[type, name, name, selector, name.capitalize_first_letter, type, name] + "\n"
234
+ end
235
+ end
236
+ number_accessors.empty? ? "" : "\n" + PRAGMA_MARK_NUMBER_ACCESSORS + "\n\n" + number_accessors
237
+ end
238
+
239
+ def require_overriding(entity)
240
+ if entity.has_primary_key? or entity.attributes.count > 0
241
+ return true
242
+ end
243
+ false
244
+ end
245
+
246
+ def generate_primary_key(entity)
247
+ primary_key = String.new
248
+ if entity.has_primary_key?
249
+ primary_key << "\n" + '+ (NSString *)primaryKey' + "\n"
250
+ primary_key << '{' + "\n"
251
+ primary_key << ' ' + "return @\"" + entity.identity_attribute + "\";" + "\n"
252
+ primary_key << '}' + "\n"
253
+ end
254
+ primary_key
255
+ end
256
+
257
+ def generate_required_properties(entity)
258
+ required_properties = String.new
259
+ if entity.has_required?
260
+ required_properties << "\n" + '// Specify required properties' + "\n"
261
+ required_properties << '+ (NSArray *)requiredProperties' + "\n"
262
+ required_properties << '{' + "\n"
263
+ required_properties << ' ' + 'return @['
264
+ entity.attributes.each do |_, attribute|
265
+ required_properties << ARRAY_TEMPLATE%[attribute.name.add_quotes] if entity.is_required?(attribute)
266
+ end
267
+ required_properties = required_properties[0..required_properties.length - 3] # delete last coma
268
+ required_properties << '];' + "\n"
269
+ required_properties << '}' + "\n"
270
+ end
271
+ required_properties
272
+ end
273
+
274
+ def generate_default_values(entity)
275
+ default_values = String.new
276
+ if entity.has_required?
277
+ default_values << "\n" + '// Specify default values for required properties' + "\n"
278
+ default_values << '+ (NSDictionary *)defaultPropertyValues' + "\n"
279
+ default_values << '{' + "\n"
280
+ default_values << ' ' + 'return @{'
281
+ entity.attributes.each do |_, attribute|
282
+ if entity.is_required?(attribute)
283
+ default_value = convert_default(attribute.type)
284
+ if entity.has_default_value?(attribute) && !attribute.default.empty?
285
+ default_value = attribute.type == :string ? "@\"#{attribute.default})\"" : "@(#{attribute.default})"
286
+ end
287
+ default_values << DICTIONARY_DEFAULT%[attribute.name.add_quotes, default_value] + ' '
288
+ end
289
+ end
290
+ default_values = default_values[0..default_values.length - 3] # delete last coma
291
+ default_values << '};' + "\n"
292
+ default_values << '}' + "\n"
293
+ end
294
+ default_values
295
+ end
296
+
297
+ def generate_ignored_properties(entity)
298
+ ignored_properties = String.new
299
+ if entity.has_ignored?
300
+ ignored_properties << "\n" + "// Specify properties to ignore (Realm won't persist these)" + "\n"
301
+ ignored_properties << '+ (NSArray *)ignoredProperties' + "\n"
302
+ ignored_properties << '{' + "\n"
303
+ ignored_properties << ' ' + 'return @['
304
+ entity.attributes.each do |_, attribute|
305
+ ignored_properties << ARRAY_TEMPLATE%[attribute.name.add_quotes] if attribute.realm_ignored?
306
+ end
307
+ entity.relationships.each do |_, relationship|
308
+ ignored_properties << ARRAY_TEMPLATE%[relationship.name.add_quotes] if relationship.realm_ignored?
309
+ end
310
+ ignored_properties = ignored_properties[0..ignored_properties.length - 3] # delete last coma
311
+ ignored_properties << '];' + "\n"
312
+ ignored_properties << '}' + "\n"
313
+ end
314
+ ignored_properties
315
+ end
316
+
317
+ def generate_read_only_properties(entity, use_nsnumber)
318
+ read_only_properties = String.new
319
+ entity.attributes.each do |_, attribute|
320
+ unless attribute.realm_read_only.empty?
321
+ type = attribute.enum? ? attribute.enum_type : convert_type(attribute.type, use_nsnumber)
322
+ read_only_properties << "\n" + READ_ONLY_DEF_TEMPLATE%[type, attribute.name] + "\n"
323
+ read_only_properties << '{' + "\n"
324
+ read_only_properties << ' ' + attribute.realm_read_only + "\n"
325
+ read_only_properties << '}' + "\n"
326
+ end
327
+ end
328
+ read_only_properties
329
+ end
330
+
331
+ def generate_inverse_properties(entity)
332
+ inverse_properties = String.new
333
+ entity.relationships.each do |_, relationship|
334
+ if relationship.inverse?
335
+ if relationship.type == :to_many
336
+ definition = INVERSE_DEF_TEMPLATE%['NSArray', relationship.name.delete_inverse_suffix]
337
+ value = INVERSE_MANY_TEMPLATE%[relationship.inverse_type, relationship.inverse_name]
338
+ else
339
+ definition = INVERSE_DEF_TEMPLATE%[relationship.inverse_type, relationship.name.delete_inverse_suffix]
340
+ value = INVERSE_ONE_TEMPLATE%[relationship.inverse_type, relationship.inverse_name]
341
+ end
342
+ inverse_properties << "\n" + definition + "\n"
343
+ inverse_properties << '{' + "\n"
344
+ inverse_properties << ' ' + value + "\n"
345
+ inverse_properties << '}' + "\n"
346
+ end
347
+ end
348
+ inverse_properties
349
+ end
350
+
351
+ def generate_indexed_properties(entity)
352
+ indexed_properties = String.new
353
+ if entity.has_indexed_attributes?
354
+ indexed_properties << "\n" + '// Specify properties to index' + "\n"
355
+ indexed_properties << '+ (NSArray *)ignoredProperties' + "\n"
356
+ indexed_properties << '{' + "\n"
357
+ indexed_properties << ' ' + 'return @['
358
+ entity.attributes.each do |_, attribute|
359
+ if attribute.indexed
360
+ indexed_properties << ARRAY_TEMPLATE%[attribute.name.add_quotes]
361
+ end
362
+ end
363
+ indexed_properties = indexed_properties[0..indexed_properties.length - 3] # delete last coma
364
+ indexed_properties << '];' + "\n"
365
+ indexed_properties << '}' + "\n"
366
+ end
367
+ indexed_properties
368
+ end
369
+
370
+ end
371
+ end
372
+ end
373
+ end