gyro 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,172 @@
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('../../utils/file_utils', File.dirname(__FILE__))
19
+ require File.expand_path('../../utils/string_xcdatamodel', File.dirname(__FILE__))
20
+
21
+ module Gyro
22
+ module Realm
23
+ module ObjC
24
+ module JSONCategoryGenerator
25
+
26
+ # INCLUDES #############################################################
27
+
28
+ include Templates
29
+
30
+ # PUBLIC METHODS #######################################################
31
+
32
+ def generate_objc_categories(path, xcdatamodel, framework = false)
33
+ json_path = File.join(path, 'JSON')
34
+ Dir.mkdir(json_path) unless Dir.exists?(json_path)
35
+ xcdatamodel.entities.each do |_, entity|
36
+ generate_json_category_file(json_path, entity, framework)
37
+ end
38
+ end
39
+
40
+ private #################################################################
41
+
42
+ def generate_json_category_file(path, entity, framework)
43
+ if !entity.attributes.empty? || !entity.relationships.empty?
44
+ source_file = generate_source_category_file(entity)
45
+ header_file = generate_header_category_file(entity, framework)
46
+ file_name = JSON_CATEGORY_NAME%[entity.name]
47
+ Gyro.write_file_with_name(path, HEADER_TEMPLATE%[file_name], header_file) unless header_file.empty?
48
+ Gyro.write_file_with_name(path, SOURCE_TEMPLATE%[file_name], source_file) unless source_file.empty?
49
+ end
50
+ end
51
+
52
+ def generate_header_category_file(entity, framework)
53
+ header_file = String.new
54
+ header_file << GENERATED_MESSAGE + "\n"
55
+ header_file << "\n" + SEPARATOR + "\n\n"
56
+ header_file << PRAGMA_MARK_IMPORTS + "\n\n"
57
+ header_file << (framework ? IMPORT_REALM_JSON_FRAMEWORK : IMPORT_REALM_JSON_LIBRARY) + "\n"
58
+ header_file << IMPORT_HEADER%[entity.name] + "\n"
59
+ header_file << "\n" + SEPARATOR + "\n\n"
60
+ header_file << PRAGMA_MARK_INTERFACE + "\n\n"
61
+ header_file << JSON_CATEGORY_INTERFACE%[entity.name] + "\n\n"
62
+ header_file << END_CODE + "\n"
63
+ header_file
64
+ end
65
+
66
+ def generate_source_category_file(entity)
67
+ source_file = String.new
68
+ source_file << GENERATED_MESSAGE + "\n"
69
+ source_file << "\n" + SEPARATOR + "\n\n"
70
+ source_file << PRAGMA_MARK_IMPORTS + "\n\n"
71
+ source_file << IMPORT_HEADER%[JSON_CATEGORY_NAME%[entity.name]] + "\n"
72
+ source_file << IMPORT_HEADER%[ENUM_FILE_NAME] + "\n" if entity.has_enum_attributes?
73
+ entity.transformers.each do |name|
74
+ source_file << IMPORT_HEADER%[name]+"\n"
75
+ end
76
+ source_file << "\n" + SEPARATOR + "\n\n"
77
+ source_file << PRAGMA_MARK_IMPLEMENTATION + "\n\n"
78
+ source_file << JSON_CATEGORY_IMPLEMENTATION%[entity.name] + "\n\n"
79
+ source_file << generate_mapping(entity)
80
+ source_file << "\n" + generate_json_transformers(entity) if entity.need_transformer?
81
+ source_file << "\n" + END_CODE + "\n"
82
+ source_file
83
+ end
84
+
85
+ def generate_mapping(entity)
86
+ inbound_mapping_string = '+ (NSDictionary *)JSONInboundMappingDictionary' + "\n"
87
+ inbound_mapping_string << '{' + "\n"
88
+ inbound_mapping_string << ' ' + 'return @{' + "\n"
89
+ outbound_mapping_string = '+ (NSDictionary *)JSONOutboundMappingDictionary' + "\n"
90
+ outbound_mapping_string << '{' + "\n"
91
+ outbound_mapping_string << ' '+ 'return @{' + "\n"
92
+
93
+ entity.attributes.each do |_, attribute|
94
+ json_value = attribute.json_key_path.empty? ? attribute.name.add_quotes : attribute.json_key_path.add_quotes
95
+ inbound_mapping_string << ' ' + DICTIONARY_JSON%[json_value, attribute.name.add_quotes] + "\n"
96
+ outbound_mapping_string << ' ' + DICTIONARY_JSON%[attribute.name.add_quotes, json_value] + "\n"
97
+ end
98
+
99
+ entity.relationships.each do |_, relationship|
100
+ json_value = relationship.json_key_path.empty? ? relationship.name.add_quotes : relationship.json_key_path.add_quotes
101
+ inbound_mapping_string << ' ' + DICTIONARY_JSON%[json_value, relationship.name.add_quotes] + "\n"
102
+ outbound_mapping_string << ' ' + DICTIONARY_JSON%[relationship.name.add_quotes, json_value] + "\n"
103
+ end
104
+
105
+ #delete last coma
106
+ inbound_mapping_string = inbound_mapping_string[0..inbound_mapping_string.length - 3] + "\n"
107
+ inbound_mapping_string << ' ' +'};' + "\n"
108
+ inbound_mapping_string << '}' + "\n\n"
109
+ outbound_mapping_string = outbound_mapping_string[0..outbound_mapping_string.length - 3] + "\n"
110
+ outbound_mapping_string << ' ' + '};' + "\n"
111
+ outbound_mapping_string << '}' + "\n"
112
+ inbound_mapping_string + outbound_mapping_string
113
+ end
114
+
115
+ def generate_json_transformers(entity)
116
+ json_transformer_string = String.new
117
+ first_transformer = true
118
+ entity.attributes.each do |(_, attribute)|
119
+ if attribute.need_transformer?
120
+ json_transformer_string << "\n" unless first_transformer
121
+ first_transformer = false
122
+ json_transformer_string << JSON_TRANSFORMER_DEF%[attribute.name] + "\n"
123
+ json_transformer_string << '{'+ "\n"
124
+ if !attribute.enum_type.empty? or attribute.type == :boolean # Enum | Boolean
125
+ json_transformer_string << ' ' + 'return [MCJSONValueTransformer valueTransformerWithMappingDictionary:@{' + "\n"
126
+ if attribute.type == :boolean
127
+ json_values = TRANSFORMER_BOOL_JSON
128
+ model_values = TRANSFORMER_BOOL_MODEL
129
+ else
130
+ if attribute.json_values.empty?
131
+ Raise::error("The attribute \"%s\" from \"%s\" is enum without JSONValues - please fix it"%[attribute.name, attribute.entity_name])
132
+ end
133
+ json_values = TRANSFORMER_ENUM_JSON + attribute.json_values.map { |enum| '@' + enum.add_quotes }
134
+ enums = attribute.enum_values
135
+ if attribute.optional?
136
+ default = attribute.enum_type + 'None'
137
+ else
138
+ default = enums[attribute.default.to_i]
139
+ end
140
+ model_values = [default, default, default] + enums
141
+ model_values = [default, default, default, default] + enums
142
+ end
143
+ json_transformer_string << format_json_transformers(json_values, model_values)
144
+
145
+ # delete last coma
146
+ json_transformer_string = json_transformer_string[0..json_transformer_string.length - 3] + "\n"
147
+ json_transformer_string << ' ' + '}];' + "\n"
148
+ else # custom transformer, or a default one
149
+ transformer = attribute.transformer
150
+ transformer = 'ISO8601DateTransform' if transformer.empty? && attribute.type == :date # default one for dates if none provided
151
+ json_transformer_string << ' ' + TRANSFORMER%[transformer] + "\n" unless transformer.empty?
152
+ end
153
+ json_transformer_string << '}' + "\n"
154
+ end
155
+ end
156
+ json_transformer_string
157
+ end
158
+
159
+ def format_json_transformers(json_values, model_values)
160
+ json_transformer_string = String.new
161
+ (0..model_values.length - 1).each { |enum|
162
+ json_value = json_values[enum]
163
+ enum_value = model_values[enum].add_parentheses
164
+ json_transformer_string << ' ' + DICTIONARY_JSON_CATEGORY%[json_value, enum_value] + "\n"
165
+ }
166
+ json_transformer_string
167
+ end
168
+
169
+ end
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,59 @@
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 ProtocolGenerator
26
+
27
+ # INCLUDES #############################################################
28
+
29
+ include Templates
30
+ include Converter
31
+
32
+ # PUBLIC METHODS #######################################################
33
+
34
+ def generate_protocol_file(path, xcdatamodel)
35
+ content = String.new
36
+ xcdatamodel.entities.each do |_, entity|
37
+ unless entity.abstract?
38
+ if entity.used_as_list_by_other?(xcdatamodel.entities)
39
+ content << protocol_file_template if content.empty?
40
+ content << REALM_LIST_TYPE_TEMPLATE%[entity.name, entity.name] + "\n"
41
+ end
42
+ end
43
+ end
44
+ Gyro.write_file_with_name(path, HEADER_TEMPLATE%[PROTOCOL_FILE_NAME], content) unless content.empty?
45
+ end
46
+
47
+ private ################################################################
48
+
49
+ def protocol_file_template
50
+ content = String.new
51
+ content << GENERATED_MESSAGE + "\n"
52
+ content << "\n" + SEPARATOR + "\n\n"
53
+ content << PRAGMA_MARK_PROTOCOLS + "\n\n"
54
+ end
55
+
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,100 @@
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 Templates
21
+
22
+ # IMPORTS
23
+ IMPORT_REALM = '#import <Realm/Realm.h>'
24
+ IMPORT_HEADER = '#import "%s.h"'
25
+ IMPORT_REALM_JSON_LIBRARY = '#import <Realm+JSON/RLMObject+JSON.h>'
26
+ IMPORT_REALM_JSON_FRAMEWORK = '#import "RLMObject+JSON.h"'
27
+
28
+
29
+ # PRAGMA
30
+ PRAGMA_MARK_IMPORTS = '#pragma mark - Imports'
31
+ PRAGMA_MARK_TYPES = '#pragma mark - Types'
32
+ PRAGMA_MARK_CONSTANTS = '#pragma mark - Defines & Constants'
33
+ PRAGMA_MARK_INTERFACE = '#pragma mark - Interface'
34
+ PRAGMA_MARK_PROPERTIES = '#pragma mark - Properties'
35
+ PRAGMA_MARK_PROTOCOLS = '#pragma mark - Protocols'
36
+ PRAGMA_MARK_IMPLEMENTATION = '#pragma mark - Implementation'
37
+ PRAGMA_MARK_NUMBER_ACCESSORS = '#pragma mark - NSNumber Convenience Accessors'
38
+ PRAGMA_MARK_SUPER = '#pragma mark - Superclass Overrides'
39
+
40
+ # COMMONS
41
+ GENERATED_MESSAGE = '// DO NOT EDIT | Generated by gyro'
42
+ END_CODE = '@end'
43
+ SEPARATOR = '////////////////////////////////////////////////////////////////////////////////'
44
+ DICTIONARY_JSON = '@%s : @%s,'
45
+ DICTIONARY_DEFAULT = '@%s : %s,'
46
+ DICTIONARY_JSON_CATEGORY = '%s : @%s,'
47
+
48
+ # HEADER
49
+ HEADER_TEMPLATE = '%s.h'
50
+ NUMBER_TRANSFORMER_FILE_NAME = 'NFNumberTransformer'
51
+ CLASS_COMMENT_TEMPLATE = "/**\n * %s\n */"
52
+ CLASS_TEMPLATE = '@class %s;'
53
+ INTERFACE_TEMPLATE = '@interface %s : RLMObject'
54
+ PROPERTY_COMMENT_TEMPLATE = '/** %s */'
55
+ SIMPLE_PROPERTY_TEMPLATE = '@property %s%s;'
56
+ OBJECT_PROPERTY_TEMPLATE = '@property %s *%s;'
57
+ NUMBER_ACCESSOR_DECL_TEMPLATES = "-(%s)%sValue;\n-(void)set%sValue:(%s)value;\n"
58
+ LIST_TEMPLATE = 'NSArray<%s>'
59
+ REALM_LIST_TYPE_TEMPLATE = "// This protocol enables typed collections. i.e.: RLMArray<%s>\nRLM_ARRAY_TYPE(%s)"
60
+ REALM_LIST_TEMPLATE = 'RLMArray<%s>'
61
+
62
+ # COMMONS
63
+ CONSTANT_ATTRIBUTES_NAME = '%sAttributes'
64
+ CONSTANT_RELATIONSHIPS_NAME = '%sRelationships'
65
+ CONSTANT_HEADER_ATTRIBUTES = 'extern const struct %s {'
66
+ CONSTANT_HEADER_RELATIONSHIPS = 'extern const struct %s {'
67
+ CONSTANT_HEADER_ITEM = '__unsafe_unretained NSString *%s;'
68
+ CONSTANT_SOURCE_ATTRIBUTES = 'const struct %s %s = {'
69
+ CONSTANT_SOURCE_RELATIONSHIPS = 'const struct %s %s = {'
70
+ CONSTANT_SOURCE_ITEM = '.%s = @"%s"'
71
+
72
+ # ENUM
73
+ ENUM_TYPEDEF_TEMPLATE = 'typedef NS_ENUM(%s, %s) {'
74
+ ENUM_FILE_NAME = 'RLMTypes'
75
+ PROTOCOL_FILE_NAME = 'RLMProtocols'
76
+
77
+ # SOURCE
78
+ SOURCE_TEMPLATE = '%s.m'
79
+ IMPLEMENTATION_TEMPLATE = '@implementation %s'
80
+ ARRAY_TEMPLATE ='@%s, '
81
+ READ_ONLY_DEF_TEMPLATE = '- (%s)%s'
82
+ NUMBER_ACCESSOR_SOURCE_TEMPLATES = "-(%s)%sValue\n{\n return [self.%s %s];\n}\n-(void)set%sValue:(%s)value\n{\n self.%s = @(value);\n}"
83
+ INVERSE_DEF_TEMPLATE = '- (%s *)%s'
84
+ INVERSE_MANY_TEMPLATE = 'return [self linkingObjectsOfClass:@"%s" forProperty:@"%s"];'
85
+ INVERSE_ONE_TEMPLATE = 'return [[self linkingObjectsOfClass:@"%s" forProperty:@"%s"] objectAtIndex:0];'
86
+
87
+ # JSON_CATEGORY
88
+ JSON_CATEGORY_NAME = '%s+JSON'
89
+ JSON_TRANSFORMER_DEF = '+ (NSValueTransformer *)%sJSONTransformer'
90
+ JSON_CATEGORY_IMPLEMENTATION = '@implementation %s (JSON)'
91
+ JSON_CATEGORY_INTERFACE = '@interface %s (JSON)'
92
+ TRANSFORMER_BOOL_JSON = ['@"null"', '[NSNull null]', '@"<null>"', '@"false"', '@"true"', '@(NO)', '@(YES)']
93
+ TRANSFORMER_BOOL_MODEL = %w(NO NO NO NO YES NO YES)
94
+ TRANSFORMER_ENUM_JSON = ['@"null"', '[NSNull null]', '@"<null>"', '@""']
95
+ TRANSFORMER = 'return [[%s alloc] init];'
96
+
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,74 @@
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 Swift
20
+ module Converter
21
+
22
+ TYPES = {
23
+ :integer_16 => 'Int16',
24
+ :integer_32 => 'Int32',
25
+ :integer_64 => 'Int64',
26
+ :decimal => 'Double',
27
+ :double => 'Double',
28
+ :float => 'Float',
29
+ :string => 'String',
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 => 'false',
44
+ :date => 'NSDate()',
45
+ :binary => 'NSData()'
46
+ }
47
+
48
+ def convert_type(type)
49
+ TYPES[type]
50
+ end
51
+
52
+ def convert_default(type, value = nil)
53
+ if value.nil?
54
+ return DEFAULTS[type]
55
+ end
56
+ # Do some conversions for some special types
57
+ case [type, value]
58
+ when [:boolean, 'YES']
59
+ return 'true'
60
+ when [:boolean, 'NO']
61
+ return 'false'
62
+ else
63
+ return value
64
+ end
65
+ end
66
+
67
+ def is_number?(type)
68
+ type != :string && type != :date && type != :binary
69
+ end
70
+
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,73 @@
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('../../utils/string_xcdatamodel', File.dirname(__FILE__))
19
+ require File.expand_path('../../utils/file_utils', File.dirname(__FILE__))
20
+
21
+ module Gyro
22
+ module Realm
23
+ module Swift
24
+ module EnumGenerator
25
+
26
+ # INCLUDES #############################################################
27
+
28
+ include Templates
29
+
30
+ # PUBLIC METHODS #######################################################
31
+
32
+ def generate_enums(path, attributes)
33
+ enums = Array.new
34
+ attributes.each do |_, attribute|
35
+ if attribute.enum? and !enums.include?(attribute.enum_type)
36
+ enum_type = attribute.enum_type.delete_objc_prefix
37
+ enums.push(enum_type)
38
+ generate_enum(path, enum_type, attribute.enum_values, attribute.json_values)
39
+ end
40
+ end
41
+ end
42
+
43
+ private ################################################################
44
+
45
+ def generate_enum(path, enum_name, enum_values, raw_values)
46
+ enum_file = String.new
47
+ enum_file << GENERATED_MESSAGE + "\n\n"
48
+ enum_file << ENUM_STRING_DEF_TEMPLATE%[enum_name] + "\n"
49
+ raw_values = raw_values(enum_values, raw_values)
50
+ if !enum_values.empty? and raw_values.length == enum_values.length
51
+ (0..enum_values.length - 1).each { |idx|
52
+ enum_value = enum_values[idx].delete_objc_prefix
53
+ raw_value = raw_values[idx]
54
+ enum_file << ' ' + ENUM_STRING_CASE_TEMPLATE%[enum_value, raw_value] + "\n"
55
+ }
56
+ enum_file << '}' + "\n"
57
+ Gyro.write_file_with_name(path, SWIFT_FILE_TEMPLATE%[enum_name], enum_file)
58
+ end
59
+ end
60
+
61
+ def raw_values(enum_values, raw_values)
62
+ if raw_values.empty?
63
+ raw_values = enum_values.map { |value|
64
+ value.delete_objc_prefix.underscore
65
+ }
66
+ end
67
+ raw_values
68
+ end
69
+
70
+ end
71
+ end
72
+ end
73
+ end